About obfuscating email addresses

Many people obfuscate their email address on web sites in the hope that bots are unable to extract their address from websites. That could look like the following:

email [AT] example [dot] tld

This approach is for example used by Mailman’s archiver pipermail and the MARC mail interface used by the KDE mailing lists. Some people even ask to “not quote the e-mail address unobfuscated in message bodies”.

So is it useful to obfuscate the email address? Does that add any security?

The answer is No. This obfuscation is a kind of a CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) which requires that a computer cannot solve the Artificial Intelligence problem when it has access to all information required to create the test. Yesterday I tried to proof that this kind of CAPTCHA is broken and wrote a small application which is able to extract the email addresses from a public pipermail archive. The application is less than 300 lines of code and can automatically download all emails for a given month and year and extract the sender’s address by just extracting all a elements from the online accessible emails and applying a regular expression on the text to get the email address. I only wanted to work half an hour on that. In the end I had to compile Qt 4.6 because I needed the new QWebElement 😉 If someone is interested in the source code I could create a repository on gitorious.

The following image shows the result of an “attack” on the plasma-devel archive. For privacy reasons I blurred the user part of the mail address.

Picasaweb

I don’t think there is any reliable way to obfuscate an email address using simple text. If there is an algorithm to obfuscate the address, there is a regular expression to unobfuscate the email. The only way to protect an email address is to not include it anywhere where a bot could harvest. That is replace it by a “real” CAPTCHA that will reveal the email address when solving it. For websites there is for example the Mailhide API of reCAPTCHA. For mailinglists that is completely useless as the email address is already included in plain text in the email headers. Instead of parsing websites bots could just subscribe to the mailinglists.

So please stop obfuscating your email addresses. It is useless and makes it impossible to just click on an email link. Instead the reader has to solve the useless CAPTCHA.

Why distributions shouldn’t ship development versions

At Desktop Summit Lubos asked me what openSUSE has to do that I will switch back to SUSE. I replied that I am satisfied with Kubuntu and so I don’t see any need to switch the distribution. So what has changed since July?

Kubuntu will ship the Plasma Netbook Shell in their next release. Of course the Netbook Shell is under heavy development and will be shipped in KDE 4.4 for the first time. Given the current release plan we can consider the current state as pre-alpha. But that seems not to be any problem for Kubuntu – they even are able to support it for 18 months as it is in the main repository. They are even able to ship a recent SVN revison: the current package is svn rev 1016996. So quite decent and no problem at all, isn’t it? Well no, KDE 4.3 got branched way before and since then trunk is KDE 4.4 and code in trunk may depend on trunk. But if there were a dependency it would break at compile time, wouldn’t it?

But couldn’t there be runtime dependencies? No way, that’s totally impossible. It’s a plasma netbook shell, not a KDE workspace netbook shell! So it’s totally impossible that KWin added changes to improve the netbook shell. So we have in the netbook shell a commit with this commit message:

Activate present windows by setting a property instead of faking keys. Requires kwin svn rev 988110

Of course a distribution checks all the svn log entries and knows about such issues. So they will probably use the old code, which was just a placeholder to be replaced as soon as trunk becomes 4.4 as happened. So I downloaded the source package and woops it contains my commit. Hmm so there is still the possibility that KWin was patched. That would be really bad as present windows received lots of changes at the beginning of 4.4 release cycle. Which is great but shouldn’t be shipped in a distribution before it has been tested probably. So I thought, let’s check the patches in bazaar. Well there is no such patch to KWin. So the applet is basically broken in the Kubuntu edition. Kubuntu will not only ship and advertise a development snapshot, they will be shipping broken software. (which btw is not the first time that Kubuntu ships development snapshot unsuited for usage – just remember the NetworkManager Plasmoid).

Update: Kubuntu assured that the Plasma Netbook Shell will only be published as a tech preview and that it will communicated as that. This makes of course the points mentioned above invalid.

While browsing the patches in bazaar I found a different patch which really upset me. It is a patch which was discussed on kcd last week and was rejected by all workspace developers who replied to that patch. So a patch which is not good enough for KDE is good enough for Kubuntu. I though Kubuntu wants to be the best KDE distribution. Sorry, that isn’t. I am disappointed and I think it is a bad sign if decisions by the upstream project are ignored (the change to package kdebase-workspace was commit after the discussion started on kcd). I objected to the patch for technical reasons and there was agreement to improve the notification instead of stepping back to present nag dialogs.

