From d893adb290c3740ae57b761d9e57a2f4d79e6c7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 7 Sep 2016 17:38:33 +0800 Subject: [PATCH] clutter: Compress instead of discard motion events Clutter discards any motion event if next event happens to also be a motion event. This is problematic when the motion event carries relative motion deltas, since the information about them is completely lost. Until we have moved away made the stage stop discarding motion events, lets work around the issue by compressing them, effectively adding multiple relative motion deltas together, would one be discarded. https://bugzilla.gnome.org/show_bug.cgi?id=771049 --- .../clutter/clutter-device-manager-private.h | 4 +++ clutter/clutter/clutter-device-manager.c | 17 ++++++++++++ clutter/clutter/clutter-device-manager.h | 5 +++- clutter/clutter/clutter-stage.c | 10 +++++++ .../evdev/clutter-device-manager-evdev.c | 26 +++++++++++++++++++ 5 files changed, 61 insertions(+), 1 deletion(-) diff --git a/clutter/clutter/clutter-device-manager-private.h b/clutter/clutter/clutter-device-manager-private.h index 7efe76857..108e8c5f4 100644 --- a/clutter/clutter/clutter-device-manager-private.h +++ b/clutter/clutter/clutter-device-manager-private.h @@ -188,6 +188,10 @@ void _clutter_device_manager_select_stage_events (ClutterDeviceMa ClutterStage *stage); ClutterBackend *_clutter_device_manager_get_backend (ClutterDeviceManager *device_manager); +void _clutter_device_manager_compress_motion (ClutterDeviceManager *device_manger, + ClutterEvent *event, + const ClutterEvent *to_discard); + /* input device */ gboolean _clutter_input_device_has_sequence (ClutterInputDevice *device, ClutterEventSequence *sequence); diff --git a/clutter/clutter/clutter-device-manager.c b/clutter/clutter/clutter-device-manager.c index c30bc8eef..f9222e765 100644 --- a/clutter/clutter/clutter-device-manager.c +++ b/clutter/clutter/clutter-device-manager.c @@ -458,3 +458,20 @@ clutter_device_manager_create_virtual_device (ClutterDeviceManager *device_man return manager_class->create_virtual_device (device_manager, device_type); } + +void +_clutter_device_manager_compress_motion (ClutterDeviceManager *device_manager, + ClutterEvent *event, + const ClutterEvent *to_discard) +{ + ClutterDeviceManagerClass *manager_class; + + g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager)); + + + manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager); + if (!manager_class->compress_motion) + return; + + manager_class->compress_motion (device_manager, event, to_discard); +} diff --git a/clutter/clutter/clutter-device-manager.h b/clutter/clutter/clutter-device-manager.h index da6bd2cb2..926d3b528 100644 --- a/clutter/clutter/clutter-device-manager.h +++ b/clutter/clutter/clutter-device-manager.h @@ -85,9 +85,12 @@ struct _ClutterDeviceManagerClass ClutterStage *stage); ClutterVirtualInputDevice *(* create_virtual_device) (ClutterDeviceManager *manager, ClutterInputDeviceType device_type); + void (* compress_motion) (ClutterDeviceManager *device_manger, + ClutterEvent *event, + const ClutterEvent *to_discard); /* padding */ - gpointer _padding[7]; + gpointer _padding[6]; }; CLUTTER_AVAILABLE_IN_1_2 diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index 85cb343eb..1f0c3f8c0 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -998,6 +998,16 @@ _clutter_stage_process_queued_events (ClutterStage *stage) "Omitting motion event at %d, %d", (int) event->motion.x, (int) event->motion.y); + + if (next_event->type == CLUTTER_MOTION) + { + ClutterDeviceManager *device_manager = + clutter_device_manager_get_default (); + + _clutter_device_manager_compress_motion (device_manager, + next_event, event); + } + goto next_event; } else if (event->type == CLUTTER_TOUCH_UPDATE && diff --git a/clutter/clutter/evdev/clutter-device-manager-evdev.c b/clutter/clutter/evdev/clutter-device-manager-evdev.c index 4e52ecf80..b42b57665 100644 --- a/clutter/clutter/evdev/clutter-device-manager-evdev.c +++ b/clutter/clutter/evdev/clutter-device-manager-evdev.c @@ -1970,6 +1970,31 @@ clutter_device_manager_evdev_create_virtual_device (ClutterDeviceManager *manag NULL); } +static void +clutter_device_manager_evdev_compress_motion (ClutterDeviceManager *device_manger, + ClutterEvent *event, + const ClutterEvent *to_discard) +{ + double dx, dy; + double dx_unaccel, dy_unaccel; + double dst_dx = 0.0, dst_dy = 0.0; + double dst_dx_unaccel = 0.0, dst_dy_unaccel = 0.0; + + if (!clutter_evdev_event_get_relative_motion (to_discard, + &dx, &dy, + &dx_unaccel, &dy_unaccel)) + return; + + clutter_evdev_event_get_relative_motion (event, + &dst_dx, &dst_dy, + &dst_dx_unaccel, &dst_dy_unaccel); + _clutter_evdev_event_set_relative_motion (event, + dx + dst_dx, + dy + dst_dy, + dx_unaccel + dst_dx_unaccel, + dy_unaccel + dst_dy_unaccel); +} + /* * GObject implementation */ @@ -2110,6 +2135,7 @@ clutter_device_manager_evdev_class_init (ClutterDeviceManagerEvdevClass *klass) manager_class->get_core_device = clutter_device_manager_evdev_get_core_device; manager_class->get_device = clutter_device_manager_evdev_get_device; manager_class->create_virtual_device = clutter_device_manager_evdev_create_virtual_device; + manager_class->compress_motion = clutter_device_manager_evdev_compress_motion; } static void