Enabling Others to do Awesome

Recently Aaron wrote a blog series for the introduction of Spark, I want to cite a central saying of one post:

I want the things which I help make to become opportunities for others in their turn to participate with their own voice, their own movement and their own passion.

If I reflect my own motivation for my work on KWin and especially the areas of work I decided to work on in the 4.9 cycle I see quite some parallels to the paragraph cited above. But personally I would phrase it slightly different:

I want to help others to do awesome.

This describes perfectly what I am currently working on. I no longer want to write fancy effects – in fact I stopped adding effects quite some time ago. I don’t want to extend KWin to be the window manager which incorporates all other window manager concepts no matter how useful they are – we stopped doing that as well.

But still I want that our users get the window manager they want. Whether it is fancy effects or a tiling window manager or new concepts for virtual desktops, KWin should be the base for it.

At the heart of all these efforts we have the scripting bindings. While we already had bindings since 4.6 they never really got used – this will change :-) But JavaScript bindings is just one part of the game, the other part is declarative, that is QML, bindings.

In 4.8 we already experimented with QML for the window switcher layouts to test whether QML fits our needs and I am very happy so far with it. But 4.8 does not yet include the possibility to really write own layouts. While it is possible to do so, there is no way to configure a custom one or even distribute this.

For 4.9 the installation of the window switcher has been adjusted to use the Plasma Package structure which makes it possible to install window switcher through the plasmapkg tool. But this is only part of it: plasmapkg has been extended to support any kind of scriptable KWin content, be it window switchers, KWin scripts or KWin effects written in JavaScript (decoration to be added soon).

For this KWin scripts follow also the Plasma Package structure which is quite awesome as it finally allows to dynamically enable/disable scripts through our KCM:

This dialog wants to tell me: “I want Get Hot New Stuff integration” to directly download new scripts from the Internet. And sure it does need that and this will be added for the 4.9 release.

The screenshot shows two scripts I’m currently working on – both will be shipped with KWin in 4.9. Videowall is a script which scales fullscreen video players over all attached screens to generate a video wall. This is the first script which actually replaces functionality from KWin core. KWin had the functionality to disable multiscreen support for fullscreen windows and that really cluttered both code and UI. And it just did not make any sense. There are just no valid usecases to have in general fullscreen windows span all screens, except for video walls. And that’s what we have here: a small KWin script to make an obsoleted functionality sane. We improved KWin for everyone by removing an difficult and confusing control module without taking away the functionality for expert users.

But even more interesting than the video wall is the other script. This is not a JavaScript based KWin script, but a declarative QML script. It will replace the existing C++ based implementation of the desktop change OSD without any functionality loss. Which means less code and much more readable code :-)

And what’s really awesome: JavaScript and QML have the same bindings, the API is exactly the same. So going from QML to JavaScript and vice versa is extremely simple. But that’s not all with QML based KWin scripts you can include live window thumbnails. So this is a technology to allow you to do awesome new switchers like Present Windows or Desktop Grid.

As you notice I’m currently dogfooding the bindings to myself. This helps me to see what is needed, what can be improved and to ensure that the bindings will work for any given usecase we can imagine. My wish is to see for example the complete window tiling support in KWin to be rewritten as a KWin script. This should be possible and would proof that you can use scripting to get a completely different window management.

So if you want to make awesome things with your window manager, now is the time to get started. Don’t hesitate to contact me and demand further bindings if anything is missing.

Disclaimer: QML support has not yet been merged into master.

KWin Effects written in JavaScript

Today I cannot make such a nice announcement as Aaron yesterday, but I can at least try announce something I personally consider as awesome.

This weekend I tried to make it possible to write KWin effects in JavaScript. After about two hours of work the effect loader was adjusted to load a Qt script instead of the library written in C++. This is a quite important step for the future of effects in KWin. It finally makes it possible to share effects via Get Hot New Stuff, so that our users can download new effects directly from the control module.

For packaging effects we use the well established Plasma Package structure, so that our script developers only need to know this one common way. The API itself will share as much as possible with the KWin scripting API – of course with adjustments for effects. For animating the API is based on the AnimationEffect introduced in 4.8.

From a performance point of view using JavaScript does not change anything. Our effect system has two phases: one to react on changes in the window manager (e.g. a window got activated) and one to perform the rendering. The scripting API only interacts with the window manager, so all the rendering is still good old C++ code – a similar approach to QML.