For quite some time I am disappointed by the developments of Kubuntu. With 4.3 packages the translations broke again (as every half year) and that is just the worst which could happen to user experience. Because of that problem I stopped to recommend Kubuntu to my friends. But now I see a development in Karmic which I do not want to use myself. There is a broken development snapshot of the netbook shell, an alpha release of k3b is shipped, which is not even shipped by Fedora, because it “isn’t quite ready, and not recommended for use by upstream” and Karmic will ship an additional notification system, which doesn’t support actions, to “test” how KDE users will get along with it. I don’t have any problems with Canonical deciding to develop and ship a different notification system but as soon as it degrades the KDE workspace it has to stop. By shipping that patch there is a degeneration of the user experience as a dialog is shown instead of a notification. If you doubt that the change was done just because of the Ayatana notifications please read this mail. I do not want to know how many additional changes there are breaking user experience.

Update: Scott stated in the comment section that the patch is controversial in the Kubuntu community and it has not yet been decided if the patch will be shipped.

So to me this is the end. It’s time to part from Kubuntu after four years of usage as I cannot say any more that it is a good KDE distribution and satisfies my needs. I won’t update to Karmic and instead will install a different distribution. I do not yet know which one I will choose, maybe I return to openSUSE, maybe I will use Debian testing/unstable or switch to Gentoo. Probably Debian will win as I do not want to learn a different packaging system.

Quick tiling and TabBox updates

During the last weeks quite some work has gone into KWin, which is great and needs to be mentioned here. First of all a big thanks to Hugo Pereira for his work on Nitrogen. You might have heard that we imported Nitrogen from kde-look.org to replace Ozone. Lots of work and realy great improvements has gone into it and it’s just awesome that we can provide the two highest rated window decorations from kde-look in the next KDE release. If you want to see some screenshots have a look at the web gallery. I hope we will finally merge Nitrogen back into Oxygen and only provide one decoration.

As already mentioned in the dot story I worked on a feature known as “Aero Snap” during Tokamak. (Btw. big thanks to Mario for the great event and thanks to the Plasma crew for the invitation. You are a great group of people 😀 And I hope I will find the time to go to next Tokamak.) Currently a new contributor, Robin, is working on adding keybindings to quick tiling, so it will rock even more. It’s difficult to show it in a screenshot, but here it is:

Von KWin

Finally (un)loading effects does not result in flicker any more. This is a real improvement but it feels strange when you are used to the flicker as indication that the changes were successfully applied. The fix will be backported to 4.3.2 and thanks a lot to Robin for the help on that one.

One of the biggest changes for 4.4 so far is the new TabBox which has been merged into trunk today. I already blogged about it but some things have been improved since last time. It’s now possible to have two independent switchers with different shortcuts. So you can have for example alt+tab with windows from all desktops and meta+tab with windows only from current desktop. It’s also possible to assign different effects to the two switchers which allows to use both the “normal” TabBox as well as a fancy switcher (when effects are disabled it will of course fall back to the normal switcher). Most improvements went into the classic switcher so far, but some will be implemented in the effects as well. E.g. switching with cursor keys might be useful if you use Present Windows. One of the nice new features is that you can close a window with middle click on the entry in the list.

Since my last blog post I improved the KCM as well. The layout bits were moved into an own dialog with a live preview (sorry for the black border, it worked correctly yesterday evening):

Von TabBox
Von TabBox

TabBox der nächsten Generation

Dies ist eine Übersetzung des englischen Posts TabBox NG

Ich arbeite aktuell an der TabBox “Next Generation”. Für die, die nicht wissen was die TabBox ist: dies ist die Liste, welche angezeigt wird beim Benutzen von Alt+Tab in KDE. Sie kann zum Anzeigen von Fenstern und virtueller Arbeitsflächen (in statischer oder zuletzt verwendeter Sortierreihenfolge) verwendet werden. Zusätzlich ist es möglich die Liste durch einen KWin Effekt zu ersetzen.

Diese Neuimplementierung ist der zweite Teil meiner Überarbeitung von Alt+Tab. Der erste Teil ist bereits implementiert und verfügbar als Fenster Runner. Mit diesem kann KRunner auch die offenen Fenster anzeigen und bietet Interaktionen wie Schließen, Minimieren, etc. an.

