gnome-power-manager tray icon not appearing on startup fixed!

Yes, that’s right. gnome-power-manager-2.20.0-r1 in Gentoo now shows its tray icon after GNOME startup.
So everyone using some workaround hacks (usually involving scripts with sleeps, killalls and restarts), please remove them after upgrading to this revision 😉
As Gnome-2.20 is planned to go to stable tree quite soon, I didn’t fix the 2.18 series.

So what was wrong you might ask?
Well, let me explain then, at least then this post might be somewhat useful to Planet GNOME readers, considering that there are some notions that other programs might be affected:

Somewhere in the 2.17 development cycle, gnome-power-manager added code to handle some special X keysyms, such as XF86XK_PowerOff. This code is realized through a callback from the gdk_window_add_filter mechanism. The documentation of it says the following:

Adds an event filter to window, allowing you to intercept events before they reach GDK. This is a low-level operation and makes it easy to break GDK and/or GTK+, so you have to know what you're doing.

If the GdkFilterFunc() callback returns GDK_FILTER_REMOVE then the processing of this event is stopped and gtk+ won’t see it, if it returns GDK_FILTER_CONTINUE then it’s continued and gtk+ will see it if some other filter that might be set up doesn’t stop it.
When a notification area applet is ready to accept icons, it acquires ownership of the _NET_SYSTEM_TRAY_Sn (n is the screen number) X selection on MANAGER atom and GtkStatusIcon takes notice of this through a XClientMessageEvent that is listened in a GdkFilterFunc of its own to know when it can create the icon and set up some other filters for a (orientation) property and destroy notification.
Now, the gnome-power-managers filter that is set up tries to filter for keypresses to catch the power management related ones and return GDK_FILTER_REMOVE for those and any other event gets a GDK_FILTER_CONTINUE. Well, that seemed to be the plan, it’s just that instead of
if (xev->type == KeyPress) { ...; return GDK_FILTER_REMOVE; } return GDK_FILTER_CONTINUE;
there was
if (xev->type != KeyPress) { ...; return GDK_FILTER_REMOVE; } return GDK_FILTER_CONTINUE;
stopping propagation of any non-keypress up to gtk+ and especially gtktrayicon-x11.c that was trying to listen to xev->type == ClientMessage type of events on the X root window for knowing about the tray manager appearing to create the tray icon into it. Whoops. No icon, no reaction to the keys.

So, lesson of the day – if you are an application or daemon with a tray icon be triple-careful if you need to use gdk_window_add_filter for some reason, or you might end up with the icon not appearing if the app is launched on startup or when the notification-area-applet (or any other notification manager) is reloaded manually or on a gnome-panel crash. You already need to be double-careful in using this mechanism and use it only when really really necessary – it’s a great way to make GDK or GTK+ break, just as the documentation says.

This is already fixed on trunk in the gnome-power-manager case, as per the relevant bug. Thanks, Richard. Also many thanks to Shogun, who figured out this happens in the –enable-xevents specific code, which is also probably the reason many of the other distros weren’t affected as they likely just don’t use this configure switch.

And, again, if you use a workaround hack for this, please remove it after getting the revision with the fix (now or in the near future in case of a stable tree usage) as starting gnome-power-manager twice is no fun