]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkdevicemanager-win32.c
Merge branch 'master' into broadway2
[~andy/gtk] / gdk / win32 / gdkdevicemanager-win32.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, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <math.h>
25
26 #include <gdk/gdk.h>
27 #include "gdkprivate-win32.h"
28 #include "gdkdevicemanager-win32.h"
29 #include "gdkdeviceprivate.h"
30 #include "gdkdevice-win32.h"
31 #include "gdkdevice-wintab.h"
32 #include "gdkwin32.h"
33 #include "gdkdisplayprivate.h"
34
35 #include <windows.h>
36 #include <wintab.h>
37
38 #define WINTAB32_DLL "Wintab32.dll"
39
40 #define PACKETDATA (PK_CONTEXT | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y  | PK_NORMAL_PRESSURE | PK_ORIENTATION)
41 /* We want everything in absolute mode */
42 #define PACKETMODE (0)
43 #include <pktdef.h>
44
45 #define DEBUG_WINTAB 1          /* Verbose debug messages enabled */
46 #define PROXIMITY_OUT_DELAY 200 /* In milliseconds, see set_ignore_core */
47 #define TWOPI (2 * G_PI)
48
49 static GList     *wintab_contexts = NULL;
50 static GdkWindow *wintab_window = NULL;
51 static guint      ignore_core_timer = 0;
52 extern gint       _gdk_input_ignore_core;
53
54 typedef UINT (WINAPI *t_WTInfoA) (UINT a, UINT b, LPVOID c);
55 typedef UINT (WINAPI *t_WTInfoW) (UINT a, UINT b, LPVOID c);
56 typedef BOOL (WINAPI *t_WTEnable) (HCTX a, BOOL b);
57 typedef HCTX (WINAPI *t_WTOpenA) (HWND a, LPLOGCONTEXTA b, BOOL c);
58 typedef BOOL (WINAPI *t_WTOverlap) (HCTX a, BOOL b);
59 typedef BOOL (WINAPI *t_WTPacket) (HCTX a, UINT b, LPVOID c);
60 typedef int (WINAPI *t_WTQueueSizeSet) (HCTX a, int b);
61
62 static t_WTInfoA p_WTInfoA;
63 static t_WTInfoW p_WTInfoW;
64 static t_WTEnable p_WTEnable;
65 static t_WTOpenA p_WTOpenA;
66 static t_WTOverlap p_WTOverlap;
67 static t_WTPacket p_WTPacket;
68 static t_WTQueueSizeSet p_WTQueueSizeSet;
69
70
71 static void    gdk_device_manager_win32_finalize    (GObject *object);
72 static void    gdk_device_manager_win32_constructed (GObject *object);
73
74 static GList * gdk_device_manager_win32_list_devices (GdkDeviceManager *device_manager,
75                                                       GdkDeviceType     type);
76 static GdkDevice * gdk_device_manager_win32_get_client_pointer (GdkDeviceManager *device_manager);
77
78
79 G_DEFINE_TYPE (GdkDeviceManagerWin32, gdk_device_manager_win32, GDK_TYPE_DEVICE_MANAGER)
80
81 static void
82 gdk_device_manager_win32_class_init (GdkDeviceManagerWin32Class *klass)
83 {
84   GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
85   GObjectClass *object_class = G_OBJECT_CLASS (klass);
86
87   object_class->finalize = gdk_device_manager_win32_finalize;
88   object_class->constructed = gdk_device_manager_win32_constructed;
89   device_manager_class->list_devices = gdk_device_manager_win32_list_devices;
90   device_manager_class->get_client_pointer = gdk_device_manager_win32_get_client_pointer;
91 }
92
93 static GdkDevice *
94 create_core_pointer (GdkDeviceManager *device_manager)
95 {
96   return g_object_new (GDK_TYPE_DEVICE_WIN32,
97                        "name", "Core Pointer",
98                        "type", GDK_DEVICE_TYPE_MASTER,
99                        "input-source", GDK_SOURCE_MOUSE,
100                        "input-mode", GDK_MODE_SCREEN,
101                        "has-cursor", TRUE,
102                        "display", _gdk_display,
103                        "device-manager", device_manager,
104                        NULL);
105 }
106
107 static GdkDevice *
108 create_core_keyboard (GdkDeviceManager *device_manager)
109 {
110   return g_object_new (GDK_TYPE_DEVICE_WIN32,
111                        "name", "Core Keyboard",
112                        "type", GDK_DEVICE_TYPE_MASTER,
113                        "input-source", GDK_SOURCE_KEYBOARD,
114                        "input-mode", GDK_MODE_SCREEN,
115                        "has-cursor", FALSE,
116                        "display", _gdk_display,
117                        "device-manager", device_manager,
118                        NULL);
119 }
120
121 static void
122 gdk_device_manager_win32_init (GdkDeviceManagerWin32 *device_manager_win32)
123 {
124 }
125
126 static void
127 gdk_device_manager_win32_finalize (GObject *object)
128 {
129   GdkDeviceManagerWin32 *device_manager_win32;
130
131   device_manager_win32 = GDK_DEVICE_MANAGER_WIN32 (object);
132
133   g_object_unref (device_manager_win32->core_pointer);
134   g_object_unref (device_manager_win32->core_keyboard);
135
136   G_OBJECT_CLASS (gdk_device_manager_win32_parent_class)->finalize (object);
137 }
138
139 #if DEBUG_WINTAB
140
141 static void
142 print_lc(LOGCONTEXT *lc)
143 {
144   g_print ("lcName = %s\n", lc->lcName);
145   g_print ("lcOptions =");
146   if (lc->lcOptions & CXO_SYSTEM) g_print (" CXO_SYSTEM");
147   if (lc->lcOptions & CXO_PEN) g_print (" CXO_PEN");
148   if (lc->lcOptions & CXO_MESSAGES) g_print (" CXO_MESSAGES");
149   if (lc->lcOptions & CXO_MARGIN) g_print (" CXO_MARGIN");
150   if (lc->lcOptions & CXO_MGNINSIDE) g_print (" CXO_MGNINSIDE");
151   if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
152   g_print ("\n");
153   g_print ("lcStatus =");
154   if (lc->lcStatus & CXS_DISABLED) g_print (" CXS_DISABLED");
155   if (lc->lcStatus & CXS_OBSCURED) g_print (" CXS_OBSCURED");
156   if (lc->lcStatus & CXS_ONTOP) g_print (" CXS_ONTOP");
157   g_print ("\n");
158   g_print ("lcLocks =");
159   if (lc->lcLocks & CXL_INSIZE) g_print (" CXL_INSIZE");
160   if (lc->lcLocks & CXL_INASPECT) g_print (" CXL_INASPECT");
161   if (lc->lcLocks & CXL_SENSITIVITY) g_print (" CXL_SENSITIVITY");
162   if (lc->lcLocks & CXL_MARGIN) g_print (" CXL_MARGIN");
163   g_print ("\n");
164   g_print ("lcMsgBase = %#x, lcDevice = %#x, lcPktRate = %d\n",
165           lc->lcMsgBase, lc->lcDevice, lc->lcPktRate);
166   g_print ("lcPktData =");
167   if (lc->lcPktData & PK_CONTEXT) g_print (" PK_CONTEXT");
168   if (lc->lcPktData & PK_STATUS) g_print (" PK_STATUS");
169   if (lc->lcPktData & PK_TIME) g_print (" PK_TIME");
170   if (lc->lcPktData & PK_CHANGED) g_print (" PK_CHANGED");
171   if (lc->lcPktData & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
172   if (lc->lcPktData & PK_CURSOR) g_print (" PK_CURSOR");
173   if (lc->lcPktData & PK_BUTTONS) g_print (" PK_BUTTONS");
174   if (lc->lcPktData & PK_X) g_print (" PK_X");
175   if (lc->lcPktData & PK_Y) g_print (" PK_Y");
176   if (lc->lcPktData & PK_Z) g_print (" PK_Z");
177   if (lc->lcPktData & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
178   if (lc->lcPktData & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
179   if (lc->lcPktData & PK_ORIENTATION) g_print (" PK_ORIENTATION");
180   if (lc->lcPktData & PK_ROTATION) g_print (" PK_ROTATION");
181   g_print ("\n");
182   g_print ("lcPktMode =");
183   if (lc->lcPktMode & PK_CONTEXT) g_print (" PK_CONTEXT");
184   if (lc->lcPktMode & PK_STATUS) g_print (" PK_STATUS");
185   if (lc->lcPktMode & PK_TIME) g_print (" PK_TIME");
186   if (lc->lcPktMode & PK_CHANGED) g_print (" PK_CHANGED");
187   if (lc->lcPktMode & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
188   if (lc->lcPktMode & PK_CURSOR) g_print (" PK_CURSOR");
189   if (lc->lcPktMode & PK_BUTTONS) g_print (" PK_BUTTONS");
190   if (lc->lcPktMode & PK_X) g_print (" PK_X");
191   if (lc->lcPktMode & PK_Y) g_print (" PK_Y");
192   if (lc->lcPktMode & PK_Z) g_print (" PK_Z");
193   if (lc->lcPktMode & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
194   if (lc->lcPktMode & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
195   if (lc->lcPktMode & PK_ORIENTATION) g_print (" PK_ORIENTATION");
196   if (lc->lcPktMode & PK_ROTATION) g_print (" PK_ROTATION");
197   g_print ("\n");
198   g_print ("lcMoveMask =");
199   if (lc->lcMoveMask & PK_CONTEXT) g_print (" PK_CONTEXT");
200   if (lc->lcMoveMask & PK_STATUS) g_print (" PK_STATUS");
201   if (lc->lcMoveMask & PK_TIME) g_print (" PK_TIME");
202   if (lc->lcMoveMask & PK_CHANGED) g_print (" PK_CHANGED");
203   if (lc->lcMoveMask & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
204   if (lc->lcMoveMask & PK_CURSOR) g_print (" PK_CURSOR");
205   if (lc->lcMoveMask & PK_BUTTONS) g_print (" PK_BUTTONS");
206   if (lc->lcMoveMask & PK_X) g_print (" PK_X");
207   if (lc->lcMoveMask & PK_Y) g_print (" PK_Y");
208   if (lc->lcMoveMask & PK_Z) g_print (" PK_Z");
209   if (lc->lcMoveMask & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
210   if (lc->lcMoveMask & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
211   if (lc->lcMoveMask & PK_ORIENTATION) g_print (" PK_ORIENTATION");
212   if (lc->lcMoveMask & PK_ROTATION) g_print (" PK_ROTATION");
213   g_print ("\n");
214   g_print ("lcBtnDnMask = %#x, lcBtnUpMask = %#x\n",
215           (guint) lc->lcBtnDnMask, (guint) lc->lcBtnUpMask);
216   g_print ("lcInOrgX = %ld, lcInOrgY = %ld, lcInOrgZ = %ld\n",
217           lc->lcInOrgX, lc->lcInOrgY, lc->lcInOrgZ);
218   g_print ("lcInExtX = %ld, lcInExtY = %ld, lcInExtZ = %ld\n",
219           lc->lcInExtX, lc->lcInExtY, lc->lcInExtZ);
220   g_print ("lcOutOrgX = %ld, lcOutOrgY = %ld, lcOutOrgZ = %ld\n",
221           lc->lcOutOrgX, lc->lcOutOrgY, lc->lcOutOrgZ);
222   g_print ("lcOutExtX = %ld, lcOutExtY = %ld, lcOutExtZ = %ld\n",
223           lc->lcOutExtX, lc->lcOutExtY, lc->lcOutExtZ);
224   g_print ("lcSensX = %g, lcSensY = %g, lcSensZ = %g\n",
225           lc->lcSensX / 65536., lc->lcSensY / 65536., lc->lcSensZ / 65536.);
226   g_print ("lcSysMode = %d\n", lc->lcSysMode);
227   g_print ("lcSysOrgX = %d, lcSysOrgY = %d\n",
228           lc->lcSysOrgX, lc->lcSysOrgY);
229   g_print ("lcSysExtX = %d, lcSysExtY = %d\n",
230           lc->lcSysExtX, lc->lcSysExtY);
231   g_print ("lcSysSensX = %g, lcSysSensY = %g\n",
232           lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.);
233 }
234
235 static void
236 print_cursor (int index)
237 {
238   int size;
239   int i;
240   char *name;
241   BOOL active;
242   WTPKT wtpkt;
243   BYTE buttons;
244   BYTE buttonbits;
245   char *btnnames;
246   char *p;
247   BYTE buttonmap[32];
248   BYTE sysbtnmap[32];
249   BYTE npbutton;
250   UINT npbtnmarks[2];
251   UINT *npresponse;
252   BYTE tpbutton;
253   UINT tpbtnmarks[2];
254   UINT *tpresponse;
255   DWORD physid;
256   UINT mode;
257   UINT minpktdata;
258   UINT minbuttons;
259   UINT capabilities;
260
261   size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_NAME, NULL);
262   name = g_malloc (size + 1);
263   (*p_WTInfoA) (WTI_CURSORS + index, CSR_NAME, name);
264   g_print ("NAME: %s\n", name);
265   (*p_WTInfoA) (WTI_CURSORS + index, CSR_ACTIVE, &active);
266   g_print ("ACTIVE: %s\n", active ? "YES" : "NO");
267   (*p_WTInfoA) (WTI_CURSORS + index, CSR_PKTDATA, &wtpkt);
268   g_print ("PKTDATA: %#x:", (guint) wtpkt);
269 #define BIT(x) if (wtpkt & PK_##x) g_print (" " #x)
270   BIT (CONTEXT);
271   BIT (STATUS);
272   BIT (TIME);
273   BIT (CHANGED);
274   BIT (SERIAL_NUMBER);
275   BIT (BUTTONS);
276   BIT (X);
277   BIT (Y);
278   BIT (Z);
279   BIT (NORMAL_PRESSURE);
280   BIT (TANGENT_PRESSURE);
281   BIT (ORIENTATION);
282   BIT (ROTATION);
283 #undef BIT
284   g_print ("\n");
285   (*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONS, &buttons);
286   g_print ("BUTTONS: %d\n", buttons);
287   (*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONBITS, &buttonbits);
288   g_print ("BUTTONBITS: %d\n", buttonbits);
289   size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_BTNNAMES, NULL);
290   g_print ("BTNNAMES:");
291   if (size > 0)
292     {
293       btnnames = g_malloc (size + 1);
294       (*p_WTInfoA) (WTI_CURSORS + index, CSR_BTNNAMES, btnnames);
295       p = btnnames;
296       while (*p)
297         {
298           g_print (" %s", p);
299           p += strlen (p) + 1;
300         }
301     }
302   g_print ("\n");
303   (*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONMAP, buttonmap);
304   g_print ("BUTTONMAP:");
305   for (i = 0; i < buttons; i++)
306     g_print (" %d", buttonmap[i]);
307   g_print ("\n");
308   (*p_WTInfoA) (WTI_CURSORS + index, CSR_SYSBTNMAP, sysbtnmap);
309   g_print ("SYSBTNMAP:");
310   for (i = 0; i < buttons; i++)
311     g_print (" %d", sysbtnmap[i]);
312   g_print ("\n");
313   (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPBUTTON, &npbutton);
314   g_print ("NPBUTTON: %d\n", npbutton);
315   (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPBTNMARKS, npbtnmarks);
316   g_print ("NPBTNMARKS: %d %d\n", npbtnmarks[0], npbtnmarks[1]);
317   size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPRESPONSE, NULL);
318   g_print ("NPRESPONSE:");
319   if (size > 0)
320     {
321       npresponse = g_malloc (size);
322       (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPRESPONSE, npresponse);
323       for (i = 0; i < size / sizeof (UINT); i++)
324         g_print (" %d", npresponse[i]);
325     }
326   g_print ("\n");
327   (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPBUTTON, &tpbutton);
328   g_print ("TPBUTTON: %d\n", tpbutton);
329   (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPBTNMARKS, tpbtnmarks);
330   g_print ("TPBTNMARKS: %d %d\n", tpbtnmarks[0], tpbtnmarks[1]);
331   size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPRESPONSE, NULL);
332   g_print ("TPRESPONSE:");
333   if (size > 0)
334     {
335       tpresponse = g_malloc (size);
336       (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPRESPONSE, tpresponse);
337       for (i = 0; i < size / sizeof (UINT); i++)
338         g_print (" %d", tpresponse[i]);
339     }
340   g_print ("\n");
341   (*p_WTInfoA) (WTI_CURSORS + index, CSR_PHYSID, &physid);
342   g_print ("PHYSID: %#x\n", (guint) physid);
343   (*p_WTInfoA) (WTI_CURSORS + index, CSR_CAPABILITIES, &capabilities);
344   g_print ("CAPABILITIES: %#x:", capabilities);
345 #define BIT(x) if (capabilities & CRC_##x) g_print (" " #x)
346   BIT (MULTIMODE);
347   BIT (AGGREGATE);
348   BIT (INVERT);
349 #undef BIT
350   g_print ("\n");
351   if (capabilities & CRC_MULTIMODE)
352     {
353       (*p_WTInfoA) (WTI_CURSORS + index, CSR_MODE, &mode);
354       g_print ("MODE: %d\n", mode);
355     }
356   if (capabilities & CRC_AGGREGATE)
357     {
358       (*p_WTInfoA) (WTI_CURSORS + index, CSR_MINPKTDATA, &minpktdata);
359       g_print ("MINPKTDATA: %d\n", minpktdata);
360       (*p_WTInfoA) (WTI_CURSORS + index, CSR_MINBUTTONS, &minbuttons);
361       g_print ("MINBUTTONS: %d\n", minbuttons);
362     }
363 }
364 #endif
365
366 static void
367 _gdk_input_wintab_init_check (GdkDeviceManagerWin32 *device_manager)
368 {
369   static gboolean wintab_initialized = FALSE;
370   GdkDeviceWintab *device;
371   GdkWindowAttr wa;
372   WORD specversion;
373   HCTX *hctx;
374   UINT ndevices, ncursors, ncsrtypes, firstcsr, hardware;
375   BOOL active;
376   DWORD physid;
377   AXIS axis_x, axis_y, axis_npressure, axis_or[3];
378   int i, devix, cursorix, num_axes = 0;
379   wchar_t devname[100], csrname[100];
380   gchar *devname_utf8, *csrname_utf8, *device_name;
381   BOOL defcontext_done;
382   HMODULE wintab32;
383   char *wintab32_dll_path;
384   char dummy;
385   int n, k;
386
387   if (wintab_initialized)
388     return;
389
390   wintab_initialized = TRUE;
391
392   wintab_contexts = NULL;
393
394   if (_gdk_input_ignore_wintab)
395     return;
396
397   n = GetSystemDirectory (&dummy, 0);
398
399   if (n <= 0)
400     return;
401
402   wintab32_dll_path = g_malloc (n + 1 + strlen (WINTAB32_DLL));
403   k = GetSystemDirectory (wintab32_dll_path, n);
404   
405   if (k == 0 || k > n)
406     {
407       g_free (wintab32_dll_path);
408       return;
409     }
410
411   if (!G_IS_DIR_SEPARATOR (wintab32_dll_path[strlen (wintab32_dll_path) -1]))
412     strcat (wintab32_dll_path, G_DIR_SEPARATOR_S);
413   strcat (wintab32_dll_path, WINTAB32_DLL);
414
415   if ((wintab32 = LoadLibrary (wintab32_dll_path)) == NULL)
416     return;
417
418   if ((p_WTInfoA = (t_WTInfoA) GetProcAddress (wintab32, "WTInfoA")) == NULL)
419     return;
420   if ((p_WTInfoW = (t_WTInfoW) GetProcAddress (wintab32, "WTInfoW")) == NULL)
421     return;
422   if ((p_WTEnable = (t_WTEnable) GetProcAddress (wintab32, "WTEnable")) == NULL)
423     return;
424   if ((p_WTOpenA = (t_WTOpenA) GetProcAddress (wintab32, "WTOpenA")) == NULL)
425     return;
426   if ((p_WTOverlap = (t_WTOverlap) GetProcAddress (wintab32, "WTOverlap")) == NULL)
427     return;
428   if ((p_WTPacket = (t_WTPacket) GetProcAddress (wintab32, "WTPacket")) == NULL)
429     return;
430   if ((p_WTQueueSizeSet = (t_WTQueueSizeSet) GetProcAddress (wintab32, "WTQueueSizeSet")) == NULL)
431     return;
432
433   if (!(*p_WTInfoA) (0, 0, NULL))
434     return;
435
436   (*p_WTInfoA) (WTI_INTERFACE, IFC_SPECVERSION, &specversion);
437   GDK_NOTE (INPUT, g_print ("Wintab interface version %d.%d\n",
438                             HIBYTE (specversion), LOBYTE (specversion)));
439   (*p_WTInfoA) (WTI_INTERFACE, IFC_NDEVICES, &ndevices);
440   (*p_WTInfoA) (WTI_INTERFACE, IFC_NCURSORS, &ncursors);
441 #if DEBUG_WINTAB
442   GDK_NOTE (INPUT, g_print ("NDEVICES: %d, NCURSORS: %d\n",
443                             ndevices, ncursors));
444 #endif
445   /* Create a dummy window to receive wintab events */
446   wa.wclass = GDK_INPUT_OUTPUT;
447   wa.event_mask = GDK_ALL_EVENTS_MASK;
448   wa.width = 2;
449   wa.height = 2;
450   wa.x = -100;
451   wa.y = -100;
452   wa.window_type = GDK_WINDOW_TOPLEVEL;
453   if ((wintab_window = gdk_window_new (NULL, &wa, GDK_WA_X|GDK_WA_Y)) == NULL)
454     {
455       g_warning ("gdk_input_wintab_init: gdk_window_new failed");
456       return;
457     }
458   g_object_ref (wintab_window);
459
460   for (devix = 0; devix < ndevices; devix++)
461     {
462       LOGCONTEXT lc;
463
464       /* We open the Wintab device (hmm, what if there are several, or
465        * can there even be several, probably not?) as a system
466        * pointing device, i.e. it controls the normal Windows
467        * cursor. This seems much more natural.
468        */
469
470       (*p_WTInfoW) (WTI_DEVICES + devix, DVC_NAME, devname);
471       devname_utf8 = g_utf16_to_utf8 (devname, -1, NULL, NULL, NULL);
472 #ifdef DEBUG_WINTAB
473       GDK_NOTE (INPUT, (g_print("Device %d: %s\n", devix, devname_utf8)));
474 #endif
475       (*p_WTInfoA) (WTI_DEVICES + devix, DVC_NCSRTYPES, &ncsrtypes);
476       (*p_WTInfoA) (WTI_DEVICES + devix, DVC_FIRSTCSR, &firstcsr);
477       (*p_WTInfoA) (WTI_DEVICES + devix, DVC_HARDWARE, &hardware);
478       (*p_WTInfoA) (WTI_DEVICES + devix, DVC_X, &axis_x);
479       (*p_WTInfoA) (WTI_DEVICES + devix, DVC_Y, &axis_y);
480       (*p_WTInfoA) (WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure);
481       (*p_WTInfoA) (WTI_DEVICES + devix, DVC_ORIENTATION, axis_or);
482
483       defcontext_done = FALSE;
484       if (HIBYTE (specversion) > 1 || LOBYTE (specversion) >= 1)
485         {
486           /* Try to get device-specific default context */
487           /* Some drivers, e.g. Aiptek, don't provide this info */
488           if ((*p_WTInfoA) (WTI_DSCTXS + devix, 0, &lc) > 0)
489             defcontext_done = TRUE;
490 #if DEBUG_WINTAB
491           if (defcontext_done)
492             GDK_NOTE (INPUT, (g_print("Using device-specific default context\n")));
493           else
494             GDK_NOTE (INPUT, (g_print("Note: Driver did not provide device specific default context info despite claiming to support version 1.1\n")));
495 #endif
496         }
497
498       if (!defcontext_done)
499         (*p_WTInfoA) (WTI_DEFSYSCTX, 0, &lc);
500 #if DEBUG_WINTAB
501       GDK_NOTE (INPUT, (g_print("Default context:\n"), print_lc(&lc)));
502 #endif
503       lc.lcOptions |= CXO_MESSAGES;
504       lc.lcStatus = 0;
505       lc.lcMsgBase = WT_DEFBASE;
506       lc.lcPktRate = 0;
507       lc.lcPktData = PACKETDATA;
508       lc.lcPktMode = PACKETMODE;
509       lc.lcMoveMask = PACKETDATA;
510       lc.lcBtnUpMask = lc.lcBtnDnMask = ~0;
511       lc.lcOutOrgX = axis_x.axMin;
512       lc.lcOutOrgY = axis_y.axMin;
513       lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
514       lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
515       lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
516 #if DEBUG_WINTAB
517       GDK_NOTE (INPUT, (g_print("context for device %d:\n", devix),
518                         print_lc(&lc)));
519 #endif
520       hctx = g_new (HCTX, 1);
521       if ((*hctx = (*p_WTOpenA) (GDK_WINDOW_HWND (wintab_window), &lc, TRUE)) == NULL)
522         {
523           g_warning ("gdk_input_wintab_init: WTOpen failed");
524           return;
525         }
526       GDK_NOTE (INPUT, g_print ("opened Wintab device %d %p\n",
527                                 devix, *hctx));
528
529       wintab_contexts = g_list_append (wintab_contexts, hctx);
530 #if 0
531       (*p_WTEnable) (*hctx, TRUE);
532 #endif
533       (*p_WTOverlap) (*hctx, TRUE);
534
535 #if DEBUG_WINTAB
536       GDK_NOTE (INPUT, (g_print("context for device %d after WTOpen:\n", devix),
537                         print_lc(&lc)));
538 #endif
539       /* Increase packet queue size to reduce the risk of lost packets.
540        * According to the specs, if the function fails we must try again
541        * with a smaller queue size.
542        */
543       GDK_NOTE (INPUT, g_print("Attempting to increase queue size\n"));
544       for (i = 32; i >= 1; i >>= 1)
545         {
546           if ((*p_WTQueueSizeSet) (*hctx, i))
547             {
548               GDK_NOTE (INPUT, g_print("Queue size set to %d\n", i));
549               break;
550             }
551         }
552       if (!i)
553         GDK_NOTE (INPUT, g_print("Whoops, no queue size could be set\n"));
554       for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes; cursorix++)
555         {
556 #ifdef DEBUG_WINTAB
557           GDK_NOTE (INPUT, (g_print("Cursor %d:\n", cursorix), print_cursor (cursorix)));
558 #endif
559           active = FALSE;
560           (*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_ACTIVE, &active);
561           if (!active)
562             continue;
563
564           /* Wacom tablets seem to report cursors corresponding to
565            * nonexistent pens or pucks. At least my ArtPad II reports
566            * six cursors: a puck, pressure stylus and eraser stylus,
567            * and then the same three again. I only have a
568            * pressure-sensitive pen. The puck instances, and the
569            * second instances of the styluses report physid zero. So
570            * at least for Wacom, skip cursors with physid zero.
571            */
572           (*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_PHYSID, &physid);
573           if (wcscmp (devname, L"WACOM Tablet") == 0 && physid == 0)
574             continue;
575
576           (*p_WTInfoW) (WTI_CURSORS + cursorix, CSR_NAME, csrname);
577           csrname_utf8 = g_utf16_to_utf8 (csrname, -1, NULL, NULL, NULL);
578           device_name = g_strconcat (devname_utf8, " ", csrname_utf8, NULL);
579
580           device = g_object_new (GDK_TYPE_DEVICE_WINTAB,
581                                  "name", device_name,
582                                  "type", GDK_DEVICE_TYPE_SLAVE,
583                                  "source", GDK_SOURCE_PEN,
584                                  "mode", GDK_MODE_SCREEN,
585                                  "has-cursor", FALSE,
586                                  "display", _gdk_display,
587                                  "device-manager", device_manager,
588                                  NULL);
589
590           g_free (csrname_utf8);
591
592           device->hctx = *hctx;
593           device->cursor = cursorix;
594           (*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_PKTDATA, &device->pktdata);
595
596           if (device->pktdata & PK_X)
597             {
598               _gdk_device_add_axis (GDK_DEVICE (device),
599                                     GDK_NONE,
600                                     GDK_AXIS_X,
601                                     axis_x.axMin,
602                                     axis_x.axMax,
603                                     axis_x.axResolution / 65535);
604               num_axes++;
605             }
606
607           if (device->pktdata & PK_Y)
608             {
609               _gdk_device_add_axis (GDK_DEVICE (device),
610                                     GDK_NONE,
611                                     GDK_AXIS_Y,
612                                     axis_y.axMin,
613                                     axis_y.axMax,
614                                     axis_y.axResolution / 65535);
615               num_axes++;
616             }
617
618
619           if (device->pktdata & PK_NORMAL_PRESSURE)
620             {
621               _gdk_device_add_axis (GDK_DEVICE (device),
622                                     GDK_NONE,
623                                     GDK_AXIS_PRESSURE,
624                                     axis_npressure.axMin,
625                                     axis_npressure.axMax,
626                                     axis_npressure.axResolution / 65535);
627               num_axes++;
628             }
629
630           /* The wintab driver for the Wacom ArtPad II reports
631            * PK_ORIENTATION in CSR_PKTDATA, but the tablet doesn't
632            * actually sense tilt. Catch this by noticing that the
633            * orientation axis's azimuth resolution is zero.
634            */
635           if ((device->pktdata & PK_ORIENTATION) && axis_or[0].axResolution == 0)
636             {
637               device->orientation_axes[0] = axis_or[0];
638               device->orientation_axes[1] = axis_or[1];
639
640               /* Wintab gives us aximuth and altitude, which
641                * we convert to x and y tilt in the -1000..1000 range
642                */
643               _gdk_device_add_axis (GDK_DEVICE (device),
644                                     GDK_NONE,
645                                     GDK_AXIS_XTILT,
646                                     -1000,
647                                     1000,
648                                     1000);
649
650               _gdk_device_add_axis (GDK_DEVICE (device),
651                                     GDK_NONE,
652                                     GDK_AXIS_YTILT,
653                                     -1000,
654                                     1000,
655                                     1000);
656               num_axes += 2;
657             }
658
659           device->last_axis_data = g_new (gint, num_axes);
660
661           GDK_NOTE (INPUT, g_print ("device: (%d) %s axes: %d\n",
662                                     cursorix,
663                                     device_name,
664                                     num_axes));
665
666 #if 0
667           for (i = 0; i < gdkdev->info.num_axes; i++)
668             GDK_NOTE (INPUT, g_print ("... axis %d: %d--%d@%d\n",
669                                       i,
670                                       gdkdev->axes[i].min_value,
671                                       gdkdev->axes[i].max_value,
672                                       gdkdev->axes[i].resolution));
673 #endif
674
675           device_manager->wintab_devices = g_list_append (device_manager->wintab_devices,
676                                                           device);
677
678           g_free (device_name);
679         }
680
681       g_free (devname_utf8);
682     }
683 }
684
685 static void
686 gdk_device_manager_win32_constructed (GObject *object)
687 {
688   GdkDeviceManagerWin32 *device_manager;
689
690   device_manager = GDK_DEVICE_MANAGER_WIN32 (object);
691   device_manager->core_pointer = create_core_pointer (GDK_DEVICE_MANAGER (device_manager));
692   device_manager->core_keyboard = create_core_keyboard (GDK_DEVICE_MANAGER (device_manager));
693
694   _gdk_device_set_associated_device (device_manager->core_pointer, device_manager->core_keyboard);
695   _gdk_device_set_associated_device (device_manager->core_keyboard, device_manager->core_pointer);
696
697   _gdk_input_wintab_init_check (device_manager);
698 }
699
700 static GList *
701 gdk_device_manager_win32_list_devices (GdkDeviceManager *device_manager,
702                                        GdkDeviceType     type)
703 {
704   GdkDeviceManagerWin32 *device_manager_win32;
705   GList *devices = NULL;
706
707   device_manager_win32 = (GdkDeviceManagerWin32 *) device_manager;
708
709   if (type == GDK_DEVICE_TYPE_MASTER)
710     {
711       devices = g_list_prepend (devices, device_manager_win32->core_keyboard);
712       devices = g_list_prepend (devices, device_manager_win32->core_pointer);
713     }
714   else if (type == GDK_DEVICE_TYPE_FLOATING)
715     devices = g_list_copy (device_manager_win32->wintab_devices);
716
717   return devices;
718 }
719
720 static GdkDevice *
721 gdk_device_manager_win32_get_client_pointer (GdkDeviceManager *device_manager)
722 {
723   GdkDeviceManagerWin32 *device_manager_win32;
724
725   device_manager_win32 = (GdkDeviceManagerWin32 *) device_manager;
726   return device_manager_win32->core_pointer;
727 }
728
729 void
730 _gdk_input_set_tablet_active (void)
731 {
732   GList *tmp_list;
733   HCTX *hctx;
734
735   /* Bring the contexts to the top of the overlap order when one of the
736    * application's windows is activated */
737
738   if (!wintab_contexts)
739     return; /* No tablet devices found, or Wintab not initialized yet */
740
741   GDK_NOTE (INPUT, g_print ("_gdk_input_set_tablet_active: "
742                             "Bringing Wintab contexts to the top of the overlap order\n"));
743
744   tmp_list = wintab_contexts;
745
746   while (tmp_list)
747     {
748       hctx = (HCTX *) (tmp_list->data);
749       (*p_WTOverlap) (*hctx, TRUE);
750       tmp_list = tmp_list->next;
751     }
752 }
753
754 static void
755 decode_tilt (gint   *axis_data,
756              AXIS   *axes,
757              PACKET *packet)
758 {
759   double az, el;
760
761   /* As I don't have a tilt-sensing tablet,
762    * I cannot test this code.
763    */
764   az = TWOPI * packet->pkOrientation.orAzimuth /
765     (axes[0].axResolution / 65536.);
766   el = TWOPI * packet->pkOrientation.orAltitude /
767     (axes[1].axResolution / 65536.);
768
769   /* X tilt */
770   axis_data[0] = cos (az) * cos (el) * 1000;
771   /* Y tilt */
772   axis_data[1] = sin (az) * cos (el) * 1000;
773 }
774
775 /*
776  * Get the currently active keyboard modifiers (ignoring the mouse buttons)
777  * We could use gdk_window_get_pointer but that function does a lot of other
778  * expensive things besides getting the modifiers. This code is somewhat based
779  * on build_pointer_event_state from gdkevents-win32.c
780  */
781 static guint
782 get_modifier_key_state (void)
783 {
784   guint state;
785
786   state = 0;
787   /* High-order bit is up/down, low order bit is toggled/untoggled */
788   if (GetKeyState (VK_CONTROL) < 0)
789     state |= GDK_CONTROL_MASK;
790   if (GetKeyState (VK_SHIFT) < 0)
791     state |= GDK_SHIFT_MASK;
792   if (GetKeyState (VK_MENU) < 0)
793     state |= GDK_MOD1_MASK;
794   if (GetKeyState (VK_CAPITAL) & 0x1)
795     state |= GDK_LOCK_MASK;
796
797   return state;
798 }
799
800 static gboolean
801 ignore_core_timefunc (gpointer data)
802 {
803   /* The delay has passed */
804   _gdk_input_ignore_core = FALSE;
805   ignore_core_timer = 0;
806
807   return FALSE; /* remove timeout */
808 }
809
810 /*
811  * Set or unset the _gdk_input_ignore_core variable that tells GDK
812  * to ignore events for the core pointer when the tablet is in proximity
813  * The unsetting is delayed slightly so that if a tablet event arrives
814  * just after proximity out, it does not cause a core pointer event
815  * which e.g. causes GIMP to switch tools.
816  */
817 static void
818 set_ignore_core (gboolean ignore)
819 {
820   if (ignore)
821     {
822       _gdk_input_ignore_core = TRUE;
823       /* Remove any pending clear */
824       if (ignore_core_timer)
825         {
826           g_source_remove (ignore_core_timer);
827           ignore_core_timer = 0;
828         }
829     }
830   else if (!ignore_core_timer)
831     ignore_core_timer = gdk_threads_add_timeout (PROXIMITY_OUT_DELAY,
832                                                  ignore_core_timefunc, NULL);
833 }
834
835 static GdkDeviceWintab *
836 _gdk_device_manager_find_wintab_device (HCTX hctx,
837                                         UINT cursor)
838 {
839   GdkDeviceManagerWin32 *device_manager;
840   GdkDeviceWintab *device;
841   GList *tmp_list;
842
843   device_manager = GDK_DEVICE_MANAGER_WIN32 (gdk_display_get_device_manager (_gdk_display));
844   tmp_list = device_manager->wintab_devices;
845
846   while (tmp_list)
847     {
848       device = tmp_list->data;
849       tmp_list = tmp_list->next;
850
851       if (device->hctx == hctx &&
852           device->cursor == cursor)
853         return device;
854     }
855
856   return NULL;
857 }
858
859 gboolean
860 _gdk_input_other_event (GdkEvent  *event,
861                         MSG       *msg,
862                         GdkWindow *window)
863 {
864   GdkDisplay *display;
865   GdkDeviceWintab *device = NULL;
866   GdkDeviceGrabInfo *last_grab;
867   GdkEventMask masktest;
868   guint key_state;
869   POINT pt;
870
871   PACKET packet;
872   gdouble root_x, root_y;
873   gint num_axes;
874   gint x, y;
875   guint translated_buttons, button_diff, button_mask;
876   /* Translation from tablet button state to GDK button state for
877    * buttons 1-3 - swap button 2 and 3.
878    */
879   static guint button_map[8] = {0, 1, 4, 5, 2, 3, 6, 7};
880
881   if (event->any.window != wintab_window)
882     {
883       g_warning ("_gdk_input_other_event: not wintab_window?");
884       return FALSE;
885     }
886
887   window = gdk_window_at_pointer (&x, &y);
888   if (window == NULL)
889     window = _gdk_root;
890
891   g_object_ref (window);
892   display = gdk_window_get_display (window);
893
894   GDK_NOTE (EVENTS_OR_INPUT,
895             g_print ("_gdk_input_other_event: window=%p %+d%+d\n",
896                GDK_WINDOW_HWND (window), x, y));
897
898   if (msg->message == WT_PACKET)
899     {
900       if (!(*p_WTPacket) ((HCTX) msg->lParam, msg->wParam, &packet))
901         return FALSE;
902     }
903
904   switch (msg->message)
905     {
906     case WT_PACKET:
907       /* Don't produce any button or motion events while a window is being
908        * moved or resized, see bug #151090.
909        */
910       if (_modal_operation_in_progress)
911         {
912           GDK_NOTE (EVENTS_OR_INPUT, g_print ("... ignored when moving/sizing\n"));
913           return FALSE;
914         }
915
916       if ((device = _gdk_device_manager_find_wintab_device ((HCTX) msg->lParam,
917                                                             packet.pkCursor)) == NULL)
918         return FALSE;
919
920       if (gdk_device_get_mode (GDK_DEVICE (device)) == GDK_MODE_DISABLED)
921         return FALSE;
922
923       last_grab = _gdk_display_get_last_device_grab (_gdk_display, GDK_DEVICE (device));
924
925       if (last_grab && last_grab->window)
926         {
927           g_object_unref (window);
928
929           window = g_object_ref (last_grab->window);
930         }
931
932       if (window == _gdk_root)
933         {
934           GDK_NOTE (EVENTS_OR_INPUT, g_print ("... is root\n"));
935           return FALSE;
936         }
937
938       num_axes = 0;
939       if (device->pktdata & PK_X)
940         device->last_axis_data[num_axes++] = packet.pkX;
941       if (device->pktdata & PK_Y)
942         device->last_axis_data[num_axes++] = packet.pkY;
943       if (device->pktdata & PK_NORMAL_PRESSURE)
944         device->last_axis_data[num_axes++] = packet.pkNormalPressure;
945       if (device->pktdata & PK_ORIENTATION)
946         {
947           decode_tilt (device->last_axis_data + num_axes,
948                        device->orientation_axes, &packet);
949           num_axes += 2;
950         }
951
952       translated_buttons = button_map[packet.pkButtons & 0x07] | (packet.pkButtons & ~0x07);
953
954       if (translated_buttons != device->button_state)
955         {
956           /* At least one button has changed state so produce a button event
957            * If more than one button has changed state (unlikely),
958            * just care about the first and act on the next the next time
959            * we get a packet
960            */
961           button_diff = translated_buttons ^ device->button_state;
962
963           /* Gdk buttons are numbered 1.. */
964           event->button.button = 1;
965
966           for (button_mask = 1; button_mask != 0x80000000;
967                button_mask <<= 1, event->button.button++)
968             {
969               if (button_diff & button_mask)
970                 {
971                   /* Found a button that has changed state */
972                   break;
973                 }
974             }
975
976           if (!(translated_buttons & button_mask))
977             {
978               event->any.type = GDK_BUTTON_RELEASE;
979               masktest = GDK_BUTTON_RELEASE_MASK;
980             }
981           else
982             {
983               event->any.type = GDK_BUTTON_PRESS;
984               masktest = GDK_BUTTON_PRESS_MASK;
985             }
986           device->button_state ^= button_mask;
987         }
988       else
989         {
990           event->any.type = GDK_MOTION_NOTIFY;
991           masktest = GDK_POINTER_MOTION_MASK;
992           if (device->button_state & (1 << 0))
993             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK;
994           if (device->button_state & (1 << 1))
995             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK;
996           if (device->button_state & (1 << 2))
997             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK;
998         }
999
1000       /* Now we can check if the window wants the event, and
1001        * propagate if necessary.
1002        */
1003       while (gdk_window_get_device_events (window, GDK_DEVICE (device)) == 0)
1004         {
1005           GDK_NOTE (EVENTS_OR_INPUT, g_print ("... not selected\n"));
1006
1007           if (window->parent == GDK_WINDOW (_gdk_root))
1008             return FALSE;
1009
1010           /* It is not good to propagate the extended events up to the parent
1011            * if this window wants normal (not extended) motion/button events */
1012           if (window->event_mask & masktest)
1013             {
1014               GDK_NOTE (EVENTS_OR_INPUT,
1015                         g_print ("... wants ordinary event, ignoring this\n"));
1016               return FALSE;
1017             }
1018
1019           pt.x = x;
1020           pt.y = y;
1021           ClientToScreen (GDK_WINDOW_HWND (window), &pt);
1022           g_object_unref (window);
1023           window = window->parent;
1024           g_object_ref (window);
1025           ScreenToClient (GDK_WINDOW_HWND (window), &pt);
1026           x = pt.x;
1027           y = pt.y;
1028           GDK_NOTE (EVENTS_OR_INPUT, g_print ("... propagating to %p %+d%+d\n",
1029                                               GDK_WINDOW_HWND (window), x, y));
1030         }
1031
1032       if (gdk_window_get_device_events (window, GDK_DEVICE (device)) == 0)
1033         return FALSE;
1034
1035       event->any.window = window;
1036       key_state = get_modifier_key_state ();
1037       if (event->any.type == GDK_BUTTON_PRESS ||
1038           event->any.type == GDK_BUTTON_RELEASE)
1039         {
1040           event->button.time = _gdk_win32_get_next_tick (msg->time);
1041           gdk_event_set_device (event, GDK_DEVICE (device));
1042
1043           event->button.axes = g_new (gdouble, num_axes);
1044           _gdk_device_wintab_get_window_coords (window, &root_x, &root_y);
1045
1046           _gdk_device_wintab_translate_axes (device,
1047                                              window,
1048                                              event->button.axes,
1049                                              &event->button.x,
1050                                              &event->button.y);
1051
1052           event->button.x_root = event->button.x + root_x;
1053           event->button.y_root = event->button.y + root_y;
1054
1055           event->button.state =
1056             key_state | ((device->button_state << 8)
1057                          & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1058                             | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1059                             | GDK_BUTTON5_MASK));
1060
1061           GDK_NOTE (EVENTS_OR_INPUT,
1062                     g_print ("WINTAB button %s:%d %g,%g\n",
1063                              (event->button.type == GDK_BUTTON_PRESS ?
1064                               "press" : "release"),
1065                              event->button.button,
1066                              event->button.x, event->button.y));
1067         }
1068       else
1069         {
1070           event->motion.time = _gdk_win32_get_next_tick (msg->time);
1071           event->motion.is_hint = FALSE;
1072           gdk_event_set_device (event, GDK_DEVICE (device));
1073
1074           event->motion.axes = g_new (gdouble, num_axes);
1075           _gdk_device_wintab_get_window_coords (window, &root_x, &root_y);
1076
1077           _gdk_device_wintab_translate_axes (device,
1078                                              window,
1079                                              event->motion.axes,
1080                                              &event->motion.x,
1081                                              &event->motion.y);
1082
1083           event->motion.x_root = event->motion.x + root_x;
1084           event->motion.y_root = event->motion.y + root_y;
1085
1086           event->motion.state =
1087             key_state | ((device->button_state << 8)
1088                          & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1089                             | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1090                             | GDK_BUTTON5_MASK));
1091
1092           GDK_NOTE (EVENTS_OR_INPUT,
1093                     g_print ("WINTAB motion: %g,%g\n",
1094                              event->motion.x, event->motion.y));
1095         }
1096       return TRUE;
1097
1098     case WT_PROXIMITY:
1099       if (LOWORD (msg->lParam) == 0)
1100         {
1101           event->proximity.type = GDK_PROXIMITY_OUT;
1102           set_ignore_core (FALSE);
1103         }
1104       else
1105         {
1106           event->proximity.type = GDK_PROXIMITY_IN;
1107           set_ignore_core (TRUE);
1108         }
1109       event->proximity.time = _gdk_win32_get_next_tick (msg->time);
1110       gdk_event_set_device (event, GDK_DEVICE (device));
1111
1112       GDK_NOTE (EVENTS_OR_INPUT,
1113                 g_print ("WINTAB proximity %s\n",
1114                          (event->proximity.type == GDK_PROXIMITY_IN ?
1115                           "in" : "out")));
1116       return TRUE;
1117     }
1118
1119   return FALSE;
1120 }