</mouse>
+ <!--
+ Tablet buttons emulate regular mouse buttons.
+
+ The tablet *button* can be set to any of [tip|stylus|stylus2|stylus3].
+ Valid *to* mouse buttons are [left|right|middle].
+ -->
+ <tablet>
+ <map button="tip" to="left" />
+ <map button="stylus" to="right" />
+ <map button="stylus2" to="middle" />
+ </tablet>
+
<!--
The *category* element can be set to touch, touchpad, non-touch, default or
the name of a device. You can obtain device names by running *libinput
#include "common/border.h"
#include "common/buf.h"
#include "common/font.h"
+#include "config/tablet.h"
#include "config/libinput.h"
#include "resize_indicator.h"
#include "theme.h"
struct wl_list mousebinds; /* struct mousebind.link */
double scroll_factor;
+ /* graphics tablet */
+ struct tablet_config {
+ uint16_t button_map_count;
+ struct button_map_entry button_map[BUTTON_MAP_MAX];
+ } tablet;
+
/* libinput */
struct wl_list libinput_categories;
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef LABWC_TABLET_CONFIG_H
+#define LABWC_TABLET_CONFIG_H
+
+#include <stdint.h>
+
+#define BUTTON_MAP_MAX 16
+struct button_map_entry {
+ uint32_t from;
+ uint32_t to;
+};
+
+uint32_t tablet_button_from_str(const char *button);
+uint32_t mouse_button_from_str(const char *button);
+void tablet_button_mapping_add(uint32_t from, uint32_t to);
+void tablet_load_default_button_mappings(void);
+
+#endif /* LABWC_TABLET_CONFIG_H */
'keybind.c',
'session.c',
'mousebind.c',
+ 'tablet.c',
'libinput.c',
)
#include "config/keybind.h"
#include "config/libinput.h"
#include "config/mousebind.h"
+#include "config/tablet.h"
#include "config/rcxml.h"
#include "labwc.h"
#include "regions.h"
/* current <theme><font place=""></font></theme> */
static enum font_place font_place = FONT_PLACE_NONE;
+ static uint32_t button_map_from;
+
if (!nodename) {
return;
}
return;
}
+ if (!strcasecmp(nodename, "map.tablet")) {
+ button_map_from = UINT32_MAX;
+ return;
+ }
+
/* handle the rest */
if (!content) {
return;
} else {
wlr_log(WLR_ERROR, "Invalid value for <resize popupShow />");
}
+ } else if (!strcasecmp(nodename, "button.map.tablet")) {
+ button_map_from = tablet_button_from_str(content);
+ } else if (!strcasecmp(nodename, "to.map.tablet")) {
+ if (button_map_from != UINT32_MAX) {
+ uint32_t button_map_to = mouse_button_from_str(content);
+ if (button_map_to != UINT32_MAX) {
+ tablet_button_mapping_add(button_map_from, button_map_to);
+ }
+ } else {
+ wlr_log(WLR_ERROR, "Missing 'button' argument for tablet button mapping");
+ }
}
}
rc.doubleclick_time = 500;
rc.scroll_factor = 1.0;
+
+ rc.tablet.button_map_count = 0;
+ tablet_load_default_button_mappings();
+
rc.repeat_rate = 25;
rc.repeat_delay = 600;
rc.kb_numlock_enable = true;
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+#define _POSIX_C_SOURCE 200809L
+#include <linux/input-event-codes.h>
+#include <stdint.h>
+#include <strings.h>
+#include <wlr/util/log.h>
+#include "config/tablet.h"
+#include "config/rcxml.h"
+
+uint32_t tablet_button_from_str(const char *button)
+{
+ if (!strcasecmp(button, "Tip")) {
+ return BTN_TOOL_PEN;
+ } else if (!strcasecmp(button, "Stylus")) {
+ return BTN_STYLUS;
+ } else if (!strcasecmp(button, "Stylus2")) {
+ return BTN_STYLUS2;
+ } else if (!strcasecmp(button, "Stylus3")) {
+ return BTN_STYLUS3;
+ }
+ wlr_log(WLR_ERROR, "Invalid value for tablet button: %s", button);
+ return UINT32_MAX;
+}
+
+uint32_t mouse_button_from_str(const char *button)
+{
+ if (!strcasecmp(button, "Left")) {
+ return BTN_LEFT;
+ } else if (!strcasecmp(button, "Right")) {
+ return BTN_RIGHT;
+ } else if (!strcasecmp(button, "Middle")) {
+ return BTN_MIDDLE;
+ }
+ wlr_log(WLR_ERROR, "Invalid value for mouse button: %s", button);
+ return UINT32_MAX;
+}
+
+void tablet_button_mapping_add(uint32_t from, uint32_t to)
+{
+ struct button_map_entry *entry;
+ for (size_t i = 0; i < rc.tablet.button_map_count; i++) {
+ entry = &rc.tablet.button_map[i];
+ if (entry->from == from) {
+ entry->to = to;
+ wlr_log(WLR_INFO, "Overwriting button map for 0x%x with 0x%x", from, to);
+ return;
+ }
+ }
+ if (rc.tablet.button_map_count == BUTTON_MAP_MAX) {
+ wlr_log(WLR_ERROR,
+ "Failed to add button mapping: only supporting up to %u mappings",
+ BUTTON_MAP_MAX);
+ return;
+ }
+ wlr_log(WLR_INFO, "Adding button map for 0x%x with 0x%x", from, to);
+ entry = &rc.tablet.button_map[rc.tablet.button_map_count];
+ entry->from = from;
+ entry->to = to;
+ rc.tablet.button_map_count++;
+}
+
+void tablet_load_default_button_mappings(void)
+{
+ tablet_button_mapping_add(BTN_TOOL_PEN, BTN_LEFT); /* Used for the pen tip */
+ tablet_button_mapping_add(BTN_STYLUS, BTN_RIGHT);
+ tablet_button_mapping_add(BTN_STYLUS2, BTN_MIDDLE);
+}