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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user