Repository navigation
Conversation
…hown on
Add an opt-in setting, "Remember which monitor the main window was shown
on", to the General tab of Preferences. Without it, the main window opens
where DS_CENTER places it, on a monitor chosen by the system, which on a
multi-monitor setup is often not the monitor the user keeps VeraCrypt on.
The monitor is stored by display device name (for example \\.\DISPLAY2)
as LastMainWindowMonitor: a monitor handle cannot be kept from one run to
the next, and EnumDisplayMonitors defines no order an index could rely
on. When the setting is enabled:
- At the end of WM_INITDIALOG, the window is centered on the work area
of the remembered monitor if that monitor is attached and the window
has not been shown yet. Prompts displayed during startup, such as for
mounting from the command line, keep their usual placement. Whether
the window is then shown normally or minimized, or stays in the
notification area, it restores to that position.
- The monitor is recorded when the user moves the window to another
monitor (a click on the caption, which also enters the move loop,
records nothing), when the setting is turned on, and when the
settings are saved. Saving records it only if no monitor was
remembered yet, or if the remembered monitor is attached and the
window was placed on it, or a monitor was recorded, during this run
without the remembered monitor being detached since. This picks up a
move made with Win+Shift+Arrow, but not the monitor the system chose
because the remembered one was missing, as on a laptop used without
its external monitor. Nothing is recorded while the window is hidden,
minimized or outside every monitor.
- RepairMainWindowPlacement brings a window whose restore position lies
outside every monitor back on the remembered monitor instead of the
primary one, and converts the new position with that monitor's work
area offset. A restore position that lies on a monitor is repaired on
that monitor, as before.
Both placements now use the same centering, which keeps the caption on
the work area when the window is larger than it.
Turning the setting off clears the remembered monitor. While the setting
is on, the settings file is rewritten when the remembered monitor
changes, and only then. The English text of the new string is appended
to all language files.
idrassi
left a comment
There was a problem hiding this comment.
The option makes sense, especially for people who keep VeraCrypt on a secondary display. See inline for the issues I see.
| if (!bRememberWindowMonitor || !MainDlg || !IsWindowVisible (MainDlg) || IsIconic (MainDlg)) | ||
| return; |
There was a problem hiding this comment.
A move made with Win+Shift+Arrow isn't recorded until SaveSettings runs. That leaves a gap if the user hides the window first.
For example, open VeraCrypt on remembered monitor A and move it to B with the keyboard shortcut. Hide it through the hotkey or tray menu, then exit from the tray. ChangeMainWindowVisibility doesn't record the monitor before hiding the window. When settings are finally saved, this check prevents B from being recorded, so the next start returns to A. Minimizing before exiting has the same problem.
Dragging to B works because WM_EXITSIZEMOVE records it earlier. Could we preserve the keyboard choice while the window is still visible, before it gets hidden or minimized? We still need the protection against recording Windows parked position.
| if (LastMainWindowMonitorDevice[0] && !FindMonitorByDevice (LastMainWindowMonitorDevice)) | ||
| MainWindowMonitorChosen = FALSE; |
There was a problem hiding this comment.
Once MainWindowMonitorChosen becomes FALSE here, reconnecting the monitor doesn't restore the ability to record keyboard moves.
Consider two displays. Start with the window on remembered monitor A, then disconnect A. After reconnecting it, let Windows return the window to A. Now move it to B with Win+Shift+Arrow and save while the window is visible. RememberMainWindowMonitor still rejects the update because this flag remains FALSE, leaving A remembered.
Please make sure a later keyboard move can establish a new choice without requiring a drag or toggling the option. Simply resetting the flag on reconnection would need care, since that could allow Windows temporary placement to replace the user choice.
| "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,158,20,150,16 | ||
|
|
||
| GROUPBOX "Windows",IDT_WINDOWS_RELATED_SETTING,7,53,304,135 | ||
| GROUPBOX "Windows",IDT_WINDOWS_RELATED_SETTING,7,53,304,148 |
There was a problem hiding this comment.
The larger group box extends below its tab page.
I checked this: 100% scaling, the page's client area ends at y=319, while the group box ends at y=327. Its bottom border is clipped by eight pixels. The checkbox ends at y=300, so the checkbox itself fits.
PreferencesDlgProc resizes the page using the result from TabCtrl_AdjustRect. We can't rely on the height declared in the page template when choosing the group height. Could we adjust this to fit the space actually assigned to the page? The original group height fits at this scale.
| memset (&mi, 0, sizeof (mi)); | ||
| mi.cbSize = sizeof (mi); | ||
| if (GetMonitorInfoW (hMonitor, (LPMONITORINFO) &mi) && wcscmp (mi.szDevice, search->device) == 0) | ||
| { | ||
| search->hMonitor = hMonitor; | ||
| return FALSE; | ||
| } |
There was a problem hiding this comment.
What guarantees do we have that this name still identifies the same monitor after a restart or a change in how the displays are connected?
\\.\DISPLAY2 identifies a GDI display source. Microsoft documents the source name separately from the monitor target information. If the saved name later belongs to another display, this comparison would accept that display and also treat the remembered monitor as still attached.
I would like us to settle whether we're remembering a Windows display source or the same physical monitor before relying on this comparison to preserve the choice across reconnections.
Follow-up to #1858. On a multi-monitor setup the main window opens where
DS_CENTERplaces it, on a monitor chosen by the system, which is often not the one the user keeps VeraCrypt on. This adds an opt-in setting, "Remember which monitor the main window was shown on" (Preferences, General tab), that opens the main window on the monitor it was last shown on.Behaviour, when the setting is on
WM_INITDIALOG, if the remembered monitor is attached and the window hasn't been shown yet, the window is centered on that monitor's work area, usingMainDlgNormalSizeasRepairMainWindowPlacementdoes. Prompts displayed during startup (command-line mounts, auto-mount) are shown before that and keep their usual placement. Whether the window is then shown normally or minimized, or stays in the notification area, it restores to that position.WM_ENTERSIZEMOVE/WM_EXITSIZEMOVE, so a click on the caption records nothing), when the setting is turned on, and when the settings are saved. Saving does not replace the remembered monitor with one the system chose because the remembered monitor was missing at startup or was detached during the run, as on a laptop used without its external monitor; it does pick up a move made with Win+Shift+Arrow. Nothing is recorded while the window is hidden, minimized or outside every monitor.RepairMainWindowPlacementbrings a window whose restore position lies outside every monitor back on the remembered monitor rather than on the primary one, converting with that monitor's work-area offset. A restore position that lies on a monitor is repaired on that monitor, as before.With the main window shown, the wait dialog and the Secure Desktop prompt follow it (#1865, #1912). While it is hidden in the notification area or minimized, they keep their current placement:
GetWindowMonitorWorkAreaCenterskips such a parent, and this PR doesn't change that.Settings
RememberWindowMonitor(default 0) andLastMainWindowMonitor, the display device name of the monitor, e.g.\\.\DISPLAY2. A monitor handle can't be kept between runs, andEnumDisplayMonitorsdefines no order an index could rely on.Translations
The English text of the new string is appended to all language files, as the XML validation requires.
Testing
Windows 11, Debug x64 build of this branch. Two displays at different scale factors: the primary one external, 1920x1080 at (0,0), and the laptop panel below it at (-302,1080), 1260x840 in logical coordinates; "secondary" below is the laptop panel. The test script described in #1858 reads the placement, checks whether the window is centered on a work area, and produces the off-screen states and the appbar.
/q background, then the notification area icon clickedRememberWindowMonitor0 andLastMainWindowMonitorempty in the settings file; the next start opens on the primaryIn Preferences, with the Russian translation (which shows the English text of the new string), the new checkbox fits inside the Windows group box.
For the detach case, Windows 11's "Remember window locations based on monitor connection" was turned off. With it on, which is the default, Windows moves the window back to the secondary when the display is attached again, so the case doesn't arise. For
/q background, a volume was mounted, as a Debug build ends a hidden background task when no volume is mounted.