More refactoring work. Since the first part was such a success, may as well continue. We're actually going to be in very good shape if things keep going this well.
This commit is contained in:
+42
-28
@@ -135,6 +135,7 @@ class APIHelper:
|
|||||||
self._gestureBindings[contextName].append(binding)
|
self._gestureBindings[contextName].append(binding)
|
||||||
logger.info(f"Stored binding in context '{contextName}'")
|
logger.info(f"Stored binding in context '{contextName}'")
|
||||||
|
|
||||||
|
plugin_manager = None
|
||||||
if contextName and self.app:
|
if contextName and self.app:
|
||||||
try:
|
try:
|
||||||
plugin_manager = self.app.getPluginSystemManager()
|
plugin_manager = self.app.getPluginSystemManager()
|
||||||
@@ -143,21 +144,26 @@ class APIHelper:
|
|||||||
if plugin_manager:
|
if plugin_manager:
|
||||||
plugin_manager.add_keybinding(contextName, binding, global_binding=globalBinding)
|
plugin_manager.add_keybinding(contextName, binding, global_binding=globalBinding)
|
||||||
|
|
||||||
# Only add to active script if one exists
|
if contextName and self.app and plugin_manager:
|
||||||
if cthulhu_state.activeScript and not globalBinding:
|
if not globalBinding and cthulhu_state.activeScript:
|
||||||
logger.info(f"Adding binding to active script: {cthulhu_state.activeScript}")
|
plugin_manager.activate_keybindings_for_plugin(contextName)
|
||||||
bindings = cthulhu_state.activeScript.getKeyBindings()
|
elif not globalBinding:
|
||||||
bindings.add(binding)
|
debug.printMessage(debug.LEVEL_INFO, "No active script available - binding stored for later registration", True)
|
||||||
|
|
||||||
# Register key grab at the system level
|
|
||||||
grab_ids = addKeyGrab(binding)
|
|
||||||
logger.info(f"Key grab IDs: {grab_ids}")
|
|
||||||
|
|
||||||
# For later removal
|
|
||||||
if grab_ids:
|
|
||||||
binding._grab_ids = grab_ids
|
|
||||||
else:
|
else:
|
||||||
debug.printMessage(debug.LEVEL_INFO, "No active script available - binding stored for later registration", True)
|
if cthulhu_state.activeScript and not globalBinding:
|
||||||
|
logger.info(f"Adding binding to active script: {cthulhu_state.activeScript}")
|
||||||
|
bindings = cthulhu_state.activeScript.getKeyBindings()
|
||||||
|
bindings.add(binding)
|
||||||
|
|
||||||
|
# Register key grab at the system level
|
||||||
|
grab_ids = addKeyGrab(binding)
|
||||||
|
logger.info(f"Key grab IDs: {grab_ids}")
|
||||||
|
|
||||||
|
# For later removal
|
||||||
|
if grab_ids:
|
||||||
|
binding._grab_ids = grab_ids
|
||||||
|
else:
|
||||||
|
debug.printMessage(debug.LEVEL_INFO, "No active script available - binding stored for later registration", True)
|
||||||
|
|
||||||
debug.printMessage(debug.LEVEL_INFO, f"Created binding: {binding.keysymstring} with modifiers {binding.modifiers}", True)
|
debug.printMessage(debug.LEVEL_INFO, f"Created binding: {binding.keysymstring} with modifiers {binding.modifiers}", True)
|
||||||
logger.info("=== APIHelper.registerGestureByString completed ===")
|
logger.info("=== APIHelper.registerGestureByString completed ===")
|
||||||
@@ -174,16 +180,26 @@ class APIHelper:
|
|||||||
- binding: the binding to unregister
|
- binding: the binding to unregister
|
||||||
- contextName: the context for this gesture
|
- contextName: the context for this gesture
|
||||||
"""
|
"""
|
||||||
# Remove from script's keybindings
|
removed_via_plugin_manager = False
|
||||||
from . import cthulhu_state
|
if contextName and self.app:
|
||||||
if cthulhu_state.activeScript:
|
try:
|
||||||
bindings = cthulhu_state.activeScript.getKeyBindings()
|
plugin_manager = self.app.getPluginSystemManager()
|
||||||
bindings.remove(binding)
|
except Exception:
|
||||||
|
plugin_manager = None
|
||||||
|
if plugin_manager:
|
||||||
|
plugin_manager.remove_keybinding(contextName, binding)
|
||||||
|
removed_via_plugin_manager = True
|
||||||
|
if not removed_via_plugin_manager:
|
||||||
|
# Remove from script's keybindings
|
||||||
|
from . import cthulhu_state
|
||||||
|
if cthulhu_state.activeScript:
|
||||||
|
bindings = cthulhu_state.activeScript.getKeyBindings()
|
||||||
|
bindings.remove(binding)
|
||||||
|
|
||||||
# Remove key grab at system level
|
# Remove key grab at system level
|
||||||
if hasattr(binding, '_grab_ids'):
|
if hasattr(binding, '_grab_ids'):
|
||||||
for grab_id in binding._grab_ids:
|
for grab_id in binding._grab_ids:
|
||||||
self.app.removeKeyGrab(grab_id)
|
self.app.removeKeyGrab(grab_id)
|
||||||
|
|
||||||
# Remove from tracking
|
# Remove from tracking
|
||||||
if contextName in self._gestureBindings:
|
if contextName in self._gestureBindings:
|
||||||
@@ -858,17 +874,15 @@ def main():
|
|||||||
# setActiveWindow does some corrective work needed thanks to
|
# setActiveWindow does some corrective work needed thanks to
|
||||||
# mutter-x11-frames. So retrieve the window just in case.
|
# mutter-x11-frames. So retrieve the window just in case.
|
||||||
window = cthulhu_state.activeWindow
|
window = cthulhu_state.activeWindow
|
||||||
script = cthulhuApp.scriptManager.get_script(app, window)
|
cthulhuApp.scriptManager.activate_script_for_context(app, window, "startup: launch")
|
||||||
cthulhuApp.scriptManager.set_active_script(script, "Launching.")
|
|
||||||
|
|
||||||
focusedObject = AXUtilities.get_focused_object(window)
|
focusedObject = AXUtilities.get_focused_object(window)
|
||||||
tokens = ["CTHULHU: Focused object is:", focusedObject]
|
tokens = ["CTHULHU: Focused object is:", focusedObject]
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
||||||
if focusedObject:
|
if focusedObject:
|
||||||
setLocusOfFocus(None, focusedObject)
|
setLocusOfFocus(None, focusedObject)
|
||||||
script = cthulhuApp.scriptManager.get_script(
|
cthulhuApp.scriptManager.activate_script_for_context(
|
||||||
AXObject.get_application(focusedObject), focusedObject)
|
AXObject.get_application(focusedObject), focusedObject, "startup: focused-object")
|
||||||
cthulhuApp.scriptManager.set_active_script(script, "Found focused object.")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
msg = "CTHULHU: Starting ATSPI registry."
|
msg = "CTHULHU: Starting ATSPI registry."
|
||||||
|
|||||||
@@ -675,7 +675,7 @@ class EventManager:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
defaultScript = cthulhu.cthulhuApp.scriptManager.get_default_script()
|
defaultScript = cthulhu.cthulhuApp.scriptManager.get_default_script()
|
||||||
cthulhu.cthulhuApp.scriptManager.set_active_script(defaultScript, 'No focus')
|
cthulhu.cthulhuApp.scriptManager.set_active_script(defaultScript, 'focus: none')
|
||||||
defaultScript.idleMessage()
|
defaultScript.idleMessage()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -900,6 +900,15 @@ class EventManager:
|
|||||||
if not script.isActivatableEvent(event):
|
if not script.isActivatableEvent(event):
|
||||||
return False, "The script says not to activate for this event."
|
return False, "The script says not to activate for this event."
|
||||||
|
|
||||||
|
if cthulhu_state.activeScript is None:
|
||||||
|
active_window = cthulhu_state.activeWindow
|
||||||
|
if AXUtilities.is_focused(event.source):
|
||||||
|
return True, "No active script and event source is focused."
|
||||||
|
if active_window and AXObject.is_ancestor(event.source, active_window, inclusive=True):
|
||||||
|
return True, "No active script and event is in active window."
|
||||||
|
if AXUtilities.is_frame(event.source) or AXUtilities.is_window(event.source):
|
||||||
|
return True, "No active script and event source is window/frame."
|
||||||
|
|
||||||
if script.forceScriptActivation(event):
|
if script.forceScriptActivation(event):
|
||||||
return True, "The script insists it should be activated for this event."
|
return True, "The script insists it should be activated for this event."
|
||||||
|
|
||||||
@@ -1097,7 +1106,7 @@ class EventManager:
|
|||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
||||||
cthulhu_state.locusOfFocus = None
|
cthulhu_state.locusOfFocus = None
|
||||||
cthulhu_state.activeWindow = None
|
cthulhu_state.activeWindow = None
|
||||||
cthulhu.cthulhuApp.scriptManager.set_active_script(None, "Active window is dead or defunct")
|
cthulhu.cthulhuApp.scriptManager.set_active_script(None, "focus: active-window-dead")
|
||||||
return
|
return
|
||||||
|
|
||||||
if AXUtilities.is_iconified(event.source):
|
if AXUtilities.is_iconified(event.source):
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ class FocusManager:
|
|||||||
if event and (script and not script.app):
|
if event and (script and not script.app):
|
||||||
app = _get_ax_utilities().get_application(event.source)
|
app = _get_ax_utilities().get_application(event.source)
|
||||||
script = self.app.scriptManager.get_script(app, event.source)
|
script = self.app.scriptManager.get_script(app, event.source)
|
||||||
self.app.scriptManager.set_active_script(script, "Setting locus of focus")
|
self.app.scriptManager.activate_script_for_context(app, event.source, "focus: locus-of-focus")
|
||||||
|
|
||||||
old_focus = self._focus
|
old_focus = self._focus
|
||||||
if AXObject.is_dead(old_focus):
|
if AXObject.is_dead(old_focus):
|
||||||
@@ -384,8 +384,7 @@ class FocusManager:
|
|||||||
self.set_locus_of_focus(None, self._window, notify_script=True)
|
self.set_locus_of_focus(None, self._window, notify_script=True)
|
||||||
|
|
||||||
app = _get_ax_utilities().get_application(self._focus)
|
app = _get_ax_utilities().get_application(self._focus)
|
||||||
script = self.app.scriptManager.get_script(app, self._focus)
|
self.app.scriptManager.activate_script_for_context(app, self._focus, "focus: active-window")
|
||||||
self.app.scriptManager.set_active_script(script, "Setting active window")
|
|
||||||
|
|
||||||
@dbus_service.command
|
@dbus_service.command
|
||||||
def toggle_presentation_mode(
|
def toggle_presentation_mode(
|
||||||
@@ -472,4 +471,3 @@ def get_manager():
|
|||||||
from . import cthulhu
|
from . import cthulhu
|
||||||
_manager = FocusManager(cthulhu.cthulhuApp)
|
_manager = FocusManager(cthulhu.cthulhuApp)
|
||||||
return _manager
|
return _manager
|
||||||
|
|
||||||
|
|||||||
+17
-11
@@ -778,6 +778,20 @@ class KeyboardEvent(InputEvent):
|
|||||||
|
|
||||||
return self._handler
|
return self._handler
|
||||||
|
|
||||||
|
def _resolveHandler(self):
|
||||||
|
"""Resolve handler for this event, returning True if a global handler was used."""
|
||||||
|
|
||||||
|
if not self._handler and self._script:
|
||||||
|
self._handler = self._script.keyBindings.getInputHandler(self)
|
||||||
|
|
||||||
|
if not self._handler:
|
||||||
|
globalHandler = self._getGlobalHandler()
|
||||||
|
if globalHandler:
|
||||||
|
self._handler = globalHandler
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def shouldConsume(self):
|
def shouldConsume(self):
|
||||||
"""Returns True if this event should be consumed."""
|
"""Returns True if this event should be consumed."""
|
||||||
|
|
||||||
@@ -810,23 +824,15 @@ class KeyboardEvent(InputEvent):
|
|||||||
if cthulhu_state.bypassNextCommand:
|
if cthulhu_state.bypassNextCommand:
|
||||||
return False, 'Bypass next command'
|
return False, 'Bypass next command'
|
||||||
|
|
||||||
if not self._handler:
|
globalHandlerUsed = globalHandlerUsed or self._resolveHandler()
|
||||||
self._handler = self._script.keyBindings.getInputHandler(self)
|
|
||||||
if not self._handler:
|
|
||||||
globalHandler = self._getGlobalHandler()
|
|
||||||
if globalHandler:
|
|
||||||
self._handler = globalHandler
|
|
||||||
globalHandlerUsed = True
|
|
||||||
|
|
||||||
if self._handler:
|
if self._handler:
|
||||||
debug.printMessage(debug.LEVEL_INFO, f"shouldConsume: Handler found: {self._handler.description}", True)
|
debug.printMessage(debug.LEVEL_INFO, f"shouldConsume: Handler found: {self._handler.description}", True)
|
||||||
else:
|
else:
|
||||||
debug.printMessage(debug.LEVEL_INFO, "shouldConsume: No handler found", True)
|
debug.printMessage(debug.LEVEL_INFO, "shouldConsume: No handler found", True)
|
||||||
|
|
||||||
# TODO - JD: Right now we need to always call consumesKeyboardEvent()
|
self._script.updateKeyboardEventState(self, self._handler)
|
||||||
# because that method is updating state, even in instances where there
|
scriptConsumes = self._script.shouldConsumeKeyboardEvent(self, self._handler)
|
||||||
# is no handler.
|
|
||||||
scriptConsumes = self._script.consumesKeyboardEvent(self)
|
|
||||||
if globalHandlerUsed:
|
if globalHandlerUsed:
|
||||||
scriptConsumes = True
|
scriptConsumes = True
|
||||||
debug.printMessage(debug.LEVEL_INFO, f"shouldConsume: scriptConsumes={scriptConsumes}", True)
|
debug.printMessage(debug.LEVEL_INFO, f"shouldConsume: scriptConsumes={scriptConsumes}", True)
|
||||||
|
|||||||
@@ -133,6 +133,10 @@ class InputEventManager:
|
|||||||
grab_ids.append(grab_id)
|
grab_ids.append(grab_id)
|
||||||
self._grabbed_bindings[grab_id] = binding
|
self._grabbed_bindings[grab_id] = binding
|
||||||
|
|
||||||
|
if grab_ids:
|
||||||
|
tokens = ["INPUT EVENT MANAGER: Added grabs", grab_ids, "for", binding]
|
||||||
|
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
||||||
|
|
||||||
return grab_ids
|
return grab_ids
|
||||||
|
|
||||||
def remove_grabs_for_keybinding(self, binding: keybindings.KeyBinding) -> None:
|
def remove_grabs_for_keybinding(self, binding: keybindings.KeyBinding) -> None:
|
||||||
@@ -154,6 +158,9 @@ class InputEventManager:
|
|||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
tokens = ["INPUT EVENT MANAGER: Removing grabs", grab_ids, "for", binding]
|
||||||
|
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
||||||
|
|
||||||
for grab_id in grab_ids:
|
for grab_id in grab_ids:
|
||||||
self._device.remove_key_grab(grab_id)
|
self._device.remove_key_grab(grab_id)
|
||||||
removed = self._grabbed_bindings.pop(grab_id, None)
|
removed = self._grabbed_bindings.pop(grab_id, None)
|
||||||
@@ -179,6 +186,9 @@ class InputEventManager:
|
|||||||
binding._grab_ids.remove(grab_id)
|
binding._grab_ids.remove(grab_id)
|
||||||
if not binding._grab_ids:
|
if not binding._grab_ids:
|
||||||
delattr(binding, "_grab_ids")
|
delattr(binding, "_grab_ids")
|
||||||
|
if binding:
|
||||||
|
tokens = ["INPUT EVENT MANAGER: Removed grab", grab_id, "for", binding]
|
||||||
|
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
||||||
|
|
||||||
def map_keysym_to_modifier(self, keysym: int) -> int:
|
def map_keysym_to_modifier(self, keysym: int) -> int:
|
||||||
"""Maps keysym as a modifier, returns the newly-mapped modifier."""
|
"""Maps keysym as a modifier, returns the newly-mapped modifier."""
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ from enum import IntEnum
|
|||||||
|
|
||||||
import pluggy
|
import pluggy
|
||||||
from . import dbus_service
|
from . import dbus_service
|
||||||
|
from . import input_event_manager
|
||||||
from . import keybindings # Added import
|
from . import keybindings # Added import
|
||||||
|
|
||||||
# Set to True for more detailed plugin loading debug info
|
# Set to True for more detailed plugin loading debug info
|
||||||
@@ -144,6 +145,7 @@ class PluginSystemManager:
|
|||||||
self._plugin_keybindings = {} # plugin_name -> [KeyBinding]
|
self._plugin_keybindings = {} # plugin_name -> [KeyBinding]
|
||||||
self._global_keybindings = keybindings.KeyBindings()
|
self._global_keybindings = keybindings.KeyBindings()
|
||||||
self._global_bindings = []
|
self._global_bindings = []
|
||||||
|
self._last_active_script = None
|
||||||
|
|
||||||
# Create plugin directories
|
# Create plugin directories
|
||||||
self._setup_plugin_dirs()
|
self._setup_plugin_dirs()
|
||||||
@@ -166,12 +168,42 @@ class PluginSystemManager:
|
|||||||
if binding not in self._global_bindings:
|
if binding not in self._global_bindings:
|
||||||
self._global_bindings.append(binding)
|
self._global_bindings.append(binding)
|
||||||
self._global_keybindings.add(binding)
|
self._global_keybindings.add(binding)
|
||||||
grab_ids = self.app.addKeyGrab(binding)
|
grab_ids = input_event_manager.get_manager().add_grabs_for_keybinding(binding)
|
||||||
if grab_ids:
|
if grab_ids:
|
||||||
binding._global_grab_ids = grab_ids
|
binding._global_grab_ids = grab_ids
|
||||||
else:
|
else:
|
||||||
logger.warning(f"Failed to create global key grab for {binding.keysymstring}")
|
logger.warning(f"Failed to create global key grab for {binding.keysymstring}")
|
||||||
|
|
||||||
|
def activate_keybindings_for_plugin(self, plugin_name):
|
||||||
|
"""Activates keybindings for a single plugin with the active script."""
|
||||||
|
plugin_info = self._plugins.get(plugin_name)
|
||||||
|
if not plugin_info or not plugin_info.loaded:
|
||||||
|
return
|
||||||
|
self._activate_plugin_keybindings(plugin_info)
|
||||||
|
|
||||||
|
def remove_keybinding(self, plugin_name, binding):
|
||||||
|
"""Remove a keybinding associated with a specific plugin."""
|
||||||
|
if plugin_name in self._plugin_keybindings:
|
||||||
|
if binding in self._plugin_keybindings[plugin_name]:
|
||||||
|
self._plugin_keybindings[plugin_name].remove(binding)
|
||||||
|
|
||||||
|
if binding in self._global_bindings:
|
||||||
|
if hasattr(binding, '_global_grab_ids'):
|
||||||
|
for grab_id in binding._global_grab_ids:
|
||||||
|
input_event_manager.get_manager().remove_grab_by_id(grab_id)
|
||||||
|
del binding._global_grab_ids
|
||||||
|
if binding in self._global_bindings:
|
||||||
|
self._global_bindings.remove(binding)
|
||||||
|
self._global_keybindings.remove(binding)
|
||||||
|
return
|
||||||
|
|
||||||
|
from . import cthulhu_state
|
||||||
|
if cthulhu_state.activeScript:
|
||||||
|
active_script = cthulhu_state.activeScript
|
||||||
|
if active_script.getKeyBindings().hasKeyBinding(binding, "keysNoMask"):
|
||||||
|
active_script.getKeyBindings().remove(binding)
|
||||||
|
input_event_manager.get_manager().remove_grabs_for_keybinding(binding)
|
||||||
|
|
||||||
def _activate_plugin_keybindings(self, plugin_info):
|
def _activate_plugin_keybindings(self, plugin_info):
|
||||||
"""Activates all keybindings for a given plugin with the active script."""
|
"""Activates all keybindings for a given plugin with the active script."""
|
||||||
from . import cthulhu_state # Import here to avoid circular dependency
|
from . import cthulhu_state # Import here to avoid circular dependency
|
||||||
@@ -182,12 +214,13 @@ class PluginSystemManager:
|
|||||||
plugin_name = plugin_info.get_module_name()
|
plugin_name = plugin_info.get_module_name()
|
||||||
if plugin_name in self._plugin_keybindings:
|
if plugin_name in self._plugin_keybindings:
|
||||||
active_script = cthulhu_state.activeScript
|
active_script = cthulhu_state.activeScript
|
||||||
|
input_manager = input_event_manager.get_manager()
|
||||||
for binding in self._plugin_keybindings[plugin_name]:
|
for binding in self._plugin_keybindings[plugin_name]:
|
||||||
if binding in self._global_bindings:
|
if binding in self._global_bindings:
|
||||||
continue
|
continue
|
||||||
if not active_script.getKeyBindings().hasKeyBinding(binding, "keysNoMask"):
|
if not active_script.getKeyBindings().hasKeyBinding(binding, "keysNoMask"):
|
||||||
active_script.getKeyBindings().add(binding)
|
active_script.getKeyBindings().add(binding)
|
||||||
grab_ids = self.app.addKeyGrab(binding)
|
grab_ids = input_event_manager.get_manager().add_grabs_for_keybinding(binding)
|
||||||
if grab_ids:
|
if grab_ids:
|
||||||
binding._grab_ids = grab_ids
|
binding._grab_ids = grab_ids
|
||||||
else:
|
else:
|
||||||
@@ -216,10 +249,7 @@ class PluginSystemManager:
|
|||||||
continue
|
continue
|
||||||
if active_script.getKeyBindings().hasKeyBinding(binding, "keysNoMask"):
|
if active_script.getKeyBindings().hasKeyBinding(binding, "keysNoMask"):
|
||||||
active_script.getKeyBindings().remove(binding)
|
active_script.getKeyBindings().remove(binding)
|
||||||
if hasattr(binding, '_grab_ids'):
|
input_manager.remove_grabs_for_keybinding(binding)
|
||||||
for grab_id in binding._grab_ids:
|
|
||||||
self.app.removeKeyGrab(grab_id)
|
|
||||||
del binding._grab_ids
|
|
||||||
logger.debug(f"Deactivated keybinding '{binding.asString()}' for plugin '{plugin_name}'")
|
logger.debug(f"Deactivated keybinding '{binding.asString()}' for plugin '{plugin_name}'")
|
||||||
|
|
||||||
def refresh_active_script_keybindings(self):
|
def refresh_active_script_keybindings(self):
|
||||||
@@ -237,22 +267,20 @@ class PluginSystemManager:
|
|||||||
|
|
||||||
# First, remove all existing plugin keybindings from the old script
|
# First, remove all existing plugin keybindings from the old script
|
||||||
# This requires iterating through all plugins, not just active ones, to ensure cleanup
|
# This requires iterating through all plugins, not just active ones, to ensure cleanup
|
||||||
from . import cthulhu_state
|
old_script = self._last_active_script
|
||||||
if cthulhu_state.activeScript: # If there was an old active script
|
if old_script:
|
||||||
old_script = cthulhu_state.activeScript
|
input_manager = input_event_manager.get_manager()
|
||||||
for plugin_name, bindings in self._plugin_keybindings.items():
|
for plugin_name, bindings in self._plugin_keybindings.items():
|
||||||
for binding in bindings:
|
for binding in bindings:
|
||||||
if binding in self._global_bindings:
|
if binding in self._global_bindings:
|
||||||
continue
|
continue
|
||||||
if old_script.getKeyBindings().hasKeyBinding(binding, "keysNoMask"):
|
if old_script.getKeyBindings().hasKeyBinding(binding, "keysNoMask"):
|
||||||
old_script.getKeyBindings().remove(binding)
|
old_script.getKeyBindings().remove(binding)
|
||||||
if hasattr(binding, '_grab_ids'):
|
input_manager.remove_grabs_for_keybinding(binding)
|
||||||
for grab_id in binding._grab_ids:
|
|
||||||
self.app.removeKeyGrab(grab_id)
|
|
||||||
del binding._grab_ids
|
|
||||||
logger.debug(f"Removed keybinding '{binding.asString()}' from old script for plugin '{plugin_name}'")
|
logger.debug(f"Removed keybinding '{binding.asString()}' from old script for plugin '{plugin_name}'")
|
||||||
|
|
||||||
# Now, if there's a new active script, apply keybindings for currently active plugins
|
# Now, if there's a new active script, apply keybindings for currently active plugins
|
||||||
|
self._last_active_script = new_script
|
||||||
if new_script:
|
if new_script:
|
||||||
for plugin_name in self._active_plugins:
|
for plugin_name in self._active_plugins:
|
||||||
plugin_info = self._plugins.get(plugin_name)
|
plugin_info = self._plugins.get(plugin_name)
|
||||||
|
|||||||
+11
-3
@@ -496,11 +496,19 @@ class Script:
|
|||||||
Returns True if the event is of interest.
|
Returns True if the event is of interest.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
handler = self.keyBindings.getInputHandler(keyboardEvent)
|
||||||
|
self.updateKeyboardEventState(keyboardEvent, handler)
|
||||||
|
return self.shouldConsumeKeyboardEvent(keyboardEvent, handler)
|
||||||
|
|
||||||
|
def updateKeyboardEventState(self, keyboardEvent, handler):
|
||||||
|
"""Update internal state for a keyboard event without deciding consumption."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def shouldConsumeKeyboardEvent(self, keyboardEvent, handler):
|
||||||
|
"""Returns True if the script will consume this keyboard event."""
|
||||||
consumes = False
|
consumes = False
|
||||||
self._lastCommandWasStructNav = False
|
self._lastCommandWasStructNav = False
|
||||||
handler = self.keyBindings.getInputHandler(keyboardEvent)
|
if handler and handler.function in self.structuralNavigation.functions:
|
||||||
if handler \
|
|
||||||
and handler.function in self.structuralNavigation.functions:
|
|
||||||
consumes = self.useStructuralNavigationModel()
|
consumes = self.useStructuralNavigationModel()
|
||||||
if consumes:
|
if consumes:
|
||||||
self._lastCommandWasStructNav = True
|
self._lastCommandWasStructNav = True
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ class ScriptManager:
|
|||||||
self._toolkitNames = \
|
self._toolkitNames = \
|
||||||
{'WebKitGTK': 'WebKitGtk', 'GTK': 'gtk'}
|
{'WebKitGTK': 'WebKitGtk', 'GTK': 'gtk'}
|
||||||
|
|
||||||
self.set_active_script(None, "__init__")
|
self.set_active_script(None, "lifecycle: init")
|
||||||
self._active = False
|
self._active = False
|
||||||
debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Initialized", True)
|
debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Initialized", True)
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ class ScriptManager:
|
|||||||
debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Activating", True)
|
debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Activating", True)
|
||||||
self._defaultScript = self.get_script(None)
|
self._defaultScript = self.get_script(None)
|
||||||
self._defaultScript.registerEventListeners()
|
self._defaultScript.registerEventListeners()
|
||||||
self.set_active_script(self._defaultScript, "activate")
|
self.set_active_script(self._defaultScript, "lifecycle: activate")
|
||||||
self._active = True
|
self._active = True
|
||||||
debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Activated", True)
|
debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Activated", True)
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ class ScriptManager:
|
|||||||
if self._defaultScript:
|
if self._defaultScript:
|
||||||
self._defaultScript.deregisterEventListeners()
|
self._defaultScript.deregisterEventListeners()
|
||||||
self._defaultScript = None
|
self._defaultScript = None
|
||||||
self.set_active_script(None, "deactivate")
|
self.set_active_script(None, "lifecycle: deactivate")
|
||||||
self.appScripts = {}
|
self.appScripts = {}
|
||||||
self.toolkitScripts = {}
|
self.toolkitScripts = {}
|
||||||
self.customScripts = {}
|
self.customScripts = {}
|
||||||
@@ -342,6 +342,7 @@ class ScriptManager:
|
|||||||
|
|
||||||
cthulhu_state.activeScript = newScript
|
cthulhu_state.activeScript = newScript
|
||||||
if not newScript:
|
if not newScript:
|
||||||
|
self._log_active_state(reason)
|
||||||
return
|
return
|
||||||
|
|
||||||
newScript.activate()
|
newScript.activate()
|
||||||
@@ -352,6 +353,22 @@ class ScriptManager:
|
|||||||
|
|
||||||
tokens = ["SCRIPT MANAGER: Setting active script to", newScript, "reason:", reason]
|
tokens = ["SCRIPT MANAGER: Setting active script to", newScript, "reason:", reason]
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
||||||
|
self._log_active_state(reason)
|
||||||
|
|
||||||
|
def activate_script_for_context(self, app, obj, reason=None):
|
||||||
|
script = self.get_script(app, obj)
|
||||||
|
self.set_active_script(script, reason)
|
||||||
|
return script
|
||||||
|
|
||||||
|
def _log_active_state(self, reason=None):
|
||||||
|
tokens = [
|
||||||
|
"SCRIPT MANAGER: Active state:",
|
||||||
|
"window", cthulhu_state.activeWindow,
|
||||||
|
"focus", cthulhu_state.locusOfFocus,
|
||||||
|
"script", cthulhu_state.activeScript,
|
||||||
|
"reason", reason
|
||||||
|
]
|
||||||
|
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
||||||
|
|
||||||
def _get_script_for_app_replicant(self, app):
|
def _get_script_for_app_replicant(self, app):
|
||||||
if not self._active:
|
if not self._active:
|
||||||
@@ -436,4 +453,3 @@ def get_manager():
|
|||||||
from . import cthulhu
|
from . import cthulhu
|
||||||
_manager = ScriptManager(cthulhu.cthulhuApp)
|
_manager = ScriptManager(cthulhu.cthulhuApp)
|
||||||
return _manager
|
return _manager
|
||||||
|
|
||||||
|
|||||||
@@ -1983,7 +1983,7 @@ class Script(script.Script):
|
|||||||
|
|
||||||
cthulhu.setLocusOfFocus(event, None)
|
cthulhu.setLocusOfFocus(event, None)
|
||||||
cthulhu.setActiveWindow(None)
|
cthulhu.setActiveWindow(None)
|
||||||
cthulhu.cthulhuApp.scriptManager.set_active_script(None, "Window deactivated")
|
cthulhu.cthulhuApp.scriptManager.set_active_script(None, "focus: window-deactivated")
|
||||||
|
|
||||||
def onClipboardContentsChanged(self, *args):
|
def onClipboardContentsChanged(self, *args):
|
||||||
if self.flatReviewPresenter.is_active():
|
if self.flatReviewPresenter.is_active():
|
||||||
|
|||||||
@@ -587,18 +587,19 @@ class Script(default.Script):
|
|||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
||||||
self.liveRegionManager.flushMessages()
|
self.liveRegionManager.flushMessages()
|
||||||
|
|
||||||
def consumesKeyboardEvent(self, keyboardEvent):
|
def updateKeyboardEventState(self, keyboardEvent, handler):
|
||||||
"""Returns True if the script will consume this keyboard event."""
|
"""Update internal state for a keyboard event without deciding consumption."""
|
||||||
|
|
||||||
# We need to do this here. Cthulhu caret and structural navigation
|
# We need to do this here. Cthulhu caret and structural navigation
|
||||||
# often result in the user being repositioned without our getting
|
# often result in the user being repositioned without our getting
|
||||||
# a corresponding AT-SPI event. Without an AT-SPI event, script.py
|
# a corresponding AT-SPI event. Without an AT-SPI event, script.py
|
||||||
# won't know to dump the generator cache. See bgo#618827.
|
# won't know to dump the generator cache. See bgo#618827.
|
||||||
self.generatorCache = {}
|
self.generatorCache = {}
|
||||||
|
|
||||||
self._lastMouseButtonContext = None, -1
|
self._lastMouseButtonContext = None, -1
|
||||||
|
|
||||||
handler = self.keyBindings.getInputHandler(keyboardEvent)
|
def shouldConsumeKeyboardEvent(self, keyboardEvent, handler):
|
||||||
|
"""Returns True if the script will consume this keyboard event."""
|
||||||
|
|
||||||
if handler and self.caretNavigation.handles_navigation(handler):
|
if handler and self.caretNavigation.handles_navigation(handler):
|
||||||
consumes = self.useCaretNavigationModel(keyboardEvent)
|
consumes = self.useCaretNavigationModel(keyboardEvent)
|
||||||
self._lastCommandWasCaretNav = consumes
|
self._lastCommandWasCaretNav = consumes
|
||||||
@@ -627,7 +628,7 @@ class Script(default.Script):
|
|||||||
self._lastCommandWasMouseButton = False
|
self._lastCommandWasMouseButton = False
|
||||||
|
|
||||||
# Check parent first
|
# Check parent first
|
||||||
consumes = super().consumesKeyboardEvent(keyboardEvent)
|
consumes = super().shouldConsumeKeyboardEvent(keyboardEvent, handler)
|
||||||
|
|
||||||
# If parent doesn't consume Return key, try our clickable fallback
|
# If parent doesn't consume Return key, try our clickable fallback
|
||||||
if not consumes and keyboardEvent.event_string == "Return":
|
if not consumes and keyboardEvent.event_string == "Return":
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ class SleepModeManager:
|
|||||||
if notifyUser:
|
if notifyUser:
|
||||||
newScript.presentMessage(
|
newScript.presentMessage(
|
||||||
messages.SLEEP_MODE_DISABLED_FOR % AXObject.get_name(script.app))
|
messages.SLEEP_MODE_DISABLED_FOR % AXObject.get_name(script.app))
|
||||||
scriptManager.set_active_script(newScript, "Sleep mode toggled off")
|
scriptManager.set_active_script(newScript, "sleep: off")
|
||||||
debug.printMessage(debug.LEVEL_INFO, f"SLEEP MODE: Disabled for {AXObject.get_name(script.app)}", True)
|
debug.printMessage(debug.LEVEL_INFO, f"SLEEP MODE: Disabled for {AXObject.get_name(script.app)}", True)
|
||||||
# Reset debounce timer after successful toggle
|
# Reset debounce timer after successful toggle
|
||||||
self._lastToggleTime = 0
|
self._lastToggleTime = 0
|
||||||
@@ -173,7 +173,7 @@ class SleepModeManager:
|
|||||||
debug.printMessage(debug.LEVEL_INFO, f"SLEEP MODE: Got sleep script: {sleepScript}", True)
|
debug.printMessage(debug.LEVEL_INFO, f"SLEEP MODE: Got sleep script: {sleepScript}", True)
|
||||||
|
|
||||||
debug.printMessage(debug.LEVEL_INFO, f"SLEEP MODE: Setting active script", True)
|
debug.printMessage(debug.LEVEL_INFO, f"SLEEP MODE: Setting active script", True)
|
||||||
scriptManager.set_active_script(sleepScript, "Sleep mode toggled on")
|
scriptManager.set_active_script(sleepScript, "sleep: on")
|
||||||
debug.printMessage(debug.LEVEL_INFO, f"SLEEP MODE: Active script set successfully", True)
|
debug.printMessage(debug.LEVEL_INFO, f"SLEEP MODE: Active script set successfully", True)
|
||||||
|
|
||||||
debug.printMessage(debug.LEVEL_INFO, f"SLEEP MODE: Adding app to sleep list", True)
|
debug.printMessage(debug.LEVEL_INFO, f"SLEEP MODE: Adding app to sleep list", True)
|
||||||
|
|||||||
Reference in New Issue
Block a user