Added a fix for X11 / Cinnamon window popups and maximize button not visible.

This commit is contained in:
2026-09-07 22:19:05 +02:00
parent f06fc2e4e3
commit 1cfe8625e9
10 changed files with 678 additions and 34 deletions

View File

@@ -44,7 +44,6 @@ _X_PROPERTY_CHANGE_MASK = 1 << 22
_X_SUBSTRUCTURE_NOTIFY_MASK = 1 << 19
_X_SUBSTRUCTURE_REDIRECT_MASK = 1 << 20
_X_WM_STATE_WITHDRAWN = 0
_X_WM_STATE_NORMAL = 1
_X_WM_STATE_ICONIC = 3
_NET_WM_STATE_REMOVE = 0
_NET_WM_STATE_SOURCE_APPLICATION = 1
@@ -450,18 +449,6 @@ class _X11:
return None
return values[0]
def restore_normal_window_state(self, window: int) -> bool:
"""Undo a nested iconify request without raising the host window."""
self._replace_long_property(
window,
b"WM_STATE",
b"WM_STATE",
(_X_WM_STATE_NORMAL, 0),
)
self.library.XSync(self.display, 0)
return self.window_state(window) == _X_WM_STATE_NORMAL
def window_is_borderless(self, window: int) -> bool | None:
"""Return whether the client currently requests no Motif decorations."""
@@ -1010,6 +997,13 @@ class _X11:
return False
return int(focused.value) == window
def window_is_active(self, window: int) -> bool:
"""Return whether the desktop already considers this client active."""
root = self.library.XDefaultRootWindow(self.display)
active = self._long_property(root, b"_NET_ACTIVE_WINDOW", 1)
return bool(active and active[0] == window)
def activate_window(self, window: int) -> bool:
"""Ask the window manager to restore and activate one client."""
@@ -1436,15 +1430,19 @@ def _focus_game_window(mapper: _X11, window: int) -> None:
def _repair_game_window_focus(mapper: _X11, window: int) -> bool:
"""Repair Wine's input focus only while its desktop window remains active."""
try:
if mapper.window_state(window) == _X_WM_STATE_ICONIC:
return False
if not mapper.window_is_active(window):
return False
if mapper.window_is_focused(window):
return True
except Exception:
return False
try:
mapper.activate_window(window)
time.sleep(WINDOW_ACTIVATION_DELAY_SECONDS)
mapper.focus_window(window)
mapper.restore_input_focus(window)
return mapper.window_is_focused(window)
except Exception as exc:
print(
@@ -1460,6 +1458,8 @@ def _repair_gamescope_game_window_focus(mapper: _X11, window: int) -> bool:
"""Restore nested focus without asking the desktop to activate Gamescope."""
try:
if mapper.window_state(window) == _X_WM_STATE_ICONIC:
return False
if mapper.window_is_focused(window):
return True
except Exception:
@@ -1491,18 +1491,9 @@ def _resolve_gamescope_game_window(
except Exception:
state = None
if state == _X_WM_STATE_ICONIC:
try:
if not mapper.restore_normal_window_state(window):
return None
except Exception:
return None
print(
"Game login window requested minimization; kept it visible inside "
"Gamescope.",
file=sys.stderr,
flush=True,
)
return window
# IconicState can be a real desktop minimize request. Monitoring must never
# turn that user-controlled state back into a visible window.
return None
if state is not None and state != _X_WM_STATE_WITHDRAWN:
return window
@@ -1733,18 +1724,22 @@ def _guard_game_window_startup(
became_iconic = state == _X_WM_STATE_ICONIC
entered_screen_filling_mode = screen_filling is True
login_style_reset = borderless_was_applied and borderless_now is False
if became_iconic:
print(
"Game startup window was minimized; leaving it minimized.",
file=sys.stderr,
flush=True,
)
return False
if (
not became_iconic
and not entered_screen_filling_mode
not entered_screen_filling_mode
and not login_style_reset
):
time.sleep(WINDOW_STARTUP_POLL_SECONDS)
continue
recovery_count += 1
if became_iconic:
reason = "was minimized"
elif entered_screen_filling_mode:
if entered_screen_filling_mode:
reason = "entered fullscreen/maximized mode"
else:
reason = "changed its window layout"