Merge branch 'jorth/mdbook' into 'main'
Convert docbook to mdbook Closes #584 See merge request wayland/wayland!516
|
|
@ -78,10 +78,10 @@ workflow:
|
||||||
variables:
|
variables:
|
||||||
BUILD_OS: debian
|
BUILD_OS: debian
|
||||||
FDO_DISTRIBUTION_VERSION: trixie
|
FDO_DISTRIBUTION_VERSION: trixie
|
||||||
FDO_DISTRIBUTION_PACKAGES: 'build-essential pkg-config libexpat1-dev libffi-dev libxml2-dev doxygen graphviz xmlto xsltproc docbook-xsl meson ninja-build'
|
FDO_DISTRIBUTION_PACKAGES: 'build-essential pkg-config libexpat1-dev libffi-dev libxml2-dev doxygen graphviz xmlto xsltproc docbook-xsl mdbook meson ninja-build'
|
||||||
# bump this tag every time you change something which requires rebuilding the
|
# bump this tag every time you change something which requires rebuilding the
|
||||||
# base image
|
# base image
|
||||||
FDO_DISTRIBUTION_TAG: "2025-12-27.0"
|
FDO_DISTRIBUTION_TAG: "2026-01-31.0"
|
||||||
|
|
||||||
.debian-x86_64:
|
.debian-x86_64:
|
||||||
extends:
|
extends:
|
||||||
|
|
|
||||||
1
doc/book/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/book
|
||||||
9
doc/book/book.toml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
[book]
|
||||||
|
title = "Wayland"
|
||||||
|
authors = ["Kristian Høgsberg"]
|
||||||
|
language = "en"
|
||||||
|
|
||||||
|
[output.html]
|
||||||
|
git-repository-url = "https://gitlab.freedesktop.org/wayland/wayland"
|
||||||
|
edit-url-template = "https://gitlab.freedesktop.org/wayland/wayland/-/edit/main/doc/book/{path}"
|
||||||
|
site-url = "/docs/book/"
|
||||||
67
doc/book/meson.build
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
srcs = files(
|
||||||
|
'src/Protocol.md',
|
||||||
|
'src/Foreword.md',
|
||||||
|
'src/Xwayland.md',
|
||||||
|
'src/SUMMARY.md',
|
||||||
|
'src/Content_Updates.md',
|
||||||
|
'src/Color.md',
|
||||||
|
'src/Message_XML.md',
|
||||||
|
'src/Architecture.md',
|
||||||
|
'src/Introduction.md',
|
||||||
|
'src/images/content-updates/sync-to-desync-subsurf-3.png',
|
||||||
|
'src/images/content-updates/sync-subsurf-case1.drawio',
|
||||||
|
'src/images/content-updates/sync-subsurf-case2-2.png',
|
||||||
|
'src/images/content-updates/simple-synchronized-state-4.png',
|
||||||
|
'src/images/content-updates/sync-subsurf-case2-3.png',
|
||||||
|
'src/images/content-updates/simple-desynchronized.drawio',
|
||||||
|
'src/images/content-updates/sync-to-desync-transition-2.png',
|
||||||
|
'src/images/content-updates/simple-desynchronized-state-4.png',
|
||||||
|
'src/images/content-updates/simple-synchronized-state-3.png',
|
||||||
|
'src/images/content-updates/simple-synchronized.drawio',
|
||||||
|
'src/images/content-updates/simple-synchronized-state-1.png',
|
||||||
|
'src/images/content-updates/sync-subsurf-case1-4.png',
|
||||||
|
'src/images/content-updates/sync-to-desync-subsurf-1.png',
|
||||||
|
'src/images/content-updates/simple-desynchronized-state-1.png',
|
||||||
|
'src/images/content-updates/simple-desynchronized-state-3.png',
|
||||||
|
'src/images/content-updates/sync-subsurf-case2.drawio',
|
||||||
|
'src/images/content-updates/simple-desynchronized-state-6.png',
|
||||||
|
'src/images/content-updates/sync-subsurf-case1-2.png',
|
||||||
|
'src/images/content-updates/sync-subsurf-case1-1.png',
|
||||||
|
'src/images/content-updates/simple-synchronized-state-5.png',
|
||||||
|
'src/images/content-updates/simple-synchronized-state-2.png',
|
||||||
|
'src/images/content-updates/simple-desynchronized-state-2.png',
|
||||||
|
'src/images/content-updates/content-update-legend.png',
|
||||||
|
'src/images/content-updates/sync-to-desync-subsurf.drawio',
|
||||||
|
'src/images/content-updates/sync-to-desync-subsurf-2.png',
|
||||||
|
'src/images/content-updates/sync-to-desync-transition-3.png',
|
||||||
|
'src/images/content-updates/sync-subsurf-case2-1.png',
|
||||||
|
'src/images/content-updates/content-updates.drawio',
|
||||||
|
'src/images/content-updates/sync-subsurf-case1-5.png',
|
||||||
|
'src/images/content-updates/sync-subsurf-case1-3.png',
|
||||||
|
'src/images/content-updates/sync-to-desync-transition.drawio',
|
||||||
|
'src/images/content-updates/simple-desynchronized-state-5.png',
|
||||||
|
'src/images/content-updates/sync-to-desync-transition-1.png',
|
||||||
|
'src/images/icon.svg',
|
||||||
|
'src/images/x-architecture.gv',
|
||||||
|
'src/images/x-architecture.png',
|
||||||
|
'src/images/wayland.png',
|
||||||
|
'src/images/wayland-architecture.gv',
|
||||||
|
'src/images/wayland-architecture.png',
|
||||||
|
'src/images/xwayland-architecture.png',
|
||||||
|
'src/Compositors.md',
|
||||||
|
)
|
||||||
|
|
||||||
|
custom_target(
|
||||||
|
'Wayland-book',
|
||||||
|
command: [
|
||||||
|
mdbook,
|
||||||
|
'build',
|
||||||
|
'-d', meson.current_build_dir() / 'book',
|
||||||
|
meson.current_source_dir(),
|
||||||
|
],
|
||||||
|
depend_files: srcs,
|
||||||
|
output: 'book',
|
||||||
|
build_by_default: true,
|
||||||
|
install: true,
|
||||||
|
install_dir: publican_install_prefix,
|
||||||
|
)
|
||||||
215
doc/book/src/Architecture.md
Normal file
|
|
@ -0,0 +1,215 @@
|
||||||
|
# Wayland Architecture
|
||||||
|
|
||||||
|
## X vs. Wayland Architecture
|
||||||
|
|
||||||
|
A good way to understand the Wayland architecture and how it is different from X
|
||||||
|
is to follow an event from the input device to the point where the change it
|
||||||
|
affects appears on screen.
|
||||||
|
|
||||||
|
This is where we are now with X:
|
||||||
|
|
||||||
|
**X architecture diagram**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
1. The kernel gets an event from an input device and sends it to X through the
|
||||||
|
evdev input driver. The kernel does all the hard work here by driving the
|
||||||
|
device and translating the different device specific event protocols to the
|
||||||
|
linux evdev input event standard.
|
||||||
|
|
||||||
|
2. The X server determines which window the event affects and sends it to the
|
||||||
|
clients that have selected for the event in question on that window. The X
|
||||||
|
server doesn't actually know how to do this right, since the window location
|
||||||
|
on screen is controlled by the compositor and may be transformed in a number
|
||||||
|
of ways that the X server doesn't understand (scaled down, rotated, wobbling,
|
||||||
|
etc).
|
||||||
|
|
||||||
|
3. The client looks at the event and decides what to do. Often the UI will have
|
||||||
|
to change in response to the event - perhaps a check box was clicked or the
|
||||||
|
pointer entered a button that must be highlighted. Thus the client sends a
|
||||||
|
rendering request back to the X server.
|
||||||
|
|
||||||
|
4. When the X server receives the rendering request, it sends it to the driver
|
||||||
|
to let it program the hardware to do the rendering. The X server also
|
||||||
|
calculates the bounding region of the rendering, and sends that to the
|
||||||
|
compositor as a damage event.
|
||||||
|
|
||||||
|
5. The damage event tells the compositor that something changed in the window
|
||||||
|
and that it has to recomposite the part of the screen where that window is
|
||||||
|
visible. The compositor is responsible for rendering the entire screen
|
||||||
|
contents based on its scenegraph and the contents of the X windows. Yet, it
|
||||||
|
has to go through the X server to render this.
|
||||||
|
|
||||||
|
6. The X server receives the rendering requests from the compositor and either
|
||||||
|
copies the compositor back buffer to the front buffer or does a pageflip. In
|
||||||
|
the general case, the X server has to do this step so it can account for
|
||||||
|
overlapping windows, which may require clipping and determine whether or not
|
||||||
|
it can page flip. However, for a compositor, which is always fullscreen, this
|
||||||
|
is another unnecessary context switch.
|
||||||
|
|
||||||
|
As suggested above, there are a few problems with this approach. The X server
|
||||||
|
doesn't have the information to decide which window should receive the event,
|
||||||
|
nor can it transform the screen coordinates to window-local coordinates. And
|
||||||
|
even though X has handed responsibility for the final painting of the screen to
|
||||||
|
the compositing manager, X still controls the front buffer and modesetting. Most
|
||||||
|
of the complexity that the X server used to handle is now available in the
|
||||||
|
kernel or self contained libraries (KMS, evdev, mesa, fontconfig, freetype,
|
||||||
|
cairo, Qt etc). In general, the X server is now just a middle man that
|
||||||
|
introduces an extra step between applications and the compositor and an extra
|
||||||
|
step between the compositor and the hardware.
|
||||||
|
|
||||||
|
In Wayland the compositor is the display server. We transfer the control of KMS
|
||||||
|
and evdev to the compositor. The Wayland protocol lets the compositor send the
|
||||||
|
input events directly to the clients and lets the client send the damage event
|
||||||
|
directly to the compositor:
|
||||||
|
|
||||||
|
**Wayland architecture diagram**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
1. The kernel gets an event and sends it to the compositor. This is similar to
|
||||||
|
the X case, which is great, since we get to reuse all the input drivers in
|
||||||
|
the kernel.
|
||||||
|
|
||||||
|
2. The compositor looks through its scenegraph to determine which window should
|
||||||
|
receive the event. The scenegraph corresponds to what's on screen and the
|
||||||
|
compositor understands the transformations that it may have applied to the
|
||||||
|
elements in the scenegraph. Thus, the compositor can pick the right window
|
||||||
|
and transform the screen coordinates to window-local coordinates, by applying
|
||||||
|
the inverse transformations. The types of transformation that can be applied
|
||||||
|
to a window is only restricted to what the compositor can do, as long as it
|
||||||
|
can compute the inverse transformation for the input events.
|
||||||
|
|
||||||
|
3. As in the X case, when the client receives the event, it updates the UI in
|
||||||
|
response. But in the Wayland case, the rendering happens in the client, and
|
||||||
|
the client just sends a request to the compositor to indicate the region that
|
||||||
|
was updated.
|
||||||
|
|
||||||
|
4. The compositor collects damage requests from its clients and then
|
||||||
|
recomposites the screen. The compositor can then directly issue an ioctl to
|
||||||
|
schedule a pageflip with KMS.
|
||||||
|
|
||||||
|
## Wayland Rendering
|
||||||
|
|
||||||
|
One of the details I left out in the above overview is how clients actually
|
||||||
|
render under Wayland. By removing the X server from the picture we also removed
|
||||||
|
the mechanism by which X clients typically render. But there's another mechanism
|
||||||
|
that we're already using with DRI2 under X: direct rendering. With direct
|
||||||
|
rendering, the client and the server share a video memory buffer. The client
|
||||||
|
links to a rendering library such as OpenGL that knows how to program the
|
||||||
|
hardware and renders directly into the buffer. The compositor in turn can take
|
||||||
|
the buffer and use it as a texture when it composites the desktop. After the
|
||||||
|
initial setup, the client only needs to tell the compositor which buffer to use
|
||||||
|
and when and where it has rendered new content into it.
|
||||||
|
|
||||||
|
This leaves an application with two ways to update its window contents:
|
||||||
|
|
||||||
|
1. Render the new content into a new buffer and tell the compositor to use that
|
||||||
|
instead of the old buffer. The application can allocate a new buffer every
|
||||||
|
time it needs to update the window contents or it can keep two (or more)
|
||||||
|
buffers around and cycle between them. The buffer management is entirely
|
||||||
|
under application control.
|
||||||
|
|
||||||
|
2. Render the new content into the buffer that it previously told the compositor
|
||||||
|
to to use. While it's possible to just render directly into the buffer shared
|
||||||
|
with the compositor, this might race with the compositor. What can happen is
|
||||||
|
that repainting the window contents could be interrupted by the compositor
|
||||||
|
repainting the desktop. If the application gets interrupted just after
|
||||||
|
clearing the window but before rendering the contents, the compositor will
|
||||||
|
texture from a blank buffer. The result is that the application window will
|
||||||
|
flicker between a blank window or half-rendered content. The traditional way
|
||||||
|
to avoid this is to render the new content into a back buffer and then copy
|
||||||
|
from there into the compositor surface. The back buffer can be allocated on
|
||||||
|
the fly and just big enough to hold the new content, or the application can
|
||||||
|
keep a buffer around. Again, this is under application control.
|
||||||
|
|
||||||
|
In either case, the application must tell the compositor which area of the
|
||||||
|
surface holds new contents. When the application renders directly to the shared
|
||||||
|
buffer, the compositor needs to be noticed that there is new content. But also
|
||||||
|
when exchanging buffers, the compositor doesn't assume anything changed, and
|
||||||
|
needs a request from the application before it will repaint the desktop. The
|
||||||
|
idea that even if an application passes a new buffer to the compositor, only a
|
||||||
|
small part of the buffer may be different, like a blinking cursor or a spinner.
|
||||||
|
|
||||||
|
## Accelerated GPU Buffer Exchange
|
||||||
|
|
||||||
|
Clients
|
||||||
|
[exchange](https://docs.kernel.org/userspace-api/dma-buf-alloc-exchange.html)
|
||||||
|
GPU buffers with the compositor as dma-buf file descriptors, which are universal
|
||||||
|
handles that are independent of any particular rendering API or memory
|
||||||
|
allocator. The
|
||||||
|
[linux-dmabuf-v1](https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/stable/linux-dmabuf/linux-dmabuf-v1.xml)
|
||||||
|
protocol is used to turn one or more dma-buf FDs into a
|
||||||
|
[wl_buffer](https://wayland.app/protocols/wayland#wl_buffer).
|
||||||
|
|
||||||
|
If the client uses the
|
||||||
|
[Vulkan](https://docs.vulkan.org/spec/latest/chapters/VK_KHR_surface/wsi.html)
|
||||||
|
or
|
||||||
|
[EGL](https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_platform_wayland.txt)
|
||||||
|
(via
|
||||||
|
[wayland-egl](https://gitlab.freedesktop.org/wayland/wayland/-/tree/main/egl))
|
||||||
|
window-system integration (WSI), this is done transparently by the WSI.
|
||||||
|
|
||||||
|
Clients can alternatively allocate and import dma-bufs themselves using the GBM
|
||||||
|
library, Vulkan, udmabuf, or dma-buf heaps.
|
||||||
|
|
||||||
|
- Using GBM, the client can allocate a gbm_bo and export one or more dma-buf FDs
|
||||||
|
from it.
|
||||||
|
|
||||||
|
- Using Vulkan, the client can create a VkDeviceMemory object and use
|
||||||
|
[VK_EXT_external_memory_dma_buf](https://docs.vulkan.org/refpages/latest/refpages/source/VK_EXT_external_memory_dma_buf.html)
|
||||||
|
and
|
||||||
|
[VK_EXT_image_drm_format_modifier](https://docs.vulkan.org/refpages/latest/refpages/source/VK_EXT_image_drm_format_modifier.html)
|
||||||
|
to export a dma-buf FD from it.
|
||||||
|
|
||||||
|
- [udmabuf](https://lwn.net/Articles/749206/) can be used to create dma-buf FDs
|
||||||
|
from linear host memory.
|
||||||
|
|
||||||
|
- [Dma-buf heaps](https://docs.kernel.org/userspace-api/dma-buf-heaps.html) can
|
||||||
|
be used by privileged applications to create dma-buf FDs on embedded devices.
|
||||||
|
|
||||||
|
Compositors use
|
||||||
|
[VK_EXT_external_memory_dma_buf](https://docs.vulkan.org/refpages/latest/refpages/source/VK_EXT_external_memory_dma_buf.html)
|
||||||
|
and
|
||||||
|
[VK_EXT_image_drm_format_modifier](https://docs.vulkan.org/refpages/latest/refpages/source/VK_EXT_image_drm_format_modifier.html)
|
||||||
|
or
|
||||||
|
[EGL_EXT_image_dma_buf_import](https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_image_dma_buf_import.txt)
|
||||||
|
and
|
||||||
|
[EGL_EXT_image_dma_buf_import_modifiers](https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_image_dma_buf_import_modifiers.txt)
|
||||||
|
to import the dma-bufs provided by the client into their own Vulkan or EGL
|
||||||
|
renderers.
|
||||||
|
|
||||||
|
Clients do not need to wait for the GPU to finish rendering before submitting
|
||||||
|
dma-bufs to the compositor. Clients can use the
|
||||||
|
[linux-drm-syncobj-v1](https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml)
|
||||||
|
protocol to exchange DRM synchronization objects with the compositor. These
|
||||||
|
objects are used to asynchronously signal ownership transfer of buffers from
|
||||||
|
clients to the compositor and vice versa. The WSIs do this transparently.
|
||||||
|
|
||||||
|
If the linux-drm-syncobj-v1 protocol is not supported by the compositor, clients
|
||||||
|
and compositors can use the
|
||||||
|
[DMA_BUF_IOCTL_EXPORT_SYNC_FILE](https://docs.kernel.org/driver-api/dma-buf.html#c.dma_buf_export_sync_file)
|
||||||
|
and
|
||||||
|
[DMA_BUF_IOCTL_IMPORT_SYNC_FILE](https://docs.kernel.org/driver-api/dma-buf.html#c.dma_buf_import_sync_file)
|
||||||
|
ioctls to access and create implicit synchronization barriers.
|
||||||
|
|
||||||
|
## Display Programming
|
||||||
|
|
||||||
|
Compositors enumerate DRM KMS devices using
|
||||||
|
[udev](https://en.wikipedia.org/wiki/Udev). Udev also notifies compositors of
|
||||||
|
KMS device and display hotplug events.
|
||||||
|
|
||||||
|
Access to DRM KMS device ioctls is privileged. Since compositors usually run as
|
||||||
|
unprivileged applications, they typically gain access to a privileged file
|
||||||
|
descriptor using the
|
||||||
|
[TakeDevice](https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.login1.html#Session%20Objects)
|
||||||
|
method provided by logind.
|
||||||
|
|
||||||
|
Using the file descriptor, compositors use KMS
|
||||||
|
[ioctls](https://docs.kernel.org/gpu/drm-kms.html) to enumerate the available
|
||||||
|
displays.
|
||||||
|
|
||||||
|
Compositors use [atomic mode
|
||||||
|
setting](https://docs.kernel.org/gpu/drm-kms.html#atomic-mode-setting) to change
|
||||||
|
the buffer shown by the display, to change the display's resolution, to enable
|
||||||
|
or disable HDR, and so on.
|
||||||
100
doc/book/src/Color.md
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
# Color management
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Color management in Wayland considers only displays. All pictures in Wayland are
|
||||||
|
always display-referred, meaning that the pixel values are intended as-is for
|
||||||
|
some specific display where they would produce the light emissions
|
||||||
|
([stimuli](https://cie.co.at/eilvterm/17-23-002)) the picture's author desired.
|
||||||
|
Wayland does not support displaying "raw" camera or scanner images as they are
|
||||||
|
not display-referred, nor are they even pictures without complex and subjective
|
||||||
|
processing.
|
||||||
|
|
||||||
|
Stimuli — the picture itself — are only half of the picture reproduction. The
|
||||||
|
other half is the environment where a display is viewed. A striking example is
|
||||||
|
comparing a brightly lit office to a dark movie theater, the stimuli required to
|
||||||
|
produce a good reading of the picture is greatly different. Therefore
|
||||||
|
display-referred does not include only the display but the viewing environment
|
||||||
|
as well.
|
||||||
|
|
||||||
|
Window systems have been very well capable of operating without any explicit
|
||||||
|
consideration to color management. This is because there used to be the implicit
|
||||||
|
assumption of the standard display, the sRGB display, which all computer
|
||||||
|
monitors implemented, more or less. The viewing environment was and still is
|
||||||
|
accounted by adjusting the display and/or the room to produce a workable
|
||||||
|
experience. Pictures are authored on a computer system by drawing, painting and
|
||||||
|
adjusting the picture until it looks right on the author's monitor. This
|
||||||
|
implicitly builds the standard display and environment assumption into the
|
||||||
|
picture data. Deviations from the sRGB specification were minor enough that they
|
||||||
|
often did not matter if not in a professional context like the printing
|
||||||
|
industry. Displaying video material required some more attention to the details,
|
||||||
|
because video and television standards differ enough from the sRGB display. What
|
||||||
|
really made explicit color management a hard requirement for entertainment is
|
||||||
|
the coming of wide color gamut (WCG) and high dynamic range (HDR) materials and
|
||||||
|
displays.
|
||||||
|
|
||||||
|
The color management design in Wayland follows the general Wayland design
|
||||||
|
principles: compositors tell clients what would be the optimal thing to do,
|
||||||
|
clients tell the compositors what kind of pictures they are actually producing,
|
||||||
|
and then compositors display those pictures the best they can.
|
||||||
|
|
||||||
|
## Protocol Interfaces
|
||||||
|
|
||||||
|
Color management interfaces in Wayland and divided into two protocols:
|
||||||
|
[color-management](https://gitlab.freedesktop.org/wayland/wayland-protocols/-/tree/main/staging/color-management?ref_type=heads)
|
||||||
|
and
|
||||||
|
[color-representation](https://gitlab.freedesktop.org/wayland/wayland-protocols/-/tree/main/staging/color-representation?ref_type=heads).
|
||||||
|
They are designed to work together, but they can also be used independently when
|
||||||
|
the other one is not needed.
|
||||||
|
|
||||||
|
### Color-management
|
||||||
|
|
||||||
|
Color management protocol has two main purposes. First, it puts the
|
||||||
|
responsibility of color management on the compositor. This means that clients do
|
||||||
|
not necessarily need to care about color management at all, and can display just
|
||||||
|
fine by using the traditional standard display assumption even when the actual
|
||||||
|
display is wildly different. Clients can also choose to target some other
|
||||||
|
assumed display and let the compositor handle it, or they can explicitly render
|
||||||
|
for the actual display at hand. Second, when the window system has multiple
|
||||||
|
different monitors, and a wl_surface happens to span more than one monitor, the
|
||||||
|
compositor can display the surface content correctly on all spanned monitors
|
||||||
|
simultaneously, as much as physically possible.
|
||||||
|
|
||||||
|
Color-management protocol concentrates on colorimetry: when you have a pixel
|
||||||
|
with RGB values, what stimulus do those values represent. The stimulus
|
||||||
|
definition follows the CIE 1931 two-degree observer model. Some core concepts
|
||||||
|
here are color primaries, white point, transfer function, and dynamic range. The
|
||||||
|
viewing environment is represented in an extremely simplified way as the
|
||||||
|
reference white luminance. The connection between pixel RGB values and stimulus
|
||||||
|
plus viewing environment is recorded in an _image description_ object. Clients
|
||||||
|
can create image description objects and tag `wl_surface`s with them, to
|
||||||
|
indicate what kind of surface content there will be. Clients can also ask what
|
||||||
|
image description the compositor would prefer to have on the `wl_surface`, and
|
||||||
|
that preference can change over time, e.g. when the `wl_surface` is moved from
|
||||||
|
one `wl_output` to another. Following the compositor's preference may provide
|
||||||
|
advantages in image quality and power consumption.
|
||||||
|
|
||||||
|
Image description objects can come in two flavors: parametric and ICC-based. The
|
||||||
|
above was written with parametric image descriptions in mind, and they have
|
||||||
|
first-class support for HDR. ICC-based image descriptions are wrapping an ICC
|
||||||
|
profile and have no other data. ICC profiles are the standard tool for standard
|
||||||
|
dynamic range (SDR) display color management. This means the capabilities
|
||||||
|
between the two flavors differ, and one cannot always be replaced by the other.
|
||||||
|
Compositor support for each flavor is optional.
|
||||||
|
|
||||||
|
### Color-representation
|
||||||
|
|
||||||
|
Color-representation protocol deals with (potentially sub-sampled) YCbCr-RGB
|
||||||
|
conversion, quantization range, and the inclusion of alpha in the RGB color
|
||||||
|
channels, a.k.a. pre-multiplication. There are several different specifications
|
||||||
|
on how an YCbCr-like (including ICtCp) signal, with chroma sub-sampling or not,
|
||||||
|
is created from a full-resolution RGB image. Again, a client can tag a
|
||||||
|
`wl_surface` with color-representation metadata to tell the compositor what kind
|
||||||
|
of pixel data will be displayed through the wl_surface.
|
||||||
|
|
||||||
|
The main purpose of color-representation is to correctly off-load the YCbCr-RGB
|
||||||
|
conversion to the compositor, which can then opportunistically off-load it
|
||||||
|
further to very power-efficient fixed-function circuitry in a display
|
||||||
|
controller. This can significantly reduce power consumption when watching videos
|
||||||
|
compared to using a GPU for the same, and on some embedded hardware platforms it
|
||||||
|
is a hard requirement for processing high resolution video.
|
||||||
76
doc/book/src/Compositors.md
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
# Types of Compositors
|
||||||
|
|
||||||
|
Compositors come in different types, depending on which role they play in the
|
||||||
|
overall architecture of the OS. For instance, a [system
|
||||||
|
compositor](#system-compositor) can be used for booting the system, handling
|
||||||
|
multiple user switching, a possible console terminal emulator and so forth. A
|
||||||
|
different compositor, a [session compositor](#session-compositor) would provide
|
||||||
|
the actual desktop environment. There are many ways for different types of
|
||||||
|
compositors to co-exist.
|
||||||
|
|
||||||
|
In this section, we introduce three types of Wayland compositors relying on
|
||||||
|
[libwayland-server](https://gitlab.freedesktop.org/wayland/wayland).
|
||||||
|
|
||||||
|
## System Compositor
|
||||||
|
|
||||||
|
A system compositor can run from early boot until shutdown. It effectively
|
||||||
|
replaces the kernel vt system, and can tie in with the systems graphical boot
|
||||||
|
setup and multiseat support.
|
||||||
|
|
||||||
|
A system compositor can host different types of session compositors, and let us
|
||||||
|
switch between multiple sessions (fast user switching, or secure/personal
|
||||||
|
desktop switching).
|
||||||
|
|
||||||
|
A linux implementation of a system compositor will typically use libudev, egl,
|
||||||
|
kms, evdev and cairo.
|
||||||
|
|
||||||
|
For fullscreen clients, the system compositor can reprogram the video scanout
|
||||||
|
address to read directly from the client provided buffer.
|
||||||
|
|
||||||
|
## Session Compositor
|
||||||
|
|
||||||
|
A session compositor is responsible for a single user session. If a system
|
||||||
|
compositor is present, the session compositor will run nested under the system
|
||||||
|
compositor. Nesting is feasible because the protocol is asynchronous; roundtrips
|
||||||
|
would be too expensive when nesting is involved. If no system compositor is
|
||||||
|
present, a session compositor can run directly on the hardware.
|
||||||
|
|
||||||
|
X applications can continue working under a session compositor by means of a
|
||||||
|
root-less X server that is activated on demand.
|
||||||
|
|
||||||
|
Possible examples for session compositors include
|
||||||
|
|
||||||
|
- gnome-shell
|
||||||
|
|
||||||
|
- moblin
|
||||||
|
|
||||||
|
- kwin
|
||||||
|
|
||||||
|
- kmscon
|
||||||
|
|
||||||
|
- rdp session
|
||||||
|
|
||||||
|
- Weston with X11 or Wayland backend is a session compositor nested in another
|
||||||
|
session compositor.
|
||||||
|
|
||||||
|
- fullscreen X session under Wayland
|
||||||
|
|
||||||
|
## Embedding Compositor
|
||||||
|
|
||||||
|
X11 lets clients embed windows from other clients, or lets clients copy pixmap
|
||||||
|
contents rendered by another client into their window. This is often used for
|
||||||
|
applets in a panel, browser plugins and similar. Wayland doesn't directly allow
|
||||||
|
this, but clients can communicate GEM buffer names out-of-band, for example,
|
||||||
|
using D-Bus, or command line arguments when the panel launches the applet.
|
||||||
|
Another option is to use a nested Wayland instance. For this, the Wayland server
|
||||||
|
will have to be a library that the host application links to. The host
|
||||||
|
application will then pass the Wayland server socket name to the embedded
|
||||||
|
application, and will need to implement the Wayland compositor interface. The
|
||||||
|
host application composites the client surfaces as part of it's window, that is,
|
||||||
|
in the web page or in the panel. The benefit of nesting the Wayland server is
|
||||||
|
that it provides the requests the embedded client needs to inform the host about
|
||||||
|
buffer updates and a mechanism for forwarding input events from the host
|
||||||
|
application.
|
||||||
|
|
||||||
|
An example for this kind of setup is firefox embedding the flash player as a
|
||||||
|
kind of special-purpose compositor.
|
||||||
214
doc/book/src/Content_Updates.md
Normal file
|
|
@ -0,0 +1,214 @@
|
||||||
|
# Content Updates
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
In the Wayland protocol, requests are asynchronous but take effect immediately
|
||||||
|
when the compositor receives them. However, some requests on surfaces are not
|
||||||
|
applied immediately but are instead double-buffered to allow atomic changes.
|
||||||
|
These double-buffered changes are committed through the wl_surface.commit
|
||||||
|
request, which creates a Content Update.
|
||||||
|
|
||||||
|
Content Updates encapsulate all double-buffered state changes and can be applied
|
||||||
|
by the compositor. The complexity arises when considering subsurfaces, which can
|
||||||
|
operate in synchronized mode. When a subsurface is synchronized, its Content
|
||||||
|
Updates must be applied atomically together with the parent surface's state.
|
||||||
|
This synchronization can extend through an entire tree of subsurfaces, where
|
||||||
|
child subsurfaces inherit the synchronized behavior from their parents.
|
||||||
|
|
||||||
|
Historically, Content Updates from synchronized subsurfaces were merged into the
|
||||||
|
pending state of the parent surface on commit. However, the introduction of
|
||||||
|
constraints—which can defer the application of Content Updates—necessitated a
|
||||||
|
more sophisticated model. This led to the implementation of per-surface queues
|
||||||
|
of Content Updates, with dependencies between Content Updates across different
|
||||||
|
queues. This queuing model maintains backwards compatibility with the earlier
|
||||||
|
approach of merging Content Updates into the parent's pending state on commit.
|
||||||
|
|
||||||
|
The core protocol defines the semantics of Content Updates using per-surface
|
||||||
|
queues, but compositors that do not need to support constraints may implement
|
||||||
|
the simpler legacy model where synchronized subsurface states are merged
|
||||||
|
directly into the parent's pending state.
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
The core protocol specifies the behavior in wl_subsurface and wl_surface.commit.
|
||||||
|
The behavior can be summarized by the following rules:
|
||||||
|
|
||||||
|
1. Content Updates (CU) contain all double-buffered state of the surface and
|
||||||
|
selected state from their direct children.
|
||||||
|
|
||||||
|
2. Surfaces which are effectively synchronized create Synchronized Content
|
||||||
|
Updates (SCU), otherwise they create Desync Content Updates (DCU).
|
||||||
|
|
||||||
|
3. When a CU is created, it gets a dependency on the previous CU of the same
|
||||||
|
queues (if it exists).
|
||||||
|
|
||||||
|
4. When a CU is created, it gets a dependency on the last SCU of direct child
|
||||||
|
surfaces that are not reachable (if they exists).
|
||||||
|
|
||||||
|
5. The CUs and their dependencies form a DAG, where CUs are nodes and
|
||||||
|
dependencies are edges.
|
||||||
|
|
||||||
|
6. All DCUs starting from the front of the queues until the first SCU or the
|
||||||
|
back of the queue is reached are candidates.
|
||||||
|
|
||||||
|
7. If the maximal DAG that's reachable from a candidate (candidate DAG) does not
|
||||||
|
have any constraints, then this DAG can be applied.
|
||||||
|
|
||||||
|
8. A DAG is applied atomically by recursively applying a content update without
|
||||||
|
dependencies and removing it from the DAG.
|
||||||
|
|
||||||
|
9. Surfaces transition from effectively sync to effectively desync after their
|
||||||
|
parents.
|
||||||
|
|
||||||
|
10. When a surface transitions to effectively desync, all SCUs in its queue
|
||||||
|
which are not reachable by a DCU become DCUs.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
These examples should help to build an intuition for how content updates
|
||||||
|
actually behave. They cover the interesting edge cases, such as subsurfaces with
|
||||||
|
constraints, and transitioning from a sync subsurface to a desync one.
|
||||||
|
|
||||||
|
In all the examples below, the surface T1 refers to a toplevel surface, SS1
|
||||||
|
refers to a sub-surface which is a child of T1, and SS2 refers to a sub-surface
|
||||||
|
which is a child of SS1.
|
||||||
|
|
||||||
|
### Legend
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Simple Desynchronized Case
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
SS2 is effectively desynchronized and commits. This results in the
|
||||||
|
desynchronized content update (DCU) _1_.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
DCU _1_ is a candidate, and the candidate DAG reachable from DCU _1_ is only DCU
|
||||||
|
_1_ itself. DCU _1_ and thus the candidate DAG does not have any constraints and
|
||||||
|
can be applied.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The content updates of the candidate DAG get applied to the surface atomically.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
T1 commits a DCU with a _buffer-sync_ constraint. It is a candidate but its DAG
|
||||||
|
can't be applied because it contains a constraint.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
T1 commits another CU (DCU _3_) which is added at the end of the queue, with a
|
||||||
|
dependency to the previous CU (DCU _2_). Both DCU _2_ and DCU _3_ are
|
||||||
|
candidates, but both DAGs contain DCU _2_ with a constraint, and can't be
|
||||||
|
applied.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
When the constraint gets cleared, both DAGs can be applied to the surface
|
||||||
|
atomitcally (either only _2_, or _2_ and _3_).
|
||||||
|
|
||||||
|
### Simple Synchronized Case
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
SS1 and SS2 are effectively synchronized. SS2 commits SCU _1_.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
SS1 commits SCU _2_. The direct child surfaces SS2 has the last SCU _1_ in its
|
||||||
|
queue, which is not reachable. This creates a dependency from SCU _2_ to SCU
|
||||||
|
_1_.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
SS1 commits SCU _3_. The direct child surfaces SS2 has the last SCU _1_ in its
|
||||||
|
queue, which is already reachable by SCU _2_. No dependency to SCU _1_ is
|
||||||
|
created. A dependency to the previous CU of the same queue (SCU _2_) is created.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
T1 commit DCU _4_. It is a candidate, its DAG does not contain any constraint
|
||||||
|
and it can be applied.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The DAG gets applied to the surfaces atomically.
|
||||||
|
|
||||||
|
### Complex Synchronized Subsurface Case 1
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Every DCU (_1_ and _6_) contain CUs with constraints in their candidate DAG
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Waiting until the _buffer-sync_ constrain on CU _1_ is cleared, the candidate
|
||||||
|
DAG of CU _1_ does not contain constraints and can be applied
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
That leaves the candidate DAG of CU _6_ which still contains another CU with a
|
||||||
|
_buffer-sync_ constrain
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Waiting until the _buffer-sync_ constrain on CU _6_ is cleared, the candidate
|
||||||
|
DAG of _6_ does not contain CUs with constraints and can be applied.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
There is no DCU left and no constraint remaining. Nothing more can be applied
|
||||||
|
without a new CU.
|
||||||
|
|
||||||
|
### Complex Synchronized Subsurface Case 2
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Both DCUs (_1_ and _6_) have a reachable DAG containing CU _1_ with a constraint
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Waiting until the _buffer-sync_ constrain on _1_ is cleared, both DAGs contain
|
||||||
|
no CU with constraints and can be applied in any order
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
That leaves the same state as in the previous case
|
||||||
|
|
||||||
|
### Synchronized to Desynchronized Subsurface
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
There is one DCU (_4_) with its reachable DAG that cannot be applied because CU
|
||||||
|
_4_ contains a constraint
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Surface _SS1_ transitions from effectively synchronized to effectively
|
||||||
|
desynchronized. SCU _2_ is reachable by DCU _4_ so nothing changes.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Surface _SS1_ provides a new DCU (_5_) but because the CU before (_2_) is a
|
||||||
|
Synchronized CU, it is not a candidate
|
||||||
|
|
||||||
|
### Synchronized to Desynchronized Transition
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
There are four SCUs and all surfaces are effectively synchronized.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Surface _SS1_ transitions to effectively desynchronized and SCU _2_ becomes a
|
||||||
|
DCU because it is not reachable from a DCU
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Surface _SS2_ transitions to effectively desynchronized. SCUs _3_ and _4_ become
|
||||||
|
DCUs because they are not reachable from a DCU. SCU _1_ does not change because
|
||||||
|
it is reachable by DCU _2_.
|
||||||
48
doc/book/src/Foreword.md
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
# Preface
|
||||||
|
|
||||||
|
This document describes the Wayland architecture and Wayland model of operation.
|
||||||
|
This document is aimed primarily at Wayland developers and those looking to
|
||||||
|
program with it; it does not cover application development.
|
||||||
|
|
||||||
|
There have been many contributors to this document and since this is only the
|
||||||
|
first edition many errors are expected to be found. We appreciate corrections.
|
||||||
|
|
||||||
|
Yours, the Wayland open-source community November 2012
|
||||||
|
|
||||||
|
## Protocol Documentation
|
||||||
|
|
||||||
|
This document does not describe the semantics of individual messages sent
|
||||||
|
between compositors and clients. Consult the following documents to learn about
|
||||||
|
concrete Wayland interfaces, requests, and events.
|
||||||
|
|
||||||
|
- [wayland.xml] - The official documentation of the core protocol.
|
||||||
|
- [wayland-protocols] - Standardized Wayland extension protocols.
|
||||||
|
- [wayland.app] - A community-maintained website that renders these protocols,
|
||||||
|
and many more, as easily accessible HTML pages.
|
||||||
|
|
||||||
|
[wayland.xml]: https://gitlab.freedesktop.org/wayland/wayland/-/blob/main/protocol/wayland.xml
|
||||||
|
[wayland-protocols]: https://gitlab.freedesktop.org/wayland/wayland-protocols
|
||||||
|
[wayland.app]: https://wayland.app
|
||||||
|
|
||||||
|
## Copyright
|
||||||
|
|
||||||
|
Copyright © 2012 Kristian Høgsberg
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice (including the next
|
||||||
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
73
doc/book/src/Introduction.md
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
# Introduction
|
||||||
|
|
||||||
|
## Motivation
|
||||||
|
|
||||||
|
Most Linux and Unix-based systems rely on the X Window System (or simply _X_) as
|
||||||
|
the low-level protocol for building bitmap graphics interfaces. On these
|
||||||
|
systems, the X stack has grown to encompass functionality arguably belonging in
|
||||||
|
client libraries, helper libraries, or the host operating system kernel. Support
|
||||||
|
for things like PCI resource management, display configuration management,
|
||||||
|
direct rendering, and memory management has been integrated into the X stack,
|
||||||
|
imposing limitations like limited support for standalone applications,
|
||||||
|
duplication in other projects (e.g. the Linux fb layer or the DirectFB project),
|
||||||
|
and high levels of complexity for systems combining multiple elements (for
|
||||||
|
example radeon memory map handling between the fb driver and X driver, or VT
|
||||||
|
switching).
|
||||||
|
|
||||||
|
Moreover, X has grown to incorporate modern features like offscreen rendering
|
||||||
|
and scene composition, but subject to the limitations of the X architecture. For
|
||||||
|
example, the X implementation of composition adds additional context switches
|
||||||
|
and makes things like input redirection difficult.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The diagram above illustrates the central role of the X server and compositor in
|
||||||
|
operations, and the steps required to get contents on to the screen.
|
||||||
|
|
||||||
|
Over time, X developers came to understand the shortcomings of this approach and
|
||||||
|
worked to split things up. Over the past several years, a lot of functionality
|
||||||
|
has moved out of the X server and into client-side libraries or kernel drivers.
|
||||||
|
One of the first components to move out was font rendering, with freetype and
|
||||||
|
fontconfig providing an alternative to the core X fonts. Direct rendering OpenGL
|
||||||
|
as a graphics driver in a client side library went through some iterations,
|
||||||
|
ending up as DRI2, which abstracted most of the direct rendering buffer
|
||||||
|
management from client code. Then cairo came along and provided a modern 2D
|
||||||
|
rendering library independent of X, and compositing managers took over control
|
||||||
|
of the rendering of the desktop as toolkits like GTK+ and Qt moved away from
|
||||||
|
using X APIs for rendering. Recently, memory and display management have moved
|
||||||
|
to the Linux kernel, further reducing the scope of X and its driver stack. The
|
||||||
|
end result is a highly modular graphics stack.
|
||||||
|
|
||||||
|
## The compositing manager as the display server
|
||||||
|
|
||||||
|
Wayland is a new display server and compositing protocol, and Weston is the
|
||||||
|
implementation of this protocol which builds on top of all the components above.
|
||||||
|
We are trying to distill out the functionality in the X server that is still
|
||||||
|
used by the modern Linux desktop. This turns out to be not a whole lot.
|
||||||
|
Applications can allocate their own off-screen buffers and render their window
|
||||||
|
contents directly, using hardware accelerated libraries like libGL, or high
|
||||||
|
quality software implementations like those found in Cairo. In the end, what’s
|
||||||
|
needed is a way to present the resulting window surface for display, and a way
|
||||||
|
to receive and arbitrate input among multiple clients. This is what Wayland
|
||||||
|
provides, by piecing together the components already in the eco-system in a
|
||||||
|
slightly different way.
|
||||||
|
|
||||||
|
X will always be relevant, in the same way Fortran compilers and VRML browsers
|
||||||
|
are, but it’s time that we think about moving it out of the critical path and
|
||||||
|
provide it as an optional component for legacy applications.
|
||||||
|
|
||||||
|
Overall, the philosophy of Wayland is to provide clients with a way to manage
|
||||||
|
windows and how their contents are displayed. Rendering is left to clients, and
|
||||||
|
system wide memory management interfaces are used to pass buffer handles between
|
||||||
|
clients and the compositing manager.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The figure above illustrates how Wayland clients interact with a Wayland server.
|
||||||
|
Note that window management and composition are handled entirely in the server,
|
||||||
|
significantly reducing complexity while marginally improving performance through
|
||||||
|
reduced context switching. The resulting system is easier to build and extend
|
||||||
|
than a similar X system, because often changes need only be made in one place.
|
||||||
|
Or in the case of protocol extensions, two (rather than 3 or 4 in the X case
|
||||||
|
where window management and/or composition handling may also need to be
|
||||||
|
updated).
|
||||||
493
doc/book/src/Message_XML.md
Normal file
|
|
@ -0,0 +1,493 @@
|
||||||
|
# Message Definition Language
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The fundamentals of the Wayland protocol are explained in [Wayland Protocol and
|
||||||
|
Model of Operation](Protocol.md). This chapter formally defines the language
|
||||||
|
used to define Wayland protocols.
|
||||||
|
|
||||||
|
Wayland is an object-oriented protocol. Each object follows exactly one
|
||||||
|
interface. An interface is a collection of message and enumeration definitions.
|
||||||
|
A message can be either a request (sent by a client) or an event (sent by a
|
||||||
|
server). A message can have arguments. All arguments are typed.
|
||||||
|
|
||||||
|
## XML Elements
|
||||||
|
|
||||||
|
### protocol
|
||||||
|
|
||||||
|
```
|
||||||
|
protocol ::= (copyright?, description? interface+)
|
||||||
|
```
|
||||||
|
|
||||||
|
`protocol` is the root element in a Wayland protocol XML file. Code generation
|
||||||
|
tools may optionally use the protocol `name` in API symbol names. The XML file
|
||||||
|
name should be similar to the protocol name.
|
||||||
|
|
||||||
|
The description element should be used to document the intended purpose of the
|
||||||
|
protocol, give an overview, and give any development stage notices if
|
||||||
|
applicable.
|
||||||
|
|
||||||
|
The copyright element should be used to indicate the copyrights and the license
|
||||||
|
of the XML file.
|
||||||
|
|
||||||
|
**Required attributes**
|
||||||
|
|
||||||
|
`name`="`cname`"
|
||||||
|
: The name of the protocol (a.k.a protocol extension). cname-requirements
|
||||||
|
|
||||||
|
The name should be globally unique. Protocols to be included in
|
||||||
|
[wayland-protocols](https://gitlab.freedesktop.org/wayland/wayland-protocols)
|
||||||
|
must follow the naming rules set there. Other protocols should use a unique
|
||||||
|
prefix for the name, e.g. referring to the owning project's name.
|
||||||
|
|
||||||
|
### copyright
|
||||||
|
|
||||||
|
Parent elements: protocol
|
||||||
|
|
||||||
|
```
|
||||||
|
copyright ::= #PCDATA
|
||||||
|
```
|
||||||
|
|
||||||
|
Contains free-form, pre-formatted text for copyright and license notices.
|
||||||
|
|
||||||
|
### description
|
||||||
|
|
||||||
|
Parent elements: protocol, interface, request, event, arg, enum, entry
|
||||||
|
|
||||||
|
```
|
||||||
|
description ::= #PCDATA
|
||||||
|
```
|
||||||
|
|
||||||
|
Contains human-readable documentation for its parent element. May contain
|
||||||
|
formatted text, including paragraphs and bulleted lists.
|
||||||
|
|
||||||
|
**Optional attributes**
|
||||||
|
|
||||||
|
`summary`="`summary`"
|
||||||
|
: A short (half a line at most) description of the documented element.
|
||||||
|
|
||||||
|
When a description element is used, it is recommended to not use the
|
||||||
|
`summary` attribute of the parent element.
|
||||||
|
|
||||||
|
### interface
|
||||||
|
|
||||||
|
Parent elements: protocol
|
||||||
|
|
||||||
|
```
|
||||||
|
interface ::= (description?, (request|event|enum)+)
|
||||||
|
```
|
||||||
|
|
||||||
|
An interface element contains the requests and events that form the interface.
|
||||||
|
Enumerations can also be defined with enum elements. These all belong into the
|
||||||
|
namespace of the interface. Code generation tools may use the interface `name`
|
||||||
|
in API symbol names.
|
||||||
|
|
||||||
|
Interfaces form an ancestry tree. Aside from
|
||||||
|
[wl_display](https://wayland.app/protocols/wayland#wl_display), new protocol
|
||||||
|
objects are always created through an existing protocol object that may be
|
||||||
|
referred to as _the factory object_. This can happen in one of two ways: the
|
||||||
|
factory object's interface either defines or does not define the new object's
|
||||||
|
interface.
|
||||||
|
|
||||||
|
When the factory interface defines the new object's interface, the new object
|
||||||
|
also inherits the factory object's interface version number. This number defines
|
||||||
|
the interface version of the new object. The factory object is referred to as
|
||||||
|
_the parent object_ and the factory interface is referred to as _the parent
|
||||||
|
interface_. This forms the ancestry tree of interfaces.
|
||||||
|
|
||||||
|
When the factory interface does not define the new object's interface, both the
|
||||||
|
interface name and the version must be communicated explicitly. The foremost
|
||||||
|
example of this is
|
||||||
|
[wl_registry.bind](https://wayland.app/protocols/wayland#wl_registry:request:bind).
|
||||||
|
In this case the terms "parent" or "ancestor" are not used. Interfaces that are
|
||||||
|
advertised through
|
||||||
|
[wl_registry](https://wayland.app/protocols/wayland#wl_registry) are called
|
||||||
|
_global interfaces_, or globals for short.
|
||||||
|
|
||||||
|
If objects having the interface can cause protocol errors, the protocol error
|
||||||
|
codes must be defined within the interface with an enum element with its `name`
|
||||||
|
set to `"error"`. Protocol error codes are always specific to the interface of
|
||||||
|
the object referred to in
|
||||||
|
[wl_display.error](https://wayland.app/protocols/wayland#wl_display:event:error).
|
||||||
|
|
||||||
|
The description element should be used to describe the purpose and the general
|
||||||
|
usage of the interface.
|
||||||
|
|
||||||
|
**Required attributes**
|
||||||
|
|
||||||
|
`name`="`cname`"
|
||||||
|
: The name of the interface. cname-requirements The name must be unique in the
|
||||||
|
protocol, and preferably it should also be globally unique to avoid API
|
||||||
|
conflicts in language bindings of multiple protocols.
|
||||||
|
|
||||||
|
Protocols to be included in
|
||||||
|
[wayland-protocols](https://gitlab.freedesktop.org/wayland/wayland-protocols)
|
||||||
|
must follow the interface naming rules set there. Other protocols should use
|
||||||
|
a unique prefix for the name, e.g. referring to the owning project's name.
|
||||||
|
|
||||||
|
`version`="`V`"
|
||||||
|
: The interface's latest version number `V` must be an integer greater than
|
||||||
|
zero. An interface element defines all versions of the interface from 1 to
|
||||||
|
`V` inclusive. The contents of each interface version are defined in each of
|
||||||
|
the request, event, enum and entry elements using the attributes `since` and
|
||||||
|
`deprecated-since`, and in the specification text.
|
||||||
|
|
||||||
|
When an interface is extended, the version number must be incremented on all
|
||||||
|
the interfaces part of the same interface ancestry tree. The exception to
|
||||||
|
this rule are interfaces which are forever stuck to version 1, which is
|
||||||
|
usually caused by having multiple parent interfaces with independent
|
||||||
|
ancestor global interfaces.
|
||||||
|
|
||||||
|
A protocol object may have any defined version of the interface. The version
|
||||||
|
of the object is determined at runtime either by inheritance from another
|
||||||
|
protocol object or explicitly.
|
||||||
|
|
||||||
|
It is possible for a protocol object to have a version higher than defined
|
||||||
|
by its interface. This may happen when the interface is stuck at version 1
|
||||||
|
as per above. It may also happen when a protocol XML file has not been
|
||||||
|
thoroughly updated as required. In such cases the object shall function as
|
||||||
|
with the highest defined interface version.
|
||||||
|
|
||||||
|
### request
|
||||||
|
|
||||||
|
Parent elements: interface
|
||||||
|
|
||||||
|
```
|
||||||
|
request ::= (description?, arg*)
|
||||||
|
```
|
||||||
|
|
||||||
|
Defines a request, a message from a client to a server. Requests are always
|
||||||
|
associated with a specific protocol object.
|
||||||
|
|
||||||
|
Requests are automatically assigned opcodes in the order they appear inside the
|
||||||
|
interface element. Therefore the only backwards-compatible way to add requests
|
||||||
|
to an interface is to add them to the end. Any event elements do not interfere
|
||||||
|
with request opcode assignments.
|
||||||
|
|
||||||
|
The arg elements declare the request's arguments. There can be 0 to 20 arguments
|
||||||
|
for a request. The order of arg inside the request element defines the order of
|
||||||
|
the arguments on the wire. All declared arguments are mandatory, and extra
|
||||||
|
arguments are not allowed on the wire.
|
||||||
|
|
||||||
|
The description element should be used to document the request.
|
||||||
|
|
||||||
|
**Required attributes**
|
||||||
|
|
||||||
|
`name`="`cname`"
|
||||||
|
: The name of the request. cname-requirements The name must be unique within
|
||||||
|
all requests and events in the containing interface.
|
||||||
|
|
||||||
|
Code and language binding generators may use the name in the API they
|
||||||
|
create. The `name` of the containing interface provides the namespace for
|
||||||
|
requests.
|
||||||
|
|
||||||
|
**Optional attributes**
|
||||||
|
|
||||||
|
`type`="`destructor`"
|
||||||
|
: When this attribute is present, the request is a destructor: it shall
|
||||||
|
destroy the protocol object it is sent on. Protocol IPC libraries may use
|
||||||
|
this for bookkeeping protocol object lifetimes.
|
||||||
|
|
||||||
|
Libwayland-client uses this information to ignore incoming events for
|
||||||
|
destroyed protocol objects. Such events may occur due to a natural race
|
||||||
|
condition between the client destroying a protocol object and the server
|
||||||
|
sending events before processing the destroy request.
|
||||||
|
|
||||||
|
`since`="`S`"
|
||||||
|
: `S` must be an integer greater than zero. If `since` is not specified,
|
||||||
|
`since="1"` is assumed.
|
||||||
|
|
||||||
|
This request was added in interface `version` `S`. The request does not
|
||||||
|
exist if the protocol object has a bound version smaller than `S`. Attempts
|
||||||
|
to use it in such a case shall raise the protocol error
|
||||||
|
`wl_display.error.invalid_method`.
|
||||||
|
|
||||||
|
`deprecated-since`="`D`"
|
||||||
|
: `D` must be an integer greater than the value of `since`. If
|
||||||
|
`deprecated-since` is not specified, then the request is not deprecated in
|
||||||
|
any version of the containing interface.
|
||||||
|
|
||||||
|
This request was deprecated in interface `version` `D` and above, and should
|
||||||
|
not be sent on protocol objects of such version. This is informational.
|
||||||
|
Compositors must still be prepared to handle the request unless specified
|
||||||
|
otherwise.
|
||||||
|
|
||||||
|
### event
|
||||||
|
|
||||||
|
Parent elements: interface
|
||||||
|
|
||||||
|
```
|
||||||
|
event ::= (description?, arg*)
|
||||||
|
```
|
||||||
|
|
||||||
|
Defines an event, a message from a server to a client. Events are always
|
||||||
|
associated with a specific protocol object.
|
||||||
|
|
||||||
|
Events are automatically assigned opcodes in the order they appear inside the
|
||||||
|
interface element. Therefore the only backwards-compatible way to add events to
|
||||||
|
an interface is to add them to the end. Any request elements do not interfere
|
||||||
|
with event opcode assignments.
|
||||||
|
|
||||||
|
The arg elements declare the event's arguments. There can be 0 to 20 arguments
|
||||||
|
for an event. The order of arg inside the event element defines the order of the
|
||||||
|
arguments on the wire. All declared arguments are mandatory, and extra arguments
|
||||||
|
are not allowed on the wire.
|
||||||
|
|
||||||
|
The description element should be used to document the event.
|
||||||
|
|
||||||
|
**Required attributes**
|
||||||
|
|
||||||
|
`name`="`cname`"
|
||||||
|
: The name of the event. cname-requirements The name must be unique within all
|
||||||
|
requests and events in the containing interface.
|
||||||
|
|
||||||
|
Code and language binding generators may use the name in the API they
|
||||||
|
create. The `name` of the containing interface provides the namespace for
|
||||||
|
events.
|
||||||
|
|
||||||
|
**Optional attributes**
|
||||||
|
|
||||||
|
`type`="`destructor`"
|
||||||
|
: When this attribute is present, the event is a destructor: it shall destroy
|
||||||
|
the protocol object it is sent on. Protocol IPC libraries may use this for
|
||||||
|
bookkeeping protocol object lifetimes.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> Destructor events are an underdeveloped feature in Wayland. They can be
|
||||||
|
> used only on client-created protocol objects, and it is the protocol
|
||||||
|
> designer's responsibility to design such a message exchange that race
|
||||||
|
> conditions cannot occur. The main problem would be a client sending a
|
||||||
|
> request at the same time as the server is sending a destructor event. The
|
||||||
|
> server will consider the protocol object to be already invalid or even
|
||||||
|
> recycled when it proceeds to process the request. This often results in
|
||||||
|
> protocol errors, but under specific conditions it might also result in
|
||||||
|
> silently incorrect behavior.
|
||||||
|
>
|
||||||
|
> Destructor events should not be used in new protocols. If a destructor
|
||||||
|
> event is necessary, the simplest way to avoid these problems is to have
|
||||||
|
> the interface not contain any requests.
|
||||||
|
|
||||||
|
`since`="`S`"
|
||||||
|
: `S` must be an integer greater than zero. If `since` is not specified,
|
||||||
|
`since="1"` is assumed.
|
||||||
|
|
||||||
|
This event was added in interface `version` `S`. The event does not exist if
|
||||||
|
the protocol object has a bound version smaller than `S`.
|
||||||
|
|
||||||
|
`deprecated-since`="`D`"
|
||||||
|
: `D` must be an integer greater than the value of `since`. If
|
||||||
|
`deprecated-since` is not specified, then the event is not deprecated in any
|
||||||
|
version of the containing interface.
|
||||||
|
|
||||||
|
This event was deprecated in interface `version` `D` and above, and should
|
||||||
|
not be sent on protocol objects of such version. This is informational.
|
||||||
|
Clients must still be prepared to receive this event unless otherwise
|
||||||
|
specified.
|
||||||
|
|
||||||
|
### arg
|
||||||
|
|
||||||
|
Parent elements: request, event
|
||||||
|
|
||||||
|
```
|
||||||
|
arg ::= description?
|
||||||
|
```
|
||||||
|
|
||||||
|
This element declares one argument for the request or the event.
|
||||||
|
|
||||||
|
**Required attributes**
|
||||||
|
|
||||||
|
`name`="`cname`"
|
||||||
|
: The name of the argument. cname-requirements The name must be unique within
|
||||||
|
all the arguments of the parent element.
|
||||||
|
|
||||||
|
`type`="`T`"
|
||||||
|
: The type `T` of the argument datum must be one of:
|
||||||
|
|
||||||
|
`int`
|
||||||
|
: 32-bit signed integer.
|
||||||
|
|
||||||
|
`uint`
|
||||||
|
: 32-bit unsigned integer.
|
||||||
|
|
||||||
|
`fixed`
|
||||||
|
: Signed 24.8-bit fixed-point value.
|
||||||
|
|
||||||
|
`string`
|
||||||
|
: UTF-8 encoded string value, NUL byte terminated. Interior NUL bytes are
|
||||||
|
not allowed.
|
||||||
|
|
||||||
|
`array`
|
||||||
|
: A byte array of arbitrary data.
|
||||||
|
|
||||||
|
`fd`
|
||||||
|
: A file descriptor.
|
||||||
|
|
||||||
|
The file descriptor must be open and valid on send. It is not possible
|
||||||
|
to pass a null value.
|
||||||
|
|
||||||
|
`new_id`
|
||||||
|
: Creates a new protocol object. A request or an event may have at most
|
||||||
|
one `new_id` argument.
|
||||||
|
|
||||||
|
If `interface` is specified, the new protocol object shall have the
|
||||||
|
specified interface, and the new object's (interface) version shall be
|
||||||
|
the version of the object on which the request or event is being sent.
|
||||||
|
|
||||||
|
If `interface` is not specified, the request shall implicitly have two
|
||||||
|
additional arguments: A `string` for an interface name, and a `uint` for
|
||||||
|
the new object's version. Leaving the interface unspecified is reserved
|
||||||
|
for special use,
|
||||||
|
[wl_registry.bind](https://wayland.app/protocols/wayland#wl_registry:request:bind)
|
||||||
|
for example.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> An event argument must always specify the `new_id` `interface`.
|
||||||
|
|
||||||
|
`object`
|
||||||
|
: Reference to an existing protocol object.
|
||||||
|
|
||||||
|
The attribute `interface` should be specified. Otherwise IPC libraries
|
||||||
|
cannot enforce the interface, and checking the interface falls on user
|
||||||
|
code and specification text.
|
||||||
|
|
||||||
|
**Optional attributes**
|
||||||
|
|
||||||
|
`summary`="`summary`"
|
||||||
|
: A short (half a line at most) description. This attribute should not be used
|
||||||
|
if a description is used.
|
||||||
|
|
||||||
|
`interface`="`iface`"
|
||||||
|
: If given, `iface` must be the `name` of some interface, and `type` of this
|
||||||
|
argument must be either `"object"` or `"new_id"`. This indicates that the
|
||||||
|
existing or new object must have the interface `iface`. Use for other
|
||||||
|
argument types is forbidden.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> If an interface from another protocol is used, then this creates a
|
||||||
|
> dependency between the protocols. If an application generates code for one
|
||||||
|
> protocol, then it must also generate code for all dependencies. Therefore
|
||||||
|
> this would not be a backwards compatible change.
|
||||||
|
|
||||||
|
`allow-null`="`true`" | "`false`"
|
||||||
|
: Whether the argument value can be null on send. Defaults to `"false"`,
|
||||||
|
meaning it is illegal to send a null value. Can be used only when `type` is
|
||||||
|
`"string"` or `"object"`.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Even though this attribute can be used to forbid a compositor from sending
|
||||||
|
> a null object as an event argument, an IPC library implementation may not
|
||||||
|
> protect the client from receiving a null object. This can happen with
|
||||||
|
> libwayland-client when the client has destroyed the protocol object before
|
||||||
|
> dispatching an event that referred to it in an argument.
|
||||||
|
|
||||||
|
`enum`="`enum-cname-suffix`"
|
||||||
|
: If specified, indicates that the argument value should come from the enum
|
||||||
|
named `enum-cname-suffix`. If the enumeration is a bitfield, then `type`
|
||||||
|
must be `"uint"`. Otherwise `type` must be either `"uint"` or `"int"`.
|
||||||
|
|
||||||
|
The name `enum-cname-suffix` refers to an enum in the same interface by
|
||||||
|
default. If it is necessary to refer to an enumeration from another
|
||||||
|
interface, the interface name can be given with a period:
|
||||||
|
|
||||||
|
```
|
||||||
|
`enum`="`iface`.`enum-cname-suffix`"
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> This attribute alone does not automatically restrict the legal values for
|
||||||
|
> this argument. If values from outside of the enumeration need to be
|
||||||
|
> forbidden, that must be specified explicitly in the documentation.
|
||||||
|
>
|
||||||
|
> A common design pattern is to have the server advertise the supported
|
||||||
|
> enumeration or bit values with events and explicitly forbid clients from
|
||||||
|
> using any other values in requests. This also requires a protocol error
|
||||||
|
> code to be specified with the error enum to be raised if a client uses an
|
||||||
|
> illegal value, see [interface](#interface).
|
||||||
|
|
||||||
|
### enum
|
||||||
|
|
||||||
|
Parent elements: protocol
|
||||||
|
|
||||||
|
```
|
||||||
|
enum ::= (description?, entry*)
|
||||||
|
```
|
||||||
|
|
||||||
|
This tag defines an enumeration of integer values. Enumerations are merely a
|
||||||
|
syntactic construct to give names to arbitrary integer constants. Each constant
|
||||||
|
is listed as an entry with its name. There are two types of enumerations:
|
||||||
|
regular enumerations and bitfields.
|
||||||
|
|
||||||
|
Regular enumerations do not use `bitfield` attribute, or they set it to
|
||||||
|
`"false"`. The set of pre-defined values that belong to a regular enumeration is
|
||||||
|
exactly the set of values listed as entry elements after the protocol object
|
||||||
|
version is taken into account. See the entry attributes `since` and
|
||||||
|
`deprecated-since`.
|
||||||
|
|
||||||
|
Bitfields set `bitfield` to `"true"`. The set of values that belong to a
|
||||||
|
bitfield enumeration are all the values that can be formed by the bitwise-or
|
||||||
|
operator from the set of values listed as entry elements like in the regular
|
||||||
|
enumeration. Usually also zero is implicitly included.
|
||||||
|
|
||||||
|
All the values in a regular enumeration must be either signed or unsigned 32-bit
|
||||||
|
integers. All the values in a bitfield enumeration must be unsigned 32-bit
|
||||||
|
integers.
|
||||||
|
|
||||||
|
**Required attributes**
|
||||||
|
|
||||||
|
`name`="`cname-suffix`"
|
||||||
|
: The name of the enumeration. cname-suffix-requirements The name must be
|
||||||
|
unique within all enumerations in the containing interface. The name is used
|
||||||
|
as the namespace for all the contained entry elements.
|
||||||
|
|
||||||
|
**Optional attributes**
|
||||||
|
|
||||||
|
`since`="`S`"
|
||||||
|
: `S` must be an integer greater than zero. If `since` is not specified,
|
||||||
|
`since="1"` is assumed.
|
||||||
|
|
||||||
|
This enumeration was added in interface `version` `S`. The enumeration does
|
||||||
|
not exist if the protocol object has a bound version smaller than `S`.
|
||||||
|
|
||||||
|
`bitfield`="`true`" | "`false`"
|
||||||
|
: Specifies if this enumeration is a bitfield. Defaults to `"false"`.
|
||||||
|
|
||||||
|
### entry
|
||||||
|
|
||||||
|
Parent elements: enum
|
||||||
|
|
||||||
|
```
|
||||||
|
entry ::= description?
|
||||||
|
```
|
||||||
|
|
||||||
|
Defines a name for an integer constant and makes it part of the set of values of
|
||||||
|
the containing enumeration.
|
||||||
|
|
||||||
|
**Required attributes**
|
||||||
|
|
||||||
|
`name`="`cname-suffix`"
|
||||||
|
: The name of a value in an enumeration. cname-suffix-requirements The name
|
||||||
|
must be unique within all entry elements in the containing enum.
|
||||||
|
|
||||||
|
`value`="`V`"
|
||||||
|
: An integer value. The value can be given in decimal, hexadecimal, or octal
|
||||||
|
representation.
|
||||||
|
|
||||||
|
**Optional attributes**
|
||||||
|
|
||||||
|
`summary`="`summary`"
|
||||||
|
: A short (half a line at most) description. This attribute should not be used
|
||||||
|
if a description is used.
|
||||||
|
|
||||||
|
`since`="`S`"
|
||||||
|
: `S` must be an integer greater than zero. If `since` is not specified,
|
||||||
|
`since="1"` is assumed.
|
||||||
|
|
||||||
|
This value was added in interface `version` `S`.
|
||||||
|
|
||||||
|
`deprecated-since`="`D`"
|
||||||
|
: `D` must be an integer greater than the value of `since`. If
|
||||||
|
`deprecated-since` is not specified, then the value is not deprecated in any
|
||||||
|
version of the containing interface.
|
||||||
|
|
||||||
|
This value was removed in interface `version` `D`. This does not make the
|
||||||
|
value automatically illegal to use, see [arg](#arg) attribute `enum`.
|
||||||
371
doc/book/src/Protocol.md
Normal file
|
|
@ -0,0 +1,371 @@
|
||||||
|
# Wayland Protocol and Model of Operation
|
||||||
|
|
||||||
|
## Basic Principles
|
||||||
|
|
||||||
|
The Wayland protocol is an asynchronous object oriented protocol. All requests
|
||||||
|
are method invocations on some object. The requests include an object ID that
|
||||||
|
uniquely identifies an object on the server. Each object implements an interface
|
||||||
|
and the requests include an opcode that identifies which method in the interface
|
||||||
|
to invoke.
|
||||||
|
|
||||||
|
The protocol is message-based. A message sent by a client to the server is
|
||||||
|
called request. A message from the server to a client is called event. A message
|
||||||
|
has a number of arguments, each of which has a certain type (see [Wire
|
||||||
|
Format](#wire-format) for a list of argument types).
|
||||||
|
|
||||||
|
Additionally, the protocol can specify `enum`s which associate names to specific
|
||||||
|
numeric enumeration values. These are primarily just descriptive in nature: at
|
||||||
|
the wire format level enums are just integers. But they also serve a secondary
|
||||||
|
purpose to enhance type safety or otherwise add context for use in language
|
||||||
|
bindings or other such code. This latter usage is only supported so long as code
|
||||||
|
written before these attributes were introduced still works after; in other
|
||||||
|
words, adding an enum should not break API, otherwise it puts backwards
|
||||||
|
compatibility at risk.
|
||||||
|
|
||||||
|
`enum`s can be defined as just a set of integers, or as bitfields. This is
|
||||||
|
specified via the `bitfield` boolean attribute in the `enum` definition. If this
|
||||||
|
attribute is true, the enum is intended to be accessed primarily using bitwise
|
||||||
|
operations, for example when arbitrarily many choices of the enum can be ORed
|
||||||
|
together; if it is false, or the attribute is omitted, then the enum arguments
|
||||||
|
are a just a sequence of numerical values.
|
||||||
|
|
||||||
|
The `enum` attribute can be used on either `uint` or `int` arguments, however if
|
||||||
|
the `enum` is defined as a `bitfield`, it can only be used on `uint` args.
|
||||||
|
|
||||||
|
The server sends back events to the client, each event is emitted from an
|
||||||
|
object. Events can be error conditions. The event includes the object ID and the
|
||||||
|
event opcode, from which the client can determine the type of event. Events are
|
||||||
|
generated both in response to requests (in which case the request and the event
|
||||||
|
constitutes a round trip) or spontaneously when the server state changes.
|
||||||
|
|
||||||
|
- State is broadcast on connect, events are sent out when state changes. Clients
|
||||||
|
must listen for these changes and cache the state. There is no need (or
|
||||||
|
mechanism) to query server state.
|
||||||
|
|
||||||
|
- The server will broadcast the presence of a number of global objects, which in
|
||||||
|
turn will broadcast their current state.
|
||||||
|
|
||||||
|
## Code Generation
|
||||||
|
|
||||||
|
The interfaces, requests and events are defined in
|
||||||
|
[protocol/wayland.xml](https://gitlab.freedesktop.org/wayland/wayland/-/blob/main/protocol/wayland.xml).
|
||||||
|
This xml is used to generate the function prototypes that can be used by clients
|
||||||
|
and compositors.
|
||||||
|
|
||||||
|
The protocol entry points are generated as inline functions which just wrap the
|
||||||
|
`wl_proxy_*` functions. The inline functions aren't part of the library ABI and
|
||||||
|
language bindings should generate their own stubs for the protocol entry points
|
||||||
|
from the xml.
|
||||||
|
|
||||||
|
## Wire Format
|
||||||
|
|
||||||
|
The protocol is sent over a UNIX domain stream socket, where the endpoint
|
||||||
|
usually is named `wayland-0` (although it can be changed via _WAYLAND_DISPLAY_
|
||||||
|
in the environment). Beginning in Wayland 1.15, implementations can optionally
|
||||||
|
support server socket endpoints located at arbitrary locations in the filesystem
|
||||||
|
by setting _WAYLAND_DISPLAY_ to the absolute path at which the server endpoint
|
||||||
|
listens. The socket may also be provided through file descriptor inheritance, in
|
||||||
|
which case _WAYLAND_SOCKET_ is set.
|
||||||
|
|
||||||
|
Every message is structured as 32-bit words; values are represented in the
|
||||||
|
host's byte-order. The message header has 2 words in it:
|
||||||
|
|
||||||
|
- The first word is the sender's object ID (32-bit).
|
||||||
|
|
||||||
|
- The second has 2 parts of 16-bit. The upper 16-bits are the message size in
|
||||||
|
bytes, starting at the header (i.e. it has a minimum value of 8).The lower is
|
||||||
|
the request/event opcode.
|
||||||
|
|
||||||
|
The payload describes the request/event arguments. Every argument is always
|
||||||
|
aligned to 32-bits. Where padding is required, the value of padding bytes is
|
||||||
|
undefined. There is no prefix that describes the type, but it is inferred
|
||||||
|
implicitly from the xml specification.
|
||||||
|
|
||||||
|
The representation of argument types are as follows:
|
||||||
|
|
||||||
|
int
|
||||||
|
uint
|
||||||
|
: The value is the 32-bit value of the signed/unsigned int.
|
||||||
|
|
||||||
|
fixed
|
||||||
|
: Signed 24.8 decimal numbers. It is a signed decimal type which offers a sign
|
||||||
|
bit, 23 bits of integer precision and 8 bits of decimal precision. This is
|
||||||
|
exposed as an opaque struct with conversion helpers to and from double and
|
||||||
|
int on the C API side.
|
||||||
|
|
||||||
|
string
|
||||||
|
: Starts with an unsigned 32-bit length (including null terminator), followed
|
||||||
|
by the UTF-8 encoded string contents, including terminating null byte, then
|
||||||
|
padding to a 32-bit boundary. A null value is represented with a length of
|
||||||
|
0. Interior null bytes are not permitted.
|
||||||
|
|
||||||
|
object
|
||||||
|
: 32-bit object ID. A null value is represented with an ID of 0.
|
||||||
|
|
||||||
|
new_id
|
||||||
|
: The 32-bit object ID. Generally, the interface used for the new object is
|
||||||
|
inferred from the xml, but in the case where it's not specified, a new_id is
|
||||||
|
preceded by a `string` specifying the interface name, and a `uint`
|
||||||
|
specifying the version.
|
||||||
|
|
||||||
|
array
|
||||||
|
: Starts with 32-bit array size in bytes, followed by the array contents
|
||||||
|
verbatim, and finally padding to a 32-bit boundary.
|
||||||
|
|
||||||
|
fd
|
||||||
|
: The file descriptor is not stored in the message buffer, but in the
|
||||||
|
ancillary data of the UNIX domain socket message (msg_control).
|
||||||
|
|
||||||
|
The protocol does not specify the exact position of the ancillary data in the
|
||||||
|
stream, except that the order of file descriptors is the same as the order of
|
||||||
|
messages and `fd` arguments within messages on the wire.
|
||||||
|
|
||||||
|
In particular, it means that any byte of the stream, even the message header,
|
||||||
|
may carry the ancillary data with file descriptors.
|
||||||
|
|
||||||
|
Clients and compositors should queue incoming data until they have whole
|
||||||
|
messages to process, as file descriptors may arrive earlier or later than the
|
||||||
|
corresponding data bytes.
|
||||||
|
|
||||||
|
## Versioning
|
||||||
|
|
||||||
|
Every interface is versioned and every protocol object implements a particular
|
||||||
|
version of its interface. For global objects, the maximum version supported by
|
||||||
|
the server is advertised with the global and the actual version of the created
|
||||||
|
protocol object is determined by the version argument passed to
|
||||||
|
wl_registry.bind(). For objects that are not globals, their version is inferred
|
||||||
|
from the object that created them.
|
||||||
|
|
||||||
|
In order to keep things sane, this has a few implications for interface
|
||||||
|
versions:
|
||||||
|
|
||||||
|
- The object creation hierarchy must be a tree. Otherwise, inferring object
|
||||||
|
versions from the parent object becomes a much more difficult to properly
|
||||||
|
track.
|
||||||
|
|
||||||
|
- When the version of an interface increases, so does the version of its parent
|
||||||
|
(recursively until you get to a global interface)
|
||||||
|
|
||||||
|
- A global interface's version number acts like a counter for all of its child
|
||||||
|
interfaces. Whenever a child interface gets modified, the global parent's
|
||||||
|
interface version number also increases (see above). The child interface then
|
||||||
|
takes on the same version number as the new version of its parent global
|
||||||
|
interface.
|
||||||
|
|
||||||
|
To illustrate the above, consider the wl_compositor interface. It has two
|
||||||
|
children, wl_surface and wl_region. As of wayland version 1.2, wl_surface and
|
||||||
|
wl_compositor are both at version 3. If something is added to the wl_region
|
||||||
|
interface, both wl_region and wl_compositor will get bumpped to version 4. If,
|
||||||
|
afterwards, wl_surface is changed, both wl_compositor and wl_surface will be at
|
||||||
|
version 5. In this way the global interface version is used as a sort of
|
||||||
|
"counter" for all of its child interfaces. This makes it very simple to know the
|
||||||
|
version of the child given the version of its parent. The child is at the
|
||||||
|
highest possible interface version that is less than or equal to its parent's
|
||||||
|
version.
|
||||||
|
|
||||||
|
It is worth noting a particular exception to the above versioning scheme. The
|
||||||
|
wl_display (and, by extension, wl_registry) interface cannot change because it
|
||||||
|
is the core protocol object and its version is never advertised nor is there a
|
||||||
|
mechanism to request a different version.
|
||||||
|
|
||||||
|
## Connect Time
|
||||||
|
|
||||||
|
There is no fixed connection setup information, the server emits multiple events
|
||||||
|
at connect time, to indicate the presence and properties of global objects:
|
||||||
|
outputs, compositor, input devices.
|
||||||
|
|
||||||
|
## Security and Authentication
|
||||||
|
|
||||||
|
- mostly about access to underlying buffers, need new drm auth mechanism (the
|
||||||
|
grant-to ioctl idea), need to check the cmd stream?
|
||||||
|
|
||||||
|
- getting the server socket depends on the compositor type, could be a system
|
||||||
|
wide name, through fd passing on the session dbus. or the client is forked by
|
||||||
|
the compositor and the fd is already opened.
|
||||||
|
|
||||||
|
## Creating Objects
|
||||||
|
|
||||||
|
Each object has a unique ID. The IDs are allocated by the entity creating the
|
||||||
|
object (either client or server). IDs allocated by the client are in the range
|
||||||
|
[1, 0xfeffffff] while IDs allocated by the server are in the range [0xff000000,
|
||||||
|
0xffffffff]. The 0 ID is reserved to represent a null or non-existent object.
|
||||||
|
For efficiency purposes, the IDs are densely packed in the sense that the ID N
|
||||||
|
will not be used until N-1 has been used. This ordering is not merely a
|
||||||
|
guideline, but a strict requirement, and there are implementations of the
|
||||||
|
protocol that rigorously enforce this rule, including the ubiquitous libwayland.
|
||||||
|
|
||||||
|
## Compositor
|
||||||
|
|
||||||
|
The compositor is a global object, advertised at connect time.
|
||||||
|
|
||||||
|
See [wl_compositor](https://wayland.app/protocols/wayland#wl_compositor) for the
|
||||||
|
protocol description.
|
||||||
|
|
||||||
|
## Surfaces
|
||||||
|
|
||||||
|
A surface manages a rectangular grid of pixels that clients create for
|
||||||
|
displaying their content to the screen. Clients don't know the global position
|
||||||
|
of their surfaces, and cannot access other clients' surfaces.
|
||||||
|
|
||||||
|
Once the client has finished writing pixels, it 'commits' the buffer; this
|
||||||
|
permits the compositor to access the buffer and read the pixels. When the
|
||||||
|
compositor is finished, it releases the buffer back to the client.
|
||||||
|
|
||||||
|
See [wl_surface](https://wayland.app/protocols/wayland#wl_surface) for the
|
||||||
|
protocol description.
|
||||||
|
|
||||||
|
## Input
|
||||||
|
|
||||||
|
A seat represents a group of input devices including mice, keyboards and
|
||||||
|
touchscreens. It has a keyboard and pointer focus. Seats are global objects.
|
||||||
|
Pointer events are delivered in surface-local coordinates.
|
||||||
|
|
||||||
|
The compositor maintains an implicit grab when a button is pressed, to ensure
|
||||||
|
that the corresponding button release event gets delivered to the same surface.
|
||||||
|
But there is no way for clients to take an explicit grab. Instead, surfaces can
|
||||||
|
be mapped as 'popup', which combines transient window semantics with a pointer
|
||||||
|
grab.
|
||||||
|
|
||||||
|
To avoid race conditions, input events that are likely to trigger further
|
||||||
|
requests (such as button presses, key events, pointer motions) carry serial
|
||||||
|
numbers, and requests such as wl_surface.set_popup require that the serial
|
||||||
|
number of the triggering event is specified. The server maintains a
|
||||||
|
monotonically increasing counter for these serial numbers.
|
||||||
|
|
||||||
|
Input events also carry timestamps with millisecond granularity. Their base is
|
||||||
|
undefined, so they can't be compared against system time (as obtained with
|
||||||
|
clock_gettime or gettimeofday). They can be compared with each other though, and
|
||||||
|
for instance be used to identify sequences of button presses as double or triple
|
||||||
|
clicks.
|
||||||
|
|
||||||
|
See [wl_seat](https://wayland.app/protocols/wayland#wl_seat) for the protocol
|
||||||
|
description.
|
||||||
|
|
||||||
|
Talk about:
|
||||||
|
|
||||||
|
- keyboard map, change events
|
||||||
|
|
||||||
|
- xkb on Wayland
|
||||||
|
|
||||||
|
- multi pointer Wayland
|
||||||
|
|
||||||
|
A surface can change the pointer image when the surface is the pointer focus of
|
||||||
|
the input device. Wayland doesn't automatically change the pointer image when a
|
||||||
|
pointer enters a surface, but expects the application to set the cursor it wants
|
||||||
|
in response to the pointer focus and motion events. The rationale is that a
|
||||||
|
client has to manage changing pointer images for UI elements within the surface
|
||||||
|
in response to motion events anyway, so we'll make that the only mechanism for
|
||||||
|
setting or changing the pointer image. If the server receives a request to set
|
||||||
|
the pointer image after the surface loses pointer focus, the request is ignored.
|
||||||
|
To the client this will look like it successfully set the pointer image.
|
||||||
|
|
||||||
|
Setting the pointer image to NULL causes the cursor to be hidden.
|
||||||
|
|
||||||
|
The compositor will revert the pointer image back to a default image when no
|
||||||
|
surface has the pointer focus for that device.
|
||||||
|
|
||||||
|
What if the pointer moves from one window which has set a special pointer image
|
||||||
|
to a surface that doesn't set an image in response to the motion event? The new
|
||||||
|
surface will be stuck with the special pointer image. We can't just revert the
|
||||||
|
pointer image on leaving a surface, since if we immediately enter a surface that
|
||||||
|
sets a different image, the image will flicker. If a client does not set a
|
||||||
|
pointer image when the pointer enters a surface, the pointer stays with the
|
||||||
|
image set by the last surface that changed it, possibly even hidden. Such a
|
||||||
|
client is likely just broken.
|
||||||
|
|
||||||
|
## Output
|
||||||
|
|
||||||
|
An output is a global object, advertised at connect time or as it comes and
|
||||||
|
goes.
|
||||||
|
|
||||||
|
See [wl_output](https://wayland.app/protocols/wayland#wl_output) for the
|
||||||
|
protocol description.
|
||||||
|
|
||||||
|
- laid out in a big (compositor) coordinate system
|
||||||
|
|
||||||
|
- basically xrandr over Wayland
|
||||||
|
|
||||||
|
- geometry needs position in compositor coordinate system
|
||||||
|
|
||||||
|
- events to advertise available modes, requests to move and change modes
|
||||||
|
|
||||||
|
## Data sharing between clients
|
||||||
|
|
||||||
|
The Wayland protocol provides clients a mechanism for sharing data that allows
|
||||||
|
the implementation of copy-paste and drag-and-drop. The client providing the
|
||||||
|
data creates a `wl_data_source` object and the clients obtaining the data will
|
||||||
|
see it as `wl_data_offer` object. This interface allows the clients to agree on
|
||||||
|
a mutually supported mime type and transfer the data via a file descriptor that
|
||||||
|
is passed through the protocol.
|
||||||
|
|
||||||
|
The next section explains the negotiation between data source and data offer
|
||||||
|
objects. [Data devices](#data-devices) explains how these objects are created
|
||||||
|
and passed to different clients using the `wl_data_device` interface that
|
||||||
|
implements copy-paste and drag-and-drop support.
|
||||||
|
|
||||||
|
See [wl_data_offer](https://wayland.app/protocols/wayland#wl_data_offer),
|
||||||
|
[wl_data_source](https://wayland.app/protocols/wayland#wl_data_source),
|
||||||
|
[wl_data_device](https://wayland.app/protocols/wayland#wl_data_device) and
|
||||||
|
[wl_data_device_manager](https://wayland.app/protocols/wayland#wl_data_device_manager)
|
||||||
|
for protocol descriptions.
|
||||||
|
|
||||||
|
MIME is defined in RFC's 2045-2049. A [registry of MIME
|
||||||
|
types](https://www.iana.org/assignments/media-types/media-types.xhtml) is
|
||||||
|
maintained by the Internet Assigned Numbers Authority (IANA).
|
||||||
|
|
||||||
|
### Data negotiation
|
||||||
|
|
||||||
|
A client providing data to other clients will create a `wl_data_source` object
|
||||||
|
and advertise the mime types for the formats it supports for that data through
|
||||||
|
the `wl_data_source.offer` request. On the receiving end, the data offer object
|
||||||
|
will generate one `wl_data_offer.offer` event for each supported mime type.
|
||||||
|
|
||||||
|
The actual data transfer happens when the receiving client sends a
|
||||||
|
`wl_data_offer.receive` request. This request takes a mime type and a file
|
||||||
|
descriptor as arguments. This request will generate a `wl_data_source.send`
|
||||||
|
event on the sending client with the same arguments, and the latter client is
|
||||||
|
expected to write its data to the given file descriptor using the chosen mime
|
||||||
|
type.
|
||||||
|
|
||||||
|
### Data devices
|
||||||
|
|
||||||
|
Data devices glue data sources and offers together. A data device is associated
|
||||||
|
with a `wl_seat` and is obtained by the clients using the
|
||||||
|
`wl_data_device_manager` factory object, which is also responsible for creating
|
||||||
|
data sources.
|
||||||
|
|
||||||
|
Clients are informed of new data offers through the `wl_data_device.data_offer`
|
||||||
|
event. After this event is generated the data offer will advertise the available
|
||||||
|
mime types. New data offers are introduced prior to their use for copy-paste or
|
||||||
|
drag-and-drop.
|
||||||
|
|
||||||
|
#### Selection
|
||||||
|
|
||||||
|
Each data device has a selection data source. Clients create a data source
|
||||||
|
object using the device manager and may set it as the current selection for a
|
||||||
|
given data device. Whenever the current selection changes, the client with
|
||||||
|
keyboard focus receives a `wl_data_device.selection` event. This event is also
|
||||||
|
generated on a client immediately before it receives keyboard focus.
|
||||||
|
|
||||||
|
The data offer is introduced with `wl_data_device.data_offer` event before the
|
||||||
|
selection event.
|
||||||
|
|
||||||
|
#### Drag and Drop
|
||||||
|
|
||||||
|
A drag-and-drop operation is started using the `wl_data_device.start_drag`
|
||||||
|
request. This requests causes a pointer grab that will generate enter, motion
|
||||||
|
and leave events on the data device. A data source is supplied as argument to
|
||||||
|
start_drag, and data offers associated with it are supplied to clients surfaces
|
||||||
|
under the pointer in the `wl_data_device.enter` event. The data offer is
|
||||||
|
introduced to the client prior to the enter event with the
|
||||||
|
`wl_data_device.data_offer` event.
|
||||||
|
|
||||||
|
Clients are expected to provide feedback to the data sending client by calling
|
||||||
|
the `wl_data_offer.accept` request with a mime type it accepts. If none of the
|
||||||
|
advertised mime types is supported by the receiving client, it should supply
|
||||||
|
NULL to the accept request. The accept request causes the sending client to
|
||||||
|
receive a `wl_data_source.target` event with the chosen mime type.
|
||||||
|
|
||||||
|
When the drag ends, the receiving client receives a `wl_data_device.drop` event
|
||||||
|
at which it is expected to transfer the data using the `wl_data_offer.receive`
|
||||||
|
request.
|
||||||
12
doc/book/src/SUMMARY.md
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Summary
|
||||||
|
|
||||||
|
[Foreword](Foreword.md)
|
||||||
|
|
||||||
|
- [Introduction](./Introduction.md)
|
||||||
|
- [Types of Compositors](./Compositors.md)
|
||||||
|
- [Wayland Architecture](./Architecture.md)
|
||||||
|
- [Wayland Protocol and Model of Operation](./Protocol.md)
|
||||||
|
- [Message Definition Language](./Message_XML.md)
|
||||||
|
- [X11 Application Support](./Xwayland.md)
|
||||||
|
- [Content Updates](./Content_Updates.md)
|
||||||
|
- [Color management](./Color.md)
|
||||||
120
doc/book/src/Xwayland.md
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
# X11 Application Support
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
Being able to run existing X11 applications is crucial for the adoption of
|
||||||
|
Wayland, especially on desktops, as there will always be X11 applications that
|
||||||
|
have not been or cannot be converted into Wayland applications, and throwing
|
||||||
|
them all away would be prohibitive. Therefore a Wayland compositor often needs
|
||||||
|
to support running X11 applications.
|
||||||
|
|
||||||
|
X11 and Wayland are different enough that there is no "simple" way to translate
|
||||||
|
between them. Most of X11 is uninteresting to a Wayland compositor. That,
|
||||||
|
combined with the gigantic implementation effort needed to support X11, makes it
|
||||||
|
intractable to just write X11 support directly in a Wayland compositor. The
|
||||||
|
implementation would be nothing short of a real X11 server.
|
||||||
|
|
||||||
|
Therefore, Wayland compositors should use Xwayland, the X11 server that lives in
|
||||||
|
the Xorg server source code repository and shares most of the implementation
|
||||||
|
with the Xorg server. Xwayland is a complete X11 server, just like Xorg is, but
|
||||||
|
instead of driving the displays and opening input devices, it acts as a Wayland
|
||||||
|
client. The rest of this chapter talks about how Xwayland works.
|
||||||
|
|
||||||
|
For integration and architecture reasons, while Xwayland is a Wayland client of
|
||||||
|
the Wayland compositor, the Wayland compositor is an X11 client of Xwayland.
|
||||||
|
This circular dependency requires special care from the Wayland compositor.
|
||||||
|
|
||||||
|
## Two Modes for Foreign Windows
|
||||||
|
|
||||||
|
In general, windows from a foreign window system can be presented in one of two
|
||||||
|
ways: rootless and rootful (not rootless).
|
||||||
|
|
||||||
|
In rootful mode, the foreign window system as a whole is represented as a window
|
||||||
|
(or more) of its own. You have a native window, inside which all the foreign
|
||||||
|
windows are. The advantage of this approach in Xwayland's case is that you can
|
||||||
|
run your favourite X11 window manager to manage your X11 applications. The
|
||||||
|
disadvantage is that the foreign windows do not integrate with the native
|
||||||
|
desktop. Therefore this mode is not usually used.
|
||||||
|
|
||||||
|
In rootless mode, each foreign window is a first-class resident among the native
|
||||||
|
windows. Foreign windows are not confined inside a native window but act as if
|
||||||
|
they were native windows. The advantage is that one can freely stack and mix
|
||||||
|
native and foreign windows, which is not possible in rootful mode. The
|
||||||
|
disadvantage is that this mode is harder to implement and fundamental
|
||||||
|
differences in window systems may prevent some things from working. With
|
||||||
|
rootless Xwayland, the Wayland compositor must take the role as the X11 window
|
||||||
|
manager, and one cannot use any other X11 window manager in its place.
|
||||||
|
|
||||||
|
This chapter concentrates on the rootless mode, and ignores the rootful mode.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
A Wayland compositor usually takes care of launching Xwayland. Xwayland works in
|
||||||
|
cooperation with a Wayland compositor as follows:
|
||||||
|
|
||||||
|
**Xwayland architecture diagram**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
An X11 application connects to Xwayland just like it would connect to any X
|
||||||
|
server. Xwayland processes all the X11 requests. On the other end, Xwayland is a
|
||||||
|
Wayland client that connects to the Wayland compositor.
|
||||||
|
|
||||||
|
The X11 window manager (XWM) is an integral part of the Wayland compositor. XWM
|
||||||
|
uses the usual X11 window management protocol to manage all X11 windows in
|
||||||
|
Xwayland. Most importantly, XWM acts as a bridge between Xwayland window state
|
||||||
|
and the Wayland compositor's window manager (WWM). This way WWM can manage all
|
||||||
|
windows, both native Wayland and X11 (Xwayland) windows. This is very important
|
||||||
|
for a coherent user experience.
|
||||||
|
|
||||||
|
Since Xwayland uses Wayland for input and output, it does not have any use for
|
||||||
|
the device drivers that Xorg uses. None of the xf86-video-* or xf86-input-*
|
||||||
|
modules are used. There also is no configuration file for the Xwayland server.
|
||||||
|
For optional hardware accelerated rendering, Xwayland uses GLAMOR.
|
||||||
|
|
||||||
|
A Wayland compositor usually spawns only one Xwayland instance. This is because
|
||||||
|
many X11 applications assume they can communicate with other X11 applications
|
||||||
|
through the X server, and this requires a shared X server instance. This also
|
||||||
|
means that Xwayland does not protect nor isolate X11 clients from each other,
|
||||||
|
unless the Wayland compositor specifically chooses to break the X11 client
|
||||||
|
intercommunications by spawning application specific Xwayland instances. X11
|
||||||
|
clients are naturally isolated from Wayland clients.
|
||||||
|
|
||||||
|
Xwayland compatibility compared to a native X server will probably never reach
|
||||||
|
100%. Desktop environment (DE) components, specifically X11 window managers, are
|
||||||
|
practically never supported. An X11 window manager would not know about native
|
||||||
|
Wayland windows, so it could manage only X11 windows. On the other hand, there
|
||||||
|
must be an XWM that reserves the exclusive window manager role so that the
|
||||||
|
Wayland compositor could show the X11 windows appropriately. For other DE
|
||||||
|
components, like pagers and panels, adding the necessary interfaces to support
|
||||||
|
them in WWM through XWM is often considered not worthwhile.
|
||||||
|
|
||||||
|
## X Window Manager (XWM)
|
||||||
|
|
||||||
|
From the X11 point of view, the X window manager (XWM) living inside a Wayland
|
||||||
|
compositor is just like any other window manager. The difference is mostly in
|
||||||
|
which process it resides in, and the few extra conventions in the X11 protocol
|
||||||
|
to support Wayland window management (WWM) specifically.
|
||||||
|
|
||||||
|
There are two separate asynchronous communication channels between Xwayland and
|
||||||
|
a Wayland compositor: one uses the Wayland protocol, and the other one, solely
|
||||||
|
for XWM, uses X11 protocol. This setting demands great care from the XWM
|
||||||
|
implementation to avoid (random) deadlocks with Xwayland. It is often nearly
|
||||||
|
impossible to prove that synchronous or blocking X11 calls from XWM cannot cause
|
||||||
|
a deadlock, and therefore it is strongly recommended to make all X11
|
||||||
|
communications asynchronous. All Wayland communications are already asynchronous
|
||||||
|
by design.
|
||||||
|
|
||||||
|
### Window identification
|
||||||
|
|
||||||
|
In Xwayland, an X11 window may have a corresponding wl_surface object in
|
||||||
|
Wayland. The wl_surface object is used for input and output: it is referenced by
|
||||||
|
input events and used to provide the X11 window content to the Wayland
|
||||||
|
compositor. The X11 window and the wl_surface live in different protocol
|
||||||
|
streams, and they need to be matched for XWM to do its job.
|
||||||
|
|
||||||
|
When Xwayland creates a wl_surface on Wayland, it will also send an X11
|
||||||
|
ClientMessage of type atom "WL_SURFACE_ID" to the X11 window carrying the
|
||||||
|
wl_surface Wayland object ID as the first 32-bit data element. This is how XWM
|
||||||
|
can associate a wl_surface with an X11 window. Note that the request to create a
|
||||||
|
wl_surface and the ID message may arrive in any order in the Wayland compositor.
|
||||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
BIN
doc/book/src/images/wayland-architecture.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
BIN
doc/book/src/images/x-architecture.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
|
|
@ -9,11 +9,6 @@ import sys
|
||||||
|
|
||||||
# Custom configuration for each documentation format
|
# Custom configuration for each documentation format
|
||||||
doxygen_templates = {
|
doxygen_templates = {
|
||||||
'xml': [
|
|
||||||
'GENERATE_XML=YES\n',
|
|
||||||
'XML_OUTPUT={format}/{section}\n',
|
|
||||||
'INPUT= {files}\n',
|
|
||||||
],
|
|
||||||
'html': [
|
'html': [
|
||||||
'GENERATE_HTML=YES\n',
|
'GENERATE_HTML=YES\n',
|
||||||
'HTML_OUTPUT={format}/{section}\n',
|
'HTML_OUTPUT={format}/{section}\n',
|
||||||
|
|
@ -60,9 +55,9 @@ parser.add_argument('--section',
|
||||||
metavar='NAME',
|
metavar='NAME',
|
||||||
default='Client')
|
default='Client')
|
||||||
parser.add_argument('--output-format',
|
parser.add_argument('--output-format',
|
||||||
help='The output format: xml, html, man',
|
help='The output format: html, man',
|
||||||
metavar='FORMAT',
|
metavar='FORMAT',
|
||||||
default='xml')
|
default='html')
|
||||||
parser.add_argument('--stamp',
|
parser.add_argument('--stamp',
|
||||||
help='Stamp file to output',
|
help='Stamp file to output',
|
||||||
metavar='STAMP_FILE',
|
metavar='STAMP_FILE',
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@
|
||||||
* - <a href="../Cursor/index.html">Cursor helper library API</a>
|
* - <a href="../Cursor/index.html">Cursor helper library API</a>
|
||||||
*
|
*
|
||||||
* Further documentation about the architecture and principles of Wayland is
|
* Further documentation about the architecture and principles of Wayland is
|
||||||
* available in the
|
* available on the
|
||||||
* <a href="https://wayland.freedesktop.org/docs/html">Wayland Book</a>
|
* <a href="https://wayland.freedesktop.org/docs">website</a>.
|
||||||
*
|
*
|
||||||
* @section ifaces Interfaces
|
* @section ifaces Interfaces
|
||||||
* For the list of available interfaces, please see the
|
* For the list of available interfaces, please see the
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,6 @@ extra_cursor_files = [
|
||||||
|
|
||||||
gen_doxygen = find_program('gen-doxygen.py')
|
gen_doxygen = find_program('gen-doxygen.py')
|
||||||
|
|
||||||
subdir('xml')
|
|
||||||
|
|
||||||
formats = {
|
formats = {
|
||||||
'html': {
|
'html': {
|
||||||
'Client': shared_files + client_files + extra_client_files,
|
'Client': shared_files + client_files + extra_client_files,
|
||||||
|
|
@ -58,6 +56,8 @@ formats = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html_targets = []
|
||||||
|
|
||||||
foreach f_name, sections: formats
|
foreach f_name, sections: formats
|
||||||
foreach s_name, s_files: sections
|
foreach s_name, s_files: sections
|
||||||
t_name = '@0@-@1@-doc'.format(f_name, s_name)
|
t_name = '@0@-@1@-doc'.format(f_name, s_name)
|
||||||
|
|
@ -66,7 +66,7 @@ foreach f_name, sections: formats
|
||||||
# will complain if one is not set, so we use a
|
# will complain if one is not set, so we use a
|
||||||
# dummy 'stamp' file
|
# dummy 'stamp' file
|
||||||
stamp = join_paths(meson.current_build_dir(), '@0@.stamp'.format(t_name))
|
stamp = join_paths(meson.current_build_dir(), '@0@.stamp'.format(t_name))
|
||||||
custom_target(
|
html_targets += custom_target(
|
||||||
t_name,
|
t_name,
|
||||||
command: [
|
command: [
|
||||||
gen_doxygen,
|
gen_doxygen,
|
||||||
|
|
@ -85,6 +85,16 @@ foreach f_name, sections: formats
|
||||||
endforeach
|
endforeach
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
|
custom_target(
|
||||||
|
'html',
|
||||||
|
input: html_targets,
|
||||||
|
output: 'html',
|
||||||
|
command: 'true',
|
||||||
|
build_by_default: true,
|
||||||
|
install: true,
|
||||||
|
install_dir: publican_install_prefix,
|
||||||
|
)
|
||||||
|
|
||||||
man_files = shared_files + server_files + client_files + cursor_files
|
man_files = shared_files + server_files + client_files + cursor_files
|
||||||
stamp = join_paths(meson.current_build_dir(), 'man3.stamp')
|
stamp = join_paths(meson.current_build_dir(), 'man3.stamp')
|
||||||
custom_target(
|
custom_target(
|
||||||
|
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
tgt = custom_target(
|
|
||||||
'xml-Client-doc',
|
|
||||||
command: [
|
|
||||||
gen_doxygen,
|
|
||||||
# XXX pass doxygen path as argument
|
|
||||||
'--builddir=@OUTDIR@',
|
|
||||||
'--section=Client',
|
|
||||||
'--output-format=xml',
|
|
||||||
wayland_doxygen,
|
|
||||||
'@INPUT@',
|
|
||||||
],
|
|
||||||
input: [ shared_files, client_files ],
|
|
||||||
output: [ 'combine.xslt', 'index.xml' ],
|
|
||||||
)
|
|
||||||
|
|
||||||
doxygen_Client_combine_xslt = tgt[0]
|
|
||||||
doxygen_Client_index_xml = tgt[1]
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
tgt = custom_target(
|
|
||||||
'xml-Server-doc',
|
|
||||||
command: [
|
|
||||||
gen_doxygen,
|
|
||||||
# XXX pass doxygen path as argument
|
|
||||||
'--builddir=@OUTDIR@',
|
|
||||||
'--section=Server',
|
|
||||||
'--output-format=xml',
|
|
||||||
wayland_doxygen,
|
|
||||||
'@INPUT@',
|
|
||||||
],
|
|
||||||
input: [ shared_files, server_files ],
|
|
||||||
output: [ 'combine.xslt', 'index.xml' ],
|
|
||||||
)
|
|
||||||
|
|
||||||
doxygen_Server_combine_xslt = tgt[0]
|
|
||||||
doxygen_Server_index_xml = tgt[1]
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
subdir('Client')
|
|
||||||
subdir('Server')
|
|
||||||
|
|
@ -2,10 +2,8 @@ if not get_option('libraries')
|
||||||
error('-Ddocumentation=true requires -Dlibraries=true')
|
error('-Ddocumentation=true requires -Dlibraries=true')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
dot = find_program('dot')
|
|
||||||
doxygen = find_program('doxygen')
|
doxygen = find_program('doxygen')
|
||||||
xsltproc = find_program('xsltproc')
|
mdbook = find_program('mdbook')
|
||||||
xmlto = find_program('xmlto')
|
|
||||||
|
|
||||||
cmd = run_command(doxygen, '--version', check: true)
|
cmd = run_command(doxygen, '--version', check: true)
|
||||||
message('doxygen: ' + cmd.stdout().strip())
|
message('doxygen: ' + cmd.stdout().strip())
|
||||||
|
|
@ -14,19 +12,6 @@ if vers.version_compare('< 1.6.0')
|
||||||
error('Doxygen 1.6 or later is required for building documentation, found @0@.'.format(vers))
|
error('Doxygen 1.6 or later is required for building documentation, found @0@.'.format(vers))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
cmd = run_command(dot, '-V', check: true)
|
|
||||||
message('dot: ' + cmd.stderr().strip())
|
|
||||||
vers = cmd.stderr().split('version')[1].strip().split(' ')[0]
|
|
||||||
if vers.version_compare('< 2.26.0')
|
|
||||||
error('Dot (Graphviz) 2.26 or later is required for building documentation, found @0@.'.format(vers))
|
|
||||||
endif
|
|
||||||
|
|
||||||
manpage_xsl = 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl'
|
|
||||||
cmd = run_command(xsltproc, '--nonet', manpage_xsl, check: false)
|
|
||||||
if cmd.returncode() != 0
|
|
||||||
error('The style sheet for man pages providing "@0@" was not found.'.format(manpage_xsl))
|
|
||||||
endif
|
|
||||||
|
|
||||||
publican_install_prefix = join_paths(
|
publican_install_prefix = join_paths(
|
||||||
get_option('prefix'),
|
get_option('prefix'),
|
||||||
get_option('datadir'),
|
get_option('datadir'),
|
||||||
|
|
@ -38,4 +23,4 @@ publican_install_prefix = join_paths(
|
||||||
publican_html_dir = 'html'
|
publican_html_dir = 'html'
|
||||||
|
|
||||||
subdir('doxygen')
|
subdir('doxygen')
|
||||||
subdir('publican')
|
subdir('book')
|
||||||
|
|
|
||||||
3
doc/publican/.gitignore
vendored
|
|
@ -1,3 +0,0 @@
|
||||||
Wayland
|
|
||||||
en-US/
|
|
||||||
publican-copy.cfg
|
|
||||||
|
|
@ -1,392 +0,0 @@
|
||||||
<?xml version='1.0' encoding='utf-8' ?>
|
|
||||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
||||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
|
||||||
%BOOK_ENTITIES;
|
|
||||||
]>
|
|
||||||
<chapter id="chap-Wayland-Architecture">
|
|
||||||
<title>Wayland Architecture</title>
|
|
||||||
<section id="sect-Wayland-Architecture-wayland_architecture">
|
|
||||||
<title>X vs. Wayland Architecture</title>
|
|
||||||
<para>
|
|
||||||
A good way to understand the Wayland architecture
|
|
||||||
and how it is different from X is to follow an event
|
|
||||||
from the input device to the point where the change
|
|
||||||
it affects appears on screen.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This is where we are now with X:
|
|
||||||
</para>
|
|
||||||
<figure>
|
|
||||||
<title>X architecture diagram</title>
|
|
||||||
<mediaobjectco>
|
|
||||||
<imageobjectco>
|
|
||||||
<areaspec id="map1" units="other" otherunits="imagemap">
|
|
||||||
<area id="area1_1" linkends="x_flow_1" x_steal="#step_1"/>
|
|
||||||
<area id="area1_2" linkends="x_flow_2" x_steal="#step_2"/>
|
|
||||||
<area id="area1_3" linkends="x_flow_3" x_steal="#step_3"/>
|
|
||||||
<area id="area1_4" linkends="x_flow_4" x_steal="#step_4"/>
|
|
||||||
<area id="area1_5" linkends="x_flow_5" x_steal="#step_5"/>
|
|
||||||
<area id="area1_6" linkends="x_flow_6" x_steal="#step_6"/>
|
|
||||||
</areaspec>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/x-architecture.png" format="PNG" />
|
|
||||||
</imageobject>
|
|
||||||
</imageobjectco>
|
|
||||||
</mediaobjectco>
|
|
||||||
</figure>
|
|
||||||
<para>
|
|
||||||
<orderedlist>
|
|
||||||
<listitem id="x_flow_1">
|
|
||||||
<para>
|
|
||||||
The kernel gets an event from an input
|
|
||||||
device and sends it to X through the evdev
|
|
||||||
input driver. The kernel does all the hard
|
|
||||||
work here by driving the device and
|
|
||||||
translating the different device specific
|
|
||||||
event protocols to the linux evdev input
|
|
||||||
event standard.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem id="x_flow_2">
|
|
||||||
<para>
|
|
||||||
The X server determines which window the
|
|
||||||
event affects and sends it to the clients
|
|
||||||
that have selected for the event in question
|
|
||||||
on that window. The X server doesn't
|
|
||||||
actually know how to do this right, since
|
|
||||||
the window location on screen is controlled
|
|
||||||
by the compositor and may be transformed in
|
|
||||||
a number of ways that the X server doesn't
|
|
||||||
understand (scaled down, rotated, wobbling,
|
|
||||||
etc).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem id="x_flow_3">
|
|
||||||
<para>
|
|
||||||
The client looks at the event and decides
|
|
||||||
what to do. Often the UI will have to change
|
|
||||||
in response to the event - perhaps a check
|
|
||||||
box was clicked or the pointer entered a
|
|
||||||
button that must be highlighted. Thus the
|
|
||||||
client sends a rendering request back to the
|
|
||||||
X server.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem id="x_flow_4">
|
|
||||||
<para>
|
|
||||||
When the X server receives the rendering
|
|
||||||
request, it sends it to the driver to let it
|
|
||||||
program the hardware to do the rendering.
|
|
||||||
The X server also calculates the bounding
|
|
||||||
region of the rendering, and sends that to
|
|
||||||
the compositor as a damage event.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem id="x_flow_5">
|
|
||||||
<para>
|
|
||||||
The damage event tells the compositor that
|
|
||||||
something changed in the window and that it
|
|
||||||
has to recomposite the part of the screen
|
|
||||||
where that window is visible. The compositor
|
|
||||||
is responsible for rendering the entire
|
|
||||||
screen contents based on its scenegraph and
|
|
||||||
the contents of the X windows. Yet, it has
|
|
||||||
to go through the X server to render this.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem id="x_flow_6">
|
|
||||||
<para>
|
|
||||||
The X server receives the rendering requests
|
|
||||||
from the compositor and either copies the
|
|
||||||
compositor back buffer to the front buffer
|
|
||||||
or does a pageflip. In the general case, the
|
|
||||||
X server has to do this step so it can
|
|
||||||
account for overlapping windows, which may
|
|
||||||
require clipping and determine whether or
|
|
||||||
not it can page flip. However, for a
|
|
||||||
compositor, which is always fullscreen, this
|
|
||||||
is another unnecessary context switch.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</orderedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
As suggested above, there are a few problems with this
|
|
||||||
approach. The X server doesn't have the information to
|
|
||||||
decide which window should receive the event, nor can it
|
|
||||||
transform the screen coordinates to window-local
|
|
||||||
coordinates. And even though X has handed responsibility for
|
|
||||||
the final painting of the screen to the compositing manager,
|
|
||||||
X still controls the front buffer and modesetting. Most of
|
|
||||||
the complexity that the X server used to handle is now
|
|
||||||
available in the kernel or self contained libraries (KMS,
|
|
||||||
evdev, mesa, fontconfig, freetype, cairo, Qt etc). In
|
|
||||||
general, the X server is now just a middle man that
|
|
||||||
introduces an extra step between applications and the
|
|
||||||
compositor and an extra step between the compositor and the
|
|
||||||
hardware.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In Wayland the compositor is the display server. We transfer
|
|
||||||
the control of KMS and evdev to the compositor. The Wayland
|
|
||||||
protocol lets the compositor send the input events directly
|
|
||||||
to the clients and lets the client send the damage event
|
|
||||||
directly to the compositor:
|
|
||||||
</para>
|
|
||||||
<figure>
|
|
||||||
<title>Wayland architecture diagram</title>
|
|
||||||
<mediaobjectco>
|
|
||||||
<imageobjectco>
|
|
||||||
<areaspec id="mapB" units="other" otherunits="imagemap">
|
|
||||||
<area id="areaB_1" linkends="wayland_flow_1" x_steal="#step_1"/>
|
|
||||||
<area id="areaB_2" linkends="wayland_flow_2" x_steal="#step_2"/>
|
|
||||||
<area id="areaB_3" linkends="wayland_flow_3" x_steal="#step_3"/>
|
|
||||||
<area id="areaB_4" linkends="wayland_flow_4" x_steal="#step_4"/>
|
|
||||||
</areaspec>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/wayland-architecture.png" format="PNG" />
|
|
||||||
</imageobject>
|
|
||||||
</imageobjectco>
|
|
||||||
</mediaobjectco>
|
|
||||||
</figure>
|
|
||||||
<para>
|
|
||||||
<orderedlist>
|
|
||||||
<listitem id="wayland_flow_1">
|
|
||||||
<para>
|
|
||||||
The kernel gets an event and sends
|
|
||||||
it to the compositor. This
|
|
||||||
is similar to the X case, which is
|
|
||||||
great, since we get to reuse all the
|
|
||||||
input drivers in the kernel.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem id="wayland_flow_2">
|
|
||||||
<para>
|
|
||||||
The compositor looks through its
|
|
||||||
scenegraph to determine which window
|
|
||||||
should receive the event. The
|
|
||||||
scenegraph corresponds to what's on
|
|
||||||
screen and the compositor
|
|
||||||
understands the transformations that
|
|
||||||
it may have applied to the elements
|
|
||||||
in the scenegraph. Thus, the
|
|
||||||
compositor can pick the right window
|
|
||||||
and transform the screen coordinates
|
|
||||||
to window-local coordinates, by
|
|
||||||
applying the inverse
|
|
||||||
transformations. The types of
|
|
||||||
transformation that can be applied
|
|
||||||
to a window is only restricted to
|
|
||||||
what the compositor can do, as long
|
|
||||||
as it can compute the inverse
|
|
||||||
transformation for the input events.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem id="wayland_flow_3">
|
|
||||||
<para>
|
|
||||||
As in the X case, when the client
|
|
||||||
receives the event, it updates the
|
|
||||||
UI in response. But in the Wayland
|
|
||||||
case, the rendering happens in the
|
|
||||||
client, and the client just sends a
|
|
||||||
request to the compositor to
|
|
||||||
indicate the region that was
|
|
||||||
updated.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem id="wayland_flow_4">
|
|
||||||
<para>
|
|
||||||
The compositor collects damage
|
|
||||||
requests from its clients and then
|
|
||||||
recomposites the screen. The
|
|
||||||
compositor can then directly issue
|
|
||||||
an ioctl to schedule a pageflip with
|
|
||||||
KMS.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
|
|
||||||
</orderedlist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-Wayland-Architecture-wayland_rendering">
|
|
||||||
<title>Wayland Rendering</title>
|
|
||||||
<para>
|
|
||||||
One of the details I left out in the above overview
|
|
||||||
is how clients actually render under Wayland. By
|
|
||||||
removing the X server from the picture we also
|
|
||||||
removed the mechanism by which X clients typically
|
|
||||||
render. But there's another mechanism that we're
|
|
||||||
already using with DRI2 under X: direct rendering.
|
|
||||||
With direct rendering, the client and the server
|
|
||||||
share a video memory buffer. The client links to a
|
|
||||||
rendering library such as OpenGL that knows how to
|
|
||||||
program the hardware and renders directly into the
|
|
||||||
buffer. The compositor in turn can take the buffer
|
|
||||||
and use it as a texture when it composites the
|
|
||||||
desktop. After the initial setup, the client only
|
|
||||||
needs to tell the compositor which buffer to use and
|
|
||||||
when and where it has rendered new content into it.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
This leaves an application with two ways to update its window contents:
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<orderedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Render the new content into a new buffer and tell the compositor
|
|
||||||
to use that instead of the old buffer. The application can
|
|
||||||
allocate a new buffer every time it needs to update the window
|
|
||||||
contents or it can keep two (or more) buffers around and cycle
|
|
||||||
between them. The buffer management is entirely under
|
|
||||||
application control.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Render the new content into the buffer that it previously
|
|
||||||
told the compositor to to use. While it's possible to just
|
|
||||||
render directly into the buffer shared with the compositor,
|
|
||||||
this might race with the compositor. What can happen is that
|
|
||||||
repainting the window contents could be interrupted by the
|
|
||||||
compositor repainting the desktop. If the application gets
|
|
||||||
interrupted just after clearing the window but before
|
|
||||||
rendering the contents, the compositor will texture from a
|
|
||||||
blank buffer. The result is that the application window will
|
|
||||||
flicker between a blank window or half-rendered content. The
|
|
||||||
traditional way to avoid this is to render the new content
|
|
||||||
into a back buffer and then copy from there into the
|
|
||||||
compositor surface. The back buffer can be allocated on the
|
|
||||||
fly and just big enough to hold the new content, or the
|
|
||||||
application can keep a buffer around. Again, this is under
|
|
||||||
application control.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</orderedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In either case, the application must tell the compositor
|
|
||||||
which area of the surface holds new contents. When the
|
|
||||||
application renders directly to the shared buffer, the
|
|
||||||
compositor needs to be noticed that there is new content.
|
|
||||||
But also when exchanging buffers, the compositor doesn't
|
|
||||||
assume anything changed, and needs a request from the
|
|
||||||
application before it will repaint the desktop. The idea
|
|
||||||
that even if an application passes a new buffer to the
|
|
||||||
compositor, only a small part of the buffer may be
|
|
||||||
different, like a blinking cursor or a spinner.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-Wayland-Architecture-wayland_hw_enabling">
|
|
||||||
<title>Accelerated GPU Buffer Exchange</title>
|
|
||||||
<para>
|
|
||||||
Clients
|
|
||||||
<ulink url="https://docs.kernel.org/userspace-api/dma-buf-alloc-exchange.html">exchange</ulink>
|
|
||||||
GPU buffers with the compositor as dma-buf file descriptors, which are universal handles
|
|
||||||
that are independent of any particular rendering API or memory allocator. The
|
|
||||||
<ulink url="https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/stable/linux-dmabuf/linux-dmabuf-v1.xml">linux-dmabuf-v1</ulink>
|
|
||||||
protocol is used to turn one or more dma-buf FDs into a
|
|
||||||
<link linkend="protocol-spec-wl_buffer">wl_buffer</link>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If the client uses the
|
|
||||||
<ulink url="https://docs.vulkan.org/spec/latest/chapters/VK_KHR_surface/wsi.html">Vulkan</ulink>
|
|
||||||
or
|
|
||||||
<ulink url="https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_platform_wayland.txt">EGL</ulink>
|
|
||||||
(via
|
|
||||||
<ulink url="https://gitlab.freedesktop.org/wayland/wayland/-/tree/main/egl">wayland-egl</ulink>)
|
|
||||||
window-system integration
|
|
||||||
(WSI), this is done transparently by the WSI.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Clients can alternatively allocate and import dma-bufs themselves
|
|
||||||
using the GBM library, Vulkan, udmabuf, or dma-buf heaps.
|
|
||||||
</para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Using GBM, the client can allocate a gbm_bo and export one or more
|
|
||||||
dma-buf FDs from it.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Using Vulkan, the client can create a VkDeviceMemory object and use
|
|
||||||
<ulink url="https://docs.vulkan.org/refpages/latest/refpages/source/VK_EXT_external_memory_dma_buf.html">VK_EXT_external_memory_dma_buf</ulink>
|
|
||||||
and
|
|
||||||
<ulink url="https://docs.vulkan.org/refpages/latest/refpages/source/VK_EXT_image_drm_format_modifier.html">VK_EXT_image_drm_format_modifier</ulink>
|
|
||||||
to export a dma-buf FD from it.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<ulink url="https://lwn.net/Articles/749206/">udmabuf</ulink>
|
|
||||||
can be used to create dma-buf FDs from linear host memory.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<ulink url="https://docs.kernel.org/userspace-api/dma-buf-heaps.html">Dma-buf heaps</ulink>
|
|
||||||
can be used by privileged applications to create dma-buf FDs on embedded
|
|
||||||
devices.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
<para>
|
|
||||||
Compositors use
|
|
||||||
<ulink url="https://docs.vulkan.org/refpages/latest/refpages/source/VK_EXT_external_memory_dma_buf.html">VK_EXT_external_memory_dma_buf</ulink>
|
|
||||||
and
|
|
||||||
<ulink url="https://docs.vulkan.org/refpages/latest/refpages/source/VK_EXT_image_drm_format_modifier.html">VK_EXT_image_drm_format_modifier</ulink>
|
|
||||||
or
|
|
||||||
<ulink url="https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_image_dma_buf_import.txt">EGL_EXT_image_dma_buf_import</ulink>
|
|
||||||
and
|
|
||||||
<ulink url="https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_image_dma_buf_import_modifiers.txt">EGL_EXT_image_dma_buf_import_modifiers</ulink>
|
|
||||||
to import the dma-bufs provided by the client into their own Vulkan or
|
|
||||||
EGL renderers.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Clients do not need to wait for the GPU to finish rendering before submitting
|
|
||||||
dma-bufs to the compositor. Clients can use the
|
|
||||||
<ulink url="https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml">linux-drm-syncobj-v1</ulink>
|
|
||||||
protocol to exchange DRM synchronization objects with the compositor. These objects
|
|
||||||
are used to asynchronously signal ownership transfer of buffers from clients to the
|
|
||||||
compositor and vice versa. The WSIs do this transparently.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If the linux-drm-syncobj-v1 protocol is not supported by the compositor, clients
|
|
||||||
and compositors can use the
|
|
||||||
<ulink url="https://docs.kernel.org/driver-api/dma-buf.html#c.dma_buf_export_sync_file">DMA_BUF_IOCTL_EXPORT_SYNC_FILE</ulink>
|
|
||||||
and
|
|
||||||
<ulink url="https://docs.kernel.org/driver-api/dma-buf.html#c.dma_buf_import_sync_file">DMA_BUF_IOCTL_IMPORT_SYNC_FILE</ulink>
|
|
||||||
ioctls to access and create implicit synchronization barriers.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-Wayland-Architecture-kms">
|
|
||||||
<title>Display Programming</title>
|
|
||||||
<para>
|
|
||||||
Compositors enumerate DRM KMS devices using
|
|
||||||
<ulink url="https://en.wikipedia.org/wiki/Udev">udev</ulink>.
|
|
||||||
Udev also notifies compositors of KMS device and display hotplug events.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Access to DRM KMS device ioctls is privileged. Since compositors usually run as
|
|
||||||
unprivileged applications, they typically gain access to a privileged file
|
|
||||||
descriptor using the
|
|
||||||
<ulink url="https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.login1.html#Session%20Objects">TakeDevice</ulink>
|
|
||||||
method provided by logind.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Using the file descriptor, compositors use KMS
|
|
||||||
<ulink url="https://docs.kernel.org/gpu/drm-kms.html">ioctls</ulink>
|
|
||||||
to enumerate the available displays.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Compositors use
|
|
||||||
<ulink url="https://docs.kernel.org/gpu/drm-kms.html#atomic-mode-setting">atomic mode setting</ulink>
|
|
||||||
to change the buffer shown by the display, to change the display's resolution, to
|
|
||||||
enable or disable HDR, and so on.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
<?xml version='1.0' encoding='utf-8' ?>
|
|
||||||
<!DOCTYPE authorgroup PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
||||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
|
||||||
%BOOK_ENTITIES;
|
|
||||||
]>
|
|
||||||
<authorgroup>
|
|
||||||
<author>
|
|
||||||
<firstname>Kristian</firstname>
|
|
||||||
<surname>Høgsberg</surname>
|
|
||||||
<affiliation>
|
|
||||||
<orgname>Intel Corporation</orgname>
|
|
||||||
</affiliation>
|
|
||||||
<email>krh@bitplanet.net</email>
|
|
||||||
</author>
|
|
||||||
</authorgroup>
|
|
||||||
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
<?xml version='1.0' encoding='utf-8' ?>
|
|
||||||
<!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
||||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
|
||||||
%BOOK_ENTITIES;
|
|
||||||
]>
|
|
||||||
<bookinfo id="book-Wayland-Wayland">
|
|
||||||
<title>Wayland</title>
|
|
||||||
<subtitle>The Wayland Protocol</subtitle>
|
|
||||||
<productname>Documentation</productname>
|
|
||||||
<productnumber>0.1</productnumber>
|
|
||||||
<edition>1</edition>
|
|
||||||
<pubsnumber>0</pubsnumber>
|
|
||||||
<abstract>
|
|
||||||
<para>
|
|
||||||
Wayland is a protocol for a compositor to talk to
|
|
||||||
its clients as well as a C library implementation of
|
|
||||||
that protocol. The compositor can be a standalone
|
|
||||||
display server running on Linux kernel modesetting
|
|
||||||
and evdev input devices, an X application, or a
|
|
||||||
Wayland client itself. The clients can be
|
|
||||||
traditional applications, X servers (rootless or
|
|
||||||
fullscreen) or other display servers.
|
|
||||||
</para>
|
|
||||||
</abstract>
|
|
||||||
<corpauthor>
|
|
||||||
<inlinemediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/wayland.png" format="PNG" />
|
|
||||||
</imageobject>
|
|
||||||
<textobject>
|
|
||||||
<phrase>
|
|
||||||
Wayland logo
|
|
||||||
</phrase>
|
|
||||||
</textobject>
|
|
||||||
</inlinemediaobject>
|
|
||||||
</corpauthor>
|
|
||||||
|
|
||||||
<legalnotice lang="en-US">
|
|
||||||
<para>
|
|
||||||
Copyright <trademark class="copyright"></trademark> &YEAR; &HOLDER;
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
copy of this software and associated documentation files (the "Software"),
|
|
||||||
to deal in the Software without restriction, including without limitation
|
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
Software is furnished to do so, subject to the following conditions:
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The above copyright notice and this permission notice (including the next
|
|
||||||
paragraph) shall be included in all copies or substantial portions of the
|
|
||||||
Software.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
DEALINGS IN THE SOFTWARE.
|
|
||||||
</para>
|
|
||||||
</legalnotice>
|
|
||||||
|
|
||||||
|
|
||||||
<xi:include href="Author_Group.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
||||||
</bookinfo>
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
<?xml version='1.0' encoding='utf-8' ?>
|
|
||||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
||||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
|
||||||
<!ENTITY doxygen SYSTEM "ClientAPI.xml">
|
|
||||||
%BOOK_ENTITIES;
|
|
||||||
]>
|
|
||||||
<appendix id="sect-Library-Client">
|
|
||||||
<title>Client API</title>
|
|
||||||
<section><title>Introduction</title>
|
|
||||||
<para>
|
|
||||||
The open-source reference implementation of Wayland protocol is
|
|
||||||
split in two C libraries, libwayland-client and <link
|
|
||||||
linkend="sect-Library-Server">libwayland-server</link>. Their main
|
|
||||||
responsibility is to handle the Inter-process communication
|
|
||||||
(<emphasis>IPC</emphasis>) with each other, therefore guaranteeing
|
|
||||||
the protocol objects marshaling and messages synchronization.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
A client uses libwayland-client to communicate with one or more
|
|
||||||
wayland servers. A <link
|
|
||||||
linkend="Client-classwl__display">wl_display</link> object is
|
|
||||||
created and manages each open connection to a server. At least one
|
|
||||||
<link linkend="Client-classwl__event__queue">wl_event_queue</link>
|
|
||||||
object is created for each wl_display, this holds events as they
|
|
||||||
are received from the server until they can be
|
|
||||||
processed. Multi-threading is supported by creating an additional
|
|
||||||
wl_event_queue for each additional thread, each object can have
|
|
||||||
it's events placed in a particular queue, so potentially a
|
|
||||||
different thread could be made to handle the events for each
|
|
||||||
object created.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Though some convenience functions are provided, libwayland-client
|
|
||||||
is designed to allow the calling code to wait for events, so that
|
|
||||||
different polling mechanisms can be used. A file descriptor is
|
|
||||||
provided, when it becomes ready for reading the calling code can
|
|
||||||
ask libwayland-client to read the available events from it into
|
|
||||||
the wl_event_queue objects.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The library only provides low-level access to the wayland objects.
|
|
||||||
Each object created by the client is represented by a <link
|
|
||||||
linkend="Client-classwl__proxy">wl_proxy</link> object that this
|
|
||||||
library creates. This includes the id that is actually
|
|
||||||
communicated over the socket to the server, a void* data pointer
|
|
||||||
that is intended to point at a client's representation of the
|
|
||||||
object, and a pointer to a static <link
|
|
||||||
linkend="Client-structwl__interface">wl_interface</link> object,
|
|
||||||
which is generated from the xml and identifies the object's class
|
|
||||||
and can be used for introspection into the messages and events.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Messages are sent by calling wl_proxy_marshal. This will write a
|
|
||||||
message to the socket, by using the message id and the
|
|
||||||
wl_interface to identify the types of each argument and convert
|
|
||||||
them into stream format. Most software will call type-safe
|
|
||||||
wrappers generated from the xml description of the <link
|
|
||||||
linkend="appe-Wayland-Protocol">Wayland protocols</link>. For
|
|
||||||
instance the C header file generated from the xml defines the
|
|
||||||
following inline function to transmit the <link
|
|
||||||
linkend="protocol-spec-wl_surface-request-attach">wl_surface::attach</link>
|
|
||||||
message:
|
|
||||||
</para>
|
|
||||||
<programlisting>static inline void
|
|
||||||
wl_surface_attach(struct wl_surface *wl_surface, struct wl_buffer *buffer, int32_t x, int32_t y)
|
|
||||||
{
|
|
||||||
wl_proxy_marshal((struct wl_proxy *) wl_surface, WL_SURFACE_ATTACH, buffer, x, y);
|
|
||||||
}</programlisting>
|
|
||||||
<para>
|
|
||||||
Events (messages from the server) are handled by calling a
|
|
||||||
"dispatcher" callback the client stores in the wl_proxy for each
|
|
||||||
event. A language binding for a string-based interpreter, such as
|
|
||||||
CPython, might have a dispatcher that uses the event name from the
|
|
||||||
wl_interface to identify the function to call. The default
|
|
||||||
dispatcher uses the message id number to index an array of
|
|
||||||
functions pointers, called a wl_listener, and the wl_interface to
|
|
||||||
convert data from the stream into arguments to the function. The
|
|
||||||
C header file generated from the xml defines a per-class structure
|
|
||||||
that forces the function pointers to be of the correct type, for
|
|
||||||
instance the <link
|
|
||||||
linkend="protocol-spec-wl_surface-event-enter">wl_surface::enter</link>
|
|
||||||
event defines this pointer in the wl_surface_listener object:
|
|
||||||
</para>
|
|
||||||
<programlisting>struct wl_surface_listener {
|
|
||||||
void (*enter)(void *data, struct wl_surface *, struct wl_output *);
|
|
||||||
...
|
|
||||||
}</programlisting>
|
|
||||||
<para>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
&doxygen;
|
|
||||||
</appendix>
|
|
||||||
|
|
@ -1,139 +0,0 @@
|
||||||
<?xml version='1.0' encoding='utf-8' ?>
|
|
||||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
||||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
|
||||||
%BOOK_ENTITIES;
|
|
||||||
]>
|
|
||||||
|
|
||||||
<chapter id="chap-Color-Management">
|
|
||||||
<title>Color management</title>
|
|
||||||
|
|
||||||
<section id="sect-Color-Management-preface">
|
|
||||||
<title>Overview</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Color management in Wayland considers only displays. All pictures in
|
|
||||||
Wayland are always display-referred, meaning that the pixel values are
|
|
||||||
intended as-is for some specific display where they would produce the
|
|
||||||
light emissions (<ulink
|
|
||||||
url="https://cie.co.at/eilvterm/17-23-002">stimuli</ulink>) the picture's
|
|
||||||
author desired. Wayland does not support displaying "raw" camera or
|
|
||||||
scanner images as they are not display-referred, nor are they even
|
|
||||||
pictures without complex and subjective processing.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Stimuli — the picture itself — are only half of the picture reproduction.
|
|
||||||
The other half is the environment where a display is viewed. A striking
|
|
||||||
example is comparing a brightly lit office to a dark movie theater, the
|
|
||||||
stimuli required to produce a good reading of the picture is greatly
|
|
||||||
different. Therefore display-referred does not include only the display
|
|
||||||
but the viewing environment as well.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Window systems have been very well capable of operating without any
|
|
||||||
explicit consideration to color management. This is because there used to
|
|
||||||
be the implicit assumption of the standard display, the sRGB display,
|
|
||||||
which all computer monitors implemented, more or less. The viewing
|
|
||||||
environment was and still is accounted by adjusting the display and/or the
|
|
||||||
room to produce a workable experience. Pictures are authored on a computer
|
|
||||||
system by drawing, painting and adjusting the picture until it looks right
|
|
||||||
on the author's monitor. This implicitly builds the standard display and
|
|
||||||
environment assumption into the picture data. Deviations from the sRGB
|
|
||||||
specification were minor enough that they often did not matter if not in a
|
|
||||||
professional context like the printing industry. Displaying video material
|
|
||||||
required some more attention to the details, because video and television
|
|
||||||
standards differ enough from the sRGB display. What really made explicit
|
|
||||||
color management a hard requirement for entertainment is the coming of
|
|
||||||
wide color gamut (WCG) and high dynamic range (HDR) materials and
|
|
||||||
displays.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The color management design in Wayland follows the general Wayland design
|
|
||||||
principles: compositors tell clients what would be the optimal thing to
|
|
||||||
do, clients tell the compositors what kind of pictures they are actually
|
|
||||||
producing, and then compositors display those pictures the best they can.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="sect-Color-Management-Protocol">
|
|
||||||
<title>Protocol Interfaces</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Color management interfaces in Wayland and divided into two protocols:
|
|
||||||
<ulink url="https://gitlab.freedesktop.org/wayland/wayland-protocols/-/tree/main/staging/color-management?ref_type=heads">color-management</ulink>
|
|
||||||
and
|
|
||||||
<ulink url="https://gitlab.freedesktop.org/wayland/wayland-protocols/-/tree/main/staging/color-representation?ref_type=heads">color-representation</ulink>.
|
|
||||||
They are designed to work together, but they can also be used
|
|
||||||
independently when the other one is not needed.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section id="sect-Color-Management-Protocol-color-management">
|
|
||||||
<title>Color-management</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Color management protocol has two main purposes. First, it puts the
|
|
||||||
responsibility of color management on the compositor. This means that
|
|
||||||
clients do not necessarily need to care about color management at all,
|
|
||||||
and can display just fine by using the traditional standard display
|
|
||||||
assumption even when the actual display is wildly different. Clients
|
|
||||||
can also choose to target some other assumed display and let the
|
|
||||||
compositor handle it, or they can explicitly render for the actual
|
|
||||||
display at hand. Second, when the window system has multiple different
|
|
||||||
monitors, and a wl_surface happens to span more than one monitor, the
|
|
||||||
compositor can display the surface content correctly on all spanned
|
|
||||||
monitors simultaneously, as much as physically possible.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Color-management protocol concentrates on colorimetry: when you have a
|
|
||||||
pixel with RGB values, what stimulus do those values represent. The
|
|
||||||
stimulus definition follows the CIE 1931 two-degree observer model. Some
|
|
||||||
core concepts here are color primaries, white point, transfer function,
|
|
||||||
and dynamic range. The viewing environment is represented in an
|
|
||||||
extremely simplified way as the reference white luminance. The
|
|
||||||
connection between pixel RGB values and stimulus plus viewing
|
|
||||||
environment is recorded in an <emphasis>image description</emphasis>
|
|
||||||
object. Clients can create image description objects and tag
|
|
||||||
<code>wl_surface</code>s with them, to indicate what kind of surface
|
|
||||||
content there will be. Clients can also ask what image description the
|
|
||||||
compositor would prefer to have on the <code>wl_surface</code>, and that
|
|
||||||
preference can change over time, e.g. when the <code>wl_surface</code>
|
|
||||||
is moved from one
|
|
||||||
<code>wl_output</code> to another. Following the compositor's preference
|
|
||||||
may provide advantages in image quality and power consumption.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Image description objects can come in two flavors: parametric and
|
|
||||||
ICC-based. The above was written with parametric image descriptions in
|
|
||||||
mind, and they have first-class support for HDR. ICC-based image
|
|
||||||
descriptions are wrapping an ICC profile and have no other data. ICC
|
|
||||||
profiles are the standard tool for standard dynamic range (SDR) display
|
|
||||||
color management. This means the capabilities between the two flavors
|
|
||||||
differ, and one cannot always be replaced by the other. Compositor
|
|
||||||
support for each flavor is optional.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="sect-Color-Management-Protocol-color-representation">
|
|
||||||
<title>Color-representation</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Color-representation protocol deals with (potentially sub-sampled)
|
|
||||||
YCbCr-RGB conversion, quantization range, and the inclusion of alpha in
|
|
||||||
the RGB color channels, a.k.a. pre-multiplication. There are several
|
|
||||||
different specifications on how an YCbCr-like (including ICtCp) signal,
|
|
||||||
with chroma sub-sampling or not, is created from a full-resolution RGB
|
|
||||||
image. Again, a client can tag a <code>wl_surface</code> with
|
|
||||||
color-representation metadata to tell the compositor what kind of pixel
|
|
||||||
data will be displayed through the wl_surface.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The main purpose of color-representation is to correctly off-load the
|
|
||||||
YCbCr-RGB conversion to the compositor, which can then opportunistically
|
|
||||||
off-load it further to very power-efficient fixed-function circuitry in
|
|
||||||
a display controller. This can significantly reduce power consumption
|
|
||||||
when watching videos compared to using a GPU for the same, and on some
|
|
||||||
embedded hardware platforms it is a hard requirement for processing high
|
|
||||||
resolution video.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
||||||
|
|
@ -1,128 +0,0 @@
|
||||||
<?xml version='1.0' encoding='utf-8' ?>
|
|
||||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
||||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
|
||||||
%BOOK_ENTITIES;
|
|
||||||
]>
|
|
||||||
<chapter id="chap-Compositors">
|
|
||||||
<title>Types of Compositors</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Compositors come in different types, depending on which
|
|
||||||
role they play in the overall architecture of the OS.
|
|
||||||
For instance, a
|
|
||||||
<link linkend="sect-Compositors-System-Compositor">system compositor</link>
|
|
||||||
can be used for booting the system, handling multiple user switching, a
|
|
||||||
possible console terminal emulator and so forth. A different compositor, a
|
|
||||||
<link linkend="sect-Compositors-Session-Compositor">session compositor</link>
|
|
||||||
would provide the actual desktop environment. There are many ways for
|
|
||||||
different types of compositors to co-exist.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In this section, we introduce three types of Wayland compositors relying
|
|
||||||
on <link linkend="sect-Library-Server">libwayland-server</link>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section id="sect-Compositors-System-Compositor">
|
|
||||||
<title>System Compositor</title>
|
|
||||||
<para>
|
|
||||||
A system compositor can run from early boot until shutdown.
|
|
||||||
It effectively replaces the kernel vt system, and can tie in
|
|
||||||
with the systems graphical boot setup and multiseat support.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
A system compositor can host different types of session
|
|
||||||
compositors, and let us switch between multiple sessions
|
|
||||||
(fast user switching, or secure/personal desktop switching).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
A linux implementation of a system compositor will typically
|
|
||||||
use libudev, egl, kms, evdev and cairo.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For fullscreen clients, the system compositor can reprogram the
|
|
||||||
video scanout address to read directly from the client provided
|
|
||||||
buffer.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-Compositors-Session-Compositor">
|
|
||||||
<title>Session Compositor</title>
|
|
||||||
<para>
|
|
||||||
A session compositor is responsible for a single user session.
|
|
||||||
If a system compositor is present, the session compositor will
|
|
||||||
run nested under the system compositor. Nesting is feasible because
|
|
||||||
the protocol is asynchronous; roundtrips would be too expensive
|
|
||||||
when nesting is involved. If no system compositor is present, a
|
|
||||||
session compositor can run directly on the hardware.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
X applications can continue working under a session compositor
|
|
||||||
by means of a root-less X server that is activated on demand.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Possible examples for session compositors include
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
gnome-shell
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
moblin
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
kwin
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
kmscon
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
rdp session
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Weston with X11 or Wayland backend is a session compositor nested
|
|
||||||
in another session compositor.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
fullscreen X session under Wayland
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-Compositors-Embedding-Compositor">
|
|
||||||
<title>Embedding Compositor</title>
|
|
||||||
<para>
|
|
||||||
X11 lets clients embed windows from other clients, or lets clients
|
|
||||||
copy pixmap contents rendered by another client into their window.
|
|
||||||
This is often used for applets in a panel, browser plugins and similar.
|
|
||||||
Wayland doesn't directly allow this, but clients can communicate GEM
|
|
||||||
buffer names out-of-band, for example, using D-Bus, or command line
|
|
||||||
arguments when the panel launches the applet. Another option is to
|
|
||||||
use a nested Wayland instance. For this, the Wayland server will have
|
|
||||||
to be a library that the host application links to. The host
|
|
||||||
application will then pass the Wayland server socket name to the
|
|
||||||
embedded application, and will need to implement the Wayland
|
|
||||||
compositor interface. The host application composites the client
|
|
||||||
surfaces as part of it's window, that is, in the web page or in the
|
|
||||||
panel. The benefit of nesting the Wayland server is that it provides
|
|
||||||
the requests the embedded client needs to inform the host about buffer
|
|
||||||
updates and a mechanism for forwarding input events from the host
|
|
||||||
application.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
An example for this kind of setup is firefox embedding the flash
|
|
||||||
player as a kind of special-purpose compositor.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
||||||
|
|
@ -1,460 +0,0 @@
|
||||||
<?xml version='1.0' encoding='utf-8' ?>
|
|
||||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
||||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
|
||||||
%BOOK_ENTITIES;
|
|
||||||
]>
|
|
||||||
|
|
||||||
<chapter id="chap-Content-Updates">
|
|
||||||
<title>Content Updates</title>
|
|
||||||
|
|
||||||
<section id="sect-Content-Updates-preface">
|
|
||||||
<title>Overview</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
In the Wayland protocol, requests are asynchronous but take effect
|
|
||||||
immediately when the compositor receives them. However, some requests on
|
|
||||||
surfaces are not applied immediately but are instead double-buffered to
|
|
||||||
allow atomic changes. These double-buffered changes are committed through
|
|
||||||
the wl_surface.commit request, which creates a Content Update.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Content Updates encapsulate all double-buffered state changes and can be
|
|
||||||
applied by the compositor. The complexity arises when considering
|
|
||||||
subsurfaces, which can operate in synchronized mode. When a subsurface is
|
|
||||||
synchronized, its Content Updates must be applied atomically together with
|
|
||||||
the parent surface's state. This synchronization can extend through an
|
|
||||||
entire tree of subsurfaces, where child subsurfaces inherit the
|
|
||||||
synchronized behavior from their parents.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Historically, Content Updates from synchronized subsurfaces were merged
|
|
||||||
into the pending state of the parent surface on commit. However, the
|
|
||||||
introduction of constraints—which can defer the application of Content
|
|
||||||
Updates—necessitated a more sophisticated model. This led to the
|
|
||||||
implementation of per-surface queues of Content Updates, with dependencies
|
|
||||||
between Content Updates across different queues. This queuing model
|
|
||||||
maintains backwards compatibility with the earlier approach of merging
|
|
||||||
Content Updates into the parent's pending state on commit.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The core protocol defines the semantics of Content Updates using
|
|
||||||
per-surface queues, but compositors that do not need to support constraints
|
|
||||||
may implement the simpler legacy model where synchronized subsurface states
|
|
||||||
are merged directly into the parent's pending state.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="sect-Content-Updates-rules">
|
|
||||||
<title>Rules</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The core protocol specifies the behavior in wl_subsurface and
|
|
||||||
wl_surface.commit. The behavior can be summarized by the following rules:
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<orderedlist numeration="arabic">
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Content Updates (CU) contain all double-buffered state of the surface and
|
|
||||||
selected state from their direct children.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Surfaces which are effectively synchronized create Synchronized
|
|
||||||
Content Updates (SCU), otherwise they create Desync Content Updates
|
|
||||||
(DCU).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
When a CU is created, it gets a dependency on the previous CU of the
|
|
||||||
same queues (if it exists).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
When a CU is created, it gets a dependency on the last SCU of direct
|
|
||||||
child surfaces that are not reachable (if they exists).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The CUs and their dependencies form a DAG, where CUs are nodes and
|
|
||||||
dependencies are edges.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
All DCUs starting from the front of the queues until the first SCU or
|
|
||||||
the back of the queue is reached are candidates.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If the maximal DAG that's reachable from a candidate (candidate DAG)
|
|
||||||
does not have any constraints, then this DAG can be applied.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
A DAG is applied atomically by recursively applying a content update
|
|
||||||
without dependencies and removing it from the DAG.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Surfaces transition from effectively sync to effectively desync after
|
|
||||||
their parents.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
When a surface transitions to effectively desync, all SCUs in its
|
|
||||||
queue which are not reachable by a DCU become DCUs.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</orderedlist>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="sect-Content-Updates-examples">
|
|
||||||
<title>Examples</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
These examples should help to build an intuition for how content updates
|
|
||||||
actually behave. They cover the interesting edge cases, such as
|
|
||||||
subsurfaces with constraints, and transitioning from a sync subsurface to
|
|
||||||
a desync one.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In all the examples below, the surface T1 refers to a toplevel surface,
|
|
||||||
SS1 refers to a sub-surface which is a child of T1, and SS2 refers to a
|
|
||||||
sub-surface which is a child of SS1.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<figure>
|
|
||||||
<title>Legend</title>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/content-update-legend.png"/>
|
|
||||||
</imageobject>
|
|
||||||
</mediaobject>
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
<figure>
|
|
||||||
<title>Simple Desynchronized Case</title>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/simple-desynchronized-state-1.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
SS2 is effectively desynchronized and commits. This results in the
|
|
||||||
desynchronized content update (DCU) <emphasis>1</emphasis>.
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/simple-desynchronized-state-2.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
DCU <emphasis>1</emphasis> is a candidate, and the candidate DAG
|
|
||||||
reachable from DCU <emphasis>1</emphasis> is only
|
|
||||||
DCU <emphasis>1</emphasis> itself. DCU <emphasis>1</emphasis> and
|
|
||||||
thus the candidate DAG does not have any constraints and can be
|
|
||||||
applied.
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/simple-desynchronized-state-3.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
The content updates of the candidate DAG get applied to the surface
|
|
||||||
atomically.
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/simple-desynchronized-state-4.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
T1 commits a DCU with a <emphasis>buffer-sync</emphasis> constraint.
|
|
||||||
It is a candidate but its DAG can't be applied because it contains a
|
|
||||||
constraint.
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/simple-desynchronized-state-5.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
T1 commits another CU (DCU <emphasis>3</emphasis>) which is added at
|
|
||||||
the end of the queue, with a dependency to the previous CU (DCU
|
|
||||||
<emphasis>2</emphasis>). Both DCU <emphasis>2</emphasis> and DCU
|
|
||||||
<emphasis>3</emphasis> are candidates, but both DAGs contain DCU
|
|
||||||
<emphasis>2</emphasis> with a constraint, and can't be applied.
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/simple-desynchronized-state-6.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
When the constraint gets cleared, both DAGs can be applied to the
|
|
||||||
surface atomitcally (either only <emphasis>2</emphasis>, or
|
|
||||||
<emphasis>2</emphasis> and <emphasis>3</emphasis>).
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
<figure>
|
|
||||||
<title>Simple Synchronized Case</title>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/simple-synchronized-state-1.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
SS1 and SS2 are effectively synchronized. SS2 commits SCU <emphasis>1</emphasis>.
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/simple-synchronized-state-2.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
SS1 commits SCU <emphasis>2</emphasis>. The direct child surfaces SS2 has the last SCU <emphasis>1</emphasis> in its queue, which is not reachable. This creates a dependency from SCU <emphasis>2</emphasis> to SCU <emphasis>1</emphasis>.
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/simple-synchronized-state-3.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
SS1 commits SCU <emphasis>3</emphasis>. The direct child surfaces SS2 has the last SCU <emphasis>1</emphasis> in its queue, which is already reachable by SCU <emphasis>2</emphasis>. No dependency to SCU <emphasis>1</emphasis> is created. A dependency to the previous CU of the same queue (SCU <emphasis>2</emphasis>) is created.
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/simple-synchronized-state-4.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
T1 commit DCU <emphasis>4</emphasis>. It is a candidate, its DAG does not contain any constraint and it can be applied.
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/simple-synchronized-state-5.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
The DAG gets applied to the surfaces atomically.
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
<figure>
|
|
||||||
<title>Complex Synchronized Subsurface Case 1</title>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/sync-subsurf-case1-1.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
Every DCU (<emphasis>1</emphasis> and <emphasis>6</emphasis>) contain
|
|
||||||
CUs with constraints in their candidate DAG
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/sync-subsurf-case1-2.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
Waiting until the <emphasis>buffer-sync</emphasis> constrain on CU
|
|
||||||
<emphasis>1</emphasis> is cleared, the candidate DAG of CU
|
|
||||||
<emphasis>1</emphasis> does not contain constraints and can be applied
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/sync-subsurf-case1-3.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
That leaves the candidate DAG of CU <emphasis>6</emphasis> which still
|
|
||||||
contains another CU with a <emphasis>buffer-sync</emphasis> constrain
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/sync-subsurf-case1-4.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
Waiting until the <emphasis>buffer-sync</emphasis> constrain on CU
|
|
||||||
<emphasis>6</emphasis> is cleared, the candidate DAG of
|
|
||||||
<emphasis>6</emphasis> does not contain CUs with constraints and can
|
|
||||||
be applied.
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/sync-subsurf-case1-5.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
There is no DCU left and no constraint remaining. Nothing more can be
|
|
||||||
applied without a new CU.
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
<figure>
|
|
||||||
<title>Complex Synchronized Subsurface Case 2</title>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/sync-subsurf-case2-1.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
Both DCUs (<emphasis>1</emphasis> and <emphasis>6</emphasis>) have a
|
|
||||||
reachable DAG containing CU <emphasis>1</emphasis> with a constraint
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/sync-subsurf-case2-2.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
Waiting until the <emphasis>buffer-sync</emphasis> constrain on
|
|
||||||
<emphasis>1</emphasis> is cleared, both DAGs contain no CU with
|
|
||||||
constraints and can be applied in any order
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/sync-subsurf-case2-3.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
That leaves the same state as in the previous case
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
<figure>
|
|
||||||
<title>Synchronized to Desynchronized Subsurface</title>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/sync-to-desync-subsurf-1.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
There is one DCU (<emphasis>4</emphasis>) with its reachable DAG
|
|
||||||
that cannot be applied because CU <emphasis>4</emphasis> contains a
|
|
||||||
constraint
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/sync-to-desync-subsurf-2.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
Surface <emphasis>SS1</emphasis> transitions from effectively
|
|
||||||
synchronized to effectively desynchronized. SCU
|
|
||||||
<emphasis>2</emphasis> is reachable by DCU <emphasis>4</emphasis> so
|
|
||||||
nothing changes.
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/sync-to-desync-subsurf-3.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
Surface <emphasis>SS1</emphasis> provides a new DCU
|
|
||||||
(<emphasis>5</emphasis>) but because the CU before
|
|
||||||
(<emphasis>2</emphasis>) is a Synchronized CU, it is not a candidate
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
<figure>
|
|
||||||
<title>Synchronized to Desynchronized Transition</title>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/sync-to-desync-transition-1.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
There are four SCUs and all surfaces are effectively synchronized.
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/sync-to-desync-transition-2.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
Surface <emphasis>SS1</emphasis> transitions to effectively
|
|
||||||
desynchronized and SCU <emphasis>2</emphasis> becomes a DCU because
|
|
||||||
it is not reachable from a DCU
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/content-updates/sync-to-desync-transition-3.png"/>
|
|
||||||
</imageobject>
|
|
||||||
<caption>
|
|
||||||
<para>
|
|
||||||
Surface <emphasis>SS2</emphasis> transitions to effectively
|
|
||||||
desynchronized. SCUs <emphasis>3</emphasis> and
|
|
||||||
<emphasis>4</emphasis> become DCUs because they are not reachable
|
|
||||||
from a DCU. SCU <emphasis>1</emphasis> does not change because it is
|
|
||||||
reachable by DCU <emphasis>2</emphasis>.
|
|
||||||
</para>
|
|
||||||
</caption>
|
|
||||||
</mediaobject>
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
<?xml version='1.0' encoding='utf-8' ?>
|
|
||||||
<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
|
||||||
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
||||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
|
||||||
%BOOK_ENTITIES;
|
|
||||||
]>
|
|
||||||
|
|
||||||
<preface>
|
|
||||||
<title>Preface</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
This document describes the (i) Wayland architecture, (ii) Wayland model of
|
|
||||||
operation and (iii) its library API. Also, the Wayland protocol specification is shown
|
|
||||||
in the Appendix. This document is aimed primarily at Wayland developers and
|
|
||||||
those looking to program with it; it does not cover application development.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
There have been many contributors to this document and since this is only the
|
|
||||||
first edition many errors are expected to be found. We appreciate
|
|
||||||
corrections.
|
|
||||||
</para>
|
|
||||||
<literallayout>
|
|
||||||
Yours,
|
|
||||||
|
|
||||||
the Wayland open-source community
|
|
||||||
November 2012
|
|
||||||
</literallayout>
|
|
||||||
</preface>
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
||||||
<?xml version='1.0' encoding='utf-8' ?>
|
|
||||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
||||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
|
||||||
%BOOK_ENTITIES;
|
|
||||||
]>
|
|
||||||
<chapter id="chap-Introduction">
|
|
||||||
<title>Introduction</title>
|
|
||||||
<section id="sect-Motivation">
|
|
||||||
<title>Motivation</title>
|
|
||||||
<para>
|
|
||||||
Most Linux and Unix-based systems rely on the X Window System (or
|
|
||||||
simply <emphasis>X</emphasis>) as the low-level protocol for building
|
|
||||||
bitmap graphics interfaces. On these systems, the X stack has grown to
|
|
||||||
encompass functionality arguably belonging in client libraries,
|
|
||||||
helper libraries, or the host operating system kernel. Support for
|
|
||||||
things like PCI resource management, display configuration management,
|
|
||||||
direct rendering, and memory management has been integrated into the X
|
|
||||||
stack, imposing limitations like limited support for standalone
|
|
||||||
applications, duplication in other projects (e.g. the Linux fb layer
|
|
||||||
or the DirectFB project), and high levels of complexity for systems
|
|
||||||
combining multiple elements (for example radeon memory map handling
|
|
||||||
between the fb driver and X driver, or VT switching).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Moreover, X has grown to incorporate modern features like offscreen
|
|
||||||
rendering and scene composition, but subject to the limitations of the
|
|
||||||
X architecture. For example, the X implementation of composition adds
|
|
||||||
additional context switches and makes things like input redirection
|
|
||||||
difficult.
|
|
||||||
</para>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/x-architecture.png" format="PNG" />
|
|
||||||
</imageobject>
|
|
||||||
<textobject>
|
|
||||||
<phrase>
|
|
||||||
X architecture diagram
|
|
||||||
</phrase>
|
|
||||||
</textobject>
|
|
||||||
</mediaobject>
|
|
||||||
<para>
|
|
||||||
The diagram above illustrates the central role of the X server and
|
|
||||||
compositor in operations, and the steps required to get contents on to
|
|
||||||
the screen.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Over time, X developers came to understand the shortcomings of this
|
|
||||||
approach and worked to split things up. Over the past several years,
|
|
||||||
a lot of functionality has moved out of the X server and into
|
|
||||||
client-side libraries or kernel drivers. One of the first components
|
|
||||||
to move out was font rendering, with freetype and fontconfig providing
|
|
||||||
an alternative to the core X fonts. Direct rendering OpenGL as a
|
|
||||||
graphics driver in a client side library went through some iterations,
|
|
||||||
ending up as DRI2, which abstracted most of the direct rendering
|
|
||||||
buffer management from client code. Then cairo came along and provided
|
|
||||||
a modern 2D rendering library independent of X, and compositing
|
|
||||||
managers took over control of the rendering of the desktop as toolkits
|
|
||||||
like GTK+ and Qt moved away from using X APIs for rendering. Recently,
|
|
||||||
memory and display management have moved to the Linux kernel, further
|
|
||||||
reducing the scope of X and its driver stack. The end result is a
|
|
||||||
highly modular graphics stack.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="sect-Compositing-manager-display-server">
|
|
||||||
<title>The compositing manager as the display server</title>
|
|
||||||
<para>
|
|
||||||
Wayland is a new display server and compositing protocol, and Weston
|
|
||||||
is the implementation of this protocol which builds on top of all the
|
|
||||||
components above. We are trying to distill out the functionality in
|
|
||||||
the X server that is still used by the modern Linux desktop. This
|
|
||||||
turns out to be not a whole lot. Applications can allocate their own
|
|
||||||
off-screen buffers and render their window contents directly, using
|
|
||||||
hardware accelerated libraries like libGL, or high quality software
|
|
||||||
implementations like those found in Cairo. In the end, what’s needed
|
|
||||||
is a way to present the resulting window surface for display, and a
|
|
||||||
way to receive and arbitrate input among multiple clients. This is
|
|
||||||
what Wayland provides, by piecing together the components already in
|
|
||||||
the eco-system in a slightly different way.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
X will always be relevant, in the same way Fortran compilers and VRML
|
|
||||||
browsers are, but it’s time that we think about moving it out of the
|
|
||||||
critical path and provide it as an optional component for legacy
|
|
||||||
applications.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Overall, the philosophy of Wayland is to provide clients with a way to
|
|
||||||
manage windows and how their contents are displayed. Rendering is left
|
|
||||||
to clients, and system wide memory management interfaces are used to
|
|
||||||
pass buffer handles between clients and the compositing manager.
|
|
||||||
</para>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/wayland-architecture.png" format="PNG" />
|
|
||||||
</imageobject>
|
|
||||||
<textobject>
|
|
||||||
<phrase>
|
|
||||||
Wayland architecture diagram
|
|
||||||
</phrase>
|
|
||||||
</textobject>
|
|
||||||
</mediaobject>
|
|
||||||
<para>
|
|
||||||
The figure above illustrates how Wayland clients interact with a
|
|
||||||
Wayland server. Note that window management and composition are
|
|
||||||
handled entirely in the server, significantly reducing complexity
|
|
||||||
while marginally improving performance through reduced context
|
|
||||||
switching. The resulting system is easier to build and extend than a
|
|
||||||
similar X system, because often changes need only be made in one
|
|
||||||
place. Or in the case of protocol extensions, two (rather than 3 or 4
|
|
||||||
in the X case where window management and/or composition handling may
|
|
||||||
also need to be updated).
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
||||||
|
|
@ -1,928 +0,0 @@
|
||||||
<?xml version='1.0' encoding='utf-8' ?>
|
|
||||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
||||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
|
||||||
%BOOK_ENTITIES;
|
|
||||||
|
|
||||||
<!ENTITY protocol "<link linkend='sect-MessageXML-tag-protocol'>protocol</link>">
|
|
||||||
<!ENTITY copyright "<link linkend='sect-MessageXML-tag-copyright'>copyright</link>">
|
|
||||||
<!ENTITY description "<link linkend='sect-MessageXML-tag-description'>description</link>">
|
|
||||||
<!ENTITY interface "<link linkend='sect-MessageXML-tag-interface'>interface</link>">
|
|
||||||
<!ENTITY enum "<link linkend='sect-MessageXML-tag-enum'>enum</link>">
|
|
||||||
<!ENTITY entry "<link linkend='sect-MessageXML-tag-entry'>entry</link>">
|
|
||||||
<!ENTITY request "<link linkend='sect-MessageXML-tag-request'>request</link>">
|
|
||||||
<!ENTITY event "<link linkend='sect-MessageXML-tag-event'>event</link>">
|
|
||||||
<!ENTITY arg "<link linkend='sect-MessageXML-tag-arg'>arg</link>">
|
|
||||||
|
|
||||||
<!ENTITY cname-requirements "The name must start with one of the ASCII
|
|
||||||
characters a-z, A-Z, or underscore, and the following characters may
|
|
||||||
additionally include numbers 0-9.">
|
|
||||||
<!ENTITY cname-suffix-requirements "The name must contain only the ASCII
|
|
||||||
characters a-z, A-Z, 0-9, or underscore. The name cannot be empty.">
|
|
||||||
]>
|
|
||||||
|
|
||||||
<chapter id="chap-MessageXML">
|
|
||||||
<title>Message Definition Language</title>
|
|
||||||
|
|
||||||
<section id="sect-MessageXML-preface">
|
|
||||||
<title>Overview</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The fundamentals of the Wayland protocol are explained in
|
|
||||||
<xref linkend="chap-Protocol"/>. This chapter formally defines the
|
|
||||||
language used to define Wayland protocols.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Wayland is an object-oriented protocol. Each object follows exactly
|
|
||||||
one interface. An interface is a collection of message and enumeration
|
|
||||||
definitions. A message can be either a request (sent by a client)
|
|
||||||
or an event (sent by a server). A message can have arguments.
|
|
||||||
All arguments are typed.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="sect-MessageXML-tags">
|
|
||||||
<title>XML Elements</title>
|
|
||||||
|
|
||||||
<section id="sect-MessageXML-tag-protocol">
|
|
||||||
<title>protocol</title>
|
|
||||||
|
|
||||||
<synopsis>protocol ::= (©right;?, &description;? &interface;+)</synopsis>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<code>protocol</code> is the root element in a Wayland protocol XML file.
|
|
||||||
Code generation tools may optionally use the protocol
|
|
||||||
<varname>name</varname> in API symbol names. The XML file name should be
|
|
||||||
similar to the protocol name.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The &description; element should be used to document the intended
|
|
||||||
purpose of the protocol, give an overview, and give any development
|
|
||||||
stage notices if applicable.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The ©right; element should be used to indicate the copyrights and
|
|
||||||
the license of the XML file.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
<title>Required attributes</title>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>name</varname>="<userinput>cname</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The name of the protocol (a.k.a protocol extension).
|
|
||||||
&cname-requirements;
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The name should be globally unique. Protocols to be included in
|
|
||||||
<ulink url="https://gitlab.freedesktop.org/wayland/wayland-protocols">wayland-protocols</ulink>
|
|
||||||
must follow the naming rules set there. Other protocols should use
|
|
||||||
a unique prefix for the name, e.g. referring to the owning project's
|
|
||||||
name.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="sect-MessageXML-tag-copyright">
|
|
||||||
<title>copyright</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Parent elements: &protocol;
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<synopsis>copyright ::= #PCDATA</synopsis>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Contains free-form, pre-formatted text for copyright and license
|
|
||||||
notices.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="sect-MessageXML-tag-description">
|
|
||||||
<title>description</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Parent elements: &protocol;, &interface;, &request;, &event;,
|
|
||||||
&arg;, &enum;, &entry;
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<synopsis>description ::= #PCDATA</synopsis>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Contains human-readable documentation for its parent element.
|
|
||||||
May contain formatted text, including paragraphs and bulleted
|
|
||||||
lists.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
<title>Optional attributes</title>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>summary</varname>="<userinput>summary</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
A short (half a line at most) description of the documented
|
|
||||||
element.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
When a &description; element is used, it is recommended to
|
|
||||||
not use the <varname>summary</varname> attribute of the parent
|
|
||||||
element.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="sect-MessageXML-tag-interface">
|
|
||||||
<title>interface</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Parent elements: &protocol;
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<synopsis>interface ::= (&description;?, (&request;|&event;|&enum;)+)</synopsis>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
An interface element contains the &request;s and &event;s that form the
|
|
||||||
interface. Enumerations can also be defined with &enum; elements.
|
|
||||||
These all belong into the namespace of the interface. Code generation
|
|
||||||
tools may use the interface <varname>name</varname> in API symbol names.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Interfaces form an ancestry tree. Aside from
|
|
||||||
<xref linkend="protocol-spec-wl_display" />, new protocol objects are
|
|
||||||
always created through an existing protocol object that may be referred to
|
|
||||||
as <firstterm>the factory object</firstterm>.
|
|
||||||
This can happen in one of two ways: the factory object's interface either
|
|
||||||
defines or does not define the new object's interface.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
When the factory interface defines the new object's interface, the new
|
|
||||||
object also inherits the factory object's interface version number.
|
|
||||||
This number defines the interface version of the new object.
|
|
||||||
The factory object is referred to as
|
|
||||||
<firstterm>the parent object</firstterm> and the factory interface is
|
|
||||||
referred to as <firstterm>the parent interface</firstterm>. This
|
|
||||||
forms the ancestry tree of interfaces.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
When the factory interface does not define the new object's interface,
|
|
||||||
both the interface name and the version must be communicated explicitly.
|
|
||||||
The foremost example of this is
|
|
||||||
<xref linkend="protocol-spec-wl_registry-request-bind" />.
|
|
||||||
In this case the terms "parent" or "ancestor" are not used. Interfaces
|
|
||||||
that are advertised through <xref linkend="protocol-spec-wl_registry" />
|
|
||||||
are called <firstterm>global interfaces</firstterm>, or globals for short.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If objects having the interface can cause protocol errors, the protocol
|
|
||||||
error codes must be defined within the interface with an &enum;
|
|
||||||
element with its <varname>name</varname> set to <literal>"error"</literal>.
|
|
||||||
Protocol error codes are always specific to the interface of the object
|
|
||||||
referred to in <xref linkend="protocol-spec-wl_display-event-error" />.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The &description; element should be used to describe the purpose and
|
|
||||||
the general usage of the interface.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
<title>Required attributes</title>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>name</varname>="<userinput>cname</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The name of the interface. &cname-requirements;
|
|
||||||
The name must be unique in the &protocol;, and preferably it should
|
|
||||||
also be globally unique to avoid API conflicts in language bindings
|
|
||||||
of multiple protocols.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Protocols to be included in
|
|
||||||
<ulink url="https://gitlab.freedesktop.org/wayland/wayland-protocols">wayland-protocols</ulink>
|
|
||||||
must follow the interface naming rules set there. Other protocols
|
|
||||||
should use a unique prefix for the name, e.g. referring to the owning
|
|
||||||
project's name.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>version</varname>="<userinput>V</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The interface's latest version number <userinput>V</userinput> must
|
|
||||||
be an integer greater than zero. An interface element defines
|
|
||||||
all versions of the interface from 1 to <userinput>V</userinput>
|
|
||||||
inclusive. The contents of each interface version are defined in each of
|
|
||||||
the &request;, &event;, &enum; and &entry; elements using the attributes
|
|
||||||
<varname>since</varname> and <varname>deprecated-since</varname>, and
|
|
||||||
in the specification text.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
When an interface is extended, the version number must be incremented
|
|
||||||
on all the interfaces part of the same interface ancestry tree.
|
|
||||||
The exception to this rule are interfaces which are forever stuck
|
|
||||||
to version 1, which is usually caused by having multiple parent
|
|
||||||
interfaces with independent ancestor global interfaces.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
A protocol object may have any defined version of the interface.
|
|
||||||
The version of the object is determined at runtime either
|
|
||||||
by inheritance from another protocol object or explicitly.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
It is possible for a protocol object to have a version higher than
|
|
||||||
defined by its interface. This may happen when the interface is
|
|
||||||
stuck at version 1 as per above. It may also happen when a protocol
|
|
||||||
XML file has not been thoroughly updated as required. In such cases
|
|
||||||
the object shall function as with the highest defined interface
|
|
||||||
version.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="sect-MessageXML-tag-request">
|
|
||||||
<title>request</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Parent elements: &interface;
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<synopsis>request ::= (&description;?, &arg;*)</synopsis>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Defines a request, a message from a client to a server.
|
|
||||||
Requests are always associated with a specific protocol object.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Requests are automatically assigned opcodes in the order they
|
|
||||||
appear inside the &interface; element. Therefore the only
|
|
||||||
backwards-compatible way to add requests to an interface is to
|
|
||||||
add them to the end. Any &event; elements do not interfere
|
|
||||||
with request opcode assignments.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The &arg; elements declare the request's arguments.
|
|
||||||
There can be 0 to 20 arguments for a request.
|
|
||||||
The order of &arg; inside the request element defines the order of
|
|
||||||
the arguments on the wire. All declared arguments are mandatory,
|
|
||||||
and extra arguments are not allowed on the wire.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The &description; element should be used to document the request.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
<title>Required attributes</title>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>name</varname>="<userinput>cname</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The name of the request. &cname-requirements;
|
|
||||||
The name must be unique within all requests and &event;s in the
|
|
||||||
containing &interface;.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Code and language binding generators may use the name in the API
|
|
||||||
they create. The <varname>name</varname> of the containing
|
|
||||||
&interface; provides the namespace for requests.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
<title>Optional attributes</title>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>type</varname>="<literal>destructor</literal>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
When this attribute is present, the request is a destructor:
|
|
||||||
it shall destroy the protocol object it is sent on. Protocol IPC
|
|
||||||
libraries may use this for bookkeeping protocol object lifetimes.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Libwayland-client uses this information to ignore incoming &event;s
|
|
||||||
for destroyed protocol objects. Such events may occur due to a
|
|
||||||
natural race condition between the client destroying a protocol
|
|
||||||
object and the server sending events before processing the
|
|
||||||
destroy request.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>since</varname>="<userinput>S</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<userinput>S</userinput> must be an integer greater than zero.
|
|
||||||
If <varname>since</varname> is not specified,
|
|
||||||
<code>since="1"</code> is assumed.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This request was added in &interface; <varname>version</varname>
|
|
||||||
<userinput>S</userinput>. The request does not exist if the
|
|
||||||
protocol object has a bound version smaller than
|
|
||||||
<userinput>S</userinput>. Attempts to use it in such a case
|
|
||||||
shall raise the protocol error
|
|
||||||
<varname>wl_display.error.invalid_method</varname>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>deprecated-since</varname>="<userinput>D</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<userinput>D</userinput> must be an integer greater than the
|
|
||||||
value of <varname>since</varname>.
|
|
||||||
If <varname>deprecated-since</varname> is not specified, then
|
|
||||||
the request is not deprecated in any version of the containing
|
|
||||||
&interface;.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This request was deprecated in &interface; <varname>version</varname>
|
|
||||||
<userinput>D</userinput> and above, and should not be sent on
|
|
||||||
protocol objects of such version. This is informational.
|
|
||||||
Compositors must still be prepared to handle the
|
|
||||||
request unless specified otherwise.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="sect-MessageXML-tag-event">
|
|
||||||
<title>event</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Parent elements: &interface;
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<synopsis>event ::= (&description;?, &arg;*)</synopsis>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Defines an event, a message from a server to a client.
|
|
||||||
Events are always associated with a specific protocol object.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Events are automatically assigned opcodes in the order they
|
|
||||||
appear inside the &interface; element. Therefore the only
|
|
||||||
backwards-compatible way to add events to an interface is to
|
|
||||||
add them to the end. Any &request; elements do not interfere
|
|
||||||
with event opcode assignments.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The &arg; elements declare the event's arguments.
|
|
||||||
There can be 0 to 20 arguments for an event.
|
|
||||||
The order of &arg; inside the event element defines the order of
|
|
||||||
the arguments on the wire. All declared arguments are mandatory,
|
|
||||||
and extra arguments are not allowed on the wire.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The &description; element should be used to document the event.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
<title>Required attributes</title>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>name</varname>="<userinput>cname</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The name of the event. &cname-requirements;
|
|
||||||
The name must be unique within all &request;s and events in the
|
|
||||||
containing &interface;.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Code and language binding generators may use the name in the API
|
|
||||||
they create. The <varname>name</varname> of the containing
|
|
||||||
&interface; provides the namespace for events.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
<title>Optional attributes</title>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>type</varname>="<literal>destructor</literal>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
When this attribute is present, the event is a destructor:
|
|
||||||
it shall destroy the protocol object it is sent on. Protocol IPC
|
|
||||||
libraries may use this for bookkeeping protocol object lifetimes.
|
|
||||||
</para>
|
|
||||||
<warning>
|
|
||||||
<para>
|
|
||||||
Destructor events are an underdeveloped feature in Wayland.
|
|
||||||
They can be used only on client-created protocol objects, and
|
|
||||||
it is the protocol designer's responsibility
|
|
||||||
to design such a message exchange that race conditions cannot
|
|
||||||
occur. The main problem would be a client sending a request at the
|
|
||||||
same time as the server is sending a destructor event. The
|
|
||||||
server will consider the protocol object to be already invalid
|
|
||||||
or even recycled when it proceeds to process the request.
|
|
||||||
This often results in protocol errors, but under specific
|
|
||||||
conditions it might also result in silently incorrect behavior.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Destructor events should not be used in new protocols.
|
|
||||||
If a destructor event is necessary, the simplest way to avoid
|
|
||||||
these problems is to have the &interface; not contain any
|
|
||||||
&request;s.
|
|
||||||
</para>
|
|
||||||
</warning>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>since</varname>="<userinput>S</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<userinput>S</userinput> must be an integer greater than zero.
|
|
||||||
If <varname>since</varname> is not specified,
|
|
||||||
<code>since="1"</code> is assumed.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This event was added in &interface; <varname>version</varname>
|
|
||||||
<userinput>S</userinput>. The event does not exist if the
|
|
||||||
protocol object has a bound version smaller than
|
|
||||||
<userinput>S</userinput>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>deprecated-since</varname>="<userinput>D</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<userinput>D</userinput> must be an integer greater than the
|
|
||||||
value of <varname>since</varname>.
|
|
||||||
If <varname>deprecated-since</varname> is not specified, then
|
|
||||||
the event is not deprecated in any version of the containing
|
|
||||||
&interface;.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This event was deprecated in &interface; <varname>version</varname>
|
|
||||||
<userinput>D</userinput> and above, and should not be sent on
|
|
||||||
protocol objects of such version. This is informational.
|
|
||||||
Clients must still be prepared to receive this event
|
|
||||||
unless otherwise specified.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="sect-MessageXML-tag-arg">
|
|
||||||
<title>arg</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Parent elements: &request;, &event;
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<synopsis>arg ::= &description;?</synopsis>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
This element declares one argument for the request or the event.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
<title>Required attributes</title>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>name</varname>="<userinput>cname</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The name of the argument. &cname-requirements;
|
|
||||||
The name must be unique within all the arguments of the parent element.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>type</varname>="<userinput>T</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The type <userinput>T</userinput> of the argument datum must
|
|
||||||
be one of:
|
|
||||||
</para>
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term><literal>int</literal></term>
|
|
||||||
<listitem>
|
|
||||||
<simpara>32-bit signed integer.</simpara>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term><literal>uint</literal></term>
|
|
||||||
<listitem>
|
|
||||||
<simpara>32-bit unsigned integer.</simpara>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term><literal>fixed</literal></term>
|
|
||||||
<listitem>
|
|
||||||
<simpara>Signed 24.8-bit fixed-point value.</simpara>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term><literal>string</literal></term>
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
UTF-8 encoded string value, NUL byte terminated.
|
|
||||||
Interior NUL bytes are not allowed.
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term><literal>array</literal></term>
|
|
||||||
<listitem>
|
|
||||||
<simpara>A byte array of arbitrary data.</simpara>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term><literal>fd</literal></term>
|
|
||||||
<listitem>
|
|
||||||
<simpara>A file descriptor.</simpara>
|
|
||||||
<simpara>
|
|
||||||
The file descriptor must be open and valid on send.
|
|
||||||
It is not possible to pass a null value.
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term><literal>new_id</literal></term>
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
Creates a new protocol object. A &request; or an &event; may
|
|
||||||
have at most one <literal>new_id</literal> argument.
|
|
||||||
</simpara>
|
|
||||||
<simpara>
|
|
||||||
If <varname>interface</varname> is specified, the new
|
|
||||||
protocol object shall have the specified &interface;,
|
|
||||||
and the new object's (interface) version shall be the
|
|
||||||
version of the object on which the &request; or &event;
|
|
||||||
is being sent.
|
|
||||||
</simpara>
|
|
||||||
<simpara>
|
|
||||||
If <varname>interface</varname> is not specified, the
|
|
||||||
&request; shall implicitly have two additional arguments:
|
|
||||||
A <literal>string</literal> for an &interface; name, and
|
|
||||||
a <literal>uint</literal> for the new object's version.
|
|
||||||
Leaving the interface unspecified is reserved for special use,
|
|
||||||
<xref linkend="protocol-spec-wl_registry-request-bind" />
|
|
||||||
for example.
|
|
||||||
</simpara>
|
|
||||||
<note>
|
|
||||||
<simpara>
|
|
||||||
An &event; argument must always specify the
|
|
||||||
<literal>new_id</literal> <varname>interface</varname>.
|
|
||||||
</simpara>
|
|
||||||
</note>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term><literal>object</literal></term>
|
|
||||||
<listitem>
|
|
||||||
<simpara>Reference to an existing protocol object.</simpara>
|
|
||||||
<simpara>
|
|
||||||
The attribute <varname>interface</varname> should be
|
|
||||||
specified. Otherwise IPC libraries cannot enforce the
|
|
||||||
interface, and checking the interface falls on user code
|
|
||||||
and specification text.
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
<title>Optional attributes</title>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>summary</varname>="<userinput>summary</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
A short (half a line at most) description. This attribute
|
|
||||||
should not be used if a &description; is used.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>interface</varname>="<userinput>iface</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If given, <userinput>iface</userinput> must be the
|
|
||||||
<varname>name</varname> of some &interface;, and
|
|
||||||
<varname>type</varname> of this argument must be either
|
|
||||||
<literal>"object"</literal> or <literal>"new_id"</literal>.
|
|
||||||
This indicates that the existing or new object must have
|
|
||||||
the interface <userinput>iface</userinput>.
|
|
||||||
Use for other argument types is forbidden.
|
|
||||||
</para>
|
|
||||||
<note>
|
|
||||||
<simpara>
|
|
||||||
If an interface from another protocol is used, then this
|
|
||||||
creates a dependency between the protocols. If an application
|
|
||||||
generates code for one protocol, then it must also generate
|
|
||||||
code for all dependencies. Therefore this would not be a
|
|
||||||
backwards compatible change.
|
|
||||||
</simpara>
|
|
||||||
</note>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>allow-null</varname>="<literal>true</literal>" | "<literal>false</literal>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Whether the argument value can be null on send.
|
|
||||||
Defaults to <literal>"false"</literal>, meaning it is illegal
|
|
||||||
to send a null value.
|
|
||||||
Can be used only when <varname>type</varname> is
|
|
||||||
<literal>"string"</literal> or <literal>"object"</literal>.
|
|
||||||
</para>
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
Even though this attribute can be used to forbid a compositor
|
|
||||||
from sending a null object as an event argument, an IPC library
|
|
||||||
implementation may not protect the client from receiving a null
|
|
||||||
object. This can happen with libwayland-client when the client
|
|
||||||
has destroyed the protocol object before dispatching an event
|
|
||||||
that referred to it in an argument.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>enum</varname>="<userinput>enum-cname-suffix</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If specified, indicates that the argument value should come from the
|
|
||||||
&enum; named <userinput>enum-cname-suffix</userinput>. If the
|
|
||||||
enumeration is a bitfield, then <varname>type</varname> must be
|
|
||||||
<literal>"uint"</literal>. Otherwise <varname>type</varname> must
|
|
||||||
be either <literal>"uint"</literal> or <literal>"int"</literal>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The name <userinput>enum-cname-suffix</userinput> refers to an &enum;
|
|
||||||
in the same &interface; by default. If it is necessary to refer to an
|
|
||||||
enumeration from another interface, the interface name can be
|
|
||||||
given with a period:
|
|
||||||
<synopsis><varname>enum</varname>="<userinput>iface</userinput>.<userinput>enum-cname-suffix</userinput>"</synopsis>
|
|
||||||
</para>
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
This attribute alone does not automatically restrict the legal
|
|
||||||
values for this argument.
|
|
||||||
If values from outside of the enumeration need to be forbidden,
|
|
||||||
that must be specified explicitly in the documentation.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
A common design pattern is to have the server advertise the
|
|
||||||
supported enumeration or bit values with &event;s and
|
|
||||||
explicitly forbid clients from using any other values in
|
|
||||||
requests. This also requires a protocol error code to be
|
|
||||||
specified with the error &enum; to be raised if a client
|
|
||||||
uses an illegal value, see
|
|
||||||
<xref linkend="sect-MessageXML-tag-interface" />.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="sect-MessageXML-tag-enum">
|
|
||||||
<title>enum</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Parent elements: &protocol;
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<synopsis>enum ::= (&description;?, &entry;*)</synopsis>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
This tag defines an enumeration of integer values. Enumerations are
|
|
||||||
merely a syntactic construct to give names to arbitrary integer
|
|
||||||
constants. Each constant is listed as an &entry; with its name.
|
|
||||||
There are two types of enumerations: regular enumerations and bitfields.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Regular enumerations do not use <varname>bitfield</varname>
|
|
||||||
attribute, or they set it to <literal>"false"</literal>.
|
|
||||||
The set of pre-defined values that belong to a regular enumeration is
|
|
||||||
exactly the set of values listed as &entry; elements after
|
|
||||||
the protocol object version is taken into account.
|
|
||||||
See the &entry; attributes <varname>since</varname> and
|
|
||||||
<varname>deprecated-since</varname>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Bitfields set <varname>bitfield</varname> to
|
|
||||||
<literal>"true"</literal>. The set of values that belong to a
|
|
||||||
bitfield enumeration are all the values that can be formed by
|
|
||||||
the bitwise-or operator from the set of values listed as &entry;
|
|
||||||
elements like in the regular enumeration. Usually also zero is
|
|
||||||
implicitly included.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
All the values in a regular enumeration must be either
|
|
||||||
signed or unsigned 32-bit integers. All the values in a
|
|
||||||
bitfield enumeration must be unsigned 32-bit integers.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
<title>Required attributes</title>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>name</varname>="<userinput>cname-suffix</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The name of the enumeration. &cname-suffix-requirements;
|
|
||||||
The name must be unique within all enumerations in the containing
|
|
||||||
&interface;. The name is used as the namespace for all the
|
|
||||||
contained &entry; elements.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
<title>Optional attributes</title>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>since</varname>="<userinput>S</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<userinput>S</userinput> must be an integer greater than zero.
|
|
||||||
If <varname>since</varname> is not specified,
|
|
||||||
<code>since="1"</code> is assumed.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This enumeration was added in &interface; <varname>version</varname>
|
|
||||||
<userinput>S</userinput>. The enumeration does not exist if the
|
|
||||||
protocol object has a bound version smaller than
|
|
||||||
<userinput>S</userinput>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>bitfield</varname>="<literal>true</literal>" | "<literal>false</literal>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Specifies if this enumeration is a bitfield.
|
|
||||||
Defaults to <literal>"false"</literal>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="sect-MessageXML-tag-entry">
|
|
||||||
<title>entry</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Parent elements: &enum;
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<synopsis>entry ::= &description;?</synopsis>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Defines a name for an integer constant and makes it part of the
|
|
||||||
set of values of the containing enumeration.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
<title>Required attributes</title>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>name</varname>="<userinput>cname-suffix</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The name of a value in an enumeration. &cname-suffix-requirements;
|
|
||||||
The name must be unique within all entry elements in the containing
|
|
||||||
&enum;.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>value</varname>="<userinput>V</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
An integer value.
|
|
||||||
The value can be given in decimal, hexadecimal, or octal
|
|
||||||
representation.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
<title>Optional attributes</title>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>summary</varname>="<userinput>summary</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
A short (half a line at most) description. This attribute
|
|
||||||
should not be used if a &description; is used.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>since</varname>="<userinput>S</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<userinput>S</userinput> must be an integer greater than zero.
|
|
||||||
If <varname>since</varname> is not specified,
|
|
||||||
<code>since="1"</code> is assumed.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This value was added in &interface; <varname>version</varname>
|
|
||||||
<userinput>S</userinput>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<synopsis><varname>deprecated-since</varname>="<userinput>D</userinput>"</synopsis>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<userinput>D</userinput> must be an integer greater than the
|
|
||||||
value of <varname>since</varname>.
|
|
||||||
If <varname>deprecated-since</varname> is not specified, then
|
|
||||||
the value is not deprecated in any version of the containing
|
|
||||||
&interface;.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This value was removed in &interface; <varname>version</varname>
|
|
||||||
<userinput>D</userinput>. This does not make the value
|
|
||||||
automatically illegal to use, see
|
|
||||||
<xref linkend="sect-MessageXML-tag-arg" /> attribute
|
|
||||||
<varname>enum</varname>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
||||||
|
|
@ -1,592 +0,0 @@
|
||||||
<?xml version='1.0' encoding='utf-8' ?>
|
|
||||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
||||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
|
||||||
%BOOK_ENTITIES;
|
|
||||||
]>
|
|
||||||
<chapter id="chap-Protocol">
|
|
||||||
<title>Wayland Protocol and Model of Operation</title>
|
|
||||||
<section id="sect-Protocol-Basic-Principles">
|
|
||||||
<title>Basic Principles</title>
|
|
||||||
<para>
|
|
||||||
The Wayland protocol is an asynchronous object oriented protocol. All
|
|
||||||
requests are method invocations on some object. The requests include
|
|
||||||
an object ID that uniquely identifies an object on the server. Each
|
|
||||||
object implements an interface and the requests include an opcode that
|
|
||||||
identifies which method in the interface to invoke.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The protocol is message-based. A message sent by a client to the server
|
|
||||||
is called request. A message from the server to a client is called event.
|
|
||||||
A message has a number of arguments, each of which has a certain type (see
|
|
||||||
<xref linkend="sect-Protocol-Wire-Format"/> for a list of argument types).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Additionally, the protocol can specify <type>enum</type>s which associate
|
|
||||||
names to specific numeric enumeration values. These are primarily just
|
|
||||||
descriptive in nature: at the wire format level enums are just integers.
|
|
||||||
But they also serve a secondary purpose to enhance type safety or
|
|
||||||
otherwise add context for use in language bindings or other such code.
|
|
||||||
This latter usage is only supported so long as code written before these
|
|
||||||
attributes were introduced still works after; in other words, adding an
|
|
||||||
enum should not break API, otherwise it puts backwards compatibility at
|
|
||||||
risk.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<type>enum</type>s can be defined as just a set of integers, or as
|
|
||||||
bitfields. This is specified via the <type>bitfield</type> boolean
|
|
||||||
attribute in the <type>enum</type> definition. If this attribute is true,
|
|
||||||
the enum is intended to be accessed primarily using bitwise operations,
|
|
||||||
for example when arbitrarily many choices of the enum can be ORed
|
|
||||||
together; if it is false, or the attribute is omitted, then the enum
|
|
||||||
arguments are a just a sequence of numerical values.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The <type>enum</type> attribute can be used on either <type>uint</type>
|
|
||||||
or <type>int</type> arguments, however if the <type>enum</type> is
|
|
||||||
defined as a <type>bitfield</type>, it can only be used on
|
|
||||||
<type>uint</type> args.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The server sends back events to the client, each event is emitted from
|
|
||||||
an object. Events can be error conditions. The event includes the
|
|
||||||
object ID and the event opcode, from which the client can determine
|
|
||||||
the type of event. Events are generated both in response to requests
|
|
||||||
(in which case the request and the event constitutes a round trip) or
|
|
||||||
spontaneously when the server state changes.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
State is broadcast on connect, events are sent
|
|
||||||
out when state changes. Clients must listen for
|
|
||||||
these changes and cache the state.
|
|
||||||
There is no need (or mechanism) to query server state.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The server will broadcast the presence of a number of global objects,
|
|
||||||
which in turn will broadcast their current state.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-Protocol-Code-Generation">
|
|
||||||
<title>Code Generation</title>
|
|
||||||
<para>
|
|
||||||
The interfaces, requests and events are defined in
|
|
||||||
<filename>protocol/wayland.xml</filename>.
|
|
||||||
This xml is used to generate the function prototypes that can be used by
|
|
||||||
clients and compositors.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The protocol entry points are generated as inline functions which just
|
|
||||||
wrap the <function>wl_proxy_*</function> functions. The inline functions aren't
|
|
||||||
part of the library ABI and language bindings should generate their
|
|
||||||
own stubs for the protocol entry points from the xml.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-Protocol-Wire-Format">
|
|
||||||
<title>Wire Format</title>
|
|
||||||
<para>
|
|
||||||
The protocol is sent over a UNIX domain stream socket, where the endpoint
|
|
||||||
usually is named <systemitem class="service">wayland-0</systemitem>
|
|
||||||
(although it can be changed via <emphasis>WAYLAND_DISPLAY</emphasis>
|
|
||||||
in the environment). Beginning in Wayland 1.15, implementations can
|
|
||||||
optionally support server socket endpoints located at arbitrary
|
|
||||||
locations in the filesystem by setting <emphasis>WAYLAND_DISPLAY</emphasis>
|
|
||||||
to the absolute path at which the server endpoint listens. The socket may
|
|
||||||
also be provided through file descriptor inheritance, in which case
|
|
||||||
<emphasis>WAYLAND_SOCKET</emphasis> is set.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Every message is structured as 32-bit words; values are represented in the
|
|
||||||
host's byte-order. The message header has 2 words in it:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The first word is the sender's object ID (32-bit).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The second has 2 parts of 16-bit. The upper 16-bits are the message
|
|
||||||
size in bytes, starting at the header (i.e. it has a minimum value of 8).The lower is the request/event opcode.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
The payload describes the request/event arguments. Every argument is always
|
|
||||||
aligned to 32-bits. Where padding is required, the value of padding bytes is
|
|
||||||
undefined. There is no prefix that describes the type, but it is
|
|
||||||
inferred implicitly from the xml specification.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
|
|
||||||
The representation of argument types are as follows:
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>int</term>
|
|
||||||
<term>uint</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The value is the 32-bit value of the signed/unsigned
|
|
||||||
int.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>fixed</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Signed 24.8 decimal numbers. It is a signed decimal type which
|
|
||||||
offers a sign bit, 23 bits of integer precision and 8 bits of
|
|
||||||
decimal precision. This is exposed as an opaque struct with
|
|
||||||
conversion helpers to and from double and int on the C API side.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>string</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Starts with an unsigned 32-bit length (including null terminator),
|
|
||||||
followed by the UTF-8 encoded string contents, including
|
|
||||||
terminating null byte, then padding to a 32-bit boundary. A null
|
|
||||||
value is represented with a length of 0. Interior null bytes are
|
|
||||||
not permitted.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>object</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
32-bit object ID. A null value is represented with an ID of 0.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>new_id</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The 32-bit object ID. Generally, the interface used for the new
|
|
||||||
object is inferred from the xml, but in the case where it's not
|
|
||||||
specified, a new_id is preceded by a <code>string</code> specifying
|
|
||||||
the interface name, and a <code>uint</code> specifying the version.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>array</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Starts with 32-bit array size in bytes, followed by the array
|
|
||||||
contents verbatim, and finally padding to a 32-bit boundary.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>fd</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The file descriptor is not stored in the message buffer, but in
|
|
||||||
the ancillary data of the UNIX domain socket message (msg_control).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The protocol does not specify the exact position of the ancillary data
|
|
||||||
in the stream, except that the order of file descriptors is the same as
|
|
||||||
the order of messages and <code>fd</code> arguments within messages on
|
|
||||||
the wire.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In particular, it means that any byte of the stream, even the message
|
|
||||||
header, may carry the ancillary data with file descriptors.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Clients and compositors should queue incoming data until they have
|
|
||||||
whole messages to process, as file descriptors may arrive earlier
|
|
||||||
or later than the corresponding data bytes.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<xi:include href="ProtocolInterfaces.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
|
|
||||||
<section id="sect-Protocol-Versioning">
|
|
||||||
<title>Versioning</title>
|
|
||||||
<para>
|
|
||||||
Every interface is versioned and every protocol object implements a
|
|
||||||
particular version of its interface. For global objects, the maximum
|
|
||||||
version supported by the server is advertised with the global and the
|
|
||||||
actual version of the created protocol object is determined by the
|
|
||||||
version argument passed to wl_registry.bind(). For objects that are
|
|
||||||
not globals, their version is inferred from the object that created
|
|
||||||
them.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In order to keep things sane, this has a few implications for
|
|
||||||
interface versions:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The object creation hierarchy must be a tree. Otherwise,
|
|
||||||
inferring object versions from the parent object becomes a much
|
|
||||||
more difficult to properly track.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
When the version of an interface increases, so does the version
|
|
||||||
of its parent (recursively until you get to a global interface)
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
A global interface's version number acts like a counter for all
|
|
||||||
of its child interfaces. Whenever a child interface gets
|
|
||||||
modified, the global parent's interface version number also
|
|
||||||
increases (see above). The child interface then takes on the
|
|
||||||
same version number as the new version of its parent global
|
|
||||||
interface.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To illustrate the above, consider the wl_compositor interface. It
|
|
||||||
has two children, wl_surface and wl_region. As of wayland version
|
|
||||||
1.2, wl_surface and wl_compositor are both at version 3. If
|
|
||||||
something is added to the wl_region interface, both wl_region and
|
|
||||||
wl_compositor will get bumpped to version 4. If, afterwards,
|
|
||||||
wl_surface is changed, both wl_compositor and wl_surface will be at
|
|
||||||
version 5. In this way the global interface version is used as a
|
|
||||||
sort of "counter" for all of its child interfaces. This makes it
|
|
||||||
very simple to know the version of the child given the version of its
|
|
||||||
parent. The child is at the highest possible interface version that
|
|
||||||
is less than or equal to its parent's version.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
It is worth noting a particular exception to the above versioning
|
|
||||||
scheme. The wl_display (and, by extension, wl_registry) interface
|
|
||||||
cannot change because it is the core protocol object and its version
|
|
||||||
is never advertised nor is there a mechanism to request a different
|
|
||||||
version.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-Protocol-Connect-Time">
|
|
||||||
<title>Connect Time</title>
|
|
||||||
<para>
|
|
||||||
There is no fixed connection setup information, the server emits
|
|
||||||
multiple events at connect time, to indicate the presence and
|
|
||||||
properties of global objects: outputs, compositor, input devices.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-Protocol-Security-and-Authentication">
|
|
||||||
<title>Security and Authentication</title>
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
mostly about access to underlying buffers, need new drm auth
|
|
||||||
mechanism (the grant-to ioctl idea), need to check the cmd stream?
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
getting the server socket depends on the compositor type, could
|
|
||||||
be a system wide name, through fd passing on the session dbus.
|
|
||||||
or the client is forked by the compositor and the fd is
|
|
||||||
already opened.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-Protocol-Creating-Objects">
|
|
||||||
<title>Creating Objects</title>
|
|
||||||
<para>
|
|
||||||
Each object has a unique ID. The IDs are allocated by the entity
|
|
||||||
creating the object (either client or server). IDs allocated by the
|
|
||||||
client are in the range [1, 0xfeffffff] while IDs allocated by the
|
|
||||||
server are in the range [0xff000000, 0xffffffff]. The 0 ID is
|
|
||||||
reserved to represent a null or non-existent object.
|
|
||||||
|
|
||||||
For efficiency purposes, the IDs are densely packed in the sense that
|
|
||||||
the ID N will not be used until N-1 has been used. This ordering is
|
|
||||||
not merely a guideline, but a strict requirement, and there are
|
|
||||||
implementations of the protocol that rigorously enforce this rule,
|
|
||||||
including the ubiquitous libwayland.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-Protocol-Compositor">
|
|
||||||
<title>Compositor</title>
|
|
||||||
<para>
|
|
||||||
The compositor is a global object, advertised at connect time.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
See <xref linkend="protocol-spec-wl_compositor"/> for the
|
|
||||||
protocol description.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-Protocol-Surface">
|
|
||||||
<title>Surfaces</title>
|
|
||||||
<para>
|
|
||||||
A surface manages a rectangular grid of pixels that clients create
|
|
||||||
for displaying their content to the screen. Clients don't know
|
|
||||||
the global position of their surfaces, and cannot access other
|
|
||||||
clients' surfaces.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Once the client has finished writing pixels, it 'commits' the
|
|
||||||
buffer; this permits the compositor to access the buffer and read
|
|
||||||
the pixels. When the compositor is finished, it releases the
|
|
||||||
buffer back to the client.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
See <xref linkend="protocol-spec-wl_surface"/> for the protocol
|
|
||||||
description.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-Protocol-Input">
|
|
||||||
<title>Input</title>
|
|
||||||
<para>
|
|
||||||
A seat represents a group of input devices including mice,
|
|
||||||
keyboards and touchscreens. It has a keyboard and pointer
|
|
||||||
focus. Seats are global objects. Pointer events are delivered
|
|
||||||
in surface-local coordinates.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The compositor maintains an implicit grab when a button is
|
|
||||||
pressed, to ensure that the corresponding button release
|
|
||||||
event gets delivered to the same surface. But there is no way
|
|
||||||
for clients to take an explicit grab. Instead, surfaces can
|
|
||||||
be mapped as 'popup', which combines transient window semantics
|
|
||||||
with a pointer grab.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To avoid race conditions, input events that are likely to
|
|
||||||
trigger further requests (such as button presses, key events,
|
|
||||||
pointer motions) carry serial numbers, and requests such as
|
|
||||||
wl_surface.set_popup require that the serial number of the
|
|
||||||
triggering event is specified. The server maintains a
|
|
||||||
monotonically increasing counter for these serial numbers.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Input events also carry timestamps with millisecond granularity.
|
|
||||||
Their base is undefined, so they can't be compared against
|
|
||||||
system time (as obtained with clock_gettime or gettimeofday).
|
|
||||||
They can be compared with each other though, and for instance
|
|
||||||
be used to identify sequences of button presses as double
|
|
||||||
or triple clicks.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
See <xref linkend="protocol-spec-wl_seat"/> for the
|
|
||||||
protocol description.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Talk about:
|
|
||||||
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
keyboard map, change events
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
xkb on Wayland
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
multi pointer Wayland
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
A surface can change the pointer image when the surface is the pointer
|
|
||||||
focus of the input device. Wayland doesn't automatically change the
|
|
||||||
pointer image when a pointer enters a surface, but expects the
|
|
||||||
application to set the cursor it wants in response to the pointer
|
|
||||||
focus and motion events. The rationale is that a client has to manage
|
|
||||||
changing pointer images for UI elements within the surface in response
|
|
||||||
to motion events anyway, so we'll make that the only mechanism for
|
|
||||||
setting or changing the pointer image. If the server receives a request
|
|
||||||
to set the pointer image after the surface loses pointer focus, the
|
|
||||||
request is ignored. To the client this will look like it successfully
|
|
||||||
set the pointer image.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Setting the pointer image to NULL causes the cursor to be hidden.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The compositor will revert the pointer image back to a default image
|
|
||||||
when no surface has the pointer focus for that device.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
What if the pointer moves from one window which has set a special
|
|
||||||
pointer image to a surface that doesn't set an image in response to
|
|
||||||
the motion event? The new surface will be stuck with the special
|
|
||||||
pointer image. We can't just revert the pointer image on leaving a
|
|
||||||
surface, since if we immediately enter a surface that sets a different
|
|
||||||
image, the image will flicker. If a client does not set a pointer image
|
|
||||||
when the pointer enters a surface, the pointer stays with the image set
|
|
||||||
by the last surface that changed it, possibly even hidden. Such a client
|
|
||||||
is likely just broken.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-Protocol-Output">
|
|
||||||
<title>Output</title>
|
|
||||||
<para>
|
|
||||||
An output is a global object, advertised at connect time or as it
|
|
||||||
comes and goes.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
See <xref linkend="protocol-spec-wl_output"/> for the protocol
|
|
||||||
description.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
</para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
laid out in a big (compositor) coordinate system
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
basically xrandr over Wayland
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
geometry needs position in compositor coordinate system
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
events to advertise available modes, requests to move and change
|
|
||||||
modes
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</section>
|
|
||||||
<section id="sect-Protocol-data-sharing">
|
|
||||||
<title>Data sharing between clients</title>
|
|
||||||
<para>
|
|
||||||
The Wayland protocol provides clients a mechanism for sharing
|
|
||||||
data that allows the implementation of copy-paste and
|
|
||||||
drag-and-drop. The client providing the data creates a
|
|
||||||
<function>wl_data_source</function> object and the clients
|
|
||||||
obtaining the data will see it as <function>wl_data_offer</function>
|
|
||||||
object. This interface allows the clients to agree on a mutually
|
|
||||||
supported mime type and transfer the data via a file descriptor
|
|
||||||
that is passed through the protocol.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The next section explains the negotiation between data source and
|
|
||||||
data offer objects. <xref linkend="sect-Protocol-data-sharing-devices"/>
|
|
||||||
explains how these objects are created and passed to different
|
|
||||||
clients using the <function>wl_data_device</function> interface
|
|
||||||
that implements copy-paste and drag-and-drop support.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
See <xref linkend="protocol-spec-wl_data_offer"/>,
|
|
||||||
<xref linkend="protocol-spec-wl_data_source"/>,
|
|
||||||
<xref linkend="protocol-spec-wl_data_device"/> and
|
|
||||||
<xref linkend="protocol-spec-wl_data_device_manager"/> for
|
|
||||||
protocol descriptions.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
MIME is defined in RFC's 2045-2049. A
|
|
||||||
<ulink url="https://www.iana.org/assignments/media-types/media-types.xhtml">
|
|
||||||
registry of MIME types</ulink> is maintained by the Internet Assigned
|
|
||||||
Numbers Authority (IANA).
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Data negotiation</title>
|
|
||||||
<para>
|
|
||||||
A client providing data to other clients will create a <function>wl_data_source</function>
|
|
||||||
object and advertise the mime types for the formats it supports for
|
|
||||||
that data through the <function>wl_data_source.offer</function>
|
|
||||||
request. On the receiving end, the data offer object will generate one
|
|
||||||
<function>wl_data_offer.offer</function> event for each supported mime
|
|
||||||
type.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The actual data transfer happens when the receiving client sends a
|
|
||||||
<function>wl_data_offer.receive</function> request. This request takes
|
|
||||||
a mime type and a file descriptor as arguments. This request will generate a
|
|
||||||
<function>wl_data_source.send</function> event on the sending client
|
|
||||||
with the same arguments, and the latter client is expected to write its
|
|
||||||
data to the given file descriptor using the chosen mime type.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-Protocol-data-sharing-devices">
|
|
||||||
<title>Data devices</title>
|
|
||||||
<para>
|
|
||||||
Data devices glue data sources and offers together. A data device is
|
|
||||||
associated with a <function>wl_seat</function> and is obtained by the clients using the
|
|
||||||
<function>wl_data_device_manager</function> factory object, which is also responsible for
|
|
||||||
creating data sources.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Clients are informed of new data offers through the
|
|
||||||
<function>wl_data_device.data_offer</function> event. After this
|
|
||||||
event is generated the data offer will advertise the available mime
|
|
||||||
types. New data offers are introduced prior to their use for
|
|
||||||
copy-paste or drag-and-drop.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Selection</title>
|
|
||||||
<para>
|
|
||||||
Each data device has a selection data source. Clients create a data
|
|
||||||
source object using the device manager and may set it as the
|
|
||||||
current selection for a given data device. Whenever the current
|
|
||||||
selection changes, the client with keyboard focus receives a
|
|
||||||
<function>wl_data_device.selection</function> event. This event is
|
|
||||||
also generated on a client immediately before it receives keyboard
|
|
||||||
focus.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The data offer is introduced with
|
|
||||||
<function>wl_data_device.data_offer</function> event before the
|
|
||||||
selection event.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Drag and Drop</title>
|
|
||||||
<para>
|
|
||||||
A drag-and-drop operation is started using the
|
|
||||||
<function>wl_data_device.start_drag</function> request. This
|
|
||||||
requests causes a pointer grab that will generate enter, motion and
|
|
||||||
leave events on the data device. A data source is supplied as
|
|
||||||
argument to start_drag, and data offers associated with it are
|
|
||||||
supplied to clients surfaces under the pointer in the
|
|
||||||
<function>wl_data_device.enter</function> event. The data offer
|
|
||||||
is introduced to the client prior to the enter event with the
|
|
||||||
<function>wl_data_device.data_offer</function> event.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Clients are expected to provide feedback to the data sending client
|
|
||||||
by calling the <function>wl_data_offer.accept</function> request with
|
|
||||||
a mime type it accepts. If none of the advertised mime types is
|
|
||||||
supported by the receiving client, it should supply NULL to the
|
|
||||||
accept request. The accept request causes the sending client to
|
|
||||||
receive a <function>wl_data_source.target</function> event with the
|
|
||||||
chosen mime type.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
When the drag ends, the receiving client receives a
|
|
||||||
<function>wl_data_device.drop</function> event at which it is expected
|
|
||||||
to transfer the data using the
|
|
||||||
<function>wl_data_offer.receive</function> request.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
<?xml version='1.0' encoding='utf-8' ?>
|
|
||||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
||||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
|
||||||
<!ENTITY doxygen SYSTEM "ServerAPI.xml">
|
|
||||||
%BOOK_ENTITIES;
|
|
||||||
]>
|
|
||||||
<appendix id="sect-Library-Server">
|
|
||||||
<title>Server API</title>
|
|
||||||
<section><title>Introduction</title>
|
|
||||||
<para>
|
|
||||||
The open-source reference implementation of Wayland protocol is
|
|
||||||
split in two C libraries, <link
|
|
||||||
linkend="sect-Library-Client">libwayland-client</link> and
|
|
||||||
libwayland-server. Their main responsibility is to handle the
|
|
||||||
Inter-process communication (<emphasis>IPC</emphasis>) with each
|
|
||||||
other, therefore guaranteeing the protocol objects marshaling and
|
|
||||||
messages synchronization.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The server library is designed to work much like libwayland-client,
|
|
||||||
although it is considerably complicated due to the server needing
|
|
||||||
to support multiple versions of the protocol. It is best to learn
|
|
||||||
libwayland-client first.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Each open socket to a client is represented by a <link
|
|
||||||
linkend="Server-structwl__client">wl_client</link>. The equivalent
|
|
||||||
of the <link linkend="Client-classwl__proxy">wl_proxy</link> that
|
|
||||||
libwayland-client uses to represent an object is <link
|
|
||||||
linkend="Server-structwl__resource">wl_resource</link> for
|
|
||||||
client-created objects, and <link
|
|
||||||
linkend="Server-structwl__global">wl_global</link> for objects
|
|
||||||
created by the server.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Often a server is also a client for another Wayland server, and
|
|
||||||
thus must link with both libwayland-client and libwayland-server.
|
|
||||||
This produces some type name conflicts (such as the <link
|
|
||||||
linkend="Client-classwl__display">client wl_display</link> and
|
|
||||||
<link linkend="Server-structwl__display">server wl_display</link>,
|
|
||||||
but the duplicate-but-not-the-same types are opaque, and accessed
|
|
||||||
only inside the correct library where it came from. Naturally that
|
|
||||||
means that the program writer needs to always know if a pointer to
|
|
||||||
a wl_display is for the server or client side and use the
|
|
||||||
corresponding functions.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
&doxygen;
|
|
||||||
</appendix>
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
<!ENTITY PRODUCT "Documentation">
|
|
||||||
<!ENTITY BOOKID "Wayland">
|
|
||||||
<!ENTITY YEAR "2012">
|
|
||||||
<!ENTITY HOLDER "Kristian Høgsberg, Intel Corporation">
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
<?xml version='1.0' encoding='utf-8' ?>
|
|
||||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
||||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
|
||||||
%BOOK_ENTITIES;
|
|
||||||
]>
|
|
||||||
<book>
|
|
||||||
<xi:include href="Book_Info.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
||||||
<xi:include href="Foreword.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
||||||
<xi:include href="Introduction.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
||||||
<xi:include href="Compositors.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
||||||
<xi:include href="Architecture.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
||||||
<xi:include href="Protocol.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
||||||
<xi:include href="Message_XML.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
||||||
<xi:include href="Xwayland.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
||||||
<xi:include href="Content_Updates.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
||||||
<xi:include href="Color.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
||||||
<xi:include href="ProtocolSpec.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
||||||
<xi:include href="Client.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
|
|
||||||
<xi:include href="Server.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
|
|
||||||
</book>
|
|
||||||
|
|
@ -1,168 +0,0 @@
|
||||||
<?xml version='1.0' encoding='utf-8' ?>
|
|
||||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
||||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
|
||||||
%BOOK_ENTITIES;
|
|
||||||
]>
|
|
||||||
<chapter id="chap-X11-Application-Support">
|
|
||||||
<title>X11 Application Support</title>
|
|
||||||
<section id="sect-X11-Application-Support-introduction">
|
|
||||||
<title>Introduction</title>
|
|
||||||
<para>
|
|
||||||
Being able to run existing X11 applications is crucial for the adoption
|
|
||||||
of Wayland, especially on desktops, as there will always be X11
|
|
||||||
applications that have not been or cannot be converted into Wayland
|
|
||||||
applications, and throwing them all away would be prohibitive.
|
|
||||||
Therefore a Wayland compositor often needs to support running X11
|
|
||||||
applications.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
X11 and Wayland are different enough that there is no "simple" way to
|
|
||||||
translate between them. Most of X11 is uninteresting to a Wayland
|
|
||||||
compositor. That, combined with the gigantic implementation effort needed
|
|
||||||
to support X11, makes it intractable to just write X11 support directly in
|
|
||||||
a Wayland compositor. The implementation would be nothing short of a
|
|
||||||
real X11 server.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Therefore, Wayland compositors should use Xwayland, the X11 server that
|
|
||||||
lives in the Xorg server source code repository and shares most of the
|
|
||||||
implementation with the Xorg server. Xwayland is a complete X11 server,
|
|
||||||
just like Xorg is, but instead of driving the displays and opening input
|
|
||||||
devices, it acts as a Wayland client. The rest of this chapter talks
|
|
||||||
about how Xwayland works.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For integration and architecture reasons, while Xwayland is a Wayland
|
|
||||||
client of the Wayland compositor, the Wayland compositor is an X11 client
|
|
||||||
of Xwayland. This circular dependency requires special care from the
|
|
||||||
Wayland compositor.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-X11-Application-Support-two-modes">
|
|
||||||
<title>Two Modes for Foreign Windows</title>
|
|
||||||
<para>
|
|
||||||
In general, windows from a foreign window system can be presented in one
|
|
||||||
of two ways: rootless and rootful (not rootless).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In rootful mode, the foreign window system as a whole is represented as a
|
|
||||||
window (or more) of its own. You have a native window, inside which all
|
|
||||||
the foreign windows are. The advantage of this approach in Xwayland's
|
|
||||||
case is that you can run your favourite X11 window manager to manage your
|
|
||||||
X11 applications. The disadvantage is that the foreign windows do not
|
|
||||||
integrate with the native desktop. Therefore this mode is not usually
|
|
||||||
used.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In rootless mode, each foreign window is a first-class resident among the
|
|
||||||
native windows. Foreign windows are not confined inside a native window
|
|
||||||
but act as if they were native windows. The advantage is that one can
|
|
||||||
freely stack and mix native and foreign windows, which is not possible in
|
|
||||||
rootful mode. The disadvantage is that this mode is harder to implement
|
|
||||||
and fundamental differences in window systems may prevent some things
|
|
||||||
from working. With rootless Xwayland, the Wayland compositor must take
|
|
||||||
the role as the X11 window manager, and one cannot use any other X11
|
|
||||||
window manager in its place.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This chapter concentrates on the rootless mode, and ignores the rootful
|
|
||||||
mode.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-X11-Application-Support-architecture">
|
|
||||||
<title>Architecture</title>
|
|
||||||
<para>
|
|
||||||
A Wayland compositor usually takes care of launching Xwayland.
|
|
||||||
Xwayland works in cooperation with a Wayland compositor as follows:
|
|
||||||
</para>
|
|
||||||
<figure>
|
|
||||||
<title>Xwayland architecture diagram</title>
|
|
||||||
<mediaobject>
|
|
||||||
<imageobject>
|
|
||||||
<imagedata fileref="images/xwayland-architecture.png" format="PNG" />
|
|
||||||
</imageobject>
|
|
||||||
</mediaobject>
|
|
||||||
</figure>
|
|
||||||
<para>
|
|
||||||
An X11 application connects to Xwayland just like it would connect to any
|
|
||||||
X server. Xwayland processes all the X11 requests. On the other end,
|
|
||||||
Xwayland is a Wayland client that connects to the Wayland compositor.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The X11 window manager (XWM) is an integral part of the Wayland
|
|
||||||
compositor. XWM uses the usual X11 window management protocol to manage
|
|
||||||
all X11 windows in Xwayland. Most importantly, XWM acts as a bridge
|
|
||||||
between Xwayland window state and the Wayland compositor's window manager
|
|
||||||
(WWM). This way WWM can manage all windows, both native Wayland and X11
|
|
||||||
(Xwayland) windows. This is very important for a coherent user
|
|
||||||
experience.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Since Xwayland uses Wayland for input and output, it does not have any
|
|
||||||
use for the device drivers that Xorg uses. None of the xf86-video-* or
|
|
||||||
xf86-input-* modules are used. There also is no configuration file for
|
|
||||||
the Xwayland server. For optional hardware accelerated rendering,
|
|
||||||
Xwayland uses GLAMOR.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
A Wayland compositor usually spawns only one Xwayland instance. This is
|
|
||||||
because many X11 applications assume they can communicate with other X11
|
|
||||||
applications through the X server, and this requires a shared X server
|
|
||||||
instance. This also means that Xwayland does not protect nor isolate X11
|
|
||||||
clients from each other, unless the Wayland compositor specifically
|
|
||||||
chooses to break the X11 client intercommunications by spawning
|
|
||||||
application specific Xwayland instances. X11 clients are naturally
|
|
||||||
isolated from Wayland clients.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Xwayland compatibility compared to a native X server will probably never
|
|
||||||
reach 100%. Desktop environment (DE) components, specifically X11 window
|
|
||||||
managers, are practically never supported. An X11 window manager would
|
|
||||||
not know about native Wayland windows, so it could manage only X11
|
|
||||||
windows. On the other hand, there must be an XWM that reserves the
|
|
||||||
exclusive window manager role so that the Wayland compositor could show
|
|
||||||
the X11 windows appropriately. For other DE components, like pagers and
|
|
||||||
panels, adding the necessary interfaces to support them in WWM through XWM
|
|
||||||
is often considered not worthwhile.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sect-X11-Application-Support-xwm">
|
|
||||||
<title>X Window Manager (XWM)</title>
|
|
||||||
<para>
|
|
||||||
From the X11 point of view, the X window manager (XWM) living inside a
|
|
||||||
Wayland compositor is just like any other window manager. The difference
|
|
||||||
is mostly in which process it resides in, and the few extra conventions
|
|
||||||
in the X11 protocol to support Wayland window management (WWM)
|
|
||||||
specifically.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
There are two separate asynchronous communication channels between
|
|
||||||
Xwayland and a Wayland compositor: one uses the Wayland protocol, and the
|
|
||||||
other one, solely for XWM, uses X11 protocol. This setting demands great
|
|
||||||
care from the XWM implementation to avoid (random) deadlocks with
|
|
||||||
Xwayland. It is often nearly impossible to prove that synchronous or
|
|
||||||
blocking X11 calls from XWM cannot cause a deadlock, and therefore it is
|
|
||||||
strongly recommended to make all X11 communications asynchronous. All
|
|
||||||
Wayland communications are already asynchronous by design.
|
|
||||||
</para>
|
|
||||||
<section id="sect-X11-Application-Support-xwm-window-identification">
|
|
||||||
<title>Window identification</title>
|
|
||||||
<para>
|
|
||||||
In Xwayland, an X11 window may have a corresponding wl_surface object
|
|
||||||
in Wayland. The wl_surface object is used for input and output: it is
|
|
||||||
referenced by input events and used to provide the X11 window content
|
|
||||||
to the Wayland compositor. The X11 window and the wl_surface live in
|
|
||||||
different protocol streams, and they need to be matched for XWM to do
|
|
||||||
its job.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
When Xwayland creates a wl_surface on Wayland, it will also send an X11
|
|
||||||
ClientMessage of type atom "WL_SURFACE_ID" to the X11 window carrying
|
|
||||||
the wl_surface Wayland object ID as the first 32-bit data element. This
|
|
||||||
is how XWM can associate a wl_surface with an X11 window. Note that
|
|
||||||
the request to create a wl_surface and the ID message may arrive in any
|
|
||||||
order in the Wayland compositor.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
@import url("common.css");
|
|
||||||
@import url("overrides.css");
|
|
||||||
@import url("lang.css");
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
foreach src : files([
|
|
||||||
'common.css',
|
|
||||||
'default.css',
|
|
||||||
])
|
|
||||||
name = fs.name(src)
|
|
||||||
publican_inputs += fs.copyfile(
|
|
||||||
name,
|
|
||||||
install: true,
|
|
||||||
install_dir: publican_install_prefix + '/html/css',
|
|
||||||
)
|
|
||||||
endforeach
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
foreach src : files([
|
|
||||||
'simple-desynchronized-state-1.png',
|
|
||||||
'simple-desynchronized-state-2.png',
|
|
||||||
'simple-desynchronized-state-3.png',
|
|
||||||
'simple-desynchronized-state-4.png',
|
|
||||||
'simple-desynchronized-state-5.png',
|
|
||||||
'simple-desynchronized-state-6.png',
|
|
||||||
'simple-synchronized-state-1.png',
|
|
||||||
'simple-synchronized-state-2.png',
|
|
||||||
'simple-synchronized-state-3.png',
|
|
||||||
'simple-synchronized-state-4.png',
|
|
||||||
'simple-synchronized-state-5.png',
|
|
||||||
'sync-subsurf-case1-1.png',
|
|
||||||
'sync-subsurf-case1-2.png',
|
|
||||||
'sync-subsurf-case1-3.png',
|
|
||||||
'sync-subsurf-case1-4.png',
|
|
||||||
'sync-subsurf-case1-5.png',
|
|
||||||
'sync-subsurf-case2-1.png',
|
|
||||||
'sync-subsurf-case2-2.png',
|
|
||||||
'sync-subsurf-case2-3.png',
|
|
||||||
'sync-to-desync-subsurf-1.png',
|
|
||||||
'sync-to-desync-subsurf-2.png',
|
|
||||||
'sync-to-desync-subsurf-3.png',
|
|
||||||
'sync-to-desync-transition-1.png',
|
|
||||||
'sync-to-desync-transition-2.png',
|
|
||||||
'sync-to-desync-transition-3.png',
|
|
||||||
'content-update-legend.png',
|
|
||||||
])
|
|
||||||
name = fs.name(src)
|
|
||||||
publican_inputs += fs.copyfile(
|
|
||||||
name,
|
|
||||||
install: true,
|
|
||||||
install_dir: publican_install_prefix + '/html/images/content-updates',
|
|
||||||
)
|
|
||||||
endforeach
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
foreach src : files([
|
|
||||||
'icon.svg',
|
|
||||||
'wayland.png',
|
|
||||||
])
|
|
||||||
name = fs.name(src)
|
|
||||||
publican_inputs += fs.copyfile(
|
|
||||||
name,
|
|
||||||
install: true,
|
|
||||||
install_dir: publican_install_prefix + '/html/images',
|
|
||||||
)
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
subdir('content-updates')
|
|
||||||
|
|
||||||
foreach src : files([
|
|
||||||
'wayland-architecture.gv',
|
|
||||||
'x-architecture.gv',
|
|
||||||
])
|
|
||||||
input = fs.name(src)
|
|
||||||
output = fs.stem(src) + '.png'
|
|
||||||
|
|
||||||
publican_inputs += custom_target(
|
|
||||||
input + '.png',
|
|
||||||
command: [ dot, '-Tpng', '-o@OUTPUT@', '@INPUT@' ],
|
|
||||||
input: input,
|
|
||||||
output: output,
|
|
||||||
install: true,
|
|
||||||
install_dir: publican_install_prefix + '/html/images',
|
|
||||||
)
|
|
||||||
|
|
||||||
publican_image_maps += custom_target(
|
|
||||||
input + '.map',
|
|
||||||
command: [ dot, '-Tcmapx_np', '-o@OUTPUT@', '@INPUT@' ],
|
|
||||||
input: input,
|
|
||||||
output: fs.stem(src) + '.map',
|
|
||||||
)
|
|
||||||
endforeach
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
||||||
proto_to_docboox_xsl = files('xsl/protocol-to-docbook.xsl')
|
|
||||||
proto_iface_to_docboox_xsl = files('xsl/protocol-interfaces-to-docbook.xsl')
|
|
||||||
merge_mapcoords_xsl = files('xsl/merge-mapcoords.xsl')
|
|
||||||
to_publican_xsl = files('xsl/doxygen-to-publican.xsl')
|
|
||||||
|
|
||||||
publican_inputs = []
|
|
||||||
publican_image_maps = []
|
|
||||||
|
|
||||||
foreach src : files([
|
|
||||||
'Wayland.xml', # must be first in publican_inputs
|
|
||||||
'Wayland.ent',
|
|
||||||
'Book_Info.xml',
|
|
||||||
'Author_Group.xml',
|
|
||||||
'Foreword.xml',
|
|
||||||
'Protocol.xml',
|
|
||||||
'Xwayland.xml',
|
|
||||||
'Compositors.xml',
|
|
||||||
'Content_Updates.xml',
|
|
||||||
'Color.xml',
|
|
||||||
'Client.xml',
|
|
||||||
'Server.xml',
|
|
||||||
'Message_XML.xml',
|
|
||||||
])
|
|
||||||
name = fs.name(src)
|
|
||||||
publican_inputs += fs.copyfile(name)
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
publican_inputs += custom_target(
|
|
||||||
'ProtocolSpec.xml',
|
|
||||||
command: [ xsltproc, '-o', '@OUTPUT@', proto_to_docboox_xsl, '@INPUT@' ],
|
|
||||||
input: wayland_protocol_xml,
|
|
||||||
output: 'ProtocolSpec.xml'
|
|
||||||
)
|
|
||||||
|
|
||||||
publican_inputs += custom_target(
|
|
||||||
'ProtocolInterfaces.xml',
|
|
||||||
command: [ xsltproc, '-o', '@OUTPUT@', proto_iface_to_docboox_xsl, '@INPUT@' ],
|
|
||||||
input: wayland_protocol_xml,
|
|
||||||
output: 'ProtocolInterfaces.xml'
|
|
||||||
)
|
|
||||||
|
|
||||||
# Doxygen generates a myriad of files, and offers an XSLT
|
|
||||||
# to combine them all into one. This does the combining.
|
|
||||||
# The result is still Doxygen XML.
|
|
||||||
ClientAPI_combined = custom_target(
|
|
||||||
'ClientAPI-combine-doxygen-files',
|
|
||||||
command: [ xsltproc, '-o', '@OUTPUT@', '@INPUT@' ],
|
|
||||||
input: [ doxygen_Client_combine_xslt, doxygen_Client_index_xml ],
|
|
||||||
output: 'ClientAPI-combined.xml'
|
|
||||||
)
|
|
||||||
|
|
||||||
# This converts Doxygen XML to DocBook XML.
|
|
||||||
publican_inputs += custom_target(
|
|
||||||
'ClientAPI-doxygen-to-docbook',
|
|
||||||
command: [ xsltproc, '-o', '@OUTPUT@', '--stringparam', 'which', 'Client', to_publican_xsl, '@INPUT@' ],
|
|
||||||
input: ClientAPI_combined,
|
|
||||||
output: 'ClientAPI.xml'
|
|
||||||
)
|
|
||||||
|
|
||||||
ServerAPI_combined = custom_target(
|
|
||||||
'ServerAPI-combine-doxygen-files',
|
|
||||||
command: [ xsltproc, '-o', '@OUTPUT@', '@INPUT@' ],
|
|
||||||
input: [ doxygen_Server_combine_xslt, doxygen_Server_index_xml ],
|
|
||||||
output: 'ServerAPI-combined.xml'
|
|
||||||
)
|
|
||||||
|
|
||||||
publican_inputs += custom_target(
|
|
||||||
'ServerAPI-doxygen-to-docbook',
|
|
||||||
command: [ xsltproc, '-o', '@OUTPUT@', '--stringparam', 'which', 'Server', to_publican_xsl, '@INPUT@' ],
|
|
||||||
input: ServerAPI_combined,
|
|
||||||
output: 'ServerAPI.xml'
|
|
||||||
)
|
|
||||||
|
|
||||||
subdir('html/css')
|
|
||||||
subdir('html/images')
|
|
||||||
|
|
||||||
foreach src : files([
|
|
||||||
'Architecture.xml',
|
|
||||||
'Introduction.xml'
|
|
||||||
])
|
|
||||||
name = fs.name(src)
|
|
||||||
publican_inputs += custom_target(
|
|
||||||
name,
|
|
||||||
command: [
|
|
||||||
xsltproc,
|
|
||||||
'-o', '@OUTPUT@',
|
|
||||||
'--stringparam', 'basedir', meson.current_build_dir() / 'html',
|
|
||||||
merge_mapcoords_xsl,
|
|
||||||
'@INPUT@',
|
|
||||||
],
|
|
||||||
input: src,
|
|
||||||
output: [name],
|
|
||||||
depends: publican_image_maps,
|
|
||||||
)
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
custom_target(
|
|
||||||
'Wayland-docbook-html',
|
|
||||||
command: [
|
|
||||||
xmlto,
|
|
||||||
'--skip-validation',
|
|
||||||
'--stringparam', 'chunker.output.encoding=UTF-8',
|
|
||||||
'--stringparam', 'chunk.section.depth=0',
|
|
||||||
'--stringparam', 'toc.section.depth=1',
|
|
||||||
'--stringparam', 'generate.consistent.ids=1',
|
|
||||||
'--stringparam', 'html.stylesheet=css/default.css',
|
|
||||||
'-o', '@OUTPUT@',
|
|
||||||
'html',
|
|
||||||
'@INPUT0@'
|
|
||||||
],
|
|
||||||
input: publican_inputs,
|
|
||||||
output: 'html',
|
|
||||||
build_by_default: true,
|
|
||||||
install: true,
|
|
||||||
install_dir: publican_install_prefix,
|
|
||||||
)
|
|
||||||
|
|
@ -1,160 +0,0 @@
|
||||||
<?xml version="1.0" ?>
|
|
||||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
||||||
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
|
|
||||||
<xsl:param name="which" />
|
|
||||||
|
|
||||||
<xsl:template match="/">
|
|
||||||
<xsl:apply-templates select="/doxygen/compounddef[@kind!='file' and @kind!='dir']" />
|
|
||||||
|
|
||||||
<section id="{$which}-Functions">
|
|
||||||
<title>Functions</title>
|
|
||||||
<para />
|
|
||||||
<xsl:apply-templates select="/doxygen/compounddef[@kind='file']/sectiondef" />
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<xsl:template match="parameteritem">
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<xsl:apply-templates select="parameternamelist/parametername"/>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<simpara><xsl:apply-templates select="parameterdescription"/></simpara>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<xsl:template match="parameterlist">
|
|
||||||
<xsl:if test="parameteritem">
|
|
||||||
<variablelist>
|
|
||||||
<xsl:apply-templates select="parameteritem" />
|
|
||||||
</variablelist>
|
|
||||||
</xsl:if>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<xsl:template match="ref">
|
|
||||||
<link linkend="{$which}-{@refid}"><xsl:value-of select="." /></link>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<xsl:template match="simplesect[@kind='return']">
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Returns:</term>
|
|
||||||
<listitem>
|
|
||||||
<simpara><xsl:apply-templates /></simpara>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<xsl:template match="simplesect[@kind='see']">
|
|
||||||
See also: <xsl:apply-templates />
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<xsl:template match="simplesect[@kind='since']">
|
|
||||||
Since: <xsl:apply-templates />
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<xsl:template match="simplesect[@kind='note']">
|
|
||||||
<emphasis>Note: <xsl:apply-templates /></emphasis>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<xsl:template match="sp">
|
|
||||||
<xsl:text> </xsl:text>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<xsl:template match="programlisting">
|
|
||||||
<programlisting><xsl:apply-templates /></programlisting>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<xsl:template match="itemizedlist">
|
|
||||||
<itemizedlist><xsl:apply-templates select="listitem" /></itemizedlist>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<xsl:template match="listitem">
|
|
||||||
<listitem><simpara><xsl:apply-templates /></simpara></listitem>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<!-- stops cross-references in the section titles -->
|
|
||||||
<xsl:template match="briefdescription">
|
|
||||||
<xsl:value-of select="." />
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<!-- this opens a para for each detaileddescription/para. I could not find a
|
|
||||||
way to extract the right text for the description from the
|
|
||||||
source otherwise. Downside: we can't use para for return value, "see
|
|
||||||
also", etc. because they're already inside a para. So they're lists.
|
|
||||||
|
|
||||||
It also means we don't control the order of when something is added to
|
|
||||||
the output, it matches the input file
|
|
||||||
-->
|
|
||||||
<xsl:template match="detaileddescription/para">
|
|
||||||
<para><xsl:apply-templates /></para>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<xsl:template match="detaileddescription">
|
|
||||||
<xsl:apply-templates select="para" />
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<xsl:template match="sectiondef">
|
|
||||||
<xsl:variable name="docitems"
|
|
||||||
select="memberdef[
|
|
||||||
(@kind = 'function' and
|
|
||||||
(@static = 'no' or
|
|
||||||
substring(location/@bodyfile,
|
|
||||||
string-length(location/@bodyfile) - 1,
|
|
||||||
1000) = '.h'
|
|
||||||
)
|
|
||||||
and @prot = 'public'
|
|
||||||
)
|
|
||||||
or
|
|
||||||
(@kind != 'function' and normalize-space(briefdescription) != '')
|
|
||||||
]" />
|
|
||||||
<xsl:if test="$docitems">
|
|
||||||
<variablelist>
|
|
||||||
<!-- Apply memberdef template -->
|
|
||||||
<xsl:apply-templates select="$docitems" />
|
|
||||||
</variablelist>
|
|
||||||
</xsl:if>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<!-- methods -->
|
|
||||||
<xsl:template match="memberdef" >
|
|
||||||
<varlistentry id="{$which}-{@id}">
|
|
||||||
<term>
|
|
||||||
<xsl:value-of select="name"/>
|
|
||||||
<xsl:if test="normalize-space(briefdescription) != ''">
|
|
||||||
- <xsl:apply-templates select="briefdescription" />
|
|
||||||
</xsl:if>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<synopsis>
|
|
||||||
<xsl:apply-templates select="definition"/><xsl:apply-templates select="argsstring"/>
|
|
||||||
</synopsis>
|
|
||||||
<xsl:apply-templates select="detaileddescription" />
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<!-- classes -->
|
|
||||||
<xsl:template match="compounddef" >
|
|
||||||
<section id="{$which}-{@id}">
|
|
||||||
<title>
|
|
||||||
<xsl:value-of select="compoundname" />
|
|
||||||
<xsl:if test="normalize-space(briefdescription) != ''">
|
|
||||||
- <xsl:apply-templates select="briefdescription" />
|
|
||||||
</xsl:if>
|
|
||||||
</title>
|
|
||||||
<xsl:choose>
|
|
||||||
<xsl:when test="normalize-space(detaileddescription) != ''">
|
|
||||||
<xsl:apply-templates select="detaileddescription" />
|
|
||||||
</xsl:when>
|
|
||||||
<xsl:otherwise>
|
|
||||||
<para />
|
|
||||||
</xsl:otherwise>
|
|
||||||
</xsl:choose>
|
|
||||||
<xsl:apply-templates select="sectiondef" />
|
|
||||||
</section>
|
|
||||||
</xsl:template>
|
|
||||||
</xsl:stylesheet>
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
||||||
<xsl:param name="basedir"/>
|
|
||||||
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
|
|
||||||
<!-- -->
|
|
||||||
<!-- Template for the root so we can add a DOCTYPE -->
|
|
||||||
<xsl:template match="/">
|
|
||||||
<xsl:text disable-output-escaping="yes"><![CDATA[<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
||||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
|
||||||
%BOOK_ENTITIES;
|
|
||||||
]>
|
|
||||||
]]></xsl:text>
|
|
||||||
<xsl:apply-templates select="@*|node()"/>
|
|
||||||
</xsl:template>
|
|
||||||
<!-- -->
|
|
||||||
<xsl:template match="@*|node()">
|
|
||||||
<xsl:copy>
|
|
||||||
<xsl:apply-templates select="@*|node()"/>
|
|
||||||
</xsl:copy>
|
|
||||||
</xsl:template>
|
|
||||||
<!-- -->
|
|
||||||
<!-- suppress existing image map areas -->
|
|
||||||
<xsl:template match="area"/>
|
|
||||||
<!-- -->
|
|
||||||
<xsl:template match="areaspec[area][name(..)='imageobjectco']">
|
|
||||||
<xsl:element name="areaspec">
|
|
||||||
<xsl:apply-templates select="@*"/>
|
|
||||||
<xsl:text>
</xsl:text>
|
|
||||||
<xsl:variable name="pngfile" select="../imageobject/imagedata/@fileref"/>
|
|
||||||
<xsl:variable name="mapfile" select="concat(substring($pngfile, 1, string-length($pngfile)-3), 'map')"/>
|
|
||||||
<xsl:variable name="maproot" select="document(concat($basedir, '/', $mapfile))"/>
|
|
||||||
<!-- -->
|
|
||||||
<!-- now emit the needed areas -->
|
|
||||||
<xsl:for-each select="area">
|
|
||||||
<xsl:variable name="anchor" select="."/>
|
|
||||||
<xsl:variable name="other" select="($maproot)//area[@href=($anchor)/@x_steal]"/>
|
|
||||||
<xsl:choose>
|
|
||||||
<xsl:when test="$other">
|
|
||||||
<xsl:text>	 </xsl:text>
|
|
||||||
<xsl:element name="area">
|
|
||||||
<xsl:attribute name="id">
|
|
||||||
<xsl:value-of select="@id"/>
|
|
||||||
</xsl:attribute>
|
|
||||||
<xsl:attribute name="linkends">
|
|
||||||
<xsl:value-of select="@linkends"/>
|
|
||||||
</xsl:attribute>
|
|
||||||
<xsl:attribute name="coords">
|
|
||||||
<xsl:value-of select="($other)/@coords"/>
|
|
||||||
</xsl:attribute>
|
|
||||||
</xsl:element>
|
|
||||||
</xsl:when>
|
|
||||||
<xsl:otherwise>
|
|
||||||
<xsl:text>	 </xsl:text>
|
|
||||||
<xsl:comment>
|
|
||||||
<xsl:value-of select="concat('Warning: unable to locate area tagged ', ($anchor)/@x_steal)"/>
|
|
||||||
</xsl:comment>
|
|
||||||
</xsl:otherwise>
|
|
||||||
</xsl:choose>
|
|
||||||
<xsl:text>
</xsl:text>
|
|
||||||
</xsl:for-each>
|
|
||||||
<!-- -->
|
|
||||||
<xsl:text>	 </xsl:text>
|
|
||||||
</xsl:element>
|
|
||||||
</xsl:template>
|
|
||||||
</xsl:stylesheet>
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
<?xml version="1.0" ?>
|
|
||||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
||||||
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
|
|
||||||
|
|
||||||
<xsl:template match="/">
|
|
||||||
<!-- insert docbook's DOCTYPE blurb -->
|
|
||||||
<xsl:text disable-output-escaping = "yes"><![CDATA[
|
|
||||||
<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
||||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
|
||||||
%BOOK_ENTITIES;
|
|
||||||
]>
|
|
||||||
]]></xsl:text>
|
|
||||||
|
|
||||||
<section id="sect-Protocol-Interfaces">
|
|
||||||
<title>Interfaces</title>
|
|
||||||
<para>
|
|
||||||
The protocol includes several interfaces which are used for
|
|
||||||
interacting with the server. Each interface provides requests,
|
|
||||||
events, and errors (which are really just special events) as described
|
|
||||||
above. Specific compositor implementations may have their own
|
|
||||||
interfaces provided as extensions, but there are several which are
|
|
||||||
always expected to be present.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Core interfaces:
|
|
||||||
<variablelist>
|
|
||||||
<xsl:apply-templates select="protocol/interface" />
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<!-- Interfaces summary -->
|
|
||||||
<xsl:template match="interface" >
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
<link linkend="protocol-spec-{@name}">
|
|
||||||
<xsl:value-of select="@name" />
|
|
||||||
</link>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<xsl:value-of select="description/@summary" />
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
</xsl:stylesheet>
|
|
||||||
<!-- vim: set expandtab shiftwidth=2: -->
|
|
||||||
|
|
@ -1,225 +0,0 @@
|
||||||
<?xml version="1.0" ?>
|
|
||||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
||||||
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
|
|
||||||
|
|
||||||
<xsl:template match="/">
|
|
||||||
<!-- insert docbook's DOCTYPE blurb -->
|
|
||||||
<xsl:text disable-output-escaping = "yes"><![CDATA[
|
|
||||||
<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
||||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
|
||||||
%BOOK_ENTITIES;
|
|
||||||
]>
|
|
||||||
]]></xsl:text>
|
|
||||||
|
|
||||||
<appendix id="appe-Wayland-Protocol">
|
|
||||||
<title>Wayland Protocol Specification</title>
|
|
||||||
<xsl:apply-templates select="protocol/copyright" />
|
|
||||||
|
|
||||||
<xsl:apply-templates select="protocol/interface" />
|
|
||||||
</appendix>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<!-- Break text blocks separated by two new lines into paragraphs -->
|
|
||||||
<xsl:template name="break">
|
|
||||||
<xsl:param name="text" />
|
|
||||||
<xsl:param name="linebreak" select="' '" />
|
|
||||||
<xsl:choose>
|
|
||||||
<xsl:when test="contains($text,$linebreak)">
|
|
||||||
<para>
|
|
||||||
<xsl:value-of select="substring-before($text,$linebreak)" />
|
|
||||||
</para>
|
|
||||||
<xsl:call-template name="break">
|
|
||||||
<xsl:with-param name="text" select="substring-after($text,$linebreak)" />
|
|
||||||
</xsl:call-template>
|
|
||||||
</xsl:when>
|
|
||||||
<xsl:otherwise>
|
|
||||||
<para><xsl:value-of select="$text" /></para>
|
|
||||||
</xsl:otherwise>
|
|
||||||
</xsl:choose>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<!-- Copyright blurb -->
|
|
||||||
<xsl:template match="copyright">
|
|
||||||
<para>
|
|
||||||
<literallayout>
|
|
||||||
<xsl:value-of select="." disable-output-escaping="yes"/>
|
|
||||||
</literallayout>
|
|
||||||
</para>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<!-- Interface descriptions -->
|
|
||||||
<xsl:template match="interface" >
|
|
||||||
<section id="protocol-spec-{@name}">
|
|
||||||
<title>
|
|
||||||
<xsl:value-of select="@name" />
|
|
||||||
<!-- only show summary if it exists -->
|
|
||||||
<xsl:if test="description/@summary">
|
|
||||||
- <xsl:value-of select="description/@summary" />
|
|
||||||
</xsl:if>
|
|
||||||
</title>
|
|
||||||
<xsl:call-template name="break">
|
|
||||||
<xsl:with-param name="text" select="description" />
|
|
||||||
</xsl:call-template>
|
|
||||||
<xsl:if test="request">
|
|
||||||
<section>
|
|
||||||
<title>Requests provided by <xsl:value-of select="@name" /></title>
|
|
||||||
<xsl:apply-templates select="request" />
|
|
||||||
</section>
|
|
||||||
</xsl:if>
|
|
||||||
<xsl:if test="event">
|
|
||||||
<section>
|
|
||||||
<title>Events provided by <xsl:value-of select="@name" /></title>
|
|
||||||
<xsl:apply-templates select="event" />
|
|
||||||
</section>
|
|
||||||
</xsl:if>
|
|
||||||
<xsl:if test="enum">
|
|
||||||
<section>
|
|
||||||
<title>Enums provided by <xsl:value-of select="@name" /></title>
|
|
||||||
<xsl:apply-templates select="enum" />
|
|
||||||
</section>
|
|
||||||
</xsl:if>
|
|
||||||
</section>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<!-- table contents for enum values -->
|
|
||||||
<xsl:template match="entry">
|
|
||||||
<varlistentry>
|
|
||||||
<term><xsl:value-of select="@name"/></term>
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<xsl:value-of select="@value"/>
|
|
||||||
<xsl:if test="@summary" >
|
|
||||||
- <xsl:value-of select="@summary"/>
|
|
||||||
</xsl:if>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<!-- table contents for request/event arguments -->
|
|
||||||
<xsl:template match="arg">
|
|
||||||
<varlistentry>
|
|
||||||
<term><xsl:value-of select="@name"/></term>
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<xsl:value-of select="@type"/>
|
|
||||||
<xsl:if test="@summary" >
|
|
||||||
- <xsl:value-of select="@summary"/>
|
|
||||||
</xsl:if>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<!-- id arguments -->
|
|
||||||
<xsl:template match="arg[@type='object' and @interface]">
|
|
||||||
<varlistentry>
|
|
||||||
<term><xsl:value-of select="@name"/></term>
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<link linkend="protocol-spec-{@interface}">
|
|
||||||
<xsl:value-of select="@interface"/>
|
|
||||||
</link>
|
|
||||||
<xsl:if test="@summary" >
|
|
||||||
- <xsl:value-of select="@summary"/>
|
|
||||||
</xsl:if>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<!-- new_id arguments -->
|
|
||||||
<xsl:template match="arg[@type='new_id' and @interface]">
|
|
||||||
<varlistentry>
|
|
||||||
<term><xsl:value-of select="@name"/></term>
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
id for the new
|
|
||||||
<link linkend="protocol-spec-{@interface}">
|
|
||||||
<xsl:value-of select="@interface"/>
|
|
||||||
</link>
|
|
||||||
<xsl:if test="@summary" >
|
|
||||||
- <xsl:value-of select="@summary"/>
|
|
||||||
</xsl:if>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<!-- enum and bitfield arguments -->
|
|
||||||
<xsl:template match="arg[@enum]">
|
|
||||||
<varlistentry>
|
|
||||||
<term><xsl:value-of select="@name"/></term>
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<xsl:choose>
|
|
||||||
<xsl:when test="contains(@enum, '.')">
|
|
||||||
<link linkend="protocol-spec-{substring-before(@enum, '.')}-enum-{substring-after(@enum, '.')}">
|
|
||||||
<xsl:value-of select="substring-before(@enum, '.')"/>
|
|
||||||
<xsl:text>::</xsl:text>
|
|
||||||
<xsl:value-of select="substring-after(@enum, '.')"/>
|
|
||||||
</link>
|
|
||||||
</xsl:when>
|
|
||||||
<xsl:otherwise>
|
|
||||||
<link linkend="protocol-spec-{../../@name}-enum-{@enum}">
|
|
||||||
<xsl:value-of select="../../@name"/>
|
|
||||||
<xsl:text>::</xsl:text>
|
|
||||||
<xsl:value-of select="@enum"/>
|
|
||||||
</link>
|
|
||||||
</xsl:otherwise>
|
|
||||||
</xsl:choose>
|
|
||||||
(<xsl:value-of select="@type"/>)
|
|
||||||
<xsl:if test="@summary" >
|
|
||||||
- <xsl:value-of select="@summary"/>
|
|
||||||
</xsl:if>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<!-- Request/event list -->
|
|
||||||
<xsl:template match="request|event">
|
|
||||||
<section id="protocol-spec-{../@name}-{name()}-{@name}">
|
|
||||||
<title>
|
|
||||||
<xsl:value-of select="../@name"/>::<xsl:value-of select="@name" />
|
|
||||||
<xsl:if test="description/@summary">
|
|
||||||
- <xsl:value-of select="description/@summary" />
|
|
||||||
</xsl:if>
|
|
||||||
</title>
|
|
||||||
<xsl:if test="arg">
|
|
||||||
<para>
|
|
||||||
<variablelist>
|
|
||||||
<xsl:apply-templates select="arg"/>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
</xsl:if>
|
|
||||||
<xsl:call-template name="break">
|
|
||||||
<xsl:with-param name="text" select="description" />
|
|
||||||
</xsl:call-template>
|
|
||||||
</section>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
<!-- Enumeration -->
|
|
||||||
<xsl:template match="enum">
|
|
||||||
<section id="protocol-spec-{../@name}-enum-{@name}">
|
|
||||||
<title>
|
|
||||||
<xsl:value-of select="../@name"/>::<xsl:value-of select="@name" />
|
|
||||||
<xsl:if test="@bitfield">
|
|
||||||
- bitfield
|
|
||||||
</xsl:if>
|
|
||||||
<xsl:if test="description/@summary">
|
|
||||||
- <xsl:value-of select="description/@summary" />
|
|
||||||
</xsl:if>
|
|
||||||
</title>
|
|
||||||
<xsl:call-template name="break">
|
|
||||||
<xsl:with-param name="text" select="description" />
|
|
||||||
</xsl:call-template>
|
|
||||||
<variablelist>
|
|
||||||
<xsl:apply-templates select="entry"/>
|
|
||||||
</variablelist>
|
|
||||||
</section>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
</xsl:stylesheet>
|
|
||||||
|
|
||||||
<!-- vim: set expandtab shiftwidth=2: -->
|
|
||||||