]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkinput-win32.c
gdk/win32/gdkinput-win32.h Drop the GdkEvent* parameter, it wasn't used.
[~andy/gtk] / gdk / win32 / gdkinput-win32.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  * Copyright (C) 1998-2002 Tor Lillqvist
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
26  */
27
28 #include "config.h"
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <math.h>
33
34 #include "gdk.h"
35 #include "gdkinput.h"
36 #include "gdkinternals.h"
37 #include "gdkprivate-win32.h"
38 #include "gdkinput-win32.h"
39
40 #ifdef HAVE_WINTAB
41
42 #define PACKETDATA (PK_CONTEXT | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y  | PK_NORMAL_PRESSURE | PK_ORIENTATION)
43 #define PACKETMODE (PK_BUTTONS)
44 #include <pktdef.h>
45
46 /* If USE_SYSCONTEXT is on, we open the Wintab device (hmm, what if
47  * there are several?) as a system pointing device, i.e. it controls
48  * the normal Windows cursor. This seems much more natural.
49  */
50 #define USE_SYSCONTEXT 1        /* The code for the other choice is not
51                                  * good at all.
52                                  */
53
54 #define DEBUG_WINTAB 1          /* Verbose debug messages enabled */
55
56 #endif
57
58 #if defined(HAVE_WINTAB) || defined(HAVE_WHATEVER_OTHER)
59 #define HAVE_SOME_XINPUT
60 #endif
61
62 #define TWOPI (2.*G_PI)
63
64 /* Forward declarations */
65
66 #if !USE_SYSCONTEXT
67 static GdkInputWindow *gdk_input_window_find_within (GdkWindow *window);
68 #endif
69
70 #ifdef HAVE_WINTAB
71
72 static GdkDevicePrivate *gdk_input_find_dev_from_ctx (HCTX hctx,
73                                                       UINT id);
74 static GList     *wintab_contexts;
75
76 static GdkWindow *wintab_window;
77
78 #endif /* HAVE_WINTAB */
79
80 #ifdef HAVE_WINTAB
81
82 static GdkDevicePrivate *
83 gdk_input_find_dev_from_ctx (HCTX hctx,
84                              UINT cursor)
85 {
86   GList *tmp_list = _gdk_input_devices;
87   GdkDevicePrivate *gdkdev;
88
89   while (tmp_list)
90     {
91       gdkdev = (GdkDevicePrivate *) (tmp_list->data);
92       if (gdkdev->hctx == hctx && gdkdev->cursor == cursor)
93         return gdkdev;
94       tmp_list = tmp_list->next;
95     }
96   return NULL;
97 }
98
99 #if DEBUG_WINTAB
100
101 static void
102 print_lc(LOGCONTEXT *lc)
103 {
104   g_print ("lcName = %s\n", lc->lcName);
105   g_print ("lcOptions =");
106   if (lc->lcOptions & CXO_SYSTEM) g_print (" CXO_SYSTEM");
107   if (lc->lcOptions & CXO_PEN) g_print (" CXO_PEN");
108   if (lc->lcOptions & CXO_MESSAGES) g_print (" CXO_MESSAGES");
109   if (lc->lcOptions & CXO_MARGIN) g_print (" CXO_MARGIN");
110   if (lc->lcOptions & CXO_MGNINSIDE) g_print (" CXO_MGNINSIDE");
111   if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
112   if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
113   g_print ("\n");
114   g_print ("lcStatus =");
115   if (lc->lcStatus & CXS_DISABLED) g_print (" CXS_DISABLED");
116   if (lc->lcStatus & CXS_OBSCURED) g_print (" CXS_OBSCURED");
117   if (lc->lcStatus & CXS_ONTOP) g_print (" CXS_ONTOP");
118   g_print ("\n");
119   g_print ("lcLocks =");
120   if (lc->lcLocks & CXL_INSIZE) g_print (" CXL_INSIZE");
121   if (lc->lcLocks & CXL_INASPECT) g_print (" CXL_INASPECT");
122   if (lc->lcLocks & CXL_SENSITIVITY) g_print (" CXL_SENSITIVITY");
123   if (lc->lcLocks & CXL_MARGIN) g_print (" CXL_MARGIN");
124   g_print ("\n");
125   g_print ("lcMsgBase = %#x, lcDevice = %#x, lcPktRate = %d\n",
126           lc->lcMsgBase, lc->lcDevice, lc->lcPktRate);
127   g_print ("lcPktData =");
128   if (lc->lcPktData & PK_CONTEXT) g_print (" PK_CONTEXT");
129   if (lc->lcPktData & PK_STATUS) g_print (" PK_STATUS");
130   if (lc->lcPktData & PK_TIME) g_print (" PK_TIME");
131   if (lc->lcPktData & PK_CHANGED) g_print (" PK_CHANGED");
132   if (lc->lcPktData & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
133   if (lc->lcPktData & PK_CURSOR) g_print (" PK_CURSOR");
134   if (lc->lcPktData & PK_BUTTONS) g_print (" PK_BUTTONS");
135   if (lc->lcPktData & PK_X) g_print (" PK_X");
136   if (lc->lcPktData & PK_Y) g_print (" PK_Y");
137   if (lc->lcPktData & PK_Z) g_print (" PK_Z");
138   if (lc->lcPktData & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
139   if (lc->lcPktData & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
140   if (lc->lcPktData & PK_ORIENTATION) g_print (" PK_ORIENTATION");
141   if (lc->lcPktData & PK_ROTATION) g_print (" PK_ROTATION");
142   g_print ("\n");
143   g_print ("lcPktMode =");
144   if (lc->lcPktMode & PK_CONTEXT) g_print (" PK_CONTEXT");
145   if (lc->lcPktMode & PK_STATUS) g_print (" PK_STATUS");
146   if (lc->lcPktMode & PK_TIME) g_print (" PK_TIME");
147   if (lc->lcPktMode & PK_CHANGED) g_print (" PK_CHANGED");
148   if (lc->lcPktMode & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
149   if (lc->lcPktMode & PK_CURSOR) g_print (" PK_CURSOR");
150   if (lc->lcPktMode & PK_BUTTONS) g_print (" PK_BUTTONS");
151   if (lc->lcPktMode & PK_X) g_print (" PK_X");
152   if (lc->lcPktMode & PK_Y) g_print (" PK_Y");
153   if (lc->lcPktMode & PK_Z) g_print (" PK_Z");
154   if (lc->lcPktMode & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
155   if (lc->lcPktMode & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
156   if (lc->lcPktMode & PK_ORIENTATION) g_print (" PK_ORIENTATION");
157   if (lc->lcPktMode & PK_ROTATION) g_print (" PK_ROTATION");
158   g_print ("\n");
159   g_print ("lcMoveMask =");
160   if (lc->lcMoveMask & PK_CONTEXT) g_print (" PK_CONTEXT");
161   if (lc->lcMoveMask & PK_STATUS) g_print (" PK_STATUS");
162   if (lc->lcMoveMask & PK_TIME) g_print (" PK_TIME");
163   if (lc->lcMoveMask & PK_CHANGED) g_print (" PK_CHANGED");
164   if (lc->lcMoveMask & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
165   if (lc->lcMoveMask & PK_CURSOR) g_print (" PK_CURSOR");
166   if (lc->lcMoveMask & PK_BUTTONS) g_print (" PK_BUTTONS");
167   if (lc->lcMoveMask & PK_X) g_print (" PK_X");
168   if (lc->lcMoveMask & PK_Y) g_print (" PK_Y");
169   if (lc->lcMoveMask & PK_Z) g_print (" PK_Z");
170   if (lc->lcMoveMask & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
171   if (lc->lcMoveMask & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
172   if (lc->lcMoveMask & PK_ORIENTATION) g_print (" PK_ORIENTATION");
173   if (lc->lcMoveMask & PK_ROTATION) g_print (" PK_ROTATION");
174   g_print ("\n");
175   g_print ("lcBtnDnMask = %#x, lcBtnUpMask = %#x\n",
176           (guint) lc->lcBtnDnMask, (guint) lc->lcBtnUpMask);
177   g_print ("lcInOrgX = %ld, lcInOrgY = %ld, lcInOrgZ = %ld\n",
178           lc->lcInOrgX, lc->lcInOrgY, lc->lcInOrgZ);
179   g_print ("lcInExtX = %ld, lcInExtY = %ld, lcInExtZ = %ld\n",
180           lc->lcInExtX, lc->lcInExtY, lc->lcInExtZ);
181   g_print ("lcOutOrgX = %ld, lcOutOrgY = %ld, lcOutOrgZ = %ld\n",
182           lc->lcOutOrgX, lc->lcOutOrgY, lc->lcOutOrgZ);
183   g_print ("lcOutExtX = %ld, lcOutExtY = %ld, lcOutExtZ = %ld\n",
184           lc->lcOutExtX, lc->lcOutExtY, lc->lcOutExtZ);
185   g_print ("lcSensX = %g, lcSensY = %g, lcSensZ = %g\n",
186           lc->lcSensX / 65536., lc->lcSensY / 65536., lc->lcSensZ / 65536.);
187   g_print ("lcSysMode = %d\n", lc->lcSysMode);
188   g_print ("lcSysOrgX = %d, lcSysOrgY = %d\n",
189           lc->lcSysOrgX, lc->lcSysOrgY);
190   g_print ("lcSysExtX = %d, lcSysExtY = %d\n",
191           lc->lcSysExtX, lc->lcSysExtY);
192   g_print ("lcSysSensX = %g, lcSysSensY = %g\n",
193           lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.);
194 }
195
196 #endif
197
198 static void
199 gdk_input_wintab_init (void)
200 {
201   GdkDevicePrivate *gdkdev;
202   GdkWindowAttr wa;
203   WORD specversion;
204   LOGCONTEXT defcontext;
205   HCTX *hctx;
206   UINT ndevices, ncursors, ncsrtypes, firstcsr, hardware;
207   BOOL active;
208   AXIS axis_x, axis_y, axis_npressure, axis_or[3];
209   int i, k;
210   int devix, cursorix;
211   char devname[100], csrname[100];
212
213   _gdk_input_devices = NULL;
214   wintab_contexts = NULL;
215
216   if (!_gdk_input_ignore_wintab &&
217       WTInfo (0, 0, NULL))
218     {
219       WTInfo (WTI_INTERFACE, IFC_SPECVERSION, &specversion);
220       GDK_NOTE (INPUT, g_print ("Wintab interface version %d.%d\n",
221                                HIBYTE (specversion), LOBYTE (specversion)));
222 #if USE_SYSCONTEXT
223       WTInfo (WTI_DEFSYSCTX, 0, &defcontext);
224 #if DEBUG_WINTAB
225       GDK_NOTE (INPUT, (g_print("DEFSYSCTX:\n"), print_lc(&defcontext)));
226 #endif
227 #else
228       WTInfo (WTI_DEFCONTEXT, 0, &defcontext);
229 #if DEBUG_WINTAB
230       GDK_NOTE (INPUT, (g_print("DEFCONTEXT:\n"), print_lc(&defcontext)));
231 #endif
232 #endif
233       WTInfo (WTI_INTERFACE, IFC_NDEVICES, &ndevices);
234       WTInfo (WTI_INTERFACE, IFC_NCURSORS, &ncursors);
235 #if DEBUG_WINTAB
236       GDK_NOTE (INPUT, g_print ("NDEVICES: %d, NCURSORS: %d\n",
237                                ndevices, ncursors));
238 #endif
239       /* Create a dummy window to receive wintab events */
240       wa.wclass = GDK_INPUT_OUTPUT;
241       wa.event_mask = GDK_ALL_EVENTS_MASK;
242       wa.width = 2;
243       wa.height = 2;
244       wa.x = -100;
245       wa.y = -100;
246       wa.window_type = GDK_WINDOW_TOPLEVEL;
247       if ((wintab_window = gdk_window_new (NULL, &wa, GDK_WA_X|GDK_WA_Y)) == NULL)
248         {
249           g_warning ("gdk_input_wintab_init: gdk_window_new failed");
250           return;
251         }
252       g_object_ref (wintab_window);
253       
254       for (devix = 0; devix < ndevices; devix++)
255         {
256           LOGCONTEXT lc;
257
258           WTInfo (WTI_DEVICES + devix, DVC_NAME, devname);
259       
260           WTInfo (WTI_DEVICES + devix, DVC_NCSRTYPES, &ncsrtypes);
261           WTInfo (WTI_DEVICES + devix, DVC_FIRSTCSR, &firstcsr);
262           WTInfo (WTI_DEVICES + devix, DVC_HARDWARE, &hardware);
263           WTInfo (WTI_DEVICES + devix, DVC_X, &axis_x);
264           WTInfo (WTI_DEVICES + devix, DVC_Y, &axis_y);
265           WTInfo (WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure);
266           WTInfo (WTI_DEVICES + devix, DVC_ORIENTATION, axis_or);
267
268           if (HIBYTE (specversion) > 1 || LOBYTE (specversion) >= 1)
269             {
270               WTInfo (WTI_DDCTXS + devix, CTX_NAME, lc.lcName);
271               WTInfo (WTI_DDCTXS + devix, CTX_OPTIONS, &lc.lcOptions);
272               lc.lcOptions |= CXO_MESSAGES;
273 #if USE_SYSCONTEXT
274               lc.lcOptions |= CXO_SYSTEM;
275 #endif
276               lc.lcStatus = 0;
277               WTInfo (WTI_DDCTXS + devix, CTX_LOCKS, &lc.lcLocks);
278               lc.lcMsgBase = WT_DEFBASE;
279               lc.lcDevice = devix;
280               lc.lcPktRate = 50;
281               lc.lcPktData = PACKETDATA;
282               lc.lcPktMode = PK_BUTTONS; /* We want buttons in relative mode */
283               lc.lcMoveMask = PACKETDATA;
284               lc.lcBtnDnMask = lc.lcBtnUpMask = ~0;
285               WTInfo (WTI_DDCTXS + devix, CTX_INORGX, &lc.lcInOrgX);
286               WTInfo (WTI_DDCTXS + devix, CTX_INORGY, &lc.lcInOrgY);
287               WTInfo (WTI_DDCTXS + devix, CTX_INORGZ, &lc.lcInOrgZ);
288               WTInfo (WTI_DDCTXS + devix, CTX_INEXTX, &lc.lcInExtX);
289               WTInfo (WTI_DDCTXS + devix, CTX_INEXTY, &lc.lcInExtY);
290               WTInfo (WTI_DDCTXS + devix, CTX_INEXTZ, &lc.lcInExtZ);
291               lc.lcOutOrgX = axis_x.axMin;
292               lc.lcOutOrgY = axis_y.axMin;
293               lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
294               lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
295               lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
296               WTInfo (WTI_DDCTXS + devix, CTX_SENSX, &lc.lcSensX);
297               WTInfo (WTI_DDCTXS + devix, CTX_SENSY, &lc.lcSensY);
298               WTInfo (WTI_DDCTXS + devix, CTX_SENSZ, &lc.lcSensZ);
299               WTInfo (WTI_DDCTXS + devix, CTX_SYSMODE, &lc.lcSysMode);
300               lc.lcSysOrgX = lc.lcSysOrgY = 0;
301               WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTX, &lc.lcSysExtX);
302               WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTY, &lc.lcSysExtY);
303               WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSX, &lc.lcSysSensX);
304               WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSY, &lc.lcSysSensY);
305             }
306           else
307             {
308               lc = defcontext;
309               lc.lcOptions |= CXO_MESSAGES;
310               lc.lcMsgBase = WT_DEFBASE;
311               lc.lcPktRate = 50;
312               lc.lcPktData = PACKETDATA;
313               lc.lcPktMode = PACKETMODE;
314               lc.lcMoveMask = PACKETDATA;
315               lc.lcBtnUpMask = lc.lcBtnDnMask = ~0;
316 #if 0
317               lc.lcOutExtY = -lc.lcOutExtY; /* Y grows downward */
318 #else
319               lc.lcOutOrgX = axis_x.axMin;
320               lc.lcOutOrgY = axis_y.axMin;
321               lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
322               lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
323               lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
324 #endif
325             }
326 #if DEBUG_WINTAB
327           GDK_NOTE (INPUT, (g_print("context for device %d:\n", devix),
328                            print_lc(&lc)));
329 #endif
330           hctx = g_new (HCTX, 1);
331           if ((*hctx = WTOpen (GDK_WINDOW_HWND (wintab_window), &lc, TRUE)) == NULL)
332             {
333               g_warning ("gdk_input_wintab_init: WTOpen failed");
334               return;
335             }
336           GDK_NOTE (INPUT, g_print ("opened Wintab device %d %p\n",
337                                    devix, *hctx));
338
339           wintab_contexts = g_list_append (wintab_contexts, hctx);
340 #if 0
341           WTEnable (*hctx, TRUE);
342 #endif
343           WTOverlap (*hctx, TRUE);
344
345 #if DEBUG_WINTAB
346           GDK_NOTE (INPUT, (g_print("context for device %d after WTOpen:\n", devix),
347                            print_lc(&lc)));
348 #endif
349           for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes; cursorix++)
350             {
351               active = FALSE;
352               WTInfo (WTI_CURSORS + cursorix, CSR_ACTIVE, &active);
353               if (!active)
354                 continue;
355               gdkdev = g_object_new (GDK_TYPE_DEVICE, NULL);
356               WTInfo (WTI_CURSORS + cursorix, CSR_NAME, csrname);
357               gdkdev->info.name = g_strconcat (devname, " ", csrname, NULL);
358               gdkdev->info.source = GDK_SOURCE_PEN;
359               gdkdev->info.mode = GDK_MODE_SCREEN;
360 #if USE_SYSCONTEXT
361               gdkdev->info.has_cursor = TRUE;
362 #else
363               gdkdev->info.has_cursor = FALSE;
364 #endif
365               gdkdev->hctx = *hctx;
366               gdkdev->cursor = cursorix;
367               WTInfo (WTI_CURSORS + cursorix, CSR_PKTDATA, &gdkdev->pktdata);
368               gdkdev->info.num_axes = 0;
369               if (gdkdev->pktdata & PK_X)
370                 gdkdev->info.num_axes++;
371               if (gdkdev->pktdata & PK_Y)
372                 gdkdev->info.num_axes++;
373               if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
374                 gdkdev->info.num_axes++;
375               /* The wintab driver for the Wacom ArtPad II reports
376                * PK_ORIENTATION in CSR_PKTDATA, but the tablet doesn't
377                * actually sense tilt. Catch this by noticing that the
378                * orientation axis's azimuth resolution is zero.
379                */
380               if ((gdkdev->pktdata & PK_ORIENTATION)
381                   && axis_or[0].axResolution == 0)
382                 gdkdev->pktdata &= ~PK_ORIENTATION;
383
384               if (gdkdev->pktdata & PK_ORIENTATION)
385                 gdkdev->info.num_axes += 2; /* x and y tilt */
386               WTInfo (WTI_CURSORS + cursorix, CSR_NPBTNMARKS, &gdkdev->npbtnmarks);
387               gdkdev->info.axes = g_new (GdkDeviceAxis, gdkdev->info.num_axes);
388               gdkdev->axes = g_new (GdkAxisInfo, gdkdev->info.num_axes);
389               gdkdev->last_axis_data = g_new (gint, gdkdev->info.num_axes);
390               
391               k = 0;
392               if (gdkdev->pktdata & PK_X)
393                 {
394                   gdkdev->axes[k].xresolution =
395                     gdkdev->axes[k].resolution = axis_x.axResolution / 65535.;
396                   gdkdev->axes[k].xmin_value =
397                     gdkdev->axes[k].min_value = axis_x.axMin;
398                   gdkdev->axes[k].xmax_value =
399                     gdkdev->axes[k].max_value = axis_x.axMax;
400                   gdkdev->info.axes[k].use = GDK_AXIS_X;
401                   gdkdev->info.axes[k].min = axis_x.axMin;
402                   gdkdev->info.axes[k].min = axis_x.axMax;
403                   k++;
404                 }
405               if (gdkdev->pktdata & PK_Y)
406                 {
407                   gdkdev->axes[k].xresolution =
408                     gdkdev->axes[k].resolution = axis_y.axResolution / 65535.;
409                   gdkdev->axes[k].xmin_value =
410                     gdkdev->axes[k].min_value = axis_y.axMin;
411                   gdkdev->axes[k].xmax_value =
412                     gdkdev->axes[k].max_value = axis_y.axMax;
413                   gdkdev->info.axes[k].use = GDK_AXIS_Y;
414                   gdkdev->info.axes[k].min = axis_y.axMin;
415                   gdkdev->info.axes[k].min = axis_y.axMax;
416                   k++;
417                 }
418               if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
419                 {
420                   gdkdev->axes[k].xresolution =
421                     gdkdev->axes[k].resolution = axis_npressure.axResolution / 65535.;
422                   gdkdev->axes[k].xmin_value =
423                     gdkdev->axes[k].min_value = axis_npressure.axMin;
424                   gdkdev->axes[k].xmax_value =
425                     gdkdev->axes[k].max_value = axis_npressure.axMax;
426                   gdkdev->info.axes[k].use = GDK_AXIS_PRESSURE;
427                   gdkdev->info.axes[k].min = axis_npressure.axMin;
428                   gdkdev->info.axes[k].min = axis_npressure.axMax;
429                   k++;
430                 }
431               if (gdkdev->pktdata & PK_ORIENTATION)
432                 {
433                   GdkAxisUse axis;
434
435                   gdkdev->orientation_axes[0] = axis_or[0];
436                   gdkdev->orientation_axes[1] = axis_or[1];
437                   for (axis = GDK_AXIS_XTILT; axis <= GDK_AXIS_YTILT; axis++)
438                     {
439                       /* Wintab gives us aximuth and altitude, which
440                        * we convert to x and y tilt in the -1000..1000 range
441                        */
442                       gdkdev->axes[k].xresolution =
443                         gdkdev->axes[k].resolution = 1000;
444                       gdkdev->axes[k].xmin_value =
445                         gdkdev->axes[k].min_value = -1000;
446                       gdkdev->axes[k].xmax_value =
447                         gdkdev->axes[k].max_value = 1000;
448                       gdkdev->info.axes[k].use = axis;
449                       gdkdev->info.axes[k].min = -1000;
450                       gdkdev->info.axes[k].min = 1000;
451                       k++;
452                     }
453                 }
454               gdkdev->info.num_keys = 0;
455               gdkdev->info.keys = NULL;
456               GDK_NOTE (INPUT,
457                         g_print ("device: (%d) %s axes: %d\n",
458                                  cursorix,
459                                  gdkdev->info.name,
460                                  gdkdev->info.num_axes));
461               for (i = 0; i < gdkdev->info.num_axes; i++)
462                 GDK_NOTE (INPUT,
463                           g_print ("...axis %d: %d--%d@%d (%d--%d@%d)\n",
464                                    i,
465                                    gdkdev->axes[i].xmin_value, 
466                                    gdkdev->axes[i].xmax_value, 
467                                    gdkdev->axes[i].xresolution, 
468                                    gdkdev->axes[i].min_value, 
469                                    gdkdev->axes[i].max_value, 
470                                    gdkdev->axes[i].resolution));
471               _gdk_input_devices = g_list_append (_gdk_input_devices,
472                                                  gdkdev);
473             }
474         }
475     }
476 }
477
478 static void
479 decode_tilt (gint   *axis_data,
480              AXIS   *axes,
481              PACKET *packet)
482 {
483   /* As I don't have a tilt-sensing tablet,
484    * I cannot test this code.
485    */
486   
487   double az, el;
488
489   az = TWOPI * packet->pkOrientation.orAzimuth /
490     (axes[0].axResolution / 65536.);
491   el = TWOPI * packet->pkOrientation.orAltitude /
492     (axes[1].axResolution / 65536.);
493   
494   /* X tilt */
495   axis_data[0] = cos (az) * cos (el) * 1000;
496   /* Y tilt */
497   axis_data[1] = sin (az) * cos (el) * 1000;
498 }
499
500 #if !USE_SYSCONTEXT
501
502 static GdkInputWindow *
503 gdk_input_window_find_within (GdkWindow *window)
504 {
505   GList *list;
506   GdkWindow *tmpw;
507   GdkInputWindow *candidate = NULL;
508
509   for (list = _gdk_input_windows; list != NULL; list = list->next)
510     {
511       tmpw = ((GdkInputWindow *) (tmp_list->data))->window;
512       if (tmpw == window
513           || IsChild (GDK_WINDOW_HWND (window), GDK_WINDOW_HWND (tmpw)))
514         {
515           if (candidate)
516             return NULL;                /* Multiple hits */
517           candidate = (GdkInputWindow *) (list->data);
518         }
519     }
520
521   return candidate;
522 }
523
524 #endif /* USE_SYSCONTEXT */
525
526 #endif /* HAVE_WINTAB */
527
528 static void
529 gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
530                                  GdkInputWindow   *input_window,
531                                  gint             *axis_data,
532                                  gdouble          *axis_out,
533                                  gdouble          *x_out,
534                                  gdouble          *y_out)
535 {
536   GdkWindowImplWin32 *impl;
537
538   int i;
539   int x_axis = 0;
540   int y_axis = 0;
541
542   double device_width, device_height;
543   double x_offset, y_offset, x_scale, y_scale;
544
545   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (input_window->window)->impl);
546
547   for (i=0; i<gdkdev->info.num_axes; i++)
548     {
549       switch (gdkdev->info.axes[i].use)
550         {
551         case GDK_AXIS_X:
552           x_axis = i;
553           break;
554         case GDK_AXIS_Y:
555           y_axis = i;
556           break;
557         default:
558           break;
559         }
560     }
561   
562   device_width = gdkdev->axes[x_axis].max_value - 
563                    gdkdev->axes[x_axis].min_value;
564   device_height = gdkdev->axes[y_axis].max_value - 
565                     gdkdev->axes[y_axis].min_value;
566
567   if (gdkdev->info.mode == GDK_MODE_SCREEN) 
568     {
569       x_scale = GetSystemMetrics (SM_CXSCREEN) / device_width;
570       y_scale = GetSystemMetrics (SM_CYSCREEN) / device_height;
571
572       x_offset = - input_window->root_x;
573       y_offset = - input_window->root_y;
574     }
575   else                          /* GDK_MODE_WINDOW */
576     {
577       double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
578         (device_width*gdkdev->axes[x_axis].resolution);
579
580       if (device_aspect * impl->width >= impl->height)
581         {
582           /* device taller than window */
583           x_scale = impl->width / device_width;
584           y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
585             / gdkdev->axes[y_axis].resolution;
586
587           x_offset = 0;
588           y_offset = -(device_height * y_scale - 
589                                impl->height)/2;
590         }
591       else
592         {
593           /* window taller than device */
594           y_scale = impl->height / device_height;
595           x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
596             / gdkdev->axes[x_axis].resolution;
597
598           y_offset = 0;
599           x_offset = - (device_width * x_scale - impl->width)/2;
600         }
601     }
602
603   for (i=0; i<gdkdev->info.num_axes; i++)
604     {
605       switch (gdkdev->info.axes[i].use)
606         {
607         case GDK_AXIS_X:
608           axis_out[i] = x_offset + x_scale*axis_data[x_axis];
609           if (x_out)
610             *x_out = axis_out[i];
611           break;
612         case GDK_AXIS_Y:
613           axis_out[i] = y_offset + y_scale*axis_data[y_axis];
614           if (y_out)
615             *y_out = axis_out[i];
616           break;
617         default:
618           axis_out[i] =
619             (gdkdev->info.axes[i].max * (axis_data[i] - gdkdev->axes[i].min_value) +
620              gdkdev->info.axes[i].min * (gdkdev->axes[i].max_value - axis_data[i])) /
621             (gdkdev->axes[i].max_value - gdkdev->axes[i].min_value);
622           break;
623         }
624     }
625 }
626
627 static void
628 gdk_input_get_root_relative_geometry (HWND w,
629                                       int  *x_ret,
630                                       int  *y_ret)
631 {
632   RECT rect;
633
634   GetWindowRect (w, &rect);
635
636   if (x_ret)
637     *x_ret = rect.left;
638   if (y_ret)
639     *y_ret = rect.top;
640 }
641
642 GdkTimeCoord *
643 gdk_input_motion_events (GdkWindow *window,
644                          guint32    deviceid,
645                          guint32    start,
646                          guint32    stop,
647                          gint      *nevents_return)
648 {
649   g_return_val_if_fail (window != NULL, NULL);
650   if (GDK_WINDOW_DESTROYED (window))
651     return NULL;
652
653   *nevents_return = 0;
654   return NULL;          /* ??? */
655 }
656
657 void
658 _gdk_input_configure_event (GdkWindow         *window)
659 {
660   GdkInputWindow *input_window;
661   int root_x, root_y;
662
663   input_window = _gdk_input_window_find (window);
664   g_return_if_fail (window != NULL);
665
666   gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window),
667                                         &root_x, &root_y);
668
669   input_window->root_x = root_x;
670   input_window->root_y = root_y;
671 }
672
673 void 
674 _gdk_input_enter_event (GdkWindow        *window)
675 {
676   GdkInputWindow *input_window;
677   int root_x, root_y;
678
679   input_window = _gdk_input_window_find (window);
680   g_return_if_fail (window != NULL);
681
682   gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window), &root_x, &root_y);
683
684   input_window->root_x = root_x;
685   input_window->root_y = root_y;
686 }
687
688 gboolean 
689 _gdk_input_other_event (GdkEvent  *event,
690                         MSG       *msg,
691                         GdkWindow *window)
692 {
693 #ifdef HAVE_WINTAB
694 #if !USE_SYSCONTEXT
695   GdkWindow *current_window;
696 #endif
697   GdkDisplay *display;
698   GdkWindowObject *obj;
699   GdkWindowImplWin32 *impl;
700   GdkInputWindow *input_window;
701   GdkDevicePrivate *gdkdev = NULL;
702   GdkEventMask masktest;
703   POINT pt;
704
705   PACKET packet;
706   gint k;
707   gint x, y;
708
709   if (event->any.window != wintab_window)
710     {
711       g_warning ("_gdk_input_other_event: not wintab_window?");
712       return FALSE;
713     }
714
715 #if USE_SYSCONTEXT
716   window = gdk_window_at_pointer (&x, &y);
717   if (window == NULL)
718     window = _gdk_parent_root;
719
720   g_object_ref (window);
721   display = gdk_drawable_get_display (window);
722
723   GDK_NOTE (EVENTS_OR_INPUT,
724             g_print ("gdk_input_win32_other_event: window=%p (%d,%d)\n",
725                      GDK_WINDOW_HWND (window), x, y));
726   
727 #else
728   /* ??? This code is pretty bogus */
729   current_window = gdk_win32_handle_table_lookup (GetActiveWindow ());
730   if (current_window == NULL)
731     return FALSE;
732   
733   input_window = gdk_input_window_find_within (current_window);
734   if (input_window == NULL)
735     return FALSE;
736 #endif
737
738   if (msg->message == WT_PACKET)
739     {
740       if (!WTPacket ((HCTX) msg->lParam, msg->wParam, &packet))
741         return FALSE;
742     }
743
744   obj = GDK_WINDOW_OBJECT (window);
745   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
746
747   switch (msg->message)
748     {
749     case WT_PACKET:
750       if (window == _gdk_parent_root)
751         {
752           GDK_NOTE (EVENTS_OR_INPUT, g_print ("...is root\n"));
753           return FALSE;
754         }
755
756       if ((gdkdev = gdk_input_find_dev_from_ctx ((HCTX) msg->lParam,
757                                                  packet.pkCursor)) == NULL)
758         return FALSE;
759
760       if (gdkdev->info.mode == GDK_MODE_DISABLED)
761         return FALSE;
762       
763       k = 0;
764       if (gdkdev->pktdata & PK_X)
765         gdkdev->last_axis_data[k++] = packet.pkX;
766       if (gdkdev->pktdata & PK_Y)
767         gdkdev->last_axis_data[k++] = packet.pkY;
768       if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
769         gdkdev->last_axis_data[k++] = packet.pkNormalPressure;
770       if (gdkdev->pktdata & PK_ORIENTATION)
771         {
772           decode_tilt (gdkdev->last_axis_data + k,
773                        gdkdev->orientation_axes, &packet);
774           k += 2;
775         }
776
777       g_assert (k == gdkdev->info.num_axes);
778
779       if (HIWORD (packet.pkButtons) != TBN_NONE)
780         {
781           /* Gdk buttons are numbered 1.. */
782           event->button.button = 1 + LOWORD (packet.pkButtons);
783
784           if (HIWORD (packet.pkButtons) == TBN_UP)
785             {
786               event->any.type = GDK_BUTTON_RELEASE;
787               masktest = GDK_BUTTON_RELEASE_MASK;
788               gdkdev->button_state &= ~(1 << LOWORD (packet.pkButtons));
789             }
790           else
791             {
792               event->any.type = GDK_BUTTON_PRESS;
793               masktest = GDK_BUTTON_PRESS_MASK;
794               gdkdev->button_state |= 1 << LOWORD (packet.pkButtons);
795             }
796         }
797       else
798         {
799           event->any.type = GDK_MOTION_NOTIFY;
800           masktest = GDK_POINTER_MOTION_MASK;
801           if (gdkdev->button_state & (1 << 0))
802             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK;
803           if (gdkdev->button_state & (1 << 1))
804             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK;
805           if (gdkdev->button_state & (1 << 2))
806             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK;
807         }
808
809       /* Now we can check if the window wants the event, and
810        * propagate if necessary.
811        */
812     dijkstra:
813       if (!impl->extension_events_selected
814           || !(obj->extension_events & masktest))
815         {
816           GDK_NOTE (EVENTS_OR_INPUT, g_print ("...not selected\n"));
817
818           if (obj->parent == GDK_WINDOW_OBJECT (_gdk_parent_root))
819             return FALSE;
820           
821           pt.x = x;
822           pt.y = y;
823           ClientToScreen (GDK_WINDOW_HWND (window), &pt);
824           g_object_unref (window);
825           window = (GdkWindow *) obj->parent;
826           obj = GDK_WINDOW_OBJECT (window);
827           g_object_ref (window);
828           ScreenToClient (GDK_WINDOW_HWND (window), &pt);
829           x = pt.x;
830           y = pt.y;
831           GDK_NOTE (EVENTS_OR_INPUT, g_print ("...propagating to %p (%d,%d)\n",
832                                               GDK_WINDOW_HWND (window), x, y));
833           goto dijkstra;
834         }
835
836       input_window = _gdk_input_window_find (window);
837
838       g_assert (input_window != NULL);
839
840       if (gdkdev->info.mode == GDK_MODE_WINDOW
841           && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
842         return FALSE;
843
844       event->any.window = window;
845
846       if (event->any.type == GDK_BUTTON_PRESS
847           || event->any.type == GDK_BUTTON_RELEASE)
848         {
849           event->button.time = _gdk_win32_get_next_tick (msg->time);
850           event->button.device = &gdkdev->info;
851           
852 #if 0
853 #if USE_SYSCONTEXT
854           /* Buttons 1 to 3 will come in as WM_[LMR]BUTTON{DOWN,UP} */
855           if (event->button.button <= 3)
856             return FALSE;
857 #endif
858 #endif
859           gdk_input_translate_coordinates (gdkdev, input_window,
860                                            gdkdev->last_axis_data,
861                                            event->button.axes,
862                                            &event->button.x, 
863                                            &event->button.y);
864
865           event->button.state = ((gdkdev->button_state << 8)
866                                  & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
867                                     | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
868                                     | GDK_BUTTON5_MASK));
869           GDK_NOTE (EVENTS_OR_INPUT,
870                     g_print ("WINTAB button %s:%d %g,%g\n",
871                              (event->button.type == GDK_BUTTON_PRESS ?
872                               "press" : "release"),
873                              event->button.button,
874                              event->button.x, event->button.y));
875         }
876       else
877         {
878           event->motion.time = _gdk_win32_get_next_tick (msg->time);
879           event->motion.is_hint = FALSE;
880           event->motion.device = &gdkdev->info;
881
882           gdk_input_translate_coordinates (gdkdev, input_window,
883                                            gdkdev->last_axis_data,
884                                            event->motion.axes,
885                                            &event->motion.x, 
886                                            &event->motion.y);
887
888           event->motion.state = ((gdkdev->button_state << 8)
889                                  & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
890                                     | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
891                                     | GDK_BUTTON5_MASK));
892
893           GDK_NOTE (EVENTS_OR_INPUT,
894                     g_print ("WINTAB motion: %g,%g\n",
895                              event->motion.x, event->motion.y));
896
897           /* Check for missing release or press events for the normal
898            * pressure button. At least on my ArtPadII I sometimes miss a
899            * release event?
900            */
901           if ((gdkdev->pktdata & PK_NORMAL_PRESSURE
902                && (event->motion.state & GDK_BUTTON1_MASK)
903                && packet.pkNormalPressure <= MAX (0, gdkdev->npbtnmarks[0] - 2))
904               || (gdkdev->pktdata & PK_NORMAL_PRESSURE
905                   && !(event->motion.state & GDK_BUTTON1_MASK)
906                   && packet.pkNormalPressure > gdkdev->npbtnmarks[1] + 2))
907             {
908               GdkEvent *event2 = gdk_event_copy (event);
909               if (event->motion.state & GDK_BUTTON1_MASK)
910                 {
911                   event2->button.type = GDK_BUTTON_RELEASE;
912                   gdkdev->button_state &= ~1;
913                 }
914               else
915                 {
916                   event2->button.type = GDK_BUTTON_PRESS;
917                   gdkdev->button_state |= 1;
918                 }
919               event2->button.state = ((gdkdev->button_state << 8)
920                                       & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
921                                          | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
922                                          | GDK_BUTTON5_MASK));
923               event2->button.button = 1;
924               GDK_NOTE (EVENTS_OR_INPUT,
925                         g_print ("WINTAB synthesized button %s: %d %g,%gg\n",
926                                  (event2->button.type == GDK_BUTTON_PRESS ?
927                                   "press" : "release"),
928                                  event2->button.button,
929                                  event2->button.x,
930                                  event2->button.y));
931               _gdk_event_queue_append (display, event2);
932             }
933         }
934       return TRUE;
935
936     case WT_PROXIMITY:
937       if (LOWORD (msg->lParam) == 0)
938         {
939           event->proximity.type = GDK_PROXIMITY_OUT;
940           _gdk_input_ignore_core = FALSE;
941         }
942       else
943         {
944           event->proximity.type = GDK_PROXIMITY_IN;
945           _gdk_input_ignore_core = TRUE;
946         }
947       event->proximity.time = _gdk_win32_get_next_tick (msg->time);
948       event->proximity.device = &gdkdev->info;
949
950       GDK_NOTE (EVENTS_OR_INPUT,
951                 g_print ("WINTAB proximity %s\n",
952                          (event->proximity.type == GDK_PROXIMITY_IN ?
953                           "in" : "out")));
954       return TRUE;
955     }
956 #endif
957   return FALSE;
958 }
959
960 gboolean
961 _gdk_input_enable_window (GdkWindow        *window,
962                           GdkDevicePrivate *gdkdev)
963 {
964 #ifdef HAVE_SOME_XINPUT
965   GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
966
967   impl->extension_events_selected = TRUE;
968 #endif
969
970   return TRUE;
971 }
972
973 gboolean
974 _gdk_input_disable_window (GdkWindow        *window,
975                            GdkDevicePrivate *gdkdev)
976 {
977 #ifdef HAVE_SOME_XINPUT
978   GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
979
980   impl->extension_events_selected = FALSE;
981 #endif
982
983   return TRUE;
984 }
985
986 gint
987 _gdk_input_grab_pointer (GdkWindow    *window,
988                          gint          owner_events,
989                          GdkEventMask  event_mask,
990                          GdkWindow    *confine_to,
991                          guint32       time)
992 {
993 #ifdef HAVE_SOME_XINPUT
994   GdkInputWindow *input_window, *new_window;
995   gboolean need_ungrab;
996   GdkDevicePrivate *gdkdev;
997   GList *tmp_list;
998
999   tmp_list = _gdk_input_windows;
1000   new_window = NULL;
1001   need_ungrab = FALSE;
1002
1003   GDK_NOTE (INPUT, g_print ("gdk_input_win32_grab_pointer: %p %d %p\n",
1004                            GDK_WINDOW_HWND (window),
1005                            owner_events,
1006                            (confine_to ? GDK_WINDOW_HWND (confine_to) : 0)));
1007
1008   while (tmp_list)
1009     {
1010       input_window = (GdkInputWindow *)tmp_list->data;
1011
1012       if (input_window->window == window)
1013         new_window = input_window;
1014       else if (input_window->grabbed)
1015         {
1016           input_window->grabbed = FALSE;
1017           need_ungrab = TRUE;
1018         }
1019
1020       tmp_list = tmp_list->next;
1021     }
1022
1023   if (new_window)
1024     {
1025       new_window->grabbed = TRUE;
1026       
1027       tmp_list = _gdk_input_devices;
1028       while (tmp_list)
1029         {
1030           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1031           if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx)
1032             {
1033 #if 0         
1034               /* XXX */
1035               gdk_input_common_find_events (window, gdkdev,
1036                                             event_mask,
1037                                             event_classes, &num_classes);
1038               
1039               result = XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
1040                                     GDK_WINDOW_XWINDOW (window),
1041                                     owner_events, num_classes, event_classes,
1042                                     GrabModeAsync, GrabModeAsync, time);
1043               
1044               /* FIXME: if failure occurs on something other than the first
1045                  device, things will be badly inconsistent */
1046               if (result != Success)
1047                 return result;
1048 #endif
1049             }
1050           tmp_list = tmp_list->next;
1051         }
1052     }
1053   else
1054     { 
1055       tmp_list = _gdk_input_devices;
1056       while (tmp_list)
1057         {
1058           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1059           if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx &&
1060               ((gdkdev->button_state != 0) || need_ungrab))
1061             {
1062 #if 0
1063               /* XXX */
1064               XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1065 #endif
1066               gdkdev->button_state = 0;
1067             }
1068           
1069           tmp_list = tmp_list->next;
1070         }
1071     }
1072 #endif
1073
1074   return GDK_GRAB_SUCCESS;
1075 }
1076
1077 void 
1078 _gdk_input_ungrab_pointer (guint32 time)
1079 {
1080 #ifdef HAVE_SOME_XINPUT
1081   GdkInputWindow *input_window;
1082   GdkDevicePrivate *gdkdev;
1083   GList *tmp_list;
1084
1085   GDK_NOTE (INPUT, g_print ("gdk_input_win32_ungrab_pointer\n"));
1086
1087   tmp_list = _gdk_input_windows;
1088   while (tmp_list)
1089     {
1090       input_window = (GdkInputWindow *)tmp_list->data;
1091       if (input_window->grabbed)
1092         break;
1093       tmp_list = tmp_list->next;
1094     }
1095
1096   if (tmp_list)                 /* we found a grabbed window */
1097     {
1098       input_window->grabbed = FALSE;
1099
1100       tmp_list = _gdk_input_devices;
1101       while (tmp_list)
1102         {
1103           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1104 #if 0
1105           /* XXX */
1106           if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
1107             XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1108 #endif
1109           tmp_list = tmp_list->next;
1110         }
1111     }
1112 #endif
1113 }
1114
1115 gboolean
1116 _gdk_device_get_history (GdkDevice         *device,
1117                          GdkWindow         *window,
1118                          guint32            start,
1119                          guint32            stop,
1120                          GdkTimeCoord    ***events,
1121                          gint              *n_events)
1122 {
1123   return FALSE;
1124 }
1125
1126 void 
1127 gdk_device_get_state (GdkDevice       *device,
1128                       GdkWindow       *window,
1129                       gdouble         *axes,
1130                       GdkModifierType *mask)
1131 {
1132   g_return_if_fail (device != NULL);
1133   g_return_if_fail (GDK_IS_WINDOW (window));
1134
1135   if (GDK_IS_CORE (device))
1136     {
1137       gint x_int, y_int;
1138       
1139       gdk_window_get_pointer (window, &x_int, &y_int, mask);
1140
1141       if (axes)
1142         {
1143           axes[0] = x_int;
1144           axes[1] = y_int;
1145         }
1146     }
1147   else
1148     {
1149       GdkDevicePrivate *gdkdev;
1150       GdkInputWindow *input_window;
1151       
1152       if (mask)
1153         gdk_window_get_pointer (window, NULL, NULL, mask);
1154       
1155       gdkdev = (GdkDevicePrivate *)device;
1156       input_window = _gdk_input_window_find (window);
1157       g_return_if_fail (input_window != NULL);
1158
1159 #if 0 /* FIXME */
1160       state = XQueryDeviceState (gdk_display, gdkdev->xdevice);
1161       input_class = state->data;
1162       for (i = 0; i < state->num_classes; i++)
1163         {
1164           switch (input_class->class)
1165             {
1166             case ValuatorClass:
1167               if (axes)
1168                 gdk_input_translate_coordinates (gdkdev, input_window,
1169                                                  ((XValuatorState *)input_class)->valuators,
1170                                                  axes, NULL, NULL);
1171               break;
1172               
1173             case ButtonClass:
1174               if (mask)
1175                 {
1176                   *mask &= 0xFF;
1177                   if (((XButtonState *)input_class)->num_buttons > 0)
1178                     *mask |= ((XButtonState *)input_class)->buttons[0] << 7;
1179                   /* GDK_BUTTON1_MASK = 1 << 8, and button n is stored
1180                    * in bit 1<<(n%8) in byte n/8. n = 1,2,... */
1181                 }
1182               break;
1183             }
1184           input_class = (XInputClass *)(((char *)input_class)+input_class->length);
1185         }
1186       XFreeDeviceState (state);
1187 #endif
1188     }
1189 }
1190
1191 void 
1192 _gdk_input_init (GdkDisplay *display)
1193 {
1194   _gdk_input_ignore_core = FALSE;
1195   _gdk_input_devices = NULL;
1196
1197   _gdk_init_input_core (display);
1198 #ifdef HAVE_WINTAB
1199   gdk_input_wintab_init ();
1200 #endif /* HAVE_WINTAB */
1201
1202   _gdk_input_devices = g_list_append (_gdk_input_devices, display->core_pointer);
1203 }
1204