How to apply KDE Plasma KWin script change without restarting KWin?

I originally needed this for changes to take effect after upgrading Krohnkite (How to restart Krohnkite after upgrading for changes to take effect? · anametologin/krohnkite · Discussion #90 · GitHub) but I’m not the only one interested in such a feature – linux - How to apply KDE Plasma KWin script change without restarting KWin? - Stack Overflow

I see this has been asked in the past – How to properly reload a kwin script where people shared some workarounds…

Could we have kwin.scripting tag here?

I created a kwin-scripting tag. I hope that works for you.

1 Like

Thanks!
Now, thinking about this there’s broader scope of plasma scripting which kwin scripting is a subset of. I’m not sure if there should be both kwin-scripting and plasma-scripting or only the latter one would be enough?

Does not killing plasmashell and relaunching always shows all the Plasma changes?
killall plasmashell and plasmashell &

Hmm, probably but it seems like overkill, no?
Btw, running simply plasmashell & does not disconnect process from tty so the output is seen in the console… I guess restarting plasma should make use of systemd units nowadays?

I usually use this command when I need to restart the Plasma Shell

plasmashell --replace

I run it from KRunner, so I don’t mind detaching the command from a CLI

2 Likes

I enter ‘prestart’ command in krunner which executes script systemctl --user restart plasma-plasmashell.service which is bound to a secret keyboard shortcut Yes, well it’s secret… don’t be nosy!

1 Like

I did a quick test with the following script (installed with kpackagetool6 -t KWin/Script -i .):

function mytest() {
    print("x");
}

registerShortcut("MyTest", "Test", "Meta+R", mytest);

and after making a change to the installed code at /home/me/.local/share/kwin/scripts/testscript/contents/code/main.js and restarting plasmashell the change does not make effect so restarting plasmashell does not reload KWin scripts.

1 Like

Intelligence fail here - when I messed with kwin tiling scripts I would always log out and log in again… so yes, that’s right.

So how about :

  • unloading the script?
    qdbus org.kde.KWin /Scripting unloadScript "YourScriptName"

  • Load the script again**:
    qdbus org.kde.KWin /Scripting loadScript "YourScriptName"

Are these methods documented somewhere?

$ qdbus-qt6 org.kde.KWin /Scripting unloadScript "testscript"
true
$ qdbus-qt6 org.kde.KWin /Scripting loadScript "testscript"
2

After this the script stopped working. It looks like there’s some problem with loadScript?

KWin’s internal D-Bus API, not prominently documented in official user-facing KDE documentation.

qdbus is mostly a workaround for developers who want to reload scripts without restarting KWin or logging out… considered ‘internal’ and used by the KWin Script KCM module in settings.

https://develop.kde.org/docs/plasma/kwin/api/https://develop.kde.org/docs/plasma/kwin/tutorials/

D-Bus instrospection - inspect directly using qdbus or d-feet…

qdbus org.kde.KWin /Scripting

This will list methods exposed by the /Scripting D-Bus object, including ‘loadscript’ and ‘unloadscript’.

They are defined in KWin - such as src/scripting/scripting.cpp · master · Plasma / KWin · GitLab

I remember I used to employ ’ kwin_x11 --replace or kwin_wayland --replace - basically restarting KWin entirely if scripts misbehave (previously a top feature of Krohnkite :wink: )

1 Like

This works:

$ qdbus-qt6 org.kde.KWin /Scripting unloadScript "testscript"
$ qdbus-qt6 org.kde.KWin /Scripting start

so the same @Laurent_Constantin came out with at How to properly reload a kwin script - #2 by Laurent_Constantin

3 Likes

Hello from the future! I can’t get Plasma/KWin to reload my KWin script unless I restart KWin itself. The only way to get KWin to read/run any code updates is to restart it via kwin_wayland --replace &. This is horrible as it then closes all my applications, so productivity slows to near-zero.

This is my justfile, which is similar to a Makefile:

project_name := "awesome"

# Install the KWin script (update if exists, else fresh install)
install:
	kpackagetool6 -t KWin/Script -s {{project_name}} \
		&& kpackagetool6 -t KWin/Script -u . \
		|| kpackagetool6 -t KWin/Script -i .
	qdbus-qt6 org.kde.KWin /Scripting start

# Uninstall the KWin script
uninstall:
    -kpackagetool6 -t KWin/Script -r {{project_name}}

# Unloads the script from KWin
unload:
	dbus-send --session --print-reply=literal --dest="org.kde.KWin" "/Scripting" "org.kde.kwin.Scripting.unloadScript" string:"{{project_name}}"
	@while dbus-send --session --print-reply --dest=org.kde.KWin /Scripting \
		org.kde.kwin.Scripting.isScriptLoaded string:"{{project_name}}" 2>/dev/null \
		| grep -q "boolean true"; do sleep 0.05; done

# Reloads the script without restarting KWin
reload: unload install

I have no idea what I’m doing wrong. I’ve been up and down the documentation and KDE forums. Solutions seem to work for other people, but not me.

Any other ideas?

Try unloading the just-reinstalled[1] script before starting it (rather than unloading the “old” script before the kpackagetool6 call that re/installs it).

So, before you do this…

qdbus-qt6 org.kde.KWin /Scripting start

…do this:

qdbus-qt6 org.kde.KWin /Scripting unloadScript "{{ project_name }}"

That’s what I do in my justfile, based on the “Solution” in this thread, and it works for me.


  1. No pun intended when I wrote this ↩︎

It’s just not working for me at all. I’ve created a minimal example that demos the exact problem and I’ve put it on GitHub, but the forum won’t allow me to post a link. If you search for the project kwin-helloworld on GitHub, I believe it’s the only one.

I’m baffled. Totally baffled.

Sorry for back to back replies, but I can’t edit my previous comment. I’ve concluded that this is a bug in the way KWin handles loading/unloading of QML scripts, or as KWin calls it declarativescript. The underlying QML engine has built in caching based on filename and requires a call to https://doc.qt.io/qt-6/qqmlengine.html#clearComponentCache in order to invalidate the cache, but it seems like this is never being called by KWin.

I’ve filed a bug here: https://bugs.kde.org/show_bug.cgi?id=514131

Ah, fair enough, I’ve only used Javascript and not QML.