KWin Scripting from 5.x to 6.x -- Compatible?

Afaik there is not any metadata needed, and needing no extra metadata is the point of doing the separation by category in the store. You upload the version that will work for v5 to the v5 category, and the version that will work for v6 to the v6 category.

Categories is fine, but what if the KWin script can actually be compatible with both, as suggested by @jinliu earlier? Will the metadata have to say that the script is only for 5 or 6 somehow?

The suggestion by jinliu just helps you generate the two different versions of the code from one common template, the resulting scripts will still be v5 or v6 only.

I’m not aware of any technical reason that there would actually need to be two separate (and different) KWin scripts for 5/6, rather than just two separate uploads of the same identical script.

Because of many breaking changes to the scripting API, such as the renaming of “client” to “window” in many commands which would affect just about any script.

In short, I think it is not worth trying to engineer some automatic compatibility magic, you’ll need two different versions of the script for 5 and 6 anyway, so I’d say just treat them that way, as two separate versions.

1 Like

you’ll need two different versions of the script for 5 and 6 anyway,

To clarify, by this I mean that 1. you’ll most likely need two different versions of the code content because of the yet to be documented API changes, and 2. you’ll need two copies of the package, no matter how similar, to upload them to the different store categories so people will find them where they’re looking for, if you want to distribute them via the official way. You will not need any checks or special metadata, from what I understood.

1 Like

How you then do the source code management, if you want to work with branches, separate repositories or folders, if you want to employ code templates or do the parellisation by hand, is a question of personal preference and not of technical limitations as far as the API is concerned.

Afaik there is not any metadata needed

By “metadata” I was talking about the stuff that already has to be included with the KWin script, like metadata.json. So I gather there isn’t something in there that will have to specify whether the script is for KDE 5 or 6? With GNOME extensions they have to specify the compatible shell version(s), so the older extension would have [“43”, “44”] and the newer one would have [“45”] in the shell versions list. Seems like a rational thing to have if KWin scripts are going to have a similar compatibility split.

The suggestion by jinliu just helps you generate the two different versions of the code from one common template, the resulting scripts will still be v5 or v6 only.

That was a separate, but interesting, suggestion. Earlier there was just an if/else, and in my messing around I tried setting up aliases that would just abstract away the API naming differences after testing whether the KDE 6 versions were present. Should work in theory, but I’ll take your word for there being enough breaking changes to make it probably not worthwhile.

How you then do the source code management, if you want to work with branches, separate repositories or folders, if you want to employ code templates or do the parellisation by hand, is a question of personal preference and not of technical limitations as far as the API is concerned.

True, but which approach makes more sense and will be easier to maintain depends on exactly what the situation is between 5 and 6. I’m just trying to get a handle on that.

Sounds like separate scripts in different subfolders would at the very least be a good start.

Thanks for the clarifications.

So I gather there isn’t something in there that will have to specify whether the script is for KDE 5 or 6? With GNOME extensions they have to specify the compatible shell version(s), so the older extension would have [“43”, “44”] and the newer one would have [“45”] in the shell versions list. Seems like a rational thing to have if KWin scripts are going to have a similar compatibility split.

Yes, that would make sense if we had a compatibility check in place, which I agree would be a good thing too, but afaik this is currently not the case. @mart would know.

True, but which approach makes more sense and will be easier to maintain depends on exactly what the situation is between 5 and 6. I’m just trying to get a handle on that.

Sure. It also depends on whether you want to keep actively supporting Plasma 5 in parallel or just do the porting once and then only maintain the Plasma 6 version going forward.

I expect that a mixture of some find-and-replace and some manual adjustments will get you pretty far for a one time porting.

1 Like

in my messing around I tried setting up aliases that would just abstract away the API naming differences after testing whether the KDE 6 versions were present

That might work for dynamically generating the appropriate version in a custom install script. It won’t help though if you want to distribute your extensions on the store, because at the point of you uploading the package there, the code already needs to be the final version against the respective API, and it is not possible to provide custom install scripts for KWin scripts there.

Unfortunately there are some long-term distros where they take forever to move on to a more recent version of major desktop environments, including Plasma. The RHEL types are still on GNOME 40, that’s about 3 years old now. CentOS 7 will finally be EoL in 2024 I think, and if you put KDE on that it’s KDE 4.

I’m kind of expecting it to be reasonable to keep supporting KDE 5 for about 3 years after the KDE 6 stable release. Maybe longer. Only time will tell how long the LTS distros want to remain on KDE 5 rather than moving onto some LTS version of KDE 6.

