Compare commits
77 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d36b664319 | ||
|
02be96aa69 | ||
|
48575ab6cd | ||
|
2c28021ed4 | ||
|
8a79725df8 | ||
|
1b4c4916e3 | ||
|
35a83327ac | ||
|
c712bea421 | ||
|
815d39fc3f | ||
|
231d74efa0 | ||
|
7876a18c12 | ||
|
0b7cf681c3 | ||
|
4b8ebcb599 | ||
|
d6a373c726 | ||
|
dfe20fca30 | ||
|
3f7d60763d | ||
|
084d4fe85f | ||
|
6bbe6e47fc | ||
|
312476bbed | ||
|
0005d5ec71 | ||
|
88ad9833d2 | ||
|
654f1acc21 | ||
|
dfb53fff89 | ||
|
9cdb9f74e5 | ||
|
41dae26d90 | ||
|
edc1cbf7af | ||
|
d3d268004b | ||
|
a8e16fcf01 | ||
|
6bbf3d0e67 | ||
|
cbe3424e29 | ||
|
1cf566c37c | ||
|
936153f307 | ||
|
29f8697a9f | ||
|
ba735c554b | ||
|
1c9ca14272 | ||
|
d6af91bf42 | ||
|
5dd872535d | ||
|
8e9ea3af5a | ||
|
a40087cd20 | ||
|
35acddeb8f | ||
|
327ad99e49 | ||
|
c46cf1c939 | ||
|
80033b3f37 | ||
|
53e6e095b3 | ||
|
d863cf0353 | ||
|
a97bb30ed3 | ||
|
e9916bbcc4 | ||
|
6e480db630 | ||
|
384479a0a5 | ||
|
deccf846d8 | ||
|
92a909edb8 | ||
|
55c7de8c65 | ||
|
5a744a6809 | ||
|
63539e8122 | ||
|
5178a66a6f | ||
|
89891f18af | ||
|
71add76898 | ||
|
1a9eb35418 | ||
|
ba6382c3cd | ||
|
17febf488c | ||
|
09718e5901 | ||
|
03bed6c5d4 | ||
|
d28e0086d9 | ||
|
515827e830 | ||
|
4f6260eb6f | ||
|
b6a44df82a | ||
|
0cadb12c00 | ||
|
2f6fde6896 | ||
|
89467b6988 | ||
|
17d2773344 | ||
|
0abe30791d | ||
|
087dcc3ab2 | ||
|
4eaa4fae86 | ||
|
ba0169b016 | ||
|
7605e7d60f | ||
|
9562c08130 | ||
|
8a9bbefeac |
@ -29,6 +29,8 @@ Cthulhu has the following dependencies:
|
|||||||
* liblouis - Liblouis (<http://liblouis.org/>) support for contracted braille (optional)
|
* liblouis - Liblouis (<http://liblouis.org/>) support for contracted braille (optional)
|
||||||
* py-setproctitle - Python library to set the process title (optional)
|
* py-setproctitle - Python library to set the process title (optional)
|
||||||
* gstreamer-1.0 - GStreamer - Streaming media framework (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
|
You are strongly encouraged to also have the latest stable versions
|
||||||
of AT-SPI2 and ATK.
|
of AT-SPI2 and ATK.
|
||||||
|
1
TODO
1
TODO
@ -1,4 +1,3 @@
|
|||||||
- Add Simple Cthulhu Plugin System as native code for Cthulhu
|
|
||||||
- Merge in sleep mode.
|
- Merge in sleep mode.
|
||||||
- Add in ocrdesktop code so that Cthulhu has native ocr support.
|
- 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.
|
- Get rid of build systems. My hope is git clone and run so long as requirements are satisfied.
|
||||||
|
25
configure.ac
25
configure.ac
@ -1,4 +1,7 @@
|
|||||||
m4_define([cthulhu_version], [0.3])
|
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(pygobject_required_version, 3.18)
|
||||||
m4_define(atspi_required_version, 2.48)
|
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([ATSPI2], [atspi-2 >= atspi_required_version])
|
||||||
PKG_CHECK_MODULES([ATKBRIDGE], [atk-bridge-2.0 >= atkbridge_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([GSTREAMER], [gstreamer-1.0], [gstreamer="yes"], [gstreamer="no"])
|
||||||
|
PKG_CHECK_MODULES([LIBPEAS], [libpeas-1.0])
|
||||||
|
|
||||||
dnl Needed programs
|
dnl Needed programs
|
||||||
AC_PROG_INSTALL
|
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(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(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(brlapi,,[brlapi_available="yes"],[brlapi_available="no"])
|
||||||
AM_CHECK_PYMOD(speechd,,[speechd_available="yes"],[speechd_available="no"])
|
AM_CHECK_PYMOD(speechd,,[speechd_available="yes"],[speechd_available="no"])
|
||||||
AC_ARG_WITH([liblouis],
|
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/smuxi-frontend-gnome/Makefile
|
||||||
src/cthulhu/scripts/apps/Thunderbird/Makefile
|
src/cthulhu/scripts/apps/Thunderbird/Makefile
|
||||||
src/cthulhu/scripts/apps/xfwm4/Makefile
|
src/cthulhu/scripts/apps/xfwm4/Makefile
|
||||||
|
src/cthulhu/scripts/sleepmode/Makefile
|
||||||
src/cthulhu/scripts/switcher/Makefile
|
src/cthulhu/scripts/switcher/Makefile
|
||||||
src/cthulhu/scripts/terminal/Makefile
|
src/cthulhu/scripts/terminal/Makefile
|
||||||
src/cthulhu/scripts/web/Makefile
|
src/cthulhu/scripts/web/Makefile
|
||||||
@ -121,15 +127,11 @@ src/cthulhu/scripts/toolkits/gtk/Makefile
|
|||||||
src/cthulhu/plugins/Makefile
|
src/cthulhu/plugins/Makefile
|
||||||
src/cthulhu/plugins/ByeCthulhu/Makefile
|
src/cthulhu/plugins/ByeCthulhu/Makefile
|
||||||
src/cthulhu/plugins/HelloCthulhu/Makefile
|
src/cthulhu/plugins/HelloCthulhu/Makefile
|
||||||
src/cthulhu/plugins/PluginManager/Makefile
|
|
||||||
src/cthulhu/plugins/Clipboard/Makefile
|
src/cthulhu/plugins/Clipboard/Makefile
|
||||||
src/cthulhu/plugins/HelloWorld/Makefile
|
src/cthulhu/plugins/DisplayVersion/Makefile
|
||||||
src/cthulhu/plugins/CapsLockHack/Makefile
|
src/cthulhu/plugins/hello_world/Makefile
|
||||||
src/cthulhu/plugins/SelfVoice/Makefile
|
src/cthulhu/plugins/self_voice/Makefile
|
||||||
src/cthulhu/plugins/Date/Makefile
|
src/cthulhu/plugins/SimplePluginSystem/Makefile
|
||||||
src/cthulhu/plugins/Time/Makefile
|
|
||||||
src/cthulhu/plugins/MouseReview/Makefile
|
|
||||||
src/cthulhu/plugins/ClassicPreferences/Makefile
|
|
||||||
src/cthulhu/backends/Makefile
|
src/cthulhu/backends/Makefile
|
||||||
src/cthulhu/cthulhu_bin.py
|
src/cthulhu/cthulhu_bin.py
|
||||||
src/cthulhu/cthulhu_i18n.py
|
src/cthulhu/cthulhu_i18n.py
|
||||||
@ -157,7 +159,12 @@ echo
|
|||||||
echo "NOTE: Sound support requires gstreamer-1.0."
|
echo "NOTE: Sound support requires gstreamer-1.0."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$have_libpeas" = "no"; then
|
||||||
|
AC_MSG_ERROR([libpeas-1.0 >= 1.20 is required])
|
||||||
|
fi
|
||||||
|
|
||||||
echo
|
echo
|
||||||
|
echo Use pluggy: $pluggy_available
|
||||||
echo Use speech-dispatcher: $speechd_available
|
echo Use speech-dispatcher: $speechd_available
|
||||||
echo Use brltty: $brlapi_available
|
echo Use brltty: $brlapi_available
|
||||||
echo Use liblouis: $louis_available
|
echo Use liblouis: $louis_available
|
||||||
|
20
contrib/toggle.screenreader.gschema.xml
Normal file
20
contrib/toggle.screenreader.gschema.xml
Normal 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>'<Shift><Alt>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>
|
@ -1,7 +1,7 @@
|
|||||||
# Maintainer: Storm Dragon <storm_dragon@stormux.org>
|
# Maintainer: Storm Dragon <storm_dragon@stormux.org>
|
||||||
|
|
||||||
pkgname=cthulhu
|
pkgname=cthulhu
|
||||||
pkgver=0.3
|
pkgver=0.4
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="Screen reader for individuals who are blind or visually impaired forked from Orca"
|
pkgdesc="Screen reader for individuals who are blind or visually impaired forked from Orca"
|
||||||
url="https://git.stormux.org/storm/cthulhu"
|
url="https://git.stormux.org/storm/cthulhu"
|
||||||
@ -44,6 +44,11 @@ prepare() {
|
|||||||
NOCONFIGURE=1 ./autogen.sh
|
NOCONFIGURE=1 ./autogen.sh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pkgver() {
|
||||||
|
cd cthulhu
|
||||||
|
grep "^version = " src/cthulhu/cthulhuVersion.py | sed 's/version = "\(.*\)"/\1/'
|
||||||
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
cd cthulhu
|
cd cthulhu
|
||||||
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var
|
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var
|
||||||
|
98
distro-packages/Slackware/cthulhu.SlackBuild
Executable file
98
distro-packages/Slackware/cthulhu.SlackBuild
Executable 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
distro-packages/Slint/README
Normal file
28
distro-packages/Slint/README
Normal 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
distro-packages/Slint/cthulhu-info
Normal file
10
distro-packages/Slint/cthulhu-info
Normal 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
distro-packages/Slint/cthulhu.SlackBuild
Executable file
98
distro-packages/Slint/cthulhu.SlackBuild
Executable 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
distro-packages/Slint/doinst.sh
Normal file
9
distro-packages/Slint/doinst.sh
Normal 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
distro-packages/Slint/slack-desc
Normal file
19
distro-packages/Slint/slack-desc
Normal 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,10 +1,27 @@
|
|||||||
# Ruff linter.
|
[build-system]
|
||||||
#
|
requires = ["hatchling"]
|
||||||
# Repository: https://github.com/astral-sh/ruff
|
build-backend = "hatchling.build"
|
||||||
#
|
|
||||||
# Documentation: https://beta.ruff.rs/docs/
|
[project]
|
||||||
[tool.ruff]
|
name = "cthulhu"
|
||||||
line-length = 100 # same as rustfmt
|
dynamic = ["version"]
|
||||||
ignore = [
|
description = "Fork of the Orca screen reader based on gnome-45"
|
||||||
"E402", # Module level import not at top of file
|
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
src/cthulhu.py
Normal file
294
src/cthulhu.py
Normal 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())
|
@ -29,6 +29,7 @@ cthulhu_python_PYTHON = \
|
|||||||
cmdnames.py \
|
cmdnames.py \
|
||||||
colornames.py \
|
colornames.py \
|
||||||
common_keyboardmap.py \
|
common_keyboardmap.py \
|
||||||
|
cthulhuVersion.py \
|
||||||
date_and_time_presenter.py \
|
date_and_time_presenter.py \
|
||||||
debug.py \
|
debug.py \
|
||||||
desktop_keyboardmap.py \
|
desktop_keyboardmap.py \
|
||||||
|
@ -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"""
|
"""Cthulhu Screen Reader"""
|
||||||
|
|
||||||
__copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
|
__copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2005-2008 Google Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Portions Copyright 2007-2008, Sun Microsystems, Inc.
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# modify it under the terms of the GNU Lesser General Public
|
||||||
@ -18,6 +20,9 @@
|
|||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# Boston MA 02110-1301 USA.
|
||||||
#
|
#
|
||||||
|
# Fork of Orca Screen Reader (GNOME)
|
||||||
|
# Original source: https://gitlab.gnome.org/GNOME/orca
|
||||||
|
|
||||||
"""ACSS --- Aural CSS.
|
"""ACSS --- Aural CSS.
|
||||||
|
|
||||||
Class ACSS defines a simple wrapper for holding ACSS voice
|
Class ACSS defines a simple wrapper for holding ACSS voice
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2023 Igalia, S.L.
|
# Copyright (c) 2024 Stormux
|
||||||
# Author: Joanmarie Diggs <jdiggs@igalia.com>
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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"""
|
"""Module for performing accessible actions via a menu"""
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Utilities for obtaining objects via the collection interface.
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2023 Igalia, S.L.
|
# Copyright (c) 2024 Stormux
|
||||||
# Author: Joanmarie Diggs <jdiggs@igalia.com>
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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.
|
Utilities for obtaining objects via the collection interface.
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2005-2008 Sun Microsystems Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2018-2023 Igalia, S.L.
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""Provides support for synthesizing accessible input events."""
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Utilities for obtaining information about accessible objects.
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2023 Igalia, S.L.
|
# Copyright (c) 2024 Stormux
|
||||||
# Author: Joanmarie Diggs <jdiggs@igalia.com>
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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.
|
Utilities for obtaining information about accessible objects.
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Utilities for obtaining information about containers supporting selection
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2023 Igalia, S.L.
|
# Copyright (c) 2024 Stormux
|
||||||
# Author: Joanmarie Diggs <jdiggs@igalia.com>
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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.
|
Utilities for obtaining information about containers supporting selection.
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Utilities for performing tasks related to accessibility inspection.
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2023 Igalia, S.L.
|
# Copyright (c) 2024 Stormux
|
||||||
# Author: Joanmarie Diggs <jdiggs@igalia.com>
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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.
|
Utilities for performing tasks related to accessibility inspection.
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Utilities for finding all objects that meet a certain criteria.
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2023 Igalia, S.L.
|
# Copyright (c) 2024 Stormux
|
||||||
# Author: Joanmarie Diggs <jdiggs@igalia.com>
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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.
|
Utilities for finding all objects that meet a certain criteria.
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Utilities for obtaining role-related information.
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2023 Igalia, S.L.
|
# Copyright (c) 2024 Stormux
|
||||||
# Author: Joanmarie Diggs <jdiggs@igalia.com>
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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.
|
Utilities for obtaining role-related information.
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Utilities for obtaining state-related information.
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2023 Igalia, S.L.
|
# Copyright (c) 2024 Stormux
|
||||||
# Author: Joanmarie Diggs <jdiggs@igalia.com>
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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.
|
Utilities for obtaining state-related information.
|
||||||
|
@ -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,8 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2010-2011 Consorcio Fernando de los Rios.
|
# Copyright (c) 2024 Stormux
|
||||||
# Author: Juanje Ojeda Croissier <jojeda@emergya.es>
|
# Copyright (c) 2010-2012 The Orca Team
|
||||||
# Author: Javier Hernandez Antunez <jhernandez@emergya.es>
|
# Copyright (c) 2012 Igalia, S.L.
|
||||||
|
# Copyright (c) 2005-2010 Sun Microsystems Inc.
|
||||||
#
|
#
|
||||||
# This library is free software; you can redistribute it and/or
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# Boston MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# Fork of Orca Screen Reader (GNOME)
|
||||||
|
# Original source: https://gitlab.gnome.org/GNOME/orca
|
||||||
|
|
||||||
"""JSON backend for Cthulhu settings"""
|
"""JSON backend for Cthulhu settings"""
|
||||||
|
|
||||||
|
@ -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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""Provides the default implementation for bookmarks in Cthulhu."""
|
||||||
|
|
||||||
|
@ -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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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
|
"""A very experimental approach to the refreshable Braille display. This
|
||||||
module treats each line of the display as a sequential set of regions, where
|
module treats each line of the display as a sequential set of regions, where
|
||||||
|
@ -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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""Utilities for obtaining braille presentations for objects."""
|
||||||
|
|
||||||
|
@ -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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""Dictionary of abbreviated rolenames for use with braille."""
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
# -*- coding: utf-8 -*-
|
#!/usr/bin/env python3
|
||||||
# Cthulhu
|
|
||||||
#
|
#
|
||||||
# Copyright 2006-2008 Sun Microsystems Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2011 The Cthulhu Team.
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""Provides a graphical braille display, mainly for development tasks."""
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2004-2009 Sun Microsystems Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2010-2013 The Cthulhu Team
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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
|
"""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
|
so that we can present them in the correct language when users change the
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2013-2015 Igalia, S.L.
|
# Copyright (c) 2024 Stormux
|
||||||
# Author: Joanmarie Diggs <jdiggs@igalia.com>
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""Provides an Cthulhu-controlled caret for text content."""
|
||||||
|
|
||||||
|
@ -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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# Boston MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# Fork of Orca Screen Reader (GNOME)
|
||||||
|
# Original source: https://gitlab.gnome.org/GNOME/orca
|
||||||
|
|
||||||
"""Implements generic chat support."""
|
"""Implements generic chat support."""
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# -*- coding: utf-8 -*-
|
#!/usr/bin/env python3
|
||||||
# Cthulhu
|
|
||||||
#
|
#
|
||||||
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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
|
"""Provides getCharacterName that maps punctuation marks and other
|
||||||
individual characters into localized words."""
|
individual characters into localized words."""
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2004-2009 Sun Microsystems Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2010-2013 The Cthulhu Team
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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
|
"""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
|
have been put in their own module so that we can present them in
|
||||||
@ -455,6 +460,9 @@ TOGGLE_SPEECH = _("Toggle the silencing of speech")
|
|||||||
# This string describes that command.
|
# This string describes that command.
|
||||||
TOGGLE_SPEECH_VERBOSITY = _("Toggle speech verbosity level")
|
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
|
# Translators: this string is associated with the keyboard shortcut to quit
|
||||||
# Cthulhu.
|
# Cthulhu.
|
||||||
QUIT_CTHULHU = _("Quit the screen reader")
|
QUIT_CTHULHU = _("Quit the screen reader")
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2014 Igalia, S.L.
|
# Copyright (c) 2024 Stormux
|
||||||
#
|
# Copyright (c) 2010-2012 The Orca Team
|
||||||
# Author: Joanmarie Diggs <jdiggs@igalia.com>
|
# Copyright (c) 2012 Igalia, S.L.
|
||||||
|
# Copyright (c) 2005-2010 Sun Microsystems Inc.
|
||||||
#
|
#
|
||||||
# This library is free software; you can redistribute it and/or
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# Boston MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# Fork of Orca Screen Reader (GNOME)
|
||||||
|
# Original source: https://gitlab.gnome.org/GNOME/orca
|
||||||
|
|
||||||
__id__ = "$Id$"
|
__id__ = "$Id$"
|
||||||
__version__ = "$Revision$"
|
__version__ = "$Revision$"
|
||||||
|
@ -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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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
|
""" A list of common keybindings and unbound keys
|
||||||
pulled out from default.py: getKeyBindings()
|
pulled out from default.py: getKeyBindings()
|
||||||
@ -51,6 +57,9 @@ keymap = (
|
|||||||
("BackSpace", defaultModifierMask, CTHULHU_MODIFIER_MASK,
|
("BackSpace", defaultModifierMask, CTHULHU_MODIFIER_MASK,
|
||||||
"bypassNextCommandHandler"),
|
"bypassNextCommandHandler"),
|
||||||
|
|
||||||
|
("q", defaultModifierMask, CTHULHU_CTRL_ALT_MODIFIER_MASK, CTHULHU_SHIFT_MODIFIER_MASK,
|
||||||
|
"toggleSleepModeHandler"),
|
||||||
|
|
||||||
("q", defaultModifierMask, CTHULHU_MODIFIER_MASK,
|
("q", defaultModifierMask, CTHULHU_MODIFIER_MASK,
|
||||||
"shutdownHandler"),
|
"shutdownHandler"),
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2004-2009 Sun Microsystems Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2010-2011 The Cthulhu Team
|
# Copyright (c) 2010-2012 The Orca Team
|
||||||
# Copyright 2012 Igalia, S.L.
|
# Copyright (c) 2012 Igalia, S.L.
|
||||||
|
# Copyright (c) 2005-2010 Sun Microsystems Inc.
|
||||||
#
|
#
|
||||||
# This library is free software; you can redistribute it and/or
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""The main module for the Cthulhu screen reader."""
|
||||||
|
|
||||||
@ -30,6 +34,108 @@ __copyright__ = "Copyright (c) 2004-2009 Sun Microsystems Inc." \
|
|||||||
__license__ = "LGPL"
|
__license__ = "LGPL"
|
||||||
|
|
||||||
import faulthandler
|
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_parts = key.lower().split("+")
|
||||||
|
|
||||||
|
# Determine appropriate modifier mask
|
||||||
|
modifiers = keybindings.CTHULHU_MODIFIER_MASK
|
||||||
|
|
||||||
|
# Extract the final key (without modifiers)
|
||||||
|
final_key = key_parts[-1]
|
||||||
|
|
||||||
|
# Check for additional modifiers
|
||||||
|
if "shift" in key_parts:
|
||||||
|
modifiers = keybindings.CTHULHU_SHIFT_MODIFIER_MASK
|
||||||
|
elif "ctrl" in key_parts or "control" in key_parts:
|
||||||
|
modifiers = keybindings.CTHULHU_CTRL_MODIFIER_MASK
|
||||||
|
elif "alt" in key_parts:
|
||||||
|
modifiers = keybindings.CTHULHU_ALT_MODIFIER_MASK
|
||||||
|
|
||||||
|
# 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(
|
||||||
|
final_key,
|
||||||
|
keybindings.defaultModifierMask,
|
||||||
|
modifiers,
|
||||||
|
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 gi
|
||||||
import importlib
|
import importlib
|
||||||
import os
|
import os
|
||||||
@ -70,7 +176,7 @@ from .ax_object import AXObject
|
|||||||
from .ax_utilities import AXUtilities
|
from .ax_utilities import AXUtilities
|
||||||
from .input_event import BrailleEvent
|
from .input_event import BrailleEvent
|
||||||
from . import cmdnames
|
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 guilabels
|
||||||
from . import acss
|
from . import acss
|
||||||
from . import text_attribute_names
|
from . import text_attribute_names
|
||||||
@ -530,6 +636,55 @@ def loadUserSettings(script=None, inputEvent=None, skipReloadMessage=False):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def _showPreferencesUI(script, prefs):
|
||||||
|
if cthulhu_state.cthulhuOS:
|
||||||
|
cthulhu_state.cthulhuOS.showGUI()
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
module = importlib.import_module('.cthulhu_gui_prefs', 'cthulhu')
|
||||||
|
except Exception:
|
||||||
|
debug.printException(debug.LEVEL_SEVERE)
|
||||||
|
return
|
||||||
|
|
||||||
|
uiFile = os.path.join(cthulhu_platform.datadir,
|
||||||
|
cthulhu_platform.package,
|
||||||
|
"ui",
|
||||||
|
"cthulhu-setup.ui")
|
||||||
|
|
||||||
|
cthulhu_state.cthulhuOS = module.CthulhuSetupGUI(uiFile, "cthulhuSetupWindow", prefs)
|
||||||
|
cthulhu_state.cthulhuOS.init(script)
|
||||||
|
cthulhu_state.cthulhuOS.showGUI()
|
||||||
|
|
||||||
|
def showAppPreferencesGUI(script=None, inputEvent=None):
|
||||||
|
"""Displays the user interface to configure the settings for a
|
||||||
|
specific applications within Cthulhu and set up those app-specific
|
||||||
|
user preferences using a GUI.
|
||||||
|
|
||||||
|
Returns True to indicate the input event has been consumed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
prefs = {}
|
||||||
|
for key in settings.userCustomizableSettings:
|
||||||
|
prefs[key] = _settingsManager.getSetting(key)
|
||||||
|
|
||||||
|
script = script or cthulhu_state.activeScript
|
||||||
|
_showPreferencesUI(script, prefs)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def showPreferencesGUI(script=None, inputEvent=None):
|
||||||
|
"""Displays the user interface to configure Cthulhu and set up
|
||||||
|
user preferences using a GUI.
|
||||||
|
|
||||||
|
Returns True to indicate the input event has been consumed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
prefs = _settingsManager.getGeneralSettings(_settingsManager.profile)
|
||||||
|
script = _scriptManager.getDefaultScript()
|
||||||
|
_showPreferencesUI(script, prefs)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def addKeyGrab(binding):
|
def addKeyGrab(binding):
|
||||||
""" Add a key grab for the given key binding."""
|
""" Add a key grab for the given key binding."""
|
||||||
@ -867,7 +1022,6 @@ class Cthulhu(GObject.Object):
|
|||||||
GObject.Object.__init__(self)
|
GObject.Object.__init__(self)
|
||||||
# add members
|
# add members
|
||||||
self.resourceManager = resource_manager.ResourceManager(self)
|
self.resourceManager = resource_manager.ResourceManager(self)
|
||||||
self.APIHelper = plugin_system_manager.APIHelper(self)
|
|
||||||
self.eventManager = _eventManager
|
self.eventManager = _eventManager
|
||||||
self.settingsManager = _settingsManager
|
self.settingsManager = _settingsManager
|
||||||
self.scriptManager = _scriptManager
|
self.scriptManager = _scriptManager
|
||||||
@ -875,8 +1029,11 @@ class Cthulhu(GObject.Object):
|
|||||||
self.dynamicApiManager = dynamic_api_manager.DynamicApiManager(self)
|
self.dynamicApiManager = dynamic_api_manager.DynamicApiManager(self)
|
||||||
self.translationManager = translation_manager.TranslationManager(self)
|
self.translationManager = translation_manager.TranslationManager(self)
|
||||||
self.debugManager = debug
|
self.debugManager = debug
|
||||||
|
self.APIHelper = APIHelper(self)
|
||||||
self.createCompatAPI()
|
self.createCompatAPI()
|
||||||
self.pluginSystemManager = plugin_system_manager.PluginSystemManager(self)
|
self.pluginSystemManager = plugin_system_manager.PluginSystemManager(self)
|
||||||
|
# Scan for available plugins at startup
|
||||||
|
self.pluginSystemManager.rescanPlugins()
|
||||||
def getAPIHelper(self):
|
def getAPIHelper(self):
|
||||||
return self.APIHelper
|
return self.APIHelper
|
||||||
def getPluginSystemManager(self):
|
def getPluginSystemManager(self):
|
||||||
@ -934,6 +1091,7 @@ class Cthulhu(GObject.Object):
|
|||||||
# cthulhu lets say, special compat handling....
|
# cthulhu lets say, special compat handling....
|
||||||
self.getDynamicApiManager().registerAPI('EmitRegionChanged', emitRegionChanged)
|
self.getDynamicApiManager().registerAPI('EmitRegionChanged', emitRegionChanged)
|
||||||
self.getDynamicApiManager().registerAPI('LoadUserSettings', loadUserSettings)
|
self.getDynamicApiManager().registerAPI('LoadUserSettings', loadUserSettings)
|
||||||
|
self.getDynamicApiManager().registerAPI('APIHelper', self.APIHelper)
|
||||||
|
|
||||||
cthulhuApp = Cthulhu()
|
cthulhuApp = Cthulhu()
|
||||||
|
|
||||||
|
27
src/cthulhu/cthulhuVersion.py
Normal file
27
src/cthulhu/cthulhuVersion.py
Normal 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.04"
|
||||||
|
codeName = "testing"
|
@ -1,9 +1,9 @@
|
|||||||
#!@PYTHON@
|
#!@PYTHON@
|
||||||
#
|
#
|
||||||
# Cthulhu
|
# Copyright (c) 2024 Stormux
|
||||||
#
|
# Copyright (c) 2010-2012 The Orca Team
|
||||||
# Copyright 2010-2012 The Cthulhu Team
|
# Copyright (c) 2012 Igalia, S.L.
|
||||||
# Copyright 2012 Igalia, S.L.
|
# Copyright (c) 2005-2010 Sun Microsystems Inc.
|
||||||
#
|
#
|
||||||
# This library is free software; you can redistribute it and/or
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# Boston MA 02110-1301 USA.
|
||||||
|
#
|
||||||
__id__ = "$Id$"
|
# Fork of Orca Screen Reader (GNOME)
|
||||||
__version__ = "$Revision$"
|
# Original source: https://gitlab.gnome.org/GNOME/orca
|
||||||
__date__ = "$Date$"
|
|
||||||
__copyright__ = "Copyright (c) 2010-2012 The Cthulhu Team" \
|
|
||||||
"Copyright (c) 2012 Igalia, S.L."
|
|
||||||
__license__ = "LGPL"
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import gi
|
import gi
|
||||||
|
@ -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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""Displays a GUI for the user to quit Cthulhu."""
|
||||||
|
|
||||||
|
@ -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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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"""
|
"""Displays a GUI for the Cthulhu Find window"""
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2012 Igalia, S.L.
|
# Copyright (c) 2024 Stormux
|
||||||
#
|
# Copyright (c) 2010-2012 The Orca Team
|
||||||
# Author: Joanmarie Diggs <jdiggs@igalia.com>
|
# Copyright (c) 2012 Igalia, S.L.
|
||||||
|
# Copyright (c) 2005-2010 Sun Microsystems Inc.
|
||||||
#
|
#
|
||||||
# This library is free software; you can redistribute it and/or
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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"""
|
"""Displays a GUI for Cthulhu navigation list dialogs"""
|
||||||
|
|
||||||
|
@ -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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""Displays a GUI for the user to set Cthulhu preferences."""
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2010 Consorcio Fernando de los Rios.
|
# Copyright (c) 2024 Stormux
|
||||||
# Author: Javier Hernandez Antunez <jhernandez@emergya.es>
|
# Copyright (c) 2010-2012 The Orca Team
|
||||||
# Author: Alejandro Leiva <aleiva@emergya.es>
|
# Copyright (c) 2012 Igalia, S.L.
|
||||||
|
# Copyright (c) 2005-2010 Sun Microsystems Inc.
|
||||||
#
|
#
|
||||||
# This library is free software; you can redistribute it and/or
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""Displays the Save Profile As dialog."""
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# Boston MA 02110-1301 USA.
|
||||||
|
|
||||||
|
from cthulhu import cthulhuVersion
|
||||||
|
|
||||||
"""Holds platform-specific settings.
|
"""Holds platform-specific settings.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -28,7 +30,7 @@ __license__ = "LGPL"
|
|||||||
|
|
||||||
# $CTHULHU_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
|
# The revision if built from git; otherwise an empty string
|
||||||
#
|
#
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2005-2009 Sun Microsystems Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2010 Joanmarie Diggs, Mesar Hameed
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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.
|
"""Holds state that is shared among many modules.
|
||||||
"""
|
"""
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2005-2008 Sun Microsystems Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2016-2023 Igalia, S.L.
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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"""
|
"""Module for date and time presentation"""
|
||||||
|
|
||||||
|
@ -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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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
|
"""Provides debug utilities for Cthulhu. Debugging is managed by a debug
|
||||||
level, which is held in the debugLevel field. All other methods take
|
level, which is held in the debugLevel field. All other methods take
|
||||||
|
@ -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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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
|
""" A list of common keybindings and unbound keys
|
||||||
pulled out from default.py: __getDesktopBindings()
|
pulled out from default.py: __getDesktopBindings()
|
||||||
|
@ -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
|
import gi
|
||||||
from gi.repository import GObject
|
from gi.repository import GObject
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2011. Cthulhu Team.
|
# Copyright (c) 2024 Stormux
|
||||||
# Author: Joanmarie Diggs <joanmarie.diggs@gmail.com>
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# Boston MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# Fork of Orca Screen Reader (GNOME)
|
||||||
|
# Original source: https://gitlab.gnome.org/GNOME/orca
|
||||||
|
|
||||||
__id__ = "$Id$"
|
__id__ = "$Id$"
|
||||||
__version__ = "$Revision$"
|
__version__ = "$Revision$"
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2006-2008 Sun Microsystems Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2022 Igalia, S.L.
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""Provides support for a flat review find."""
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2005-2008 Sun Microsystems Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2016 Igalia, S.L.
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""Provides the default implementation for flat review for Cthulhu."""
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2005-2008 Sun Microsystems Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2016-2023 Igalia, S.L.
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# Boston MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# Fork of Orca Screen Reader (GNOME)
|
||||||
|
# Original source: https://gitlab.gnome.org/GNOME/orca
|
||||||
|
|
||||||
"""Module for flat-review commands"""
|
"""Module for flat-review commands"""
|
||||||
|
|
||||||
|
@ -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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""Manages the formatting settings for Cthulhu."""
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2009 Sun Microsystems Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2015-2016 Igalia, S.L.
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""Superclass of classes used to generate presentations for objects."""
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2004-2009 Sun Microsystems Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2010-2013 The Cthulhu Team
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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
|
"""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
|
can present them in the correct language when users change the language on the
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2023 Igalia, S.L.
|
# Copyright (c) 2024 Stormux
|
||||||
# Author: Joanmarie Diggs <jdiggs@igalia.com>
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""Module for drawing highlights over an area of interest."""
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2005-2008 Sun Microsystems Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2011-2016 Igalia, S.L.
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""Provides support for handling input events."""
|
||||||
|
|
||||||
|
@ -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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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
|
"""Provides support for defining keybindings and matching them to input
|
||||||
events."""
|
events."""
|
||||||
|
@ -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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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
|
"""Exposes a dictionary, keynames, that maps key events
|
||||||
into localized words."""
|
into localized words."""
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright (C) 2011-2013 Igalia, S.L.
|
# Copyright (c) 2024 Stormux
|
||||||
#
|
# Copyright (c) 2010-2012 The Orca Team
|
||||||
# Author: Joanmarie Diggs <jdiggs@igalia.com>
|
# Copyright (c) 2012 Igalia, S.L.
|
||||||
|
# Copyright (c) 2005-2010 Sun Microsystems Inc.
|
||||||
#
|
#
|
||||||
# This library is free software; you can redistribute it and/or
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""Heuristic means to infer the functional/displayed label of a widget."""
|
||||||
|
|
||||||
|
@ -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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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
|
""" A list of common keybindings and unbound keys
|
||||||
pulled out from default.py: __getLaptopBindings()
|
pulled out from default.py: __getLaptopBindings()
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2005-2008 Sun Microsystems Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2016-2023 Igalia, S.L.
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# Boston MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# Fork of Orca Screen Reader (GNOME)
|
||||||
|
# Original source: https://gitlab.gnome.org/GNOME/orca
|
||||||
|
|
||||||
"""Module for learn mode"""
|
"""Module for learn mode"""
|
||||||
|
|
||||||
|
@ -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
|
import gi
|
||||||
gi.require_version("Atspi", "2.0")
|
gi.require_version("Atspi", "2.0")
|
||||||
from gi.repository import Atspi
|
from gi.repository import Atspi
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2008 Sun Microsystems Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2012 Igalia, S.L.
|
# Copyright (c) 2010-2012 The Orca Team
|
||||||
#
|
# Copyright (c) 2012 Igalia, S.L.
|
||||||
# Author: Joanmarie Diggs <jdiggs@igalia.com>
|
# Copyright (c) 2005-2010 Sun Microsystems Inc.
|
||||||
#
|
#
|
||||||
# This library is free software; you can redistribute it and/or
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# Boston MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# Fork of Orca Screen Reader (GNOME)
|
||||||
|
# Original source: https://gitlab.gnome.org/GNOME/orca
|
||||||
|
|
||||||
"""Output logger for regression testing."""
|
"""Output logger for regression testing."""
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2014 Igalia, S.L.
|
# Copyright (c) 2024 Stormux
|
||||||
#
|
# Copyright (c) 2010-2012 The Orca Team
|
||||||
# Author: Joanmarie Diggs <jdiggs@igalia.com>
|
# Copyright (c) 2012 Igalia, S.L.
|
||||||
|
# Copyright (c) 2005-2010 Sun Microsystems Inc.
|
||||||
#
|
#
|
||||||
# This library is free software; you can redistribute it and/or
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# Boston MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# Fork of Orca Screen Reader (GNOME)
|
||||||
|
# Original source: https://gitlab.gnome.org/GNOME/orca
|
||||||
|
|
||||||
__id__ = "$Id$"
|
__id__ = "$Id$"
|
||||||
__version__ = "$Revision$"
|
__version__ = "$Revision$"
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2004-2009 Sun Microsystems Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2010-2013 The Cthulhu Team
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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
|
"""Messages which Cthulhu presents in speech and/or braille. These
|
||||||
have been put in their own module so that we can present them in
|
have been put in their own module so that we can present them in
|
||||||
@ -2294,7 +2299,12 @@ SPOKEN_ELLIPSIS = _(" dot dot dot")
|
|||||||
START_CTHULHU = _("Cthulhu welcomes you.")
|
START_CTHULHU = _("Cthulhu welcomes you.")
|
||||||
|
|
||||||
# Translators: This message is presented to the user when Cthulhu is quit.
|
# Translators: This message is presented to the user when Cthulhu is quit.
|
||||||
STOP_CTHULHU = _("Cthulhu lerks beneath the waves.")
|
STOP_CTHULHU = _("Cthulhu lurks beneath the waves.")
|
||||||
|
|
||||||
|
# Sleep Mode
|
||||||
|
# Translators: This message is presented to the user when Cthulhu enters or leaves sleep mode.
|
||||||
|
SLEEP_MODE_ENABLED_FOR = _("Sleep mode enabled for %s")
|
||||||
|
SLEEP_MODE_DISABLED_FOR = _("Sleep mode disabled for %s")
|
||||||
|
|
||||||
# Translators: This message means speech synthesis is not installed or working.
|
# Translators: This message means speech synthesis is not installed or working.
|
||||||
SPEECH_UNAVAILABLE = _("Speech is unavailable.")
|
SPEECH_UNAVAILABLE = _("Speech is unavailable.")
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Mouse reviewer for Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2008 Eitan Isaacson
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2016 Igalia, S.L.
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# Boston MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# Fork of Orca Screen Reader (GNOME)
|
||||||
|
# Original source: https://gitlab.gnome.org/GNOME/orca
|
||||||
|
|
||||||
"""Mouse review mode."""
|
"""Mouse review mode."""
|
||||||
|
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2023 Igalia, S.L.
|
# Copyright (c) 2024 Stormux
|
||||||
# Author: Joanmarie Diggs <jdiggs@igalia.com>
|
# Copyright (c) 2010-2012 The Orca Team
|
||||||
# Based on the feature created by:
|
# Copyright (c) 2012 Igalia, S.L.
|
||||||
# Author: Jose Vilmar <vilmar@informal.com.br>
|
# Copyright (c) 2005-2010 Sun Microsystems Inc.
|
||||||
# Copyright 2010 Informal Informatica LTDA.
|
|
||||||
#
|
#
|
||||||
# This library is free software; you can redistribute it and/or
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# Boston MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# Fork of Orca Screen Reader (GNOME)
|
||||||
|
# Original source: https://gitlab.gnome.org/GNOME/orca
|
||||||
|
|
||||||
"""Module for notification messages"""
|
"""Module for notification messages"""
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2023 The Cthulhu Team
|
# Copyright (c) 2024 Stormux
|
||||||
# Author: Rynhardt Kruger <rynkruger@gmail.com>
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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."""
|
"""Provides ability to navigate objects hierarchically."""
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Cthulhu
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# Copyright 2004-2009 Sun Microsystems Inc.
|
# Copyright (c) 2024 Stormux
|
||||||
# Copyright 2010-2013 The Cthulhu Team
|
# 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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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
|
"""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
|
so that we can present them in the correct language when users change the
|
||||||
|
@ -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
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# 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
|
# License along with this library; if not, write to the
|
||||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||||
# Boston MA 02110-1301 USA.
|
# 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
|
"""Provides getPhoneticName method that maps each letter of the
|
||||||
alphabet into its localized phonetic equivalent."""
|
alphabet into its localized phonetic equivalent."""
|
||||||
|
@ -1,160 +1,92 @@
|
|||||||
import os, inspect
|
#!/usr/bin/env python3
|
||||||
import gi
|
# Copyright (c) 2024 Stormux
|
||||||
from gi.repository import GObject
|
#
|
||||||
|
# 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():
|
"""Base class for Cthulhu plugins using pluggy."""
|
||||||
#__gtype_name__ = 'BasePlugin'
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
import os
|
||||||
self.API = None
|
import logging
|
||||||
self.pluginInfo = None
|
|
||||||
self.moduleDir = ''
|
# Import pluggy for hook specifications
|
||||||
self.hidden = False
|
try:
|
||||||
self.moduleName = ''
|
import pluggy
|
||||||
|
cthulhu_hookimpl = pluggy.HookimplMarker("cthulhu")
|
||||||
|
PLUGGY_AVAILABLE = True
|
||||||
|
logging.getLogger(__name__).info("Successfully imported pluggy")
|
||||||
|
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__).warning("Pluggy not available, plugins will be disabled")
|
||||||
|
import traceback
|
||||||
|
logging.getLogger(__name__).debug(traceback.format_exc())
|
||||||
|
|
||||||
|
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.name = ''
|
||||||
self.version = ''
|
self.version = ''
|
||||||
self.website = ''
|
|
||||||
self.authors = []
|
|
||||||
self.buildIn = False
|
|
||||||
self.description = ''
|
self.description = ''
|
||||||
self.iconName = ''
|
|
||||||
self.copyright = ''
|
def set_app(self, app):
|
||||||
self.dependencies = False
|
"""Set the application reference."""
|
||||||
self.helpUri = ''
|
|
||||||
self.dataDir = ''
|
|
||||||
self.translationContext = None
|
|
||||||
def setApp(self, app):
|
|
||||||
self.app = app
|
self.app = app
|
||||||
self.dynamicApiManager = app.getDynamicApiManager()
|
|
||||||
self.signalManager = app.getSignalManager()
|
|
||||||
|
|
||||||
def getApp(self):
|
def set_plugin_info(self, plugin_info):
|
||||||
return self.app
|
"""Set plugin information and extract relevant attributes."""
|
||||||
def setPluginInfo(self, pluginInfo):
|
self.plugin_info = plugin_info
|
||||||
self.pluginInfo = pluginInfo
|
if plugin_info:
|
||||||
self.updatePluginInfoAttributes()
|
self.module_name = getattr(plugin_info, 'module_name', '')
|
||||||
def getPluginInfo(self):
|
self.name = getattr(plugin_info, 'name', '')
|
||||||
return self.pluginInfo
|
self.version = getattr(plugin_info, 'version', '')
|
||||||
def updatePluginInfoAttributes(self):
|
self.description = getattr(plugin_info, 'description', '')
|
||||||
self.moduleDir = ''
|
|
||||||
self.hidden = False
|
@cthulhu_hookimpl
|
||||||
self.moduleName = ''
|
def activate(self, plugin=None):
|
||||||
self.name = ''
|
"""Activate the plugin. Override this in subclasses."""
|
||||||
self.version = ''
|
if plugin is not None and plugin is not self:
|
||||||
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:
|
|
||||||
return
|
return
|
||||||
self.moduleName = self.getApp().getPluginSystemManager().getPluginModuleName(pluginInfo)
|
logger.info(f"Activating plugin: {self.name}")
|
||||||
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)
|
|
||||||
|
|
||||||
#settings = self.getApp().getPluginSystemManager().getPluginSettings(pluginInfo)
|
@cthulhu_hookimpl
|
||||||
#hasDependencies = self.getApp().getPluginSystemManager().hasPluginDependency(pluginInfo)
|
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)
|
def registerGestureByString(self, function, name, gestureString, learnModeEnabled=True):
|
||||||
self.helpUri = self.getApp().getPluginSystemManager().getPlugingetHelpUri(pluginInfo)
|
"""Register a gesture by string."""
|
||||||
self.dataDir = self.getApp().getPluginSystemManager().getPluginDataDir(pluginInfo)
|
if self.app:
|
||||||
self.updateTranslationContext()
|
api_helper = self.app.getAPIHelper()
|
||||||
|
if api_helper:
|
||||||
def updateTranslationContext(self, domain = None, localeDir = None, language = None, fallbackToCthulhuTranslation = True):
|
return api_helper.registerGestureByString(
|
||||||
self.translationContext = None
|
function,
|
||||||
useLocaleDir = '{}/locale/'.format(self.getModuleDir())
|
name,
|
||||||
if localeDir:
|
gestureString,
|
||||||
if os.path.isdir(localeDir):
|
'default',
|
||||||
useLocaleDir = localeDir
|
'cthulhu',
|
||||||
useName = self.getModuleName()
|
learnModeEnabled,
|
||||||
useDomain = useName
|
contextName=self.module_name
|
||||||
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())
|
|
||||||
return None
|
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())
|
|
||||||
|
@ -1,520 +1,469 @@
|
|||||||
#!/bin/python
|
#!/usr/bin/env python3
|
||||||
"""PluginManager for loading cthulhu plugins."""
|
# Copyright (c) 2024 Stormux
|
||||||
import os, inspect, sys, tarfile, shutil
|
#
|
||||||
|
# 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
|
from enum import IntEnum
|
||||||
|
|
||||||
version = sys.version[:3] # we only need major.minor version.
|
# Import pluggy if available
|
||||||
if version in ["3.3","3.4"]:
|
try:
|
||||||
from importlib.machinery import SourceFileLoader
|
import pluggy
|
||||||
else: # Python 3.5+, no support for python < 3.3.
|
PLUGGY_AVAILABLE = True
|
||||||
import importlib.util
|
except ImportError:
|
||||||
|
PLUGGY_AVAILABLE = False
|
||||||
|
logging.getLogger(__name__).info("Pluggy not available, plugins will be disabled")
|
||||||
|
|
||||||
import gi
|
# Set to True for more detailed plugin loading debug info
|
||||||
gi.require_version('Peas', '1.0')
|
PLUGIN_DEBUG = True
|
||||||
from gi.repository import GObject
|
|
||||||
from gi.repository import Peas
|
|
||||||
|
|
||||||
gi.require_version('Atspi', '2.0')
|
logger = logging.getLogger(__name__)
|
||||||
from gi.repository import Atspi
|
if PLUGIN_DEBUG:
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
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
|
|
||||||
|
|
||||||
class PluginType(IntEnum):
|
class PluginType(IntEnum):
|
||||||
"""Types of plugins we support, depending on their directory location."""
|
"""Types of plugins we support."""
|
||||||
# pylint: disable=comparison-with-callable,inconsistent-return-statements,no-else-return
|
|
||||||
# SYSTEM: provides system wide plugins
|
|
||||||
SYSTEM = 1
|
SYSTEM = 1
|
||||||
# USER: provides per user plugin
|
|
||||||
USER = 2
|
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):
|
def get_root_dir(self):
|
||||||
"""Returns the directory where this type of plugins can be found."""
|
"""Returns the directory where this type of plugins can be found."""
|
||||||
if self.value == PluginType.SYSTEM:
|
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:
|
elif self.value == PluginType.USER:
|
||||||
return os.path.expanduser('~') + '/.local/share/cthulhu/plugins'
|
return os.path.expanduser('~/.local/share/cthulhu/plugins')
|
||||||
|
|
||||||
|
|
||||||
class PluginSystemManager():
|
class PluginInfo:
|
||||||
"""Cthulhu Plugin Manager to handle a set of plugins.
|
"""Information about a plugin."""
|
||||||
Attributes:
|
|
||||||
DEFAULT_LOADERS (tuple): Default loaders used by the plugin manager. For
|
def __init__(self, name, module_name, module_dir, metadata=None):
|
||||||
possible values see
|
self.name = name
|
||||||
https://developer.gnome.org/libpeas/stable/PeasEngine.html#peas-engine-enable-loader
|
self.module_name = module_name
|
||||||
"""
|
self.module_dir = module_dir
|
||||||
DEFAULT_LOADERS = ("python3", )
|
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):
|
def __init__(self, app):
|
||||||
self.app = app
|
self.app = app
|
||||||
self.engine = Peas.Engine.get_default()
|
logger.info("Initializing PluginSystemManager")
|
||||||
|
|
||||||
for loader in self.DEFAULT_LOADERS:
|
# Initialize plugin manager
|
||||||
self.engine.enable_loader(loader)
|
if PLUGGY_AVAILABLE:
|
||||||
|
logger.info("Pluggy is available, setting up plugin manager")
|
||||||
|
self.plugin_manager = pluggy.PluginManager("cthulhu")
|
||||||
|
|
||||||
self._setupPluginsDir()
|
# Define hook specifications
|
||||||
self._setupExtensionSet()
|
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
|
||||||
|
|
||||||
|
logger.info("Adding hook specifications to plugin manager")
|
||||||
|
self.plugin_manager.add_hookspecs(CthulhuHookSpecs)
|
||||||
|
else:
|
||||||
|
logger.warning("Pluggy is not available, plugins will be disabled")
|
||||||
|
self.plugin_manager = None
|
||||||
|
|
||||||
|
# Plugin storage
|
||||||
|
self._plugins = {} # module_name -> PluginInfo
|
||||||
|
self._active_plugins = []
|
||||||
|
|
||||||
|
# Create plugin directories
|
||||||
|
self._setup_plugin_dirs()
|
||||||
|
|
||||||
|
# Log available plugins directory paths
|
||||||
|
logger.info(f"System plugins directory: {PluginType.SYSTEM.get_root_dir()}")
|
||||||
|
logger.info(f"User plugins directory: {PluginType.USER.get_root_dir()}")
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
if self.app:
|
|
||||||
self.gsettingsManager = self.app.getSettingsManager()
|
|
||||||
# settings else:
|
|
||||||
# settings self.gsettingsManager = gsettings_manager.getSettingsManager(self.app)
|
|
||||||
self._activePlugins = []
|
|
||||||
self._ignorePluginModulePath = []
|
|
||||||
@property
|
@property
|
||||||
def plugins(self):
|
def plugins(self):
|
||||||
"""Gets the engine's plugin list."""
|
"""Get all available plugins."""
|
||||||
return self.engine.get_plugin_list()
|
return list(self._plugins.values())
|
||||||
@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
|
|
||||||
|
|
||||||
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):
|
def getApp(self):
|
||||||
return self.app
|
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 getActivePlugins(self):
|
|
||||||
return self._activePlugins
|
|
||||||
def setActivePlugins(self, activePlugins):
|
|
||||||
self._activePlugins = 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):
|
def rescanPlugins(self):
|
||||||
return self._ignorePluginModulePath
|
"""Scan for plugins in the plugin directories."""
|
||||||
def setIgnoredPlugins(self, pluginModulePath, ignored):
|
old_plugins = self._plugins.copy()
|
||||||
if pluginModulePath.endswith('/'):
|
self._plugins = {}
|
||||||
pluginModulePath = pluginModulePath[:-1]
|
|
||||||
if ignored:
|
# Scan system and user plugins
|
||||||
if not pluginModulePath in self.getIgnoredPlugins():
|
self._scan_plugins_in_directory(PluginType.SYSTEM.get_root_dir())
|
||||||
self._ignorePluginModulePath.append(pluginModulePath)
|
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):
|
||||||
|
logger.warning(f"Plugin directory not found or not a directory: {directory}")
|
||||||
|
return
|
||||||
|
|
||||||
|
logger.info(f"Scanning for plugins in directory: {directory}")
|
||||||
|
for item in os.listdir(directory):
|
||||||
|
plugin_dir = os.path.join(directory, item)
|
||||||
|
if not os.path.isdir(plugin_dir):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Check for the traditional structure first (plugin.py & plugin.info)
|
||||||
|
plugin_file = os.path.join(plugin_dir, "plugin.py")
|
||||||
|
metadata_file = os.path.join(plugin_dir, "plugin.info")
|
||||||
|
|
||||||
|
# Fall back to [PluginName].py if plugin.py doesn't exist
|
||||||
|
if not os.path.isfile(plugin_file):
|
||||||
|
alternative_plugin_file = os.path.join(plugin_dir, f"{item}.py")
|
||||||
|
if os.path.isfile(alternative_plugin_file):
|
||||||
|
plugin_file = alternative_plugin_file
|
||||||
|
logger.info(f"Using alternative plugin file: {alternative_plugin_file}")
|
||||||
|
|
||||||
|
# Check if we have any valid plugin file
|
||||||
|
if os.path.isfile(plugin_file):
|
||||||
|
# Extract plugin info
|
||||||
|
module_name = os.path.basename(plugin_dir)
|
||||||
|
logger.info(f"Found plugin: {module_name} in {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'
|
||||||
|
|
||||||
|
logger.info(f"Adding plugin to registry: {module_name}")
|
||||||
|
self._plugins[module_name] = plugin_info
|
||||||
else:
|
else:
|
||||||
if pluginModulePath in self.getIgnoredPlugins():
|
logger.warning(f"No plugin file found in directory: {plugin_dir}")
|
||||||
self._ignorePluginModulePath.remove(pluginModulePath)
|
|
||||||
|
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):
|
||||||
|
"""Get the list of active plugin names."""
|
||||||
|
return self._active_plugins
|
||||||
|
|
||||||
|
def setActivePlugins(self, activePlugins):
|
||||||
|
"""Set active plugins and sync their state."""
|
||||||
|
logger.info(f"Setting active plugins: {activePlugins}")
|
||||||
|
|
||||||
|
# Make sure we have scanned for plugins first
|
||||||
|
if not self._plugins:
|
||||||
|
logger.info("No plugins found, rescanning...")
|
||||||
|
self.rescanPlugins()
|
||||||
|
|
||||||
|
self._active_plugins = activePlugins
|
||||||
|
|
||||||
|
# Log active vs available plugins
|
||||||
|
available_plugins = [p.get_module_name() for p in self.plugins]
|
||||||
|
logger.info(f"Available plugins: {available_plugins}")
|
||||||
|
logger.info(f"Active plugins: {self._active_plugins}")
|
||||||
|
|
||||||
|
# Find missing plugins
|
||||||
|
missing_plugins = [p for p in self._active_plugins if p not in available_plugins]
|
||||||
|
if missing_plugins:
|
||||||
|
logger.warning(f"Active plugins not found: {missing_plugins}")
|
||||||
|
|
||||||
|
self.syncAllPluginsActive()
|
||||||
|
|
||||||
def setPluginActive(self, pluginInfo, active):
|
def setPluginActive(self, pluginInfo, active):
|
||||||
if self.isPluginBuildIn(pluginInfo):
|
"""Set the active state of a plugin."""
|
||||||
|
if pluginInfo.builtin:
|
||||||
active = True
|
active = True
|
||||||
pluginName = self.getPluginModuleName(pluginInfo)
|
|
||||||
|
pluginName = pluginInfo.get_module_name()
|
||||||
|
|
||||||
if active:
|
if active:
|
||||||
if not pluginName in self.getActivePlugins():
|
if pluginName not in self.getActivePlugins():
|
||||||
if self.loadPlugin(pluginInfo):
|
if self.loadPlugin(pluginInfo):
|
||||||
self._activePlugins.append(pluginName )
|
self._active_plugins.append(pluginName)
|
||||||
else:
|
else:
|
||||||
if pluginName in self.getActivePlugins():
|
if pluginName in self.getActivePlugins():
|
||||||
if self.unloadPlugin(pluginInfo):
|
if self.unloadPlugin(pluginInfo):
|
||||||
self._activePlugins.remove(pluginName )
|
self._active_plugins.remove(pluginName)
|
||||||
|
|
||||||
def isPluginActive(self, pluginInfo):
|
def isPluginActive(self, pluginInfo):
|
||||||
if self.isPluginBuildIn(pluginInfo):
|
"""Check if a plugin is active."""
|
||||||
return True
|
module_name = pluginInfo.get_module_name()
|
||||||
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):
|
# Builtin plugins are always active
|
||||||
"""Loads plugins from settings."""
|
if pluginInfo.builtin:
|
||||||
|
logger.debug(f"Plugin {module_name} is builtin, active by default")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# If a plugin is already loaded, it's active
|
||||||
|
if pluginInfo.loaded:
|
||||||
|
logger.debug(f"Plugin {module_name} is already loaded, considered active")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Check case-insensitive match in active plugins list
|
||||||
|
active_plugins = self.getActivePlugins()
|
||||||
|
|
||||||
|
# Try exact match first
|
||||||
|
if module_name in active_plugins:
|
||||||
|
logger.debug(f"Plugin {module_name} found in active plugins list")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Try case-insensitive match
|
||||||
|
module_name_lower = module_name.lower()
|
||||||
|
is_active = any(plugin.lower() == module_name_lower for plugin in active_plugins)
|
||||||
|
|
||||||
|
if is_active:
|
||||||
|
logger.debug(f"Plugin {module_name} found in active plugins list (case-insensitive match)")
|
||||||
|
else:
|
||||||
|
logger.debug(f"Plugin {module_name} not found in active plugins list")
|
||||||
|
|
||||||
|
return is_active
|
||||||
|
|
||||||
|
def syncAllPluginsActive(self):
|
||||||
|
"""Sync the active state of all plugins."""
|
||||||
|
logger.info("Syncing active state of all plugins")
|
||||||
|
|
||||||
|
# Log plugin status before syncing
|
||||||
|
if PLUGIN_DEBUG:
|
||||||
for pluginInfo in self.plugins:
|
for pluginInfo in self.plugins:
|
||||||
if self.isPluginActive(pluginInfo) or ForceAllPlugins:
|
is_active = self.isPluginActive(pluginInfo)
|
||||||
self.loadPlugin(pluginInfo)
|
is_loaded = pluginInfo.loaded
|
||||||
|
logger.debug(f"Plugin {pluginInfo.get_module_name()}: active={is_active}, loaded={is_loaded}")
|
||||||
|
|
||||||
def loadPlugin(self, pluginInfo):
|
# First unload inactive plugins
|
||||||
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)
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def unloadAllPlugins(self, ForceAllPlugins=False):
|
|
||||||
"""Loads plugins from settings."""
|
|
||||||
for pluginInfo in self.plugins:
|
for pluginInfo in self.plugins:
|
||||||
if not self.isPluginActive(pluginInfo) or ForceAllPlugins:
|
if not self.isPluginActive(pluginInfo) and pluginInfo.loaded:
|
||||||
|
logger.info(f"Unloading inactive plugin: {pluginInfo.get_module_name()}")
|
||||||
self.unloadPlugin(pluginInfo)
|
self.unloadPlugin(pluginInfo)
|
||||||
|
|
||||||
|
# Then load active plugins
|
||||||
|
for pluginInfo in self.plugins:
|
||||||
|
if self.isPluginActive(pluginInfo) and not pluginInfo.loaded:
|
||||||
|
logger.info(f"Loading active plugin: {pluginInfo.get_module_name()}")
|
||||||
|
result = self.loadPlugin(pluginInfo)
|
||||||
|
logger.info(f"Plugin {pluginInfo.get_module_name()} load result: {result}")
|
||||||
|
|
||||||
|
# Log final plugin status
|
||||||
|
active_plugins = [p.get_module_name() for p in self.plugins if p.loaded]
|
||||||
|
logger.info(f"Active plugins after sync: {active_plugins}")
|
||||||
|
inactive_plugins = [p.get_module_name() for p in self.plugins if not p.loaded]
|
||||||
|
logger.info(f"Inactive plugins after sync: {inactive_plugins}")
|
||||||
|
|
||||||
|
def loadPlugin(self, pluginInfo):
|
||||||
|
"""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
|
||||||
|
|
||||||
|
module_name = pluginInfo.get_module_name()
|
||||||
|
logger.info(f"Attempting to load plugin: {module_name}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Already loaded?
|
||||||
|
if pluginInfo.loaded:
|
||||||
|
logger.info(f"Plugin {module_name} already loaded, skipping")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Try to find the plugin file
|
||||||
|
module_name = pluginInfo.get_module_name()
|
||||||
|
plugin_dir = pluginInfo.get_module_dir()
|
||||||
|
|
||||||
|
# Check for plugin.py first (standard format)
|
||||||
|
plugin_file = os.path.join(plugin_dir, "plugin.py")
|
||||||
|
|
||||||
|
# Fall back to [PluginName].py if plugin.py doesn't exist
|
||||||
|
if not os.path.exists(plugin_file):
|
||||||
|
alternative_plugin_file = os.path.join(plugin_dir, f"{module_name}.py")
|
||||||
|
if os.path.exists(alternative_plugin_file):
|
||||||
|
plugin_file = alternative_plugin_file
|
||||||
|
logger.info(f"Using alternative plugin file: {alternative_plugin_file}")
|
||||||
|
|
||||||
|
if not os.path.exists(plugin_file):
|
||||||
|
logger.error(f"Plugin file not found: {plugin_file}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
logger.info(f"Loading plugin from: {plugin_file}")
|
||||||
|
spec = importlib.util.spec_from_file_location(module_name, plugin_file)
|
||||||
|
if spec is None:
|
||||||
|
logger.error(f"Failed to create spec for plugin: {module_name}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
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
|
||||||
|
logger.info(f"Found plugin class: {attr.__name__} in {module_name}")
|
||||||
|
break
|
||||||
|
|
||||||
|
if not plugin_class:
|
||||||
|
logger.error(f"No plugin class found in {module_name}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Create and initialize plugin instance
|
||||||
|
logger.info(f"Creating instance of plugin class: {plugin_class.__name__}")
|
||||||
|
plugin_instance = plugin_class()
|
||||||
|
pluginInfo.instance = plugin_instance
|
||||||
|
|
||||||
|
# Ensure plugins have a reference to the app
|
||||||
|
plugin_instance.app = self.getApp()
|
||||||
|
logger.info(f"Set app reference for plugin: {module_name}")
|
||||||
|
|
||||||
|
if hasattr(plugin_instance, 'set_app'):
|
||||||
|
plugin_instance.set_app(self.getApp())
|
||||||
|
logger.info(f"Called set_app() for plugin: {module_name}")
|
||||||
|
|
||||||
|
if hasattr(plugin_instance, 'set_plugin_info'):
|
||||||
|
plugin_instance.set_plugin_info(pluginInfo)
|
||||||
|
logger.info(f"Called set_plugin_info() for plugin: {module_name}")
|
||||||
|
|
||||||
|
# Register with pluggy and activate
|
||||||
|
if self.plugin_manager is None:
|
||||||
|
logger.error(f"Plugin manager is None when loading {module_name}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
logger.info(f"Registering plugin with pluggy: {module_name}")
|
||||||
|
self.plugin_manager.register(plugin_instance)
|
||||||
|
|
||||||
|
try:
|
||||||
|
logger.info(f"Activating plugin: {module_name}")
|
||||||
|
self.plugin_manager.hook.activate(plugin=plugin_instance)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error activating plugin {module_name}: {e}")
|
||||||
|
import traceback
|
||||||
|
logger.error(traceback.format_exc())
|
||||||
|
return False
|
||||||
|
|
||||||
|
pluginInfo.loaded = True
|
||||||
|
logger.info(f"Successfully loaded plugin: {module_name}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to load plugin {module_name}: {e}")
|
||||||
|
import traceback
|
||||||
|
logger.error(traceback.format_exc())
|
||||||
|
return False
|
||||||
|
|
||||||
def unloadPlugin(self, pluginInfo):
|
def unloadPlugin(self, pluginInfo):
|
||||||
resourceManager = self.getApp().getResourceManager()
|
"""Unload a plugin."""
|
||||||
moduleName = pluginInfo.get_module_name()
|
# Skip if pluggy is not available
|
||||||
|
if not PLUGGY_AVAILABLE:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if pluginInfo.builtin:
|
||||||
|
return False
|
||||||
|
|
||||||
|
module_name = pluginInfo.get_module_name()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if pluginInfo not in self.plugins:
|
# Not loaded?
|
||||||
print("Plugin missing: {}".format(moduleName))
|
if not pluginInfo.loaded:
|
||||||
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)
|
|
||||||
return False
|
|
||||||
return True
|
return True
|
||||||
def installPlugin(self, pluginFilePath, pluginType=PluginType.USER):
|
|
||||||
if not self.isValidPluginFile(pluginFilePath):
|
# Deactivate plugin
|
||||||
return False
|
plugin_instance = pluginInfo.instance
|
||||||
pluginFolder = pluginType.get_root_dir()
|
if plugin_instance:
|
||||||
if not pluginFolder.endswith('/'):
|
|
||||||
pluginFolder += '/'
|
|
||||||
if not os.path.exists(pluginFolder):
|
|
||||||
os.mkdir(pluginFolder)
|
|
||||||
else:
|
|
||||||
if not os.path.isdir(pluginFolder):
|
|
||||||
return False
|
|
||||||
try:
|
try:
|
||||||
with tarfile.open(pluginFilePath) as tar:
|
self.plugin_manager.hook.deactivate(plugin=plugin_instance)
|
||||||
tar.extractall(path=pluginFolder)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
logger.error(f"Error deactivating plugin {module_name}: {e}")
|
||||||
|
|
||||||
pluginModulePath = self.getModuleDirByPluginFile(pluginFilePath)
|
# Unregister from pluggy
|
||||||
if pluginModulePath != '':
|
self.plugin_manager.unregister(plugin_instance)
|
||||||
pluginModulePath = pluginFolder + pluginModulePath
|
|
||||||
self.setIgnoredPlugins(pluginModulePath[:-1], False) # without ending /
|
|
||||||
print('install', pluginFilePath)
|
|
||||||
self.callPackageTriggers(pluginModulePath, 'onPostInstall')
|
|
||||||
self.rescanPlugins()
|
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
pluginInfo.instance = None
|
||||||
|
pluginInfo.loaded = False
|
||||||
|
|
||||||
|
logger.info(f"Unloaded plugin: {module_name}")
|
||||||
return True
|
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):
|
|
||||||
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:
|
except Exception as e:
|
||||||
print(e)
|
logger.error(f"Failed to unload plugin {module_name}: {e}")
|
||||||
return False
|
return False
|
||||||
self.setIgnoredPlugins(pluginFolder, True)
|
|
||||||
self.rescanPlugins()
|
|
||||||
|
|
||||||
return True
|
def unloadAllPlugins(self, ForceAllPlugins=False):
|
||||||
def callPackageTriggers(self, pluginPath, trigger):
|
"""Unload all plugins."""
|
||||||
if not os.path.exists(pluginPath):
|
if not PLUGGY_AVAILABLE:
|
||||||
return
|
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':
|
for pluginInfo in self.plugins:
|
||||||
try:
|
if ForceAllPlugins or pluginInfo.loaded:
|
||||||
package.onPostInstall(pluginPath, self.getApp())
|
self.unloadPlugin(pluginInfo)
|
||||||
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_CTHULHU
|
|
||||||
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
|
|
||||||
|
@ -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 ByeCthulhu(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_CTHULHU, resetStyles=False)
|
|
@ -1,7 +1,7 @@
|
|||||||
cthulhu_python_PYTHON = \
|
cthulhu_python_PYTHON = \
|
||||||
__init__.py \
|
__init__.py \
|
||||||
ByeCthulhu.plugin \
|
plugin.info \
|
||||||
ByeCthulhu.py
|
plugin.py
|
||||||
|
|
||||||
cthulhu_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
|
||||||
|
|
8
src/cthulhu/plugins/ByeCthulhu/plugin.info
Normal file
8
src/cthulhu/plugins/ByeCthulhu/plugin.info
Normal file
@ -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
|
75
src/cthulhu/plugins/ByeCthulhu/plugin.py
Normal file
75
src/cthulhu/plugins/ByeCthulhu/plugin.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#!/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,
|
||||||
|
"default" # Add profile parameter
|
||||||
|
)
|
||||||
|
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()
|
||||||
|
# Use disconnectSignalByFunction instead since disconnectSignal doesn't exist
|
||||||
|
signal_manager.disconnectSignalByFunction(
|
||||||
|
self.process
|
||||||
|
)
|
||||||
|
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,6 +0,0 @@
|
|||||||
[Plugin]
|
|
||||||
Module=CapsLockHack
|
|
||||||
Loader=python3
|
|
||||||
Name=Caps Lock Hack
|
|
||||||
Description=Fix Capslock sometimes switch on / off when its used as modifier
|
|
||||||
Authors=Chrys chrys@linux-a11y.org
|
|
@ -1,119 +0,0 @@
|
|||||||
from cthulhu import plugin
|
|
||||||
|
|
||||||
import gi
|
|
||||||
gi.require_version('Peas', '1.0')
|
|
||||||
from gi.repository import GObject
|
|
||||||
from gi.repository import Peas
|
|
||||||
from threading import Thread, Lock
|
|
||||||
import subprocess, time, re, os
|
|
||||||
|
|
||||||
class CapsLockHack(GObject.Object, Peas.Activatable, plugin.Plugin):
|
|
||||||
__gtype_name__ = 'CapsLockHack'
|
|
||||||
|
|
||||||
object = GObject.Property(type=GObject.Object)
|
|
||||||
def __init__(self):
|
|
||||||
plugin.Plugin.__init__(self)
|
|
||||||
self.lock = Lock()
|
|
||||||
self.active = False
|
|
||||||
self.workerThread = Thread(target=self.worker)
|
|
||||||
def do_activate(self):
|
|
||||||
API = self.object
|
|
||||||
"""Enable or disable use of the caps lock key as an Cthulhu modifier key."""
|
|
||||||
self.interpretCapsLineProg = re.compile(
|
|
||||||
r'^\s*interpret\s+Caps[_+]Lock[_+]AnyOfOrNone\s*\(all\)\s*{\s*$', re.I)
|
|
||||||
self.normalCapsLineProg = re.compile(
|
|
||||||
r'^\s*action\s*=\s*LockMods\s*\(\s*modifiers\s*=\s*Lock\s*\)\s*;\s*$', re.I)
|
|
||||||
self.interpretShiftLineProg = re.compile(
|
|
||||||
r'^\s*interpret\s+Shift[_+]Lock[_+]AnyOf\s*\(\s*Shift\s*\+\s*Lock\s*\)\s*{\s*$', re.I)
|
|
||||||
self.normalShiftLineProg = re.compile(
|
|
||||||
r'^\s*action\s*=\s*LockMods\s*\(\s*modifiers\s*=\s*Shift\s*\)\s*;\s*$', re.I)
|
|
||||||
self.disabledModLineProg = re.compile(
|
|
||||||
r'^\s*action\s*=\s*NoAction\s*\(\s*\)\s*;\s*$', re.I)
|
|
||||||
self.normalCapsLine = ' action= LockMods(modifiers=Lock);'
|
|
||||||
self.normalShiftLine = ' action= LockMods(modifiers=Shift);'
|
|
||||||
self.disabledModLine = ' action= NoAction();'
|
|
||||||
self.activateWorker()
|
|
||||||
def do_deactivate(self):
|
|
||||||
API = self.object
|
|
||||||
self.deactivateWorker()
|
|
||||||
def do_update_state(self):
|
|
||||||
API = self.object
|
|
||||||
def deactivateWorker(self):
|
|
||||||
with self.lock:
|
|
||||||
self.active = False
|
|
||||||
self.workerThread.join()
|
|
||||||
def activateWorker(self):
|
|
||||||
with self.lock:
|
|
||||||
self.active = True
|
|
||||||
self.workerThread.start()
|
|
||||||
def isActive(self):
|
|
||||||
with self.lock:
|
|
||||||
return self.active
|
|
||||||
def worker(self):
|
|
||||||
"""Makes an Cthulhu-specific Xmodmap so that the keys behave as we
|
|
||||||
need them to do. This is especially the case for the Cthulhu modifier.
|
|
||||||
"""
|
|
||||||
API = self.object
|
|
||||||
capsLockCleared = False
|
|
||||||
settings = API.app.getDynamicApiManager().getAPI('Settings')
|
|
||||||
time.sleep(3)
|
|
||||||
while self.isActive():
|
|
||||||
if "Caps_Lock" in settings.cthulhuModifierKeys \
|
|
||||||
or "Shift_Lock" in settings.cthulhuModifierKeys:
|
|
||||||
self.setCapsLockAsCthulhuModifier(True)
|
|
||||||
capsLockCleared = True
|
|
||||||
elif capsLockCleared:
|
|
||||||
self.setCapsLockAsCthulhuModifier(False)
|
|
||||||
capsLockCleared = False
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
def setCapsLockAsCthulhuModifier(self, enable):
|
|
||||||
originalXmodmap = None
|
|
||||||
lines = None
|
|
||||||
try:
|
|
||||||
originalXmodmap = subprocess.check_output(['xkbcomp', os.environ['DISPLAY'], '-'])
|
|
||||||
lines = originalXmodmap.decode('UTF-8').split('\n')
|
|
||||||
except:
|
|
||||||
return
|
|
||||||
foundCapsInterpretSection = False
|
|
||||||
foundShiftInterpretSection = False
|
|
||||||
modified = False
|
|
||||||
for i, line in enumerate(lines):
|
|
||||||
if not foundCapsInterpretSection and not foundShiftInterpretSection:
|
|
||||||
if self.interpretCapsLineProg.match(line):
|
|
||||||
foundCapsInterpretSection = True
|
|
||||||
elif self.interpretShiftLineProg.match(line):
|
|
||||||
foundShiftInterpretSection = True
|
|
||||||
elif foundCapsInterpretSection:
|
|
||||||
if enable:
|
|
||||||
if self.normalCapsLineProg.match(line):
|
|
||||||
lines[i] = self.disabledModLine
|
|
||||||
modified = True
|
|
||||||
else:
|
|
||||||
if self.disabledModLineProg.match(line):
|
|
||||||
lines[i] = self.normalCapsLine
|
|
||||||
modified = True
|
|
||||||
if line.find('}'):
|
|
||||||
foundCapsInterpretSection = False
|
|
||||||
else: # foundShiftInterpretSection
|
|
||||||
if enable:
|
|
||||||
if self.normalShiftLineProg.match(line):
|
|
||||||
lines[i] = self.disabledModLine
|
|
||||||
modified = True
|
|
||||||
else:
|
|
||||||
if self.disabledModLineProg.match(line):
|
|
||||||
lines[i] = self.normalShiftLine
|
|
||||||
modified = True
|
|
||||||
if line.find('}'):
|
|
||||||
foundShiftInterpretSection = False
|
|
||||||
if modified:
|
|
||||||
newXmodMap = bytes('\n'.join(lines), 'UTF-8')
|
|
||||||
self.setXmodmap(newXmodMap)
|
|
||||||
def setXmodmap(self, xkbmap):
|
|
||||||
"""Set the keyboard map using xkbcomp."""
|
|
||||||
try:
|
|
||||||
p = subprocess.Popen(['xkbcomp', '-w0', '-', os.environ['DISPLAY']],
|
|
||||||
stdin=subprocess.PIPE, stdout=None, stderr=None)
|
|
||||||
p.communicate(xkbmap)
|
|
||||||
except:
|
|
||||||
pass
|
|
@ -1,7 +0,0 @@
|
|||||||
cthulhu_python_PYTHON = \
|
|
||||||
__init__.py \
|
|
||||||
CapsLockHack.plugin \
|
|
||||||
CapsLockHack.py
|
|
||||||
|
|
||||||
cthulhu_pythondir=$(pkgpythondir)/plugins/CapsLockHack
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
|||||||
[Plugin]
|
|
||||||
Module=ClassicPreferences
|
|
||||||
Loader=python3
|
|
||||||
Name=Classic Preferences UI
|
|
||||||
Description=The classic preferences dialog
|
|
||||||
Authors=Chrys chrys@linux-a11y.org
|
|
||||||
Website=
|
|
||||||
Version=1.0
|
|
||||||
Copyright=
|
|
||||||
Builtin=true
|
|
||||||
Hidden=true
|
|
||||||
Depends=
|
|
||||||
Icon=
|
|
||||||
Help=
|
|
@ -1,84 +0,0 @@
|
|||||||
from cthulhu import plugin
|
|
||||||
|
|
||||||
import gi, time
|
|
||||||
gi.require_version('Peas', '1.0')
|
|
||||||
from gi.repository import GObject
|
|
||||||
from gi.repository import Peas
|
|
||||||
import importlib, os
|
|
||||||
import cthulhu_gui_prefs
|
|
||||||
|
|
||||||
class ClassicPreferences(GObject.Object, Peas.Activatable, plugin.Plugin):
|
|
||||||
#__gtype_name__ = 'ClassicPreferences'
|
|
||||||
|
|
||||||
object = GObject.Property(type=GObject.Object)
|
|
||||||
def __init__(self):
|
|
||||||
plugin.Plugin.__init__(self)
|
|
||||||
def do_activate(self):
|
|
||||||
API = self.object
|
|
||||||
self.connectSignal("setup-inputeventhandlers-completed", self.setupCompatBinding)
|
|
||||||
#self.setupCompatBinding(API.app)
|
|
||||||
def setupCompatBinding(self, app):
|
|
||||||
cmdnames = app.getDynamicApiManager().getAPI('Cmdnames')
|
|
||||||
inputEventHandlers = app.getDynamicApiManager().getAPI('inputEventHandlers')
|
|
||||||
inputEventHandlers['preferencesSettingsHandler'] = app.getAPIHelper().createInputEventHandler(self.showPreferencesGUI, cmdnames.SHOW_PREFERENCES_GUI)
|
|
||||||
inputEventHandlers['appPreferencesSettingsHandler'] = app.getAPIHelper().createInputEventHandler(self.showAppPreferencesGUI, cmdnames.SHOW_APP_PREFERENCES_GUI)
|
|
||||||
def do_deactivate(self):
|
|
||||||
API = self.object
|
|
||||||
inputEventHandlers = API.app.getDynamicApiManager().getAPI('inputEventHandlers')
|
|
||||||
del inputEventHandlers['preferencesSettingsHandler']
|
|
||||||
del inputEventHandlers['appPreferencesSettingsHandler']
|
|
||||||
def do_update_state(self):
|
|
||||||
API = self.object
|
|
||||||
def showAppPreferencesGUI(self, script=None, inputEvent=None):
|
|
||||||
"""Displays the user interface to configure the settings for a
|
|
||||||
specific applications within Cthulhu and set up those app-specific
|
|
||||||
user preferences using a GUI.
|
|
||||||
|
|
||||||
Returns True to indicate the input event has been consumed.
|
|
||||||
"""
|
|
||||||
API = self.object
|
|
||||||
cthulhu_state = API.app.getDynamicApiManager().getAPI('CthulhuState')
|
|
||||||
settings = API.app.getDynamicApiManager().getAPI('Settings')
|
|
||||||
_settingsManager = API.app.getDynamicApiManager().getAPI('SettingsManager').getManager()
|
|
||||||
_scriptManager = API.app.getDynamicApiManager().getAPI('ScriptManager').getManager()
|
|
||||||
|
|
||||||
prefs = {}
|
|
||||||
for key in settings.userCustomizableSettings:
|
|
||||||
prefs[key] = _settingsManager.getSetting(key)
|
|
||||||
|
|
||||||
script = script or cthulhu_state.activeScript
|
|
||||||
self._showPreferencesUI(script, prefs)
|
|
||||||
return True
|
|
||||||
def showPreferencesGUI(self, script=None, inputEvent=None):
|
|
||||||
"""Displays the user interface to configure Cthulhu and set up
|
|
||||||
user preferences using a GUI.
|
|
||||||
|
|
||||||
Returns True to indicate the input event has been consumed.
|
|
||||||
"""
|
|
||||||
API = self.object
|
|
||||||
cthulhu_state = API.app.getDynamicApiManager().getAPI('CthulhuState')
|
|
||||||
settings = API.app.getDynamicApiManager().getAPI('Settings')
|
|
||||||
_settingsManager = API.app.getDynamicApiManager().getAPI('SettingsManager').getManager()
|
|
||||||
_scriptManager = API.app.getDynamicApiManager().getAPI('ScriptManager').getManager()
|
|
||||||
debug = API.app.getDynamicApiManager().getAPI('Debug')
|
|
||||||
prefs = _settingsManager.getGeneralSettings(_settingsManager.profile)
|
|
||||||
script = _scriptManager.getDefaultScript()
|
|
||||||
self._showPreferencesUI(script, prefs)
|
|
||||||
return True
|
|
||||||
def _showPreferencesUI(self, script, prefs):
|
|
||||||
API = self.object
|
|
||||||
cthulhu_state = API.app.getDynamicApiManager().getAPI('CthulhuState')
|
|
||||||
debug = API.app.getDynamicApiManager().getAPI('Debug')
|
|
||||||
cthulhu_platform = API.app.getDynamicApiManager().getAPI('CthulhuPlatform')
|
|
||||||
|
|
||||||
if cthulhu_state.cthulhuOS:
|
|
||||||
cthulhu_state.cthulhuOS.showGUI()
|
|
||||||
return
|
|
||||||
|
|
||||||
uiFile = os.path.join(self.getModuleDir(),
|
|
||||||
"cthulhu-setup.ui")
|
|
||||||
|
|
||||||
cthulhu_state.cthulhuOS = cthulhu_gui_prefs.CthulhuSetupGUI(uiFile, "cthulhuSetupWindow", prefs, API.app)
|
|
||||||
cthulhu_state.cthulhuOS.init(script)
|
|
||||||
cthulhu_state.cthulhuOS.setTranslationContext(self.getTranslationContext())
|
|
||||||
cthulhu_state.cthulhuOS.showGUI()
|
|
@ -1,10 +0,0 @@
|
|||||||
cthulhu_python_PYTHON = \
|
|
||||||
__init__.py \
|
|
||||||
ClassicPreferences.plugin \
|
|
||||||
ClassicPreferences.py \
|
|
||||||
cthulhu_gui_prefs.py \
|
|
||||||
cthulhu_gui_profile.py \
|
|
||||||
cthulhu-setup.ui
|
|
||||||
|
|
||||||
cthulhu_pythondir=$(pkgpythondir)/plugins/ClassicPreferences
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,163 +0,0 @@
|
|||||||
# Cthulhu
|
|
||||||
#
|
|
||||||
# Copyright 2010 Consorcio Fernando de los Rios.
|
|
||||||
# Author: Javier Hernandez Antunez <jhernandez@emergya.es>
|
|
||||||
# Author: Alejandro Leiva <aleiva@emergya.es>
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
"""Displays the Save Profile As dialog."""
|
|
||||||
|
|
||||||
__id__ = "$Id$"
|
|
||||||
__version__ = "$Revision$"
|
|
||||||
__date__ = "$Date$"
|
|
||||||
__copyright__ = "Copyright (c) 2010 Consorcio Fernando de los Rios."
|
|
||||||
__license__ = "LGPL"
|
|
||||||
|
|
||||||
import locale
|
|
||||||
import sys
|
|
||||||
from gi.repository import Gtk
|
|
||||||
|
|
||||||
cthulhu_state = None
|
|
||||||
guilabels = None
|
|
||||||
|
|
||||||
OS = None
|
|
||||||
newProfile = None
|
|
||||||
|
|
||||||
app = None
|
|
||||||
|
|
||||||
class CthulhuProfileGUI(Gtk.Dialog):
|
|
||||||
|
|
||||||
def __init__(self, app):
|
|
||||||
"""Initialize the Cthulhu profile configuration GUI."""
|
|
||||||
self.app = app
|
|
||||||
global guilabels
|
|
||||||
global cthulhu_state
|
|
||||||
|
|
||||||
guilabels = self.app.getDynamicApiManager().getAPI('GuiLabels')
|
|
||||||
cthulhu_state = self.app.getDynamicApiManager().getAPI('CthulhuState')
|
|
||||||
|
|
||||||
Gtk.Dialog.__init__(self)
|
|
||||||
self.set_title(guilabels.PROFILE_SAVE_AS_TITLE)
|
|
||||||
self.set_has_resize_grip(False)
|
|
||||||
|
|
||||||
self.add_button('gtk-cancel', Gtk.ResponseType.CANCEL)
|
|
||||||
self.add_button('gtk-save', Gtk.ResponseType.ACCEPT)
|
|
||||||
|
|
||||||
grid = Gtk.Grid()
|
|
||||||
grid.set_property('margin', 12)
|
|
||||||
grid.set_row_spacing(10)
|
|
||||||
grid.set_column_spacing(10)
|
|
||||||
|
|
||||||
# Right now the content area is a GtkBox. We'll need to update
|
|
||||||
# this once GtkBox is fully deprecated.
|
|
||||||
contentArea = self.get_content_area()
|
|
||||||
contentArea.pack_start(grid, True, True, 0)
|
|
||||||
|
|
||||||
self.profileEntry = Gtk.Entry()
|
|
||||||
self.profileEntry.set_property('hexpand', True)
|
|
||||||
self.profileEntry.set_activates_default(True)
|
|
||||||
grid.attach(self.profileEntry, 1, 0, 1, 1)
|
|
||||||
|
|
||||||
label = Gtk.Label(guilabels.PROFILE_NAME_LABEL)
|
|
||||||
label.set_use_underline(True)
|
|
||||||
label.set_mnemonic_widget(self.profileEntry)
|
|
||||||
grid.attach(label, 0, 0, 1, 1)
|
|
||||||
|
|
||||||
defaultButton = self.get_widget_for_response(Gtk.ResponseType.ACCEPT)
|
|
||||||
defaultButton.set_property('can-default', True)
|
|
||||||
defaultButton.set_property('has-default', True)
|
|
||||||
|
|
||||||
self.connect('response', self.onResponse)
|
|
||||||
self.connect('destroy', self.onDestroy)
|
|
||||||
|
|
||||||
self.searchString = None
|
|
||||||
self.profileString = None
|
|
||||||
self.prefsDialog = None
|
|
||||||
self.translationContext = None
|
|
||||||
|
|
||||||
def init(self):
|
|
||||||
self.profileString = ''
|
|
||||||
|
|
||||||
def showGUI(self, prefsDialog):
|
|
||||||
"""Show the Save Profile As dialog."""
|
|
||||||
|
|
||||||
self.show_all()
|
|
||||||
self.prefsDialog = prefsDialog
|
|
||||||
self.profileEntry.set_text(self.profileString)
|
|
||||||
ts = 0
|
|
||||||
try:
|
|
||||||
ts = cthulhu_state.lastInputEvent.timestamp
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if ts == 0:
|
|
||||||
ts = Gtk.get_current_event_time()
|
|
||||||
self.present_with_time(ts)
|
|
||||||
|
|
||||||
def onResponse(self, widget, response):
|
|
||||||
"""Signal handler for the responses emitted by the dialog."""
|
|
||||||
|
|
||||||
if response in [Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT]:
|
|
||||||
self.hide()
|
|
||||||
return
|
|
||||||
|
|
||||||
if response == Gtk.ResponseType.ACCEPT:
|
|
||||||
global newProfile
|
|
||||||
|
|
||||||
newProfile = self.profileEntry.get_text()
|
|
||||||
if newProfile:
|
|
||||||
self.destroy()
|
|
||||||
if self.prefsDialog:
|
|
||||||
self.prefsDialog.saveProfile(newProfile)
|
|
||||||
|
|
||||||
def onDestroy(self, widget):
|
|
||||||
"""Signal handler for the 'destroy' signal of the dialog."""
|
|
||||||
|
|
||||||
global OS
|
|
||||||
|
|
||||||
OS = None
|
|
||||||
|
|
||||||
def setTranslationContext(newTranslationContext):
|
|
||||||
global _, translationContext
|
|
||||||
translationContext = newTranslationContext
|
|
||||||
_ = newTranslationContext.gettext
|
|
||||||
|
|
||||||
def setApp(newApp):
|
|
||||||
global app
|
|
||||||
app = newApp
|
|
||||||
|
|
||||||
def showProfileUI(prefsDialog=None):
|
|
||||||
global OS
|
|
||||||
global newProfile
|
|
||||||
|
|
||||||
newProfile = None
|
|
||||||
|
|
||||||
if not OS:
|
|
||||||
OS = CthulhuProfileGUI(app)
|
|
||||||
OS.init()
|
|
||||||
|
|
||||||
OS.showGUI(prefsDialog)
|
|
||||||
|
|
||||||
def main():
|
|
||||||
locale.setlocale(locale.LC_ALL, '')
|
|
||||||
|
|
||||||
showProfileUI()
|
|
||||||
|
|
||||||
Gtk.main()
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
@ -1,6 +0,0 @@
|
|||||||
[Plugin]
|
|
||||||
Module=Clipboard
|
|
||||||
Loader=python3
|
|
||||||
Name=Clipboard
|
|
||||||
Description=Present the content of the current clipboard
|
|
||||||
Authors=Chrys chrys@linux-a11y.org
|
|
@ -1,76 +0,0 @@
|
|||||||
from cthulhu import plugin
|
|
||||||
|
|
||||||
import gi, os
|
|
||||||
gi.require_version('Peas', '1.0')
|
|
||||||
from gi.repository import GObject
|
|
||||||
from gi.repository import Peas
|
|
||||||
gi.require_version("Gtk", "3.0")
|
|
||||||
from gi.repository import Gtk, Gdk
|
|
||||||
|
|
||||||
class Clipboard(GObject.Object, Peas.Activatable, plugin.Plugin):
|
|
||||||
#__gtype_name__ = 'Clipboard'
|
|
||||||
|
|
||||||
object = GObject.Property(type=GObject.Object)
|
|
||||||
def __init__(self):
|
|
||||||
plugin.Plugin.__init__(self)
|
|
||||||
def do_activate(self):
|
|
||||||
API = self.object
|
|
||||||
self.registerGestureByString(self.speakClipboard, _('clipboard'), 'kb:cthulhu+c')
|
|
||||||
def do_deactivate(self):
|
|
||||||
API = self.object
|
|
||||||
def do_update_state(self):
|
|
||||||
API = self.object
|
|
||||||
def speakClipboard(self, script=None, inputEvent=None):
|
|
||||||
API = self.object
|
|
||||||
Message = self.getClipboard()
|
|
||||||
API.app.getDynamicApiManager().getAPI('CthulhuState').activeScript.presentMessage(Message, resetStyles=False)
|
|
||||||
return True
|
|
||||||
def getClipboard(self):
|
|
||||||
Message = ""
|
|
||||||
FoundClipboardContent = False
|
|
||||||
# Get Clipboard
|
|
||||||
ClipboardObj = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
|
|
||||||
|
|
||||||
ClipboardText = ClipboardObj.wait_for_text()
|
|
||||||
ClipboardImage = ClipboardObj.wait_for_image()
|
|
||||||
ClipboardURI = ClipboardObj.wait_for_uris()
|
|
||||||
if (ClipboardText != None):
|
|
||||||
FoundClipboardContent = True
|
|
||||||
if (ClipboardObj.wait_is_uris_available()):
|
|
||||||
noOfObjects = 0
|
|
||||||
noOfFolder = 0
|
|
||||||
noOfFiles = 0
|
|
||||||
noOfDisks = 0
|
|
||||||
noOfLinks = 0
|
|
||||||
for Uri in ClipboardURI:
|
|
||||||
if Uri == '':
|
|
||||||
continue
|
|
||||||
noOfObjects += 1
|
|
||||||
uriWithoutProtocoll = Uri[Uri.find('://') + 3:]
|
|
||||||
Message += " " + Uri[Uri.rfind('/') + 1:] + " "
|
|
||||||
if (os.path.isdir(uriWithoutProtocoll)):
|
|
||||||
noOfFolder += 1
|
|
||||||
Message = Message + _("Folder") #Folder
|
|
||||||
if (os.path.isfile(uriWithoutProtocoll)):
|
|
||||||
noOfFiles += 1
|
|
||||||
Message = Message + _("File") #File
|
|
||||||
if (os.path.ismount(uriWithoutProtocoll)):
|
|
||||||
noOfDisks += 1
|
|
||||||
Message = Message + _("Disk") #Mountpoint
|
|
||||||
if (os.path.islink(uriWithoutProtocoll)):
|
|
||||||
noOfLinks += 1
|
|
||||||
Message = Message + _("Link") #Link
|
|
||||||
if (noOfObjects > 1):
|
|
||||||
Message = str(noOfObjects) + _(" Objects in clipboard ") + Message # X Objects in Clipboard Object Object
|
|
||||||
else:
|
|
||||||
Message = str(noOfObjects) + _(" Object in clipboard ") + Message # 1 Object in Clipboard Object
|
|
||||||
else:
|
|
||||||
Message = _("Text in clipboard ") + ClipboardText # Text in Clipboard
|
|
||||||
|
|
||||||
if (ClipboardImage != None):
|
|
||||||
FoundClipboardContent = True
|
|
||||||
Message = _("The clipboard contains a image") # Image is in Clipboard
|
|
||||||
|
|
||||||
if (not FoundClipboardContent):
|
|
||||||
Message = _("The clipboard is empty")
|
|
||||||
return Message
|
|
@ -1,7 +1,7 @@
|
|||||||
cthulhu_python_PYTHON = \
|
cthulhu_python_PYTHON = \
|
||||||
__init__.py \
|
__init__.py \
|
||||||
Clipboard.plugin \
|
plugin.info \
|
||||||
Clipboard.py
|
plugin.py
|
||||||
|
|
||||||
cthulhu_pythondir=$(pkgpythondir)/plugins/Clipboard
|
cthulhu_pythondir=$(pkgpythondir)/plugins/Clipboard
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
7
src/cthulhu/plugins/Clipboard/plugin.info
Normal file
7
src/cthulhu/plugins/Clipboard/plugin.info
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[Plugin]
|
||||||
|
Name = Clipboard
|
||||||
|
Module = Clipboard
|
||||||
|
Description = Present the content of the current clipboard
|
||||||
|
Authors = Storm Dragon <storm_dragon@stormux.org>
|
||||||
|
Version = 1.0
|
||||||
|
Category = Utilities
|
193
src/cthulhu/plugins/Clipboard/plugin.py
Normal file
193
src/cthulhu/plugins/Clipboard/plugin.py
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
#!/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
|
||||||
|
|
||||||
|
"""Clipboard plugin for Cthulhu."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
import gettext
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
from gi.repository import Gtk, Gdk
|
||||||
|
|
||||||
|
from cthulhu.plugin import Plugin, cthulhu_hookimpl
|
||||||
|
|
||||||
|
# Set up translation function
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class Clipboard(Plugin):
|
||||||
|
"""Plugin to read the clipboard contents."""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
"""Initialize the plugin."""
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
logger.info("Clipboard 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 Clipboard plugin")
|
||||||
|
try:
|
||||||
|
# Register keyboard shortcut
|
||||||
|
self.registerGestureByString(self.speakClipboard, _('clipboard'), 'kb:cthulhu+shift+c')
|
||||||
|
logger.debug("Registered shortcut for clipboard")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error activating Clipboard 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 Clipboard plugin")
|
||||||
|
try:
|
||||||
|
# Unregister keyboard shortcut
|
||||||
|
if self.app:
|
||||||
|
api_helper = self.app.getAPIHelper()
|
||||||
|
if api_helper and hasattr(api_helper, 'unregisterShortcut'):
|
||||||
|
api_helper.unregisterShortcut('kb:cthulhu+shift+c')
|
||||||
|
logger.debug("Unregistered clipboard shortcut")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error deactivating Clipboard plugin: {e}")
|
||||||
|
"""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 Clipboard plugin")
|
||||||
|
try:
|
||||||
|
# Register keyboard shortcut
|
||||||
|
self.registerGestureByString(self.speakClipboard, _('clipboard'), 'kb:cthulhu+shift+c')
|
||||||
|
logger.debug("Registered shortcut for clipboard")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error activating Clipboard 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 Clipboard plugin")
|
||||||
|
try:
|
||||||
|
# Unregister keyboard shortcut
|
||||||
|
self.unregisterGestureByString('kb:cthulhu+shift+c')
|
||||||
|
logger.debug("Unregistered clipboard shortcut")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error deactivating Clipboard plugin: {e}")
|
||||||
|
|
||||||
|
def speakClipboard(self, script=None, inputEvent=None):
|
||||||
|
"""Present the contents of the clipboard."""
|
||||||
|
try:
|
||||||
|
message = self.getClipboard()
|
||||||
|
|
||||||
|
state = self.app.getDynamicApiManager().getAPI('CthulhuState')
|
||||||
|
if state and state.activeScript:
|
||||||
|
state.activeScript.presentMessage(message, resetStyles=False)
|
||||||
|
logger.debug("Presented clipboard contents")
|
||||||
|
else:
|
||||||
|
logger.warning("Could not present clipboard: no active script")
|
||||||
|
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error in speakClipboard: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def getClipboard(self):
|
||||||
|
"""Get the contents of the clipboard."""
|
||||||
|
try:
|
||||||
|
message = ""
|
||||||
|
found_clipboard_content = False
|
||||||
|
|
||||||
|
# Get Clipboard
|
||||||
|
clipboard_obj = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
|
||||||
|
|
||||||
|
clipboard_text = clipboard_obj.wait_for_text()
|
||||||
|
clipboard_image = clipboard_obj.wait_for_image()
|
||||||
|
clipboard_uri = clipboard_obj.wait_for_uris()
|
||||||
|
|
||||||
|
if clipboard_text is not None:
|
||||||
|
found_clipboard_content = True
|
||||||
|
|
||||||
|
if clipboard_obj.wait_is_uris_available():
|
||||||
|
no_of_objects = 0
|
||||||
|
no_of_folder = 0
|
||||||
|
no_of_files = 0
|
||||||
|
no_of_disks = 0
|
||||||
|
no_of_links = 0
|
||||||
|
|
||||||
|
for uri in clipboard_uri:
|
||||||
|
if uri == '':
|
||||||
|
continue
|
||||||
|
|
||||||
|
no_of_objects += 1
|
||||||
|
uri_without_protocol = uri[uri.find('://') + 3:]
|
||||||
|
message += " " + uri[uri.rfind('/') + 1:] + " "
|
||||||
|
|
||||||
|
if os.path.isdir(uri_without_protocol):
|
||||||
|
no_of_folder += 1
|
||||||
|
message = message + _("Folder")
|
||||||
|
|
||||||
|
if os.path.isfile(uri_without_protocol):
|
||||||
|
no_of_files += 1
|
||||||
|
message = message + _("File")
|
||||||
|
|
||||||
|
if os.path.ismount(uri_without_protocol):
|
||||||
|
no_of_disks += 1
|
||||||
|
message = message + _("Disk")
|
||||||
|
|
||||||
|
if os.path.islink(uri_without_protocol):
|
||||||
|
no_of_links += 1
|
||||||
|
message = message + _("Link")
|
||||||
|
|
||||||
|
if no_of_objects > 1:
|
||||||
|
message = str(no_of_objects) + _(" Objects in clipboard ") + message
|
||||||
|
else:
|
||||||
|
message = str(no_of_objects) + _(" Object in clipboard ") + message
|
||||||
|
else:
|
||||||
|
message = _("Text in clipboard ") + clipboard_text
|
||||||
|
|
||||||
|
if clipboard_image is not None:
|
||||||
|
found_clipboard_content = True
|
||||||
|
message = _("The clipboard contains a image")
|
||||||
|
|
||||||
|
if not found_clipboard_content:
|
||||||
|
message = _("The clipboard is empty")
|
||||||
|
|
||||||
|
return message
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error getting clipboard content: {e}")
|
||||||
|
return _("Error accessing clipboard")
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user