[gtk+/smooth-scrolling: 10/16] devicemanager, xi2: Implement smooth scrolling
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/smooth-scrolling: 10/16] devicemanager, xi2: Implement smooth scrolling
- Date: Sat, 18 Feb 2012 17:10:07 +0000 (UTC)
commit dd498d825fed94d749491bb0c57b24587e72e0f9
Author: Carlos Garnacho <carlosg gnome org>
Date: Tue Jan 24 00:49:52 2012 +0100
devicemanager,xi2: Implement smooth scrolling
XInput >= 2.1 allows for implementing smooth scrolling,
reporting the different scrolling axes as valuators.
Any change in those will be reported as GdkEventScroll
events with delta_x/y information.
the older kind of scroll events is still handled, and
emulated in devices able to provide smooth scrolling,
setting _gdk_event_set_pointer_emulated() in that case.
gdk/x11/gdkdevice-xi2.c | 99 ++++++++++++++++++++++++++++++++++++++
gdk/x11/gdkdevicemanager-xi2.c | 102 +++++++++++++++++++++++++++++++++++++++-
gdk/x11/gdkprivate-x11.h | 10 ++++
3 files changed, 209 insertions(+), 2 deletions(-)
---
diff --git a/gdk/x11/gdkdevice-xi2.c b/gdk/x11/gdkdevice-xi2.c
index 3b009e5..86f5785 100644
--- a/gdk/x11/gdkdevice-xi2.c
+++ b/gdk/x11/gdkdevice-xi2.c
@@ -35,11 +35,21 @@
#endif
+typedef struct _ScrollValuator ScrollValuator;
+
+struct _ScrollValuator
+{
+ guint n_valuator : 4;
+ guint direction : 4;
+ gdouble last_value;
+};
+
struct _GdkX11DeviceXI2
{
GdkDevice parent_instance;
gint device_id;
+ GArray *scroll_valuators;
};
struct _GdkX11DeviceXI2Class
@@ -51,6 +61,7 @@ G_DEFINE_TYPE (GdkX11DeviceXI2, gdk_x11_device_xi2, GDK_TYPE_DEVICE)
#ifdef XINPUT_2
+static void gdk_x11_device_xi2_finalize (GObject *object);
static void gdk_x11_device_xi2_get_property (GObject *object,
guint prop_id,
GValue *value,
@@ -112,6 +123,7 @@ gdk_x11_device_xi2_class_init (GdkX11DeviceXI2Class *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
+ object_class->finalize = gdk_x11_device_xi2_finalize;
object_class->get_property = gdk_x11_device_xi2_get_property;
object_class->set_property = gdk_x11_device_xi2_set_property;
@@ -136,6 +148,17 @@ gdk_x11_device_xi2_class_init (GdkX11DeviceXI2Class *klass)
static void
gdk_x11_device_xi2_init (GdkX11DeviceXI2 *device)
{
+ device->scroll_valuators = g_array_new (FALSE, FALSE, sizeof (ScrollValuator));
+}
+
+static void
+gdk_x11_device_xi2_finalize (GObject *object)
+{
+ GdkX11DeviceXI2 *device = GDK_X11_DEVICE_XI2 (object);
+
+ g_array_free (device->scroll_valuators, TRUE);
+
+ G_OBJECT_CLASS (gdk_x11_device_xi2_parent_class)->finalize (object);
}
static void
@@ -779,6 +802,82 @@ _gdk_x11_device_xi2_translate_state (XIModifierState *mods_state,
return state;
}
+void
+_gdk_x11_device_xi2_add_scroll_valuator (GdkX11DeviceXI2 *device,
+ guint n_valuator,
+ GdkScrollDirection direction,
+ gdouble current_value)
+{
+ ScrollValuator scroll;
+
+ g_return_if_fail (GDK_IS_X11_DEVICE_XI2 (device));
+ g_return_if_fail (n_valuator < gdk_device_get_n_axes (GDK_DEVICE (device)));
+
+ scroll.n_valuator = n_valuator;
+ scroll.direction = direction;
+ scroll.last_value = current_value;
+
+ g_array_append_val (device->scroll_valuators, scroll);
+}
+
+gboolean
+_gdk_x11_device_xi2_is_scroll_valuator (GdkX11DeviceXI2 *device,
+ guint n_valuator,
+ GdkScrollDirection *direction)
+{
+ guint i;
+
+ g_return_val_if_fail (GDK_IS_X11_DEVICE_XI2 (device), FALSE);
+ g_return_val_if_fail (n_valuator < gdk_device_get_n_axes (GDK_DEVICE (device)), FALSE);
+
+ for (i = 0; i < device->scroll_valuators->len; i++)
+ {
+ ScrollValuator *scroll;
+
+ scroll = &g_array_index (device->scroll_valuators, ScrollValuator, i);
+
+ if (scroll->n_valuator == n_valuator)
+ {
+ if (*direction)
+ *direction = scroll->direction;
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+gdouble
+_gdk_x11_device_xi2_get_scroll_delta (GdkX11DeviceXI2 *device,
+ guint n_valuator,
+ gdouble valuator_value)
+{
+ guint i;
+
+ g_return_val_if_fail (GDK_IS_X11_DEVICE_XI2 (device), 0);
+ g_return_val_if_fail (n_valuator < gdk_device_get_n_axes (GDK_DEVICE (device)), 0);
+
+ for (i = 0; i < device->scroll_valuators->len; i++)
+ {
+ ScrollValuator *scroll;
+
+ scroll = &g_array_index (device->scroll_valuators, ScrollValuator, i);
+
+ if (scroll->n_valuator == n_valuator)
+ {
+ gdouble delta;
+
+ delta = valuator_value - scroll->last_value;
+ scroll->last_value = valuator_value;
+
+ return delta;
+ }
+ }
+
+ return 0;
+}
+
gint
_gdk_x11_device_xi2_get_id (GdkX11DeviceXI2 *device)
{
diff --git a/gdk/x11/gdkdevicemanager-xi2.c b/gdk/x11/gdkdevicemanager-xi2.c
index b172964..d7ed206 100644
--- a/gdk/x11/gdkdevicemanager-xi2.c
+++ b/gdk/x11/gdkdevicemanager-xi2.c
@@ -243,6 +243,32 @@ translate_device_classes (GdkDisplay *display,
valuator_info->resolution);
}
break;
+#ifdef XINPUT_2_2
+ case XIScrollClass:
+ {
+ XIScrollClassInfo *scroll_info = (XIScrollClassInfo *) class_info;
+ XIValuatorClassInfo *scroll_valuator_info = NULL;
+ GdkScrollDirection direction;
+ gint j;
+
+ for (j = 0; j < n_classes; j++)
+ {
+ if (classes[j]->type == XIValuatorClass &&
+ ((XIValuatorClassInfo *) classes[j])->number == scroll_info->number)
+ scroll_valuator_info = (XIValuatorClassInfo *) classes[j];
+ }
+
+ if (scroll_info->scroll_type == XIScrollTypeVertical)
+ direction = GDK_SCROLL_DOWN;
+ else
+ direction = GDK_SCROLL_RIGHT;
+
+ _gdk_x11_device_xi2_add_scroll_valuator (GDK_X11_DEVICE_XI2 (device),
+ scroll_info->number,
+ direction,
+ scroll_valuator_info->value);
+ }
+#endif /* XINPUT_2_2 */
default:
/* Ignore */
break;
@@ -1009,6 +1035,47 @@ gdk_x11_device_manager_xi2_translate_core_event (GdkEventTranslator *translator,
}
static gboolean
+scroll_valuators_changed (GdkX11DeviceXI2 *device,
+ XIValuatorState *valuators,
+ gdouble *dx,
+ gdouble *dy)
+{
+ gdouble has_scroll_valuators = FALSE;
+ GdkScrollDirection direction;
+ guint n_axes, i, n_val;
+ gdouble *vals;
+
+ n_axes = gdk_device_get_n_axes (GDK_DEVICE (device));
+ vals = valuators->values;
+ *dx = *dy = 0;
+ n_val = 0;
+
+ for (i = 0; i < MIN (valuators->mask_len * 8, n_axes); i++)
+ {
+ if (!XIMaskIsSet (valuators->mask, i))
+ continue;
+
+ if (_gdk_x11_device_xi2_is_scroll_valuator (device, i, &direction))
+ {
+ gdouble delta;
+
+ has_scroll_valuators = TRUE;
+ delta = _gdk_x11_device_xi2_get_scroll_delta (device, i, vals[n_val]);
+
+ if (direction == GDK_SCROLL_UP ||
+ direction == GDK_SCROLL_DOWN)
+ *dy = delta;
+ else
+ *dx = delta;
+ }
+
+ n_val++;
+ }
+
+ return has_scroll_valuators;
+}
+
+static gboolean
gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
GdkDisplay *display,
GdkEvent *event,
@@ -1139,6 +1206,8 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
event->scroll.y = (gdouble) xev->event_y;
event->scroll.x_root = (gdouble) xev->root_x;
event->scroll.y_root = (gdouble) xev->root_y;
+ event->scroll.delta_x = 0;
+ event->scroll.delta_y = 0;
event->scroll.device = g_hash_table_lookup (device_manager->id_table,
GUINT_TO_POINTER (xev->deviceid));
@@ -1148,6 +1217,9 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
gdk_event_set_source_device (event, source_device);
event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
+
+ if (xev->flags & XIPointerEmulated)
+ _gdk_event_set_pointer_emulated (event, TRUE);
}
else
{
@@ -1230,6 +1302,34 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
{
XIDeviceEvent *xev = (XIDeviceEvent *) ev;
GdkDevice *source_device;
+ gdouble delta_x, delta_y;
+
+ source_device = g_hash_table_lookup (device_manager->id_table,
+ GUINT_TO_POINTER (xev->sourceid));
+
+ if (scroll_valuators_changed (GDK_X11_DEVICE_XI2 (source_device),
+ &xev->valuators, &delta_x, &delta_y))
+ {
+ event->scroll.type = GDK_SCROLL;
+ event->scroll.direction = GDK_SCROLL_SMOOTH;
+
+ event->scroll.window = window;
+ event->scroll.time = xev->time;
+ event->scroll.x = (gdouble) xev->event_x;
+ event->scroll.y = (gdouble) xev->event_y;
+ event->scroll.x_root = (gdouble) xev->root_x;
+ event->scroll.y_root = (gdouble) xev->root_y;
+ event->scroll.delta_x = delta_x;
+ event->scroll.delta_y = delta_y;
+
+ event->scroll.device = g_hash_table_lookup (device_manager->id_table,
+ GUINT_TO_POINTER (xev->deviceid));
+
+ gdk_event_set_source_device (event, source_device);
+
+ event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
+ break;
+ }
if (ev->evtype == XI_Motion)
{
@@ -1255,8 +1355,6 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
event->motion.device = g_hash_table_lookup (device_manager->id_table,
GINT_TO_POINTER (xev->deviceid));
- source_device = g_hash_table_lookup (device_manager->id_table,
- GUINT_TO_POINTER (xev->sourceid));
gdk_event_set_source_device (event, source_device);
event->motion.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h
index 803dad7..d6b39b8 100644
--- a/gdk/x11/gdkprivate-x11.h
+++ b/gdk/x11/gdkprivate-x11.h
@@ -257,6 +257,16 @@ gint _gdk_x11_device_xi2_get_id (GdkX11DeviceXI2 *device);
GdkDevice * _gdk_x11_device_manager_xi2_lookup (GdkX11DeviceManagerXI2 *device_manager_xi2,
gint device_id);
+void _gdk_x11_device_xi2_add_scroll_valuator (GdkX11DeviceXI2 *device,
+ guint n_valuator,
+ GdkScrollDirection direction,
+ gdouble current_value);
+gboolean _gdk_x11_device_xi2_is_scroll_valuator (GdkX11DeviceXI2 *device,
+ guint n_valuator,
+ GdkScrollDirection *direction);
+gdouble _gdk_x11_device_xi2_get_scroll_delta (GdkX11DeviceXI2 *device,
+ guint n_valuator,
+ gdouble valuator_value);
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]