Idea how to make systray icons work correctly

Dennis Kasprzyk onestone at compiz-fusion.org
Sat Oct 18 04:59:54 CEST 2008


Hi,

during the last week I've tried to make systray icons work correcty. Let me explain what the real problem is first:

- Systray icons are normal X11 windows that are reparented into systray area of the panel.
- They usually have the visual of the creating application in most cases (= RGB).
- To have the right background they set their background pixmap to ParentRelative. This means that everywhere they don't draw anything the content of the parent window (panel) will be used.
 
And this is our problem:
- Plasma has a RGBA visual (transparency in the panel)
- You can't reparent a ParentRelative window to a window with a different visual
- We can't change the ParentRelative flag to out own pixmap / color because this makes gtk systray window crash the whole application
- We can put a window (With no ParentRelative background) between the systray window and the panel
- But we can't get any transparency
- The systray windows are reparented with the panel window and can't be animated with the panel autohide

I've tried the following hack to make it work.
- set the background of the window (wrapper) that sits between the systray window and the panel to a given color (pink in my case)
- Used XComposite to redirect the wrapper window into a pixmap. I got a systray area with invisible icons but I could click on them
- Used XGetImage to get the content of the redirected systray into plasma
- Converted the Image into a new RGBA image and replaced all "pink" pixels with a full transparent pixel.
- Converted the image into a QPixmap
- Painted the new pixmap into the panel

I've got following results:
- Qt applications had still a broken background (like we see with the current systray)
- GTK applications had a transparent systray icon but a dark pink shadow around them
Why did it not work correctly:
GTK: They get individual pixels you of the parent window and blend them internally to provide fake transparency (pink background + shadow = dark pink).
QT: Does almost the same but it calls QPixmap::grepWindow on itself. For some reason this doesn't really read out the parent window content and instead takes a "screenshot" of the area where it thinks the window currently is. (This is also why we see broken backgrounds with the current implementation). This also means that my icons got never blended with the pink background in my test.

I thought a while how we could fix it correctly, and this is my idea:

1. Extend the current systray spec, and allow a new property (_NET_SYSTRAY_ICON) on the systray window that holds the id of a rgba systray icon pixmap
2. Use the current systray system that reparents the systray icon window into the panel.
3. If the window has the _NET_SYSTRAY_ICON property set:
- Use XComposite to redirect the content of the normal systray icon (The window will still be there and get input but won't display anything)
- Use QT/XRender to display the icon pixmap (this should even work with the autohide animation if done right)
- Use XDamage on the pixmap to get informed about changes of the pixmap to initiate a redraw

The benefits should be pretty clear:
- only a small change of the systray spec that will not break any panel/systray implementation
- real RGBA icons that can also be animated with the autohide animation

Thanks
Dennis



More information about the Plasma-devel mailing list