kick/meson.build
Andrew Hamilton 08202dc6c3 fix X11 app startup: no forced toolkit backends; X11 windows join tabs at first map
GDK_BACKEND/QT_QPA_PLATFORM forced to wayland stripped toolkits' fallback,
killing X11-only builds like emacs-gtk ('cannot open display' against a
healthy Xwayland). Children now self-select from WAYLAND_DISPLAY/DISPLAY,
and XAUTHORITY is cleared.

Separately, X11 membership decisions moved from window-creation time to
first map: GTK leader windows never map, yet claimed the tab slot at
creation, leaving a permanent black tab while the real frame was demoted
to a stacked member -- and Alt-cycling onto that phantom main member
crashed on wlr_seat_keyboard_notify_enter(NULL). Never-mapped windows now
free silently; keyboard-entry paths guard on live surfaces. New
tests/xleader.c probe (unmapped leader + mapped frame) locks the behaviour
in.
2026-08-24 10:43:41 +10:00

190 lines
7.1 KiB
Meson

project('kick', 'c',
version: '0.1.0',
meson_version: '>=1.0',
default_options: ['c_std=c11', 'warning_level=2'])
wlroots_ver = '>=0.19,<0.20'
# wlroots' pkg-config name varies between distributions (wlroots-0.19 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.19', 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'),
dependency('freetype2'),
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'),
]
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',
],
'wlr-data-control-unstable-v1': [
'wlr-protocols/wlr-data-control-unstable-v1.xml',
'wlr-data-control',
],
'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',
],
}
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
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).
executable('wltest',
'tests/wltest.c',
code_by_name['xdg-shell'],
code_by_name['cursor-shape'],
code_by_name['tablet-v2'],
code_by_name['pointer-constraints'],
code_by_name['relative-pointer'],
code_by_name['primary-selection'],
client_headers['xdg-shell'],
client_headers['cursor-shape'],
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)
endif