X11, Xorg, window managers, and Xwayland

Explain X11 clients, server policy and the Xwayland boundary.

13 min readChapter 128 of 168Intermediate → advanced
In this chapter

Before you start#

Read Wayland protocol objects, surface buffers and events, and compositors. This lesson studies Xorg server 21.1.13 and Xwayland 24.1.1 as separate source baselines. They are historical examples, not claims about installed versions.

Learning goals#

Explain how an X client communicates with a server, trace a validated window-creation request, distinguish Xorg's device-dependent and independent layers, and follow a rootless Xwayland window into a Wayland compositor. Interpret asynchronous errors, presentation and lifetime without accessing an existing desktop session.

Source walkthrough#

Xwayland bridges two protocols
Xwayland bridges two protocolsX client: Requests and receives events over the X connection → Xwayland server: Dispatches X requests and manages X resources (X11 requests). Window manager bridge: Coordinates X window policy → Xwayland server: Dispatches X requests and manages X resources (XWM protocol). X client: Requests and receives events over the X connection → Wayland compositor: Receives surfaces and controls output policy (surfaces and buffers)X11 requestsXWM protocolsurfaces and buffersX clientRequests and receives eventsover the X connectionWindow manager bridgeCoordinates X window policyXwayland serverDispatches X requests andmanages X resourcesWayland compositorReceives surfaces andcontrols output policy
X clientRequests and receives events over the X connection
Xwayland serverDispatches X requests and manages X resources
Window manager bridgeCoordinates X window policy
Xwayland serverDispatches X requests and manages X resources
X clientRequests and receives events over the X connection
Wayland compositorReceives surfaces and controls output policy
Read the text version
  • X client: Requests and receives events over the X connection → Xwayland server: Dispatches X requests and manages X resources (X11 requests)
  • Window manager bridge: Coordinates X window policy → Xwayland server: Dispatches X requests and manages X resources (XWM protocol)
  • X client: Requests and receives events over the X connection → Wayland compositor: Receives surfaces and controls output policy (surfaces and buffers)
Conceptual model. Rootless Xwayland is an X server and a Wayland client; the compositor remains the display authority.

X11 is a network-transparent window system protocol. An X server manages display-side resources and accepts connections from client programs. The server can run on the same machine as its clients; the names describe roles, not physical placement. Xlib and XCB are client libraries that marshal protocol requests and receive replies, events and errors. A window is an X server resource identified by an XID, not a process or necessarily a separate physical display. Pixmaps, graphics contexts and other resources also have IDs, with types and lifetimes enforced by the server. IDs are meaningful within the server's resource namespace and allocation rules, not globally unique forever.

A connection starts with byte-order negotiation and authentication data. Most subsequent protocol requests begin with an opcode and a length measured in four-byte units; request-specific fields follow, with padding and extension rules. A reply or error corresponds to a request sequence, while events can arrive asynchronously. Sequence fields on the wire are finite and wrap; a library uses connection bookkeeping to associate replies with outstanding requests. The sequence is not a globally unique timestamp, and receiving an event between two replies does not mean those requests were executed in that event's order. The Xorg server dispatch implementation shows the server's processing boundary.

XCB makes asynchronous operation explicit. A reply-producing request returns a cookie, which the client later uses to retrieve a reply or error. A request with no ordinary reply can still generate an error; a checked request can arrange for the library to report it through an explicit check. Unchecked errors may arrive through the event stream. Calling a library function can therefore succeed locally even though the server subsequently rejects the request. A client must consume and free replies and errors according to its library's rules, and keep the connection alive until pending operations have been handled or intentionally abandoned. Disconnect causes server-side resources owned by that connection to be released subject to resource-specific rules; it is not a synchronization event that saves application pointers from other threads.

Server request processing

Xorg separates device-independent X server machinery, often called DIX, from device-dependent code, or DDX, that integrates particular display and input implementations. DIX handles core request dispatch, resource validation and window semantics. DDX supplies screens and hardware-facing integration, while extensions introduce additional requests and events. A rootful Xorg server can use a DRM/KMS driver or other backend where configured; this is conditional on hardware, session permissions and driver. The Linux kernel implements device interfaces and isolation mechanisms, not X11 window IDs, X11 request dispatch, ICCCM policy or Xwayland's protocol bridge.

The main loop in Xorg 21.1.13 dix/dispatch.c, Dispatch, reads a client request. This excerpt is covered by the file's Open Group permissive license; surrounding scheduling and extension handling are omitted:

