Feat/add remote desktop direct mode on wayland#689
Feat/add remote desktop direct mode on wayland#689petit-aigle wants to merge 4 commits intocjpais:mainfrom
Conversation
e287ddf to
eb11166
Compare
|
I think we should try to unify the UI for permissions giving into the onboarding similar to how it's done on Mac. Otherwise I'm excited about this PR |
7b29955 to
326aacd
Compare
|
@cjpais Thanks for the feedback, glad to hear you’re excited about the PR 🙂 I’m not entirely sure what you’re referring to regarding the macOS onboarding flow. I don’t currently have access to a Mac, so I haven’t been able to observe or test how permissions are presented there in this project. Otherwise, since opening the merge request, I’ve fixed two issues: first, a wording/translation issue where “GNOME Wayland” was used instead of simply “Wayland”, even though Wayland can be used outside of GNOME. Second, I fixed the handling of accented characters, which were previously not supported and are now correctly handled. Despite this fix, two issues remain:
I don’t yet have a reliable fix that doesn’t turn into a mess of edge-case handling. |
|
@petit-aigle you can look at the UI code for this, even if you are unfamiliar. It should be relatively trivial to have it appear also for linux. |
|
FYI I pulled this down to test (couldn't get anything else to work in Ubuntu + Gnome + Wayland) and this worked perfectly! I also agree that this is the "right way" of doing things. Great work @petit-aigle 🚀 |
|
@bkanuka thanks for the confirmation, I'll probably be taking a look today and trying to merge |
delthas
left a comment
There was a problem hiding this comment.
The README should probably also be updated? Namely https://github.com/cjpais/Handy?tab=readme-ov-file#major-issues-help-wanted and https://github.com/cjpais/Handy?tab=readme-ov-file#linux-notes
|
Tested on my end, works fine on GNOME, except that many/most characters are always dropped (running with a French keyboard layout and French words): all upper case (Initially I thought the first letter of all my inputs was dropped, but that was just because the first letter was always capital, and upper case letters are dropped on my system.) Possibly more but that's what I was able to find. |
|
Interesting! I didn't have that experience at all. Capitals, numbers, punctuation, all came through - but I only speak English @delthas could you test in English? Setting gnome to a English layout? It would be interesting to know if that's the reason things are dropped for you. |
|
@delthas @bkanuka
|
|
Okay, I've fixed the problem normally. The initial problem was that some accented characters were arriving “split”: the letter on one side and the accent on the other (e.g., “é” sent as U+0065 for “e” then U+0301 for the acute accent). Sent separately, the accent was mispositioned or lost. I therefore glued these pieces back together before sending, so each accented character is typed in a single shot. That introduced another issue: if the active keyboard language doesn’t include a character (e.g., a layout without accents), pressing that character is ignored. To work around this, I now use the Ctrl+Shift+U method (example: Ctrl+Shift+U, then 00E9, then Enter → é) followed by the character’s Unicode code, then validation. This types the symbol directly and works regardless of the chosen keyboard language. I think this is the best solution currently available for managing different keyboard configurations. @delthas I wasn’t able to reproduce the issue with numbers or with uppercase letters. I am also on GNOME with a French keyboard. Could you test the latest solution and let me know whether the other issues have already been fixed on your side, and whether the problems with numbers and uppercase letters still persist ? Thank you. |
2c08495 to
e7048cd
Compare
e7048cd to
88bf6bf
Compare
88bf6bf to
2c44625
Compare
Before Submitting This PR
Please confirm you have done the following:
If this is a feature or change that was previously closed/rejected:
Human Written Description
This PR introduces a Wayland-native keyboard injection path implemented on top of the GNOME Remote Desktop portal.
It adds a fully portal-backed flow for direct typing, including explicit user authorization, permission lifecycle management, and compositor-mediated input injection.
The objective is to enable direct text injection on Wayland using the mechanisms explicitly designed for it, while keeping the interaction constrained to a well-defined, user-approved security boundary.
Today, common Linux workarounds rely on installing tools such as
ydotool, adding the user to theinputgroup, and deploying permissive udev rules that grant write access to/dev/uinput. This setup enables global input injection for any process owned by the user, permanently widening the local attack surface and bypassing Wayland’s isolation guarantees.By contrast, the portal-based approach keeps input injection scoped, revocable, and mediated by the compositor itself. The trust boundary remains explicit and auditable, aligning with Wayland’s original security goals rather than working against them (see discussion: #522 (comment)).
Related Issues / Discussions
Fixes #
Discussion: #522 (comment)
Community Feedback
No dedicated feedback thread yet.
This change is intentionally scoped to a specific security and architectural axis; broader feedback can be gathered after initial review if needed.
Information about previous fixes
The initial problem was that some accented characters were arriving “split”: the letter on one side and the accent on the other (e.g., “é” sent as U+0065 for “e” then U+0301 for the acute accent). Sent separately, the accent was mispositioned or lost. I therefore glued these pieces back together before sending, so each accented character is typed in a single shot.
That introduced another issue: if the active keyboard language doesn’t include a character (e.g., a layout without accents), pressing that character is ignored.
To work around this, I now use the Ctrl+Shift+U method followed by the character’s Unicode code, then validation. This types the symbol directly and works regardless of the chosen keyboard language. I think this is the best solution currently available for managing different keyboard configurations.
Testing
Manual tests only
Authorization, Token & UI Consistency
Useful commands (Flatpak permission store – Remote Desktop)
Some of them can remove all Remote Desktop authorizations, not just the ones created by Handy.
Always inspect the current state before running destructive commands, and only proceed if you are sure no other Remote Desktop permissions are in use.
flatpak permissions remote-desktopLists all entries stored in the Flatpak permission table for the Remote Desktop portal.
flatpak permission-remove remote-desktop <OBJECT_ID>Removes the Remote Desktop portal permission for a single specific object/application ID.
This is the recommended and safe way to revoke one authorization without affecting others.
flatpak permissions remote-desktop | awk '{print $2, ($3=="-"?"":$3)}' | xargs -n2 sh -c 'flatpak permission-remove remote-desktop "$0"'Iterates over the Flatpak permission table and removes multiple entries via
flatpak permission-remove.❗Highly destructive ❗: this can wipe all Remote Desktop permissions at once.
Flatpak portal permissions rely on a stable application identifier derived from desktop integration (i.e. a
.desktopentry).In an installed build, this identifier exists and allows Flatpak Permissions to associate Remote Desktop authorizations with the application.
In a development context, this desktop integration does not exist, so no stable application ID can be resolved and the permission entry may be empty.
This is expected behavior of the Flatpak permission system in dev environments, not a bug in the implementation.
Platform Coverage
Screenshots / Videos
Screenshots showing:
Permission request UI and live authorization state

Same source, video format -> handy_wayland_remote_desktop_permission_ui_video
Active typing session indicator (GNOME screen-sharing icon during injection)
Note: The GNOME screen-sharing indicator appears during injection and may linger briefly after completion. This is expected portal behavior and may warrant a short user-facing note in settings.
AI Assistance
If AI was used:
ed and to accelerate development. Codex was used in particular to bootstrap and navigate Rust-specific aspects, as I am an experienced Python developer but not a Rust specialist. AI was also used to help generate and translate the newly introduced i18n strings across all supported languages. Each portion of source code generated by AI was analyzed, validated, maîtrisée, challenged, and modified where necessary to ensure a high level of code quality. All architectural and technical decisions were made by me, and I remain fully responsible for the final design, implementation choices, and code.