diff --git a/client/ui/recenter_linux.go b/client/ui/recenter_linux.go index d25666306..2c574e08f 100644 --- a/client/ui/recenter_linux.go +++ b/client/ui/recenter_linux.go @@ -2,57 +2,16 @@ package main -import ( - "os" - "strings" -) - // recenterOnShowPredicate returns the predicate WindowManager uses to decide // whether to re-center its Go-shown windows (main, Settings) on each show. // -// Re-centering is needed only on bare WMs (fluxbox, IceWM, twm …) that neither -// place small windows for us nor restore their position across a hide -> show -// round-trip — the same environment the in-process XEmbed tray host serves. -// xembedTrayAvailable (a _NET_SYSTEM_TRAY_S0 selection-owner probe) detects -// that host, but it is NOT a clean proxy for "bare WM": full desktops like -// Cinnamon, MATE, XFCE and LXDE ship a legacy XEmbed systray AND a real -// compositing WM (Muffin/Marco/xfwm4) that places windows itself. On those, -// running the post-show X11 re-center makes the window visibly jump from the -// WM's placement to ours (reported on Cinnamon/Mint/X11). So we additionally -// require that the session does NOT advertise a known full desktop. -// -// Evaluated per show (not once at startup) because the XEmbed tray can appear -// after the UI starts — the panel and the autostarted app race at login — and -// xembedTrayAvailable is a cheap, side-effect-free selection-owner probe. +// On Linux this is xembedTrayAvailable: re-centering is needed only in the +// minimal-WM / in-process-XEmbed-tray environment, where the window manager +// neither centers small windows for us nor restores their position across a +// hide -> show round-trip. The predicate is evaluated per show (not once at +// startup) because the XEmbed tray can appear after the UI starts — the panel +// and the autostarted app race at login — and xembedTrayAvailable is a cheap, +// side-effect-free selection-owner probe, fine to call repeatedly. func recenterOnShowPredicate() func() bool { - return func() bool { - return xembedTrayAvailable() && !inFullDesktopEnvironment() - } -} - -// fullDesktopTokens are desktop-environment identifiers whose window manager -// places and restores windows for us. Several also expose a legacy XEmbed -// systray, so they must be excluded from the re-center path explicitly. -// Matched case-insensitively against the colon-separated XDG_CURRENT_DESKTOP / -// DESKTOP_SESSION tokens. Bare WMs leave these unset (or report their own name, -// e.g. "Fluxbox"), which is absent here — so they still re-center. -var fullDesktopTokens = []string{ - "cinnamon", "mate", "xfce", "gnome", "kde", "plasma", - "lxde", "lxqt", "unity", "budgie", "deepin", "pantheon", -} - -// inFullDesktopEnvironment reports whether the session advertises one of the -// known full desktop environments via XDG_CURRENT_DESKTOP or DESKTOP_SESSION. -func inFullDesktopEnvironment() bool { - for _, env := range []string{"XDG_CURRENT_DESKTOP", "DESKTOP_SESSION"} { - for _, tok := range strings.Split(os.Getenv(env), ":") { - tok = strings.ToLower(strings.TrimSpace(tok)) - for _, full := range fullDesktopTokens { - if strings.Contains(tok, full) { - return true - } - } - } - } - return false + return xembedTrayAvailable } diff --git a/client/ui/services/windowmanager.go b/client/ui/services/windowmanager.go index 27777d7cb..d3d06324b 100644 --- a/client/ui/services/windowmanager.go +++ b/client/ui/services/windowmanager.go @@ -163,12 +163,10 @@ type WindowManager struct { hiddenForLogin []application.Window mu sync.Mutex // recenterOnShow reports whether Go should re-center the Go-shown - // windows (main, Settings) on each show. Only true on bare WMs (the - // in-process XEmbed-tray environment minus the full desktops — Cinnamon, - // MATE, XFCE … — that also expose an XEmbed systray), where the WM neither - // centers small windows for us nor restores their position across a - // hide -> show round-trip. On full desktops (GNOME/KDE/Cinnamon) the WM - // handles placement, so + // windows (main, Settings) on each show. Only true in the minimal-WM / + // in-process XEmbed-tray environment, where the WM neither centers small + // windows for us nor restores their position across a hide -> show + // round-trip. On full desktops (GNOME/KDE) the WM handles placement, so // re-centering is unnecessary and would fight a window the user moved — // there this stays nil and centerWhenReady is a no-op. Set by the Linux // startup path via SetRecenterOnShow; nil on macOS/Windows and in tests. @@ -651,10 +649,9 @@ func (s *WindowManager) ShowMain() { // SetRecenterOnShow installs the predicate that gates Go-side re-centering of // the main and Settings windows (see the recenterOnShow field). The Linux -// startup path passes a predicate that is true only on bare WMs (XEmbed tray -// present and no full desktop advertised), so re-centering happens only where -// the WM won't place windows for us; macOS/Windows and tests leave it unset, -// making centerWhenReady a no-op. +// startup path passes xembedTrayAvailable so re-centering happens only in the +// minimal-WM / in-process-XEmbed-tray environment; macOS/Windows and tests +// leave it unset, making centerWhenReady a no-op. func (s *WindowManager) SetRecenterOnShow(pred func() bool) { s.recenterOnShow = pred }