[PATCH libinput 5/5] touchpad: when disabling a TOPBUTTONPAD, leave the buttons enabled
Peter Hutterer
peter.hutterer at who-t.net
Wed Sep 3 23:31:59 PDT 2014
On a TOPBUTTONPAD, we can't disable the touchpad altogether - the trackstick
relies on the touchpad's top software buttons. On those devices, stretch the
top buttons down to INT_MAX on suspend and then route any button click events
through the trackstick device.
On resume, restore the original configuration.
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
Obviously the trackpoint detection is a bit rough here, see Hans' patch for
how to do this based on the kernel property (once that is merged).
src/evdev-mt-touchpad-buttons.c | 17 +++++++++++-
src/evdev-mt-touchpad.c | 24 ++++++++++++++++-
src/evdev-mt-touchpad.h | 6 +++++
src/evdev.c | 11 ++++++++
src/evdev.h | 1 +
test/device.c | 58 +++++++++++++++++++++++++++++++++++++++++
6 files changed, 115 insertions(+), 2 deletions(-)
diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c
index 02d3205..bf2fbc2 100644
--- a/src/evdev-mt-touchpad-buttons.c
+++ b/src/evdev-mt-touchpad-buttons.c
@@ -540,6 +540,16 @@ tp_init_softbuttons(struct tp_dispatch *tp,
}
}
+void
+tp_expand_softbuttons(struct tp_dispatch *tp)
+{
+ /* simply stretch the top software button area down */
+ if (tp->buttons.has_topbuttons) {
+ tp->buttons.top_area.bottom_edge = INT_MAX;
+ tp->buttons.bottom_area.top_edge = INT_MAX;
+ }
+}
+
int
tp_init_buttons(struct tp_dispatch *tp,
struct evdev_device *device)
@@ -737,7 +747,12 @@ tp_post_softbutton_buttons(struct tp_dispatch *tp, uint64_t time)
tp->buttons.click_pending = false;
if (button) {
- evdev_pointer_notify_button(tp->device,
+ struct evdev_device *device = tp->device;
+
+ if (tp->sendevents.disabled && tp->buttons.trackpoint)
+ device = tp->buttons.trackpoint;
+
+ evdev_pointer_notify_button(device,
time,
button,
state);
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index adb3d02..2d3a677 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -667,13 +667,25 @@ tp_suspend(struct tp_dispatch *tp, struct evdev_device *device)
tp_handle_state(tp, now);
- evdev_device_suspend(device);
+ tp->sendevents.disabled = true;
+
+ /* On the T440s with top softwarebuttons, don't disable the device,
+ merely pull the top buttons down to cover the whole touchpad.
+ */
+ if (tp->buttons.has_topbuttons)
+ tp_expand_softbuttons(tp);
+ else
+ evdev_device_suspend(device);
}
static void
tp_resume(struct tp_dispatch *tp, struct evdev_device *device)
{
evdev_device_resume(device);
+
+ tp->sendevents.disabled = false;
+ if (tp->buttons.has_topbuttons)
+ tp_init_softbuttons(tp, device);
}
static void
@@ -682,6 +694,11 @@ tp_device_added(struct evdev_device *device,
{
struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
+ if (tp->buttons.has_topbuttons &&
+ tp->buttons.trackpoint == NULL &&
+ added_device->tags & EVDEV_TAG_TRACKPOINT)
+ tp->buttons.trackpoint = added_device;
+
if (tp->sendevents.current_mode !=
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
return;
@@ -697,6 +714,9 @@ tp_device_removed(struct evdev_device *device,
struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
struct libinput_device *dev;
+ if (removed_device == tp->buttons.trackpoint)
+ tp->buttons.trackpoint = NULL;
+
if (tp->sendevents.current_mode !=
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
return;
@@ -924,6 +944,8 @@ tp_init(struct tp_dispatch *tp,
if (tp_init_palmdetect(tp, device) != 0)
return -1;
+ tp->sendevents.disabled = false;
+
device->seat_caps |= EVDEV_DEVICE_POINTER;
return 0;
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index b67b063..efcfc95 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -198,6 +198,8 @@ struct tp_dispatch {
int32_t rightbutton_left_edge;
int32_t leftbutton_right_edge;
} top_area;
+
+ struct evdev_device *trackpoint;
} buttons; /* physical buttons */
struct {
@@ -221,6 +223,7 @@ struct tp_dispatch {
struct {
struct libinput_device_config_send_events config;
enum libinput_config_send_events_mode current_mode;
+ bool disabled;
} sendevents;
};
@@ -249,6 +252,9 @@ void
tp_init_softbuttons(struct tp_dispatch *tp, struct evdev_device *device);
void
+tp_expand_softbuttons(struct tp_dispatch *tp);
+
+void
tp_destroy_buttons(struct tp_dispatch *tp);
int
diff --git a/src/evdev.c b/src/evdev.c
index 0a8f2ba..0233ec6 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -560,6 +560,16 @@ evdev_tag_external_mouse(struct evdev_device *device,
}
static void
+evdev_tag_trackpoint(struct evdev_device *device,
+ struct udev_device *udev_device)
+{
+ const char *name = libevdev_get_name(device->evdev);
+
+ if (strstr(name, "TrackPoint") != NULL)
+ device->tags |= EVDEV_TAG_TRACKPOINT;
+}
+
+static void
fallback_process(struct evdev_dispatch *dispatch,
struct evdev_device *device,
struct input_event *event,
@@ -597,6 +607,7 @@ fallback_tag_device(struct evdev_device *device,
struct udev_device *udev_device)
{
evdev_tag_external_mouse(device, udev_device);
+ evdev_tag_trackpoint(device, udev_device);
}
static int
diff --git a/src/evdev.h b/src/evdev.h
index f5345fa..5101de4 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -51,6 +51,7 @@ enum evdev_device_seat_capability {
enum evdev_device_tags {
EVDEV_TAG_EXTERNAL_MOUSE = (1 << 0),
EVDEV_TAG_INTERNAL_TOUCHPAD = (1 << 1),
+ EVDEV_TAG_TRACKPOINT = (1 << 2),
};
struct mt_slot {
diff --git a/test/device.c b/test/device.c
index 3f7ec4c..33aae04 100644
--- a/test/device.c
+++ b/test/device.c
@@ -509,6 +509,62 @@ START_TEST(device_disable_release_softbutton)
}
END_TEST
+START_TEST(device_disable_topsoftbutton)
+{
+ struct litest_device *dev = litest_current_device();
+ struct litest_device *trackpoint;
+ struct libinput *li = dev->libinput;
+ struct libinput_device *device;
+ enum libinput_config_status status;
+
+ struct libinput_event *event;
+ struct libinput_event_pointer *ptrevent;
+
+ device = dev->libinput_device;
+
+ trackpoint = litest_add_device(li, LITEST_TRACKPOINT);
+
+ status = libinput_device_config_send_events_set_mode(device,
+ LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
+ ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
+ litest_drain_events(li);
+
+ litest_touch_down(dev, 0, 90, 10);
+ litest_button_click(dev, BTN_LEFT, true);
+ litest_button_click(dev, BTN_LEFT, false);
+ litest_touch_up(dev, 0);
+
+ litest_wait_for_event(li);
+ event = libinput_get_event(li);
+ ck_assert_int_eq(libinput_event_get_type(event),
+ LIBINPUT_EVENT_POINTER_BUTTON);
+ ck_assert_int_eq(libinput_event_get_device(event),
+ trackpoint->libinput_device);
+ ptrevent = libinput_event_get_pointer_event(event);
+ ck_assert_int_eq(libinput_event_pointer_get_button(ptrevent),
+ BTN_RIGHT);
+ ck_assert_int_eq(libinput_event_pointer_get_button_state(ptrevent),
+ LIBINPUT_BUTTON_STATE_PRESSED);
+ libinput_event_destroy(event);
+
+ event = libinput_get_event(li);
+ ck_assert_int_eq(libinput_event_get_type(event),
+ LIBINPUT_EVENT_POINTER_BUTTON);
+ ck_assert_int_eq(libinput_event_get_device(event),
+ trackpoint->libinput_device);
+ ptrevent = libinput_event_get_pointer_event(event);
+ ck_assert_int_eq(libinput_event_pointer_get_button(ptrevent),
+ BTN_RIGHT);
+ ck_assert_int_eq(libinput_event_pointer_get_button_state(ptrevent),
+ LIBINPUT_BUTTON_STATE_RELEASED);
+ libinput_event_destroy(event);
+
+ litest_assert_empty_queue(li);
+
+ litest_delete_device(trackpoint);
+}
+END_TEST
+
int main (int argc, char **argv)
{
litest_add("device:sendevents", device_sendevents_config, LITEST_ANY, LITEST_TOUCHPAD);
@@ -527,5 +583,7 @@ int main (int argc, char **argv)
litest_add("device:sendevents", device_disable_release_tap_n_drag, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("device:sendevents", device_disable_release_softbutton, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD);
+ litest_add("device:sendevents", device_disable_topsoftbutton, LITEST_TOPBUTTONPAD, LITEST_ANY);
+
return litest_run(argc, argv);
}
--
1.9.3
More information about the wayland-devel
mailing list