c
                result = ReadRequestFromClient(client);
                if (result <= 0) {
                    if (result < 0)
                        CloseDownClient(client);
                    break;
                }

The first statement asks the connection layer for a request. A nonpositive result leaves the inner request-processing loop. A negative result additionally closes down the client; the code does not pass an incomplete or failed read to an ordinary request handler. The surrounding function increments the client sequence for a request, identifies the major opcode, checks request length and dispatches through that client's request vector, subject to its hooks. A request handler's failure can become a protocol error; it does not imply the whole server must terminate. See also the pinned source archive.

ProcCreateWindow illustrates the resource boundary. It checks request size, verifies that the new window ID is legal for this client, looks up the parent with required access, checks the number of value-list entries against the mask, and rejects zero width or height. It calls CreateWindow, then registers the resulting resource if creation succeeded. An invalid parent, forbidden access, bad length or allocation failure therefore has a distinct outcome from a mapped window. Client code must not assume that allocating an XID locally means the server accepted the resource. Destroying a parent can also affect children; clients must handle corresponding events and errors rather than use stale IDs indefinitely.

From Xorg 21.1.13 dix/dispatch.c, ProcCreateWindow, under the file's Open Group permissive notice (surrounding code omitted):

c
    LEGAL_NEW_RESOURCE(stuff->wid, client);
    /* ... (lines omitted: parent lookup and value-count checks) ... */
    if (!stuff->width || !stuff->height) {
        client->errorValue = 0;
        return BadValue;
    }

The zero-size check runs before CreateWindow, so a zero-width request returns BadValue and never reaches the AddResource registration that follows the call. The excerpt does not show the parent lookup or the value-list check, nor how the client library reports the error, which arrives asynchronously unless the request is checked.

Windows, policy, compositing, and presentation

Creating an X window creates a server object in a hierarchy. Mapping asks that it become viewable subject to its ancestors and window manager policy. A window manager is another X client that selects appropriate events on the root and implements window placement, decorations and interaction. ICCCM describes conventions for cooperation between clients and window managers; EWMH adds common desktop conventions through properties and messages. These are conventions and protocols between programs, not functions provided by the Linux scheduler. A client may request a size or state without being entitled to force it.

The X Composite extension permits a compositing manager to redirect windows and combine their contents. A window manager and compositing manager may be combined in one process or be separate. Xorg can run without the same compositing policy as a modern desktop. Extensions such as Present and DRI3 add presentation and rendering-sharing mechanisms: DRI3 can transfer buffer descriptors over a local connection, and Present coordinates presentation of pixmaps and completion/idle events. Their availability, versions and synchronization behavior must be queried. Passing a file descriptor is an ownership and lifetime transfer under the relevant protocol; it does not imply that every frame is zero-copy or that a descriptor is a GPU address. A Present completion is distinct from the later condition that a particular backing pixmap can safely be reused. See the server's Present implementation and DRI3 implementation.

Glamor is an Xorg acceleration layer that can use OpenGL to implement X drawing operations. It is not synonymous with DRI3, the window manager, or a physical display driver. A driver can use a different acceleration path or software rendering. Likewise, an X11 application using a GPU might render into shared storage and present through extensions, while another uses core drawing requests. Buffer format, modifier, synchronization and renderer support constrain any specific path. A source trace must identify the actual extension and backend rather than claim all X rendering follows one pipeline.

Xwayland as an X server and Wayland client

Xwayland implements the X server side for X clients while acting as a Wayland client of a compositor. In rootless integration, an X window manager bridge, commonly called XWM, coordinates X window policy with the Wayland compositor's scene and shell management. Xwayland creates Wayland surfaces for suitable X windows and supplies their buffers; the compositor decides how those surfaces appear alongside native clients. The bridge has to correlate X window identity and Wayland surface identity, handle asynchronous creation and destruction on both connections, and avoid treating an XID as a Wayland object ID. An X window can disappear before all queued notifications are processed.

Who owns which layer
X clients
Speak the X11 protocol through Xlib or XCB.
Xorg DIX
Core request dispatch and resource validation.
Xorg DDX and extensions
Device backends; Present and DRI3 handle presentation and buffer sharing.
Xwayland and XWM
Acts as the X server for X clients and as a Wayland client.
Wayland compositor
Places surfaces and, in rootless mode, controls the outputs.
Kernel DRM/KMS
Device interface only; it has no X11 windows or ICCCM policy.
Conceptual model. Responsibility layers for Xorg 21.1.13 and Xwayland 24.1.1; a configuration map, not a runtime trace. Rootful, nested and headless setups differ.

