[gtk+/xi2] Rework axes translation.
- From: Carlos Garnacho <carlosg src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gtk+/xi2] Rework axes translation.
- Date: Sun, 4 Oct 2009 10:33:08 +0000 (UTC)
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]