/* GDK - The GIMP Drawing Kit * Copyright (C) 2009 Carlos Garnacho * * 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 #include #include #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, gint *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, gint *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_wintab, 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 < gdk_device_get_n_axes (device); 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) { GdkWindow *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); } }