fix(window): stop forcing maximised on a window the user left normal
The previous version over-corrected: a normal window came back maximised after Win+D. Two causes, both fixed. - It read FMX's WindowState, which does not reliably follow a native un-maximise, so FWantMaximized never cleared. Now reads Win32 IsZoomed / IsIconic, which is the actual truth. - The restore fires its own resize, reporting whatever FMX decided — recording that erased the very intent we were preserving. FWasMinimized now gates the restore's resize out of the tracking. Activate then corrects both directions: re-maximise when FMX dropped a maximised window, restore when Windows brought a normal one back maximised. Degrades safely — if the minimise resize never fires, it simply does nothing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -79,6 +79,9 @@ type
|
||||
// which happens however the user comes back. FWantMaximized mirrors the
|
||||
// user's LAST deliberate choice, so we never fight a normal-size window.
|
||||
FWantMaximized: Boolean;
|
||||
// True between an external minimise and the following activate, so the
|
||||
// restore's own resize is not mistaken for a user resize.
|
||||
FWasMinimized: Boolean;
|
||||
FServer: TPMHTTPServer;
|
||||
FBridge: TPMBridge;
|
||||
// Accumulates base64 chunks for large file saves (attachments too big
|
||||
@@ -174,6 +177,7 @@ begin
|
||||
// The .fmx ships WindowState = wsMaximized, so that is the starting intent.
|
||||
// Wired here (not in the .fmx) to keep the designer file untouched.
|
||||
FWantMaximized := (WindowState = TWindowState.wsMaximized);
|
||||
FWasMinimized := False;
|
||||
OnResize := FormResizeTrackState;
|
||||
OnActivate := FormActivateRestoreState;
|
||||
|
||||
@@ -1503,23 +1507,44 @@ begin
|
||||
Application.Terminate;
|
||||
end;
|
||||
|
||||
// Remember the window state the USER settled on. Minimised is skipped on
|
||||
// purpose: that is precisely the state we have to survive, not record.
|
||||
// Remember the state the USER settled on. Reads Win32 (IsZoomed/IsIconic)
|
||||
// rather than FMX's WindowState, which does not reliably follow a native
|
||||
// un-maximise — that is why the first version never cleared the flag.
|
||||
//
|
||||
// The restore itself fires a resize too, and that one must NOT be recorded:
|
||||
// it reports whatever FMX decided (often "normal"), which would erase the
|
||||
// intent we are trying to preserve. FWasMinimized gates it out.
|
||||
procedure TMainForm.FormResizeTrackState(Sender: TObject);
|
||||
var
|
||||
LHwnd: HWND;
|
||||
begin
|
||||
if WindowState = TWindowState.wsMaximized then
|
||||
FWantMaximized := True
|
||||
else if WindowState = TWindowState.wsNormal then
|
||||
FWantMaximized := False;
|
||||
LHwnd := WindowHandleToPlatform(Self.Handle).Wnd;
|
||||
if LHwnd = 0 then Exit;
|
||||
if IsIconic(LHwnd) then
|
||||
begin
|
||||
FWasMinimized := True; // the state we must survive, not record
|
||||
Exit;
|
||||
end;
|
||||
if FWasMinimized then Exit; // this resize IS the restore
|
||||
FWantMaximized := IsZoomed(LHwnd); // genuine user-driven resize
|
||||
end;
|
||||
|
||||
// Re-apply "maximised" when the window comes back from an external minimise.
|
||||
// Runs however the user returns (taskbar, tray, Alt+Tab), because none of our
|
||||
// own restore paths are involved in a plain taskbar click.
|
||||
// Re-apply the remembered state once the window is back. Runs however the
|
||||
// user returns (taskbar, tray, Alt+Tab) — a plain taskbar restore never goes
|
||||
// through any of our own restore paths. Corrects BOTH directions: FMX drops
|
||||
// a maximised window to normal, and Windows can restore a normal window
|
||||
// maximised.
|
||||
procedure TMainForm.FormActivateRestoreState(Sender: TObject);
|
||||
var
|
||||
LHwnd: HWND;
|
||||
begin
|
||||
if FWantMaximized and (WindowState = TWindowState.wsNormal) then
|
||||
WindowState := TWindowState.wsMaximized;
|
||||
if not FWasMinimized then Exit;
|
||||
LHwnd := WindowHandleToPlatform(Self.Handle).Wnd;
|
||||
if (LHwnd = 0) or IsIconic(LHwnd) then Exit;
|
||||
FWasMinimized := False;
|
||||
if FWantMaximized = IsZoomed(LHwnd) then Exit; // already right
|
||||
if FWantMaximized then ShowWindow(LHwnd, SW_SHOWMAXIMIZED)
|
||||
else ShowWindow(LHwnd, SW_RESTORE);
|
||||
end;
|
||||
|
||||
procedure TMainForm.AutofillTimerTick(Sender: TObject);
|
||||
|
||||
Reference in New Issue
Block a user