]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkdevice-wintab.c
Change FSF Address
[~andy/gtk] / gdk / win32 / gdkdevice-wintab.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
3  *
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.
8  *
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.
13  *
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/>.
16  */
17
18 #include "config.h"
19
20 #include <gdk/gdkwindow.h>
21
22 #include <windowsx.h>
23 #include <objbase.h>
24
25 #include "gdkwin32.h"
26 #include "gdkdevice-wintab.h"
27
28 static GQuark quark_window_input_info = 0;
29 static GSList *input_windows = NULL;
30
31 typedef struct
32 {
33   gdouble root_x;
34   gdouble root_y;
35   GHashTable *device_events;
36 } GdkWindowInputInfo;
37
38 static gboolean gdk_device_wintab_get_history (GdkDevice      *device,
39                                                GdkWindow      *window,
40                                                guint32         start,
41                                                guint32         stop,
42                                                GdkTimeCoord ***events,
43                                                gint           *n_events);
44 static void gdk_device_wintab_get_state (GdkDevice       *device,
45                                          GdkWindow       *window,
46                                          gdouble         *axes,
47                                          GdkModifierType *mask);
48 static void gdk_device_wintab_set_window_cursor (GdkDevice *device,
49                                                  GdkWindow *window,
50                                                  GdkCursor *cursor);
51 static void gdk_device_wintab_warp (GdkDevice *device,
52                                     GdkScreen *screen,
53                                     gint       x,
54                                     gint       y);
55 static gboolean gdk_device_wintab_query_state (GdkDevice        *device,
56                                                GdkWindow        *window,
57                                                GdkWindow       **root_window,
58                                                GdkWindow       **child_window,
59                                                gint             *root_x,
60                                                gint             *root_y,
61                                                gint             *win_x,
62                                                gint             *win_y,
63                                                GdkModifierType  *mask);
64 static GdkGrabStatus gdk_device_wintab_grab   (GdkDevice     *device,
65                                                GdkWindow     *window,
66                                                gboolean       owner_events,
67                                                GdkEventMask   event_mask,
68                                                GdkWindow     *confine_to,
69                                                GdkCursor     *cursor,
70                                                guint32        time_);
71 static void          gdk_device_wintab_ungrab (GdkDevice     *device,
72                                                guint32        time_);
73 static GdkWindow * gdk_device_wintab_window_at_position (GdkDevice       *device,
74                                                          gint            *win_x,
75                                                          gint            *win_y,
76                                                          GdkModifierType *mask,
77                                                          gboolean         get_toplevel);
78 static void      gdk_device_wintab_select_window_events (GdkDevice       *device,
79                                                          GdkWindow       *window,
80                                                          GdkEventMask     event_mask);
81
82
83 G_DEFINE_TYPE (GdkDeviceWintab, gdk_device_wintab, GDK_TYPE_DEVICE)
84
85 static void
86 gdk_device_wintab_class_init (GdkDeviceWintabClass *klass)
87 {
88   GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
89
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;
99
100   quark_window_input_info = g_quark_from_static_string ("gdk-window-input-info");
101 }
102
103 static void
104 gdk_device_wintab_init (GdkDeviceWintab *device_wintab)
105 {
106   GdkDevice *device;
107
108   device = GDK_DEVICE (device_wintab);
109 }
110
111 static gboolean
112 gdk_device_wintab_get_history (GdkDevice      *device,
113                                GdkWindow      *window,
114                                guint32         start,
115                                guint32         stop,
116                                GdkTimeCoord ***events,
117                                gint           *n_events)
118 {
119   return FALSE;
120 }
121
122 static void
123 gdk_device_wintab_get_state (GdkDevice       *device,
124                              GdkWindow       *window,
125                              gdouble         *axes,
126                              GdkModifierType *mask)
127 {
128   GdkDeviceWintab *device_wintab;
129
130   device_wintab = GDK_DEVICE_WINTAB (device);
131
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 */
135   if (mask)
136     {
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));
143     }
144
145   if (device_wintab->last_axis_data)
146     _gdk_device_wintab_translate_axes (device_wintab, window, axes, NULL, NULL);
147 }
148
149 static void
150 gdk_device_wintab_set_window_cursor (GdkDevice *device,
151                                      GdkWindow *window,
152                                      GdkCursor *cursor)
153 {
154 }
155
156 static void
157 gdk_device_wintab_warp (GdkDevice *device,
158                         GdkScreen *screen,
159                         gint       x,
160                         gint       y)
161 {
162 }
163
164 static gboolean
165 gdk_device_wintab_query_state (GdkDevice        *device,
166                                GdkWindow        *window,
167                                GdkWindow       **root_window,
168                                GdkWindow       **child_window,
169                                gint             *root_x,
170                                gint             *root_y,
171                                gint             *win_x,
172                                gint             *win_y,
173                                GdkModifierType  *mask)
174 {
175   return FALSE;
176 }
177
178 static GdkGrabStatus
179 gdk_device_wintab_grab (GdkDevice    *device,
180                         GdkWindow    *window,
181                         gboolean      owner_events,
182                         GdkEventMask  event_mask,
183                         GdkWindow    *confine_to,
184                         GdkCursor    *cursor,
185                         guint32       time_)
186 {
187   return GDK_GRAB_SUCCESS;
188 }
189
190 static void
191 gdk_device_wintab_ungrab (GdkDevice *device,
192                           guint32    time_)
193 {
194 }
195
196 static GdkWindow *
197 gdk_device_wintab_window_at_position (GdkDevice       *device,
198                                       gint            *win_x,
199                                       gint            *win_y,
200                                       GdkModifierType *mask,
201                                       gboolean         get_toplevel)
202 {
203   return NULL;
204 }
205
206 static void
207 input_info_free (GdkWindowInputInfo *info)
208 {
209   g_hash_table_destroy (info->device_events);
210   g_free (info);
211 }
212
213 static void
214 gdk_device_wintab_select_window_events (GdkDevice    *device,
215                                         GdkWindow    *window,
216                                         GdkEventMask  event_mask)
217 {
218   GdkWindowInputInfo *info;
219
220   info = g_object_get_qdata (G_OBJECT (window),
221                              quark_window_input_info);
222   if (event_mask)
223     {
224       if (!info)
225         {
226           info = g_new0 (GdkWindowInputInfo, 1);
227           info->device_events = g_hash_table_new (NULL, NULL);
228
229           g_object_set_qdata_full (G_OBJECT (window),
230                                    quark_window_input_info,
231                                    info,
232                                    (GDestroyNotify) input_info_free);
233           input_windows = g_slist_prepend (input_windows, window);
234         }
235
236       g_hash_table_insert (info->device_events, device,
237                            GUINT_TO_POINTER (event_mask));
238     }
239   else if (info)
240     {
241       g_hash_table_remove (info->device_events, device);
242
243       if (g_hash_table_size (info->device_events) == 0)
244         {
245           g_object_set_qdata (G_OBJECT (window),
246                               quark_window_input_info,
247                               NULL);
248           input_windows = g_slist_remove (input_windows, window);
249         }
250     }
251 }
252
253 GdkEventMask
254 _gdk_device_wintab_get_events (GdkDeviceWintab *device,
255                                GdkWindow       *window)
256 {
257   GdkWindowInputInfo *info;
258
259   info = g_object_get_qdata (G_OBJECT (window),
260                              quark_window_input_info);
261
262   if (!info)
263     return 0;
264
265   return GPOINTER_TO_UINT (g_hash_table_lookup (info->device_events, device));
266 }
267
268 gboolean
269 _gdk_device_wintab_get_window_coords (GdkWindow *window,
270                                       gdouble   *root_x,
271                                       gdouble   *root_y)
272 {
273   GdkWindowInputInfo *info;
274
275   info = g_object_get_qdata (G_OBJECT (window),
276                              quark_window_input_info);
277
278   if (!info)
279     return FALSE;
280
281   *root_x = info->root_x;
282   *root_y = info->root_y;
283
284   return TRUE;
285 }
286
287 void
288 _gdk_device_wintab_update_window_coords (GdkWindow *window)
289 {
290   GdkWindowInputInfo *info;
291   gint root_x, root_y;
292
293   info = g_object_get_qdata (G_OBJECT (window),
294                              quark_window_input_info);
295
296   g_return_if_fail (info != NULL);
297
298   gdk_window_get_origin (window, &root_x, &root_y);
299   info->root_x = (gdouble) root_x;
300   info->root_y = (gdouble) root_y;
301 }
302
303 void
304 _gdk_device_wintab_translate_axes (GdkDeviceWintab *device_wintab,
305                                    GdkWindow       *window,
306                                    gdouble         *axes,
307                                    gdouble         *x,
308                                    gdouble         *y)
309 {
310   GdkDevice *device;
311   GdkWindow *impl_window;
312   gdouble root_x, root_y;
313   gdouble temp_x, temp_y;
314   gint i;
315
316   device = GDK_DEVICE (device_wintab);
317   impl_window = _gdk_window_get_impl_window (window);
318   temp_x = temp_y = 0;
319
320   if (!_gdk_device_wintab_get_window_coords (impl_window, &root_x, &root_y))
321     return;
322
323   for (i = 0; i < gdk_device_get_n_axes (device); i++)
324     {
325       GdkAxisUse use;
326
327       use = gdk_device_get_axis_use (device, i);
328
329       switch (use)
330         {
331         case GDK_AXIS_X:
332         case GDK_AXIS_Y:
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],
336                                                 &axes[i]);
337           else
338             _gdk_device_translate_screen_coord (device, window,
339                                                 root_x, root_y, i,
340                                                 device_wintab->last_axis_data[i],
341                                                 &axes[i]);
342           if (use == GDK_AXIS_X)
343             temp_x = axes[i];
344           else if (use == GDK_AXIS_Y)
345             temp_y = axes[i];
346
347           break;
348         default:
349           _gdk_device_translate_axis (device, i,
350                                       device_wintab->last_axis_data[i],
351                                       &axes[i]);
352           break;
353         }
354     }
355
356   if (x)
357     *x = temp_x;
358
359   if (y)
360     *y = temp_y;
361 }
362
363 void
364 _gdk_input_check_extension_events (GdkDevice *device)
365 {
366   GSList *l;
367
368   if (!GDK_IS_DEVICE_WINTAB (device))
369     return;
370
371   for (l = input_windows; l; l = l->next)
372     {
373       GdkWindow *window_private;
374       GdkEventMask event_mask = 0;
375
376       window_private = l->data;
377
378       if (gdk_device_get_mode (device) != GDK_MODE_DISABLED)
379         event_mask = window_private->extension_events;
380
381       gdk_window_set_device_events (GDK_WINDOW (window_private),
382                                     device, event_mask);
383     }
384 }