In KDE 4.3 erhielt die klassische TabBox bereits eine nette visuelle Überarbeitung und sieht integrierter in den KDE Workspace aus. Warum sollte man also an einer neuen Implementierung arbeiten? Um diese Frage zu beantworten zeige ich eine Liste der neuen Funktionen:

  • Wenn die Liste nicht auf den Bildschirm passt, werden die Einträge nicht mehr entfernt, sondern die Liste scrollt.
  • Mausrad scrollt in der Liste
  • Anwender kann wählen zwischen horizontalem, vertikalem und tabularischem Layout
  • Navigation mit links/rechts/hoch/runter Tasten – nützlich für tabularisches Layout und Present Windows Effekt
  • Model für Fenster und für virtuelle Desktops: neue Wechselmodi erfordern nur das Schreiben eines neuen Models und eines Delegates. (Das könnte nützlich werden, wenn wir die Plasma Activities integrieren – mehr dazu nach Tokamak)
  • Statischen und zuletzt verwendete Desktop Wechseln ist nur eine andere Sortierung im Model
  • Optionale Integration des Highlight Windows Effekt
  • Outline des ausgewählten Fensters kann ausgeschaltet werden
  • Ausschalten der Liste zerstört nicht mehr das Verhalten
  • Und zuletzt: Komplett konfigurierbares Layout der Einträge. Dies bedeutet, dass der Anwender zwischen einigen vordefinierten Layouts wie ein informatives, ein kompaktes, ein nur kleine Icons, ein nur große Icons, ein nur Text und eigenen Layouts wählen kann. Zusammen mit dem Layout der Liste kann man sich nun eine TabBox, die wie die MacOS oder die Windows XP aussieht, ohne Probleme zusammenstellen.

Ich kann ja viel erzählen, aber ein Video, welches die neuen Funktionen zeigt, sagt mehr:

Download ogg video

Einiges ist immer noch zu implementieren:

  • Konfigurationsinterface für die Layouts der Einträge
  • Layouts für Desktop Einträge
  • Eine zweite optionale Liste welche nur den ausgewählten Eintrag zeigt – wird benötigt für nur Icon Modus zum Anzeigen des Namens (also MacOS Stil 😉 )
  • Hinzufügen einer zweiten TabBox mit eigenem Tastenkürzel und eigenen Einstellungen, so dass man zum Beispiel eine TabBox für Fenster auf aktueller Arbeitsfläche haben kann und eine für Fenster auf allen Arbeitsflächen.

Ich hoffe es in einen Stand für das Review zu bekommen wenn Tokamak beginnt, da ich mit dem Zug hinfahre und viel Zeit habe, daran zu arbeiten.

Ach und wenn man sich gewundert hat, warum die Focus Policy das Alt+Tab Verhalten zerstört: bitte einen Blick auf folgenden Screenshot werfen.

Von TabBox

TabBox NG

I’m currently working on the TabBox “Next Generation”. For those who do not know, what the TabBox is: it is the list view shown when using Alt+Tab and can display the windows or desktops (in static or most recently used order). It is also possible to replace the list view by a KWin effect.

This new implementation is the second part of my rework for alt+tab. The first is already implemented and available as a window runner so KRunner also lists your open windows and you can even interact with them, like closing, minimizing, etc.

In KDE 4.3 the classical TabBox already received a nice facelifting and looks integrated into the Workspace. So why working on a new implementation? Well to answer that I will present a list of the new features:

  • If the list doesn’t fit on the screen items are not cut off, but the view scrolls
  • Mouse wheel scrolls the list
  • User can choose if the items are laid out vertical, horizontal or tabular
  • Navigating with left/right/up/down keys – useful for tabular layout and for present windows
  • Model for clients and for desktops; adding new switching modes just requires to write a model and the delegate. (That could become useful when we integrate Plasma activities – more after Tokamak)
  • Static and most recently used desktop switching is just a different sort mode in the model
  • Optional Integration of highlight windows effect
  • Outline can be turned off
  • Disabling the view does not break the behaviour
  • And last but not least: Completely configurable item layout. That is the user can choose between some predefined layouts like an informative, a compact, small icons only, big icons only, text only and can define custom layouts. In combination with the view layout configuration you can build a TabBox which looks like the MacOS or the Windows XP without any problems.

So I can talk a lot but there is no better thing than a video, showing the new features:

Download ogg video

There are some things I still have to do:

  • Config interface for the item layouts
  • Layouts for desktop items
  • A second optional view for showing just the selected item – needed for icon only mode to show the text of selected item (that is the MacOS style 😉 )
  • Adding a secondary TabBox with own shortcuts and own settings, so that you can have a TabBox for e.g. only clients on current desktop and another one for clients on all desktops

