1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20 #include <gdk/gdkwindow.h>
26 #include "gdkdevice-wintab.h"
28 static GQuark quark_window_input_info = 0;
29 static GSList *input_windows = NULL;
35 GHashTable *device_events;
38 static gboolean gdk_device_wintab_get_history (GdkDevice *device,
42 GdkTimeCoord ***events,
44 static void gdk_device_wintab_get_state (GdkDevice *device,
47 GdkModifierType *mask);
48 static void gdk_device_wintab_set_window_cursor (GdkDevice *device,
51 static void gdk_device_wintab_warp (GdkDevice *device,
55 static gboolean gdk_device_wintab_query_state (GdkDevice *device,
57 GdkWindow **root_window,
58 GdkWindow **child_window,
63 GdkModifierType *mask);
64 static GdkGrabStatus gdk_device_wintab_grab (GdkDevice *device,
66 gboolean owner_events,
67 GdkEventMask event_mask,
68 GdkWindow *confine_to,
71 static void gdk_device_wintab_ungrab (GdkDevice *device,
73 static GdkWindow * gdk_device_wintab_window_at_position (GdkDevice *device,
76 GdkModifierType *mask,
77 gboolean get_toplevel);
78 static void gdk_device_wintab_select_window_events (GdkDevice *device,
80 GdkEventMask event_mask);
83 G_DEFINE_TYPE (GdkDeviceWintab, gdk_device_wintab, GDK_TYPE_DEVICE)
86 gdk_device_wintab_class_init (GdkDeviceWintabClass *klass)
88 GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
90 device_class->get_history = gdk_device_wintab_get_history;
91 device_class->get_state = gdk_device_wintab_get_state;
92 device_class->set_window_cursor = gdk_device_wintab_set_window_cursor;
93 device_class->warp = gdk_device_wintab_warp;
94 device_class->query_state = gdk_device_wintab_query_state;
95 device_class->grab = gdk_device_wintab_grab;
96 device_class->ungrab = gdk_device_wintab_ungrab;
97 device_class->window_at_position = gdk_device_wintab_window_at_position;
98 device_class->select_window_events = gdk_device_wintab_select_window_events;
100 quark_window_input_info = g_quark_from_static_string ("gdk-window-input-info");
104 gdk_device_wintab_init (GdkDeviceWintab *device_wintab)
108 device = GDK_DEVICE (device_wintab);
112 gdk_device_wintab_get_history (GdkDevice *device,
116 GdkTimeCoord ***events,
123 gdk_device_wintab_get_state (GdkDevice *device,
126 GdkModifierType *mask)
128 GdkDeviceWintab *device_wintab;
130 device_wintab = GDK_DEVICE_WINTAB (device);
132 /* For now just use the last known button and axis state of the device.
133 * Since graphical tablets send an insane amount of motion events each
134 * second, the info should be fairly up to date */
137 gdk_window_get_pointer (window, NULL, NULL, mask);
138 *mask &= 0xFF; /* Mask away core pointer buttons */
139 *mask |= ((device_wintab->button_state << 8)
140 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
141 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
142 | GDK_BUTTON5_MASK));
145 if (device_wintab->last_axis_data)
146 _gdk_device_wintab_translate_axes (device_wintab, window, axes, NULL, NULL);
150 gdk_device_wintab_set_window_cursor (GdkDevice *device,
157 gdk_device_wintab_warp (GdkDevice *device,
165 gdk_device_wintab_query_state (GdkDevice *device,
167 GdkWindow **root_window,
168 GdkWindow **child_window,
173 GdkModifierType *mask)
179 gdk_device_wintab_grab (GdkDevice *device,
181 gboolean owner_events,
182 GdkEventMask event_mask,
183 GdkWindow *confine_to,
187 return GDK_GRAB_SUCCESS;
191 gdk_device_wintab_ungrab (GdkDevice *device,
197 gdk_device_wintab_window_at_position (GdkDevice *device,
200 GdkModifierType *mask,
201 gboolean get_toplevel)
207 input_info_free (GdkWindowInputInfo *info)
209 g_hash_table_destroy (info->device_events);
214 gdk_device_wintab_select_window_events (GdkDevice *device,
216 GdkEventMask event_mask)
218 GdkWindowInputInfo *info;
220 info = g_object_get_qdata (G_OBJECT (window),
221 quark_window_input_info);
226 info = g_new0 (GdkWindowInputInfo, 1);
227 info->device_events = g_hash_table_new (NULL, NULL);
229 g_object_set_qdata_full (G_OBJECT (window),
230 quark_window_input_info,
232 (GDestroyNotify) input_info_free);
233 input_windows = g_slist_prepend (input_windows, window);
236 g_hash_table_insert (info->device_events, device,
237 GUINT_TO_POINTER (event_mask));
241 g_hash_table_remove (info->device_events, device);
243 if (g_hash_table_size (info->device_events) == 0)
245 g_object_set_qdata (G_OBJECT (window),
246 quark_window_input_info,
248 input_windows = g_slist_remove (input_windows, window);
254 _gdk_device_wintab_get_events (GdkDeviceWintab *device,
257 GdkWindowInputInfo *info;
259 info = g_object_get_qdata (G_OBJECT (window),
260 quark_window_input_info);
265 return GPOINTER_TO_UINT (g_hash_table_lookup (info->device_events, device));
269 _gdk_device_wintab_get_window_coords (GdkWindow *window,
273 GdkWindowInputInfo *info;
275 info = g_object_get_qdata (G_OBJECT (window),
276 quark_window_input_info);
281 *root_x = info->root_x;
282 *root_y = info->root_y;
288 _gdk_device_wintab_update_window_coords (GdkWindow *window)
290 GdkWindowInputInfo *info;
293 info = g_object_get_qdata (G_OBJECT (window),
294 quark_window_input_info);
296 g_return_if_fail (info != NULL);
298 gdk_window_get_origin (window, &root_x, &root_y);
299 info->root_x = (gdouble) root_x;
300 info->root_y = (gdouble) root_y;
304 _gdk_device_wintab_translate_axes (GdkDeviceWintab *device_wintab,
311 GdkWindow *impl_window;
312 gdouble root_x, root_y;
313 gdouble temp_x, temp_y;
316 device = GDK_DEVICE (device_wintab);
317 impl_window = _gdk_window_get_impl_window (window);
320 if (!_gdk_device_wintab_get_window_coords (impl_window, &root_x, &root_y))
323 for (i = 0; i < gdk_device_get_n_axes (device); i++)
327 use = gdk_device_get_axis_use (device, i);
333 if (gdk_device_get_mode (device) == GDK_MODE_WINDOW)
334 _gdk_device_translate_window_coord (device, window, i,
335 device_wintab->last_axis_data[i],
338 _gdk_device_translate_screen_coord (device, window,
340 device_wintab->last_axis_data[i],
342 if (use == GDK_AXIS_X)
344 else if (use == GDK_AXIS_Y)
349 _gdk_device_translate_axis (device, i,
350 device_wintab->last_axis_data[i],
364 _gdk_input_check_extension_events (GdkDevice *device)
368 if (!GDK_IS_DEVICE_WINTAB (device))
371 for (l = input_windows; l; l = l->next)
373 GdkWindow *window_private;
374 GdkEventMask event_mask = 0;
376 window_private = l->data;
378 if (gdk_device_get_mode (device) != GDK_MODE_DISABLED)
379 event_mask = window_private->extension_events;
381 gdk_window_set_device_events (GDK_WINDOW (window_private),