X Window System core protocol explained

The X Window System core protocol[1] [2] [3] is the base protocol of the X Window System, which is a networked windowing system for bitmap displays used to build graphical user interfaces on Unix, Unix-like, and other operating systems. The X Window System is based on a client–server model: a single server controls the input/output hardware, such as the screen, the keyboard, and the mouse; all application programs act as clients, interacting with the user and with the other clients via the server. This interaction is regulated by the X Window System core protocol. Other protocols related to the X Window System exist, both built at the top of the X Window System core protocol or as separate protocols.

In the X Window System core protocol, only four kinds of packets are sent, asynchronously, over the network: requests, replies, events, and errors. Requests are sent by a client to the server to ask it to perform some operation (for example, create a new window) and to send back data it holds. Replies are sent by the server to provide such data. Events are sent by the server to notify clients of user activity or other occurrences they are interested in. Errors are packets sent by the server to notify a client of errors occurred during processing of its requests. Requests may generate replies, events, and errors; other than this, the protocol does not mandate a specific order in which packets are sent over the network. Some extensions to the core protocol exist, each one having its own requests, replies, events, and errors.

X originated at MIT in 1984 (its release X11 appeared in September 1987). Its designers Bob Scheifler and Jim Gettys set as an early principle that its core protocol was to "create mechanism, not policy". As a result, the core protocol does not specify the interaction between clients and between a client and the user. These interactions are the subject of separate specifications,[4] such as the ICCCM and the freedesktop.org specifications, and are typically enforced automatically by using a given widget set.

Overview

Communication between server and clients is done by exchanging packets over a channel. The connection is established by the client (how the client is started is not specified in the protocol). The client also sends the first packet, containing the byte order to be used and information about the version of the protocol and the kind of authentication the client expects the server to use. The server answers by sending back a packet stating the acceptance or refusal of the connection, or with a request for a further authentication. If the connection is accepted, the acceptance packet contains data for the client to use in the subsequent interaction with the server.

After connection is established, four types of packets are exchanged between client and server over the channel:

  1. Request: The client requests information from the server or requests it to perform an action.
  2. Reply: The server responds to a request. Not all requests generate replies.
  3. Event: The server informs the client of an event, such as keyboard or mouse input, a window being moved, resized or exposed, etc.
  4. Error: The server sends an error packet if a request is invalid. Since requests are queued, error packets generated by a request may not be sent immediately.

Request and reply packets have varying length, while event and error packets have a fixed length of 32 bytes.

Request packets are numbered sequentially by the server as soon as it receives them: the first request from a client is numbered 1, the second 2, etc. The least significant 16 bits of the sequential number of a request is included in the reply and error packets generated by the request, if any. They are also included in event packets to indicate the sequential number of the request that the server is currently processing or has just finished processing.

Windows

What is usually called a window in most graphical user interfaces is called a top-level window in the X Window System. The term window is also used to denote windows that lie within another window, that is, the subwindows of a parent window. Graphical elements such as buttons, menus, icons, etc. can be realized using subwindows.

A client can request the creation of a window. More precisely, it can request the creation of a subwindow of an existing window. As a result, the windows created by clients are arranged in a tree (a hierarchy). The root of this tree is the root window, which is a special window created automatically by the server at startup. All other windows are directly or indirectly subwindows of the root window. The top-level windows are the direct subwindows of the root window. Visibly, the root window is as large as the virtual desktop, and lies behind all other windows. The content of a window is not always guaranteed to be preserved over time. In particular, the window content may be destroyed when the window is moved, resized, covered by other windows, and in general made totally or partly non-visible. In particular, content is lost if the X server is not maintaining a backing store of the window content. The client can request backing store for a window to be maintained, but there is no obligation for the server to do so. Therefore, clients cannot assume that backing store is maintained. If a visible part of a window has an unspecified content, an event is sent to notify the client that the window content has to be drawn again.

Every window has an associated set of attributes, such as the geometry of the window (size and position), the background image, whether backing store has been requested for it, etc. The protocol includes requests for a client to inspect and change the attributes of a window.

Windows can be InputOutput or InputOnly. InputOutput windows can be shown on the screen and are used for drawing. InputOnly windows are never shown on the screen and are used only to receive input.

The decorative frame and title bar (possibly including buttons) that is usually seen around windows are created by the window manager, not by the client that creates the window. The window manager also handles input related to these elements, such as resizing the window when the user clicks and drags the window frame. Clients usually operate on the window they created disregarding the changes operated by the window manager. A change it has to take into account is that re-parenting window managers, which almost all modern window managers are, change the parent of top-level windows to a window that is not the root. From the point of view of the core protocol, the window manager is a client, not different from the other applications.

Data about a window can be obtained by running the xwininfo program. Passing it the -tree command-line argument, this program shows the tree of subwindows of a window, along with their identifiers and geometry data.

Pixmaps and drawables

A pixmap is a region of memory that can be used for drawing. Unlike windows, pixmaps are not automatically shown on the screen. However, the content of a pixmap (or a part of it) can be transferred to a window and vice versa. This allows for techniques such as double buffering. Most of the graphical operations that can be done on windows can also be done on pixmaps.

Windows and pixmaps are collectively named drawables, and their content data resides on the server. A client can however request the content of a drawable to be transferred from the server to the client or vice versa.

Graphic contexts and fonts

The client can request a number of graphic operations, such as clearing an area, copying an area into another, drawing points, lines, rectangles, and text. Beside clearing, all operations are possible on all drawables, both windows and pixmaps.

Most requests for graphic operations include a graphic context, which is a structure that contains the parameters of the graphic operations. A graphic context includes the foreground color, the background color, the font of text, and other graphic parameters. When requesting a graphic operation, the client includes a graphic context. Not all parameters of the graphic context affect the operation: for example, the font does not affect drawing a line.

The core protocol specifies the use of server-side fonts.[5] Such fonts are stored as files, and the server accesses them either directly via the local filesystem or via the network from another program called font server. Clients can request the list of fonts available to the server and can request a font to be loaded (if not already) or unloaded (if not used by other clients) by the server. A client can request general information about a font (for example, the font ascent) and the space a specific string takes when drawn with a specific font.

The names of the fonts are arbitrary strings at the level of the X Window core protocol. The X logical font description conventions[6] specify how fonts should be named according to their attributes. These conventions also specify the values of optional properties that can be attached to fonts.

The xlsfonts program prints the list of fonts stored in the server. The xfontsel program shows the glyphs of fonts, and allows the user to select the name of a font for pasting it in another window.

The use of server-side fonts is currently considered deprecated in favour of client-side fonts.[7] Such fonts are rendered by the client, not by the server, with the support of the Xft or cairo libraries and the XRender extension. No specification on client-side fonts is given in the core protocol.

Resources and identifiers

All data about windows, pixmaps, fonts, etc. are stored in the server. The client knows identifiers of these objects—integers it uses as names for them when interacting with the server. For example, if a client wishes a window to be created, it requests the server to create a window with a given identifier. The identifier can be later used by the client to request, for example, a string to be drawn in the window. The following objects reside in the server and are known by the client via a numerical identifier:

These objects are called resources. When a client requests the creation of one such resource, it also specifies an identifier for it. For example, for creating a new window, the client specifies both the attributes of the window (parent, width, height, etc.) and the identifier to associate with the window.

Identifiers are 32-bit integers with their three most significant bits equal to zero. Every client has its own set of identifiers it can use for creating new resources. This set is specified by the server as two integers included in the acceptance packet (the packet it sends to the client to inform it that the connection is accepted). Clients choose identifiers that are in this set in such a way they do not clash: two objects among windows, pixmaps, fonts, colormaps, and graphic contexts cannot have the same identifier.

Once a resource has been created, its identifier is used by the client to request operations about it to the server. Some operations affect the given resource (for example, requests to move windows); others ask for resource data stored from the server (for example, requests for the attributes of windows).

