config: add tablet button mapping configuration

Co-authored-by: Consolatis <35009135+Consolatis@users.noreply.github.com>
This commit is contained in:
Jens Peters 2023-12-29 10:06:17 +01:00 committed by Johan Malm
parent f0b72e3af7
commit 567b81ea10
6 changed files with 128 additions and 0 deletions

View file

@ -393,6 +393,18 @@
</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

View file

@ -9,6 +9,7 @@
#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"
@ -80,6 +81,12 @@ struct rcxml {
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;

18
include/config/tablet.h Normal file
View file

@ -0,0 +1,18 @@
/* 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 */

View file

@ -3,5 +3,6 @@ labwc_sources += files(
'keybind.c',
'session.c',
'mousebind.c',
'tablet.c',
'libinput.c',
)

View file

@ -23,6 +23,7 @@
#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"
@ -615,6 +616,8 @@ entry(xmlNode *node, char *nodename, char *content)
/* current <theme><font place=""></font></theme> */
static enum font_place font_place = FONT_PLACE_NONE;
static uint32_t button_map_from;
if (!nodename) {
return;
}
@ -683,6 +686,11 @@ entry(xmlNode *node, char *nodename, char *content)
return;
}
if (!strcasecmp(nodename, "map.tablet")) {
button_map_from = UINT32_MAX;
return;
}
/* handle the rest */
if (!content) {
return;
@ -818,6 +826,17 @@ entry(xmlNode *node, char *nodename, char *content)
} 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");
}
}
}
@ -977,6 +996,10 @@ rcxml_init(void)
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;

67
src/config/tablet.c Normal file
View file

@ -0,0 +1,67 @@
// 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);
}