summaryrefslogtreecommitdiff
path: root/gdk/win32/gdkdevice-wintab.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2010-05-25 18:38:44 -0400
committerMatthias Clasen <mclasen@redhat.com>2010-05-25 18:38:44 -0400
commitbd4609b14042a91646cd9057764eecfbc6faf42b (patch)
tree8721405d2b45a998f87cccc672b4070780907fb8 /gdk/win32/gdkdevice-wintab.c
parenta538f639b69a39d7bb85b39af2dfd296d28fc0aa (diff)
downloadgtk+-bd4609b14042a91646cd9057764eecfbc6faf42b.tar.gz
Merge the xi2-for-master branch
Diffstat (limited to 'gdk/win32/gdkdevice-wintab.c')
-rw-r--r--gdk/win32/gdkdevice-wintab.c386
1 files changed, 386 insertions, 0 deletions
diff --git a/gdk/win32/gdkdevice-wintab.c b/gdk/win32/gdkdevice-wintab.c
new file mode 100644
index 0000000000..392e10b2e4
--- /dev/null
+++ b/gdk/win32/gdkdevice-wintab.c
@@ -0,0 +1,386 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <gdk/gdkwindow.h>
+
+#include <windowsx.h>
+#include <objbase.h>
+
+#include "gdkwin32.h"
+#include "gdkdevice-wintab.h"
+
+static GQuark quark_window_input_info = 0;
+static GSList *input_windows = NULL;
+
+typedef struct
+{
+ gdouble root_x;
+ gdouble root_y;
+ GHashTable *device_events;
+} GdkWindowInputInfo;
+
+static gboolean gdk_device_wintab_get_history (GdkDevice *device,
+ GdkWindow *window,
+ guint32 start,
+ guint32 stop,
+ GdkTimeCoord ***events,
+ guint *n_events);
+static void gdk_device_wintab_get_state (GdkDevice *device,
+ GdkWindow *window,
+ gdouble *axes,
+ GdkModifierType *mask);
+static void gdk_device_wintab_set_window_cursor (GdkDevice *device,
+ GdkWindow *window,
+ GdkCursor *cursor);
+static void gdk_device_wintab_warp (GdkDevice *device,
+ GdkScreen *screen,
+ gint x,
+ gint y);
+static gboolean gdk_device_wintab_query_state (GdkDevice *device,
+ GdkWindow *window,
+ GdkWindow **root_window,
+ GdkWindow **child_window,
+ gint *root_x,
+ gint *root_y,
+ gint *win_x,
+ gint *win_y,
+ GdkModifierType *mask);
+static GdkGrabStatus gdk_device_wintab_grab (GdkDevice *device,
+ GdkWindow *window,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ GdkWindow *confine_to,
+ GdkCursor *cursor,
+ guint32 time_);
+static void gdk_device_wintab_ungrab (GdkDevice *device,
+ guint32 time_);
+static GdkWindow * gdk_device_wintab_window_at_position (GdkDevice *device,
+ gint *win_x,
+ gint *win_y,
+ GdkModifierType *mask,
+ gboolean get_toplevel);
+static void gdk_device_wintab_select_window_events (GdkDevice *device,
+ GdkWindow *window,
+ GdkEventMask event_mask);
+
+
+G_DEFINE_TYPE (GdkDeviceWintab, gdk_device_wintab, GDK_TYPE_DEVICE)
+
+static void
+gdk_device_wintab_class_init (GdkDeviceWintabClass *klass)
+{
+ GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
+
+ device_class->get_history = gdk_device_wintab_get_history;
+ device_class->get_state = gdk_device_wintab_get_state;
+ device_class->set_window_cursor = gdk_device_wintab_set_window_cursor;
+ device_class->warp = gdk_device_wintab_warp;
+ device_class->query_state = gdk_device_wintab_query_state;
+ device_class->grab = gdk_device_wintab_grab;
+ device_class->ungrab = gdk_device_wintab_ungrab;
+ device_class->window_at_position = gdk_device_wintab_window_at_position;
+ device_class->select_window_events = gdk_device_wintab_select_window_events;
+
+ quark_window_input_info = g_quark_from_static_string ("gdk-window-input-info");
+}
+
+static void
+gdk_device_wintab_init (GdkDeviceWintab *device_wintab)
+{
+ GdkDevice *device;
+
+ device = GDK_DEVICE (device_wintab);
+}
+
+static gboolean
+gdk_device_wintab_get_history (GdkDevice *device,
+ GdkWindow *window,
+ guint32 start,
+ guint32 stop,
+ GdkTimeCoord ***events,
+ guint *n_events)
+{
+ return FALSE;
+}
+
+static void
+gdk_device_wintab_get_state (GdkDevice *device,
+ GdkWindow *window,
+ gdouble *axes,
+ GdkModifierType *mask)
+{
+ GdkDeviceWintab *device_wintab;
+
+ device_wintab = GDK_DEVICE_WINTAB (device);
+
+ /* For now just use the last known button and axis state of the device.
+ * Since graphical tablets send an insane amount of motion events each
+ * second, the info should be fairly up to date */
+ if (mask)
+ {
+ gdk_window_get_pointer (window, NULL, NULL, mask);
+ *mask &= 0xFF; /* Mask away core pointer buttons */
+ *mask |= ((device_wintab->button_state << 8)
+ & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
+ | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
+ | GDK_BUTTON5_MASK));
+ }
+
+ if (device_wintab->last_axis_data)
+ _gdk_device_wintab_translate_axes (device, window, axes, NULL, NULL);
+}
+
+static void
+gdk_device_wintab_set_window_cursor (GdkDevice *device,
+ GdkWindow *window,
+ GdkCursor *cursor)
+{
+}
+
+static void
+gdk_device_wintab_warp (GdkDevice *device,
+ GdkScreen *screen,
+ gint x,
+ gint y)
+{
+}
+
+static gboolean
+gdk_device_wintab_query_state (GdkDevice *device,
+ GdkWindow *window,
+ GdkWindow **root_window,
+ GdkWindow **child_window,
+ gint *root_x,
+ gint *root_y,
+ gint *win_x,
+ gint *win_y,
+ GdkModifierType *mask)
+{
+ return FALSE;
+}
+
+static GdkGrabStatus
+gdk_device_wintab_grab (GdkDevice *device,
+ GdkWindow *window,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ GdkWindow *confine_to,
+ GdkCursor *cursor,
+ guint32 time_)
+{
+ return GDK_GRAB_SUCCESS;
+}
+
+static void
+gdk_device_wintab_ungrab (GdkDevice *device,
+ guint32 time_)
+{
+}
+
+static GdkWindow *
+gdk_device_wintab_window_at_position (GdkDevice *device,
+ gint *win_x,
+ gint *win_y,
+ GdkModifierType *mask,
+ gboolean get_toplevel)
+{
+ return NULL;
+}
+
+static void
+input_info_free (GdkWindowInputInfo *info)
+{
+ g_hash_table_destroy (info->device_events);
+ g_free (info);
+}
+
+static void
+gdk_device_wintab_select_window_events (GdkDevice *device,
+ GdkWindow *window,
+ GdkEventMask event_mask)
+{
+ GdkWindowInputInfo *info;
+
+ info = g_object_get_qdata (G_OBJECT (window),
+ quark_window_input_info);
+ if (event_mask)
+ {
+ if (!info)
+ {
+ info = g_new0 (GdkWindowInputInfo, 1);
+ info->device_events = g_hash_table_new (NULL, NULL);
+
+ g_object_set_qdata_full (G_OBJECT (window),
+ quark_window_input_info,
+ info,
+ (GDestroyNotify) input_info_free);
+ input_windows = g_slist_prepend (input_windows, window);
+ }
+
+ g_hash_table_insert (info->device_events, device,
+ GUINT_TO_POINTER (event_mask));
+ }
+ else if (info)
+ {
+ g_hash_table_remove (info->device_events, device);
+
+ if (g_hash_table_size (info->device_events) == 0)
+ {
+ g_object_set_qdata (G_OBJECT (window),
+ quark_window_input_info,
+ NULL);
+ input_windows = g_slist_remove (input_windows, window);
+ }
+ }
+}
+
+GdkEventMask
+_gdk_device_wintab_get_events (GdkDeviceWintab *device,
+ GdkWindow *window)
+{
+ GdkWindowInputInfo *info;
+
+ info = g_object_get_qdata (G_OBJECT (window),
+ quark_window_input_info);
+
+ if (!info)
+ return 0;
+
+ return GPOINTER_TO_UINT (g_hash_table_lookup (info->device_events, device));
+}
+
+gboolean
+_gdk_device_wintab_get_window_coords (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_wintab_update_window_coords (GdkWindow *window)
+{
+ GdkWindowInputInfo *info;
+ gint root_x, root_y;
+
+ info = g_object_get_qdata (G_OBJECT (window),
+ quark_window_input_info);
+
+ g_return_if_fail (info != NULL);
+
+ gdk_window_get_origin (window, &root_x, &root_y);
+ info->root_x = (gdouble) root_x;
+ info->root_y = (gdouble) root_y;
+}
+
+void
+_gdk_device_wintab_translate_axes (GdkDeviceWintab *device_wintab,
+ GdkWindow *window,
+ gdouble *axes,
+ gdouble *x,
+ gdouble *y)
+{
+ GdkDevice *device;
+ GdkWindow *impl_window;
+ gdouble root_x, root_y;
+ gdouble temp_x, temp_y;
+ gint i;
+
+ device = GDK_DEVICE (device_wintab);
+ impl_window = _gdk_window_get_impl_window (window);
+ temp_x = temp_y = 0;
+
+ if (!_gdk_device_wintab_get_window_coords (impl_window, &root_x, &root_y))
+ return;
+
+ for (i = 0; i < device->num_axes; i++)
+ {
+ GdkAxisUse use;
+
+ use = _gdk_device_get_axis_use (device, i);
+
+ switch (use)
+ {
+ case GDK_AXIS_X:
+ case GDK_AXIS_Y:
+ if (gdk_device_get_mode (device) == GDK_MODE_WINDOW)
+ _gdk_device_translate_window_coord (device, window, i,
+ device_wintab->last_axis_data[i],
+ &axes[i]);
+ else
+ _gdk_device_translate_screen_coord (device, window,
+ root_x, root_y, i,
+ device_wintab->last_axis_data[i],
+ &axes[i]);
+ if (use == GDK_AXIS_X)
+ temp_x = axes[i];
+ else if (use == GDK_AXIS_Y)
+ temp_y = axes[i];
+
+ break;
+ default:
+ _gdk_device_translate_axis (device, i,
+ device_wintab->last_axis_data[i],
+ &axes[i]);
+ break;
+ }
+ }
+
+ if (x)
+ *x = temp_x;
+
+ if (y)
+ *y = temp_y;
+}
+
+void
+_gdk_input_check_extension_events (GdkDevice *device)
+{
+ GSList *l;
+
+ if (!GDK_IS_DEVICE_WINTAB (device))
+ return;
+
+ for (l = input_windows; l; l = l->next)
+ {
+ GdkWindowObject *window_private;
+ GdkEventMask event_mask = 0;
+
+ window_private = l->data;
+
+ if (gdk_device_get_mode (device) != GDK_MODE_DISABLED)
+ event_mask = window_private->extension_events;
+
+ gdk_window_set_device_events (GDK_WINDOW (window_private),
+ device, event_mask);
+ }
+}