Identifiers are unique to the server, not only to the client; for example, no two windows have the same identifier, even if created by two different clients. A client can access any object given its identifier. In particular, it can also access resources created by any other client, even if their identifiers are outside the set of identifiers it can create. As a result, two clients connected to the same server can use the same identifier to refer to the same resource. For example, if a client creates a window of identifier 0x1e00021 and passes this number 0x1e00021 to another application (via any available means, for example by storing this number in a file that is also accessible to the other application), this other application is able to operate on the very same window. This possibility is for example exploited by the X Window version of Ghostview: this program creates a subwindow, storing its identifier in an environment variable, and calls Ghostscript; this program draws the content of the PostScript file to show in this window.[8]

Resources are normally destroyed when the client that created them closes the connection with the server. However, before closing connection, a client can request the server not to destroy them.

Events

Events are packets sent by the server to a client to communicate that something the client may be interested in has happened. For example, an event is sent when the user presses a key or clicks a mouse button. Events are not only used for input: for example, events are sent to indicate the creation of new subwindows of a given window.

Every event is relative to a window. For example, if the user clicks when the pointer is in a window, the event will be relative to that window. The event packet contains the identifier of that window.

A client can request the server to send an event to another client; this is used for communication between clients. Such an event is for example generated when a client requests the text that is currently selected: this event is sent to the client that is currently handling the window that holds the selection.

The Expose event is sent when an area of a window of destroyed and content is made visible. The content of a window may be destroyed in some conditions, for example, if the window is covered and the server is not maintaining a backing store. The server generates an Expose event to notify the client that a part of the window has to be drawn.

Most kinds of events are sent only if the client previously stated an interest in them. This is because clients may only be interested in some kind of events. For example, a client may be interested in keyboard-related events but not in mouse-related events. Some kinds of events are however sent to clients even if they have not specifically requested them. Clients specify which kinds of events they want to be sent by setting an attribute of a window. For example, in order to redraw a window when its content has been destroyed, a client must receive the Expose events, which inform it that the window needs to be drawn again. The client will however be sent Expose events only if the client has previously stated its interest in these events, which is done by appropriately setting the event mask attribute of the window.

Different clients can request events on the same window. They can even set different event masks on the same window. For example, a client may request only keyboard events on a window while another client requests only mouse events on the same window. This is possible because the server, for each window, maintains a separate event mask for each client. However, there are some kinds of events that can only be selected by one client at time for each window. In particular, these events report mouse button clicks and some changes related to window management.

The xev program shows the events relative to a window. In particular, xev -id WID requests all possible events relative to the window of identifier WID and prints them.

Example

The following is a possible example of interaction between a server and a program that creates a window with a black box in it and exits on a keypress. In this example, the server does not send any reply because the client requests do not generate replies. These requests could generate errors.

  1. The client opens the connection with the server and sends the initial packet specifying the byte order it is using.
  2. The server accepts the connection (no authorization is involved in this example) by sending an appropriate packet, which contains other information such as the identifier of the root window (e.g., 0x0000002b) and which identifiers the client can create.
  3. The client requests the creation of a default graphic context with identifier 0x00200000 (this request, like the other requests of this example, does not generate replies from the server)
  4. The client requests the server to create a top-level window (that is, it specifies the parent to be the root window 0x0000002b) with identifier 0x00200001, size 200x200, position (10,10), etc.
  5. The client requests a change in the attributes of the window 0x00200001, specifying it is interested in receiving Expose and KeyPress events.
  6. The client requests the window 0x00200001 to be mapped (shown on the screen)
  7. When the window is made visible and its content has to be drawn, the server sends the client an Expose event
  8. In response to this event, the client requests a box to be drawn by sending a PolyFillRectangle request with window 0x00200001 and graphic context 0x00200000

If the window is covered by another window and uncovered again, assuming that backing store is not maintained:

  1. The server sends another Expose event to tell the client that the window has to be drawn again
  2. The client redraws the window by sending a PolyFillRectangle request

If a key is pressed:

  1. The server sends a KeyPress event to the client to notify it that the user has pressed a key
  2. The client reacts appropriately (in this case, it terminates)

