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