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

  1. Find the XML spec URL from the wayland-protocols or wlroots repository.

  2. 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
  1. Run the scanner:
dart run bin/scanner.dart scan --protocols=protocols.yaml
  1. 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:

  1. Core Protocol (lib/src/protocol/) — Unix socket I/O (Context, UnixSocket), message serialization, proxy management, shared memory helpers (mmapFd, writeToFd, createAnonymousFile).

  2. 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 by bin/scanner.dart.

  3. 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