Merge branch 'testing'
This commit is contained in:
@@ -63,6 +63,15 @@ class CompositorStateAdapter:
|
||||
def get_snapshot(self) -> DesktopContextSnapshot:
|
||||
return self._snapshot
|
||||
|
||||
def refresh_workspace_context(self, reason: str) -> DesktopContextSnapshot:
|
||||
"""Refreshes and returns the selected backend's current workspace context."""
|
||||
|
||||
backend = self._workspaceBackend
|
||||
refreshContext = getattr(backend, "refresh_context", None)
|
||||
if callable(refreshContext):
|
||||
refreshContext(reason)
|
||||
return self._snapshot
|
||||
|
||||
def get_session_type(self) -> str:
|
||||
return get_session_type()
|
||||
|
||||
|
||||
@@ -92,6 +92,11 @@ class I3WorkspaceBackend:
|
||||
self._emitSignal = None
|
||||
self._lastContext = None
|
||||
|
||||
def refresh_context(self, reason: str) -> None:
|
||||
"""Refreshes the cached i3 focus context without emitting a transition."""
|
||||
|
||||
self._refresh_context(reason, transition=False)
|
||||
|
||||
def _ensure_connection(self) -> bool:
|
||||
if self._connection is not None:
|
||||
return True
|
||||
|
||||
@@ -115,6 +115,7 @@ class EventManager:
|
||||
self._churnSuppressed: bool = cthulhu_state.pauseAtspiChurn
|
||||
self._prioritizedContextToken: Optional[str] = cthulhu_state.prioritizedDesktopContextToken
|
||||
self._desktopContextConfirmedEmpty: bool = False
|
||||
self._flushingStaleAtspiEvents: bool = False
|
||||
self._relevanceBurstWindow: float = 0.15
|
||||
self._relevanceBurstHistory: Dict[Tuple[str, str, str], float] = {}
|
||||
|
||||
@@ -173,6 +174,7 @@ class EventManager:
|
||||
|
||||
debug.printMessage(debug.LEVEL_INFO, 'EVENT MANAGER: Activating keyboard handling', True)
|
||||
self._inputEventManager = input_event_manager.get_manager()
|
||||
self._inputEventManager.set_compositor_state_adapter(self._compositorStateAdapter)
|
||||
self._inputEventManager.start_key_watcher()
|
||||
cthulhu_state.device = self._inputEventManager._device
|
||||
self._keyHandlingActive = True
|
||||
@@ -276,6 +278,8 @@ class EventManager:
|
||||
self._compositorStateAdapter.remove_listener(self._handle_compositor_signal)
|
||||
|
||||
self._compositorStateAdapter = adapter
|
||||
if self._inputEventManager is not None:
|
||||
self._inputEventManager.set_compositor_state_adapter(adapter)
|
||||
if adapter is not None and hasattr(adapter, "add_listener"):
|
||||
adapter.add_listener(self._handle_compositor_signal)
|
||||
|
||||
@@ -924,32 +928,32 @@ class EventManager:
|
||||
|
||||
return False
|
||||
|
||||
def _addToQueue(self, event: Any, asyncMode: bool) -> None:
|
||||
def _addToQueue(self, event: Any, asyncMode: bool) -> bool:
|
||||
debugging = debug.debugEventQueue
|
||||
if debugging:
|
||||
debug.printMessage(debug.LEVEL_ALL, " acquiring lock...")
|
||||
self._gidleLock.acquire()
|
||||
|
||||
if debugging:
|
||||
debug.printMessage(debug.LEVEL_ALL, " ...acquired")
|
||||
debug.printMessage(debug.LEVEL_ALL, " calling queue.put...")
|
||||
debug.printMessage(debug.LEVEL_ALL, " (full=%s)" \
|
||||
% self._eventQueue.full())
|
||||
with self._gidleLock:
|
||||
effectiveAsyncMode = asyncMode or self._flushingStaleAtspiEvents
|
||||
if debugging:
|
||||
debug.printMessage(debug.LEVEL_ALL, " ...acquired")
|
||||
debug.printMessage(debug.LEVEL_ALL, " calling queue.put...")
|
||||
debug.printMessage(debug.LEVEL_ALL, " (full=%s)" \
|
||||
% self._eventQueue.full())
|
||||
|
||||
self._eventQueue.put(event)
|
||||
if debugging:
|
||||
debug.printMessage(debug.LEVEL_ALL, " ...put complete")
|
||||
self._eventQueue.put(event)
|
||||
if debugging:
|
||||
debug.printMessage(debug.LEVEL_ALL, " ...put complete")
|
||||
|
||||
if asyncMode and not self._gidleId:
|
||||
if self._gilSleepTime:
|
||||
time.sleep(self._gilSleepTime)
|
||||
self._gidleId = GLib.idle_add(self._dequeue)
|
||||
if effectiveAsyncMode and not self._gidleId:
|
||||
if self._gilSleepTime:
|
||||
time.sleep(self._gilSleepTime)
|
||||
self._gidleId = GLib.idle_add(self._dequeue)
|
||||
|
||||
if debugging:
|
||||
debug.printMessage(debug.LEVEL_ALL, " releasing lock...")
|
||||
self._gidleLock.release()
|
||||
if debug.debugEventQueue:
|
||||
debug.printMessage(debug.LEVEL_ALL, " releasing lock...")
|
||||
debug.printMessage(debug.LEVEL_ALL, " ...released")
|
||||
return effectiveAsyncMode
|
||||
|
||||
def _queuePrintln(self, e: Any, isEnqueue: bool = True, isPrune: Optional[bool] = None) -> None:
|
||||
"""Convenience method to output queue-related debugging info."""
|
||||
@@ -1118,7 +1122,7 @@ class EventManager:
|
||||
script = cthulhu.cthulhuApp.scriptManager.get_script(AXObject.get_application(e.source), e.source)
|
||||
script.eventCache[e.type] = (e, time.time())
|
||||
|
||||
self._addToQueue(e, asyncMode)
|
||||
asyncMode = self._addToQueue(e, asyncMode)
|
||||
if not asyncMode:
|
||||
self._dequeue()
|
||||
|
||||
@@ -1727,26 +1731,58 @@ class EventManager:
|
||||
def _flush_stale_atspi_events(self) -> None:
|
||||
"""Drops queued events that no longer match the compositor context."""
|
||||
|
||||
self._gidleLock.acquire()
|
||||
try:
|
||||
with self._gidleLock:
|
||||
self._flushingStaleAtspiEvents = True
|
||||
originalQueue = self._eventQueue
|
||||
newQueue: queue.Queue[Any] = queue.Queue(0)
|
||||
self._eventQueue = queue.Queue(0)
|
||||
|
||||
retainedEvents: list[Any] = []
|
||||
try:
|
||||
while not originalQueue.empty():
|
||||
try:
|
||||
event = originalQueue.get_nowait()
|
||||
except queue.Empty:
|
||||
break
|
||||
|
||||
if self._event_is_from_stale_context(event) and not self._should_preserve_during_suppression(event):
|
||||
# Accessible property calls can dispatch nested AT-SPI events.
|
||||
# Keep them outside _gidleLock so a nested enqueue cannot deadlock.
|
||||
try:
|
||||
isStale = self._event_is_from_stale_context(event)
|
||||
shouldPreserve = (
|
||||
isStale
|
||||
and self._should_preserve_during_suppression(event)
|
||||
)
|
||||
except Exception:
|
||||
retainedEvents.append(event)
|
||||
raise
|
||||
|
||||
if isStale and not shouldPreserve:
|
||||
continue
|
||||
|
||||
newQueue.put(event)
|
||||
|
||||
self._eventQueue = newQueue
|
||||
if self._asyncMode and not self._eventQueue.empty() and not self._gidleId:
|
||||
self._gidleId = GLib.idle_add(self._dequeue)
|
||||
retainedEvents.append(event)
|
||||
finally:
|
||||
self._gidleLock.release()
|
||||
while not originalQueue.empty():
|
||||
try:
|
||||
retainedEvents.append(originalQueue.get_nowait())
|
||||
except queue.Empty:
|
||||
break
|
||||
|
||||
with self._gidleLock:
|
||||
eventsQueuedDuringFlush = self._eventQueue
|
||||
mergedQueue: queue.Queue[Any] = queue.Queue(0)
|
||||
for event in retainedEvents:
|
||||
mergedQueue.put(event)
|
||||
|
||||
while not eventsQueuedDuringFlush.empty():
|
||||
try:
|
||||
mergedQueue.put(eventsQueuedDuringFlush.get_nowait())
|
||||
except queue.Empty:
|
||||
break
|
||||
|
||||
self._eventQueue = mergedQueue
|
||||
self._flushingStaleAtspiEvents = False
|
||||
if self._asyncMode and not self._eventQueue.empty() and not self._gidleId:
|
||||
self._gidleId = GLib.idle_add(self._dequeue)
|
||||
|
||||
def _inFlood(self) -> bool:
|
||||
size = self._eventQueue.qsize()
|
||||
|
||||
@@ -134,6 +134,12 @@ class InputEventManager:
|
||||
self._xtermRecoverySourceId: int = 0
|
||||
self._xtermRecoveryPollCount: int = 0
|
||||
self._xtermHandoffHistory: List[str] = []
|
||||
self._compositorStateAdapter: Optional[Any] = None
|
||||
|
||||
def set_compositor_state_adapter(self, adapter: Optional[Any]) -> None:
|
||||
"""Stores the compositor adapter used to refresh XTerm handoff state."""
|
||||
|
||||
self._compositorStateAdapter = adapter
|
||||
|
||||
def activate_device(self) -> Atspi.Device:
|
||||
"""Creates and returns the AT-SPI device used by this manager."""
|
||||
@@ -847,9 +853,17 @@ class InputEventManager:
|
||||
|
||||
snapshot = cthulhu_state.compositorSnapshot
|
||||
usingI3Context = snapshot is not None and snapshot.backend_name == "i3-ipc"
|
||||
if usingI3Context and self._lastEwmhXtermMatch is True:
|
||||
adapter = self._compositorStateAdapter
|
||||
refreshContext = getattr(adapter, "refresh_workspace_context", None)
|
||||
if callable(refreshContext):
|
||||
snapshot = refreshContext("xterm-handoff-check")
|
||||
usingI3Context = snapshot is not None and snapshot.backend_name == "i3-ipc"
|
||||
if usingI3Context and snapshot.focused_workspace_empty is True:
|
||||
self._record_xterm_handoff_action("i3:confirmed-empty-workspace")
|
||||
self._lastEwmhReadWindowId = None
|
||||
self._lastEwmhActiveWindowId = None
|
||||
self._lastEwmhXtermMatch = False
|
||||
return False
|
||||
|
||||
if usingI3Context and snapshot.focused_window_id is not None:
|
||||
|
||||
Reference in New Issue
Block a user