From Xwayland 24.1.1 hw/xwayland/xwayland-window.c, xwl_window_attach_buffer, the file's permissive Intel copyright license; earlier declarations and later damage handling are omitted:

c
    if (!buffer) {
        ErrorF("Error getting buffer\n");
        return FALSE;
    }

    wl_surface_attach(xwl_window->surface, buffer, 0, 0);

The earlier code obtains a pixmap and attempts to obtain its Wayland buffer. If that lookup fails, it logs an error and returns false before attaching. If it succeeds, the final line attaches that buffer to the Wayland surface's pending state; it does not itself prove that the surface has been committed or displayed. The surrounding function describes damage, and xwl_window_post_damage checks failure before requesting a frame callback and clearing its tracked damage. Buffer release and completion remain separate from request submission. The Xwayland 24.1.1 release archive supplies the pinned source.

Rootless Xwayland normally does not acquire physical KMS ownership merely because it is an X server; the Wayland compositor's backend controls its outputs. A rootful Xorg server with a DRM backend has a different device relationship. Nested and headless configurations introduce further alternatives. Native Wayland and Xwayland may share renderer and DMA-BUF infrastructure, but an X11 application's requests are not magically native Wayland requests: Xwayland translates and manages an X server resource model. It must manage both X-side pixmap references and Wayland-side buffer uses during teardown.

Worked request and window timeline

Consider a synthetic XCB client connection. It allocates an XID W, sends CreateWindow as sequence 100 and MapWindow as sequence 101, and requests window attributes at sequence 102. A successful local send of 100 means bytes were queued; it is not proof that the server accepted W. Suppose the create request used a zero width. The server's ProcCreateWindow returns BadValue; W was not registered as a valid window. The later map or query can then produce a separate invalid-window error. The reply cookie for 102 identifies the query's result, not a general success certificate for request 100. With checked create, the client explicitly checks its error; otherwise its event/error handling must account for asynchronous errors.

A rejected create leaves no window
A rejected create leaves no window1. XCB client to ProcCreateWindow: CreateWindow W, seq 100, width 0. 2. ProcCreateWindow to XCB client (return): BadValue for seq 100. 3. XCB client to ProcMapWindow: MapWindow W, seq 101. 4. ProcMapWindow to XCB client (return): error: no valid window W. 5. XCB client to ProcGetWindowAttributes: GetWindowAttributes W, seq 102. 6. ProcGetWindowAttributes to XCB client (return): error: no valid window W.XCB clientProcCreateWindowProcMapWindowProcGetWindowAttributesCreateWindow W, seq100, width 0BadValue for seq 100MapWindow W, seq 101error: no valid window WGetWindowAttributes W, seq 102error: no valid window W
  1. XCB clientProcCreateWindow

    CreateWindow W, seq 100, width 0

  2. ProcCreateWindowXCB client

    Return. BadValue for seq 100

  3. XCB clientProcMapWindow

    MapWindow W, seq 101

  4. ProcMapWindowXCB client

    Return. error: no valid window W

  5. XCB clientProcGetWindowAttributes

    GetWindowAttributes W, seq 102

  6. ProcGetWindowAttributesXCB client

    Return. error: no valid window W

Time runs downward. Dashed arrows show returns.

Read the text version
  1. XCB client → ProcCreateWindow: CreateWindow W, seq 100, width 0
  2. ProcCreateWindow → XCB client (return): BadValue for seq 100
  3. XCB client → ProcMapWindow: MapWindow W, seq 101
  4. ProcMapWindow → XCB client (return): error: no valid window W
  5. XCB client → ProcGetWindowAttributes: GetWindowAttributes W, seq 102
  6. ProcGetWindowAttributes → XCB client (return): error: no valid window W
Conceptual model. Teaching model of the 100-102 timeline for Xorg 21.1.13. Only the zero-size BadValue check is verified in dix/dispatch.c; the later error codes are illustrative.

Now change the width to 640 and height to 480 and assume all other validation and allocation succeed. The server registers W. Mapping can be redirected to the window manager, which can apply its policy before the window becomes viewable. In a rootless Xwayland session, the integration associates the X window with a Wayland surface, obtains a usable buffer, attaches and eventually commits surface state. The Wayland compositor can render or otherwise place that surface. A window being mapped in X is not proof of physical presentation; an occluded surface may never appear on a monitor. When W is destroyed, both sides must retire their own references and queued callbacks safely. This is an explanatory sequence, not a captured session or a claim that all window managers follow identical timing.

