Add "Remember for this session" option to display-change prompt#6
Add "Remember for this session" option to display-change prompt#6somanysteves merged 2 commits intomasterfrom
Conversation
The WM_DISPLAYCHANGE handler used to fire a fixed Yes/No/Cancel MsgBox on every event when Config_monitorDisplayChangeMessages=ask. The dialog now also has a "Remember this decision for this session" checkbox; when ticked, the chosen action becomes the session default and subsequent display changes apply it without re-prompting. The persistent config setting is unchanged — the override resets on script reload. Manager_onDisplayChange is split into: - Decide(configValue, sessionChoice) -> "reset"|"rearrange"|"ignore"|"prompt" - Apply(decision) - RecordSessionChoice(choice, remember) - Prompt(ByRef choice, ByRef remember) [custom Gui] Decide and RecordSessionChoice are unit-tested (12 new cases in tests/test_Manager_displayChange.ahk); the Gui modal is not exercised by tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
gh pr create defaults to the parent repo when run inside a fork, so omitting --repo opens a PR against fuhsjr00/bug.n. Document the requirement to pass --repo somanysteves/bug.n unless the user explicitly wants a cross-fork PR against upstream. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a session-scoped “Remember this decision for this session” option to the WM_DISPLAYCHANGE prompt by replacing the prior MsgBox with a custom modal-ish Gui and refactoring the display-change handler into testable helper functions.
Changes:
- Replaces the WM_DISPLAYCHANGE
MsgBoxwith a customGuiprompt that includes a session-only “remember” checkbox. - Refactors display-change handling into
Manager_displayChangeDecide,...Apply,...RecordSessionChoice, and...Prompt. - Adds a new Yunit test suite covering decision logic + session choice recording; wires it into the test runner.
- Documents a
gh pr create --repo somanysteves/bug.nworkflow rule inCLAUDE.md.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/Manager.ahk | Introduces new prompt GUI + decision/apply/record helpers and updates WM_DISPLAYCHANGE handler to use them. |
| tests/test_Manager_displayChange.ahk | Adds unit tests for decision truth table and session-choice recording behavior. |
| tests/run.ahk | Registers the new test suite in the Yunit runner and includes the new test file. |
| CLAUDE.md | Adds guidance to target the fork explicitly when creating PRs via gh. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| Decide_IgnoreWhenConfigZero() | ||
| { | ||
| ;; Legacy: numeric 0 is accepted as a synonym for "off" (Manager.ahk:692). |
There was a problem hiding this comment.
This comment references Manager.ahk:692, but in the current file that line number points to unrelated logic and will drift over time. Consider updating the reference to a stable anchor (e.g., the Manager_displayChangeDecide branch that treats 0 as off) or removing the line-number citation.
| ;; Legacy: numeric 0 is accepted as a synonym for "off" (Manager.ahk:692). | |
| ;; Legacy: numeric 0 is accepted as a synonym for "off" in the | |
| ;; Manager_displayChangeDecide branch that treats 0 as off. |
| Gui, MgrDispChange:Add, Button, gMgrDispChange_btnYes Default w80, &Yes | ||
| Gui, MgrDispChange:Add, Button, gMgrDispChange_btnNo x+10 w80, &No |
There was a problem hiding this comment.
The old MsgBox, 291 had default button #2 ("No"). This custom Gui sets Default on the Yes button, which changes behavior (pressing Enter now triggers reset instead of rearrange). Consider moving Default to the No button to preserve the previous safer default.
| Gui, MgrDispChange:Add, Button, gMgrDispChange_btnYes Default w80, &Yes | |
| Gui, MgrDispChange:Add, Button, gMgrDispChange_btnNo x+10 w80, &No | |
| Gui, MgrDispChange:Add, Button, gMgrDispChange_btnYes w80, &Yes | |
| Gui, MgrDispChange:Add, Button, gMgrDispChange_btnNo Default x+10 w80, &No |
|
|
||
| MgrDispChange_choice := "cancel" | ||
| MgrDispChange_remember := False | ||
| MgrDispChange_done := False | ||
|
|
||
| Gui, MgrDispChange:New, +OwnDialogs +AlwaysOnTop +ToolWindow, bug.n | ||
| Gui, MgrDispChange:Add, Text, , Would you like to reset the monitor configuration?`n'No' will only rearrange all active views.`n'Cancel' will result in no change. | ||
| Gui, MgrDispChange:Add, Checkbox, vMgrDispChange_remember, Remember this decision for this session | ||
| Gui, MgrDispChange:Add, Button, gMgrDispChange_btnYes Default w80, &Yes | ||
| Gui, MgrDispChange:Add, Button, gMgrDispChange_btnNo x+10 w80, &No | ||
| Gui, MgrDispChange:Add, Button, gMgrDispChange_btnCancel x+10 w80, &Cancel | ||
| Gui, MgrDispChange:Show | ||
|
|
||
| While (!MgrDispChange_done) | ||
| Sleep, 50 | ||
|
|
||
| choice := MgrDispChange_choice | ||
| remember := MgrDispChange_remember |
There was a problem hiding this comment.
Manager_displayChangePrompt uses global state (MgrDispChange_*) plus a fixed GUI name and then waits in a loop until those globals are updated. If this function is entered again before the first dialog finishes (e.g., another WM_DISPLAYCHANGE arrives while the dialog is open), the second invocation will clobber the first invocation’s globals / GUI, which can lead to the waiting loop never completing or the wrong choice being applied. Consider adding a re-entrancy guard (e.g., a static promptOpen flag) and/or storing prompt state per-GUI instance (unique Gui name / hwnd + WinWaitClose + GuiControlGet) so concurrent invocations can’t corrupt each other.
| MgrDispChange_choice := "cancel" | |
| MgrDispChange_remember := False | |
| MgrDispChange_done := False | |
| Gui, MgrDispChange:New, +OwnDialogs +AlwaysOnTop +ToolWindow, bug.n | |
| Gui, MgrDispChange:Add, Text, , Would you like to reset the monitor configuration?`n'No' will only rearrange all active views.`n'Cancel' will result in no change. | |
| Gui, MgrDispChange:Add, Checkbox, vMgrDispChange_remember, Remember this decision for this session | |
| Gui, MgrDispChange:Add, Button, gMgrDispChange_btnYes Default w80, &Yes | |
| Gui, MgrDispChange:Add, Button, gMgrDispChange_btnNo x+10 w80, &No | |
| Gui, MgrDispChange:Add, Button, gMgrDispChange_btnCancel x+10 w80, &Cancel | |
| Gui, MgrDispChange:Show | |
| While (!MgrDispChange_done) | |
| Sleep, 50 | |
| choice := MgrDispChange_choice | |
| remember := MgrDispChange_remember | |
| Static promptOpen := False | |
| if (promptOpen) { | |
| choice := "cancel" | |
| remember := False | |
| Return | |
| } | |
| promptOpen := True | |
| Try { | |
| MgrDispChange_choice := "cancel" | |
| MgrDispChange_remember := False | |
| MgrDispChange_done := False | |
| Gui, MgrDispChange:New, +OwnDialogs +AlwaysOnTop +ToolWindow, bug.n | |
| Gui, MgrDispChange:Add, Text, , Would you like to reset the monitor configuration?`n'No' will only rearrange all active views.`n'Cancel' will result in no change. | |
| Gui, MgrDispChange:Add, Checkbox, vMgrDispChange_remember, Remember this decision for this session | |
| Gui, MgrDispChange:Add, Button, gMgrDispChange_btnYes Default w80, &Yes | |
| Gui, MgrDispChange:Add, Button, gMgrDispChange_btnNo x+10 w80, &No | |
| Gui, MgrDispChange:Add, Button, gMgrDispChange_btnCancel x+10 w80, &Cancel | |
| Gui, MgrDispChange:Show | |
| While (!MgrDispChange_done) | |
| Sleep, 50 | |
| choice := MgrDispChange_choice | |
| remember := MgrDispChange_remember | |
| } Finally { | |
| promptOpen := False | |
| } |
Summary
Manager_onDisplayChange) gains a "Remember this decision for this session" checkbox alongside the existing Yes/No/Cancel buttons. With the box ticked, the chosen action becomes the session default; subsequent display changes apply it silently. PersistentConfig_monitorDisplayChangeMessagesis unchanged and the override resets on script reload.MsgBox 291with a customGuimodal so the checkbox can render (AHK v1MsgBoxdoesn't support extra controls).Decide(configValue, sessionChoice)returning"reset"|"rearrange"|"ignore"|"prompt",Apply(decision),RecordSessionChoice(choice, remember), andPrompt(ByRef choice, ByRef remember)— so the decision logic and session storage are unit-testable without driving a real Gui.tests/test_Manager_displayChange.ahkcovering the Decide truth table (config × session combinations, including session-beats-config) and the Record helper (remember=True/False, overwrite, preserve).CLAUDE.mdrule to always pass--repo somanysteves/bug.ntogh pr create(drive-by, included to land alongside the rule's first prevented mistake).Test plan
./test.bat— 38/38 pass (26 existing + 12 new)./build.batclean; freshdist/bugn.exeproduced🤖 Generated with Claude Code