fix(keyboard): verify Ctrl key capability in evdev backend availability check (#128)
* fix(keyboard): verify Ctrl key capability in evdev backend availability check The evdev backend's is_available() method was incorrectly returning True when keyboard devices were found, even if the user lacked permission to access them or if the accessible devices didn't have Ctrl key capability. This caused keyboard shortcuts to fail silently on Wayland when the user wasn't in the 'input' group, as the backend was selected but couldn't actually monitor keyboard events. Changes: - Add device_has_ctrl_key() helper to verify a device supports Ctrl keys - Update is_available() to check both device accessibility AND Ctrl key capability - Now correctly returns False when no usable keyboard device is found, triggering proper error messages about permissions This ensures users get clear feedback about missing permissions instead of silently non-working keyboard shortcuts. * fix(install): use sg command to apply input group without logout The install.sh script adds the user to the 'input' group for keyboard shortcuts on Wayland, but this change doesn't take effect until logout. Updated wrapper scripts to use 'sg input -c ...' to run vocalinux with the input group applied, even if the user hasn't logged out yet. This provides a much better user experience as keyboard shortcuts work immediately after installation. The wrapper detects if: 1. User is in /etc/group for 'input' group 2. Current session doesn't have the group active If both conditions are true, it uses 'sg' to apply the group.
This commit is contained in:
+20
-2
@@ -1019,11 +1019,21 @@ VOSK_CONFIG
|
||||
mkdir -p "$HOME/.local/bin"
|
||||
|
||||
# Create vocalinux wrapper script
|
||||
# Uses 'sg input' to run with input group for keyboard shortcuts on Wayland
|
||||
# This allows shortcuts to work without logging out after installation
|
||||
cat > "$HOME/.local/bin/vocalinux" << WRAPPER_EOF
|
||||
#!/bin/bash
|
||||
# Wrapper script for Vocalinux that sets required environment variables
|
||||
# and applies the 'input' group for keyboard shortcuts on Wayland
|
||||
export GI_TYPELIB_PATH=/usr/lib/girepository-1.0
|
||||
exec "$VENV_DIR/bin/vocalinux" "\$@"
|
||||
|
||||
# Check if user is in input group but current session doesn't have it
|
||||
if grep -q "^input:.*\b\$(whoami)\b" /etc/group 2>/dev/null && ! groups | grep -q '\binput\b'; then
|
||||
# Use sg to run with input group without requiring logout
|
||||
exec sg input -c "$VENV_DIR/bin/vocalinux \$*"
|
||||
else
|
||||
exec "$VENV_DIR/bin/vocalinux" "\$@"
|
||||
fi
|
||||
WRAPPER_EOF
|
||||
chmod +x "$HOME/.local/bin/vocalinux"
|
||||
print_info "Created wrapper: ~/.local/bin/vocalinux"
|
||||
@@ -1032,8 +1042,16 @@ WRAPPER_EOF
|
||||
cat > "$HOME/.local/bin/vocalinux-gui" << WRAPPER_EOF
|
||||
#!/bin/bash
|
||||
# Wrapper script for Vocalinux GUI that sets required environment variables
|
||||
# and applies the 'input' group for keyboard shortcuts on Wayland
|
||||
export GI_TYPELIB_PATH=/usr/lib/girepository-1.0
|
||||
exec "$VENV_DIR/bin/vocalinux-gui" "\$@"
|
||||
|
||||
# Check if user is in input group but current session doesn't have it
|
||||
if grep -q "^input:.*\b\$(whoami)\b" /etc/group 2>/dev/null && ! groups | grep -q '\binput\b'; then
|
||||
# Use sg to run with input group without requiring logout
|
||||
exec sg input -c "$VENV_DIR/bin/vocalinux-gui \$*"
|
||||
else
|
||||
exec "$VENV_DIR/bin/vocalinux-gui" "\$@"
|
||||
fi
|
||||
WRAPPER_EOF
|
||||
chmod +x "$HOME/.local/bin/vocalinux-gui"
|
||||
print_info "Created wrapper: ~/.local/bin/vocalinux-gui"
|
||||
|
||||
@@ -76,6 +76,36 @@ def find_keyboard_devices() -> List[str]:
|
||||
return keyboard_devices
|
||||
|
||||
|
||||
def device_has_ctrl_key(device_path: str) -> bool:
|
||||
"""
|
||||
Check if a device has Ctrl key capability.
|
||||
|
||||
Args:
|
||||
device_path: Path to the input device
|
||||
|
||||
Returns:
|
||||
True if the device can send Ctrl key events
|
||||
"""
|
||||
if not EVDEV_AVAILABLE:
|
||||
return False
|
||||
|
||||
try:
|
||||
device = InputDevice(device_path)
|
||||
capabilities = device.capabilities()
|
||||
device.close()
|
||||
|
||||
# Check if device has EV_KEY capability and supports Ctrl keys
|
||||
if ecodes.EV_KEY in capabilities:
|
||||
key_caps = capabilities[ecodes.EV_KEY]
|
||||
# Check for left or right Ctrl key
|
||||
if KEY_LEFTCTRL in key_caps or KEY_RIGHTCTRL in key_caps:
|
||||
return True
|
||||
except (OSError, IOError):
|
||||
pass
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class EvdevKeyboardBackend(KeyboardBackend):
|
||||
"""
|
||||
Keyboard backend using python-evdev.
|
||||
@@ -102,14 +132,23 @@ class EvdevKeyboardBackend(KeyboardBackend):
|
||||
logger.error("python-evdev not available")
|
||||
|
||||
def is_available(self) -> bool:
|
||||
"""Check if evdev is available."""
|
||||
"""Check if evdev is available and we can access a keyboard device with Ctrl key."""
|
||||
if not EVDEV_AVAILABLE:
|
||||
return False
|
||||
|
||||
# Check if we can access at least one keyboard device
|
||||
# Check if we can access at least one keyboard device with Ctrl key capability
|
||||
try:
|
||||
devices = find_keyboard_devices()
|
||||
return len(devices) > 0
|
||||
if not devices:
|
||||
return False
|
||||
|
||||
# Try to find at least one device with Ctrl key that we can open
|
||||
for device_path in devices:
|
||||
if device_has_ctrl_key(device_path):
|
||||
return True
|
||||
|
||||
# Could not find any accessible device with Ctrl key
|
||||
return False
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@@ -292,4 +331,9 @@ class EvdevKeyboardBackend(KeyboardBackend):
|
||||
|
||||
|
||||
# Export availability
|
||||
__all__ = ["EvdevKeyboardBackend", "EVDEV_AVAILABLE", "find_keyboard_devices"]
|
||||
__all__ = [
|
||||
"EvdevKeyboardBackend",
|
||||
"EVDEV_AVAILABLE",
|
||||
"find_keyboard_devices",
|
||||
"device_has_ctrl_key",
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user