Re: System tray windows



Hi,

So I talked to Owen about this issue for a while, and played with the
KDE 3 implementation (recent RPMs from the Red Hat beta).

I think Gregory is right on two points:

 - there is no real reason to have the window manager involved; 
   seems to just create odd issues

 - the KDE setup does not handle multiple system trays at all 
   well. I added several to the panel, and got some 
   entertaining infinite loops with system tray icons 
   moving around between trays, sometimes a tray eventually 
   manages to get one permanently but which one will get the 
   icon is random.

Looking at the KDE source code, I discovered another interesting
point, which is that KDE already uses QXEmbed to embed the tray 
icons, using a draft of the XEMBED protocol.


Let me make a proposal which is a bit different from the various
current setups.


Discovery
===

The system tray has to own a manager selection. I would modify
Gregory's proposal in these ways:

 - add the screen number to the selection name to 
   handle multihead

 - use the manager selection _only_ for uniqueness 
   (in the same way XSETTINGS uses it). This avoids 
   the complicated code needed to convert/provide 
   selection data, we just need the simple stuff.

Because the selection owner window is apparently supposed to be
destroyed when the manager selection is lost, normally the 
selection owner window will not be the same as any of the 
user-visible windows.

A system tray that fails to get the selection can ask the user 
if it should exit, or just do nothing, as it sees fit.

To have multiple system tray applets, the best approach is to have
them all in one process owning the manager selection - i.e. have one
system tray app that handles multiple user-visible tray areas.  This
app would then support a mechanism for moving tray icons between
areas, for example.

Use of XEMBED
===

Since we probably want to use GtkPlug for this purpose in GTK,
and KDE already uses QXEmbed, this only makes sense. By using 
XEMBED we automatically handle issues such as keyboard focus
and avoid having to specify them for the system tray specifically.

The disadvantage is that XEMBED is not really finished off or
interoperable yet. I think we need to just fix that, by poking Owen
and Matthias and Bradley. The system tray will be a good XEMBED test
bed.

For the short term, we can just use GtkSocket/GtkPlug to implement the
GNOME tray, and KDE can use QXEmbed; thus when those widgets are fixed
to interoperate the system tray will magically come along.  (They
probably sort of interoperate already, just some small details are
likely messed up.)

Docking
===

According to Owen, he and Matthias agreed that the "recommended" way
to do docking is to provide the plug ID to the socket, rather than 
the plug finding the socket. Thus we want to ask the socket to insert 
the plug.

Rather than doing this via the window manager, one suggestion is: the
application sends a client message to the manager selection owner
window. This window may not correspond to the window the plug will be
reparented into (in fact, KDE now uses and GTK will want to use a
separate socket window for each plug, plus the issue of needing
to destroy the selection owner when losing the selection).

Client message is nicer than the manager selection because it avoids
the sizable amount of code that can be required to implement
getting/setting selection data in a robust way and is just generally
easier to deal with.

Ending embedding
===

The XEMBED spec needs to specify how to un-embed, that mechanism will 
be used to remove a system tray docklet.

There's an unavoidable problem where if the system tray crashes,
embedded plug windows will get X errors.

Mapping
===

XEMBED is apparently currently in flux with respect to how mapping
works, where Owen wanted plugs to be able to map/unmap while remaining
embedded, and the original spec always maps the plug immediately.

But anyhow, the way it works is that the system tray is given the
window ID of the docklet via some mechanism such as the client
message, and then the XEMBED spec kicks in and specifies the rest of
it.

Class hint on plug
===

Docked windows should set a class hint, this is mostly so that 
the system tray can remember the position of docked windows by 
type. For a simple tray, the tray might remember the order in which 
the docked windows appear. For a more complex case where a single 
manager selection holder has two user-visible tray areas, 
it could remember which tray each icon should appear inside.

Handling changing system tray
===

When the system tray dies, apps that want to keep providing a 
docklet will need to watch for a new system tray grabbing the manager
selection, and provide a new docklet when they see one.

This is in contrast to the current KDE setup, where the new system 
tray appears and gets the list of existing docklets, and then 
reparents them. Instead I'm suggesting that each docklet self-reparent 
into a system tray if they see one. This avoids having to keep track
of the list in the window manager.

The "fallback" mode can also be handled by clients in this way; they
can choose to fall back by not displaying the tray icon, by displaying
an error, by displaying a small window, or as appropriate. Nicer than
displaying tiny little windows all the time.


So in summary:

 - manager selection to fix uniqueness problem
 - simple client message to get the docklet ID 
   to the system tray
 - punt all the behavior specification to XEMBED 
   as soon as we have the docklet ID communicated
 - clients are responsible for handling 
   system tray appearing/disappearing
 - we provide the implementation note that 
   system tray icons should set a class hint

I think that covers all the issues, and is very simple to implement.
Moving KDE to this method I believe would mostly involve deleting
code; all the KWin and kwinmodule code would go away, and the
KSystemTray class would be modified to handle the
appearance/disappearance of system trays and send the client message.
The applet code would remain the same except for trivial selection
ownership code (can be copied from XSETTINGS sample implementation for
example).

Havoc



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]