tom-james-watson / Emote

Emoji Picker for Linux written in GTK3
https://snapcraft.io/emote
GNU General Public License v3.0
640 stars 36 forks source link

Pasting in Wayland redux #157

Open protist opened 2 months ago

protist commented 2 months ago

I know Wayland has been discussed here before, but I think there is a way to paste emoji.

Emote is already using wl-clipboard, specifically wl-copy to copy the emoji. Hence, it should be straightforward to use wl-paste from the same repository.

Having said that, I tried messing with Emote's code, but I couldn't get it to work. I tried variations on the following.

--- a/emote/picker.py   2024-05-17 20:40:02.000000000 +1000
+++ b/emote/picker.py   2024-06-19 22:28:28.977476352 +1000
@@ -648,9 +648,13 @@

         self.destroy()

+        time.sleep(0.15)
         if not config.is_wayland:
-            time.sleep(0.15)
             os.system("xdotool key ctrl+v")
+        else:
+            os.system("wl-paste")

     def add_emoji_to_recent(self, emoji):
         user_data.update_recent_emojis(emoji)

but nothing ever pasted. FWIW I don't entirely understand how the code works here. Even in X11, isn't the "ctrl+v" operating while Emote is still in the foreground? I tried increasing the sleep, but this just delays how long the Emote window stays open.

Another option could be using ydotool, e.g. pasting with

+            os.system("ydotool key 29:1 47:1 47:0 29:0")

or even better, bypassing the clipboard and directly

+            os.system("ydotool type " + emoji)

However, neither of these worked for me either.

nightgolfer commented 3 weeks ago

Hope a solution is found, really miss Emote working properly now that I've gone to Fedora 40 and Wayland is default 😓

theamazing0 commented 3 weeks ago

Running "wl-paste" in the terminal seems to just be printing the current clipboard content in the terminal, not pasting it at the current cursor location.

protist commented 3 weeks ago

@theamazing0 I'm not sure what you mean. If you are typing wl-paste in the terminal, then isn't the terminal the "current cursor location"? Either way, this is essentially what the emote code already did with xdotool key ctrl+v.

(If you want to test it in another location, try something like sleep 1 ; wl-paste in the terminal, then quickly change the cursor location elsewhere.)

theamazing0 commented 3 weeks ago

Yes, that's what I did. I ran the command to sleep and then wl-paste, and changed my cursor location to somewhere else in Firefox.

I just read further, and saw you also tried ydotool, did these commands work if you ran them directly in the terminal?

ZimbiX commented 3 weeks ago

Running "wl-paste" in the terminal seems to just be printing the current clipboard content in the terminal, not pasting it at the current cursor location.

I was going to comment the same thing yesterday! (I tried it by prefixing sleep, obviously). In the wl-paste usage shown in the wl-clipboard readme, the paste output is being piped to other commands, so it looks like simply outputting the clipboard to stdout is its intended functionality.

Edit: So wl-paste looks more equivalent to MacOS's pbpaste

ZimbiX commented 3 weeks ago

For pasting to support terminal as well, I'm trying using Ctrl+Shift+V. That shortcut works in Kitty, Chrome, and Firefox; though not Dolphin, Nautilus, or Gnome Settings (but that's acceptable for my usage).

ydotool key 29:1 42:1 47:1 47:0 42:0 29:0

I noticed in /usr/include/linux/input-event-codes.h there is a code for KEY_PASTE, but it doesn't seem to do anything.

ZimbiX commented 3 weeks ago

PR submitted

theamazing0 commented 3 weeks ago

Shouldn't the Wayland behavior be consistent with X? If it should be Ctl+v or Ctrl+Shift+v should be another issue, as the current X behavior is to use Ctrl+v, and the Wayland behavior should do the same thing for now.

protist commented 3 weeks ago

Sorry for double-posting. Much of my original comment is redundant to due more research. I've deleted that comment and added a new one here.

Apologies @theamazing0 and @ZimbiX, you are totally correct. wl-paste does indeed send to std out. The command I use in general is

ydotool type -d0 "$(wl-paste)"

I think this strategy is probably slightly neater than using ydotool to send a literal ctrl-v or ctrl-shift-v, because it's more direct. It doesn't depend on specific keyboard shortcuts of the program (as stated above by @ZimbiX ), and also it has less chance of failing if the user has another modifier held down. Even better is bypassing the clipboard as per my OP, i.e. using ydotool to directly type the emoji. This has even less chance of failing, and also doesn't pollute the clipboard.

However, ydotool cannot type emoji, so that won't be an option. OTOH apparently wtype can type emoji, but this program doesn't work on KDE nor Gnome. Other alternatives are dotool and kdotool. I can have a look at these later.

@ZimbiX Your trick of backgrounding the command with & works well for me. I could get emote working with a similar strategy. FWIW ctrl-shift-v doesn't work in the programs I use, so I modified it to ctrl-v instead. i.e.

os.system('bash -c "sleep 1; ydotool key 29:1 47:1 47:0 29:0" &')

EDIT: after more research, kdotool can't type characters, and dotool doesn't seem to work for emoji, giving me the error dotool: WARNING: impossible character for layout: 😰. So it looks like the only remaining solution is using ydotool to type ctrl-v (or ctrl-shift-v, which doesn't work for many of my programs).

tom-james-watson commented 3 weeks ago

Hey all - thanks for thinking about this stuff - it would be awesome if we could get this working!

See https://github.com/tom-james-watson/Emote/pull/161#issuecomment-2301348415 - the difficult part is packaging the app so that this works out of the box with flatpak and/or snap, not just the invocation of the utils themselves.

protist commented 3 weeks ago

Thanks @tom-james-watson . I don't know a lot about it, but I suspect that the way Wayland works is to require a root daemon for security reasons. I think some of the other programs (e.g. dotool) also have a root component. Hence I suspect there's no way for a non-privileged user-installed version to paste in Wayland.

If that is the case, could we just check for a running instance of ydotool, then if that exists use the ydotool command? Or maybe just run ydotool and let if fail if it fails. Otherwise the alternative is patching it in every distro, which doesn't seem optimal either.

tom-james-watson commented 3 weeks ago

I think it's likely solvable in snap/flatpak directly, by someone with enough knowledge.

I don't really want to ship features that require the user to manually install other packages and set up systemd services and things like that.

protist commented 3 weeks ago

Fair enough. I don't user snap/flatpack, but I just realised that it's possible to install them with root privileges, so you are probably correct that there might be a solution.

tom-james-watson commented 3 weeks ago

Snap and Flatpak are the only officially supported installation methods, so any code changes need to work for them specifically.