Execute a command from a kwin script

I want to write a kwin script that executes a command when the currently active window is changed, but I can’t find a possibility to execute a command via the scripting API. Is this not possible?

The kwin script can emit a dbus signal, and you can have another piece of code that listens for that signal and fires your command.

For example: automation - How do I run a script on a dbus signal? - Ask Ubuntu

(I don’t know if there are other/better options for how to listen to the dbus. I will need to use something like this for one of my projects but I haven’t properly started out on it yet.)

That does not seem to work, because you can’t create a new d-bus endpoint with d-bus monitor as far as I understand it. I guess you could hijack some existing endpoint that does allow sending arbitrary strings, but this does not seem like a good idea.

Late response, since I finally got round to doing that project.

With this technique, you don’t need to hijack an existing endpoint, or “create a new endpoint” in dbus-monitor (i.e. dbus-monitor doesn’t need an XML definition of the endpoint, like the one you might use in some frameworks).

You can just choose your own bus service name (+ object path + interface name), make calls to that from your KWin script, and dbus-monitor will see those calls.

For example, I wanted to make a bus call sending out the resourceClass and caption of the newly activated window.

When I had this KWin script running…

const SERVICE_NAME = 'com.example.myproject';
const OBJECT_PATH = '/com/example/myproject';
const INTERFACE_NAME = 'com.example.myproject';

workspace.windowActivated.connect(function(client){
    if (client) {
        callDBus(
            SERVICE_NAME,
            OBJECT_PATH,
            INTERFACE_NAME,
            'SomeMethodName',
            client.resourceClass,
            client.caption
        );
    }
});

…I could see the calls by running this in a terminal…

dbus-monitor --session "interface='com.example.myproject'"

I didn’t need to define that service name, object path or interface name in any place other than the two pieces of code I’ve shown.

(As it happens, I was using dbus-monitor just for some smoke testing. The actual consumer of the DBus messages in my project is some Python code. But if you wanted to use dbus-monitor as your means of triggering a command when a DBus message arrives, you could do so using the technique shown on that Ask Ubuntu page linked above. That works as long as you can form your command based only on reading the output of dbus-monitor; if you need to do something more complicated, then you probably want to use a DBus binding library in your preferred programming language.)

2 Likes