I hope to get it into a state for review when Tokamak starts as I will go by train and have lots of time for working on it.

And if you never understood why your focus policy destroyed your alt+tab behaviour: have a look at this screenshot.

Von TabBox

Get Hot New Stuff in Aurorae

Dank Frank Karlitschek gibt es nun eine eigene Kategorie für Aurorae Themes auf kde-look.org. Er hat auch einen Get Hot New Stuff (GHNS) Provider hinzugefügt und ich hab diesen bereits implementiert und eine neue Aurorae Version veröffentlicht. Über GHNS kann man direkt aus dem Konfigurationsdialog neue Themes herunterladen. Hier der obligatorische Screenshot:

Von Aurorae

Es gibt mittlerweile schon einige Aurorae Themes und das ist einfach großartig. An dieser Stelle möchte ich einfach allen mal danken, die ein Theme erstellt haben. Einige Themes sehen richtig umwerfend aus und passen wunderbar zu einem Plasma Theme. Genau das wollte ich mit der Engine erreichen. Ein Beispiel für diese tolle Umsetzung ist das Gaia 09 Theme. Es ist schön zu sehen, wie viele Anwender die Theme Engine herunterladen und Designs erstellen, obwohl es mit der 4.3 Abhängigkeit nicht gerade einfach war (nun dieses Problem sollte seit gestern behoben sein).

Get Hot New Stuff support in Aurorae

Thanks to Frank Karlitschek there is a category for Aurorae themes on kde-look.org. He also added a GHNS provider and of course I already implemented it and updated the Aurorae version. Here the obligatory screenshot:

Von Aurorae

There are many themes already available for Aurorae and that’s awesome. I just want to say thanks to everybody who designed a theme. Some are really great looking and working nicely together with a Plasma theme. That’s exactly what I wanted to achieve. Have a look for example at the Gaia 09 theme. It’s really great to see so many users picking up the theme engine although it was quite difficult to use as it has a 4.3 requirement (well that problem is solved since yesterday).

Gran Canaria Desktop Summit – persönliche Zusammenfassung

Die letzte Woche war ich auf dem Gran Canaria Desktop Summit, der erstmalig gemeinsamen Konferenz von GNOME und KDE. Ich muss sagen es hat sich gelohnt und hoffe, dass in Zukunft öfter aKademy und Guadec zusammen stattfinden werden.

Ich war am Freitag in Las Palmas angekommen. Das Wetter war bei weitem nicht so schlimm, wie ich befürchtet hatte – es war richtig angenehm. Der starke Seewind und die Bewölkung machten die Hitze durchaus erträglich. Trotzdem: die Sonne ist gefährlich – das sagt mir zumindest mein Rücken 😉

Am Freitag Abend war das erste Social Event gesponsort von Canonical. Es war somit die erste Möglichkeit die GNOME Leute kennen zu lernen. Wenn man sich so umgeschaut hat, sah man aber, dass die KDE Leute mit den KDE Leuten sprachen, die GNOME Leute mit den GNOME Leuten. War ja irgendwie zu erwarten – man kennt sich halt 😉 Dennoch gab es wohl auch einige Gespräche über die Grenzen hinweg und ich hab ein ausführliches Gespräch mit einem GNOME Shell Entwickler gehabt und Ideen ausgetauscht.

Am Samstag morgen begann die Konferenz – trotz Party am Vorabend gut besucht. Das Konfernzgebäude war einfach gigantisch. Die Mitarbeiter wurden aber wohl nicht richtig darauf vorbereitet, dass eine freie Software Konfernz nicht wie eine normale Konfernz ist. Bei Lightning Talks jeweils neues Wasser und ein Namensschild zum Rednerpult zu bringen ist irgendwie overkill 😉

Die Konferenz wurde von einigen Vertretern von Gran Canaria/Spanien eröffnet. Leider hab ich keine Ahnung was sie uns sagen wollten, da sie auf Spanisch gesprochen hatten. Am Besten war ein Redner der anfing mit “mein Englisch ist nicht wirklich gut, daher halte ich meine Rede auf Spanisch”. Bei schlechtem Englisch hätte ich ja was verstanden, bei Spanisch leider nicht.

