Fix Python 3.13 and Wayland compatibility (#125)
* Fix Python 3.13 and Wayland compatibility This commit addresses installation failures on modern Linux distributions (Ubuntu 25.10+) with Python 3.13 and Wayland-only sessions. Changes: 1. **Add Python 3.13 support** (pyproject.toml) - Add Python 3.13 to classifiers - Update black target versions to include py312, py313 - No code changes needed - already compatible 2. **Use system site-packages for PyGObject** (install.sh) - Change venv creation to use --system-site-packages flag - Avoids PyGObject build failures with Python 3.13 - System PyGObject (python3-gi) is already installed as dependency - Building from source is unnecessary and fragile with new Python versions 3. **Improve Wayland text injection support** (install.sh) - Install ydotool as fallback (wtype doesn't work with GNOME Wayland) - Add user to 'input' group for uinput device access - Install udev rule for /dev/uinput permissions - Provide clear warning about logout requirement Technical details: - wtype uses Wayland virtual keyboard protocol (not supported by GNOME) - ydotool uses Linux uinput kernel module (works with all compositors) - System PyGObject 3.50.0+ supports Python 3.13 - Building PyGObject 3.54.5 from source fails with Python 3.13 build tools Fixes installation on: - Ubuntu 25.10 (Questing Quokka) - Wayland-only, Python 3.13 - Arch Linux with Python 3.13 - Fedora 41+ with Python 3.13 Tested on: Ubuntu 25.10 with Python 3.13.7, GNOME 49 Wayland Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * Prioritize ydotool over wtype for universal Wayland compatibility wtype uses the virtual-keyboard Wayland protocol which is not supported by GNOME/Mutter compositors. ydotool uses the Linux uinput kernel module which works with all Wayland compositors including GNOME. This change swaps the priority order to check ydotool first, ensuring text injection works on GNOME Wayland (Ubuntu 25.10+) while still falling back to wtype for compositors that support it. Tested on Ubuntu 25.10 with GNOME 49 Wayland - text injection now works perfectly with ydotool. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * ci: trigger workflow run * ci: run lint/tests on python 3.13 --------- Co-authored-by: ACT900 <179795730+ACT900@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.5
ACT900
parent
b5f67b4bc0
commit
6f54dd80e0
@@ -60,7 +60,7 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.10'
|
||||
python-version: '3.13'
|
||||
cache: 'pip'
|
||||
|
||||
- name: Install linting tools
|
||||
@@ -87,7 +87,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ['3.8', '3.10', '3.11']
|
||||
python-version: ['3.8', '3.10', '3.11', '3.13']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
repos:
|
||||
# Code formatting with Black
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 24.1.1
|
||||
rev: 26.1.0
|
||||
hooks:
|
||||
- id: black
|
||||
language_version: python3
|
||||
|
||||
+40
-3
@@ -656,6 +656,43 @@ install_text_input_tools() {
|
||||
print_warning "Please install 'wtype' manually for Wayland text input support."
|
||||
;;
|
||||
esac
|
||||
|
||||
# Try to install ydotool as additional fallback for Wayland
|
||||
# ydotool works better with some compositors (like GNOME) where wtype may fail
|
||||
print_info "Attempting to install ydotool for better Wayland compatibility..."
|
||||
case "$DISTRO_FAMILY" in
|
||||
ubuntu|debian)
|
||||
if ! apt_package_installed "ydotool"; then
|
||||
sudo apt install -y ydotool 2>/dev/null || print_info "ydotool not available in repos (optional)"
|
||||
fi
|
||||
;;
|
||||
fedora)
|
||||
if command_exists dnf; then
|
||||
sudo dnf install -y ydotool 2>/dev/null || print_info "ydotool not available in repos (optional)"
|
||||
fi
|
||||
;;
|
||||
arch)
|
||||
if ! pacman_package_installed "ydotool"; then
|
||||
sudo pacman -S --noconfirm ydotool 2>/dev/null || print_info "ydotool not available in repos (optional)"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Add user to input group for ydotool/dotool support
|
||||
if ! groups | grep -q '\binput\b'; then
|
||||
print_info "Adding $USER to 'input' group for text injection..."
|
||||
sudo usermod -aG input "$USER" || print_warning "Failed to add user to input group"
|
||||
print_warning "You will need to LOG OUT and back in for text injection to work with ydotool/dotool"
|
||||
fi
|
||||
|
||||
# Install udev rule for ydotool/dotool
|
||||
if [ ! -f /etc/udev/rules.d/80-dotool.rules ]; then
|
||||
print_info "Installing udev rule for input device access..."
|
||||
echo 'KERNEL=="uinput", GROUP="input", MODE="0620", OPTIONS+="static_node=uinput"' \
|
||||
| sudo tee /etc/udev/rules.d/80-dotool.rules >/dev/null 2>&1 || print_warning "Failed to install udev rule"
|
||||
sudo udevadm control --reload 2>/dev/null || true
|
||||
sudo udevadm trigger 2>/dev/null || true
|
||||
fi
|
||||
;;
|
||||
|
||||
x11|"")
|
||||
@@ -786,9 +823,9 @@ setup_virtual_environment() {
|
||||
fi
|
||||
|
||||
# Create virtual environment
|
||||
# Note: We don't use --system-site-packages to avoid conflicts with system packages
|
||||
# that may be incompatible with Python 3.12+ (e.g., old coverage versions)
|
||||
python3 -m venv "$VENV_DIR" || {
|
||||
# Use --system-site-packages to access pre-compiled system packages like PyGObject
|
||||
# This avoids build failures with Python 3.13+ where PyGObject may not build from source
|
||||
python3 -m venv --system-site-packages "$VENV_DIR" || {
|
||||
print_error "Failed to create virtual environment. Please check your Python installation."
|
||||
exit 1
|
||||
}
|
||||
|
||||
+2
-1
@@ -31,6 +31,7 @@ classifiers = [
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Topic :: Desktop Environment :: Gnome",
|
||||
"Topic :: Multimedia :: Sound/Audio :: Speech",
|
||||
"Topic :: Text Processing",
|
||||
@@ -95,7 +96,7 @@ version = {attr = "vocalinux.version.__version__"}
|
||||
|
||||
[tool.black]
|
||||
line-length = 100
|
||||
target-version = ['py38', 'py39', 'py310', 'py311']
|
||||
target-version = ['py38', 'py39', 'py310', 'py311', 'py312', 'py313']
|
||||
include = '\.pyi?$'
|
||||
exclude = '''
|
||||
/(
|
||||
|
||||
@@ -118,15 +118,18 @@ class TextInjector:
|
||||
raise RuntimeError("Missing required dependency: xdotool")
|
||||
else:
|
||||
# Check for wtype or ydotool for Wayland
|
||||
# Prefer ydotool as it works universally (including GNOME Wayland)
|
||||
wtype_available = shutil.which("wtype") is not None
|
||||
ydotool_available = shutil.which("ydotool") is not None
|
||||
xdotool_available = shutil.which("xdotool") is not None
|
||||
|
||||
if wtype_available:
|
||||
self.wayland_tool = "wtype"
|
||||
logger.info(f"Using {self.wayland_tool} for Wayland text injection")
|
||||
elif ydotool_available:
|
||||
if ydotool_available:
|
||||
self.wayland_tool = "ydotool"
|
||||
logger.info(
|
||||
f"Using {self.wayland_tool} for Wayland text injection (universal compatibility)"
|
||||
)
|
||||
elif wtype_available:
|
||||
self.wayland_tool = "wtype"
|
||||
logger.info(f"Using {self.wayland_tool} for Wayland text injection")
|
||||
elif xdotool_available:
|
||||
# Fallback to xdotool with XWayland
|
||||
|
||||
Reference in New Issue
Block a user