1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 * Copyright (C) 1999 Tor Lillqvist
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.
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.
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.
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/.
39 #define M_PI 3.14159265358979323846
42 /* If USE_SYSCONTEXT is on, we open the Wintab device (hmm, what if
43 * there are several?) as a system pointing device, i.e. it controls
44 * the normal Windows cursor. This seems much more natural.
46 #define USE_SYSCONTEXT 1 /* The code for the other choice is not
50 #define TWOPI (2.*M_PI)
52 #define PING() g_print("%s: %d\n",__FILE__,__LINE__)
54 /* Forward declarations */
56 static gint gdk_input_win32_set_mode (guint32 deviceid,
58 static void gdk_input_win32_get_pointer (GdkWindow *window,
65 GdkModifierType *mask);
66 static void gdk_input_none_get_pointer (GdkWindow *window,
73 GdkModifierType *mask);
74 static gint gdk_input_win32_grab_pointer (GdkWindow * window,
76 GdkEventMask event_mask,
77 GdkWindow *confine_to,
79 static void gdk_input_win32_ungrab_pointer (guint32 time);
80 static void gdk_input_win32_configure_event (GdkEventConfigure *event,
82 static void gdk_input_win32_enter_event (GdkEventCrossing *xevent,
84 static gint gdk_input_win32_other_event (GdkEvent *event,
86 static gint gdk_input_win32_enable_window (GdkWindow *window,
87 GdkDevicePrivate *gdkdev);
88 static gint gdk_input_win32_disable_window (GdkWindow *window,
89 GdkDevicePrivate *gdkdev);
91 static GdkInputWindow *gdk_input_window_find (GdkWindow *window);
92 static GdkInputWindow *gdk_input_window_find_within (GdkWindow *window);
93 static GdkDevicePrivate *gdk_input_find_device (guint32 deviceid);
94 static GdkDevicePrivate *gdk_input_find_dev_from_ctx (HCTX hctx,
99 static GList *gdk_input_devices;
100 static GList *gdk_input_windows;
101 static GList *wintab_contexts;
103 static gint gdk_input_root_width;
104 static gint gdk_input_root_height;
106 static GdkWindow *wintab_window;
108 static guint32 last_moved_cursor_id;
110 static GdkAxisUse gdk_input_core_axes[] = { GDK_AXIS_X, GDK_AXIS_Y };
112 static GdkDeviceInfo gdk_input_core_info =
123 /* Global variables */
125 GdkInputVTable gdk_input_vtable;
126 gint gdk_input_ignore_core;
127 gint gdk_input_ignore_wintab = FALSE;
132 print_lc(LOGCONTEXT *lc)
134 g_print ("lcName = %s\n", lc->lcName);
135 g_print ("lcOptions =");
136 if (lc->lcOptions & CXO_SYSTEM) g_print (" CXO_SYSTEM");
137 if (lc->lcOptions & CXO_PEN) g_print (" CXO_PEN");
138 if (lc->lcOptions & CXO_MESSAGES) g_print (" CXO_MESSAGES");
139 if (lc->lcOptions & CXO_MARGIN) g_print (" CXO_MARGIN");
140 if (lc->lcOptions & CXO_MGNINSIDE) g_print (" CXO_MGNINSIDE");
141 if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
142 if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
144 g_print ("lcStatus =");
145 if (lc->lcStatus & CXS_DISABLED) g_print (" CXS_DISABLED");
146 if (lc->lcStatus & CXS_OBSCURED) g_print (" CXS_OBSCURED");
147 if (lc->lcStatus & CXS_ONTOP) g_print (" CXS_ONTOP");
149 g_print ("lcLocks =");
150 if (lc->lcLocks & CXL_INSIZE) g_print (" CXL_INSIZE");
151 if (lc->lcLocks & CXL_INASPECT) g_print (" CXL_INASPECT");
152 if (lc->lcLocks & CXL_SENSITIVITY) g_print (" CXL_SENSITIVITY");
153 if (lc->lcLocks & CXL_MARGIN) g_print (" CXL_MARGIN");
155 g_print ("lcMsgBase = %#x, lcDevice = %#x, lcPktRate = %d\n",
156 lc->lcMsgBase, lc->lcDevice, lc->lcPktRate);
157 g_print ("lcPktData =");
158 if (lc->lcPktData & PK_CONTEXT) g_print (" PK_CONTEXT");
159 if (lc->lcPktData & PK_STATUS) g_print (" PK_STATUS");
160 if (lc->lcPktData & PK_TIME) g_print (" PK_TIME");
161 if (lc->lcPktData & PK_CHANGED) g_print (" PK_CHANGED");
162 if (lc->lcPktData & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
163 if (lc->lcPktData & PK_CURSOR) g_print (" PK_CURSOR");
164 if (lc->lcPktData & PK_BUTTONS) g_print (" PK_BUTTONS");
165 if (lc->lcPktData & PK_X) g_print (" PK_X");
166 if (lc->lcPktData & PK_Y) g_print (" PK_Y");
167 if (lc->lcPktData & PK_Z) g_print (" PK_Z");
168 if (lc->lcPktData & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
169 if (lc->lcPktData & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
170 if (lc->lcPktData & PK_ORIENTATION) g_print (" PK_ORIENTATION");
171 if (lc->lcPktData & PK_ROTATION) g_print (" PK_ROTATION");
173 g_print ("lcPktMode =");
174 if (lc->lcPktMode & PK_CONTEXT) g_print (" PK_CONTEXT");
175 if (lc->lcPktMode & PK_STATUS) g_print (" PK_STATUS");
176 if (lc->lcPktMode & PK_TIME) g_print (" PK_TIME");
177 if (lc->lcPktMode & PK_CHANGED) g_print (" PK_CHANGED");
178 if (lc->lcPktMode & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
179 if (lc->lcPktMode & PK_CURSOR) g_print (" PK_CURSOR");
180 if (lc->lcPktMode & PK_BUTTONS) g_print (" PK_BUTTONS");
181 if (lc->lcPktMode & PK_X) g_print (" PK_X");
182 if (lc->lcPktMode & PK_Y) g_print (" PK_Y");
183 if (lc->lcPktMode & PK_Z) g_print (" PK_Z");
184 if (lc->lcPktMode & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
185 if (lc->lcPktMode & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
186 if (lc->lcPktMode & PK_ORIENTATION) g_print (" PK_ORIENTATION");
187 if (lc->lcPktMode & PK_ROTATION) g_print (" PK_ROTATION");
189 g_print ("lcMoveMask =");
190 if (lc->lcMoveMask & PK_CONTEXT) g_print (" PK_CONTEXT");
191 if (lc->lcMoveMask & PK_STATUS) g_print (" PK_STATUS");
192 if (lc->lcMoveMask & PK_TIME) g_print (" PK_TIME");
193 if (lc->lcMoveMask & PK_CHANGED) g_print (" PK_CHANGED");
194 if (lc->lcMoveMask & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
195 if (lc->lcMoveMask & PK_CURSOR) g_print (" PK_CURSOR");
196 if (lc->lcMoveMask & PK_BUTTONS) g_print (" PK_BUTTONS");
197 if (lc->lcMoveMask & PK_X) g_print (" PK_X");
198 if (lc->lcMoveMask & PK_Y) g_print (" PK_Y");
199 if (lc->lcMoveMask & PK_Z) g_print (" PK_Z");
200 if (lc->lcMoveMask & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
201 if (lc->lcMoveMask & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
202 if (lc->lcMoveMask & PK_ORIENTATION) g_print (" PK_ORIENTATION");
203 if (lc->lcMoveMask & PK_ROTATION) g_print (" PK_ROTATION");
205 g_print ("lcBtnDnMask = %#x, lcBtnUpMask = %#x\n",
206 lc->lcBtnDnMask, lc->lcBtnUpMask);
207 g_print ("lcInOrgX = %d, lcInOrgY = %d, lcInOrgZ = %d\n",
208 lc->lcInOrgX, lc->lcInOrgY, lc->lcInOrgZ);
209 g_print ("lcInExtX = %d, lcInExtY = %d, lcInExtZ = %d\n",
210 lc->lcInExtX, lc->lcInExtY, lc->lcInExtZ);
211 g_print ("lcOutOrgX = %d, lcOutOrgY = %d, lcOutOrgZ = %d\n",
212 lc->lcOutOrgX, lc->lcOutOrgY, lc->lcOutOrgZ);
213 g_print ("lcOutExtX = %d, lcOutExtY = %d, lcOutExtZ = %d\n",
214 lc->lcOutExtX, lc->lcOutExtY, lc->lcOutExtZ);
215 g_print ("lcSensX = %g, lcSensY = %g, lcSensZ = %g\n",
216 lc->lcSensX / 65536., lc->lcSensY / 65536., lc->lcSensZ / 65536.);
217 g_print ("lcSysMode = %d\n", lc->lcSysMode);
218 g_print ("lcSysOrgX = %d, lcSysOrgY = %d\n",
219 lc->lcSysOrgX, lc->lcSysOrgY);
220 g_print ("lcSysExtX = %d, lcSysExtY = %d\n",
221 lc->lcSysExtX, lc->lcSysExtY);
222 g_print ("lcSysSensX = %g, lcSysSensY = %g\n",
223 lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.);
229 gdk_input_init (void)
231 GdkDevicePrivate *gdkdev;
232 GdkWindowPrivate *window_private;
235 LOGCONTEXT defcontext;
237 UINT ndevices, ncursors, ncsrtypes, firstcsr, hardware;
238 AXIS axis_x, axis_y, axis_npressure, axis_orientation[3];
240 char devname[100], csrname[100];
241 guint32 deviceid_counter = 0;
243 gdk_input_devices = NULL;
244 wintab_contexts = NULL;
246 if (!gdk_input_ignore_wintab &&
249 WTInfo (WTI_INTERFACE, IFC_SPECVERSION, &specversion);
252 WTInfo (WTI_DEFSYSCTX, 0, &defcontext);
254 WTInfo (WTI_DEFCONTEXT, 0, &defcontext);
257 g_print("DEFCONTEXT:\n"); print_lc(&defcontext);
259 WTInfo (WTI_INTERFACE, IFC_NDEVICES, &ndevices);
260 WTInfo (WTI_INTERFACE, IFC_NCURSORS, &ncursors);
262 /* Create a dummy window to receive wintab events */
263 wa.wclass = GDK_INPUT_OUTPUT;
264 wa.event_mask = GDK_ALL_EVENTS_MASK;
269 wa.window_type = GDK_WINDOW_TOPLEVEL;
270 if ((wintab_window = gdk_window_new (NULL, &wa, GDK_WA_X|GDK_WA_Y)) == NULL)
272 g_warning ("gdk_input_init: gdk_window_new failed");
275 gdk_window_ref (wintab_window);
276 window_private = (GdkWindowPrivate *) wintab_window;
278 for (i = 0; i < ndevices; i++)
282 WTInfo (WTI_DEVICES + i, DVC_NAME, devname);
284 WTInfo (WTI_DEVICES + i, DVC_NCSRTYPES, &ncsrtypes);
285 WTInfo (WTI_DEVICES + i, DVC_FIRSTCSR, &firstcsr);
286 WTInfo (WTI_DEVICES + i, DVC_HARDWARE, &hardware);
287 WTInfo (WTI_DEVICES + i, DVC_X, &axis_x);
288 WTInfo (WTI_DEVICES + i, DVC_Y, &axis_y);
289 WTInfo (WTI_DEVICES + i, DVC_NPRESSURE, &axis_npressure);
290 WTInfo (WTI_DEVICES + i, DVC_ORIENTATION, axis_orientation);
292 if (HIBYTE (specversion) > 1 || LOBYTE (specversion) >= 1)
294 WTInfo (WTI_DDCTXS + i, CTX_NAME, lc.lcName);
295 WTInfo (WTI_DDCTXS + i, CTX_OPTIONS, &lc.lcOptions);
296 lc.lcOptions |= CXO_MESSAGES;
298 WTInfo (WTI_DDCTXS + i, CTX_LOCKS, &lc.lcLocks);
299 lc.lcMsgBase = WT_DEFBASE;
302 lc.lcPktData = PACKETDATA;
303 lc.lcPktMode = PK_BUTTONS; /* We want buttons in relative mode */
304 lc.lcMoveMask = PACKETDATA;
305 lc.lcBtnDnMask = lc.lcBtnUpMask = ~0;
306 WTInfo (WTI_DDCTXS + i, CTX_INORGX, &lc.lcInOrgX);
307 WTInfo (WTI_DDCTXS + i, CTX_INORGY, &lc.lcInOrgY);
308 WTInfo (WTI_DDCTXS + i, CTX_INORGZ, &lc.lcInOrgZ);
309 WTInfo (WTI_DDCTXS + i, CTX_INEXTX, &lc.lcInExtX);
310 WTInfo (WTI_DDCTXS + i, CTX_INEXTY, &lc.lcInExtY);
311 WTInfo (WTI_DDCTXS + i, CTX_INEXTZ, &lc.lcInExtZ);
312 lc.lcOutOrgX = axis_x.axMin;
313 lc.lcOutOrgY = axis_y.axMin;
314 lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
315 lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
316 lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
317 WTInfo (WTI_DDCTXS + i, CTX_SENSX, &lc.lcSensX);
318 WTInfo (WTI_DDCTXS + i, CTX_SENSY, &lc.lcSensY);
319 WTInfo (WTI_DDCTXS + i, CTX_SENSZ, &lc.lcSensZ);
320 WTInfo (WTI_DDCTXS + i, CTX_SYSMODE, &lc.lcSysMode);
321 lc.lcSysOrgX = lc.lcSysOrgY = 0;
322 WTInfo (WTI_DDCTXS + i, CTX_SYSEXTX, &lc.lcSysExtX);
323 WTInfo (WTI_DDCTXS + i, CTX_SYSEXTY, &lc.lcSysExtY);
324 WTInfo (WTI_DDCTXS + i, CTX_SYSSENSX, &lc.lcSysSensX);
325 WTInfo (WTI_DDCTXS + i, CTX_SYSSENSY, &lc.lcSysSensY);
330 lc.lcOptions |= CXO_MESSAGES;
331 lc.lcMsgBase = WT_DEFBASE;
332 lc.lcPktRate = 20; /* Slow down the packets a bit */
333 lc.lcPktData = PACKETDATA;
334 lc.lcPktMode = PACKETMODE;
335 lc.lcMoveMask = PACKETDATA;
336 lc.lcBtnUpMask = lc.lcBtnDnMask = ~0;
338 lc.lcOutExtY = -lc.lcOutExtY; /* Y grows downward */
340 lc.lcOutOrgX = axis_x.axMin;
341 lc.lcOutOrgY = axis_y.axMin;
342 lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
343 lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
344 lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
348 g_print("context for device %d:\n", i); print_lc(&lc);
350 hctx = g_new (HCTX, 1);
351 if ((*hctx = WTOpen (window_private->xwindow, &lc, TRUE)) == NULL)
353 g_warning ("gdk_input_init: WTOpen failed");
356 GDK_NOTE (MISC, g_print ("gdk_input_init: opened Wintab device %d %#x\n",
359 wintab_contexts = g_list_append (wintab_contexts, hctx);
361 WTEnable (*hctx, TRUE);
363 WTOverlap (*hctx, TRUE);
366 g_print("context for device %d after WTOpen:\n", i); print_lc(&lc);
368 for (j = firstcsr; j < firstcsr + ncsrtypes; j++)
370 gdkdev = g_new (GdkDevicePrivate, 1);
371 WTInfo (WTI_CURSORS + j, CSR_NAME, csrname);
372 gdkdev->info.name = g_strconcat (devname, " ", csrname, NULL);
373 gdkdev->info.deviceid = deviceid_counter++;
374 gdkdev->info.source = GDK_SOURCE_PEN;
375 gdkdev->info.mode = GDK_MODE_SCREEN;
377 gdkdev->info.has_cursor = TRUE;
379 gdkdev->info.has_cursor = FALSE;
381 gdkdev->hctx = *hctx;
383 WTInfo (WTI_CURSORS + j, CSR_PKTDATA, &gdkdev->pktdata);
384 gdkdev->info.num_axes = 0;
385 if (gdkdev->pktdata & PK_X)
386 gdkdev->info.num_axes++;
387 if (gdkdev->pktdata & PK_Y)
388 gdkdev->info.num_axes++;
389 if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
390 gdkdev->info.num_axes++;
391 if (gdkdev->pktdata & PK_ORIENTATION)
392 gdkdev->info.num_axes += 2; /* x and y tilt */
393 WTInfo (WTI_CURSORS + j, CSR_NPBTNMARKS, &gdkdev->npbtnmarks);
394 gdkdev->axes = g_new (GdkAxisInfo, gdkdev->info.num_axes);
395 gdkdev->info.axes = g_new (GdkAxisUse, gdkdev->info.num_axes);
396 gdkdev->last_axis_data = g_new (gint, gdkdev->info.num_axes);
398 for (k = 0; k < GDK_AXIS_LAST; k++)
399 gdkdev->axis_for_use[k] = -1;
402 if (gdkdev->pktdata & PK_X)
404 gdkdev->axes[k].xresolution =
405 gdkdev->axes[k].resolution = axis_x.axResolution / 65535.;
406 gdkdev->axes[k].xmin_value =
407 gdkdev->axes[k].min_value = axis_x.axMin;
408 gdkdev->axes[k].xmax_value =
409 gdkdev->axes[k].max_value = axis_x.axMax;
410 gdkdev->info.axes[k] = GDK_AXIS_X;
411 gdkdev->axis_for_use[GDK_AXIS_X] = k;
414 if (gdkdev->pktdata & PK_Y)
416 gdkdev->axes[k].xresolution =
417 gdkdev->axes[k].resolution = axis_y.axResolution / 65535.;
418 gdkdev->axes[k].xmin_value =
419 gdkdev->axes[k].min_value = axis_y.axMin;
420 gdkdev->axes[k].xmax_value =
421 gdkdev->axes[k].max_value = axis_y.axMax;
422 gdkdev->info.axes[k] = GDK_AXIS_Y;
423 gdkdev->axis_for_use[GDK_AXIS_Y] = k;
426 if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
428 gdkdev->axes[k].xresolution =
429 gdkdev->axes[k].resolution = axis_npressure.axResolution / 65535.;
430 gdkdev->axes[k].xmin_value =
431 gdkdev->axes[k].min_value = axis_npressure.axMin;
432 gdkdev->axes[k].xmax_value =
433 gdkdev->axes[k].max_value = axis_npressure.axMax;
434 gdkdev->info.axes[k] = GDK_AXIS_PRESSURE;
435 gdkdev->axis_for_use[GDK_AXIS_PRESSURE] = k;
438 if (gdkdev->pktdata & PK_ORIENTATION)
442 gdkdev->orientation_axes[0] = axis_orientation[0];
443 gdkdev->orientation_axes[1] = axis_orientation[1];
444 for (axis = GDK_AXIS_XTILT; axis <= GDK_AXIS_YTILT; axis++)
446 gdkdev->axes[k].xresolution =
447 gdkdev->axes[k].resolution = 1000;
448 gdkdev->axes[k].xmin_value =
449 gdkdev->axes[k].min_value = -1000;
450 gdkdev->axes[k].xmax_value =
451 gdkdev->axes[k].max_value = 1000;
452 gdkdev->info.axes[k] = axis;
453 gdkdev->axis_for_use[axis] = k;
457 gdkdev->info.num_keys = 0;
458 gdkdev->info.keys = NULL;
460 g_print ("gdk_input_init: device: %d axes: %d\n",
461 gdkdev->info.deviceid,
462 gdkdev->info.num_axes));
463 gdk_input_devices = g_list_append (gdk_input_devices,
467 gdk_input_vtable.set_mode = gdk_input_win32_set_mode;
468 gdk_input_vtable.set_axes = NULL;
469 gdk_input_vtable.set_key = NULL;
470 gdk_input_vtable.motion_events = NULL;
471 gdk_input_vtable.get_pointer = gdk_input_win32_get_pointer;
472 gdk_input_vtable.grab_pointer = gdk_input_win32_grab_pointer;
473 gdk_input_vtable.ungrab_pointer = gdk_input_win32_ungrab_pointer;
474 gdk_input_vtable.configure_event = gdk_input_win32_configure_event;
475 gdk_input_vtable.enter_event = gdk_input_win32_enter_event;
476 gdk_input_vtable.other_event = gdk_input_win32_other_event;
477 gdk_input_vtable.enable_window = gdk_input_win32_enable_window;
478 gdk_input_vtable.disable_window = gdk_input_win32_disable_window;
480 gdk_input_root_width = gdk_screen_width ();
481 gdk_input_root_height = gdk_screen_height ();
482 gdk_input_ignore_core = FALSE;
486 gdk_input_vtable.set_mode = NULL;
487 gdk_input_vtable.set_axes = NULL;
488 gdk_input_vtable.set_key = NULL;
489 gdk_input_vtable.motion_events = NULL;
490 gdk_input_vtable.get_pointer = gdk_input_none_get_pointer;
491 gdk_input_vtable.grab_pointer = NULL;
492 gdk_input_vtable.ungrab_pointer = NULL;
493 gdk_input_vtable.configure_event = NULL;
494 gdk_input_vtable.enter_event = NULL;
495 gdk_input_vtable.other_event = NULL;
496 gdk_input_vtable.enable_window = NULL;
497 gdk_input_vtable.disable_window = NULL;
498 gdk_input_ignore_core = FALSE;
501 gdk_input_devices = g_list_append (gdk_input_devices, &gdk_input_core_info);
505 gdk_input_get_root_relative_geometry (HWND w,
511 GetWindowRect (w, &rect);
520 gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
521 GdkInputWindow *input_window,
529 GdkWindowPrivate *window_private;
530 gint x_axis, y_axis, pressure_axis, xtilt_axis, ytilt_axis;
531 gdouble device_width, device_height;
532 gdouble x_offset, y_offset, x_scale, y_scale;
534 window_private = (GdkWindowPrivate *) input_window->window;
536 x_axis = gdkdev->axis_for_use[GDK_AXIS_X];
537 y_axis = gdkdev->axis_for_use[GDK_AXIS_Y];
538 pressure_axis = gdkdev->axis_for_use[GDK_AXIS_PRESSURE];
539 xtilt_axis = gdkdev->axis_for_use[GDK_AXIS_XTILT];
540 ytilt_axis = gdkdev->axis_for_use[GDK_AXIS_YTILT];
542 device_width = gdkdev->axes[x_axis].max_value -
543 gdkdev->axes[x_axis].min_value;
544 device_height = gdkdev->axes[y_axis].max_value -
545 gdkdev->axes[y_axis].min_value;
547 if (gdkdev->info.mode == GDK_MODE_SCREEN)
549 x_scale = gdk_input_root_width / device_width;
550 y_scale = gdk_input_root_height / device_height;
552 x_offset = -input_window->root_x;
553 y_offset = -input_window->root_y;
555 else /* GDK_MODE_WINDOW */
557 double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
558 (device_width*gdkdev->axes[x_axis].resolution);
560 if (device_aspect * window_private->width >= window_private->height)
562 /* device taller than window */
563 x_scale = window_private->width / device_width;
564 y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
565 / gdkdev->axes[y_axis].resolution;
568 y_offset = -(device_height * y_scale -
569 window_private->height)/2;
573 /* window taller than device */
574 y_scale = window_private->height / device_height;
575 x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
576 / gdkdev->axes[x_axis].resolution;
579 x_offset = -(device_width * x_scale - window_private->width)/2;
584 *x = x_offset + x_scale*axis_data[x_axis];
586 *y = y_offset + y_scale*axis_data[y_axis];
590 if (pressure_axis != -1)
591 *pressure = ((double)axis_data[pressure_axis]
592 - gdkdev->axes[pressure_axis].min_value)
593 / (gdkdev->axes[pressure_axis].max_value
594 - gdkdev->axes[pressure_axis].min_value);
601 if (xtilt_axis != -1)
603 *xtilt = 2. * (double)(axis_data[xtilt_axis] -
604 (gdkdev->axes[xtilt_axis].min_value +
605 gdkdev->axes[xtilt_axis].max_value)/2) /
606 (gdkdev->axes[xtilt_axis].max_value -
607 gdkdev->axes[xtilt_axis].min_value);
615 if (ytilt_axis != -1)
617 *ytilt = 2. * (double)(axis_data[ytilt_axis] -
618 (gdkdev->axes[ytilt_axis].min_value +
619 gdkdev->axes[ytilt_axis].max_value)/2) /
620 (gdkdev->axes[ytilt_axis].max_value -
621 gdkdev->axes[ytilt_axis].min_value);
629 gdk_input_set_mode (guint32 deviceid,
632 if (deviceid == GDK_CORE_POINTER)
635 if (gdk_input_vtable.set_mode)
636 return gdk_input_vtable.set_mode (deviceid, mode);
642 gdk_input_set_axes (guint32 deviceid,
646 GdkDevicePrivate *gdkdev = gdk_input_find_device (deviceid);
647 g_return_if_fail (gdkdev != NULL);
649 if (deviceid == GDK_CORE_POINTER)
652 for (i = GDK_AXIS_IGNORE; i < GDK_AXIS_LAST; i++)
654 gdkdev->axis_for_use[i] = -1;
657 for (i = 0; i < gdkdev->info.num_axes; i++)
659 gdkdev->info.axes[i] = axes[i];
660 gdkdev->axis_for_use[axes[i]] = i;
665 gdk_input_win32_get_pointer (GdkWindow *window,
672 GdkModifierType *mask)
674 GdkDevicePrivate *gdkdev;
675 GdkInputWindow *input_window;
679 if (deviceid == GDK_CORE_POINTER)
681 gdk_window_get_pointer (window, &x_int, &y_int, mask);
696 gdk_window_get_pointer (window, NULL, NULL, mask);
698 gdkdev = gdk_input_find_device (deviceid);
699 g_return_if_fail (gdkdev != NULL);
701 input_window = gdk_input_window_find (window);
702 g_return_if_fail (input_window != NULL);
704 gdk_input_translate_coordinates (gdkdev, input_window,
705 gdkdev->last_axis_data,
711 *mask |= ((gdkdev->last_buttons & 0x1F) << 8);
717 gdk_input_none_get_pointer (GdkWindow *window,
724 GdkModifierType *mask)
728 gdk_window_get_pointer (window, &x_int, &y_int, mask);
743 gdk_input_win32_set_mode (guint32 deviceid,
747 GdkDevicePrivate *gdkdev;
748 GdkInputMode old_mode;
749 GdkInputWindow *input_window;
751 if (deviceid == GDK_CORE_POINTER)
754 gdkdev = gdk_input_find_device (deviceid);
755 g_return_val_if_fail (gdkdev != NULL, FALSE);
756 old_mode = gdkdev->info.mode;
758 if (old_mode == mode)
761 gdkdev->info.mode = mode;
763 if (mode == GDK_MODE_WINDOW)
765 gdkdev->info.has_cursor = FALSE;
766 for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
768 input_window = (GdkInputWindow *)tmp_list->data;
769 if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
770 gdk_input_win32_enable_window (input_window->window, gdkdev);
772 if (old_mode != GDK_MODE_DISABLED)
773 gdk_input_win32_disable_window (input_window->window, gdkdev);
776 else if (mode == GDK_MODE_SCREEN)
778 gdkdev->info.has_cursor = TRUE;
779 for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
780 gdk_input_win32_enable_window (((GdkInputWindow *)tmp_list->data)->window,
783 else /* mode == GDK_MODE_DISABLED */
785 for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
787 input_window = (GdkInputWindow *)tmp_list->data;
788 if (old_mode != GDK_MODE_WINDOW ||
789 input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
790 gdk_input_win32_disable_window (input_window->window, gdkdev);
798 gdk_input_win32_configure_event (GdkEventConfigure *event,
801 GdkInputWindow *input_window;
804 input_window = gdk_input_window_find (window);
805 g_return_if_fail (window != NULL);
807 gdk_input_get_root_relative_geometry (GDK_WINDOW_XWINDOW (window),
810 input_window->root_x = root_x;
811 input_window->root_y = root_y;
815 gdk_input_win32_enter_event (GdkEventCrossing *event,
818 GdkInputWindow *input_window;
821 input_window = gdk_input_window_find (window);
822 g_return_if_fail (window != NULL);
824 gdk_input_get_root_relative_geometry (GDK_WINDOW_XWINDOW (window),
827 input_window->root_x = root_x;
828 input_window->root_y = root_y;
832 decode_tilt (gint *axis_data,
836 /* As I don't have a tilt-sensing tablet,
837 * I cannot test this code.
842 az = TWOPI * packet->pkOrientation.orAzimuth /
843 (axes[0].axResolution / 65536.);
844 el = TWOPI * packet->pkOrientation.orAltitude /
845 (axes[1].axResolution / 65536.);
848 axis_data[0] = cos (az) * cos (el) * 1000;
850 axis_data[1] = sin (az) * cos (el) * 1000;
854 gdk_input_win32_other_event (GdkEvent *event,
857 GdkWindow *current_window;
858 GdkInputWindow *input_window;
860 GdkWindowPrivate *window_private;
861 GdkDevicePrivate *gdkdev;
862 GdkEventMask masktest;
869 if (event->any.window != wintab_window)
870 g_warning ("gdk_input_win32_other_event: not wintab_window?");
873 window = gdk_window_at_pointer (&x, &y);
875 window = (GdkWindow *) &gdk_root_parent;
877 gdk_window_ref (window);
879 window_private = (GdkWindowPrivate *) window;
881 GDK_NOTE (EVENTS, g_print ("gdk_input_win32_other_event: window=%#x (%d,%d)\n", window_private->xwindow, x, y));
884 /* ??? This code is pretty bogus */
885 current_window = gdk_window_lookup (GetActiveWindow ());
886 if (current_window == NULL)
889 input_window = gdk_input_window_find_within (current_window);
890 if (input_window == NULL)
894 if (xevent->message == WT_PACKET)
896 if (!WTPacket ((HCTX) xevent->lParam, xevent->wParam, &packet))
900 switch (xevent->message)
903 if (window_private == &gdk_root_parent)
905 GDK_NOTE (EVENTS, g_print ("...is root\n"));
909 if ((gdkdev = gdk_input_find_dev_from_ctx ((HCTX) xevent->lParam,
910 packet.pkCursor)) == NULL)
913 if (gdkdev->info.mode == GDK_MODE_DISABLED)
917 if (gdkdev->pktdata & PK_X)
918 gdkdev->last_axis_data[k++] = packet.pkX;
919 if (gdkdev->pktdata & PK_Y)
920 gdkdev->last_axis_data[k++] = packet.pkY;
921 if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
922 gdkdev->last_axis_data[k++] = packet.pkNormalPressure;
923 if (gdkdev->pktdata & PK_ORIENTATION)
925 decode_tilt (gdkdev->last_axis_data + k,
926 gdkdev->orientation_axes, &packet);
930 g_assert (k == gdkdev->info.num_axes);
932 if (HIWORD (packet.pkButtons) != TBN_NONE)
934 /* Gdk buttons are numbered 1.. */
935 event->button.button = 1 + LOWORD (packet.pkButtons);
937 if (HIWORD (packet.pkButtons) == TBN_UP)
939 event->any.type = GDK_BUTTON_RELEASE;
940 masktest = GDK_BUTTON_RELEASE_MASK;
941 gdkdev->button_state &= ~(1 << LOWORD (packet.pkButtons));
945 event->any.type = GDK_BUTTON_PRESS;
946 masktest = GDK_BUTTON_PRESS_MASK;
947 gdkdev->button_state |= 1 << LOWORD (packet.pkButtons);
952 event->any.type = GDK_MOTION_NOTIFY;
953 masktest = GDK_POINTER_MOTION_MASK;
954 if (gdkdev->button_state & (1 << 0))
955 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK;
956 if (gdkdev->button_state & (1 << 1))
957 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK;
958 if (gdkdev->button_state & (1 << 2))
959 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK;
962 /* Now we can check if the window wants the event, and
963 * propagate if necessary.
966 if (!window_private->extension_events_selected
967 || !(window_private->extension_events & masktest))
969 GDK_NOTE (EVENTS, g_print ("...not selected\n"));
971 if (window_private->parent == (GdkWindow *) &gdk_root_parent)
976 ClientToScreen (window_private->xwindow, &pt);
977 gdk_window_unref (window);
978 window = window_private->parent;
979 gdk_window_ref (window);
980 window_private = (GdkWindowPrivate *) window;
981 ScreenToClient (window_private->xwindow, &pt);
984 GDK_NOTE (EVENTS, g_print ("...propagating to %#x, (%d,%d)\n", window_private->xwindow, x, y));
988 input_window = gdk_input_window_find (window);
990 g_assert (input_window != NULL);
992 if (gdkdev->info.mode == GDK_MODE_WINDOW
993 && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
996 event->any.window = window;
998 if (event->any.type == GDK_BUTTON_PRESS
999 || event->any.type == GDK_BUTTON_RELEASE)
1001 event->button.time = xevent->time;
1002 event->button.source = gdkdev->info.source;
1003 last_moved_cursor_id =
1004 event->button.deviceid = gdkdev->info.deviceid;
1008 /* Buttons 1 to 3 will come in as WM_[LMR]BUTTON{DOWN,UP} */
1009 if (event->button.button <= 3)
1013 gdk_input_translate_coordinates (gdkdev, input_window,
1014 gdkdev->last_axis_data,
1015 &event->button.x, &event->button.y,
1016 &event->button.pressure,
1017 &event->button.xtilt,
1018 &event->button.ytilt);
1020 event->button.state = ((gdkdev->button_state << 8)
1021 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1022 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1023 | GDK_BUTTON5_MASK));
1024 GDK_NOTE (EVENTS, g_print ("WINTAB button %s: %d %d %g,%g %g\n",
1025 (event->button.type == GDK_BUTTON_PRESS ?
1026 "press" : "release"),
1027 event->button.deviceid,
1028 event->button.button,
1029 event->button.x, event->button.y,
1030 event->button.pressure));
1034 event->motion.time = xevent->time;
1035 last_moved_cursor_id =
1036 event->motion.deviceid = gdkdev->info.deviceid;
1037 event->motion.is_hint = FALSE;
1038 event->motion.source = gdkdev->info.source;
1040 gdk_input_translate_coordinates (gdkdev, input_window,
1041 gdkdev->last_axis_data,
1042 &event->motion.x, &event->motion.y,
1043 &event->motion.pressure,
1044 &event->motion.xtilt,
1045 &event->motion.ytilt);
1047 event->motion.state = ((gdkdev->button_state << 8)
1048 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1049 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1050 | GDK_BUTTON5_MASK));
1052 GDK_NOTE (EVENTS, g_print ("WINTAB motion: %d %g,%g %g\n",
1053 event->motion.deviceid,
1054 event->motion.x, event->motion.y,
1055 event->motion.pressure));
1057 /* Check for missing release or press events for the normal
1058 * pressure button. At least on my ArtPadII I sometimes miss a
1061 if ((gdkdev->pktdata & PK_NORMAL_PRESSURE
1062 && (event->motion.state & GDK_BUTTON1_MASK)
1063 && packet.pkNormalPressure <= MAX (0, gdkdev->npbtnmarks[0] - 2))
1064 || (gdkdev->pktdata & PK_NORMAL_PRESSURE
1065 && !(event->motion.state & GDK_BUTTON1_MASK)
1066 && packet.pkNormalPressure > gdkdev->npbtnmarks[1] + 2))
1068 GdkEvent *event2 = gdk_event_copy (event);
1069 if (event->motion.state & GDK_BUTTON1_MASK)
1071 event2->button.type = GDK_BUTTON_RELEASE;
1072 gdkdev->button_state &= ~1;
1076 event2->button.type = GDK_BUTTON_PRESS;
1077 gdkdev->button_state |= 1;
1079 event2->button.state = ((gdkdev->button_state << 8)
1080 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1081 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1082 | GDK_BUTTON5_MASK));
1083 event2->button.button = 1;
1084 GDK_NOTE (EVENTS, g_print ("WINTAB synthesized button %s: %d %d %g,%g %g\n",
1085 (event2->button.type == GDK_BUTTON_PRESS ?
1086 "press" : "release"),
1087 event2->button.deviceid,
1088 event2->button.button,
1089 event2->button.x, event2->button.y,
1090 event2->button.pressure));
1091 gdk_event_queue_append (event2);
1097 if (LOWORD (xevent->lParam) == 0)
1099 event->proximity.type = GDK_PROXIMITY_OUT;
1100 gdk_input_ignore_core = FALSE;
1104 event->proximity.type = GDK_PROXIMITY_IN;
1105 gdk_input_ignore_core = TRUE;
1107 event->proximity.time = xevent->time;
1108 event->proximity.source = GDK_SOURCE_PEN;
1109 event->proximity.deviceid = last_moved_cursor_id;
1111 GDK_NOTE (EVENTS, g_print ("WINTAB proximity %s: %d\n",
1112 (event->proximity.type == GDK_PROXIMITY_IN ?
1114 event->proximity.deviceid));
1122 gdk_input_win32_enable_window (GdkWindow *window,
1123 GdkDevicePrivate *gdkdev)
1125 GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
1127 window_private->extension_events_selected = TRUE;
1132 gdk_input_win32_disable_window (GdkWindow *window,
1133 GdkDevicePrivate *gdkdev)
1135 GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
1137 window_private->extension_events_selected = FALSE;
1142 gdk_input_win32_grab_pointer (GdkWindow *window,
1144 GdkEventMask event_mask,
1145 GdkWindow *confine_to,
1148 GdkInputWindow *input_window, *new_window;
1149 gboolean need_ungrab;
1150 GdkDevicePrivate *gdkdev;
1154 tmp_list = gdk_input_windows;
1156 need_ungrab = FALSE;
1158 GDK_NOTE (MISC, g_print ("gdk_input_win32_grab_pointer: %#x %d %#x\n",
1159 ((GdkWindowPrivate *) window)->xwindow,
1162 ((GdkWindowPrivate *) confine_to)->xwindow :
1167 input_window = (GdkInputWindow *)tmp_list->data;
1169 if (input_window->window == window)
1170 new_window = input_window;
1171 else if (input_window->grabbed)
1173 input_window->grabbed = FALSE;
1177 tmp_list = tmp_list->next;
1182 new_window->grabbed = TRUE;
1184 tmp_list = gdk_input_devices;
1187 gdkdev = (GdkDevicePrivate *)tmp_list->data;
1188 if (gdkdev->info.deviceid != GDK_CORE_POINTER)
1191 gdk_input_find_events (window, gdkdev,
1193 event_classes, &num_classes);
1194 result = XGrabDevice (GDK_DISPLAY(), gdkdev->xdevice,
1195 GDK_WINDOW_XWINDOW (window),
1196 owner_events, num_classes, event_classes,
1197 GrabModeAsync, GrabModeAsync, time);
1199 /* FIXME: if failure occurs on something other than the first
1200 device, things will be badly inconsistent */
1201 if (result != Success)
1205 tmp_list = tmp_list->next;
1210 tmp_list = gdk_input_devices;
1213 gdkdev = (GdkDevicePrivate *)tmp_list->data;
1214 if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
1215 ((gdkdev->button_state != 0) || need_ungrab))
1218 XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1220 gdkdev->button_state = 0;
1223 tmp_list = tmp_list->next;
1232 gdk_input_win32_ungrab_pointer (guint32 time)
1234 GdkInputWindow *input_window;
1235 GdkDevicePrivate *gdkdev;
1238 GDK_NOTE (MISC, g_print ("gdk_input_win32_ungrab_pointer\n"));
1240 tmp_list = gdk_input_windows;
1243 input_window = (GdkInputWindow *)tmp_list->data;
1244 if (input_window->grabbed)
1246 tmp_list = tmp_list->next;
1249 if (tmp_list) /* we found a grabbed window */
1251 input_window->grabbed = FALSE;
1253 tmp_list = gdk_input_devices;
1256 gdkdev = (GdkDevicePrivate *)tmp_list->data;
1258 if (gdkdev->info.deviceid != GDK_CORE_POINTER && gdkdev->xdevice)
1259 XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1261 tmp_list = tmp_list->next;
1267 gdk_input_list_devices (void)
1269 return gdk_input_devices;
1273 gdk_input_set_source (guint32 deviceid,
1274 GdkInputSource source)
1276 GdkDevicePrivate *gdkdev = gdk_input_find_device (deviceid);
1277 g_return_if_fail (gdkdev != NULL);
1279 gdkdev->info.source = source;
1282 void gdk_input_set_key (guint32 deviceid,
1285 GdkModifierType modifiers)
1287 if (deviceid != GDK_CORE_POINTER && gdk_input_vtable.set_key)
1288 gdk_input_vtable.set_key (deviceid, index, keyval, modifiers);
1292 gdk_input_motion_events (GdkWindow *window,
1296 gint *nevents_return)
1298 GdkWindowPrivate *window_private;
1299 GdkTimeCoord *coords;
1302 g_return_val_if_fail (window != NULL, NULL);
1303 window_private = (GdkWindowPrivate *) window;
1304 if (window_private->destroyed)
1307 *nevents_return = 0;
1308 return NULL; /* ??? */
1311 static GdkInputWindow *
1312 gdk_input_window_find (GdkWindow *window)
1316 for (tmp_list=gdk_input_windows; tmp_list; tmp_list=tmp_list->next)
1317 if (((GdkInputWindow *)(tmp_list->data))->window == window)
1318 return (GdkInputWindow *)(tmp_list->data);
1320 return NULL; /* Not found */
1323 static GdkInputWindow *
1324 gdk_input_window_find_within (GdkWindow *window)
1327 GdkWindowPrivate *window_private;
1328 GdkWindowPrivate *tmp_private;
1329 GdkInputWindow *candidate = NULL;
1331 window_private = (GdkWindowPrivate *) window;
1333 for (tmp_list=gdk_input_windows; tmp_list; tmp_list=tmp_list->next)
1335 (GdkWindowPrivate *) tmp_private =
1336 (GdkWindowPrivate *) (((GdkInputWindow *)(tmp_list->data))->window);
1337 if (tmp_private == window_private
1338 || IsChild (window_private->xwindow, tmp_private->xwindow))
1341 return NULL; /* Multiple hits */
1342 candidate = (GdkInputWindow *)(tmp_list->data);
1349 /* FIXME: this routine currently needs to be called between creation
1350 and the corresponding configure event (because it doesn't get the
1351 root_relative_geometry). This should work with
1352 gtk_window_set_extension_events, but will likely fail in other
1356 gdk_input_set_extension_events (GdkWindow *window,
1358 GdkExtensionMode mode)
1360 GdkWindowPrivate *window_private;
1364 g_return_if_fail (window != NULL);
1365 window_private = (GdkWindowPrivate *) window;
1366 if (window_private->destroyed)
1369 if (mode == GDK_EXTENSION_EVENTS_NONE)
1374 iw = g_new (GdkInputWindow,1);
1376 iw->window = window;
1379 iw->grabbed = FALSE;
1381 gdk_input_windows = g_list_append (gdk_input_windows, iw);
1382 window_private->extension_events = mask;
1384 /* Add enter window events to the event mask */
1385 gdk_window_set_events (window,
1386 gdk_window_get_events (window) |
1387 GDK_ENTER_NOTIFY_MASK);
1391 iw = gdk_input_window_find (window);
1394 gdk_input_windows = g_list_remove (gdk_input_windows, iw);
1398 window_private->extension_events = 0;
1401 for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
1403 GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
1405 if (gdkdev->info.deviceid != GDK_CORE_POINTER)
1407 if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
1408 && (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL))
1409 gdk_input_win32_enable_window (window, gdkdev);
1411 gdk_input_win32_disable_window (window, gdkdev);
1417 gdk_input_window_destroy (GdkWindow *window)
1419 GdkInputWindow *input_window;
1421 input_window = gdk_input_window_find (window);
1422 g_return_if_fail (input_window != NULL);
1424 gdk_input_windows = g_list_remove (gdk_input_windows,input_window);
1425 g_free (input_window);
1429 gdk_input_exit (void)
1432 GdkDevicePrivate *gdkdev;
1434 for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
1436 gdkdev = (GdkDevicePrivate *)(tmp_list->data);
1437 if (gdkdev->info.deviceid != GDK_CORE_POINTER)
1439 gdk_input_win32_set_mode (gdkdev->info.deviceid, GDK_MODE_DISABLED);
1440 g_free (gdkdev->info.name);
1441 g_free (gdkdev->last_axis_data);
1442 g_free (gdkdev->info.axes);
1443 g_free (gdkdev->info.keys);
1444 g_free (gdkdev->axes);
1449 g_list_free (gdk_input_devices);
1451 for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
1453 g_free (tmp_list->data);
1455 g_list_free (gdk_input_windows);
1458 for (tmp_list = wintab_contexts; tmp_list; tmp_list = tmp_list->next)
1460 HCTX *hctx = (HCTX *) tmp_list->data;
1464 /* For some reason WTEnable and/or WTClose tend to crash here.
1465 * Protect with __try/__except to avoid a message box.
1468 #endif /* _MSC_VER */
1470 WTEnable (*hctx, FALSE);
1472 result = WTClose (*hctx);
1475 __except (/* GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? */
1476 EXCEPTION_EXECUTE_HANDLER /*:
1477 EXCEPTION_CONTINUE_SEARCH */) {
1480 #endif /* _MSC_VER */
1482 g_warning ("gdk_input_exit: Closing Wintab context %#x failed", *hctx);
1486 g_list_free (wintab_contexts);
1489 static GdkDevicePrivate *
1490 gdk_input_find_device (guint32 id)
1492 GList *tmp_list = gdk_input_devices;
1493 GdkDevicePrivate *gdkdev;
1497 gdkdev = (GdkDevicePrivate *) (tmp_list->data);
1498 if (gdkdev->info.deviceid == id)
1500 tmp_list = tmp_list->next;
1505 static GdkDevicePrivate *
1506 gdk_input_find_dev_from_ctx (HCTX hctx,
1509 GList *tmp_list = gdk_input_devices;
1510 GdkDevicePrivate *gdkdev;
1514 gdkdev = (GdkDevicePrivate *) (tmp_list->data);
1515 if (gdkdev->hctx == hctx && gdkdev->cursor == cursor)
1517 tmp_list = tmp_list->next;
1523 gdk_input_window_get_pointer (GdkWindow *window,
1530 GdkModifierType *mask)
1532 if (gdk_input_vtable.get_pointer)
1533 gdk_input_vtable.get_pointer (window, deviceid, x, y, pressure,
1534 xtilt, ytilt, mask);