Nach der Eröffnung folgten die drei Keynotes. Ich war ja besonders an der Stallman Keynote interessiert. Da er ja zuvor schon auf Mono rumgehackt hatte, hatte ich erwartet, dass er auf die Problematik eingeht. Und ich wurde in dem Punkt nicht enttäuscht: seine ganze Rede ging eingentlich um die Mono Problematik. Die Rede war sehr gut aufgebaut: er begann mit einem Rückblick auf die Qt Problematik und wie es zu GNOME führte. Dass damals die freie Software bedroht war, weil der einzige freie Desktop auf eine unfreie Komponente aufbaute. Er erwähnte auch, dass dieses Problem heute gelöst ist. Mit diesem Rückblick motivierte er die Mono Diskussion: da Microsoft Patente auf C# hat, stellt das Entwickeln in dieser Sprache seiner Meinung nach eine Gefahr dar. Es sei schwer zu sagen an welchem Punkt es gefährlich wird, einzelne Anwendungen sind ok, aber komplett darauf aufzubauen nicht. So könnte man sagen, dass Tomboy ok ist, weil man es problemlos durch Gnote ersetzen kann. Also falls MS jemals auf die Idee kommt die Patente einzusetzen, wäre nichts verloren. Wie sich am Anschluss seiner Diskussion zeigt, kennt er sich jedoch mit der Problematik nicht wirklich aus. Er weiß nicht welche Teile patentiert sind, er weiß nicht in wie weit MS versprochen hat, keine Patente einzusetzen und seine Argumentation dreht sich um den Punkt “MS ist böse, MS hat gesagt sie wollen freie Software zerstören, also dürfen wir keine MS Technologie verwenden”. Auch wenn ich persönlich die gleiche Argumentation für mich folge und daher C# nicht verwenden würde, klingt seine Argumentation in meinen Ohren als FUD. Besonders die Empfehlung Lisp anstatt C# als Sprache zu verwenden, ist nun ja irgendwie weltfremd.

Ich persönlich habe vor der Rede ja auch eine Meinung zu Stallman gehabt und die ist nicht wirklich positiv. Er hat tolles für freie Software geleistet, aber irgendwie glaube ich nicht, dass er heute noch die richtige Person dafür ist. Und leider wurde meine in diesen Punkten ablehnende Haltung bestätigt. Nach seinem Mono Bashing verwandelte er sich in “St. IGNUcius of the Church of Emacs”. Eine meiner Meinung nach sehr peinliche Vorstellung und ich habe mit niemandem gesprochen der dieses gut geheißen hat. Es gab zwar viel Gelächter und Applaus aber irgendwie glaube ich mitlerweile die Leute haben ihn eher ausgelacht als das gutgeheißen. Für mich war dieser Teil der Rede ein “nein ich will nichts mit soetwas zu tun haben”. Da sage ich dann doch lieber ich bin ein Open Source Programmierer und kein Freie Software Programmierer. Ich kann mir nicht vorstellen, dass Microsoft ihn Ernst nimmt, wenn er als “Heiliger” mit Heiligenschein auftritt. Für eine Keynote bei solch einem Ereignis eine sehr schwache Nummer und ich war nicht der einzige, der sich daran störte.

Nach den Keynotes folgten die ersten Talks – zuerst einige Lightning Talks mit zum Teil grandiosen Projekten. Am nächsten Tag begannen die eigentlichen Vorträge, jeweils vier gleichzeitig – ich muss noch einige Videos anschauen. Es wird an doch bedeutend mehr Stellen zusammengearbeitet als ich dachte.

Nachmittags begann dann die eigentliche aKademy mit einer sehr guten Keynote von Glyn Moody. Ein schöner Rückblick wie Freie Software die Welt bereits veränderte. Die folgenden anderthalb Tage war ich also damit beschäftigt mir Talks anzuhören 😉

Am Dienstag war mein freier Tag, da ich nicht im e.V. und somit nicht zur Hauptversammlung gehen konnte. Die Zeit ein bißchen am Strand verbracht und ein bißchen für 4.4 gehackt.

Mittwoch wurde die Konferenz in die außerhalb Las Palmas gelegene Universität verlegt. Obwohl sie erst 20 Jahre alt ist ohne Klimaanlage – recht überraschend. Zumindest war hier das Internet – im Gegensatz zum Konferenzgebäude – top. An jedem Platz Ethernetkabel und Steckdose. Perfekt für Akademy. Die erste BOF session betraf die Umstellung auf git. Der Raum war komplett voll und überhaupt nicht wie ein BOF sein sollte. Es gibt einiges zu tun und es haben sich einige Freiwillige gefunden. Grober Zeitplan bis zum 4.4 Freeze – also wohl noch dieses Jahr 🙂

