]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkinput-win32.c
Further hacking. Now actually compiles. Haven't tried yet whether
[~andy/gtk] / gdk / win32 / gdkinput-win32.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  * Copyright (C) 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 #include "gdkwin32.h"
38
39 #ifdef HAVE_WINTAB
40 #include <wintab.h>
41 #define PACKETDATA (PK_CONTEXT | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y  | PK_NORMAL_PRESSURE | PK_ORIENTATION)
42 #define PACKETMODE (PK_BUTTONS)
43 #include <pktdef.h>
44 #endif
45
46 #include "gdkinputprivate.h"
47
48 struct _GdkDevicePrivate {
49   GdkDeviceInfo  info;
50
51   /* information about the axes */
52   GdkAxisInfo *axes;
53
54   /* reverse lookup on axis use type */
55   gint axis_for_use[GDK_AXIS_LAST];
56   
57   /* true if we need to select a different set of events, but
58    * can't because this is the core pointer
59    */
60   gint needs_update;
61
62   /* State of buttons */
63   gint button_state;
64
65   gint *last_axis_data;
66   gint last_buttons;
67 #ifdef HAVE_WINTAB
68   /* WINTAB stuff: */
69   HCTX hctx;
70   /* Cursor number */
71   UINT cursor;
72   /* The cursor's CSR_PKTDATA */
73   WTPKT pktdata;
74   /* CSR_NPBTNMARKS */
75   UINT npbtnmarks[2];
76   /* Azimuth and altitude axis */
77   AXIS orientation_axes[2];
78 #endif
79 };
80
81 #ifndef G_PI
82 #define G_PI 3.14159265358979323846
83 #endif
84
85 /* If USE_SYSCONTEXT is on, we open the Wintab device (hmm, what if
86  * there are several?) as a system pointing device, i.e. it controls
87  * the normal Windows cursor. This seems much more natural.
88  */
89 #define USE_SYSCONTEXT 1        /* The code for the other choice is not
90                                  * good at all.
91                                  */
92
93 #ifdef HAVE_WINTAB
94 #define DEBUG_WINTAB 1
95 #endif
96
97 #define TWOPI (2.*G_PI)
98
99 #define PING() g_print("%s: %d\n",__FILE__,__LINE__)
100
101 /* Forward declarations */
102
103 static gint gdk_input_enable_window (GdkWindow *window,
104                                      GdkDevicePrivate *gdkdev);
105 static gint gdk_input_disable_window (GdkWindow *window,
106                                       GdkDevicePrivate *gdkdev);
107 static void gdk_input_none_get_pointer (GdkWindow       *window,
108                                         guint32          deviceid,
109                                         gdouble         *x,
110                                         gdouble         *y,
111                                         gdouble         *pressure,
112                                         gdouble         *xtilt,
113                                         gdouble         *ytilt,
114                                         GdkModifierType *mask);
115
116 static GdkDevicePrivate *gdk_input_find_device (guint32 deviceid);
117
118 #ifdef HAVE_WINTAB
119
120 static gint gdk_input_win32_set_mode (guint32      deviceid,
121                                       GdkInputMode mode);
122 static void gdk_input_win32_get_pointer (GdkWindow       *window,
123                                          guint32            deviceid,
124                                          gdouble         *x,
125                                          gdouble         *y,
126                                          gdouble         *pressure,
127                                          gdouble         *xtilt,
128                                          gdouble         *ytilt,
129                                          GdkModifierType *mask);
130 static gint gdk_input_win32_grab_pointer (GdkWindow *     window,
131                                           gint            owner_events,
132                                           GdkEventMask    event_mask,
133                                           GdkWindow      *confine_to,
134                                           guint32         time);
135 static void gdk_input_win32_ungrab_pointer (guint32 time);
136 static void gdk_input_win32_configure_event (GdkEventConfigure *event, 
137                                              GdkWindow         *window);
138 static void gdk_input_win32_enter_event (GdkEventCrossing  *xevent, 
139                                          GdkWindow         *window);
140 static gint gdk_input_win32_other_event (GdkEvent  *event, 
141                                          MSG       *xevent);
142 static gint gdk_input_win32_enable_window (GdkWindow        *window,
143                                            GdkDevicePrivate *gdkdev);
144 static gint gdk_input_win32_disable_window (GdkWindow        *window,
145                                             GdkDevicePrivate *gdkdev);
146
147 static GdkInputWindow *gdk_input_window_find (GdkWindow *window);
148 #if !USE_SYSCONTEXT
149 static GdkInputWindow *gdk_input_window_find_within (GdkWindow *window);
150 #endif
151 static GdkDevicePrivate *gdk_input_find_dev_from_ctx (HCTX hctx,
152                                                       UINT id);
153 #endif /* HAVE_WINTAB */
154
155 /* Local variables */
156
157 static GList     *gdk_input_devices;
158 static GList     *gdk_input_windows;
159 static GList     *wintab_contexts;
160
161 static gint gdk_input_root_width;
162 static gint gdk_input_root_height;
163
164 static GdkWindow *wintab_window;
165
166 static guint32 last_moved_cursor_id;
167
168 static GdkAxisUse gdk_input_core_axes[] = { GDK_AXIS_X, GDK_AXIS_Y };
169
170 static GdkDeviceInfo gdk_input_core_info =
171 {
172   GDK_CORE_POINTER,
173   "Core Pointer",
174   GDK_SOURCE_MOUSE,
175   GDK_MODE_SCREEN,
176   TRUE,
177   2,
178   gdk_input_core_axes
179 };
180
181 /* Global variables  */
182
183 GdkInputVTable    gdk_input_vtable;
184 gint              gdk_input_ignore_core;
185 gint              gdk_input_ignore_wintab = FALSE;
186
187 #if DEBUG_WINTAB
188
189 static void
190 print_lc(LOGCONTEXT *lc)
191 {
192   g_print ("lcName = %s\n", lc->lcName);
193   g_print ("lcOptions =");
194   if (lc->lcOptions & CXO_SYSTEM) g_print (" CXO_SYSTEM");
195   if (lc->lcOptions & CXO_PEN) g_print (" CXO_PEN");
196   if (lc->lcOptions & CXO_MESSAGES) g_print (" CXO_MESSAGES");
197   if (lc->lcOptions & CXO_MARGIN) g_print (" CXO_MARGIN");
198   if (lc->lcOptions & CXO_MGNINSIDE) g_print (" CXO_MGNINSIDE");
199   if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
200   if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
201   g_print ("\n");
202   g_print ("lcStatus =");
203   if (lc->lcStatus & CXS_DISABLED) g_print (" CXS_DISABLED");
204   if (lc->lcStatus & CXS_OBSCURED) g_print (" CXS_OBSCURED");
205   if (lc->lcStatus & CXS_ONTOP) g_print (" CXS_ONTOP");
206   g_print ("\n");
207   g_print ("lcLocks =");
208   if (lc->lcLocks & CXL_INSIZE) g_print (" CXL_INSIZE");
209   if (lc->lcLocks & CXL_INASPECT) g_print (" CXL_INASPECT");
210   if (lc->lcLocks & CXL_SENSITIVITY) g_print (" CXL_SENSITIVITY");
211   if (lc->lcLocks & CXL_MARGIN) g_print (" CXL_MARGIN");
212   g_print ("\n");
213   g_print ("lcMsgBase = %#x, lcDevice = %#x, lcPktRate = %d\n",
214           lc->lcMsgBase, lc->lcDevice, lc->lcPktRate);
215   g_print ("lcPktData =");
216   if (lc->lcPktData & PK_CONTEXT) g_print (" PK_CONTEXT");
217   if (lc->lcPktData & PK_STATUS) g_print (" PK_STATUS");
218   if (lc->lcPktData & PK_TIME) g_print (" PK_TIME");
219   if (lc->lcPktData & PK_CHANGED) g_print (" PK_CHANGED");
220   if (lc->lcPktData & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
221   if (lc->lcPktData & PK_CURSOR) g_print (" PK_CURSOR");
222   if (lc->lcPktData & PK_BUTTONS) g_print (" PK_BUTTONS");
223   if (lc->lcPktData & PK_X) g_print (" PK_X");
224   if (lc->lcPktData & PK_Y) g_print (" PK_Y");
225   if (lc->lcPktData & PK_Z) g_print (" PK_Z");
226   if (lc->lcPktData & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
227   if (lc->lcPktData & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
228   if (lc->lcPktData & PK_ORIENTATION) g_print (" PK_ORIENTATION");
229   if (lc->lcPktData & PK_ROTATION) g_print (" PK_ROTATION");
230   g_print ("\n");
231   g_print ("lcPktMode =");
232   if (lc->lcPktMode & PK_CONTEXT) g_print (" PK_CONTEXT");
233   if (lc->lcPktMode & PK_STATUS) g_print (" PK_STATUS");
234   if (lc->lcPktMode & PK_TIME) g_print (" PK_TIME");
235   if (lc->lcPktMode & PK_CHANGED) g_print (" PK_CHANGED");
236   if (lc->lcPktMode & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
237   if (lc->lcPktMode & PK_CURSOR) g_print (" PK_CURSOR");
238   if (lc->lcPktMode & PK_BUTTONS) g_print (" PK_BUTTONS");
239   if (lc->lcPktMode & PK_X) g_print (" PK_X");
240   if (lc->lcPktMode & PK_Y) g_print (" PK_Y");
241   if (lc->lcPktMode & PK_Z) g_print (" PK_Z");
242   if (lc->lcPktMode & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
243   if (lc->lcPktMode & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
244   if (lc->lcPktMode & PK_ORIENTATION) g_print (" PK_ORIENTATION");
245   if (lc->lcPktMode & PK_ROTATION) g_print (" PK_ROTATION");
246   g_print ("\n");
247   g_print ("lcMoveMask =");
248   if (lc->lcMoveMask & PK_CONTEXT) g_print (" PK_CONTEXT");
249   if (lc->lcMoveMask & PK_STATUS) g_print (" PK_STATUS");
250   if (lc->lcMoveMask & PK_TIME) g_print (" PK_TIME");
251   if (lc->lcMoveMask & PK_CHANGED) g_print (" PK_CHANGED");
252   if (lc->lcMoveMask & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
253   if (lc->lcMoveMask & PK_CURSOR) g_print (" PK_CURSOR");
254   if (lc->lcMoveMask & PK_BUTTONS) g_print (" PK_BUTTONS");
255   if (lc->lcMoveMask & PK_X) g_print (" PK_X");
256   if (lc->lcMoveMask & PK_Y) g_print (" PK_Y");
257   if (lc->lcMoveMask & PK_Z) g_print (" PK_Z");
258   if (lc->lcMoveMask & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
259   if (lc->lcMoveMask & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
260   if (lc->lcMoveMask & PK_ORIENTATION) g_print (" PK_ORIENTATION");
261   if (lc->lcMoveMask & PK_ROTATION) g_print (" PK_ROTATION");
262   g_print ("\n");
263   g_print ("lcBtnDnMask = %#x, lcBtnUpMask = %#x\n",
264           lc->lcBtnDnMask, lc->lcBtnUpMask);
265   g_print ("lcInOrgX = %d, lcInOrgY = %d, lcInOrgZ = %d\n",
266           lc->lcInOrgX, lc->lcInOrgY, lc->lcInOrgZ);
267   g_print ("lcInExtX = %d, lcInExtY = %d, lcInExtZ = %d\n",
268           lc->lcInExtX, lc->lcInExtY, lc->lcInExtZ);
269   g_print ("lcOutOrgX = %d, lcOutOrgY = %d, lcOutOrgZ = %d\n",
270           lc->lcOutOrgX, lc->lcOutOrgY, lc->lcOutOrgZ);
271   g_print ("lcOutExtX = %d, lcOutExtY = %d, lcOutExtZ = %d\n",
272           lc->lcOutExtX, lc->lcOutExtY, lc->lcOutExtZ);
273   g_print ("lcSensX = %g, lcSensY = %g, lcSensZ = %g\n",
274           lc->lcSensX / 65536., lc->lcSensY / 65536., lc->lcSensZ / 65536.);
275   g_print ("lcSysMode = %d\n", lc->lcSysMode);
276   g_print ("lcSysOrgX = %d, lcSysOrgY = %d\n",
277           lc->lcSysOrgX, lc->lcSysOrgY);
278   g_print ("lcSysExtX = %d, lcSysExtY = %d\n",
279           lc->lcSysExtX, lc->lcSysExtY);
280   g_print ("lcSysSensX = %g, lcSysSensY = %g\n",
281           lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.);
282 }
283
284 #endif
285
286 void 
287 gdk_input_init (void)
288 {
289   guint32 deviceid_counter = 0;
290 #ifdef HAVE_WINTAB
291   GdkDevicePrivate *gdkdev;
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       
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 (GDK_DRAWABLE_XID (wintab_window), &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   GdkDrawablePrivate *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 = (GdkDrawablePrivate *) 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     (GDK_DRAWABLE_XID (window), &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     (GDK_DRAWABLE_XID (window), &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   GdkDevicePrivate *gdkdev;
993   GdkEventMask masktest;
994   POINT pt;
995   PACKET packet;
996   gint return_val;
997   gint k;
998   gint x, y;
999
1000   if (event->any.window != wintab_window)
1001     {
1002       g_warning ("gdk_input_win32_other_event: not wintab_window?");
1003       return FALSE;
1004     }
1005
1006 #if USE_SYSCONTEXT
1007   window = gdk_window_at_pointer (&x, &y);
1008   if (window == NULL)
1009     window = gdk_parent_root;
1010
1011   gdk_window_ref (window);
1012
1013   GDK_NOTE (EVENTS,
1014             g_print ("gdk_input_win32_other_event: window=%#x (%d,%d)\n",
1015                      GDK_DRAWABLE_XID (window), x, y));
1016   
1017 #else
1018   /* ??? This code is pretty bogus */
1019   current_window = gdk_window_lookup (GetActiveWindow ());
1020   if (current_window == NULL)
1021     return FALSE;
1022   
1023   input_window = gdk_input_window_find_within (current_window);
1024   if (input_window == NULL)
1025     return FALSE;
1026 #endif
1027
1028   if (xevent->message == WT_PACKET)
1029     {
1030       if (!WTPacket ((HCTX) xevent->lParam, xevent->wParam, &packet))
1031         return FALSE;
1032     }
1033
1034   switch (xevent->message)
1035     {
1036     case WT_PACKET:
1037       if (window == gdk_parent_root)
1038         {
1039           GDK_NOTE (EVENTS, g_print ("...is root\n"));
1040           return FALSE;
1041         }
1042
1043       if ((gdkdev = gdk_input_find_dev_from_ctx ((HCTX) xevent->lParam,
1044                                                  packet.pkCursor)) == NULL)
1045         return FALSE;
1046
1047       if (gdkdev->info.mode == GDK_MODE_DISABLED)
1048         return FALSE;
1049       
1050       k = 0;
1051       if (gdkdev->pktdata & PK_X)
1052         gdkdev->last_axis_data[k++] = packet.pkX;
1053       if (gdkdev->pktdata & PK_Y)
1054         gdkdev->last_axis_data[k++] = packet.pkY;
1055       if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
1056         gdkdev->last_axis_data[k++] = packet.pkNormalPressure;
1057       if (gdkdev->pktdata & PK_ORIENTATION)
1058         {
1059           decode_tilt (gdkdev->last_axis_data + k,
1060                        gdkdev->orientation_axes, &packet);
1061           k += 2;
1062         }
1063
1064       g_assert (k == gdkdev->info.num_axes);
1065
1066       if (HIWORD (packet.pkButtons) != TBN_NONE)
1067         {
1068           /* Gdk buttons are numbered 1.. */
1069           event->button.button = 1 + LOWORD (packet.pkButtons);
1070
1071           if (HIWORD (packet.pkButtons) == TBN_UP)
1072             {
1073               event->any.type = GDK_BUTTON_RELEASE;
1074               masktest = GDK_BUTTON_RELEASE_MASK;
1075               gdkdev->button_state &= ~(1 << LOWORD (packet.pkButtons));
1076             }
1077           else
1078             {
1079               event->any.type = GDK_BUTTON_PRESS;
1080               masktest = GDK_BUTTON_PRESS_MASK;
1081               gdkdev->button_state |= 1 << LOWORD (packet.pkButtons);
1082             }
1083         }
1084       else
1085         {
1086           event->any.type = GDK_MOTION_NOTIFY;
1087           masktest = GDK_POINTER_MOTION_MASK;
1088           if (gdkdev->button_state & (1 << 0))
1089             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK;
1090           if (gdkdev->button_state & (1 << 1))
1091             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK;
1092           if (gdkdev->button_state & (1 << 2))
1093             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK;
1094         }
1095
1096       /* Now we can check if the window wants the event, and
1097        * propagate if necessary.
1098        */
1099     dijkstra:
1100       if (!GDK_WINDOW_WIN32DATA (window)->extension_events_selected
1101           || !(GDK_WINDOW_WIN32DATA (window)->extension_events & masktest))
1102         {
1103           GDK_NOTE (EVENTS, g_print ("...not selected\n"));
1104
1105           if (((GdkWindowPrivate *) window)->parent == gdk_parent_root)
1106             return FALSE;
1107           
1108           pt.x = x;
1109           pt.y = y;
1110           ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
1111           gdk_window_unref (window);
1112           window = ((GdkWindowPrivate *) window)->parent;
1113           gdk_window_ref (window);
1114           ScreenToClient (GDK_DRAWABLE_XID (window), &pt);
1115           x = pt.x;
1116           y = pt.y;
1117           GDK_NOTE (EVENTS, g_print ("...propagating to %#x, (%d,%d)\n",
1118                                      GDK_DRAWABLE_XID (window), x, y));
1119           goto dijkstra;
1120         }
1121
1122       input_window = gdk_input_window_find (window);
1123
1124       g_assert (input_window != NULL);
1125
1126       if (gdkdev->info.mode == GDK_MODE_WINDOW
1127           && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
1128         return FALSE;
1129
1130       event->any.window = window;
1131
1132       if (event->any.type == GDK_BUTTON_PRESS
1133           || event->any.type == GDK_BUTTON_RELEASE)
1134         {
1135           event->button.time = xevent->time;
1136           event->button.source = gdkdev->info.source;
1137           last_moved_cursor_id = 
1138             event->button.deviceid = gdkdev->info.deviceid;
1139           
1140 #if 0
1141 #if USE_SYSCONTEXT
1142           /* Buttons 1 to 3 will come in as WM_[LMR]BUTTON{DOWN,UP} */
1143           if (event->button.button <= 3)
1144             return FALSE;
1145 #endif
1146 #endif
1147           gdk_input_translate_coordinates (gdkdev, input_window,
1148                                            gdkdev->last_axis_data,
1149                                            &event->button.x, &event->button.y,
1150                                            &event->button.pressure,
1151                                            &event->button.xtilt, 
1152                                            &event->button.ytilt);
1153
1154           event->button.state = ((gdkdev->button_state << 8)
1155                                  & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1156                                     | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1157                                     | GDK_BUTTON5_MASK));
1158           GDK_NOTE (EVENTS, g_print ("WINTAB button %s: %d %d %g,%g %g %g,%g\n",
1159                                      (event->button.type == GDK_BUTTON_PRESS ?
1160                                       "press" : "release"),
1161                                      event->button.deviceid,
1162                                      event->button.button,
1163                                      event->button.x, event->button.y,
1164                                      event->button.pressure,
1165                                      event->button.xtilt, event->button.ytilt));
1166         }
1167       else
1168         {
1169           event->motion.time = xevent->time;
1170           last_moved_cursor_id =
1171             event->motion.deviceid = gdkdev->info.deviceid;
1172           event->motion.is_hint = FALSE;
1173           event->motion.source = gdkdev->info.source;
1174
1175           gdk_input_translate_coordinates (gdkdev, input_window,
1176                                            gdkdev->last_axis_data,
1177                                            &event->motion.x, &event->motion.y,
1178                                            &event->motion.pressure,
1179                                            &event->motion.xtilt, 
1180                                            &event->motion.ytilt);
1181
1182           event->motion.state = ((gdkdev->button_state << 8)
1183                                  & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1184                                     | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1185                                     | GDK_BUTTON5_MASK));
1186
1187           GDK_NOTE (EVENTS, g_print ("WINTAB motion: %d %g,%g %g %g,%g\n",
1188                                      event->motion.deviceid,
1189                                      event->motion.x, event->motion.y,
1190                                      event->motion.pressure,
1191                                      event->motion.xtilt, event->motion.ytilt));
1192
1193           /* Check for missing release or press events for the normal
1194            * pressure button. At least on my ArtPadII I sometimes miss a
1195            * release event?
1196            */
1197           if ((gdkdev->pktdata & PK_NORMAL_PRESSURE
1198                && (event->motion.state & GDK_BUTTON1_MASK)
1199                && packet.pkNormalPressure <= MAX (0, gdkdev->npbtnmarks[0] - 2))
1200               || (gdkdev->pktdata & PK_NORMAL_PRESSURE
1201                   && !(event->motion.state & GDK_BUTTON1_MASK)
1202                   && packet.pkNormalPressure > gdkdev->npbtnmarks[1] + 2))
1203             {
1204               GdkEvent *event2 = gdk_event_copy (event);
1205               if (event->motion.state & GDK_BUTTON1_MASK)
1206                 {
1207                   event2->button.type = GDK_BUTTON_RELEASE;
1208                   gdkdev->button_state &= ~1;
1209                 }
1210               else
1211                 {
1212                   event2->button.type = GDK_BUTTON_PRESS;
1213                   gdkdev->button_state |= 1;
1214                 }
1215               event2->button.state = ((gdkdev->button_state << 8)
1216                                       & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1217                                          | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1218                                          | GDK_BUTTON5_MASK));
1219               event2->button.button = 1;
1220               GDK_NOTE (EVENTS, g_print ("WINTAB synthesized button %s: %d %d %g,%g %g\n",
1221                                          (event2->button.type == GDK_BUTTON_PRESS ?
1222                                           "press" : "release"),
1223                                          event2->button.deviceid,
1224                                          event2->button.button,
1225                                          event2->button.x, event2->button.y,
1226                                          event2->button.pressure));
1227               gdk_event_queue_append (event2);
1228             }
1229         }
1230       return TRUE;
1231
1232     case WT_PROXIMITY:
1233       if (LOWORD (xevent->lParam) == 0)
1234         {
1235           event->proximity.type = GDK_PROXIMITY_OUT;
1236           gdk_input_ignore_core = FALSE;
1237         }
1238       else
1239         {
1240           event->proximity.type = GDK_PROXIMITY_IN;
1241           gdk_input_ignore_core = TRUE;
1242         }
1243       event->proximity.time = xevent->time;
1244       event->proximity.source = GDK_SOURCE_PEN;
1245       event->proximity.deviceid = last_moved_cursor_id;
1246
1247       GDK_NOTE (EVENTS, g_print ("WINTAB proximity %s: %d\n",
1248                                  (event->proximity.type == GDK_PROXIMITY_IN ?
1249                                   "in" : "out"),
1250                                  event->proximity.deviceid));
1251       return TRUE;
1252     }
1253   return FALSE;
1254 }
1255
1256 static gint
1257 gdk_input_win32_enable_window (GdkWindow        *window,
1258                                GdkDevicePrivate *gdkdev)
1259 {
1260   GDK_WINDOW_WIN32DATA (window)->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   GDK_WINDOW_WIN32DATA (window)->extension_events_selected = FALSE;
1269   return TRUE;
1270 }
1271
1272 static gint
1273 gdk_input_win32_grab_pointer (GdkWindow    *window,
1274                               gint          owner_events,
1275                               GdkEventMask  event_mask,
1276                               GdkWindow    *confine_to,
1277                               guint32       time)
1278 {
1279   GdkInputWindow *input_window, *new_window;
1280   gboolean need_ungrab;
1281   GdkDevicePrivate *gdkdev;
1282   GList *tmp_list;
1283   gint result;
1284
1285   tmp_list = gdk_input_windows;
1286   new_window = NULL;
1287   need_ungrab = FALSE;
1288
1289   GDK_NOTE (MISC, g_print ("gdk_input_win32_grab_pointer: %#x %d %#x\n",
1290                            GDK_DRAWABLE_XID (window),
1291                            owner_events,
1292                            (confine_to ? GDK_DRAWABLE_XID (confine_to) : 0)));
1293
1294   while (tmp_list)
1295     {
1296       input_window = (GdkInputWindow *)tmp_list->data;
1297
1298       if (input_window->window == window)
1299         new_window = input_window;
1300       else if (input_window->grabbed)
1301         {
1302           input_window->grabbed = FALSE;
1303           need_ungrab = TRUE;
1304         }
1305
1306       tmp_list = tmp_list->next;
1307     }
1308
1309   if (new_window)
1310     {
1311       new_window->grabbed = TRUE;
1312       
1313       tmp_list = gdk_input_devices;
1314       while (tmp_list)
1315         {
1316           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1317           if (gdkdev->info.deviceid != GDK_CORE_POINTER)
1318             {
1319 #if 0         
1320               /* XXX */
1321               gdk_input_find_events (window, gdkdev,
1322                                      event_mask,
1323                                      event_classes, &num_classes);
1324               result = XGrabDevice (GDK_DISPLAY(), gdkdev->xdevice,
1325                                     GDK_WINDOW_XWINDOW (window),
1326                                     owner_events, num_classes, event_classes,
1327                                     GrabModeAsync, GrabModeAsync, time);
1328               
1329               /* FIXME: if failure occurs on something other than the first
1330                  device, things will be badly inconsistent */
1331               if (result != Success)
1332                 return result;
1333 #endif
1334             }
1335           tmp_list = tmp_list->next;
1336         }
1337     }
1338   else
1339     { 
1340       tmp_list = gdk_input_devices;
1341       while (tmp_list)
1342         {
1343           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1344           if (gdkdev->info.deviceid != GDK_CORE_POINTER && 
1345               ((gdkdev->button_state != 0) || need_ungrab))
1346             {
1347 #if 0
1348               /* XXX */
1349               XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1350 #endif
1351               gdkdev->button_state = 0;
1352             }
1353           
1354           tmp_list = tmp_list->next;
1355         }
1356     }
1357
1358   return Success;
1359       
1360 }
1361
1362 static void 
1363 gdk_input_win32_ungrab_pointer (guint32 time)
1364 {
1365   GdkInputWindow *input_window;
1366   GdkDevicePrivate *gdkdev;
1367   GList *tmp_list;
1368
1369   GDK_NOTE (MISC, g_print ("gdk_input_win32_ungrab_pointer\n"));
1370
1371   tmp_list = gdk_input_windows;
1372   while (tmp_list)
1373     {
1374       input_window = (GdkInputWindow *)tmp_list->data;
1375       if (input_window->grabbed)
1376         break;
1377       tmp_list = tmp_list->next;
1378     }
1379
1380   if (tmp_list)                 /* we found a grabbed window */
1381     {
1382       input_window->grabbed = FALSE;
1383
1384       tmp_list = gdk_input_devices;
1385       while (tmp_list)
1386         {
1387           gdkdev = (GdkDevicePrivate *)tmp_list->data;
1388 #if 0
1389           /* XXX */
1390           if (gdkdev->info.deviceid != GDK_CORE_POINTER && gdkdev->xdevice)
1391             XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1392 #endif
1393           tmp_list = tmp_list->next;
1394         }
1395     }
1396 }
1397
1398 #endif /* HAVE_WINTAB */
1399
1400 GList *
1401 gdk_input_list_devices (void)
1402 {
1403   return gdk_input_devices;
1404 }
1405
1406 void
1407 gdk_input_set_source (guint32        deviceid,
1408                       GdkInputSource source)
1409 {
1410   GdkDevicePrivate *gdkdev = gdk_input_find_device (deviceid);
1411   g_return_if_fail (gdkdev != NULL);
1412
1413   gdkdev->info.source = source;
1414 }
1415
1416 void gdk_input_set_key (guint32 deviceid,
1417                         guint   index,
1418                         guint   keyval,
1419                         GdkModifierType modifiers)
1420 {
1421   if (deviceid != GDK_CORE_POINTER && gdk_input_vtable.set_key)
1422     gdk_input_vtable.set_key (deviceid, index, keyval, modifiers);
1423 }
1424
1425 GdkTimeCoord *
1426 gdk_input_motion_events (GdkWindow *window,
1427                          guint32    deviceid,
1428                          guint32    start,
1429                          guint32    stop,
1430                          gint      *nevents_return)
1431 {
1432   g_return_val_if_fail (window != NULL, NULL);
1433   if (GDK_DRAWABLE_DESTROYED (window))
1434     return NULL;
1435
1436   *nevents_return = 0;
1437   return NULL;          /* ??? */
1438 }
1439
1440 static gint
1441 gdk_input_enable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
1442 {
1443   if (gdk_input_vtable.enable_window)
1444     return gdk_input_vtable.enable_window (window, gdkdev);
1445   else
1446     return TRUE;
1447 }
1448
1449 static gint
1450 gdk_input_disable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
1451 {
1452   if (gdk_input_vtable.disable_window)
1453     return gdk_input_vtable.disable_window(window,gdkdev);
1454   else
1455     return TRUE;
1456 }
1457
1458
1459 static GdkInputWindow *
1460 gdk_input_window_find (GdkWindow *window)
1461 {
1462   GList *tmp_list;
1463
1464   for (tmp_list=gdk_input_windows; tmp_list; tmp_list=tmp_list->next)
1465     if (((GdkInputWindow *)(tmp_list->data))->window == window)
1466       return (GdkInputWindow *)(tmp_list->data);
1467
1468   return NULL;      /* Not found */
1469 }
1470
1471 #if !USE_SYSCONTEXT
1472
1473 static GdkInputWindow *
1474 gdk_input_window_find_within (GdkWindow *window)
1475 {
1476   GList *list;
1477   GdkWindow *tmpw;
1478   GdkInputWindow *candidate = NULL;
1479
1480   for (list = gdk_input_windows; list != NULL; list = list->next)
1481     {
1482       tmpw = ((GdkInputWindow *) (tmp_list->data))->window;
1483       if (tmpw == window
1484           || IsChild (GDK_DRAWABLE_XID (window), GDK_DRAWABLE_XID (tmpw)))
1485         {
1486           if (candidate)
1487             return NULL;                /* Multiple hits */
1488           candidate = (GdkInputWindow *) (list->data);
1489         }
1490     }
1491
1492   return candidate;
1493 }
1494
1495 #endif
1496
1497 /* FIXME: this routine currently needs to be called between creation
1498    and the corresponding configure event (because it doesn't get the
1499    root_relative_geometry).  This should work with
1500    gtk_window_set_extension_events, but will likely fail in other
1501    cases */
1502
1503 void
1504 gdk_input_set_extension_events (GdkWindow       *window,
1505                                 gint             mask,
1506                                 GdkExtensionMode mode)
1507 {
1508   GdkWindowPrivate *window_private;
1509   GList *tmp_list;
1510   GdkInputWindow *iw;
1511
1512   g_return_if_fail (window != NULL);
1513   if (GDK_DRAWABLE_DESTROYED (window))
1514     return;
1515   window_private = (GdkWindowPrivate *) window;
1516
1517   if (mode == GDK_EXTENSION_EVENTS_NONE)
1518     mask = 0;
1519
1520   if (mask != 0)
1521     {
1522       iw = g_new (GdkInputWindow,1);
1523
1524       iw->window = window;
1525       iw->mode = mode;
1526
1527       iw->grabbed = FALSE;
1528
1529       gdk_input_windows = g_list_append (gdk_input_windows, iw);
1530       window_private->extension_events = mask;
1531
1532       /* Add enter window events to the event mask */
1533       gdk_window_set_events (window,
1534                              gdk_window_get_events (window) | 
1535                              GDK_ENTER_NOTIFY_MASK);
1536     }
1537   else
1538     {
1539       iw = gdk_input_window_find (window);
1540       if (iw)
1541         {
1542           gdk_input_windows = g_list_remove (gdk_input_windows, iw);
1543           g_free (iw);
1544         }
1545
1546       window_private->extension_events = 0;
1547     }
1548
1549   for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
1550     {
1551       GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
1552
1553       if (gdkdev->info.deviceid != GDK_CORE_POINTER)
1554         {
1555           if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
1556               && (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL))
1557             gdk_input_enable_window (window, gdkdev);
1558           else
1559             gdk_input_disable_window (window, gdkdev);
1560         }
1561     }
1562 }
1563
1564 void
1565 gdk_input_window_destroy (GdkWindow *window)
1566 {
1567   GdkInputWindow *input_window;
1568
1569   input_window = gdk_input_window_find (window);
1570   g_return_if_fail (input_window != NULL);
1571
1572   gdk_input_windows = g_list_remove (gdk_input_windows,input_window);
1573   g_free (input_window);
1574 }
1575
1576 void
1577 gdk_input_exit (void)
1578 {
1579 #ifdef HAVE_WINTAB
1580   GList *tmp_list;
1581   GdkDevicePrivate *gdkdev;
1582
1583   for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
1584     {
1585       gdkdev = (GdkDevicePrivate *)(tmp_list->data);
1586       if (gdkdev->info.deviceid != GDK_CORE_POINTER)
1587         {
1588           gdk_input_win32_set_mode (gdkdev->info.deviceid, GDK_MODE_DISABLED);
1589           g_free (gdkdev->info.name);
1590           g_free (gdkdev->last_axis_data);
1591           g_free (gdkdev->info.axes);
1592           g_free (gdkdev->info.keys);
1593           g_free (gdkdev->axes);
1594           g_free (gdkdev);
1595         }
1596     }
1597
1598   g_list_free (gdk_input_devices);
1599
1600   for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
1601     {
1602       g_free (tmp_list->data);
1603     }
1604   g_list_free (gdk_input_windows);
1605   gdk_input_windows = NULL;
1606
1607   gdk_window_unref (wintab_window);
1608   wintab_window = NULL;
1609
1610 #if 1
1611   for (tmp_list = wintab_contexts; tmp_list; tmp_list = tmp_list->next)
1612     {
1613       HCTX *hctx = (HCTX *) tmp_list->data;
1614       BOOL result;
1615
1616 #ifdef _MSC_VER
1617       /* For some reason WTEnable and/or WTClose tend to crash here.
1618        * Protect with __try/__except to avoid a message box.
1619        * When compiling with gcc, we cannot use __try/__except, so
1620        * don't call WTClose. I think this means that we'll
1621        * eventually run out of Wintab contexts, sigh.
1622        */
1623       __try {
1624 #if 0
1625         WTEnable (*hctx, FALSE);
1626 #endif
1627         result = WTClose (*hctx);
1628       }
1629       __except (/* GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? */
1630                 EXCEPTION_EXECUTE_HANDLER /*: 
1631                 EXCEPTION_CONTINUE_SEARCH */) {
1632         result = FALSE;
1633       }
1634       if (!result)
1635         g_warning ("gdk_input_exit: Closing Wintab context %#x failed", *hctx);
1636 #endif /* _MSC_VER */
1637       g_free (hctx);
1638     }
1639 #endif
1640   g_list_free (wintab_contexts);
1641   wintab_contexts = NULL;
1642 #endif
1643 }
1644
1645 static GdkDevicePrivate *
1646 gdk_input_find_device (guint32 id)
1647 {
1648   GList *tmp_list = gdk_input_devices;
1649   GdkDevicePrivate *gdkdev;
1650
1651   while (tmp_list)
1652     {
1653       gdkdev = (GdkDevicePrivate *) (tmp_list->data);
1654       if (gdkdev->info.deviceid == id)
1655         return gdkdev;
1656       tmp_list = tmp_list->next;
1657     }
1658   return NULL;
1659 }
1660
1661 void
1662 gdk_input_window_get_pointer (GdkWindow       *window,
1663                               guint32          deviceid,
1664                               gdouble         *x,
1665                               gdouble         *y,
1666                               gdouble         *pressure,
1667                               gdouble         *xtilt,
1668                               gdouble         *ytilt,
1669                               GdkModifierType *mask)
1670 {
1671   if (gdk_input_vtable.get_pointer)
1672     gdk_input_vtable.get_pointer (window, deviceid, x, y, pressure,
1673                                   xtilt, ytilt, mask);
1674 }