Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,21 @@ FROM debian:13.2-slim
ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update -qq && \
# xargs apt-get install -y --no-install-recommends < /etc/DEPENDENCIES && \
apt-get install -y --no-install-recommends \
weston=14.* \
libgl1-mesa-dri=25.* \
dbus \
gettext-base \
libgl1-mesa-dri=25.* \
libinput10 \
udev \
weston=14.* \
&& rm -rf /var/lib/apt/lists/*

# Setup Weston
RUN mkdir -p /etc/xdg/weston
COPY weston.ini /etc/xdg/weston/weston.ini
RUN mkdir -p /etc/weston/templates
COPY weston-templates/ /etc/weston/templates/
COPY weston-env-defaults.sh /etc/weston/weston-env-defaults.sh


COPY entry.sh /usr/bin/entry.sh
RUN chmod +x /usr/bin/entry.sh

Expand Down
41 changes: 30 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,34 @@ SOCKET="$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY"
while [ ! -e "$SOCKET" ]; do sleep 1; done
exec your-app
```
## Configuration

You can configure Weston sections and keys using the following environment variables:
| Variable | Options | Default | Description |
|---------------------------------|---------------------------------------|---------------|------------------------------------------------------------------------------------------------------------------------|
| `XDG_RUNTIME_DIR` | valid directory path | `/run/user/0` | Directory where the Wayland socket is created. |
| `SOCKET_NAME` | [String] (e.g., `wayland-0`, `wayland-1`) | `wayland-0` | Name of the Wayland socket |
| `WESTON_DEBUG` | true, false | `false` | Enable debug mode |
| `WESTON_INI_PATH` | Absolute path to a custom `weston.ini` file | - | When this variable is set and the file is present, Weston will be luanched directly using the provided file. Consequently any other `WESTON_INI_*` environment variables defined for the container will be ignored. |
| `WESTON_INI_CORE_SHELL` | `desktop`, `fullscreen`, `ivi`, `kiosk` | `kiosk` | Defines the shell plugin to load. kiosk confines the UI to a single full-screen surface, ideal for embedded use cases. |
| `WESTON_INI_CORE_IDLE_TIME` | [Integer] (seconds) | `0` | Time in seconds before the compositor enters an inactive mode and blanks the screen. 0 disables the idle timeout. |
| `WESTON_INI_CORE_REQUIRE_INPUT` | `true`, `false` | `false` | Dictates whether Weston requires an active input device to launch. false permits display-only deployments. |
| `WESTON_INI_SHELL_LOCKING` | `true`, `false` | `false` | Enables or disables screen locking functionality within the shell context. |
| `WESTON_INI_SHELL_PANEL_POSITION` | `top`, `bottom`, `left`, `right`, `none` | `none ` | Sets the location of the desktop panel. none disables the panel entirely, ensuring an unobstructed viewport. |

## Advanced Configuration

If the configurations provided does not suit your use case such as complex output management—such as requiring complex output management, multiple independent displays, or custom launchers—you must provide a custom `weston.ini` via a Dockerfile override.

The following snippets demonstrate how to override the configuration by inheriting from the base image and copying a custom `weston.ini`. You must also configure `WESTON_INI_PATH` to the absolute path of your `weston.ini` file for it to take effect.

**`./display/Dockerfile.template`**
```dockerfile
FROM bh.cr/balena_solutions/display-%%BALENA_ARCH%%

# Inject your custom Weston configuration
COPY weston.ini /etc/weston/weston.ini
```

## Examples

Expand Down Expand Up @@ -158,22 +186,12 @@ GPU acceleration is enabled through:
1. **DRM Backend** — Weston connects directly to the GPU via `/dev/dri`
2. **Mesa Graphics Libraries** — Provides OpenGL/Vulkan drivers



### Docker Privileges
The display container requires:
- `privileged: true` — DRM master access
- `/dev/dri` — GPU device access
- `io.balena.features.dbus: '1'` — D-Bus access (for stopping Plymouth)

## Environment Variables

| Variable | Default | Description |
|---|---|---|
| `XDG_RUNTIME_DIR` | `/run/user/0` | Directory where the Wayland socket is created |
| `SOCKET_NAME` | `wayland-0` | Name of the Wayland socket |
| `WESTON_DEBUG` | `false` | Enable debug mode and screenshooter support |

## Debugging

**Common issues:**
Expand All @@ -182,4 +200,5 @@ The display container requires:
- `[WARN] D-Bus socket not found` → Missing `io.balena.features.dbus: '1'` label on display service; Plymouth may still hold the DRM lock


[block-ref-url]:https://docs.balena.io/learn/develop/blocks/#getting-started-with-blocks
[block-ref-url]:https://docs.balena.io/learn/develop/blocks/#getting-started-with-blocks
[weston-ini-ref-url]:https://manpages.debian.org/trixie/weston/weston.ini.5.en.html
57 changes: 43 additions & 14 deletions entry.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
#!/bin/bash
set -e

# ==============================================================================
# ENVIRONMENT VARIABLES & DEFAULTS
# ==============================================================================
# Define the Runtime Directory
# Wayland requires this directory to communicate via sockets.
export XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR:-"/run/user/0"}
SOCKET_NAME=${SOCKET_NAME:-"wayland-0"}
WESTON_DEBUG=${WESTON_DEBUG:-"false"} # Default: Disabled
export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/0}"
SOCKET_NAME="${SOCKET_NAME:-wayland-0}"
WESTON_DEBUG="${WESTON_DEBUG:-false}"

# Load Weston configuration defaults from weston-env-defaults.sh
source /etc/weston/weston-env-defaults.sh

# ==============================================================================
# STOP PLYMOUTH (Release DRM Master)
Expand Down Expand Up @@ -36,7 +42,7 @@ cleanup () {
cleanup

# ==============================================================================
# UDEV
# UDEV
# ==============================================================================
setup_devtmpfs() {
newdev=/tmp/dev
Expand All @@ -50,35 +56,58 @@ setup_devtmpfs() {
mount --move "$newdev" /dev
ln -sf /dev/pts/ptmx /dev/ptmx
}

setup_devtmpfs

unshare --net /lib/systemd/systemd-udevd --daemon
udevadm control --reload-rules
udevadm trigger
udevadm settle


# Set up the directory structure and permissions
# It must be owned by the user (root in this case) and have 0700 permissions.
echo "Setting up XDG_RUNTIME_DIR at $XDG_RUNTIME_DIR..."
mkdir -p "$XDG_RUNTIME_DIR"
chmod 0700 "$XDG_RUNTIME_DIR"
ARGS="--idle-time=0 --socket=$SOCKET_NAME"

# ==============================================================================
# weson configuration
# ==============================================================================
if [ -n "$WESTON_INI_PATH" ] && [ -f "$WESTON_INI_PATH" ]; then
echo "INFO: WESTON_INI_PATH is set. Bypassing dynamic template generation."
echo "INFO: Using static configuration file at: $WESTON_INI_PATH"

CONFIG_FILE="$WESTON_INI_PATH"
else
echo "INFO: Generating dynamic weston.ini from template fragments..."

# Target configuration file
CONFIG_DIR="${XDG_CONFIG_HOME:-$XDG_RUNTIME_DIR}/weston"
mkdir -p "$CONFIG_DIR"
CONFIG_FILE="$CONFIG_DIR/weston.ini"

# Substitute env vars in .ini.template files via envsubst.
# We iterate explicitly to ensure a trailing newline separates each fragment,
# preventing syntax errors if a template file lacks an EOF newline.
for template in /etc/weston/templates/*.ini.template; do
cat "$template"
echo ""
done | envsubst > "$CONFIG_FILE"
fi

# ==============================================================================
# LAUNCH WESTON
# ==============================================================================
ARGS="--socket=$SOCKET_NAME --config=$CONFIG_FILE"

# Conditionally enable Debug Mode and Export Version
if [ "$WESTON_DEBUG" == "true" ]; then
echo "[INFO] Enabling Weston Debug Mode (Screenshooter authorized)"
echo "[INFO] Enabling Weston Debug Mode"
ARGS="$ARGS --debug"

# Export version ONLY if debug is on
echo "Exporting Weston version to shared volume..."
weston --version > "$XDG_RUNTIME_DIR/weston_version.txt" 2>&1
fi

echo "--- LAUNCHING WESTON ---"
echo "Command: exec weston $ARGS"

# Replace shell with Weston process
exec weston $ARGS

exec weston $ARGS
17 changes: 17 additions & 0 deletions weston-env-defaults.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash
# Defines fallback values for the Weston configuration templates.

# ==============================================================================
# DEFAULT TEMPLATE VALUES
# ==============================================================================

# [core]
export WESTON_INI_CORE_SHELL="${WESTON_INI_CORE_SHELL:-kiosk}"
export WESTON_INI_CORE_IDLE_TIME="${WESTON_INI_CORE_IDLE_TIME:-0}"
export WESTON_INI_CORE_REQUIRE_INPUT="${WESTON_INI_CORE_REQUIRE_INPUT:-false}"

# [shell]
export WESTON_INI_SHELL_LOCKING="${WESTON_INI_SHELL_LOCKING:-false}"
export WESTON_INI_SHELL_PANEL_POSITION="${WESTON_INI_SHELL_PANEL_POSITION:-none}"

# [libinput] is explicitly hardcoded in its template and requires no variables.
4 changes: 4 additions & 0 deletions weston-templates/01-core.ini.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[core]
shell=${WESTON_INI_CORE_SHELL}
idle-time=${WESTON_INI_CORE_IDLE_TIME}
require-input=${WESTON_INI_CORE_REQUIRE_INPUT}
3 changes: 3 additions & 0 deletions weston-templates/02-shell.ini.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[shell]
locking=${WESTON_INI_SHELL_LOCKING}
panel-position=${WESTON_INI_SHELL_PANEL_POSITION}
3 changes: 3 additions & 0 deletions weston-templates/03-libinput.ini.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[libinput]
enable-tap=true
middle-button-emulation=true