diff --git a/configure.ac b/configure.ac index 82802df..aa855ad 100644 --- a/configure.ac +++ b/configure.ac @@ -110,6 +110,7 @@ src/cthulhu/scripts/apps/SeaMonkey/Makefile src/cthulhu/scripts/apps/smuxi-frontend-gnome/Makefile src/cthulhu/scripts/apps/Thunderbird/Makefile src/cthulhu/scripts/apps/xfwm4/Makefile +src/cthulhu/scripts/sleepmode/Makefile src/cthulhu/scripts/switcher/Makefile src/cthulhu/scripts/terminal/Makefile src/cthulhu/scripts/web/Makefile diff --git a/src/cthulhu/common_keyboardmap.py b/src/cthulhu/common_keyboardmap.py index 9bcde94..400ae0a 100644 --- a/src/cthulhu/common_keyboardmap.py +++ b/src/cthulhu/common_keyboardmap.py @@ -57,6 +57,9 @@ keymap = ( ("BackSpace", defaultModifierMask, CTHULHU_MODIFIER_MASK, "bypassNextCommandHandler"), + ("q", defaultModifierMask, CTHULHU_CTRL_ALT_MODIFIER_MASK | SHIFT_ALT_MODIFIER_MASK, + "toggleSleepModeHandler"), + ("q", defaultModifierMask, CTHULHU_MODIFIER_MASK, "shutdownHandler"), diff --git a/src/cthulhu/cthulhuVersion.py b/src/cthulhu/cthulhuVersion.py index ffe2d21..6ab45f7 100644 --- a/src/cthulhu/cthulhuVersion.py +++ b/src/cthulhu/cthulhuVersion.py @@ -23,5 +23,5 @@ # Fork of Orca Screen Reader (GNOME) # Original source: https://gitlab.gnome.org/GNOME/orca -version = "2024.12.19" +version = "2024.12.22" codeName = "testing" diff --git a/src/cthulhu/messages.py b/src/cthulhu/messages.py index ffb4f36..2187fad 100644 --- a/src/cthulhu/messages.py +++ b/src/cthulhu/messages.py @@ -2299,7 +2299,12 @@ SPOKEN_ELLIPSIS = _(" dot dot dot") START_CTHULHU = _("Cthulhu welcomes you.") # Translators: This message is presented to the user when Cthulhu is quit. -STOP_CTHULHU = _("Cthulhu lerks beneath the waves.") +STOP_CTHULHU = _("Cthulhu lurks beneath the waves.") + +# Sleep Mode +# Translators: This message is presented to the user when Cthulhu enters or leaves sleep mode. +SLEEP_MODE_ENABLED_FOR = _("Sleep mode enabled for %s") +SLEEP_MODE_DISABLED_FOR = _("Sleep mode disabled for %s") # Translators: This message means speech synthesis is not installed or working. SPEECH_UNAVAILABLE = _("Speech is unavailable.") diff --git a/src/cthulhu/scripts/Makefile.am b/src/cthulhu/scripts/Makefile.am index 879ac6e..37b53ee 100644 --- a/src/cthulhu/scripts/Makefile.am +++ b/src/cthulhu/scripts/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = apps toolkits switcher terminal web +SUBDIRS = apps toolkits sleepmode switcher terminal web cthulhu_python_PYTHON = \ __init__.py \ diff --git a/src/cthulhu/scripts/sleepmode/Makefile.am b/src/cthulhu/scripts/sleepmode/Makefile.am new file mode 100644 index 0000000..39c7ea1 --- /dev/null +++ b/src/cthulhu/scripts/sleepmode/Makefile.am @@ -0,0 +1,6 @@ +cthulhu_python_PYTHON = \ + __init__.py \ + script.py \ + script_utilities.py + +cthulhu_pythondir=$(pkgpythondir)/scripts/terminal diff --git a/src/cthulhu/scripts/sleepmode/__init__.py b/src/cthulhu/scripts/sleepmode/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/cthulhu/scripts/sleepmode/script.py b/src/cthulhu/scripts/sleepmode/script.py new file mode 100644 index 0000000..942bd65 --- /dev/null +++ b/src/cthulhu/scripts/sleepmode/script.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 Sun Microsystems Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., Franklin Street, Fifth Floor, +# Boston MA 02110-1301 USA. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Script for sleep mode where Cthulhu ignores events and commands.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2024 Stormux" +__license__ = "LGPL" + +import cthulhu.debug as debug +import cthulhu.scripts.default as default +import cthulhu.input_event as input_event +import cthulhu.keybindings as keybindings +import cthulhu.messages as messages +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +class Script(default.Script): + """The sleep-mode script.""" + + def __init__(self, app): + super().__init__(app) + self.presentIfInactive = True + + def activate(self): + """Called when this script is activated.""" + tokens = ["SLEEP MODE: Activating script for", self.app] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + # Only keep the sleep mode toggle binding active + self.removeKeyGrabs() + self.addKeyGrabs() + + # Present sleep mode status + self.clearBraille() + self.presentMessage(messages.SLEEP_MODE_ENABLED_FOR % AXObject.get_name(self.app)) + + def deactivate(self): + """Called when this script is deactivated.""" + tokens = ["SLEEP MODE: De-activating script for", self.app] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.removeKeyGrabs() + + def getKeyBindings(self): + """Only provide the key binding needed to exit sleep mode.""" + keyBindings = keybindings.KeyBindings() + + keyBindings.load([("q", keybindings.defaultModifierMask, + keybindings.CTHULHU_CTRL_ALT_MODIFIER_MASK | keybindings.SHIFT_ALT_MODIFIER_MASK, + "toggleSleepModeHandler")], + self.inputEventHandlers) + return keyBindings + + def setupInputEventHandlers(self): + """Sets up the input event handlers for sleep mode.""" + super().setupInputEventHandlers() + self.inputEventHandlers["toggleSleepModeHandler"] = \ + input_event.InputEventHandler( + Script.toggleSleepMode, + "Toggles sleep mode on/off") + + def toggleSleepMode(self, input_event=None): + """Toggles between sleep mode and regular mode.""" + script_manager = _scriptManager + script_manager.setActiveScript(script_manager.getDefaultScript(), "Sleep mode toggled") + self.presentMessage(messages.SLEEP_MODE_DISABLED_FOR % AXObject.get_name(self.app)) + return True + + def locusOfFocusChanged(self, event, oldLocusOfFocus, newLocusOfFocus): + """Handles changes of focus of interest to the script.""" + tokens = ["SLEEP MODE: focus changed from", oldLocusOfFocus, "to", newLocusOfFocus] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if oldLocusOfFocus is None and AXUtilities.is_application(AXObject.get_parent(newLocusOfFocus)): + self.clearBraille() + self.presentMessage(messages.SLEEP_MODE_ENABLED_FOR % AXObject.get_name(self.app)) + return + + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def presentKeyboardEvent(self, event): + """Prevents keyboard echo in sleep mode.""" + msg = "SLEEP MODE: Not presenting keyboard event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + def updateBraille(self, obj, **args): + """Don't update braille in sleep mode.""" + msg = "SLEEP MODE: Not updating braille." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + # Event handler overrides - all do nothing + def onActiveChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onActiveDescendantChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onBusyChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onCaretMoved(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onCheckedChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onChildrenAdded(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onChildrenRemoved(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onColumnReordered(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onDocumentLoadComplete(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onDocumentLoadStopped(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onDocumentReload(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onExpandedChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onFocus(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onFocusedChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onMouseButton(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onNameChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onSelectedChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onSelectionChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onShowingChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onTextAttributesChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onTextDeleted(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onTextInserted(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onTextSelectionChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onWindowActivated(self, event): + """Callback for window:activate accessibility events.""" + self.clearBraille() + self.presentMessage(messages.SLEEP_MODE_ENABLED_FOR % AXObject.get_name(self.app)) + + def onWindowDeactivated(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) diff --git a/src/cthulhu/scripts/sleepmode/script_utilities.py b/src/cthulhu/scripts/sleepmode/script_utilities.py new file mode 100644 index 0000000..13c5ee5 --- /dev/null +++ b/src/cthulhu/scripts/sleepmode/script_utilities.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 Sun Microsystems Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., Franklin Street, Fifth Floor, +# Boston MA 02110-1301 USA. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Utilities for Sleep Mode. Helps ensure we do nothing. When nothing is done, nothing is left undone.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2024 Stormux" +__license__ = "LGPL" + +import cthulhu.debug as debug +import cthulhu.script_utilities as script_utilities + +class Utilities(script_utilities.Utilities): + """Utilities class for the sleep-mode script.""" + + def willEchoCharacter(self, event): + """Returns True if we'll echo this character.""" + + msg = "SLEEP MODE: Will not echo character." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + def displayRegionChanged(self, obj, start, end, mode): + """Don't track changes in sleep mode.""" + + msg = "SLEEP MODE: Will not track display changes." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + def shouldPresentContext(self): + """Don't present context in sleep mode.""" + + msg = "SLEEP MODE: Will not present context." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False