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")) {
/*
* First we try to get a type based on a number of
* pre-defined terms, for example: 'default', 'touch',
* 'touchpad' and 'non-touch'
*/
category->type = get_device_type(content);
if (!state->current_libinput_category) { /*
return; * If we couldn't match against any of those terms, we
} * use the provided value to define the device name
* that the settings should be applicable to.
string_truncate_at_pattern(nodename, ".device.libinput"); */
if (category->type == LAB_LIBINPUT_DEVICE_NONE) {
if (!strcmp(nodename, "category")) { xstrdup_replace(category->name, content);
/* }
* First we try to get a type based on a number of pre-defined } else if (!strcasecmp(key, "naturalScroll")) {
* terms, for example: 'default', 'touch', 'touchpad' and set_bool_as_int(content, &category->natural_scroll);
* 'non-touch' } else if (!strcasecmp(key, "leftHanded")) {
*/ set_bool_as_int(content, &category->left_handed);
state->current_libinput_category->type = get_device_type(content); } else if (!strcasecmp(key, "pointerSpeed")) {
set_float(content, &category->pointer_speed);
/* if (category->pointer_speed < -1) {
* If we couldn't match against any of those terms, we use the category->pointer_speed = -1;
* provided value to define the device name that the settings } else if (category->pointer_speed > 1) {
* should be applicable to. category->pointer_speed = 1;
*/ }
if (state->current_libinput_category->type == LAB_LIBINPUT_DEVICE_NONE) { } else if (!strcasecmp(key, "tap")) {
xstrdup_replace(state->current_libinput_category->name, content); int ret = parse_bool(content, -1);
} if (ret < 0) {
} else if (!strcasecmp(nodename, "naturalScroll")) { continue;
set_bool_as_int(content, &state->current_libinput_category->natural_scroll); }
} else if (!strcasecmp(nodename, "leftHanded")) { category->tap = ret
set_bool_as_int(content, &state->current_libinput_category->left_handed); ? LIBINPUT_CONFIG_TAP_ENABLED
} else if (!strcasecmp(nodename, "pointerSpeed")) { : LIBINPUT_CONFIG_TAP_DISABLED;
set_float(content, &state->current_libinput_category->pointer_speed); } else if (!strcasecmp(key, "tapButtonMap")) {
if (state->current_libinput_category->pointer_speed < -1) { if (!strcmp(content, "lrm")) {
state->current_libinput_category->pointer_speed = -1; category->tap_button_map =
} else if (state->current_libinput_category->pointer_speed > 1) { LIBINPUT_CONFIG_TAP_MAP_LRM;
state->current_libinput_category->pointer_speed = 1; } else if (!strcmp(content, "lmr")) {
} category->tap_button_map =
} else if (!strcasecmp(nodename, "tap")) { LIBINPUT_CONFIG_TAP_MAP_LMR;
int ret = parse_bool(content, -1); } else {
if (ret < 0) { wlr_log(WLR_ERROR, "invalid tapButtonMap");
return; }
} } else if (!strcasecmp(key, "tapAndDrag")) {
state->current_libinput_category->tap = ret int ret = parse_bool(content, -1);
? LIBINPUT_CONFIG_TAP_ENABLED if (ret < 0) {
: LIBINPUT_CONFIG_TAP_DISABLED; continue;
} else if (!strcasecmp(nodename, "tapButtonMap")) { }
if (!strcmp(content, "lrm")) { category->tap_and_drag = ret
state->current_libinput_category->tap_button_map = ? LIBINPUT_CONFIG_DRAG_ENABLED
LIBINPUT_CONFIG_TAP_MAP_LRM; : LIBINPUT_CONFIG_DRAG_DISABLED;
} else if (!strcmp(content, "lmr")) { } else if (!strcasecmp(key, "dragLock")) {
state->current_libinput_category->tap_button_map = if (!strcasecmp(content, "timeout")) {
LIBINPUT_CONFIG_TAP_MAP_LMR; /* "timeout" enables drag-lock with timeout */
} else { category->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED;
wlr_log(WLR_ERROR, "invalid tapButtonMap"); continue;
} }
} else if (!strcasecmp(nodename, "tapAndDrag")) { int ret = parse_bool(content, -1);
int ret = parse_bool(content, -1); if (ret < 0) {
if (ret < 0) { continue;
return; }
} /* "yes" enables drag-lock, without timeout if libinput >= 1.27 */
state->current_libinput_category->tap_and_drag = ret int enabled = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED;
? LIBINPUT_CONFIG_DRAG_ENABLED
: LIBINPUT_CONFIG_DRAG_DISABLED;
} else if (!strcasecmp(nodename, "dragLock")) {
if (!strcasecmp(content, "timeout")) {
/* "timeout" enables drag-lock with timeout */
state->current_libinput_category->drag_lock =
LIBINPUT_CONFIG_DRAG_LOCK_ENABLED;
return;
}
int ret = parse_bool(content, -1);
if (ret < 0) {
return;
}
/* "yes" enables drag-lock, without timeout if libinput >= 1.27 */
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
? LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED
: LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED;
} else if (!strcasecmp(nodename, "disableWhileTyping")) {
int ret = parse_bool(content, -1);
if (ret < 0) {
return;
}
state->current_libinput_category->dwt = ret
? LIBINPUT_CONFIG_DWT_ENABLED
: LIBINPUT_CONFIG_DWT_DISABLED;
} else if (!strcasecmp(nodename, "clickMethod")) {
if (!strcasecmp(content, "none")) {
state->current_libinput_category->click_method =
LIBINPUT_CONFIG_CLICK_METHOD_NONE;
} else if (!strcasecmp(content, "clickfinger")) {
state->current_libinput_category->click_method =
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
} else if (!strcasecmp(content, "buttonAreas")) {
state->current_libinput_category->click_method =
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
} else {
wlr_log(WLR_ERROR, "invalid clickMethod");
}
} else if (!strcasecmp(nodename, "scrollMethod")) {
if (!strcasecmp(content, "none")) {
state->current_libinput_category->scroll_method =
LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
} else if (!strcasecmp(content, "edge")) {
state->current_libinput_category->scroll_method =
LIBINPUT_CONFIG_SCROLL_EDGE;
} else if (!strcasecmp(content, "twofinger")) {
state->current_libinput_category->scroll_method =
LIBINPUT_CONFIG_SCROLL_2FG;
} else {
wlr_log(WLR_ERROR, "invalid scrollMethod");
}
} else if (!strcasecmp(nodename, "sendEventsMode")) {
state->current_libinput_category->send_events_mode =
get_send_events_mode(content);
} else if (!strcasecmp(nodename, "calibrationMatrix")) {
errno = 0;
state->current_libinput_category->have_calibration_matrix = true;
float *mat = state->current_libinput_category->calibration_matrix;
gchar **elements = g_strsplit(content, " ", -1);
guint i = 0;
for (; elements[i]; ++i) {
char *end_str = NULL;
mat[i] = strtof(elements[i], &end_str);
if (errno == ERANGE || *end_str != '\0' || i == 6 || *elements[i] == '\0') {
wlr_log(WLR_ERROR, "invalid calibration matrix element"
" %s (index %d), expect six floats",
elements[i], i);
state->current_libinput_category->have_calibration_matrix = false;
errno = 0;
break;
} }
category->middle_emu = ret
? LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED
: LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED;
} else if (!strcasecmp(key, "disableWhileTyping")) {
int ret = parse_bool(content, -1);
if (ret < 0) {
continue;
}
category->dwt = ret
? LIBINPUT_CONFIG_DWT_ENABLED
: LIBINPUT_CONFIG_DWT_DISABLED;
} else if (!strcasecmp(key, "clickMethod")) {
if (!strcasecmp(content, "none")) {
category->click_method =
LIBINPUT_CONFIG_CLICK_METHOD_NONE;
} else if (!strcasecmp(content, "clickfinger")) {
category->click_method =
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
} else if (!strcasecmp(content, "buttonAreas")) {
category->click_method =
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
} else {
wlr_log(WLR_ERROR, "invalid clickMethod");
}
} else if (!strcasecmp(key, "scrollMethod")) {
if (!strcasecmp(content, "none")) {
category->scroll_method =
LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
} else if (!strcasecmp(content, "edge")) {
category->scroll_method =
LIBINPUT_CONFIG_SCROLL_EDGE;
} else if (!strcasecmp(content, "twofinger")) {
category->scroll_method =
LIBINPUT_CONFIG_SCROLL_2FG;
} else {
wlr_log(WLR_ERROR, "invalid scrollMethod");
}
} else if (!strcasecmp(key, "sendEventsMode")) {
category->send_events_mode =
get_send_events_mode(content);
} else if (!strcasecmp(key, "calibrationMatrix")) {
errno = 0;
category->have_calibration_matrix = true;
float *mat = category->calibration_matrix;
gchar **elements = g_strsplit(content, " ", -1);
guint i = 0;
for (; elements[i]; ++i) {
char *end_str = NULL;
mat[i] = strtof(elements[i], &end_str);
if (errno == ERANGE || *end_str != '\0' || i == 6
|| *elements[i] == '\0') {
wlr_log(WLR_ERROR, "invalid calibration "
"matrix element %s (index %d), "
"expect six floats", elements[i], i);
category->have_calibration_matrix = false;
errno = 0;
break;
}
}
if (i != 6 && category->have_calibration_matrix) {
wlr_log(WLR_ERROR, "wrong number of calibration "
"matrix elements, expected 6, got %d", i);
category->have_calibration_matrix = false;
}
g_strfreev(elements);
} else if (!strcasecmp(key, "scrollFactor")) {
set_double(content, &category->scroll_factor);
} }
if (i != 6 && state->current_libinput_category->have_calibration_matrix) {
wlr_log(WLR_ERROR, "wrong number of calibration matrix elements,"
" expected 6, got %d", i);
state->current_libinput_category->have_calibration_matrix = false;
}
g_strfreev(elements);
} else if (!strcasecmp(nodename, "scrollFactor")) {
set_double(content, &state->current_libinput_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) {