76 Commits

Author SHA1 Message Date
Storm Dragon 3f7d60763d Merge branch 'testing'
Plugins are currently broken as Cthulhu moves over to pluggy. Libpeas and pygobject no longer play nicely together after latest updates. I really did not want to make a new release yet, because it is not ready, but a screen reader that at least reads instead of crashing at launch is better than nothing.
2025-04-03 20:17:14 -04:00
Storm Dragon 084d4fe85f Attempt to get pluggy working. 2025-04-03 20:10:54 -04:00
Storm Dragon 6bbe6e47fc Simplified the plugin code. Hopefully it at least somewhat works better now. 2025-04-03 14:00:06 -04:00
Storm Dragon 312476bbed A simple test plugin added for testing. 2025-03-27 23:23:01 -04:00
Storm Dragon 0005d5ec71 Activate the plugin in settings.py. 2025-03-26 01:45:58 -04:00
Storm Dragon 88ad9833d2 Forgot to update configure.ac. 2025-03-26 01:26:22 -04:00
Storm Dragon 654f1acc21 Start updating plugins. 2025-03-26 01:21:28 -04:00
Storm Dragon dfb53fff89 And another line I forgot to remove. 2025-03-25 20:18:57 -04:00
Storm Dragon 9cdb9f74e5 Decided to make the api helper part of the plugin_system_manager file. Forgot to remove the import from cthulhu.py. 2025-03-25 20:15:54 -04:00
Storm Dragon 41dae26d90 Fixed a message to be more clear. 2025-03-25 20:02:06 -04:00
Storm Dragon edc1cbf7af Continue work on switching to pluggy for plugins. 2025-03-25 19:59:50 -04:00
Storm Dragon d3d268004b Start migration to pluggy for plugins. 2025-03-25 19:41:57 -04:00
Didier Spaier a8e16fcf01 Toggle screen reader keyboard shortcut for desktops relying on glib-2.0/gio such as Mate. 2024-12-23 14:29:10 -05:00
Storm Dragon 6bbf3d0e67 Merge branch 'testing' latest changes merged. 2024-12-22 19:04:57 -05:00
Storm Dragon cbe3424e29 Fix the version.py file in preparation for merging. 2024-12-22 19:04:39 -05:00
Storm Dragon 1cf566c37c Error out if libpeas is not found during build. 2024-12-22 18:59:48 -05:00
Storm Dragon 936153f307 Fixed typo in keybinding. 2024-12-22 17:00:36 -05:00
Storm Dragon 29f8697a9f Fix missing method in default.py for scripts. 2024-12-22 15:16:18 -05:00
Storm Dragon ba735c554b Try to fix sleep mode so it is actually detected. 2024-12-22 14:49:31 -05:00
Storm Dragon 1c9ca14272 Attempt to back port sleepmode. 2024-12-22 14:22:56 -05:00
Storm Dragon d6af91bf42 Added version to active plugins. Reverted keybind to cthulhu+shift+v 2024-12-19 09:44:01 -05:00
Storm Dragon 5dd872535d Temperarily change the keyboard short fo version to cthulhu+x. 2024-12-19 09:30:59 -05:00
Storm Dragon 8e9ea3af5a Attempt to fix the cthulhu+shift+v keybinding. 2024-12-19 08:37:45 -05:00
Storm Dragon a40087cd20 Update configure.ac. 2024-12-19 08:29:11 -05:00
Storm Dragon 35acddeb8f Added Display Version plugin, cthul+shift=V. 2024-12-19 08:20:21 -05:00
Storm Dragon 327ad99e49 Preparing for stable tag release. 2024-12-18 19:49:25 -05:00
Storm Dragon c46cf1c939 Merge branch 'testing' fixed preferences GUI. 2024-12-18 19:45:59 -05:00
Storm Dragon 80033b3f37 Fixed missing function. 2024-12-18 19:41:39 -05:00
Storm Dragon 53e6e095b3 Oops, forgot to change orca to cthulhu in a couple of spots, no worky. 2024-12-18 19:33:16 -05:00
Storm Dragon d863cf0353 Fixed the preferences gui keyboard shortcut. 2024-12-18 19:25:24 -05:00
Storm Dragon a97bb30ed3 New version system merged. 2024-12-18 11:42:52 -05:00
Storm Dragon e9916bbcc4 Fixed wrong variable names in version. 2024-12-18 11:34:18 -05:00
Storm Dragon 6e480db630 Forgot to add the version file to the Makefile.am. 2024-12-18 11:28:57 -05:00
Storm Dragon 384479a0a5 Add the code name to the version. 2024-12-18 11:22:41 -05:00
Storm Dragon deccf846d8 Fix how version is obtained in PKGBUILD. 2024-12-18 11:01:55 -05:00
Storm Dragon 92a909edb8 Fixed path for version file in configure.ac. 2024-12-18 10:55:51 -05:00
Storm Dragon 55c7de8c65 Attempt to change the version number to be more like Fenrir's. Will work on adding the codename part if this works. 2024-12-18 10:52:07 -05:00
Storm Dragon 5a744a6809 One last modification to headers. 2024-12-18 10:20:50 -05:00
Storm Dragon 63539e8122 Updated headers in python files. 2024-12-18 10:05:44 -05:00
Storm Dragon 5178a66a6f Tidy up spacing. 2024-11-28 15:06:23 -05:00
Storm Dragon 89891f18af Forgot to restore _showPreferenceSUI. 2024-11-28 14:57:40 -05:00
Storm Dragon 71add76898 More fixes to removing classic preferences. 2024-11-28 14:48:34 -05:00
Storm Dragon 1a9eb35418 More fixes for preferences. 2024-11-28 06:32:21 -05:00
Storm Dragon ba6382c3cd Hopefully fix the -s flag which was broken by plugin updates. 2024-11-28 06:22:07 -05:00
Storm Dragon 17febf488c Another file edited. 2024-11-28 06:00:17 -05:00
Storm Dragon 09718e5901 Missed a file, remove the last of classic preferences plugin. 2024-11-28 05:56:08 -05:00
Storm Dragon 03bed6c5d4 Remove Classic Preference plugin because of breakages. 2024-11-28 05:46:35 -05:00
Storm Dragon d28e0086d9 Slackbuild added. 2024-11-24 13:59:46 -05:00
Storm Dragon 515827e830 Bump pkgver for the PKGBUILD. 2024-11-01 11:49:27 -04:00
Storm Dragon 4f6260eb6f Version bump, check for libpeas in configure.ac. 2024-11-01 11:36:08 -04:00
Storm Dragon b6a44df82a updated the README. 2024-10-28 21:14:23 -04:00
Storm Dragon 0cadb12c00 Merge branch 'sps' of git.stormux.org:storm/cthulhu into sps 2024-10-23 19:16:07 -04:00
Storm Dragon 2f6fde6896 Removed add SimplePluginSystem as it is now done. 2024-10-23 19:15:45 -04:00
Chrys 89467b6988 remove unused variable 2024-10-24 00:58:11 +02:00
Chrys 17d2773344 make shortcuts work, migrate to plugin api 2024-10-24 00:55:22 +02:00
Chrys 0abe30791d fix all syntax issues in SOPS 2024-10-24 00:08:25 +02:00
Chrys 087dcc3ab2 add SimplePlugin to settings.py 2024-10-23 19:06:12 +02:00
Chrys 4eaa4fae86 add SimplePlugin to configure.ac 2024-10-23 19:04:22 +02:00
Chrys ba0169b016 add SimplePlugin to make 2024-10-23 19:03:06 +02:00
Storm Dragon 7605e7d60f Found some stuff I missed on the initial attempt to get this working. 2024-10-23 09:37:42 -04:00
Storm Dragon 9562c08130 fixed author lines, I think. 2024-10-23 08:16:37 -04:00
Storm Dragon 8a9bbefeac Initial attempt at chaning SOPS into a plugin for Cthulhu. 2024-10-23 07:58:44 -04:00
Storm Dragon 9f2a349239 Version bump to 0.3. 2024-10-21 17:52:09 -04:00
Chrys 9e749ef62e add missing Makefile include 2024-10-21 23:28:25 +02:00
Chrys 3f1eb6e5af add to settings.conf 2024-10-21 23:18:58 +02:00
Chrys f6085a187e make ClassicPreferences plugin work 2024-10-21 23:17:13 +02:00
Storm Dragon 814e210a7f Added ClassicPreferences plugin but it needs more work before it is functioning. 2024-10-21 16:48:01 -04:00
Storm Dragon 41cf7ad88d Hopefully got the desktop file working. 2024-10-21 13:20:40 -04:00
Storm Dragon dfc0ea7351 Forgot to do version bump for PKGBUILD. 2024-10-21 13:01:01 -04:00
Storm Dragon 064c325e60 Updated PKGBUILD. 2024-10-21 12:55:42 -04:00
Storm Dragon 4a90dfa38f Updated README. Bumped version to 0.2. 2024-10-21 12:53:24 -04:00
Storm Dragon 8245135cbd Self-voicing no longer has the pid on the end of the /tmp/cthulhu.sock file. 2024-10-21 12:07:48 -04:00
Storm Dragon 604dc67407 Updated some message text. 2024-10-20 23:07:05 -04:00
Storm Dragon 524bdd049a Updated the README somewhat. 2024-10-20 21:23:20 -04:00
Storm Dragon 7445eacbca Fixed the PKGBUILD. 2024-10-20 21:16:28 -04:00
Storm Dragon bc660dc217 More cleanup, changing references to orca to cthulhu instead. 2024-10-20 21:11:35 -04:00
682 changed files with 14637 additions and 2111 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
Orca Authors
Cthulhu Authors
Marc Mulcahy
Willie Walker
+8 -8
View File
@@ -1867,7 +1867,7 @@
* Release Cthulhu v2.24.0. Somehow I forgot to mark this.
The svn version is 4292 and can be found at the tag
of ORCA_24_0.
of CTHULHU_24_0.
2008-09-20 Joanmarie Diggs <joanmarie.diggs@gmail.com>
@@ -5747,7 +5747,7 @@
* src/cthulhu/app_gui_prefs.py:
src/cthulhu/cthulhu_gui_prefs.py:
src/cthulhu/cthulhu_state.py:
Fix breakage to ORCA_MODIFIER-Control-Space to bring up the
Fix breakage to CTHULHU_MODIFIER-Control-Space to bring up the
application specific Cthulhu preferences dialog.
2007-12-12 Willie Walker <william.walker@sun.com>
@@ -10456,7 +10456,7 @@
Fix for bug #372273 - Add ability to configure app-specific
settings via GUI.
Adjusted <ORCA MODIFIER>+Control+Space to now bring up
Adjusted <CTHULHU MODIFIER>+Control+Space to now bring up
the application specific preferences dialog. The previous
usage (reload user settings) is now gone.
@@ -12574,7 +12574,7 @@
2007-01-07 Willie Walker <william.walker@sun.com>
* svn+ssh://wwalker@svn.gnome.org/svn/cthulhu/tags/ORCA_2_17_5:
* svn+ssh://wwalker@svn.gnome.org/svn/cthulhu/tags/CTHULHU_2_17_5:
final prep for v2.17.5. Everything below this line is included
in v2.17.5 - many many thanks to all involved.
@@ -17730,7 +17730,7 @@
* po/POTFILES.in: remove Gecko.py.
* configure.in: get the ORCA_SETUP_GLADE_DIR working better.
* configure.in: get the CTHULHU_SETUP_GLADE_DIR working better.
* src/cthulhu/mag.py: minor attempt to follow the caret when it
moves.
@@ -19296,7 +19296,7 @@
* src/cthulhu/{default.py, gnomespeechfactory.py, cthulhu-setup.in,
cthulhu.py, settings.py, speech.py}, src/cthulhu/scripts/Gecko.py:
migrate voice defaults to setting.py.
NOTE: THIS REQUIRES YOU TO RERUN ORCA-SETUP.
NOTE: THIS REQUIRES YOU TO RERUN CTHULHU-SETUP.
* src/cthulhu/*.py: use string constants to get settings (I got
bit by a mispelling when using raw strings).
@@ -19335,7 +19335,7 @@
src/cthulhu/scripts/{Gecko.py,metacity.py}: new speech structure
done in collaboration with T.V. Raman of Google who donated
code under the LGPL license. NOTE: THIS REQUIRES YOU TO
RERUN ORCA-SETUP.
RERUN CTHULHU-SETUP.
2005-11-14 Rich Burridge <rich.burridge@sun.com>
@@ -19359,7 +19359,7 @@
src/cthulhu/scripts/Gecko.py, src/cthulhu/scripts/gaim.py,
src/cthulhu/scripts/gcalctool.py, src/cthulhu/scripts/metacity.py: First
pass at new speech system based on conversations with T.V. Raman.
NOTE: THIS REQUIRES YOU TO RERUN ORCA-SETUP. If you don't cthulhu
NOTE: THIS REQUIRES YOU TO RERUN CTHULHU-SETUP. If you don't cthulhu
will fail on startup.
2005-11-09 Mike Pedersen <michael.pedersen@sun.com>
+1 -1
View File
@@ -1,6 +1,6 @@
Welcome to Cthulhu
We are excited to have you here and welcome your contributions to the Cthulhu screen reader project! This project is a fork of Orca, with a focus on creating an open and collaborative community where contributions are encouraged.
We are excited to have you here and welcome your contributions to the Cthulhu screen reader project! This project is a fork of Cthulhu, with a focus on creating an open and collaborative community where contributions are encouraged.
How to Contribute
+1 -1
View File
@@ -44,7 +44,7 @@ dist-hook:
echo Creating ChangeLog && \
( cd "$(top_srcdir)" && \
echo '# Generated by Makefile. Do not edit.'; echo; \
$(top_srcdir)/missing --run git log --pretty=format:"%ai %an <%ae>%n%n %s%n" --name-status ORCA_2_26_0.. ) > ChangeLog.tmp \
$(top_srcdir)/missing --run git log --pretty=format:"%ai %an <%ae>%n%n %s%n" --name-status CTHULHU_2_26_0.. ) > ChangeLog.tmp \
&& mv -f ChangeLog.tmp $(top_distdir)/ChangeLog \
|| ( rm -f ChangeLog.tmp ; \
echo Failed to generate ChangeLog >&2 ); \
+5 -5
View File
@@ -11255,7 +11255,7 @@ Firefox:
* Fix for bug 445578 - Link preview information would be desirable for
Firefox. This is obtained when performing a "Where Am I" operation
(KP_Enter for desktop bindings, ORCA_MODIFIER+Return for laptop
(KP_Enter for desktop bindings, CTHULHU_MODIFIER+Return for laptop
bindings). Many thanks to new community member Scott Haeger for
this functionality!
@@ -11439,7 +11439,7 @@ General Cthulhu:
of tool tips
* Fix for bug 372273 - Add ability to configure app-specific settings
via GUI. NOTE: Adjusted ORCA_MODIFIER+Control+Space to now bring
via GUI. NOTE: Adjusted CTHULHU_MODIFIER+Control+Space to now bring
up the application-specific preferences dialog. The previous usage
(reload user settings) is now gone.
@@ -11476,7 +11476,7 @@ Firefox:
stylesheet results in bad behavior
* Partial fix for bug 420540 - Firefox keyboard control wish list.
ORCA_MODIFIER+Z will now toggle the structural navigation keys
CTHULHU_MODIFIER+Z will now toggle the structural navigation keys
on/off.
* Fix for bug 422924 - Add more support for accessing HTML tables in
@@ -11493,8 +11493,8 @@ Firefox:
of verbiage. Therefore, these are all customizable settings.
* Fix for bug 423427 - Need to add form field structural navigation in
Firefox. ORCA_MODIFIER+Tab should move you to the next form field
and ORCA_MODIFIER+Shift+Tab should move you to the previous form
Firefox. CTHULHU_MODIFIER+Tab should move you to the next form field
and CTHULHU_MODIFIER+Shift+Tab should move you to the previous form
field.
* Fix for bug 423435 - Cthulhu is too chatty when loading a page in
+22 -15
View File
@@ -1,4 +1,4 @@
# Cthulhu v45.3
# Cthulhu
## Introduction
@@ -11,20 +11,12 @@ technology service provider interface (AT-SPI), which is the primary
assistive technology infrastructure for the Solaris and Linux
operating environments. Applications and toolkits supporting the
AT-SPI include the GNOME GTK+ toolkit, the Java platform's Swing
toolkit, OpenOffice/LibreOffice, Gecko, and WebKitGtk. AT-SPI support
for the KDE Qt toolkit is currently being pursued.
toolkit, OpenOffice/LibreOffice, Gecko, WebKitGtk, and KDE Qt toolkit.
See also <http://wiki.gnome.org/Projects/Cthulhu> for detailed information
on Cthulhu, including how to run Cthulhu, how to communicate with the Cthulhu user
community, and where to log bugs and feature requests.
## Dependencies
Cthulhu v45.x is supported on GNOME 45.x only. We highly suggest you
use the latest releases of GNOME because they contain accessibility
infrastructure and application bug fixes that help Cthulhu work better.
Cthulhu also has the following dependencies:
Cthulhu has the following dependencies:
* Python 3 - Python platform
* pygobject-3.0 - Python bindings for the GObject library
@@ -37,12 +29,14 @@ Cthulhu also has the following dependencies:
* liblouis - Liblouis (<http://liblouis.org/>) support for contracted braille (optional)
* py-setproctitle - Python library to set the process title (optional)
* gstreamer-1.0 - GStreamer - Streaming media framework (optional)
* socat - Used for self-voicing functionality.
* libpeas - For the plugin system.
You are strongly encouraged to also have the latest stable versions
of AT-SPI2 and ATK for the GNOME 45.x release.
of AT-SPI2 and ATK.
## NOTE FOR BRLTTY USERS:
## Braille
Cthulhu depends upon the Python bindings for BrlAPI available in BrlTTY v4.5
or better. You can determine if the Python bindings for BrlAPI are
@@ -66,10 +60,23 @@ learn mode, press "Escape." Finally, the preferences dialog contains
a "Key Bindings" tab that lists the keyboard binding for Cthulhu.
For more information, see the Cthulhu documentation which is available
within Cthulhu as well as at: <https://help.gnome.org/users/cthulhu/stable/>
within Cthulhu.
## Scripting Cthulhu
So, you want to write a script for Cthulhu? The best thing to do is
start by looking at other scripts under the src/cthulhu/scripts/ hierarchy
of the source tree.
of the source tree. Cthulhu also has an excellent plugin system, more documentation and examples coming soon.
## Self-voicing
Cthulhu offers a mechanism through which messages may be spoken directly by the screen reader. Usage is as follows:
```bash
# Speak hello world.
echo "Hello world." | socat - UNIX-CLIENT:/tmp/cthulhu.sock
# Speak Hello world without interrupting the previous speech.
echo "<!#APPEND#!>Hello world." | socat - UNIX-CLIENT:/tmp/cthulhu.sock
# Make hello world persistant in Braille.
echo "Hello world.<#APPEND#>" | socat - UNIX-CLIENT:/tmp/cthulhu.sock
```
+7 -7
View File
@@ -22,17 +22,17 @@ Make sure you are up to date:
Update ./NEWS with changes from the last tagged release. You can use
commands like the following:
Detailed commits since the ORCA_40_BETA tag:
Detailed commits since the CTHULHU_40_BETA tag:
git log ORCA_40_BETA..
git log CTHULHU_40_BETA..
Short list of translation changes with author names and files:
git log ORCA_40_BETA.. --grep translation --pretty=format:"%s - %an" --name-only
git log CTHULHU_40_BETA.. --grep translation --pretty=format:"%s - %an" --name-only
Quick-and-dirty formatted list of translation changes:
git log ORCA_40_BETA.. --grep translation --pretty=format:"%s,%an" --name-only |
git log CTHULHU_40_BETA.. --grep translation --pretty=format:"%s,%an" --name-only |
awk -F/ '/\.(po|am)/ {gsub("(\.po|Makefile.am)", "", $NF); printf(",%s",$NF); next;}
{gsub("(Updated* |Add(ed)* | translation| help)", "", $0); printf("\n%s",$0);}' |
awk -F, '!seen[$0]++ {if (NF == 3) printf(" %-15s %-25s %s\n", $3, $1, $2);}' |
@@ -40,7 +40,7 @@ Quick-and-dirty formatted list of translation changes:
Short list of non-translation commits:
git log ORCA_40_BETA.. --grep translation --invert-grep --pretty=format:" * %s%n"
git log CTHULHU_40_BETA.. --grep translation --invert-grep --pretty=format:" * %s%n"
NOTE: You should also make sure the external dependencies listed in
configure.ac and README are accurate.
@@ -56,8 +56,8 @@ COMMIT RELEASE CHANGES AND TAG THE RELEASE:
git commit -a
git push
git tag -a -s ORCA_40_RC
git push origin ORCA_40_RC
git tag -a -s CTHULHU_40_RC
git push origin CTHULHU_40_RC
UPLOAD THE RELEASE:
-1
View File
@@ -1,4 +1,3 @@
- Add Simple Orca Plugin System as native code for Cthulhu
- Merge in sleep mode.
- Add in ocrdesktop code so that Cthulhu has native ocr support.
- Get rid of build systems. My hope is git clone and run so long as requirements are satisfied.
+16 -3
View File
@@ -1,4 +1,7 @@
m4_define([cthulhu_version], [0.1])
m4_define([get_version], [m4_esyscmd_s([
grep "^version = " src/cthulhu/cthulhuVersion.py | sed 's/version = "\(.*\)"/\1/'
])])
m4_define([cthulhu_version], [get_version])
m4_define(pygobject_required_version, 3.18)
m4_define(atspi_required_version, 2.48)
@@ -28,6 +31,7 @@ PKG_CHECK_MODULES([PYGOBJECT], [pygobject-3.0 >= pygobject_required_version])
PKG_CHECK_MODULES([ATSPI2], [atspi-2 >= atspi_required_version])
PKG_CHECK_MODULES([ATKBRIDGE], [atk-bridge-2.0 >= atkbridge_required_version])
PKG_CHECK_MODULES([GSTREAMER], [gstreamer-1.0], [gstreamer="yes"], [gstreamer="no"])
PKG_CHECK_MODULES([LIBPEAS], [libpeas-1.0])
dnl Needed programs
AC_PROG_INSTALL
@@ -42,6 +46,7 @@ AM_PATH_PYTHON(3.3)
AM_CHECK_PYMOD(gi,,,[AC_MSG_ERROR(Could not find python module: gi)])
AM_CHECK_PYMOD(json,,,[AC_MSG_ERROR(Could not find python module: json)])
AM_CHECK_PYMOD(pluggy,,[pluggy_available="yes"],[pluggy_available="no"])
AM_CHECK_PYMOD(brlapi,,[brlapi_available="yes"],[brlapi_available="no"])
AM_CHECK_PYMOD(speechd,,[speechd_available="yes"],[speechd_available="no"])
AC_ARG_WITH([liblouis],
@@ -106,6 +111,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
@@ -123,12 +129,14 @@ src/cthulhu/plugins/ByeCthulhu/Makefile
src/cthulhu/plugins/HelloCthulhu/Makefile
src/cthulhu/plugins/PluginManager/Makefile
src/cthulhu/plugins/Clipboard/Makefile
src/cthulhu/plugins/HelloWorld/Makefile
src/cthulhu/plugins/DisplayVersion/Makefile
src/cthulhu/plugins/hello_world/Makefile
src/cthulhu/plugins/CapsLockHack/Makefile
src/cthulhu/plugins/SelfVoice/Makefile
src/cthulhu/plugins/self_voice/Makefile
src/cthulhu/plugins/Date/Makefile
src/cthulhu/plugins/Time/Makefile
src/cthulhu/plugins/MouseReview/Makefile
src/cthulhu/plugins/SimplePluginSystem/Makefile
src/cthulhu/backends/Makefile
src/cthulhu/cthulhu_bin.py
src/cthulhu/cthulhu_i18n.py
@@ -156,7 +164,12 @@ echo
echo "NOTE: Sound support requires gstreamer-1.0."
fi
if test "$have_libpeas" = "no"; then
AC_MSG_ERROR([libpeas-1.0 >= 1.20 is required])
fi
echo
echo Use pluggy: $pluggy_available
echo Use speech-dispatcher: $speechd_available
echo Use brltty: $brlapi_available
echo Use liblouis: $louis_available
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<schemalist gettext-domain="slint">
<schema id="toggle.screenreader" path="/toggle/screenreader/">
<key name="binding" type="s">
<default>'&lt;Shift&gt;&lt;Alt&gt;v'</default>
<summary>Keybinding</summary>
<description>Keybinding associated to toggle screen reader.</description>
</key>
<key name="action" type="s">
<default>'/opt/I38/scripts/toggle_screenreader.sh 1>/dev/null'</default>
<summary>Command</summary>
<description>Command to toggle the screen reader between orca and cthulhu.</description>
</key>
<key name="name" type="s">
<default>'Toggle screenreader'</default>
<summary>Name</summary>
<description>Description associated to toggle screen reader.</description>
</key>
</schema>
</schemalist>
+29 -42
View File
@@ -1,59 +1,46 @@
[Desktop Entry]
Type=Application
Name[an]=Lector de pantalla Cthulhu
Name[ast]=Llector de pantalla d'Cthulhu
Name[be]=Чытач з экрана Cthulhu
Name[bg]=Cthulhu — екранен четец
Name[bs]=Cthulhu čitač ekrana
Name[ast]=Llector de pantalla Cthulhu
Name[be]=ÐÑÑÐÑÑÐ Cthulhu
Name[bg]=Cthulhu âÐÐÐ ÑÑÑName[bs]=Cthulhu ÄtaÄekrana
Name[ca]=Lector de pantalla Cthulhu
Name[cs]=Čtečka obrazovky Cthulhu
Name[da]=Skærmlæseren Cthulhu
Name[cs]=ÄeÄa obrazovky Cthulhu
Name[da]=SkÃmlÃeren Cthulhu
Name[de]=Cthulhu-Bildschirmleser
Name[el]=Αναγνώστης οθόνης Cthulhu
Name[el]=ÎÎÎÏÎ ÎÏÎ Cthulhu
Name[en_GB]=Cthulhu Screen Reader
Name[eo]=Ekranlegilo Orko
Name[eo]=Ekranlegilo Cthulhu
Name[es]=Lector de pantalla Cthulhu
Name[eu]=Cthulhu pantaila-irakurlea
Name[fa]=صفحه‌خوان اورکا
Name[fi]=Cthulhu-näytönlukija
Name[fr]=Lecteur d’écran Cthulhu
Name[fa]=ØØâØ Cthulhu
Name[fi]=Cthulhu-nÃtÃlukija
Name[fr]=Lecteur dâran Cthulhu
Name[gl]=Lector da pantalla Cthulhu
Name[he]=מקריא המסך Cthulhu
Name[hi]=Cthulhu स्क्रीन वाचक
Name[hu]=Orka képernyőolvasó
Name[id]=Pembaca Layar Cthulhu
Name[is]=Cthulhu skjálestur
Name[he]=××××× Cthulhu
Name[hi]=Cthulhu àààà
Name[hu]=Cthulhu kÃernyÅlvasÃName[id]=Pembaca Layar Cthulhu
Name[is]=Cthulhu skjÃestur
Name[it]=Lettore schermo Cthulhu
Name[ka]=Cthulhu - ეკრანის მკითხველი
Name[kk]=Cthulhu экраннан оқитын қолданбасы
Name[lt]=Cthulhu ekrano skaityklė
Name[lv]=Cthulhu ekrāna lasītājs
Name[mk]=Cthulhu читач на екранот
Name[nb]=Cthulhu skjermleser
Name[ne]=ओर्का दृष्टि वाचक
Name[nl]=Cthulhu schermlezer
Name[ka]=Cthulhu - ááááááName[kk]=Cthulhu ÑÑÐÐ ÐÐÑ ÒÐÐÐÑ
Name[lt]=Cthulhu ekrano skaityklÄName[lv]=Cthulhu ekrÄa lasÄÄs
Name[mk]=Cthulhu ÑÑÑÐ ÐÑÐÑName[nb]=Cthulhu skjermleser
Name[ne]=Cthulhu àà ààame[nl]=Cthulhu schermlezer
Name[oc]=Lector d'ecran Cthulhu
Name[pa]=ਓਰਕਾ ਸਕਰੀਨ ਰੀਡਰ
Name[pl]=Czytnik ekranowy Cthulhu
Name[pt]=Leitor de ecrã Cthulhu
Name[pa]=Cthulhu ààààame[pl]=Czytnik ekranowy Cthulhu
Name[pt]=Leitor de ecrÃCthulhu
Name[pt_BR]=Leitor de tela Cthulhu
Name[ro]=Cititorul de ecran Cthulhu
Name[ru]=Экранный диктор Cthulhu
Name[sl]=Zaslonski bralnik Orka
Name[sr]=Читач екрана Орка
Name[sv]=Cthulhu skärmläsare
Name[ta]=ஆர்கா திரை படிப்பி
Name[te]=ఓర్కా తెరచదువరి
Name[tg]=Хонандаи экрани Cthulhu
Name[ru]=ÐÑÐÑ ÐÐÐ Cthulhu
Name[sl]=Zaslonski bralnik Cthulhu
Name[sr]=ÐÑÑÐÑÐ Cthulhu
Name[sv]=Cthulhu skÃmlÃare
Name[ta]=Cthulhu àààà
Name[te]=Cthulhu ààà
Name[tg]=ÐÐÐÐ ÑÑÐ Cthulhu
Name[tr]=Cthulhu Ekran Okuyucu
Name[ug]=Cthulhu ئېكران ئوقۇغۇ
Name[uk]=Інструмент читання з екрана «Cthulhu»
Name[zh_CN]=Cthulhu 屏幕阅读器
Name[zh_HK]=Cthulhu 螢幕閱讀器
Name=Cthulhu Screen Reader
Name[ug]=Cthulhu ØÙØ ØÙØ
Name[uk]=ÐÑÑÐÐ ÑÑÐÑÐÐÑÐ ÂthulhuÂName[zh_CN]=Cthulhu åèName[zh_HK]=Cthulhu èèName=Cthulhu Screen Reader
Exec=cthulhu
NoDisplay=true
AutostartCondition=GSettings org.gnome.desktop.a11y.applications screen-reader-enabled
X-GNOME-AutoRestart=true
#X-GNOME-Autostart-Phase=Initialization
OnlyShowIn=GNOME;MATE;Unity;Cinnamon;
+7 -3
View File
@@ -1,7 +1,7 @@
# Maintainer: Storm Dragon <storm_dragon@stormux.org>
pkgname=cthulhu
pkgver=0.1
pkgver=0.4
pkgrel=1
pkgdesc="Screen reader for individuals who are blind or visually impaired forked from Orca"
url="https://git.stormux.org/storm/cthulhu"
@@ -26,6 +26,7 @@ depends=(
python-cairo
python-gobject
python-setproctitle
socat
speech-dispatcher
xorg-xkbcomp
xorg-xmodmap
@@ -35,8 +36,6 @@ makedepends=(
itstool
yelp-tools
)
groups=(gnome)
_commit=9e77d1baf9bd24b78d7499ad9b2e8bb80c9a0c81 # tags/ORCA_45_1^0
source=("git+https://git.stormux.org/storm/cthulhu.git")
b2sums=('SKIP')
@@ -45,6 +44,11 @@ prepare() {
NOCONFIGURE=1 ./autogen.sh
}
pkgver() {
cd cthulhu
grep "^version = " src/cthulhu/cthulhuVersion.py | sed 's/version = "\(.*\)"/\1/'
}
build() {
cd cthulhu
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var
+98
View File
@@ -0,0 +1,98 @@
#!/bin/bash
# Slackware build script for cthulhu
# Created based on PKGBUILD from Storm Dragon <storm_dragon@stormux.org>
cd $(dirname $0) ; CWD=$(pwd)
PRGNAM=cthulhu
VERSION=${VERSION:-0.4}
BUILD=${BUILD:-1}
TAG=storm
PKGTYPE=txz
export PYTHON=/usr/bin/python3.11
if [ -z "$ARCH" ]; then
case "$( uname -m )" in
i?86) ARCH=i586 ;;
arm*) ARCH=arm ;;
*) ARCH=$( uname -m ) ;;
esac
fi
# If the variable PRINT_PACKAGE_NAME is set, then this script will report what
# the name of the created package would be, and then exit. This information
# could be useful to other scripts.
if [ ! -z "${PRINT_PACKAGE_NAME}" ]; then
echo "$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE"
exit 0
fi
TMP=$CWD
PKG=$TMP/package-$PRGNAM
OUTPUT=$CWD
if [ "$ARCH" = "i586" ]; then
SLKCFLAGS="-O2 -march=i586 -mtune=i686"
LIBDIRSUFFIX=""
elif [ "$ARCH" = "i686" ]; then
SLKCFLAGS="-O2 -march=i686 -mtune=i686"
LIBDIRSUFFIX=""
elif [ "$ARCH" = "x86_64" ]; then
SLKCFLAGS="-O2 -fPIC"
LIBDIRSUFFIX="64"
else
SLKCFLAGS="-O2"
LIBDIRSUFFIX=""
fi
set -e
rm -rf $PKG
mkdir -p $TMP $PKG $OUTPUT
cd $TMP
rm -rf $PRGNAM-$VERSION
git clone https://git.stormux.org/storm/cthulhu.git $PRGNAM-$VERSION
cd $PRGNAM-$VERSION
chown -R root:root .
find -L . \
\( -perm 777 -o -perm 775 -o -perm 750 -o -perm 711 -o -perm 555 \
-o -perm 511 \) -exec chmod 755 {} \; -o \
\( -perm 666 -o -perm 664 -o -perm 640 -o -perm 600 -o -perm 444 \
-o -perm 440 -o -perm 400 \) -exec chmod 644 {} \;
# Prepare the source
NOCONFIGURE=1 ./autogen.sh
CFLAGS="$SLKCFLAGS" \
CXXFLAGS="$SLKCFLAGS" \
./configure \
--prefix=/usr \
--libdir=/usr/lib${LIBDIRSUFFIX} \
--sysconfdir=/etc \
--localstatedir=/var \
--mandir=/usr/man \
--docdir=/usr/doc/$PRGNAM-$VERSION \
--build=$ARCH-slackware-linux
make
make install DESTDIR=$PKG
find $PKG -print0 | xargs -0 file | grep -e "executable" -e "shared object" | grep ELF \
| cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true
mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION
cp -a AUTHORS COPYING ChangeLog NEWS README.md \
$PKG/usr/doc/$PRGNAM-$VERSION
cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild
mkdir -p $PKG/install
cat $CWD/slack-desc > $PKG/install/slack-desc
cat $CWD/doinst.sh > $PKG/install/doinst.sh
cd $PKG
# let's avoid a "bad interpreter error
sed "s,#!python3.11,#!/usr/bin/python3.11," usr/bin/cthulhu > dummy
mv dummy usr/bin/cthulhu
chmod 755 usr/bin/cthulhu
/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE
+28
View File
@@ -0,0 +1,28 @@
Cthulhu is a screen reader for individuals who are blind or visually impaired,
forked from Orca. It provides access to applications and toolkits that support
the AT-SPI (e.g., the GNOME desktop).
This screen reader helps users navigate their desktop environment and applications
through speech synthesis and braille output.
After installation, you can start Cthulhu through the GNOME desktop environment
or by running 'cthulhu' from the command line.
DEPENDENCIES:
This package requires the following packages, all available from SlackBuilds.org:
- at-spi2-core
- brltty
- gobject-introspection
- gsettings-desktop-schemas
- gstreamer
- gst-plugins-base
- gst-plugins-good
- gtk3
- liblouis
- libpeas
- libwnck3
- python3-atspi
- python3-cairo
- python3-gobject
- python3-setproctitle
- speech-dispatcher
+10
View File
@@ -0,0 +1,10 @@
PRGNAM="cthulhu"
VERSION="0.4"
HOMEPAGE="https://git.stormux.org/storm/cthulhu"
DOWNLOAD="https://git.stormux.org/storm/cthulhu.git"
MD5SUM="SKIP"
DOWNLOAD_x86_64=""
MD5SUM_x86_64=""
REQUIRES="at-spi2-core brltty gobject-introspection gsettings-desktop-schemas gstreamer gst-plugins-base gst-plugins-good gtk3 liblouis libpeas libwnck3 python3-atspi python3-cairo python3-gobject python3-setproctitle speech-dispatcher"
MAINTAINER="Storm Dragon"
EMAIL="storm_dragon@stormux.org"
+98
View File
@@ -0,0 +1,98 @@
#!/bin/bash
# Slackware build script for cthulhu
# Created based on PKGBUILD from Storm Dragon <storm_dragon@stormux.org>
cd $(dirname $0) ; CWD=$(pwd)
PRGNAM=cthulhu
VERSION=${VERSION:-0.4}
BUILD=${BUILD:-1}
TAG=storm
PKGTYPE=txz
export PYTHON=/usr/bin/python3.11
if [ -z "$ARCH" ]; then
case "$( uname -m )" in
i?86) ARCH=i586 ;;
arm*) ARCH=arm ;;
*) ARCH=$( uname -m ) ;;
esac
fi
# If the variable PRINT_PACKAGE_NAME is set, then this script will report what
# the name of the created package would be, and then exit. This information
# could be useful to other scripts.
if [ ! -z "${PRINT_PACKAGE_NAME}" ]; then
echo "$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE"
exit 0
fi
TMP=$CWD
PKG=$TMP/package-$PRGNAM
OUTPUT=$CWD
if [ "$ARCH" = "i586" ]; then
SLKCFLAGS="-O2 -march=i586 -mtune=i686"
LIBDIRSUFFIX=""
elif [ "$ARCH" = "i686" ]; then
SLKCFLAGS="-O2 -march=i686 -mtune=i686"
LIBDIRSUFFIX=""
elif [ "$ARCH" = "x86_64" ]; then
SLKCFLAGS="-O2 -fPIC"
LIBDIRSUFFIX="64"
else
SLKCFLAGS="-O2"
LIBDIRSUFFIX=""
fi
set -e
rm -rf $PKG
mkdir -p $TMP $PKG $OUTPUT
cd $TMP
rm -rf $PRGNAM-$VERSION
git clone https://git.stormux.org/storm/cthulhu.git $PRGNAM-$VERSION
cd $PRGNAM-$VERSION
chown -R root:root .
find -L . \
\( -perm 777 -o -perm 775 -o -perm 750 -o -perm 711 -o -perm 555 \
-o -perm 511 \) -exec chmod 755 {} \; -o \
\( -perm 666 -o -perm 664 -o -perm 640 -o -perm 600 -o -perm 444 \
-o -perm 440 -o -perm 400 \) -exec chmod 644 {} \;
# Prepare the source
NOCONFIGURE=1 ./autogen.sh
CFLAGS="$SLKCFLAGS" \
CXXFLAGS="$SLKCFLAGS" \
./configure \
--prefix=/usr \
--libdir=/usr/lib${LIBDIRSUFFIX} \
--sysconfdir=/etc \
--localstatedir=/var \
--mandir=/usr/man \
--docdir=/usr/doc/$PRGNAM-$VERSION \
--build=$ARCH-slackware-linux
make
make install DESTDIR=$PKG
find $PKG -print0 | xargs -0 file | grep -e "executable" -e "shared object" | grep ELF \
| cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true
mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION
cp -a AUTHORS COPYING ChangeLog NEWS README.md \
$PKG/usr/doc/$PRGNAM-$VERSION
cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild
mkdir -p $PKG/install
cat $CWD/slack-desc > $PKG/install/slack-desc
cat $CWD/doinst.sh > $PKG/install/doinst.sh
cd $PKG
# let's avoid a "bad interpreter error
sed "s,#!python3.11,#!/usr/bin/python3.11," usr/bin/cthulhu > dummy
mv dummy usr/bin/cthulhu
chmod 755 usr/bin/cthulhu
/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE
+9
View File
@@ -0,0 +1,9 @@
if [ -x /usr/bin/update-desktop-database ]; then
/usr/bin/update-desktop-database -q usr/share/applications >/dev/null 2>&1
fi
if [ -e usr/share/icons/hicolor/icon-theme.cache ]; then
if [ -x /usr/bin/gtk-update-icon-cache ]; then
/usr/bin/gtk-update-icon-cache usr/share/icons/hicolor >/dev/null 2>&1
fi
fi
+19
View File
@@ -0,0 +1,19 @@
# HOW TO EDIT THIS FILE:
# The "handy ruler" below makes it easier to edit a package description.
# Line up the first '|' above the ':' following the base package name, and
# the '|' on the right side marks the last column you can put a character in.
# You must make exactly 11 lines for the formatting to be correct. It's also
# customary to leave one space after the ':' except on otherwise blank lines.
|-----handy-ruler------------------------------------------------------|
cthulhu: cthulhu (Screen reader for blind or visually impaired users)
cthulhu:
cthulhu: Cthulhu is a screen reader for individuals who are blind or visually
cthulhu: impaired, forked from Orca. It provides a way to access applications
cthulhu: and toolkits that support the AT-SPI (e.g., the GNOME desktop).
cthulhu:
cthulhu: Homepage: https://git.stormux.org/storm/cthulhu
cthulhu:
cthulhu:
cthulhu:
cthulhu:
+1 -1
View File
@@ -2710,7 +2710,7 @@ msgstr ""
"DENGUNA GARANTÍA; ensin denguna implicación de garantía de COMERCIABILIDÁ o CALIDÁ PA DENGÚN PROPÓSITU PARTICULAR. Consulta la Llicencia Pública Xeneral Reducida GNU pa más\n"
"detalles.\n"
"\n"
"Tendríes de recibir una copia de la Llicencia Pública Xeneral Reducida de GNU xuntu con ORCA, de lo contrario, escribi a la Free Software Foundation, Inc, Franklin\n"
"Tendríes de recibir una copia de la Llicencia Pública Xeneral Reducida de GNU xuntu con CTHULHU, de lo contrario, escribi a la Free Software Foundation, Inc, Franklin\n"
"Street, Fifth Floor, Boston, MA 02110-1301, EE. UU."
#. DESCRIP
+2 -2
View File
@@ -1,6 +1,6 @@
# translation of cthulhu.HEAD.po to Español
# Traducción de Cthulhu al Español
# This file is distributed under the same license as the ORCA package.
# This file is distributed under the same license as the CTHULHU package.
# Copyright (C) 2005 GNOME Foundation.
#
# Francisco Javier F. Serrador <serrador@cvs.gnome.org>, 2004, 2006.
@@ -15099,7 +15099,7 @@ msgstr ""
#~ "detalles.\n"
#~ "\n"
#~ "Debería haber recibido una copia de la Licencia Pública General Reducida "
#~ "de GNU junto con ORCA, de lo contrario, escriba a la Free Software "
#~ "de GNU junto con CTHULHU, de lo contrario, escriba a la Free Software "
#~ "Foundation, Inc, \n"
#~ "Franklin Street, Fifth Floor, Boston, MA 02110-1301, EE. UU."
+1 -1
View File
@@ -1,6 +1,6 @@
# Përkthimi i cthulhu.HEAD në shqip.
# Copyright (C) 2007 Free Software Foundation, Inc.
# This file is distributed under the same license as the ORCA package.
# This file is distributed under the same license as the CTHULHU package.
#
# Laurent Dhima <laurenti@alblinux.net>, 2007.
msgid ""
+26 -9
View File
@@ -1,10 +1,27 @@
# Ruff linter.
#
# Repository: https://github.com/astral-sh/ruff
#
# Documentation: https://beta.ruff.rs/docs/
[tool.ruff]
line-length = 100 # same as rustfmt
ignore = [
"E402", # Module level import not at top of file
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "cthulhu"
dynamic = ["version"]
description = "Fork of the Orca screen reader based on gnome-45"
readme = "README.md"
requires-python = ">=3.3"
license = { text = "LGPL-2.1-or-later" }
dependencies = [
"pygobject>=3.18",
"python-atspi>=2.48",
"brlapi; extra == 'braille'",
"python-speechd; extra == 'speech'",
"louis; extra == 'braille'"
]
[project.scripts]
cthulhu = "cthulhu.cthulhu:main"
[tool.hatch.version]
path = "src/cthulhu/__init__.py"
[tool.hatch.build.targets.wheel]
packages = ["src/cthulhu"]
+294
View File
@@ -0,0 +1,294 @@
#!/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
import argparse
import gi
gi.require_version("Atspi", "2.0")
from gi.repository import Atspi
import os
import signal
import subprocess
import sys
import time
def setup_paths():
"""Configure paths for both installed and source directory execution."""
currentDir = os.path.dirname(os.path.abspath(__file__))
# Check if running from source
if os.path.exists(os.path.join(currentDir, 'plugins')):
# Running from source directory
sys.path.insert(0, os.path.dirname(currentDir))
pythondir = currentDir
else:
# Running installed
sys.prefix = '/usr'
pythondir = os.path.join(sys.prefix, 'lib', f'python{sys.version_info.major}.{sys.version_info.minor}', 'site-packages')
sys.path.insert(1, pythondir)
# Set environment variables for resource paths
if 'CTHULHU_DATA_DIR' not in os.environ:
if os.path.exists(os.path.join(currentDir, 'plugins')):
os.environ['CTHULHU_DATA_DIR'] = currentDir
else:
os.environ['CTHULHU_DATA_DIR'] = os.path.join(sys.prefix, 'share', 'cthulhu')
# Set up paths before importing Cthulhu modules
setup_paths()
from cthulhu import debug
from cthulhu import messages
from cthulhu import settings
from cthulhu.ax_object import AXObject
from cthulhu.ax_utilities import AXUtilities
from cthulhu.cthulhu_platform import version
class ListApps(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
desktop = AXUtilities.get_desktop()
for app in AXObject.iter_children(desktop):
pid = AXObject.get_process_id(app)
try:
name = Atspi.Accessible.get_name(app) or "(none)"
except Exception:
name = "[DEAD]"
try:
cmdline = subprocess.getoutput('cat /proc/%s/cmdline' % pid)
except Exception:
cmdline = '(exception encountered)'
else:
cmdline = cmdline.replace('\x00', ' ')
print(time.strftime('%H:%M:%S', time.localtime()),
' pid: %5s %-25s %s' % (pid, name, cmdline))
parser.exit()
class Settings(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
settingsDict = getattr(namespace, 'settings', {})
invalid = getattr(namespace, 'invalid', [])
for value in values.split(','):
item = str.title(value).replace('-', '')
try:
test = 'enable%s' % item
eval('settings.%s' % test)
except AttributeError:
try:
test = 'show%s' % item
eval('settings.%s' % test)
except AttributeError:
invalid.append(value)
continue
settingsDict[test] = self.const
setattr(namespace, 'settings', settingsDict)
setattr(namespace, 'invalid', invalid)
class HelpFormatter(argparse.HelpFormatter):
def __init__(self, prog, indent_increment=2, max_help_position=32,
width=None):
super().__init__(prog, indent_increment, max_help_position, width)
def add_usage(self, usage, actions, groups, prefix=None):
super().add_usage(usage, actions, groups, messages.CLI_USAGE)
class Parser(argparse.ArgumentParser):
def __init__(self, *args, **kwargs):
super(Parser, self).__init__(
epilog=messages.CLI_EPILOG, formatter_class=HelpFormatter, add_help=False)
self.add_argument(
"-h", "--help", action="help", help=messages.CLI_HELP)
self.add_argument(
"-v", "--version", action="version", version=version, help=messages.CLI_VERSION)
self.add_argument(
"-r", "--replace", action="store_true", help=messages.CLI_REPLACE)
self.add_argument(
"-s", "--setup", action="store_true", help=messages.CLI_GUI_SETUP)
self.add_argument(
"-l", "--list-apps", action=ListApps, nargs=0,
help=messages.CLI_LIST_APPS)
self.add_argument(
"-e", "--enable", action=Settings, const=True,
help=messages.CLI_ENABLE_OPTION, metavar=messages.CLI_OPTION)
self.add_argument(
"-d", "--disable", action=Settings, const=False,
help=messages.CLI_DISABLE_OPTION, metavar=messages.CLI_OPTION)
self.add_argument(
"-p", "--profile", action="store",
help=messages.CLI_LOAD_PROFILE, metavar=messages.CLI_PROFILE_NAME)
self.add_argument(
"-u", "--user-prefs", action="store",
help=messages.CLI_LOAD_PREFS, metavar=messages.CLI_PREFS_DIR)
self.add_argument(
"--debug-file", action="store",
help=messages.CLI_DEBUG_FILE, metavar=messages.CLI_DEBUG_FILE_NAME)
self.add_argument(
"--debug", action="store_true", help=messages.CLI_ENABLE_DEBUG)
self._optionals.title = messages.CLI_OPTIONAL_ARGUMENTS
def parse_known_args(self, *args, **kwargs):
opts, invalid = super(Parser, self).parse_known_args(*args, **kwargs)
try:
invalid.extend(opts.invalid)
except Exception:
pass
if invalid:
print((messages.CLI_INVALID_OPTIONS + " ".join(invalid)))
if opts.debug_file:
opts.debug = True
elif opts.debug:
opts.debug_file = time.strftime('debug-%Y-%m-%d-%H:%M:%S.out')
return opts, invalid
def setProcessName(name):
"""Attempts to set the process name to the specified name."""
sys.argv[0] = name
try:
from setproctitle import setproctitle
except ImportError:
pass
else:
setproctitle(name)
return True
try:
from ctypes import cdll, byref, create_string_buffer
libc = cdll.LoadLibrary('libc.so.6')
stringBuffer = create_string_buffer(len(name) + 1)
stringBuffer.value = bytes(name, 'UTF-8')
libc.prctl(15, byref(stringBuffer), 0, 0, 0)
return True
except Exception:
pass
return False
def inGraphicalDesktop():
"""Returns True if we are in a graphical desktop."""
# TODO - JD: Make this desktop environment agnostic
try:
import gi
gi.require_version("Gdk", "3.0")
from gi.repository import Gdk
display = Gdk.Display.get_default()
except Exception:
return False
return display is not None
def otherCthulhus():
"""Returns the pid of any other instances of Cthulhu owned by this user."""
openFile = subprocess.Popen('pgrep -u %s -x cthulhu' % os.getuid(),
shell=True,
stdout=subprocess.PIPE).stdout
pids = openFile.read()
openFile.close()
cthulhus = [int(p) for p in pids.split()]
pid = os.getpid()
return [p for p in cthulhus if p != pid]
def cleanup(sigval):
"""Tries to clean up any other running Cthulhu instances owned by this user."""
cthulhusToKill = otherCthulhus()
debug.printMessage(debug.LEVEL_INFO, "INFO: Cleaning up these PIDs: %s" % cthulhusToKill)
def onTimeout(signum, frame):
cthulhusToKill = otherCthulhus()
debug.printMessage(debug.LEVEL_INFO, "INFO: Timeout cleaning up: %s" % cthulhusToKill)
for pid in cthulhusToKill:
os.kill(pid, signal.SIGKILL)
for pid in cthulhusToKill:
os.kill(pid, sigval)
signal.signal(signal.SIGALRM, onTimeout)
signal.alarm(2)
while otherCthulhus():
time.sleep(0.5)
def main():
setProcessName('cthulhu')
parser = Parser()
args, invalid = parser.parse_known_args()
if args.debug:
debug.debugLevel = debug.LEVEL_ALL
debug.eventDebugLevel = debug.LEVEL_OFF
debug.debugFile = open(args.debug_file, 'w')
if args.replace:
cleanup(signal.SIGKILL)
settingsDict = getattr(args, 'settings', {})
if not inGraphicalDesktop():
print(messages.CLI_NO_DESKTOP_ERROR)
return 1
debug.printMessage(debug.LEVEL_INFO, "INFO: Preparing to launch.", True)
from cthulhu import cthulhu
manager = cthulhu.getSettingsManager()
if not manager:
print(messages.CLI_SETTINGS_MANAGER_ERROR)
return 1
debug.printMessage(debug.LEVEL_INFO, "INFO: About to activate settings manager.", True)
manager.activate(args.user_prefs, settingsDict)
sys.path.insert(0, manager.getPrefsDir())
if args.profile:
try:
manager.setProfile(args.profile)
except Exception:
print(messages.CLI_LOAD_PROFILE_ERROR % args.profile)
manager.setProfile()
if args.setup:
cleanup(signal.SIGKILL)
cthulhu.showPreferencesGUI()
if otherCthulhus():
print(messages.CLI_OTHER_CTHULHUS_ERROR)
return 1
debug.printMessage(debug.LEVEL_INFO, "INFO: About to launch Cthulhu.", True)
return cthulhu.main()
if __name__ == "__main__":
sys.exit(main())
+1
View File
@@ -29,6 +29,7 @@ cthulhu_python_PYTHON = \
cmdnames.py \
colornames.py \
common_keyboardmap.py \
cthulhuVersion.py \
date_and_time_presenter.py \
debug.py \
desktop_keyboardmap.py \
+25
View File
@@ -1,3 +1,28 @@
#!/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
"""Cthulhu Screen Reader"""
__copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
+8 -3
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2005-2008 Google Inc.
# Portions Copyright 2007-2008, Sun Microsystems, Inc.
# 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
@@ -18,6 +20,9 @@
# 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
"""ACSS --- Aural CSS.
Class ACSS defines a simple wrapper for holding ACSS voice
+9 -4
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2023 Igalia, S.L.
# Author: Joanmarie Diggs <jdiggs@igalia.com>
# 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
@@ -17,6 +19,9 @@
# 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
"""Module for performing accessible actions via a menu"""
@@ -81,7 +86,7 @@ class ActionPresenter:
keybindings.KeyBinding(
"a",
keybindings.defaultModifierMask,
keybindings.ORCA_SHIFT_MODIFIER_MASK,
keybindings.CTHULHU_SHIFT_MODIFIER_MASK,
self._handlers.get("show_actions_menu")))
return bindings
+8 -3
View File
@@ -1,7 +1,9 @@
# Utilities for obtaining objects via the collection interface.
#!/usr/bin/env python3
#
# Copyright 2023 Igalia, S.L.
# Author: Joanmarie Diggs <jdiggs@igalia.com>
# 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
@@ -17,6 +19,9 @@
# 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 obtaining objects via the collection interface.
+8 -3
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2005-2008 Sun Microsystems Inc.
# Copyright 2018-2023 Igalia, S.L.
# 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
@@ -17,6 +19,9 @@
# 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
"""Provides support for synthesizing accessible input events."""
+8 -3
View File
@@ -1,7 +1,9 @@
# Utilities for obtaining information about accessible objects.
#!/usr/bin/env python3
#
# Copyright 2023 Igalia, S.L.
# Author: Joanmarie Diggs <jdiggs@igalia.com>
# 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
@@ -17,6 +19,9 @@
# 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 obtaining information about accessible objects.
+8 -3
View File
@@ -1,7 +1,9 @@
# Utilities for obtaining information about containers supporting selection
#!/usr/bin/env python3
#
# Copyright 2023 Igalia, S.L.
# Author: Joanmarie Diggs <jdiggs@igalia.com>
# 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
@@ -17,6 +19,9 @@
# 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 obtaining information about containers supporting selection.
+8 -3
View File
@@ -1,7 +1,9 @@
# Utilities for performing tasks related to accessibility inspection.
#!/usr/bin/env python3
#
# Copyright 2023 Igalia, S.L.
# Author: Joanmarie Diggs <jdiggs@igalia.com>
# 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
@@ -17,6 +19,9 @@
# 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 performing tasks related to accessibility inspection.
+8 -3
View File
@@ -1,7 +1,9 @@
# Utilities for finding all objects that meet a certain criteria.
#!/usr/bin/env python3
#
# Copyright 2023 Igalia, S.L.
# Author: Joanmarie Diggs <jdiggs@igalia.com>
# 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
@@ -17,6 +19,9 @@
# 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 finding all objects that meet a certain criteria.
+8 -3
View File
@@ -1,7 +1,9 @@
# Utilities for obtaining role-related information.
#!/usr/bin/env python3
#
# Copyright 2023 Igalia, S.L.
# Author: Joanmarie Diggs <jdiggs@igalia.com>
# 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
@@ -17,6 +19,9 @@
# 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 obtaining role-related information.
+8 -3
View File
@@ -1,7 +1,9 @@
# Utilities for obtaining state-related information.
#!/usr/bin/env python3
#
# Copyright 2023 Igalia, S.L.
# Author: Joanmarie Diggs <jdiggs@igalia.com>
# 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
@@ -17,6 +19,9 @@
# 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 obtaining state-related information.
+25
View File
@@ -0,0 +1,25 @@
#!/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
+8 -4
View File
@@ -1,8 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2010-2011 Consorcio Fernando de los Rios.
# Author: Juanje Ojeda Croissier <jojeda@emergya.es>
# Author: Javier Hernandez Antunez <jhernandez@emergya.es>
# 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
@@ -18,6 +19,9 @@
# 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
"""JSON backend for Cthulhu settings"""
+13 -7
View File
@@ -1,6 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2005-2008 Sun Microsystems Inc.
# 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
@@ -16,6 +19,9 @@
# 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
"""Provides the default implementation for bookmarks in Cthulhu."""
@@ -95,21 +101,21 @@ class Bookmarks:
keybindings.KeyBinding(
"b",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("goToNextBookmark")))
bindings.add(
keybindings.KeyBinding(
"b",
keybindings.defaultModifierMask,
keybindings.ORCA_SHIFT_MODIFIER_MASK,
keybindings.CTHULHU_SHIFT_MODIFIER_MASK,
self._handlers.get("goToPrevBookmark")))
bindings.add(
keybindings.KeyBinding(
"b",
keybindings.defaultModifierMask,
keybindings.ORCA_ALT_MODIFIER_MASK,
keybindings.CTHULHU_ALT_MODIFIER_MASK,
self._handlers.get("saveBookmarks")))
for i in range(6):
@@ -117,14 +123,14 @@ class Bookmarks:
keybindings.KeyBinding(
str(i + 1),
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("goToBookmark")))
bindings.add(
keybindings.KeyBinding(
str(i + 1),
keybindings.defaultModifierMask,
keybindings.ORCA_ALT_MODIFIER_MASK,
keybindings.CTHULHU_ALT_MODIFIER_MASK,
self._handlers.get("addBookmark")))
return bindings
+8 -2
View File
@@ -1,6 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2005-2009 Sun Microsystems Inc.
# 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
@@ -16,6 +19,9 @@
# 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
"""A very experimental approach to the refreshable Braille display. This
module treats each line of the display as a sequential set of regions, where
+8 -2
View File
@@ -1,6 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2005-2009 Sun Microsystems Inc.
# 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
@@ -16,6 +19,9 @@
# 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 obtaining braille presentations for objects."""
+8 -2
View File
@@ -1,6 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2012 Igalia, S.L.
# 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
@@ -16,6 +19,9 @@
# 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
"""Dictionary of abbreviated rolenames for use with braille."""
+8 -4
View File
@@ -1,8 +1,9 @@
# -*- coding: utf-8 -*-
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2006-2008 Sun Microsystems Inc.
# Copyright 2011 The Cthulhu Team.
# 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
@@ -18,6 +19,9 @@
# 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
"""Provides a graphical braille display, mainly for development tasks."""
+8 -3
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2004-2009 Sun Microsystems Inc.
# Copyright 2010-2013 The Cthulhu Team
# 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
@@ -17,6 +19,9 @@
# 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
"""Braille translation table names. These have been put in their own module
so that we can present them in the correct language when users change the
+10 -5
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2013-2015 Igalia, S.L.
# Author: Joanmarie Diggs <jdiggs@igalia.com>
# 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
@@ -17,6 +19,9 @@
# 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
"""Provides an Cthulhu-controlled caret for text content."""
@@ -144,7 +149,7 @@ class CaretNavigation:
keybindings.KeyBinding(
"F12",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("toggle_enabled")))
bindings.add(
@@ -229,7 +234,7 @@ class CaretNavigation:
_settings_manager = settings_manager.getManager()
enabled = not _settings_manager.getSetting('caretNavigationEnabled')
if enabled:
string = messages.CARET_CONTROL_ORCA
string = messages.CARET_CONTROL_CTHULHU
else:
string = messages.CARET_CONTROL_APP
+10 -4
View File
@@ -1,6 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2010-2011 The Cthulhu Team
# 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
@@ -16,6 +19,9 @@
# 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
"""Implements generic chat support."""
@@ -308,7 +314,7 @@ class Chat:
#
self.messageKeys = \
["F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"]
self.messageKeyModifier = keybindings.ORCA_MODIFIER_MASK
self.messageKeyModifier = keybindings.CTHULHU_MODIFIER_MASK
self.inputEventHandlers = {}
self.setupInputEventHandlers()
self.keyBindings = self.getKeyBindings()
@@ -387,7 +393,7 @@ class Chat:
keybindings.KeyBinding(
messageKey,
self.messageKeyModifier,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self.inputEventHandlers["reviewMessage"]))
return keyBindings
+8 -3
View File
@@ -1,7 +1,9 @@
# -*- coding: utf-8 -*-
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2004-2008 Sun Microsystems Inc.
# 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
@@ -17,6 +19,9 @@
# 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
"""Provides getCharacterName that maps punctuation marks and other
individual characters into localized words."""
+12 -4
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2004-2009 Sun Microsystems Inc.
# Copyright 2010-2013 The Cthulhu Team
# 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
@@ -17,6 +19,9 @@
# 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
"""Command names which Cthulhu presents in speech and/or braille. These
have been put in their own module so that we can present them in
@@ -455,9 +460,12 @@ TOGGLE_SPEECH = _("Toggle the silencing of speech")
# This string describes that command.
TOGGLE_SPEECH_VERBOSITY = _("Toggle speech verbosity level")
# Translators: this string is associated with the keyboard shortcut to toggle sleepmode
TOGGLE_SLEEP_MODE = _("Toggle sleep mode")
# Translators: this string is associated with the keyboard shortcut to quit
# Cthulhu.
QUIT_ORCA = _("Quit the screen reader")
QUIT_CTHULHU = _("Quit the screen reader")
# Translators: the preferences configuration dialog is the dialog that allows
# users to set their preferences for Cthulhu.
+8 -4
View File
@@ -1,8 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2014 Igalia, S.L.
#
# Author: Joanmarie Diggs <jdiggs@igalia.com>
# 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
@@ -18,6 +19,9 @@
# 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
__id__ = "$Id$"
__version__ = "$Revision$"
+20 -11
View File
@@ -1,6 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2010-2011 The Cthulhu Team
# 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
@@ -16,6 +19,9 @@
# 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
""" A list of common keybindings and unbound keys
pulled out from default.py: getKeyBindings()
@@ -32,26 +38,29 @@ from . import keybindings
# Storing values
defaultModifierMask = keybindings.defaultModifierMask
ORCA_MODIFIER_MASK = keybindings.ORCA_MODIFIER_MASK
CTHULHU_MODIFIER_MASK = keybindings.CTHULHU_MODIFIER_MASK
NO_MODIFIER_MASK = keybindings.NO_MODIFIER_MASK
ORCA_SHIFT_MODIFIER_MASK = keybindings.ORCA_SHIFT_MODIFIER_MASK
ORCA_CTRL_MODIFIER_MASK = keybindings.ORCA_CTRL_MODIFIER_MASK
ORCA_ALT_MODIFIER_MASK = keybindings.ORCA_ALT_MODIFIER_MASK
ORCA_CTRL_ALT_MODIFIER_MASK = keybindings.ORCA_CTRL_ALT_MODIFIER_MASK
CTHULHU_SHIFT_MODIFIER_MASK = keybindings.CTHULHU_SHIFT_MODIFIER_MASK
CTHULHU_CTRL_MODIFIER_MASK = keybindings.CTHULHU_CTRL_MODIFIER_MASK
CTHULHU_ALT_MODIFIER_MASK = keybindings.CTHULHU_ALT_MODIFIER_MASK
CTHULHU_CTRL_ALT_MODIFIER_MASK = keybindings.CTHULHU_CTRL_ALT_MODIFIER_MASK
SHIFT_ALT_MODIFIER_MASK = keybindings.SHIFT_ALT_MODIFIER_MASK
keymap = (
("space", defaultModifierMask, ORCA_MODIFIER_MASK,
("space", defaultModifierMask, CTHULHU_MODIFIER_MASK,
"preferencesSettingsHandler"),
("space", defaultModifierMask, ORCA_CTRL_MODIFIER_MASK,
("space", defaultModifierMask, CTHULHU_CTRL_MODIFIER_MASK,
"appPreferencesSettingsHandler"),
("BackSpace", defaultModifierMask, ORCA_MODIFIER_MASK,
("BackSpace", defaultModifierMask, CTHULHU_MODIFIER_MASK,
"bypassNextCommandHandler"),
("q", defaultModifierMask, ORCA_MODIFIER_MASK,
("q", defaultModifierMask, CTHULHU_CTRL_ALT_MODIFIER_MASK, CTHULHU_SHIFT_MODIFIER_MASK,
"toggleSleepModeHandler"),
("q", defaultModifierMask, CTHULHU_MODIFIER_MASK,
"shutdownHandler"),
+141 -48
View File
@@ -1,8 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2004-2009 Sun Microsystems Inc.
# Copyright 2010-2011 The Cthulhu Team
# Copyright 2012 Igalia, S.L.
# 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
@@ -18,6 +19,9 @@
# 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
"""The main module for the Cthulhu screen reader."""
@@ -30,6 +34,94 @@ __copyright__ = "Copyright (c) 2004-2009 Sun Microsystems Inc." \
__license__ = "LGPL"
import faulthandler
class APIHelper:
"""Helper class for plugin API interactions, including keybindings."""
def __init__(self, app):
"""Initialize the APIHelper.
Arguments:
- app: the Cthulhu application
"""
self.app = app
self._gestureBindings = {}
def registerGestureByString(self, function, name, gestureString,
inputEventType='default', normalizer='cthulhu',
learnModeEnabled=True, contextName=None):
"""Register a gesture by string.
Arguments:
- function: the function to call when the gesture is performed
- name: a human-readable name for this gesture
- gestureString: string representation of the gesture (e.g., 'kb:cthulhu+z')
- inputEventType: the type of input event
- normalizer: the normalizer to use
- learnModeEnabled: whether this should be available in learn mode
- contextName: the context for this gesture (e.g., plugin name)
Returns the binding ID or None if registration failed
"""
if not gestureString.startswith("kb:"):
return None
# Extract the key portion from the gesture string
key = gestureString.split(":", 1)[1]
# Handle Cthulhu modifier specially
if "cthulhu+" in key.lower():
from . import keybindings
key = key.lower().replace("cthulhu+", "")
# Create a keybinding handler
class GestureHandler:
def __init__(self, function, description):
self.function = function
self.description = description
def __call__(self, script, inputEvent):
return self.function(script, inputEvent)
handler = GestureHandler(function, name)
# Register the binding with the active script
from . import cthulhu_state
if cthulhu_state.activeScript:
bindings = cthulhu_state.activeScript.getKeyBindings()
binding = keybindings.KeyBinding(
key,
keybindings.defaultModifierMask,
keybindings.CTHULHU_MODIFIER_MASK,
handler)
bindings.add(binding)
# Store binding for later reference
if contextName not in self._gestureBindings:
self._gestureBindings[contextName] = []
self._gestureBindings[contextName].append(binding)
return binding
return None
def unregisterShortcut(self, binding, contextName=None):
"""Unregister a previously registered shortcut.
Arguments:
- binding: the binding to unregister
- contextName: the context for this gesture
"""
# Remove from script's keybindings
from . import cthulhu_state
if cthulhu_state.activeScript:
bindings = cthulhu_state.activeScript.getKeyBindings()
bindings.remove(binding)
# Remove from our tracking
if contextName in self._gestureBindings:
if binding in self._gestureBindings[contextName]:
self._gestureBindings[contextName].remove(binding)
import gi
import importlib
import os
@@ -70,7 +162,7 @@ from .ax_object import AXObject
from .ax_utilities import AXUtilities
from .input_event import BrailleEvent
from . import cmdnames
from . import plugin_system_manager
from . import plugin_system_manager # This will now be your pluggy-based implementation
from . import guilabels
from . import acss
from . import text_attribute_names
@@ -132,7 +224,7 @@ OBJECT_NAVIGATOR = "object-navigator"
SAY_ALL = "say-all"
def getActiveModeAndObjectOfInterest():
tokens = ["ORCA: Active mode:", cthulhu_state.activeMode,
tokens = ["CTHULHU: Active mode:", cthulhu_state.activeMode,
"Object of interest:", cthulhu_state.objOfInterest]
debug.printTokens(debug.LEVEL_INFO, tokens, True)
return cthulhu_state.activeMode, cthulhu_state.objOfInterest
@@ -150,42 +242,42 @@ def emitRegionChanged(obj, startOffset=None, endOffset=None, mode=None):
try:
obj.emit("mode-changed::" + mode, 1, "")
except Exception:
msg = "ORCA: Exception emitting mode-changed notification"
msg = "CTHULHU: Exception emitting mode-changed notification"
debug.printMessage(debug.LEVEL_INFO, msg, True)
if mode != cthulhu_state.activeMode:
tokens = ["ORCA: Switching active mode from", cthulhu_state.activeMode, "to", mode]
tokens = ["CTHULHU: Switching active mode from", cthulhu_state.activeMode, "to", mode]
debug.printTokens(debug.LEVEL_INFO, tokens, True)
cthulhu_state.activeMode = mode
try:
tokens = ["ORCA: Region of interest:", obj, "(", startOffset, ")", endOffset]
tokens = ["CTHULHU: Region of interest:", obj, "(", startOffset, ")", endOffset]
debug.printTokens(debug.LEVEL_INFO, tokens, True)
obj.emit("region-changed", startOffset, endOffset)
except Exception:
msg = "ORCA: Exception emitting region-changed notification"
msg = "CTHULHU: Exception emitting region-changed notification"
debug.printMessage(debug.LEVEL_INFO, msg, True)
if obj != cthulhu_state.objOfInterest:
tokens = ["ORCA: Switching object of interest from", cthulhu_state.objOfInterest, "to", obj]
tokens = ["CTHULHU: Switching object of interest from", cthulhu_state.objOfInterest, "to", obj]
debug.printTokens(debug.LEVEL_INFO, tokens, True)
cthulhu_state.objOfInterest = obj
def setActiveWindow(frame, app=None, alsoSetLocusOfFocus=False, notifyScript=False):
tokens = ["ORCA: Request to set active window to", frame]
tokens = ["CTHULHU: Request to set active window to", frame]
if app is not None:
tokens.extend(["in", app])
debug.printTokens(debug.LEVEL_INFO, tokens, True)
if frame == cthulhu_state.activeWindow:
msg = "ORCA: Setting activeWindow to existing activeWindow"
msg = "CTHULHU: Setting activeWindow to existing activeWindow"
debug.printMessage(debug.LEVEL_INFO, msg, True)
elif frame is None:
cthulhu_state.activeWindow = None
else:
real_app, real_frame = AXObject.find_real_app_and_window_for(frame, app)
if real_frame != frame:
tokens = ["ORCA: Correcting active window to", real_frame, "in", real_app]
tokens = ["CTHULHU: Correcting active window to", real_frame, "in", real_app]
debug.printTokens(debug.LEVEL_INFO, tokens, True)
cthulhu_state.activeWindow = real_frame
else:
@@ -208,7 +300,7 @@ def setLocusOfFocus(event, obj, notifyScript=True, force=False):
"""
if not force and obj == cthulhu_state.locusOfFocus:
msg = "ORCA: Setting locusOfFocus to existing locusOfFocus"
msg = "CTHULHU: Setting locusOfFocus to existing locusOfFocus"
debug.printMessage(debug.LEVEL_INFO, msg, True)
return
@@ -222,13 +314,13 @@ def setLocusOfFocus(event, obj, notifyScript=True, force=False):
oldFocus = None
if obj is None:
msg = "ORCA: New locusOfFocus is null (being cleared)"
msg = "CTHULHU: New locusOfFocus is null (being cleared)"
debug.printMessage(debug.LEVEL_INFO, msg, True)
cthulhu_state.locusOfFocus = None
return
if cthulhu_state.activeScript:
tokens = ["ORCA: Active script is:", cthulhu_state.activeScript]
tokens = ["CTHULHU: Active script is:", cthulhu_state.activeScript]
debug.printTokens(debug.LEVEL_INFO, tokens, True)
if cthulhu_state.activeScript.utilities.isZombie(obj):
tokens = ["ERROR: New locusOfFocus (", obj, ") is zombie. Not updating."]
@@ -239,7 +331,7 @@ def setLocusOfFocus(event, obj, notifyScript=True, force=False):
debug.printTokens(debug.LEVEL_INFO, tokens, True)
return
tokens = ["ORCA: Changing locusOfFocus from", oldFocus, "to", obj, ". Notify:", notifyScript]
tokens = ["CTHULHU: Changing locusOfFocus from", oldFocus, "to", obj, ". Notify:", notifyScript]
debug.printTokens(debug.LEVEL_INFO, tokens, True)
cthulhu_state.locusOfFocus = obj
@@ -247,7 +339,7 @@ def setLocusOfFocus(event, obj, notifyScript=True, force=False):
return
if not cthulhu_state.activeScript:
msg = "ORCA: Cannot notify active script because there isn't one"
msg = "CTHULHU: Cannot notify active script because there isn't one"
debug.printMessage(debug.LEVEL_INFO, msg, True)
return
@@ -299,7 +391,7 @@ def deviceChangeHandler(deviceManager, device):
so we have to re-apply"""
source = device.get_source()
if source == Gdk.InputSource.KEYBOARD:
msg = "ORCA: Keyboard change detected, re-creating the xmodmap"
msg = "CTHULHU: Keyboard change detected, re-creating the xmodmap"
debug.printMessage(debug.LEVEL_INFO, msg, True)
_createCthulhuXmodmap()
@@ -409,7 +501,7 @@ def _restoreXmodmap(keyList=[]):
to restore the entire saved xmodmap.
"""
msg = "ORCA: Attempting to restore original xmodmap"
msg = "CTHULHU: Attempting to restore original xmodmap"
debug.printMessage(debug.LEVEL_INFO, msg, True)
global _capsLockCleared
@@ -418,7 +510,7 @@ def _restoreXmodmap(keyList=[]):
stdin=subprocess.PIPE, stdout=None, stderr=None)
p.communicate(_originalXmodmap)
msg = "ORCA: Original xmodmap restored"
msg = "CTHULHU: Original xmodmap restored"
debug.printMessage(debug.LEVEL_INFO, msg, True)
def setKeyHandling(new):
@@ -433,7 +525,7 @@ def loadUserSettings(script=None, inputEvent=None, skipReloadMessage=False):
Returns True to indicate the input event has been consumed.
"""
debug.printMessage(debug.LEVEL_INFO, 'ORCA: Loading User Settings', True)
debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Loading User Settings', True)
global _userSettings
@@ -473,7 +565,7 @@ def loadUserSettings(script=None, inputEvent=None, skipReloadMessage=False):
_settingsManager.loadAppSettings(script)
if _settingsManager.getSetting('enableSpeech'):
msg = 'ORCA: About to enable speech'
msg = 'CTHULHU: About to enable speech'
debug.printMessage(debug.LEVEL_INFO, msg, True)
try:
speech.init()
@@ -482,20 +574,20 @@ def loadUserSettings(script=None, inputEvent=None, skipReloadMessage=False):
except Exception:
debug.printException(debug.LEVEL_SEVERE)
else:
msg = 'ORCA: Speech is not enabled in settings'
msg = 'CTHULHU: Speech is not enabled in settings'
debug.printMessage(debug.LEVEL_INFO, msg, True)
if _settingsManager.getSetting('enableBraille'):
msg = 'ORCA: About to enable braille'
msg = 'CTHULHU: About to enable braille'
debug.printMessage(debug.LEVEL_INFO, msg, True)
try:
braille.init(_processBrailleEvent)
except Exception:
debug.printException(debug.LEVEL_WARNING)
msg = 'ORCA: Could not initialize connection to braille.'
msg = 'CTHULHU: Could not initialize connection to braille.'
debug.printMessage(debug.LEVEL_WARNING, msg, True)
else:
msg = 'ORCA: Braille is not enabled in settings'
msg = 'CTHULHU: Braille is not enabled in settings'
debug.printMessage(debug.LEVEL_INFO, msg, True)
@@ -526,7 +618,7 @@ def loadUserSettings(script=None, inputEvent=None, skipReloadMessage=False):
cthulhuApp.getSignalManager().emitSignal('load-setting-completed')
debug.printMessage(debug.LEVEL_INFO, 'ORCA: User Settings Loaded', True)
debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: User Settings Loaded', True)
return True
@@ -641,12 +733,12 @@ def init():
module has already been initialized.
"""
debug.printMessage(debug.LEVEL_INFO, 'ORCA: Initializing', True)
debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Initializing', True)
global _initialized
if _initialized and _settingsManager.isScreenReaderServiceEnabled():
debug.printMessage(debug.LEVEL_INFO, 'ORCA: Already initialized', True)
debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Already initialized', True)
return False
# Do not hang on initialization if we can help it.
@@ -667,14 +759,14 @@ def init():
if a11yAppSettings:
a11yAppSettings.connect('changed', onEnabledChanged)
debug.printMessage(debug.LEVEL_INFO, 'ORCA: Initialized', True)
debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Initialized', True)
return True
def start():
"""Starts Cthulhu."""
debug.printMessage(debug.LEVEL_INFO, 'ORCA: Starting', True)
debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Starting', True)
if not _initialized:
init()
@@ -698,10 +790,10 @@ def start():
devmanager.connect("device-removed", deviceChangeHandler)
Gdk.notify_startup_complete()
msg = 'ORCA: Startup complete notification made'
msg = 'CTHULHU: Startup complete notification made'
debug.printMessage(debug.LEVEL_INFO, msg, True)
debug.printMessage(debug.LEVEL_INFO, 'ORCA: Starting Atspi main event loop', True)
debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Starting Atspi main event loop', True)
Atspi.event_main()
def die(exitCode=1):
@@ -730,7 +822,7 @@ def shutdown(script=None, inputEvent=None):
was never initialized.
"""
debug.printMessage(debug.LEVEL_INFO, 'ORCA: Shutting down', True)
debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Shutting down', True)
global _initialized
@@ -769,9 +861,9 @@ def shutdown(script=None, inputEvent=None):
_initialized = False
_restoreXmodmap(_cthulhuModifiers)
debug.printMessage(debug.LEVEL_INFO, 'ORCA: Quitting Atspi main event loop', True)
debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Quitting Atspi main event loop', True)
Atspi.event_quit()
debug.printMessage(debug.LEVEL_INFO, 'ORCA: Shutdown complete', True)
debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Shutdown complete', True)
return True
@@ -780,7 +872,7 @@ def shutdownOnSignal(signum, frame):
global exitCount
signalString = f'({signal.strsignal(signum)})'
msg = f"ORCA: Shutting down and exiting due to signal={signum} {signalString}"
msg = f"CTHULHU: Shutting down and exiting due to signal={signum} {signalString}"
debug.printMessage(debug.LEVEL_INFO, msg, True)
# Well...we'll try to exit nicely, but if we keep getting called,
@@ -818,7 +910,7 @@ def shutdownOnSignal(signum, frame):
def crashOnSignal(signum, frame):
signalString = f'({signal.strsignal(signum)})'
msg = f"ORCA: Shutting down and exiting due to signal={signum} {signalString}"
msg = f"CTHULHU: Shutting down and exiting due to signal={signum} {signalString}"
debug.printMessage(debug.LEVEL_SEVERE, msg, True)
debug.printStack(debug.LEVEL_SEVERE)
_restoreXmodmap(_cthulhuModifiers)
@@ -831,7 +923,7 @@ def main():
an exit code of 0 means normal completion and an exit code of 50
means Cthulhu exited because of a hang."""
msg = f"ORCA: Launching version {cthulhu_platform.version}"
msg = f"CTHULHU: Launching version {cthulhu_platform.version}"
if cthulhu_platform.revision:
msg += f" (rev {cthulhu_platform.revision})"
@@ -859,13 +951,13 @@ def main():
signal.signal(signal.SIGQUIT, shutdownOnSignal)
signal.signal(signal.SIGSEGV, crashOnSignal)
debug.printMessage(debug.LEVEL_INFO, "ORCA: Enabling accessibility (if needed).", True)
debug.printMessage(debug.LEVEL_INFO, "CTHULHU: Enabling accessibility (if needed).", True)
if not _settingsManager.isAccessibilityEnabled():
_settingsManager.setAccessibility(True)
debug.printMessage(debug.LEVEL_INFO, "ORCA: Initializing.", True)
debug.printMessage(debug.LEVEL_INFO, "CTHULHU: Initializing.", True)
init()
debug.printMessage(debug.LEVEL_INFO, "ORCA: Initialized.", True)
debug.printMessage(debug.LEVEL_INFO, "CTHULHU: Initialized.", True)
script = cthulhu_state.activeScript
cthulhuApp.getSignalManager().emitSignal('start-application-completed')
@@ -883,7 +975,7 @@ def main():
_scriptManager.setActiveScript(script, "Launching.")
focusedObject = AXUtilities.get_focused_object(window)
tokens = ["ORCA: Focused object is:", focusedObject]
tokens = ["CTHULHU: Focused object is:", focusedObject]
debug.printTokens(debug.LEVEL_INFO, tokens, True)
if focusedObject:
setLocusOfFocus(None, focusedObject)
@@ -892,11 +984,11 @@ def main():
_scriptManager.setActiveScript(script, "Found focused object.")
try:
msg = "ORCA: Starting ATSPI registry."
msg = "CTHULHU: Starting ATSPI registry."
debug.printMessage(debug.LEVEL_INFO, msg, True)
start() # waits until we stop the registry
except Exception:
msg = "ORCA: Exception starting ATSPI registry."
msg = "CTHULHU: Exception starting ATSPI registry."
debug.printMessage(debug.LEVEL_SEVERE, msg, True)
die(EXIT_CODE_HANG)
return 0
@@ -916,7 +1008,6 @@ class Cthulhu(GObject.Object):
GObject.Object.__init__(self)
# add members
self.resourceManager = resource_manager.ResourceManager(self)
self.APIHelper = plugin_system_manager.APIHelper(self)
self.eventManager = _eventManager
self.settingsManager = _settingsManager
self.scriptManager = _scriptManager
@@ -924,6 +1015,7 @@ class Cthulhu(GObject.Object):
self.dynamicApiManager = dynamic_api_manager.DynamicApiManager(self)
self.translationManager = translation_manager.TranslationManager(self)
self.debugManager = debug
self.APIHelper = APIHelper(self)
self.createCompatAPI()
self.pluginSystemManager = plugin_system_manager.PluginSystemManager(self)
def getAPIHelper(self):
@@ -983,6 +1075,7 @@ class Cthulhu(GObject.Object):
# cthulhu lets say, special compat handling....
self.getDynamicApiManager().registerAPI('EmitRegionChanged', emitRegionChanged)
self.getDynamicApiManager().registerAPI('LoadUserSettings', loadUserSettings)
self.getDynamicApiManager().registerAPI('APIHelper', self.APIHelper)
cthulhuApp = Cthulhu()
+27
View File
@@ -0,0 +1,27 @@
#!/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
version = "2025.04.03"
codeName = "testing"
+8 -12
View File
@@ -1,9 +1,9 @@
#!@PYTHON@
#
# Cthulhu
#
# Copyright 2010-2012 The Cthulhu Team
# Copyright 2012 Igalia, S.L.
# 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
@@ -19,13 +19,9 @@
# License along with this library; if not, write to the
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA 02110-1301 USA.
__id__ = "$Id$"
__version__ = "$Revision$"
__date__ = "$Date$"
__copyright__ = "Copyright (c) 2010-2012 The Cthulhu Team" \
"Copyright (c) 2012 Igalia, S.L."
__license__ = "LGPL"
#
# Fork of Orca Screen Reader (GNOME)
# Original source: https://gitlab.gnome.org/GNOME/orca
import argparse
import gi
@@ -272,7 +268,7 @@ def main():
cthulhu.showPreferencesGUI()
if otherCthulhus():
print(messages.CLI_OTHER_ORCAS_ERROR)
print(messages.CLI_OTHER_CTHULHUS_ERROR)
return 1
debug.printMessage(debug.LEVEL_INFO, "INFO: About to launch Cthulhu.", True)
+8 -2
View File
@@ -1,6 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2005-2009 Sun Microsystems Inc.
# 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
@@ -16,6 +19,9 @@
# 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
"""Displays a GUI for the user to quit Cthulhu."""
+8 -2
View File
@@ -1,6 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2005-2009 Sun Microsystems Inc.
# 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
@@ -16,6 +19,9 @@
# 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
"""Displays a GUI for the Cthulhu Find window"""
+8 -4
View File
@@ -1,8 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2012 Igalia, S.L.
#
# Author: Joanmarie Diggs <jdiggs@igalia.com>
# 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
@@ -18,6 +19,9 @@
# 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
"""Displays a GUI for Cthulhu navigation list dialogs"""
+21 -15
View File
@@ -1,6 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2005-2009 Sun Microsystems Inc.
# 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
@@ -16,6 +19,9 @@
# 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
"""Displays a GUI for the user to set Cthulhu preferences."""
@@ -187,7 +193,7 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
# ***** Key Bindings treeview initialization *****
self.keyBindView = self.get_widget("keyBindingsTreeview")
if self.keyBindView.get_columns():
for column in self.keyBindView.get_columns():
self.keyBindView.remove_column(column)
@@ -331,7 +337,7 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
column.set_resizable(True)
column.set_sort_column_id(EDITABLE)
self.keyBindView.append_column(column)
# Populates the treeview with all the keybindings:
#
self._populateKeyBindings()
@@ -576,7 +582,7 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
self.get_widget("rateScale").set_value(rate)
else:
self.get_widget("rateScale").set_value(50.0)
pitch = self._getPitchForVoiceType(voiceType)
if pitch is not None:
self.get_widget("pitchScale").set_value(pitch)
@@ -1144,7 +1150,7 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
grid = self.get_widget('flashMessageDurationGrid')
grid.set_sensitive(not checkbox.get_active())
self.prefsDict["flashIsPersistent"] = checkbox.get_active()
def textAttributeSpokenToggled(self, cell, path, model):
"""The user has toggled the state of one of the text attribute
checkboxes to be spoken. Update our model to reflect this, then
@@ -1590,7 +1596,7 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
elif dateFormat == messages.DATE_FORMAT_ABBREVIATED_YMD:
indexdate = DATE_FORMAT_ABBREVIATED_YMD
combobox2.set_active (indexdate)
combobox3 = self.get_widget("timeFormatCombo")
self.populateComboBox(combobox3,
[sdtime(messages.TIME_FORMAT_LOCALE, ltime()),
@@ -1751,7 +1757,7 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
prefs["enableEchoByWord"])
self.get_widget("enableEchoBySentenceCheckButton").set_active( \
prefs["enableEchoBySentence"])
# Text attributes pane.
#
self._createTextAttributesTreeView()
@@ -1779,7 +1785,7 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
self.get_widget("generalDesktopButton").set_active(True)
else:
self.get_widget("generalLaptopButton").set_active(True)
combobox = self.get_widget("sayAllStyle")
self.populateComboBox(combobox, [guilabels.SAY_ALL_STYLE_LINE,
guilabels.SAY_ALL_STYLE_SENTENCE])
@@ -2742,7 +2748,7 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
elif dateFormatCombo == DATE_FORMAT_ABBREVIATED_YMD:
newFormat = messages.DATE_FORMAT_ABBREVIATED_YMD
self.prefsDict["presentDateFormat"] = newFormat
def timeFormatChanged(self, widget):
"""Signal handler for the "changed" signal for the timeFormat
GtkComboBox widget. Set the 'timeFormat' preference to the
@@ -2878,7 +2884,7 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
cthulhuMods = settings.cthulhuModifierKeys
if eventString in cthulhuMods:
self._capturedKey = ['', keybindings.ORCA_MODIFIER_MASK, 0]
self._capturedKey = ['', keybindings.CTHULHU_MODIFIER_MASK, 0]
return False
modifierKeys = ['Alt_L', 'Alt_R', 'Control_L', 'Control_R',
@@ -2894,9 +2900,9 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
return True
string, modifiers, clickCount = self._capturedKey
isCthulhuModifier = modifiers & keybindings.ORCA_MODIFIER_MASK
isCthulhuModifier = modifiers & keybindings.CTHULHU_MODIFIER_MASK
if isCthulhuModifier:
eventState |= keybindings.ORCA_MODIFIER_MASK
eventState |= keybindings.CTHULHU_MODIFIER_MASK
self._capturedKey = [eventString, eventState, clickCount + 1]
return True
@@ -2918,7 +2924,7 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
if not keyName or keyName in ["Return", "Escape"]:
return False
isCthulhuModifier = modifiers & keybindings.ORCA_MODIFIER_MASK
isCthulhuModifier = modifiers & keybindings.CTHULHU_MODIFIER_MASK
if keyName in ["Delete", "BackSpace"] and not isCthulhuModifier:
editable.set_text("")
self._presentMessage(messages.KB_DELETED)
@@ -2983,7 +2989,7 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
mods = mods & Gdk.ModifierType.MODIFIER_MASK
if mods & (1 << Atspi.ModifierType.SHIFTLOCK) \
and mods & keybindings.ORCA_MODIFIER_MASK:
and mods & keybindings.CTHULHU_MODIFIER_MASK:
mods ^= (1 << Atspi.ModifierType.SHIFTLOCK)
treeModel.set(myiter,
+8 -4
View File
@@ -1,8 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2010 Consorcio Fernando de los Rios.
# Author: Javier Hernandez Antunez <jhernandez@emergya.es>
# Author: Alejandro Leiva <aleiva@emergya.es>
# 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
@@ -18,6 +19,9 @@
# 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
"""Displays the Save Profile As dialog."""
+4 -2
View File
@@ -17,6 +17,8 @@
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA 02110-1301 USA.
from cthulhu import cthulhuVersion
"""Holds platform-specific settings.
"""
@@ -26,9 +28,9 @@ __date__ = "$Date$"
__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
__license__ = "LGPL"
# $ORCA_VERSION
# $CTHULHU_VERSION
#
version = "@VERSION@"
version = f"Cthulhu screen reader version {cthulhuVersion.version}-{cthulhuVersion.codeName}"
# The revision if built from git; otherwise an empty string
#
+8 -3
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2005-2009 Sun Microsystems Inc.
# Copyright 2010 Joanmarie Diggs, Mesar Hameed
# 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
@@ -17,6 +19,9 @@
# 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
"""Holds state that is shared among many modules.
"""
+10 -5
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2005-2008 Sun Microsystems Inc.
# Copyright 2016-2023 Igalia, S.L.
# 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
@@ -17,6 +19,9 @@
# 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
"""Module for date and time presentation"""
@@ -79,7 +84,7 @@ class DateAndTimePresenter:
keybindings.KeyBinding(
"t",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("presentTimeHandler"),
1))
@@ -87,7 +92,7 @@ class DateAndTimePresenter:
keybindings.KeyBinding(
"t",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("presentDateHandler"),
2))
+8 -2
View File
@@ -1,6 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2005-2008 Sun Microsystems Inc.
# 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
@@ -16,6 +19,9 @@
# 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
"""Provides debug utilities for Cthulhu. Debugging is managed by a debug
level, which is held in the debugLevel field. All other methods take
+15 -9
View File
@@ -1,6 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2010 Joanmarie Diggs, Mesar Hameed.
# 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
@@ -16,6 +19,9 @@
# 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
""" A list of common keybindings and unbound keys
pulled out from default.py: __getDesktopBindings()
@@ -32,13 +38,13 @@ from . import keybindings
# Storing values
defaultModifierMask = keybindings.defaultModifierMask
ORCA_MODIFIER_MASK = keybindings.ORCA_MODIFIER_MASK
CTHULHU_MODIFIER_MASK = keybindings.CTHULHU_MODIFIER_MASK
NO_MODIFIER_MASK = keybindings.NO_MODIFIER_MASK
ORCA_SHIFT_MODIFIER_MASK = keybindings.ORCA_SHIFT_MODIFIER_MASK
CTHULHU_SHIFT_MODIFIER_MASK = keybindings.CTHULHU_SHIFT_MODIFIER_MASK
keymap = (
("KP_Divide", defaultModifierMask, ORCA_MODIFIER_MASK,
("KP_Divide", defaultModifierMask, CTHULHU_MODIFIER_MASK,
"routePointerToItemHandler"),
# We want the user to be able to combine modifiers with the
@@ -46,10 +52,10 @@ keymap = (
# do not "care" about the modifiers -- unless it's the Cthulhu
# modifier.
#
("KP_Divide", ORCA_MODIFIER_MASK, NO_MODIFIER_MASK,
("KP_Divide", CTHULHU_MODIFIER_MASK, NO_MODIFIER_MASK,
"leftClickReviewItemHandler"),
("KP_Multiply", ORCA_MODIFIER_MASK, NO_MODIFIER_MASK,
("KP_Multiply", CTHULHU_MODIFIER_MASK, NO_MODIFIER_MASK,
"rightClickReviewItemHandler"),
("KP_Add", defaultModifierMask, NO_MODIFIER_MASK,
@@ -58,9 +64,9 @@ keymap = (
("KP_Delete", defaultModifierMask, NO_MODIFIER_MASK,
"findHandler"),
("KP_Delete", defaultModifierMask, ORCA_MODIFIER_MASK,
("KP_Delete", defaultModifierMask, CTHULHU_MODIFIER_MASK,
"findNextHandler"),
("KP_Delete", defaultModifierMask, ORCA_SHIFT_MODIFIER_MASK,
("KP_Delete", defaultModifierMask, CTHULHU_SHIFT_MODIFIER_MASK,
"findPreviousHandler"),
)
+27 -2
View File
@@ -1,3 +1,28 @@
#!/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
import gi
from gi.repository import GObject
@@ -41,7 +66,7 @@ class DynamicApiManager():
def getAPI(self, key, application = '', fallback = True):
# get dynamic API
api = None
try:
api = self.api[application][key]
return api
@@ -58,5 +83,5 @@ class DynamicApiManager():
api = self.api[application]['']
except:
print('API Key: "{}/{}" not found,'.format(application, key))
return api
+8 -3
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2011. Cthulhu Team.
# Author: Joanmarie Diggs <joanmarie.diggs@gmail.com>
# 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
@@ -17,6 +19,9 @@
# 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
__id__ = "$Id$"
__version__ = "$Revision$"
+8 -3
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2006-2008 Sun Microsystems Inc.
# Copyright 2022 Igalia, S.L.
# 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
@@ -17,6 +19,9 @@
# 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
"""Provides support for a flat review find."""
+8 -3
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2005-2008 Sun Microsystems Inc.
# Copyright 2016 Igalia, S.L.
# 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
@@ -17,6 +19,9 @@
# 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
"""Provides the default implementation for flat review for Cthulhu."""
+37 -32
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2005-2008 Sun Microsystems Inc.
# Copyright 2016-2023 Igalia, S.L.
# 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
@@ -17,6 +19,9 @@
# 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
"""Module for flat-review commands"""
@@ -320,7 +325,7 @@ class FlatReviewPresenter:
keybindings.KeyBinding(
"KP_Home",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewHomeHandler")))
bindings.add(
@@ -365,7 +370,7 @@ class FlatReviewPresenter:
keybindings.KeyBinding(
"KP_Page_Up",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewEndHandler")))
bindings.add(
@@ -379,7 +384,7 @@ class FlatReviewPresenter:
keybindings.KeyBinding(
"KP_Left",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewAboveHandler")))
bindings.add(
@@ -410,7 +415,7 @@ class FlatReviewPresenter:
keybindings.KeyBinding(
"KP_Begin",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewCurrentAccessibleHandler")))
bindings.add(
@@ -424,7 +429,7 @@ class FlatReviewPresenter:
keybindings.KeyBinding(
"KP_Right",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewBelowHandler")))
bindings.add(
@@ -438,7 +443,7 @@ class FlatReviewPresenter:
keybindings.KeyBinding(
"KP_End",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewEndOfLineHandler")))
bindings.add(
@@ -511,14 +516,14 @@ class FlatReviewPresenter:
keybindings.KeyBinding(
"p",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("toggleFlatReviewModeHandler")))
bindings.add(
keybindings.KeyBinding(
"semicolon",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("flatReviewSayAllHandler"),
2))
@@ -526,21 +531,21 @@ class FlatReviewPresenter:
keybindings.KeyBinding(
"u",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewPreviousLineHandler")))
bindings.add(
keybindings.KeyBinding(
"u",
keybindings.defaultModifierMask,
keybindings.ORCA_CTRL_MODIFIER_MASK,
keybindings.CTHULHU_CTRL_MODIFIER_MASK,
self._handlers.get("reviewHomeHandler")))
bindings.add(
keybindings.KeyBinding(
"i",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewCurrentLineHandler"),
1))
@@ -548,7 +553,7 @@ class FlatReviewPresenter:
keybindings.KeyBinding(
"i",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewSpellCurrentLineHandler"),
2))
@@ -556,7 +561,7 @@ class FlatReviewPresenter:
keybindings.KeyBinding(
"i",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewPhoneticCurrentLineHandler"),
3))
@@ -564,35 +569,35 @@ class FlatReviewPresenter:
keybindings.KeyBinding(
"o",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewNextLineHandler")))
bindings.add(
keybindings.KeyBinding(
"o",
keybindings.defaultModifierMask,
keybindings.ORCA_CTRL_MODIFIER_MASK,
keybindings.CTHULHU_CTRL_MODIFIER_MASK,
self._handlers.get("reviewEndHandler")))
bindings.add(
keybindings.KeyBinding(
"j",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewPreviousItemHandler")))
bindings.add(
keybindings.KeyBinding(
"j",
keybindings.defaultModifierMask,
keybindings.ORCA_CTRL_MODIFIER_MASK,
keybindings.CTHULHU_CTRL_MODIFIER_MASK,
self._handlers.get("reviewAboveHandler")))
bindings.add(
keybindings.KeyBinding(
"k",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewCurrentItemHandler"),
1))
@@ -600,7 +605,7 @@ class FlatReviewPresenter:
keybindings.KeyBinding(
"k",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewSpellCurrentItemHandler"),
2))
@@ -608,7 +613,7 @@ class FlatReviewPresenter:
keybindings.KeyBinding(
"k",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewPhoneticCurrentItemHandler"),
3))
@@ -616,42 +621,42 @@ class FlatReviewPresenter:
keybindings.KeyBinding(
"k",
keybindings.defaultModifierMask,
keybindings.ORCA_CTRL_MODIFIER_MASK,
keybindings.CTHULHU_CTRL_MODIFIER_MASK,
self._handlers.get("reviewCurrentAccessibleHandler")))
bindings.add(
keybindings.KeyBinding(
"l",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewNextItemHandler")))
bindings.add(
keybindings.KeyBinding(
"l",
keybindings.defaultModifierMask,
keybindings.ORCA_CTRL_MODIFIER_MASK,
keybindings.CTHULHU_CTRL_MODIFIER_MASK,
self._handlers.get("reviewBelowHandler")))
bindings.add(
keybindings.KeyBinding(
"m",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewPreviousCharacterHandler")))
bindings.add(
keybindings.KeyBinding(
"m",
keybindings.defaultModifierMask,
keybindings.ORCA_CTRL_MODIFIER_MASK,
keybindings.CTHULHU_CTRL_MODIFIER_MASK,
self._handlers.get("reviewEndOfLineHandler")))
bindings.add(
keybindings.KeyBinding(
"comma",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewCurrentCharacterHandler"),
1))
@@ -659,7 +664,7 @@ class FlatReviewPresenter:
keybindings.KeyBinding(
"comma",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewSpellCurrentCharacterHandler"),
2))
@@ -667,7 +672,7 @@ class FlatReviewPresenter:
keybindings.KeyBinding(
"comma",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewUnicodeCurrentCharacterHandler"),
3))
@@ -675,7 +680,7 @@ class FlatReviewPresenter:
keybindings.KeyBinding(
"period",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("reviewNextCharacterHandler")))
bindings.add(
+8 -2
View File
@@ -1,6 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2004-2009 Sun Microsystems Inc.
# 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
@@ -16,6 +19,9 @@
# 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
"""Manages the formatting settings for Cthulhu."""
+8 -3
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2009 Sun Microsystems Inc.
# Copyright 2015-2016 Igalia, S.L.
# 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
@@ -17,6 +19,9 @@
# 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
"""Superclass of classes used to generate presentations for objects."""
+8 -3
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2004-2009 Sun Microsystems Inc.
# Copyright 2010-2013 The Cthulhu Team
# 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
@@ -17,6 +19,9 @@
# 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
"""Labels for Cthulhu's GUIs. These have been put in their own module so that we
can present them in the correct language when users change the language on the
+8 -3
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2023 Igalia, S.L.
# Author: Joanmarie Diggs <jdiggs@igalia.com>
# 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
@@ -17,6 +19,9 @@
# 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
"""Module for drawing highlights over an area of interest."""
+12 -7
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2005-2008 Sun Microsystems Inc.
# Copyright 2011-2016 Igalia, S.L.
# 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
@@ -17,6 +19,9 @@
# 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
"""Provides support for handling input events."""
@@ -309,7 +314,7 @@ class KeyboardEvent(InputEvent):
and not KeyboardEvent.lastCthulhuModifierAlone:
doubleEvent = self._getDoubleClickCandidate()
if doubleEvent and \
doubleEvent.modifiers & keybindings.ORCA_MODIFIER_MASK:
doubleEvent.modifiers & keybindings.CTHULHU_MODIFIER_MASK:
# this is the second event of a double-click, and sticky Cthulhu
# affected the first, so copy over the modifiers to the second
KeyboardEvent.cthulhuStickyModifiers = doubleEvent.modifiers
@@ -395,7 +400,7 @@ class KeyboardEvent(InputEvent):
KeyboardEvent.cthulhuModifierPressed = False
if KeyboardEvent.cthulhuModifierPressed:
self.modifiers |= keybindings.ORCA_MODIFIER_MASK
self.modifiers |= keybindings.CTHULHU_MODIFIER_MASK
if KeyboardEvent.stickyKeys:
# apply all recorded sticky modifiers
@@ -482,7 +487,7 @@ class KeyboardEvent(InputEvent):
if self.modifiers & keybindings.CTRL_MODIFIER_MASK \
or self.modifiers & keybindings.ALT_MODIFIER_MASK \
or self.modifiers & keybindings.ORCA_MODIFIER_MASK:
or self.modifiers & keybindings.CTHULHU_MODIFIER_MASK:
return False
return True
@@ -627,7 +632,7 @@ class KeyboardEvent(InputEvent):
if cthulhu_state.bypassNextCommand:
return False
return self.modifiers & keybindings.ORCA_MODIFIER_MASK
return self.modifiers & keybindings.CTHULHU_MODIFIER_MASK
def isKeyPadKeyWithNumlockOn(self):
"""Return True if this is a key pad key with numlock on."""
+18 -12
View File
@@ -1,6 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2005-2008 Sun Microsystems Inc.
# 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
@@ -16,6 +19,9 @@
# 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
"""Provides support for defining keybindings and matching them to input
events."""
@@ -43,19 +49,19 @@ from .cthulhu_i18n import _
_keysymsCache = {}
_keycodeCache = {}
MODIFIER_ORCA = 8
MODIFIER_CTHULHU = 8
NO_MODIFIER_MASK = 0
ALT_MODIFIER_MASK = 1 << Atspi.ModifierType.ALT
CTRL_MODIFIER_MASK = 1 << Atspi.ModifierType.CONTROL
ORCA_MODIFIER_MASK = 1 << MODIFIER_ORCA
ORCA_ALT_MODIFIER_MASK = (1 << MODIFIER_ORCA |
CTHULHU_MODIFIER_MASK = 1 << MODIFIER_CTHULHU
CTHULHU_ALT_MODIFIER_MASK = (1 << MODIFIER_CTHULHU |
1 << Atspi.ModifierType.ALT)
ORCA_CTRL_MODIFIER_MASK = (1 << MODIFIER_ORCA |
CTHULHU_CTRL_MODIFIER_MASK = (1 << MODIFIER_CTHULHU |
1 << Atspi.ModifierType.CONTROL)
ORCA_CTRL_ALT_MODIFIER_MASK = (1 << MODIFIER_ORCA |
CTHULHU_CTRL_ALT_MODIFIER_MASK = (1 << MODIFIER_CTHULHU |
1 << Atspi.ModifierType.CONTROL |
1 << Atspi.ModifierType.ALT)
ORCA_SHIFT_MODIFIER_MASK = (1 << MODIFIER_ORCA |
CTHULHU_SHIFT_MODIFIER_MASK = (1 << MODIFIER_CTHULHU |
1 << Atspi.ModifierType.SHIFT)
SHIFT_MODIFIER_MASK = 1 << Atspi.ModifierType.SHIFT
SHIFT_ALT_MODIFIER_MASK = (1 << Atspi.ModifierType.SHIFT |
@@ -71,7 +77,7 @@ NON_LOCKING_MODIFIER_MASK = (1 << Atspi.ModifierType.SHIFT |
1 << Atspi.ModifierType.CONTROL |
1 << Atspi.ModifierType.META2 |
1 << Atspi.ModifierType.META3 |
1 << MODIFIER_ORCA)
1 << MODIFIER_CTHULHU)
defaultModifierMask = NON_LOCKING_MODIFIER_MASK
def getKeycode(keysym):
@@ -137,7 +143,7 @@ def getModifierNames(mods):
"""
text = ""
if mods & ORCA_MODIFIER_MASK:
if mods & CTHULHU_MODIFIER_MASK:
if settings.keyboardLayout == settings.GENERAL_KEYBOARD_LAYOUT_DESKTOP:
# Translators: this is presented in a GUI to represent the
# "insert" key when used as the Cthulhu modifier.
@@ -280,12 +286,12 @@ class KeyBinding:
if not self.keycode:
self.keycode = getKeycode(self.keysymstring)
if self.modifiers & ORCA_MODIFIER_MASK:
if self.modifiers & CTHULHU_MODIFIER_MASK:
device = cthulhu_state.device
if device is None:
return ret
modList = []
otherMods = self.modifiers & ~ORCA_MODIFIER_MASK
otherMods = self.modifiers & ~CTHULHU_MODIFIER_MASK
numLockMod = device.get_modifier(getKeycode("Num_Lock"))
lockedMods = device.get_locked_modifiers()
numLockOn = lockedMods & numLockMod
+8 -2
View File
@@ -1,6 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2006-2008 Sun Microsystems Inc.
# 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
@@ -16,6 +19,9 @@
# 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
"""Exposes a dictionary, keynames, that maps key events
into localized words."""
+8 -4
View File
@@ -1,8 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright (C) 2011-2013 Igalia, S.L.
#
# Author: Joanmarie Diggs <jdiggs@igalia.com>
# 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
@@ -18,6 +19,9 @@
# 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
"""Heuristic means to infer the functional/displayed label of a widget."""
+19 -13
View File
@@ -1,6 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2010 Joanmarie Diggs, Mesar Hameed.
# 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
@@ -16,6 +19,9 @@
# 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
""" A list of common keybindings and unbound keys
pulled out from default.py: __getLaptopBindings()
@@ -32,14 +38,14 @@ from . import keybindings
# Storing values
defaultModifierMask = keybindings.defaultModifierMask
ORCA_MODIFIER_MASK = keybindings.ORCA_MODIFIER_MASK
CTHULHU_MODIFIER_MASK = keybindings.CTHULHU_MODIFIER_MASK
NO_MODIFIER_MASK = keybindings.NO_MODIFIER_MASK
ORCA_SHIFT_MODIFIER_MASK = keybindings.ORCA_SHIFT_MODIFIER_MASK
ORCA_CTRL_MODIFIER_MASK = keybindings.ORCA_CTRL_MODIFIER_MASK
CTHULHU_SHIFT_MODIFIER_MASK = keybindings.CTHULHU_SHIFT_MODIFIER_MASK
CTHULHU_CTRL_MODIFIER_MASK = keybindings.CTHULHU_CTRL_MODIFIER_MASK
keymap = (
("9", defaultModifierMask, ORCA_MODIFIER_MASK,
("9", defaultModifierMask, CTHULHU_MODIFIER_MASK,
"routePointerToItemHandler"),
# We want the user to be able to combine modifiers with the
@@ -48,22 +54,22 @@ keymap = (
# modifier).
#
("7", ORCA_MODIFIER_MASK, ORCA_MODIFIER_MASK,
("7", CTHULHU_MODIFIER_MASK, CTHULHU_MODIFIER_MASK,
"leftClickReviewItemHandler"),
("8", ORCA_MODIFIER_MASK, ORCA_MODIFIER_MASK,
("8", CTHULHU_MODIFIER_MASK, CTHULHU_MODIFIER_MASK,
"rightClickReviewItemHandler"),
("semicolon", defaultModifierMask, ORCA_MODIFIER_MASK,
("semicolon", defaultModifierMask, CTHULHU_MODIFIER_MASK,
"sayAllHandler", 1),
("bracketleft", defaultModifierMask, ORCA_MODIFIER_MASK,
("bracketleft", defaultModifierMask, CTHULHU_MODIFIER_MASK,
"findHandler"),
("bracketright", defaultModifierMask, ORCA_MODIFIER_MASK,
("bracketright", defaultModifierMask, CTHULHU_MODIFIER_MASK,
"findNextHandler"),
("bracketright", defaultModifierMask, ORCA_CTRL_MODIFIER_MASK,
("bracketright", defaultModifierMask, CTHULHU_CTRL_MODIFIER_MASK,
"findPreviousHandler"),
)
+9 -4
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2005-2008 Sun Microsystems Inc.
# Copyright 2016-2023 Igalia, S.L.
# 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
@@ -17,6 +19,9 @@
# 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
"""Module for learn mode"""
@@ -94,7 +99,7 @@ class LearnModePresenter:
keybindings.KeyBinding(
"h",
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self._handlers.get("enterLearnModeHandler")))
return bindings
+27 -2
View File
@@ -1,3 +1,28 @@
#!/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
import gi
gi.require_version("Atspi", "2.0")
from gi.repository import Atspi
@@ -168,7 +193,7 @@ class LiveRegionManager:
keybindings.KeyBinding(
"backslash",
keybindings.defaultModifierMask,
keybindings.ORCA_SHIFT_MODIFIER_MASK,
keybindings.CTHULHU_SHIFT_MODIFIER_MASK,
self.inputEventHandlers.get("monitorLiveRegions")))
for key in ["F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"]:
@@ -176,7 +201,7 @@ class LiveRegionManager:
keybindings.KeyBinding(
key,
keybindings.defaultModifierMask,
keybindings.ORCA_MODIFIER_MASK,
keybindings.CTHULHU_MODIFIER_MASK,
self.inputEventHandlers.get("reviewLiveAnnouncement")))
return keyBindings
+8 -5
View File
@@ -1,9 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2008 Sun Microsystems Inc.
# Copyright 2012 Igalia, S.L.
#
# Author: Joanmarie Diggs <jdiggs@igalia.com>
# 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
@@ -19,6 +19,9 @@
# 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
"""Output logger for regression testing."""
+8 -4
View File
@@ -1,8 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2014 Igalia, S.L.
#
# Author: Joanmarie Diggs <jdiggs@igalia.com>
# 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
@@ -18,6 +19,9 @@
# 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
__id__ = "$Id$"
__version__ = "$Revision$"
+24 -14
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2004-2009 Sun Microsystems Inc.
# Copyright 2010-2013 The Cthulhu Team
# 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
@@ -17,6 +19,9 @@
# 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
"""Messages which Cthulhu presents in speech and/or braille. These
have been put in their own module so that we can present them in
@@ -162,7 +167,7 @@ CARET_CONTROL_APP = _("The application is controlling the caret.")
# itself controls how the arrow keys move the caret around HTML content. It's
# often broken, so Cthulhu needs to provide its own support. As such, Cthulhu offers
# the user the ability to toggle which application is controlling the caret.
CARET_CONTROL_ORCA = _("The screen reader is controlling the caret.")
CARET_CONTROL_CTHULHU = _("Cthulhu is controlling the caret.")
# Translators: this is the name of a cell in a spreadsheet.
CELL = _("Cell %s")
@@ -241,7 +246,7 @@ CLI_LOAD_PROFILE_ERROR = _("Profile could not be loaded: %s")
# Translators: This message is presented to the user who attempts to launch Cthulhu
# from some other environment than the graphical desktop.
CLI_NO_DESKTOP_ERROR = \
_("Cannot start the screen reader because it cannot connect to the Desktop.")
_("Cannot start Cthulhu because it cannot connect to the Desktop.")
# Translators: This message is presented to the user who attempts to launch Cthulhu
# but the launch fails due to an error related to the settings manager.
@@ -250,8 +255,8 @@ CLI_SETTINGS_MANAGER_ERROR = \
# Translators: This message is presented to the user when he/she tries to launch
# Cthulhu, but Cthulhu is already running.
CLI_OTHER_ORCAS_ERROR = \
_('Another screen reader process is already running for this ' \
CLI_OTHER_CTHULHUS_ERROR = \
_('Another Cthulhu process is already running for this ' \
'session.\nRun “cthulhu --replace” to replace that ' \
'process with a new one.')
@@ -274,7 +279,7 @@ CLI_VERSION = _("Version of this application")
# Translators: This is the description of command line option '-r, --replace'
# which tells Cthulhu to replace any existing Cthulhu process that might be running.
CLI_REPLACE = _("Replace a currently running instance of this screen reader")
CLI_REPLACE = _("Replace a currently running instance of Cthulhu")
# Translators: this is the description of command line option '-h, --help'
# which lists all the available command line options.
@@ -1194,9 +1199,9 @@ LEARN_MODE_START_BRAILLE = _("Learn mode. Press escape to exit.")
# Mode.
LEARN_MODE_START_SPEECH = \
_("Entering learn mode. Press any key to hear its function. " \
"To view the screen readers documentation, press F1. " \
"To get a list of the screen readers default shortcuts, press F2. " \
"To get a list of the screen readers shortcuts for the current application, " \
"To view Cthulhus documentation, press F1. " \
"To get a list of Cthulhus default shortcuts, press F2. " \
"To get a list of Cthulhus shortcuts for the current application, " \
"press F3. " \
"To exit learn mode, press the escape key.")
@@ -2291,10 +2296,15 @@ SPEECH_VERBOSITY_VERBOSE = C_("Speech", "Verbosity level: verbose")
SPOKEN_ELLIPSIS = _(" dot dot dot")
# Translators: This message is presented to the user when Cthulhu is launched.
START_ORCA = _("Cthulhu welcomes you.")
START_CTHULHU = _("Cthulhu welcomes you.")
# Translators: This message is presented to the user when Cthulhu is quit.
STOP_ORCA = _("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.")
@@ -2512,7 +2522,7 @@ UNDO = C_("command", "undo")
REDO = C_("command", "redo")
# Translators: This message presents the Cthulhu version number.
VERSION = _("Screen reader version %s.") % version
VERSION = _("Cthulhu version %s.") % version
# Translators: This is presented when the user has navigated to a line with only
# whitespace characters (space, tab, etc.) on it.
+8 -3
View File
@@ -1,7 +1,9 @@
# Mouse reviewer for Cthulhu
#!/usr/bin/env python3
#
# Copyright 2008 Eitan Isaacson
# Copyright 2016 Igalia, S.L.
# 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
@@ -17,6 +19,9 @@
# 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
"""Mouse review mode."""
+8 -6
View File
@@ -1,10 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2023 Igalia, S.L.
# Author: Joanmarie Diggs <jdiggs@igalia.com>
# Based on the feature created by:
# Author: Jose Vilmar <vilmar@informal.com.br>
# Copyright 2010 Informal Informatica LTDA.
# 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
@@ -20,6 +19,9 @@
# 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
"""Module for notification messages"""
+14 -9
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2023 The Cthulhu Team
# Author: Rynhardt Kruger <rynkruger@gmail.com>
# 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
@@ -17,6 +19,9 @@
# 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
"""Provides ability to navigate objects hierarchically."""
@@ -68,42 +73,42 @@ class ObjectNavigator:
keybindings.KeyBinding(
"Up",
keybindings.defaultModifierMask,
keybindings.ORCA_CTRL_MODIFIER_MASK,
keybindings.CTHULHU_CTRL_MODIFIER_MASK,
self._handlers.get("object_navigator_up")))
bindings.add(
keybindings.KeyBinding(
"Down",
keybindings.defaultModifierMask,
keybindings.ORCA_CTRL_MODIFIER_MASK,
keybindings.CTHULHU_CTRL_MODIFIER_MASK,
self._handlers.get("object_navigator_down")))
bindings.add(
keybindings.KeyBinding(
"Right",
keybindings.defaultModifierMask,
keybindings.ORCA_CTRL_MODIFIER_MASK,
keybindings.CTHULHU_CTRL_MODIFIER_MASK,
self._handlers.get("object_navigator_next")))
bindings.add(
keybindings.KeyBinding(
"Left",
keybindings.defaultModifierMask,
keybindings.ORCA_CTRL_MODIFIER_MASK,
keybindings.CTHULHU_CTRL_MODIFIER_MASK,
self._handlers.get("object_navigator_previous")))
bindings.add(
keybindings.KeyBinding(
"Return",
keybindings.defaultModifierMask,
keybindings.ORCA_CTRL_MODIFIER_MASK,
keybindings.CTHULHU_CTRL_MODIFIER_MASK,
self._handlers.get("object_navigator_perform_action")))
bindings.add(
keybindings.KeyBinding(
"s",
keybindings.defaultModifierMask,
keybindings.ORCA_CTRL_MODIFIER_MASK,
keybindings.CTHULHU_CTRL_MODIFIER_MASK,
self._handlers.get("object_navigator_toggle_simplify")))
return bindings
+8 -3
View File
@@ -1,7 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2004-2009 Sun Microsystems Inc.
# Copyright 2010-2013 The Cthulhu Team
# 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
@@ -17,6 +19,9 @@
# 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
"""Propeerties of accessible objects. These have been put in their own module
so that we can present them in the correct language when users change the
+8 -2
View File
@@ -1,6 +1,9 @@
# Cthulhu
#!/usr/bin/env python3
#
# Copyright 2006-2008 Sun Microsystems Inc.
# 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
@@ -16,6 +19,9 @@
# 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
"""Provides getPhoneticName method that maps each letter of the
alphabet into its localized phonetic equivalent."""
+78 -149
View File
@@ -1,160 +1,89 @@
import os, inspect
import gi
from gi.repository import GObject
#!/usr/bin/env python3
# Copyright (c) 2024 Stormux
#
# 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.
class Plugin():
#__gtype_name__ = 'BasePlugin'
"""Base class for Cthulhu plugins using pluggy."""
def __init__(self, *args, **kwargs):
self.API = None
self.pluginInfo = None
self.moduleDir = ''
self.hidden = False
self.moduleName = ''
import os
import logging
# Import pluggy for hook specifications
try:
import pluggy
cthulhu_hookimpl = pluggy.HookimplMarker("cthulhu")
PLUGGY_AVAILABLE = True
except ImportError:
# Fallback if pluggy is not available
def cthulhu_hookimpl(func=None, **kwargs):
"""Fallback decorator when pluggy is not available.
This is a no-op decorator that returns the original function.
It allows the code to continue working without pluggy, though
plugins will be disabled.
"""
if func is None:
return lambda f: f
return func
PLUGGY_AVAILABLE = False
logging.getLogger(__name__).info("Pluggy not available, plugins will be disabled")
logger = logging.getLogger(__name__)
class Plugin:
"""Base class for Cthulhu plugins."""
def __init__(self):
"""Initialize the plugin with default attributes."""
self.app = None
self.plugin_info = None
self.module_name = ''
self.name = ''
self.version = ''
self.website = ''
self.authors = []
self.buildIn = False
self.description = ''
self.iconName = ''
self.copyright = ''
self.dependencies = False
self.helpUri = ''
self.dataDir = ''
self.translationContext = None
def setApp(self, app):
def set_app(self, app):
"""Set the application reference."""
self.app = app
self.dynamicApiManager = app.getDynamicApiManager()
self.signalManager = app.getSignalManager()
def getApp(self):
return self.app
def setPluginInfo(self, pluginInfo):
self.pluginInfo = pluginInfo
self.updatePluginInfoAttributes()
def getPluginInfo(self):
return self.pluginInfo
def updatePluginInfoAttributes(self):
self.moduleDir = ''
self.hidden = False
self.moduleName = ''
self.name = ''
self.version = ''
self.website = ''
self.authors = []
self.buildIn = False
self.description = ''
self.iconName = ''
self.copyright = ''
self.dependencies = False
self.helpUri = ''
self.dataDir = ''
pluginInfo = self.getPluginInfo()
if pluginInfo == None:
def set_plugin_info(self, plugin_info):
"""Set plugin information and extract relevant attributes."""
self.plugin_info = plugin_info
if plugin_info:
self.module_name = getattr(plugin_info, 'module_name', '')
self.name = getattr(plugin_info, 'name', '')
self.version = getattr(plugin_info, 'version', '')
self.description = getattr(plugin_info, 'description', '')
@cthulhu_hookimpl
def activate(self, plugin=None):
"""Activate the plugin. Override this in subclasses."""
if plugin is not None and plugin is not self:
return
self.moduleName = self.getApp().getPluginSystemManager().getPluginModuleName(pluginInfo)
self.name = self.getApp().getPluginSystemManager().getPluginName(pluginInfo)
self.version = self.getApp().getPluginSystemManager().getPluginVersion(pluginInfo)
self.moduleDir = self.getApp().getPluginSystemManager().getPluginModuleDir(pluginInfo)
self.buildIn = self.getApp().getPluginSystemManager().isPluginBuildIn(pluginInfo)
self.description = self.getApp().getPluginSystemManager().getPluginDescription(pluginInfo)
self.hidden = self.getApp().getPluginSystemManager().isPluginHidden(pluginInfo)
self.website = self.getApp().getPluginSystemManager().getPluginWebsite(pluginInfo)
self.authors = self.getApp().getPluginSystemManager().getPluginAuthors(pluginInfo)
self.iconName = self.getApp().getPluginSystemManager().getPluginIconName(pluginInfo)
self.copyright = self.getApp().getPluginSystemManager().getPluginCopyright(pluginInfo)
self.dependencies = self.getApp().getPluginSystemManager().getPluginDependencies(pluginInfo)
logger.info(f"Activating plugin: {self.name}")
#settings = self.getApp().getPluginSystemManager().getPluginSettings(pluginInfo)
#hasDependencies = self.getApp().getPluginSystemManager().hasPluginDependency(pluginInfo)
@cthulhu_hookimpl
def deactivate(self, plugin=None):
"""Deactivate the plugin. Override this in subclasses."""
if plugin is not None and plugin is not self:
return
logger.info(f"Deactivating plugin: {self.name}")
#externalData = self.getApp().getPluginSystemManager().getPluginExternalData(pluginInfo)
self.helpUri = self.getApp().getPluginSystemManager().getPlugingetHelpUri(pluginInfo)
self.dataDir = self.getApp().getPluginSystemManager().getPluginDataDir(pluginInfo)
self.updateTranslationContext()
def updateTranslationContext(self, domain = None, localeDir = None, language = None, fallbackToCthulhuTranslation = True):
self.translationContext = None
useLocaleDir = '{}/locale/'.format(self.getModuleDir())
if localeDir:
if os.path.isdir(localeDir):
useLocaleDir = localeDir
useName = self.getModuleName()
useDomain = useName
if domain:
useDomain = domain
useLanguage = None
if language:
useLanguage = language
self.translationContext = self.getApp().getTranslationManager().initTranslation(useName, domain=useDomain, localeDir=useLocaleDir, language=useLanguage, fallbackToCthulhuTranslation=fallbackToCthulhuTranslation)
# Point _ to the translation object in the globals namespace of the caller frame
try:
callerFrame = inspect.currentframe().f_back
# Install our gettext and ngettext function to the upper frame
callerFrame.f_globals['_'] = self.translationContext.gettext
callerFrame.f_globals['ngettext'] = self.translationContext.ngettext
finally:
del callerFrame # Avoid reference problems with frames (per python docs)
def getTranslationContext(self):
return self.translationContext
def isPluginBuildIn(self):
return self.buildIn
def isPluginHidden(self):
return self.hidden
def getAuthors(self):
return self.authors
def getCopyright(self):
return self.copyright
def getDataDir(self):
return self.dataDir
def getDependencies(self):
return self.dependencies
def getDescription(self):
return self.description
def getgetHelpUri(self):
return self.helpUri
def getIconName(self):
return self.iconName
def getModuleDir(self):
return self.moduleDir
def getModuleName(self):
return self.moduleName
def getName(self):
return self.name
def getVersion(self):
return self.version
def getWebsite(self):
return self.website
def getSetting(key):
#self.getModuleName())
def registerGestureByString(self, function, name, gestureString, learnModeEnabled=True):
"""Register a gesture by string."""
if self.app:
api_helper = self.app.getAPIHelper()
if api_helper:
return api_helper.registerGestureByString(
function,
name,
gestureString,
'default',
'cthulhu',
learnModeEnabled,
contextName=self.module_name
)
return None
def setSetting(key, value):
#self.getModuleName())
pass
def registerGestureByString(self, function, name, gestureString, learnModeEnabled = True):
keybinding = self.getApp().getAPIHelper().registerGestureByString(function, name, gestureString, 'default', 'cthulhu', learnModeEnabled, contextName = self.getModuleName())
return keybinding
def unregisterShortcut(self, function, name, gestureString, learnModeEnabled = True):
ok = self.getApp().getAPIHelper().unregisterShortcut(keybinding, contextName = self.getModuleName())
return ok
def registerSignal(self, signalName, signalFlag = GObject.SignalFlags.RUN_LAST, closure = GObject.TYPE_NONE, accumulator=()):
ok = self.signalManager.registerSignal(signalName, signalFlag, closure, accumulator, contextName = self.getModuleName())
return ok
def unregisterSignal(self, signalName):
# how to unregister?
pass
def connectSignal(self, signalName, function, param = None):
signalID = self.signalManager.connectSignal(signalName, function, param, contextName = self.getModuleName())
return signalID
def disconnectSignalByFunction(self, function):
# need get mapped function
mappedFunction = function
self.signalManager.disconnectSignalByFunction(mappedFunction, contextName = self.getModuleName())
def registerAPI(self, key, value, application = ''):
ok = self.dynamicApiManager.registerAPI(key, value, application = application, contextName = self.getModuleName())
return ok
def unregisterAPI(self, key, application = ''):
self.dynamicApiManager.unregisterAPI(key, application = application, contextName = self.getModuleName())
+297 -474
View File
@@ -1,520 +1,343 @@
#!/bin/python
"""PluginManager for loading cthulhu plugins."""
import os, inspect, sys, tarfile, shutil
#!/usr/bin/env python3
# Copyright (c) 2024 Stormux
#
# 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.
"""Plugin System Manager for Cthulhu using pluggy."""
import os
import inspect
import importlib.util
import logging
from enum import IntEnum
version = sys.version[:3] # we only need major.minor version.
if version in ["3.3","3.4"]:
from importlib.machinery import SourceFileLoader
else: # Python 3.5+, no support for python < 3.3.
import importlib.util
# Import pluggy if available
try:
import pluggy
PLUGGY_AVAILABLE = True
except ImportError:
PLUGGY_AVAILABLE = False
logging.getLogger(__name__).info("Pluggy not available, plugins will be disabled")
import gi
gi.require_version('Peas', '1.0')
from gi.repository import GObject
from gi.repository import Peas
gi.require_version('Atspi', '2.0')
from gi.repository import Atspi
from cthulhu import resource_manager
class API(GObject.GObject):
"""Interface that gives access to all the objects of Cthulhu."""
def __init__(self, app):
GObject.GObject.__init__(self)
self.app = app
logger = logging.getLogger(__name__)
class PluginType(IntEnum):
"""Types of plugins we support, depending on their directory location."""
# pylint: disable=comparison-with-callable,inconsistent-return-statements,no-else-return
# SYSTEM: provides system wide plugins
"""Types of plugins we support."""
SYSTEM = 1
# USER: provides per user plugin
USER = 2
def __str__(self):
if self.value == PluginType.SYSTEM:
return _("System plugin")
elif self.value == PluginType.USER:
return _("User plugin")
def get_root_dir(self):
"""Returns the directory where this type of plugins can be found."""
if self.value == PluginType.SYSTEM:
return os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe())))) + '/plugins'
current_file = inspect.getfile(inspect.currentframe())
current_dir = os.path.dirname(os.path.realpath(os.path.abspath(current_file)))
return os.path.join(current_dir, 'plugins')
elif self.value == PluginType.USER:
return os.path.expanduser('~') + '/.local/share/cthulhu/plugins'
return os.path.expanduser('~/.local/share/cthulhu/plugins')
class PluginSystemManager():
"""Orca Plugin Manager to handle a set of plugins.
Attributes:
DEFAULT_LOADERS (tuple): Default loaders used by the plugin manager. For
possible values see
https://developer.gnome.org/libpeas/stable/PeasEngine.html#peas-engine-enable-loader
"""
DEFAULT_LOADERS = ("python3", )
class PluginInfo:
"""Information about a plugin."""
def __init__(self, name, module_name, module_dir, metadata=None):
self.name = name
self.module_name = module_name
self.module_dir = module_dir
self.metadata = metadata or {}
self.builtin = False
self.hidden = False
self.module = None
self.instance = None
self.loaded = False
def get_module_name(self):
return self.module_name
def get_name(self):
return self.metadata.get('name', self.name)
def get_version(self):
return self.metadata.get('version', '0.0.0')
def get_description(self):
return self.metadata.get('description', '')
def get_module_dir(self):
return self.module_dir
class PluginSystemManager:
"""Cthulhu Plugin Manager using pluggy."""
def __init__(self, app):
self.app = app
self.engine = Peas.Engine.get_default()
for loader in self.DEFAULT_LOADERS:
self.engine.enable_loader(loader)
# Initialize plugin manager
if PLUGGY_AVAILABLE:
self.plugin_manager = pluggy.PluginManager("cthulhu")
# Define hook specifications
hook_spec = pluggy.HookspecMarker("cthulhu")
class CthulhuHookSpecs:
@hook_spec
def activate(self, plugin=None):
"""Called when the plugin is activated."""
pass
@hook_spec
def deactivate(self, plugin=None):
"""Called when the plugin is deactivated."""
pass
self.plugin_manager.add_hookspecs(CthulhuHookSpecs)
else:
self.plugin_manager = None
# Plugin storage
self._plugins = {} # module_name -> PluginInfo
self._active_plugins = []
# Create plugin directories
self._setup_plugin_dirs()
def _setup_plugin_dirs(self):
"""Ensure plugin directories exist."""
os.makedirs(PluginType.SYSTEM.get_root_dir(), exist_ok=True)
os.makedirs(PluginType.USER.get_root_dir(), exist_ok=True)
self._setupPluginsDir()
self._setupExtensionSet()
if self.app:
self.gsettingsManager = self.app.getSettingsManager()
# settings else:
# settings self.gsettingsManager = gsettings_manager.getSettingsManager(self.app)
self._activePlugins = []
self._ignorePluginModulePath = []
@property
def plugins(self):
"""Gets the engine's plugin list."""
return self.engine.get_plugin_list()
@classmethod
def getPluginType(cls, pluginInfo):
"""Gets the PluginType for the specified Peas.PluginInfo."""
paths = [pluginInfo.get_data_dir(), PluginType.SYSTEM.get_root_dir()]
if os.path.commonprefix(paths) == PluginType.SYSTEM.get_root_dir():
return PluginType.SYSTEM
return PluginType.USER
"""Get all available plugins."""
return list(self._plugins.values())
def getExtension(self, pluginInfo):
if not pluginInfo:
return None
return self.extension_set.get_extension(pluginInfo)
def rescanPlugins(self):
self.engine.garbage_collect()
self.engine.rescan_plugins()
def getApp(self):
return self.app
def getPluginInfoByName(self, pluginName, pluginType=PluginType.USER):
"""Gets the plugin info for the specified plugin name.
Args:
pluginName (str): The name from the .plugin file of the module.
Returns:
Peas.PluginInfo: The plugin info if it exists. Otherwise, `None`.
"""
for pluginInfo in self.plugins:
if pluginInfo.get_module_name() == pluginName and PluginSystemManager.getPluginType(pluginInfo) == pluginType:
return pluginInfo
return None
def rescanPlugins(self):
"""Scan for plugins in the plugin directories."""
old_plugins = self._plugins.copy()
self._plugins = {}
# Scan system and user plugins
self._scan_plugins_in_directory(PluginType.SYSTEM.get_root_dir())
self._scan_plugins_in_directory(PluginType.USER.get_root_dir())
# Preserve state for already loaded plugins
for name, old_info in old_plugins.items():
if name in self._plugins and old_info.loaded:
self._plugins[name].loaded = True
self._plugins[name].instance = old_info.instance
self._plugins[name].module = old_info.module
def _scan_plugins_in_directory(self, directory):
"""Scan for plugins in a directory."""
if not os.path.exists(directory) or not os.path.isdir(directory):
return
for item in os.listdir(directory):
plugin_dir = os.path.join(directory, item)
if not os.path.isdir(plugin_dir):
continue
plugin_file = os.path.join(plugin_dir, "plugin.py")
metadata_file = os.path.join(plugin_dir, "plugin.info")
if os.path.isfile(plugin_file):
# Extract plugin info
module_name = os.path.basename(plugin_dir)
metadata = self._load_plugin_metadata(metadata_file)
plugin_info = PluginInfo(
metadata.get('name', module_name),
module_name,
plugin_dir,
metadata
)
# Check if it's a built-in or hidden plugin
plugin_info.builtin = metadata.get('builtin', 'false').lower() == 'true'
plugin_info.hidden = metadata.get('hidden', 'false').lower() == 'true'
self._plugins[module_name] = plugin_info
def _load_plugin_metadata(self, metadata_file):
"""Load plugin metadata from a file."""
metadata = {}
if os.path.isfile(metadata_file):
try:
with open(metadata_file, 'r') as f:
for line in f:
line = line.strip()
if not line or line.startswith('#'):
continue
if '=' in line:
key, value = line.split('=', 1)
metadata[key.strip()] = value.strip()
except Exception as e:
logger.error(f"Error loading plugin metadata: {e}")
return metadata
def getActivePlugins(self):
return self._activePlugins
"""Get the list of active plugin names."""
return self._active_plugins
def setActivePlugins(self, activePlugins):
self._activePlugins = activePlugins
"""Set active plugins and sync their state."""
self._active_plugins = activePlugins
self.syncAllPluginsActive()
def isPluginBuildIn(self, pluginInfo):
return pluginInfo.is_builtin()
def isPluginHidden(self, pluginInfo):
return pluginInfo.is_hidden()
def getPluginAuthors(self, pluginInfo):
return pluginInfo.get_authors()
def getPluginCopyright(self, pluginInfo):
return pluginInfo.get_copyright()
def getPluginDataDir(self, pluginInfo):
return pluginInfo.get_data_dir()
def getPluginDependencies(self, pluginInfo):
return pluginInfo.get_dependencies()
def getPluginDescription(self, pluginInfo):
return pluginInfo.get_description()
def getPlugingetHelpUri(self, pluginInfo):
return pluginInfo.get_help_uri()
def getPluginIconName(self, pluginInfo):
return pluginInfo.get_icon_name()
def getPluginModuleDir(self, pluginInfo):
return pluginInfo.get_module_dir()
def getPluginModuleName(self, pluginInfo):
return pluginInfo.get_module_name()
def getPluginName(self, pluginInfo):
return pluginInfo.get_name()
def getPluginSettings(self, pluginInfo):
return pluginInfo.get_settings()
def getPluginVersion(self, pluginInfo):
return pluginInfo.get_version()
def getPluginWebsite(self, pluginInfo):
return pluginInfo.get_website()
# has_dependency and get_external_data seems broken-> takes exactly 2 arguments (1 given) but documentation doesnt say any parameter
#def hasPluginDependency(self, pluginInfo):
# return pluginInfo.has_dependency()
#def getPluginExternalData(self, pluginInfo):
# return pluginInfo.get_external_data()
def isPluginAvailable(self, pluginInfo):
try:
return pluginInfo.is_available()
except:
return False
def isPluginLoaded(self, pluginInfo):
try:
return pluginInfo.is_loaded()
except:
return False
def getIgnoredPlugins(self):
return self._ignorePluginModulePath
def setIgnoredPlugins(self, pluginModulePath, ignored):
if pluginModulePath.endswith('/'):
pluginModulePath = pluginModulePath[:-1]
if ignored:
if not pluginModulePath in self.getIgnoredPlugins():
self._ignorePluginModulePath.append(pluginModulePath)
else:
if pluginModulePath in self.getIgnoredPlugins():
self._ignorePluginModulePath.remove(pluginModulePath)
def setPluginActive(self, pluginInfo, active):
if self.isPluginBuildIn(pluginInfo):
"""Set the active state of a plugin."""
if pluginInfo.builtin:
active = True
pluginName = self.getPluginModuleName(pluginInfo)
if active:
if not pluginName in self.getActivePlugins():
if self.loadPlugin(pluginInfo):
self._activePlugins.append(pluginName )
else:
if pluginName in self.getActivePlugins():
if self.unloadPlugin(pluginInfo):
self._activePlugins.remove(pluginName )
def isPluginActive(self, pluginInfo):
if self.isPluginBuildIn(pluginInfo):
return True
if self.isPluginLoaded(pluginInfo):
return True
active_plugin_names = self.getActivePlugins()
return self.getPluginModuleName(pluginInfo) in active_plugin_names
def syncAllPluginsActive(self, ForceAllPlugins=False):
self.unloadAllPlugins(ForceAllPlugins)
self.loadAllPlugins(ForceAllPlugins)
def loadAllPlugins(self, ForceAllPlugins=False):
"""Loads plugins from settings."""
pluginName = pluginInfo.get_module_name()
if active:
if pluginName not in self.getActivePlugins():
if self.loadPlugin(pluginInfo):
self._active_plugins.append(pluginName)
else:
if pluginName in self.getActivePlugins():
if self.unloadPlugin(pluginInfo):
self._active_plugins.remove(pluginName)
def isPluginActive(self, pluginInfo):
"""Check if a plugin is active."""
if pluginInfo.builtin:
return True
if pluginInfo.loaded:
return True
return pluginInfo.get_module_name() in self.getActivePlugins()
def syncAllPluginsActive(self):
"""Sync the active state of all plugins."""
# First unload inactive plugins
for pluginInfo in self.plugins:
if self.isPluginActive(pluginInfo) or ForceAllPlugins:
if not self.isPluginActive(pluginInfo) and pluginInfo.loaded:
self.unloadPlugin(pluginInfo)
# Then load active plugins
for pluginInfo in self.plugins:
if self.isPluginActive(pluginInfo) and not pluginInfo.loaded:
self.loadPlugin(pluginInfo)
def loadPlugin(self, pluginInfo):
resourceManager = self.getApp().getResourceManager()
moduleName = pluginInfo.get_module_name()
try:
if pluginInfo not in self.plugins:
print("Plugin missing: {}".format(moduleName))
return False
resourceManager.addResourceContext(moduleName)
self.engine.load_plugin(pluginInfo)
except Exception as e:
print('loadPlugin:',e)
"""Load a plugin."""
# Skip if pluggy is not available
if not PLUGGY_AVAILABLE:
logger.info(f"Skipping plugin {pluginInfo.get_name()}: pluggy not available")
return False
return True
def unloadAllPlugins(self, ForceAllPlugins=False):
"""Loads plugins from settings."""
for pluginInfo in self.plugins:
if not self.isPluginActive(pluginInfo) or ForceAllPlugins:
self.unloadPlugin(pluginInfo)
module_name = pluginInfo.get_module_name()
try:
# Already loaded?
if pluginInfo.loaded:
return True
# Import plugin module
plugin_file = os.path.join(pluginInfo.get_module_dir(), "plugin.py")
spec = importlib.util.spec_from_file_location(module_name, plugin_file)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
pluginInfo.module = module
# Find Plugin class
plugin_class = None
for attr_name in dir(module):
attr = getattr(module, attr_name)
if (inspect.isclass(attr) and
attr.__module__ == module.__name__ and
hasattr(attr, 'activate')):
plugin_class = attr
break
if not plugin_class:
logger.error(f"No plugin class found in {module_name}")
return False
# Create and initialize plugin instance
plugin_instance = plugin_class()
pluginInfo.instance = plugin_instance
# Ensure plugins have a reference to the app
plugin_instance.app = self.getApp()
if hasattr(plugin_instance, 'set_app'):
plugin_instance.set_app(self.getApp())
if hasattr(plugin_instance, 'set_plugin_info'):
plugin_instance.set_plugin_info(pluginInfo)
# Register with pluggy and activate
self.plugin_manager.register(plugin_instance)
try:
self.plugin_manager.hook.activate(plugin=plugin_instance)
except Exception as e:
logger.error(f"Error activating plugin {module_name}: {e}")
return False
pluginInfo.loaded = True
logger.info(f"Loaded plugin: {module_name}")
return True
except Exception as e:
logger.error(f"Failed to load plugin {module_name}: {e}")
return False
def unloadPlugin(self, pluginInfo):
resourceManager = self.getApp().getResourceManager()
moduleName = pluginInfo.get_module_name()
try:
if pluginInfo not in self.plugins:
print("Plugin missing: {}".format(moduleName))
return False
if self.isPluginBuildIn(pluginInfo):
return False
self.engine.unload_plugin(pluginInfo)
self.getApp().getResourceManager().removeResourceContext(moduleName)
self.engine.garbage_collect()
except Exception as e:
print('unloadPlugin:',e)
"""Unload a plugin."""
# Skip if pluggy is not available
if not PLUGGY_AVAILABLE:
return False
return True
def installPlugin(self, pluginFilePath, pluginType=PluginType.USER):
if not self.isValidPluginFile(pluginFilePath):
return False
pluginFolder = pluginType.get_root_dir()
if not pluginFolder.endswith('/'):
pluginFolder += '/'
if not os.path.exists(pluginFolder):
os.mkdir(pluginFolder)
else:
if not os.path.isdir(pluginFolder):
return False
try:
with tarfile.open(pluginFilePath) as tar:
tar.extractall(path=pluginFolder)
except Exception as e:
print(e)
pluginModulePath = self.getModuleDirByPluginFile(pluginFilePath)
if pluginModulePath != '':
pluginModulePath = pluginFolder + pluginModulePath
self.setIgnoredPlugins(pluginModulePath[:-1], False) # without ending /
print('install', pluginFilePath)
self.callPackageTriggers(pluginModulePath, 'onPostInstall')
self.rescanPlugins()
return True
def getModuleDirByPluginFile(self, pluginFilePath):
if not isinstance(pluginFilePath, str):
return ''
if pluginFilePath == '':
return ''
if not os.path.exists(pluginFilePath):
return ''
try:
with tarfile.open(pluginFilePath) as tar:
tarMembers = tar.getmembers()
for tarMember in tarMembers:
if tarMember.isdir():
return tarMember.name
except Exception as e:
print(e)
return ''
def isValidPluginFile(self, pluginFilePath):
if not isinstance(pluginFilePath, str):
if pluginInfo.builtin:
return False
if pluginFilePath == '':
return False
if not os.path.exists(pluginFilePath):
return False
pluginFolder = ''
pluginFileExists = False
packageFileExists = False
try:
with tarfile.open(pluginFilePath) as tar:
tarMembers = tar.getmembers()
for tarMember in tarMembers:
if tarMember.isdir():
if pluginFolder == '':
pluginFolder = tarMember.name
if tarMember.isfile():
if tarMember.name.endswith('.plugin'):
pluginFileExists = True
if tarMember.name.endswith('package.py'):
pluginFileExists = True
if not tarMember.name.startswith(pluginFolder):
return False
except Exception as e:
print(e)
return False
return pluginFileExists
def uninstallPlugin(self, pluginInfo):
if self.isPluginBuildIn(pluginInfo):
return False
# do we want to allow removing system plugins?
if PluginSystemManager.getPluginType(pluginInfo) == PluginType.SYSTEM:
return False
pluginFolder = pluginInfo.get_data_dir()
if not pluginFolder.endswith('/'):
pluginFolder += '/'
if not os.path.isdir(pluginFolder):
return False
if self.isPluginActive(pluginInfo):
self.setPluginActive(pluginInfo, False)
SettingsManager = self.app.getSettingsManager()
# TODO SettingsManager.set_settings_value_list('active-plugins', self.getActivePlugins())
self.callPackageTriggers(pluginFolder, 'onPreUninstall')
try:
shutil.rmtree(pluginFolder, ignore_errors=True)
except Exception as e:
print(e)
return False
self.setIgnoredPlugins(pluginFolder, True)
self.rescanPlugins()
return True
def callPackageTriggers(self, pluginPath, trigger):
if not os.path.exists(pluginPath):
module_name = pluginInfo.get_module_name()
try:
# Not loaded?
if not pluginInfo.loaded:
return True
# Deactivate plugin
plugin_instance = pluginInfo.instance
if plugin_instance:
try:
self.plugin_manager.hook.deactivate(plugin=plugin_instance)
except Exception as e:
logger.error(f"Error deactivating plugin {module_name}: {e}")
# Unregister from pluggy
self.plugin_manager.unregister(plugin_instance)
# Clean up
pluginInfo.instance = None
pluginInfo.loaded = False
logger.info(f"Unloaded plugin: {module_name}")
return True
except Exception as e:
logger.error(f"Failed to unload plugin {module_name}: {e}")
return False
def unloadAllPlugins(self, ForceAllPlugins=False):
"""Unload all plugins."""
if not PLUGGY_AVAILABLE:
return
if not pluginPath.endswith('/'):
pluginPath += '/'
packageModulePath = pluginPath + 'package.py'
if not os.path.isfile(packageModulePath):
return
if not os.access(packageModulePath, os.R_OK):
return
package = self.getApp().getAPIHelper().importModule('package', packageModulePath)
if trigger == 'onPostInstall':
try:
package.onPostInstall(pluginPath, self.getApp())
except Exception as e:
print(e)
elif trigger == 'onPreUninstall':
try:
package.onPreUninstall(pluginPath, self.getApp())
except Exception as e:
print(e)
def _setupExtensionSet(self):
plugin_iface = API(self.getApp())
self.extension_set = Peas.ExtensionSet.new(self.engine,
Peas.Activatable,
["object"],
[plugin_iface])
self.extension_set.connect("extension-removed",
self.__extensionRemoved)
self.extension_set.connect("extension-added",
self.__extensionAdded)
def _setupPluginsDir(self):
system_plugins_dir = PluginType.SYSTEM.get_root_dir()
user_plugins_dir = PluginType.USER.get_root_dir()
if os.path.exists(user_plugins_dir):
self.engine.add_search_path(user_plugins_dir)
if os.path.exists(system_plugins_dir):
self.engine.add_search_path(system_plugins_dir)
def __extensionRemoved(self, unusedSet, pluginInfo, extension):
extension.deactivate()
def __extensionAdded(self, unusedSet, pluginInfo, extension):
extension.setApp(self.getApp())
extension.setPluginInfo(pluginInfo)
extension.activate()
def __loadedPlugins(self, engine, unusedSet):
"""Handles the changing of the loaded plugin list."""
self.getApp().settings.ActivePlugins = engine.get_property("loaded-plugins")
class APIHelper():
def __init__(self, app):
self.app = app
self.cthulhuKeyBindings = None
'''
_pluginAPIManager.seCthulhuAPI('Logger', _logger)
_pluginAPIManager.setCthulhuAPI('SettingsManager', _settingsManager)
_pluginAPIManager.setCthulhuAPI('ScriptManager', _scriptManager)
_pluginAPIManager.setCthulhuAPI('EventManager', _eventManager)
_pluginAPIManager.setCthulhuAPI('Speech', speech)
_pluginAPIManager.setCthulhuAPI('Sound', sound)
_pluginAPIManager.setCthulhuAPI('Braille', braille)
_pluginAPIManager.setCthulhuAPI('Debug', debug)
_pluginAPIManager.setCthulhuAPI('Messages', messages)
_pluginAPIManager.setCthulhuAPI('MouseReview', mouse_review)
_pluginAPIManager.setCthulhuAPI('NotificationMessages', notification_messages)
_pluginAPIManager.setCthulhuAPI('CthulhuState', cthulhu_state)
_pluginAPIManager.setCthulhuAPI('CthulhuPlatform', cthulhu_platform)
_pluginAPIManager.setCthulhuAPI('Settings', settings)
_pluginAPIManager.setCthulhuAPI('Keybindings', keybindings)
'''
def outputMessage(self, Message, interrupt=False):
settings = self.app.getDynamicApiManager().getAPI('Settings')
braille = self.app.getDynamicApiManager().getAPI('Braille')
speech = self.app.getDynamicApiManager().getAPI('Speech')
if speech != None:
if (settings.enableSpeech):
if interrupt:
speech.cancel()
if Message != '':
speech.speak(Message)
if braille != None:
if (settings.enableBraille):
braille.displayMessage(Message)
def createInputEventHandler(self, function, name, learnModeEnabled=True):
EventManager = self.app.getDynamicApiManager().getAPI('EventManager')
newInputEventHandler = EventManager.input_event.InputEventHandler(function, name, learnModeEnabled)
return newInputEventHandler
def registerGestureByString(self, function, name, gestureString, profile, application, learnModeEnabled = True, contextName = None):
gestureList = gestureString.split(',')
registeredGestures = []
for gesture in gestureList:
if gesture.startswith('kb:'):
shortcutString = gesture[3:]
registuredGesture = self.registerShortcutByString(function, name, shortcutString, profile, application, learnModeEnabled, contextName=contextName)
if registuredGesture:
registeredGestures.append(registuredGesture)
return registeredGestures
def registerShortcutByString(self, function, name, shortcutString, profile, application, learnModeEnabled = True, contextName = None):
keybindings = self.app.getDynamicApiManager().getAPI('Keybindings')
settings = self.app.getDynamicApiManager().getAPI('Settings')
resourceManager = self.app.getResourceManager()
clickCount = 0
cthulhuKey = False
shiftKey = False
ctrlKey = False
altKey = False
key = ''
shortcutList = shortcutString.split('+')
for shortcutElement in shortcutList:
shortcutElementLower = shortcutElement.lower()
if shortcutElementLower == 'press':
clickCount += 1
elif shortcutElement == 'cthulhu':
cthulhuKey = True
elif shortcutElementLower == 'shift':
shiftKey = True
elif shortcutElementLower == 'control':
ctrlKey = True
elif shortcutElementLower == 'alt':
altKey = True
else:
key = shortcutElementLower
if clickCount == 0:
clickCount = 1
if self.cthulhuKeyBindings == None:
self.cthulhuKeyBindings = keybindings.KeyBindings()
tryFunction = resource_manager.TryFunction(function)
newInputEventHandler = self.createInputEventHandler(tryFunction.runInputEvent, name, learnModeEnabled)
currModifierMask = keybindings.NO_MODIFIER_MASK
if cthulhuKey:
currModifierMask = currModifierMask | 1 << keybindings.MODIFIER_ORCA
if shiftKey:
currModifierMask = currModifierMask | 1 << Atspi.ModifierType.SHIFT
if altKey:
currModifierMask = currModifierMask | 1 << Atspi.ModifierType.ALT
if ctrlKey:
currModifierMask = currModifierMask | 1 << Atspi.ModifierType.CONTROL
newKeyBinding = keybindings.KeyBinding(key, keybindings.defaultModifierMask, currModifierMask, newInputEventHandler, clickCount)
self.cthulhuKeyBindings.add(newKeyBinding)
settings.keyBindingsMap["default"] = self.cthulhuKeyBindings
if contextName:
resourceContext = resourceManager.getResourceContext(contextName)
if resourceContext:
resourceEntry = resource_manager.ResourceEntry('keyboard', newKeyBinding, function, tryFunction, shortcutString)
resourceContext.addGesture(profile, application, newKeyBinding, resourceEntry)
return newKeyBinding
def unregisterShortcut(self, KeyBindingToRemove, contextName = None):
ok = False
keybindings = self.app.getDynamicApiManager().getAPI('Keybindings')
settings = self.app.getDynamicApiManager().getAPI('Settings')
resourceManager = self.app.getResourceManager()
if self.cthulhuKeyBindings == None:
self.cthulhuKeyBindings = keybindings.KeyBindings()
try:
self.cthulhuKeyBindings.remove(KeyBindingToRemove)
settings.keyBindingsMap["default"] = self.cthulhuKeyBindings
ok = True
except KeyError:
pass
if contextName:
resourceContext = resourceManager.getResourceContext(contextName)
if resourceContext:
resourceContext.removeGesture(KeyBindingToRemove)
return ok
def importModule(self, moduleName, moduleLocation):
if version in ["3.3","3.4"]:
return SourceFileLoader(moduleName, moduleLocation).load_module()
else:
spec = importlib.util.spec_from_file_location(moduleName, moduleLocation)
driver_mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(driver_mod)
return driver_mod
for pluginInfo in self.plugins:
if ForceAllPlugins or pluginInfo.loaded:
self.unloadPlugin(pluginInfo)
@@ -1,6 +0,0 @@
[Plugin]
Module=ByeCthulhu
Loader=python3
Name=Stop announcement for cthulhu
Description=Test plugin for cthulhu
Authors=Chrys chrys@linux-a11y.org
@@ -1,27 +0,0 @@
from cthulhu import plugin
import gi
gi.require_version('Peas', '1.0')
from gi.repository import GObject
from gi.repository import Peas
import time
class ByeOrca(GObject.Object, Peas.Activatable, plugin.Plugin):
#__gtype_name__ = 'ByeCthulhu'
object = GObject.Property(type=GObject.Object)
def __init__(self):
plugin.Plugin.__init__(self)
def do_activate(self):
API = self.object
self.connectSignal("stop-application-completed", self.process)
def do_deactivate(self):
API = self.object
def do_update_state(self):
API = self.object
def process(self, app):
messages = app.getDynamicApiManager().getAPI('Messages')
activeScript = app.getDynamicApiManager().getAPI('CthulhuState').activeScript
activeScript.presentationInterrupt()
activeScript.presentMessage(messages.STOP_ORCA, resetStyles=False)
+4 -4
View File
@@ -1,7 +1,7 @@
orca_python_PYTHON = \
cthulhu_python_PYTHON = \
__init__.py \
ByeCthulhu.plugin \
ByeCthulhu.py
plugin.info \
plugin.py
orca_pythondir=$(pkgpythondir)/plugins/ByeCthulhu
cthulhu_pythondir=$(pkgpythondir)/plugins/ByeCthulhu
@@ -0,0 +1,25 @@
#!/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
@@ -0,0 +1,8 @@
name = Bye Cthulhu
version = 1.0.0
description = Says goodbye when Cthulhu is shutting down
authors = Stormux <storm_dragon@stormux.org>
website = https://stormux.org
copyright = Copyright 2025
builtin = false
hidden = false
+74
View File
@@ -0,0 +1,74 @@
#!/usr/bin/env python3
#
# Copyright (c) 2025 Stormux
#
# 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.
"""Bye Cthulhu plugin for Cthulhu."""
import logging
import time
from cthulhu.plugin import Plugin, cthulhu_hookimpl
logger = logging.getLogger(__name__)
class ByeCthulhu(Plugin):
"""Plugin that speaks a goodbye message when Cthulhu is shutting down."""
def __init__(self, *args, **kwargs):
"""Initialize the plugin."""
super().__init__(*args, **kwargs)
logger.info("ByeCthulhu plugin initialized")
self._signal_handler_id = None
@cthulhu_hookimpl
def activate(self, plugin=None):
"""Activate the plugin."""
# Skip if this activation call isn't for us
if plugin is not None and plugin is not self:
return
logger.info("Activating ByeCthulhu plugin")
try:
# Connect to the stop-application-completed signal
signal_manager = self.app.getSignalManager()
self._signal_handler_id = signal_manager.connectSignal(
"stop-application-completed",
self.process
)
except Exception as e:
logger.error(f"Error activating ByeCthulhu plugin: {e}")
@cthulhu_hookimpl
def deactivate(self, plugin=None):
"""Deactivate the plugin."""
# Skip if this deactivation call isn't for us
if plugin is not None and plugin is not self:
return
logger.info("Deactivating ByeCthulhu plugin")
try:
# Disconnect signal if we have an ID
if self._signal_handler_id is not None:
signal_manager = self.app.getSignalManager()
signal_manager.disconnectSignal(
"stop-application-completed",
self._signal_handler_id
)
self._signal_handler_id = None
except Exception as e:
logger.error(f"Error deactivating ByeCthulhu plugin: {e}")
def process(self, app):
"""Process the stop-application-completed signal."""
try:
messages = app.getDynamicApiManager().getAPI('Messages')
state = app.getDynamicApiManager().getAPI('CthulhuState')
if state.activeScript:
state.activeScript.presentationInterrupt()
state.activeScript.presentMessage(messages.STOP_CTHULHU, resetStyles=False)
except Exception as e:
logger.error(f"Error in ByeCthulhu process: {e}")
@@ -1,3 +1,28 @@
#!/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
from cthulhu import plugin
import gi
@@ -58,16 +83,16 @@ class CapsLockHack(GObject.Object, Peas.Activatable, plugin.Plugin):
settings = API.app.getDynamicApiManager().getAPI('Settings')
time.sleep(3)
while self.isActive():
if "Caps_Lock" in settings.orcaModifierKeys \
or "Shift_Lock" in settings.orcaModifierKeys:
self.setCapsLockAsOrcaModifier(True)
if "Caps_Lock" in settings.cthulhuModifierKeys \
or "Shift_Lock" in settings.cthulhuModifierKeys:
self.setCapsLockAsCthulhuModifier(True)
capsLockCleared = True
elif capsLockCleared:
self.setCapsLockAsOrcaModifier(False)
self.setCapsLockAsCthulhuModifier(False)
capsLockCleared = False
time.sleep(1)
def setCapsLockAsOrcaModifier(self, enable):
def setCapsLockAsCthulhuModifier(self, enable):
originalXmodmap = None
lines = None
try:
+2 -2
View File
@@ -1,7 +1,7 @@
orca_python_PYTHON = \
cthulhu_python_PYTHON = \
__init__.py \
CapsLockHack.plugin \
CapsLockHack.py
orca_pythondir=$(pkgpythondir)/plugins/CapsLockHack
cthulhu_pythondir=$(pkgpythondir)/plugins/CapsLockHack
@@ -0,0 +1,25 @@
#!/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
@@ -1,3 +1,28 @@
#!/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
from cthulhu import plugin
import gi, os
+2 -2
View File
@@ -1,7 +1,7 @@
orca_python_PYTHON = \
cthulhu_python_PYTHON = \
__init__.py \
Clipboard.plugin \
Clipboard.py
orca_pythondir=$(pkgpythondir)/plugins/Clipboard
cthulhu_pythondir=$(pkgpythondir)/plugins/Clipboard
+25
View File
@@ -0,0 +1,25 @@
#!/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

Some files were not shown because too many files have changed in this diff Show More