rcxml: rewrite <libinput> parser

This commit is contained in:
tokyo4j 2025-04-12 01:40:39 +09:00 committed by Johan Malm
parent 7adbfe88aa
commit a0d2e6a64b

View file

@ -700,112 +700,102 @@ err:
} }
static void static void
fill_libinput_category(char *nodename, char *content, struct parser_state *state) fill_libinput_category(xmlNode *node)
{ {
/* /*
* Create a new profile (libinput-category) on `<libinput><device>` * Create a new profile (libinput-category) on `<libinput><device>`
* so that the 'default' profile can be created without even providing a * so that the 'default' profile can be created without even providing a
* category="" attribute (same as <device category="default">...) * category="" attribute (same as <device category="default">...)
*/ */
if (!strcmp(nodename, "device.libinput")) { struct libinput_category *category = libinput_category_create();
state->current_libinput_category = libinput_category_create();
}
if (!content) { xmlNode *child;
return; char *key, *content;
} LAB_XML_FOR_EACH(node, child, key, content) {
if (!strcmp(key, "category")) {
if (!state->current_libinput_category) {
return;
}
string_truncate_at_pattern(nodename, ".device.libinput");
if (!strcmp(nodename, "category")) {
/* /*
* First we try to get a type based on a number of pre-defined * First we try to get a type based on a number of
* terms, for example: 'default', 'touch', 'touchpad' and * pre-defined terms, for example: 'default', 'touch',
* 'non-touch' * 'touchpad' and 'non-touch'
*/ */
state->current_libinput_category->type = get_device_type(content); category->type = get_device_type(content);
/* /*
* If we couldn't match against any of those terms, we use the * If we couldn't match against any of those terms, we
* provided value to define the device name that the settings * use the provided value to define the device name
* should be applicable to. * that the settings should be applicable to.
*/ */
if (state->current_libinput_category->type == LAB_LIBINPUT_DEVICE_NONE) { if (category->type == LAB_LIBINPUT_DEVICE_NONE) {
xstrdup_replace(state->current_libinput_category->name, content); xstrdup_replace(category->name, content);
} }
} else if (!strcasecmp(nodename, "naturalScroll")) { } else if (!strcasecmp(key, "naturalScroll")) {
set_bool_as_int(content, &state->current_libinput_category->natural_scroll); set_bool_as_int(content, &category->natural_scroll);
} else if (!strcasecmp(nodename, "leftHanded")) { } else if (!strcasecmp(key, "leftHanded")) {
set_bool_as_int(content, &state->current_libinput_category->left_handed); set_bool_as_int(content, &category->left_handed);
} else if (!strcasecmp(nodename, "pointerSpeed")) { } else if (!strcasecmp(key, "pointerSpeed")) {
set_float(content, &state->current_libinput_category->pointer_speed); set_float(content, &category->pointer_speed);
if (state->current_libinput_category->pointer_speed < -1) { if (category->pointer_speed < -1) {
state->current_libinput_category->pointer_speed = -1; category->pointer_speed = -1;
} else if (state->current_libinput_category->pointer_speed > 1) { } else if (category->pointer_speed > 1) {
state->current_libinput_category->pointer_speed = 1; category->pointer_speed = 1;
} }
} else if (!strcasecmp(nodename, "tap")) { } else if (!strcasecmp(key, "tap")) {
int ret = parse_bool(content, -1); int ret = parse_bool(content, -1);
if (ret < 0) { if (ret < 0) {
return; continue;
} }
state->current_libinput_category->tap = ret category->tap = ret
? LIBINPUT_CONFIG_TAP_ENABLED ? LIBINPUT_CONFIG_TAP_ENABLED
: LIBINPUT_CONFIG_TAP_DISABLED; : LIBINPUT_CONFIG_TAP_DISABLED;
} else if (!strcasecmp(nodename, "tapButtonMap")) { } else if (!strcasecmp(key, "tapButtonMap")) {
if (!strcmp(content, "lrm")) { if (!strcmp(content, "lrm")) {
state->current_libinput_category->tap_button_map = category->tap_button_map =
LIBINPUT_CONFIG_TAP_MAP_LRM; LIBINPUT_CONFIG_TAP_MAP_LRM;
} else if (!strcmp(content, "lmr")) { } else if (!strcmp(content, "lmr")) {
state->current_libinput_category->tap_button_map = category->tap_button_map =
LIBINPUT_CONFIG_TAP_MAP_LMR; LIBINPUT_CONFIG_TAP_MAP_LMR;
} else { } else {
wlr_log(WLR_ERROR, "invalid tapButtonMap"); wlr_log(WLR_ERROR, "invalid tapButtonMap");
} }
} else if (!strcasecmp(nodename, "tapAndDrag")) { } else if (!strcasecmp(key, "tapAndDrag")) {
int ret = parse_bool(content, -1); int ret = parse_bool(content, -1);
if (ret < 0) { if (ret < 0) {
return; continue;
} }
state->current_libinput_category->tap_and_drag = ret category->tap_and_drag = ret
? LIBINPUT_CONFIG_DRAG_ENABLED ? LIBINPUT_CONFIG_DRAG_ENABLED
: LIBINPUT_CONFIG_DRAG_DISABLED; : LIBINPUT_CONFIG_DRAG_DISABLED;
} else if (!strcasecmp(nodename, "dragLock")) { } else if (!strcasecmp(key, "dragLock")) {
if (!strcasecmp(content, "timeout")) { if (!strcasecmp(content, "timeout")) {
/* "timeout" enables drag-lock with timeout */ /* "timeout" enables drag-lock with timeout */
state->current_libinput_category->drag_lock = category->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED;
LIBINPUT_CONFIG_DRAG_LOCK_ENABLED; continue;
return;
} }
int ret = parse_bool(content, -1); int ret = parse_bool(content, -1);
if (ret < 0) { if (ret < 0) {
return; continue;
} }
/* "yes" enables drag-lock, without timeout if libinput >= 1.27 */ /* "yes" enables drag-lock, without timeout if libinput >= 1.27 */
int enabled = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED; int enabled = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED;
#if HAVE_LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY #if HAVE_LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY
enabled = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY; enabled = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY;
#endif #endif
state->current_libinput_category->drag_lock = ret ? category->drag_lock = ret ?
enabled : LIBINPUT_CONFIG_DRAG_LOCK_DISABLED; enabled : LIBINPUT_CONFIG_DRAG_LOCK_DISABLED;
} else if (!strcasecmp(nodename, "threeFingerDrag")) { } else if (!strcasecmp(key, "threeFingerDrag")) {
#if HAVE_LIBINPUT_CONFIG_3FG_DRAG_ENABLED_3FG #if HAVE_LIBINPUT_CONFIG_3FG_DRAG_ENABLED_3FG
if (!strcmp(content, "3")) { if (!strcmp(content, "3")) {
state->current_libinput_category->three_finger_drag = category->three_finger_drag =
LIBINPUT_CONFIG_3FG_DRAG_ENABLED_3FG; LIBINPUT_CONFIG_3FG_DRAG_ENABLED_3FG;
} else if (!strcmp(content, "4")) { } else if (!strcmp(content, "4")) {
state->current_libinput_category->three_finger_drag = category->three_finger_drag =
LIBINPUT_CONFIG_3FG_DRAG_ENABLED_4FG; LIBINPUT_CONFIG_3FG_DRAG_ENABLED_4FG;
} else { } else {
int ret = parse_bool(content, -1); int ret = parse_bool(content, -1);
if (ret < 0) { if (ret < 0) {
return; continue;
} }
state->current_libinput_category->three_finger_drag = ret category->three_finger_drag = ret
? LIBINPUT_CONFIG_3FG_DRAG_ENABLED_3FG ? LIBINPUT_CONFIG_3FG_DRAG_ENABLED_3FG
: LIBINPUT_CONFIG_3FG_DRAG_DISABLED; : LIBINPUT_CONFIG_3FG_DRAG_DISABLED;
} }
@ -813,80 +803,82 @@ fill_libinput_category(char *nodename, char *content, struct parser_state *state
wlr_log(WLR_ERROR, "<threeFingerDrag> is only" wlr_log(WLR_ERROR, "<threeFingerDrag> is only"
" supported in libinput >= 1.28"); " supported in libinput >= 1.28");
#endif #endif
} else if (!strcasecmp(nodename, "accelProfile")) { } else if (!strcasecmp(key, "accelProfile")) {
state->current_libinput_category->accel_profile = category->accel_profile =
get_accel_profile(content); get_accel_profile(content);
} else if (!strcasecmp(nodename, "middleEmulation")) { } else if (!strcasecmp(key, "middleEmulation")) {
int ret = parse_bool(content, -1); int ret = parse_bool(content, -1);
if (ret < 0) { if (ret < 0) {
return; continue;
} }
state->current_libinput_category->middle_emu = ret category->middle_emu = ret
? LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED ? LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED
: LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED; : LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED;
} else if (!strcasecmp(nodename, "disableWhileTyping")) { } else if (!strcasecmp(key, "disableWhileTyping")) {
int ret = parse_bool(content, -1); int ret = parse_bool(content, -1);
if (ret < 0) { if (ret < 0) {
return; continue;
} }
state->current_libinput_category->dwt = ret category->dwt = ret
? LIBINPUT_CONFIG_DWT_ENABLED ? LIBINPUT_CONFIG_DWT_ENABLED
: LIBINPUT_CONFIG_DWT_DISABLED; : LIBINPUT_CONFIG_DWT_DISABLED;
} else if (!strcasecmp(nodename, "clickMethod")) { } else if (!strcasecmp(key, "clickMethod")) {
if (!strcasecmp(content, "none")) { if (!strcasecmp(content, "none")) {
state->current_libinput_category->click_method = category->click_method =
LIBINPUT_CONFIG_CLICK_METHOD_NONE; LIBINPUT_CONFIG_CLICK_METHOD_NONE;
} else if (!strcasecmp(content, "clickfinger")) { } else if (!strcasecmp(content, "clickfinger")) {
state->current_libinput_category->click_method = category->click_method =
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER; LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
} else if (!strcasecmp(content, "buttonAreas")) { } else if (!strcasecmp(content, "buttonAreas")) {
state->current_libinput_category->click_method = category->click_method =
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
} else { } else {
wlr_log(WLR_ERROR, "invalid clickMethod"); wlr_log(WLR_ERROR, "invalid clickMethod");
} }
} else if (!strcasecmp(nodename, "scrollMethod")) { } else if (!strcasecmp(key, "scrollMethod")) {
if (!strcasecmp(content, "none")) { if (!strcasecmp(content, "none")) {
state->current_libinput_category->scroll_method = category->scroll_method =
LIBINPUT_CONFIG_SCROLL_NO_SCROLL; LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
} else if (!strcasecmp(content, "edge")) { } else if (!strcasecmp(content, "edge")) {
state->current_libinput_category->scroll_method = category->scroll_method =
LIBINPUT_CONFIG_SCROLL_EDGE; LIBINPUT_CONFIG_SCROLL_EDGE;
} else if (!strcasecmp(content, "twofinger")) { } else if (!strcasecmp(content, "twofinger")) {
state->current_libinput_category->scroll_method = category->scroll_method =
LIBINPUT_CONFIG_SCROLL_2FG; LIBINPUT_CONFIG_SCROLL_2FG;
} else { } else {
wlr_log(WLR_ERROR, "invalid scrollMethod"); wlr_log(WLR_ERROR, "invalid scrollMethod");
} }
} else if (!strcasecmp(nodename, "sendEventsMode")) { } else if (!strcasecmp(key, "sendEventsMode")) {
state->current_libinput_category->send_events_mode = category->send_events_mode =
get_send_events_mode(content); get_send_events_mode(content);
} else if (!strcasecmp(nodename, "calibrationMatrix")) { } else if (!strcasecmp(key, "calibrationMatrix")) {
errno = 0; errno = 0;
state->current_libinput_category->have_calibration_matrix = true; category->have_calibration_matrix = true;
float *mat = state->current_libinput_category->calibration_matrix; float *mat = category->calibration_matrix;
gchar **elements = g_strsplit(content, " ", -1); gchar **elements = g_strsplit(content, " ", -1);
guint i = 0; guint i = 0;
for (; elements[i]; ++i) { for (; elements[i]; ++i) {
char *end_str = NULL; char *end_str = NULL;
mat[i] = strtof(elements[i], &end_str); mat[i] = strtof(elements[i], &end_str);
if (errno == ERANGE || *end_str != '\0' || i == 6 || *elements[i] == '\0') { if (errno == ERANGE || *end_str != '\0' || i == 6
wlr_log(WLR_ERROR, "invalid calibration matrix element" || *elements[i] == '\0') {
" %s (index %d), expect six floats", wlr_log(WLR_ERROR, "invalid calibration "
elements[i], i); "matrix element %s (index %d), "
state->current_libinput_category->have_calibration_matrix = false; "expect six floats", elements[i], i);
category->have_calibration_matrix = false;
errno = 0; errno = 0;
break; break;
} }
} }
if (i != 6 && state->current_libinput_category->have_calibration_matrix) { if (i != 6 && category->have_calibration_matrix) {
wlr_log(WLR_ERROR, "wrong number of calibration matrix elements," wlr_log(WLR_ERROR, "wrong number of calibration "
" expected 6, got %d", i); "matrix elements, expected 6, got %d", i);
state->current_libinput_category->have_calibration_matrix = false; category->have_calibration_matrix = false;
} }
g_strfreev(elements); g_strfreev(elements);
} else if (!strcasecmp(nodename, "scrollFactor")) { } else if (!strcasecmp(key, "scrollFactor")) {
set_double(content, &state->current_libinput_category->scroll_factor); set_double(content, &category->scroll_factor);
}
} }
} }
@ -1061,8 +1053,8 @@ entry(xmlNode *node, char *nodename, char *content, struct parser_state *state)
fill_touch(node); fill_touch(node);
return; return;
} }
if (state->in_libinput_category) { if (!strcasecmp(nodename, "device.libinput")) {
fill_libinput_category(nodename, content, state); fill_libinput_category(node);
return; return;
} }
if (state->in_regions) { if (state->in_regions) {