rvaiya / keyd

A key remapping daemon for linux.
MIT License
2.65k stars 157 forks source link

Feature request: support plasma wayland in keyd-application-mapper #399

Open dinkonin opened 1 year ago

dinkonin commented 1 year ago

Hello, first of all thanks for this amazing tool!

Is plasma wayland support on the roadmap of keyd-application-mapper. What are the showstopping issues if any?

I read somewhere that generally it's hard to get the Active Window Class/name in plasma wayland, but in my amateur testing it's fairy trivial to do so using kwin scripting.

dinkonin commented 1 year ago

As an example this a simple kwin script logging the window class and caption to the systemd journal.

workspace.clientActivated.connect(logMostRecent);
function logMostRecent(client) {
  if (client) {console.info("ActiveClass:", client.resourceClass, "ActiveCaption:", client.caption)}}

and this is how you load it using a bash script for testing:

tmp_js_file="/tmp/kwin_test.js"
echo 'workspace.clientActivated.connect(logMostRecent);function logMostRecent(client) {if (client) {console.info("ActiveClass:", client.resourceClass, "ActiveCaption:", client.caption)}}' > $tmp_js_file

num=$(dbus-send --print-reply --dest=org.kde.KWin \
    /Scripting org.kde.kwin.Scripting.loadScript \
    "string:$tmp_js_file" | awk 'END {print $2}' )

dbus-send --print-reply --dest=org.kde.KWin /$num org.kde.kwin.Script.run

then you can monitor it with journalctl _COMM=kwin_wayland -f -g "ActiveClass"

Sorry for not making a PR but my python (and coding in general) skills are shamefully lacking.

rvaiya commented 1 year ago

Thanks for putting in the initial leg work. It should be possible to turn this into a suitable keyd-application-mapper class with some additional effort. The hard part is exfiltrating the window data from KDE, which, like Gnome, appears to use a (poorly documented) embedded javascript engine with an even more spartan API.

Ideally there should be an init-system agnostic way to obtain the script output (to avoid scraping journalctl). I couldn't find any documented APIs which allow for file manipulation after a quick search, but something like that would probably be necessary. I did find some references to a mysterious callDBus function which might be used to generate a dbus signal, but I couldn't find any corresponding documentation. I will investigate further when I have some time. In the meantime feel free to submit a PR if you are able to hack an (init agnostic) solution together.

dinkonin commented 1 year ago

You were very correct about the poor documentation. I cobbled together an example dbus service and modified the kwin script service which I think should do the trick when implemented in keyd-application-mapper.

This the example dbus service

#!/usr/bin/env python
import dbus
import dbus.service
import dbus.mainloop.glib

from gi.repository import GLib
class keydDbus(dbus.service.Object):
    def __init__(self, conn=None, object_path=None, bus_name=None):
        dbus.service.Object.__init__(self, conn, object_path, bus_name)
    @dbus.service.method(dbus_interface="org.keyd", in_signature="ss", out_signature="s", sender_keyword="sender", connection_keyword="conn")
    def Run(self, winclass, wincaption, sender=None, conn=None):
       #HERE WE PROCESS THE ACTIVE WINDOW 
       print(winclass,wincaption)
       return "done"
if __name__ == "__main__":
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
    bus = dbus.SessionBus()
    name = dbus.service.BusName("org.keyd", bus)
    processwindow = keydDbus(bus, "/getinfo")
    mainloop = GLib.MainLoop()
    mainloop.run()

and this is the kwin script calling it on every window change:

workspace.clientActivated.connect(logMostRecent);
function logMostRecent(client) {
  if (client) { callDBus( 'org.keyd', '/getinfo', 'org.keyd', 'Run', client.resourceClass.toString(), client.caption);}
}
Ataraksia commented 1 year ago

So, uh, just out of curiosity, @rvaiya , have you actually attempted using keyd in Plasma Wayland? After reading all this, I went into it fully expecting I was going to have to have to make the necessary additions to the code myself in order to get it to work only to find out that, as it it turns out, everything already works flawlessly. Well I shouldn't necessarily go that far, everything that I've tested so far (which is a fair bit) has worked just the same in Plasma as it did in X. I'm completely new to the inner workings of input remapping like this, even more so with regards to how it works in Linux (although I am a software developer by trade and after spending a bit of time this afternoon digging into the code, I have a general idea of what's going on), but I'm guessing the reason it works is perhaps related to your usage of xmodmap? Per what the developer of input remapper wrote in this thread

* localized key names (kind of - they're actually custom configured)

This works for X11, gnome on wayland, plasma on wayland, but other DEs that run on wayland may not support it properly. Input-remapper has to rely on using `xmodmap -pke` to get that information, which is part of xorg. Right now this is not causing trouble.

But yeah, as I said, complete noob to this topic. Nevertheless, I thought you'd be happy to know that it was the case; I know I was certainly happy to discover I didn't need to implement it myself haha.

ibrahimkettaneh commented 5 months ago

I would like to boost this