In this article we’re going to go over the big list of words found in
When I worked on 2bwm I didn’t have much experience with X programming in general. I’ve sort of learned it on the spot. That’s why I’m trying to gain more knowledge before continuing to re-rewrite 2bwm from scratch. Now that I’ve got a bit more background I think it’s good to share it with the world, for others that are like me, looking for knowledge and good articles on the topic.
I’ve set the ground for the basic differences between
XCB, Xlib, Wayland, and others in “Xcb, X11, Xlib,
Explained what we meant by window
managers and desktop environments in “WM &
had a group discussion about the topic of customization/ricing in
I’ve also tried to explain the font stack in “Fonts on
And I’m now implementing good font support for
xcb, which I’m going to write
about later on.
Apart from the basics of basics in X11, like event creation, event loop, mapping windows, drawing on them using graphic context, etc. I’d like in this article to focus on explaining topics that are more confusing and less discussed. The kind of topics that are or written too shallowly or written only in not-so-approachable technical papers.
Drawables, regions, and shapes
If you started reading a bit about the X windowing system, for example by going through the basic Xlib or XCB tutorials, then you’ve certainly heard of X drawables. This is an abstract concept that might be a bit confusing, what’s a drawable?
The quick answer is that X drawables are surfaces to draw on, you pass
their identifier to any drawing functions (geometric shapes and figures,
using graphic context, font, etc.) and they’re all going to be treated
the same way. However, that’s too broad. To be precise X Drawable is an
abstract type, and it’s implemented by both X Windows and Pixmaps. It’s a
way to not differentiate, making it generic, when drawing on any of them.
The difference between a window and a pixmap is that a window is an actual window that can be mapped on the screen, with attributes and that can have atoms, receive events, etc. The pixmap is only a surface to draw on, hold in memory but never directly on the screen. To be drawn on the screen a pixmap has to be copied unto a window, think about it like a stamp that can be reused.
As far as the differences in drawing mechanism goes, when we draw on the pixmap we draw on specifically allocated memory buffer for it, each pixmap creates its own buffer/its own surface. When we draw on a window we draw directly on the region of the front buffer that is owned by this window. The front buffer is the final surface, where everything is combined and drawn on, that X server takes and display on the screen pixel per pixel. In a way, this is sort of like the pixmap of the root window, that is the first parent of all windows. We’ll explain parenting a bit more in a sec, meanwhile here’s an illustration that can help understand this.
The X server associates the visible region owned by a window on the front
buffer with the window so that it can pass on events happening on that
region if they have been registered to be passed on by that window. For
example a window might register the expose event, which is an event
that is triggered when the region owned by the window is displayed on
the screen. This is what is meant by region, it’s the portion of the
front buffer that is shown, owned, and associated to a window.
There are actually two regions: the bounding region and the clip region. The bounding region is the region that we’ve been talking about thus far, the surface occupied by the window to be drawn on and receiving events. However, windows can have borders and this creates a subset inside the window delimited by the borders, this is the clip region: the area in the bounding region minus the border.
Those regions usually have rectangular shapes, however using an extension
called X Shape we can choose to use any arbitrary shape for the window
regions modifying both bounding regions and clip regions. The new region
shapes are called client regions: client bounding region and client
clip region. Inside the X server the window is still represented as a
rectangle but everything that happens outside the client bounding region
and withing the default bounding region (if the window was considered
a rectangle) is ignored. The intersection between the default bounding
region and the client bounding region is what is actually displayed,
the effective bounding region.
Here’s a summary.
There’s one thing we need to mention in what we’ve talked earlier (region,
drawing, events) to make it fully precise.
We said the root window was the parent of all windows and that other windows own their bounding regions over it, but the X windowing system allows any window to be the parent of another window, and that child window will own a region in it. This is what we call reparenting.
Reparenting creates a hierarchical structure of windows, each owning
a region within the other window and registering to events from that
window. When an event is received on the root window it’ll bubble up to
its direct children, the top-level windows which have as parent the root
window, and if those children have children that registered to receive
this event and the event was received on a region that is owned by them
then they’ll receive it, and it continues like that.
Windows within other windows are called sub-windows. Those sub-windows can only live within the clip region of their parent (antecedent clipping), this is the reason it is called “clip” because other windows are clipped to it. Their X and Y position are relative to the parent window, like top-level windows have they X and Y position relative to the root window. This also means that if you move the parent window it’ll move all the sub-windows contained in it.
The clear disadvantage with using a complex layer of sub-windows is that it’s expensive to push the events all around and to assign who can draw where and within what. You can find a summary in this illustration.
Redirecting & Composition
The disadvantage with having windows drawn directly on the front buffer is that if some of their region is hidden by another window there’s no way to access the pixels that would’ve been there. All you have access to is what is currently seen. With such mechanism it becomes impossible to create iconic representation of windows in a taskbar for example, or create an overview mechanism when “alt-tabbing”, or to create transparency, etc.
This is where the composite extension comes as a solution. This extension
allows windows to redirect their drawing to an offscreen, not drawn
on the screen, pixmap instead of the front buffer. This means that the
full content of the window is available in that pixmap to be accessed
by other applications.
However this poses two issues, the first is that pixmaps are rectangular, and the second is that those redirected offscreen pixmaps are not drawn on the screen, and so they need to be handled and drawn by another program. The first point is solved via an extension called the X Fixes extension, an extension that has independent fixes for many things. The relevant fixes are about region object manipulation. As for the other point it is up to whoever wants to use the composition extension to implement how the pixmaps are joined back together and drawn on the front buffer, which is what we’re going to discuss next, but first an illustration.
Composition, Rendering, & Undirecting
As we’ve said the role of mixing together the offscreen pixmaps and draw
them on the front buffer should be delegated to a third party software
which we call the compositor.
There are many ways to implement this compositor but all of them have to do some rendering, that is manipulating the pixels of those pixmaps to create a final image suited to be displayed on the screen. One thing we didn’t mention in the previous section is that the window still owns the region on the front buffer, so it still receives events that are happening on it, even though the drawing is redirected somewhere else. And so the compositor has to respect the positions of the windows.
There are many rendering engines, X provides one via the extension X render but compositors don’t have to be limited to using it, the OpenGL provides a way to convert from pixmap to texture, the type of data it can handle. So here you can imagine all sort of complex manipulation that can happen on those pixmaps.
However, all of this is costly, pixmaps are drawn offscreen, the compositor has to join them back together the way it likes via whatever renderer it has chosen and it has to send back that final result to the X server for it to be drawn on the front buffer. This can be slow.
This is where the Direct Rendering Infrastructure for OpenGL (DRI) and the Accelerated indirect GLX (AIGLX) come in to the rescue. There’s an early obsolete solution called Xgl which is a custom Xserver implementation which allows direct rendering, that is the windows can send directly opengl command to the graphic card, and a newer more flexible one called AIGLX that let the windows send GLX (protocol of an X extension) commands to the server and let the server send those to the graphic card in an accelerated way. Both of those try to reduce the overhead of the transfer from the OpenGL renderer with the X server by sharing a direct buffer with it. This also means that those solutions are machine dependent and won’t work over the network.
The last issue it poses is for applications that don’t want to pass by the compositor because there’s no need to: full screen applications. Full screen applications usually want full graphical power and passing through composition might be too extensive. This is why some compositors are smart enough to turn off redirection for full screen application and letting them own the front buffer all to themselves. This is called undirecting.
Checkout this illustration to better grasp all of this.
(NB: As stated here, AIGLX is sort of deprecated, disabled by default in most installation, most seem to rely on XRender instead)
Types of window managers
What are the ways to build a window manager? This is an interesting
question and based on the content of this article you might have
many ideas. A window manager could be rough, without special border,
without special shape. A window manager could reparent the windows to
one that it uses for decoration. A window manager could create a window
for decoration that it puts in the back of the new spawned windows,
moves it along with it as a decoration, without reparenting it. A window
manager could implement composition in itself instead of relying on a
third party application, adding decoration as it wishes in the rendering
and manipulating the region using XFixes so that it becomes part of
the window. So many ways to create a window manager.
However there are some standards that all window managers should try to follow, those are the ICCCM, Inter-Client Communication Conventions Manual, and EWMH, Extended Window Manager Hints, standards set by the XDG, the X desktop group, now called “freedesktop.org”. The EWMH are special atoms set on windows that the window manager should respect and behave accordingly. For instance a window might have an EWMH that says it’s a taskbar, and so the window manager should not draw borders around it. There’s a lot of specification, check the ewmh spec to know more. The ICCCM is similar in nature but is not limited to the window manager, the clients should also respect those hints, in fact the EWMH specs are based on the more generic ICCCM specs. Be sure to check them out here.
I hope this article will fill the gap and that it helps understand those topics. The X windowing system is slowly getting deprecated in favor of Wayland but the basis is similar so knowing a bit more about X would help.
Xplain the basics
the real story behind Wayland and X
The linux graphic stack
The linux graphic stack again
X Shape documentation
Xplain about composite
X11 compositor tutorial
texture from pixmap
Issues with gaming with compositor
About writing a window manager
Tutorial on writing a window manager
If you want to have a more in depth discussion I'm always available by email or irc.
We can discuss and argue about what you like and dislike, about new ideas to consider, opinions, etc..
If you don't feel like "having a discussion" or are intimidated by emails then you can simply say something small in the comment sections below and/or share it with your friends.