kick/meson.build
Andrew Hamilton 31f413ff9f fix: advertise a render node as the dmabuf main device
On split display/render platforms (vc4 display + v3d render) the
GLES2 renderer resolves to the display node, which has no 3D engine
-- and wlroots then advertises that node as the dmabuf main device,
so Mesa clients try to render there and fall back to llvmpipe (mpv
goes software, drops hundreds of frames).  Discover a real render
node under /dev/dri and override the advertised main device with it;
rendering, allocation and scanout paths are untouched, and a missing
node falls back to the previous renderer-derived behavior.
2026-09-23 13:25:19 +10:00

524 lines
23 KiB
Meson

project('kick', 'c',
version: '0.1.0',
meson_version: '>=1.0',
default_options: ['c_std=c11', 'warning_level=2'])
wlroots_ver = '>=0.20,<0.21'
# wlroots' pkg-config name varies between distributions (wlroots-0.20 on
# Debian/Ubuntu, plain wlroots on Arch/Fedora). Prefer the system copy, and
# fall back to a pinned source build from subprojects/wlroots.wrap when no
# matching system library is found.
wlroots = dependency('wlroots-0.20', version: wlroots_ver, required: false)
if not wlroots.found()
wlroots = dependency('wlroots', version: wlroots_ver, required: false)
endif
if not wlroots.found()
wlroots_subproj = subproject('wlroots',
default_options: ['examples=false', 'werror=false'])
wlroots = wlroots_subproj.get_variable('wlroots')
endif
deps = [
wlroots,
dependency('wayland-server'),
dependency('wayland-client'),
dependency('wayland-egl'),
dependency('xkbcommon'),
dependency('egl'),
dependency('glesv2'),
# Overlay tab-title text via Pango+Cairo (the labwc/sway/mutter stack):
# shaping, UTF-8 and fontconfig fallback in, no hand-rolled atlas.
dependency('pangocairo'),
dependency('libpng'),
dependency('librsvg-2.0'),
# Direct pixman use in kick.c (pointer-constraint region extents).
dependency('pixman-1'),
# Server-side/client-side window decorations via libdecor (nested mode).
dependency('libdecor-0'),
# libdrm for render-node discovery (dmabuf main device override).
dependency('libdrm'),
]
cc = meson.get_compiler('c')
libm = cc.find_library('m', required: false)
if libm.found()
deps += libm
endif
# --- XWayland (optional) ------------------------------------------------
# Enabling XWayland needs two things: the linked wlroots built with xwayland
# (advertised publicly as WLR_HAS_XWAYLAND in <wlr/config.h>, checked in
# kick.c) and the xcb dev packages pulled in by <wlr/xwayland/xwayland.h>.
# When either is missing the build stays green and kick simply runs without
# X11 support.
xcb_deps = []
xcb_all = true
foreach depname : ['xcb', 'xcb-icccm', 'xcb-ewmh']
d = dependency(depname, required: false)
if d.found()
xcb_deps += d
else
xcb_all = false
endif
endforeach
deps += xcb_deps
kick_c_args = ['-DWLR_USE_UNSTABLE']
if xcb_all
kick_c_args += ['-DKICK_HAVE_XCB=1']
endif
# --- Wayland protocol stubs -------------------------------------------
# The protocol implementation and headers are generated at build time by
# wayland-scanner instead of being committed, so they always match the
# installed wayland-protocols (the previously committed copies were produced
# by wayland-scanner 1.24/1.26 and drifted apart). Outputs land in the build
# directory, which Meson adds to every target's include path automatically;
# that also satisfies the bundled wlroots subproject's wlr_xdg_shell.h and its
# quoted #include "xdg-shell-protocol.h".
wayland_protocols = dependency('wayland-protocols', version: '>=1.17',
fallback: 'wayland-protocols', default_options: ['tests=false'])
wl_protocols_dir = wayland_protocols.get_variable('pkgdatadir')
wayland_scanner_dep = dependency('wayland-scanner', native: true)
wayland_scanner = find_program(
wayland_scanner_dep.get_variable('wayland_scanner'))
# (input xml, output base name). The output base names keep historical
# suffixes: xdg-shell is generated plain because the sources #include that
# exact name.
protocols = {
'xdg-shell': [
wl_protocols_dir / 'stable/xdg-shell/xdg-shell.xml',
'xdg-shell',
],
# xdg-decoration is the unstable-v1 protocol but keeps the plain
# "xdg-decoration" base name because the host-window code includes
# those exact generated names (SSD-compositor direct path).
'xdg-decoration': [
wl_protocols_dir / 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml',
'xdg-decoration',
],
'ext-data-control': [
wl_protocols_dir / 'staging/ext-data-control/ext-data-control-v1.xml',
'ext-data-control-v1',
],
# wlr-layer-shell is what waybar and other panels use to make an
# always-visible bar. Bundled locally (like the foreign-toplevel and
# output-management XMLs) rather than referenced from the wlroots tree,
# so it works with either a system wlroots or the pinned subproject.
'wlr-layer-shell-unstable-v1': [
'wlr-protocols/wlr-layer-shell-unstable-v1.xml',
'wlr-layer-shell-unstable-v1',
],
# wlr-foreign-toplevel-management is the taskbar protocol: a per-window
# handle with client-pull state. Bundled locally (like the layer-shell
# XML) so it works with either a system wlroots or the pinned subproject.
'wlr-foreign-toplevel-management-unstable-v1': [
'wlr-protocols/wlr-foreign-toplevel-management-unstable-v1.xml',
'wlr-foreign-toplevel-management',
],
# ext-foreign-toplevel-list ships as a staging protocol in
# wayland-protocols (>= 1.36); it is the shipman/taskbar-side read of the
# same per-window list, driven server-side rather than by the client.
'ext-foreign-toplevel-list': [
wl_protocols_dir / 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml',
'ext-foreign-toplevel-list-v1',
],
# Idle: ext-idle-notify (a client asks for a timeout, the compositor fires
# "idle" once that much time passes without input) and idle-inhibit (a
# client can suppress idle notifications while its buffer stays up).
'ext-idle-notify': [
wl_protocols_dir / 'staging/ext-idle-notify/ext-idle-notify-v1.xml',
'ext-idle-notify-v1',
],
'idle-inhibit-unstable-v1': [
wl_protocols_dir / 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml',
'idle-inhibit-unstable-v1',
],
# Session lock: the lock client (swaylock) grabs the session and private
# protocol surfaces cover each output; the compositor blanking the screen
# while locked.
'ext-session-lock': [
wl_protocols_dir / 'staging/ext-session-lock/ext-session-lock-v1.xml',
'ext-session-lock-v1',
],
# Screen capture (ext-image-copy-capture-v1 + ext-image-capture-source-v1),
# the protocol grim uses. Staging protocols from wayland-protocols; the
# XMLs are referenced from the installed package.
'ext-image-copy-capture': [
wl_protocols_dir / 'staging/ext-image-copy-capture/ext-image-copy-capture-v1.xml',
'ext-image-copy-capture-v1',
],
'ext-image-capture-source': [
wl_protocols_dir / 'staging/ext-image-capture-source/ext-image-capture-source-v1.xml',
'ext-image-capture-source-v1',
],
# Tearing control (a surface asks for unthrottled presentation) and
# fractional scale (a surface learns a non-integer output scale).
# Both are staging protocols; tearing drives the output commit's
# async-flip flag from the shown surface's hint, fractional scale is
# notified from the output scale on claim.
'tearing-control': [
wl_protocols_dir / 'staging/tearing-control/tearing-control-v1.xml',
'tearing-control-v1',
],
'fractional-scale': [
wl_protocols_dir / 'staging/fractional-scale/fractional-scale-v1.xml',
'fractional-scale-v1',
],
# Output power management (a client blanks/unblanks an output). Bundled
# locally like the other wlr-protocols XMLs (copied from the pinned
# wlroots subproject).
'wlr-output-power-management-unstable-v1': [
'wlr-protocols/wlr-output-power-management-unstable-v1.xml',
'wlr-output-power-management-unstable-v1',
],
# Keyboard shortcuts inhibit (a fullscreen game/VM grabs the compositor's
# shortcuts). Unstable protocol; the test client binds it to prove the
# compositor activates the inhibitor for the focused surface.
'keyboard-shortcuts-inhibit': [
wl_protocols_dir / 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml',
'keyboard-shortcuts-inhibit-unstable-v1',
],
# Virtual keyboard/pointer (synthesised input from clients like wtype).
# Bundled locally (copied from the pinned wlroots subproject).
'virtual-keyboard-unstable-v1': [
'wlr-protocols/virtual-keyboard-unstable-v1.xml',
'virtual-keyboard-unstable-v1',
],
'wlr-virtual-pointer-unstable-v1': [
'wlr-protocols/wlr-virtual-pointer-unstable-v1.xml',
'wlr-virtual-pointer-unstable-v1',
],
# Xdg-activation (launchers focus windows by token). Staging protocol.
'xdg-activation': [
wl_protocols_dir / 'staging/xdg-activation/xdg-activation-v1.xml',
'xdg-activation-v1',
],
'cursor-shape': [
wl_protocols_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
'cursor-shape-v1',
],
# cursor-shape-v1's get_tablet_tool_v2 request points at zwp_tablet_tool_v2,
# so its private code needs tablet-v2's generated code (wlroots' own copy is
# not exported: wlroots.syms keeps every non-wlr_* symbol local).
'tablet-v2': [
wl_protocols_dir / 'stable/tablet/tablet-v2.xml',
'tablet-v2',
],
'pointer-constraints': [
wl_protocols_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
'pointer-constraints-unstable-v1',
],
'relative-pointer': [
wl_protocols_dir / 'unstable/relative-pointer/relative-pointer-unstable-v1.xml',
'relative-pointer-unstable-v1',
],
'primary-selection': [
wl_protocols_dir / 'unstable/primary-selection/primary-selection-unstable-v1.xml',
'primary-selection-unstable-v1',
],
# Text input (OSK/IME): zwp_text_input_v3 (clients) + input-method-v2
# (the IME side). text-input comes from the system wayland-protocols;
# input-method-v2 only ships inside wlroots, so like the other bundled
# wlr-protocols XMLs it is vendored under wlr-protocols/ (Meson forbids
# referencing a nested subproject's files from the parent project).
'text-input': [
wl_protocols_dir / 'unstable/text-input/text-input-unstable-v3.xml',
'text-input-unstable-v3',
],
'input-method': [
'wlr-protocols/input-method-unstable-v2.xml',
'input-method-unstable-v2',
],
# Gamma control (night-light tools like wlsunset/gammastep): wlroots
# extension, vendored like the other wlr-protocols XMLs.
'gamma-control': [
'wlr-protocols/wlr-gamma-control-unstable-v1.xml',
'wlr-gamma-control-unstable-v1',
],
# xdg-dialog (modal toplevels): staging protocol from the system
# wayland-protocols. Only the client stub is generated for wltest;
# the server side is wlroots' wlr_xdg_wm_dialog_v1 (no quoted
# server-header include, so no extra custom_target needed).
'xdg-dialog': [
wl_protocols_dir / 'staging/xdg-dialog/xdg-dialog-v1.xml',
'xdg-dialog-v1',
],
# Pointer gestures (touchpad swipe/pinch/hold): unstable protocol
# from the system wayland-protocols. Only client stubs are needed
# for wltest; the server side is wlroots' wlr_pointer_gestures_v1
# (no quoted server-header include).
'pointer-gestures': [
wl_protocols_dir / 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml',
'pointer-gestures-unstable-v1',
],
# Toplevel icons (exact window artwork from the client): staging
# protocol from the system wayland-protocols. Only client stubs are
# needed for wltest; the server side is wlroots'
# wlr_xdg_toplevel_icon_manager_v1 (no quoted server-header include).
'toplevel-icon': [
wl_protocols_dir / 'staging/xdg-toplevel-icon/xdg-toplevel-icon-v1.xml',
'xdg-toplevel-icon-v1',
],
# Toplevel tags (client-supplied window labels like "settings" plus a
# translated description): staging protocol from the system
# wayland-protocols. Only client stubs are needed for wltest; the
# server side is wlroots' wlr_xdg_toplevel_tag_manager_v1 (no quoted
# server-header include).
'toplevel-tag': [
wl_protocols_dir / 'staging/xdg-toplevel-tag/xdg-toplevel-tag-v1.xml',
'xdg-toplevel-tag-v1',
],
# Color representation (a surface declares its alpha mode / matrix
# coefficients / range): staging protocol from the system
# wayland-protocols. Only client stubs are needed for wltest; the
# server side is wlroots' wlr_color_representation_manager_v1 (the
# generated enum header ships with wayland-protocols).
'color-representation': [
wl_protocols_dir / 'staging/color-representation/color-representation-v1.xml',
'color-representation-v1',
],
# Color management (clients describe surface colors, outputs advertise
# image descriptions): staging protocol from the system
# wayland-protocols. Only client stubs are needed for wltest; the
# server side is wlroots' wlr_color_manager_v1 (the generated enum
# header ships with wayland-protocols).
'color-management': [
wl_protocols_dir / 'staging/color-management/color-management-v1.xml',
'color-management-v1',
],
# System bell (a client asks the compositor to ring the bell):
# staging protocol from the system wayland-protocols. Only client
# stubs are needed for wltest; the server side is wlroots'
# wlr_xdg_system_bell_v1.
'system-bell': [
wl_protocols_dir / 'staging/xdg-system-bell/xdg-system-bell-v1.xml',
'xdg-system-bell-v1',
],
# Output management (kanshi/wdisplays reconfigure the output):
# wlroots extension, vendored like the other wlr-protocols XMLs.
'output-management': [
'wlr-protocols/wlr-output-management-unstable-v1.xml',
'wlr-output-management-unstable-v1',
],
# Content hints (photo/video/game) + single-pixel buffers (1x1 solid
# color without a shm pool). Both are staging protocols from the
# system wayland-protocols, like wlroots itself uses.
'content-type': [
wl_protocols_dir / 'staging/content-type/content-type-v1.xml',
'content-type-v1',
],
'single-pixel': [
wl_protocols_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml',
'single-pixel-buffer-v1',
],
# Alpha modifier (a surface multiplies its own alpha): staging
# protocol from the system wayland-protocols. Only client stubs are
# needed for wltest; the server side is wlroots'
# wlr_alpha_modifier_v1.
'alpha-modifier': [
wl_protocols_dir / 'staging/alpha-modifier/alpha-modifier-v1.xml',
'alpha-modifier-v1',
],
# Viewporter (stable): only the client stub is needed (the server side
# is wlroots' wlr_viewporter_create). wltest uses it to scale a 1x1
# single-pixel buffer up to the window size.
'viewporter': [
wl_protocols_dir / 'stable/viewporter/viewporter.xml',
'viewporter',
],
}
protocol_sources = []
protocol_headers = []
client_headers = {}
code_by_name = {}
foreach protocol, p : protocols
xml = p[0]
base = p[1]
code = custom_target(protocol + ' protocol code',
input: xml,
output: base + '-protocol.c',
command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'])
protocol_sources += code
code_by_name += { protocol: code }
client_header = custom_target(protocol + ' client header',
input: xml,
output: base + '-client.h',
command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'])
protocol_headers += client_header
client_headers += { protocol: client_header }
if protocol == 'xdg-shell'
protocol_headers += custom_target(protocol + ' server header',
input: xml,
output: base + '-protocol.h',
command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@'])
endif
if protocol == 'cursor-shape'
# Serves the wlroots header's quoted #include "cursor-shape-v1-protocol.h";
# the system wlroots packages don't install the generated protocol headers.
protocol_headers += custom_target(protocol + ' server header',
input: xml,
output: base + '-protocol.h',
command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@'])
endif
if protocol == 'pointer-constraints'
# Serves wlr_pointer_constraints_v1.h's quoted
# #include "pointer-constraints-unstable-v1-protocol.h".
protocol_headers += custom_target(protocol + ' server header',
input: xml,
output: base + '-protocol.h',
command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@'])
endif
if protocol == 'wlr-layer-shell-unstable-v1'
# Serves wlr_layer_shell_v1.h's quoted
# #include "wlr-layer-shell-unstable-v1-protocol.h".
protocol_headers += custom_target(protocol + ' server header',
input: xml,
output: base + '-protocol.h',
command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@'])
endif
if protocol == 'tearing-control'
# Serves wlr_tearing_control_v1.h's quoted
# #include "tearing-control-v1-protocol.h".
protocol_headers += custom_target(protocol + ' server header',
input: xml,
output: base + '-protocol.h',
command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@'])
endif
if protocol == 'content-type'
# Serves wlr_content_type_v1.h's quoted
# #include "content-type-v1-protocol.h".
protocol_headers += custom_target(protocol + ' server header',
input: xml,
output: base + '-protocol.h',
command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@'])
endif
if protocol == 'wlr-output-power-management-unstable-v1'
# Serves wlr_output_power_management_v1.h's quoted
# #include "wlr-output-power-management-unstable-v1-protocol.h".
protocol_headers += custom_target(protocol + ' server header',
input: xml,
output: base + '-protocol.h',
command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@'])
endif
endforeach
executable('kick',
'kick.c',
protocol_sources,
protocol_headers,
dependencies: deps,
c_args: kick_c_args)
# wltest needs the xdg-shell stub plus the cursor-shape client stack (whose
# private code references zwp_tablet_tool_v2, hence tablet-v2 too). The
# --layer mode uses the wlr-layer-shell client protocol; the --foreign mode
# uses the wlr-foreign-toplevel and ext-foreign-toplevel-list client stubs.
# --idle mode uses ext-idle-notify and idle-inhibit. --tearing and
# --fractional-out need their own protocol code linked in.
executable('wltest',
'tests/wltest.c',
code_by_name['xdg-shell'],
code_by_name['cursor-shape'],
code_by_name['tablet-v2'],
code_by_name['tearing-control'],
code_by_name['fractional-scale'],
code_by_name['pointer-constraints'],
code_by_name['relative-pointer'],
code_by_name['primary-selection'],
code_by_name['ext-data-control'],
code_by_name['wlr-layer-shell-unstable-v1'],
code_by_name['wlr-foreign-toplevel-management-unstable-v1'],
code_by_name['ext-foreign-toplevel-list'],
code_by_name['ext-idle-notify'],
code_by_name['idle-inhibit-unstable-v1'],
code_by_name['ext-session-lock'],
code_by_name['ext-image-copy-capture'],
code_by_name['ext-image-capture-source'],
code_by_name['keyboard-shortcuts-inhibit'],
code_by_name['wlr-output-power-management-unstable-v1'],
code_by_name['virtual-keyboard-unstable-v1'],
code_by_name['wlr-virtual-pointer-unstable-v1'],
code_by_name['xdg-activation'],
code_by_name['text-input'],
code_by_name['input-method'],
code_by_name['content-type'],
code_by_name['single-pixel'],
code_by_name['alpha-modifier'],
code_by_name['viewporter'],
code_by_name['gamma-control'],
code_by_name['xdg-dialog'],
code_by_name['pointer-gestures'],
code_by_name['toplevel-icon'],
code_by_name['color-representation'],
code_by_name['color-management'],
code_by_name['system-bell'],
code_by_name['toplevel-tag'],
code_by_name['output-management'],
client_headers['xdg-shell'],
client_headers['cursor-shape'],
client_headers['wlr-layer-shell-unstable-v1'],
client_headers['wlr-foreign-toplevel-management-unstable-v1'],
client_headers['ext-foreign-toplevel-list'],
client_headers['ext-idle-notify'],
client_headers['idle-inhibit-unstable-v1'],
client_headers['ext-session-lock'],
client_headers['ext-image-copy-capture'],
client_headers['ext-image-capture-source'],
client_headers['keyboard-shortcuts-inhibit'],
client_headers['virtual-keyboard-unstable-v1'],
client_headers['wlr-virtual-pointer-unstable-v1'],
client_headers['xdg-activation'],
client_headers['text-input'],
client_headers['input-method'],
client_headers['content-type'],
client_headers['single-pixel'],
client_headers['alpha-modifier'],
client_headers['viewporter'],
client_headers['gamma-control'],
client_headers['xdg-dialog'],
client_headers['pointer-gestures'],
client_headers['tearing-control'],
client_headers['fractional-scale'],
client_headers['toplevel-icon'],
client_headers['color-representation'],
client_headers['color-management'],
client_headers['system-bell'],
client_headers['toplevel-tag'],
client_headers['output-management'],
client_headers['ext-data-control'],
dependencies: [dependency('wayland-client'),
dependency('xkbcommon')])
# xdeco: xdg-decoration mode probe for the client-side regression test --
# maps one toplevel and reports the configured decoration mode.
executable('xdeco', 'tests/xdeco.c',
code_by_name['xdg-shell'],
code_by_name['xdg-decoration'],
client_headers['xdg-shell'],
client_headers['xdg-decoration'],
dependencies: [dependency('wayland-client')])
# xleader: X11 twin-window probe used by the leader-window regression test --
# an unmapped GTK-style leader plus a mapped frame, both carrying _NET_WM_PID.
x11_dep = dependency('x11', required: false)
if x11_dep.found()
executable('xleader', 'tests/xleader.c', dependencies: x11_dep)
# xpopup: instantly-mapped managed transient (synthetic menu) for the
# late-association regression test.
executable('xpopup', 'tests/xpopup.c', dependencies: x11_dep)
# xormenu: override-redirect focus-stealing menu probe (frame + menu in
# separate processes) for the or_focus_owner regression test.
executable('xormenu', 'tests/xormenu.c', dependencies: x11_dep)
# xclass: WM_CLASS set-then-delete probe for the set_class NULL
# app_id regression test.
executable('xclass', 'tests/xclass.c', dependencies: x11_dep)
# xreqs: client-request probe driving a managed X11 window through
# retitle/minimize/fullscreen/move+resize/raise/maximize/close, plus an
# unmapped create+destroy for the pending-surface teardown path.
executable('xreqs', 'tests/xreqs.c', dependencies: x11_dep)
endif