diff --git a/CODING_STYLE b/CODING_STYLE index 1a64ffe6..3648a4e2 100644 --- a/CODING_STYLE +++ b/CODING_STYLE @@ -62,6 +62,17 @@ useit(c); } +- if/else: { on the same line, no curly braces if both blocks are a single + statement. If either if or else block are multiple statements, both must + have curly braces. + + if (foo) { + blah(); + bar(); + } else { + a = 10; + } + - public functions MUST be doxygen-commented, use doxygen's @foo rather than \foo notation diff --git a/doc/tapping.dox b/doc/tapping.dox index 1337fc53..483219ad 100644 --- a/doc/tapping.dox +++ b/doc/tapping.dox @@ -29,17 +29,24 @@ libinput also supports "tap-and-drag" where a tap immediately followed by a finger down and that finger being held down emulates a button press. Moving the finger around can thus drag the selected item on the screen. +Optional is a feature called "drag lock". With drag lock disabled, lifting +the finger will stop any drag process. When enabled, libinput will ignore a +finger up event during a drag process, provided the finger is set down again +within a implementation-specific timeout. Drag lock can be enabled and +disabled with libinput_device_config_tap_set_drag_lock_enabled(). + @image html tap-n-drag.svg "Tap-and-drag process" The above diagram explains the process, a tap (a) followed by a finger held down (b) starts the drag process and logically holds the left mouse button down. A movement of the finger (c) will drag the selected item until the -finger is relased (e). If needed, the finger's position can be reset by -lifting and quickly setting it down again on the touchpad (d). This will be -interpreted as continuing move and is especially useful on small touchpads -or with slow pointer acceleration. -The release of the mouse buttons after the finger release (e) is triggered -by a timeout. To release the button immediately, simply tap again (f). +finger is relased (e). If needed and drag lock is enabled, the finger's +position can be reset by lifting and quickly setting it down again on the +touchpad (d). This will be interpreted as continuing move and is especially +useful on small touchpads or with slow pointer acceleration. +If drag lock is enabled, the release of the mouse buttons after the finger +release (e) is triggered by a timeout. To release the button immediately, +simply tap again (f). If two fingers are supported by the hardware, a second finger can be used to drag while the first is held in-place. diff --git a/doc/touchpad-tap-state-machine.svg b/doc/touchpad-tap-state-machine.svg index 39b0b86b..89c34fa0 100644 --- a/doc/touchpad-tap-state-machine.svg +++ b/doc/touchpad-tap-state-machine.svg @@ -1,16 +1,14 @@ - - - - - - - - + + + + + + @@ -28,15 +26,15 @@ finger down - - + + finger up - - + + @@ -49,8 +47,8 @@ timeout - - + + @@ -58,8 +56,8 @@ threshold - - + + @@ -67,8 +65,8 @@ finger down - - + + @@ -81,8 +79,8 @@ finger up - - + + @@ -102,10 +100,10 @@ timeout - - - - + + + + @@ -120,10 +118,10 @@ release - - - - + + + + @@ -134,8 +132,8 @@ timeout - - + + @@ -143,8 +141,8 @@ finger down - - + + @@ -157,19 +155,19 @@ finger up - + - + btn1 - + release - - + + - - + + @@ -182,15 +180,15 @@ finger down - - + + TOUCH_3 - - + + @@ -214,8 +212,8 @@ threshold - - + + @@ -226,8 +224,8 @@ timeout - - + + @@ -235,8 +233,8 @@ finger up - - + + @@ -249,24 +247,24 @@ finger down - - - - + + + + DRAGGING_OR_DOUBLETAP - - + + timeout - - + + @@ -274,8 +272,8 @@ finger up - - + + @@ -297,8 +295,8 @@ release - - + + @@ -306,8 +304,8 @@ finger down - - + + @@ -315,10 +313,10 @@ threshold - - - - + + + + @@ -331,10 +329,10 @@ finger up - - - - + + + + @@ -342,12 +340,12 @@ finger down - - - - - - + + + + + + @@ -360,8 +358,8 @@ finger up - - + + @@ -369,11 +367,11 @@ finger up - - - + + + - + @@ -382,19 +380,19 @@ finger down - - - - - - + + + + + + TOUCH_3_HOLD - - + + @@ -407,12 +405,12 @@ DEAD - - - - - - + + + + + + @@ -430,13 +428,13 @@ any finger up - - - - + + + + - - + + yes @@ -444,14 +442,14 @@ any finger up - - - - - - - - + + + + + + + + @@ -464,12 +462,12 @@ count == 0 - - - - - - + + + + + + @@ -482,10 +480,10 @@ DRAGGING_2 - - - - + + + + @@ -493,12 +491,12 @@ finger up - - - - - - + + + + + + @@ -506,12 +504,12 @@ finger down - - - - - - + + + + + + @@ -519,8 +517,8 @@ finger down - - + + @@ -528,8 +526,8 @@ release - - + + @@ -539,18 +537,18 @@ press - - - - - - - - - + + + + + + + + + - - + + @@ -560,8 +558,8 @@ press - - + + @@ -569,41 +567,41 @@ release - - - - - - - - - - - + + + + + + + + + + + - + DRAGGING_WAIT - + - + timeout - - - - - - - + + + + + + + - + first - + finger down - - + + @@ -614,31 +612,31 @@ TOUCH_IDLE - - - - - - - - + + + + + + + + TOUCH_DEAD - - - - - - - - + + + + + + + + - + yes @@ -647,56 +645,56 @@ TOUCH_DEAD - - - - - - + + + + + + TOUCH_IDLE - - + + TOUCH_TOUCH - - - - + + + + TOUCH_IDLE - - + + TOUCH_IDLE - - + + TOUCH_IDLE - - + + TOUCH_TOUCH - - + + @@ -704,19 +702,19 @@ TOUCH_IDLE - - + + TOUCH_DEAD - - - - - - + + + + + + @@ -724,13 +722,13 @@ TOUCH_IDLE - - - - + + + + - - + + no @@ -738,8 +736,8 @@ TOUCH_TOUCH - - + + @@ -750,24 +748,24 @@ TOUCH_TOUCH - - + + TOUCH_DEAD - - - - + + + + TOUCH_IDLE - - + + @@ -778,43 +776,43 @@ TOUCH_TOUCH - - + + TOUCH_IDLE - - + + TOUCH_IDLE - - + + TOUCH_TOUCH - - + + TOUCH_IDLE - - + + TOUCH_TOUCH - - + + @@ -822,8 +820,8 @@ TOUCH_IDLE - - + + @@ -846,22 +844,22 @@ TOUCH_DEAD - - + + TOUCH_DEAD - - + + TOUCH_DEAD - - + + @@ -876,11 +874,11 @@ TOUCH_TOUCH - - + + - - + + no @@ -888,8 +886,8 @@ TOUCH_DEAD - - + + @@ -912,30 +910,30 @@ MULTITAP - - - - + + + + timeout - - - - + + + + IDLE - - - - - - + + + + + + @@ -948,10 +946,10 @@ press - - - - + + + + @@ -959,8 +957,8 @@ finger up - - + + @@ -968,8 +966,8 @@ release - - + + @@ -989,12 +987,12 @@ threshold - - - - - - + + + + + + @@ -1009,12 +1007,12 @@ press - - - - - - + + + + + + @@ -1029,12 +1027,12 @@ press - - - - - - + + + + + + @@ -1049,28 +1047,28 @@ press - - - - - - - - + + + + + + + + TOUCH_TOUCH - - + + TOUCH_IDLE - - + + @@ -1080,12 +1078,12 @@ press - - - - - - + + + + + + @@ -1098,17 +1096,17 @@ finger up - - + + timeout - - - - + + + + @@ -1116,26 +1114,70 @@ threshold - - - - - - - - - - + + + + + + + + + + TOUCH_IDLE - - - - - - + + + + + + + + + + +
+
+ drag lock
+ enabled?
+
+
+
+ + [Not supported by viewer] +
+
+ + + + + +
+
+ no
+
+
+ + [Not supported by viewer] +
+
+ + + + + +
+
+ yes
+
+
+
+ + [Not supported by viewer] +
+
diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c index 8d4e278e..9c1c096c 100644 --- a/src/evdev-mt-touchpad-buttons.c +++ b/src/evdev-mt-touchpad-buttons.c @@ -527,8 +527,8 @@ tp_init_softbuttons(struct tp_dispatch *tp, xoffset = absinfo_x->minimum, yoffset = absinfo_y->minimum; yres = absinfo_y->resolution; - width = abs(absinfo_x->maximum - absinfo_x->minimum); - height = abs(absinfo_y->maximum - absinfo_y->minimum); + width = device->abs.dimensions.x; + height = device->abs.dimensions.y; /* button height: 10mm or 15% of the touchpad height, whichever is smaller */ @@ -558,8 +558,8 @@ tp_init_top_softbuttons(struct tp_dispatch *tp, xoffset = absinfo_x->minimum, yoffset = absinfo_y->minimum; yres = absinfo_y->resolution; - width = abs(absinfo_x->maximum - absinfo_x->minimum); - height = abs(absinfo_y->maximum - absinfo_y->minimum); + width = device->abs.dimensions.x; + height = device->abs.dimensions.y; if (tp->buttons.has_topbuttons) { /* T440s has the top button line 5mm from the top, event @@ -741,9 +741,9 @@ tp_init_buttons(struct tp_dispatch *tp, /* pinned-finger motion threshold, see tp_unpin_finger. The MAGIC for resolution-less touchpads ends up as 2% of the diagonal */ if (device->abs.fake_resolution) { - const int BUTTON_MOTION_MAGIC = 0.007; - width = abs(absinfo_x->maximum - absinfo_x->minimum); - height = abs(absinfo_y->maximum - absinfo_y->minimum); + const double BUTTON_MOTION_MAGIC = 0.007; + width = device->abs.dimensions.x; + height = device->abs.dimensions.y; diagonal = sqrt(width*width + height*height); tp->buttons.motion_dist.x_scale_coeff = diagonal * BUTTON_MOTION_MAGIC; tp->buttons.motion_dist.y_scale_coeff = diagonal * BUTTON_MOTION_MAGIC; @@ -838,10 +838,8 @@ tp_check_clickfinger_distance(struct tp_dispatch *tp, /* Use a maximum of 30% of the touchpad width or height if * we dont' have resolution. */ - w = tp->device->abs.absinfo_x->maximum - - tp->device->abs.absinfo_x->minimum; - h = tp->device->abs.absinfo_y->maximum - - tp->device->abs.absinfo_y->minimum; + w = tp->device->abs.dimensions.x; + h = tp->device->abs.dimensions.y; return (x < w * 0.3 && y < h * 0.3) ? 1 : 0; } else { diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c index 56f1e8a0..9a9d3b84 100644 --- a/src/evdev-mt-touchpad-edge-scroll.c +++ b/src/evdev-mt-touchpad-edge-scroll.c @@ -39,7 +39,7 @@ avoid accidentally locking in scrolling mode when trying to use the entire touchpad to move the pointer. The user can wait for the timeout to trigger to do a small scroll. */ -#define DEFAULT_SCROLL_THRESHOLD TP_MM_TO_DPI_NORMALIZED(5) +#define DEFAULT_SCROLL_THRESHOLD TP_MM_TO_DPI_NORMALIZED(3) enum scroll_event { SCROLL_EVENT_TOUCH, @@ -275,8 +275,8 @@ tp_edge_scroll_init(struct tp_dispatch *tp, struct evdev_device *device) int width, height; int edge_width, edge_height; - width = device->abs.absinfo_x->maximum - device->abs.absinfo_x->minimum; - height = device->abs.absinfo_y->maximum - device->abs.absinfo_y->minimum; + width = device->abs.dimensions.x; + height = device->abs.dimensions.y; switch (tp->model) { case MODEL_ALPS: @@ -353,7 +353,7 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) struct tp_touch *t; enum libinput_pointer_axis axis; double *delta; - struct normalized_coords normalized; + struct normalized_coords normalized, tmp; const struct normalized_coords zero = { 0.0, 0.0 }; const struct discrete_coords zero_discrete = { 0.0, 0.0 }; @@ -402,11 +402,14 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) t->scroll.edge_state); break; case EDGE_SCROLL_TOUCH_STATE_EDGE_NEW: + tmp = normalized; normalized = tp_normalize_delta(tp, device_delta(t->point, t->scroll.initial)); if (fabs(*delta) < DEFAULT_SCROLL_THRESHOLD) normalized = zero; + else + normalized = tmp; break; case EDGE_SCROLL_TOUCH_STATE_EDGE: break; diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index 2951ee6a..7f241de5 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -389,8 +389,16 @@ tp_tap_dragging_handle_event(struct tp_dispatch *tp, tp->tap.state = TAP_STATE_DRAGGING_2; break; case TAP_EVENT_RELEASE: - tp->tap.state = TAP_STATE_DRAGGING_WAIT; - tp_tap_set_drag_timer(tp, time); + if (tp->tap.drag_lock_enabled) { + tp->tap.state = TAP_STATE_DRAGGING_WAIT; + tp_tap_set_drag_timer(tp, time); + } else { + tp_tap_notify(tp, + time, + 1, + LIBINPUT_BUTTON_STATE_RELEASED); + tp->tap.state = TAP_STATE_IDLE; + } break; case TAP_EVENT_MOTION: case TAP_EVENT_TIMEOUT: @@ -845,6 +853,44 @@ tp_tap_config_get_default(struct libinput_device *device) return tp_tap_default(evdev); } +static enum libinput_config_status +tp_tap_config_set_draglock_enabled(struct libinput_device *device, + enum libinput_config_drag_lock_state enabled) +{ + struct evdev_dispatch *dispatch = ((struct evdev_device *) device)->dispatch; + struct tp_dispatch *tp = NULL; + + tp = container_of(dispatch, tp, base); + tp->tap.drag_lock_enabled = enabled; + + return LIBINPUT_CONFIG_STATUS_SUCCESS; +} + +static enum libinput_config_drag_lock_state +tp_tap_config_get_draglock_enabled(struct libinput_device *device) +{ + struct evdev_device *evdev = (struct evdev_device *)device; + struct tp_dispatch *tp = NULL; + + tp = container_of(evdev->dispatch, tp, base); + + return tp->tap.drag_lock_enabled; +} + +static inline enum libinput_config_drag_lock_state +tp_drag_lock_default(struct evdev_device *device) +{ + return LIBINPUT_CONFIG_DRAG_LOCK_DISABLED; +} + +static enum libinput_config_drag_lock_state +tp_tap_config_get_default_draglock_enabled(struct libinput_device *device) +{ + struct evdev_device *evdev = (struct evdev_device *)device; + + return tp_drag_lock_default(evdev); +} + int tp_init_tap(struct tp_dispatch *tp) { @@ -852,10 +898,14 @@ tp_init_tap(struct tp_dispatch *tp) tp->tap.config.set_enabled = tp_tap_config_set_enabled; tp->tap.config.get_enabled = tp_tap_config_is_enabled; tp->tap.config.get_default = tp_tap_config_get_default; + tp->tap.config.set_draglock_enabled = tp_tap_config_set_draglock_enabled; + tp->tap.config.get_draglock_enabled = tp_tap_config_get_draglock_enabled; + tp->tap.config.get_default_draglock_enabled = tp_tap_config_get_default_draglock_enabled; tp->device->base.config.tap = &tp->tap.config; tp->tap.state = TAP_STATE_IDLE; tp->tap.enabled = tp_tap_default(tp->device); + tp->tap.drag_lock_enabled = tp_drag_lock_default(tp->device); libinput_timer_init(&tp->tap.timer, tp_libinput_context(tp), diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 189a5aa4..f19f434e 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -426,7 +426,7 @@ tp_process_key(struct tp_dispatch *tp, static void tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t) { - unsigned int xdist, ydist; + double xdist, ydist; if (!t->pinned.is_pinned) return; @@ -524,7 +524,7 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) int dirs; if (tp_palm_detect_dwt(tp, t, time)) - goto out; + goto out; /* If labelled a touch as palm, we unlabel as palm when we move out of the palm edge zone within the timeout, provided @@ -1403,10 +1403,8 @@ tp_init_palmdetect(struct tp_dispatch *tp, tp->palm.left_edge = INT_MIN; tp->palm.vert_center = INT_MIN; - width = abs(device->abs.absinfo_x->maximum - - device->abs.absinfo_x->minimum); - height = abs(device->abs.absinfo_y->maximum - - device->abs.absinfo_y->minimum); + width = device->abs.dimensions.x; + height = device->abs.dimensions.y; /* Wacom doesn't have internal touchpads, * Apple touchpads are always big enough to warrant palm detection */ @@ -1485,10 +1483,8 @@ tp_init(struct tp_dispatch *tp, if (tp_init_slots(tp, device) != 0) return -1; - width = abs(device->abs.absinfo_x->maximum - - device->abs.absinfo_x->minimum); - height = abs(device->abs.absinfo_y->maximum - - device->abs.absinfo_y->minimum); + width = device->abs.dimensions.x; + height = device->abs.dimensions.y; diagonal = sqrt(width*width + height*height); tp->reports_distance = libevdev_has_event_code(device->evdev, diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 9357969c..36260c68 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -269,6 +269,8 @@ struct tp_dispatch { enum tp_tap_state state; uint32_t buttons_pressed; uint64_t multitap_last_time; + + bool drag_lock_enabled; } tap; struct { diff --git a/src/evdev.c b/src/evdev.c index 4695f079..c18279a6 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "linux/input.h" #include #include @@ -253,6 +254,23 @@ normalize_delta(struct evdev_device *device, normalized->y = delta->y * DEFAULT_MOUSE_DPI / (double)device->dpi; } +static inline bool +evdev_post_trackpoint_scroll(struct evdev_device *device, + struct normalized_coords unaccel, + uint64_t time) +{ + if (device->scroll.method != LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN || + !hw_is_key_down(device, device->scroll.button)) + return false; + + if (device->scroll.button_scroll_active) + evdev_post_scroll(device, time, + LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS, + &unaccel); + + return true; +} + static void evdev_flush_pending_event(struct evdev_device *device, uint64_t time) { @@ -275,14 +293,8 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) device->rel.y = 0; /* Use unaccelerated deltas for pointing stick scroll */ - if (device->scroll.method == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN && - hw_is_key_down(device, device->scroll.button)) { - if (device->scroll.button_scroll_active) - evdev_post_scroll(device, time, - LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS, - &unaccel); - break; - } + if (evdev_post_trackpoint_scroll(device, unaccel, time)) + break; /* Apply pointer acceleration. */ accel = filter_dispatch(device->pointer.filter, @@ -1497,6 +1509,10 @@ evdev_read_dpi_prop(struct evdev_device *device) DEFAULT_MOUSE_DPI); dpi = DEFAULT_MOUSE_DPI; } + log_info(libinput, + "Device '%s' set to %d DPI\n", + device->devname, + dpi); } return dpi; @@ -1762,6 +1778,10 @@ evdev_configure_mt_device(struct evdev_device *device) device->abs.absinfo_x = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X); device->abs.absinfo_y = libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y); + device->abs.dimensions.x = abs(device->abs.absinfo_x->maximum - + device->abs.absinfo_x->minimum); + device->abs.dimensions.y = abs(device->abs.absinfo_y->maximum - + device->abs.absinfo_y->minimum); device->is_mt = 1; /* We only handle the slotted Protocol B in libinput. @@ -1875,6 +1895,10 @@ evdev_configure_device(struct evdev_device *device) device->abs.absinfo_y = libevdev_get_abs_info(evdev, ABS_Y); device->abs.point.x = device->abs.absinfo_x->value; device->abs.point.y = device->abs.absinfo_y->value; + device->abs.dimensions.x = abs(device->abs.absinfo_x->maximum - + device->abs.absinfo_x->minimum); + device->abs.dimensions.y = abs(device->abs.absinfo_y->maximum - + device->abs.absinfo_y->minimum); if (evdev_is_fake_mt_device(device)) { udev_tags &= ~EVDEV_UDEV_TAG_TOUCHSCREEN; @@ -2104,6 +2128,8 @@ evdev_device_create(struct libinput_seat *seat, device->scroll.wheel_click_angle = evdev_read_wheel_click_prop(device); device->model = evdev_read_model(device); + device->dpi = evdev_read_dpi_prop(device); + /* at most 5 SYN_DROPPED log-messages per 30s */ ratelimit_init(&device->syn_drop_limit, 30ULL * 1000, 5); @@ -2114,8 +2140,6 @@ evdev_device_create(struct libinput_seat *seat, if (evdev_configure_device(device) == -1) goto err; - device->dpi = evdev_read_dpi_prop(device); - if (device->seat_caps == 0) { unhandled_device = 1; goto err; diff --git a/src/evdev.h b/src/evdev.h index 3dddb8bf..8787d0c7 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -138,6 +138,8 @@ struct evdev_device { struct matrix calibration; struct matrix default_calibration; /* from LIBINPUT_CALIBRATION_MATRIX */ struct matrix usermatrix; /* as supplied by the caller */ + + struct device_coords dimensions; } abs; struct { diff --git a/src/filter.c b/src/filter.c index a4142e98..b37ca766 100644 --- a/src/filter.c +++ b/src/filter.c @@ -385,11 +385,14 @@ pointer_accel_profile_linear(struct motion_filter *filter, const double max_accel = accel_filter->accel; /* unitless factor */ const double threshold = accel_filter->threshold; /* units/ms */ const double incline = accel_filter->incline; + double factor; s1 = min(1, 0.3 + speed_in * 4); s2 = 1 + (speed_in - threshold) * incline; - return min(max_accel, s2 > 1 ? s2 : s1); + factor = min(max_accel, s2 > 1 ? s2 : s1); + + return factor; } double diff --git a/src/libinput-private.h b/src/libinput-private.h index b687f94a..c6514c6a 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -121,6 +121,11 @@ struct libinput_device_config_tap { enum libinput_config_tap_state enable); enum libinput_config_tap_state (*get_enabled)(struct libinput_device *device); enum libinput_config_tap_state (*get_default)(struct libinput_device *device); + + enum libinput_config_status (*set_draglock_enabled)(struct libinput_device *device, + enum libinput_config_drag_lock_state); + enum libinput_config_drag_lock_state (*get_draglock_enabled)(struct libinput_device *device); + enum libinput_config_drag_lock_state (*get_default_draglock_enabled)(struct libinput_device *device); }; struct libinput_device_config_calibration { diff --git a/src/libinput-util.h b/src/libinput-util.h index f17842e9..50edb492 100644 --- a/src/libinput-util.h +++ b/src/libinput-util.h @@ -95,6 +95,16 @@ int list_empty(const struct list *list); #define NCHARS(x) ((size_t)(((x) + 7) / 8)) +#ifdef DEBUG_TRACE +#define debug_trace(...) \ + do { \ + printf("%s:%d %s() - ", __FILE__, __LINE__, __func__); \ + printf(__VA_ARGS__); \ + } while (0) +#else +#define debug_trace(...) { } +#endif + #define LIBINPUT_EXPORT __attribute__ ((visibility("default"))) static inline void * diff --git a/src/libinput.c b/src/libinput.c index 08c45e32..7f2c15d1 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -2116,6 +2116,39 @@ libinput_device_config_tap_get_default_enabled(struct libinput_device *device) return device->config.tap->get_default(device); } +LIBINPUT_EXPORT enum libinput_config_status +libinput_device_config_tap_set_drag_lock_enabled(struct libinput_device *device, + enum libinput_config_drag_lock_state enable) +{ + if (enable != LIBINPUT_CONFIG_DRAG_LOCK_ENABLED && + enable != LIBINPUT_CONFIG_DRAG_LOCK_DISABLED) + return LIBINPUT_CONFIG_STATUS_INVALID; + + if (libinput_device_config_tap_get_finger_count(device) == 0) + return enable ? LIBINPUT_CONFIG_STATUS_UNSUPPORTED : + LIBINPUT_CONFIG_STATUS_SUCCESS; + + return device->config.tap->set_draglock_enabled(device, enable); +} + +LIBINPUT_EXPORT enum libinput_config_drag_lock_state +libinput_device_config_tap_get_drag_lock_enabled(struct libinput_device *device) +{ + if (libinput_device_config_tap_get_finger_count(device) == 0) + return LIBINPUT_CONFIG_DRAG_LOCK_DISABLED; + + return device->config.tap->get_draglock_enabled(device); +} + +LIBINPUT_EXPORT enum libinput_config_drag_lock_state +libinput_device_config_tap_get_default_drag_lock_enabled(struct libinput_device *device) +{ + if (libinput_device_config_tap_get_finger_count(device) == 0) + return LIBINPUT_CONFIG_DRAG_LOCK_DISABLED; + + return device->config.tap->get_default_draglock_enabled(device); +} + LIBINPUT_EXPORT int libinput_device_config_calibration_has_matrix(struct libinput_device *device) { diff --git a/src/libinput.h b/src/libinput.h index ad605feb..f2bc96b4 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -38,6 +38,8 @@ extern "C" { #define LIBINPUT_ATTRIBUTE_DEPRECATED __attribute__ ((deprecated)) /** + * @ingroup base + * * Log priority for internal logging messages. */ enum libinput_log_priority { @@ -2394,6 +2396,85 @@ libinput_device_config_tap_get_enabled(struct libinput_device *device); enum libinput_config_tap_state libinput_device_config_tap_get_default_enabled(struct libinput_device *device); +/** + * @ingroup config + */ +enum libinput_config_drag_lock_state { + /** Drag lock is to be disabled, or is currently disabled */ + LIBINPUT_CONFIG_DRAG_LOCK_DISABLED, + /** Drag lock is to be enabled, or is currently disabled */ + LIBINPUT_CONFIG_DRAG_LOCK_ENABLED, +}; + +/** + * @ingroup config + * + * Enable or disable drag-lock during tapping on this device. When enabled, + * a finger may be lifted and put back on the touchpad within a timeout and + * the drag process continues. When disabled, lifting the finger during a + * tap-and-drag will immediately stop the drag. See @ref tapndrag for + * details. + * + * Enabling drag lock on a device that has tapping disabled is permitted, + * but has no effect until tapping is enabled. + * + * @param device The device to configure + * @param enable @ref LIBINPUT_CONFIG_DRAG_LOCK_ENABLED to enable drag lock + * or @ref LIBINPUT_CONFIG_DRAG_LOCK_DISABLED to disable drag lock + * + * @return A config status code. Disabling drag lock on a device that does not + * support tapping always succeeds. + * + * @see libinput_device_config_tap_get_drag_lock_enabled + * @see libinput_device_config_tap_get_default_drag_lock_enabled + */ +enum libinput_config_status +libinput_device_config_tap_set_drag_lock_enabled(struct libinput_device *device, + enum libinput_config_drag_lock_state enable); + +/** + * @ingroup config + * + * Check if drag-lock during tapping is enabled on this device. If the + * device does not support tapping, this function always returns + * @ref LIBINPUT_CONFIG_DRAG_LOCK_DISABLED. + * + * Drag lock may be enabled even when tapping is disabled. + * + * @param device The device to configure + * + * @retval LIBINPUT_CONFIG_DRAG_LOCK_ENABLED If drag lock is currently enabled + * @retval LIBINPUT_CONFIG_DRAG_LOCK_DISABLED If drag lock is currently disabled + * + * @see libinput_device_config_tap_set_drag_lock_enabled + * @see libinput_device_config_tap_get_default_drag_lock_enabled + */ +enum libinput_config_drag_lock_state +libinput_device_config_tap_get_drag_lock_enabled(struct libinput_device *device); + +/** + * @ingroup config + * + * Check if drag-lock during tapping is enabled by default on this device. + * If the device does not support tapping, this function always returns + * @ref LIBINPUT_CONFIG_DRAG_LOCK_DISABLED. + * + * Drag lock may be enabled by default even when tapping is disabled by + * default. + * + * @param device The device to configure + * + * @retval LIBINPUT_CONFIG_DRAG_LOCK_ENABLED If drag lock is enabled by + * default + * @retval LIBINPUT_CONFIG_DRAG_LOCK_DISABLED If drag lock is disabled by + * default + * + * @see libinput_device_config_tap_set_drag_lock_enabled + * @see libinput_device_config_tap_get_drag_lock_enabled + */ +enum libinput_config_drag_lock_state +libinput_device_config_tap_get_default_drag_lock_enabled(struct libinput_device *device); + /** * @ingroup config * diff --git a/src/libinput.sym b/src/libinput.sym index 6d21877d..bc2c73e7 100644 --- a/src/libinput.sym +++ b/src/libinput.sym @@ -142,6 +142,12 @@ global: libinput_device_keyboard_has_key; } LIBINPUT_0.14.0; +LIBINPUT_0.19.0 { + libinput_device_config_tap_set_drag_lock_enabled; + libinput_device_config_tap_get_drag_lock_enabled; + libinput_device_config_tap_get_default_drag_lock_enabled; +} LIBINPUT_0.15.0; + /* tablet APIs, they are not part of any stable API promise yet. * keep them separate */ LIBINPUT_TABLET_SUPPORT { @@ -168,4 +174,4 @@ LIBINPUT_TABLET_SUPPORT { libinput_tool_ref; libinput_tool_set_user_data; libinput_tool_unref; -} LIBINPUT_0.15.0; +} LIBINPUT_0.19.0; diff --git a/src/path.c b/src/path.c index 92535cda..ab4d0655 100644 --- a/src/path.c +++ b/src/path.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "path.h" diff --git a/test/litest.h b/test/litest.h index 50c24f13..4f65208c 100644 --- a/test/litest.h +++ b/test/litest.h @@ -455,4 +455,28 @@ void litest_semi_mt_touch_up(struct litest_device *d, #define ck_assert_notnull(ptr) ck_assert_ptr_ne(ptr, NULL) #endif +static inline void +litest_enable_tap(struct libinput_device *device) +{ + enum libinput_config_status status, expected; + + expected = LIBINPUT_CONFIG_STATUS_SUCCESS; + status = libinput_device_config_tap_set_enabled(device, + LIBINPUT_CONFIG_TAP_ENABLED); + + litest_assert_int_eq(status, expected); +} + +static inline void +litest_disable_tap(struct libinput_device *device) +{ + enum libinput_config_status status, expected; + + expected = LIBINPUT_CONFIG_STATUS_SUCCESS; + status = libinput_device_config_tap_set_enabled(device, + LIBINPUT_CONFIG_TAP_DISABLED); + + litest_assert_int_eq(status, expected); +} + #endif /* LITEST_H */ diff --git a/test/touchpad-tap.c b/test/touchpad-tap.c index 22079302..c021f1dc 100644 --- a/test/touchpad-tap.c +++ b/test/touchpad-tap.c @@ -32,14 +32,37 @@ #include "libinput-util.h" #include "litest.h" +static inline void +enable_drag_lock(struct libinput_device *device) +{ + enum libinput_config_status status, expected; + + expected = LIBINPUT_CONFIG_STATUS_SUCCESS; + status = libinput_device_config_tap_set_drag_lock_enabled(device, + LIBINPUT_CONFIG_DRAG_LOCK_ENABLED); + + litest_assert_int_eq(status, expected); +} + +static inline void +disable_drag_lock(struct libinput_device *device) +{ + enum libinput_config_status status, expected; + + expected = LIBINPUT_CONFIG_STATUS_SUCCESS; + status = libinput_device_config_tap_set_drag_lock_enabled(device, + LIBINPUT_CONFIG_DRAG_LOCK_DISABLED); + + litest_assert_int_eq(status, expected); +} + START_TEST(touchpad_1fg_tap) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; struct libinput_event *event; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -68,8 +91,7 @@ START_TEST(touchpad_1fg_doubletap) struct libinput_event_pointer *ptrev; uint32_t oldtime, curtime; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -129,8 +151,7 @@ START_TEST(touchpad_1fg_multitap) int range = _i, /* looped test */ ntaps; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -178,8 +199,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_move) int range = _i, /* looped test */ ntaps; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -245,8 +265,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_2fg) int range = _i, ntaps; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -317,8 +336,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_click) int range = _i, /* looped test */ ntaps; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -378,8 +396,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_timeout) int range = _i, /* looped test */ ntaps; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -449,8 +466,8 @@ START_TEST(touchpad_1fg_multitap_n_drag_tap) int range = _i, /* looped test */ ntaps; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); + enable_drag_lock(dev->libinput_device); litest_drain_events(li); @@ -522,8 +539,8 @@ START_TEST(touchpad_1fg_multitap_n_drag_tap_click) int range = _i, /* looped test */ ntaps; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); + enable_drag_lock(dev->libinput_device); litest_drain_events(li); @@ -600,9 +617,53 @@ START_TEST(touchpad_1fg_tap_n_drag) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_pointer *ptrev __attribute__((unused)); - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); + disable_drag_lock(dev->libinput_device); + + litest_drain_events(li); + + litest_touch_down(dev, 0, 50, 50); + litest_touch_up(dev, 0); + litest_touch_down(dev, 0, 50, 50); + litest_touch_move_to(dev, 0, 50, 50, 80, 80, 5, 40); + + libinput_dispatch(li); + + litest_assert_button_event(li, BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + + libinput_dispatch(li); + + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); + + litest_touch_up(dev, 0); + + /* don't use helper functions here, we expect the event be available + * immediately, not after a timeout that the helper functions may + * trigger. + */ + libinput_dispatch(li); + event = libinput_get_event(li); + ck_assert_notnull(event); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_RELEASED); + libinput_event_destroy(event); + + litest_assert_empty_queue(li); +} +END_TEST + +START_TEST(touchpad_1fg_tap_n_drag_draglock) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + + litest_enable_tap(dev->libinput_device); + enable_drag_lock(dev->libinput_device); litest_drain_events(li); @@ -637,13 +698,13 @@ START_TEST(touchpad_1fg_tap_n_drag) } END_TEST -START_TEST(touchpad_1fg_tap_n_drag_tap) +START_TEST(touchpad_1fg_tap_n_drag_draglock_tap) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); + enable_drag_lock(dev->libinput_device); litest_drain_events(li); @@ -679,13 +740,13 @@ START_TEST(touchpad_1fg_tap_n_drag_tap) } END_TEST -START_TEST(touchpad_1fg_tap_n_drag_tap_click) +START_TEST(touchpad_1fg_tap_n_drag_draglock_tap_click) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); + enable_drag_lock(dev->libinput_device); litest_drain_events(li); @@ -724,13 +785,13 @@ START_TEST(touchpad_1fg_tap_n_drag_tap_click) } END_TEST -START_TEST(touchpad_1fg_tap_n_drag_timeout) +START_TEST(touchpad_1fg_tap_n_drag_draglock_timeout) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); + enable_drag_lock(dev->libinput_device); litest_drain_events(li); @@ -759,8 +820,8 @@ START_TEST(touchpad_2fg_tap_n_drag) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); + disable_drag_lock(dev->libinput_device); litest_drain_events(li); @@ -779,7 +840,6 @@ START_TEST(touchpad_2fg_tap_n_drag) litest_touch_up(dev, 0); litest_touch_up(dev, 1); - /* This will wait for the DRAGGING_WAIT timeout */ litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_RELEASED); @@ -796,8 +856,7 @@ START_TEST(touchpad_2fg_tap_n_drag_3fg_btntool) ABS_MT_SLOT) > 2) return; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -842,8 +901,7 @@ START_TEST(touchpad_2fg_tap_n_drag_3fg) ABS_MT_SLOT) <= 2) return; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -881,8 +939,7 @@ START_TEST(touchpad_2fg_tap) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(dev->libinput); @@ -908,8 +965,7 @@ START_TEST(touchpad_2fg_tap_inverted) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(dev->libinput); @@ -935,8 +991,7 @@ START_TEST(touchpad_2fg_tap_quickrelease) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(dev->libinput); @@ -967,8 +1022,7 @@ START_TEST(touchpad_1fg_tap_click) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(dev->libinput); @@ -1000,8 +1054,7 @@ START_TEST(touchpad_2fg_tap_click) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(dev->libinput); @@ -1036,8 +1089,7 @@ START_TEST(clickpad_2fg_tap_click) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(dev->libinput); @@ -1068,8 +1120,7 @@ START_TEST(touchpad_2fg_tap_click_apple) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(dev->libinput); @@ -1101,8 +1152,7 @@ START_TEST(touchpad_no_2fg_tap_after_move) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(dev->libinput); /* one finger down, move past threshold, @@ -1125,8 +1175,7 @@ START_TEST(touchpad_no_2fg_tap_after_timeout) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(dev->libinput); /* one finger down, wait past tap timeout, @@ -1152,8 +1201,7 @@ START_TEST(touchpad_no_first_fg_tap_after_move) struct libinput *li = dev->libinput; struct libinput_event *event; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(dev->libinput); @@ -1184,8 +1232,7 @@ START_TEST(touchpad_1fg_double_tap_click) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(dev->libinput); @@ -1220,8 +1267,7 @@ START_TEST(touchpad_1fg_tap_n_drag_click) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(dev->libinput); @@ -1269,8 +1315,7 @@ START_TEST(touchpad_3fg_tap) ABS_MT_SLOT) <= 2) return; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); for (i = 0; i < 3; i++) { litest_drain_events(li); @@ -1307,8 +1352,7 @@ START_TEST(touchpad_3fg_tap_quickrelease) ABS_MT_SLOT) <= 2) return; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -1348,7 +1392,7 @@ START_TEST(touchpad_3fg_tap_btntool) ABS_MT_SLOT) > 2) return; - libinput_device_config_tap_set_enabled(dev->libinput_device, 1); + litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -1387,7 +1431,7 @@ START_TEST(touchpad_3fg_tap_btntool_inverted) ABS_MT_SLOT) > 2) return; - libinput_device_config_tap_set_enabled(dev->libinput_device, 1); + litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -1427,8 +1471,7 @@ START_TEST(touchpad_4fg_tap) ABS_MT_SLOT) <= 3) return; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); for (i = 0; i < 4; i++) { litest_drain_events(li); @@ -1462,8 +1505,7 @@ START_TEST(touchpad_4fg_tap_quickrelease) ABS_MT_SLOT) <= 3) return; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -1502,8 +1544,7 @@ START_TEST(touchpad_5fg_tap) ABS_MT_SLOT) <= 4) return; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); for (i = 0; i < 5; i++) { litest_drain_events(li); @@ -1539,8 +1580,7 @@ START_TEST(touchpad_5fg_tap_quickrelease) ABS_MT_SLOT) <= 4) return; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -1576,8 +1616,7 @@ START_TEST(clickpad_1fg_tap_click) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(dev->libinput); @@ -1660,6 +1699,60 @@ START_TEST(touchpad_tap_invalid) } END_TEST +START_TEST(touchpad_drag_lock_default_disabled) +{ + struct litest_device *dev = litest_current_device(); + struct libinput_device *device = dev->libinput_device; + enum libinput_config_status status; + + ck_assert_int_eq(libinput_device_config_tap_get_drag_lock_enabled(device), + LIBINPUT_CONFIG_DRAG_LOCK_DISABLED); + ck_assert_int_eq(libinput_device_config_tap_get_default_drag_lock_enabled(device), + LIBINPUT_CONFIG_DRAG_LOCK_DISABLED); + + status = libinput_device_config_tap_set_drag_lock_enabled(device, + LIBINPUT_CONFIG_DRAG_LOCK_ENABLED); + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + + status = libinput_device_config_tap_set_drag_lock_enabled(device, + LIBINPUT_CONFIG_DRAG_LOCK_DISABLED); + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + + status = libinput_device_config_tap_set_drag_lock_enabled(device, + LIBINPUT_CONFIG_DRAG_LOCK_ENABLED); + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + + status = libinput_device_config_tap_set_drag_lock_enabled(device, + 3); + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID); +} +END_TEST + +START_TEST(touchpad_drag_lock_default_unavailable) +{ + struct litest_device *dev = litest_current_device(); + struct libinput_device *device = dev->libinput_device; + enum libinput_config_status status; + + ck_assert_int_eq(libinput_device_config_tap_get_drag_lock_enabled(device), + LIBINPUT_CONFIG_DRAG_LOCK_DISABLED); + ck_assert_int_eq(libinput_device_config_tap_get_default_drag_lock_enabled(device), + LIBINPUT_CONFIG_DRAG_LOCK_DISABLED); + + status = libinput_device_config_tap_set_drag_lock_enabled(device, + LIBINPUT_CONFIG_DRAG_LOCK_ENABLED); + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED); + + status = libinput_device_config_tap_set_drag_lock_enabled(device, + LIBINPUT_CONFIG_DRAG_LOCK_DISABLED); + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + + status = libinput_device_config_tap_set_drag_lock_enabled(device, + 3); + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID); +} +END_TEST + void litest_setup_tests(void) { @@ -1674,8 +1767,9 @@ litest_setup_tests(void) litest_add_ranged("touchpad:tap", touchpad_1fg_multitap_n_drag_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &multitap_range); litest_add_ranged("touchpad:tap", touchpad_1fg_multitap_n_drag_click, LITEST_CLICKPAD, LITEST_ANY, &multitap_range); litest_add("touchpad:tap", touchpad_1fg_tap_n_drag, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:tap", touchpad_1fg_tap_n_drag_tap, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:tap", touchpad_1fg_tap_n_drag_timeout, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:tap", touchpad_1fg_tap_n_drag_draglock, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:tap", touchpad_1fg_tap_n_drag_draglock_tap, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:tap", touchpad_1fg_tap_n_drag_draglock_timeout, LITEST_TOUCHPAD, LITEST_ANY); litest_add("touchpad:tap", touchpad_2fg_tap_n_drag, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); litest_add("touchpad:tap", touchpad_2fg_tap_n_drag_3fg_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_APPLE_CLICKPAD); litest_add("touchpad:tap", touchpad_2fg_tap_n_drag_3fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); @@ -1704,7 +1798,7 @@ litest_setup_tests(void) litest_add("touchpad:tap", touchpad_1fg_double_tap_click, LITEST_CLICKPAD, LITEST_ANY); litest_add("touchpad:tap", touchpad_1fg_tap_n_drag_click, LITEST_CLICKPAD, LITEST_ANY); litest_add_ranged("touchpad:tap", touchpad_1fg_multitap_n_drag_tap_click, LITEST_CLICKPAD, LITEST_ANY, &multitap_range); - litest_add("touchpad:tap", touchpad_1fg_tap_n_drag_tap_click, LITEST_CLICKPAD, LITEST_ANY); + litest_add("touchpad:tap", touchpad_1fg_tap_n_drag_draglock_tap_click, LITEST_CLICKPAD, LITEST_ANY); litest_add("touchpad:tap", touchpad_tap_default_disabled, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_ANY); litest_add("touchpad:tap", touchpad_tap_default_enabled, LITEST_TOUCHPAD, LITEST_BUTTON); @@ -1715,4 +1809,7 @@ litest_setup_tests(void) litest_add("touchpad:tap", clickpad_1fg_tap_click, LITEST_CLICKPAD, LITEST_ANY); litest_add("touchpad:tap", clickpad_2fg_tap_click, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH|LITEST_APPLE_CLICKPAD); + litest_add("touchpad:tap", touchpad_drag_lock_default_disabled, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:tap", touchpad_drag_lock_default_unavailable, LITEST_ANY, LITEST_TOUCHPAD); + } diff --git a/test/touchpad.c b/test/touchpad.c index 1179d57e..443c8c1f 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -39,8 +39,7 @@ START_TEST(touchpad_1fg_motion) struct libinput_event *event; struct libinput_event_pointer *ptrev; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_DISABLED); + litest_disable_tap(dev->libinput_device); litest_drain_events(li); @@ -683,8 +682,7 @@ START_TEST(clickpad_softbutton_left_tap_n_drag) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -726,8 +724,7 @@ START_TEST(clickpad_softbutton_right_tap_n_drag) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -1675,8 +1672,7 @@ START_TEST(touchpad_palm_detect_at_edge) if (!touchpad_has_palm_detect_size(dev)) return; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_DISABLED); + litest_disable_tap(dev->libinput_device); litest_drain_events(li); @@ -1720,8 +1716,7 @@ START_TEST(touchpad_palm_detect_at_bottom_corners) if (!touchpad_has_palm_detect_size(dev)) return; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_DISABLED); + litest_disable_tap(dev->libinput_device); /* Run for non-clickpads only: make sure the bottom corners trigger palm detection too */ @@ -1747,8 +1742,7 @@ START_TEST(touchpad_palm_detect_at_top_corners) if (!touchpad_has_palm_detect_size(dev)) return; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_DISABLED); + litest_disable_tap(dev->libinput_device); /* Run for non-clickpads only: make sure the bottom corners trigger palm detection too */ @@ -1774,8 +1768,7 @@ START_TEST(touchpad_palm_detect_palm_stays_palm) if (!touchpad_has_palm_detect_size(dev)) return; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_DISABLED); + litest_disable_tap(dev->libinput_device); litest_drain_events(li); @@ -1794,8 +1787,7 @@ START_TEST(touchpad_palm_detect_palm_becomes_pointer) if (!touchpad_has_palm_detect_size(dev)) return; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_DISABLED); + litest_disable_tap(dev->libinput_device); litest_drain_events(li); @@ -1819,8 +1811,7 @@ START_TEST(touchpad_palm_detect_no_palm_moving_into_edges) if (!touchpad_has_palm_detect_size(dev)) return; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_DISABLED); + litest_disable_tap(dev->libinput_device); /* moving non-palm into the edge does not label it as palm */ litest_drain_events(li); @@ -1849,8 +1840,7 @@ START_TEST(touchpad_palm_detect_tap) if (!touchpad_has_palm_detect_size(dev)) return; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -2028,8 +2018,8 @@ START_TEST(touchpad_left_handed_tapping) struct libinput *li = dev->libinput; enum libinput_config_status status; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); + status = libinput_device_config_left_handed_set(d, 1); ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); @@ -2059,8 +2049,8 @@ START_TEST(touchpad_left_handed_tapping_2fg) struct libinput *li = dev->libinput; enum libinput_config_status status; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(dev->libinput_device); + status = libinput_device_config_left_handed_set(d, 1); ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); @@ -3022,8 +3012,7 @@ START_TEST(touchpad_initial_state) dev = litest_current_device(); libinput1 = dev->libinput; - libinput_device_config_tap_set_enabled(dev->libinput_device, - LIBINPUT_CONFIG_TAP_DISABLED); + litest_disable_tap(dev->libinput_device); litest_touch_down(dev, 0, x, y); litest_touch_up(dev, 0); @@ -3088,8 +3077,7 @@ START_TEST(touchpad_dwt) return; keyboard = litest_add_device(li, LITEST_KEYBOARD); - libinput_device_config_tap_set_enabled(touchpad->libinput_device, - LIBINPUT_CONFIG_TAP_DISABLED); + litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); litest_keyboard_key(keyboard, KEY_A, true); @@ -3131,8 +3119,7 @@ START_TEST(touchpad_dwt_enable_touch) return; keyboard = litest_add_device(li, LITEST_KEYBOARD); - libinput_device_config_tap_set_enabled(touchpad->libinput_device, - LIBINPUT_CONFIG_TAP_DISABLED); + litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); litest_keyboard_key(keyboard, KEY_A, true); @@ -3170,8 +3157,7 @@ START_TEST(touchpad_dwt_touch_hold) return; keyboard = litest_add_device(li, LITEST_KEYBOARD); - libinput_device_config_tap_set_enabled(touchpad->libinput_device, - LIBINPUT_CONFIG_TAP_DISABLED); + litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); litest_keyboard_key(keyboard, KEY_A, true); @@ -3208,8 +3194,7 @@ START_TEST(touchpad_dwt_key_hold) return; keyboard = litest_add_device(li, LITEST_KEYBOARD); - libinput_device_config_tap_set_enabled(touchpad->libinput_device, - LIBINPUT_CONFIG_TAP_DISABLED); + litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); litest_keyboard_key(keyboard, KEY_A, true); @@ -3237,8 +3222,7 @@ START_TEST(touchpad_dwt_type) return; keyboard = litest_add_device(li, LITEST_KEYBOARD); - libinput_device_config_tap_set_enabled(touchpad->libinput_device, - LIBINPUT_CONFIG_TAP_DISABLED); + litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); for (i = 0; i < 5; i++) { @@ -3276,8 +3260,7 @@ START_TEST(touchpad_dwt_type_short_timeout) return; keyboard = litest_add_device(li, LITEST_KEYBOARD); - libinput_device_config_tap_set_enabled(touchpad->libinput_device, - LIBINPUT_CONFIG_TAP_DISABLED); + litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); for (i = 0; i < 5; i++) { @@ -3314,8 +3297,7 @@ START_TEST(touchpad_dwt_tap) return; keyboard = litest_add_device(li, LITEST_KEYBOARD); - libinput_device_config_tap_set_enabled(touchpad->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(touchpad->libinput_device); litest_drain_events(li); litest_keyboard_key(keyboard, KEY_A, true); @@ -3345,8 +3327,7 @@ START_TEST(touchpad_dwt_tap_drag) return; keyboard = litest_add_device(li, LITEST_KEYBOARD); - libinput_device_config_tap_set_enabled(touchpad->libinput_device, - LIBINPUT_CONFIG_TAP_ENABLED); + litest_enable_tap(touchpad->libinput_device); litest_drain_events(li); litest_keyboard_key(keyboard, KEY_A, true); @@ -3380,8 +3361,7 @@ START_TEST(touchpad_dwt_click) return; keyboard = litest_add_device(li, LITEST_KEYBOARD); - libinput_device_config_tap_set_enabled(touchpad->libinput_device, - LIBINPUT_CONFIG_TAP_DISABLED); + litest_disable_tap(touchpad->libinput_device); litest_drain_events(li); litest_keyboard_key(keyboard, KEY_A, true); diff --git a/tools/event-debug.c b/tools/event-debug.c index 0655a96d..834a3247 100644 --- a/tools/event-debug.c +++ b/tools/event-debug.c @@ -42,27 +42,9 @@ uint32_t start_time; static const uint32_t screen_width = 100; static const uint32_t screen_height = 100; -struct tools_options options; +struct tools_context context; static unsigned int stop = 0; -static int -open_restricted(const char *path, int flags, void *user_data) -{ - int fd = open(path, flags); - return fd < 0 ? -errno : fd; -} - -static void -close_restricted(int fd, void *user_data) -{ - close(fd); -} - -static const struct libinput_interface interface = { - .open_restricted = open_restricted, - .close_restricted = close_restricted, -}; - static void print_event_header(struct libinput_event *ev) { @@ -169,8 +151,13 @@ print_device_notify(struct libinput_event *ev) if (libinput_device_get_size(dev, &w, &h) == 0) printf("\tsize %.2f/%.2fmm", w, h); - if (libinput_device_config_tap_get_finger_count(dev)) + if (libinput_device_config_tap_get_finger_count(dev)) { printf(" tap"); + if (libinput_device_config_tap_get_drag_lock_enabled(dev)) + printf("(dl on)"); + else + printf("(dl off)"); + } if (libinput_device_config_left_handed_is_available(dev)) printf(" left"); if (libinput_device_config_scroll_has_natural_scroll(dev)) @@ -547,7 +534,7 @@ handle_and_print_events(struct libinput *li) case LIBINPUT_EVENT_DEVICE_REMOVED: print_device_notify(ev); tools_device_apply_config(libinput_event_get_device(ev), - &options); + &context.options); break; case LIBINPUT_EVENT_KEYBOARD_KEY: print_key_event(ev); @@ -638,18 +625,18 @@ main(int argc, char **argv) struct libinput *li; struct timespec tp; - clock_gettime(CLOCK_MONOTONIC, &tp); - start_time = tp.tv_sec * 1000 + tp.tv_nsec / 1000000; + tools_init_context(&context); - tools_init_options(&options); - - if (tools_parse_args(argc, argv, &options)) + if (tools_parse_args(argc, argv, &context)) return 1; - li = tools_open_backend(&options, NULL, &interface); + li = tools_open_backend(&context); if (!li) return 1; + clock_gettime(CLOCK_MONOTONIC, &tp); + start_time = tp.tv_sec * 1000 + tp.tv_nsec / 1000000; + mainloop(li); libinput_unref(li); diff --git a/tools/event-gui.c b/tools/event-gui.c index 697bf9f1..6c9cf03f 100644 --- a/tools/event-gui.c +++ b/tools/event-gui.c @@ -44,7 +44,7 @@ #define clip(val_, min_, max_) min((max_), max((min_), (val_))) -struct tools_options options; +struct tools_context context; struct touch { int active; @@ -264,6 +264,7 @@ change_ptraccel(struct window *w, double amount) static void handle_event_device_notify(struct libinput_event *ev) { + struct tools_context *context; struct libinput_device *dev = libinput_event_get_device(ev); struct libinput *li; struct window *w; @@ -280,11 +281,12 @@ handle_event_device_notify(struct libinput_event *ev) libinput_device_get_name(dev), type); - tools_device_apply_config(libinput_event_get_device(ev), - &options); - li = libinput_event_get_context(ev); - w = libinput_get_user_data(li); + context = libinput_get_user_data(li); + w = context->user_data; + + tools_device_apply_config(libinput_event_get_device(ev), + &context->options); if (libinput_event_get_type(ev) == LIBINPUT_EVENT_DEVICE_ADDED) { for (i = 0; i < ARRAY_LENGTH(w->devices); i++) { @@ -430,7 +432,8 @@ static gboolean handle_event_libinput(GIOChannel *source, GIOCondition condition, gpointer data) { struct libinput *li = data; - struct window *w = libinput_get_user_data(li); + struct tools_context *context = libinput_get_user_data(li); + struct window *w = context->user_data; struct libinput_event *ev; libinput_dispatch(li); @@ -493,24 +496,6 @@ sockets_init(struct libinput *li) g_io_add_watch(c, G_IO_IN, handle_event_libinput, li); } -static int -open_restricted(const char *path, int flags, void *user_data) -{ - int fd = open(path, flags); - return fd < 0 ? -errno : fd; -} - -static void -close_restricted(int fd, void *user_data) -{ - close(fd); -} - -static const struct libinput_interface interface = { - .open_restricted = open_restricted, - .close_restricted = close_restricted, -}; - int main(int argc, char *argv[]) { @@ -520,16 +505,17 @@ main(int argc, char *argv[]) gtk_init(&argc, &argv); - tools_init_options(&options); + tools_init_context(&context); - if (tools_parse_args(argc, argv, &options) != 0) + if (tools_parse_args(argc, argv, &context) != 0) return 1; udev = udev_new(); if (!udev) error("Failed to initialize udev\n"); - li = tools_open_backend(&options, &w, &interface); + context.user_data = &w; + li = tools_open_backend(&context); if (!li) return 1; diff --git a/tools/libinput-list-devices.c b/tools/libinput-list-devices.c index d76e5db5..6d162e2f 100644 --- a/tools/libinput-list-devices.c +++ b/tools/libinput-list-devices.c @@ -23,7 +23,6 @@ #define _GNU_SOURCE #include -#include #include #include #include @@ -36,27 +35,6 @@ #include "shared.h" -static int -open_restricted(const char *path, int flags, void *user_data) -{ - int fd = open(path, flags); - if (fd < 0) - fprintf(stderr, "Failed to open %s (%s)\n", - path, strerror(errno)); - return fd < 0 ? -errno : fd; -} - -static void -close_restricted(int fd, void *user_data) -{ - close(fd); -} - -static const struct libinput_interface interface = { - .open_restricted = open_restricted, - .close_restricted = close_restricted, -}; - static inline const char* bool_to_str(bool b) { @@ -78,6 +56,18 @@ tap_default(struct libinput_device *device) return "disabled"; } +static const char * +draglock_default(struct libinput_device *device) +{ + if (!libinput_device_config_tap_get_finger_count(device)) + return "n/a"; + + if (libinput_device_config_tap_get_default_drag_lock_enabled(device)) + return "enabled"; + else + return "disabled"; +} + static const char* left_handed_default(struct libinput_device *device) { @@ -238,6 +228,7 @@ print_device_notify(struct libinput_event *ev) printf("\n"); printf("Tap-to-click: %s\n", tap_default(dev)); + printf("Tap drag lock: %s\n", draglock_default(dev)); printf("Left-handed: %s\n", left_handed_default(dev)); printf("Nat.scrolling: %s\n", nat_scroll_default(dev)); printf("Middle emulation: %s\n", middle_emulation_default(dev)); @@ -277,7 +268,7 @@ int main(int argc, char **argv) { struct libinput *li; - struct tools_options options; + struct tools_context context; struct libinput_event *ev; if (argc > 1) { @@ -293,9 +284,9 @@ main(int argc, char **argv) } } - tools_init_options(&options); + tools_init_context(&context); - li = tools_open_backend(&options, NULL, &interface); + li = tools_open_backend(&context); if (!li) return 1; diff --git a/tools/ptraccel-debug.c b/tools/ptraccel-debug.c index 8b800ee1..c774e3bf 100644 --- a/tools/ptraccel-debug.c +++ b/tools/ptraccel-debug.c @@ -95,7 +95,7 @@ print_ptraccel_movement(struct motion_filter *filter, motion.y = 0; time += 12; /* pretend 80Hz data */ - filter_dispatch(filter, &motion, NULL, time); + motion = filter_dispatch(filter, &motion, NULL, time); printf("%d %.3f %.3f\n", i, motion.x, dx); @@ -129,7 +129,7 @@ print_ptraccel_sequence(struct motion_filter *filter, motion.y = 0; time += 12; /* pretend 80Hz data */ - filter_dispatch(filter, &motion, NULL, time); + motion = filter_dispatch(filter, &motion, NULL, time); printf("%d %.3f %.3f\n", i, motion.x, *dx); } @@ -165,9 +165,9 @@ usage(void) " delta ... print delta to accelerated delta\n" " accel ... print accel factor\n" " sequence ... print motion for custom delta sequence\n" - "--maxdx=\n ... in motion mode only. Stop increasing dx at maxdx\n" - "--steps=\n ... in motion and delta modes only. Increase dx by step each round\n" - "--speed=\n ... accel speed [-1, 1], default 0\n" + "--maxdx= ... in motion mode only. Stop increasing dx at maxdx\n" + "--steps= ... in motion and delta modes only. Increase dx by step each round\n" + "--speed= ... accel speed [-1, 1], default 0\n" "\n" "If extra arguments are present and mode is not given, mode defaults to 'sequence'\n" "and the arguments are interpreted as sequence of delta x coordinates\n" diff --git a/tools/shared.c b/tools/shared.c index 1858c93f..64544c5c 100644 --- a/tools/shared.c +++ b/tools/shared.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -39,10 +40,13 @@ enum options { OPT_DEVICE, OPT_UDEV, + OPT_GRAB, OPT_HELP, OPT_VERBOSE, OPT_TAP_ENABLE, OPT_TAP_DISABLE, + OPT_DRAG_LOCK_ENABLE, + OPT_DRAG_LOCK_DISABLE, OPT_NATURAL_SCROLL_ENABLE, OPT_NATURAL_SCROLL_DISABLE, OPT_LEFT_HANDED_ENABLE, @@ -75,6 +79,8 @@ tools_usage() "Features:\n" "--enable-tap\n" "--disable-tap.... enable/disable tapping\n" + "--enable-drag-lock\n" + "--disable-drag-lock.... enable/disable tapping drag lock\n" "--enable-natural-scrolling\n" "--disable-natural-scrolling.... enable/disable natural scrolling\n" "--enable-left-handed\n" @@ -90,16 +96,22 @@ tools_usage() "is not explicitly specified it is left at each device's default.\n" "\n" "Other options:\n" + "--grab .......... Exclusively grab all openend devices\n" "--verbose ....... Print debugging output.\n" "--help .......... Print this help.\n", program_invocation_short_name); } void -tools_init_options(struct tools_options *options) +tools_init_context(struct tools_context *context) { + struct tools_options *options = &context->options; + + context->user_data = NULL; + memset(options, 0, sizeof(*options)); options->tapping = -1; + options->drag_lock = -1; options->natural_scroll = -1; options->left_handed = -1; options->middlebutton = -1; @@ -112,18 +124,23 @@ tools_init_options(struct tools_options *options) } int -tools_parse_args(int argc, char **argv, struct tools_options *options) +tools_parse_args(int argc, char **argv, struct tools_context *context) { + struct tools_options *options = &context->options; + while (1) { int c; int option_index = 0; static struct option opts[] = { { "device", 1, 0, OPT_DEVICE }, { "udev", 0, 0, OPT_UDEV }, + { "grab", 0, 0, OPT_GRAB }, { "help", 0, 0, OPT_HELP }, { "verbose", 0, 0, OPT_VERBOSE }, { "enable-tap", 0, 0, OPT_TAP_ENABLE }, { "disable-tap", 0, 0, OPT_TAP_DISABLE }, + { "enable-drag-lock", 0, 0, OPT_DRAG_LOCK_ENABLE }, + { "disable-drag-lock", 0, 0, OPT_DRAG_LOCK_DISABLE }, { "enable-natural-scrolling", 0, 0, OPT_NATURAL_SCROLL_ENABLE }, { "disable-natural-scrolling", 0, 0, OPT_NATURAL_SCROLL_DISABLE }, { "enable-left-handed", 0, 0, OPT_LEFT_HANDED_ENABLE }, @@ -142,11 +159,11 @@ tools_parse_args(int argc, char **argv, struct tools_options *options) break; switch(c) { - case 'h': /* --help */ + case 'h': case OPT_HELP: tools_usage(); exit(0); - case OPT_DEVICE: /* --device */ + case OPT_DEVICE: options->backend = BACKEND_DEVICE; if (!optarg) { tools_usage(); @@ -154,12 +171,15 @@ tools_parse_args(int argc, char **argv, struct tools_options *options) } options->device = optarg; break; - case OPT_UDEV: /* --udev */ + case OPT_UDEV: options->backend = BACKEND_UDEV; if (optarg) options->seat = optarg; break; - case OPT_VERBOSE: /* --verbose */ + case OPT_GRAB: + options->grab = 1; + break; + case OPT_VERBOSE: options->verbose = 1; break; case OPT_TAP_ENABLE: @@ -168,6 +188,12 @@ tools_parse_args(int argc, char **argv, struct tools_options *options) case OPT_TAP_DISABLE: options->tapping = 0; break; + case OPT_DRAG_LOCK_ENABLE: + options->drag_lock = 1; + break; + case OPT_DRAG_LOCK_DISABLE: + options->drag_lock = 0; + break; case OPT_NATURAL_SCROLL_ENABLE: options->natural_scroll = 1; break; @@ -331,17 +357,44 @@ open_device(const struct libinput_interface *interface, return li; } +static int +open_restricted(const char *path, int flags, void *user_data) +{ + const struct tools_context *context = user_data; + int fd = open(path, flags); + + if (fd < 0) + fprintf(stderr, "Failed to open %s (%s)\n", + path, strerror(errno)); + else if (context->options.grab && + ioctl(fd, EVIOCGRAB, (void*)1) == -1) + fprintf(stderr, "Grab requested, but failed for %s (%s)\n", + path, strerror(errno)); + + return fd < 0 ? -errno : fd; +} + +static void +close_restricted(int fd, void *user_data) +{ + close(fd); +} + +static const struct libinput_interface interface = { + .open_restricted = open_restricted, + .close_restricted = close_restricted, +}; + struct libinput * -tools_open_backend(struct tools_options *options, - void *userdata, - const struct libinput_interface *interface) +tools_open_backend(struct tools_context *context) { struct libinput *li = NULL; + struct tools_options *options = &context->options; if (options->backend == BACKEND_UDEV) { - li = open_udev(interface, userdata, options->seat, options->verbose); + li = open_udev(&interface, context, options->seat, options->verbose); } else if (options->backend == BACKEND_DEVICE) { - li = open_device(interface, userdata, options->device, options->verbose); + li = open_device(&interface, context, options->device, options->verbose); } else abort(); @@ -354,6 +407,9 @@ tools_device_apply_config(struct libinput_device *device, { if (options->tapping != -1) libinput_device_config_tap_set_enabled(device, options->tapping); + if (options->drag_lock != -1) + libinput_device_config_tap_set_drag_lock_enabled(device, + options->drag_lock); if (options->natural_scroll != -1) libinput_device_config_scroll_set_natural_scroll_enabled(device, options->natural_scroll); diff --git a/tools/shared.h b/tools/shared.h index 3ce2e1ca..a848e2d1 100644 --- a/tools/shared.h +++ b/tools/shared.h @@ -35,9 +35,11 @@ struct tools_options { enum tools_backend backend; const char *device; /* if backend is BACKEND_DEVICE */ const char *seat; /* if backend is BACKEND_UDEV */ + int grab; /* EVIOCGRAB */ int verbose; int tapping; + int drag_lock; int natural_scroll; int left_handed; int middlebutton; @@ -47,11 +49,14 @@ struct tools_options { double speed; }; -void tools_init_options(struct tools_options *options); -int tools_parse_args(int argc, char **argv, struct tools_options *options); -struct libinput* tools_open_backend(struct tools_options *options, - void *userdata, - const struct libinput_interface *interface); +struct tools_context { + struct tools_options options; + void *user_data; +}; + +void tools_init_context(struct tools_context *context); +int tools_parse_args(int argc, char **argv, struct tools_context *context); +struct libinput* tools_open_backend(struct tools_context *context); void tools_device_apply_config(struct libinput_device *device, struct tools_options *options); void tools_usage(); diff --git a/udev/libinput-device-group.c b/udev/libinput-device-group.c index 50bfbe02..adbd6b7f 100644 --- a/udev/libinput-device-group.c +++ b/udev/libinput-device-group.c @@ -10,8 +10,9 @@ int main(int argc, char **argv) struct udev_device *device = NULL; const char *syspath, *phys = NULL; - char *group, - *str; + const char *product; + char group[1024]; + char *str; if (argc != 2) return 1; @@ -45,9 +46,12 @@ int main(int argc, char **argv) if (!phys) goto out; - group = strdup(phys); - if (!group) - goto out; + /* udev sets PRODUCT on the same device we find PHYS on, let's rely + on that*/ + product = udev_device_get_property_value(device, "PRODUCT"); + if (!product) + product = ""; + snprintf(group, sizeof(group), "%s:%s", product, phys); str = strstr(group, "/input"); if (str) @@ -64,7 +68,6 @@ int main(int argc, char **argv) *str = '\0'; printf("%s\n", group); - free(group); rc = 0; out: