]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkinput-win32.c
Make the core pointer object per-display. (#85698)
[~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_init: gdk_window_new failed");
250           return;
251         }
252       gdk_drawable_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_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 = gdk_screen_width() / device_width;
570       y_scale = gdk_screen_height() / 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 (GdkEventConfigure *event,
659                             GdkWindow         *window)
660 {
661   GdkInputWindow *input_window;
662   int root_x, root_y;
663
664   input_window = gdk_input_window_find (window);
665   g_return_if_fail (window != NULL);
666
667   gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window),
668                                         &root_x, &root_y);
669
670   input_window->root_x = root_x;
671   input_window->root_y = root_y;
672 }
673
674 void 
675 _gdk_input_enter_event (GdkEventCrossing *event, 
676                         GdkWindow        *window)
677 {
678   GdkInputWindow *input_window;
679   int root_x, root_y;
680
681   input_window = gdk_input_window_find (window);
682   g_return_if_fail (window != NULL);
683
684   gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window), &root_x, &root_y);
685
686   input_window->root_x = root_x;
687   input_window->root_y = root_y;
688 }
689
690 gint 
691 _gdk_input_other_event (GdkEvent  *event,
692                         MSG       *msg,
693                         GdkWindow *window)
694 {
695 #ifdef HAVE_WINTAB
696 #if !USE_SYSCONTEXT
697   GdkWindow *current_window;
698 #endif
699   GdkDisplay *display;
700   GdkWindowObject *obj;
701   GdkWindowImplWin32 *impl;
702   GdkInputWindow *input_window;
703   GdkDevicePrivate *gdkdev = NULL;
704   GdkEventMask masktest;
705   POINT pt;
706
707   PACKET packet;
708   gint k;
709   gint x, y;
710
711   if (event->any.window != wintab_window)
712     {
713       g_warning ("_gdk_input_other_event: not wintab_window?");
714       return FALSE;
715     }
716
717 #if USE_SYSCONTEXT
718   window = gdk_window_at_pointer (&x, &y);
719   if (window == NULL)
720     window = _gdk_parent_root;
721
722   gdk_drawable_ref (window);
723   display = gdk_drawable_get_display (window);
724
725   GDK_NOTE (EVENTS_OR_INPUT,
726             g_print ("gdk_input_win32_other_event: window=%p (%d,%d)\n",
727                      GDK_WINDOW_HWND (window), x, y));
728   
729 #else
730   /* ??? This code is pretty bogus */
731   current_window = gdk_win32_handle_table_lookup (GetActiveWindow ());
732   if (current_window == NULL)
733     return FALSE;
734   
735   input_window = gdk_input_window_find_within (current_window);
736   if (input_window == NULL)
737     return FALSE;
738 #endif
739
740   if (msg->message == WT_PACKET)
741     {
742       if (!WTPacket ((HCTX) msg->lParam, msg->wParam, &packet))
743         return FALSE;
744     }
745
746   obj = GDK_WINDOW_OBJECT (window);
747   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
748
749   switch (msg->message)
750     {
751     case WT_PACKET:
752       if (window == _gdk_parent_root)
753         {
754           GDK_NOTE (EVENTS_OR_INPUT, g_print ("...is root\n"));
755           return FALSE;
756         }
757
758       if ((gdkdev = gdk_input_find_dev_from_ctx ((HCTX) msg->lParam,
759                                                  packet.pkCursor)) == NULL)
760         return FALSE;
761
762       if (gdkdev->info.mode == GDK_MODE_DISABLED)
763         return FALSE;
764       
765       k = 0;
766       if (gdkdev->pktdata & PK_X)
767         gdkdev->last_axis_data[k++] = packet.pkX;
768       if (gdkdev->pktdata & PK_Y)
769         gdkdev->last_axis_data[k++] = packet.pkY;
770       if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
771         gdkdev->last_axis_data[k++] = packet.pkNormalPressure;
772       if (gdkdev->pktdata & PK_ORIENTATION)
773         {
774           decode_tilt (gdkdev->last_axis_data + k,
775                        gdkdev->orientation_axes, &packet);
776           k += 2;
777         }
778
779       g_assert (k == gdkdev->info.num_axes);
780
781       if (HIWORD (packet.pkButtons) != TBN_NONE)
782         {
783           /* Gdk buttons are numbered 1.. */
784           event->button.button = 1 + LOWORD (packet.pkButtons);
785
786           if (HIWORD (packet.pkButtons) == TBN_UP)
787             {
788               event->any.type = GDK_BUTTON_RELEASE;
789               masktest = GDK_BUTTON_RELEASE_MASK;
790               gdkdev->button_state &= ~(1 << LOWORD (packet.pkButtons));
791             }
792           else
793             {
794               event->any.type = GDK_BUTTON_PRESS;
795               masktest = GDK_BUTTON_PRESS_MASK;
796               gdkdev->button_state |= 1 << LOWORD (packet.pkButtons);
797             }
798         }
799       else
800         {
801           event->any.type = GDK_MOTION_NOTIFY;
802           masktest = GDK_POINTER_MOTION_MASK;
803           if (gdkdev->button_state & (1 << 0))
804             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK;
805           if (gdkdev->button_state & (1 << 1))
806             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK;
807           if (gdkdev->button_state & (1 << 2))
808             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK;
809         }
810
811       /* Now we can check if the window wants the event, and
812        * propagate if necessary.
813        */
814     dijkstra:
815       if (!impl->extension_events_selected
816           || !(obj->extension_events & masktest))
817         {
818           GDK_NOTE (EVENTS_OR_INPUT, g_print ("...not selected\n"));
819
820           if (obj->parent == GDK_WINDOW_OBJECT (_gdk_parent_root))
821             return FALSE;
822           
823           pt.x = x;
824           pt.y = y;
825           ClientToScreen (GDK_WINDOW_HWND (window), &pt);
826           gdk_drawable_unref (window);
827           window = (GdkWindow *) obj->parent;
828           obj = GDK_WINDOW_OBJECT (window);
829           gdk_drawable_ref (window);
830           ScreenToClient (GDK_WINDOW_HWND (window), &pt);
831           x = pt.x;
832           y = pt.y;
833           GDK_NOTE (EVENTS_OR_INPUT, g_print ("...propagating to %p (%d,%d)\n",
834                                               GDK_WINDOW_HWND (window), x, y));
835           goto dijkstra;
836         }
837
838       input_window = gdk_input_window_find (window);
839
840       g_assert (input_window != NULL);
841
842       if (gdkdev->info.mode == GDK_MODE_WINDOW
843           && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
844         return FALSE;
845
846       event->any.window = window;
847
848       if (event->any.type == GDK_BUTTON_PRESS
849           || event->any.type == GDK_BUTTON_RELEASE)
850         {
851           event->button.time = msg->time;
852           event->button.device = &gdkdev->info;
853           
854 #if 0
855 #if USE_SYSCONTEXT
856           /* Buttons 1 to 3 will come in as WM_[LMR]BUTTON{DOWN,UP} */
857           if (event->button.button <= 3)
858             return FALSE;
859 #endif
860 #endif
861           gdk_input_translate_coordinates (gdkdev, input_window,
862                                            gdkdev->last_axis_data,
863                                            event->button.axes,
864                                            &event->button.x, 
865                                            &event->button.y);
866
867           event->button.state = ((gdkdev->button_state << 8)
868                                  & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
869                                     | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
870                                     | GDK_BUTTON5_MASK));
871           GDK_NOTE (EVENTS_OR_INPUT,
872                     g_print ("WINTAB button %s:%d %g,%g\n",
873                              (event->button.type == GDK_BUTTON_PRESS ?
874                               "press" : "release"),
875                              event->button.button,
876                              event->button.x, event->button.y));
877         }
878       else
879         {
880           event->motion.time = msg->time;
881           event->motion.is_hint = FALSE;
882           event->motion.device = &gdkdev->info;
883
884           gdk_input_translate_coordinates (gdkdev, input_window,
885                                            gdkdev->last_axis_data,
886                                            event->motion.axes,
887                                            &event->motion.x, 
888                                            &event->motion.y);
889
890           event->motion.state = ((gdkdev->button_state << 8)
891                                  & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
892                                     | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
893                                     | GDK_BUTTON5_MASK));
894
895           GDK_NOTE (EVENTS_OR_INPUT,
896                     g_print ("WINTAB motion: %g,%g\n",
897                              event->motion.x, event->motion.y));
898
899           /* Check for missing release or press events for the normal
900            * pressure button. At least on my ArtPadII I sometimes miss a
901            * release event?
902            */
903           if ((gdkdev->pktdata & PK_NORMAL_PRESSURE
904                && (event->motion.state & GDK_BUTTON1_MASK)
905                && packet.pkNormalPressure <= MAX (0, gdkdev->npbtnmarks[0] - 2))
906               || (gdkdev->pktdata & PK_NORMAL_PRESSURE
907                   && !(event->motion.state & GDK_BUTTON1_MASK)
908                   && packet.pkNormalPressure > gdkdev->npbtnmarks[1] + 2))
909             {
910               GdkEvent *event2 = gdk_event_copy (event);
911               if (event->motion.state & GDK_BUTTON1_MASK)
912                 {
913                   event2->button.type = GDK_BUTTON_RELEASE;
914                   gdkdev->button_state &= ~1;
915                 }
916               else
917                 {
918                   event2->button.type = GDK_BUTTON_PRESS;
919                   gdkdev->button_state |= 1;
920                 }
921               event2->button.state = ((gdkdev->button_state << 8)
922                                       & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
923                                          | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
924                                          | GDK_BUTTON5_MASK));
925               event2->button.button = 1;
926               GDK_NOTE (EVENTS_OR_INPUT,
927                         g_print ("WINTAB synthesized button %s: %d %g,%gg\n",
928                                  (event2->button.type == GDK_BUTTON_PRESS ?
929                                   "press" : "release"),
930                                  event2->button.button,
931                                  event2->button.x,
932                                  event2->button.y));
933               _gdk_event_queue_append (display, event2);
934             }
935         }
936       return TRUE;
937
938     case WT_PROXIMITY:
939       if (LOWORD (msg->lParam) == 0)
940         {
941           event->proximity.type = GDK_PROXIMITY_OUT;
942           _gdk_input_ignore_core = FALSE;
943         }
944       else
945         {
946           event->proximity.type = GDK_PROXIMITY_IN;
947           _gdk_input_ignore_core = TRUE;
948         }
949       event->proximity.time = msg->time;
950       event->proximity.device = &gdkdev->info;
951
952       GDK_NOTE (EVENTS_OR_INPUT,
953                 g_print ("WINTAB proximity %s\n",
954                          (event->proximity.type == GDK_PROXIMITY_IN ?
955                           "in" : "out")));
956       return TRUE;
957     }
958 #endif
959   return -1;
960 }
961
962 gboolean
963 _gdk_input_enable_window (GdkWindow        *window,
964                           GdkDevicePrivate *gdkdev)
965 {
966 #ifdef HAVE_SOME_XINPUT
967   GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
968
969   impl->extension_events_selected = TRUE;
970 #endif
971
972   return TRUE;
973 }
974
975 gboolean
976 _gdk_input_disable_window (GdkWindow        *window,
977                            GdkDevicePrivate *gdkdev)
978 {
979 #ifdef HAVE_SOME_XINPUT
980   GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
981
982   impl->extension_events_selected = FALSE;
983 #endif
984
985   return TRUE;
986 }
987
988 gint
989 _gdk_input_grab_pointer (GdkWindow    *window,
990                          gint          owner_events,
991                          GdkEventMask  event_mask,
992                          GdkWindow    *confine_to,
993                          guint32       time)
994 {
995 #ifdef HAVE_SOME_XINPUT
996   GdkInputWindow *input_window, *new_window;
997   gboolean need_ungrab;
998   GdkDevicePrivate *gdkdev;
999   GList *tmp_list;
1000
1001   tmp_list = _gdk_input_windows;
1002   new_window = NULL;
1003   need_ungrab = FALSE;
1004
1005   GDK_NOTE (INPUT, g_print ("gdk_input_win32_grab_pointer: %p %d %p\n",
1006                            GDK_WINDOW_HWND (window),
1007                            owner_events,
1008                            (confine_to ? GDK_WINDOW_HWND (confine_to) : 0)));
1009
1010   while (tmp_list)
1011     {
1012       input_window = (GdkInputWindow *)tmp_list->data;
1013
1014       if (input_window->window == window)
1015         new_window = input_window;
1016       else if (input_window->grabbed)
1017         {
1018           input_window->grabbed = FALSE;
1019           need_ungrab = TRUE;
1020         }
1021
1022       tmp_list = tmp_list->next;
1023     }
1024
1025   if (new_window)
1026     {
1027       new_window->grabbed = TRUE;
1028       
1029       tmp_list = _gdk_input_devices;
1030       while (tmp_list)
1031         {
1032           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1033           if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx)
1034             {
1035 #if 0         
1036               /* XXX */
1037               gdk_input_common_find_events (window, gdkdev,
1038                                             event_mask,
1039                                             event_classes, &num_classes);
1040               
1041               result = XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
1042                                     GDK_WINDOW_XWINDOW (window),
1043                                     owner_events, num_classes, event_classes,
1044                                     GrabModeAsync, GrabModeAsync, time);
1045               
1046               /* FIXME: if failure occurs on something other than the first
1047                  device, things will be badly inconsistent */
1048               if (result != Success)
1049                 return result;
1050 #endif
1051             }
1052           tmp_list = tmp_list->next;
1053         }
1054     }
1055   else
1056     { 
1057       tmp_list = _gdk_input_devices;
1058       while (tmp_list)
1059         {
1060           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1061           if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx &&
1062               ((gdkdev->button_state != 0) || need_ungrab))
1063             {
1064 #if 0
1065               /* XXX */
1066               XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1067 #endif
1068               gdkdev->button_state = 0;
1069             }
1070           
1071           tmp_list = tmp_list->next;
1072         }
1073     }
1074 #endif
1075
1076   return GDK_GRAB_SUCCESS;
1077 }
1078
1079 void 
1080 _gdk_input_ungrab_pointer (guint32 time)
1081 {
1082 #ifdef HAVE_SOME_XINPUT
1083   GdkInputWindow *input_window;
1084   GdkDevicePrivate *gdkdev;
1085   GList *tmp_list;
1086
1087   GDK_NOTE (INPUT, g_print ("gdk_input_win32_ungrab_pointer\n"));
1088
1089   tmp_list = _gdk_input_windows;
1090   while (tmp_list)
1091     {
1092       input_window = (GdkInputWindow *)tmp_list->data;
1093       if (input_window->grabbed)
1094         break;
1095       tmp_list = tmp_list->next;
1096     }
1097
1098   if (tmp_list)                 /* we found a grabbed window */
1099     {
1100       input_window->grabbed = FALSE;
1101
1102       tmp_list = _gdk_input_devices;
1103       while (tmp_list)
1104         {
1105           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1106 #if 0
1107           /* XXX */
1108           if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
1109             XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1110 #endif
1111           tmp_list = tmp_list->next;
1112         }
1113     }
1114 #endif
1115 }
1116
1117 gint 
1118 _gdk_input_window_none_event (GdkEvent *event,
1119                               MSG      *msg)
1120 {
1121   return -1;
1122 }
1123
1124 gboolean
1125 _gdk_device_get_history (GdkDevice         *device,
1126                          GdkWindow         *window,
1127                          guint32            start,
1128                          guint32            stop,
1129                          GdkTimeCoord    ***events,
1130                          gint              *n_events)
1131 {
1132   return FALSE;
1133 }
1134
1135 void 
1136 gdk_device_get_state (GdkDevice       *device,
1137                       GdkWindow       *window,
1138                       gdouble         *axes,
1139                       GdkModifierType *mask)
1140 {
1141   g_return_if_fail (device != NULL);
1142   g_return_if_fail (GDK_IS_WINDOW (window));
1143
1144   if (GDK_IS_CORE (device))
1145     {
1146       gint x_int, y_int;
1147       
1148       gdk_window_get_pointer (window, &x_int, &y_int, mask);
1149
1150       if (axes)
1151         {
1152           axes[0] = x_int;
1153           axes[1] = y_int;
1154         }
1155     }
1156   else
1157     {
1158       GdkDevicePrivate *gdkdev;
1159       GdkInputWindow *input_window;
1160       
1161       if (mask)
1162         gdk_window_get_pointer (window, NULL, NULL, mask);
1163       
1164       gdkdev = (GdkDevicePrivate *)device;
1165       input_window = gdk_input_window_find (window);
1166       g_return_if_fail (input_window != NULL);
1167
1168 #if 0 /* FIXME */
1169       state = XQueryDeviceState (gdk_display, gdkdev->xdevice);
1170       input_class = state->data;
1171       for (i = 0; i < state->num_classes; i++)
1172         {
1173           switch (input_class->class)
1174             {
1175             case ValuatorClass:
1176               if (axes)
1177                 gdk_input_translate_coordinates (gdkdev, input_window,
1178                                                  ((XValuatorState *)input_class)->valuators,
1179                                                  axes, NULL, NULL);
1180               break;
1181               
1182             case ButtonClass:
1183               if (mask)
1184                 {
1185                   *mask &= 0xFF;
1186                   if (((XButtonState *)input_class)->num_buttons > 0)
1187                     *mask |= ((XButtonState *)input_class)->buttons[0] << 7;
1188                   /* GDK_BUTTON1_MASK = 1 << 8, and button n is stored
1189                    * in bit 1<<(n%8) in byte n/8. n = 1,2,... */
1190                 }
1191               break;
1192             }
1193           input_class = (XInputClass *)(((char *)input_class)+input_class->length);
1194         }
1195       XFreeDeviceState (state);
1196 #endif
1197     }
1198 }
1199
1200 void 
1201 _gdk_input_init (void)
1202 {
1203   _gdk_input_ignore_core = FALSE;
1204   _gdk_input_devices = NULL;
1205
1206   _gdk_init_input_core ();
1207 #ifdef HAVE_WINTAB
1208   gdk_input_wintab_init ();
1209 #endif /* HAVE_WINTAB */
1210
1211   _gdk_input_devices = g_list_append (_gdk_input_devices, display->core_pointer);
1212 }
1213