[clutter] x11: Add support for scroll valuators on XInput2.2
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [clutter] x11: Add support for scroll valuators on XInput2.2
- Date: Mon, 19 Mar 2012 14:49:05 +0000 (UTC)
commit 676a31743993915437da419551d7c5193f0b9f43
Author: Emmanuele Bassi <ebassi linux intel com>
Date: Mon Mar 19 12:16:53 2012 +0000
x11: Add support for scroll valuators on XInput2.2
clutter/clutter-device-manager-private.h | 23 ++++++
clutter/clutter-input-device.c | 96 ++++++++++++++++++++++++++
clutter/x11/clutter-backend-x11.c | 5 ++
clutter/x11/clutter-device-manager-xi2.c | 111 +++++++++++++++++++++++++++++-
4 files changed, 233 insertions(+), 2 deletions(-)
---
diff --git a/clutter/clutter-device-manager-private.h b/clutter/clutter-device-manager-private.h
index df9b8df..de89ecd 100644
--- a/clutter/clutter-device-manager-private.h
+++ b/clutter/clutter-device-manager-private.h
@@ -50,6 +50,16 @@ typedef struct _ClutterKeyInfo
ClutterModifierType modifiers;
} ClutterKeyInfo;
+typedef struct _ClutterScrollInfo
+{
+ guint axis_id;
+ ClutterScrollDirection direction;
+ gdouble increment;
+
+ gdouble last_value;
+ guint last_value_valid : 1;
+} ClutterScrollInfo;
+
struct _ClutterInputDevice
{
GObject parent_instance;
@@ -102,6 +112,8 @@ struct _ClutterInputDevice
guint n_keys;
GArray *keys;
+ GArray *scroll_info;
+
guint has_cursor : 1;
guint is_enabled : 1;
};
@@ -170,6 +182,17 @@ gboolean _clutter_input_device_translate_axis (ClutterInputDev
gdouble value,
gdouble *axis_value);
+void _clutter_input_device_add_scroll_info (ClutterInputDevice *device,
+ guint index_,
+ ClutterScrollDirection direction,
+ gdouble increment);
+void _clutter_input_device_reset_scroll_info (ClutterInputDevice *device);
+gboolean _clutter_input_device_get_scroll_delta (ClutterInputDevice *device,
+ guint index_,
+ gdouble value,
+ ClutterScrollDirection *direction_p,
+ gdouble *delta_p);
+
G_END_DECLS
#endif /* __CLUTTER_DEVICE_MANAGER_PRIVATE_H__ */
diff --git a/clutter/clutter-input-device.c b/clutter/clutter-input-device.c
index 41196ee..4e3554b 100644
--- a/clutter/clutter-input-device.c
+++ b/clutter/clutter-input-device.c
@@ -1444,3 +1444,99 @@ clutter_input_device_keycode_to_evdev (ClutterInputDevice *device,
hardware_keycode,
evdev_keycode);
}
+
+void
+_clutter_input_device_add_scroll_info (ClutterInputDevice *device,
+ guint index_,
+ ClutterScrollDirection direction,
+ gdouble increment)
+{
+ ClutterScrollInfo info;
+
+ g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
+ g_return_if_fail (index_ < clutter_input_device_get_n_axes (device));
+
+ info.axis_id = index_;
+ info.direction = direction;
+ info.increment = increment;
+ info.last_value_valid = FALSE;
+
+ if (device->scroll_info == NULL)
+ {
+ device->scroll_info = g_array_new (FALSE,
+ FALSE,
+ sizeof (ClutterScrollInfo));
+ }
+
+ g_array_append_val (device->scroll_info, info);
+}
+
+gboolean
+_clutter_input_device_get_scroll_delta (ClutterInputDevice *device,
+ guint index_,
+ gdouble value,
+ ClutterScrollDirection *direction_p,
+ gdouble *delta_p)
+{
+ guint i;
+
+ g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
+ g_return_val_if_fail (index_ < clutter_input_device_get_n_axes (device), FALSE);
+
+ if (device->scroll_info == NULL)
+ return FALSE;
+
+ for (i = 0; i < device->scroll_info->len; i++)
+ {
+ ClutterScrollInfo *info = &g_array_index (device->scroll_info,
+ ClutterScrollInfo,
+ i);
+
+ if (info->axis_id == index_)
+ {
+ if (direction_p != NULL)
+ *direction_p = info->direction;
+
+ if (delta_p != NULL)
+ *delta_p = 0.0;
+
+ if (info->last_value_valid)
+ {
+ if (delta_p != NULL)
+ {
+ *delta_p = (value - info->last_value)
+ / info->increment;
+ }
+
+ info->last_value = value;
+ }
+ else
+ {
+ info->last_value = value;
+ info->last_value_valid = TRUE;
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+void
+_clutter_input_device_reset_scroll_info (ClutterInputDevice *device)
+{
+ guint i;
+
+ if (device->scroll_info == NULL)
+ return;
+
+ for (i = 0; i < device->scroll_info->len; i++)
+ {
+ ClutterScrollInfo *info = &g_array_index (device->scroll_info,
+ ClutterScrollInfo,
+ i);
+
+ info->last_value_valid = FALSE;
+ }
+}
diff --git a/clutter/x11/clutter-backend-x11.c b/clutter/x11/clutter-backend-x11.c
index f781767..7cd6a78 100644
--- a/clutter/x11/clutter-backend-x11.c
+++ b/clutter/x11/clutter-backend-x11.c
@@ -239,7 +239,12 @@ clutter_backend_x11_create_device_manager (ClutterBackendX11 *backend_x11)
{
#ifdef HAVE_XINPUT_2
int major = 2;
+
+#ifdef HAVE_XINPUT_2_2
+ int minor = 2;
+#else
int minor = 0;
+#endif /* HAVE_XINPUT_2_2 */
if (XIQueryVersion (backend_x11->xdpy, &major, &minor) != BadRequest)
{
diff --git a/clutter/x11/clutter-device-manager-xi2.c b/clutter/x11/clutter-device-manager-xi2.c
index 28e0ba2..bdbe536 100644
--- a/clutter/x11/clutter-device-manager-xi2.c
+++ b/clutter/x11/clutter-device-manager-xi2.c
@@ -154,6 +154,32 @@ translate_device_classes (Display *xdisplay,
(XIValuatorClassInfo *) class_info);
break;
+#ifdef XINPUT_2_2
+ case XIScrollClass:
+ {
+ XIScrollClassInfo *scroll_info = (XIScrollClassInfo *) class_info;
+ ClutterScrollDirection direction;
+
+ if (scroll_info->scroll_type == XIScrollTypeVertical)
+ direction = CLUTTER_SCROLL_DOWN;
+ else
+ direction = CLUTTER_SCROLL_RIGHT;
+
+ CLUTTER_NOTE (BACKEND, "Scroll valuator %d: %s, increment: %f",
+ scroll_info->number,
+ scroll_info->scroll_type == XIScrollTypeVertical
+ ? "vertical"
+ : "horizontal",
+ scroll_info->increment);
+
+ _clutter_input_device_add_scroll_info (device,
+ scroll_info->number,
+ direction,
+ scroll_info->increment);
+ }
+ break;
+#endif /* XINPUT_2_2 */
+
default:
break;
}
@@ -541,6 +567,51 @@ translate_axes (ClutterInputDevice *device,
return retval;
}
+static gdouble
+scroll_valuators_changed (ClutterInputDevice *device,
+ XIValuatorState *valuators,
+ gdouble *dx_p,
+ gdouble *dy_p)
+{
+ gboolean retval = FALSE;
+ guint n_axes, n_val, i;
+ double *values;
+
+ n_axes = clutter_input_device_get_n_axes (device);
+ values = valuators->values;
+
+ *dx_p = *dy_p = 0.0;
+
+ n_val = 0;
+
+ for (i = 0; i < MIN (valuators->mask_len * 8, n_axes); i++)
+ {
+ ClutterScrollDirection direction;
+ gdouble delta;
+
+ if (!XIMaskIsSet (valuators->mask, i))
+ continue;
+
+ if (_clutter_input_device_get_scroll_delta (device, i,
+ values[n_val],
+ &direction,
+ &delta))
+ {
+ retval = TRUE;
+
+ if (direction == CLUTTER_SCROLL_UP ||
+ direction == CLUTTER_SCROLL_DOWN)
+ *dx_p = delta;
+ else
+ *dy_p = delta;
+ }
+
+ n_val += 1;
+ }
+
+ return retval;
+}
+
static ClutterTranslateReturn
clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
gpointer native,
@@ -793,6 +864,44 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
case XI_Motion:
{
XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
+ gdouble delta_x, delta_y;
+
+ source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (xev->sourceid));
+
+ if (scroll_valuators_changed (source_device,
+ &xev->valuators,
+ &delta_x, &delta_y))
+ {
+ event->scroll.type = event->type = CLUTTER_SCROLL;
+ event->scroll.direction = CLUTTER_SCROLL_SMOOTH;
+
+ event->scroll.stage = stage;
+ event->scroll.time = xev->time;
+ event->scroll.x = xev->event_x;
+ event->scroll.y = xev->event_y;
+ event->scroll.modifier_state =
+ _clutter_input_device_xi2_translate_state (&xev->mods,
+ &xev->buttons);
+
+ clutter_event_set_scroll_delta (event, delta_x, delta_y);
+ clutter_event_set_source_device (event, source_device);
+
+ device = g_hash_table_lookup (manager_xi2->devices_by_id,
+ GINT_TO_POINTER (xev->deviceid));
+ clutter_event_set_device (event, device);
+
+ CLUTTER_NOTE (EVENT,
+ "smooth scroll: win:0x%x device:%s (x:%.2f, y:%.2f, delta:%f, %f)",
+ (unsigned int) stage_x11->xwin,
+ event->scroll.device->device_name,
+ event->scroll.x,
+ event->scroll.y,
+ delta_x, delta_y);
+
+ retval = CLUTTER_TRANSLATE_QUEUE;
+ break;
+ }
event->motion.type = event->type = CLUTTER_MOTION;
@@ -805,8 +914,6 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
_clutter_input_device_xi2_translate_state (&xev->mods,
&xev->buttons);
- source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
- GINT_TO_POINTER (xev->sourceid));
clutter_event_set_source_device (event, source_device);
device = g_hash_table_lookup (manager_xi2->devices_by_id,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]