Debugging kwin forceblur — SITREP 1

Bouteiller < A2N > Alan
6 min readAug 24, 2023


The SITREP series is a "blog like" article that I wrote to note and share some of my research, debugging or work. Take it like a vlog if you want.

I hope you find something interesting in it. Or, in the worst case scenario, I hope you have learned something reading it.

Today, I have reinstalled EOS on my new Tuxedo pc. After a reboot and some config I have setup kitty and the theme I wanted for it. In my config, I have setup the background to have 80% of transparency, and, with the aid of forceblur I blurred the background.

In theory.
With this new install this script doesn’t work.

Ok so, why ? Have I made a mistake ? After some test and a certain amount of reboot, I decided to check the github page of the project. And I found an issue referencing that the script doesn’t work since KDE update to 5.25.

Ok, but that was a long time ago, but the last commit (1f92ed5) on this project is old too : Feb 13th 2022.

So with that in mind, I decided to embark on another journey for debugging some KDE plugins.

First step : I checked the tutorial of the kwin script provided by KDE, for two main raisons :
- I have never really done a kwin script, so maybe some stuff may change compared to the development of a plasmoid for example
- I know that kde have made some update so I wanted to check the command needed for installing the plugin

There I found what I have searched for :
Install a kwin script :
kpackagetool5 — type=KWin/Script -i ~/Downloads/forceblur

If you want to enable it :
The key is the name of the script followed by "Enabled"
kwriteconfig5 — file kwinrc — group Plugins — key forceblurEnabled true

Next we can reload kwin :
qdbus org.kde.KWin /KWin reconfigure

The log is found on the journalctl :
- the last log in live : journalctl -f
- filtered : journalctl -f QT_CATEGORY=js QT_CATEGORY=kwin_scripting

So, after a clone of the repo, I started by updating the architecture of the project like the documentation recommended doing so.

Nothing funky here, I just move the main.qml file to a new folder called "code".
The new file organisation is pretty simple :
├── contents
│ ├── code
│ │ └── main.qml
│ ├── config
│ │ └── main.xml
│ └── ui
│ └── config.ui
└── metadata.json

The next step is to move the old metadata.desktop to his new format, metadata.json.
Here, again, nothing new, I just have to move the right key and value into the json :

the new metadata.json

And voilà, after opening the pr on esjeon repo, I started to check what the bug can be.

So, first, what is the behaviour of the problem ?

- Since I know that the script work well with kitty in the past I have added kitty on the target list.
- When kitty is already open and I turn off and on the script, the console is blurred. So, already created windows works fine when the script is reactivated via the kwin settings.
- When the script is active, and I pop a new kitty window, the window is not blurred.

Ok, if I check the output of the journalctl nothing weird appear, I just have the two logs created by esjeon on is code :

The kitty keyword is present, and the script is loaded.

So I decided to remove the two following possibilities for the bug :
- the script doesn’t load
- the parameter window doesn’t work

We need to check the code.

How works the code made by esjeon ?


  • first we have an Item identified has root, nothing new here
  • three read-only properties are defined to store the value of the params
  • a DataSource identified has shell is created for executing some command
  • a function onClientAdded handle the call to the datasource shell with the check of the class name of the window : if the targeted window have the same name as a value set in the parameters, let’s blur it
  • in this function, the id of the window is retrieved by the following code : var wid = “0x” + client.windowId.toString(16);
  • the command call for blurring the window is a xprop command
  • a function called onClientGeometryChanged allows updating the blur region if the user change the height or the width of a window
  • nothing particular in the function, the cmd called for the update is the same as the one in the onClientAdded function
  • a function called registerHintUpdater is present too, it’s called in place of the cmd if the user chose to blur the content of the window via the parameter
  • and finally the bootloader of this script (if I may) : the onCompleted component, this thing allows you to execute what you want when the script is activated. Inside we have, for example, the two logs that I have talk before. We retrieve, too, the call for blurring the already present windows and the signal that called the onClientAdded function when a user adds a window workspace.onClientAdded.connect.

What part of that may fail ?

Maybe the command ? Maybe the onClientAdded signal ? Maybe the id of the window is not understood ?

The fact that the already present kitty is blurred let me think that the command is ok, but I wanted to check that for sure.

For that, I just added a print with the generated command :

If I execute this command with the id of a non-blurred kitty window, the window is blurred.

For being sure everything is fine, I change the id (“0x” + client.windowId.toString(16)) by the one given by the client object (client.windowId), but the result is exactly the same.

I have taken the time to add two signals to the shell DataSource :

The second signal gives me the opportunity to check the stdout and the stderr of the command. But when I do that, nothing weird too…

So […] next I have created a "debug" function called by the "onClientAdded" signal, the purpose of the function is just to check if the signal is really triggered and the "client" really transferred by it.

By the way, the signal is still present on the documentation, so no update to do here.

And with no surprise, everything looks fine :

Ok I need a break […] and a coffee, I stop this SITREP here and give you any update of this situation on another one.

The code made so far is here :

See ya folk.