diff --git a/delphi-backend/UMainForm.pas b/delphi-backend/UMainForm.pas index 7078051..d6ce83a 100644 --- a/delphi-backend/UMainForm.pas +++ b/delphi-backend/UMainForm.pas @@ -173,6 +173,9 @@ type // stuck raised (see the implementation). // One-shot: hides the window the first time FMX shows it on a --tray // launch, then unhooks itself. + // Hides the form AND the FMX taskbar proxy right now, logging whether the + // window was actually visible — that is what pins down when FMX shows it. + procedure TrayHideNow(const ATag: string); procedure TrayStartupHideOnce(Sender: TObject); procedure RestoreWindowFromTray; procedure WinStateMinimizeStart; @@ -221,6 +224,7 @@ begin Visible := False; OnActivate := TrayStartupHideOnce; LogLine('[tray] FormCreate begin at ' + FormatDateTime('hh:nn:ss.zzz', Now)); + TrayHideNow('hide#1 top-of-FormCreate'); end; // The .fmx ships WindowState = wsMaximized, so that is the starting intent. @@ -261,6 +265,9 @@ begin {$ENDIF} WebBrowser.Parent := Self; WebBrowser.Align := TAlignLayout.Client; + // Parenting forces the form's window handle to exist, and that is the point + // FMX may show it — hide again right away. + if FindCmdLineSwitch('tray', True) then TrayHideNow('hide#2 after-browser-parent'); FServer := TPMHTTPServer.Create; FServer.OnLog := LogLine; @@ -326,7 +333,7 @@ begin // it's noise when Windows itself put us in the tray (the user // didn't actively minimise). Manual launches still see it once. FBridge.BalloonShown := True; - LogLine('[tray] FormCreate end at ' + FormatDateTime('hh:nn:ss.zzz', Now)); + TrayHideNow('hide#3 end-of-FormCreate'); TThread.ForceQueue(nil, procedure begin @@ -1601,24 +1608,27 @@ begin else if AEvent = EVENT_SYSTEM_MINIMIZEEND then MainForm.WinStateMinimizeEnd; end; -procedure TMainForm.TrayStartupHideOnce(Sender: TObject); +procedure TMainForm.TrayHideNow(const ATag: string); var LHwnd, LAppHwnd: HWND; + LWasVisible: Boolean; +begin + LHwnd := WindowHandleToPlatform(Self.Handle).Wnd; + LWasVisible := (LHwnd <> 0) and IsWindowVisible(LHwnd); + if LHwnd <> 0 then ShowWindow(LHwnd, SW_HIDE); + LAppHwnd := 0; + if Assigned(FBridge) then LAppHwnd := FBridge.FindFMXAppWindow; + if LAppHwnd <> 0 then ShowWindow(LAppHwnd, SW_HIDE); + LogLine(Format('[tray] %s at %s — form_visible_was=%s hwnd=%d app=%d', + [ATag, FormatDateTime('hh:nn:ss.zzz', Now), + BoolToStr(LWasVisible, True), LHwnd, LAppHwnd])); +end; + +procedure TMainForm.TrayStartupHideOnce(Sender: TObject); begin OnActivate := nil; // one shot — never fight the user afterwards Visible := False; - LHwnd := WindowHandleToPlatform(Self.Handle).Wnd; - if LHwnd <> 0 then - ShowWindow(LHwnd, SW_HIDE); - // The taskbar entry belongs to the FMX proxy window, not the form — hiding - // the form alone leaves the button on the taskbar. - if Assigned(FBridge) then - begin - LAppHwnd := FBridge.FindFMXAppWindow; - if LAppHwnd <> 0 then ShowWindow(LAppHwnd, SW_HIDE); - end; - LogLine('[tray] activate-hide fired at ' + - FormatDateTime('hh:nn:ss.zzz', Now)); + TrayHideNow('hide#4 on-activate'); end; // Single entry point for every tray restore. ExecuteAutofill really minimises