Authentication and trust

An X authentication cookie controls whether a client may connect to a server under the server's configuration. It is a bearer secret; possessing it can grant access, and a local filesystem permission mistake can expose it. Authentication is not encryption: a network connection needs a separately protected transport where appropriate. Traditional X11 grants connected clients broad visibility and interaction capabilities, subject to extensions and policy; do not assume mutually untrusted X clients are isolated from one another merely because their windows are separate. Xwayland integrations can restrict or alter some behaviors, but their precise boundary depends on version and configuration.

Wayland's object and focus model changes the default interactions available to ordinary clients; it is not an all-purpose sandbox for a process that can access files, devices or privileged services through other means. Security conclusions require examining the entire session, authentication and application sandbox. This lesson does not inspect cookies, connect to the user's X server, read window titles or change access-control settings.

Sequence and resource lifetime details

The protocol's connection order matters, but it does not make a client-side cookie an owned server resource. A cookie tracks a request for the client library; an XID identifies a server resource, and each has separate reuse rules. After sequence numbers wrap on the wire, matching requires the library's outstanding-request bookkeeping. An application must not compare a short sequence field as though it were a universally increasing timestamp. Multiple client connections have independent request streams, so coordination between them needs an explicit protocol or synchronization mechanism.

A window manager can receive a request to map a window and decide when to perform the map. If the client disconnects during that negotiation, its resource may disappear before the manager acts. The manager must handle the resulting error or destruction event and discard associated state. Similarly, a Wayland compositor may destroy an associated surface while Xwayland still has queued X-side work; correct integration needs lifetime tracking on each side, not an assumption that two separate connections deliver destruction notifications simultaneously.

Practice#

The following self-contained model illustrates request order and asynchronous errors without opening an X socket. It is synthetic, not an X server test:

sh
python3 - <<'PY'
requests = [(100, 'create width=0'), (101, 'map W'), (102, 'get attributes W')]
results = {100: 'BadValue', 101: 'BadWindow', 102: 'BadWindow'}
for seq, request in requests:
    print(seq, request, '->', results[seq])
assert results[100] != 'success'
PY

The expected three lines show that subsequent requests can fail after the original bad creation. Replace the model's result for 100 with success and explain why that alone does not establish that a window is visible. For a source-only alternative, use the ProcCreateWindow checks described above: with width zero, the path returns BadValue before resource registration; with positive dimensions, parent lookup and allocation can still fail. Deliver a timeline naming each request, possible error and which object exists. The Python output is authored teaching data, not observed X11 traffic.

Knowledge check#

  1. What distinguishes an XID allocated by a client from an accepted server resource?
  2. Why can a void request still require error handling?
  3. What does wl_surface_attach establish in the Xwayland example?
  4. Who controls physical KMS in a typical rootless Xwayland session?
  5. Does an X authentication cookie encrypt X traffic or isolate connected clients?

Answers#

  1. The client chooses an ID within its allowed range, but the server must validate the request and register the resource. A failed create leaves no usable window under that ID.
  2. Server processing is asynchronous; a no-reply request can still fail validation and produce a protocol error that the client must check or dispatch.
  3. It places a buffer in pending surface state. A subsequent commit and compositor processing are separate, and neither attach nor commit proves presentation.
  4. The Wayland compositor's output backend ordinarily controls the display. Xwayland is the X server for X clients and a client of that compositor; other configurations differ.
  5. No. It authorizes connection under the configured policy; encryption requires a separate transport and connected clients may have broad traditional X11 authority.

Checkpoint#

Submit the 100–102 request timeline and a diagram separating X client, Xwayland, XWM, Wayland compositor and kernel DRM. Pass when the error case never claims W exists, the valid case distinguishes mapping from presentation, and the diagram assigns physical output control conditionally. If not, revisit the two source excerpts and trace the state transitions again. This is practice, not certification.

Sources#

The pinned Xorg dispatch source, Present source, DRI3 source, and Xwayland window source support the version-scoped walkthrough. No live server, physical GPU or desktop session was used to establish the example.

A little further beneath the surface.

Check your understanding with the checkpoint. Marking a chapter as read saves a bookmark, not a proficiency assessment.