Colors

At the protocol level, a color is represented by a 32-bit unsigned integer, called a pixelvalue. The following elements affect the representation of colors:

  1. the color depth
  2. the colormap, which is a table containing red, green, and blue intensity values
  3. the visual type, which specifies how the table is used to represent colors

In the easiest case, the colormap is a table containing a RGB triple in each row. A pixelvalue x represents the color contained in the x-th row of the table. If the client can change the entries in the colormap, this representation is identified by the PseudoColor visual class. The visual class StaticColor is similar, but the client cannot change the entries in the colormap.

There are a total of six possible visual classes, each one identifying a different way for representing an RGB triple with a pixelvalue. PseudoColor and StaticColor are two. Another two are GrayScale and StaticGray, which differ in that they only display shades of grey.

The two remaining visual classes differ from the ones above because they break pixelvalues in three parts and use three separate tables for the red, green, and blue intensity. According to this color representation, a pixelvalue is converted into an RGB triple as follows:

  1. the pixelvalue is seen as a sequence of bits
  2. this sequence is broken in three parts
  3. each of these three chunks of bits is seen as an integer and used as an index to find a value in each of three separate tables

This mechanism requires the colormap to be composed of three separate tables, one for each primary color. The result of the conversion is still a triple of intensity values. The visual classes using this representation are the DirectColor and TrueColor ones, differing on whether the client can change colormaps or not.

These six mechanisms for representing colors with pixelvalues all require some additional parameters to work. These parameters are collected into a visual type, which contains a visual class and other parameters of the representation of colors. Each server has a fixed set of visualtypes, each one associated with a numerical identifier. These identifiers are 32-bit unsigned integers, but are not necessarily different from identifiers of resources or atoms.

When the connection from a client is accepted, the acceptance packet sent by the server contains a sequence of blocks, each one containing information about a single screen. For each screen, the relative block contains a list of other blocks, each one relative to a specific color depth that is supported by the screen. For each supported depth, this list contains a list of visualtypes. As a result, each screen is associated a number of possible depths, and each depth of each screen is associated a number of possible visual types. A given visual type can be used for more screens and for different depths.

For each visual type, the acceptance packet contains both its identifier and the actual parameters it contains (visual class, etc.) The client stores this information, as it cannot request it afterwards. Moreover, clients cannot change or create new visual types. Requests for creation of a new window include the depth and the identifier of the visual type to use for representing colors of this window.

Colormaps are used regardless of whether the hardware controlling the screen (e.g., a graphic card) uses a palette, which is a table that is also used for representing colors. Servers use colormaps even if the hardware is not using a palette. Whenever the hardware uses palettes, only a limited number of colormaps can be installed. In particular, a colormap is installed when the hardware shows colors according to it. A client can request the server to install a colormap. However, this may require the uninstalling of another colormap: the effect is that windows using the uninstalled colormap are not shown with the correct color, an effect dubbed color flashing or technicolor. This problem can be solved using standard colormaps, which are colormaps with a predictable association between pixelvalues and colors. Thanks to this property, standard colormaps can be used by different applications.

The creation of colormaps is regulated by the ICCCM convention. Standard colormaps are regulated by the ICCCM and by the Xlib specification.

A part of the X colour system is the X Color Management System (xcms). This system was introduced with X11R6 Release 5 in 1991. This system consists of several additional features in xlib, found in the Xcms* series of functions. This system defines device independent color schemes which can be converted into device dependent RGB systems. The system consists of the xlib Xcms* functions and as well the X Device Color Characterization Convention (XDCCC) which describes how to convert the various device independent colour systems into device dependent RGB colour systems. This system supports the CIEXYZ, xyY, CIELUV and CIELAB and as well the TekHVC colour systems.http://insar.stanford.edu/~lharcke/programming/Xcms/, http://tronche.com/gui/x/xlib/color/

Atoms

