From 862d230ff94137c0d0cbb4ddee8e61b6fbabe260 Mon Sep 17 00:00:00 2001 From: GlassOnTin Date: Mon, 30 Mar 2026 11:55:49 +0100 Subject: [PATCH 01/14] Make labnag a meson feature flag Add a 'labnag' meson option (default: auto) to allow disabling the labnag notification daemon at build time. This is useful for embedded/headless deployments (e.g. Android) where labnag is not needed, and avoids building its wayland-client dependencies. Disable with: meson setup build -Dlabnag=disabled --- clients/meson.build | 106 ++++++++++++++++++++++---------------------- meson_options.txt | 1 + 2 files changed, 55 insertions(+), 52 deletions(-) diff --git a/clients/meson.build b/clients/meson.build index 467bc035..55a4c0e5 100644 --- a/clients/meson.build +++ b/clients/meson.build @@ -1,59 +1,61 @@ -wayland_client = dependency('wayland-client') -wayland_cursor = dependency('wayland-cursor') +if get_option('labnag').allowed() + wayland_client = dependency('wayland-client') + wayland_cursor = dependency('wayland-cursor') -nag_sources = files( - 'labnag.c', - 'pool-buffer.c', -) - -wl_protocol_dir = wayland_protos.get_variable('pkgdatadir') - -protocols = [ - wl_protocol_dir / 'stable/tablet/tablet-v2.xml', - wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml', - wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml', - '../protocols/wlr-layer-shell-unstable-v1.xml', -] - -foreach xml : protocols - nag_sources += custom_target( - xml.underscorify() + '_c', - input: xml, - output: '@BASENAME@-protocol.c', - command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'], + nag_sources = files( + 'labnag.c', + 'pool-buffer.c', ) - nag_sources += custom_target( - xml.underscorify() + '_client_h', - input: xml, - output: '@BASENAME@-client-protocol.h', - command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'], - ) -endforeach -if host_machine.system() in ['freebsd', 'openbsd'] - # For signalfd() - epoll_dep = dependency('epoll-shim') -else - epoll_dep = [] + wl_protocol_dir = wayland_protos.get_variable('pkgdatadir') + + protocols = [ + wl_protocol_dir / 'stable/tablet/tablet-v2.xml', + wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml', + wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml', + '../protocols/wlr-layer-shell-unstable-v1.xml', + ] + + foreach xml : protocols + nag_sources += custom_target( + xml.underscorify() + '_c', + input: xml, + output: '@BASENAME@-protocol.c', + command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'], + ) + nag_sources += custom_target( + xml.underscorify() + '_client_h', + input: xml, + output: '@BASENAME@-client-protocol.h', + command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'], + ) + endforeach + + if host_machine.system() in ['freebsd', 'openbsd'] + # For signalfd() + epoll_dep = dependency('epoll-shim') + else + epoll_dep = [] + endif + + executable( + 'labnag', + nag_sources, + dependencies: [ + cairo, + pangocairo, + glib, + wayland_client, + wayland_cursor, + wlroots, + server_protos, + epoll_dep, + xkbcommon, + ], + include_directories: [labwc_inc], + install: true, + ) endif -executable( - 'labnag', - nag_sources, - dependencies: [ - cairo, - pangocairo, - glib, - wayland_client, - wayland_cursor, - wlroots, - server_protos, - epoll_dep, - xkbcommon, - ], - include_directories: [labwc_inc], - install: true, -) - clients = files('lab-sensible-terminal') install_data(clients, install_dir: get_option('bindir')) diff --git a/meson_options.txt b/meson_options.txt index a3da65a8..a47efa86 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -2,6 +2,7 @@ option('man-pages', type: 'feature', value: 'auto', description: 'Generate and i option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications') option('svg', type: 'feature', value: 'enabled', description: 'Enable svg window buttons') option('icon', type: 'feature', value: 'enabled', description: 'Enable window icons') +option('labnag', type: 'feature', value: 'auto', description: 'Build labnag notification daemon') option('nls', type: 'feature', value: 'auto', description: 'Enable native language support') option('static_analyzer', type: 'feature', value: 'disabled', description: 'Run gcc static analyzer') option('test', type: 'feature', value: 'disabled', description: 'Run tests') From 9a8154836c04765e209f77bd1e3810e2a4818324 Mon Sep 17 00:00:00 2001 From: GlassOnTin Date: Mon, 30 Mar 2026 11:56:31 +0100 Subject: [PATCH 02/14] keyboard: use XKB_CONTEXT_NO_SECURE_GETENV on Android Android's bionic libc implements secure_getenv() as a function that always returns NULL because app processes don't have AT_SECURE set. This prevents xkbcommon from reading XKB_DEFAULT_LAYOUT and other environment variables when resolving keyboard layouts. Use XKB_CONTEXT_NO_SECURE_GETENV on Android so xkbcommon falls back to regular getenv(), which works correctly in the Android app environment. --- src/input/keyboard.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/input/keyboard.c b/src/input/keyboard.c index 8e5c1f78..5a5c7595 100644 --- a/src/input/keyboard.c +++ b/src/input/keyboard.c @@ -745,7 +745,18 @@ set_layout(struct wlr_keyboard *kb) static bool fallback_mode; struct xkb_rule_names rules = { 0 }; - struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + enum xkb_context_flags ctx_flags = XKB_CONTEXT_NO_FLAGS; +#ifdef __ANDROID__ + /* + * Android's bionic libc implements secure_getenv() as a function + * that always returns NULL (the app process has no AT_SECURE). + * This prevents xkbcommon from reading XKB_DEFAULT_LAYOUT and + * friends via secure_getenv(). Use the flag to fall back to + * regular getenv() which works fine on Android. + */ + ctx_flags |= XKB_CONTEXT_NO_SECURE_GETENV; +#endif + struct xkb_context *context = xkb_context_new(ctx_flags); struct xkb_keymap *keymap = xkb_map_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); From 46d687ab5414f2bd2d55db49be14601054d2fe75 Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Mon, 30 Mar 2026 22:04:01 +0100 Subject: [PATCH 03/14] clients/labnag.c: return zero on get_text_size() error Ref: https://github.com/swaywm/sway/pull/9070 --- clients/labnag.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/clients/labnag.c b/clients/labnag.c index 237ee958..82b6e8cd 100644 --- a/clients/labnag.c +++ b/clients/labnag.c @@ -206,6 +206,16 @@ static void get_text_size(cairo_t *cairo, const PangoFontDescription *desc, int *width, int *height, int *baseline, double scale, bool markup, const char *fmt, ...) { + if (width) { + *width = 0; + } + if (height) { + *height = 0; + } + if (baseline) { + *baseline = 0; + } + va_list args; va_start(args, fmt); gchar *buf = g_strdup_vprintf(fmt, args); From 9209f611d552adbb36e59cef05aaca5d1e834efe Mon Sep 17 00:00:00 2001 From: Jens Peters Date: Tue, 31 Mar 2026 19:17:33 +0200 Subject: [PATCH 04/14] build: require libinput 1.26 Bump the requirement for having support for tablet tool pressure range configuration. --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 4b622b5e..de73e8ea 100644 --- a/meson.build +++ b/meson.build @@ -71,7 +71,7 @@ xml2 = dependency('libxml-2.0') glib = dependency('glib-2.0') cairo = dependency('cairo') pangocairo = dependency('pangocairo') -input = dependency('libinput', version: '>=1.14') +input = dependency('libinput', version: '>=1.26') pixman = dependency('pixman-1') math = cc.find_library('m') png = dependency('libpng') From 0d049552bc98a59db7c0cc62f673a83c0de67b0c Mon Sep 17 00:00:00 2001 From: Jens Peters Date: Sun, 13 Jul 2025 21:38:00 +0200 Subject: [PATCH 05/14] input: support tablet tool pressure range configuration Needs wlroots 0.20.0. --- include/config/rcxml.h | 2 ++ src/config/rcxml.c | 8 ++++++++ src/input/tablet.c | 23 +++++++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/include/config/rcxml.h b/include/config/rcxml.h index aa950234..517cd907 100644 --- a/include/config/rcxml.h +++ b/include/config/rcxml.h @@ -144,6 +144,8 @@ struct rcxml { struct tablet_tool_config { enum lab_motion motion; double relative_motion_sensitivity; + double min_pressure; + double max_pressure; } tablet_tool; /* libinput */ diff --git a/src/config/rcxml.c b/src/config/rcxml.c index 45093781..a3eeed63 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -1355,6 +1355,12 @@ entry(xmlNode *node, char *nodename, char *content) } else if (!strcasecmp(nodename, "relativeMotionSensitivity.tabletTool")) { rc.tablet_tool.relative_motion_sensitivity = tablet_get_dbl_if_positive(content, "relativeMotionSensitivity"); + } else if (!strcasecmp(nodename, "minPressure.tabletTool")) { + rc.tablet_tool.min_pressure = + tablet_get_dbl_if_positive(content, "minPressure"); + } else if (!strcasecmp(nodename, "maxPressure.tabletTool")) { + rc.tablet_tool.max_pressure = + tablet_get_dbl_if_positive(content, "maxPressure"); } else if (!strcasecmp(nodename, "ignoreButtonReleasePeriod.menu")) { rc.menu_ignore_button_release_period = atoi(content); } else if (!strcasecmp(nodename, "showIcons.menu")) { @@ -1475,6 +1481,8 @@ rcxml_init(void) tablet_load_default_button_mappings(); rc.tablet_tool.motion = LAB_MOTION_ABSOLUTE; rc.tablet_tool.relative_motion_sensitivity = 1.0; + rc.tablet_tool.min_pressure = 0.0; + rc.tablet_tool.max_pressure = 1.0; rc.repeat_rate = 25; rc.repeat_delay = 600; diff --git a/src/input/tablet.c b/src/input/tablet.c index ed596e15..a4ca0fab 100644 --- a/src/input/tablet.c +++ b/src/input/tablet.c @@ -2,11 +2,13 @@ #include "input/tablet.h" #include #include +#include "wlr/backend/libinput.h" #include #include #include #include #include +#include #include "common/macros.h" #include "common/mem.h" #include "common/scene-helpers.h" @@ -336,6 +338,27 @@ handle_tablet_tool_proximity(struct wl_listener *listener, void *data) tool = tablet_tool_create(tablet->seat, ev->tool); } + struct libinput_tablet_tool *libinput_tool = + wlr_libinput_get_tablet_tool_handle(tool->tool_v2->wlr_tool); + + /* + * Configure tool pressure range using libinput. Note that a runtime change + * needs two proximity-in events. First one is for applying the pressure range + * here and second one until it is effectively applied, probably because of + * how lininput applies pressure range changes internally. + */ + if (libinput_tablet_tool_config_pressure_range_is_available(libinput_tool) > 0 + && rc.tablet_tool.min_pressure >= 0.0 + && rc.tablet_tool.max_pressure <= 1.0) { + double min = libinput_tablet_tool_config_pressure_range_get_minimum(libinput_tool); + double max = libinput_tablet_tool_config_pressure_range_get_maximum(libinput_tool); + if (min != rc.tablet_tool.min_pressure || max != rc.tablet_tool.max_pressure) { + wlr_log(WLR_INFO, "tablet tool pressure range configured"); + libinput_tablet_tool_config_pressure_range_set(libinput_tool, + rc.tablet_tool.min_pressure, rc.tablet_tool.max_pressure); + } + } + /* * Enforce mouse emulation when the current tool is a tablet mouse. * Client support for tablet mouses in tablet mode is often incomplete From 674238caa9d56a623c3a0182a1aca75065f97cdd Mon Sep 17 00:00:00 2001 From: Jens Peters Date: Mon, 14 Jul 2025 21:50:32 +0200 Subject: [PATCH 06/14] docs: document tablet tool pressure range --- docs/labwc-config.5.scd | 13 ++++++++++++- docs/rc.xml.all | 5 ++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index 03d5fc24..09f7b3eb 100644 --- a/docs/labwc-config.5.scd +++ b/docs/labwc-config.5.scd @@ -1090,7 +1090,8 @@ Note: To rotate touch events with output rotation, use the libinput ## TABLET TOOL ``` - + ``` ** [absolute|relative] @@ -1105,6 +1106,16 @@ Note: To rotate touch events with output rotation, use the libinput speed, using a value greater than 1.0 increases the speed of the cursor. The default is "1.0". +** +** + The pressure range of a tablet tool can be controlled by adjusting + *minPressure* and *maxPressure*. Setting the minimum pressure to + a value greater than zero requires more pressure for the tip + threshold, setting the maximum pressure to a value less than 1.0 + requires less pressure for the user before the maximum is reached. + The default is 0 for the minimum pressure and 1.0 for the maximum + pressure. + ## LIBINPUT ``` diff --git a/docs/rc.xml.all b/docs/rc.xml.all index bc9566fe..bbec9d0b 100644 --- a/docs/rc.xml.all +++ b/docs/rc.xml.all @@ -573,8 +573,11 @@ *relativeMotionSensitivity* controls the speed of the cursor. Using a value lower than 1.0 decreases the speed, using a value greater than 1.0 increases the speed of the cursor. + The pressure range of a tablet tool can be controlled by adjusting + *minPressure* and *maxPressure*. --> - +