fix: dispatch Wayland workspace events at runtime

This commit is contained in:
2026-04-09 09:21:03 -04:00
parent 3671b0d6b9
commit 80d53ebcc3
2 changed files with 102 additions and 0 deletions
+66
View File
@@ -15,6 +15,8 @@ import os
from collections.abc import Mapping, Sequence
from typing import Any
from gi.repository import GLib
from .compositor_state_types import (
DESKTOP_TRANSITION_FINISHED,
DESKTOP_TRANSITION_STARTED,
@@ -62,6 +64,7 @@ class WaylandSharedProtocolsBackend:
self._workspaceStates: dict[Any, dict[str, Any]] = {}
self._batchDirty = False
self._transitionPending = False
self._dispatchSourceId = 0
def is_available(self, session_type: str | None = None) -> bool:
effectiveSessionType = (session_type or get_session_type()).strip().lower()
@@ -94,6 +97,7 @@ class WaylandSharedProtocolsBackend:
self._bind_listener(self._registry, "global", self._handle_registry_global)
self._bind_listener(self._registry, "global_remove", self._handle_registry_global_remove)
self._roundtrip()
self._install_dispatch_watch()
except Exception:
self.deactivate()
@@ -101,6 +105,7 @@ class WaylandSharedProtocolsBackend:
self._workspaceStates = {}
self._batchDirty = False
self._transitionPending = False
self._remove_dispatch_watch()
self._safe_close_proxy(self._workspaceManager)
self._safe_close_proxy(self._registry)
self._workspaceManager = None
@@ -154,6 +159,67 @@ class WaylandSharedProtocolsBackend:
method()
break
def _install_dispatch_watch(self) -> None:
if self._display is None or self._dispatchSourceId:
return
getFd = getattr(self._display, "get_fd", None)
if not callable(getFd):
return
try:
displayFd = int(getFd())
except Exception:
return
if displayFd < 0:
return
self._dispatchSourceId = GLib.io_add_watch(
displayFd,
GLib.PRIORITY_DEFAULT,
GLib.IO_IN | GLib.IO_ERR | GLib.IO_HUP,
self._dispatch_display_events,
)
def _remove_dispatch_watch(self) -> None:
if not self._dispatchSourceId:
return
try:
GLib.source_remove(self._dispatchSourceId)
except Exception:
pass
self._dispatchSourceId = 0
def _dispatch_display_events(self, _fd: int, condition: Any) -> bool:
if condition & (GLib.IO_ERR | GLib.IO_HUP):
self.deactivate()
return False
dispatch = getattr(self._display, "dispatch", None)
if not callable(dispatch):
self.deactivate()
return False
try:
while True:
dispatched = dispatch(block=False)
if not dispatched:
break
except TypeError:
try:
dispatch()
except Exception:
self.deactivate()
return False
except Exception:
self.deactivate()
return False
return True
def _safe_close_proxy(self, proxy: Any) -> None:
if proxy is None:
return