Am Donnerstag war das wichtige Plasma/KWin Treffen und es wird einiges tolles kommen – ich verrate jetzt mal noch nichts. Wir haben tolle und ehrgeizige Ideen, die wir aber erst noch weiter ausarbeiten müssen.

Am Mittag war der Tourist Trip. Tja Tourist Trip auf Gran Canaria bedeutet wohl nur, man geht an den Strand. Dass wir dazu mit dem Bus zum Süden der Insel fahren mussten, verstehe ich nicht wirklich – schönen Strand gab es auch in Las Palmas. Am Abend ging es für mich dann zum Flughafen, da ich einen Nachtflug hatte (wie konnte ich nur so blöd sein – ich weiß doch dass ich im Flugzeug nicht schlafen kann).

Insgesamt war es eine richtig tolle Woche und ich freue mich schon auf die aKademy nächstes Jahr. Die Community ist einfach richtig toll und es macht super Spaß in ihr zu arbeiten. Auch mit den GNOME Leuten war es eine sehr angenehme Erfahrung – aber man sieht doch Unterschiede. Mir kam es eigentlich die ganze Woche so vor, als ob mehr KDE Leute anwesend waren. Vermutlich ein rein subjektives Wahrnemen, da wir alle beim Social Event das Kubuntu T-Shirt angezogen haben und bei den Vorträgen unsere Laptops benutzten und man daher überall nur KDE sah.

How to write a KWin effect

This blog post has been in my drafts folder for weeks and I just thought it’s time to publish it – ready for Akademy 🙂 And if somebody is really interested we could have a BOF session at Akademy. I think Plasma devs want us to write a slide effect to replace their custom popup animation. That would be a perfect example to get your hands dirty.

I wrote a new Kwin effect and thought this is the ideal effect for writing a small howto. It is an effect which helps resizing windows by colouring the changed geometry. I was told that resizing is not optimal in KWin, that is if the window content is shown while resizing it is slow and if the window content is not shown it is ugly. This effect should fill the gap. Unfortunately the current code will only work with the slow show window content while resizing (the API has to be changed). Nevertheless I decided to show the code in this tutorial.

Von KWin

The effect has been committed to trunk. So you can have a look at it and if you’re running trunk you can even try it. The effect which we will write has the name “Resize”. It will support both backends: XRender and OpenGL. Each effect has an own directory in kwin/effects so we create a new directory resize. There we create the following files:

  • CMakeLists.txt
  • resize.h
  • resize.cpp
  • resize.desktop

We have to include this directory into the build, so we edit the CMakeLists.txt in the effects directory. We just add the following line to the section marked as “Common effects”:

include( resize/CMakeLists.txt )

If it were an OpenGL only effect we would place this line in the section marked as “OpenGL-specific effects”.

So at this point we are finished with the preparation. So let’s start looking at the files. First the desktop file:

[Desktop Entry]
Name=Resize Window
Icon=preferences-system-windows-effect-resize
Comment=Effect to outline geometry while resizing a window

Type=Service
X-KDE-ServiceTypes=KWin/Effect
X-KDE-PluginInfo-Author=Martin Gräßlin
X-KDE-PluginInfo-Email=kde@martin-graesslin.com
X-KDE-PluginInfo-Name=kwin4_effect_resize
X-KDE-PluginInfo-Version=0.1.0
X-KDE-PluginInfo-Category=Window Management
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=false
X-KDE-Library=kwin4_effect_builtins
X-KDE-Ordering=60

Most of it is self explaining and just needed for the “All effects” tab in the compositing kcm. The most important value is the “X-KDE-PluginInfo-Name”. This is the name used to load the effect and has to start with “kwin4_effect_” followed by your custom effect name. This last part will be needed in the source code.

Each effect is a subclass of class Effect defined in kwineffects.h and implements some of the virtual methods provided by Effect. There are methods for almost everything the window manager does. So by implementing those methods you can react on change of desktop or on opened/closed windows. In this effect we are interested in resize events so we have to implement method “windowUserMovedResized( EffectWindow *w, bool first, bool last )”. This method is called whenever a user moves or resizes the given window. The two boolean values indicate if it is the first, last or an intermediate resize event.

But there are more methods we have to implement. The effect should paint the changed geometry while resizing. So we have to implement the methods required for custom painting. KWin’s painting pass consists of three stages:

  1. pre paint
  2. paint
  3. post paint

