feat: opt-in D-Bus activation for compositor global shortcuts - #568
feat: opt-in D-Bus activation for compositor global shortcuts#568webenefits wants to merge 5 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #568 +/- ##
==========================================
+ Coverage 86.04% 86.25% +0.21%
==========================================
Files 35 36 +1
Lines 6470 6578 +108
Branches 1052 1064 +12
==========================================
+ Hits 5567 5674 +107
- Misses 682 683 +1
Partials 221 221
🚀 New features to boost your workflow:
|
jatinkrmalik
left a comment
There was a problem hiding this comment.
@webenefits Can you please rebase this branch to latest main? There are a bunch of merge conflicts that you need to resolve.
Add an opt-in external trigger so a compositor global shortcut (e.g. KDE Plasma bound to `vocalinux --toggle`) can start/stop dictation instead of the built-in evdev/pynput hotkey listener reading /dev/input. - New session-bus service com.vocalinux.Vocalinux (Gio/GDBus) with Toggle/Start/Stop; handlers marshal onto the GTK main thread and call the existing TrayIndicator methods. - CLI vocalinux --toggle/--start/--stop forwards the command to a running instance and exits (before the single-instance lock), without starting a second instance. - Opt-in shortcuts.disable_internal_hotkey skips the internal evdev/pynput listener, so no /dev/input access is required. Default behaviour unchanged. - USER_GUIDE section and unit tests (CLI dispatch, config gate, D-Bus handlers). Text injection (IBus) is untouched.
Add an "External Activation (Desktop Shortcut)" switch in Settings -> Shortcuts that toggles shortcuts.disable_internal_hotkey without editing config.json. - Live-apply: toggling starts/stops the internal listener immediately via a new callback (TrayIndicator._setup_keyboard_shortcuts), no restart needed. - When enabled, the mode/shortcut/custom-shortcut rows are greyed out and a hint points to 'vocalinux --toggle'. - Shown on all session-bus desktops (not limited to Plasma/Wayland) — the feature is compositor-independent. - Initial state loaded from config on open (no auto-apply during init). - Tests: source inspection in test_settings_shortcuts.py (repo pattern, since the dialog subclasses the mocked Gtk.Dialog).
send_command only caught GLib.Error. With no session bus available (e.g. DBUS_SESSION_BUS_ADDRESS unset in an SSH/systemd context) or a different exception type from the bindings, `vocalinux --toggle` raised an unhandled traceback instead of exiting with code 1. - Add a generic fallback except clause -> deterministic non-zero exit. - Test for the fallback path (GLib.Error patched to a real class in the harness).
The D-Bus activation tests imported vocalinux modules (and TrayIndicator) at module level. Because the file is collected early, that froze tray_indicator.GLib against a stale gi.repository mock; other test files swap sys.modules["gi.repository"] at runtime, so later GLib-identity assertions (e.g. GLib.SOURCE_REMOVE in test_suspend_handler) and single-instance tests failed depending on collection order. Make all vocalinux imports in test_dbus_activation.py lazy, mock single_instance via sys.modules instead of patching acquire_lock, and move the _setup_keyboard_shortcuts gate tests to test_tray_indicator_ext.py, where tray_indicator is imported late (after the gi.repository swaps).
Raise patch coverage on the external-activation feature: - dbus_service.py to 100%: bus-acquired/name-acquired/name-lost callbacks, _register / _on_bus_acquired / _invoke / shutdown error branches, and the GLib.Error path in send_command. - tray_indicator external Start/Stop handlers: state-guarded start/stop so repeated --start/--stop calls are idempotent. The TrayIndicator tests live in test_tray_indicator_ext.py to keep the real module imported late (avoiding the gi.repository identity issues fixed in the previous commit).
b36b909 to
8925781
Compare
|
@jatinkrmalik done! Rebased onto the latest main and resolved all conflicts. The branch is now linear on top of current upstream main (through cc69c7e), with no merge commits. The conflicts were all complementary: the external D-Bus activation feature and the newer auto_pause_monitor / model_keepalive additions touch adjacent lines in main.py, tray_indicator.py and settings_dialog.py. Both sides are kept, nothing dropped. Full test suite passes locally (Python 3.9 / 3.11 / 3.13); flake8 / black / isort clean. Ready for another look, could you re-review when you get a chance? Thanks! |
What
Adds an opt-in way to start/stop dictation via an external D-Bus trigger, so a
compositor global shortcut (e.g. KDE Plasma bound to
vocalinux --toggle) candrive activation instead of the built-in evdev/pynput hotkey listener.
Why
On Wayland the internal listener reads
/dev/input(needs theinputgroup andis effectively a system-wide key reader). Delegating activation to the compositor
removes that: no
/dev/inputaccess and noinputgroup needed just to startdictation. Text injection (IBus) is unchanged and independent of activation.
How
com.vocalinux.Vocalinux(Gio/GDBus) withToggle/Start/Stop; handlers marshal onto the GTK main thread.vocalinux --toggle/--start/--stopforwards the command to a runninginstance and exits before the single-instance lock, so it never starts a
second instance.
shortcuts.disable_internal_hotkeyskips the internal listener.shortcut controls when enabled). Shown on all desktops — the feature is
compositor-independent.
docs/USER_GUIDE.mdsection and unit tests (CLI dispatch, config gate, D-Bushandlers, settings wiring).
Default behaviour is unchanged — double-tap Ctrl still works out of the box.
Testing
pytest tests/test_dbus_activation.py tests/test_settings_shortcuts.py/dev/inputfiledescriptors are held by the process; activation works via a bound
vocalinux --toggleshortcut.