diff --git a/delphi-backend/UMainForm.pas b/delphi-backend/UMainForm.pas index ce19268..016e758 100644 --- a/delphi-backend/UMainForm.pas +++ b/delphi-backend/UMainForm.pas @@ -82,6 +82,9 @@ type // True between an external minimise and the following activate, so the // restore's own resize is not mistaken for a user resize. FWasMinimized: Boolean; + // Set from activate until the queued correction runs, so the restore's + // own resize is not mistaken for the user resizing the window. + FRestoring: Boolean; FServer: TPMHTTPServer; FBridge: TPMBridge; // Accumulates base64 chunks for large file saves (attachments too big @@ -178,6 +181,7 @@ begin // Wired here (not in the .fmx) to keep the designer file untouched. FWantMaximized := (WindowState = TWindowState.wsMaximized); FWasMinimized := False; + FRestoring := False; OnResize := FormResizeTrackState; OnActivate := FormActivateRestoreState; @@ -1523,10 +1527,18 @@ begin if IsIconic(LHwnd) then begin FWasMinimized := True; // the state we must survive, not record + LogLine('[winstate] resize: minimised'); + Exit; + end; + if FRestoring then + begin + // The restore's own resize: reports whatever FMX decided, not intent. + LogLine('[winstate] resize during restore ignored (zoomed=' + + BoolToStr(IsZoomed(LHwnd), True) + ')'); Exit; end; - if FWasMinimized then Exit; // this resize IS the restore FWantMaximized := IsZoomed(LHwnd); // genuine user-driven resize + LogLine('[winstate] resize: want_max=' + BoolToStr(FWantMaximized, True)); end; // Re-apply the remembered state once the window is back. Runs however the @@ -1536,15 +1548,37 @@ end; // maximised. procedure TMainForm.FormActivateRestoreState(Sender: TObject); var - LHwnd: HWND; + LWant: Boolean; begin - 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); + // Snapshot the intent NOW: FMX's restore-time resize may land before or + // after this activate depending on how the window came back, and if it + // lands first it would already have overwritten FWantMaximized. + LWant := FWantMaximized; + if FRestoring then Exit; // one correction per return + FRestoring := True; + LogLine('[winstate] activate: want_max=' + BoolToStr(LWant, True) + + ' was_min=' + BoolToStr(FWasMinimized, True)); + // Queue the correction so it runs AFTER FMX has finished restoring the + // window — applying it inline loses the race against FMX's own sizing. + TThread.ForceQueue(nil, + procedure + var + LHwnd: HWND; + begin + FRestoring := False; + FWasMinimized := False; + LHwnd := WindowHandleToPlatform(Self.Handle).Wnd; + if (LHwnd = 0) or IsIconic(LHwnd) then Exit; + if LWant <> IsZoomed(LHwnd) then + begin + LogLine('[winstate] correcting to ' + + BoolToStr(LWant, True) + ' (was zoomed=' + + BoolToStr(IsZoomed(LHwnd), True) + ')'); + if LWant then ShowWindow(LHwnd, SW_SHOWMAXIMIZED) + else ShowWindow(LHwnd, SW_RESTORE); + end; + FWantMaximized := LWant; // our own ShowWindow fired a resize too + end); end; procedure TMainForm.AutofillTimerTick(Sender: TObject);