]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkinput.c
Change GDK_WINDOWING_WIN32 usage to #ifdef also here.
[~andy/gtk] / gdk / win32 / gdkinput.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  * Copyright (C) 1999 Tor Lillqvist
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library 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  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library 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-1999.  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 "gdkinput.h"
35 #include "gdkprivate.h"
36
37 #ifdef HAVE_WINTAB
38 #include <wintab.h>
39 #define PACKETDATA (PK_CONTEXT | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y  | PK_NORMAL_PRESSURE | PK_ORIENTATION)
40 #define PACKETMODE (PK_BUTTONS)
41 #include <pktdef.h>
42 #endif
43
44 #include "gdkinputprivate.h"
45
46 struct _GdkDevicePrivate {
47   GdkDeviceInfo  info;
48
49   /* information about the axes */
50   GdkAxisInfo *axes;
51
52   /* reverse lookup on axis use type */
53   gint axis_for_use[GDK_AXIS_LAST];
54   
55   /* true if we need to select a different set of events, but
56    * can't because this is the core pointer
57    */
58   gint needs_update;
59
60   /* State of buttons */
61   gint button_state;
62
63   gint *last_axis_data;
64   gint last_buttons;
65 #ifdef HAVE_WINTAB
66   /* WINTAB stuff: */
67   HCTX hctx;
68   /* Cursor number */
69   UINT cursor;
70   /* The cursor's CSR_PKTDATA */
71   WTPKT pktdata;
72   /* CSR_NPBTNMARKS */
73   UINT npbtnmarks[2];
74   /* Azimuth and altitude axis */
75   AXIS orientation_axes[2];
76 #endif
77 };
78
79 #ifndef M_PI
80 #define M_PI 3.14159265358979323846
81 #endif
82
83 /* If USE_SYSCONTEXT is on, we open the Wintab device (hmm, what if
84  * there are several?) as a system pointing device, i.e. it controls
85  * the normal Windows cursor. This seems much more natural.
86  */
87 #define USE_SYSCONTEXT 1        /* The code for the other choice is not
88                                  * good at all.
89                                  */
90
91 #ifdef HAVE_WINTAB
92 #define DEBUG_WINTAB 1
93 #endif
94
95 #define TWOPI (2.*M_PI)
96
97 #define PING() g_print("%s: %d\n",__FILE__,__LINE__)
98
99 /* Forward declarations */
100
101 static gint gdk_input_enable_window (GdkWindow *window,
102                                      GdkDevicePrivate *gdkdev);
103 static gint gdk_input_disable_window (GdkWindow *window,
104                                       GdkDevicePrivate *gdkdev);
105 static void gdk_input_none_get_pointer (GdkWindow       *window,
106                                         guint32          deviceid,
107                                         gdouble         *x,
108                                         gdouble         *y,
109                                         gdouble         *pressure,
110                                         gdouble         *xtilt,
111                                         gdouble         *ytilt,
112                                         GdkModifierType *mask);
113
114 static GdkDevicePrivate *gdk_input_find_device (guint32 deviceid);
115
116 #ifdef HAVE_WINTAB
117
118 static gint gdk_input_win32_set_mode (guint32      deviceid,
119                                       GdkInputMode mode);
120 static void gdk_input_win32_get_pointer (GdkWindow       *window,
121                                          guint32            deviceid,
122                                          gdouble         *x,
123                                          gdouble         *y,
124                                          gdouble         *pressure,
125                                          gdouble         *xtilt,
126                                          gdouble         *ytilt,
127                                          GdkModifierType *mask);
128 static gint gdk_input_win32_grab_pointer (GdkWindow *     window,
129                                           gint            owner_events,
130                                           GdkEventMask    event_mask,
131                                           GdkWindow      *confine_to,
132                                           guint32         time);
133 static void gdk_input_win32_ungrab_pointer (guint32 time);
134 static void gdk_input_win32_configure_event (GdkEventConfigure *event, 
135                                              GdkWindow         *window);
136 static void gdk_input_win32_enter_event (GdkEventCrossing  *xevent, 
137                                          GdkWindow         *window);
138 static gint gdk_input_win32_other_event (GdkEvent  *event, 
139                                          MSG       *xevent);
140 static gint gdk_input_win32_enable_window (GdkWindow        *window,
141                                            GdkDevicePrivate *gdkdev);
142 static gint gdk_input_win32_disable_window (GdkWindow        *window,
143                                             GdkDevicePrivate *gdkdev);
144
145 static GdkInputWindow *gdk_input_window_find (GdkWindow *window);
146 #if !USE_SYSCONTEXT
147 static GdkInputWindow *gdk_input_window_find_within (GdkWindow *window);
148 #endif
149 static GdkDevicePrivate *gdk_input_find_dev_from_ctx (HCTX hctx,
150                                                       UINT id);
151 #endif /* HAVE_WINTAB */
152
153 /* Local variables */
154
155 static GList     *gdk_input_devices;
156 static GList     *gdk_input_windows;
157 static GList     *wintab_contexts;
158
159 static gint gdk_input_root_width;
160 static gint gdk_input_root_height;
161
162 static GdkWindow *wintab_window;
163
164 static guint32 last_moved_cursor_id;
165
166 static GdkAxisUse gdk_input_core_axes[] = { GDK_AXIS_X, GDK_AXIS_Y };
167
168 static GdkDeviceInfo gdk_input_core_info =
169 {
170   GDK_CORE_POINTER,
171   "Core Pointer",
172   GDK_SOURCE_MOUSE,
173   GDK_MODE_SCREEN,
174   TRUE,
175   2,
176   gdk_input_core_axes
177 };
178
179 /* Global variables  */
180
181 GdkInputVTable    gdk_input_vtable;
182 gint              gdk_input_ignore_core;
183 gint              gdk_input_ignore_wintab = FALSE;
184
185 #if DEBUG_WINTAB
186
187 static void
188 print_lc(LOGCONTEXT *lc)
189 {
190   g_print ("lcName = %s\n", lc->lcName);
191   g_print ("lcOptions =");
192   if (lc->lcOptions & CXO_SYSTEM) g_print (" CXO_SYSTEM");
193   if (lc->lcOptions & CXO_PEN) g_print (" CXO_PEN");
194   if (lc->lcOptions & CXO_MESSAGES) g_print (" CXO_MESSAGES");
195   if (lc->lcOptions & CXO_MARGIN) g_print (" CXO_MARGIN");
196   if (lc->lcOptions & CXO_MGNINSIDE) g_print (" CXO_MGNINSIDE");
197   if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
198   if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
199   g_print ("\n");
200   g_print ("lcStatus =");
201   if (lc->lcStatus & CXS_DISABLED) g_print (" CXS_DISABLED");
202   if (lc->lcStatus & CXS_OBSCURED) g_print (" CXS_OBSCURED");
203   if (lc->lcStatus & CXS_ONTOP) g_print (" CXS_ONTOP");
204   g_print ("\n");
205   g_print ("lcLocks =");
206   if (lc->lcLocks & CXL_INSIZE) g_print (" CXL_INSIZE");
207   if (lc->lcLocks & CXL_INASPECT) g_print (" CXL_INASPECT");
208   if (lc->lcLocks & CXL_SENSITIVITY) g_print (" CXL_SENSITIVITY");
209   if (lc->lcLocks & CXL_MARGIN) g_print (" CXL_MARGIN");
210   g_print ("\n");
211   g_print ("lcMsgBase = %#x, lcDevice = %#x, lcPktRate = %d\n",
212           lc->lcMsgBase, lc->lcDevice, lc->lcPktRate);
213   g_print ("lcPktData =");
214   if (lc->lcPktData & PK_CONTEXT) g_print (" PK_CONTEXT");
215   if (lc->lcPktData & PK_STATUS) g_print (" PK_STATUS");
216   if (lc->lcPktData & PK_TIME) g_print (" PK_TIME");
217   if (lc->lcPktData & PK_CHANGED) g_print (" PK_CHANGED");
218   if (lc->lcPktData & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
219   if (lc->lcPktData & PK_CURSOR) g_print (" PK_CURSOR");
220   if (lc->lcPktData & PK_BUTTONS) g_print (" PK_BUTTONS");
221   if (lc->lcPktData & PK_X) g_print (" PK_X");
222   if (lc->lcPktData & PK_Y) g_print (" PK_Y");
223   if (lc->lcPktData & PK_Z) g_print (" PK_Z");
224   if (lc->lcPktData & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
225   if (lc->lcPktData & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
226   if (lc->lcPktData & PK_ORIENTATION) g_print (" PK_ORIENTATION");
227   if (lc->lcPktData & PK_ROTATION) g_print (" PK_ROTATION");
228   g_print ("\n");
229   g_print ("lcPktMode =");
230   if (lc->lcPktMode & PK_CONTEXT) g_print (" PK_CONTEXT");
231   if (lc->lcPktMode & PK_STATUS) g_print (" PK_STATUS");
232   if (lc->lcPktMode & PK_TIME) g_print (" PK_TIME");
233   if (lc->lcPktMode & PK_CHANGED) g_print (" PK_CHANGED");
234   if (lc->lcPktMode & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
235   if (lc->lcPktMode & PK_CURSOR) g_print (" PK_CURSOR");
236   if (lc->lcPktMode & PK_BUTTONS) g_print (" PK_BUTTONS");
237   if (lc->lcPktMode & PK_X) g_print (" PK_X");
238   if (lc->lcPktMode & PK_Y) g_print (" PK_Y");
239   if (lc->lcPktMode & PK_Z) g_print (" PK_Z");
240   if (lc->lcPktMode & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
241   if (lc->lcPktMode & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
242   if (lc->lcPktMode & PK_ORIENTATION) g_print (" PK_ORIENTATION");
243   if (lc->lcPktMode & PK_ROTATION) g_print (" PK_ROTATION");
244   g_print ("\n");
245   g_print ("lcMoveMask =");
246   if (lc->lcMoveMask & PK_CONTEXT) g_print (" PK_CONTEXT");
247   if (lc->lcMoveMask & PK_STATUS) g_print (" PK_STATUS");
248   if (lc->lcMoveMask & PK_TIME) g_print (" PK_TIME");
249   if (lc->lcMoveMask & PK_CHANGED) g_print (" PK_CHANGED");
250   if (lc->lcMoveMask & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
251   if (lc->lcMoveMask & PK_CURSOR) g_print (" PK_CURSOR");
252   if (lc->lcMoveMask & PK_BUTTONS) g_print (" PK_BUTTONS");
253   if (lc->lcMoveMask & PK_X) g_print (" PK_X");
254   if (lc->lcMoveMask & PK_Y) g_print (" PK_Y");
255   if (lc->lcMoveMask & PK_Z) g_print (" PK_Z");
256   if (lc->lcMoveMask & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
257   if (lc->lcMoveMask & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
258   if (lc->lcMoveMask & PK_ORIENTATION) g_print (" PK_ORIENTATION");
259   if (lc->lcMoveMask & PK_ROTATION) g_print (" PK_ROTATION");
260   g_print ("\n");
261   g_print ("lcBtnDnMask = %#x, lcBtnUpMask = %#x\n",
262           lc->lcBtnDnMask, lc->lcBtnUpMask);
263   g_print ("lcInOrgX = %d, lcInOrgY = %d, lcInOrgZ = %d\n",
264           lc->lcInOrgX, lc->lcInOrgY, lc->lcInOrgZ);
265   g_print ("lcInExtX = %d, lcInExtY = %d, lcInExtZ = %d\n",
266           lc->lcInExtX, lc->lcInExtY, lc->lcInExtZ);
267   g_print ("lcOutOrgX = %d, lcOutOrgY = %d, lcOutOrgZ = %d\n",
268           lc->lcOutOrgX, lc->lcOutOrgY, lc->lcOutOrgZ);
269   g_print ("lcOutExtX = %d, lcOutExtY = %d, lcOutExtZ = %d\n",
270           lc->lcOutExtX, lc->lcOutExtY, lc->lcOutExtZ);
271   g_print ("lcSensX = %g, lcSensY = %g, lcSensZ = %g\n",
272           lc->lcSensX / 65536., lc->lcSensY / 65536., lc->lcSensZ / 65536.);
273   g_print ("lcSysMode = %d\n", lc->lcSysMode);
274   g_print ("lcSysOrgX = %d, lcSysOrgY = %d\n",
275           lc->lcSysOrgX, lc->lcSysOrgY);
276   g_print ("lcSysExtX = %d, lcSysExtY = %d\n",
277           lc->lcSysExtX, lc->lcSysExtY);
278   g_print ("lcSysSensX = %g, lcSysSensY = %g\n",
279           lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.);
280 }
281
282 #endif
283
284 void 
285 gdk_input_init (void)
286 {
287   guint32 deviceid_counter = 0;
288 #ifdef HAVE_WINTAB
289   GdkDevicePrivate *gdkdev;
290   GdkWindowPrivate *window_private;
291   GdkWindowAttr wa;
292   WORD specversion;
293   LOGCONTEXT defcontext;
294   HCTX *hctx;
295   UINT ndevices, ncursors, ncsrtypes, firstcsr, hardware;
296   BOOL active;
297   AXIS axis_x, axis_y, axis_npressure, axis_or[3];
298   int i, j, k;
299   int devix, cursorix;
300   char devname[100], csrname[100];
301
302   gdk_input_devices = NULL;
303   wintab_contexts = NULL;
304
305   if (!gdk_input_ignore_wintab &&
306       WTInfo (0, 0, NULL))
307     {
308       WTInfo (WTI_INTERFACE, IFC_SPECVERSION, &specversion);
309       GDK_NOTE (MISC, g_print ("Wintab interface version %d.%d\n",
310                                HIBYTE (specversion), LOBYTE (specversion)));
311 #if USE_SYSCONTEXT
312       WTInfo (WTI_DEFSYSCTX, 0, &defcontext);
313 #if DEBUG_WINTAB
314       GDK_NOTE (MISC, (g_print("DEFSYSCTX:\n"), print_lc(&defcontext)));
315 #endif
316 #else
317       WTInfo (WTI_DEFCONTEXT, 0, &defcontext);
318 #if DEBUG_WINTAB
319       GDK_NOTE (MISC, (g_print("DEFCONTEXT:\n"), print_lc(&defcontext)));
320 #endif
321 #endif
322       WTInfo (WTI_INTERFACE, IFC_NDEVICES, &ndevices);
323       WTInfo (WTI_INTERFACE, IFC_NCURSORS, &ncursors);
324 #if DEBUG_WINTAB
325       GDK_NOTE (MISC, g_print ("NDEVICES: %d, NCURSORS: %d\n",
326                                ndevices, ncursors));
327 #endif
328       /* Create a dummy window to receive wintab events */
329       wa.wclass = GDK_INPUT_OUTPUT;
330       wa.event_mask = GDK_ALL_EVENTS_MASK;
331       wa.width = 2;
332       wa.height = 2;
333       wa.x = -100;
334       wa.y = -100;
335       wa.window_type = GDK_WINDOW_TOPLEVEL;
336       if ((wintab_window = gdk_window_new (NULL, &wa, GDK_WA_X|GDK_WA_Y)) == NULL)
337         {
338           g_warning ("gdk_input_init: gdk_window_new failed");
339           return;
340         }
341       gdk_window_ref (wintab_window);
342       window_private = (GdkWindowPrivate *) wintab_window;
343       
344       for (devix = 0; devix < ndevices; devix++)
345         {
346           LOGCONTEXT lc;
347
348           WTInfo (WTI_DEVICES + devix, DVC_NAME, devname);
349       
350           WTInfo (WTI_DEVICES + devix, DVC_NCSRTYPES, &ncsrtypes);
351           WTInfo (WTI_DEVICES + devix, DVC_FIRSTCSR, &firstcsr);
352           WTInfo (WTI_DEVICES + devix, DVC_HARDWARE, &hardware);
353           WTInfo (WTI_DEVICES + devix, DVC_X, &axis_x);
354           WTInfo (WTI_DEVICES + devix, DVC_Y, &axis_y);
355           WTInfo (WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure);
356           WTInfo (WTI_DEVICES + devix, DVC_ORIENTATION, axis_or);
357
358           if (HIBYTE (specversion) > 1 || LOBYTE (specversion) >= 1)
359             {
360               WTInfo (WTI_DDCTXS + devix, CTX_NAME, lc.lcName);
361               WTInfo (WTI_DDCTXS + devix, CTX_OPTIONS, &lc.lcOptions);
362               lc.lcOptions |= CXO_MESSAGES;
363 #if USE_SYSCONTEXT
364               lc.lcOptions |= CXO_SYSTEM;
365 #endif
366               lc.lcStatus = 0;
367               WTInfo (WTI_DDCTXS + devix, CTX_LOCKS, &lc.lcLocks);
368               lc.lcMsgBase = WT_DEFBASE;
369               lc.lcDevice = devix;
370               lc.lcPktRate = 50;
371               lc.lcPktData = PACKETDATA;
372               lc.lcPktMode = PK_BUTTONS; /* We want buttons in relative mode */
373               lc.lcMoveMask = PACKETDATA;
374               lc.lcBtnDnMask = lc.lcBtnUpMask = ~0;
375               WTInfo (WTI_DDCTXS + devix, CTX_INORGX, &lc.lcInOrgX);
376               WTInfo (WTI_DDCTXS + devix, CTX_INORGY, &lc.lcInOrgY);
377               WTInfo (WTI_DDCTXS + devix, CTX_INORGZ, &lc.lcInOrgZ);
378               WTInfo (WTI_DDCTXS + devix, CTX_INEXTX, &lc.lcInExtX);
379               WTInfo (WTI_DDCTXS + devix, CTX_INEXTY, &lc.lcInExtY);
380               WTInfo (WTI_DDCTXS + devix, CTX_INEXTZ, &lc.lcInExtZ);
381               lc.lcOutOrgX = axis_x.axMin;
382               lc.lcOutOrgY = axis_y.axMin;
383               lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
384               lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
385               lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
386               WTInfo (WTI_DDCTXS + devix, CTX_SENSX, &lc.lcSensX);
387               WTInfo (WTI_DDCTXS + devix, CTX_SENSY, &lc.lcSensY);
388               WTInfo (WTI_DDCTXS + devix, CTX_SENSZ, &lc.lcSensZ);
389               WTInfo (WTI_DDCTXS + devix, CTX_SYSMODE, &lc.lcSysMode);
390               lc.lcSysOrgX = lc.lcSysOrgY = 0;
391               WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTX, &lc.lcSysExtX);
392               WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTY, &lc.lcSysExtY);
393               WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSX, &lc.lcSysSensX);
394               WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSY, &lc.lcSysSensY);
395             }
396           else
397             {
398               lc = defcontext;
399               lc.lcOptions |= CXO_MESSAGES;
400               lc.lcMsgBase = WT_DEFBASE;
401               lc.lcPktRate = 50;
402               lc.lcPktData = PACKETDATA;
403               lc.lcPktMode = PACKETMODE;
404               lc.lcMoveMask = PACKETDATA;
405               lc.lcBtnUpMask = lc.lcBtnDnMask = ~0;
406 #if 0
407               lc.lcOutExtY = -lc.lcOutExtY; /* Y grows downward */
408 #else
409               lc.lcOutOrgX = axis_x.axMin;
410               lc.lcOutOrgY = axis_y.axMin;
411               lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
412               lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
413               lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
414 #endif
415             }
416 #if DEBUG_WINTAB
417           GDK_NOTE (MISC, (g_print("context for device %d:\n", devix),
418                            print_lc(&lc)));
419 #endif
420           hctx = g_new (HCTX, 1);
421           if ((*hctx = WTOpen (window_private->xwindow, &lc, TRUE)) == NULL)
422             {
423               g_warning ("gdk_input_init: WTOpen failed");
424               return;
425             }
426           GDK_NOTE (MISC, g_print ("opened Wintab device %d %#x\n",
427                                    devix, *hctx));
428
429           wintab_contexts = g_list_append (wintab_contexts, hctx);
430 #if 0
431           WTEnable (*hctx, TRUE);
432 #endif
433           WTOverlap (*hctx, TRUE);
434
435 #if DEBUG_WINTAB
436           GDK_NOTE (MISC, (g_print("context for device %d after WTOpen:\n", devix),
437                            print_lc(&lc)));
438 #endif
439           for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes; cursorix++)
440             {
441               active = FALSE;
442               WTInfo (WTI_CURSORS + cursorix, CSR_ACTIVE, &active);
443               if (!active)
444                 continue;
445               gdkdev = g_new (GdkDevicePrivate, 1);
446               WTInfo (WTI_CURSORS + cursorix, CSR_NAME, csrname);
447               gdkdev->info.name = g_strconcat (devname, " ", csrname, NULL);
448               gdkdev->info.deviceid = deviceid_counter++;
449               gdkdev->info.source = GDK_SOURCE_PEN;
450               gdkdev->info.mode = GDK_MODE_SCREEN;
451 #if USE_SYSCONTEXT
452               gdkdev->info.has_cursor = TRUE;
453 #else
454               gdkdev->info.has_cursor = FALSE;
455 #endif
456               gdkdev->hctx = *hctx;
457               gdkdev->cursor = cursorix;
458               WTInfo (WTI_CURSORS + cursorix, CSR_PKTDATA, &gdkdev->pktdata);
459               gdkdev->info.num_axes = 0;
460               if (gdkdev->pktdata & PK_X)
461                 gdkdev->info.num_axes++;
462               if (gdkdev->pktdata & PK_Y)
463                 gdkdev->info.num_axes++;
464               if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
465                 gdkdev->info.num_axes++;
466               /* The wintab driver for the Wacom ArtPad II reports
467                * PK_ORIENTATION in CSR_PKTDATA, but the tablet doesn't
468                * actually sense tilt. Catch this by noticing that the
469                * orientation axis's azimuth resolution is zero.
470                */
471               if ((gdkdev->pktdata & PK_ORIENTATION)
472                   && axis_or[0].axResolution == 0)
473                 gdkdev->pktdata &= ~PK_ORIENTATION;
474
475               if (gdkdev->pktdata & PK_ORIENTATION)
476                 gdkdev->info.num_axes += 2; /* x and y tilt */
477               WTInfo (WTI_CURSORS + cursorix, CSR_NPBTNMARKS, &gdkdev->npbtnmarks);
478               gdkdev->axes = g_new (GdkAxisInfo, gdkdev->info.num_axes);
479               gdkdev->info.axes = g_new (GdkAxisUse, gdkdev->info.num_axes);
480               gdkdev->last_axis_data = g_new (gint, gdkdev->info.num_axes);
481               
482               for (k = 0; k < GDK_AXIS_LAST; k++)
483                 gdkdev->axis_for_use[k] = -1;
484
485               k = 0;
486               if (gdkdev->pktdata & PK_X)
487                 {
488                   gdkdev->axes[k].xresolution =
489                     gdkdev->axes[k].resolution = axis_x.axResolution / 65535.;
490                   gdkdev->axes[k].xmin_value =
491                     gdkdev->axes[k].min_value = axis_x.axMin;
492                   gdkdev->axes[k].xmax_value =
493                     gdkdev->axes[k].max_value = axis_x.axMax;
494                   gdkdev->info.axes[k] = GDK_AXIS_X;
495                   gdkdev->axis_for_use[GDK_AXIS_X] = k;
496                   k++;
497                 }
498               if (gdkdev->pktdata & PK_Y)
499                 {
500                   gdkdev->axes[k].xresolution =
501                     gdkdev->axes[k].resolution = axis_y.axResolution / 65535.;
502                   gdkdev->axes[k].xmin_value =
503                     gdkdev->axes[k].min_value = axis_y.axMin;
504                   gdkdev->axes[k].xmax_value =
505                     gdkdev->axes[k].max_value = axis_y.axMax;
506                   gdkdev->info.axes[k] = GDK_AXIS_Y;
507                   gdkdev->axis_for_use[GDK_AXIS_Y] = k;
508                   k++;
509                 }
510               if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
511                 {
512                   gdkdev->axes[k].xresolution =
513                     gdkdev->axes[k].resolution = axis_npressure.axResolution / 65535.;
514                   gdkdev->axes[k].xmin_value =
515                     gdkdev->axes[k].min_value = axis_npressure.axMin;
516                   gdkdev->axes[k].xmax_value =
517                     gdkdev->axes[k].max_value = axis_npressure.axMax;
518                   gdkdev->info.axes[k] = GDK_AXIS_PRESSURE;
519                   gdkdev->axis_for_use[GDK_AXIS_PRESSURE] = k;
520                   k++;
521                 }
522               if (gdkdev->pktdata & PK_ORIENTATION)
523                 {
524                   GdkAxisUse axis;
525
526                   gdkdev->orientation_axes[0] = axis_or[0];
527                   gdkdev->orientation_axes[1] = axis_or[1];
528                   for (axis = GDK_AXIS_XTILT; axis <= GDK_AXIS_YTILT; axis++)
529                     {
530                       /* Wintab gives us aximuth and altitude, which
531                        * we convert to x and y tilt in the -1000..1000 range
532                        */
533                       gdkdev->axes[k].xresolution =
534                         gdkdev->axes[k].resolution = 1000;
535                       gdkdev->axes[k].xmin_value =
536                         gdkdev->axes[k].min_value = -1000;
537                       gdkdev->axes[k].xmax_value =
538                         gdkdev->axes[k].max_value = 1000;
539                       gdkdev->info.axes[k] = axis;
540                       gdkdev->axis_for_use[axis] = k;
541                       k++;
542                     }
543                 }
544               gdkdev->info.num_keys = 0;
545               gdkdev->info.keys = NULL;
546               GDK_NOTE (EVENTS,
547                         (g_print ("device: %d (%d) %s axes: %d\n",
548                                   gdkdev->info.deviceid, cursorix,
549                                   gdkdev->info.name,
550                                   gdkdev->info.num_axes),
551                          g_print ("axes: X:%d, Y:%d, PRESSURE:%d, "
552                                   "XTILT:%d, YTILT:%d\n",
553                                   gdkdev->axis_for_use[GDK_AXIS_X],
554                                   gdkdev->axis_for_use[GDK_AXIS_Y],
555                                   gdkdev->axis_for_use[GDK_AXIS_PRESSURE],
556                                   gdkdev->axis_for_use[GDK_AXIS_XTILT],
557                                   gdkdev->axis_for_use[GDK_AXIS_YTILT])));
558               for (i = 0; i < gdkdev->info.num_axes; i++)
559                 GDK_NOTE (EVENTS,
560                           g_print ("...axis %d: %d--%d@%d (%d--%d@%d)\n",
561                                    i,
562                                    gdkdev->axes[i].xmin_value, 
563                                    gdkdev->axes[i].xmax_value, 
564                                    gdkdev->axes[i].xresolution, 
565                                    gdkdev->axes[i].min_value, 
566                                    gdkdev->axes[i].max_value, 
567                                    gdkdev->axes[i].resolution));
568               gdk_input_devices = g_list_append (gdk_input_devices,
569                                                  gdkdev);
570             }
571         }
572     }
573 #endif /* HAVE_WINTAB */
574
575   if (deviceid_counter > 0)
576     {
577 #ifdef HAVE_WINTAB
578       gdk_input_vtable.set_mode           = gdk_input_win32_set_mode;
579       gdk_input_vtable.set_axes           = NULL;
580       gdk_input_vtable.set_key            = NULL;
581       gdk_input_vtable.motion_events      = NULL;
582       gdk_input_vtable.get_pointer        = gdk_input_win32_get_pointer;
583       gdk_input_vtable.grab_pointer       = gdk_input_win32_grab_pointer;
584       gdk_input_vtable.ungrab_pointer     = gdk_input_win32_ungrab_pointer;
585       gdk_input_vtable.configure_event    = gdk_input_win32_configure_event;
586       gdk_input_vtable.enter_event        = gdk_input_win32_enter_event;
587       gdk_input_vtable.other_event        = gdk_input_win32_other_event;
588       gdk_input_vtable.enable_window      = gdk_input_win32_enable_window;
589       gdk_input_vtable.disable_window     = gdk_input_win32_disable_window;
590
591       gdk_input_root_width = gdk_screen_width ();
592       gdk_input_root_height = gdk_screen_height ();
593       gdk_input_ignore_core = FALSE;
594 #else
595       g_assert_not_reached ();
596 #endif
597     }
598   else
599     {
600       gdk_input_vtable.set_mode           = NULL;
601       gdk_input_vtable.set_axes           = NULL;
602       gdk_input_vtable.set_key            = NULL;
603       gdk_input_vtable.motion_events      = NULL;
604       gdk_input_vtable.get_pointer        = gdk_input_none_get_pointer;
605       gdk_input_vtable.grab_pointer       = NULL;
606       gdk_input_vtable.ungrab_pointer     = NULL;
607       gdk_input_vtable.configure_event    = NULL;
608       gdk_input_vtable.enter_event        = NULL;
609       gdk_input_vtable.other_event        = NULL;
610       gdk_input_vtable.enable_window      = NULL;
611       gdk_input_vtable.disable_window     = NULL;
612       gdk_input_ignore_core = FALSE;
613     }
614   
615   gdk_input_devices = g_list_append (gdk_input_devices, &gdk_input_core_info);
616 }
617
618 gint
619 gdk_input_set_mode (guint32      deviceid,
620                     GdkInputMode mode)
621 {
622   if (deviceid == GDK_CORE_POINTER)
623     return FALSE;
624
625   if (gdk_input_vtable.set_mode)
626     return gdk_input_vtable.set_mode (deviceid, mode);
627   else
628     return FALSE;
629 }
630
631 void
632 gdk_input_set_axes (guint32     deviceid,
633                     GdkAxisUse *axes)
634 {
635   int i;
636   GdkDevicePrivate *gdkdev = gdk_input_find_device (deviceid);
637   g_return_if_fail (gdkdev != NULL);
638
639   if (deviceid == GDK_CORE_POINTER)
640     return;
641
642   for (i = GDK_AXIS_IGNORE; i < GDK_AXIS_LAST; i++)
643     {
644       gdkdev->axis_for_use[i] = -1;
645     }
646
647   for (i = 0; i < gdkdev->info.num_axes; i++)
648     {
649       gdkdev->info.axes[i] = axes[i];
650       gdkdev->axis_for_use[axes[i]] = i;
651     }
652 }
653
654 static void
655 gdk_input_none_get_pointer (GdkWindow       *window,
656                             guint32          deviceid,
657                             gdouble         *x,
658                             gdouble         *y,
659                             gdouble         *pressure,
660                             gdouble         *xtilt,
661                             gdouble         *ytilt,
662                             GdkModifierType *mask)
663 {
664   gint x_int, y_int;
665
666   gdk_window_get_pointer (window, &x_int, &y_int, mask);
667
668   if (x)
669     *x = x_int;
670   if (y)
671     *y = y_int;
672   if (pressure)
673     *pressure = 0.5;
674   if (xtilt)
675     *xtilt = 0;
676   if (ytilt)
677     *ytilt = 0;
678 }
679
680 #ifdef HAVE_WINTAB
681
682 static void
683 gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
684                                  GdkInputWindow   *input_window,
685                                  gint             *axis_data,
686                                  gdouble          *x,
687                                  gdouble          *y,
688                                  gdouble          *pressure,
689                                  gdouble          *xtilt,
690                                  gdouble          *ytilt)
691 {
692   GdkWindowPrivate *window_private;
693   gint x_axis, y_axis, pressure_axis, xtilt_axis, ytilt_axis;
694   gdouble device_width, device_height;
695   gdouble x_offset, y_offset, x_scale, y_scale;
696
697   window_private = (GdkWindowPrivate *) input_window->window;
698
699   x_axis = gdkdev->axis_for_use[GDK_AXIS_X];
700   y_axis = gdkdev->axis_for_use[GDK_AXIS_Y];
701   pressure_axis = gdkdev->axis_for_use[GDK_AXIS_PRESSURE];
702   xtilt_axis = gdkdev->axis_for_use[GDK_AXIS_XTILT];
703   ytilt_axis = gdkdev->axis_for_use[GDK_AXIS_YTILT];
704
705   device_width = gdkdev->axes[x_axis].max_value - 
706                    gdkdev->axes[x_axis].min_value;
707   device_height = gdkdev->axes[y_axis].max_value - 
708                     gdkdev->axes[y_axis].min_value;
709
710   if (gdkdev->info.mode == GDK_MODE_SCREEN) 
711     {
712       x_scale = gdk_input_root_width / device_width;
713       y_scale = gdk_input_root_height / device_height;
714
715       x_offset = -input_window->root_x;
716       y_offset = -input_window->root_y;
717     }
718   else                          /* GDK_MODE_WINDOW */
719     {
720       double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
721         (device_width*gdkdev->axes[x_axis].resolution);
722
723       if (device_aspect * window_private->width >= window_private->height)
724         {
725           /* device taller than window */
726           x_scale = window_private->width / device_width;
727           y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
728             / gdkdev->axes[y_axis].resolution;
729
730           x_offset = 0;
731           y_offset = -(device_height * y_scale - 
732                                window_private->height)/2;
733         }
734       else
735         {
736           /* window taller than device */
737           y_scale = window_private->height / device_height;
738           x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
739             / gdkdev->axes[x_axis].resolution;
740
741           y_offset = 0;
742           x_offset = -(device_width * x_scale - window_private->width)/2;
743         }
744     }
745   
746   if (x)
747     *x = x_offset + x_scale*axis_data[x_axis];
748   if (y)
749     *y = y_offset + y_scale*axis_data[y_axis];
750
751   if (pressure)
752     {
753       if (pressure_axis != -1)
754         *pressure = ((double)axis_data[pressure_axis] 
755                      - gdkdev->axes[pressure_axis].min_value) 
756           / (gdkdev->axes[pressure_axis].max_value 
757              - gdkdev->axes[pressure_axis].min_value);
758       else
759         *pressure = 0.5;
760     }
761
762   if (xtilt)
763     {
764       if (xtilt_axis != -1)
765         {
766           *xtilt = 2. * (double)(axis_data[xtilt_axis] - 
767                                  (gdkdev->axes[xtilt_axis].min_value +
768                                   gdkdev->axes[xtilt_axis].max_value)/2) /
769             (gdkdev->axes[xtilt_axis].max_value -
770              gdkdev->axes[xtilt_axis].min_value);
771         }
772       else
773         *xtilt = 0;
774     }
775   
776   if (ytilt)
777     {
778       if (ytilt_axis != -1)
779         {
780           *ytilt = 2. * (double)(axis_data[ytilt_axis] - 
781                                  (gdkdev->axes[ytilt_axis].min_value +
782                                   gdkdev->axes[ytilt_axis].max_value)/2) /
783             (gdkdev->axes[ytilt_axis].max_value -
784              gdkdev->axes[ytilt_axis].min_value);
785         }
786       else
787         *ytilt = 0;
788     }
789 }
790
791 static void 
792 gdk_input_win32_get_pointer (GdkWindow       *window,
793                              guint32          deviceid,
794                              gdouble         *x,
795                              gdouble         *y,
796                              gdouble         *pressure,
797                              gdouble         *xtilt,
798                              gdouble         *ytilt,
799                              GdkModifierType *mask)
800 {
801   GdkDevicePrivate *gdkdev;
802   GdkInputWindow *input_window;
803   gint x_int, y_int;
804   gint i;
805
806   if (deviceid == GDK_CORE_POINTER)
807     {
808       gdk_window_get_pointer (window, &x_int, &y_int, mask);
809       if (x)
810         *x = x_int;
811       if (y)
812         *y = y_int;
813       if (pressure)
814         *pressure = 0.5;
815       if (xtilt)
816         *xtilt = 0;
817       if (ytilt)
818         *ytilt = 0;
819     }
820   else
821     {
822       if (mask)
823         gdk_window_get_pointer (window, NULL, NULL, mask);
824       
825       gdkdev = gdk_input_find_device (deviceid);
826       g_return_if_fail (gdkdev != NULL);
827
828       input_window = gdk_input_window_find (window);
829       g_return_if_fail (input_window != NULL);
830
831       gdk_input_translate_coordinates (gdkdev, input_window,
832                                        gdkdev->last_axis_data,
833                                        x, y, pressure,
834                                        xtilt, ytilt);
835       if (mask)
836         {
837           *mask &= 0xFF;
838           *mask |= ((gdkdev->last_buttons & 0x1F) << 8);
839         }
840     }
841 }
842
843 static void
844 gdk_input_get_root_relative_geometry (HWND w,
845                                       int  *x_ret,
846                                       int  *y_ret)
847 {
848   RECT rect;
849
850   GetWindowRect (w, &rect);
851
852   if (x_ret)
853     *x_ret = rect.left;
854   if (y_ret)
855     *y_ret = rect.top;
856 }
857
858 static gint
859 gdk_input_win32_set_mode (guint32      deviceid,
860                           GdkInputMode mode)
861 {
862   GList *tmp_list;
863   GdkDevicePrivate *gdkdev;
864   GdkInputMode old_mode;
865   GdkInputWindow *input_window;
866
867   if (deviceid == GDK_CORE_POINTER)
868     return FALSE;
869
870   gdkdev = gdk_input_find_device (deviceid);
871   g_return_val_if_fail (gdkdev != NULL, FALSE);
872   old_mode = gdkdev->info.mode;
873
874   if (old_mode == mode)
875     return TRUE;
876
877   gdkdev->info.mode = mode;
878
879   if (mode == GDK_MODE_WINDOW)
880     {
881       gdkdev->info.has_cursor = FALSE;
882       for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
883         {
884           input_window = (GdkInputWindow *)tmp_list->data;
885           if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
886             gdk_input_win32_enable_window (input_window->window, gdkdev);
887           else
888             if (old_mode != GDK_MODE_DISABLED)
889               gdk_input_win32_disable_window (input_window->window, gdkdev);
890         }
891     }
892   else if (mode == GDK_MODE_SCREEN)
893     {
894       gdkdev->info.has_cursor = TRUE;
895       for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
896         gdk_input_win32_enable_window (((GdkInputWindow *)tmp_list->data)->window,
897                                        gdkdev);
898     }
899   else  /* mode == GDK_MODE_DISABLED */
900     {
901       for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
902         {
903           input_window = (GdkInputWindow *)tmp_list->data;
904           if (old_mode != GDK_MODE_WINDOW ||
905               input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
906             gdk_input_win32_disable_window (input_window->window, gdkdev);
907         }
908     }
909
910   return TRUE;
911 }
912
913 static void
914 gdk_input_win32_configure_event (GdkEventConfigure *event,
915                                  GdkWindow         *window)
916 {
917   GdkInputWindow *input_window;
918   gint root_x, root_y;
919
920   input_window = gdk_input_window_find (window);
921   g_return_if_fail (window != NULL);
922
923   gdk_input_get_root_relative_geometry
924     ((((GdkWindowPrivate*) window)->xwindow), &root_x, &root_y);
925
926   input_window->root_x = root_x;
927   input_window->root_y = root_y;
928 }
929
930 static void 
931 gdk_input_win32_enter_event (GdkEventCrossing *event, 
932                              GdkWindow        *window)
933 {
934   GdkInputWindow *input_window;
935   gint root_x, root_y;
936
937   input_window = gdk_input_window_find (window);
938   g_return_if_fail (window != NULL);
939
940   gdk_input_get_root_relative_geometry
941     ((((GdkWindowPrivate*) window)->xwindow), &root_x, &root_y);
942
943   input_window->root_x = root_x;
944   input_window->root_y = root_y;
945 }
946
947 static void
948 decode_tilt (gint   *axis_data,
949              AXIS   *axes,
950              PACKET *packet)
951 {
952   /* As I don't have a tilt-sensing tablet,
953    * I cannot test this code.
954    */
955   
956   double az, el;
957
958   az = TWOPI * packet->pkOrientation.orAzimuth /
959     (axes[0].axResolution / 65536.);
960   el = TWOPI * packet->pkOrientation.orAltitude /
961     (axes[1].axResolution / 65536.);
962   
963   /* X tilt */
964   axis_data[0] = cos (az) * cos (el) * 1000;
965   /* Y tilt */
966   axis_data[1] = sin (az) * cos (el) * 1000;
967 }
968
969 static GdkDevicePrivate *
970 gdk_input_find_dev_from_ctx (HCTX hctx,
971                              UINT cursor)
972 {
973   GList *tmp_list = gdk_input_devices;
974   GdkDevicePrivate *gdkdev;
975
976   while (tmp_list)
977     {
978       gdkdev = (GdkDevicePrivate *) (tmp_list->data);
979       if (gdkdev->hctx == hctx && gdkdev->cursor == cursor)
980         return gdkdev;
981       tmp_list = tmp_list->next;
982     }
983   return NULL;
984 }
985 static gint 
986 gdk_input_win32_other_event (GdkEvent  *event,
987                              MSG       *xevent)
988 {
989   GdkWindow *current_window;
990   GdkInputWindow *input_window;
991   GdkWindow *window;
992   GdkWindowPrivate *window_private;
993   GdkDevicePrivate *gdkdev;
994   GdkEventMask masktest;
995   POINT pt;
996   PACKET packet;
997   gint return_val;
998   gint k;
999   gint x, y;
1000
1001   if (event->any.window != wintab_window)
1002     g_warning ("gdk_input_win32_other_event: not wintab_window?");
1003
1004 #if USE_SYSCONTEXT
1005   window = gdk_window_at_pointer (&x, &y);
1006   if (window == NULL)
1007     window = (GdkWindow *) &gdk_root_parent;
1008
1009   gdk_window_ref (window);
1010
1011   window_private = (GdkWindowPrivate *) window;
1012
1013   GDK_NOTE (EVENTS, g_print ("gdk_input_win32_other_event: window=%#x (%d,%d)\n", window_private->xwindow, x, y));
1014   
1015 #else
1016   /* ??? This code is pretty bogus */
1017   current_window = gdk_window_lookup (GetActiveWindow ());
1018   if (current_window == NULL)
1019     return FALSE;
1020   
1021   input_window = gdk_input_window_find_within (current_window);
1022   if (input_window == NULL)
1023     return FALSE;
1024 #endif
1025
1026   if (xevent->message == WT_PACKET)
1027     {
1028       if (!WTPacket ((HCTX) xevent->lParam, xevent->wParam, &packet))
1029         return FALSE;
1030     }
1031
1032   switch (xevent->message)
1033     {
1034     case WT_PACKET:
1035       if (window_private == &gdk_root_parent)
1036         {
1037           GDK_NOTE (EVENTS, g_print ("...is root\n"));
1038           return FALSE;
1039         }
1040
1041       if ((gdkdev = gdk_input_find_dev_from_ctx ((HCTX) xevent->lParam,
1042                                                  packet.pkCursor)) == NULL)
1043         return FALSE;
1044
1045       if (gdkdev->info.mode == GDK_MODE_DISABLED)
1046         return FALSE;
1047       
1048       k = 0;
1049       if (gdkdev->pktdata & PK_X)
1050         gdkdev->last_axis_data[k++] = packet.pkX;
1051       if (gdkdev->pktdata & PK_Y)
1052         gdkdev->last_axis_data[k++] = packet.pkY;
1053       if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
1054         gdkdev->last_axis_data[k++] = packet.pkNormalPressure;
1055       if (gdkdev->pktdata & PK_ORIENTATION)
1056         {
1057           decode_tilt (gdkdev->last_axis_data + k,
1058                        gdkdev->orientation_axes, &packet);
1059           k += 2;
1060         }
1061
1062       g_assert (k == gdkdev->info.num_axes);
1063
1064       if (HIWORD (packet.pkButtons) != TBN_NONE)
1065         {
1066           /* Gdk buttons are numbered 1.. */
1067           event->button.button = 1 + LOWORD (packet.pkButtons);
1068
1069           if (HIWORD (packet.pkButtons) == TBN_UP)
1070             {
1071               event->any.type = GDK_BUTTON_RELEASE;
1072               masktest = GDK_BUTTON_RELEASE_MASK;
1073               gdkdev->button_state &= ~(1 << LOWORD (packet.pkButtons));
1074             }
1075           else
1076             {
1077               event->any.type = GDK_BUTTON_PRESS;
1078               masktest = GDK_BUTTON_PRESS_MASK;
1079               gdkdev->button_state |= 1 << LOWORD (packet.pkButtons);
1080             }
1081         }
1082       else
1083         {
1084           event->any.type = GDK_MOTION_NOTIFY;
1085           masktest = GDK_POINTER_MOTION_MASK;
1086           if (gdkdev->button_state & (1 << 0))
1087             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK;
1088           if (gdkdev->button_state & (1 << 1))
1089             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK;
1090           if (gdkdev->button_state & (1 << 2))
1091             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK;
1092         }
1093
1094       /* Now we can check if the window wants the event, and
1095        * propagate if necessary.
1096        */
1097     dijkstra:
1098       if (!window_private->extension_events_selected
1099           || !(window_private->extension_events & masktest))
1100         {
1101           GDK_NOTE (EVENTS, g_print ("...not selected\n"));
1102
1103           if (window_private->parent == (GdkWindow *) &gdk_root_parent)
1104             return FALSE;
1105           
1106           pt.x = x;
1107           pt.y = y;
1108           ClientToScreen (window_private->xwindow, &pt);
1109           gdk_window_unref (window);
1110           window = window_private->parent;
1111           gdk_window_ref (window);
1112           window_private = (GdkWindowPrivate *) window;
1113           ScreenToClient (window_private->xwindow, &pt);
1114           x = pt.x;
1115           y = pt.y;
1116           GDK_NOTE (EVENTS, g_print ("...propagating to %#x, (%d,%d)\n", window_private->xwindow, x, y));
1117           goto dijkstra;
1118         }
1119
1120       input_window = gdk_input_window_find (window);
1121
1122       g_assert (input_window != NULL);
1123
1124       if (gdkdev->info.mode == GDK_MODE_WINDOW
1125           && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
1126         return FALSE;
1127
1128       event->any.window = window;
1129
1130       if (event->any.type == GDK_BUTTON_PRESS
1131           || event->any.type == GDK_BUTTON_RELEASE)
1132         {
1133           event->button.time = xevent->time;
1134           event->button.source = gdkdev->info.source;
1135           last_moved_cursor_id = 
1136             event->button.deviceid = gdkdev->info.deviceid;
1137           
1138 #if 0
1139 #if USE_SYSCONTEXT
1140           /* Buttons 1 to 3 will come in as WM_[LMR]BUTTON{DOWN,UP} */
1141           if (event->button.button <= 3)
1142             return FALSE;
1143 #endif
1144 #endif
1145           gdk_input_translate_coordinates (gdkdev, input_window,
1146                                            gdkdev->last_axis_data,
1147                                            &event->button.x, &event->button.y,
1148                                            &event->button.pressure,
1149                                            &event->button.xtilt, 
1150                                            &event->button.ytilt);
1151
1152           event->button.state = ((gdkdev->button_state << 8)
1153                                  & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1154                                     | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1155                                     | GDK_BUTTON5_MASK));
1156           GDK_NOTE (EVENTS, g_print ("WINTAB button %s: %d %d %g,%g %g %g,%g\n",
1157                                      (event->button.type == GDK_BUTTON_PRESS ?
1158                                       "press" : "release"),
1159                                      event->button.deviceid,
1160                                      event->button.button,
1161                                      event->button.x, event->button.y,
1162                                      event->button.pressure,
1163                                      event->button.xtilt, event->button.ytilt));
1164         }
1165       else
1166         {
1167           event->motion.time = xevent->time;
1168           last_moved_cursor_id =
1169             event->motion.deviceid = gdkdev->info.deviceid;
1170           event->motion.is_hint = FALSE;
1171           event->motion.source = gdkdev->info.source;
1172
1173           gdk_input_translate_coordinates (gdkdev, input_window,
1174                                            gdkdev->last_axis_data,
1175                                            &event->motion.x, &event->motion.y,
1176                                            &event->motion.pressure,
1177                                            &event->motion.xtilt, 
1178                                            &event->motion.ytilt);
1179
1180           event->motion.state = ((gdkdev->button_state << 8)
1181                                  & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1182                                     | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1183                                     | GDK_BUTTON5_MASK));
1184
1185           GDK_NOTE (EVENTS, g_print ("WINTAB motion: %d %g,%g %g %g,%g\n",
1186                                      event->motion.deviceid,
1187                                      event->motion.x, event->motion.y,
1188                                      event->motion.pressure,
1189                                      event->motion.xtilt, event->motion.ytilt));
1190
1191           /* Check for missing release or press events for the normal
1192            * pressure button. At least on my ArtPadII I sometimes miss a
1193            * release event?
1194            */
1195           if ((gdkdev->pktdata & PK_NORMAL_PRESSURE
1196                && (event->motion.state & GDK_BUTTON1_MASK)
1197                && packet.pkNormalPressure <= MAX (0, gdkdev->npbtnmarks[0] - 2))
1198               || (gdkdev->pktdata & PK_NORMAL_PRESSURE
1199                   && !(event->motion.state & GDK_BUTTON1_MASK)
1200                   && packet.pkNormalPressure > gdkdev->npbtnmarks[1] + 2))
1201             {
1202               GdkEvent *event2 = gdk_event_copy (event);
1203               if (event->motion.state & GDK_BUTTON1_MASK)
1204                 {
1205                   event2->button.type = GDK_BUTTON_RELEASE;
1206                   gdkdev->button_state &= ~1;
1207                 }
1208               else
1209                 {
1210                   event2->button.type = GDK_BUTTON_PRESS;
1211                   gdkdev->button_state |= 1;
1212                 }
1213               event2->button.state = ((gdkdev->button_state << 8)
1214                                       & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1215                                          | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1216                                          | GDK_BUTTON5_MASK));
1217               event2->button.button = 1;
1218               GDK_NOTE (EVENTS, g_print ("WINTAB synthesized button %s: %d %d %g,%g %g\n",
1219                                          (event2->button.type == GDK_BUTTON_PRESS ?
1220                                           "press" : "release"),
1221                                          event2->button.deviceid,
1222                                          event2->button.button,
1223                                          event2->button.x, event2->button.y,
1224                                          event2->button.pressure));
1225               gdk_event_queue_append (event2);
1226             }
1227         }
1228       return TRUE;
1229
1230     case WT_PROXIMITY:
1231       if (LOWORD (xevent->lParam) == 0)
1232         {
1233           event->proximity.type = GDK_PROXIMITY_OUT;
1234           gdk_input_ignore_core = FALSE;
1235         }
1236       else
1237         {
1238           event->proximity.type = GDK_PROXIMITY_IN;
1239           gdk_input_ignore_core = TRUE;
1240         }
1241       event->proximity.time = xevent->time;
1242       event->proximity.source = GDK_SOURCE_PEN;
1243       event->proximity.deviceid = last_moved_cursor_id;
1244
1245       GDK_NOTE (EVENTS, g_print ("WINTAB proximity %s: %d\n",
1246                                  (event->proximity.type == GDK_PROXIMITY_IN ?
1247                                   "in" : "out"),
1248                                  event->proximity.deviceid));
1249       return TRUE;
1250     }
1251   return FALSE;
1252 }
1253
1254 static gint
1255 gdk_input_win32_enable_window (GdkWindow        *window,
1256                                GdkDevicePrivate *gdkdev)
1257 {
1258   GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
1259
1260   window_private->extension_events_selected = TRUE;
1261   return TRUE;
1262 }
1263
1264 static gint
1265 gdk_input_win32_disable_window (GdkWindow        *window,
1266                                 GdkDevicePrivate *gdkdev)
1267 {
1268   GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
1269
1270   window_private->extension_events_selected = FALSE;
1271   return TRUE;
1272 }
1273
1274 static gint
1275 gdk_input_win32_grab_pointer (GdkWindow    *window,
1276                               gint          owner_events,
1277                               GdkEventMask  event_mask,
1278                               GdkWindow    *confine_to,
1279                               guint32       time)
1280 {
1281   GdkInputWindow *input_window, *new_window;
1282   gboolean need_ungrab;
1283   GdkDevicePrivate *gdkdev;
1284   GList *tmp_list;
1285   gint result;
1286
1287   tmp_list = gdk_input_windows;
1288   new_window = NULL;
1289   need_ungrab = FALSE;
1290
1291   GDK_NOTE (MISC, g_print ("gdk_input_win32_grab_pointer: %#x %d %#x\n",
1292                            ((GdkWindowPrivate *) window)->xwindow,
1293                            owner_events,
1294                            (confine_to ?
1295                             ((GdkWindowPrivate *) confine_to)->xwindow :
1296                             0)));
1297
1298   while (tmp_list)
1299     {
1300       input_window = (GdkInputWindow *)tmp_list->data;
1301
1302       if (input_window->window == window)
1303         new_window = input_window;
1304       else if (input_window->grabbed)
1305         {
1306           input_window->grabbed = FALSE;
1307           need_ungrab = TRUE;
1308         }
1309
1310       tmp_list = tmp_list->next;
1311     }
1312
1313   if (new_window)
1314     {
1315       new_window->grabbed = TRUE;
1316       
1317       tmp_list = gdk_input_devices;
1318       while (tmp_list)
1319         {
1320           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1321           if (gdkdev->info.deviceid != GDK_CORE_POINTER)
1322             {
1323 #if 0         
1324               /* XXX */
1325               gdk_input_find_events (window, gdkdev,
1326                                      event_mask,
1327                                      event_classes, &num_classes);
1328               result = XGrabDevice (GDK_DISPLAY(), gdkdev->xdevice,
1329                                     GDK_WINDOW_XWINDOW (window),
1330                                     owner_events, num_classes, event_classes,
1331                                     GrabModeAsync, GrabModeAsync, time);
1332               
1333               /* FIXME: if failure occurs on something other than the first
1334                  device, things will be badly inconsistent */
1335               if (result != Success)
1336                 return result;
1337 #endif
1338             }
1339           tmp_list = tmp_list->next;
1340         }
1341     }
1342   else
1343     { 
1344       tmp_list = gdk_input_devices;
1345       while (tmp_list)
1346         {
1347           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1348           if (gdkdev->info.deviceid != GDK_CORE_POINTER && 
1349               ((gdkdev->button_state != 0) || need_ungrab))
1350             {
1351 #if 0
1352               /* XXX */
1353               XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1354 #endif
1355               gdkdev->button_state = 0;
1356             }
1357           
1358           tmp_list = tmp_list->next;
1359         }
1360     }
1361
1362   return Success;
1363       
1364 }
1365
1366 static void 
1367 gdk_input_win32_ungrab_pointer (guint32 time)
1368 {
1369   GdkInputWindow *input_window;
1370   GdkDevicePrivate *gdkdev;
1371   GList *tmp_list;
1372
1373   GDK_NOTE (MISC, g_print ("gdk_input_win32_ungrab_pointer\n"));
1374
1375   tmp_list = gdk_input_windows;
1376   while (tmp_list)
1377     {
1378       input_window = (GdkInputWindow *)tmp_list->data;
1379       if (input_window->grabbed)
1380         break;
1381       tmp_list = tmp_list->next;
1382     }
1383
1384   if (tmp_list)                 /* we found a grabbed window */
1385     {
1386       input_window->grabbed = FALSE;
1387
1388       tmp_list = gdk_input_devices;
1389       while (tmp_list)
1390         {
1391           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1392 #if 0
1393           /* XXX */
1394           if (gdkdev->info.deviceid != GDK_CORE_POINTER && gdkdev->xdevice)
1395             XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1396 #endif
1397           tmp_list = tmp_list->next;
1398         }
1399     }
1400 }
1401
1402 #endif /* HAVE_WINTAB */
1403
1404 GList *
1405 gdk_input_list_devices (void)
1406 {
1407   return gdk_input_devices;
1408 }
1409
1410 void
1411 gdk_input_set_source (guint32        deviceid,
1412                       GdkInputSource source)
1413 {
1414   GdkDevicePrivate *gdkdev = gdk_input_find_device (deviceid);
1415   g_return_if_fail (gdkdev != NULL);
1416
1417   gdkdev->info.source = source;
1418 }
1419
1420 void gdk_input_set_key (guint32 deviceid,
1421                         guint   index,
1422                         guint   keyval,
1423                         GdkModifierType modifiers)
1424 {
1425   if (deviceid != GDK_CORE_POINTER && gdk_input_vtable.set_key)
1426     gdk_input_vtable.set_key (deviceid, index, keyval, modifiers);
1427 }
1428
1429 GdkTimeCoord *
1430 gdk_input_motion_events (GdkWindow *window,
1431                          guint32    deviceid,
1432                          guint32    start,
1433                          guint32    stop,
1434                          gint      *nevents_return)
1435 {
1436   GdkWindowPrivate *window_private;
1437   GdkTimeCoord *coords;
1438   int i;
1439
1440   g_return_val_if_fail (window != NULL, NULL);
1441   window_private = (GdkWindowPrivate *) window;
1442   if (window_private->destroyed)
1443     return NULL;
1444
1445   *nevents_return = 0;
1446   return NULL;          /* ??? */
1447 }
1448
1449 static gint
1450 gdk_input_enable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
1451 {
1452   if (gdk_input_vtable.enable_window)
1453     return gdk_input_vtable.enable_window (window, gdkdev);
1454   else
1455     return TRUE;
1456 }
1457
1458 static gint
1459 gdk_input_disable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
1460 {
1461   if (gdk_input_vtable.disable_window)
1462     return gdk_input_vtable.disable_window(window,gdkdev);
1463   else
1464     return TRUE;
1465 }
1466
1467
1468 static GdkInputWindow *
1469 gdk_input_window_find (GdkWindow *window)
1470 {
1471   GList *tmp_list;
1472
1473   for (tmp_list=gdk_input_windows; tmp_list; tmp_list=tmp_list->next)
1474     if (((GdkInputWindow *)(tmp_list->data))->window == window)
1475       return (GdkInputWindow *)(tmp_list->data);
1476
1477   return NULL;      /* Not found */
1478 }
1479
1480 #if !USE_SYSCONTEXT
1481
1482 static GdkInputWindow *
1483 gdk_input_window_find_within (GdkWindow *window)
1484 {
1485   GList *tmp_list;
1486   GdkWindowPrivate *window_private;
1487   GdkWindowPrivate *tmp_private;
1488   GdkInputWindow *candidate = NULL;
1489
1490   window_private = (GdkWindowPrivate *) window;
1491
1492   for (tmp_list=gdk_input_windows; tmp_list; tmp_list=tmp_list->next)
1493     {
1494       (GdkWindowPrivate *) tmp_private =
1495         (GdkWindowPrivate *) (((GdkInputWindow *)(tmp_list->data))->window);
1496       if (tmp_private == window_private
1497           || IsChild (window_private->xwindow, tmp_private->xwindow))
1498         {
1499           if (candidate)
1500             return NULL;                /* Multiple hits */
1501           candidate = (GdkInputWindow *)(tmp_list->data);
1502         }
1503     }
1504
1505   return candidate;
1506 }
1507
1508 #endif
1509
1510 /* FIXME: this routine currently needs to be called between creation
1511    and the corresponding configure event (because it doesn't get the
1512    root_relative_geometry).  This should work with
1513    gtk_window_set_extension_events, but will likely fail in other
1514    cases */
1515
1516 void
1517 gdk_input_set_extension_events (GdkWindow       *window,
1518                                 gint             mask,
1519                                 GdkExtensionMode mode)
1520 {
1521   GdkWindowPrivate *window_private;
1522   GList *tmp_list;
1523   GdkInputWindow *iw;
1524
1525   g_return_if_fail (window != NULL);
1526   window_private = (GdkWindowPrivate *) window;
1527   if (window_private->destroyed)
1528     return;
1529
1530   if (mode == GDK_EXTENSION_EVENTS_NONE)
1531     mask = 0;
1532
1533   if (mask != 0)
1534     {
1535       iw = g_new (GdkInputWindow,1);
1536
1537       iw->window = window;
1538       iw->mode = mode;
1539
1540       iw->grabbed = FALSE;
1541
1542       gdk_input_windows = g_list_append (gdk_input_windows, iw);
1543       window_private->extension_events = mask;
1544
1545       /* Add enter window events to the event mask */
1546       gdk_window_set_events (window,
1547                              gdk_window_get_events (window) | 
1548                              GDK_ENTER_NOTIFY_MASK);
1549     }
1550   else
1551     {
1552       iw = gdk_input_window_find (window);
1553       if (iw)
1554         {
1555           gdk_input_windows = g_list_remove (gdk_input_windows, iw);
1556           g_free (iw);
1557         }
1558
1559       window_private->extension_events = 0;
1560     }
1561
1562   for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
1563     {
1564       GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
1565
1566       if (gdkdev->info.deviceid != GDK_CORE_POINTER)
1567         {
1568           if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
1569               && (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL))
1570             gdk_input_enable_window (window, gdkdev);
1571           else
1572             gdk_input_disable_window (window, gdkdev);
1573         }
1574     }
1575 }
1576
1577 void
1578 gdk_input_window_destroy (GdkWindow *window)
1579 {
1580   GdkInputWindow *input_window;
1581
1582   input_window = gdk_input_window_find (window);
1583   g_return_if_fail (input_window != NULL);
1584
1585   gdk_input_windows = g_list_remove (gdk_input_windows,input_window);
1586   g_free (input_window);
1587 }
1588
1589 void
1590 gdk_input_exit (void)
1591 {
1592 #ifdef HAVE_WINTAB
1593   GList *tmp_list;
1594   GdkDevicePrivate *gdkdev;
1595
1596   for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
1597     {
1598       gdkdev = (GdkDevicePrivate *)(tmp_list->data);
1599       if (gdkdev->info.deviceid != GDK_CORE_POINTER)
1600         {
1601           gdk_input_win32_set_mode (gdkdev->info.deviceid, GDK_MODE_DISABLED);
1602           g_free (gdkdev->info.name);
1603           g_free (gdkdev->last_axis_data);
1604           g_free (gdkdev->info.axes);
1605           g_free (gdkdev->info.keys);
1606           g_free (gdkdev->axes);
1607           g_free (gdkdev);
1608         }
1609     }
1610
1611   g_list_free (gdk_input_devices);
1612
1613   for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
1614     {
1615       g_free (tmp_list->data);
1616     }
1617   g_list_free (gdk_input_windows);
1618   gdk_input_windows = NULL;
1619
1620   gdk_window_unref (wintab_window);
1621   wintab_window = NULL;
1622
1623 #if 1
1624   for (tmp_list = wintab_contexts; tmp_list; tmp_list = tmp_list->next)
1625     {
1626       HCTX *hctx = (HCTX *) tmp_list->data;
1627       BOOL result;
1628
1629 #ifdef _MSC_VER
1630       /* For some reason WTEnable and/or WTClose tend to crash here.
1631        * Protect with __try/__except to avoid a message box.
1632        * When compiling with gcc, we cannot use __try/__except, so
1633        * don't call WTClose. I think this means that we'll
1634        * eventually run out of Wintab contexts, sigh.
1635        */
1636       __try {
1637 #if 0
1638         WTEnable (*hctx, FALSE);
1639 #endif
1640         result = WTClose (*hctx);
1641       }
1642       __except (/* GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? */
1643                 EXCEPTION_EXECUTE_HANDLER /*: 
1644                 EXCEPTION_CONTINUE_SEARCH */) {
1645         result = FALSE;
1646       }
1647       if (!result)
1648         g_warning ("gdk_input_exit: Closing Wintab context %#x failed", *hctx);
1649 #endif /* _MSC_VER */
1650       g_free (hctx);
1651     }
1652 #endif
1653   g_list_free (wintab_contexts);
1654   wintab_contexts = NULL;
1655 #endif
1656 }
1657
1658 static GdkDevicePrivate *
1659 gdk_input_find_device (guint32 id)
1660 {
1661   GList *tmp_list = gdk_input_devices;
1662   GdkDevicePrivate *gdkdev;
1663
1664   while (tmp_list)
1665     {
1666       gdkdev = (GdkDevicePrivate *) (tmp_list->data);
1667       if (gdkdev->info.deviceid == id)
1668         return gdkdev;
1669       tmp_list = tmp_list->next;
1670     }
1671   return NULL;
1672 }
1673
1674 void
1675 gdk_input_window_get_pointer (GdkWindow       *window,
1676                               guint32          deviceid,
1677                               gdouble         *x,
1678                               gdouble         *y,
1679                               gdouble         *pressure,
1680                               gdouble         *xtilt,
1681                               gdouble         *ytilt,
1682                               GdkModifierType *mask)
1683 {
1684   if (gdk_input_vtable.get_pointer)
1685     gdk_input_vtable.get_pointer (window, deviceid, x, y, pressure,
1686                                   xtilt, ytilt, mask);
1687 }