From: Jonas Ådahl Date: Sun, 27 Jul 2014 13:54:49 +0000 (+0200) Subject: evdev: Keep track of button/key press count per device X-Git-Tag: 0.6.0~28 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3a3d70a3a895140b91c58bc305c90ee3f9268346;p=platform%2Fupstream%2Flibinput.git evdev: Keep track of button/key press count per device Keep track of the number of times a given button or key is pressed on a device. For regular mouse devices or keyboard devices, such a count will never exceed 1, but counting button presses could help when button presses with the same code can originate from different sources. One could for example implement overlapping tap-drags with button presses by having them deal with their own life-time independently, sorting out when the user should receive button presses or not depending on the pressed count. Signed-off-by: Jonas Ådahl Reviewed-by: Peter Hutterer --- diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c index 92624666..f6235a0a 100644 --- a/src/evdev-mt-touchpad-buttons.c +++ b/src/evdev-mt-touchpad-buttons.c @@ -607,11 +607,12 @@ tp_post_clickfinger_buttons(struct tp_dispatch *tp, uint64_t time) state = LIBINPUT_BUTTON_STATE_RELEASED; } - if (button) - pointer_notify_button(&tp->device->base, - time, - button, - state); + if (button) { + evdev_pointer_notify_button(tp->device, + time, + button, + state); + } return 1; } @@ -633,10 +634,10 @@ tp_post_physical_buttons(struct tp_dispatch *tp, uint64_t time) else state = LIBINPUT_BUTTON_STATE_RELEASED; - pointer_notify_button(&tp->device->base, - time, - button, - state); + evdev_pointer_notify_button(tp->device, + time, + button, + state); } button++; @@ -708,11 +709,12 @@ tp_post_softbutton_buttons(struct tp_dispatch *tp, uint64_t time) tp->buttons.click_pending = false; - if (button) - pointer_notify_button(&tp->device->base, - time, - button, - state); + if (button) { + evdev_pointer_notify_button(tp->device, + time, + button, + state); + } return 1; } diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index 60085074..64801a81 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -113,10 +113,10 @@ tp_tap_notify(struct tp_dispatch *tp, return; } - pointer_notify_button(&tp->device->base, - time, - button, - state); + evdev_pointer_notify_button(tp->device, + time, + button, + state); } static void diff --git a/src/evdev.c b/src/evdev.c index bc0237fb..a605964b 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -59,6 +59,58 @@ is_key_down(struct evdev_device *device, int code) return long_bit_is_set(device->key_mask, code); } +static int +update_key_down_count(struct evdev_device *device, int code, int pressed) +{ + int key_count; + assert(code >= 0 && code < KEY_CNT); + + if (pressed) { + key_count = ++device->key_count[code]; + } else { + assert(device->key_count[code] > 0); + key_count = --device->key_count[code]; + } + + if (key_count > 32) { + log_bug_libinput(device->base.seat->libinput, + "Key count for %s reached abnormal values\n", + libevdev_event_code_get_name(EV_KEY, code)); + } + + return key_count; +} + +void +evdev_keyboard_notify_key(struct evdev_device *device, + uint32_t time, + int key, + enum libinput_key_state state) +{ + int down_count; + + down_count = update_key_down_count(device, key, state); + + if ((state == LIBINPUT_KEY_STATE_PRESSED && down_count == 1) || + (state == LIBINPUT_KEY_STATE_RELEASED && down_count == 0)) + keyboard_notify_key(&device->base, time, key, state); +} + +void +evdev_pointer_notify_button(struct evdev_device *device, + uint32_t time, + int button, + enum libinput_button_state state) +{ + int down_count; + + down_count = update_key_down_count(device, button, state); + + if ((state == LIBINPUT_BUTTON_STATE_PRESSED && down_count == 1) || + (state == LIBINPUT_BUTTON_STATE_RELEASED && down_count == 0)) + pointer_notify_button(&device->base, time, button, state); +} + void evdev_device_led_update(struct evdev_device *device, enum libinput_led leds) { @@ -341,16 +393,16 @@ evdev_process_key(struct evdev_device *device, case EVDEV_KEY_TYPE_NONE: break; case EVDEV_KEY_TYPE_KEY: - keyboard_notify_key( - &device->base, + evdev_keyboard_notify_key( + device, time, e->code, e->value ? LIBINPUT_KEY_STATE_PRESSED : LIBINPUT_KEY_STATE_RELEASED); break; case EVDEV_KEY_TYPE_BUTTON: - pointer_notify_button( - &device->base, + evdev_pointer_notify_button( + device, time, e->code, e->value ? LIBINPUT_BUTTON_STATE_PRESSED : diff --git a/src/evdev.h b/src/evdev.h index 68c1234a..f1ccdc29 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -99,6 +99,9 @@ struct evdev_device { /* Bitmask of pressed keys used to ignore initial release events from * the kernel. */ unsigned long key_mask[NLONGS(KEY_CNT)]; + /* Key counter used for multiplexing button events internally in + * libinput. */ + uint8_t key_count[KEY_CNT]; }; #define EVDEV_UNHANDLED_DEVICE ((struct evdev_device *) 1) @@ -177,6 +180,18 @@ evdev_device_transform_y(struct evdev_device *device, double y, uint32_t height); +void +evdev_keyboard_notify_key(struct evdev_device *device, + uint32_t time, + int key, + enum libinput_key_state state); + +void +evdev_pointer_notify_button(struct evdev_device *device, + uint32_t time, + int button, + enum libinput_button_state state); + void evdev_device_remove(struct evdev_device *device);