Wayland Essentials

Quick Reference

# Check if running Wayland
echo $XDG_SESSION_TYPE    # wayland or x11
echo $WAYLAND_DISPLAY     # wayland-0 if Wayland

# List Wayland compositors
# Hyprland, Sway, GNOME, KDE Plasma

# XWayland for X11 apps
xlsclients              # List X11 apps (needs XWayland)

# Environment variables
export MOZ_ENABLE_WAYLAND=1         # Firefox native Wayland
export QT_QPA_PLATFORM=wayland      # Qt apps
export GDK_BACKEND=wayland          # GTK apps

Understanding Wayland

What is Wayland?

Wayland is a modern display server protocol designed to replace X11:

  • Protocol, not implementation - Defines how clients talk to compositor

  • Compositor = display server - Single process handles display

  • Per-application surfaces - Each window is independent buffer

  • Security by design - Applications can’t snoop on each other

Wayland vs X11

Aspect X11 Wayland

Architecture

Client-server with separate compositor

Compositor is the display server

Security

Any app can read any window

Apps isolated from each other

Input handling

X server handles all input

Compositor handles input directly

Rendering

Multiple paths (direct, indirect)

Client renders, passes buffer to compositor

Screen capture

Any app can capture any screen

Requires compositor permission

Network transparency

Built-in

Not built-in (use VNC/RDP)

Key Concepts

Compositor - The Wayland display server that:

  • Manages windows (surfaces)

  • Handles input (keyboard, mouse, touch)

  • Renders final output to screen

  • Controls screen layout

Surface - A rectangular area that a client draws to

Protocol - The wire format for client-compositor communication

XWayland - Compatibility layer for running X11 apps

Common Wayland Compositors

Desktop Compositors

Compositor Description DE/WM Type

GNOME (Mutter)

Default GNOME compositor

Full desktop environment

KDE Plasma (KWin)

Default KDE compositor

Full desktop environment

Hyprland

Dynamic tiling compositor

Standalone WM

Sway

i3-compatible compositor

Standalone WM

river

Dynamic tiling compositor

Standalone WM

Wayfire

3D compositor

Standalone WM

wlroots-based Compositors

Many standalone compositors use wlroots library:

  • Sway

  • Hyprland

  • river

  • wayfire

  • dwl

Benefits of wlroots:

  • Consistent protocol support

  • Shared infrastructure

  • Active development

Environment Setup

Required Environment Variables

# ~/.bashrc or ~/.zshrc (for Wayland session)

# Session type (usually set by display manager)
export XDG_SESSION_TYPE=wayland

# Wayland display socket
export WAYLAND_DISPLAY=wayland-0

# XDG runtime directory (critical for Wayland)
export XDG_RUNTIME_DIR="/run/user/$(id -u)"

Application Toolkit Variables

# Qt applications
export QT_QPA_PLATFORM=wayland
# Fallback: export QT_QPA_PLATFORM="wayland;xcb"

# GTK applications (GTK3/4)
export GDK_BACKEND=wayland
# Fallback: export GDK_BACKEND="wayland,x11"

# SDL2 applications
export SDL_VIDEODRIVER=wayland

# Firefox
export MOZ_ENABLE_WAYLAND=1

# Electron apps (varies by app)
export ELECTRON_OZONE_PLATFORM_HINT=wayland

# EFL applications
export ECORE_EVAS_ENGINE=wayland_shm

# Clutter applications
export CLUTTER_BACKEND=wayland

Hardware Acceleration

# Check GPU driver
lspci -k | grep -A 3 VGA
glxinfo | grep "OpenGL renderer"

# For AMD
export AMD_VULKAN_ICD=RADV

# For Intel
export MESA_LOADER_DRIVER_OVERRIDE=iris

# For NVIDIA (explicit sync required on newer kernels)
export __GL_GSYNC_ALLOWED=1
export __GL_VRR_ALLOWED=1

# Check Vulkan
vulkaninfo | grep "GPU"

XWayland (X11 Compatibility)

How XWayland Works

XWayland provides X11 support on Wayland:

  • Runs as an X server that outputs to Wayland

  • X11 apps think they’re running on X server

  • Compositor treats XWayland windows as Wayland surfaces

Identifying XWayland Apps

