Proposal: clean way of animating windows to/from system tray icons

Éric Tremblay xdg at deimos.ca
Mon Sep 7 15:26:16 PDT 2015


Hello everyone,

I'm programming little "zoom" animations in XFCE to show the user in a 
logical way, for example, where to click to get a window back when it 
minimizes, or where a window "comes from" when it appears, if that 
applies. The biggest problem with this is that there's no standard way 
for the different processes (window manager, tray icon manager(s), etc) 
to determine or communicate with each other where the *tray icons* are.

Taking example of the _NET_WM_ICON_GEOMETRY window property, i think 
i've come up with a clean, simple, and reliable solution. Here's a 
description of how i implemented this in XFCE, however i attempted to 
make it as portable and non-wm-specific as possible, depending only on 
X11/Xlib internals.

I'm simply using an X property on the root window of the display called 
_NET_WM_TRAY_ICON_GEOMETRIES which follows a simple format. It's an 
array of strings, with each string representing a tray icon, and 
following a format like:

"mgr=systray,classname=blueman,pid=4522,x=1332,y=1,w=22,h=22"

In this example, the "mgr" field indcates that this entry was added by 
the "systray" pluign. This information lets more than one "tray" process 
manage the string array on a given X display (as is the case with XFCE's 
"systray" (aka "notify") and "indicator" panel plugins) and also avoids 
the problem where different processes would add duplicate information, 
whcih would quickly saturate the string array. The "classname" field is 
pretty self-explanatory, it's the class name of whatever window(s) match 
up with this systray icon. The "pid" field can help in matching windows 
that have nonexistent or weird class names. If it's absent or equal to 
-1, then that means the PID of the process owning the icon couldn't be 
determined. Finally we have the x,y,w,h screen coordinates of this tray 
icon. In my implementation the fields may be read in any order, but it's 
better to write them in a more consistent format such as the above.

(at least for now) If a string contains any semicolon ";" or newline 
characters, these should be treated as separating the entry into several 
entries.

Upon creating a new systray icon, modifying an existing one, or deleting 
a systray icon, a tray manager process such as the "indicator" plugin 
would do something like the following:

     - choose a name that preferably describes its process name, such as 
"indicator", "notify", or "systray" - this would be the "mgr" field. It 
should be consistent for the entire lifespan of the tray manager process.

     - grab the X server to avoid race conditions with other tray managers

     - fetch the strings from the _NET_WM_TRAY_ICON_GEOMETRIES property 
on the X server's root window

     - *remove* all entries whose "mgr" field matches its own chosen 
process name

     - for each tray icon managed by this process: append a string to 
the array in the above format, omitting the "pid" field or setting it to 
-1 if the PID corresponding to the tray icon can't be determined, and 
omitting the "classname" field or setting it to zero-length if the class 
name can't be determined. If both can't be determined for a specific 
entry, it's pretty useless to add that entry.

     - write the string array to the _NET_WM_TRAY_ICON_GEOMETRIES 
property on the X server's root window

     - ungrab the X server


The window manager can then easily determine if it should perform an 
animation to/from a tray icon when a window opens or closes, and if so, 
what the screen coordinates of this icon are. In case both a 
_NET_WM_ICON_GEOMETRY is present *and* a match in the root window's 
_NET_WM_TRAY_ICON_GEOMETRIES array is found, it's up to the window 
manager to determine which one should take precedence, based on factors 
such as the window's class/role, whether it is itself the window's 
owner, and so on. In some cases, it's also desirable to not perform the 
animation, for example if there are several open windows matching the 
same tray icon - in this case, we'd normally want to animate only the 
last one to close.

It's also possible to setup a table of "equivalent names" for processes, 
for example we'd want pavucontrol windows (the PulseAudio volume 
control) to be considered as belonging to the indicator-sound-service 
process if it's running.

Anyway, i've been running my implementation of this on 2 of my own 
machines for a while now, and it seems to work very well.

Cheers,

   - Éric "delt" Tremblay.




More information about the xdg mailing list