These stages are executed once for the complete screen and once for every window. All effects are chained and each effect calls the stage for the next effect. How this works we will see when looking at the implementation. You can find a good documentation in the comments of scene.cpp

Now it’s time to have a look at the header file:

#ifndef KWIN_RESIZE_H
#define KWIN_RESIZE_H

#include <kwineffects.h>

namespace KWin
{

class ResizeEffect
    : public Effect
    {
    public:
        ResizeEffect();
        ~ResizeEffect();
        virtual void prePaintScreen( ScreenPrePaintData& data, int time );
        virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
        virtual void windowUserMovedResized( EffectWindow *w, bool first, bool last );

    private:
        bool m_active;
        EffectWindow* m_resizeWindow;
        QRegion m_originalWindowRect;
    };

}

#endif

We see that there are three member variables. The boolean is used to indicate if there is a window being resized, that is if we have to do some painting. The EffectWindow is a pointer on the window being resized and the QRegion stores the windows’s geometry before the start of resizing.

So now we can have a look at the implementation. I will split the code in small parts and explain the code. So first let’s look at the includes:

#include "resize.h"

#ifdef KWIN_HAVE_OPENGL_COMPOSITING
#include <GL/gl.h>
#endif                                               
#ifdef KWIN_HAVE_XRENDER_COMPOSITING                 
#include <X11/Xlib.h>
#include <X11/extensions/Xrender.h>
#endif                                                                

#include <KColorScheme>

As our effect should support both XRender and OpenGL we have to include the headers for both. As it is possible that the effect is compiled on a system which does not support one of both we use ifdef. We can be sure that at least one of both is available or the effects wouldn’t be compiled at all. If you write an OpenGL only effect you do not have to bother about such things. Also if you only use KWin’s high level API you don’t need to include those headers. But we want to paint on the screen using OpenGL or XRender directly.

So let’s have a look at the next part:

namespace KWin
{                    

KWIN_EFFECT( resize, ResizeEffect )                                                                                                                                                            

ResizeEffect::ResizeEffect()
    : m_active( false )                                                                                                                                    
    , m_resizeWindow( 0 )                                                                                                                                         
    {                                                                                                                           
    reconfigure( ReconfigureAll );                             
    }                                                                                                                           

ResizeEffect::~ResizeEffect()
    {                                                                                         
    }

Here we see the use of a macro. This has to be included or your effect will not load (it took me ten minutes to notice I forgot to add this line). The first value is the second part of X-KDE-PluginInfo-Name – I told you we will need it again. The second value is the class name. Following is constructor and deconstructor.

So let’s look at the pre paint screen stage:

void ResizeEffect::prePaintScreen( ScreenPrePaintData& data, int time )
    {                                                                                                                           
    if( m_active )                                             
        {                                                                                                                       
        data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;           
        }                                                                                                                       
    effects->prePaintScreen( data, time );                                                                                                                     
    }

Here we extend the mask to say that we paint the screen with transformed windows when the effect is active. That’s not completely true – we don’t transform a window. But this flag indicates that the complete screen will be repainted, so we eliminate the risk of artefacts. We could also track the parts which have to be repainted manually but this would probably be more work for the CPU than the complete repaint for the GPU. At this point we see the chaining for the first time. The effects->prePaintScreen( data, time ); will call the next effect in the chain. effects is a pointer on the EffectsHandler and a very useful helper.

So now we start looking at the heart of the effect:

void ResizeEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )              
    {                                                                                                                           
    effects->paintWindow( w, mask, region, data );                                                   
    if( m_active && w == m_resizeWindow )                                                                                                                 
        {                                                                                                                       
        QRegion intersection = m_originalWindowRect.intersected( w->geometry() );                                                                                                                
        QRegion paintRegion = m_originalWindowRect.united( w->geometry() ).subtracted( intersection );                                                                                                                                                          
        float alpha = 0.8f;                                                                                                                                              
        QColor color = KColorScheme( QPalette::Normal, KColorScheme::Selection ).background().color();

We first continue the paint window effect chain – this will paint the window on the screen. Now we check if we are in resizing mode (m_active) and if the currently painted window is the window which is repainted. In that case we calculate the region which has to be painted. We just subtract the intersection of current geometry with saved geometry from the union of those two. The next two lines are for the color definition. We use the background color of a selection with 80 % opacity.

Now we have to do a little bit OpenGL. In most effects where you just transform windows you don’t have to write OpenGL at all. There is a nice high level API which allows you to translate, scale and rotate windows or the complete screen. Also transforming single quads can be completely done without knowing anything about OpenGL.

#ifdef KWIN_HAVE_OPENGL_COMPOSITING
        if( effects->compositingType() == OpenGLCompositing)                                  
            {                                                                                                                   
            glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT );                                                                                                                                    
            glEnable( GL_BLEND );                              
            glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );                                                                                                                               
            glColor4f( color.red() / 255.0f, color.green() / 255.0f, color.blue() / 255.0f, alpha );                                                                                                                      
            glBegin( GL_QUADS );                               
            foreach( const QRect &r, paintRegion.rects() )                                                                                                  
                {                                                                                                               
                glVertex2i( r.x(), r.y() );                                                                                                                                                  
                glVertex2i( r.x() + r.width(), r.y() );           
                glVertex2i( r.x() + r.width(), r.y() + r.height() );                                
                glVertex2i( r.x(), r.y() + r.height() );          
                }                                                                                                               
            glEnd();                                                                        
            glPopAttrib();                                                                  
            }                                                                                                                   
