]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkinput-win32.c
c86c23a3f8d3c1a1afccd4b2f3e724f94782b610
[~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 = NULL;
75
76 static GdkWindow *wintab_window = NULL;
77
78 #endif /* HAVE_WINTAB */
79
80 #ifdef HAVE_SOME_XINPUT
81
82 static GdkWindow *x_grab_window = NULL; /* Window that currently holds
83                                          * the extended inputs grab
84                                          */
85 static GdkEventMask x_grab_mask;
86 static gboolean x_grab_owner_events;
87
88 #endif /* HAVE_SOME_XINPUT */
89
90 #ifdef HAVE_WINTAB
91
92 static GdkDevicePrivate *
93 gdk_input_find_dev_from_ctx (HCTX hctx,
94                              UINT cursor)
95 {
96   GList *tmp_list = _gdk_input_devices;
97   GdkDevicePrivate *gdkdev;
98
99   while (tmp_list)
100     {
101       gdkdev = (GdkDevicePrivate *) (tmp_list->data);
102       if (gdkdev->hctx == hctx && gdkdev->cursor == cursor)
103         return gdkdev;
104       tmp_list = tmp_list->next;
105     }
106   return NULL;
107 }
108
109 #if DEBUG_WINTAB
110
111 static void
112 print_lc(LOGCONTEXT *lc)
113 {
114   g_print ("lcName = %s\n", lc->lcName);
115   g_print ("lcOptions =");
116   if (lc->lcOptions & CXO_SYSTEM) g_print (" CXO_SYSTEM");
117   if (lc->lcOptions & CXO_PEN) g_print (" CXO_PEN");
118   if (lc->lcOptions & CXO_MESSAGES) g_print (" CXO_MESSAGES");
119   if (lc->lcOptions & CXO_MARGIN) g_print (" CXO_MARGIN");
120   if (lc->lcOptions & CXO_MGNINSIDE) g_print (" CXO_MGNINSIDE");
121   if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
122   g_print ("\n");
123   g_print ("lcStatus =");
124   if (lc->lcStatus & CXS_DISABLED) g_print (" CXS_DISABLED");
125   if (lc->lcStatus & CXS_OBSCURED) g_print (" CXS_OBSCURED");
126   if (lc->lcStatus & CXS_ONTOP) g_print (" CXS_ONTOP");
127   g_print ("\n");
128   g_print ("lcLocks =");
129   if (lc->lcLocks & CXL_INSIZE) g_print (" CXL_INSIZE");
130   if (lc->lcLocks & CXL_INASPECT) g_print (" CXL_INASPECT");
131   if (lc->lcLocks & CXL_SENSITIVITY) g_print (" CXL_SENSITIVITY");
132   if (lc->lcLocks & CXL_MARGIN) g_print (" CXL_MARGIN");
133   g_print ("\n");
134   g_print ("lcMsgBase = %#x, lcDevice = %#x, lcPktRate = %d\n",
135           lc->lcMsgBase, lc->lcDevice, lc->lcPktRate);
136   g_print ("lcPktData =");
137   if (lc->lcPktData & PK_CONTEXT) g_print (" PK_CONTEXT");
138   if (lc->lcPktData & PK_STATUS) g_print (" PK_STATUS");
139   if (lc->lcPktData & PK_TIME) g_print (" PK_TIME");
140   if (lc->lcPktData & PK_CHANGED) g_print (" PK_CHANGED");
141   if (lc->lcPktData & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
142   if (lc->lcPktData & PK_CURSOR) g_print (" PK_CURSOR");
143   if (lc->lcPktData & PK_BUTTONS) g_print (" PK_BUTTONS");
144   if (lc->lcPktData & PK_X) g_print (" PK_X");
145   if (lc->lcPktData & PK_Y) g_print (" PK_Y");
146   if (lc->lcPktData & PK_Z) g_print (" PK_Z");
147   if (lc->lcPktData & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
148   if (lc->lcPktData & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
149   if (lc->lcPktData & PK_ORIENTATION) g_print (" PK_ORIENTATION");
150   if (lc->lcPktData & PK_ROTATION) g_print (" PK_ROTATION");
151   g_print ("\n");
152   g_print ("lcPktMode =");
153   if (lc->lcPktMode & PK_CONTEXT) g_print (" PK_CONTEXT");
154   if (lc->lcPktMode & PK_STATUS) g_print (" PK_STATUS");
155   if (lc->lcPktMode & PK_TIME) g_print (" PK_TIME");
156   if (lc->lcPktMode & PK_CHANGED) g_print (" PK_CHANGED");
157   if (lc->lcPktMode & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
158   if (lc->lcPktMode & PK_CURSOR) g_print (" PK_CURSOR");
159   if (lc->lcPktMode & PK_BUTTONS) g_print (" PK_BUTTONS");
160   if (lc->lcPktMode & PK_X) g_print (" PK_X");
161   if (lc->lcPktMode & PK_Y) g_print (" PK_Y");
162   if (lc->lcPktMode & PK_Z) g_print (" PK_Z");
163   if (lc->lcPktMode & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
164   if (lc->lcPktMode & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
165   if (lc->lcPktMode & PK_ORIENTATION) g_print (" PK_ORIENTATION");
166   if (lc->lcPktMode & PK_ROTATION) g_print (" PK_ROTATION");
167   g_print ("\n");
168   g_print ("lcMoveMask =");
169   if (lc->lcMoveMask & PK_CONTEXT) g_print (" PK_CONTEXT");
170   if (lc->lcMoveMask & PK_STATUS) g_print (" PK_STATUS");
171   if (lc->lcMoveMask & PK_TIME) g_print (" PK_TIME");
172   if (lc->lcMoveMask & PK_CHANGED) g_print (" PK_CHANGED");
173   if (lc->lcMoveMask & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
174   if (lc->lcMoveMask & PK_CURSOR) g_print (" PK_CURSOR");
175   if (lc->lcMoveMask & PK_BUTTONS) g_print (" PK_BUTTONS");
176   if (lc->lcMoveMask & PK_X) g_print (" PK_X");
177   if (lc->lcMoveMask & PK_Y) g_print (" PK_Y");
178   if (lc->lcMoveMask & PK_Z) g_print (" PK_Z");
179   if (lc->lcMoveMask & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
180   if (lc->lcMoveMask & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
181   if (lc->lcMoveMask & PK_ORIENTATION) g_print (" PK_ORIENTATION");
182   if (lc->lcMoveMask & PK_ROTATION) g_print (" PK_ROTATION");
183   g_print ("\n");
184   g_print ("lcBtnDnMask = %#x, lcBtnUpMask = %#x\n",
185           (guint) lc->lcBtnDnMask, (guint) lc->lcBtnUpMask);
186   g_print ("lcInOrgX = %ld, lcInOrgY = %ld, lcInOrgZ = %ld\n",
187           lc->lcInOrgX, lc->lcInOrgY, lc->lcInOrgZ);
188   g_print ("lcInExtX = %ld, lcInExtY = %ld, lcInExtZ = %ld\n",
189           lc->lcInExtX, lc->lcInExtY, lc->lcInExtZ);
190   g_print ("lcOutOrgX = %ld, lcOutOrgY = %ld, lcOutOrgZ = %ld\n",
191           lc->lcOutOrgX, lc->lcOutOrgY, lc->lcOutOrgZ);
192   g_print ("lcOutExtX = %ld, lcOutExtY = %ld, lcOutExtZ = %ld\n",
193           lc->lcOutExtX, lc->lcOutExtY, lc->lcOutExtZ);
194   g_print ("lcSensX = %g, lcSensY = %g, lcSensZ = %g\n",
195           lc->lcSensX / 65536., lc->lcSensY / 65536., lc->lcSensZ / 65536.);
196   g_print ("lcSysMode = %d\n", lc->lcSysMode);
197   g_print ("lcSysOrgX = %d, lcSysOrgY = %d\n",
198           lc->lcSysOrgX, lc->lcSysOrgY);
199   g_print ("lcSysExtX = %d, lcSysExtY = %d\n",
200           lc->lcSysExtX, lc->lcSysExtY);
201   g_print ("lcSysSensX = %g, lcSysSensY = %g\n",
202           lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.);
203 }
204
205 #endif
206
207 void
208 _gdk_input_wintab_init_check (void)
209 {
210   static gboolean wintab_initialized = FALSE;
211   GdkDevicePrivate *gdkdev;
212   GdkWindowAttr wa;
213   WORD specversion;
214   LOGCONTEXT defcontext;
215   HCTX *hctx;
216   UINT ndevices, ncursors, ncsrtypes, firstcsr, hardware;
217   BOOL active;
218   AXIS axis_x, axis_y, axis_npressure, axis_or[3];
219   int i, k;
220   int devix, cursorix;
221   char devname[100], csrname[100];
222
223   if (wintab_initialized)
224     return;
225   
226   wintab_initialized = TRUE;
227   
228   wintab_contexts = NULL;
229
230   if (!_gdk_input_ignore_wintab &&
231       WTInfo (0, 0, NULL))
232     {
233       WTInfo (WTI_INTERFACE, IFC_SPECVERSION, &specversion);
234       GDK_NOTE (INPUT, g_print ("Wintab interface version %d.%d\n",
235                                HIBYTE (specversion), LOBYTE (specversion)));
236 #if USE_SYSCONTEXT
237       WTInfo (WTI_DEFSYSCTX, 0, &defcontext);
238 #if DEBUG_WINTAB
239       GDK_NOTE (INPUT, (g_print("DEFSYSCTX:\n"), print_lc(&defcontext)));
240 #endif
241 #else
242       WTInfo (WTI_DEFCONTEXT, 0, &defcontext);
243 #if DEBUG_WINTAB
244       GDK_NOTE (INPUT, (g_print("DEFCONTEXT:\n"), print_lc(&defcontext)));
245 #endif
246 #endif
247       WTInfo (WTI_INTERFACE, IFC_NDEVICES, &ndevices);
248       WTInfo (WTI_INTERFACE, IFC_NCURSORS, &ncursors);
249 #if DEBUG_WINTAB
250       GDK_NOTE (INPUT, g_print ("NDEVICES: %d, NCURSORS: %d\n",
251                                ndevices, ncursors));
252 #endif
253       /* Create a dummy window to receive wintab events */
254       wa.wclass = GDK_INPUT_OUTPUT;
255       wa.event_mask = GDK_ALL_EVENTS_MASK;
256       wa.width = 2;
257       wa.height = 2;
258       wa.x = -100;
259       wa.y = -100;
260       wa.window_type = GDK_WINDOW_TOPLEVEL;
261       if ((wintab_window = gdk_window_new (NULL, &wa, GDK_WA_X|GDK_WA_Y)) == NULL)
262         {
263           g_warning ("gdk_input_wintab_init: gdk_window_new failed");
264           return;
265         }
266       g_object_ref (wintab_window);
267       
268       for (devix = 0; devix < ndevices; devix++)
269         {
270           LOGCONTEXT lc;
271
272           WTInfo (WTI_DEVICES + devix, DVC_NAME, devname);
273       
274           WTInfo (WTI_DEVICES + devix, DVC_NCSRTYPES, &ncsrtypes);
275           WTInfo (WTI_DEVICES + devix, DVC_FIRSTCSR, &firstcsr);
276           WTInfo (WTI_DEVICES + devix, DVC_HARDWARE, &hardware);
277           WTInfo (WTI_DEVICES + devix, DVC_X, &axis_x);
278           WTInfo (WTI_DEVICES + devix, DVC_Y, &axis_y);
279           WTInfo (WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure);
280           WTInfo (WTI_DEVICES + devix, DVC_ORIENTATION, axis_or);
281
282           if (HIBYTE (specversion) > 1 || LOBYTE (specversion) >= 1)
283             {
284               WTInfo (WTI_DDCTXS + devix, CTX_NAME, lc.lcName);
285               WTInfo (WTI_DDCTXS + devix, CTX_OPTIONS, &lc.lcOptions);
286               lc.lcOptions |= CXO_MESSAGES;
287 #if USE_SYSCONTEXT
288               lc.lcOptions |= CXO_SYSTEM;
289 #endif
290               lc.lcStatus = 0;
291               WTInfo (WTI_DDCTXS + devix, CTX_LOCKS, &lc.lcLocks);
292               lc.lcMsgBase = WT_DEFBASE;
293               lc.lcDevice = devix;
294               lc.lcPktRate = 50;
295               lc.lcPktData = PACKETDATA;
296               lc.lcPktMode = PK_BUTTONS; /* We want buttons in relative mode */
297               lc.lcMoveMask = PACKETDATA;
298               lc.lcBtnDnMask = lc.lcBtnUpMask = ~0;
299               WTInfo (WTI_DDCTXS + devix, CTX_INORGX, &lc.lcInOrgX);
300               WTInfo (WTI_DDCTXS + devix, CTX_INORGY, &lc.lcInOrgY);
301               WTInfo (WTI_DDCTXS + devix, CTX_INORGZ, &lc.lcInOrgZ);
302               WTInfo (WTI_DDCTXS + devix, CTX_INEXTX, &lc.lcInExtX);
303               WTInfo (WTI_DDCTXS + devix, CTX_INEXTY, &lc.lcInExtY);
304               WTInfo (WTI_DDCTXS + devix, CTX_INEXTZ, &lc.lcInExtZ);
305               lc.lcOutOrgX = axis_x.axMin;
306               lc.lcOutOrgY = axis_y.axMin;
307               lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
308               lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
309               lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
310               WTInfo (WTI_DDCTXS + devix, CTX_SENSX, &lc.lcSensX);
311               WTInfo (WTI_DDCTXS + devix, CTX_SENSY, &lc.lcSensY);
312               WTInfo (WTI_DDCTXS + devix, CTX_SENSZ, &lc.lcSensZ);
313               WTInfo (WTI_DDCTXS + devix, CTX_SYSMODE, &lc.lcSysMode);
314               WTInfo (WTI_DDCTXS + devix, CTX_SYSORGX, &lc.lcSysOrgX);
315               WTInfo (WTI_DDCTXS + devix, CTX_SYSORGY, &lc.lcSysOrgY);
316               WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTX, &lc.lcSysExtX);
317               WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTY, &lc.lcSysExtY);
318               WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSX, &lc.lcSysSensX);
319               WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSY, &lc.lcSysSensY);
320             }
321           else
322             {
323               lc = defcontext;
324               lc.lcOptions |= CXO_MESSAGES;
325               lc.lcMsgBase = WT_DEFBASE;
326               lc.lcPktRate = 50;
327               lc.lcPktData = PACKETDATA;
328               lc.lcPktMode = PACKETMODE;
329               lc.lcMoveMask = PACKETDATA;
330               lc.lcBtnUpMask = lc.lcBtnDnMask = ~0;
331 #if 0
332               lc.lcOutExtY = -lc.lcOutExtY; /* Y grows downward */
333 #else
334               lc.lcOutOrgX = axis_x.axMin;
335               lc.lcOutOrgY = axis_y.axMin;
336               lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
337               lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
338               lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
339 #endif
340             }
341 #if DEBUG_WINTAB
342           GDK_NOTE (INPUT, (g_print("context for device %d:\n", devix),
343                            print_lc(&lc)));
344 #endif
345           hctx = g_new (HCTX, 1);
346           if ((*hctx = WTOpen (GDK_WINDOW_HWND (wintab_window), &lc, TRUE)) == NULL)
347             {
348               g_warning ("gdk_input_wintab_init: WTOpen failed");
349               return;
350             }
351           GDK_NOTE (INPUT, g_print ("opened Wintab device %d %p\n",
352                                    devix, *hctx));
353
354           wintab_contexts = g_list_append (wintab_contexts, hctx);
355 #if 0
356           WTEnable (*hctx, TRUE);
357 #endif
358           WTOverlap (*hctx, TRUE);
359
360 #if DEBUG_WINTAB
361           GDK_NOTE (INPUT, (g_print("context for device %d after WTOpen:\n", devix),
362                            print_lc(&lc)));
363 #endif
364           /* Increase packet queue size to reduce the risk of lost packets */
365           /* According to the specs, if the function fails we must try again */
366           /* with a smaller queue size */
367           GDK_NOTE (INPUT, g_print("Attempting to increase queue size\n"));
368           for (i = 128; i >= 1; i >>= 1)
369             {
370               if (WTQueueSizeSet(*hctx, i))
371                 {
372                   GDK_NOTE (INPUT, g_print("Queue size set to %d\n", i));
373                   break;
374                 }
375             }
376           if (!i)
377             GDK_NOTE (INPUT, g_print("Whoops, no queue size could be set\n"));
378           for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes; cursorix++)
379             {
380               active = FALSE;
381               WTInfo (WTI_CURSORS + cursorix, CSR_ACTIVE, &active);
382               if (!active)
383                 continue;
384               gdkdev = g_object_new (GDK_TYPE_DEVICE, NULL);
385               WTInfo (WTI_CURSORS + cursorix, CSR_NAME, csrname);
386               gdkdev->info.name = g_strconcat (devname, " ", csrname, NULL);
387               gdkdev->info.source = GDK_SOURCE_PEN;
388               gdkdev->info.mode = GDK_MODE_SCREEN;
389 #if USE_SYSCONTEXT
390               gdkdev->info.has_cursor = TRUE;
391 #else
392               gdkdev->info.has_cursor = FALSE;
393 #endif
394               gdkdev->hctx = *hctx;
395               gdkdev->cursor = cursorix;
396               WTInfo (WTI_CURSORS + cursorix, CSR_PKTDATA, &gdkdev->pktdata);
397               gdkdev->info.num_axes = 0;
398               if (gdkdev->pktdata & PK_X)
399                 gdkdev->info.num_axes++;
400               if (gdkdev->pktdata & PK_Y)
401                 gdkdev->info.num_axes++;
402               if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
403                 gdkdev->info.num_axes++;
404               /* The wintab driver for the Wacom ArtPad II reports
405                * PK_ORIENTATION in CSR_PKTDATA, but the tablet doesn't
406                * actually sense tilt. Catch this by noticing that the
407                * orientation axis's azimuth resolution is zero.
408                */
409               if ((gdkdev->pktdata & PK_ORIENTATION)
410                   && axis_or[0].axResolution == 0)
411                 gdkdev->pktdata &= ~PK_ORIENTATION;
412
413               if (gdkdev->pktdata & PK_ORIENTATION)
414                 gdkdev->info.num_axes += 2; /* x and y tilt */
415               WTInfo (WTI_CURSORS + cursorix, CSR_NPBTNMARKS, &gdkdev->npbtnmarks);
416               gdkdev->info.axes = g_new (GdkDeviceAxis, gdkdev->info.num_axes);
417               gdkdev->axes = g_new (GdkAxisInfo, gdkdev->info.num_axes);
418               gdkdev->last_axis_data = g_new (gint, gdkdev->info.num_axes);
419               
420               k = 0;
421               if (gdkdev->pktdata & PK_X)
422                 {
423                   gdkdev->axes[k].xresolution =
424                     gdkdev->axes[k].resolution = axis_x.axResolution / 65535.;
425                   gdkdev->axes[k].xmin_value =
426                     gdkdev->axes[k].min_value = axis_x.axMin;
427                   gdkdev->axes[k].xmax_value =
428                     gdkdev->axes[k].max_value = axis_x.axMax;
429                   gdkdev->info.axes[k].use = GDK_AXIS_X;
430                   gdkdev->info.axes[k].min = axis_x.axMin;
431                   gdkdev->info.axes[k].max = axis_x.axMax;
432                   k++;
433                 }
434               if (gdkdev->pktdata & PK_Y)
435                 {
436                   gdkdev->axes[k].xresolution =
437                     gdkdev->axes[k].resolution = axis_y.axResolution / 65535.;
438                   gdkdev->axes[k].xmin_value =
439                     gdkdev->axes[k].min_value = axis_y.axMin;
440                   gdkdev->axes[k].xmax_value =
441                     gdkdev->axes[k].max_value = axis_y.axMax;
442                   gdkdev->info.axes[k].use = GDK_AXIS_Y;
443                   gdkdev->info.axes[k].min = axis_y.axMin;
444                   gdkdev->info.axes[k].max = axis_y.axMax;
445                   k++;
446                 }
447               if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
448                 {
449                   gdkdev->axes[k].xresolution =
450                     gdkdev->axes[k].resolution = axis_npressure.axResolution / 65535.;
451                   gdkdev->axes[k].xmin_value =
452                     gdkdev->axes[k].min_value = axis_npressure.axMin;
453                   gdkdev->axes[k].xmax_value =
454                     gdkdev->axes[k].max_value = axis_npressure.axMax;
455                   gdkdev->info.axes[k].use = GDK_AXIS_PRESSURE;
456                   /* GIMP seems to expect values in the range 0-1 */
457                   gdkdev->info.axes[k].min = 0.0; /*axis_npressure.axMin;*/
458                   gdkdev->info.axes[k].max = 1.0; /*axis_npressure.axMax;*/
459                   k++;
460                 }
461               if (gdkdev->pktdata & PK_ORIENTATION)
462                 {
463                   GdkAxisUse axis;
464
465                   gdkdev->orientation_axes[0] = axis_or[0];
466                   gdkdev->orientation_axes[1] = axis_or[1];
467                   for (axis = GDK_AXIS_XTILT; axis <= GDK_AXIS_YTILT; axis++)
468                     {
469                       /* Wintab gives us aximuth and altitude, which
470                        * we convert to x and y tilt in the -1000..1000 range
471                        */
472                       gdkdev->axes[k].xresolution =
473                         gdkdev->axes[k].resolution = 1000;
474                       gdkdev->axes[k].xmin_value =
475                         gdkdev->axes[k].min_value = -1000;
476                       gdkdev->axes[k].xmax_value =
477                         gdkdev->axes[k].max_value = 1000;
478                       gdkdev->info.axes[k].use = axis;
479                       gdkdev->info.axes[k].min = -1000;
480                       gdkdev->info.axes[k].max = 1000;
481                       k++;
482                     }
483                 }
484               gdkdev->info.num_keys = 0;
485               gdkdev->info.keys = NULL;
486               GDK_NOTE (INPUT,
487                         g_print ("device: (%d) %s axes: %d\n",
488                                  cursorix,
489                                  gdkdev->info.name,
490                                  gdkdev->info.num_axes));
491               for (i = 0; i < gdkdev->info.num_axes; i++)
492                 GDK_NOTE (INPUT,
493                           g_print ("...axis %d: %d--%d@%d (%d--%d@%d)\n",
494                                    i,
495                                    gdkdev->axes[i].xmin_value, 
496                                    gdkdev->axes[i].xmax_value, 
497                                    gdkdev->axes[i].xresolution, 
498                                    gdkdev->axes[i].min_value, 
499                                    gdkdev->axes[i].max_value, 
500                                    gdkdev->axes[i].resolution));
501               _gdk_input_devices = g_list_append (_gdk_input_devices,
502                                                  gdkdev);
503             }
504         }
505     }
506 }
507
508 static void
509 decode_tilt (gint   *axis_data,
510              AXIS   *axes,
511              PACKET *packet)
512 {
513   /* As I don't have a tilt-sensing tablet,
514    * I cannot test this code.
515    */
516   
517   double az, el;
518
519   az = TWOPI * packet->pkOrientation.orAzimuth /
520     (axes[0].axResolution / 65536.);
521   el = TWOPI * packet->pkOrientation.orAltitude /
522     (axes[1].axResolution / 65536.);
523   
524   /* X tilt */
525   axis_data[0] = cos (az) * cos (el) * 1000;
526   /* Y tilt */
527   axis_data[1] = sin (az) * cos (el) * 1000;
528 }
529
530 #if !USE_SYSCONTEXT
531
532 static GdkInputWindow *
533 gdk_input_window_find_within (GdkWindow *window)
534 {
535   GList *list;
536   GdkWindow *tmpw;
537   GdkInputWindow *candidate = NULL;
538
539   for (list = _gdk_input_windows; list != NULL; list = list->next)
540     {
541       tmpw = ((GdkInputWindow *) (tmp_list->data))->window;
542       if (tmpw == window
543           || IsChild (GDK_WINDOW_HWND (window), GDK_WINDOW_HWND (tmpw)))
544         {
545           if (candidate)
546             return NULL;                /* Multiple hits */
547           candidate = (GdkInputWindow *) (list->data);
548         }
549     }
550
551   return candidate;
552 }
553
554 #endif /* USE_SYSCONTEXT */
555
556 #endif /* HAVE_WINTAB */
557
558 static void
559 gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
560                                  GdkInputWindow   *input_window,
561                                  gint             *axis_data,
562                                  gdouble          *axis_out,
563                                  gdouble          *x_out,
564                                  gdouble          *y_out)
565 {
566   GdkWindowImplWin32 *impl, *root_impl;
567
568   int i;
569   int x_axis = 0;
570   int y_axis = 0;
571
572   double device_width, device_height;
573   double x_offset, y_offset, x_scale, y_scale;
574
575   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (input_window->window)->impl);
576
577   for (i=0; i<gdkdev->info.num_axes; i++)
578     {
579       switch (gdkdev->info.axes[i].use)
580         {
581         case GDK_AXIS_X:
582           x_axis = i;
583           break;
584         case GDK_AXIS_Y:
585           y_axis = i;
586           break;
587         default:
588           break;
589         }
590     }
591   
592   device_width = gdkdev->axes[x_axis].max_value - 
593                    gdkdev->axes[x_axis].min_value;
594   device_height = gdkdev->axes[y_axis].max_value - 
595                     gdkdev->axes[y_axis].min_value;
596
597   if (gdkdev->info.mode == GDK_MODE_SCREEN) 
598     {
599       root_impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (_gdk_parent_root)->impl);
600       x_scale = root_impl->width / device_width;
601       y_scale = root_impl->height / device_height;
602
603       x_offset = - input_window->root_x;
604       y_offset = - input_window->root_y;
605     }
606   else                          /* GDK_MODE_WINDOW */
607     {
608       double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
609         (device_width*gdkdev->axes[x_axis].resolution);
610
611       if (device_aspect * impl->width >= impl->height)
612         {
613           /* device taller than window */
614           x_scale = impl->width / device_width;
615           y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
616             / gdkdev->axes[y_axis].resolution;
617
618           x_offset = 0;
619           y_offset = -(device_height * y_scale - 
620                                impl->height)/2;
621         }
622       else
623         {
624           /* window taller than device */
625           y_scale = impl->height / device_height;
626           x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
627             / gdkdev->axes[x_axis].resolution;
628
629           y_offset = 0;
630           x_offset = - (device_width * x_scale - impl->width)/2;
631         }
632     }
633
634   for (i=0; i<gdkdev->info.num_axes; i++)
635     {
636       switch (gdkdev->info.axes[i].use)
637         {
638         case GDK_AXIS_X:
639           axis_out[i] = x_offset + x_scale*axis_data[x_axis];
640           if (x_out)
641             *x_out = axis_out[i];
642           break;
643         case GDK_AXIS_Y:
644           axis_out[i] = y_offset + y_scale*axis_data[y_axis];
645           if (y_out)
646             *y_out = axis_out[i];
647           break;
648         default:
649           axis_out[i] =
650             (gdkdev->info.axes[i].max * (axis_data[i] - gdkdev->axes[i].min_value) +
651              gdkdev->info.axes[i].min * (gdkdev->axes[i].max_value - axis_data[i])) /
652             (gdkdev->axes[i].max_value - gdkdev->axes[i].min_value);
653           break;
654         }
655     }
656 }
657
658 static void
659 gdk_input_get_root_relative_geometry (HWND w,
660                                       int  *x_ret,
661                                       int  *y_ret)
662 {
663   RECT rect;
664
665   GetWindowRect (w, &rect);
666
667   if (x_ret)
668     *x_ret = rect.left + _gdk_offset_x;
669   if (y_ret)
670     *y_ret = rect.top + _gdk_offset_y;
671 }
672
673 void
674 _gdk_input_configure_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),
683                                         &root_x, &root_y);
684
685   input_window->root_x = root_x;
686   input_window->root_y = root_y;
687 }
688
689 void 
690 _gdk_input_enter_event (GdkWindow        *window)
691 {
692   GdkInputWindow *input_window;
693   int root_x, root_y;
694
695   input_window = _gdk_input_window_find (window);
696   g_return_if_fail (window != NULL);
697
698   gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window), &root_x, &root_y);
699
700   input_window->root_x = root_x;
701   input_window->root_y = root_y;
702 }
703
704 /*
705  * Get the currently active keyboard modifiers (ignoring the mouse buttons)
706  * We could use gdk_window_get_pointer but that function does a lot of other
707  * expensive things besides getting the modifiers. This code is somewhat based
708  * on build_pointer_event_state from gdkevents-win32.c
709  */
710 static guint
711 get_modifier_key_state (void)
712 {
713   guint state;
714   
715   state = 0;
716   /* High-order bit is up/down, low order bit is toggled/untoggled */
717   if (GetKeyState (VK_CONTROL) < 0)
718     state |= GDK_CONTROL_MASK;
719   if (GetKeyState (VK_SHIFT) < 0)
720     state |= GDK_SHIFT_MASK;
721   if (GetKeyState (VK_MENU) < 0)
722     state |= GDK_MOD1_MASK;
723   if (GetKeyState (VK_CAPITAL) & 0x1)
724     state |= GDK_LOCK_MASK;
725
726   return state;
727 }
728
729 gboolean 
730 _gdk_input_other_event (GdkEvent  *event,
731                         MSG       *msg,
732                         GdkWindow *window)
733 {
734 #ifdef HAVE_WINTAB
735 #if !USE_SYSCONTEXT
736   GdkWindow *current_window;
737 #endif
738   GdkDisplay *display;
739   GdkWindowObject *obj, *grab_obj;
740   GdkInputWindow *input_window;
741   GdkDevicePrivate *gdkdev = NULL;
742   GdkEventMask masktest;
743   guint key_state;
744   POINT pt;
745
746   PACKET packet;
747   gint k;
748   gint x, y;
749
750   if (event->any.window != wintab_window)
751     {
752       g_warning ("_gdk_input_other_event: not wintab_window?");
753       return FALSE;
754     }
755
756 #if USE_SYSCONTEXT
757   window = gdk_window_at_pointer (&x, &y);
758   if (window == NULL)
759     window = _gdk_parent_root;
760
761   g_object_ref (window);
762   display = gdk_drawable_get_display (window);
763
764   GDK_NOTE (EVENTS_OR_INPUT,
765             g_print ("gdk_input_win32_other_event: window=%p (%d,%d)\n",
766                      GDK_WINDOW_HWND (window), x, y));
767   
768 #else
769   /* ??? This code is pretty bogus */
770   current_window = gdk_win32_handle_table_lookup (GetActiveWindow ());
771   if (current_window == NULL)
772     return FALSE;
773   
774   input_window = gdk_input_window_find_within (current_window);
775   if (input_window == NULL)
776     return FALSE;
777 #endif
778
779   if (msg->message == WT_PACKET)
780     {
781       if (!WTPacket ((HCTX) msg->lParam, msg->wParam, &packet))
782         return FALSE;
783     }
784
785   obj = GDK_WINDOW_OBJECT (window);
786
787   switch (msg->message)
788     {
789     case WT_PACKET:
790       /* Don't produce any button or motion events while a window is being
791        * moved or resized, see bug #151090. */
792       if (_sizemove_in_progress)
793         {
794           GDK_NOTE (EVENTS_OR_INPUT, g_print ("...ignored when moving/sizing\n"));
795           return FALSE;
796         }
797       if (window == _gdk_parent_root && x_grab_window == NULL)
798         {
799           GDK_NOTE (EVENTS_OR_INPUT, g_print ("...is root\n"));
800           return FALSE;
801         }
802
803       if ((gdkdev = gdk_input_find_dev_from_ctx ((HCTX) msg->lParam,
804                                                  packet.pkCursor)) == NULL)
805         return FALSE;
806
807       if (gdkdev->info.mode == GDK_MODE_DISABLED)
808         return FALSE;
809       
810       k = 0;
811       if (gdkdev->pktdata & PK_X)
812         gdkdev->last_axis_data[k++] = packet.pkX;
813       if (gdkdev->pktdata & PK_Y)
814         gdkdev->last_axis_data[k++] = packet.pkY;
815       if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
816         gdkdev->last_axis_data[k++] = packet.pkNormalPressure;
817       if (gdkdev->pktdata & PK_ORIENTATION)
818         {
819           decode_tilt (gdkdev->last_axis_data + k,
820                        gdkdev->orientation_axes, &packet);
821           k += 2;
822         }
823
824       g_assert (k == gdkdev->info.num_axes);
825
826       if (HIWORD (packet.pkButtons) != TBN_NONE)
827         {
828           /* Gdk buttons are numbered 1.. */
829           event->button.button = 1 + LOWORD (packet.pkButtons);
830
831           if (HIWORD (packet.pkButtons) == TBN_UP)
832             {
833               event->any.type = GDK_BUTTON_RELEASE;
834               masktest = GDK_BUTTON_RELEASE_MASK;
835               gdkdev->button_state &= ~(1 << LOWORD (packet.pkButtons));
836             }
837           else
838             {
839               event->any.type = GDK_BUTTON_PRESS;
840               masktest = GDK_BUTTON_PRESS_MASK;
841               gdkdev->button_state |= 1 << LOWORD (packet.pkButtons);
842             }
843         }
844       else
845         {
846           event->any.type = GDK_MOTION_NOTIFY;
847           masktest = GDK_POINTER_MOTION_MASK;
848           if (gdkdev->button_state & (1 << 0))
849             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK;
850           if (gdkdev->button_state & (1 << 1))
851             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK;
852           if (gdkdev->button_state & (1 << 2))
853             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK;
854         }
855
856       /* See if input is grabbed */
857       /* FIXME: x_grab_owner_events should probably be handled somehow */
858       if (x_grab_window != NULL)
859         {
860           grab_obj = GDK_WINDOW_OBJECT (x_grab_window);
861           if (!GDK_WINDOW_IMPL_WIN32 (grab_obj->impl)->extension_events_selected
862               || !(grab_obj->extension_events & masktest)
863               || !(x_grab_mask && masktest))
864             {
865               GDK_NOTE (EVENTS_OR_INPUT, 
866                         g_print ("...grabber doesn't want it\n"));
867               return FALSE;
868             }
869           GDK_NOTE (EVENTS_OR_INPUT, g_print ("...to grabber\n"));
870
871           g_object_ref(x_grab_window);
872           g_object_unref(window);
873           window = x_grab_window;
874           obj = grab_obj;
875         }
876       /* Now we can check if the window wants the event, and
877        * propagate if necessary.
878        */
879     dijkstra:
880       if (!GDK_WINDOW_IMPL_WIN32 (obj->impl)->extension_events_selected
881           || !(obj->extension_events & masktest))
882         {
883           GDK_NOTE (EVENTS_OR_INPUT, g_print ("...not selected\n"));
884
885           if (obj->parent == GDK_WINDOW_OBJECT (_gdk_parent_root))
886             return FALSE;
887
888           /* It is not good to propagate the extended events up to the parent
889            * if this window wants normal (not extended) motion/button events */
890           if (obj->event_mask & masktest)
891             {
892               GDK_NOTE (EVENTS_OR_INPUT, 
893                         g_print ("...wants ordinary event, ignoring this\n"));
894               return FALSE;
895             }
896           
897           pt.x = x;
898           pt.y = y;
899           ClientToScreen (GDK_WINDOW_HWND (window), &pt);
900           g_object_unref (window);
901           window = (GdkWindow *) obj->parent;
902           obj = GDK_WINDOW_OBJECT (window);
903           g_object_ref (window);
904           ScreenToClient (GDK_WINDOW_HWND (window), &pt);
905           x = pt.x;
906           y = pt.y;
907           GDK_NOTE (EVENTS_OR_INPUT, g_print ("...propagating to %p (%d,%d)\n",
908                                               GDK_WINDOW_HWND (window), x, y));
909           goto dijkstra;
910         }
911
912       input_window = _gdk_input_window_find (window);
913
914       g_assert (input_window != NULL);
915
916       if (gdkdev->info.mode == GDK_MODE_WINDOW
917           && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
918         return FALSE;
919
920       event->any.window = window;
921       key_state = get_modifier_key_state ();
922       if (event->any.type == GDK_BUTTON_PRESS
923           || event->any.type == GDK_BUTTON_RELEASE)
924         {
925           event->button.time = _gdk_win32_get_next_tick (msg->time);
926           event->button.device = &gdkdev->info;
927           
928 #if 0
929 #if USE_SYSCONTEXT
930           /* Buttons 1 to 3 will come in as WM_[LMR]BUTTON{DOWN,UP} */
931           if (event->button.button <= 3)
932             return FALSE;
933 #endif
934 #endif
935           event->button.axes = g_new(gdouble, gdkdev->info.num_axes);
936
937           gdk_input_translate_coordinates (gdkdev, input_window,
938                                            gdkdev->last_axis_data,
939                                            event->button.axes,
940                                            &event->button.x, 
941                                            &event->button.y);
942
943           /* Also calculate root coordinates. Note that input_window->root_x
944              is in GDK root coordinates. */
945           event->button.x_root = event->button.x + input_window->root_x;
946           event->button.y_root = event->button.y + input_window->root_y;
947
948           event->button.state = ((gdkdev->button_state << 8)
949                                  & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
950                                     | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
951                                     | GDK_BUTTON5_MASK))
952                                 | key_state;
953           GDK_NOTE (EVENTS_OR_INPUT,
954                     g_print ("WINTAB button %s:%d %g,%g\n",
955                              (event->button.type == GDK_BUTTON_PRESS ?
956                               "press" : "release"),
957                              event->button.button,
958                              event->button.x, event->button.y));
959         }
960       else
961         {
962           event->motion.time = _gdk_win32_get_next_tick (msg->time);
963           event->motion.is_hint = FALSE;
964           event->motion.device = &gdkdev->info;
965
966           event->motion.axes = g_new(gdouble, gdkdev->info.num_axes);
967
968           gdk_input_translate_coordinates (gdkdev, input_window,
969                                            gdkdev->last_axis_data,
970                                            event->motion.axes,
971                                            &event->motion.x, 
972                                            &event->motion.y);
973
974           /* Also calculate root coordinates. Note that input_window->root_x
975              is in GDK root coordinates. */
976           event->motion.x_root = event->motion.x + input_window->root_x;
977           event->motion.y_root = event->motion.y + input_window->root_y;
978
979           event->motion.state = ((gdkdev->button_state << 8)
980                                  & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
981                                     | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
982                                     | GDK_BUTTON5_MASK))
983                                 | key_state;
984
985           GDK_NOTE (EVENTS_OR_INPUT,
986                     g_print ("WINTAB motion: %g,%g\n",
987                              event->motion.x, event->motion.y));
988
989           /* Check for missing release or press events for the normal
990            * pressure button. At least on my ArtPadII I sometimes miss a
991            * release event?
992            */
993           if ((gdkdev->pktdata & PK_NORMAL_PRESSURE
994                && (event->motion.state & GDK_BUTTON1_MASK)
995                && packet.pkNormalPressure <= MAX (0, (gint) gdkdev->npbtnmarks[0] - 2))
996               || (gdkdev->pktdata & PK_NORMAL_PRESSURE
997                   && !(event->motion.state & GDK_BUTTON1_MASK)
998                   && packet.pkNormalPressure > gdkdev->npbtnmarks[1] + 2))
999             {
1000               GdkEvent *event2 = gdk_event_copy (event);
1001               if (event->motion.state & GDK_BUTTON1_MASK)
1002                 {
1003                   event2->button.type = GDK_BUTTON_RELEASE;
1004                   gdkdev->button_state &= ~1;
1005                 }
1006               else
1007                 {
1008                   event2->button.type = GDK_BUTTON_PRESS;
1009                   gdkdev->button_state |= 1;
1010                 }
1011               event2->button.state = ((gdkdev->button_state << 8)
1012                                       & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1013                                          | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1014                                          | GDK_BUTTON5_MASK))
1015                                      | key_state;
1016               event2->button.button = 1;
1017               GDK_NOTE (EVENTS_OR_INPUT,
1018                         g_print ("WINTAB synthesized button %s: %d %g,%gg\n",
1019                                  (event2->button.type == GDK_BUTTON_PRESS ?
1020                                   "press" : "release"),
1021                                  event2->button.button,
1022                                  event2->button.x,
1023                                  event2->button.y));
1024               _gdk_event_queue_append (display, event2);
1025             }
1026         }
1027       return TRUE;
1028
1029     case WT_PROXIMITY:
1030       if (LOWORD (msg->lParam) == 0)
1031         {
1032           event->proximity.type = GDK_PROXIMITY_OUT;
1033           _gdk_input_ignore_core = FALSE;
1034         }
1035       else
1036         {
1037           event->proximity.type = GDK_PROXIMITY_IN;
1038           _gdk_input_ignore_core = TRUE;
1039         }
1040       event->proximity.time = _gdk_win32_get_next_tick (msg->time);
1041       event->proximity.device = &gdkdev->info;
1042
1043       GDK_NOTE (EVENTS_OR_INPUT,
1044                 g_print ("WINTAB proximity %s\n",
1045                          (event->proximity.type == GDK_PROXIMITY_IN ?
1046                           "in" : "out")));
1047       return TRUE;
1048     }
1049 #endif
1050   return FALSE;
1051 }
1052
1053 gboolean
1054 _gdk_input_enable_window (GdkWindow        *window,
1055                           GdkDevicePrivate *gdkdev)
1056 {
1057 #ifdef HAVE_SOME_XINPUT
1058   GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1059
1060   impl->extension_events_selected = TRUE;
1061 #endif
1062
1063   return TRUE;
1064 }
1065
1066 gboolean
1067 _gdk_input_disable_window (GdkWindow        *window,
1068                            GdkDevicePrivate *gdkdev)
1069 {
1070 #ifdef HAVE_SOME_XINPUT
1071   GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1072
1073   impl->extension_events_selected = FALSE;
1074 #endif
1075
1076   return TRUE;
1077 }
1078
1079 gint
1080 _gdk_input_grab_pointer (GdkWindow    *window,
1081                          gint          owner_events,
1082                          GdkEventMask  event_mask,
1083                          GdkWindow    *confine_to,
1084                          guint32       time)
1085 {
1086 #ifdef HAVE_SOME_XINPUT
1087   GdkInputWindow *input_window, *new_window;
1088   gboolean need_ungrab;
1089   GdkDevicePrivate *gdkdev;
1090   GList *tmp_list;
1091
1092   tmp_list = _gdk_input_windows;
1093   new_window = NULL;
1094   need_ungrab = FALSE;
1095
1096   GDK_NOTE (INPUT, g_print ("gdk_input_win32_grab_pointer: %p %d %p\n",
1097                            GDK_WINDOW_HWND (window),
1098                            owner_events,
1099                            (confine_to ? GDK_WINDOW_HWND (confine_to) : 0)));
1100
1101   while (tmp_list)
1102     {
1103       input_window = (GdkInputWindow *)tmp_list->data;
1104
1105       if (input_window->window == window)
1106         new_window = input_window;
1107       else if (input_window->grabbed)
1108         {
1109           input_window->grabbed = FALSE;
1110           need_ungrab = TRUE;
1111         }
1112
1113       tmp_list = tmp_list->next;
1114     }
1115
1116   if (new_window)
1117     {
1118       new_window->grabbed = TRUE;
1119       x_grab_window = window;
1120       x_grab_mask = event_mask;
1121       x_grab_owner_events = owner_events;
1122
1123       /* FIXME: Do we need to handle confine_to and time? */
1124       
1125       tmp_list = _gdk_input_devices;
1126       while (tmp_list)
1127         {
1128           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1129           if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx)
1130             {
1131 #if 0         
1132               /* XXX */
1133               gdk_input_common_find_events (window, gdkdev,
1134                                             event_mask,
1135                                             event_classes, &num_classes);
1136               
1137               result = XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
1138                                     GDK_WINDOW_XWINDOW (window),
1139                                     owner_events, num_classes, event_classes,
1140                                     GrabModeAsync, GrabModeAsync, time);
1141               
1142               /* FIXME: if failure occurs on something other than the first
1143                  device, things will be badly inconsistent */
1144               if (result != Success)
1145                 return result;
1146 #endif
1147             }
1148           tmp_list = tmp_list->next;
1149         }
1150     }
1151   else
1152     { 
1153       x_grab_window = NULL;
1154       tmp_list = _gdk_input_devices;
1155       while (tmp_list)
1156         {
1157           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1158           if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx &&
1159               ((gdkdev->button_state != 0) || need_ungrab))
1160             {
1161 #if 0
1162               /* XXX */
1163               XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1164 #endif
1165               gdkdev->button_state = 0;
1166             }
1167           
1168           tmp_list = tmp_list->next;
1169         }
1170     }
1171 #endif
1172
1173   return GDK_GRAB_SUCCESS;
1174 }
1175
1176 void 
1177 _gdk_input_ungrab_pointer (guint32 time)
1178 {
1179 #ifdef HAVE_SOME_XINPUT
1180   GdkInputWindow *input_window;
1181   GdkDevicePrivate *gdkdev;
1182   GList *tmp_list;
1183
1184   GDK_NOTE (INPUT, g_print ("gdk_input_win32_ungrab_pointer\n"));
1185
1186   tmp_list = _gdk_input_windows;
1187   while (tmp_list)
1188     {
1189       input_window = (GdkInputWindow *)tmp_list->data;
1190       if (input_window->grabbed)
1191         break;
1192       tmp_list = tmp_list->next;
1193     }
1194
1195   if (tmp_list)                 /* we found a grabbed window */
1196     {
1197       input_window->grabbed = FALSE;
1198
1199       tmp_list = _gdk_input_devices;
1200       while (tmp_list)
1201         {
1202           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1203 #if 0
1204           /* XXX */
1205           if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
1206             XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1207 #endif
1208           tmp_list = tmp_list->next;
1209         }
1210     }
1211   x_grab_window = NULL;
1212 #endif
1213 }
1214
1215 gboolean
1216 _gdk_device_get_history (GdkDevice         *device,
1217                          GdkWindow         *window,
1218                          guint32            start,
1219                          guint32            stop,
1220                          GdkTimeCoord    ***events,
1221                          gint              *n_events)
1222 {
1223   return FALSE;
1224 }
1225
1226 void 
1227 gdk_device_get_state (GdkDevice       *device,
1228                       GdkWindow       *window,
1229                       gdouble         *axes,
1230                       GdkModifierType *mask)
1231 {
1232   g_return_if_fail (device != NULL);
1233   g_return_if_fail (GDK_IS_WINDOW (window));
1234
1235   if (GDK_IS_CORE (device))
1236     {
1237       gint x_int, y_int;
1238       
1239       gdk_window_get_pointer (window, &x_int, &y_int, mask);
1240
1241       if (axes)
1242         {
1243           axes[0] = x_int;
1244           axes[1] = y_int;
1245         }
1246     }
1247   else
1248     {
1249       GdkDevicePrivate *gdkdev;
1250       GdkInputWindow *input_window;
1251       
1252       gdkdev = (GdkDevicePrivate *)device;
1253       /* For now just use the last known button and axis state of the device.
1254        * Since graphical tablets send an insane amount of motion events each
1255        * second, the info should be fairly up to date */
1256       if (mask)
1257         {
1258           gdk_window_get_pointer (window, NULL, NULL, mask);
1259           *mask &= 0xFF; /* Mask away core pointer buttons */
1260           *mask |= ((gdkdev->button_state << 8)
1261                     & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1262                        | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1263                        | GDK_BUTTON5_MASK));
1264         }
1265       input_window = _gdk_input_window_find (window);
1266       g_return_if_fail (input_window != NULL);
1267       /* For some reason, input_window is sometimes NULL when I use The GIMP 2
1268        * (bug #141543?). Avoid crashing if debugging is disabled. */
1269       if (axes && gdkdev->last_axis_data && input_window)
1270         gdk_input_translate_coordinates (gdkdev, input_window,
1271                                          gdkdev->last_axis_data,
1272                                          axes, NULL, NULL);
1273     }
1274 }
1275
1276 #ifdef HAVE_WINTAB
1277 void
1278 _gdk_input_set_tablet_active (void)
1279 {
1280   GList *tmp_list;
1281   HCTX *hctx;
1282
1283   /* Bring the contexts to the top of the overlap order when one of the
1284    * application's windows is activated */
1285   
1286   if (!wintab_contexts)
1287     return; /* No tablet devices found, or Wintab not initialized yet */
1288   
1289   GDK_NOTE (INPUT, g_print ("_gdk_input_set_tablet_active: "
1290         "Bringing Wintab contexts to the top of the overlap order\n"));
1291
1292   tmp_list = wintab_contexts;
1293   while (tmp_list)
1294     {
1295       hctx = (HCTX *) (tmp_list->data);
1296       WTOverlap (*hctx, TRUE);
1297       tmp_list = tmp_list->next;
1298     }
1299 }
1300 #endif /* HAVE_WINTAB */
1301
1302 void 
1303 _gdk_input_init (GdkDisplay *display)
1304 {
1305   _gdk_input_ignore_core = FALSE;
1306   _gdk_input_devices = NULL;
1307
1308   _gdk_init_input_core (display);
1309 #ifdef HAVE_WINTAB
1310 #ifdef WINTAB_NO_LAZY_INIT
1311   /* Normally, Wintab is only initialized when the application performs
1312    * an action that requires it, such as enabling extended input events
1313    * for a window or enumerating the devices.
1314    */
1315   _gdk_input_wintab_init_check ();
1316 #endif /* WINTAB_NO_LAZY_INIT */
1317 #endif /* HAVE_WINTAB */
1318
1319   _gdk_input_devices = g_list_append (_gdk_input_devices, display->core_pointer);
1320 }
1321