Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 46d3c66dc7 | |||
| c39f2310e3 | |||
| 2d8980051f |
@@ -2,7 +2,7 @@
|
||||
|
||||
pkgname=cthulhu-git
|
||||
_pkgname=cthulhu
|
||||
pkgver=2026.05.14.r396.ge2f9a7c
|
||||
pkgver=2026.05.25.r407.gc39f231
|
||||
pkgrel=1
|
||||
pkgdesc="Desktop-agnostic screen reader with plugin system, forked from Orca"
|
||||
url="https://git.stormux.org/storm/cthulhu"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Maintainer: Storm Dragon <storm_dragon@stormux.org>
|
||||
|
||||
pkgname=cthulhu
|
||||
pkgver=2026.05.14
|
||||
pkgver=2026.05.25
|
||||
pkgrel=1
|
||||
pkgdesc="Desktop-agnostic screen reader with plugin system, forked from Orca"
|
||||
url="https://git.stormux.org/storm/cthulhu"
|
||||
|
||||
@@ -3,16 +3,15 @@
|
||||
# Slackware build script for cthulhu
|
||||
# Created based on PKGBUILD from Storm Dragon <storm_dragon@stormux.org>
|
||||
|
||||
cd $(dirname $0) ; CWD=$(pwd)
|
||||
cd "$(dirname "$0")" ; CWD=$(pwd)
|
||||
|
||||
PRGNAM=cthulhu
|
||||
VERSION=${VERSION:-0.4}
|
||||
VERSION=${VERSION:-2026.05.25}
|
||||
BUILD=${BUILD:-1}
|
||||
TAG=storm
|
||||
PKGTYPE=txz
|
||||
export PYTHON=/usr/bin/python3.11
|
||||
|
||||
if [ -z "$ARCH" ]; then
|
||||
if [ -z "${ARCH:-}" ]; then
|
||||
case "$( uname -m )" in
|
||||
i?86) ARCH=i586 ;;
|
||||
arm*) ARCH=arm ;;
|
||||
@@ -23,7 +22,7 @@ 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
|
||||
if [ -n "${PRINT_PACKAGE_NAME:-}" ]; then
|
||||
echo "$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE"
|
||||
exit 0
|
||||
fi
|
||||
@@ -48,12 +47,12 @@ 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
|
||||
rm -rf "$PKG"
|
||||
mkdir -p "$TMP" "$PKG" "$OUTPUT"
|
||||
cd "$TMP"
|
||||
rm -rf "$PRGNAM-$VERSION"
|
||||
git clone --branch "$VERSION" --depth 1 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 \
|
||||
@@ -61,38 +60,31 @@ find -L . \
|
||||
\( -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 \
|
||||
meson setup _build \
|
||||
--prefix=/usr \
|
||||
--libdir=/usr/lib${LIBDIRSUFFIX} \
|
||||
--libdir="/usr/lib${LIBDIRSUFFIX}" \
|
||||
--sysconfdir=/etc \
|
||||
--localstatedir=/var \
|
||||
--mandir=/usr/man \
|
||||
--docdir=/usr/doc/$PRGNAM-$VERSION \
|
||||
--build=$ARCH-slackware-linux
|
||||
--buildtype=release
|
||||
meson compile -C _build
|
||||
DESTDIR="$PKG" meson install -C _build
|
||||
|
||||
make
|
||||
make install DESTDIR=$PKG
|
||||
|
||||
find $PKG -print0 | xargs -0 file | grep -e "executable" -e "shared object" | grep ELF \
|
||||
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 README.md \
|
||||
$PKG/usr/doc/$PRGNAM-$VERSION
|
||||
cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild
|
||||
rm -f "$PKG/usr/share/icons/hicolor/icon-theme.cache"
|
||||
|
||||
mkdir -p $PKG/install
|
||||
cat $CWD/slack-desc > $PKG/install/slack-desc
|
||||
cat $CWD/doinst.sh > $PKG/install/doinst.sh
|
||||
mkdir -p "$PKG/usr/doc/$PRGNAM-$VERSION"
|
||||
cp -a COPYING HACKING README.md README-DEVELOPMENT.md RELEASE-HOWTO \
|
||||
"$PKG/usr/doc/$PRGNAM-$VERSION"
|
||||
cat "$CWD/$PRGNAM.SlackBuild" > "$PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild"
|
||||
|
||||
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
|
||||
mkdir -p "$PKG/install"
|
||||
cat "$CWD/slack-desc" > "$PKG/install/slack-desc"
|
||||
cat "$CWD/doinst.sh" > "$PKG/install/doinst.sh"
|
||||
|
||||
cd "$PKG"
|
||||
/sbin/makepkg -l y -c n "$OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
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
|
||||
@@ -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 accessibility infrastructure.
|
||||
cthulhu:
|
||||
cthulhu: Homepage: https://git.stormux.org/storm/cthulhu
|
||||
cthulhu:
|
||||
cthulhu:
|
||||
cthulhu:
|
||||
cthulhu:
|
||||
@@ -25,6 +25,14 @@ This package requires the following packages, all available from SlackBuilds.org
|
||||
- libwnck3
|
||||
- python3-atspi
|
||||
- python3-cairo
|
||||
- python3-dasbus
|
||||
- python3-gobject
|
||||
- python3-pluggy
|
||||
- python3-pywayland
|
||||
- python3-setproctitle
|
||||
- python3-tomlkit
|
||||
- speech-dispatcher
|
||||
|
||||
BUILD DEPENDENCIES:
|
||||
- meson
|
||||
- ninja
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
PRGNAM="cthulhu"
|
||||
VERSION="0.4"
|
||||
VERSION="2026.05.25"
|
||||
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 gstreamer gst-plugins-base gst-plugins-good gtk3 liblouis libwnck3 python3-atspi python3-cairo python3-gobject python3-setproctitle speech-dispatcher"
|
||||
REQUIRES="at-spi2-core brltty gobject-introspection gstreamer gst-plugins-base gst-plugins-good gtk3 liblouis libwnck3 python3-atspi python3-cairo python3-dasbus python3-gobject python3-pluggy python3-pywayland python3-setproctitle python3-tomlkit speech-dispatcher"
|
||||
MAINTAINER="Storm Dragon"
|
||||
EMAIL="storm_dragon@stormux.org"
|
||||
|
||||
@@ -3,16 +3,15 @@
|
||||
# Slackware build script for cthulhu
|
||||
# Created based on PKGBUILD from Storm Dragon <storm_dragon@stormux.org>
|
||||
|
||||
cd $(dirname $0) ; CWD=$(pwd)
|
||||
cd "$(dirname "$0")" ; CWD=$(pwd)
|
||||
|
||||
PRGNAM=cthulhu
|
||||
VERSION=${VERSION:-0.4}
|
||||
VERSION=${VERSION:-2026.05.25}
|
||||
BUILD=${BUILD:-1}
|
||||
TAG=storm
|
||||
PKGTYPE=txz
|
||||
export PYTHON=/usr/bin/python3.11
|
||||
|
||||
if [ -z "$ARCH" ]; then
|
||||
if [ -z "${ARCH:-}" ]; then
|
||||
case "$( uname -m )" in
|
||||
i?86) ARCH=i586 ;;
|
||||
arm*) ARCH=arm ;;
|
||||
@@ -23,7 +22,7 @@ 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
|
||||
if [ -n "${PRINT_PACKAGE_NAME:-}" ]; then
|
||||
echo "$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE"
|
||||
exit 0
|
||||
fi
|
||||
@@ -48,12 +47,12 @@ 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
|
||||
rm -rf "$PKG"
|
||||
mkdir -p "$TMP" "$PKG" "$OUTPUT"
|
||||
cd "$TMP"
|
||||
rm -rf "$PRGNAM-$VERSION"
|
||||
git clone --branch "$VERSION" --depth 1 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 \
|
||||
@@ -61,38 +60,31 @@ find -L . \
|
||||
\( -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 \
|
||||
meson setup _build \
|
||||
--prefix=/usr \
|
||||
--libdir=/usr/lib${LIBDIRSUFFIX} \
|
||||
--libdir="/usr/lib${LIBDIRSUFFIX}" \
|
||||
--sysconfdir=/etc \
|
||||
--localstatedir=/var \
|
||||
--mandir=/usr/man \
|
||||
--docdir=/usr/doc/$PRGNAM-$VERSION \
|
||||
--build=$ARCH-slackware-linux
|
||||
--buildtype=release
|
||||
meson compile -C _build
|
||||
DESTDIR="$PKG" meson install -C _build
|
||||
|
||||
make
|
||||
make install DESTDIR=$PKG
|
||||
|
||||
find $PKG -print0 | xargs -0 file | grep -e "executable" -e "shared object" | grep ELF \
|
||||
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 README.md \
|
||||
$PKG/usr/doc/$PRGNAM-$VERSION
|
||||
cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild
|
||||
rm -f "$PKG/usr/share/icons/hicolor/icon-theme.cache"
|
||||
|
||||
mkdir -p $PKG/install
|
||||
cat $CWD/slack-desc > $PKG/install/slack-desc
|
||||
cat $CWD/doinst.sh > $PKG/install/doinst.sh
|
||||
mkdir -p "$PKG/usr/doc/$PRGNAM-$VERSION"
|
||||
cp -a COPYING HACKING README.md README-DEVELOPMENT.md RELEASE-HOWTO \
|
||||
"$PKG/usr/doc/$PRGNAM-$VERSION"
|
||||
cat "$CWD/$PRGNAM.SlackBuild" > "$PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild"
|
||||
|
||||
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
|
||||
mkdir -p "$PKG/install"
|
||||
cat "$CWD/slack-desc" > "$PKG/install/slack-desc"
|
||||
cat "$CWD/doinst.sh" > "$PKG/install/doinst.sh"
|
||||
|
||||
cd "$PKG"
|
||||
/sbin/makepkg -l y -c n "$OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE"
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -x /usr/bin/update-desktop-database ]; then
|
||||
/usr/bin/update-desktop-database -q usr/share/applications >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
project('cthulhu',
|
||||
version: '2026.05.14-master',
|
||||
version: '2026.05.25',
|
||||
meson_version: '>= 1.0.0',
|
||||
)
|
||||
|
||||
|
||||
+24
-5
@@ -59,8 +59,11 @@ fi
|
||||
cthulhuVersionFile="${scriptDir}/src/cthulhu/cthulhuVersion.py"
|
||||
mesonFile="${scriptDir}/meson.build"
|
||||
pkgbuildFile="${scriptDir}/distro-packages/Arch-Linux/cthulhu/PKGBUILD"
|
||||
slackwareBuildFile="${scriptDir}/distro-packages/Slackware/cthulhu.SlackBuild"
|
||||
slintBuildFile="${scriptDir}/distro-packages/Slint/cthulhu.SlackBuild"
|
||||
slintInfoFile="${scriptDir}/distro-packages/Slint/cthulhu-info"
|
||||
|
||||
for path in "$cthulhuVersionFile" "$mesonFile" "$pkgbuildFile"; do
|
||||
for path in "$cthulhuVersionFile" "$mesonFile" "$pkgbuildFile" "$slackwareBuildFile" "$slintBuildFile" "$slintInfoFile"; do
|
||||
if [[ ! -f "$path" ]]; then
|
||||
echo "Error: Missing file: $path" >&2
|
||||
exit 1
|
||||
@@ -68,18 +71,19 @@ for path in "$cthulhuVersionFile" "$mesonFile" "$pkgbuildFile"; do
|
||||
done
|
||||
|
||||
sed -i "s/^version = \".*\"/version = \"${pythonVersion}\"/" "$cthulhuVersionFile"
|
||||
if [[ -n "$codeNameValue" ]]; then
|
||||
sed -i "s/^codeName = \".*\"/codeName = \"${codeNameValue}\"/" "$cthulhuVersionFile"
|
||||
fi
|
||||
sed -i "s/^ version: '.*',/ version: '${fullVersion}',/" "$mesonFile"
|
||||
sed -i "s/^pkgver=.*/pkgver=${pythonVersion}/" "$pkgbuildFile"
|
||||
sed -i "s/^pkgrel=.*/pkgrel=1/" "$pkgbuildFile"
|
||||
sed -i "s/^VERSION=\${VERSION:-.*}/VERSION=\${VERSION:-${pythonVersion}}/" "$slackwareBuildFile"
|
||||
sed -i "s/^VERSION=\${VERSION:-.*}/VERSION=\${VERSION:-${pythonVersion}}/" "$slintBuildFile"
|
||||
sed -i "s/^VERSION=\".*\"/VERSION=\"${pythonVersion}\"/" "$slintInfoFile"
|
||||
|
||||
if ! rg -q "^version = \"${pythonVersion}\"" "$cthulhuVersionFile"; then
|
||||
echo "Error: Failed to update ${cthulhuVersionFile}" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "$codeNameValue" ]] && ! rg -q "^codeName = \"${codeNameValue}\"" "$cthulhuVersionFile"; then
|
||||
if ! rg -q "^codeName = \"${codeNameValue}\"" "$cthulhuVersionFile"; then
|
||||
echo "Error: Failed to update codeName in ${cthulhuVersionFile}" >&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -95,8 +99,23 @@ if ! rg -q "^pkgrel=1$" "$pkgbuildFile"; then
|
||||
echo "Error: Failed to reset pkgrel in ${pkgbuildFile}" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! rg -q "^VERSION=\\\$\\{VERSION:-${pythonVersion}\\}$" "$slackwareBuildFile"; then
|
||||
echo "Error: Failed to update ${slackwareBuildFile}" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! rg -q "^VERSION=\\\$\\{VERSION:-${pythonVersion}\\}$" "$slintBuildFile"; then
|
||||
echo "Error: Failed to update ${slintBuildFile}" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! rg -q "^VERSION=\"${pythonVersion}\"$" "$slintInfoFile"; then
|
||||
echo "Error: Failed to update ${slintInfoFile}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Updated version to ${fullVersion} in:" \
|
||||
"${cthulhuVersionFile}" \
|
||||
"${mesonFile}" \
|
||||
"${pkgbuildFile}"
|
||||
"${pkgbuildFile}" \
|
||||
"${slackwareBuildFile}" \
|
||||
"${slintBuildFile}" \
|
||||
"${slintInfoFile}"
|
||||
|
||||
@@ -23,5 +23,5 @@
|
||||
# Forked from Orca screen reader.
|
||||
# Cthulhu project: https://git.stormux.org/storm/cthulhu
|
||||
|
||||
version = "2026.05.14"
|
||||
codeName = "master"
|
||||
version = "2026.05.25"
|
||||
codeName = ""
|
||||
|
||||
@@ -30,7 +30,8 @@ __license__ = "LGPL"
|
||||
|
||||
# $CTHULHU_VERSION
|
||||
#
|
||||
version = f"Cthulhu screen reader version {cthulhuVersion.version}-{cthulhuVersion.codeName}"
|
||||
versionSuffix = f"-{cthulhuVersion.codeName}" if cthulhuVersion.codeName else ""
|
||||
version = f"Cthulhu screen reader version {cthulhuVersion.version}{versionSuffix}"
|
||||
|
||||
# The revision if built from git; otherwise an empty string
|
||||
#
|
||||
|
||||
@@ -429,41 +429,69 @@ class InputEventManager:
|
||||
identifier = os.path.basename(value.strip().lower())
|
||||
return identifier == "xterm"
|
||||
|
||||
def _active_x11_window_is_xterm(self) -> bool:
|
||||
"""Returns True when the active X11 window appears to be XTerm."""
|
||||
@staticmethod
|
||||
def _safe_call(window: Any, attrName: str) -> Optional[Any]:
|
||||
"""Returns attrName() for window, or None when unavailable."""
|
||||
|
||||
attr = getattr(window, attrName, None)
|
||||
if not callable(attr):
|
||||
return None
|
||||
|
||||
try:
|
||||
return attr()
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def _log_active_x11_window_for_xterm_check(self, window: Any) -> None:
|
||||
"""Logs X11 window details used for XTerm pass-through decisions."""
|
||||
|
||||
classGroup = self._safe_call(window, "get_class_group")
|
||||
classGroupName = None
|
||||
classGroupResClass = None
|
||||
if classGroup is not None:
|
||||
classGroupName = self._safe_call(classGroup, "get_name")
|
||||
classGroupResClass = self._safe_call(classGroup, "get_res_class")
|
||||
|
||||
tokens = [
|
||||
"INPUT EVENT MANAGER: Active X11 window for XTerm check:",
|
||||
"name",
|
||||
self._safe_call(window, "get_name"),
|
||||
"class group",
|
||||
self._safe_call(window, "get_class_group_name") or classGroupName,
|
||||
"class group res class",
|
||||
classGroupResClass,
|
||||
"class instance",
|
||||
self._safe_call(window, "get_class_instance_name"),
|
||||
"pid",
|
||||
self._safe_call(window, "get_pid"),
|
||||
]
|
||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
||||
|
||||
def _active_x11_window_xterm_match(self) -> Optional[bool]:
|
||||
"""Returns whether the active X11 window is XTerm, or None when unknown."""
|
||||
|
||||
window = self._get_active_x11_window()
|
||||
if window is None:
|
||||
return False
|
||||
msg = "INPUT EVENT MANAGER: XTerm matcher cannot identify active X11 window."
|
||||
debug.print_message(debug.LEVEL_INFO, msg, True)
|
||||
return None
|
||||
|
||||
self._log_active_x11_window_for_xterm_check(window)
|
||||
for attrName in ("get_class_group_name", "get_class_instance_name", "get_name"):
|
||||
attr = getattr(window, attrName, None)
|
||||
if not callable(attr):
|
||||
continue
|
||||
try:
|
||||
if self._identifier_is_xterm(attr()):
|
||||
if self._identifier_is_xterm(self._safe_call(window, attrName)):
|
||||
return True
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
getClassGroup = getattr(window, "get_class_group", None)
|
||||
if callable(getClassGroup):
|
||||
try:
|
||||
classGroup = getClassGroup()
|
||||
except Exception:
|
||||
classGroup = None
|
||||
classGroup = self._safe_call(window, "get_class_group")
|
||||
if classGroup is not None:
|
||||
|
||||
for attrName in ("get_name", "get_res_class"):
|
||||
attr = getattr(classGroup, attrName, None)
|
||||
if not callable(attr):
|
||||
continue
|
||||
try:
|
||||
if self._identifier_is_xterm(attr()):
|
||||
if self._identifier_is_xterm(self._safe_call(classGroup, attrName)):
|
||||
return True
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
pid = self._get_active_x11_window_pid()
|
||||
try:
|
||||
pid = int(window.get_pid())
|
||||
except Exception:
|
||||
pid = -1
|
||||
if pid < 1:
|
||||
return False
|
||||
|
||||
@@ -475,6 +503,11 @@ class InputEventManager:
|
||||
|
||||
return self._identifier_is_xterm(executable)
|
||||
|
||||
def _active_x11_window_is_xterm(self) -> bool:
|
||||
"""Returns True when the active X11 window appears to be XTerm."""
|
||||
|
||||
return self._active_x11_window_xterm_match() is True
|
||||
|
||||
def _find_active_x11_atspi_window(self) -> Optional[Atspi.Accessible]:
|
||||
"""Returns the focused AT-SPI window for the active X11 PID, if possible."""
|
||||
|
||||
@@ -589,8 +622,22 @@ class InputEventManager:
|
||||
"""Returns True when XTerm is active and Cthulhu lacks matching AT-SPI context."""
|
||||
|
||||
if pendingFocus is not None:
|
||||
msg = "INPUT EVENT MANAGER: XTerm matcher false; pending focus exists."
|
||||
debug.print_message(debug.LEVEL_INFO, msg, True)
|
||||
return False
|
||||
match = self._active_x11_window_xterm_match()
|
||||
tokens = ["INPUT EVENT MANAGER: XTerm matcher returned", match]
|
||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
||||
if match is True:
|
||||
return True
|
||||
if match is None and self._scriptWithSuspendedGrabsForXterm is not None:
|
||||
msg = (
|
||||
"INPUT EVENT MANAGER: Keeping XTerm key-grab suspension; "
|
||||
"active X11 window is temporarily unknown."
|
||||
)
|
||||
debug.print_message(debug.LEVEL_INFO, msg, True)
|
||||
return True
|
||||
return False
|
||||
return self._active_x11_window_is_xterm()
|
||||
|
||||
def _suspend_key_grabs_for_xterm(self) -> None:
|
||||
"""Suspends active-script key grabs so XTerm/Fenrir can receive them."""
|
||||
@@ -606,8 +653,11 @@ class InputEventManager:
|
||||
if not callable(removeGrabs):
|
||||
return
|
||||
|
||||
msg = "INPUT EVENT MANAGER: Removing active script key grabs while XTerm is focused."
|
||||
debug.print_message(debug.LEVEL_INFO, msg, True)
|
||||
tokens = [
|
||||
"INPUT EVENT MANAGER: Removing active script key grabs while XTerm is focused:",
|
||||
script,
|
||||
]
|
||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
||||
removeGrabs()
|
||||
self._scriptWithSuspendedGrabsForXterm = script
|
||||
|
||||
@@ -619,15 +669,25 @@ class InputEventManager:
|
||||
if script is None:
|
||||
return
|
||||
|
||||
if script is not script_manager.get_manager().get_active_script():
|
||||
activeScript = script_manager.get_manager().get_active_script()
|
||||
if script is not activeScript:
|
||||
tokens = [
|
||||
"INPUT EVENT MANAGER: Not restoring XTerm-suspended key grabs; active script changed:",
|
||||
script,
|
||||
activeScript,
|
||||
]
|
||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
||||
return
|
||||
|
||||
addGrabs = getattr(script, "addKeyGrabs", None)
|
||||
if not callable(addGrabs):
|
||||
return
|
||||
|
||||
msg = "INPUT EVENT MANAGER: Restoring active script key grabs after leaving XTerm."
|
||||
debug.print_message(debug.LEVEL_INFO, msg, True)
|
||||
tokens = [
|
||||
"INPUT EVENT MANAGER: Restoring active script key grabs after leaving XTerm:",
|
||||
script,
|
||||
]
|
||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
||||
addGrabs()
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
|
||||
@@ -35,7 +35,8 @@ class DisplayVersion(Plugin):
|
||||
|
||||
def _get_version_string(self):
|
||||
"""Generate the full version string with AT-SPI and session information."""
|
||||
msg = f'Cthulhu screen reader version {cthulhuVersion.version}-{cthulhuVersion.codeName}'
|
||||
version_suffix = f'-{cthulhuVersion.codeName}' if cthulhuVersion.codeName else ''
|
||||
msg = f'Cthulhu screen reader version {cthulhuVersion.version}{version_suffix}'
|
||||
if cthulhu_platform.revision:
|
||||
msg += f' revision {cthulhu_platform.revision}'
|
||||
|
||||
|
||||
@@ -173,6 +173,97 @@ class InputEventManagerX11FocusRegressionTests(unittest.TestCase):
|
||||
findActiveWindow.assert_not_called()
|
||||
keyboardEvent.process.assert_not_called()
|
||||
|
||||
def test_lxterminal_does_not_pass_through_as_xterm(self):
|
||||
manager = input_event_manager.InputEventManager()
|
||||
window = mock.Mock()
|
||||
window.get_class_group_name.return_value = "lxterminal"
|
||||
window.get_class_instance_name.return_value = "lxterminal"
|
||||
window.get_name.return_value = "LXTerminal"
|
||||
window.get_class_group.return_value = None
|
||||
window.get_pid.return_value = -1
|
||||
|
||||
with (
|
||||
mock.patch.object(manager, "_get_active_x11_window", return_value=window),
|
||||
mock.patch.object(input_event_manager.debug, "print_message"),
|
||||
mock.patch.object(input_event_manager.debug, "print_tokens"),
|
||||
):
|
||||
result = manager._should_pass_through_for_active_xterm(None, None, None)
|
||||
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_xterm_pass_through_stays_active_when_window_lookup_temporarily_fails(self):
|
||||
manager = input_event_manager.InputEventManager()
|
||||
focusManager = mock.Mock()
|
||||
focusManager.get_active_window.return_value = None
|
||||
focusManager.get_locus_of_focus.return_value = None
|
||||
scriptManager = mock.Mock()
|
||||
activeScript = mock.Mock(app=None)
|
||||
scriptManager.get_active_script.return_value = activeScript
|
||||
keyboardEvent = mock.Mock()
|
||||
manager._scriptWithSuspendedGrabsForXterm = activeScript
|
||||
|
||||
with (
|
||||
mock.patch.object(input_event_manager.cthulhu_state, "capturingKeys", False),
|
||||
mock.patch.object(input_event_manager.cthulhu_state, "pendingSelfHostedFocus", None),
|
||||
mock.patch.object(input_event_manager.focus_manager, "get_manager", return_value=focusManager),
|
||||
mock.patch.object(input_event_manager.script_manager, "get_manager", return_value=scriptManager),
|
||||
mock.patch.object(input_event_manager.input_event, "KeyboardEvent", return_value=keyboardEvent),
|
||||
mock.patch.object(manager, "_active_x11_window_xterm_match", return_value=None),
|
||||
mock.patch.object(input_event_manager.debug, "print_message"),
|
||||
mock.patch.object(input_event_manager.debug, "print_tokens"),
|
||||
):
|
||||
result = manager.process_keyboard_event(
|
||||
mock.Mock(),
|
||||
True,
|
||||
90,
|
||||
65438,
|
||||
0,
|
||||
"KP_Insert",
|
||||
)
|
||||
|
||||
self.assertFalse(result)
|
||||
self.assertIs(manager._scriptWithSuspendedGrabsForXterm, activeScript)
|
||||
activeScript.addKeyGrabs.assert_not_called()
|
||||
keyboardEvent.process.assert_not_called()
|
||||
|
||||
def test_xterm_grabs_restore_when_active_window_is_positively_not_xterm(self):
|
||||
manager = input_event_manager.InputEventManager()
|
||||
focusManager = mock.Mock()
|
||||
focusManager.get_active_window.return_value = None
|
||||
focusManager.get_locus_of_focus.return_value = None
|
||||
scriptManager = mock.Mock()
|
||||
activeScript = mock.Mock(app=None)
|
||||
scriptManager.get_active_script.return_value = activeScript
|
||||
keyboardEvent = mock.Mock()
|
||||
keyboardEvent.is_modifier_key.return_value = False
|
||||
manager._scriptWithSuspendedGrabsForXterm = activeScript
|
||||
|
||||
with (
|
||||
mock.patch.object(input_event_manager.cthulhu_state, "capturingKeys", False),
|
||||
mock.patch.object(input_event_manager.cthulhu_state, "pendingSelfHostedFocus", None),
|
||||
mock.patch.object(input_event_manager.focus_manager, "get_manager", return_value=focusManager),
|
||||
mock.patch.object(input_event_manager.script_manager, "get_manager", return_value=scriptManager),
|
||||
mock.patch.object(input_event_manager.input_event, "KeyboardEvent", return_value=keyboardEvent),
|
||||
mock.patch.object(manager, "_active_x11_window_xterm_match", return_value=False),
|
||||
mock.patch.object(input_event_manager.AXUtilities, "can_be_active_window", return_value=True),
|
||||
mock.patch.object(manager, "last_event_was_keyboard", return_value=False),
|
||||
mock.patch.object(input_event_manager.debug, "print_message"),
|
||||
mock.patch.object(input_event_manager.debug, "print_tokens"),
|
||||
):
|
||||
result = manager.process_keyboard_event(
|
||||
mock.Mock(),
|
||||
True,
|
||||
36,
|
||||
65293,
|
||||
0,
|
||||
"Return",
|
||||
)
|
||||
|
||||
self.assertTrue(result)
|
||||
self.assertIsNone(manager._scriptWithSuspendedGrabsForXterm)
|
||||
activeScript.addKeyGrabs.assert_called_once_with()
|
||||
keyboardEvent.process.assert_called_once_with()
|
||||
|
||||
def test_finds_focused_atspi_window_for_active_x11_pid(self):
|
||||
manager = input_event_manager.InputEventManager()
|
||||
app = object()
|
||||
|
||||
Reference in New Issue
Block a user