#endif

We check if KWin uses OpenGL as a backend. We enable blending in the OpenGL state machine (needed to have translucent colors) and set the color for our rects. OpenGL clamps colors in the range [0,1] that’s why we can’t use the values from QColor directly. Last but not least we just paint one quads for each rect of our regin.

Now just the XRender part is missing. This part is taken from show paint effect – I don’t know anything about XRender 😉

#ifdef KWIN_HAVE_XRENDER_COMPOSITING
        if( effects->compositingType() == XRenderCompositing)                                 
            {                                                                                                                   
            XRenderColor col;                                                                      
            col.alpha = int( alpha * 0xffff );                                                                 
            col.red = int( alpha * 0xffff * color.red() / 255 );                       
            col.green = int( alpha * 0xffff * color.green() / 255 );                   
            col.blue= int( alpha * 0xffff * color.blue() / 255 );                      
            foreach( const QRect &r, paintRegion.rects() )                                                                                                  
                XRenderFillRectangle( display(), PictOpOver, effects->xrenderBufferPicture(),                                                                                                                          
                    &col, r.x(), r.y(), r.width(), r.height());
            }
#endif
        }
    }

This does the same as the OpenGL part just with XRender.

Last but not least we have to track the window resizing:

void ResizeEffect::windowUserMovedResized( EffectWindow* w, bool first, bool last )
    {
    if( first && last )
        {
        // not interested in maximized
        return;
        }
    if( first && w->isUserResize() && !w->isUserMove() )
        {
        m_active = true;
        m_resizeWindow = w;
        m_originalWindowRect = w->geometry();
        w->addRepaintFull();
        }
    if( m_active && w == m_resizeWindow && last )
        {
        m_active = false;
        m_resizeWindow = NULL;
        effects->addRepaintFull();
        }
    }

} // namespace

So and that’s all. When a resize event is started we activate the effect and trigger a repaint of the window (probably not needed, but doesn’t hurt). And when the resizing is finished we deactivate the effect and trigger another repaint of the complete screen just to make sure that there are no artefacts left.

The CMakeLists.txt could just be taken from any other effect and be adjusted. So here’s the example:

#######################################
# Effect

# Source files
set( kwin4_effect_builtins_sources ${kwin4_effect_builtins_sources}
    resize/resize.cpp
    )

# .desktop files
install( FILES
    resize/resize.desktop
    DESTINATION ${SERVICES_INSTALL_DIR}/kwin )

#######################################
# Config

Now you can compile and try your new effect.

A new KWin window decoration theme engine

I started to work on a new theme engine for window decoration. The goal is to make deco themes as easy as Plasma themes. So it’s using Plasma technologies, that is FrameSvg 😉 Well here is a screenshot of current state:

Von KWin

The decoration background is based on Air’s translucent background and the icons… well you see I’m not an artist. And there is only a minimize and a close button. As you can see it uses KWin’s new ARGB decoration and the theme paints it’s own shadows. The engine does not yet really support opaque decorations that’s one of the left todos. But it’s thought with ARGB decos in mind 🙂

Currently two things are still missing: a name and example themes. So if you have ideas for names please leave a comment and if you are interested in creating a theme, please contact me.

Ah I have not yet committed any code into SVN, but you will soon find the engine in playground. There are some blockers (like the name) which have to be fixed before I want to share the code.