# List X11 clients (requires xorg-xlsclients)
xlsclients

# Check window properties (requires xorg-xprop)
xprop | grep -i wayland

# In Hyprland
hyprctl clients | grep xwayland

# In Sway
swaymsg -t get_tree | grep xwayland

XWayland Configuration

# Force app to use XWayland
GDK_BACKEND=x11 application
QT_QPA_PLATFORM=xcb application

# Force app to use native Wayland
GDK_BACKEND=wayland application
QT_QPA_PLATFORM=wayland application

Screen Capture and Recording

Portal-Based Capture

Wayland uses XDG Desktop Portal for screen capture:

# Install portal packages
# Arch
sudo pacman -S xdg-desktop-portal xdg-desktop-portal-hyprland
# or xdg-desktop-portal-wlr for wlroots compositors
# or xdg-desktop-portal-gtk for GNOME

# Portal handles:
# - Screen sharing (OBS, browser WebRTC)
# - Screenshots
# - File chooser dialogs

Screenshot Tools

# grim - Screenshot tool for wlroots compositors
grim screenshot.png                    # Full screen
grim -g "0,0 1920x1080" area.png      # Specific area
grim -o DP-1 monitor.png              # Specific output

# grim + slurp - Select area
grim -g "$(slurp)" selection.png

# Flameshot (Wayland support)
flameshot gui

# GNOME Screenshot
gnome-screenshot

# spectacle (KDE)
spectacle

Screen Recording

# wf-recorder - For wlroots compositors
wf-recorder -o DP-1                    # Record specific output
wf-recorder -g "$(slurp)"             # Record selected area
wf-recorder -f output.mp4             # Specify output file

# OBS Studio (with portal)
# Use "Screen Capture (PipeWire)" source

# GNOME built-in
# Super+Shift+R to start/stop

Clipboard

Wayland Clipboard Tools

# wl-clipboard
# Copy to clipboard
echo "text" | wl-copy
wl-copy < file.txt
wl-copy --type image/png < image.png

# Paste from clipboard
wl-paste
wl-paste --type image/png > image.png

# Clear clipboard
wl-copy --clear

# Primary selection (middle-click paste)
echo "text" | wl-copy --primary
wl-paste --primary

Clipboard Managers

# cliphist - Clipboard history
wl-paste --watch cliphist store    # Run in background

# List history
cliphist list

# Select from history (with fuzzy finder)
cliphist list | fzf | cliphist decode | wl-copy

# Integration with rofi/wofi
cliphist list | wofi --dmenu | cliphist decode | wl-copy

Input Methods

Keyboard Configuration

# Set keyboard layout (compositor-specific)

# Sway
# ~/.config/sway/config
input type:keyboard {
    xkb_layout us,de
    xkb_options grp:alt_shift_toggle,caps:escape
}

# Hyprland
# ~/.config/hypr/hyprland.conf
input {
    kb_layout = us,de
    kb_options = grp:alt_shift_toggle,caps:escape
}

# Environment variable (less reliable)
export XKB_DEFAULT_LAYOUT=us
export XKB_DEFAULT_OPTIONS=caps:escape

Input Method Frameworks

# fcitx5 (recommended for CJK input)
# ~/.bashrc
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS=@im=fcitx

# ibus
export GTK_IM_MODULE=ibus
export QT_IM_MODULE=ibus
export XMODIFIERS=@im=ibus

Output Configuration

List Outputs

# wlr-randr (wlroots compositors)
wlr-randr

# Example output:
# DP-1 "Dell Inc. DELL U2720Q"
#   Physical size: 600x340 mm
#   Enabled: yes
#   Modes:
#     3840x2160 px, 60.000000 Hz (preferred, current)

# Sway
swaymsg -t get_outputs

# Hyprland
hyprctl monitors

Configure Outputs

# wlr-randr
wlr-randr --output DP-1 --mode 3840x2160 --scale 1.5
wlr-randr --output HDMI-A-1 --pos 1920,0
wlr-randr --output eDP-1 --off

# kanshi - Dynamic output configuration
# ~/.config/kanshi/config
profile docked {
    output eDP-1 disable
    output DP-1 mode 3840x2160 position 0,0 scale 1.5
}

profile undocked {
    output eDP-1 enable mode 2560x1440 position 0,0
}

