Skip to content

fix: support X11 sessions, not just Wayland - #206

Merged
goodroot merged 18 commits into
goodroot:mainfrom
ninyawee:feat/x11-session-support
Jul 19, 2026
Merged

fix: support X11 sessions, not just Wayland#206
goodroot merged 18 commits into
goodroot:mainfrom
ninyawee:feat/x11-session-support

Conversation

@ninyawee

Copy link
Copy Markdown

Summary

hyprwhspr already had most of the machinery to run compositor-agnostically (evdev/UInput hotkey capture, ydotool paste injection, xdotool/xprop window-detection fallback), but three things stopped it from actually working under X11:

  • hyprwhspr.service's ExecStartPre hard-required a wayland-* socket in $XDG_RUNTIME_DIR before starting at all, so the service refused to even launch under an X11 session (e.g. gnome-session-x11.target). It now also accepts an X11 socket (/tmp/.X11-unix/X*) as a readiness signal.
  • _copy_text_to_clipboard/_restore_clipboard only checked whether the wl-copy binary existed, not whether a Wayland compositor was actually reachable. On a hybrid X11/Wayland machine (wl-clipboard installed for when you're on Wayland, but currently running an X11 session) wl-copy exits 1 and the code gave up instead of falling back to pyperclip — unlike _save_clipboard, which already had this fallback. Now both paths degrade the same way.
  • pyperclip's own determine_clipboard() prefers a GObject-Introspection GTK clipboard over xclip/xsel whenever gi is importable, and calls gi.require_version('Gtk', '3.0') to get it. mic_osd's layer-shell availability probe already pins this same process's Gtk namespace to 4.0, so pyperclip's request raised Namespace Gtk is already loaded with version 4.0 the first time the new clipboard fallback path actually ran. Fixed by forcing the xclip backend explicitly at import time, so pyperclip never touches gi.

Test plan

  • Confirmed hyprwhspr.service was silently crash-looping every ~17s under X11 before this fix (journalctl --user -u hyprwhspr.service, "Wayland socket not found")
  • After the systemd fix, service starts and reaches [READY] under X11, connects to the configured STT backend, NRestarts=0
  • First live dictation attempt reproduced the pyperclip/GTK4 crash (ERROR: Clipboard copy failed: Namespace Gtk already requires version 4.0, [ERROR] Text injection failed)
  • After forcing the xclip backend, retested end-to-end: Super+Alt+D → speak → Super+Alt+D → transcript received → pasted successfully into the focused window, no errors
  • Tested on Ubuntu 24.04, GNOME 46 (Mutter), X11 session, dual-monitor NVIDIA setup

README's "Requires a Wayland session" line is left as-is in this PR — happy to update it (or soften to "Wayland recommended, X11 supported") if maintainers want, once there's more confidence across other X11 setups (KDE/X11, etc.) beyond the one this was tested on.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Y87A3sADRj7eixj6ubiXnV

Nutchanon Ninyawee and others added 5 commits June 18, 2026 18:23
Remove the pulsing red recording indicator and reclaim its 30px so the
waveform bars fill the panel. Show recording duration (MM:SS) while
recording/paused and transcription time (X.Xs) while processing, frozen
on the brief success/error result.

Also force the overlay hidden at startup: if a previous session was
SIGKILLed mid-recording, the reused orphaned daemon would otherwise stay
stuck visible until the next recording.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CZT7DuDus2VDvQKiGoqYcd
- systemd unit's ExecStartPre hard-required a wayland-* socket before
  starting, so the service refused to run at all under an X11 session
  (gnome-session-x11.target etc.). Accept an X11 socket
  (/tmp/.X11-unix/X*) as an alternative readiness signal.

- _copy_text_to_clipboard/_restore_clipboard only tried wl-copy when the
  binary existed on disk, not when a Wayland compositor was actually
  reachable. On a hybrid X11/Wayland machine (wl-clipboard installed for
  the Wayland session, but currently running X11) wl-copy exits 1 and
  the code gave up instead of falling back to pyperclip, unlike
  _save_clipboard which already had this fallback.

- pyperclip's own determine_clipboard() prefers a GObject-Introspection
  GTK clipboard over xclip/xsel whenever `gi` is importable, and calls
  gi.require_version('Gtk', '3.0') to get it. mic_osd's layer-shell probe
  already pins this process's Gtk namespace to 4.0, so pyperclip's request
  raised "Namespace Gtk is already loaded with version 4.0" the first time
  the new clipboard fallback path ran. Force the xclip backend up front so
  pyperclip never touches `gi`.

Hotkey capture (evdev/UInput), paste-key injection (ydotool), and window
detection (xdotool/xprop fallback) were already compositor-agnostic and
needed no changes. Tested end-to-end on GNOME/X11 (Ubuntu 24.04).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y87A3sADRj7eixj6ubiXnV
@ninyawee
ninyawee requested a review from goodroot as a code owner July 13, 2026 10:44
@goodroot

Copy link
Copy Markdown
Owner

Whoa! Cool. I'll give this a review shortly.

@goodroot

Copy link
Copy Markdown
Owner

Thanks a lot for the PR 🎉 @ninyawee

OK: the core changes for x11 support look good.

But there are also some mic-osd visual/UX changes - were they included on purpose?

d4a6489

I don't mind them, but they should be observed/understood on their own merits.

Please split them out into a separate PR.

Once that is done, it won't take long to merge in the x11 changes.

@goodroot

Copy link
Copy Markdown
Owner

OK! Got this caught up @ninyawee please fork the OSD visualizer changes into another PR if you'd like.

This is great - very much appreciated.

@goodroot
goodroot merged commit cc0299c into goodroot:main Jul 19, 2026
2 checks passed
@goodroot

Copy link
Copy Markdown
Owner

Oh and @ninyawee PLEASE TEST! 🙏

@ninyawee

Copy link
Copy Markdown
Author

@goodroot hi
Sorry for late reply, ok next time I'll make a separate pr and also test first. 🙏

Thanks for your hardworking on this project. I'm using every day. 🥰

@goodroot

Copy link
Copy Markdown
Owner

ขอบคุณพี่ชายของฉัน

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants