fix(window): a maximised window comes back maximised after Show desktop

Win+D / Show desktop minimises the window without any tray transition, so the
restore took the non-tray branch. FMainForm.Show runs first there and
re-applies FMX's own WindowState (normal), discarding the
WPF_RESTORETOMAXIMIZED flag Windows had recorded — the app returned in normal
size.

Read the placement flag BEFORE showing, and re-apply SW_SHOWMAXIMIZED when it
was set. The tray path is untouched: it already replays its own captured
placement.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
r-zakarya
2026-07-25 19:50:24 +01:00
parent f45a17d876
commit 6bed75f49e
+20 -1
View File
@@ -693,7 +693,8 @@ end;
procedure TPMBridge.RestoreFromTray; procedure TPMBridge.RestoreFromTray;
var var
LFormHwnd, LAppHwnd: HWND; LFormHwnd, LAppHwnd: HWND;
LWasTrayHidden: Boolean; LWasTrayHidden, LRestoreMax: Boolean;
LPlace: TWindowPlacement;
begin begin
// Tray icon stays in the tray — we only show the window again. // Tray icon stays in the tray — we only show the window again.
LFormHwnd := MainFormHWND(FMainForm); LFormHwnd := MainFormHWND(FMainForm);
@@ -713,6 +714,19 @@ begin
// MinimizeToTray) vs merely taskbar-minimised (Visible but iconic). // MinimizeToTray) vs merely taskbar-minimised (Visible but iconic).
LWasTrayHidden := not FMainForm.Visible; LWasTrayHidden := not FMainForm.Visible;
// Windows remembers "this minimised window was maximised" in the placement
// flags, but FMainForm.Show below re-applies FMX's own WindowState (normal)
// and loses it — hence a maximised window coming back normal after Win+D /
// Show desktop. Read the flag BEFORE showing so we can re-apply it.
LRestoreMax := False;
if not LWasTrayHidden then
begin
FillChar(LPlace, SizeOf(LPlace), 0);
LPlace.length := SizeOf(LPlace);
LRestoreMax := GetWindowPlacement(LFormHwnd, @LPlace) and
((LPlace.flags and WPF_RESTORETOMAXIMIZED) <> 0);
end;
// Reverse order: show the app proxy first so the taskbar entry comes back, // Reverse order: show the app proxy first so the taskbar entry comes back,
// then show and foreground the form. // then show and foreground the form.
if LAppHwnd <> 0 then if LAppHwnd <> 0 then
@@ -747,6 +761,11 @@ begin
end; end;
SetWindowPlacement(LFormHwnd, @FSavedPlacement); SetWindowPlacement(LFormHwnd, @FSavedPlacement);
end end
else if LRestoreMax then
// Was maximised before Windows minimised it (Win+D, taskbar, Show
// desktop): come back maximised. SW_RESTORE alone would land on the
// pre-maximise "normal" geometry.
ShowWindow(LFormHwnd, SW_SHOWMAXIMIZED)
else else
begin begin
ShowWindow(LFormHwnd, SW_SHOW); ShowWindow(LFormHwnd, SW_SHOW);