Now I guess you want to know what you can do with it. So here I present for example a Fade like effect written in JavaScript (for comparison: C++ version is > 200 SLOC):

var duration = 250;
effects.windowAdded.connect(function(w) {
    effect.animate(w, Effect.Opacity, duration, 1.0);
});
effects.windowClosed.connect(function(w) {
    effect.animate(w, Effect.Opacity, duration, 0.0, 1.0);
});

For us KWin core developers the scripted effects will be an important step as well. For quite some time we have been unhappy with the fact that there are too many effects which become difficult to maintain – especially if we have to adjust the API. With effects written in JavaScript this becomes much simpler. As we do not have to keep the ABI (API compatibility is enough) stable we can move effects written in JavaScript out of the source tree and make them available for download.

At the moment the JavaScript API is just at the beginning. But I expect it to evolve over the course of the current release cycle. For me the scripts are rather important as it also provides us an easy way to have device specific adjustments.

As I wrote currently the scripts do not operate during the rendering. Because of that we don’t have bindings for WebGL. This would at the moment not make any sense. Nevertheless it might be that we allow to upload custom shaders, but I won’t pursue such a task in the 4.9 cycle.

Create Temporary Desktops For Applications

There are applications which are more or less a mess for a window manager. For example The GIMP opens quite a lot of windows and you want to have all of those windows visible. In general you don’t want to have any other window on the same desktop

The solution to that is to move GIMP on it’s own desktop. But how? We can use static window rules to get this working, but what if there are already windows on that desktop? The perfect solution to that would be to have a desktop which gets created when you open GIMP and gets removed again when GIMP closes.

This was so far not yet possible without manual interaction. But with todays additions to KWin scripting this became possible. Here I present a KWin script which does exactly that:

workspace.clientAdded.connect(function(client) {
  if (client.resourceClass == "gimp-2.6" && client.windowRole == "gimp-image-window") {
    // create a new workspace for the Gimp image window (kind of the main window)
    // switch to the new desktop and send the gimp window to it
    workspace.desktops = workspace.desktops+1;
    workspace.currentDesktop = workspace.desktops;
    client.desktop = workspace.currentDesktop;
  } else if (client.resourceClass == "gimp-2.6") {
    // send all other gimp windows to the current desktop
    client.desktop = workspace.currentDesktop;
  }
});

workspace.clientRemoved.connect(function(client) {
  if (client.resourceClass == "gimp-2.6" && client.windowRole == "gimp-image-window") {
    // when closing the gimp window let's remove the last desktop
    workspace.desktops = workspace.desktops-1;
  }
});

I should really start to publish the quite useful example scripts I write to test the scripting functionality on places like kde-apps :-) The API for 4.9 is documented on Techbase

What’s new in KWin Scripting?

First of all a happy and successful 2012 to everyone. Let’s work together to make this year a great success for KDE!

One of the big topics in 2012 for my development efforts in KWin will be JavaScript bindings and QML. This is a technology which will allow our users to build their own custom window manager giving even greater power to our static window rules as before. It will also reduce our maintenance need when major parts of our UI can be transitioned to either QML or JavaScript.

The work on this area has already started and the first code set has been merged into master (aka 4.9). The old scripting API had manually crafted bindings for around 30 properties for windows. Now the API is generated and everything that is available for effects is also exported to JavaScript, which means more than 60 properties, more properties than before are writable and many more signals are available. Interestingly I could drop several hundreds lines of code by exporting more properties and the code becomes cleaner and better documented. These are changes I really like :-)

The API documentation of KWin scripting is now auto-generated through Doxygen and already imported to techbase together with detailed Update Notes on what changed. If you run master and use KWin scripting be aware that you have to adjust the script. Exactly the same API will be available in QML and also the Effects API is very close – given that the property names are inspired by the Effects API.

One of my favorite changes is that our Plasma Desktop Console is now able to execute KWin Scripts:
Plasma Desktop Console executing a KWin script

To open just use KRunner and type the new keyword “wm console” or start the desktop console and switch using the toolbar button.

This is a very important change for me during development as I can easily test whether my scripts are correct and most important my implementation. But also for users it means that scripts can be tried at runtime and don’t require a KWin restart any more. So adjusting the runtime behavior becomes possible.

So what’s next? I am currently with the progress quite satisfied with the work done so far on scripting and will now concentrate on two other areas first: getting my unmerged kickoff-qml and screenlocker branch into master. Both require still a little bit of work. After that scripting and QML get my number one priority again.