From 1f0223e9fd77d9e3d586f0e2420fc1b7a2949a85 Mon Sep 17 00:00:00 2001 From: James Ye Date: Fri, 20 Jan 2017 16:54:13 +1100 Subject: [PATCH 01/18] Add a "switch" interface for parts of the SW_* range This will allow switch devices known to libinput to be exposed. Currently, this is SW_LID. libinput also handles switch events internally, e.g. a laptop touchpad will be disabled autmoatically when the lid is closed. This is transparent to the caller, although the caller will also receive the event. See https://bugs.freedesktop.org/show_bug.cgi?id=86223 This features is intended to be the main driver for the interface. Co-Authored-By: Peter Hutterer Signed-off-by: James Ye Signed-off-by: Peter Hutterer --- doc/Makefile.am | 1 + doc/switches.dox | 16 ++++++ src/libinput-private.h | 5 ++ src/libinput.c | 103 +++++++++++++++++++++++++++++++++++++ src/libinput.h | 112 +++++++++++++++++++++++++++++++++++++++++ src/libinput.sym | 9 ++++ test/litest.c | 3 ++ tools/event-debug.c | 31 ++++++++++++ tools/event-gui.c | 2 + 9 files changed, 282 insertions(+) create mode 100644 doc/switches.dox diff --git a/doc/Makefile.am b/doc/Makefile.am index 698a3161..a92d7915 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -22,6 +22,7 @@ header_files = \ $(srcdir)/reporting-bugs.dox \ $(srcdir)/scrolling.dox \ $(srcdir)/seats.dox \ + $(srcdir)/switches.dox \ $(srcdir)/t440-support.dox \ $(srcdir)/tablet-support.dox \ $(srcdir)/tapping.dox \ diff --git a/doc/switches.dox b/doc/switches.dox new file mode 100644 index 00000000..4bb26757 --- /dev/null +++ b/doc/switches.dox @@ -0,0 +1,16 @@ +/** +@page switches Switches + +libinput supports a couple of switches. Unlike button events that come in +press and release pairs, switches are usually toggled once and left at the +setting for an extended period of time. + +Only some switches are handled by libinput, see @ref libinput_switch for a +list of supported switches. Switch events are exposed to the caller, but +libinput may handle some switch events internally and enable or disable +specific features based on a switch state. + +The order of switch events is guaranteed to be correct, i.e., a switch will +never send consecutive switch on, or switch off, events. + +*/ diff --git a/src/libinput-private.h b/src/libinput-private.h index 39c169cd..07bed365 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -623,6 +623,11 @@ tablet_pad_notify_strip(struct libinput_device *device, double value, enum libinput_tablet_pad_strip_axis_source source, struct libinput_tablet_pad_mode_group *group); +void +switch_notify_toggle(struct libinput_device *device, + uint64_t time, + enum libinput_switch sw, + enum libinput_switch_state state); static inline uint64_t libinput_now(struct libinput *libinput) diff --git a/src/libinput.c b/src/libinput.c index 4daa11d7..49971530 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -159,6 +159,13 @@ struct libinput_event_tablet_pad { } strip; }; +struct libinput_event_switch { + struct libinput_event base; + uint64_t time; + enum libinput_switch sw; + enum libinput_switch_state state; +}; + LIBINPUT_ATTRIBUTE_PRINTF(3, 0) static void libinput_default_log_func(struct libinput *libinput, @@ -365,6 +372,17 @@ libinput_event_get_device_notify_event(struct libinput_event *event) return (struct libinput_event_device_notify *) event; } +LIBINPUT_EXPORT struct libinput_event_switch * +libinput_event_get_switch_event(struct libinput_event *event) +{ + require_event_type(libinput_event_get_context(event), + event->type, + NULL, + LIBINPUT_EVENT_SWITCH_TOGGLE); + + return (struct libinput_event_switch *) event; +} + LIBINPUT_EXPORT uint32_t libinput_event_keyboard_get_time(struct libinput_event_keyboard *event) { @@ -1508,6 +1526,61 @@ libinput_tablet_tool_unref(struct libinput_tablet_tool *tool) return NULL; } +LIBINPUT_EXPORT struct libinput_event * +libinput_event_switch_get_base_event(struct libinput_event_switch *event) +{ + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + NULL, + LIBINPUT_EVENT_SWITCH_TOGGLE); + + return &event->base; +} + +LIBINPUT_EXPORT enum libinput_switch +libinput_event_switch_get_switch(struct libinput_event_switch *event) +{ + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_SWITCH_TOGGLE); + + return event->sw; +} + +LIBINPUT_EXPORT enum libinput_switch_state +libinput_event_switch_get_switch_state(struct libinput_event_switch *event) +{ + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_SWITCH_TOGGLE); + + return event->state; +} + +LIBINPUT_EXPORT uint32_t +libinput_event_switch_get_time(struct libinput_event_switch *event) +{ + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_SWITCH_TOGGLE); + + return us2ms(event->time); +} + +LIBINPUT_EXPORT uint64_t +libinput_event_switch_get_time_usec(struct libinput_event_switch *event) +{ + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_SWITCH_TOGGLE); + + return event->time; +} + struct libinput_source * libinput_add_fd(struct libinput *libinput, int fd, @@ -2024,6 +2097,9 @@ device_has_cap(struct libinput_device *device, case LIBINPUT_DEVICE_CAP_TABLET_PAD: capability = "CAP_TABLET_PAD"; break; + case LIBINPUT_DEVICE_CAP_SWITCH: + capability = "CAP_SWITCH"; + break; } log_bug_libinput(device->seat->libinput, @@ -2619,6 +2695,7 @@ event_type_to_str(enum libinput_event_type type) CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_BEGIN); CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_UPDATE); CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_END); + CASE_RETURN_STRING(LIBINPUT_EVENT_SWITCH_TOGGLE); case LIBINPUT_EVENT_NONE: abort(); } @@ -2626,6 +2703,32 @@ event_type_to_str(enum libinput_event_type type) return NULL; } +void +switch_notify_toggle(struct libinput_device *device, + uint64_t time, + enum libinput_switch sw, + enum libinput_switch_state state) +{ + struct libinput_event_switch *switch_event; + + if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_SWITCH)) + return; + + switch_event = zalloc(sizeof *switch_event); + if (!switch_event) + return; + + *switch_event = (struct libinput_event_switch) { + .time = time, + .sw = sw, + .state = state, + }; + + post_device_event(device, time, + LIBINPUT_EVENT_SWITCH_TOGGLE, + &switch_event->base); +} + static void libinput_post_event(struct libinput *libinput, struct libinput_event *event) diff --git a/src/libinput.h b/src/libinput.h index fdbba3c1..f8b123a4 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -187,6 +187,7 @@ enum libinput_device_capability { LIBINPUT_DEVICE_CAP_TABLET_TOOL = 3, LIBINPUT_DEVICE_CAP_TABLET_PAD = 4, LIBINPUT_DEVICE_CAP_GESTURE = 5, + LIBINPUT_DEVICE_CAP_SWITCH = 6, }; /** @@ -597,6 +598,38 @@ void * libinput_tablet_pad_mode_group_get_user_data( struct libinput_tablet_pad_mode_group *group); +/** + * @ingroup device + * + * The state of a switch. + */ +enum libinput_switch_state { + LIBINPUT_SWITCH_STATE_OFF = 0, + LIBINPUT_SWITCH_STATE_ON = 1, +}; + +/** + * @ingroup device + * + * The type of a switch. + */ +enum libinput_switch { + /** + * The laptop lid was closed when the switch state is @ref + * LIBINPUT_SWITCH_STATE_ON, or was opened when it is @ref + * LIBINPUT_SWITCH_STATE_OFF. + */ + LIBINPUT_SWITCH_LID = 1, +}; + +/** + * @ingroup event_switch + * @struct libinput_event_switch + * + * A switch event representing a changed state in a switch. + */ +struct libinput_event_switch; + /** * @ingroup base * @@ -752,6 +785,8 @@ enum libinput_event_type { LIBINPUT_EVENT_GESTURE_PINCH_BEGIN, LIBINPUT_EVENT_GESTURE_PINCH_UPDATE, LIBINPUT_EVENT_GESTURE_PINCH_END, + + LIBINPUT_EVENT_SWITCH_TOGGLE = 900, }; /** @@ -888,6 +923,19 @@ libinput_event_get_tablet_tool_event(struct libinput_event *event); struct libinput_event_tablet_pad * libinput_event_get_tablet_pad_event(struct libinput_event *event); +/** + * @ingroup event + * + * Return the switch event that is this input event. If the event type does + * not match the switch event types, this function returns NULL. + * + * The inverse of this function is libinput_event_switch_get_base_event(). + * + * @return A switch event, or NULL for other events + */ +struct libinput_event_switch * +libinput_event_get_switch_event(struct libinput_event *event); + /** * @ingroup event * @@ -2698,6 +2746,70 @@ libinput_event_tablet_pad_get_time(struct libinput_event_tablet_pad *event); uint64_t libinput_event_tablet_pad_get_time_usec(struct libinput_event_tablet_pad *event); +/** + * @defgroup event_switch Switch events + * + * Events that come from switch devices. + */ + +/** + * @ingroup event_switch + * + * Return the switch that triggered this event. + * For pointer events that are not of type @ref + * LIBINPUT_EVENT_SWITCH_TOGGLE, this function returns 0. + * + * @note It is an application bug to call this function for events other than + * @ref LIBINPUT_EVENT_SWITCH_TOGGLE. + * + * @param event The libinput switch event + * @return The switch triggering this event + */ +enum libinput_switch +libinput_event_switch_get_switch(struct libinput_event_switch *event); + +/** + * @ingroup event_switch + * + * Return the switch state that triggered this event. + * For switch events that are not of type @ref + * LIBINPUT_EVENT_SWITCH_TOGGLE, this function returns 0. + * + * @note It is an application bug to call this function for events other than + * @ref LIBINPUT_EVENT_SWITCH_TOGGLE. + * + * @param event The libinput switch event + * @return The switch state triggering this event + */ +enum libinput_switch_state +libinput_event_switch_get_switch_state(struct libinput_event_switch *event); + +/** + * @ingroup event_switch + * + * @return The generic libinput_event of this event + */ +struct libinput_event * +libinput_event_switch_get_base_event(struct libinput_event_switch *event); + +/** + * @ingroup event_switch + * + * @param event The libinput switch event + * @return The event time for this event + */ +uint32_t +libinput_event_switch_get_time(struct libinput_event_switch *event); + +/** + * @ingroup event_switch + * + * @param event The libinput switch event + * @return The event time for this event in microseconds + */ +uint64_t +libinput_event_switch_get_time_usec(struct libinput_event_switch *event); + /** * @defgroup base Initialization and manipulation of libinput contexts */ diff --git a/src/libinput.sym b/src/libinput.sym index 97bb57f7..f440521f 100644 --- a/src/libinput.sym +++ b/src/libinput.sym @@ -280,3 +280,12 @@ LIBINPUT_1.5 { libinput_device_config_tap_get_default_button_map; libinput_device_config_tap_set_button_map; } LIBINPUT_1.4; + +LIBINPUT_SWITCH { + libinput_event_get_switch_event; + libinput_event_switch_get_base_event; + libinput_event_switch_get_switch_state; + libinput_event_switch_get_switch; + libinput_event_switch_get_time; + libinput_event_switch_get_time_usec; +} LIBINPUT_1.5; diff --git a/test/litest.c b/test/litest.c index b3e7ba3d..5b1e7b54 100644 --- a/test/litest.c +++ b/test/litest.c @@ -2203,6 +2203,9 @@ litest_event_type_str(enum libinput_event_type type) case LIBINPUT_EVENT_TABLET_PAD_STRIP: str = "TABLET PAD STRIP"; break; + case LIBINPUT_EVENT_SWITCH_TOGGLE: + str = "SWITCH TOGGLE"; + break; } return str; } diff --git a/tools/event-debug.c b/tools/event-debug.c index a3e460a2..779b54ac 100644 --- a/tools/event-debug.c +++ b/tools/event-debug.c @@ -133,6 +133,9 @@ print_event_header(struct libinput_event *ev) case LIBINPUT_EVENT_TABLET_PAD_STRIP: type = "TABLET_PAD_STRIP"; break; + case LIBINPUT_EVENT_SWITCH_TOGGLE: + type = "SWITCH_TOGGLE"; + break; } prefix = (last_device != dev) ? '-' : ' '; @@ -194,6 +197,9 @@ print_device_notify(struct libinput_event *ev) if (libinput_device_has_capability(dev, LIBINPUT_DEVICE_CAP_TABLET_PAD)) printf("P"); + if (libinput_device_has_capability(dev, + LIBINPUT_DEVICE_CAP_SWITCH)) + printf("S"); if (libinput_device_get_size(dev, &w, &h) == 0) printf(" size %.0fx%.0fmm", w, h); @@ -706,6 +712,28 @@ print_tablet_pad_strip_event(struct libinput_event *ev) mode); } +static void +print_switch_event(struct libinput_event *ev) +{ + struct libinput_event_switch *sw = libinput_event_get_switch_event(ev); + enum libinput_switch_state state; + const char *which; + + print_event_time(libinput_event_switch_get_time(sw)); + + switch (libinput_event_switch_get_switch(sw)) { + case LIBINPUT_SWITCH_LID: + which = "lid"; + break; + default: + abort(); + } + + state = libinput_event_switch_get_switch_state(sw); + + printf("switch %s state %d\n", which, state); +} + static int handle_and_print_events(struct libinput *li) { @@ -794,6 +822,9 @@ handle_and_print_events(struct libinput *li) case LIBINPUT_EVENT_TABLET_PAD_STRIP: print_tablet_pad_strip_event(ev); break; + case LIBINPUT_EVENT_SWITCH_TOGGLE: + print_switch_event(ev); + break; } libinput_event_destroy(ev); diff --git a/tools/event-gui.c b/tools/event-gui.c index e819901b..155cc95f 100644 --- a/tools/event-gui.c +++ b/tools/event-gui.c @@ -845,6 +845,8 @@ handle_event_libinput(GIOChannel *source, GIOCondition condition, gpointer data) case LIBINPUT_EVENT_TABLET_PAD_RING: case LIBINPUT_EVENT_TABLET_PAD_STRIP: break; + case LIBINPUT_EVENT_SWITCH_TOGGLE: + break; } libinput_event_destroy(ev); From 4aeb3cc018108e561597b21797883f3332c5d551 Mon Sep 17 00:00:00 2001 From: James Ye Date: Fri, 20 Jan 2017 16:54:14 +1100 Subject: [PATCH 02/18] Add evdev_dispatch interface for lid switch Create a lid_switch_interface to handle lid switch events, so the touchpad can be disabled when lid is closed. Signed-off-by: James Ye Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- src/evdev.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/evdev.h | 8 ++++ 2 files changed, 112 insertions(+), 2 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index d086c18e..245d8787 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -68,6 +68,7 @@ enum evdev_device_udev_tags { EVDEV_UDEV_TAG_TABLET_PAD = (1 << 8), EVDEV_UDEV_TAG_POINTINGSTICK = (1 << 9), EVDEV_UDEV_TAG_TRACKBALL = (1 << 10), + EVDEV_UDEV_TAG_SWITCH = (1 << 11), }; struct evdev_udev_tag_match { @@ -88,6 +89,7 @@ static const struct evdev_udev_tag_match evdev_udev_tag_matches[] = { {"ID_INPUT_ACCELEROMETER", EVDEV_UDEV_TAG_ACCELEROMETER}, {"ID_INPUT_POINTINGSTICK", EVDEV_UDEV_TAG_POINTINGSTICK}, {"ID_INPUT_TRACKBALL", EVDEV_UDEV_TAG_TRACKBALL}, + {"ID_INPUT_SWITCH", EVDEV_UDEV_TAG_SWITCH}, /* sentinel value */ { 0 }, @@ -1028,6 +1030,24 @@ fallback_process_absolute(struct fallback_dispatch *dispatch, } } +static void +lid_switch_process_switch(struct lid_switch_dispatch *dispatch, + struct evdev_device *device, + struct input_event *e, + uint64_t time) +{ + switch (e->code) { + case SW_LID: + dispatch->lid_is_closed = !!e->value; + + switch_notify_toggle(&device->base, + time, + LIBINPUT_SWITCH_LID, + dispatch->lid_is_closed); + break; + } +} + static inline bool fallback_any_button_down(struct fallback_dispatch *dispatch, struct evdev_device *device) @@ -1082,6 +1102,13 @@ evdev_tag_keyboard(struct evdev_device *device, device->tags |= EVDEV_TAG_KEYBOARD; } +static void +evdev_tag_lid_switch(struct evdev_device *device, + struct udev_device *udev_device) +{ + device->tags |= EVDEV_TAG_LID_SWITCH; +} + static void fallback_process(struct evdev_dispatch *evdev_dispatch, struct evdev_device *device, @@ -1123,6 +1150,27 @@ fallback_process(struct evdev_dispatch *evdev_dispatch, } } +static void +lid_switch_process(struct evdev_dispatch *evdev_dispatch, + struct evdev_device *device, + struct input_event *event, + uint64_t time) +{ + struct lid_switch_dispatch *dispatch = + (struct lid_switch_dispatch*)evdev_dispatch; + + switch (event->type) { + case EV_SW: + lid_switch_process_switch(dispatch, device, event, time); + break; + case EV_SYN: + break; + default: + assert(0 && "Unknown event type"); + break; + } +} + static void release_touches(struct fallback_dispatch *dispatch, struct evdev_device *device, @@ -1248,6 +1296,15 @@ fallback_destroy(struct evdev_dispatch *evdev_dispatch) free(dispatch); } +static void +lid_switch_destroy(struct evdev_dispatch *evdev_dispatch) +{ + struct lid_switch_dispatch *dispatch = + (struct lid_switch_dispatch*)evdev_dispatch; + + free(dispatch); +} + static int evdev_calibration_has_matrix(struct libinput_device *libinput_device) { @@ -1302,6 +1359,19 @@ struct evdev_dispatch_interface fallback_interface = { fallback_toggle_touch, /* toggle_touch */ }; +struct evdev_dispatch_interface lid_switch_interface = { + lid_switch_process, + NULL, /* suspend */ + NULL, /* remove */ + lid_switch_destroy, + NULL, /* device_added */ + NULL, /* device_removed */ + NULL, /* device_suspended */ + NULL, /* device_resumed */ + NULL, /* post_added */ + NULL, /* toggle_touch */ +}; + static uint32_t evdev_sendevents_get_modes(struct libinput_device *device) { @@ -1811,6 +1881,24 @@ fallback_dispatch_create(struct libinput_device *device) return &dispatch->base; } +static struct evdev_dispatch * +lid_switch_dispatch_create(struct libinput_device *device) +{ + struct lid_switch_dispatch *dispatch = zalloc(sizeof *dispatch); + struct evdev_device *lid_device = (struct evdev_device *)device; + + if (dispatch == NULL) + return NULL; + + dispatch->base.interface = &lid_switch_interface; + + evdev_init_sendevents(lid_device, &dispatch->base); + + dispatch->lid_is_closed = false; + + return &dispatch->base; +} + static inline void evdev_process_event(struct evdev_device *device, struct input_event *e) { @@ -2534,7 +2622,7 @@ evdev_configure_device(struct evdev_device *device) } log_info(libinput, - "input device '%s', %s is tagged by udev as:%s%s%s%s%s%s%s%s%s%s\n", + "input device '%s', %s is tagged by udev as:%s%s%s%s%s%s%s%s%s%s%s\n", device->devname, devnode, udev_tags & EVDEV_UDEV_TAG_KEYBOARD ? " Keyboard" : "", udev_tags & EVDEV_UDEV_TAG_MOUSE ? " Mouse" : "", @@ -2545,7 +2633,8 @@ evdev_configure_device(struct evdev_device *device) udev_tags & EVDEV_UDEV_TAG_JOYSTICK ? " Joystick" : "", udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER ? " Accelerometer" : "", udev_tags & EVDEV_UDEV_TAG_TABLET_PAD ? " TabletPad" : "", - udev_tags & EVDEV_UDEV_TAG_TRACKBALL ? " Trackball" : ""); + udev_tags & EVDEV_UDEV_TAG_TRACKBALL ? " Trackball" : "", + udev_tags & EVDEV_UDEV_TAG_SWITCH ? " Switch" : ""); if (udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER) { log_info(libinput, @@ -2657,6 +2746,17 @@ evdev_configure_device(struct evdev_device *device) device->devname, devnode); } + if (udev_tags & EVDEV_UDEV_TAG_SWITCH && + libevdev_has_event_code(evdev, EV_SW, SW_LID)) { + dispatch = lid_switch_dispatch_create(&device->base); + device->seat_caps |= EVDEV_DEVICE_SWITCH; + evdev_tag_lid_switch(device, device->udev_device); + log_info(libinput, + "input device '%s', %s is a switch device\n", + device->devname, devnode); + return dispatch; + } + if (device->seat_caps & EVDEV_DEVICE_POINTER && libevdev_has_event_code(evdev, EV_REL, REL_X) && libevdev_has_event_code(evdev, EV_REL, REL_Y) && @@ -3089,6 +3189,8 @@ evdev_device_has_capability(struct evdev_device *device, return !!(device->seat_caps & EVDEV_DEVICE_TABLET); case LIBINPUT_DEVICE_CAP_TABLET_PAD: return !!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD); + case LIBINPUT_DEVICE_CAP_SWITCH: + return !!(device->seat_caps & EVDEV_DEVICE_SWITCH); default: return false; } diff --git a/src/evdev.h b/src/evdev.h index 95cde8bc..32d854f1 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -63,6 +63,7 @@ enum evdev_device_seat_capability { EVDEV_DEVICE_TABLET = (1 << 3), EVDEV_DEVICE_TABLET_PAD = (1 << 4), EVDEV_DEVICE_GESTURE = (1 << 5), + EVDEV_DEVICE_SWITCH = (1 << 6), }; enum evdev_device_tags { @@ -71,6 +72,7 @@ enum evdev_device_tags { EVDEV_TAG_EXTERNAL_TOUCHPAD = (1 << 2), EVDEV_TAG_TRACKPOINT = (1 << 3), EVDEV_TAG_KEYBOARD = (1 << 4), + EVDEV_TAG_LID_SWITCH = (1 << 5), }; enum evdev_middlebutton_state { @@ -334,6 +336,12 @@ struct fallback_dispatch { bool ignore_events; }; +struct lid_switch_dispatch { + struct evdev_dispatch base; + + bool lid_is_closed; +}; + struct evdev_device * evdev_device_create(struct libinput_seat *seat, struct udev_device *device); From f1cf83425edd4fa64ac6601e569e10f8bc95324b Mon Sep 17 00:00:00 2001 From: James Ye Date: Fri, 20 Jan 2017 16:54:15 +1100 Subject: [PATCH 03/18] Pair touchpad and lid_switch for disable Add listener for lid switch events, disable touchpad on switch event. Signed-off-by: James Ye Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- src/evdev-mt-touchpad.c | 49 +++++++++++++++++++++++++++++++++++++++++ src/evdev-mt-touchpad.h | 5 +++++ 2 files changed, 54 insertions(+) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 56822df2..6e2818cc 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1176,6 +1176,10 @@ tp_remove_sendevents(struct tp_dispatch *tp) if (tp->dwt.keyboard) libinput_device_remove_event_listener( &tp->dwt.keyboard_listener); + + if (tp->lid_switch.lid_switch) + libinput_device_remove_event_listener( + &tp->lid_switch.lid_switch_listener); } static void @@ -1552,6 +1556,50 @@ tp_pair_trackpoint(struct evdev_device *touchpad, } } +static void +tp_lid_switch_event(uint64_t time, struct libinput_event *event, void *data) +{ + struct tp_dispatch *tp = data; + struct libinput_event_switch *swev; + + swev = libinput_event_get_switch_event(event); + + if (swev) { + switch (libinput_event_switch_get_switch_state(swev)) { + case LIBINPUT_SWITCH_STATE_OFF: + tp_resume(tp, tp->device); + log_debug(tp_libinput_context(tp), "lid: resume touchpad\n"); + break; + case LIBINPUT_SWITCH_STATE_ON: + tp_suspend(tp, tp->device); + log_debug(tp_libinput_context(tp), "lid: suspend touchpad\n"); + break; + } + } +} + +static void +tp_pair_lid_switch(struct evdev_device *touchpad, + struct evdev_device *lid_switch) +{ + struct tp_dispatch *tp = (struct tp_dispatch*)touchpad->dispatch; + + if ((lid_switch->tags & EVDEV_TAG_LID_SWITCH) == 0) + return; + + if (tp->lid_switch.lid_switch == NULL) { + log_debug(tp_libinput_context(tp), + "lid_switch: activated for %s<->%s\n", + touchpad->devname, + lid_switch->devname); + + libinput_device_add_event_listener(&lid_switch->base, + &tp->lid_switch.lid_switch_listener, + tp_lid_switch_event, tp); + tp->lid_switch.lid_switch = lid_switch; + } +} + static void tp_interface_device_added(struct evdev_device *device, struct evdev_device *added_device) @@ -1560,6 +1608,7 @@ tp_interface_device_added(struct evdev_device *device, tp_pair_trackpoint(device, added_device); tp_dwt_pair_keyboard(device, added_device); + tp_pair_lid_switch(device, added_device); if (tp->sendevents.current_mode != LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE) diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index fb15956f..8ae1bf9b 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -376,6 +376,11 @@ struct tp_dispatch { */ unsigned int nonmotion_event_count; } quirks; + + struct { + struct libinput_event_listener lid_switch_listener; + struct evdev_device *lid_switch; + } lid_switch; }; #define tp_for_each_touch(_tp, _t) \ From a817098fcb7d938eb86d6531b3aefbcb31f9dbf2 Mon Sep 17 00:00:00 2001 From: James Ye Date: Fri, 20 Jan 2017 16:54:16 +1100 Subject: [PATCH 04/18] test: add tests for lid switch Ship a custom udev rule for the test device until systemd v333 is commonplace. Signed-off-by: James Ye Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- test/Makefile.am | 4 +- test/litest-device-lid-switch.c | 69 +++++++++ test/litest.c | 30 ++++ test/litest.h | 11 ++ test/test-device.c | 3 +- test/test-lid.c | 265 ++++++++++++++++++++++++++++++++ test/test-misc.c | 50 ++++++ 7 files changed, 430 insertions(+), 2 deletions(-) create mode 100644 test/litest-device-lid-switch.c create mode 100644 test/test-lid.c diff --git a/test/Makefile.am b/test/Makefile.am index 0d54dab6..ce1973fe 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -32,6 +32,7 @@ liblitest_la_SOURCES = \ litest-device-keyboard.c \ litest-device-keyboard-all-codes.c \ litest-device-keyboard-razer-blackwidow.c \ + litest-device-lid-switch.c \ litest-device-logitech-trackball.c \ litest-device-nexus4-touch-screen.c \ litest-device-magic-trackpad.c \ @@ -117,7 +118,8 @@ libinput_test_suite_runner_SOURCES = test-udev.c \ test-misc.c \ test-keyboard.c \ test-device.c \ - test-gestures.c + test-gestures.c \ + test-lid.c libinput_test_suite_runner_CFLAGS = $(AM_CFLAGS) -DLIBINPUT_LT_VERSION="\"$(LIBINPUT_LT_VERSION)\"" libinput_test_suite_runner_LDADD = $(TEST_LIBS) diff --git a/test/litest-device-lid-switch.c b/test/litest-device-lid-switch.c new file mode 100644 index 00000000..823a5c9d --- /dev/null +++ b/test/litest-device-lid-switch.c @@ -0,0 +1,69 @@ +/* + * Copyright © 2017 James Ye + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include "litest.h" +#include "litest-int.h" + +static void +litest_lid_switch_setup(void) +{ + struct litest_device *d = litest_create_device(LITEST_LID_SWITCH); + litest_set_current_device(d); +} + +static struct input_id input_id = { + .bustype = 0x19, + .vendor = 0x0, + .product = 0x5, +}; + +static int events[] = { + EV_SW, SW_LID, + -1, -1, +}; + +static const char udev_rule[] = +"ACTION==\"remove\", GOTO=\"switch_end\"\n" +"KERNEL!=\"event*\", GOTO=\"switch_end\"\n" +"\n" +"ATTRS{name}==\"litest Lid Switch*\",\\\n" +" ENV{ID_INPUT_SWITCH}=\"1\"\n" +"\n" +"LABEL=\"switch_end\""; + +struct litest_test_device litest_lid_switch_device = { + .type = LITEST_LID_SWITCH, + .features = LITEST_SWITCH, + .shortname = "lid switch", + .setup = litest_lid_switch_setup, + .interface = NULL, + + .name = "Lid Switch", + .id = &input_id, + .events = events, + .absinfo = NULL, + + .udev_rule = udev_rule, +}; diff --git a/test/litest.c b/test/litest.c index 5b1e7b54..7a5ec57e 100644 --- a/test/litest.c +++ b/test/litest.c @@ -408,6 +408,7 @@ extern struct litest_test_device litest_acer_hawaii_keyboard_device; extern struct litest_test_device litest_acer_hawaii_touchpad_device; extern struct litest_test_device litest_synaptics_rmi4_device; extern struct litest_test_device litest_mouse_wheel_tilt_device; +extern struct litest_test_device litest_lid_switch_device; struct litest_test_device* devices[] = { &litest_synaptics_clickpad_device, @@ -470,6 +471,7 @@ struct litest_test_device* devices[] = { &litest_acer_hawaii_touchpad_device, &litest_synaptics_rmi4_device, &litest_mouse_wheel_tilt_device, + &litest_lid_switch_device, NULL, }; @@ -1907,6 +1909,14 @@ litest_keyboard_key(struct litest_device *d, unsigned int key, bool is_press) litest_button_click(d, key, is_press); } +void +litest_lid_action(struct litest_device *dev, + enum libinput_switch_state state) +{ + litest_event(dev, EV_SW, SW_LID, state); + litest_event(dev, EV_SYN, SYN_REPORT, 0); +} + static int litest_scale_axis(const struct litest_device *d, unsigned int axis, @@ -2819,6 +2829,25 @@ litest_is_pad_strip_event(struct libinput_event *event, return p; } +struct libinput_event_switch * +litest_is_switch_event(struct libinput_event *event, + enum libinput_switch sw, + enum libinput_switch_state state) +{ + struct libinput_event_switch *swev; + enum libinput_event_type type = LIBINPUT_EVENT_SWITCH_TOGGLE; + + litest_assert_notnull(event); + litest_assert_event_type(event, type); + swev = libinput_event_get_switch_event(event); + + litest_assert_int_eq(libinput_event_switch_get_switch(swev), sw); + litest_assert_int_eq(libinput_event_switch_get_switch_state(swev), + state); + + return swev; +} + void litest_assert_pad_button_event(struct libinput *li, unsigned int button, @@ -3323,6 +3352,7 @@ main(int argc, char **argv) litest_setup_tests_keyboard(); litest_setup_tests_device(); litest_setup_tests_gestures(); + litest_setup_tests_lid(); if (mode == LITEST_MODE_LIST) { litest_list_tests(&all_tests); diff --git a/test/litest.h b/test/litest.h index e6d35a90..00756046 100644 --- a/test/litest.h +++ b/test/litest.h @@ -49,6 +49,7 @@ extern void litest_setup_tests_misc(void); extern void litest_setup_tests_keyboard(void); extern void litest_setup_tests_device(void); extern void litest_setup_tests_gestures(void); +extern void litest_setup_tests_lid(void); void litest_fail_condition(const char *file, @@ -228,6 +229,7 @@ enum litest_device_type { LITEST_ACER_HAWAII_TOUCHPAD, LITEST_SYNAPTICS_RMI4, LITEST_MOUSE_WHEEL_TILT, + LITEST_LID_SWITCH, }; enum litest_device_feature { @@ -259,6 +261,7 @@ enum litest_device_feature { LITEST_STRIP = 1 << 23, LITEST_TRACKBALL = 1 << 24, LITEST_LEDS = 1 << 25, + LITEST_SWITCH = 1 << 26, }; struct litest_device { @@ -526,6 +529,9 @@ litest_keyboard_key(struct litest_device *d, unsigned int key, bool is_press); +void litest_lid_action(struct litest_device *d, + enum libinput_switch_state state); + void litest_wait_for_event(struct libinput *li); @@ -589,6 +595,11 @@ litest_is_pad_strip_event(struct libinput_event *event, unsigned int number, enum libinput_tablet_pad_strip_axis_source source); +struct libinput_event_switch * +litest_is_switch_event(struct libinput_event *event, + enum libinput_switch sw, + enum libinput_switch_state state); + void litest_assert_button_event(struct libinput *li, unsigned int button, diff --git a/test/test-device.c b/test/test-device.c index 3fa35d8b..8f06f7e4 100644 --- a/test/test-device.c +++ b/test/test-device.c @@ -1493,6 +1493,7 @@ START_TEST(device_capability_at_least_one) LIBINPUT_DEVICE_CAP_TABLET_TOOL, LIBINPUT_DEVICE_CAP_TABLET_PAD, LIBINPUT_DEVICE_CAP_GESTURE, + LIBINPUT_DEVICE_CAP_SWITCH, }; enum libinput_device_capability *cap; int ncaps = 0; @@ -1512,7 +1513,7 @@ START_TEST(device_capability_check_invalid) struct libinput_device *device = dev->libinput_device; ck_assert(!libinput_device_has_capability(device, -1)); - ck_assert(!libinput_device_has_capability(device, 6)); + ck_assert(!libinput_device_has_capability(device, 7)); ck_assert(!libinput_device_has_capability(device, 0xffff)); } diff --git a/test/test-lid.c b/test/test-lid.c new file mode 100644 index 00000000..e1a9088c --- /dev/null +++ b/test/test-lid.c @@ -0,0 +1,265 @@ +/* + * Copyright © 2017 James Ye + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +#include +#include + +#include "libinput-util.h" +#include "litest.h" + +START_TEST(lid_switch) +{ + struct litest_device *sw = litest_current_device(); + struct libinput *li = sw->libinput; + struct libinput_event *event; + + litest_drain_events(li); + + /* lid closed */ + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + libinput_dispatch(li); + + event = libinput_get_event(li); + litest_is_switch_event(event, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_ON); + libinput_event_destroy(event); + + /* lid opened */ + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_OFF); + libinput_dispatch(li); + + event = libinput_get_event(li); + litest_is_switch_event(event, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_OFF); + libinput_event_destroy(event); + + litest_assert_empty_queue(li); +} +END_TEST + +START_TEST(lid_switch_double) +{ + struct litest_device *sw = litest_current_device(); + struct libinput *li = sw->libinput; + struct libinput_event *event; + + litest_drain_events(li); + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + libinput_dispatch(li); + + event = libinput_get_event(li); + litest_is_switch_event(event, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_ON); + libinput_event_destroy(event); + + /* This will be filtered by the kernel, so this test is a bit + * useless */ + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + libinput_dispatch(li); + + litest_assert_empty_queue(li); +} +END_TEST + +static inline struct litest_device * +lid_init_paired_touchpad(struct libinput *li) +{ + enum litest_device_type which = LITEST_SYNAPTICS_I2C; + + return litest_add_device(li, which); +} + +START_TEST(lid_disable_touchpad) +{ + struct litest_device *sw = litest_current_device(); + struct litest_device *touchpad; + struct libinput *li = sw->libinput; + + touchpad = lid_init_paired_touchpad(li); + litest_disable_tap(touchpad->libinput_device); + litest_drain_events(li); + + /* lid is down - no events */ + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE); + + litest_touch_down(touchpad, 0, 50, 50); + litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1); + litest_touch_up(touchpad, 0); + litest_assert_empty_queue(li); + + /* lid is up - motion events */ + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_OFF); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE); + + litest_touch_down(touchpad, 0, 50, 50); + litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1); + litest_touch_up(touchpad, 0); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); + + litest_delete_device(touchpad); +} +END_TEST + +START_TEST(lid_disable_touchpad_during_touch) +{ + struct litest_device *sw = litest_current_device(); + struct litest_device *touchpad; + struct libinput *li = sw->libinput; + + touchpad = lid_init_paired_touchpad(li); + litest_disable_tap(touchpad->libinput_device); + litest_drain_events(li); + + litest_touch_down(touchpad, 0, 50, 50); + litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 5, 1); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE); + + litest_touch_move_to(touchpad, 0, 70, 50, 50, 50, 5, 1); + litest_touch_up(touchpad, 0); + litest_assert_empty_queue(li); + + litest_delete_device(touchpad); +} +END_TEST + +START_TEST(lid_disable_touchpad_edge_scroll) +{ + struct litest_device *sw = litest_current_device(); + struct litest_device *touchpad; + struct libinput *li = sw->libinput; + + touchpad = lid_init_paired_touchpad(li); + litest_enable_edge_scroll(touchpad); + + litest_drain_events(li); + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE); + + litest_touch_down(touchpad, 0, 99, 20); + libinput_dispatch(li); + litest_timeout_edgescroll(); + libinput_dispatch(li); + litest_assert_empty_queue(li); + + litest_touch_move_to(touchpad, 0, 99, 20, 99, 80, 60, 10); + libinput_dispatch(li); + litest_assert_empty_queue(li); + + litest_touch_move_to(touchpad, 0, 99, 80, 99, 20, 60, 10); + litest_touch_up(touchpad, 0); + libinput_dispatch(li); + litest_assert_empty_queue(li); + + litest_delete_device(touchpad); +} +END_TEST + +START_TEST(lid_disable_touchpad_edge_scroll_interrupt) +{ + struct litest_device *sw = litest_current_device(); + struct litest_device *touchpad; + struct libinput *li = sw->libinput; + struct libinput_event *event; + + touchpad = lid_init_paired_touchpad(li); + litest_enable_edge_scroll(touchpad); + + litest_drain_events(li); + + litest_touch_down(touchpad, 0, 99, 20); + libinput_dispatch(li); + litest_timeout_edgescroll(); + litest_touch_move_to(touchpad, 0, 99, 20, 99, 30, 10, 10); + libinput_dispatch(li); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + libinput_dispatch(li); + + event = libinput_get_event(li); + litest_is_axis_event(event, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + LIBINPUT_POINTER_AXIS_SOURCE_FINGER); + libinput_event_destroy(event); + + event = libinput_get_event(li); + litest_is_switch_event(event, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_ON); + libinput_event_destroy(event); + + litest_delete_device(touchpad); +} +END_TEST + +START_TEST(lid_disable_touchpad_already_open) +{ + struct litest_device *sw = litest_current_device(); + struct litest_device *touchpad; + struct libinput *li = sw->libinput; + + touchpad = lid_init_paired_touchpad(li); + litest_disable_tap(touchpad->libinput_device); + litest_drain_events(li); + + /* default: lid is up - motion events */ + litest_touch_down(touchpad, 0, 50, 50); + litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1); + litest_touch_up(touchpad, 0); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); + + /* open lid - motion events */ + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_OFF); + litest_assert_empty_queue(li); + + litest_touch_down(touchpad, 0, 50, 50); + litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1); + litest_touch_up(touchpad, 0); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); + + litest_delete_device(touchpad); +} +END_TEST + +void +litest_setup_tests_lid(void) +{ + litest_add("lid:switch", lid_switch, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:switch", lid_switch_double, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:disable_touchpad", lid_disable_touchpad, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:disable_touchpad", lid_disable_touchpad_during_touch, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:disable_touchpad", lid_disable_touchpad_edge_scroll, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:disable_touchpad", lid_disable_touchpad_edge_scroll_interrupt, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:disable_touchpad", lid_disable_touchpad_already_open, LITEST_SWITCH, LITEST_ANY); +} diff --git a/test/test-misc.c b/test/test-misc.c index ed5471db..9517042d 100644 --- a/test/test-misc.c +++ b/test/test-misc.c @@ -135,6 +135,7 @@ START_TEST(event_conversion_device_notify) ck_assert(libinput_event_get_gesture_event(event) == NULL); ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); + ck_assert(libinput_event_get_switch_event(event) == NULL); litest_restore_log_handler(li); } @@ -192,6 +193,7 @@ START_TEST(event_conversion_pointer) ck_assert(libinput_event_get_gesture_event(event) == NULL); ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); + ck_assert(libinput_event_get_switch_event(event) == NULL); litest_restore_log_handler(li); } libinput_event_destroy(event); @@ -243,6 +245,7 @@ START_TEST(event_conversion_pointer_abs) ck_assert(libinput_event_get_gesture_event(event) == NULL); ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); + ck_assert(libinput_event_get_switch_event(event) == NULL); litest_restore_log_handler(li); } libinput_event_destroy(event); @@ -287,6 +290,7 @@ START_TEST(event_conversion_key) ck_assert(libinput_event_get_gesture_event(event) == NULL); ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); + ck_assert(libinput_event_get_switch_event(event) == NULL); litest_restore_log_handler(li); } libinput_event_destroy(event); @@ -338,6 +342,7 @@ START_TEST(event_conversion_touch) ck_assert(libinput_event_get_gesture_event(event) == NULL); ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); + ck_assert(libinput_event_get_switch_event(event) == NULL); litest_restore_log_handler(li); } libinput_event_destroy(event); @@ -387,6 +392,7 @@ START_TEST(event_conversion_gesture) ck_assert(libinput_event_get_keyboard_event(event) == NULL); ck_assert(libinput_event_get_touch_event(event) == NULL); ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); + ck_assert(libinput_event_get_switch_event(event) == NULL); litest_restore_log_handler(li); } libinput_event_destroy(event); @@ -434,6 +440,7 @@ START_TEST(event_conversion_tablet) ck_assert(libinput_event_get_keyboard_event(event) == NULL); ck_assert(libinput_event_get_touch_event(event) == NULL); ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); + ck_assert(libinput_event_get_switch_event(event) == NULL); litest_restore_log_handler(li); } libinput_event_destroy(event); @@ -477,6 +484,7 @@ START_TEST(event_conversion_tablet_pad) ck_assert(libinput_event_get_keyboard_event(event) == NULL); ck_assert(libinput_event_get_touch_event(event) == NULL); ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); + ck_assert(libinput_event_get_switch_event(event) == NULL); litest_restore_log_handler(li); } libinput_event_destroy(event); @@ -486,6 +494,47 @@ START_TEST(event_conversion_tablet_pad) } END_TEST +START_TEST(event_conversion_switch) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + int sw = 0; + + litest_lid_action(dev, LIBINPUT_SWITCH_STATE_ON); + litest_lid_action(dev, LIBINPUT_SWITCH_STATE_OFF); + libinput_dispatch(li); + + while ((event = libinput_get_event(li))) { + enum libinput_event_type type; + type = libinput_event_get_type(event); + + if (type == LIBINPUT_EVENT_SWITCH_TOGGLE) { + struct libinput_event_switch *s; + struct libinput_event *base; + s = libinput_event_get_switch_event(event); + base = libinput_event_switch_get_base_event(s); + ck_assert(event == base); + + sw++; + + litest_disable_log_handler(li); + ck_assert(libinput_event_get_device_notify_event(event) == NULL); + ck_assert(libinput_event_get_keyboard_event(event) == NULL); + ck_assert(libinput_event_get_pointer_event(event) == NULL); + ck_assert(libinput_event_get_touch_event(event) == NULL); + ck_assert(libinput_event_get_gesture_event(event) == NULL); + ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); + ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); + litest_restore_log_handler(li); + } + libinput_event_destroy(event); + } + + ck_assert_int_gt(sw, 0); +} +END_TEST + START_TEST(bitfield_helpers) { /* This value has a bit set on all of the word boundaries we want to @@ -1118,6 +1167,7 @@ litest_setup_tests_misc(void) litest_add_for_device("events:conversion", event_conversion_gesture, LITEST_BCM5974); litest_add_for_device("events:conversion", event_conversion_tablet, LITEST_WACOM_CINTIQ); litest_add_for_device("events:conversion", event_conversion_tablet_pad, LITEST_WACOM_INTUOS5_PAD); + litest_add_for_device("events:conversion", event_conversion_switch, LITEST_LID_SWITCH); litest_add_no_device("misc:bitfield_helpers", bitfield_helpers); litest_add_no_device("context:refcount", context_ref_counting); From 9b4f587390f09267cf3b3c6962580e71cca32843 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 24 Jan 2017 12:14:01 +1000 Subject: [PATCH 05/18] evdev: move the lid switch process functions together Don't sprinkle them across the file Signed-off-by: Peter Hutterer --- src/evdev.c | 96 ++++++++++++++++++++++++++--------------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 245d8787..216dcc27 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1030,24 +1030,6 @@ fallback_process_absolute(struct fallback_dispatch *dispatch, } } -static void -lid_switch_process_switch(struct lid_switch_dispatch *dispatch, - struct evdev_device *device, - struct input_event *e, - uint64_t time) -{ - switch (e->code) { - case SW_LID: - dispatch->lid_is_closed = !!e->value; - - switch_notify_toggle(&device->base, - time, - LIBINPUT_SWITCH_LID, - dispatch->lid_is_closed); - break; - } -} - static inline bool fallback_any_button_down(struct fallback_dispatch *dispatch, struct evdev_device *device) @@ -1150,27 +1132,6 @@ fallback_process(struct evdev_dispatch *evdev_dispatch, } } -static void -lid_switch_process(struct evdev_dispatch *evdev_dispatch, - struct evdev_device *device, - struct input_event *event, - uint64_t time) -{ - struct lid_switch_dispatch *dispatch = - (struct lid_switch_dispatch*)evdev_dispatch; - - switch (event->type) { - case EV_SW: - lid_switch_process_switch(dispatch, device, event, time); - break; - case EV_SYN: - break; - default: - assert(0 && "Unknown event type"); - break; - } -} - static void release_touches(struct fallback_dispatch *dispatch, struct evdev_device *device, @@ -1296,15 +1257,6 @@ fallback_destroy(struct evdev_dispatch *evdev_dispatch) free(dispatch); } -static void -lid_switch_destroy(struct evdev_dispatch *evdev_dispatch) -{ - struct lid_switch_dispatch *dispatch = - (struct lid_switch_dispatch*)evdev_dispatch; - - free(dispatch); -} - static int evdev_calibration_has_matrix(struct libinput_device *libinput_device) { @@ -1359,6 +1311,54 @@ struct evdev_dispatch_interface fallback_interface = { fallback_toggle_touch, /* toggle_touch */ }; +static void +lid_switch_process_switch(struct lid_switch_dispatch *dispatch, + struct evdev_device *device, + struct input_event *e, + uint64_t time) +{ + switch (e->code) { + case SW_LID: + dispatch->lid_is_closed = !!e->value; + + switch_notify_toggle(&device->base, + time, + LIBINPUT_SWITCH_LID, + dispatch->lid_is_closed); + break; + } +} + +static void +lid_switch_process(struct evdev_dispatch *evdev_dispatch, + struct evdev_device *device, + struct input_event *event, + uint64_t time) +{ + struct lid_switch_dispatch *dispatch = + (struct lid_switch_dispatch*)evdev_dispatch; + + switch (event->type) { + case EV_SW: + lid_switch_process_switch(dispatch, device, event, time); + break; + case EV_SYN: + break; + default: + assert(0 && "Unknown event type"); + break; + } +} + +static void +lid_switch_destroy(struct evdev_dispatch *evdev_dispatch) +{ + struct lid_switch_dispatch *dispatch = + (struct lid_switch_dispatch*)evdev_dispatch; + + free(dispatch); +} + struct evdev_dispatch_interface lid_switch_interface = { lid_switch_process, NULL, /* suspend */ From 87f3ea760c7375b464ec10a295f9e3a3ae56386c Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 24 Jan 2017 12:16:08 +1000 Subject: [PATCH 06/18] touchpad: check for a switch type before handling the event Don't call get_switch_event immediately, doing so for non-switch events is documented as a bug. Check the event type instead, if that one is correct then we can assume the rest works. Signed-off-by: Peter Hutterer --- src/evdev-mt-touchpad.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 6e2818cc..5b166459 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1562,19 +1562,19 @@ tp_lid_switch_event(uint64_t time, struct libinput_event *event, void *data) struct tp_dispatch *tp = data; struct libinput_event_switch *swev; - swev = libinput_event_get_switch_event(event); + if (libinput_event_get_type(event) != LIBINPUT_EVENT_SWITCH_TOGGLE) + return; - if (swev) { - switch (libinput_event_switch_get_switch_state(swev)) { - case LIBINPUT_SWITCH_STATE_OFF: - tp_resume(tp, tp->device); - log_debug(tp_libinput_context(tp), "lid: resume touchpad\n"); - break; - case LIBINPUT_SWITCH_STATE_ON: - tp_suspend(tp, tp->device); - log_debug(tp_libinput_context(tp), "lid: suspend touchpad\n"); - break; - } + swev = libinput_event_get_switch_event(event); + switch (libinput_event_switch_get_switch_state(swev)) { + case LIBINPUT_SWITCH_STATE_OFF: + tp_resume(tp, tp->device); + log_debug(tp_libinput_context(tp), "lid: resume touchpad\n"); + break; + case LIBINPUT_SWITCH_STATE_ON: + tp_suspend(tp, tp->device); + log_debug(tp_libinput_context(tp), "lid: suspend touchpad\n"); + break; } } From e2877acb89edcba93e3567e86082a1247e179008 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 24 Jan 2017 14:58:17 +1000 Subject: [PATCH 07/18] Clarify the default 'off' position of a switch So we don't need to send an "off" event for every switch on startup. Signed-off-by: Peter Hutterer --- src/libinput.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libinput.h b/src/libinput.h index f8b123a4..436923d4 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -601,7 +601,11 @@ libinput_tablet_pad_mode_group_get_user_data( /** * @ingroup device * - * The state of a switch. + * The state of a switch. The default state of a switch is @ref + * LIBINPUT_SWITCH_STATE_OFF and no event is sent to confirm a switch in the + * off position. If a switch is logically on during initialization, libinput + * sends an event of type @ref LIBINPUT_EVENT_SWITCH_TOGGLE with a state + * @ref LIBINPUT_SWITCH_STATE_ON. */ enum libinput_switch_state { LIBINPUT_SWITCH_STATE_OFF = 0, From 2a1ed92c51843e5be3de5bea76522628505481aa Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 24 Jan 2017 15:04:39 +1000 Subject: [PATCH 08/18] switch: sync the initial state of the switch on startup This is the default behavior, based on the theory of hardware actually doing the right thing. That's not always the case, follow-up patches will change when we do the theoretically ideal thing. Signed-off-by: Peter Hutterer --- src/evdev.c | 23 ++++++++++++++++++++++- test/test-lid.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 216dcc27..2e0402b1 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1359,6 +1359,27 @@ lid_switch_destroy(struct evdev_dispatch *evdev_dispatch) free(dispatch); } +static void +lid_switch_sync_initial_state(struct evdev_device *device, + struct evdev_dispatch *evdev_dispatch) +{ + struct lid_switch_dispatch *dispatch = + (struct lid_switch_dispatch*)evdev_dispatch; + struct libevdev *evdev = device->evdev; + + dispatch->lid_is_closed = libevdev_get_event_value(evdev, + EV_SW, + SW_LID); + if (dispatch->lid_is_closed) { + uint64_t time; + time = libinput_now(evdev_libinput_context(device)); + switch_notify_toggle(&device->base, + time, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_ON); + } +} + struct evdev_dispatch_interface lid_switch_interface = { lid_switch_process, NULL, /* suspend */ @@ -1368,7 +1389,7 @@ struct evdev_dispatch_interface lid_switch_interface = { NULL, /* device_removed */ NULL, /* device_suspended */ NULL, /* device_resumed */ - NULL, /* post_added */ + lid_switch_sync_initial_state, NULL, /* toggle_touch */ }; diff --git a/test/test-lid.c b/test/test-lid.c index e1a9088c..59c461dd 100644 --- a/test/test-lid.c +++ b/test/test-lid.c @@ -87,6 +87,47 @@ START_TEST(lid_switch_double) } END_TEST +START_TEST(lid_switch_down_on_init) +{ + struct litest_device *sw = litest_current_device(); + struct libinput *li; + struct libinput_event *event; + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + + /* need separate context to test */ + li = litest_create_context(); + libinput_path_add_device(li, + libevdev_uinput_get_devnode(sw->uinput)); + libinput_dispatch(li); + + litest_wait_for_event_of_type(li, LIBINPUT_EVENT_SWITCH_TOGGLE, -1); + event = libinput_get_event(li); + litest_is_switch_event(event, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_ON); + libinput_event_destroy(event); + + while ((event = libinput_get_event(li))) { + ck_assert_int_ne(libinput_event_get_type(event), + LIBINPUT_EVENT_SWITCH_TOGGLE); + libinput_event_destroy(event); + } + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_OFF); + libinput_dispatch(li); + event = libinput_get_event(li); + litest_is_switch_event(event, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_OFF); + libinput_event_destroy(event); + litest_assert_empty_queue(li); + + libinput_unref(li); + +} +END_TEST + static inline struct litest_device * lid_init_paired_touchpad(struct libinput *li) { @@ -257,6 +298,7 @@ litest_setup_tests_lid(void) { litest_add("lid:switch", lid_switch, LITEST_SWITCH, LITEST_ANY); litest_add("lid:switch", lid_switch_double, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:switch", lid_switch_down_on_init, LITEST_SWITCH, LITEST_ANY); litest_add("lid:disable_touchpad", lid_disable_touchpad, LITEST_SWITCH, LITEST_ANY); litest_add("lid:disable_touchpad", lid_disable_touchpad_during_touch, LITEST_SWITCH, LITEST_ANY); litest_add("lid:disable_touchpad", lid_disable_touchpad_edge_scroll, LITEST_SWITCH, LITEST_ANY); From 3f5e9cb6369326b71b2efb3d149c0794c827c199 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 25 Jan 2017 13:48:01 +1000 Subject: [PATCH 09/18] switch: prevent switches to send the same event twice Signed-off-by: Peter Hutterer --- src/evdev.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 2e0402b1..50c8abd7 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1317,10 +1317,16 @@ lid_switch_process_switch(struct lid_switch_dispatch *dispatch, struct input_event *e, uint64_t time) { + bool is_closed; + switch (e->code) { case SW_LID: - dispatch->lid_is_closed = !!e->value; + is_closed = !!e->value; + if (dispatch->lid_is_closed == is_closed) + return; + + dispatch->lid_is_closed = is_closed; switch_notify_toggle(&device->base, time, LIBINPUT_SWITCH_LID, From 5f2402a41abd035164583c967995a81dcd232edc Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 25 Jan 2017 13:24:31 +1000 Subject: [PATCH 10/18] switch: only sync the initial state if we know the state is reliable This changes the default behavior to "disable the touchpad on the first lid close event", thus filtering any laptops where the switch state is buggy and always in "on" state. Devices where we know the lid switch state is reliable can be marked as such. Signed-off-by: Peter Hutterer --- src/evdev.c | 40 ++++++++++++++++++++++++++++++--- src/libinput-util.c | 17 ++++++++++++++ src/libinput-util.h | 9 ++++++++ test/litest-device-lid-switch.c | 3 ++- test/test-misc.c | 40 +++++++++++++++++++++++++++++++++ 5 files changed, 105 insertions(+), 4 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 50c8abd7..f15b8acc 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1356,6 +1356,25 @@ lid_switch_process(struct evdev_dispatch *evdev_dispatch, } } +static inline enum switch_reliability +evdev_read_switch_reliability_prop(struct evdev_device *device) +{ + const char *prop; + enum switch_reliability r; + + prop = udev_device_get_property_value(device->udev_device, + "LIBINPUT_ATTR_LID_SWITCH_RELIABILITY"); + if (!parse_switch_reliability_property(prop, &r)) { + log_error(evdev_libinput_context(device), + "%s: switch reliability set to unknown value '%s'\n", + device->devname, + prop); + r = RELIABILITY_UNKNOWN; + } + + return r; +} + static void lid_switch_destroy(struct evdev_dispatch *evdev_dispatch) { @@ -1372,10 +1391,25 @@ lid_switch_sync_initial_state(struct evdev_device *device, struct lid_switch_dispatch *dispatch = (struct lid_switch_dispatch*)evdev_dispatch; struct libevdev *evdev = device->evdev; + bool is_closed = false; - dispatch->lid_is_closed = libevdev_get_event_value(evdev, - EV_SW, - SW_LID); + /* For the initial state sync, we depend on whether the lid switch + * is reliable. If we know it's reliable, we sync as expected. + * If we're not sure, we ignore the initial state and only sync on + * the first future lid close event. Laptops with a broken switch + * that always have the switch in 'on' state thus don't mess up our + * touchpad. + */ + switch(evdev_read_switch_reliability_prop(device)) { + case RELIABILITY_UNKNOWN: + is_closed = false; + break; + case RELIABILITY_RELIABLE: + is_closed = libevdev_get_event_value(evdev, EV_SW, SW_LID); + break; + } + + dispatch->lid_is_closed = is_closed; if (dispatch->lid_is_closed) { uint64_t time; time = libinput_now(evdev_libinput_context(device)); diff --git a/src/libinput-util.c b/src/libinput-util.c index 40e1e6e5..f5d0aa7f 100644 --- a/src/libinput-util.c +++ b/src/libinput-util.c @@ -278,6 +278,23 @@ parse_dimension_property(const char *prop, size_t *w, size_t *h) return true; } +bool +parse_switch_reliability_property(const char *prop, + enum switch_reliability *reliability) +{ + if (!prop) { + *reliability = RELIABILITY_UNKNOWN; + return true; + } + + if (streq(prop, "reliable")) + *reliability = RELIABILITY_RELIABLE; + else + return false; + + return true; +} + /** * Return the next word in a string pointed to by state before the first * separator character. Call repeatedly to tokenize a whole string. diff --git a/src/libinput-util.h b/src/libinput-util.h index ba09ab6e..ce3a5acc 100644 --- a/src/libinput-util.h +++ b/src/libinput-util.h @@ -377,6 +377,15 @@ int parse_mouse_wheel_click_count_property(const char *prop); double parse_trackpoint_accel_property(const char *prop); bool parse_dimension_property(const char *prop, size_t *width, size_t *height); +enum switch_reliability { + RELIABILITY_UNKNOWN, + RELIABILITY_RELIABLE, +}; + +bool +parse_switch_reliability_property(const char *prop, + enum switch_reliability *reliability); + static inline uint64_t us(uint64_t us) { diff --git a/test/litest-device-lid-switch.c b/test/litest-device-lid-switch.c index 823a5c9d..b96592dc 100644 --- a/test/litest-device-lid-switch.c +++ b/test/litest-device-lid-switch.c @@ -49,7 +49,8 @@ static const char udev_rule[] = "KERNEL!=\"event*\", GOTO=\"switch_end\"\n" "\n" "ATTRS{name}==\"litest Lid Switch*\",\\\n" -" ENV{ID_INPUT_SWITCH}=\"1\"\n" +" ENV{ID_INPUT_SWITCH}=\"1\",\\\n" +" ENV{LIBINPUT_ATTR_LID_SWITCH_RELIABILITY}=\"reliable\"\n" "\n" "LABEL=\"switch_end\""; diff --git a/test/test-misc.c b/test/test-misc.c index 9517042d..36cabdcf 100644 --- a/test/test-misc.c +++ b/test/test-misc.c @@ -908,6 +908,45 @@ START_TEST(dimension_prop_parser) } END_TEST +struct parser_test_reliability { + char *tag; + bool success; + enum switch_reliability reliability; +}; + +START_TEST(reliability_prop_parser) +{ + struct parser_test_reliability tests[] = { + { "reliable", true, RELIABILITY_RELIABLE }, + { "unreliable", false, 0 }, + { "", false, 0 }, + { "0", false, 0 }, + { "1", false, 0 }, + { NULL, false, 0, } + }; + enum switch_reliability r; + bool success; + int i; + + for (i = 0; tests[i].tag != NULL; i++) { + r = 0xaf; + success = parse_switch_reliability_property(tests[i].tag, &r); + ck_assert(success == tests[i].success); + if (success) + ck_assert_int_eq(r, tests[i].reliability); + else + ck_assert_int_eq(r, 0xaf); + } + + success = parse_switch_reliability_property(NULL, &r); + ck_assert(success == true); + ck_assert_int_eq(r, RELIABILITY_UNKNOWN); + + success = parse_switch_reliability_property("foo", NULL); + ck_assert(success == false); +} +END_TEST + START_TEST(time_conversion) { ck_assert_int_eq(us(10), 10); @@ -1180,6 +1219,7 @@ litest_setup_tests_misc(void) litest_add_no_device("misc:parser", wheel_click_count_parser); litest_add_no_device("misc:parser", trackpoint_accel_parser); litest_add_no_device("misc:parser", dimension_prop_parser); + litest_add_no_device("misc:parser", reliability_prop_parser); litest_add_no_device("misc:parser", safe_atoi_test); litest_add_no_device("misc:parser", safe_atod_test); litest_add_no_device("misc:parser", strsplit_test); From e6806ce292506b61e2c903ec2e259d0122a75d5b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 25 Jan 2017 14:31:05 +1000 Subject: [PATCH 11/18] switch: move the lid switch bits into their own file Keep this separate from the other code so it's easier to read Signed-off-by: Peter Hutterer --- src/Makefile.am | 1 + src/evdev-lid.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++ src/evdev.c | 144 +-------------------------------------- src/evdev.h | 13 ++-- 4 files changed, 184 insertions(+), 148 deletions(-) create mode 100644 src/evdev-lid.c diff --git a/src/Makefile.am b/src/Makefile.am index a7ce4720..08e6aa1e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,6 +11,7 @@ libinput_la_SOURCES = \ libinput-private.h \ evdev.c \ evdev.h \ + evdev-lid.c \ evdev-middle-button.c \ evdev-mt-touchpad.c \ evdev-mt-touchpad.h \ diff --git a/src/evdev-lid.c b/src/evdev-lid.c new file mode 100644 index 00000000..3cc287ca --- /dev/null +++ b/src/evdev-lid.c @@ -0,0 +1,174 @@ +/* + * Copyright © 2017 James Ye + * Copyright © 2017 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include "libinput.h" +#include "evdev.h" +#include "libinput-private.h" + +struct lid_switch_dispatch { + struct evdev_dispatch base; + + bool lid_is_closed; +}; + +static void +lid_switch_process_switch(struct lid_switch_dispatch *dispatch, + struct evdev_device *device, + struct input_event *e, + uint64_t time) +{ + bool is_closed; + + switch (e->code) { + case SW_LID: + is_closed = !!e->value; + + if (dispatch->lid_is_closed == is_closed) + return; + + dispatch->lid_is_closed = is_closed; + switch_notify_toggle(&device->base, + time, + LIBINPUT_SWITCH_LID, + dispatch->lid_is_closed); + break; + } +} + +static void +lid_switch_process(struct evdev_dispatch *evdev_dispatch, + struct evdev_device *device, + struct input_event *event, + uint64_t time) +{ + struct lid_switch_dispatch *dispatch = + (struct lid_switch_dispatch*)evdev_dispatch; + + switch (event->type) { + case EV_SW: + lid_switch_process_switch(dispatch, device, event, time); + break; + case EV_SYN: + break; + default: + assert(0 && "Unknown event type"); + break; + } +} + +static inline enum switch_reliability +evdev_read_switch_reliability_prop(struct evdev_device *device) +{ + const char *prop; + enum switch_reliability r; + + prop = udev_device_get_property_value(device->udev_device, + "LIBINPUT_ATTR_LID_SWITCH_RELIABILITY"); + if (!parse_switch_reliability_property(prop, &r)) { + log_error(evdev_libinput_context(device), + "%s: switch reliability set to unknown value '%s'\n", + device->devname, + prop); + r = RELIABILITY_UNKNOWN; + } + + return r; +} + +static void +lid_switch_destroy(struct evdev_dispatch *evdev_dispatch) +{ + struct lid_switch_dispatch *dispatch = + (struct lid_switch_dispatch*)evdev_dispatch; + + free(dispatch); +} + +static void +lid_switch_sync_initial_state(struct evdev_device *device, + struct evdev_dispatch *evdev_dispatch) +{ + struct lid_switch_dispatch *dispatch = + (struct lid_switch_dispatch*)evdev_dispatch; + struct libevdev *evdev = device->evdev; + bool is_closed = false; + + /* For the initial state sync, we depend on whether the lid switch + * is reliable. If we know it's reliable, we sync as expected. + * If we're not sure, we ignore the initial state and only sync on + * the first future lid close event. Laptops with a broken switch + * that always have the switch in 'on' state thus don't mess up our + * touchpad. + */ + switch(evdev_read_switch_reliability_prop(device)) { + case RELIABILITY_UNKNOWN: + is_closed = false; + break; + case RELIABILITY_RELIABLE: + is_closed = libevdev_get_event_value(evdev, EV_SW, SW_LID); + break; + } + + dispatch->lid_is_closed = is_closed; + if (dispatch->lid_is_closed) { + uint64_t time; + time = libinput_now(evdev_libinput_context(device)); + switch_notify_toggle(&device->base, + time, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_ON); + } +} + +struct evdev_dispatch_interface lid_switch_interface = { + lid_switch_process, + NULL, /* suspend */ + NULL, /* remove */ + lid_switch_destroy, + NULL, /* device_added */ + NULL, /* device_removed */ + NULL, /* device_suspended */ + NULL, /* device_resumed */ + lid_switch_sync_initial_state, + NULL, /* toggle_touch */ +}; + +struct evdev_dispatch * +evdev_lid_switch_dispatch_create(struct evdev_device *lid_device) +{ + struct lid_switch_dispatch *dispatch = zalloc(sizeof *dispatch); + + if (dispatch == NULL) + return NULL; + + dispatch->base.interface = &lid_switch_interface; + + evdev_init_sendevents(lid_device, &dispatch->base); + + dispatch->lid_is_closed = false; + + return &dispatch->base; +} diff --git a/src/evdev.c b/src/evdev.c index f15b8acc..6ac3427d 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1311,128 +1311,6 @@ struct evdev_dispatch_interface fallback_interface = { fallback_toggle_touch, /* toggle_touch */ }; -static void -lid_switch_process_switch(struct lid_switch_dispatch *dispatch, - struct evdev_device *device, - struct input_event *e, - uint64_t time) -{ - bool is_closed; - - switch (e->code) { - case SW_LID: - is_closed = !!e->value; - - if (dispatch->lid_is_closed == is_closed) - return; - - dispatch->lid_is_closed = is_closed; - switch_notify_toggle(&device->base, - time, - LIBINPUT_SWITCH_LID, - dispatch->lid_is_closed); - break; - } -} - -static void -lid_switch_process(struct evdev_dispatch *evdev_dispatch, - struct evdev_device *device, - struct input_event *event, - uint64_t time) -{ - struct lid_switch_dispatch *dispatch = - (struct lid_switch_dispatch*)evdev_dispatch; - - switch (event->type) { - case EV_SW: - lid_switch_process_switch(dispatch, device, event, time); - break; - case EV_SYN: - break; - default: - assert(0 && "Unknown event type"); - break; - } -} - -static inline enum switch_reliability -evdev_read_switch_reliability_prop(struct evdev_device *device) -{ - const char *prop; - enum switch_reliability r; - - prop = udev_device_get_property_value(device->udev_device, - "LIBINPUT_ATTR_LID_SWITCH_RELIABILITY"); - if (!parse_switch_reliability_property(prop, &r)) { - log_error(evdev_libinput_context(device), - "%s: switch reliability set to unknown value '%s'\n", - device->devname, - prop); - r = RELIABILITY_UNKNOWN; - } - - return r; -} - -static void -lid_switch_destroy(struct evdev_dispatch *evdev_dispatch) -{ - struct lid_switch_dispatch *dispatch = - (struct lid_switch_dispatch*)evdev_dispatch; - - free(dispatch); -} - -static void -lid_switch_sync_initial_state(struct evdev_device *device, - struct evdev_dispatch *evdev_dispatch) -{ - struct lid_switch_dispatch *dispatch = - (struct lid_switch_dispatch*)evdev_dispatch; - struct libevdev *evdev = device->evdev; - bool is_closed = false; - - /* For the initial state sync, we depend on whether the lid switch - * is reliable. If we know it's reliable, we sync as expected. - * If we're not sure, we ignore the initial state and only sync on - * the first future lid close event. Laptops with a broken switch - * that always have the switch in 'on' state thus don't mess up our - * touchpad. - */ - switch(evdev_read_switch_reliability_prop(device)) { - case RELIABILITY_UNKNOWN: - is_closed = false; - break; - case RELIABILITY_RELIABLE: - is_closed = libevdev_get_event_value(evdev, EV_SW, SW_LID); - break; - } - - dispatch->lid_is_closed = is_closed; - if (dispatch->lid_is_closed) { - uint64_t time; - time = libinput_now(evdev_libinput_context(device)); - switch_notify_toggle(&device->base, - time, - LIBINPUT_SWITCH_LID, - LIBINPUT_SWITCH_STATE_ON); - } -} - -struct evdev_dispatch_interface lid_switch_interface = { - lid_switch_process, - NULL, /* suspend */ - NULL, /* remove */ - lid_switch_destroy, - NULL, /* device_added */ - NULL, /* device_removed */ - NULL, /* device_suspended */ - NULL, /* device_resumed */ - lid_switch_sync_initial_state, - NULL, /* toggle_touch */ -}; - static uint32_t evdev_sendevents_get_modes(struct libinput_device *device) { @@ -1673,7 +1551,7 @@ evdev_init_calibration(struct evdev_device *device, calibration->get_default_matrix = evdev_calibration_get_default_matrix; } -static void +void evdev_init_sendevents(struct evdev_device *device, struct evdev_dispatch *dispatch) { @@ -1942,24 +1820,6 @@ fallback_dispatch_create(struct libinput_device *device) return &dispatch->base; } -static struct evdev_dispatch * -lid_switch_dispatch_create(struct libinput_device *device) -{ - struct lid_switch_dispatch *dispatch = zalloc(sizeof *dispatch); - struct evdev_device *lid_device = (struct evdev_device *)device; - - if (dispatch == NULL) - return NULL; - - dispatch->base.interface = &lid_switch_interface; - - evdev_init_sendevents(lid_device, &dispatch->base); - - dispatch->lid_is_closed = false; - - return &dispatch->base; -} - static inline void evdev_process_event(struct evdev_device *device, struct input_event *e) { @@ -2809,7 +2669,7 @@ evdev_configure_device(struct evdev_device *device) if (udev_tags & EVDEV_UDEV_TAG_SWITCH && libevdev_has_event_code(evdev, EV_SW, SW_LID)) { - dispatch = lid_switch_dispatch_create(&device->base); + dispatch = evdev_lid_switch_dispatch_create(device); device->seat_caps |= EVDEV_DEVICE_SWITCH; evdev_tag_lid_switch(device, device->udev_device); log_info(libinput, diff --git a/src/evdev.h b/src/evdev.h index 32d854f1..1d802bad 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -336,12 +336,6 @@ struct fallback_dispatch { bool ignore_events; }; -struct lid_switch_dispatch { - struct evdev_dispatch base; - - bool lid_is_closed; -}; - struct evdev_device * evdev_device_create(struct libinput_seat *seat, struct udev_device *device); @@ -361,6 +355,10 @@ evdev_init_calibration(struct evdev_device *device, void evdev_read_calibration_prop(struct evdev_device *device); +void +evdev_init_sendevents(struct evdev_device *device, + struct evdev_dispatch *dispatch); + void evdev_device_init_pointer_acceleration(struct evdev_device *device, struct motion_filter *filter); @@ -377,6 +375,9 @@ evdev_tablet_create(struct evdev_device *device); struct evdev_dispatch * evdev_tablet_pad_create(struct evdev_device *device); +struct evdev_dispatch * +evdev_lid_switch_dispatch_create(struct evdev_device *device); + void evdev_device_led_update(struct evdev_device *device, enum libinput_led leds); From d17e84fc0fab591869d8b6f0ce8b9933cbe1c5b8 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 25 Jan 2017 15:19:50 +1000 Subject: [PATCH 12/18] Add a helper function for initializing an event listener Not needed right now as everything assumes the listener was added before it was removed. This helper is for the cases where we may call listener_remove before it was ever added. Signed-off-by: Peter Hutterer --- src/libinput-private.h | 3 +++ src/libinput.c | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/src/libinput-private.h b/src/libinput-private.h index 07bed365..205dbf89 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -466,6 +466,9 @@ void libinput_device_set_device_group(struct libinput_device *device, struct libinput_device_group *group); +void +libinput_device_init_event_listener(struct libinput_event_listener *listener); + void libinput_device_add_event_listener(struct libinput_device *device, struct libinput_event_listener *listener, diff --git a/src/libinput.c b/src/libinput.c index 49971530..ebfedece 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -1944,6 +1944,12 @@ libinput_dispatch(struct libinput *libinput) return 0; } +void +libinput_device_init_event_listener(struct libinput_event_listener *listener) +{ + list_init(&listener->link); +} + void libinput_device_add_event_listener(struct libinput_device *device, struct libinput_event_listener *listener, From 4eb29a8cc5eb36962a6cb14be032a4ca09296ffb Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 25 Jan 2017 15:21:52 +1000 Subject: [PATCH 13/18] switch: hook up to keyboard events to fix the lid switch state Extra insurance against broken lid switches. Listen to events from the (internal) keyboard when we are logically closed. If any, assume we're open after all and update accordingly. Signed-off-by: Peter Hutterer --- src/evdev-lid.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++-- test/test-lid.c | 68 ++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 4 deletions(-) diff --git a/src/evdev-lid.c b/src/evdev-lid.c index 3cc287ca..9029838e 100644 --- a/src/evdev-lid.c +++ b/src/evdev-lid.c @@ -30,10 +30,56 @@ struct lid_switch_dispatch { struct evdev_dispatch base; + struct evdev_device *device; bool lid_is_closed; + + struct { + struct evdev_device *keyboard; + struct libinput_event_listener listener; + } keyboard; }; +static void +lid_switch_keyboard_event(uint64_t time, + struct libinput_event *event, + void *data) +{ + struct lid_switch_dispatch *dispatch = + (struct lid_switch_dispatch*)data; + + if (!dispatch->lid_is_closed) + return; + + if (event->type != LIBINPUT_EVENT_KEYBOARD_KEY) + return; + + dispatch->lid_is_closed = false; + switch_notify_toggle(&dispatch->device->base, + time, + LIBINPUT_SWITCH_LID, + dispatch->lid_is_closed); +} + +static void +lid_switch_toggle_keyboard_listener(struct lid_switch_dispatch *dispatch, + bool is_closed) +{ + if (!dispatch->keyboard.keyboard) + return; + + if (is_closed) { + libinput_device_add_event_listener( + &dispatch->keyboard.keyboard->base, + &dispatch->keyboard.listener, + lid_switch_keyboard_event, + dispatch); + } else { + libinput_device_remove_event_listener( + &dispatch->keyboard.listener); + } +} + static void lid_switch_process_switch(struct lid_switch_dispatch *dispatch, struct evdev_device *device, @@ -49,7 +95,11 @@ lid_switch_process_switch(struct lid_switch_dispatch *dispatch, if (dispatch->lid_is_closed == is_closed) return; + lid_switch_toggle_keyboard_listener(dispatch, + is_closed); + dispatch->lid_is_closed = is_closed; + switch_notify_toggle(&device->base, time, LIBINPUT_SWITCH_LID, @@ -107,6 +157,56 @@ lid_switch_destroy(struct evdev_dispatch *evdev_dispatch) free(dispatch); } +static void +lid_switch_pair_keyboard(struct evdev_device *lid_switch, + struct evdev_device *keyboard) +{ + struct lid_switch_dispatch *dispatch = + (struct lid_switch_dispatch*)lid_switch->dispatch; + unsigned int bus_kbd = libevdev_get_id_bustype(keyboard->evdev); + + if ((keyboard->tags & EVDEV_TAG_KEYBOARD) == 0) + return; + + /* If we already have a keyboard paired, override it if the new one + * is a serio device. Otherwise keep the current one */ + if (dispatch->keyboard.keyboard) { + if (bus_kbd != BUS_I8042) + return; + libinput_device_remove_event_listener(&dispatch->keyboard.listener); + } + + dispatch->keyboard.keyboard = keyboard; + log_debug(evdev_libinput_context(lid_switch), + "lid: keyboard paired with %s<->%s\n", + lid_switch->devname, + keyboard->devname); + + /* We don't init the event listener yet - we don't care about + * keyboard events until the lid is closed */ +} + +static void +lid_switch_interface_device_added(struct evdev_device *device, + struct evdev_device *added_device) +{ + lid_switch_pair_keyboard(device, added_device); +} + +static void +lid_switch_interface_device_removed(struct evdev_device *device, + struct evdev_device *removed_device) +{ + struct lid_switch_dispatch *dispatch = + (struct lid_switch_dispatch*)device->dispatch; + + if (removed_device == dispatch->keyboard.keyboard) { + libinput_device_remove_event_listener( + &dispatch->keyboard.listener); + dispatch->keyboard.keyboard = NULL; + } +} + static void lid_switch_sync_initial_state(struct evdev_device *device, struct evdev_dispatch *evdev_dispatch) @@ -148,10 +248,10 @@ struct evdev_dispatch_interface lid_switch_interface = { NULL, /* suspend */ NULL, /* remove */ lid_switch_destroy, - NULL, /* device_added */ - NULL, /* device_removed */ - NULL, /* device_suspended */ - NULL, /* device_resumed */ + lid_switch_interface_device_added, + lid_switch_interface_device_removed, + lid_switch_interface_device_removed, /* device_suspended, treat as remove */ + lid_switch_interface_device_added, /* device_resumed, treat as add */ lid_switch_sync_initial_state, NULL, /* toggle_touch */ }; @@ -165,6 +265,8 @@ evdev_lid_switch_dispatch_create(struct evdev_device *lid_device) return NULL; dispatch->base.interface = &lid_switch_interface; + dispatch->device = lid_device; + libinput_device_init_event_listener(&dispatch->keyboard.listener); evdev_init_sendevents(lid_device, &dispatch->base); diff --git a/test/test-lid.c b/test/test-lid.c index 59c461dd..6577d23f 100644 --- a/test/test-lid.c +++ b/test/test-lid.c @@ -293,6 +293,71 @@ START_TEST(lid_disable_touchpad_already_open) } END_TEST +START_TEST(lid_open_on_key) +{ + struct litest_device *sw = litest_current_device(); + struct litest_device *keyboard; + struct libinput *li = sw->libinput; + struct libinput_event *event; + + keyboard = litest_add_device(li, LITEST_KEYBOARD); + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + litest_drain_events(li); + + litest_event(keyboard, EV_KEY, KEY_A, 1); + litest_event(keyboard, EV_SYN, SYN_REPORT, 0); + litest_event(keyboard, EV_KEY, KEY_A, 0); + litest_event(keyboard, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + + litest_wait_for_event_of_type(li, LIBINPUT_EVENT_SWITCH_TOGGLE, -1); + event = libinput_get_event(li); + litest_is_switch_event(event, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_OFF); + + litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY); + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_OFF); + litest_assert_empty_queue(li); + + libinput_event_destroy(event); + litest_delete_device(keyboard); +} +END_TEST + +START_TEST(lid_open_on_key_touchpad_enabled) +{ + struct litest_device *sw = litest_current_device(); + struct litest_device *keyboard, *touchpad; + struct libinput *li = sw->libinput; + + keyboard = litest_add_device(li, LITEST_KEYBOARD); + touchpad = litest_add_device(li, LITEST_SYNAPTICS_I2C); + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + litest_drain_events(li); + + litest_event(keyboard, EV_KEY, KEY_A, 1); + litest_event(keyboard, EV_SYN, SYN_REPORT, 0); + litest_event(keyboard, EV_KEY, KEY_A, 0); + litest_event(keyboard, EV_SYN, SYN_REPORT, 0); + litest_drain_events(li); + litest_timeout_dwt_long(); + + litest_touch_down(touchpad, 0, 50, 50); + litest_touch_move_to(touchpad, 0, 50, 50, 70, 70, 10, 1); + litest_touch_up(touchpad, 0); + libinput_dispatch(li); + + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); + + litest_delete_device(keyboard); + litest_delete_device(touchpad); +} +END_TEST + void litest_setup_tests_lid(void) { @@ -304,4 +369,7 @@ litest_setup_tests_lid(void) litest_add("lid:disable_touchpad", lid_disable_touchpad_edge_scroll, LITEST_SWITCH, LITEST_ANY); litest_add("lid:disable_touchpad", lid_disable_touchpad_edge_scroll_interrupt, LITEST_SWITCH, LITEST_ANY); litest_add("lid:disable_touchpad", lid_disable_touchpad_already_open, LITEST_SWITCH, LITEST_ANY); + + litest_add("lid:keyboard", lid_open_on_key, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:keyboard", lid_open_on_key_touchpad_enabled, LITEST_SWITCH, LITEST_ANY); } From 2a8d64c02d5326900703d6ea65a9e0edd74d5678 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 25 Jan 2017 17:41:54 +1000 Subject: [PATCH 14/18] udev: mark all laptops as lid switch reliable If the chassis type is 9 or 10 (Laptop, Notebook) let's assume that our lid switch works. On anything else we leave it at unknown. Signed-off-by: Peter Hutterer --- udev/90-libinput-model-quirks.hwdb | 9 +++++++++ udev/parse_hwdb.py | 8 +++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb index 04bdf9a3..a5102d2f 100644 --- a/udev/90-libinput-model-quirks.hwdb +++ b/udev/90-libinput-model-quirks.hwdb @@ -187,3 +187,12 @@ libinput:touchpad:input:b0003v056Ap* ########################################## libinput:name:*Trackball*:dmi:* LIBINPUT_MODEL_TRACKBALL=1 + +########################################## +# Chassis types 9 (Laptop) and 10 +# (Notebook) are expected to have working +# lid switches +########################################## +libinput:name:*Lid Switch*:dmi:*:ct10:* +libinput:name:*Lid Switch*:dmi:*:ct9:* + LIBINPUT_ATTR_LID_SWITCH_RELIABILITY=reliable diff --git a/udev/parse_hwdb.py b/udev/parse_hwdb.py index d90c90fc..102ef6c8 100755 --- a/udev/parse_hwdb.py +++ b/udev/parse_hwdb.py @@ -98,10 +98,16 @@ def property_grammar(): ('LIBINPUT_ATTR_SIZE_HINT', Group(dimension('SETTINGS*'))), ('LIBINPUT_ATTR_RESOLUTION_HINT', Group(dimension('SETTINGS*'))), ) + size_props = [Literal(name)('NAME') - Suppress('=') - val('VALUE') for name, val in sz_props] - grammar = Or(model_props + size_props); + reliability_tags = (Literal("reliable")) + reliability = [Literal('LIBINPUT_ATTR_LID_SWITCH_RELIABILITY')('NAME') - + Suppress('=') - + Group(OneOrMore(reliability_tags))('VALUE')] + + grammar = Or(model_props + size_props + reliability) return grammar From 078564ce7a590454c6bb9663d3a3017c56b0b7e2 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 30 Jan 2017 13:27:40 +1000 Subject: [PATCH 15/18] test: fix two test udev rules Signed-off-by: Peter Hutterer --- test/litest-device-mouse-wheel-click-angle.c | 2 +- test/litest-device-waltop-tablet.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/litest-device-mouse-wheel-click-angle.c b/test/litest-device-mouse-wheel-click-angle.c index 21c4387f..74bfcb5f 100644 --- a/test/litest-device-mouse-wheel-click-angle.c +++ b/test/litest-device-mouse-wheel-click-angle.c @@ -53,7 +53,7 @@ static const char udev_rule[] = "KERNEL!=\"event*\", GOTO=\"wheel_click_angle_end\"\n" "\n" "ATTRS{name}==\"litest Wheel Click Angle Mouse*\",\\\n" -" ENV{MOUSE_WHEEL_CLICK_ANGLE}=\"-7\",\n" +" ENV{MOUSE_WHEEL_CLICK_ANGLE}=\"-7\",\\\n" " ENV{MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL}=\"13\"\n" "\n" "LABEL=\"wheel_click_angle_end\""; diff --git a/test/litest-device-waltop-tablet.c b/test/litest-device-waltop-tablet.c index 769dc1d5..6879f2d0 100644 --- a/test/litest-device-waltop-tablet.c +++ b/test/litest-device-waltop-tablet.c @@ -232,7 +232,7 @@ static const char udev_rule[] = "ENV{ID_INPUT_TABLET}==\"\", GOTO=\"waltop_end\"\n" "\n" "ATTRS{name}==\"litest WALTOP Batteryless Tablet*\",\\\n" -" ENV{LIBINPUT_ATTR_SIZE_HINT}=\"200x200\",\n" +" ENV{LIBINPUT_ATTR_SIZE_HINT}=\"200x200\"\n" "\n" "LABEL=\"touchpad_end\""; From dc15a42d6cae4195d327253f6f05b65665eb3a93 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 30 Jan 2017 12:58:37 +1000 Subject: [PATCH 16/18] switch: for surface 3 tablets, write the lid open to the device These tablets only ever give us a close event, the open event is broken. So when we detect keyboard events, fix the kernel device's state by writing the event to the fd. We still sync the lid state manually, in case this fails and we don't get the SW_LID through the normal event sequence. If it works fine, the real open event will just be ignored. Signed-off-by: Peter Hutterer --- src/evdev-lid.c | 22 +++++- src/libinput-util.c | 2 + src/libinput-util.h | 1 + test/Makefile.am | 1 + test/litest-device-lid-switch-surface3.c | 71 +++++++++++++++++ test/litest.c | 2 + test/litest.h | 1 + test/test-lid.c | 98 ++++++++++++++++++++++++ udev/90-libinput-model-quirks.hwdb | 24 ++++-- udev/parse_hwdb.py | 4 +- 10 files changed, 215 insertions(+), 11 deletions(-) create mode 100644 test/litest-device-lid-switch-surface3.c diff --git a/src/evdev-lid.c b/src/evdev-lid.c index 9029838e..c5af7533 100644 --- a/src/evdev-lid.c +++ b/src/evdev-lid.c @@ -31,6 +31,7 @@ struct lid_switch_dispatch { struct evdev_dispatch base; struct evdev_device *device; + enum switch_reliability reliability; bool lid_is_closed; @@ -54,6 +55,18 @@ lid_switch_keyboard_event(uint64_t time, if (event->type != LIBINPUT_EVENT_KEYBOARD_KEY) return; + if (dispatch->reliability == RELIABILITY_WRITE_OPEN) { + int fd = libevdev_get_fd(dispatch->device->evdev); + struct input_event ev[2] = { + {{ 0, 0 }, EV_SW, SW_LID, 0 }, + {{ 0, 0 }, EV_SYN, SYN_REPORT, 0 }, + }; + + (void)write(fd, ev, sizeof(ev)); + /* In case write() fails, we sync the lid state manually + * regardless. */ + } + dispatch->lid_is_closed = false; switch_notify_toggle(&dispatch->device->base, time, @@ -143,6 +156,10 @@ evdev_read_switch_reliability_prop(struct evdev_device *device) device->devname, prop); r = RELIABILITY_UNKNOWN; + } else if (r == RELIABILITY_WRITE_OPEN) { + log_info(evdev_libinput_context(device), + "%s: will write switch open events\n", + device->devname); } return r; @@ -216,6 +233,8 @@ lid_switch_sync_initial_state(struct evdev_device *device, struct libevdev *evdev = device->evdev; bool is_closed = false; + dispatch->reliability = evdev_read_switch_reliability_prop(device); + /* For the initial state sync, we depend on whether the lid switch * is reliable. If we know it's reliable, we sync as expected. * If we're not sure, we ignore the initial state and only sync on @@ -223,8 +242,9 @@ lid_switch_sync_initial_state(struct evdev_device *device, * that always have the switch in 'on' state thus don't mess up our * touchpad. */ - switch(evdev_read_switch_reliability_prop(device)) { + switch(dispatch->reliability) { case RELIABILITY_UNKNOWN: + case RELIABILITY_WRITE_OPEN: is_closed = false; break; case RELIABILITY_RELIABLE: diff --git a/src/libinput-util.c b/src/libinput-util.c index f5d0aa7f..aa69a37b 100644 --- a/src/libinput-util.c +++ b/src/libinput-util.c @@ -289,6 +289,8 @@ parse_switch_reliability_property(const char *prop, if (streq(prop, "reliable")) *reliability = RELIABILITY_RELIABLE; + else if (streq(prop, "write_open")) + *reliability = RELIABILITY_WRITE_OPEN; else return false; diff --git a/src/libinput-util.h b/src/libinput-util.h index ce3a5acc..1d03ce13 100644 --- a/src/libinput-util.h +++ b/src/libinput-util.h @@ -380,6 +380,7 @@ bool parse_dimension_property(const char *prop, size_t *width, size_t *height); enum switch_reliability { RELIABILITY_UNKNOWN, RELIABILITY_RELIABLE, + RELIABILITY_WRITE_OPEN, }; bool diff --git a/test/Makefile.am b/test/Makefile.am index ce1973fe..2e565dea 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -33,6 +33,7 @@ liblitest_la_SOURCES = \ litest-device-keyboard-all-codes.c \ litest-device-keyboard-razer-blackwidow.c \ litest-device-lid-switch.c \ + litest-device-lid-switch-surface3.c \ litest-device-logitech-trackball.c \ litest-device-nexus4-touch-screen.c \ litest-device-magic-trackpad.c \ diff --git a/test/litest-device-lid-switch-surface3.c b/test/litest-device-lid-switch-surface3.c new file mode 100644 index 00000000..fde15c2f --- /dev/null +++ b/test/litest-device-lid-switch-surface3.c @@ -0,0 +1,71 @@ +/* + * Copyright © 2017 James Ye + * Copyright © 2017 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include "litest.h" +#include "litest-int.h" + +static void +litest_lid_switch_setup(void) +{ + struct litest_device *d = litest_create_device(LITEST_LID_SWITCH_SURFACE3); + litest_set_current_device(d); +} + +static struct input_id input_id = { + .bustype = 0x19, + .vendor = 0x0, + .product = 0x5, +}; + +static int events[] = { + EV_SW, SW_LID, + -1, -1, +}; + +static const char udev_rule[] = +"ACTION==\"remove\", GOTO=\"switch_end\"\n" +"KERNEL!=\"event*\", GOTO=\"switch_end\"\n" +"\n" +"ATTRS{name}==\"litest Lid Switch Surface3*\",\\\n" +" ENV{ID_INPUT_SWITCH}=\"1\",\\\n" +" ENV{LIBINPUT_ATTR_LID_SWITCH_RELIABILITY}=\"write_open\"\n" +"\n" +"LABEL=\"switch_end\""; + +struct litest_test_device litest_lid_switch_surface3_device = { + .type = LITEST_LID_SWITCH_SURFACE3, + .features = LITEST_SWITCH, + .shortname = "lid-switch-surface3", + .setup = litest_lid_switch_setup, + .interface = NULL, + + .name = "Lid Switch Surface3", + .id = &input_id, + .events = events, + .absinfo = NULL, + + .udev_rule = udev_rule, +}; diff --git a/test/litest.c b/test/litest.c index 7a5ec57e..1756940f 100644 --- a/test/litest.c +++ b/test/litest.c @@ -409,6 +409,7 @@ extern struct litest_test_device litest_acer_hawaii_touchpad_device; extern struct litest_test_device litest_synaptics_rmi4_device; extern struct litest_test_device litest_mouse_wheel_tilt_device; extern struct litest_test_device litest_lid_switch_device; +extern struct litest_test_device litest_lid_switch_surface3_device; struct litest_test_device* devices[] = { &litest_synaptics_clickpad_device, @@ -472,6 +473,7 @@ struct litest_test_device* devices[] = { &litest_synaptics_rmi4_device, &litest_mouse_wheel_tilt_device, &litest_lid_switch_device, + &litest_lid_switch_surface3_device, NULL, }; diff --git a/test/litest.h b/test/litest.h index 00756046..d779f0f7 100644 --- a/test/litest.h +++ b/test/litest.h @@ -230,6 +230,7 @@ enum litest_device_type { LITEST_SYNAPTICS_RMI4, LITEST_MOUSE_WHEEL_TILT, LITEST_LID_SWITCH, + LITEST_LID_SWITCH_SURFACE3, }; enum litest_device_feature { diff --git a/test/test-lid.c b/test/test-lid.c index 6577d23f..a5f439a0 100644 --- a/test/test-lid.c +++ b/test/test-lid.c @@ -87,12 +87,32 @@ START_TEST(lid_switch_double) } END_TEST +static bool +lid_switch_is_reliable(struct litest_device *dev) +{ + struct udev_device *udev_device; + const char *prop; + bool is_reliable = false; + + udev_device = libinput_device_get_udev_device(dev->libinput_device); + prop = udev_device_get_property_value(udev_device, + "LIBINPUT_ATTR_LID_SWITCH_RELIABILITY"); + + is_reliable = prop && streq(prop, "reliable"); + udev_device_unref(udev_device); + + return is_reliable; +} + START_TEST(lid_switch_down_on_init) { struct litest_device *sw = litest_current_device(); struct libinput *li; struct libinput_event *event; + if (!lid_switch_is_reliable(sw)) + return; + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); /* need separate context to test */ @@ -128,6 +148,35 @@ START_TEST(lid_switch_down_on_init) } END_TEST +START_TEST(lid_switch_not_down_on_init) +{ + struct litest_device *sw = litest_current_device(); + struct libinput *li; + struct libinput_event *event; + + if (lid_switch_is_reliable(sw)) + return; + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + + /* need separate context to test */ + li = litest_create_context(); + libinput_path_add_device(li, + libevdev_uinput_get_devnode(sw->uinput)); + libinput_dispatch(li); + + while ((event = libinput_get_event(li)) != NULL) { + ck_assert_int_ne(libinput_event_get_type(event), + LIBINPUT_EVENT_SWITCH_TOGGLE); + libinput_event_destroy(event); + } + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_OFF); + litest_assert_empty_queue(li); + libinput_unref(li); +} +END_TEST + static inline struct litest_device * lid_init_paired_touchpad(struct libinput *li) { @@ -358,12 +407,59 @@ START_TEST(lid_open_on_key_touchpad_enabled) } END_TEST +START_TEST(lid_update_hw_on_key) +{ + struct litest_device *sw = litest_current_device(); + struct libinput *li = sw->libinput; + struct libinput *li2; + struct litest_device *keyboard; + struct libinput_event *event; + + sleep(5); + keyboard = litest_add_device(li, LITEST_KEYBOARD); + + /* separate context to listen to the fake hw event */ + li2 = litest_create_context(); + libinput_path_add_device(li2, + libevdev_uinput_get_devnode(sw->uinput)); + litest_drain_events(li2); + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + litest_drain_events(li); + + libinput_dispatch(li2); + event = libinput_get_event(li2); + litest_is_switch_event(event, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_ON); + libinput_event_destroy(event); + + litest_event(keyboard, EV_KEY, KEY_A, 1); + litest_event(keyboard, EV_SYN, SYN_REPORT, 0); + litest_event(keyboard, EV_KEY, KEY_A, 0); + litest_event(keyboard, EV_SYN, SYN_REPORT, 0); + litest_drain_events(li); + + libinput_dispatch(li2); + event = libinput_get_event(li2); + litest_is_switch_event(event, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_OFF); + libinput_event_destroy(event); + litest_assert_empty_queue(li); + + libinput_unref(li2); + litest_delete_device(keyboard); +} +END_TEST + void litest_setup_tests_lid(void) { litest_add("lid:switch", lid_switch, LITEST_SWITCH, LITEST_ANY); litest_add("lid:switch", lid_switch_double, LITEST_SWITCH, LITEST_ANY); litest_add("lid:switch", lid_switch_down_on_init, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:switch", lid_switch_not_down_on_init, LITEST_SWITCH, LITEST_ANY); litest_add("lid:disable_touchpad", lid_disable_touchpad, LITEST_SWITCH, LITEST_ANY); litest_add("lid:disable_touchpad", lid_disable_touchpad_during_touch, LITEST_SWITCH, LITEST_ANY); litest_add("lid:disable_touchpad", lid_disable_touchpad_edge_scroll, LITEST_SWITCH, LITEST_ANY); @@ -372,4 +468,6 @@ litest_setup_tests_lid(void) litest_add("lid:keyboard", lid_open_on_key, LITEST_SWITCH, LITEST_ANY); litest_add("lid:keyboard", lid_open_on_key_touchpad_enabled, LITEST_SWITCH, LITEST_ANY); + + litest_add_for_device("lid:buggy", lid_update_hw_on_key, LITEST_LID_SWITCH_SURFACE3); } diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb index a5102d2f..86eea0dd 100644 --- a/udev/90-libinput-model-quirks.hwdb +++ b/udev/90-libinput-model-quirks.hwdb @@ -16,6 +16,15 @@ # # Sort by brand, model +########################################## +# Chassis types 9 (Laptop) and 10 +# (Notebook) are expected to have working +# lid switches +########################################## +libinput:name:*Lid Switch*:dmi:*:ct10:* +libinput:name:*Lid Switch*:dmi:*:ct9:* + LIBINPUT_ATTR_LID_SWITCH_RELIABILITY=reliable + ########################################## # ALPS ########################################## @@ -150,6 +159,13 @@ libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPadX1Carbon3rd libinput:name:*Logitech M570*:dmi:* LIBINPUT_MODEL_TRACKBALL=1 +########################################## +# Microsoft +########################################## +# Surface3 needs us to write the open lid switch event +libinput:name:*Lid Switch*:dmi:*svnMicrosoftCorporation:pnSurface3:* + LIBINPUT_ATTR_LID_SWITCH_RELIABILITY=write_open + ########################################## # Synaptics ########################################## @@ -188,11 +204,3 @@ libinput:touchpad:input:b0003v056Ap* libinput:name:*Trackball*:dmi:* LIBINPUT_MODEL_TRACKBALL=1 -########################################## -# Chassis types 9 (Laptop) and 10 -# (Notebook) are expected to have working -# lid switches -########################################## -libinput:name:*Lid Switch*:dmi:*:ct10:* -libinput:name:*Lid Switch*:dmi:*:ct9:* - LIBINPUT_ATTR_LID_SWITCH_RELIABILITY=reliable diff --git a/udev/parse_hwdb.py b/udev/parse_hwdb.py index 102ef6c8..d079be20 100755 --- a/udev/parse_hwdb.py +++ b/udev/parse_hwdb.py @@ -102,10 +102,10 @@ def property_grammar(): size_props = [Literal(name)('NAME') - Suppress('=') - val('VALUE') for name, val in sz_props] - reliability_tags = (Literal("reliable")) + reliability_tags = Or(('reliable', 'write_open')) reliability = [Literal('LIBINPUT_ATTR_LID_SWITCH_RELIABILITY')('NAME') - Suppress('=') - - Group(OneOrMore(reliability_tags))('VALUE')] + reliability_tags('VALUE')] grammar = Or(model_props + size_props + reliability) From 60de087e6521d2e098e129dae86cf40f7f7af354 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 30 Jan 2017 18:01:09 +1000 Subject: [PATCH 17/18] evdev: improve type-safety on dispatch switches Set the dispatch type on creation, then check that whenever we try to get the dispatch struct. This avoids a potential mismatch between the backends. Plus, use of container_of means we're not dependent on the exact layout anymore. Signed-off-by: Peter Hutterer --- src/evdev-lid.c | 28 +++++++++++++++++----------- src/evdev-mt-touchpad-tap.c | 22 ++++++++++++---------- src/evdev-mt-touchpad.c | 14 ++++++-------- src/evdev-mt-touchpad.h | 10 ++++++++++ src/evdev-tablet-pad.c | 7 ++++--- src/evdev-tablet-pad.h | 10 ++++++++++ src/evdev-tablet.c | 21 ++++++++------------- src/evdev-tablet.h | 10 ++++++++++ src/evdev.c | 17 +++++++++-------- src/evdev.h | 27 +++++++++++++++++++++++++++ 10 files changed, 113 insertions(+), 53 deletions(-) diff --git a/src/evdev-lid.c b/src/evdev-lid.c index c5af7533..6a2b5063 100644 --- a/src/evdev-lid.c +++ b/src/evdev-lid.c @@ -41,13 +41,22 @@ struct lid_switch_dispatch { } keyboard; }; +static inline struct lid_switch_dispatch* +lid_dispatch(struct evdev_dispatch *dispatch) +{ + struct lid_switch_dispatch *l; + + evdev_verify_dispatch_type(dispatch, DISPATCH_LID_SWITCH); + + return container_of(dispatch, l, base); +} + static void lid_switch_keyboard_event(uint64_t time, struct libinput_event *event, void *data) { - struct lid_switch_dispatch *dispatch = - (struct lid_switch_dispatch*)data; + struct lid_switch_dispatch *dispatch = lid_dispatch(data); if (!dispatch->lid_is_closed) return; @@ -127,8 +136,7 @@ lid_switch_process(struct evdev_dispatch *evdev_dispatch, struct input_event *event, uint64_t time) { - struct lid_switch_dispatch *dispatch = - (struct lid_switch_dispatch*)evdev_dispatch; + struct lid_switch_dispatch *dispatch = lid_dispatch(evdev_dispatch); switch (event->type) { case EV_SW: @@ -168,8 +176,7 @@ evdev_read_switch_reliability_prop(struct evdev_device *device) static void lid_switch_destroy(struct evdev_dispatch *evdev_dispatch) { - struct lid_switch_dispatch *dispatch = - (struct lid_switch_dispatch*)evdev_dispatch; + struct lid_switch_dispatch *dispatch = lid_dispatch(evdev_dispatch); free(dispatch); } @@ -179,7 +186,7 @@ lid_switch_pair_keyboard(struct evdev_device *lid_switch, struct evdev_device *keyboard) { struct lid_switch_dispatch *dispatch = - (struct lid_switch_dispatch*)lid_switch->dispatch; + lid_dispatch(lid_switch->dispatch); unsigned int bus_kbd = libevdev_get_id_bustype(keyboard->evdev); if ((keyboard->tags & EVDEV_TAG_KEYBOARD) == 0) @@ -214,8 +221,7 @@ static void lid_switch_interface_device_removed(struct evdev_device *device, struct evdev_device *removed_device) { - struct lid_switch_dispatch *dispatch = - (struct lid_switch_dispatch*)device->dispatch; + struct lid_switch_dispatch *dispatch = lid_dispatch(device->dispatch); if (removed_device == dispatch->keyboard.keyboard) { libinput_device_remove_event_listener( @@ -228,8 +234,7 @@ static void lid_switch_sync_initial_state(struct evdev_device *device, struct evdev_dispatch *evdev_dispatch) { - struct lid_switch_dispatch *dispatch = - (struct lid_switch_dispatch*)evdev_dispatch; + struct lid_switch_dispatch *dispatch = lid_dispatch(device->dispatch); struct libevdev *evdev = device->evdev; bool is_closed = false; @@ -284,6 +289,7 @@ evdev_lid_switch_dispatch_create(struct evdev_device *lid_device) if (dispatch == NULL) return NULL; + dispatch->base.dispatch_type = DISPATCH_LID_SWITCH; dispatch->base.interface = &lid_switch_interface; dispatch->device = lid_device; libinput_device_init_event_listener(&dispatch->keyboard.listener); diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index 9fba521f..5fccbc21 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -901,7 +901,7 @@ tp_tap_config_count(struct libinput_device *device) struct tp_dispatch *tp = NULL; dispatch = ((struct evdev_device *) device)->dispatch; - tp = container_of(dispatch, tp, base); + tp = tp_dispatch(dispatch); return min(tp->ntouches, 3U); /* we only do up to 3 finger tap */ } @@ -910,10 +910,12 @@ static enum libinput_config_status tp_tap_config_set_enabled(struct libinput_device *device, enum libinput_config_tap_state enabled) { - struct evdev_dispatch *dispatch = ((struct evdev_device *) device)->dispatch; + struct evdev_dispatch *dispatch; struct tp_dispatch *tp = NULL; - tp = container_of(dispatch, tp, base); + dispatch = ((struct evdev_device *) device)->dispatch; + tp = tp_dispatch(dispatch); + tp_tap_enabled_update(tp, tp->tap.suspended, (enabled == LIBINPUT_CONFIG_TAP_ENABLED), libinput_now(device->seat->libinput)); @@ -928,7 +930,7 @@ tp_tap_config_is_enabled(struct libinput_device *device) struct tp_dispatch *tp = NULL; dispatch = ((struct evdev_device *) device)->dispatch; - tp = container_of(dispatch, tp, base); + tp = tp_dispatch(dispatch); return tp->tap.enabled ? LIBINPUT_CONFIG_TAP_ENABLED : LIBINPUT_CONFIG_TAP_DISABLED; @@ -971,7 +973,7 @@ tp_tap_config_set_map(struct libinput_device *device, struct evdev_dispatch *dispatch = ((struct evdev_device *) device)->dispatch; struct tp_dispatch *tp = NULL; - tp = container_of(dispatch, tp, base); + tp = tp_dispatch(dispatch); tp->tap.want_map = map; tp_tap_update_map(tp); @@ -985,7 +987,7 @@ tp_tap_config_get_map(struct libinput_device *device) struct evdev_dispatch *dispatch = ((struct evdev_device *) device)->dispatch; struct tp_dispatch *tp = NULL; - tp = container_of(dispatch, tp, base); + tp = tp_dispatch(dispatch); return tp->tap.want_map; } @@ -1003,7 +1005,7 @@ tp_tap_config_set_drag_enabled(struct libinput_device *device, struct evdev_dispatch *dispatch = ((struct evdev_device *) device)->dispatch; struct tp_dispatch *tp = NULL; - tp = container_of(dispatch, tp, base); + tp = tp_dispatch(dispatch); tp->tap.drag_enabled = enabled; return LIBINPUT_CONFIG_STATUS_SUCCESS; @@ -1015,7 +1017,7 @@ tp_tap_config_get_drag_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); + tp = tp_dispatch(evdev->dispatch); return tp->tap.drag_enabled; } @@ -1041,7 +1043,7 @@ tp_tap_config_set_draglock_enabled(struct libinput_device *device, struct evdev_dispatch *dispatch = ((struct evdev_device *) device)->dispatch; struct tp_dispatch *tp = NULL; - tp = container_of(dispatch, tp, base); + tp = tp_dispatch(dispatch); tp->tap.drag_lock_enabled = enabled; return LIBINPUT_CONFIG_STATUS_SUCCESS; @@ -1053,7 +1055,7 @@ 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); + tp = tp_dispatch(evdev->dispatch); return tp->tap.drag_lock_enabled; } diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 5b166459..d2326342 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1140,8 +1140,7 @@ tp_interface_process(struct evdev_dispatch *dispatch, struct input_event *e, uint64_t time) { - struct tp_dispatch *tp = - (struct tp_dispatch *)dispatch; + struct tp_dispatch *tp = tp_dispatch(dispatch); if (tp->ignore_events) return; @@ -1185,8 +1184,7 @@ tp_remove_sendevents(struct tp_dispatch *tp) static void tp_interface_remove(struct evdev_dispatch *dispatch) { - struct tp_dispatch *tp = - (struct tp_dispatch*)dispatch; + struct tp_dispatch *tp = tp_dispatch(dispatch); tp_remove_tap(tp); tp_remove_buttons(tp); @@ -1198,8 +1196,7 @@ tp_interface_remove(struct evdev_dispatch *dispatch) static void tp_interface_destroy(struct evdev_dispatch *dispatch) { - struct tp_dispatch *tp = - (struct tp_dispatch*)dispatch; + struct tp_dispatch *tp = tp_dispatch(dispatch); free(tp->touches); free(tp); @@ -1261,7 +1258,7 @@ static void tp_interface_suspend(struct evdev_dispatch *dispatch, struct evdev_device *device) { - struct tp_dispatch *tp = (struct tp_dispatch *)dispatch; + struct tp_dispatch *tp = tp_dispatch(dispatch); tp_clear_state(tp); } @@ -1742,7 +1739,7 @@ tp_interface_toggle_touch(struct evdev_dispatch *dispatch, struct evdev_device *device, bool enable) { - struct tp_dispatch *tp = (struct tp_dispatch*)dispatch; + struct tp_dispatch *tp = tp_dispatch(dispatch); bool ignore_events = !enable; if (ignore_events == tp->ignore_events) @@ -2322,6 +2319,7 @@ static int tp_init(struct tp_dispatch *tp, struct evdev_device *device) { + tp->base.dispatch_type = DISPATCH_TOUCHPAD; tp->base.interface = &tp_interface; tp->device = device; diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 8ae1bf9b..a54eb5c5 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -383,6 +383,16 @@ struct tp_dispatch { } lid_switch; }; +static inline struct tp_dispatch* +tp_dispatch(struct evdev_dispatch *dispatch) +{ + struct tp_dispatch *tp; + + evdev_verify_dispatch_type(dispatch, DISPATCH_TOUCHPAD); + + return container_of(dispatch, tp, base); +} + #define tp_for_each_touch(_tp, _t) \ for (unsigned int _i = 0; _i < (_tp)->ntouches && (_t = &(_tp)->touches[_i]); _i++) diff --git a/src/evdev-tablet-pad.c b/src/evdev-tablet-pad.c index 82542bc6..cc7553ff 100644 --- a/src/evdev-tablet-pad.c +++ b/src/evdev-tablet-pad.c @@ -452,7 +452,7 @@ pad_process(struct evdev_dispatch *dispatch, struct input_event *e, uint64_t time) { - struct pad_dispatch *pad = (struct pad_dispatch *)dispatch; + struct pad_dispatch *pad = pad_dispatch(dispatch); switch (e->type) { case EV_ABS: @@ -481,7 +481,7 @@ static void pad_suspend(struct evdev_dispatch *dispatch, struct evdev_device *device) { - struct pad_dispatch *pad = (struct pad_dispatch *)dispatch; + struct pad_dispatch *pad = pad_dispatch(dispatch); struct libinput *libinput = pad_libinput_context(pad); unsigned int code; @@ -496,7 +496,7 @@ pad_suspend(struct evdev_dispatch *dispatch, static void pad_destroy(struct evdev_dispatch *dispatch) { - struct pad_dispatch *pad = (struct pad_dispatch*)dispatch; + struct pad_dispatch *pad = pad_dispatch(dispatch); pad_destroy_leds(pad); free(pad); @@ -556,6 +556,7 @@ pad_init_left_handed(struct evdev_device *device) static int pad_init(struct pad_dispatch *pad, struct evdev_device *device) { + pad->base.dispatch_type = DISPATCH_TABLET_PAD; pad->base.interface = &pad_interface; pad->device = device; pad->status = PAD_NONE; diff --git a/src/evdev-tablet-pad.h b/src/evdev-tablet-pad.h index 9002fca9..55690071 100644 --- a/src/evdev-tablet-pad.h +++ b/src/evdev-tablet-pad.h @@ -70,6 +70,16 @@ struct pad_dispatch { } modes; }; +static inline struct pad_dispatch* +pad_dispatch(struct evdev_dispatch *dispatch) +{ + struct pad_dispatch *p; + + evdev_verify_dispatch_type(dispatch, DISPATCH_TABLET_PAD); + + return container_of(dispatch, p, base); +} + static inline struct libinput * pad_libinput_context(const struct pad_dispatch *pad) { diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index b76d8eaa..12a014bd 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -201,8 +201,7 @@ tablet_process_absolute(struct tablet_dispatch *tablet, static void tablet_change_to_left_handed(struct evdev_device *device) { - struct tablet_dispatch *tablet = - (struct tablet_dispatch*)device->dispatch; + struct tablet_dispatch *tablet = tablet_dispatch(device->dispatch); if (device->left_handed.enabled == device->left_handed.want_enabled) return; @@ -1484,8 +1483,7 @@ tablet_process(struct evdev_dispatch *dispatch, struct input_event *e, uint64_t time) { - struct tablet_dispatch *tablet = - (struct tablet_dispatch *)dispatch; + struct tablet_dispatch *tablet = tablet_dispatch(dispatch); switch (e->type) { case EV_ABS: @@ -1518,8 +1516,7 @@ static void tablet_suspend(struct evdev_dispatch *dispatch, struct evdev_device *device) { - struct tablet_dispatch *tablet = - (struct tablet_dispatch *)dispatch; + struct tablet_dispatch *tablet = tablet_dispatch(dispatch); tablet_set_touch_device_enabled(tablet->touch_device, true); } @@ -1527,8 +1524,7 @@ tablet_suspend(struct evdev_dispatch *dispatch, static void tablet_destroy(struct evdev_dispatch *dispatch) { - struct tablet_dispatch *tablet = - (struct tablet_dispatch*)dispatch; + struct tablet_dispatch *tablet = tablet_dispatch(dispatch); struct libinput_tablet_tool *tool, *tmp; list_for_each_safe(tool, tmp, &tablet->tool_list, link) { @@ -1542,8 +1538,7 @@ static void tablet_device_added(struct evdev_device *device, struct evdev_device *added_device) { - struct tablet_dispatch *tablet = - (struct tablet_dispatch*)device->dispatch; + struct tablet_dispatch *tablet = tablet_dispatch(device->dispatch); if (libinput_device_get_device_group(&device->base) != libinput_device_get_device_group(&added_device->base)) @@ -1560,8 +1555,7 @@ static void tablet_device_removed(struct evdev_device *device, struct evdev_device *removed_device) { - struct tablet_dispatch *tablet = - (struct tablet_dispatch*)device->dispatch; + struct tablet_dispatch *tablet = tablet_dispatch(device->dispatch); if (tablet->touch_device == removed_device) tablet->touch_device = NULL; @@ -1571,10 +1565,10 @@ static void tablet_check_initial_proximity(struct evdev_device *device, struct evdev_dispatch *dispatch) { + struct tablet_dispatch *tablet = tablet_dispatch(dispatch); bool tool_in_prox = false; int code, state; enum libinput_tablet_tool_type tool; - struct tablet_dispatch *tablet = (struct tablet_dispatch*)dispatch; for (tool = LIBINPUT_TABLET_TOOL_TYPE_PEN; tool <= LIBINPUT_TABLET_TOOL_TYPE_MAX; tool++) { code = tablet_tool_to_evcode(tool); @@ -1746,6 +1740,7 @@ tablet_init(struct tablet_dispatch *tablet, enum libinput_tablet_tool_axis axis; int rc; + tablet->base.dispatch_type = DISPATCH_TABLET; tablet->base.interface = &tablet_interface; tablet->device = device; tablet->status = TABLET_NONE; diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h index 2279e03a..2b2b1a7f 100644 --- a/src/evdev-tablet.h +++ b/src/evdev-tablet.h @@ -76,6 +76,16 @@ struct tablet_dispatch { struct evdev_device *touch_device; }; +static inline struct tablet_dispatch* +tablet_dispatch(struct evdev_dispatch *dispatch) +{ + struct tablet_dispatch *t; + + evdev_verify_dispatch_type(dispatch, DISPATCH_TABLET); + + return container_of(dispatch, t, base); +} + static inline enum libinput_tablet_tool_axis evcode_to_axis(const uint32_t evcode) { diff --git a/src/evdev.c b/src/evdev.c index 6ac3427d..e040583a 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1097,7 +1097,7 @@ fallback_process(struct evdev_dispatch *evdev_dispatch, struct input_event *event, uint64_t time) { - struct fallback_dispatch *dispatch = (struct fallback_dispatch*)evdev_dispatch; + struct fallback_dispatch *dispatch = fallback_dispatch(evdev_dispatch); enum evdev_event_type sent; if (dispatch->ignore_events) @@ -1226,7 +1226,7 @@ static void fallback_suspend(struct evdev_dispatch *evdev_dispatch, struct evdev_device *device) { - struct fallback_dispatch *dispatch = (struct fallback_dispatch*)evdev_dispatch; + struct fallback_dispatch *dispatch = fallback_dispatch(evdev_dispatch); fallback_return_to_neutral_state(dispatch, device); } @@ -1236,7 +1236,7 @@ fallback_toggle_touch(struct evdev_dispatch *evdev_dispatch, struct evdev_device *device, bool enable) { - struct fallback_dispatch *dispatch = (struct fallback_dispatch*)evdev_dispatch; + struct fallback_dispatch *dispatch = fallback_dispatch(evdev_dispatch); bool ignore_events = !enable; if (ignore_events == dispatch->ignore_events) @@ -1251,7 +1251,7 @@ fallback_toggle_touch(struct evdev_dispatch *evdev_dispatch, static void fallback_destroy(struct evdev_dispatch *evdev_dispatch) { - struct fallback_dispatch *dispatch = (struct fallback_dispatch*)evdev_dispatch; + struct fallback_dispatch *dispatch = fallback_dispatch(evdev_dispatch); free(dispatch->mt.slots); free(dispatch); @@ -1369,7 +1369,7 @@ evdev_left_handed_has(struct libinput_device *device) static void evdev_change_to_left_handed(struct evdev_device *device) { - struct fallback_dispatch *dispatch = (struct fallback_dispatch*)device->dispatch; + struct fallback_dispatch *dispatch = fallback_dispatch(device->dispatch); if (device->left_handed.want_enabled == device->left_handed.enabled) return; @@ -1431,7 +1431,7 @@ evdev_scroll_get_methods(struct libinput_device *device) static void evdev_change_scroll_method(struct evdev_device *device) { - struct fallback_dispatch *dispatch = (struct fallback_dispatch*)device->dispatch; + struct fallback_dispatch *dispatch = fallback_dispatch(device->dispatch); if (device->scroll.want_method == device->scroll.method && device->scroll.want_button == device->scroll.button) @@ -1620,7 +1620,7 @@ evdev_rotation_config_set_angle(struct libinput_device *libinput_device, unsigned int degrees_cw) { struct evdev_device *device = (struct evdev_device*)libinput_device; - struct fallback_dispatch *dispatch = (struct fallback_dispatch*)device->dispatch; + struct fallback_dispatch *dispatch = fallback_dispatch(device->dispatch); dispatch->rotation.angle = degrees_cw; matrix_init_rotate(&dispatch->rotation.matrix, degrees_cw); @@ -1632,7 +1632,7 @@ static unsigned int evdev_rotation_config_get_angle(struct libinput_device *libinput_device) { struct evdev_device *device = (struct evdev_device*)libinput_device; - struct fallback_dispatch *dispatch = (struct fallback_dispatch*)device->dispatch; + struct fallback_dispatch *dispatch = fallback_dispatch(device->dispatch); return dispatch->rotation.angle; } @@ -1774,6 +1774,7 @@ fallback_dispatch_create(struct libinput_device *device) if (dispatch == NULL) return NULL; + dispatch->base.dispatch_type = DISPATCH_FALLBACK; dispatch->base.interface = &fallback_interface; dispatch->pending_event = EVDEV_NONE; diff --git a/src/evdev.h b/src/evdev.h index 1d802bad..924a4a14 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -284,7 +284,16 @@ struct evdev_dispatch_interface { bool enable); }; +enum evdev_dispatch_type { + DISPATCH_FALLBACK, + DISPATCH_TOUCHPAD, + DISPATCH_TABLET, + DISPATCH_TABLET_PAD, + DISPATCH_LID_SWITCH, +}; + struct evdev_dispatch { + enum evdev_dispatch_type dispatch_type; struct evdev_dispatch_interface *interface; struct { @@ -293,6 +302,14 @@ struct evdev_dispatch { } sendevents; }; +static inline void +evdev_verify_dispatch_type(struct evdev_dispatch *dispatch, + enum evdev_dispatch_type type) +{ + if (dispatch->dispatch_type != type) + abort(); +} + struct fallback_dispatch { struct evdev_dispatch base; @@ -336,6 +353,16 @@ struct fallback_dispatch { bool ignore_events; }; +static inline struct fallback_dispatch* +fallback_dispatch(struct evdev_dispatch *dispatch) +{ + struct fallback_dispatch *f; + + evdev_verify_dispatch_type(dispatch, DISPATCH_FALLBACK); + + return container_of(dispatch, f, base); +} + struct evdev_device * evdev_device_create(struct libinput_seat *seat, struct udev_device *device); From 2dc6534ec0bc0b42dd2437ccfaa1eed04e98dcb2 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 30 Jan 2017 19:48:33 +1000 Subject: [PATCH 18/18] evdev: add a wrapper to get the evdev device from a libinput device Signed-off-by: Peter Hutterer --- src/evdev-middle-button.c | 8 +-- src/evdev-mt-touchpad-buttons.c | 10 ++-- src/evdev-mt-touchpad-tap.c | 60 +++++++------------- src/evdev-mt-touchpad.c | 24 ++++---- src/evdev-tablet-pad.c | 4 +- src/evdev.c | 98 ++++++++++++++++----------------- src/evdev.h | 8 +++ src/libinput.c | 38 +++++-------- src/path-seat.c | 6 +- src/udev-seat.c | 4 +- 10 files changed, 119 insertions(+), 141 deletions(-) diff --git a/src/evdev-middle-button.c b/src/evdev-middle-button.c index 09f77de4..d9330bad 100644 --- a/src/evdev-middle-button.c +++ b/src/evdev-middle-button.c @@ -638,7 +638,7 @@ evdev_middlebutton_filter_button(struct evdev_device *device, static void evdev_middlebutton_handle_timeout(uint64_t now, void *data) { - struct evdev_device *device = (struct evdev_device*)data; + struct evdev_device *device = evdev_device(data); evdev_middlebutton_handle_event(device, now, MIDDLEBUTTON_EVENT_TIMEOUT); } @@ -653,7 +653,7 @@ static enum libinput_config_status evdev_middlebutton_set(struct libinput_device *device, enum libinput_config_middle_emulation_state enable) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); switch (enable) { case LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED: @@ -674,7 +674,7 @@ evdev_middlebutton_set(struct libinput_device *device, enum libinput_config_middle_emulation_state evdev_middlebutton_get(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); return evdev->middlebutton.want_enabled ? LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED : @@ -684,7 +684,7 @@ evdev_middlebutton_get(struct libinput_device *device) enum libinput_config_middle_emulation_state evdev_middlebutton_get_default(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); return evdev->middlebutton.enabled_default ? LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED : diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c index f4fe6b79..4a684707 100644 --- a/src/evdev-mt-touchpad-buttons.c +++ b/src/evdev-mt-touchpad-buttons.c @@ -627,7 +627,7 @@ tp_init_top_softbuttons(struct tp_dispatch *tp, static inline uint32_t tp_button_config_click_get_methods(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; uint32_t methods = LIBINPUT_CONFIG_CLICK_METHOD_NONE; @@ -669,7 +669,7 @@ static enum libinput_config_status tp_button_config_click_set_method(struct libinput_device *device, enum libinput_config_click_method method) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; tp->buttons.click_method = method; @@ -681,7 +681,7 @@ tp_button_config_click_set_method(struct libinput_device *device, static enum libinput_config_click_method tp_button_config_click_get_method(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; return tp->buttons.click_method; @@ -711,7 +711,7 @@ tp_click_get_default_method(struct tp_dispatch *tp) static enum libinput_config_click_method tp_button_config_click_get_default_method(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; return tp_click_get_default_method(tp); @@ -746,7 +746,7 @@ static enum libinput_config_status tp_clickpad_middlebutton_set(struct libinput_device *device, enum libinput_config_middle_emulation_state enable) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); switch (enable) { case LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED: diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index 5fccbc21..1829732f 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -897,11 +897,8 @@ tp_tap_enabled_update(struct tp_dispatch *tp, bool suspended, bool enabled, uint static int tp_tap_config_count(struct libinput_device *device) { - struct evdev_dispatch *dispatch; - struct tp_dispatch *tp = NULL; - - dispatch = ((struct evdev_device *) device)->dispatch; - tp = tp_dispatch(dispatch); + struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; + struct tp_dispatch *tp = tp_dispatch(dispatch); return min(tp->ntouches, 3U); /* we only do up to 3 finger tap */ } @@ -910,11 +907,8 @@ static enum libinput_config_status tp_tap_config_set_enabled(struct libinput_device *device, enum libinput_config_tap_state enabled) { - struct evdev_dispatch *dispatch; - struct tp_dispatch *tp = NULL; - - dispatch = ((struct evdev_device *) device)->dispatch; - tp = tp_dispatch(dispatch); + struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; + struct tp_dispatch *tp = tp_dispatch(dispatch); tp_tap_enabled_update(tp, tp->tap.suspended, (enabled == LIBINPUT_CONFIG_TAP_ENABLED), @@ -926,11 +920,8 @@ tp_tap_config_set_enabled(struct libinput_device *device, static enum libinput_config_tap_state tp_tap_config_is_enabled(struct libinput_device *device) { - struct evdev_dispatch *dispatch; - struct tp_dispatch *tp = NULL; - - dispatch = ((struct evdev_device *) device)->dispatch; - tp = tp_dispatch(dispatch); + struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; + struct tp_dispatch *tp = tp_dispatch(dispatch); return tp->tap.enabled ? LIBINPUT_CONFIG_TAP_ENABLED : LIBINPUT_CONFIG_TAP_DISABLED; @@ -961,7 +952,7 @@ tp_tap_default(struct evdev_device *evdev) static enum libinput_config_tap_state tp_tap_config_get_default(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device *)device; + struct evdev_device *evdev = evdev_device(device); return tp_tap_default(evdev); } @@ -970,10 +961,9 @@ static enum libinput_config_status tp_tap_config_set_map(struct libinput_device *device, enum libinput_config_tap_button_map map) { - struct evdev_dispatch *dispatch = ((struct evdev_device *) device)->dispatch; - struct tp_dispatch *tp = NULL; + struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; + struct tp_dispatch *tp = tp_dispatch(dispatch); - tp = tp_dispatch(dispatch); tp->tap.want_map = map; tp_tap_update_map(tp); @@ -984,10 +974,8 @@ tp_tap_config_set_map(struct libinput_device *device, static enum libinput_config_tap_button_map tp_tap_config_get_map(struct libinput_device *device) { - struct evdev_dispatch *dispatch = ((struct evdev_device *) device)->dispatch; - struct tp_dispatch *tp = NULL; - - tp = tp_dispatch(dispatch); + struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; + struct tp_dispatch *tp = tp_dispatch(dispatch); return tp->tap.want_map; } @@ -1002,10 +990,9 @@ static enum libinput_config_status tp_tap_config_set_drag_enabled(struct libinput_device *device, enum libinput_config_drag_state enabled) { - struct evdev_dispatch *dispatch = ((struct evdev_device *) device)->dispatch; - struct tp_dispatch *tp = NULL; + struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; + struct tp_dispatch *tp = tp_dispatch(dispatch); - tp = tp_dispatch(dispatch); tp->tap.drag_enabled = enabled; return LIBINPUT_CONFIG_STATUS_SUCCESS; @@ -1014,10 +1001,8 @@ tp_tap_config_set_drag_enabled(struct libinput_device *device, static enum libinput_config_drag_state tp_tap_config_get_drag_enabled(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device *)device; - struct tp_dispatch *tp = NULL; - - tp = tp_dispatch(evdev->dispatch); + struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; + struct tp_dispatch *tp = tp_dispatch(dispatch); return tp->tap.drag_enabled; } @@ -1031,7 +1016,7 @@ tp_drag_default(struct evdev_device *device) static enum libinput_config_drag_state tp_tap_config_get_default_drag_enabled(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device *)device; + struct evdev_device *evdev = evdev_device(device); return tp_drag_default(evdev); } @@ -1040,10 +1025,9 @@ 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; + struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; + struct tp_dispatch *tp = tp_dispatch(dispatch); - tp = tp_dispatch(dispatch); tp->tap.drag_lock_enabled = enabled; return LIBINPUT_CONFIG_STATUS_SUCCESS; @@ -1052,10 +1036,8 @@ tp_tap_config_set_draglock_enabled(struct libinput_device *device, 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 = tp_dispatch(evdev->dispatch); + struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; + struct tp_dispatch *tp = tp_dispatch(dispatch); return tp->tap.drag_lock_enabled; } @@ -1069,7 +1051,7 @@ tp_drag_lock_default(struct evdev_device *device) 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; + struct evdev_device *evdev = evdev_device(device); return tp_drag_lock_default(evdev); } diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index d2326342..9614f8e5 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1645,7 +1645,7 @@ tp_interface_device_removed(struct evdev_device *device, return; list_for_each(dev, &device->base.seat->devices_list, link) { - struct evdev_device *d = (struct evdev_device*)dev; + struct evdev_device *d = evdev_device(dev); if (d != removed_device && (d->tags & EVDEV_TAG_EXTERNAL_MOUSE)) { return; @@ -1982,7 +1982,7 @@ tp_scroll_get_methods(struct tp_dispatch *tp) static uint32_t tp_scroll_config_scroll_method_get_methods(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; return tp_scroll_get_methods(tp); @@ -1992,7 +1992,7 @@ static enum libinput_config_status tp_scroll_config_scroll_method_set_method(struct libinput_device *device, enum libinput_config_scroll_method method) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; uint64_t time = libinput_now(tp_libinput_context(tp)); @@ -2010,7 +2010,7 @@ tp_scroll_config_scroll_method_set_method(struct libinput_device *device, static enum libinput_config_scroll_method tp_scroll_config_scroll_method_get_method(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; return tp->scroll.method; @@ -2039,7 +2039,7 @@ tp_scroll_get_default_method(struct tp_dispatch *tp) static enum libinput_config_scroll_method tp_scroll_config_scroll_method_get_default_method(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; return tp_scroll_get_default_method(tp); @@ -2074,7 +2074,7 @@ static enum libinput_config_status tp_dwt_config_set(struct libinput_device *device, enum libinput_config_dwt_state enable) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; switch(enable) { @@ -2093,7 +2093,7 @@ tp_dwt_config_set(struct libinput_device *device, static enum libinput_config_dwt_state tp_dwt_config_get(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; return tp->dwt.dwt_enabled ? @@ -2110,7 +2110,7 @@ tp_dwt_default_enabled(struct tp_dispatch *tp) static enum libinput_config_dwt_state tp_dwt_config_get_default(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; return tp_dwt_default_enabled(tp) ? @@ -2365,7 +2365,7 @@ tp_init(struct tp_dispatch *tp, static uint32_t tp_sendevents_get_modes(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); uint32_t modes = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; if (evdev->tags & EVDEV_TAG_INTERNAL_TOUCHPAD) @@ -2381,7 +2381,7 @@ tp_suspend_conditional(struct tp_dispatch *tp, struct libinput_device *dev; list_for_each(dev, &device->base.seat->devices_list, link) { - struct evdev_device *d = (struct evdev_device*)dev; + struct evdev_device *d = evdev_device(dev); if (d->tags & EVDEV_TAG_EXTERNAL_MOUSE) { tp_suspend(tp, device); return; @@ -2393,7 +2393,7 @@ static enum libinput_config_status tp_sendevents_set_mode(struct libinput_device *device, enum libinput_config_send_events_mode mode) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; /* DISABLED overrides any DISABLED_ON_ */ @@ -2426,7 +2426,7 @@ tp_sendevents_set_mode(struct libinput_device *device, static enum libinput_config_send_events_mode tp_sendevents_get_mode(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct tp_dispatch *dispatch = (struct tp_dispatch*)evdev->dispatch; return dispatch->sendevents.current_mode; diff --git a/src/evdev-tablet-pad.c b/src/evdev-tablet-pad.c index cc7553ff..bed43b6e 100644 --- a/src/evdev-tablet-pad.c +++ b/src/evdev-tablet-pad.c @@ -580,7 +580,7 @@ static enum libinput_config_status pad_sendevents_set_mode(struct libinput_device *device, enum libinput_config_send_events_mode mode) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct pad_dispatch *pad = (struct pad_dispatch*)evdev->dispatch; if (mode == pad->sendevents.current_mode) @@ -604,7 +604,7 @@ pad_sendevents_set_mode(struct libinput_device *device, static enum libinput_config_send_events_mode pad_sendevents_get_mode(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct pad_dispatch *dispatch = (struct pad_dispatch*)evdev->dispatch; return dispatch->sendevents.current_mode; diff --git a/src/evdev.c b/src/evdev.c index e040583a..afee5906 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1260,7 +1260,7 @@ fallback_destroy(struct evdev_dispatch *evdev_dispatch) static int evdev_calibration_has_matrix(struct libinput_device *libinput_device) { - struct evdev_device *device = (struct evdev_device*)libinput_device; + struct evdev_device *device = evdev_device(libinput_device); return device->abs.absinfo_x && device->abs.absinfo_y; } @@ -1269,7 +1269,7 @@ static enum libinput_config_status evdev_calibration_set_matrix(struct libinput_device *libinput_device, const float matrix[6]) { - struct evdev_device *device = (struct evdev_device*)libinput_device; + struct evdev_device *device = evdev_device(libinput_device); evdev_device_calibrate(device, matrix); @@ -1280,7 +1280,7 @@ static int evdev_calibration_get_matrix(struct libinput_device *libinput_device, float matrix[6]) { - struct evdev_device *device = (struct evdev_device*)libinput_device; + struct evdev_device *device = evdev_device(libinput_device); matrix_to_farray6(&device->abs.usermatrix, matrix); @@ -1291,7 +1291,7 @@ static int evdev_calibration_get_default_matrix(struct libinput_device *libinput_device, float matrix[6]) { - struct evdev_device *device = (struct evdev_device*)libinput_device; + struct evdev_device *device = evdev_device(libinput_device); matrix_to_farray6(&device->abs.default_calibration, matrix); @@ -1321,7 +1321,7 @@ static enum libinput_config_status evdev_sendevents_set_mode(struct libinput_device *device, enum libinput_config_send_events_mode mode) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct evdev_dispatch *dispatch = evdev->dispatch; if (mode == dispatch->sendevents.current_mode) @@ -1346,7 +1346,7 @@ evdev_sendevents_set_mode(struct libinput_device *device, static enum libinput_config_send_events_mode evdev_sendevents_get_mode(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct evdev_dispatch *dispatch = evdev->dispatch; return dispatch->sendevents.current_mode; @@ -1383,11 +1383,11 @@ evdev_change_to_left_handed(struct evdev_device *device) static enum libinput_config_status evdev_left_handed_set(struct libinput_device *device, int left_handed) { - struct evdev_device *evdev_device = (struct evdev_device *)device; + struct evdev_device *evdev = evdev_device(device); - evdev_device->left_handed.want_enabled = left_handed ? true : false; + evdev->left_handed.want_enabled = left_handed ? true : false; - evdev_device->left_handed.change_to_enabled(evdev_device); + evdev->left_handed.change_to_enabled(evdev); return LIBINPUT_CONFIG_STATUS_SUCCESS; } @@ -1395,11 +1395,11 @@ evdev_left_handed_set(struct libinput_device *device, int left_handed) static int evdev_left_handed_get(struct libinput_device *device) { - struct evdev_device *evdev_device = (struct evdev_device *)device; + struct evdev_device *evdev = evdev_device(device); /* return the wanted configuration, even if it hasn't taken * effect yet! */ - return evdev_device->left_handed.want_enabled; + return evdev->left_handed.want_enabled; } static int @@ -1448,7 +1448,7 @@ static enum libinput_config_status evdev_scroll_set_method(struct libinput_device *device, enum libinput_config_scroll_method method) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); evdev->scroll.want_method = method; evdev->scroll.change_scroll_method(evdev); @@ -1459,7 +1459,7 @@ evdev_scroll_set_method(struct libinput_device *device, static enum libinput_config_scroll_method evdev_scroll_get_method(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device *)device; + struct evdev_device *evdev = evdev_device(device); /* return the wanted configuration, even if it hasn't taken * effect yet! */ @@ -1469,7 +1469,7 @@ evdev_scroll_get_method(struct libinput_device *device) static enum libinput_config_scroll_method evdev_scroll_get_default_method(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device *)device; + struct evdev_device *evdev = evdev_device(device); if (evdev->tags & EVDEV_TAG_TRACKPOINT) return LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; @@ -1488,7 +1488,7 @@ static enum libinput_config_status evdev_scroll_set_button(struct libinput_device *device, uint32_t button) { - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); evdev->scroll.want_button = button; evdev->scroll.change_scroll_method(evdev); @@ -1499,7 +1499,7 @@ evdev_scroll_set_button(struct libinput_device *device, static uint32_t evdev_scroll_get_button(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device *)device; + struct evdev_device *evdev = evdev_device(device); /* return the wanted configuration, even if it hasn't taken * effect yet! */ @@ -1509,7 +1509,7 @@ evdev_scroll_get_button(struct libinput_device *device) static uint32_t evdev_scroll_get_default_button(struct libinput_device *device) { - struct evdev_device *evdev = (struct evdev_device *)device; + struct evdev_device *evdev = evdev_device(device); if (libevdev_has_event_code(evdev->evdev, EV_KEY, BTN_MIDDLE)) return BTN_MIDDLE; @@ -1574,7 +1574,7 @@ static enum libinput_config_status evdev_scroll_config_natural_set(struct libinput_device *device, int enabled) { - struct evdev_device *dev = (struct evdev_device *)device; + struct evdev_device *dev = evdev_device(device); dev->scroll.natural_scrolling_enabled = enabled ? true : false; @@ -1584,7 +1584,7 @@ evdev_scroll_config_natural_set(struct libinput_device *device, static int evdev_scroll_config_natural_get(struct libinput_device *device) { - struct evdev_device *dev = (struct evdev_device *)device; + struct evdev_device *dev = evdev_device(device); return dev->scroll.natural_scrolling_enabled ? 1 : 0; } @@ -1619,7 +1619,7 @@ static enum libinput_config_status evdev_rotation_config_set_angle(struct libinput_device *libinput_device, unsigned int degrees_cw) { - struct evdev_device *device = (struct evdev_device*)libinput_device; + struct evdev_device *device = evdev_device(libinput_device); struct fallback_dispatch *dispatch = fallback_dispatch(device->dispatch); dispatch->rotation.angle = degrees_cw; @@ -1631,7 +1631,7 @@ evdev_rotation_config_set_angle(struct libinput_device *libinput_device, static unsigned int evdev_rotation_config_get_angle(struct libinput_device *libinput_device) { - struct evdev_device *device = (struct evdev_device*)libinput_device; + struct evdev_device *device = evdev_device(libinput_device); struct fallback_dispatch *dispatch = fallback_dispatch(device->dispatch); return dispatch->rotation.angle; @@ -1766,10 +1766,10 @@ fallback_dispatch_init_abs(struct fallback_dispatch *dispatch, } static struct evdev_dispatch * -fallback_dispatch_create(struct libinput_device *device) +fallback_dispatch_create(struct libinput_device *libinput_device) { struct fallback_dispatch *dispatch = zalloc(sizeof *dispatch); - struct evdev_device *evdev_device = (struct evdev_device *)device; + struct evdev_device *device = evdev_device(libinput_device); if (dispatch == NULL) return NULL; @@ -1778,42 +1778,42 @@ fallback_dispatch_create(struct libinput_device *device) dispatch->base.interface = &fallback_interface; dispatch->pending_event = EVDEV_NONE; - fallback_dispatch_init_rel(dispatch, evdev_device); - fallback_dispatch_init_abs(dispatch, evdev_device); - if (fallback_dispatch_init_slots(dispatch, evdev_device) == -1) { + fallback_dispatch_init_rel(dispatch, device); + fallback_dispatch_init_abs(dispatch, device); + if (fallback_dispatch_init_slots(dispatch, device) == -1) { free(dispatch); return NULL; } - if (evdev_device->left_handed.want_enabled) - evdev_init_left_handed(evdev_device, + if (device->left_handed.want_enabled) + evdev_init_left_handed(device, evdev_change_to_left_handed); - if (evdev_device->scroll.want_button) - evdev_init_button_scroll(evdev_device, + if (device->scroll.want_button) + evdev_init_button_scroll(device, evdev_change_scroll_method); - if (evdev_device->scroll.natural_scrolling_enabled) - evdev_init_natural_scroll(evdev_device); + if (device->scroll.natural_scrolling_enabled) + evdev_init_natural_scroll(device); - evdev_init_calibration(evdev_device, &dispatch->calibration); - evdev_init_sendevents(evdev_device, &dispatch->base); - evdev_init_rotation(evdev_device, dispatch); + evdev_init_calibration(device, &dispatch->calibration); + evdev_init_sendevents(device, &dispatch->base); + evdev_init_rotation(device, dispatch); /* BTN_MIDDLE is set on mice even when it's not present. So * we can only use the absence of BTN_MIDDLE to mean something, i.e. * we enable it by default on anything that only has L&R. * If we have L&R and no middle, we don't expose it as config * option */ - if (libevdev_has_event_code(evdev_device->evdev, EV_KEY, BTN_LEFT) && - libevdev_has_event_code(evdev_device->evdev, EV_KEY, BTN_RIGHT)) { - bool has_middle = libevdev_has_event_code(evdev_device->evdev, + if (libevdev_has_event_code(device->evdev, EV_KEY, BTN_LEFT) && + libevdev_has_event_code(device->evdev, EV_KEY, BTN_RIGHT)) { + bool has_middle = libevdev_has_event_code(device->evdev, EV_KEY, BTN_MIDDLE); bool want_config = has_middle; bool enable_by_default = !has_middle; - evdev_init_middlebutton(evdev_device, + evdev_init_middlebutton(device, enable_by_default, want_config); } @@ -1952,7 +1952,7 @@ evdev_accel_config_available(struct libinput_device *device) static enum libinput_config_status evdev_accel_config_set_speed(struct libinput_device *device, double speed) { - struct evdev_device *dev = (struct evdev_device *)device; + struct evdev_device *dev = evdev_device(device); if (!filter_set_speed(dev->pointer.filter, speed)) return LIBINPUT_CONFIG_STATUS_INVALID; @@ -1963,7 +1963,7 @@ evdev_accel_config_set_speed(struct libinput_device *device, double speed) static double evdev_accel_config_get_speed(struct libinput_device *device) { - struct evdev_device *dev = (struct evdev_device *)device; + struct evdev_device *dev = evdev_device(device); return filter_get_speed(dev->pointer.filter); } @@ -1977,7 +1977,7 @@ evdev_accel_config_get_default_speed(struct libinput_device *device) static uint32_t evdev_accel_config_get_profiles(struct libinput_device *libinput_device) { - struct evdev_device *device = (struct evdev_device*)libinput_device; + struct evdev_device *device = evdev_device(libinput_device); if (!device->pointer.filter) return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE; @@ -1990,7 +1990,7 @@ static enum libinput_config_status evdev_accel_config_set_profile(struct libinput_device *libinput_device, enum libinput_config_accel_profile profile) { - struct evdev_device *device = (struct evdev_device*)libinput_device; + struct evdev_device *device = evdev_device(libinput_device); struct motion_filter *filter; double speed; @@ -2014,7 +2014,7 @@ evdev_accel_config_set_profile(struct libinput_device *libinput_device, static enum libinput_config_accel_profile evdev_accel_config_get_profile(struct libinput_device *libinput_device) { - struct evdev_device *device = (struct evdev_device*)libinput_device; + struct evdev_device *device = evdev_device(libinput_device); return filter_get_type(device->pointer.filter); } @@ -2022,7 +2022,7 @@ evdev_accel_config_get_profile(struct libinput_device *libinput_device) static enum libinput_config_accel_profile evdev_accel_config_get_default_profile(struct libinput_device *libinput_device) { - struct evdev_device *device = (struct evdev_device*)libinput_device; + struct evdev_device *device = evdev_device(libinput_device); if (!device->pointer.filter) return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE; @@ -2698,7 +2698,7 @@ evdev_notify_added_device(struct evdev_device *device) struct libinput_device *dev; list_for_each(dev, &device->base.seat->devices_list, link) { - struct evdev_device *d = (struct evdev_device*)dev; + struct evdev_device *d = evdev_device(dev); if (dev == &device->base) continue; @@ -3282,7 +3282,7 @@ evdev_notify_suspended_device(struct evdev_device *device) return; list_for_each(it, &device->base.seat->devices_list, link) { - struct evdev_device *d = (struct evdev_device*)it; + struct evdev_device *d = evdev_device(it); if (it == &device->base) continue; @@ -3302,7 +3302,7 @@ evdev_notify_resumed_device(struct evdev_device *device) return; list_for_each(it, &device->base.seat->devices_list, link) { - struct evdev_device *d = (struct evdev_device*)it; + struct evdev_device *d = evdev_device(it); if (it == &device->base) continue; @@ -3409,7 +3409,7 @@ evdev_device_remove(struct evdev_device *device) struct libinput_device *dev; list_for_each(dev, &device->base.seat->devices_list, link) { - struct evdev_device *d = (struct evdev_device*)dev; + struct evdev_device *d = evdev_device(dev); if (dev == &device->base) continue; diff --git a/src/evdev.h b/src/evdev.h index 924a4a14..462776db 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -237,6 +237,14 @@ struct evdev_device { } middlebutton; }; +static inline struct evdev_device * +evdev_device(struct libinput_device *device) +{ + struct evdev_device *d; + + return container_of(device, d, base); +} + #define EVDEV_UNHANDLED_DEVICE ((struct evdev_device *) 1) struct evdev_dispatch; diff --git a/src/libinput.c b/src/libinput.c index ebfedece..84e329de 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -516,8 +516,7 @@ libinput_event_pointer_get_dy_unaccelerated( LIBINPUT_EXPORT double libinput_event_pointer_get_absolute_x(struct libinput_event_pointer *event) { - struct evdev_device *device = - (struct evdev_device *) event->base.device; + struct evdev_device *device = evdev_device(event->base.device); require_event_type(libinput_event_get_context(&event->base), event->base.type, @@ -530,8 +529,7 @@ libinput_event_pointer_get_absolute_x(struct libinput_event_pointer *event) LIBINPUT_EXPORT double libinput_event_pointer_get_absolute_y(struct libinput_event_pointer *event) { - struct evdev_device *device = - (struct evdev_device *) event->base.device; + struct evdev_device *device = evdev_device(event->base.device); require_event_type(libinput_event_get_context(&event->base), event->base.type, @@ -546,8 +544,7 @@ libinput_event_pointer_get_absolute_x_transformed( struct libinput_event_pointer *event, uint32_t width) { - struct evdev_device *device = - (struct evdev_device *) event->base.device; + struct evdev_device *device = evdev_device(event->base.device); require_event_type(libinput_event_get_context(&event->base), event->base.type, @@ -562,8 +559,7 @@ libinput_event_pointer_get_absolute_y_transformed( struct libinput_event_pointer *event, uint32_t height) { - struct evdev_device *device = - (struct evdev_device *) event->base.device; + struct evdev_device *device = evdev_device(event->base.device); require_event_type(libinput_event_get_context(&event->base), event->base.type, @@ -752,8 +748,7 @@ libinput_event_touch_get_seat_slot(struct libinput_event_touch *event) LIBINPUT_EXPORT double libinput_event_touch_get_x(struct libinput_event_touch *event) { - struct evdev_device *device = - (struct evdev_device *) event->base.device; + struct evdev_device *device = evdev_device(event->base.device); require_event_type(libinput_event_get_context(&event->base), event->base.type, @@ -768,8 +763,7 @@ LIBINPUT_EXPORT double libinput_event_touch_get_x_transformed(struct libinput_event_touch *event, uint32_t width) { - struct evdev_device *device = - (struct evdev_device *) event->base.device; + struct evdev_device *device = evdev_device(event->base.device); require_event_type(libinput_event_get_context(&event->base), event->base.type, @@ -784,8 +778,7 @@ LIBINPUT_EXPORT double libinput_event_touch_get_y_transformed(struct libinput_event_touch *event, uint32_t height) { - struct evdev_device *device = - (struct evdev_device *) event->base.device; + struct evdev_device *device = evdev_device(event->base.device); require_event_type(libinput_event_get_context(&event->base), event->base.type, @@ -799,8 +792,7 @@ libinput_event_touch_get_y_transformed(struct libinput_event_touch *event, LIBINPUT_EXPORT double libinput_event_touch_get_y(struct libinput_event_touch *event) { - struct evdev_device *device = - (struct evdev_device *) event->base.device; + struct evdev_device *device = evdev_device(event->base.device); require_event_type(libinput_event_get_context(&event->base), event->base.type, @@ -1110,8 +1102,7 @@ libinput_event_tablet_tool_wheel_has_changed( LIBINPUT_EXPORT double libinput_event_tablet_tool_get_x(struct libinput_event_tablet_tool *event) { - struct evdev_device *device = - (struct evdev_device *) event->base.device; + struct evdev_device *device = evdev_device(event->base.device); require_event_type(libinput_event_get_context(&event->base), event->base.type, @@ -1128,8 +1119,7 @@ libinput_event_tablet_tool_get_x(struct libinput_event_tablet_tool *event) LIBINPUT_EXPORT double libinput_event_tablet_tool_get_y(struct libinput_event_tablet_tool *event) { - struct evdev_device *device = - (struct evdev_device *) event->base.device; + struct evdev_device *device = evdev_device(event->base.device); require_event_type(libinput_event_get_context(&event->base), event->base.type, @@ -1277,8 +1267,7 @@ LIBINPUT_EXPORT double libinput_event_tablet_tool_get_x_transformed(struct libinput_event_tablet_tool *event, uint32_t width) { - struct evdev_device *device = - (struct evdev_device *) event->base.device; + struct evdev_device *device = evdev_device(event->base.device); require_event_type(libinput_event_get_context(&event->base), event->base.type, @@ -1297,8 +1286,7 @@ LIBINPUT_EXPORT double libinput_event_tablet_tool_get_y_transformed(struct libinput_event_tablet_tool *event, uint32_t height) { - struct evdev_device *device = - (struct evdev_device *) event->base.device; + struct evdev_device *device = evdev_device(event->base.device); require_event_type(libinput_event_get_context(&event->base), event->base.type, @@ -1898,7 +1886,7 @@ static void libinput_device_destroy(struct libinput_device *device) { assert(list_empty(&device->event_listeners)); - evdev_device_destroy((struct evdev_device *) device); + evdev_device_destroy(evdev_device(device)); } LIBINPUT_EXPORT struct libinput_device * diff --git a/src/path-seat.c b/src/path-seat.c index d806bfbf..e6289a29 100644 --- a/src/path-seat.c +++ b/src/path-seat.c @@ -244,11 +244,11 @@ path_device_change_seat(struct libinput_device *device, const char *seat_name) { struct libinput *libinput = device->seat->libinput; - struct evdev_device *evdev_device = (struct evdev_device *)device; + struct evdev_device *evdev = evdev_device(device); struct udev_device *udev_device = NULL; int rc = -1; - udev_device = evdev_device->udev_device; + udev_device = evdev->udev_device; udev_device_ref(udev_device); libinput_path_remove_device(device); @@ -361,7 +361,7 @@ libinput_path_remove_device(struct libinput_device *device) struct libinput *libinput = device->seat->libinput; struct path_input *input = (struct path_input*)libinput; struct libinput_seat *seat; - struct evdev_device *evdev = (struct evdev_device*)device; + struct evdev_device *evdev = evdev_device(device); struct path_device *dev; if (libinput->interface_backend != &interface_backend) { diff --git a/src/udev-seat.c b/src/udev-seat.c index d1eaed8b..a19afb4d 100644 --- a/src/udev-seat.c +++ b/src/udev-seat.c @@ -322,8 +322,8 @@ udev_device_change_seat(struct libinput_device *device, { struct libinput *libinput = device->seat->libinput; struct udev_input *input = (struct udev_input *)libinput; - struct evdev_device *evdev_device = (struct evdev_device *)device; - struct udev_device *udev_device = evdev_device->udev_device; + struct evdev_device *evdev = evdev_device(device); + struct udev_device *udev_device = evdev->udev_device; int rc; udev_device_ref(udev_device);