Dart Wayland Client Library
Pure Dart implementation of the Wayland client protocol.
Provides FFI bindings to libc for Unix socket communication and shared memory — no C
compilation required at build time.
- Full core Wayland protocol (
wl_display,wl_shm,wl_compositor,wl_seat, …) - 80+ extensions: xdg-shell, layer-shell, input-method, tablet, fractional-scale, ext-*…
- Code generation from Wayland protocol XML via built-in scanner
- Works with AOT compilation (
dart build) via native assets
Packages
This repo is a monorepo managed with Melos:
| Package | Description |
|---|---|
packages/wayland |
Core Wayland protocol bindings + code generator |
packages/window_toolkit |
Widget toolkit + layer-shell window backend |
packages/gl |
OpenGL integration |
packages/bardash |
Wayland bar (desktop panel) |
Installation
dependencies:
wayland: ^1.0.0
Quick Start
import 'dart:typed_data';
import 'package:wayland/wayland.dart';
void main() async {
final app = WaylandApp();
await app.init();
app.run();
}
class WaylandApp {
late Context context;
late WlDisplay display;
late WlRegistry registry;
late WlCompositor compositor;
late WlShm shm;
late XdgWmBase xdgWmBase;
late WlSurface surface;
late XdgSurface xdgSurface;
late XdgToplevel toplevel;
int width = 800;
int height = 600;
bool running = true;
WlShmPool? _pool;
int _fd = -1;
Future<void> init() async {
context = Context();
await context.connect();
display = WlDisplay(context);
display.onError((e) { stderr.writeln('display error: $e'); exit(1); });
registry = display.getRegistry().getOrElse((_) { exit(1); });
registry.onGlobal(_onGlobal);
_roundtrip(); _roundtrip(); // wait for globals
surface = compositor.createSurface().getOrElse((_) { exit(1); });
xdgSurface = xdgWmBase.getXdgSurface(surface).getOrElse((_) { exit(1); });
xdgSurface.onConfigure((e) {
xdgSurface.ackConfigure(e.serial);
_drawFrame();
surface.commit();
});
toplevel = xdgSurface.getToplevel().getOrElse((_) { exit(1); });
toplevel.onConfigure((e) {
if (e.width > 0 && e.height > 0) { width = e.width; height = e.height; }
});
toplevel.onClose((_) { running = false; });
toplevel.setTitle('Dart Wayland');
toplevel.setAppId('dart-wayland');
surface.commit();
}
void run() { while (running) { context.dispatch(); } }
void _roundtrip() {
final cb = display.sync().getOrElse((_) => WlCallback(context));
var done = false;
cb.onDone((_) { done = true; });
while (!done) context.dispatch();
}
void _onGlobal(dynamic global) {
switch (global.interface) {
case 'wl_compositor':
compositor = WlCompositor(context);
registry.bind(global.name, global.interface, global.version, compositor.objectId);
case 'wl_shm':
shm = WlShm(context);
registry.bind(global.name, global.interface, global.version, shm.objectId);
case 'xdg_wm_base':
xdgWmBase = XdgWmBase(context);
xdgWmBase.onPing((p) => xdgWmBase.pong(p.serial));
registry.bind(global.name, global.interface, global.version, xdgWmBase.objectId);
}
}
void _drawFrame() {
final stride = width * 4;
final size = stride * height;
if (_pool == null || size > _poolSize) {
_pool?.destroy();
closeFd(_fd);
_fd = createAnonymousFile(size);
_pool = shm.createPool(_fd, size).getOrElse((_) { exit(1); });
}
final buffer = _pool!.createBuffer(0, width, height, stride, 0).getOrElse((_) { exit(1); });
buffer.onRelease((_) => buffer.destroy());
final pixels = Uint8List(size);
// fill with white pixels …
for (var i = 0; i < pixels.length; i += 4) { pixels[i]=0xFF; pixels[i+1]=0xFF; pixels[i+2]=0xFF; pixels[i+3]=0xFF; }
writeToFd(_fd, pixels);
surface.attach(buffer, 0, 0);
}
}
Protocol Generation
Protocol bindings are generated from XML spec files using the built-in scanner. The scanner fetches protocol XMLs from remote URLs (with local caching), parses them, and outputs Dart classes.
Generate All Protocols
cd packages/wayland
dart run bin/scanner.dart scan --protocols=protocols.yaml
This processes every entry in protocols.yaml and writes generated .dart files
to lib/protocols/.
Generate a Single Protocol
dart run bin/scanner.dart scan \
-i https://gitlab.freedesktop.org/wayland/wayland-protocols/-/raw/main/staging/ext-idle-notify/ext-idle-notify-v1.xml \
-o staging/ext-idle-notify/ext_idle_notify_v1.dart \
--prefix=zwlr_
Flags:
| Flag | Description |
|---|---|
-i |
URL or local path to the protocol XML |
-o |
Output path (relative to lib/protocols/) |
--prefix |
Prefix to strip from interface names (e.g. zwlr_) |
--pkg |
Dart package name (default: wayland) |
--protocols |
YAML file listing multiple protocols |
--force |
Re-download XMLs, bypassing the cache |
--clean |
Delete the output directory before generation |
Adding a New Protocol
-
Find the XML spec URL from the wayland-protocols or wlroots repository.
-
Add an entry to
protocols.yaml:
- name: my-protocol-v1.xml
input: "https://example.org/my-protocol-v1.xml"
output: "staging/my-protocol/my_protocol_v1.dart"
# If the protocol uses a prefix like zwlr_, specify it to strip cleanly:
prefix: "zmy_"
# List dependencies (other generated files this protocol imports):
dependencies:
- stable/xdg-shell/xdg_shell.dart
- Run the scanner:
dart run bin/scanner.dart scan --protocols=protocols.yaml
- Export the new protocol from
lib/wayland.dart:
export 'protocols/staging/my-protocol/my_protocol_v1.dart';
Protocol Cache
XML files are cached in .wayland-protocol-cache/ to avoid re-downloading.
Use --force to bypass the cache and fetch fresh copies.
Development
Prerequisites
- Dart SDK >= 3.8.0
- Wayland compositor running (for tests/examples)
Setup
dart pub get
Regenerate Protocols
dart run bin/scanner.dart scan --protocols=protocols.yaml --force
Run Examples
cd example
dart pub get
dart run bin/wayland2.dart
Architecture
The library has three layers:
-
Core Protocol (
lib/src/protocol/) — Unix socket I/O (Context,UnixSocket), message serialization, proxy management, shared memory helpers (mmapFd,writeToFd,createAnonymousFile). -
Generated Bindings (
lib/protocols/) — One Dart file per Wayland protocol XML. Each file contains classes for every interface in the protocol (requests, events, enums). Generated bybin/scanner.dart. -
Scanner (
lib/src/scanner/) — XML parser + Dart code generator that reads Wayland protocol XML and produces the bindings.
API Overview
Core Types
| Class | Description |
|---|---|
Context |
Manages the Wayland display socket connection and event dispatch |
Proxy |
Base class for all Wayland proxy objects |
WlDisplay |
Core display object (id=1) |
WlRegistry |
Global registry for binding protocol extensions |
Shared Memory Helpers
int createAnonymousFile(int size) // create a memfd-backed file
void writeToFd(int fd, Uint8List) // mmap + write + munmap
void closeFd(int fd) // safe close (guards -1)
Pointer<Void> mmapFd(int fd, int size) // mmap with validation
void munmap(Pointer<Void>, int size) // unmap
Error Handling
All Wayland requests return Result<T, Object> from package:result_dart:
final surface = compositor.createSurface().getOrElse((e) {
stderr.writeln('Failed: $e');
return WlSurface(context);
});
License
MIT
Libraries
- protocols/stable/linux-dmabuf/linux_dmabuf_v1
- Copyright © 2014, 2015 Collabora, Ltd.
- protocols/stable/presentation-time/presentation_time
- Copyright © 2013-2014 Collabora, Ltd.
- protocols/stable/tablet/tablet_v2
- Copyright 2014 © Stephen "Lyude" Chandler Paul Copyright 2015-2016 © Red Hat, Inc.
- protocols/stable/viewporter/viewporter
- Copyright © 2013-2016 Collabora, Ltd.
- protocols/stable/xdg-shell/xdg_shell
- Copyright © 2008-2013 Kristian Høgsberg Copyright © 2013 Rafael Antognolli Copyright © 2013 Jasper St. Pierre Copyright © 2010-2013 Intel Corporation Copyright © 2015-2017 Samsung Electronics Co., Ltd Copyright © 2015-2017 Red Hat Inc.
- protocols/staging/alpha-modifier/alpha_modifier_v1
- Copyright © 2024 Xaver Hugl
- protocols/staging/color-management/color_management_v1
- Copyright 2019 Sebastian Wick Copyright 2019 Erwin Burema Copyright 2020 AMD Copyright 2020-2024 Collabora, Ltd. Copyright 2024 Xaver Hugl Copyright 2022-2025 Red Hat, Inc.
- protocols/staging/color-representation/color_representation_v1
- Copyright 2022 Simon Ser Copyright 2022 Red Hat, Inc. Copyright 2022 Collabora, Ltd. Copyright 2022-2025 Red Hat, Inc.
- protocols/staging/commit-timing/commit_timing_v1
- Copyright © 2023 Valve Corporation
- protocols/staging/content-type/content_type_v1
- Copyright © 2021 Emmanuel Gil Peyrot Copyright © 2022 Xaver Hugl
- protocols/staging/cursor-shape/cursor_shape_v1
- Copyright 2018 The Chromium Authors Copyright 2023 Simon Ser
- protocols/staging/drm-lease/drm_lease_v1
- Copyright © 2018 NXP Copyright © 2019 Status Research & Development GmbH. Copyright © 2021 Xaver Hugl
- protocols/staging/ext-background-effect/ext_background_effect_v1
- Copyright (C) 2015 Martin Gräßlin Copyright (C) 2015 Marco Martin Copyright (C) 2020 Vlad Zahorodnii Copyright (C) 2024 Xaver Hugl
- protocols/staging/ext-data-control/ext_data_control_v1
- Copyright © 2018 Simon Ser Copyright © 2019 Ivan Molodetskikh Copyright © 2024 Neal Gompa
- protocols/staging/ext-foreign-toplevel-list/ext_foreign_toplevel_list_v1
- Copyright © 2018 Ilia Bozhinov Copyright © 2020 Isaac Freund Copyright © 2022 wb9688 Copyright © 2023 i509VCB
- protocols/staging/ext-idle-notify/ext_idle_notify_v1
- Copyright © 2015 Martin Gräßlin Copyright © 2022 Simon Ser
- protocols/staging/ext-image-capture-source/ext_image_capture_source_v1
- Copyright © 2022 Andri Yngvason Copyright © 2024 Simon Ser
- protocols/staging/ext-image-copy-capture/ext_image_copy_capture_v1
- Copyright © 2021-2023 Andri Yngvason Copyright © 2024 Simon Ser
- protocols/staging/ext-session-lock/ext_session_lock_v1
- Copyright 2021 Isaac Freund
- protocols/staging/ext-transient-seat/ext_transient_seat_v1
- Copyright © 2020 - 2023 Andri Yngvason
- protocols/staging/ext-workspace/ext_workspace_v1
- Copyright © 2019 Christopher Billington Copyright © 2020 Ilia Bozhinov Copyright © 2022 Victoria Brekenfeld
- protocols/staging/fifo/fifo_v1
- Copyright © 2023 Valve Corporation
- protocols/staging/fractional-scale/fractional_scale_v1
- Copyright © 2022 Kenny Levinsen
- protocols/staging/linux-drm-syncobj/linux_drm_syncobj_v1
- Copyright 2016 The Chromium Authors. Copyright 2017 Intel Corporation Copyright 2018 Collabora, Ltd Copyright 2021 Simon Ser
- protocols/staging/pointer-warp/pointer_warp_v1
- Copyright © 2024 Neal Gompa Copyright © 2024 Xaver Hugl Copyright © 2024 Matthias Klumpp Copyright © 2024 Vlad Zahorodnii
- protocols/staging/security-context/security_context_v1
- Copyright © 2021 Simon Ser
- protocols/staging/single-pixel-buffer/single_pixel_buffer_v1
- Copyright © 2022 Simon Ser
- protocols/staging/tearing-control/tearing_control_v1
- Copyright © 2021 Xaver Hugl
- protocols/staging/xdg-activation/xdg_activation_v1
- Copyright © 2020 Aleix Pol Gonzalez aleixpol@kde.org Copyright © 2020 Carlos Garnacho carlosg@gnome.org
- protocols/staging/xdg-dialog/xdg_dialog_v1
- Copyright © 2023 Carlos Garnacho
- protocols/staging/xdg-session-management/xdg_session_management_v1
- Copyright 2018 Mike Blumenkrantz Copyright 2018 Samsung Electronics Co., Ltd Copyright 2018 Red Hat Inc.
- protocols/staging/xdg-system-bell/xdg_system_bell_v1
- Copyright © 2016, 2023 Red Hat
- protocols/staging/xdg-toplevel-drag/xdg_toplevel_drag_v1
- Copyright 2023 David Redondo
- protocols/staging/xdg-toplevel-icon/xdg_toplevel_icon_v1
- Copyright © 2023-2024 Matthias Klumpp Copyright © 2024 David Edmundson
- protocols/staging/xdg-toplevel-tag/xdg_toplevel_tag_v1
- Copyright © 2024 Xaver Hugl
- protocols/staging/xwayland-shell/xwayland_shell_v1
- Copyright © 2022 Joshua Ashton
- protocols/unstable/fullscreen-shell/fullscreen_shell_unstable_v1
- Copyright © 2016 Yong Bakos Copyright © 2015 Jason Ekstrand Copyright © 2015 Jonas Ådahl
- protocols/unstable/idle-inhibit/idle_inhibit_unstable_v1
- Copyright © 2015 Samsung Electronics Co., Ltd
- protocols/unstable/input-method/input_method_unstable_v1
- Copyright © 2012, 2013 Intel Corporation
- protocols/unstable/input-timestamps/input_timestamps_unstable_v1
- Copyright © 2017 Collabora, Ltd.
- protocols/unstable/keyboard-shortcuts-inhibit/keyboard_shortcuts_inhibit_unstable_v1
- Copyright © 2017 Red Hat Inc.
- protocols/unstable/linux-dmabuf/linux_dmabuf_unstable_v1
- Copyright © 2014, 2015 Collabora, Ltd.
- protocols/unstable/linux-explicit-synchronization/linux_explicit_synchronization_unstable_v1
- Copyright 2016 The Chromium Authors. Copyright 2017 Intel Corporation Copyright 2018 Collabora, Ltd
- protocols/unstable/pointer-constraints/pointer_constraints_unstable_v1
- Copyright © 2014 Jonas Ådahl Copyright © 2015 Red Hat Inc.
- protocols/unstable/pointer-gestures/pointer_gestures_unstable_v1
- protocols/unstable/primary-selection/primary_selection_unstable_v1
- Copyright © 2015, 2016 Red Hat
- protocols/unstable/relative-pointer/relative_pointer_unstable_v1
- Copyright © 2014 Jonas Ådahl Copyright © 2015 Red Hat Inc.
- protocols/unstable/tablet/tablet_unstable_v1
- Copyright 2014 © Stephen "Lyude" Chandler Paul Copyright 2015-2016 © Red Hat, Inc.
- protocols/unstable/tablet/tablet_unstable_v2
- Copyright 2014 © Stephen "Lyude" Chandler Paul Copyright 2015-2016 © Red Hat, Inc.
- protocols/unstable/text-input/text_input_unstable_v1
- Copyright © 2012, 2013 Intel Corporation
- protocols/unstable/text-input/text_input_unstable_v3
- Copyright © 2012, 2013 Intel Corporation Copyright © 2015, 2016 Jan Arne Petersen Copyright © 2017, 2018 Red Hat, Inc. Copyright © 2018 Purism SPC
- protocols/unstable/xdg-decoration/xdg_decoration_unstable_v1
- Copyright © 2018 Simon Ser
- protocols/unstable/xdg-foreign/xdg_foreign_unstable_v1
- Copyright © 2015-2016 Red Hat Inc.
- protocols/unstable/xdg-foreign/xdg_foreign_unstable_v2
- Copyright © 2015-2016 Red Hat Inc.
- protocols/unstable/xdg-output/xdg_output_unstable_v1
- Copyright © 2017 Red Hat Inc.
- protocols/unstable/xdg-shell/xdg_shell_unstable_v5
- Copyright © 2008-2013 Kristian Høgsberg Copyright © 2013 Rafael Antognolli Copyright © 2013 Jasper St. Pierre Copyright © 2010-2013 Intel Corporation
- protocols/unstable/xdg-shell/xdg_shell_unstable_v6
- Copyright © 2008-2013 Kristian Høgsberg Copyright © 2013 Rafael Antognolli Copyright © 2013 Jasper St. Pierre Copyright © 2010-2013 Intel Corporation
- protocols/unstable/xwayland-keyboard-grab/xwayland_keyboard_grab_unstable_v1
- Copyright © 2017 Red Hat Inc.
- protocols/wayland
- Copyright © 2008-2011 Kristian Høgsberg Copyright © 2010-2011 Intel Corporation Copyright © 2012-2013 Collabora, Ltd.
- protocols/wlr/wlr_data_control_unstable_v1
- Copyright © 2018 Simon Ser Copyright © 2019 Ivan Molodetskikh
- protocols/wlr/wlr_export_dmabuf_unstable_v1
- Copyright © 2018 Rostislav Pehlivanov
- protocols/wlr/wlr_foreign_toplevel_management_unstable_v1
- Copyright © 2018 Ilia Bozhinov
- protocols/wlr/wlr_gamma_control_unstable_v1
- Copyright © 2015 Giulio camuffo Copyright © 2018 Simon Ser
- protocols/wlr/wlr_input_inhibitor_unstable_v1
- Copyright © 2018 Drew DeVault
- protocols/wlr/wlr_layer_shell_unstable_v1
- Copyright © 2017 Drew DeVault
- protocols/wlr/wlr_output_management_unstable_v1
- Copyright © 2019 Purism SPC
- protocols/wlr/wlr_output_power_management_unstable_v1
- Copyright © 2019 Purism SPC
- protocols/wlr/wlr_screencopy_unstable_v1
- Copyright © 2018 Simon Ser Copyright © 2019 Andri Yngvason
- protocols/wlr/wlr_virtual_pointer_unstable_v1
- Copyright © 2019 Josef Gajdusek
- wayland
- Wayland protocol bindings for Dart