Implement Xwayland support

In order to support clients that do not use a toolkit that has a Wayland backend, we have to implement XWayland support. XWayland is a rootless X11 server that runs as a Wayland client. X11 clients connect to XWayland just as they'd connect to a regular Xorg instance, and XWayland (more or less) converts the X11 protocol requests into Wayland protocol requests.

XWayland support – perhaps surprisingly – requires the Wayland compositor to integrate a more-or-less fully-functional X11 window manager. Smithay has an xwayland module that handles a lot of the boring, boilerplate stuff, but there will be some work to be done to integrate that into our own window management logic.

Collecting some (so far non-exhaustive) specifics:

  • Window cycling include/not include skip-taskbar and skip-pager windows. (cycle_minimum)
  • Handle _GTK_FRAME_EXTENTS in the window positioning code. This values is used for CSD windows so the client can tell the WM about things like drop shadows etc. Ideally Smithay should handle it (and return the full extents in SpaceElement::bbox(), like is the case for xdg-toplevels), and then we won't need to special-case it.
  • Set _NET_FRAME_EXTENTS on decorated X11 windows to tell them the extents of their decorations.
  • Add support for _NET_WM_STATE_STICKY to smithay.
  • Add support for _NET_WM_STATE_DEMANDS_ATTENTION to smithay. (urgent_blink, repeat_urgent_blink)
  • Add support for focus-stealing prevention (prevent_focus_stealing). On X11, that's done with a combination of _NET_USER_TIME, with focus passing depending on comparing things between two windows like _NET_WM_PID and WM_CLASS. These properties, however, are set by the client. On X11 they are trusted, because applications are assumed to be well behaved, but Wayland theoretically has a higher standard. Instead of trusting these values:
    • Instead of _NET_WM_USER_TIME, I can track when the user has last interacted with a window via pointer button/axis events, touch events, or key events.
    • Instead of _NET_WM_PID, I can check if they are the same by the X11 window ID. But I need to look at resource_id_mask from an X11 connection setup reply in order to tell what bits of the ID uniquely identify a client. (Note that I need to invert it; resource_id_mask & 0x1fffffff will give me the mask I need, as X11 only ever uses 29 bits for its Window ID space.)
  • Support WM_TAKE_FOCUS
  • Support honoring or ignoring WM_HINTS.focus + WM_TAKE_FOCUS (focus_hint)
  • Set XSETTINGS on the X11 root window, and update it whenever any of our XSETTINGS-related xfconf properties change. The Xwm struct has a set_xsettings() method on it, so I don't even need to manually construct the window property.
  • Set the Xwm cursor when the cursor theme changes.
  • If the XWayland server crashes, try to restart it.
Edited by Brian Tarricone