By “actively supporting” I meant whether you want to release new changes compatible with Plasma 5; if that’s something you want to keep doing for several years, then indeed some automated mechanism for you to manage the two codebases is probably worth thinking about.
If on the other hand you just want to keep the last state of the P5 compatible version accessible and move active development to P6 only, then it’s probably best not to overthink things.

2 Likes

If the abstracting and setting aliases was going to work, there would only need to be a single (installer) script that wouldn’t care about the KDE version. Because there would only be a single (KWin) script. That would be the attraction. It wasn’t a templating thing. I was literally making aliases and setting them to the correct API calls for the version, and then using the aliases instead of the original API calls.

But like I said, I didn’t see that version of things actually working. I had made a lot of changes and didn’t get to the point of trying to do any debugging to see why it didn’t seem to be working. Probably won’t try that again. So it’s a moot point, but just interesting to think about making it work that way.

Oh, I think understand now. That’s an interesting idea, and thanks for sharing the experience.

1 Like

Adding version checks is certainly worth doing I guess. As for adding aliases, I’m not sure about that. We didn’t just do s/client/window/g, but also made other changes like changing the type of some properties or replacing some properties with absolutely other ones.

2 Likes

@nclarius @zzag

It seemed a shame to throw away the version of the KWin script I did with the abstractions, so I figured out what the problem was and made it work.

This attribute of a window object in KDE 5:

window.x11DesktopIds

Needed to be replaced with this:

window.desktops

This appears to do the same thing, providing the list of virtual desktops where the app window appears. With this and the other abstractions, the KWin script works the same way in KDE 5 and 6, in my testing, without any changes or templating operations needed. But I would appreciate a confirmation that this is the correct replacement for that specific element.

Other than that, this is all I had to do:

const isKDE6 = typeof workspace.windowList === 'function';

let activeWindow;
let windowList;
let connectWindowActivated;
let setActiveWindow;
let isAppOnCurrentDesktop;

// Set up aliases to abstract away the API differences between KDE 5 and KDE 6
if (isKDE6) {
    activeWindow                = () => workspace.activeWindow;
    windowList                  = () => workspace.windowList();
    connectWindowActivated      = (handler) => workspace.windowActivated.connect(handler);
    setActiveWindow             = (window) => { workspace.activeWindow = window; };
    isAppOnCurrentDesktop       = isAppOnCurrentDesktopKDE6
} else {
    activeWindow                = () => workspace.activeClient;
    windowList                  = () => workspace.clientList();
    connectWindowActivated      = (handler) => workspace.clientActivated.connect(handler);
    setActiveWindow             = (window) => { workspace.activeClient = window; };
    isAppOnCurrentDesktop       = isAppOnCurrentDesktopKDE5
}

I present this only as a proof-of-concept that could be worth a look for a lot of simpler KWin scripts, but may not be worth the effort on KWin scripts where the differences are more significant. Although, technically, API abstractions like this are quite common in programming, and could probably be done even with elements that now return different data types or structures. If the differences can be normalized without too much trouble. All the code cares about are the end results, right?

The journal command to monitor KWin script debugging output worked with no difficulty on Neon Unstable (KDE 6) but I haven’t had any luck seeing that output in Fedora 39 KDE spin (KDE 5) even after putting the Qt logging environment variable in ~/.bash_profile. So I really don’t know what’s going on there. It was Wayland in both cases.

I will note here that I ran into trouble with a project unrelated to this KWin script, on some Arch-based and RHEL-type distros (like AlmaLinux), with a syntax like this:

journalctl --user -u my-user-unit

or…

journalctl --user --unit=my-user-unit

I had to replace that with a combined option syntax like this:

journalctl --user-unit=my-user-unit

… to get any output for user services on those distros. (This is not related to the problem with the debugging output on Fedora 39.)

Anyway, I was able to make a version-agnostic KWin script and an installer script that pays attention to the KDE version environment variable and uses the corresponding 5/6 utilities to do the install/uninstall. Seems to work fine.

4 Likes

This looks very cool! I hope I’ll get around to testing it some time soon.

1 Like

Hi, now that plasma 6 is released and shipped in distros is there a guide for porting kwin scripts? I used some scripts before but now that I upgraded to plasma 6 they don’t even show up in the list anymore and I would like to get them back.

3 Likes

Similarly to @RedBearAK, I also introduced a backwards-compatibility layer in my KWin script(s). I did it slightly differently and for other functions. Maybe it helps someone.

2 Likes