Merge branch 'jorth/mdbook' into 'main'
Convert docbook to mdbook Closes #584 See merge request wayland/wayland!516
|
|
@ -78,10 +78,10 @@ workflow:
|
|||
variables:
|
||||
BUILD_OS: debian
|
||||
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
|
||||
# base image
|
||||
FDO_DISTRIBUTION_TAG: "2025-12-27.0"
|
||||
FDO_DISTRIBUTION_TAG: "2026-01-31.0"
|
||||
|
||||
.debian-x86_64:
|
||||
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
|
||||
doxygen_templates = {
|
||||
'xml': [
|
||||
'GENERATE_XML=YES\n',
|
||||
'XML_OUTPUT={format}/{section}\n',
|
||||
'INPUT= {files}\n',
|
||||
],
|
||||
'html': [
|
||||
'GENERATE_HTML=YES\n',
|
||||
'HTML_OUTPUT={format}/{section}\n',
|
||||
|
|
@ -60,9 +55,9 @@ parser.add_argument('--section',
|
|||
metavar='NAME',
|
||||
default='Client')
|
||||
parser.add_argument('--output-format',
|
||||
help='The output format: xml, html, man',
|
||||
help='The output format: html, man',
|
||||
metavar='FORMAT',
|
||||
default='xml')
|
||||
default='html')
|
||||
parser.add_argument('--stamp',
|
||||
help='Stamp file to output',
|
||||
metavar='STAMP_FILE',
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@
|
|||
* - <a href="../Cursor/index.html">Cursor helper library API</a>
|
||||
*
|
||||
* Further documentation about the architecture and principles of Wayland is
|
||||
* available in the
|
||||
* <a href="https://wayland.freedesktop.org/docs/html">Wayland Book</a>
|
||||
* available on the
|
||||
* <a href="https://wayland.freedesktop.org/docs">website</a>.
|
||||
*
|
||||
* @section ifaces Interfaces
|
||||
* For the list of available interfaces, please see the
|
||||
|
|
|
|||
|
|
@ -48,8 +48,6 @@ extra_cursor_files = [
|
|||
|
||||
gen_doxygen = find_program('gen-doxygen.py')
|
||||
|
||||
subdir('xml')
|
||||
|
||||
formats = {
|
||||
'html': {
|
||||
'Client': shared_files + client_files + extra_client_files,
|
||||
|
|
@ -58,6 +56,8 @@ formats = {
|
|||
},
|
||||
}
|
||||
|
||||
html_targets = []
|
||||
|
||||
foreach f_name, sections: formats
|
||||
foreach s_name, s_files: sections
|
||||
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
|
||||
# dummy 'stamp' file
|
||||
stamp = join_paths(meson.current_build_dir(), '@0@.stamp'.format(t_name))
|
||||
custom_target(
|
||||
html_targets += custom_target(
|
||||
t_name,
|
||||
command: [
|
||||
gen_doxygen,
|
||||
|
|
@ -85,6 +85,16 @@ foreach f_name, sections: formats
|
|||
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
|
||||
stamp = join_paths(meson.current_build_dir(), 'man3.stamp')
|
||||
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')
|
||||
endif
|
||||
|
||||
dot = find_program('dot')
|
||||
doxygen = find_program('doxygen')
|
||||
xsltproc = find_program('xsltproc')
|
||||
xmlto = find_program('xmlto')
|
||||
mdbook = find_program('mdbook')
|
||||
|
||||
cmd = run_command(doxygen, '--version', check: true)
|
||||
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))
|
||||
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(
|
||||
get_option('prefix'),
|
||||
get_option('datadir'),
|
||||
|
|
@ -38,4 +23,4 @@ publican_install_prefix = join_paths(
|
|||
publican_html_dir = 'html'
|
||||
|
||||
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: -->
|
||||