[gtk+/xi2] Rework axes translation.



commit 4a1f3e0b8c37d70474a3e65932c6ce0d2bf2c20b
Author: Carlos Garnacho <carlos gnome org>
Date:   Fri Oct 2 17:51:13 2009 +0200

    Rework axes translation.
    
    Axis translation has now been splitted into several utility functions in
    gdkdevice.c, both XI and XI2 implementations have been reworked to use
    these functions wherever appropriate.

 gdk/gdkdevice.c                |  252 ++++++++++++++++++++++++++--------------
 gdk/gdkdeviceprivate.h         |   29 ++++--
 gdk/x11/gdkdevice-xi.c         |  122 +++++++++++++------
 gdk/x11/gdkdevice-xi.h         |   11 ++-
 gdk/x11/gdkdevicemanager-xi.c  |   65 +++--------
 gdk/x11/gdkdevicemanager-xi2.c |   36 ++++--
 6 files changed, 319 insertions(+), 196 deletions(-)
---
diff --git a/gdk/gdkdevice.c b/gdk/gdkdevice.c
index 8a4182f..03ea87f 100644
--- a/gdk/gdkdevice.c
+++ b/gdk/gdkdevice.c
@@ -775,19 +775,36 @@ find_axis_info (GArray     *array,
   return NULL;
 }
 
+GdkAxisUse
+_gdk_device_get_axis_use (GdkDevice *device,
+                          guint      index)
+{
+  GdkDevicePrivate *priv;
+  GdkAxisInfo info;
+
+  priv = GDK_DEVICE_GET_PRIVATE (device);
+
+  info = g_array_index (priv->axes, GdkAxisInfo, index);
+  return info.use;
+}
+
 gboolean
