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 <jadahl@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Jonas Ådahl 2014-07-27 15:54:49 +02:00
parent c8017595fc
commit 3a3d70a3a8
4 changed files with 91 additions and 22 deletions

View file

@ -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;
}

View file

@ -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

View file

@ -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 :

View file

@ -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);