diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd
index fb98b328..9e18d764 100644
--- a/docs/labwc-config.5.scd
+++ b/docs/labwc-config.5.scd
@@ -959,6 +959,7 @@ extending outward from the snapped edge.
sticky
+
@@ -1033,6 +1034,16 @@ extending outward from the snapped edge.
drag lock, but if *yes* is set, the drag lock expires after a timeout.
Default is *sticky*.
+** [yes|no|3|4]
+ Enable or disable the three-finger drag feature. When enabled, three
+ fingers down will result in a button down event and subsequent finger
+ motions triggers a drag.
+
+ The available options are:
+ - *no* - Disable three-finger drag.
+ - *yes* | *3* - Enable three-finger drag for 3 fingers.
+ - *4* - Enable three-finger drag for 4 fingers.
+
** [yes|no]
Enable or disable middle button emulation for this category. Middle
emulation processes a simultaneous left and right click as a press of
diff --git a/docs/rc.xml.all b/docs/rc.xml.all
index c6f00f64..4d137f80 100644
--- a/docs/rc.xml.all
+++ b/docs/rc.xml.all
@@ -633,6 +633,7 @@
sticky
+
diff --git a/include/config/libinput.h b/include/config/libinput.h
index a891a33f..9de8f252 100644
--- a/include/config/libinput.h
+++ b/include/config/libinput.h
@@ -25,6 +25,7 @@ struct libinput_category {
enum libinput_config_tap_button_map tap_button_map;
int tap_and_drag; /* -1 or libinput_config_drag_state */
int drag_lock; /* -1 or libinput_config_drag_lock_state */
+ int three_finger_drag; /* -1 or libinput_config_3fg_drag_state */
int accel_profile; /* -1 or libinput_config_accel_profile */
int middle_emu; /* -1 or libinput_config_middle_emulation_state */
int dwt; /* -1 or libinput_config_dwt_state */
diff --git a/meson.build b/meson.build
index b83eb8c2..41b500b6 100644
--- a/meson.build
+++ b/meson.build
@@ -110,7 +110,7 @@ conf_data.set10('HAVE_RSVG', have_rsvg)
conf_data.set10('HAVE_LIBSFDO', have_libsfdo)
-foreach sym : ['LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY']
+foreach sym : ['LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY', 'LIBINPUT_CONFIG_3FG_DRAG_ENABLED_3FG']
conf_data.set10('HAVE_' + sym, cc.has_header_symbol('libinput.h', sym, dependencies: input))
endforeach
diff --git a/src/config/libinput.c b/src/config/libinput.c
index f7e07d3a..d6179d0f 100644
--- a/src/config/libinput.c
+++ b/src/config/libinput.c
@@ -24,6 +24,7 @@ libinput_category_init(struct libinput_category *l)
#else
l->drag_lock = -1;
#endif
+ l->three_finger_drag = -1;
l->accel_profile = -1;
l->middle_emu = -1;
l->dwt = -1;
diff --git a/src/config/rcxml.c b/src/config/rcxml.c
index b1bafcd8..717ff311 100644
--- a/src/config/rcxml.c
+++ b/src/config/rcxml.c
@@ -788,6 +788,27 @@ fill_libinput_category(char *nodename, char *content, struct parser_state *state
state->current_libinput_category->drag_lock = ret
? LIBINPUT_CONFIG_DRAG_LOCK_ENABLED
: LIBINPUT_CONFIG_DRAG_LOCK_DISABLED;
+ } else if (!strcasecmp(nodename, "threeFingerDrag")) {
+#if HAVE_LIBINPUT_CONFIG_3FG_DRAG_ENABLED_3FG
+ if (!strcmp(content, "3")) {
+ state->current_libinput_category->three_finger_drag =
+ LIBINPUT_CONFIG_3FG_DRAG_ENABLED_3FG;
+ } else if (!strcmp(content, "4")) {
+ state->current_libinput_category->three_finger_drag =
+ LIBINPUT_CONFIG_3FG_DRAG_ENABLED_4FG;
+ } else {
+ int ret = parse_bool(content, -1);
+ if (ret < 0) {
+ return;
+ }
+ state->current_libinput_category->three_finger_drag = ret
+ ? LIBINPUT_CONFIG_3FG_DRAG_ENABLED_3FG
+ : LIBINPUT_CONFIG_3FG_DRAG_DISABLED;
+ }
+#else
+ wlr_log(WLR_ERROR, " is only"
+ " supported in libinput >= 1.28");
+#endif
} else if (!strcasecmp(nodename, "accelProfile")) {
state->current_libinput_category->accel_profile =
get_accel_profile(content);
diff --git a/src/seat.c b/src/seat.c
index a88a37d1..2ba7fc5c 100644
--- a/src/seat.c
+++ b/src/seat.c
@@ -164,6 +164,17 @@ configure_libinput(struct wlr_input_device *wlr_input_device)
libinput_dev, dc->drag_lock);
}
+#if HAVE_LIBINPUT_CONFIG_3FG_DRAG_ENABLED_3FG
+ if (libinput_device_config_tap_get_finger_count(libinput_dev) <= 0
+ || dc->three_finger_drag < 0) {
+ wlr_log(WLR_INFO, "three-finger drag not configured");
+ } else {
+ wlr_log(WLR_INFO, "three-finger drag configured");
+ libinput_device_config_3fg_drag_set_enabled(
+ libinput_dev, dc->three_finger_drag);
+ }
+#endif
+
if (libinput_device_config_scroll_has_natural_scroll(libinput_dev) <= 0
|| dc->natural_scroll < 0) {
wlr_log(WLR_INFO, "natural scroll not configured");