Atoms are 32-bit integers representing strings. The protocol designers introduced atoms because they represent strings in a short and fixed size:[9] while a string may be arbitrarily long, an atom is always a 32-bit integer. Atom brevity was exploited by mandating their use in the kinds of packets that are likely to be sent many times with the same strings; this results in a more efficient use of the network. The fixed size of atoms was exploited by specifying a fixed size for events, namely 32 bytes: fixed-size packets can contain atoms, while they cannot contain long strings.

Precisely, atoms are identifiers of strings stored in the server. They are similar to the identifiers of resources (Windows, Pixmaps, etc.) but differ from them in two ways. First, the identifiers of atoms are chosen by the server, not by the client. In other words, when a client requests the creation of a new atom, it only sends the server the string to be stored, not its identifier; this identifier is chosen by the server and sent back as a reply to the client. The second important difference between resources and atoms is that atoms are not associated with clients. Once created, an atom survives until the server quits or resets (this is not the default behavior of resources).

Atoms are identifiers and are therefore unique. However, an atom and a resource identifier can coincide. The string associated with an atom is called the atom name. The name of an atom cannot be changed after creation, and no two atoms can have the same name. As a result, the name of an atom is commonly used to indicate the atom: “the atom ABCD” means, more precisely, “the atom whose associated string is ABCD.” or “the atom whose name is ABCD.” A client can request the creation of a new atom and can request for the atom (the identifier) of a given string. Some atoms are predefined (created by the server with given identifier and string). Atoms are used for a number of purposes, mostly related to communication between different clients connected to the same server. In particular, they are used in association with the properties of windows, which are described below.

The list of all atoms residing in a server can be printed out using the program xlsatoms. In particular, this program prints each atom (the identifier, that is, a number) with its name (its associated string).

Properties

Every window has a predefined set of attributes and a set of properties, all stored in the server and accessible to the clients via appropriate requests. Attributes are data about the window, such as its size, position, background color, etc. Properties are arbitrary pieces of data attached to a window. Unlike attributes, properties have no meaning at the level of the X Window core protocol. A client can store arbitrary data in a property of a window.

A property is characterized by a name, a type, and a value. Properties are similar to variables in imperative programming languages, in that a client can create a new property with a given name and type and store a value in it. Properties are associated to windows: two properties with the same name can exist on two different windows while having different types and values.

The name, type, and value of a property are strings; more precisely, they are atoms, that is, strings stored in the server and accessible to the clients via identifiers. A client application can access a given property by using the identifier of the atom containing the name of the property.

Properties are mostly used for inter-client communication. For example, the property named WM_NAME (the property named by the atom whose associated string is "WM_NAME") is used for storing the name of windows. Window managers typically read this property to display the name of windows in their title bar. Some types of inter-client communication use properties of the root window. For example, according to the freedesktop window manager specification,[10] window managers should store the identifier of the currently active window in the property named _NET_ACTIVE_WINDOW of the root window. The X resources, which contain parameters of programs, are also stored in properties of the root window; this way, all clients can access them, even if running on different computers. The xprop program prints the properties of a given window; xprop -root prints the name, type, and value of each property of the root window.

Notes and References

  1. Robert W. Scheifler and James Gettys: X Window System: Core and extension protocols, X version 11, releases 6 and 6.1, Digital Press 1996,
  2. RFC 1013
  3. Grant Edwards. An Introduction to X11 User Interfaces
  4. Jim Gettys. Open Source Desktop Technology Road Map
  5. Web site: comp.fonts FAQ: X11 Info. www.faqs.org.
  6. Web site: X Logical Font Description Conventions . 2005-12-30 . Jim Flowers . Stephen Gildea . 1994 . PDF . . . dead . https://web.archive.org/web/20050328124653/http://www.xfree86.org/current/xlfd.pdf . March 28, 2005 .
  7. Matthieu Herrb and Matthias Hopf. New Evolutions in the X Window System.
  8. Web site: Interface with ghostscript - GNU gv Manual. www.gnu.org.
  9. [David S. H. Rosenthal|David Rosenthal]
  10. Web site: wm-spec. www.freedesktop.org.