# Start kanshi as daemon
kanshi &

Scaling

# Integer scaling
wlr-randr --output DP-1 --scale 2

# Fractional scaling
wlr-randr --output DP-1 --scale 1.5

# Per-app scaling (Qt)
export QT_SCALE_FACTOR=1.5

# Per-app scaling (GTK)
export GDK_SCALE=2
export GDK_DPI_SCALE=0.5    # For non-HiDPI apps

Application Launchers

Wayland-Native Launchers

# wofi - Rofi-like launcher
wofi --show drun
wofi --show run

# fuzzel - Simple launcher
fuzzel

# tofi - Minimal launcher
tofi-run

# rofi (with Wayland support)
rofi -show drun

Configuration Example (wofi)

# ~/.config/wofi/config
show=drun
width=600
height=400
always_parse_args=true
show_all=true
print_command=true
layer=overlay
insensitive=true
prompt=

Notification Daemons

Wayland Notification Daemons

# mako - Lightweight notification daemon
mako &

# dunst (Wayland support)
dunst &

# fnott - Minimal daemon
fnott &

# swaync - Sway notification center
swaync &

Send Notifications

# Using notify-send (libnotify)
notify-send "Title" "Body text"
notify-send -u critical "Alert" "Critical notification"
notify-send -i firefox "Firefox" "Download complete"
notify-send -t 5000 "Timeout" "Disappears in 5 seconds"

Status Bars

Wayland Status Bars

# waybar - Highly customizable
waybar &

# eww - Elkowar's Wacky Widgets
eww daemon

# yambar - Modular status bar
yambar &

# i3status-rust - For Sway
# sfwbar - Lightweight bar

Waybar Configuration

# ~/.config/waybar/config
{
    "layer": "top",
    "position": "top",
    "modules-left": ["hyprland/workspaces"],
    "modules-center": ["clock"],
    "modules-right": ["pulseaudio", "network", "battery"],

    "clock": {
        "format": "{:%H:%M}"
    }
}

Troubleshooting

Common Issues

# App doesn't run on Wayland
# Force XWayland
GDK_BACKEND=x11 problematic-app
QT_QPA_PLATFORM=xcb problematic-app

# Electron apps not working
# Add to app launch
--enable-features=UseOzonePlatform --ozone-platform=wayland

# Screen sharing not working
# Ensure portal is running
systemctl --user status xdg-desktop-portal
systemctl --user restart xdg-desktop-portal

# Clipboard not working between apps
# Check wl-clipboard is installed
wl-copy --version

Debug Information

# Check Wayland socket
ls -la $XDG_RUNTIME_DIR/wayland-*

# Check compositor logs
journalctl --user -u hyprland
journalctl --user -u sway

# Check portal logs
journalctl --user -u xdg-desktop-portal

# Verbose application output
WAYLAND_DEBUG=1 application

NVIDIA Troubleshooting

# NVIDIA requires specific setup
# /etc/environment or shell config
export GBM_BACKEND=nvidia-drm
export __GLX_VENDOR_LIBRARY_NAME=nvidia
export WLR_NO_HARDWARE_CURSORS=1    # If cursor issues

# Check if using NVIDIA
nvidia-smi
glxinfo | grep "OpenGL vendor"

# For Hyprland/wlroots
# Ensure nvidia-drm.modeset=1 in kernel params
cat /proc/cmdline | grep nvidia-drm

Quick Reference

# Session detection
echo $XDG_SESSION_TYPE                # wayland or x11
echo $WAYLAND_DISPLAY                 # Socket name

# Application configuration
export QT_QPA_PLATFORM=wayland        # Qt apps
export GDK_BACKEND=wayland            # GTK apps
export MOZ_ENABLE_WAYLAND=1           # Firefox

# Screenshots (wlroots)
grim screenshot.png                   # Full screen
grim -g "$(slurp)" selection.png     # Selection

# Clipboard
wl-copy < file                        # Copy
wl-paste                              # Paste

# Screen recording
wf-recorder -o DP-1                   # Record output

# Output configuration
wlr-randr                             # List outputs
wlr-randr --output DP-1 --scale 2    # Set scale

# XWayland apps
xlsclients                            # List X11 apps
GDK_BACKEND=x11 app                   # Force X11