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