]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkinput-win32.c
Add missing call to g_object_ref in Wintab code. (#138341)
[~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           /* Increase packet queue size to reduce the risk of lost packets */
350           /* According to the specs, if the function fails we must try again */
351           /* with a smaller queue size */
352           GDK_NOTE (INPUT, g_print("Attempting to increase queue size\n"));
353           for (i = 128; i >= 1; i >>= 1)
354             {
355               if (WTQueueSizeSet(*hctx, i))
356                 {
357                   GDK_NOTE (INPUT, g_print("Queue size set to %d\n", i));
358                   break;
359                 }
360             }
361           if (!i)
362             GDK_NOTE (INPUT, g_print("Whoops, no queue size could be set\n"));
363           for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes; cursorix++)
364             {
365               active = FALSE;
366               WTInfo (WTI_CURSORS + cursorix, CSR_ACTIVE, &active);
367               if (!active)
368                 continue;
369               gdkdev = g_object_new (GDK_TYPE_DEVICE, NULL);
370               WTInfo (WTI_CURSORS + cursorix, CSR_NAME, csrname);
371               gdkdev->info.name = g_strconcat (devname, " ", csrname, NULL);
372               gdkdev->info.source = GDK_SOURCE_PEN;
373               gdkdev->info.mode = GDK_MODE_SCREEN;
374 #if USE_SYSCONTEXT
375               gdkdev->info.has_cursor = TRUE;
376 #else
377               gdkdev->info.has_cursor = FALSE;
378 #endif
379               gdkdev->hctx = *hctx;
380               gdkdev->cursor = cursorix;
381               WTInfo (WTI_CURSORS + cursorix, CSR_PKTDATA, &gdkdev->pktdata);
382               gdkdev->info.num_axes = 0;
383               if (gdkdev->pktdata & PK_X)
384                 gdkdev->info.num_axes++;
385               if (gdkdev->pktdata & PK_Y)
386                 gdkdev->info.num_axes++;
387               if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
388                 gdkdev->info.num_axes++;
389               /* The wintab driver for the Wacom ArtPad II reports
390                * PK_ORIENTATION in CSR_PKTDATA, but the tablet doesn't
391                * actually sense tilt. Catch this by noticing that the
392                * orientation axis's azimuth resolution is zero.
393                */
394               if ((gdkdev->pktdata & PK_ORIENTATION)
395                   && axis_or[0].axResolution == 0)
396                 gdkdev->pktdata &= ~PK_ORIENTATION;
397
398               if (gdkdev->pktdata & PK_ORIENTATION)
399                 gdkdev->info.num_axes += 2; /* x and y tilt */
400               WTInfo (WTI_CURSORS + cursorix, CSR_NPBTNMARKS, &gdkdev->npbtnmarks);
401               gdkdev->info.axes = g_new (GdkDeviceAxis, gdkdev->info.num_axes);
402               gdkdev->axes = g_new (GdkAxisInfo, gdkdev->info.num_axes);
403               gdkdev->last_axis_data = g_new (gint, gdkdev->info.num_axes);
404               
405               k = 0;
406               if (gdkdev->pktdata & PK_X)
407                 {
408                   gdkdev->axes[k].xresolution =
409                     gdkdev->axes[k].resolution = axis_x.axResolution / 65535.;
410                   gdkdev->axes[k].xmin_value =
411                     gdkdev->axes[k].min_value = axis_x.axMin;
412                   gdkdev->axes[k].xmax_value =
413                     gdkdev->axes[k].max_value = axis_x.axMax;
414                   gdkdev->info.axes[k].use = GDK_AXIS_X;
415                   gdkdev->info.axes[k].min = axis_x.axMin;
416                   gdkdev->info.axes[k].max = axis_x.axMax;
417                   k++;
418                 }
419               if (gdkdev->pktdata & PK_Y)
420                 {
421                   gdkdev->axes[k].xresolution =
422                     gdkdev->axes[k].resolution = axis_y.axResolution / 65535.;
423                   gdkdev->axes[k].xmin_value =
424                     gdkdev->axes[k].min_value = axis_y.axMin;
425                   gdkdev->axes[k].xmax_value =
426                     gdkdev->axes[k].max_value = axis_y.axMax;
427                   gdkdev->info.axes[k].use = GDK_AXIS_Y;
428                   gdkdev->info.axes[k].min = axis_y.axMin;
429                   gdkdev->info.axes[k].max = axis_y.axMax;
430                   k++;
431                 }
432               if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
433                 {
434                   gdkdev->axes[k].xresolution =
435                     gdkdev->axes[k].resolution = axis_npressure.axResolution / 65535.;
436                   gdkdev->axes[k].xmin_value =
437                     gdkdev->axes[k].min_value = axis_npressure.axMin;
438                   gdkdev->axes[k].xmax_value =
439                     gdkdev->axes[k].max_value = axis_npressure.axMax;
440                   gdkdev->info.axes[k].use = GDK_AXIS_PRESSURE;
441                   /* GIMP seems to expect values in the range 0-1 */
442                   gdkdev->info.axes[k].min = 0.0; /*axis_npressure.axMin;*/
443                   gdkdev->info.axes[k].max = 1.0; /*axis_npressure.axMax;*/
444                   k++;
445                 }
446               if (gdkdev->pktdata & PK_ORIENTATION)
447                 {
448                   GdkAxisUse axis;
449
450                   gdkdev->orientation_axes[0] = axis_or[0];
451                   gdkdev->orientation_axes[1] = axis_or[1];
452                   for (axis = GDK_AXIS_XTILT; axis <= GDK_AXIS_YTILT; axis++)
453                     {
454                       /* Wintab gives us aximuth and altitude, which
455                        * we convert to x and y tilt in the -1000..1000 range
456                        */
457                       gdkdev->axes[k].xresolution =
458                         gdkdev->axes[k].resolution = 1000;
459                       gdkdev->axes[k].xmin_value =
460                         gdkdev->axes[k].min_value = -1000;
461                       gdkdev->axes[k].xmax_value =
462                         gdkdev->axes[k].max_value = 1000;
463                       gdkdev->info.axes[k].use = axis;
464                       gdkdev->info.axes[k].min = -1000;
465                       gdkdev->info.axes[k].max = 1000;
466                       k++;
467                     }
468                 }
469               gdkdev->info.num_keys = 0;
470               gdkdev->info.keys = NULL;
471               GDK_NOTE (INPUT,
472                         g_print ("device: (%d) %s axes: %d\n",
473                                  cursorix,
474                                  gdkdev->info.name,
475                                  gdkdev->info.num_axes));
476               for (i = 0; i < gdkdev->info.num_axes; i++)
477                 GDK_NOTE (INPUT,
478                           g_print ("...axis %d: %d--%d@%d (%d--%d@%d)\n",
479                                    i,
480                                    gdkdev->axes[i].xmin_value, 
481                                    gdkdev->axes[i].xmax_value, 
482                                    gdkdev->axes[i].xresolution, 
483                                    gdkdev->axes[i].min_value, 
484                                    gdkdev->axes[i].max_value, 
485                                    gdkdev->axes[i].resolution));
486               _gdk_input_devices = g_list_append (_gdk_input_devices,
487                                                  gdkdev);
488             }
489         }
490     }
491 }
492
493 static void
494 decode_tilt (gint   *axis_data,
495              AXIS   *axes,
496              PACKET *packet)
497 {
498   /* As I don't have a tilt-sensing tablet,
499    * I cannot test this code.
500    */
501   
502   double az, el;
503
504   az = TWOPI * packet->pkOrientation.orAzimuth /
505     (axes[0].axResolution / 65536.);
506   el = TWOPI * packet->pkOrientation.orAltitude /
507     (axes[1].axResolution / 65536.);
508   
509   /* X tilt */
510   axis_data[0] = cos (az) * cos (el) * 1000;
511   /* Y tilt */
512   axis_data[1] = sin (az) * cos (el) * 1000;
513 }
514
515 #if !USE_SYSCONTEXT
516
517 static GdkInputWindow *
518 gdk_input_window_find_within (GdkWindow *window)
519 {
520   GList *list;
521   GdkWindow *tmpw;
522   GdkInputWindow *candidate = NULL;
523
524   for (list = _gdk_input_windows; list != NULL; list = list->next)
525     {
526       tmpw = ((GdkInputWindow *) (tmp_list->data))->window;
527       if (tmpw == window
528           || IsChild (GDK_WINDOW_HWND (window), GDK_WINDOW_HWND (tmpw)))
529         {
530           if (candidate)
531             return NULL;                /* Multiple hits */
532           candidate = (GdkInputWindow *) (list->data);
533         }
534     }
535
536   return candidate;
537 }
538
539 #endif /* USE_SYSCONTEXT */
540
541 #endif /* HAVE_WINTAB */
542
543 static void
544 gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
545                                  GdkInputWindow   *input_window,
546                                  gint             *axis_data,
547                                  gdouble          *axis_out,
548                                  gdouble          *x_out,
549                                  gdouble          *y_out)
550 {
551   GdkWindowImplWin32 *impl;
552
553   int i;
554   int x_axis = 0;
555   int y_axis = 0;
556
557   double device_width, device_height;
558   double x_offset, y_offset, x_scale, y_scale;
559
560   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (input_window->window)->impl);
561
562   for (i=0; i<gdkdev->info.num_axes; i++)
563     {
564       switch (gdkdev->info.axes[i].use)
565         {
566         case GDK_AXIS_X:
567           x_axis = i;
568           break;
569         case GDK_AXIS_Y:
570           y_axis = i;
571           break;
572         default:
573           break;
574         }
575     }
576   
577   device_width = gdkdev->axes[x_axis].max_value - 
578                    gdkdev->axes[x_axis].min_value;
579   device_height = gdkdev->axes[y_axis].max_value - 
580                     gdkdev->axes[y_axis].min_value;
581
582   if (gdkdev->info.mode == GDK_MODE_SCREEN) 
583     {
584       x_scale = GetSystemMetrics (SM_CXSCREEN) / device_width;
585       y_scale = GetSystemMetrics (SM_CYSCREEN) / device_height;
586
587       x_offset = - input_window->root_x;
588       y_offset = - input_window->root_y;
589     }
590   else                          /* GDK_MODE_WINDOW */
591     {
592       double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
593         (device_width*gdkdev->axes[x_axis].resolution);
594
595       if (device_aspect * impl->width >= impl->height)
596         {
597           /* device taller than window */
598           x_scale = impl->width / device_width;
599           y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
600             / gdkdev->axes[y_axis].resolution;
601
602           x_offset = 0;
603           y_offset = -(device_height * y_scale - 
604                                impl->height)/2;
605         }
606       else
607         {
608           /* window taller than device */
609           y_scale = impl->height / device_height;
610           x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
611             / gdkdev->axes[x_axis].resolution;
612
613           y_offset = 0;
614           x_offset = - (device_width * x_scale - impl->width)/2;
615         }
616     }
617
618   for (i=0; i<gdkdev->info.num_axes; i++)
619     {
620       switch (gdkdev->info.axes[i].use)
621         {
622         case GDK_AXIS_X:
623           axis_out[i] = x_offset + x_scale*axis_data[x_axis];
624           if (x_out)
625             *x_out = axis_out[i];
626           break;
627         case GDK_AXIS_Y:
628           axis_out[i] = y_offset + y_scale*axis_data[y_axis];
629           if (y_out)
630             *y_out = axis_out[i];
631           break;
632         default:
633           axis_out[i] =
634             (gdkdev->info.axes[i].max * (axis_data[i] - gdkdev->axes[i].min_value) +
635              gdkdev->info.axes[i].min * (gdkdev->axes[i].max_value - axis_data[i])) /
636             (gdkdev->axes[i].max_value - gdkdev->axes[i].min_value);
637           break;
638         }
639     }
640 }
641
642 static void
643 gdk_input_get_root_relative_geometry (HWND w,
644                                       int  *x_ret,
645                                       int  *y_ret)
646 {
647   RECT rect;
648
649   GetWindowRect (w, &rect);
650
651   if (x_ret)
652     *x_ret = rect.left;
653   if (y_ret)
654     *y_ret = rect.top;
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           event->button.axes = g_new(gdouble, gdkdev->info.num_axes);
860
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 = _gdk_win32_get_next_tick (msg->time);
881           event->motion.is_hint = FALSE;
882           event->motion.device = &gdkdev->info;
883
884           event->motion.axes = g_new(gdouble, gdkdev->info.num_axes);
885
886           gdk_input_translate_coordinates (gdkdev, input_window,
887                                            gdkdev->last_axis_data,
888                                            event->motion.axes,
889                                            &event->motion.x, 
890                                            &event->motion.y);
891
892           event->motion.state = ((gdkdev->button_state << 8)
893                                  & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
894                                     | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
895                                     | GDK_BUTTON5_MASK));
896
897           GDK_NOTE (EVENTS_OR_INPUT,
898                     g_print ("WINTAB motion: %g,%g\n",
899                              event->motion.x, event->motion.y));
900
901           /* Check for missing release or press events for the normal
902            * pressure button. At least on my ArtPadII I sometimes miss a
903            * release event?
904            */
905           if ((gdkdev->pktdata & PK_NORMAL_PRESSURE
906                && (event->motion.state & GDK_BUTTON1_MASK)
907                && packet.pkNormalPressure <= MAX (0, (gint) gdkdev->npbtnmarks[0] - 2))
908               || (gdkdev->pktdata & PK_NORMAL_PRESSURE
909                   && !(event->motion.state & GDK_BUTTON1_MASK)
910                   && packet.pkNormalPressure > gdkdev->npbtnmarks[1] + 2))
911             {
912               GdkEvent *event2 = gdk_event_copy (event);
913               if (event->motion.state & GDK_BUTTON1_MASK)
914                 {
915                   event2->button.type = GDK_BUTTON_RELEASE;
916                   gdkdev->button_state &= ~1;
917                 }
918               else
919                 {
920                   event2->button.type = GDK_BUTTON_PRESS;
921                   gdkdev->button_state |= 1;
922                 }
923               event2->button.state = ((gdkdev->button_state << 8)
924                                       & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
925                                          | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
926                                          | GDK_BUTTON5_MASK));
927               event2->button.button = 1;
928               GDK_NOTE (EVENTS_OR_INPUT,
929                         g_print ("WINTAB synthesized button %s: %d %g,%gg\n",
930                                  (event2->button.type == GDK_BUTTON_PRESS ?
931                                   "press" : "release"),
932                                  event2->button.button,
933                                  event2->button.x,
934                                  event2->button.y));
935               _gdk_event_queue_append (display, event2);
936             }
937         }
938       return TRUE;
939
940     case WT_PROXIMITY:
941       if (LOWORD (msg->lParam) == 0)
942         {
943           event->proximity.type = GDK_PROXIMITY_OUT;
944           _gdk_input_ignore_core = FALSE;
945         }
946       else
947         {
948           event->proximity.type = GDK_PROXIMITY_IN;
949           _gdk_input_ignore_core = TRUE;
950         }
951       event->proximity.time = _gdk_win32_get_next_tick (msg->time);
952       event->proximity.device = &gdkdev->info;
953
954       GDK_NOTE (EVENTS_OR_INPUT,
955                 g_print ("WINTAB proximity %s\n",
956                          (event->proximity.type == GDK_PROXIMITY_IN ?
957                           "in" : "out")));
958       return TRUE;
959     }
960 #endif
961   return FALSE;
962 }
963
964 gboolean
965 _gdk_input_enable_window (GdkWindow        *window,
966                           GdkDevicePrivate *gdkdev)
967 {
968 #ifdef HAVE_SOME_XINPUT
969   GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
970
971   impl->extension_events_selected = TRUE;
972 #endif
973
974   return TRUE;
975 }
976
977 gboolean
978 _gdk_input_disable_window (GdkWindow        *window,
979                            GdkDevicePrivate *gdkdev)
980 {
981 #ifdef HAVE_SOME_XINPUT
982   GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
983
984   impl->extension_events_selected = FALSE;
985 #endif
986
987   return TRUE;
988 }
989
990 gint
991 _gdk_input_grab_pointer (GdkWindow    *window,
992                          gint          owner_events,
993                          GdkEventMask  event_mask,
994                          GdkWindow    *confine_to,
995                          guint32       time)
996 {
997 #ifdef HAVE_SOME_XINPUT
998   GdkInputWindow *input_window, *new_window;
999   gboolean need_ungrab;
1000   GdkDevicePrivate *gdkdev;
1001   GList *tmp_list;
1002
1003   tmp_list = _gdk_input_windows;
1004   new_window = NULL;
1005   need_ungrab = FALSE;
1006
1007   GDK_NOTE (INPUT, g_print ("gdk_input_win32_grab_pointer: %p %d %p\n",
1008                            GDK_WINDOW_HWND (window),
1009                            owner_events,
1010                            (confine_to ? GDK_WINDOW_HWND (confine_to) : 0)));
1011
1012   while (tmp_list)
1013     {
1014       input_window = (GdkInputWindow *)tmp_list->data;
1015
1016       if (input_window->window == window)
1017         new_window = input_window;
1018       else if (input_window->grabbed)
1019         {
1020           input_window->grabbed = FALSE;
1021           need_ungrab = TRUE;
1022         }
1023
1024       tmp_list = tmp_list->next;
1025     }
1026
1027   if (new_window)
1028     {
1029       new_window->grabbed = TRUE;
1030       
1031       tmp_list = _gdk_input_devices;
1032       while (tmp_list)
1033         {
1034           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1035           if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx)
1036             {
1037 #if 0         
1038               /* XXX */
1039               gdk_input_common_find_events (window, gdkdev,
1040                                             event_mask,
1041                                             event_classes, &num_classes);
1042               
1043               result = XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
1044                                     GDK_WINDOW_XWINDOW (window),
1045                                     owner_events, num_classes, event_classes,
1046                                     GrabModeAsync, GrabModeAsync, time);
1047               
1048               /* FIXME: if failure occurs on something other than the first
1049                  device, things will be badly inconsistent */
1050               if (result != Success)
1051                 return result;
1052 #endif
1053             }
1054           tmp_list = tmp_list->next;
1055         }
1056     }
1057   else
1058     { 
1059       tmp_list = _gdk_input_devices;
1060       while (tmp_list)
1061         {
1062           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1063           if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx &&
1064               ((gdkdev->button_state != 0) || need_ungrab))
1065             {
1066 #if 0
1067               /* XXX */
1068               XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1069 #endif
1070               gdkdev->button_state = 0;
1071             }
1072           
1073           tmp_list = tmp_list->next;
1074         }
1075     }
1076 #endif
1077
1078   return GDK_GRAB_SUCCESS;
1079 }
1080
1081 void 
1082 _gdk_input_ungrab_pointer (guint32 time)
1083 {
1084 #ifdef HAVE_SOME_XINPUT
1085   GdkInputWindow *input_window;
1086   GdkDevicePrivate *gdkdev;
1087   GList *tmp_list;
1088
1089   GDK_NOTE (INPUT, g_print ("gdk_input_win32_ungrab_pointer\n"));
1090
1091   tmp_list = _gdk_input_windows;
1092   while (tmp_list)
1093     {
1094       input_window = (GdkInputWindow *)tmp_list->data;
1095       if (input_window->grabbed)
1096         break;
1097       tmp_list = tmp_list->next;
1098     }
1099
1100   if (tmp_list)                 /* we found a grabbed window */
1101     {
1102       input_window->grabbed = FALSE;
1103
1104       tmp_list = _gdk_input_devices;
1105       while (tmp_list)
1106         {
1107           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1108 #if 0
1109           /* XXX */
1110           if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
1111             XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1112 #endif
1113           tmp_list = tmp_list->next;
1114         }
1115     }
1116 #endif
1117 }
1118
1119 gboolean
1120 _gdk_device_get_history (GdkDevice         *device,
1121                          GdkWindow         *window,
1122                          guint32            start,
1123                          guint32            stop,
1124                          GdkTimeCoord    ***events,
1125                          gint              *n_events)
1126 {
1127   return FALSE;
1128 }
1129
1130 void 
1131 gdk_device_get_state (GdkDevice       *device,
1132                       GdkWindow       *window,
1133                       gdouble         *axes,
1134                       GdkModifierType *mask)
1135 {
1136   g_return_if_fail (device != NULL);
1137   g_return_if_fail (GDK_IS_WINDOW (window));
1138
1139   if (GDK_IS_CORE (device))
1140     {
1141       gint x_int, y_int;
1142       
1143       gdk_window_get_pointer (window, &x_int, &y_int, mask);
1144
1145       if (axes)
1146         {
1147           axes[0] = x_int;
1148           axes[1] = y_int;
1149         }
1150     }
1151   else
1152     {
1153       GdkDevicePrivate *gdkdev;
1154       GdkInputWindow *input_window;
1155       
1156       if (mask)
1157         gdk_window_get_pointer (window, NULL, NULL, mask);
1158       
1159       gdkdev = (GdkDevicePrivate *)device;
1160       input_window = _gdk_input_window_find (window);
1161       g_return_if_fail (input_window != NULL);
1162
1163 #if 0 /* FIXME */
1164       state = XQueryDeviceState (gdk_display, gdkdev->xdevice);
1165       input_class = state->data;
1166       for (i = 0; i < state->num_classes; i++)
1167         {
1168           switch (input_class->class)
1169             {
1170             case ValuatorClass:
1171               if (axes)
1172                 gdk_input_translate_coordinates (gdkdev, input_window,
1173                                                  ((XValuatorState *)input_class)->valuators,
1174                                                  axes, NULL, NULL);
1175               break;
1176               
1177             case ButtonClass:
1178               if (mask)
1179                 {
1180                   *mask &= 0xFF;
1181                   if (((XButtonState *)input_class)->num_buttons > 0)
1182                     *mask |= ((XButtonState *)input_class)->buttons[0] << 7;
1183                   /* GDK_BUTTON1_MASK = 1 << 8, and button n is stored
1184                    * in bit 1<<(n%8) in byte n/8. n = 1,2,... */
1185                 }
1186               break;
1187             }
1188           input_class = (XInputClass *)(((char *)input_class)+input_class->length);
1189         }
1190       XFreeDeviceState (state);
1191 #endif
1192     }
1193 }
1194
1195 void 
1196 _gdk_input_init (GdkDisplay *display)
1197 {
1198   _gdk_input_ignore_core = FALSE;
1199   _gdk_input_devices = NULL;
1200
1201   _gdk_init_input_core (display);
1202 #ifdef HAVE_WINTAB
1203   gdk_input_wintab_init ();
1204 #endif /* HAVE_WINTAB */
1205
1206   _gdk_input_devices = g_list_append (_gdk_input_devices, display->core_pointer);
1207 }
1208