Logo Computer scientist,
engineer, and educator

Underneath the Linux desktop

← 3. The window manager 5. Other bits and pieces →

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 be explained.

Desktops

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 Nautilus desktop running without even a window manager
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 xprop (see the previous section for how to do this). If we do this we see, among other things, the following properties.

_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 this property.
WM_NORMAL_HINTS(WM_SIZE_HINTS):
                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 twm.
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 even 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.

Panels

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 gnome-panel cannot 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 run fbpanel:

$ fbpanel --display :3 &
You'll see a display something like this:
fbpanel running without a window manager or desktop
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 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 run the 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:
fbpanel running with metacity. Note that the taskbar and desktop pager are now operational
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 — metacity, 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 fbpanel menu and 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 fbpanel window, 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 practical sense.

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. And yet fbpanel and Pidgin know absolutely nothing about each other. How is this possible?
fbpanel hosting the notification icon from the pidgin messenger
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 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.

← 3. The window manager 5. Other bits and pieces →

Copyright © 1994-2013 Kevin Boone. Updated Jul 30 2010