[PATCH] weston evdev: Filter double press, double release
Jonas Ådahl
jadahl at gmail.com
Sun Mar 17 02:18:27 PDT 2013
On Sat, Mar 16, 2013 at 1:24 PM, Martin Minarik
<minarik11 at student.fiit.stuba.sk> wrote:
> Track mouse button values. When the kernel drops, don't
> send notify again about a button, that's already pressed or released.
Hi Martin,
Not sure that the approach used in the patch is the proper fix to this
issue. It seems that what is done is avoid situations when a drop
would result in weird state transitions, but according to
documentation[0] what should be done is abort and ignore the
transaction and synchronize the appropriate states using ioctls. See
Documentation/input/event-codes.txt in the Linux kernel tarball:
* SYN_DROPPED:
- Used to indicate buffer overrun in the evdev client's event queue.
Client should ignore all events up to and including next SYN_REPORT
event and query the device (using EVIOCG* ioctls) to obtain its
current state.
Jonas
> ---
> src/evdev.c | 32 ++++++++++++++++++++++++++++++--
> src/evdev.h | 3 +++
> 2 files changed, 33 insertions(+), 2 deletions(-)
>
> diff --git a/src/evdev.c b/src/evdev.c
> index d2954b5..3740702 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -61,6 +61,20 @@ evdev_led_update(struct evdev_device *device, enum weston_led leds)
> }
>
> static inline void
> +evdev_process_syn(struct evdev_device *device, struct input_event *e, int time)
> +{
> + switch (e->code) {
> + case SYN_DROPPED:
> + device->button_sync_drop = ~0;
> + break;
> + case SYN_REPORT:
> + default:
> + device->pending_events |= EVDEV_SYN;
> + break;
> + }
> +}
> +
> +static inline void
> evdev_process_key(struct evdev_device *device, struct input_event *e, int time)
> {
> if (e->value == 2)
> @@ -75,12 +89,26 @@ evdev_process_key(struct evdev_device *device, struct input_event *e, int time)
> case BTN_FORWARD:
> case BTN_BACK:
> case BTN_TASK:
> + {
> + const uint32_t button_bit = (1 << (e->code - BTN_MOUSE));
> +
> + if (device->button_sync_drop & button_bit) {
> + const int last_value = !!(device->button_down_cache & button_bit);
> + if (last_value == e->value)
> + return;
> + device->button_sync_drop &= ~button_bit;
> + }
> notify_button(device->seat,
> time, e->code,
> e->value ? WL_POINTER_BUTTON_STATE_PRESSED :
> WL_POINTER_BUTTON_STATE_RELEASED);
> - break;
>
> + if (e->value)
> + device->button_down_cache |= button_bit;
> + else
> + device->button_down_cache &= ~button_bit;
> + }
> + break;
> default:
> notify_key(device->seat,
> time, e->code,
> @@ -308,7 +336,7 @@ fallback_process(struct evdev_dispatch *dispatch,
> evdev_process_key(device, event, time);
> break;
> case EV_SYN:
> - device->pending_events |= EVDEV_SYN;
> + evdev_process_syn(device, event, time);
> break;
> }
> }
> diff --git a/src/evdev.h b/src/evdev.h
> index eb5c868..3bdfc65 100644
> --- a/src/evdev.h
> +++ b/src/evdev.h
> @@ -77,6 +77,9 @@ struct evdev_device {
> enum evdev_device_capability caps;
>
> int is_mt;
> +
> + uint32_t button_down_cache;
> + uint32_t button_sync_drop;
> };
>
> /* copied from udev/extras/input_id/input_id.c */
> --
> 1.7.10.4
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
More information about the wayland-devel
mailing list