-_gdk_device_translate_axis (GdkDevice *device,
-                            gdouble    window_width,
-                            gdouble    window_height,
-                            gdouble    window_x,
-                            gdouble    window_y,
-                            guint      index,
-                            gdouble    value,
-                            gdouble   *axis_value)
+_gdk_device_translate_window_coord (GdkDevice *device,
+                                    GdkWindow *window,
+                                    guint      index,
+                                    gdouble    value,
+                                    gdouble   *axis_value)
 {
   GdkDevicePrivate *priv;
   GdkAxisInfo axis_info;
-  gdouble out = 0;
+  GdkAxisInfo *axis_info_x, *axis_info_y;
+  gdouble device_width, device_height;
+  gdouble x_offset, y_offset;
+  gdouble x_scale, y_scale;
+  gdouble x_resolution, y_resolution;
+  gdouble device_aspect;
+  gint window_width, window_height;
+  GdkWindowObject *window_private;
 
   priv = GDK_DEVICE_GET_PRIVATE (device);
 
@@ -796,96 +813,153 @@ _gdk_device_translate_axis (GdkDevice *device,
 
   axis_info = g_array_index (priv->axes, GdkAxisInfo, index);
 
-  if (axis_info.use == GDK_AXIS_X ||
-      axis_info.use == GDK_AXIS_Y)
+  if (axis_info.use != GDK_AXIS_X &&
+      axis_info.use != GDK_AXIS_Y)
+    return FALSE;
+
+  if (axis_info.use == GDK_AXIS_X)
+    {
+      axis_info_x = &axis_info;
+      axis_info_y = find_axis_info (priv->axes, GDK_AXIS_Y);
+    }
+  else
+    {
+      axis_info_x = find_axis_info (priv->axes, GDK_AXIS_X);
+      axis_info_y = &axis_info;
+    }
+
+  device_width = axis_info_x->max_value - axis_info_x->min_value;
+  device_height = axis_info_y->max_value - axis_info_y->min_value;
+
+  window_private = (GdkWindowObject *) window;
+  gdk_drawable_get_size (window, &window_width, &window_height);
+
+  x_resolution = axis_info_x->resolution;
+  y_resolution = axis_info_y->resolution;
+
+  /*
+   * Some drivers incorrectly report the resolution of the device
+   * as zero (in partiular linuxwacom < 0.5.3 with usb tablets).
+   * This causes the device_aspect to become NaN and totally
+   * breaks windowed mode.  If this is the case, the best we can
+   * do is to assume the resolution is non-zero is equal in both
+   * directions (which is true for many devices).  The absolute
+   * value of the resolution doesn't matter since we only use the
+   * ratio.
+   */
+  if (x_resolution == 0 || y_resolution == 0)
+    {
+      x_resolution = 1;
+      y_resolution = 1;
+    }
+
+  device_aspect = (device_height * y_resolution) /
+    (device_width * x_resolution);
+
+  if (device_aspect * window_width >= window_height)
+    {
+      /* device taller than window */
+      x_scale = window_width / device_width;
+      y_scale = (x_scale * x_resolution) / y_resolution;
+
+      x_offset = 0;
+      y_offset = - (device_height * y_scale - window_height) / 2;
+    }
+  else
     {
-      GdkAxisInfo *axis_info_x, *axis_info_y;
-      gdouble device_width, device_height;
-      gdouble x_offset, y_offset;
-      gdouble x_scale, y_scale;
+      /* window taller than device */
+      y_scale = window_height / device_height;
+      x_scale = (y_scale * y_resolution) / x_resolution;
 
+      y_offset = 0;
+      x_offset = - (device_width * x_scale - window_width) / 2;
+    }
+
+  if (axis_value)
+    {
       if (axis_info.use == GDK_AXIS_X)
-        {
-          axis_info_x = &axis_info;
-          axis_info_y = find_axis_info (priv->axes, GDK_AXIS_Y);
-        }
+        *axis_value = x_offset + x_scale * (value - axis_info.min_value);
       else
-        {
-          axis_info_x = find_axis_info (priv->axes, GDK_AXIS_X);
-          axis_info_y = &axis_info;
-        }
-
-      device_width = axis_info_x->max_value - axis_info_x->min_value;
-      device_height = axis_info_y->max_value - axis_info_y->min_value;
-
-      if (device->mode == GDK_MODE_SCREEN)
-        {
-          if (axis_info.use == GDK_AXIS_X)
-            out = window_x;
-          else
-            out = window_y;
-        }
-      else /* GDK_MODE_WINDOW */
-        {
-          gdouble x_resolution, y_resolution, device_aspect;
-
-          x_resolution = axis_info_x->resolution;
-          y_resolution = axis_info_y->resolution;
-
-          /*
-           * Some drivers incorrectly report the resolution of the device
-           * as zero (in partiular linuxwacom < 0.5.3 with usb tablets).
-           * This causes the device_aspect to become NaN and totally
-           * breaks windowed mode.  If this is the case, the best we can
-           * do is to assume the resolution is non-zero is equal in both
-           * directions (which is true for many devices).  The absolute
-           * value of the resolution doesn't matter since we only use the
-           * ratio.
-           */
-          if (x_resolution == 0 || y_resolution == 0)
-            {
-              x_resolution = 1;
-              y_resolution = 1;
-            }
-
-          device_aspect = (device_height * y_resolution) /
-            (device_width * x_resolution);
-
-          if (device_aspect * window_width >= window_height)
-            {
-              /* device taller than window */
-              x_scale = window_width / device_width;
-              y_scale = (x_scale * x_resolution) / y_resolution;
-
-              x_offset = 0;
-              y_offset = - (device_height * y_scale - window_height) / 2;
-            }
-          else
-            {
-              /* window taller than device */
-              y_scale = window_height / device_height;
-              x_scale = (y_scale * y_resolution) / x_resolution;
-
-              y_offset = 0;
-              x_offset = - (device_width * x_scale - window_width) / 2;
-            }
-
-          if (axis_info.use == GDK_AXIS_X)
-            out = x_offset + x_scale * (value - axis_info.min_value);
-          else
-            out = y_offset + y_scale * (value - axis_info.min_value);
-        }
+        *axis_value = y_offset + y_scale * (value - axis_info.min_value);
+    }
+
+  return TRUE;
+}
+
+gboolean
+_gdk_device_translate_screen_coord (GdkDevice *device,
+                                    GdkWindow *window,
+                                    gint       window_root_x,
+                                    gint       window_root_y,
+                                    guint      index,
+                                    gdouble    value,
+                                    gdouble   *axis_value)
+{
+  GdkDevicePrivate *priv;
+  GdkAxisInfo axis_info;
+  gdouble axis_width, scale, offset;
+  GdkWindowObject *window_private;
+
+  if (device->mode != GDK_MODE_SCREEN)
+    return FALSE;
+
+  priv = GDK_DEVICE_GET_PRIVATE (device);
+
+  if (index >= priv->axes->len)
+    return FALSE;
+
+  axis_info = g_array_index (priv->axes, GdkAxisInfo, index);
+
+  if (axis_info.use != GDK_AXIS_X &&
+      axis_info.use != GDK_AXIS_Y)
+    return FALSE;
+
+  axis_width = axis_info.max_value - axis_info.min_value;
+  window_private = (GdkWindowObject *) window;
+
+  if (axis_info.use == GDK_AXIS_X)
+    {
+      scale = gdk_screen_get_width (gdk_drawable_get_screen (window)) / axis_width;
+      offset = - window_root_x - window_private->abs_x;
     }
   else
     {
-      gdouble axis_width;
-
-      axis_width = axis_info.max_value - axis_info.min_value;
-      out = (axis_info.max_axis * (value - axis_info.min_value) +
-             axis_info.min_axis * (axis_info.max_value - value)) / axis_width;
+      scale = gdk_screen_get_height (gdk_drawable_get_screen (window)) / axis_width;
+      offset = - window_root_y - window_private->abs_y;
     }
 
   if (axis_value)
+    *axis_value = offset + scale * (value - axis_info.min_value);
+
+  return TRUE;
+}
+
+gboolean
+_gdk_device_translate_axis (GdkDevice *device,
+                            guint      index,
+                            gdouble    value,
+                            gdouble   *axis_value)
+{
+  GdkDevicePrivate *priv;
+  GdkAxisInfo axis_info;
+  gdouble axis_width, out;
+
+  priv = GDK_DEVICE_GET_PRIVATE (device);
+
+  if (index >= priv->axes->len)
+    return FALSE;
+
+  axis_info = g_array_index (priv->axes, GdkAxisInfo, index);
+
+  if (axis_info.use == GDK_AXIS_X ||
+      axis_info.use == GDK_AXIS_Y)
+    return FALSE;
+
+  axis_width = axis_info.max_value - axis_info.min_value;
+  out = (axis_info.max_axis * (value - axis_info.min_value) +
+         axis_info.min_axis * (axis_info.max_value - value)) / axis_width;
+
+  if (axis_value)
     *axis_value = out;
 
   return TRUE;
diff --git a/gdk/gdkdeviceprivate.h b/gdk/gdkdeviceprivate.h
index ac6fb69..0fb286f 100644
--- a/gdk/gdkdeviceprivate.h
+++ b/gdk/gdkdeviceprivate.h
@@ -98,14 +98,27 @@ guint _gdk_device_add_axis   (GdkDevice   *device,
                               gdouble      max_value,
                               gdouble      resolution);
 
-gboolean _gdk_device_translate_axis (GdkDevice *device,
-                                     gdouble    window_width,
-                                     gdouble    window_height,
-                                     gdouble    window_x,
-                                     gdouble    window_y,
-                                     guint      index,
-                                     gdouble    value,
-                                     gdouble   *axis_value);
+GdkAxisUse _gdk_device_get_axis_use (GdkDevice *device,
+                                     guint      index);
+
+gboolean   _gdk_device_translate_window_coord (GdkDevice *device,
+                                               GdkWindow *window,
+                                               guint      index,
+                                               gdouble    value,
+                                               gdouble   *axis_value);
+
+gboolean   _gdk_device_translate_screen_coord (GdkDevice *device,
+                                               GdkWindow *window,
+                                               gint       window_root_x,
+                                               gint       window_root_y,
+                                               guint      index,
+                                               gdouble    value,
+                                               gdouble   *axis_value);
+
+gboolean   _gdk_device_translate_axis         (GdkDevice *device,
+                                               guint      index,
+                                               gdouble    value,
+                                               gdouble   *axis_value);
 
 void _gdk_input_check_extension_events (GdkDevice *device);
 
diff --git a/gdk/x11/gdkdevice-xi.c b/gdk/x11/gdkdevice-xi.c
index b4df4bd..8f76a2e 100644
--- a/gdk/x11/gdkdevice-xi.c
+++ b/gdk/x11/gdkdevice-xi.c
@@ -220,14 +220,10 @@ gdk_device_xi_get_history (GdkDevice      *device,
   gint n_events_return;
   gint mode_return;
   gint axis_count_return;
-  gint n_axes, i, j;
-  gint width, height;
+  gint i;
 
   device_xi = GDK_DEVICE_XI (device);
   impl_window = _gdk_window_get_impl_window (window);
-  g_object_get (device, "n-axes", &n_axes, NULL);
-
-  gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
 
   device_coords = XGetDeviceMotionEvents (GDK_WINDOW_XDISPLAY (impl_window),
 					  device_xi->xdevice,
@@ -245,16 +241,10 @@ gdk_device_xi_get_history (GdkDevice      *device,
   for (i = 0; i < *n_events; i++)
     {
       coords[i]->time = device_coords[i].time;
-
-      for (j = 0; j < n_axes; j++)
-        {
-          _gdk_device_translate_axis (device,
-                                      width, height,
-                                      0, 0,
-                                      j,
-                                      (gdouble) device_coords[i].data[j],
-                                      &coords[i]->axes[j]);
-        }
+      gdk_device_xi_translate_axes (device, window,
+                                    device_coords[i].data,
+                                    coords[i]->axes,
+                                    NULL, NULL);
     }
 
   XFreeDeviceMotionEvents (device_coords);
@@ -273,13 +263,12 @@ gdk_device_xi_get_state (GdkDevice       *device,
   GdkDeviceXI *device_xi;
   XDeviceState *state;
   XInputClass *input_class;
-  gint i, j;
+  gint i;
 
   if (mask)
     gdk_window_get_pointer (window, NULL, NULL, mask);
 
   device_xi = GDK_DEVICE_XI (device);
-
   state = XQueryDeviceState (GDK_WINDOW_XDISPLAY (window),
                              device_xi->xdevice);
   input_class = state->data;
@@ -290,21 +279,9 @@ gdk_device_xi_get_state (GdkDevice       *device,
         {
         case ValuatorClass:
           if (axes)
-            {
-              gint width, height;
-
-              gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
-
-              for (j = 0; j < device->num_axes; j++)
-                {
-                  _gdk_device_translate_axis (device,
-                                              width, height,
-                                              0, 0,
-                                              j,
-                                              (gdouble) ((XValuatorState *) input_class)->valuators[j],
-                                              &axes[j]);
-                }
-            }
+            gdk_device_xi_translate_axes (device, window,
+                                          ((XValuatorState *) input_class)->valuators,
+                                          axes, NULL, NULL);
           break;
 
         case ButtonClass:
@@ -554,17 +531,86 @@ gdk_device_xi_select_window_events (GdkDevice    *device,
 }
 
 void
-gdk_device_xi_update_window_info (GdkWindow *window,
-                                  gdouble    root_x,
-                                  gdouble    root_y)
+gdk_device_xi_update_window_info (GdkWindow *window)
 {
   GdkWindowInputInfo *info;
+  gint root_x, root_y;
 
   info = g_object_get_qdata (G_OBJECT (window),
                              quark_window_input_info);
-  if (info)
+
+  if (!info)
+    return;
+
+  gdk_window_get_origin (window, &root_x, &root_y);
+  info->root_x = (gdouble) root_x;
+  info->root_y = (gdouble) root_y;
+}
+
+static gboolean
+gdk_device_xi_get_window_info (GdkWindow *window,
+                               gdouble   *root_x,
+                               gdouble   *root_y)
+{
+  GdkWindowInputInfo *info;
+
+  info = g_object_get_qdata (G_OBJECT (window),
+                             quark_window_input_info);
+
+  if (!info)
+    return FALSE;
+
+  *root_x = info->root_x;
+  *root_y = info->root_y;
+
+  return TRUE;
+}
+
+void
+gdk_device_xi_translate_axes (GdkDevice *device,
+                              GdkWindow *window,
+                              gint      *axis_data,
+                              gdouble   *axes,
+                              gdouble   *x,
+                              gdouble   *y)
+{
+  GdkWindow *impl_window;
+  gdouble root_x, root_y;
+  gint i;
+
+  impl_window = _gdk_window_get_impl_window (window);
+
+  if (!gdk_device_xi_get_window_info (impl_window, &root_x, &root_y))
+    return;
+
+  for (i = 0; i < device->num_axes; i++)
     {
-      info->root_x = root_x;
-      info->root_y = root_y;
+      GdkAxisUse use;
+
+      use = _gdk_device_get_axis_use (device, i);
+
+      switch (use)
+        {
+        case GDK_AXIS_X:
+        case GDK_AXIS_Y:
+          if (device->mode == GDK_MODE_WINDOW)
+            _gdk_device_translate_window_coord (device, window,
+                                                i, axis_data[i],
+                                                &axes[i]);
+          else
+            _gdk_device_translate_screen_coord (device, window,
+                                                root_x, root_y,
+                                                i, axis_data[i],
+                                                &axes[i]);
+          if (x && use == GDK_AXIS_X)
+            *x = axes[i];
+          else if (y && use == GDK_AXIS_Y)
+            *y = axes[i];
+
+          break;
+        default:
+          _gdk_device_translate_axis (device, i, axis_data[i], &axes[i]);
+          break;
+        }
     }
 }
diff --git a/gdk/x11/gdkdevice-xi.h b/gdk/x11/gdkdevice-xi.h
index c7d99cb..e84535a 100644
--- a/gdk/x11/gdkdevice-xi.h
+++ b/gdk/x11/gdkdevice-xi.h
@@ -64,9 +64,14 @@ struct _GdkDeviceXIClass
 
 GType gdk_device_xi_get_type (void) G_GNUC_CONST;
 
-void gdk_device_xi_update_window_info (GdkWindow *window,
-                                       gdouble    root_x,
-                                       gdouble    root_y);
+void     gdk_device_xi_update_window_info (GdkWindow *window);
+
+void     gdk_device_xi_translate_axes     (GdkDevice *device,
+                                           GdkWindow *window,
+                                           gint      *axis_data,
+                                           gdouble   *axes,
+                                           gdouble   *x,
+                                           gdouble   *y);
 
 G_END_DECLS
 
diff --git a/gdk/x11/gdkdevicemanager-xi.c b/gdk/x11/gdkdevicemanager-xi.c
index 8c05d91..fc2dde2 100644
--- a/gdk/x11/gdkdevicemanager-xi.c
+++ b/gdk/x11/gdkdevicemanager-xi.c
@@ -106,11 +106,8 @@ window_input_info_filter (GdkXEvent *xevent,
   display = gdk_device_manager_get_display (device_manager);
   window = gdk_window_lookup_for_display (display, xev->xany.window);
 
-  if (window &&
-      xev->type == ConfigureNotify)
-    gdk_device_xi_update_window_info (window,
-                                      (gdouble) xev->xconfigure.x,
-                                      (gdouble) xev->xconfigure.y);
+  if (window && xev->type == ConfigureNotify)
+    gdk_device_xi_update_window_info (window);
 
   return GDK_FILTER_CONTINUE;
 }
@@ -342,35 +339,6 @@ gdk_device_manager_xi_event_translator_init (GdkEventTranslatorIface *iface)
   iface->translate_event = gdk_device_manager_xi_translate_event;
 }
 
-static gdouble *
-translate_axes (GdkDevice *device,
-                GdkWindow *window,
-                gdouble    x,
-                gdouble    y,
-                gint      *axis_data)
-{
-  gdouble *data;
-  gint n_axes, i;
-  gint width, height;
-
-  n_axes = device->num_axes;
-  data = g_new0 (gdouble, n_axes);
-  gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
-
-  for (i = 0; i < device->num_axes; i++)
-    {
-      _gdk_device_translate_axis (device,
-                                  (gdouble) width,
-                                  (gdouble) height,
-                                  x, y,
-                                  i,
-                                  axis_data[i],
-                                  &data[i]);
-    }
-
-  return data;
-}
-
 /* combine the state of the core device and the device state
  * into one - for now we do this in a simple-minded manner -
  * we just take the keyboard portion of the core device and
@@ -448,15 +416,17 @@ gdk_device_manager_xi_translate_event (GdkEventTranslator *translator,
       event->button.window = g_object_ref (window);
       event->button.time = xdbe->time;
 
-      event->button.x = (gdouble) xdbe->x;
-      event->button.y = (gdouble) xdbe->y;
       event->button.x_root = (gdouble) xdbe->x_root;
       event->button.y_root = (gdouble) xdbe->y_root;
 
-      event->button.axes = translate_axes (device, window,
-                                           event->button.x,
-                                           event->button.y,
-                                           xdbe->axis_data);
+      event->button.axes = g_new0 (gdouble, device->num_axes);
+      gdk_device_xi_translate_axes (device, window,
+                                    xdbe->axis_data,
+                                    event->button.axes,
+                                    &event->button.x,
+                                    &event->button.y);
+
+      
 
       event->button.state = translate_state (xdbe->state, xdbe->device_state);
       event->button.button = xdbe->button;
@@ -480,7 +450,7 @@ gdk_device_manager_xi_translate_event (GdkEventTranslator *translator,
 	gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
 				      gdk_event_get_time (event));
       return TRUE;
-  }
+    }
 
   if ((xevent->type == device_xi->key_press_type) ||
       (xevent->type == device_xi->key_release_type))
@@ -556,17 +526,18 @@ gdk_device_manager_xi_translate_event (GdkEventTranslator *translator,
     {
       XDeviceMotionEvent *xdme = (XDeviceMotionEvent *) xevent;
 
+      priv->ignore_core_events = TRUE;
       event->motion.device = device;
 
-      event->motion.x = (gdouble) xdme->x;
-      event->motion.y = (gdouble) xdme->y;
       event->motion.x_root = (gdouble) xdme->x_root;
       event->motion.y_root = (gdouble) xdme->y_root;
 
-      event->motion.axes = translate_axes (device, window,
-                                           event->motion.x,
-                                           event->motion.y,
-                                           xdme->axis_data);
+      event->motion.axes = g_new0 (gdouble, device->num_axes);
+      gdk_device_xi_translate_axes (device, window,
+                                    xdme->axis_data,
+                                    event->motion.axes,
+                                    &event->motion.x,
+                                    &event->motion.y);
 
       event->motion.type = GDK_MOTION_NOTIFY;
       event->motion.window = g_object_ref (window);
diff --git a/gdk/x11/gdkdevicemanager-xi2.c b/gdk/x11/gdkdevicemanager-xi2.c
index 4ed4157..ef2ce08 100644
--- a/gdk/x11/gdkdevicemanager-xi2.c
+++ b/gdk/x11/gdkdevicemanager-xi2.c
@@ -696,18 +696,32 @@ translate_axes (GdkDevice       *device,
 
   for (i = 0; i < valuators->mask_len * 8; i++)
     {
-      if (XIMaskIsSet (valuators->mask, i))
+      GdkAxisUse use;
+      gdouble val;
+
+      if (!XIMaskIsSet (valuators->mask, i))
+        continue;
+
+      use = _gdk_device_get_axis_use (device, i);
+      val = *vals++;
+
+      switch (use)
         {
-          gdouble value;
-
-          _gdk_device_translate_axis (device,
-                                      (gdouble) width,
-                                      (gdouble) height,
-                                      x, y,
-                                      i,
-                                      *vals++,
-                                      &value);
-          axes[i] = value;
+        case GDK_AXIS_X:
+        case GDK_AXIS_Y:
+          if (device->mode == GDK_MODE_WINDOW)
+            _gdk_device_translate_window_coord (device, window, i, val, &axes[i]);
+          else
+            {
+              if (use == GDK_AXIS_X)
+                axes[i] = x;
+              else
+                axes[i] = y;
+            }
+          break;
+        default:
+          _gdk_device_translate_axis (device, i, val, &axes[i]);
+          break;
         }
     }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]