feat: prioritize script activation using compositor context
This commit is contained in:
@@ -1236,6 +1236,12 @@ class EventManager:
|
||||
if not script:
|
||||
return False, "There is no script for this event."
|
||||
|
||||
prioritizedContextToken = self._prioritizedContextToken or cthulhu_state.prioritizedDesktopContextToken
|
||||
if self._churnSuppressed and prioritizedContextToken:
|
||||
eventToken = self._context_token_for_event(event)
|
||||
if eventToken not in (None, prioritizedContextToken):
|
||||
return False, "Event context does not match compositor-prioritized context."
|
||||
|
||||
if script == cthulhu_state.activeScript:
|
||||
return False, "The script for this event is already active."
|
||||
|
||||
@@ -1588,6 +1594,12 @@ class EventManager:
|
||||
msg = f"EVENT MANAGER: Exception processing {event.type}: {error}"
|
||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
||||
debug.printException(debug.LEVEL_INFO)
|
||||
else:
|
||||
if self._compositorStateAdapter is not None:
|
||||
if eType.startswith("window:activate") or (
|
||||
eType.startswith("object:state-changed:focused") and event.detail1
|
||||
):
|
||||
self._compositorStateAdapter.sync_accessible_context(event.type)
|
||||
|
||||
tokens = ["EVENT MANAGER: locusOfFocus:", cthulhu_state.locusOfFocus,
|
||||
"activeScript:", cthulhu_state.activeScript]
|
||||
|
||||
@@ -103,6 +103,45 @@ class EventManagerCompositorContextRegressionTests(unittest.TestCase):
|
||||
|
||||
self.assertEqual(list(self.manager._eventQueue.queue), [currentEvent])
|
||||
|
||||
def test_stale_background_event_does_not_activate_script_during_suppression(self) -> None:
|
||||
script = mock.Mock()
|
||||
script.isActivatableEvent.return_value = True
|
||||
script.forceScriptActivation.return_value = False
|
||||
self.manager._churnSuppressed = True
|
||||
self.manager._prioritizedContextToken = "current"
|
||||
|
||||
event = FakeEvent("object:state-changed:showing", source="old")
|
||||
|
||||
result, reason = self.manager._isActivatableEvent(event, script)
|
||||
|
||||
self.assertFalse(result)
|
||||
self.assertIn("compositor-prioritized context", reason)
|
||||
|
||||
def test_focus_event_syncs_accessible_context_back_into_adapter(self) -> None:
|
||||
adapter = mock.Mock()
|
||||
script = mock.Mock()
|
||||
source = object()
|
||||
event = FakeEvent("object:state-changed:focused", source=source, detail1=1)
|
||||
self.manager._compositorStateAdapter = adapter
|
||||
self.manager._get_scriptForEvent = mock.Mock(return_value=script)
|
||||
self.manager._isActivatableEvent = mock.Mock(return_value=(False, "already active"))
|
||||
self.manager._inFlood = mock.Mock(return_value=False)
|
||||
|
||||
with (
|
||||
mock.patch.object(event_manager.debug, "printObjectEvent"),
|
||||
mock.patch.object(event_manager.debug, "printDetails"),
|
||||
mock.patch.object(event_manager.debug, "printMessage"),
|
||||
mock.patch.object(event_manager.debug, "printTokens"),
|
||||
mock.patch.object(event_manager.AXUtilities, "get_desktop", return_value=object()),
|
||||
mock.patch.object(event_manager.AXUtilities, "is_defunct", return_value=False),
|
||||
mock.patch.object(event_manager.AXUtilities, "is_iconified", return_value=False),
|
||||
mock.patch.object(event_manager.AXUtilities, "is_frame", return_value=False),
|
||||
mock.patch.object(event_manager.AXObject, "is_dead", return_value=False),
|
||||
):
|
||||
self.manager._processObjectEvent(event)
|
||||
|
||||
adapter.sync_accessible_context.assert_called_once_with("object:state-changed:focused")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user