Underneath the Linux desktop
4. Desktops and panels
Desktops, taskbars, pagers, and similar persistent features are a common
part of modern X environments. In fact, these are nothing more
than ordinary X applications following certain conventions, as will
The idea of a 'desktop' in graphical operating environments
has really taken hold over the last ten years
or so. The desktop is the thing you see if no application programs are
running, and which
typically provides access to frequently used programs and files.
In the X window system, the root window is not a desktop, despite being
the background for all the other windows. That is, it has no user interface of
its own. It's possible to add that interface using another application,
but modern practice is to ignore the root window and create the desktop
as a separate X client. So a convention is necessary so that the window
manager recognizes its special status — more on this later.
In the Gnome system, the desktop is usually drawn by the Nautilus
application, which also acts as a file manager. But there are any number
of other desktop applications that might be used instead. It's possible
to build desktop functionality into the window manager,
but this is quite unusual these days.
Provided you're prepared to put up with a few error messages, it's quite
possible to run Nautilus without Gnome, without even a window manager.
$ nautilus --display :3 &
You'll see a display something like this:
The background has gone black in this case — this is because
Nautilus can't read the user's specific configuration settings when run
this way. But the point is that nautilus is a window that, in this case,
occupies the whole screen and covers the root window.
It's quite interesting to examine the properties of the Nautilus
desktop window using
| The Nautilus desktop running without even a window manager|
xprop (see the previous section
for how to do this). If we do this we see, among other things, the
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_DESKTOP
The application has set this property to indicate to the window manager
that the window is to be treated as a desktop. What that means in
practice is entirely at the whim of the window manager. The usual
approach would be not to decorate the window, and to size it to fill
the work area. In this example we don't have a window manager to read
program specified location: 0, 0
program specified minimum size: 1024 by 768
program specified maximum size: 1024 by 768
Nautilus knows that it is to be the desktop, and has asked for its
size to be full-screen. Again, there is no window manager around to
read this property. But, nevertheless, the window has appeared full
screen. This is because, in addition to setting this property, the
Nautilus application will have requested the X server directly to set
its window to full screen. This is considered good practice in X
programming — an application should, so far as possible, be capable of
running without a window manager. Had there been a window manager running,
the X server would have rejected the application's request to set its
size full screen, and delegated the size operation to the window manager,
which would have read the WM_NORMAL_HINTS property.
The crucial importance of the collaboration between the window manager
and the application can be seen if we try to run the Nautilus
desktop with an old window manager like
| That can't be right! The Nautilus desktop running with the twm window manager, which treats it just as an ordinary window|
twm has honoured the size request and, although it's not clear
from a screenshot, it also honours the request for the desktop to be
non-user-sizeable (i.e., maximum and minimum sizes the same). But
that's as far as it goes. WM_NORMAL_HINTS is a traditional X property that
twm understands, but _NET_WM_WINDOW_TYPE is an extended
property of which
twm has no knowledge. Consequently, the
user can move the desktop around with its frame, and even iconify it. Or
just close it altogether. There's really no better demonstration than this
that the desktop is just an ordinary X application.
A panel or dock is a generic term for any user interface feature that sticks
to the edges of the screen, and typically appears above other windows.
The term 'taskbar' is often used synonymously with 'panel', but sometimes
it refers to a component for selecting applications that lives inside
a specific panel. A 'pager' is an application for selecting between different
virtual desktops and, again, it might be a panel in its own right or a
component of another panel. A 'tray' or 'system tray', or
'notification area' is a place where
other applications can display information and, again, it might be a
separate panel or it might not.
Some desktop systems provide panels that have pretty sophisticated functionality
in their own right, such a menu launchers, window selectors, system monitors,
and even command prompts. But modern practice is for the panel to be
essentially an empty window.
Unfortunately, the Gnome panel application
easily be made to run without a heap of other Gnome stuff in place, but
there are plenty of other panels that can. For the following demonstrations
I have used
fbpanel, which is available from the usual
Linux repositories. For reasons I shall explain, for this demonstration to
be clear, it is necessary to shut down the Xvnc server and re-establish a
session. Then start some applications, but not a window manager, and then
$ fbpanel --display :3 &
You'll see a display something like this:
You'll notice that the panel is in the right place, and has some capabilities — it can pop up a launcher menu, for example. But what it can't
do, and should be able to do, is display the desktop pager or the
taskbar. That is, there are applications running, but
fbpanel running without a window manager or desktop
does not seem to know about them. Why should that be?
The reason is that there is no window manager running, and it is the
job of the window manager to maintain, as a property on the root window,
the list of windows currently being managed.
This is why I suggested starting the Xvnc session again — if you had
metacity window manager in a previous demonstration,
the relevant property would most likely still be set on the root window,
and you'd still see a list of windows (possibly an incorrect list).
And, indeed, if you start
metacity now, leaving
fbpanel running, you'll see something like this:
Notice that the taskbar now shows entries for the two applications that are
running, and the pager is active, showing that we are currently looking
at the first desktop. This is quite clever, in its own way —
fbpanel running with metacity. Note that the taskbar and desktop pager are now operational
fbpanel, and the X server were developed
completely independently of one another, and yet by following a few
rudimentary conventions are able to work together tolerably well.
Incidentally, notice that the fonts in the
gnome-calculator menu are the same. This is no
coincidence — they are both based on the GTK toolkit, and read the same
configuration repository. Mix-and-match desktops won't always produce
such a fortunate result in this area.
If you look at the properties of the
the follow entries are quite interesting.
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_DOCK
This is the request to the window manager to treat this window as a dock.
As with the desktop window, it's up to the window manager to decide
what that means in terms of the user interface.
_NET_WM_STRUT(CARDINAL) = 0, 0, 0, 26
_NET_WM_STRUT_PARTIAL(CARDINAL) = 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 1024
These two properties are both telling the window manager to shrink its
work area to allow space for the dock, which requires 26 pixels from the
bottom of the screen. WM_STRUT_PARTIAL is a more complex property, as
it allows an area to be specified that is not the entire width or height
of the screen (although it is in this case). Notice that nothing in either
of these properties tells the window manager to put the panel at
the bottom of the screen. The window manager will either deduce the
location, based on the fact that only the 'bottom' parameter of
_NET_WM_STRUT is non-zero, or it will rely on the WM_NORMAL_HINTS
property which the application should have set correctly.
It's not clear what a window manager should do if WM_NORMAL_HINTS
puts the panel at the to of the screen, and _NET_WM_STRUT partial reserves
space at the bottom. There's nothing logically inconsistent in doing
this, as these properties have different purposes. But it makes little
Applets and window embedding
fbpanel is a self-contained panel application and does not
follow the modern convention of presenting an empty window for other
small applications ('applets') to fill. But it is easy to see how
this technique does work, and it provides what seems to me to be the
most remarkable display of interoperability of all.
In the screenshot below, I am running the Pidgin instant messenger application.
Note that it has created a control (the speech bubble icon) in the
fbpanel window. If you click that control it will pop up
a menu with which you can interact quite successfully.
fbpanel and Pidgin know absolutely nothing about
each other. How is this possible?
The trick here is the use of the XEMBED protocol. Using XEMBED we can
embed one application's X window inside another. Remember that X is
completely democratic — the child windows of a particular parent window
need not belong to the same application. They need not even be running
on the same physical host. So X already provides a method to put the
speech-bubble icon of Pidgin inside the panel, and make it act as if
it belonged there.
What XEMBED does is provide a set of
messages and data structures that one application can use to
request another to reparent its window. The message protocol allows
for success or failure to be notified, and for events like change of
keyboard focus to be handled smoothly.
What XEMBED does not provide is a way for the Pidgin application to determine
which window to send its embedding requests. It needs to find the
panel window or, more specifically, the window that
fbpanel hosting the notification icon from the
has designated to handle such requests. How does it do that?
If you've read the previous sections, you'll probably be thinking that
this will be done through root window properties. It would be
very easy, for example, for the panel application to set a property
on the root window carrying its own window ID.
The problem with this approach is one of synchronization. Suppose the
user (or the system configuration) tried to start two panels, each of
which tried to register itself as the panel for the purposes
of embedding. We could implement a system where the first application
to start sets the property on the root window, and subsequent invocations
check that property and don't continue if it is already set.
Apart from being prone to race conditions (admittedly unlikely), the
problem here is deciding what to do if the first panel application
fails. There's nothing to stop the root property persisting indefinitely
in that case, and it will then be impossible to launch a new panel, or
even restart the failed one.
The solution is to make use of the mechanism of selections.
Selections are small blocks of data held by the X server, and which
behave in a way like semaphores. At any given time a particular
client owns a specific selection, and although another application
can take it away, there's no ambiguity about who owns it. If the
owning application fails, the X server knows about it, and releases
the ownership of the selection.
Selections are most commonly used for drag-and-drop operations, as they
provide a neat way to share small-ish pieces of data between
applications. But they also provide a neat semaphore mechanism.
The first panel application to start up will obtain ownership of a
particular selection. Any other panel will check who owns the selection,
find that it is owned by somebody else, and not continue. If the first
panel application fails, the selection will automatically become
unowned, so the next panel to start up will find that it can continue.
Exactly the same mechanism is used by most X desktop components that really
need to be unique on a particular X server. For example, it is used
by window managers to check that there is no other window manager
running, as there's not much purpose in running two window managers on
the same display.