fix(winstate): apply the wanted window state inline, killing the restore flash

The MINIMIZEEND correction was posted through ForceQueue. Instrumenting the
hook showed the window state identical at the hook and one message-loop turn
later, so the queue guarded no race and only bought the normal-sized frame the
user saw. ApplyWantedWindowState now runs inline; the deferred pass stays as an
idempotent net.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
r-zakarya
2026-07-27 19:39:23 +01:00
parent 99b68c3e67
commit b52cdc2d0b
2 changed files with 37 additions and 26 deletions
+28 -18
View File
@@ -176,6 +176,7 @@ type
procedure RestoreWindowFromTray;
procedure WinStateMinimizeStart;
procedure WinStateMinimizeEnd;
procedure ApplyWantedWindowState;
end;
var
@@ -1657,34 +1658,43 @@ begin
FIgnoreResizes := True;
end;
// Back up: re-apply what the user had. Queued so it lands after FMX has
// finished sizing the window — inline loses that race.
// Back up: re-apply what the user had.
procedure TMainForm.WinStateMinimizeEnd;
begin
// Inline, not queued: by the time this hook fires Windows has already put the
// window back at its normal size, and measurement showed nothing touches the
// state afterwards — the extra message-loop turn a ForceQueue costs was the
// whole flicker, one painted normal-sized frame before the correction landed.
ApplyWantedWindowState;
// Second pass anyway, in case FMX sizes the window after us on some path.
// Idempotent: it only acts when the state still disagrees.
TThread.ForceQueue(nil,
procedure
var
LHwnd: HWND;
begin
LHwnd := WindowHandleToPlatform(Self.Handle).Wnd;
if (LHwnd <> 0) and (not IsIconic(LHwnd)) then
begin
if FWantMaximized and (not IsZoomed(LHwnd)) then
begin
LogLine('[winstate] re-maximising after restore');
ShowWindow(LHwnd, SW_SHOWMAXIMIZED);
end
else if (not FWantMaximized) and IsZoomed(LHwnd) then
begin
LogLine('[winstate] restoring to normal after restore');
ShowWindow(LHwnd, SW_RESTORE);
end;
end;
ApplyWantedWindowState;
// Release the guard only after our own ShowWindow's resize has passed.
TThread.ForceQueue(nil, procedure begin FIgnoreResizes := False; end);
end);
end;
procedure TMainForm.ApplyWantedWindowState;
var
LHwnd: HWND;
begin
LHwnd := WindowHandleToPlatform(Self.Handle).Wnd;
if (LHwnd = 0) or IsIconic(LHwnd) then Exit;
if FWantMaximized and (not IsZoomed(LHwnd)) then
begin
LogLine('[winstate] re-maximising after restore');
ShowWindow(LHwnd, SW_SHOWMAXIMIZED);
end
else if (not FWantMaximized) and IsZoomed(LHwnd) then
begin
LogLine('[winstate] restoring to normal after restore');
ShowWindow(LHwnd, SW_RESTORE);
end;
end;
// Track the state the user settles on. Ignored entirely while a minimise /
// restore is in flight — that is the whole point of the hook above.
procedure TMainForm.FormResizeTrackState(Sender: TObject);