Writing Compiz plugins
Compiz is a really promising thing. Together with AIGL/XGL it basicly allows you to get any XWindow as a OpenGL 2D Texture. This includes Gecko, SDL games, ancient apps, videos. So you really get everything as a 2D Texture. Using this texture allows you to do funny things. I just returned home after doing one of the many cool things. So what we do is grab the texture of the currently active window and draw many many rotated quads, triangles, polygones (X,Y,Z axis rotate). So we had like 1000 quads rotating and spinning on your desktop. After doing that we started drawing rotating cubes with the content of your running applications. So I think DoKu and I had some fun doing that but how did we get there?
Well Compiz is badly docuemtated, actually there are no comments at all and the plugins contain some weird code that really deserves an explanation, specially as some routines are complicated and could be written with less lines in a more clean way. Writing plugins is not documented at all, how to load plugins is not documented at all. But our goal was to write a plugin so we started writing a skeleton that just gets dlopened and everything is fine. Well we thought we wouldn’t need a lot of time. Change the Makefile.am, add your plugin skeleton, get it dlopened. Well without editing a one million line huge unreadable GConf schema you have almost no chanche in getting your plugin loaded by Compiz. Well almost as there is a ini.c plugin, so we edited this plugin to get our new plugin loaded, we had to reorder the DEFAULT_PLUGIN string a bit to make it work but in contrast to gconf.c this is doable. This is required as compiz effectively only loads from plugin supplied on the command line.
Plugin loading works the usual way, there is one exported method that returns a struct you have to fill out. This struct contains ABI version and function pointers for certain operations. These include initializing and closing the Display, the Screens attached to the Display and the Windows attached to the Screen. Providing functions for the Screen and Display is mandantory otherwise your application will crash.
Compiz allows you to store private structs for CompScreen, CompDisplay and CompWindow. You have to request a privateIndex (there are three methods for that, a global one, one for Screen and one for Display) and then you are free to store stuff inside the private array at this index. So you will endup creating your FOO_DISPLAY, FOO_SECTION, FOO_WINDOW macros like every other compiz plugin has.
Initialization works the following way. First the normal Init method is called, then the one for the Display, then the one for the attached Screens (yes plural) and finally the ones for each registered X window (not only the toplevel ones you see).
There are several different painting and event routines you can hook into. Display allows you to recive events, Screen allows you to enter the rendering chain. This chain includes Prepare Screen Rendering, Doing the Screen Rendering and being Done with it. A window supports the PaintWindow method. To enter these chains there are WRAP and UNWRAP macros you can use. Normally you do WRAP in the Init methods and unwrap in the Fini methods. To call the base ‘class’ you temporarily UNWRAP call the function and WRAP it again. At least this is my explanation…
So to implement the cube you hook into the PrepareScreen method to update the animation numbers e.g. calculate the new coordinates. During the PaintScreen method you call the base implementation and then you can do whatever GL magic you want to. You have access to the used output device, can get the physical coordinates, CompScreen allows you to traverse over the active Windows and the good thing is, each Window has a CompTexture and as the screen was just painted all mapped Windows have valid ones. So you just have to ask compiz to bind the CompTexture and then make use of it. E.g. drop the cube example of the many online tutorials into the code path and you are already done.
The DonePaintScene Function is normally used to damage the screen and force repainting. This is used to keep the animation going.
What makes compiz hard to use is the lack of documentation, we gathered our information by looking at undocumented other plugins. E.g. the switcher to find the unhookWindowFromScreen method, I hope that this small introduction might motivate you to look into Compiz as well, or even helps you to write your own plugins.
A video will be created on monday and will be uploaded somewhere. Ah and this is my first OpenGL hack ever, I hope to be able to do more hacking using OpenGL ES and OpenVG in the future.
h.
PS: off to bed….