Working with Weston on Torizon OS
Introductionβ
Linux systems with a graphical output need a graphics stack. There are two famous ones: X, also known as X11 or X.Org, and Wayland which aims at replacing X.
Wayland is a protocol and it requires a compositor implementation. The reference implementation, widely used, is the Weston compositor.
From our software releases 5.x onward, Toradex only supports Wayland/Weston. For Torizon, Toradex provides a Weston container, which is configured from its command line parameters, and a configuration file named weston.ini
.
This article explains how to customize the default configuration. It does not replace the Wayland documentation.
This article complies with the Typographic Conventions for the Toradex Documentation.
Prerequisitesβ
To have a better understanding of this article, the following prerequisites are recommended:
- A computer on module with Torizon OS installed.
- The display needs to be set up according to Setting up Displays with Torizon.
- Reading of Debian With Weston Wayland Compositor article.
- Acknowledge that you may need to browse the Wayland documentation, as this article does not replace it.
Debian With Weston Wayland Compositorβ
Weston is the reference implementation of the Wayland display server protocol, essentially the piece of software that makes sure that graphical application can be drawn alongside each other, superimposed and organized in windows.
As with any other official Torizon OS Docker Image, the Weston container is based on the stable release of Debian. To pull the container and start it on the module, choose your hardware from the tabs below and follow the instructions given:
After sending the command above, Weston should start on your display and you are ready to start your Wayland applications.
If the container image is not preinstalled, Docker will download it from Docker Hub and store it on the module -- this will require an internet connection on the device and may take a few minutes. It will start Weston (HDMI on Apalis SoMs, parallel RGB on Colibri SoMs, MIPI-DSI on Verdin SoMs). The container will be started in the background and you can query Weston's logs for debugging by using the Docker logs subcommand:
# docker logs weston
Most of the arguments in this command line make sure that the container can access the necessary hardware (display controller, GPU and input devices) and be notified about hardware changes (through Torizon OS's udev daemon).
Weston creates a Unix socket file so graphical client applications can communicate with it (typically in the /tmp/1000-runtime-dir
directory).
By bind mounting /tmp
into a second container, a Wayland client application (for example, a Qt application) can access the Wayland compositor despite being in separate containers. The Wayland client application will talk to Weston through the Unix socket file to coordinate drawing the window to the output screen.
As an example, let's start a second container that reuses the same image, but brings up an application on top of Weston. Select your module from the tabs below and follow the instructions:
After sending the command above, Weston should start on your display with the Wayland Terminal opened.
Weston with Composeβ
This section focuses on an example using Weston with Docker Compose.
To have a better understanding of this article, the following prerequisites are recommended:
- A Computer on Module with Torizon installed.
- (optional) Basic understanding of Docker and
docker run
command options. - (optional) Reading of Torizon OS Overview article.
- Clone the Debian Container samples from the Torizon Samples Repository with the following commands:
$ cd ~
$ git clone --branch=bookworm https://github.com/toradex/torizon-samples.git
$ cd torizon-samples/debian-container
On the board, make sure that all containers are stopped:
# docker stop $(docker ps -a -q)
Select your hardware in the box below:
By starting the demonstration using this docker-compose file, you are accepting the NXP's End-User License Agreement (EULA).
Then you can start the demo with a single command:
# docker-compose -f <your-docker-compose-file> up
With the above command, you directly attach to the containers you are about to start. To start in detached-mode, you can append -d
to the above command.
Configuration optionsβ
Weston uses a configuration file named weston.ini
for its setup.
The Toradex container has a Weston startup script. While executing docker run
, you can pass a --developer
switch that allows either of the following files to be passed to Weston:
/etc/xdg/weston/weston.ini
: used by default, if the--developer
switch is not present./etc/xdg/weston-dev/weston.ini
: used when you start the Weston container with the--developer
switch.
An example of how to use the switch is available in the article Debian Containers for Torizon.
Before proceeding, create your own weston.ini
, where you will store your custom configuration.
The weston.ini
file is sensitive to trailing whitespaces after configuration names and options. If a configuration is not applied correctly, check if there are whitespaces between text and line breaks.
How to apply configuration optionsβ
There are two options to apply changes:
- Bind mount a custom configuration file.
- Extend the Torizon Weston container with the custom configuration file.
For evaluation and prototyping you can bind mount the weston.ini
file. This will overwrite the existing configuration weston.ini
file. To do it, add a volume flag to the docker run command:
-v <path_to_directory_containing_weston.ini_file>:/etc/xdg/weston/
For development and production build your own Weston Docker image overriding the weston.ini
file. Here is an example:
Alternatively, rebuild our weston image replacing the weston.ini
configuration file.
Alternatively, rebuild our weston image replacing the weston.ini
configuration file.
You are encouraged to read the following articles for tips on how to do it:
- Debian Containers for Torizon
- Modifying Torizon OS Debian Based Container Images
- Torizon OS Containers Tags and Versioning
Customizationβ
In this section, customization that is often used by our customers is presented to you.
Note that if you start with the pre-defined weston.ini
file, many of the settings listed here will be present but commented out. Please make sure to uncomment all matching lines to ensure the functionality you requested is available.
Screen rotationβ
The screen can be rotated or flipped by adding the following to the weston.ini
file:
[output]
name=HDMI-A-1
transform=rotate-90
The name
value can be found by executing weston-info
from inside the running Weston container.
Additional transform values can be found in the weston.ini man page.
Switching between virtual terminalsβ
Switching between virtual terminals can be enabled by changing these lines in weston.ini
file:
[keyboard]
vt-switching=true
Press Ctrl+Alt+F1
till F6
key combinations to switch between virtual terminals. To come back to the graphical session, press Ctrl+Alt+F7
.
touch2pointerβ
With Wayland, it is possible to transfer touch events from the Wayland server to the client application. However, some applications are not aware of these events (e.g. QtWidgets). Therefore, they will not react to touch events and it is not possible to click buttons, etc.
touch2pointer
is an application created by Toradex that operates directly on top of the touchscreen's evdev interface and creates a virtual pointer device. This makes it possible to use such applications. However, you will lose some of the capability of touchscreens (like multitouch).
How to use:
Calibrate the touchscreen with Weston touch calibrator if it is a resistive touch. Make sure you set the LIBINPUT_CALIBRATION_MATRIX
variable to the calibration matrix.
Create a udev rule that makes Weston/libinput ignore the touch device ENV{LIBINPUT_IGNORE_DEVICE}="1"
. For example:
SUBSYSTEM=="input", KERNEL=="event0", ENV{ID_INPUT_TOUCHSCREEN}=="1", ENV{LIBINPUT_CALIBRATION_MATRIX}="1.034599 -0.008149 -0.013808 0.026801 -1.130055 1.058165"
SUBSYSTEM=="input", KERNEL=="event0", ENV{LIBINPUT_IGNORE_DEVICE}="1"
Start touch2pointer
with touchscreen
as an argument.
Changing the mouse cursorβ
This can be useful in touch displays that use the mouse as input, as it is desirable to make the cursor transparent.
You can change the mouse cursor by adding a custom X11 cursor named left_ptr in an icon theme folder like for instance /usr/share/icons/hicolor/cursors/ and enabling it in weston.ini
:
[shell]
locking=false
cursor-theme=hicolor
cursor-size=32
A transparent cursor can be found on this GitHub repo. This has been tested and confirmed to work in the Weston container.
Applying the custom cursor on Chromiumβ
The kiosk container found in Web Browser / Kiosk Mode with Torizon OS with Chromium uses its own mouse cursor by default. This can be overwritten by putting inside the container the custom left_ptr in /usr/share/icons/Adwaita/cursors/.
kiosk-shellβ
With version 9.0 Weston introduced the kiosk-shell.
Weston uses the desktop-shell by default. To use kiosk-shell, add the following to the core section in weston.ini
file:
[core]
shell=kiosk-shell.so
kiosk-shell doesn't support the background-image
field of [shell]
section in weston.ini
. After enabling kiosk-shell, the image will not be displayed even with a valid path in the background-image
field. background-color
will still work.
Multi-displayβ
This section does not explain how to enable displays or change their resolution. You might need to do it before being able to use a multi-display setup. Please refer to Setting up Displays with Torizon for more details.
Weston container extends its surface to all displays connected to the same DRM interface and display controller. Currently, Weston is unable to manage outputs, connected to multiple DRM interfaces. But it's possible to launch two instances of Weston, each on its own DRM interface. Due to this limitation, some multi-display combinations on i.MX8X modules donβt work.
To check whether displays are on the same DRM interface:
# ls /sys/class/drm/*/status
For reference, some output examples are provided:
# Verdin iMX8M Plus | native HDMI + DSI to HDMI bridge both on the same DRM interface
/sys/class/drm/card0-HDMI-A-1/status /sys/class/drm/card0-HDMI-A-2/status
# Verdin iMX8M Mini and Verdin AM62 | DSI to HDMI bridge
/sys/class/drm/card0-HDMI-A-1/status
# Colibri iMX8X, Colibri iMX7, Colibri iMX6 | parallel RGB
/sys/class/drm/card1-DPI-1/status
# Colibri iMX6 with additional HDMI enabled | parallel RGB + HDMI both on the same DRM interface
/sys/class/drm/card1-DPI-1/status /sys/class/drm/card1-HDMI-A-1/status
# Colibri iMX8X with additional DSI to HDMI enabled | parallel RGB + DSI to HDMI bridge on different DRM interfaces
/sys/class/drm/card0-DPI-1/status /sys/class/drm/card1-HDMI-A-1/status
Wayland client application
When starting another container with your Wayland client application, the window will be drawn on top of the Wayland compositor (Weston). On multi-display setup, the Wayland client application will be by default displayed on the top left output or depending on the position of the mouse cursor.
Unless explicitly stated otherwise.
Multi-display Examplesβ
In the next sections, you will get details on how to run a multi-display setup. To help you get started, use the examples from the Torizon Samples - Multi-display:
Launching two instances of Weston - two DRM interfacesβ
On modules with two DRM interfaces (i.MX8X), it's possible to launch two instances of Weston, each on its own DRM interface.
To launch two instances of Weston, each output should be associated with a seat name. Therefore we set ID_SEAT
property of the device. There are two ways of doing it, either by running the following for example:
sudo loginctl attach seat1 /sys/class/drm/card1
Or by creating an udev rule for example. This method allows you to Capture Changes in the Configuration of a Board on Torizon OS at a later moment, so you can prepare you custom image with the configuration applied:
# cat /etc/udev/rules.d/72-seat-drm-platform-display-subsystem.rules
TAG=="seat", ENV{ID_FOR_SEAT}=="drm-platform-display-subsystem", ENV{ID_SEAT}="seat1"
After that, a reboot is required to load the udev rule.
Launching instance of Weston on the seat1 (DRM card1):
docker run -e ACCEPT_FSL_EULA=1 -d --rm --name=weston --net=host --cap-add CAP_SYS_TTY_CONFIG \
-v /dev:/dev -v /tmp:/tmp -v /run/udev/:/run/udev/ \
--device-cgroup-rule='c 4:* rmw' --device-cgroup-rule='c 13:* rmw' \
--device-cgroup-rule='c 199:* rmw' --device-cgroup-rule='c 226:* rmw' \
torizon/weston-vivante:$CT_TAG_WESTON_VIVANTE --developer \
--tty=/dev/tty7 -- --seat=seat1
Launching instance of Weston on seat0 (DRM card0). Since only one card is OpenGL capable, software rendering (--use-pixman) is used:
docker run -e ACCEPT_FSL_EULA=1 -d --rm --name=weston2 --net=host --cap-add CAP_SYS_TTY_CONFIG \
-v /dev:/dev -v /tmp:/tmp -v /run/udev/:/run/udev/ \
--device-cgroup-rule='c 4:* rmw' --device-cgroup-rule='c 13:* rmw' \
--device-cgroup-rule='c 199:* rmw' --device-cgroup-rule='c 226:* rmw' \
torizon/weston-vivante:$CT_TAG_WESTON_VIVANTE --developer \
--tty=/dev/tty8 -- --seat=seat0 --use-pixman
Start weston-terminal
on card0:
docker run -e ACCEPT_FSL_EULA=1 -d --rm --name=wayland-app2 -e WAYLAND_DISPLAY=wayland-1 \
-v /dev/dri:/dev/dri -v /dev/galcore:/dev/galcore -v /tmp:/tmp \
--device-cgroup-rule='c 199:* rmw' --device-cgroup-rule='c 226:* rmw' \
torizon/weston-vivante:$CT_TAG_WESTON_VIVANTE weston-terminal
Beware that multiple tty sessions can not be "active" simultaneously. So switching to the virtual terminal of card1 (tty7) is required.
sudo chvt 7
Start weston-simple-egl
on card1:
docker run -e ACCEPT_FSL_EULA=1 -d --rm --name=wayland-app \
-v /dev/dri:/dev/dri -v /dev/galcore:/dev/galcore -v /tmp:/tmp \
--device-cgroup-rule='c 199:* rmw' --device-cgroup-rule='c 226:* rmw' \
torizon/weston-vivante:$CT_TAG_WESTON_VIVANTE weston-simple-egl
Redirecting the output - one DRM interfaceβ
If a single instance Weston using a single DRM interface is running on multiple displays, having different outputs is possible by using kiosk-shell and app-ids
.
To do this, the app id
of the Wayland application needs to be found out. The application defines its ID using the set_app_id
request. The environment WAYLAND_DEBUG must be used to see what your application is setting.
For example, run the following command inside a container with your application:
WAYLAND_DEBUG=1 <MY_APP_NAME> 2>&1 | grep app
And the output would be something like that:
[1292031.851] -> xdg_toplevel@26.set_app_id("my-app-name")
In that case, my-app-name
would be the app-id
.
Then add for example to the weston.ini
file the following:
[output]
name=DPI-1
app-ids=my-app-name
[output]
name=HDMI-A-1
app-ids=my-app-name-2
That would display each application on it's own output.
Disabling a specific outputβ
Showing the output on a particular display can also be achieved by disabling the specific display in the weston.ini
file:
[output]
name=HDMI-A-1
mode=off
Mirroringβ
To clone the output from one display to another, change the weston.ini file:
[output]
name=HDMI-A-1
same-as=HDMI-A-2
Weston's clone mode is currently limited to sharing the display timings between all displays.
Fixed Display Resolutionβ
Weston supports setting the resolution in the configuration file. Check How to Apply Configuration Options, in our Weston configuration files, weston.ini
and weston-dev.ini
we add comments to illustrate how to do it.
For more details, refer to the weston-drm documentation.
Running graphical application without a display connectedβ
Graphical applications in some cases do not run on a board that does not have a display connected. But it can be useful for example to validate graphical apps on CI pipelines, or remote access a board while sharing it with others during a development phase.
By forcing the connector state it is possible to run and access a GUI without a display connected. Depending on your board, force it as a root user with a command similar to:
echo on > /sys/class/drm/card1-HDMI-A-1/status
Screencast Recording and Screenshot Capturingβ
Weston has a built-in screencast recording which can be started and stopped by pressing the <mod-key> + r
combination. To check the modifier-key value, just search for binding-modifier in weston.ini
file.
## grep binding-modifier /etc/xdg/weston/weston.ini
binding-modifier=super
If weston.ini
does not have the definition of a modifier key, you can define it in the file as binding-modifier=super
, for example.
Screencasts are saved to the file capture.wcap
in the working directory of Weston. Since the WCAP format is specific to Weston, it's necessary to convert the capture to YUV pixel format (.y4m
). The pixel file is saved to the file capture.y4m
with the following command:
## wcap-decode --yuv4mpeg2 capture.wcap > capture.y4m
To play the recorded screencast, you need to convert the YUV pixel file (capture.y4m
) to a format that a media player understands.
To capture a screenshot you can press <mod-key> + s
combination. The captured picture is saved in PNG format and stored in the working directory.
Next Steps / Additional Resourcesβ
Additional configuration options can be found in the weston.ini man page and in the arch linux wiki.
It may also be useful to consult the following articles: