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/.
36 #include "gdkprivate.h"
40 #define PACKETDATA (PK_CONTEXT | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION)
41 #define PACKETMODE (PK_BUTTONS)
45 #include "gdkinputprivate.h"
47 struct _GdkDevicePrivate {
50 /* information about the axes */
53 /* reverse lookup on axis use type */
54 gint axis_for_use[GDK_AXIS_LAST];
56 /* true if we need to select a different set of events, but
57 * can't because this is the core pointer
61 /* State of buttons */
71 /* The cursor's CSR_PKTDATA */
75 /* Azimuth and altitude axis */
76 AXIS orientation_axes[2];
81 #define M_PI 3.14159265358979323846
84 /* If USE_SYSCONTEXT is on, we open the Wintab device (hmm, what if
85 * there are several?) as a system pointing device, i.e. it controls
86 * the normal Windows cursor. This seems much more natural.
88 #define USE_SYSCONTEXT 1 /* The code for the other choice is not
93 #define DEBUG_WINTAB 1
96 #define TWOPI (2.*M_PI)
98 #define PING() g_print("%s: %d\n",__FILE__,__LINE__)
100 /* Forward declarations */
102 static gint gdk_input_enable_window (GdkWindow *window,
103 GdkDevicePrivate *gdkdev);
104 static gint gdk_input_disable_window (GdkWindow *window,
105 GdkDevicePrivate *gdkdev);
106 static void gdk_input_none_get_pointer (GdkWindow *window,
113 GdkModifierType *mask);
115 static GdkDevicePrivate *gdk_input_find_device (guint32 deviceid);
119 static gint gdk_input_win32_set_mode (guint32 deviceid,
121 static void gdk_input_win32_get_pointer (GdkWindow *window,
128 GdkModifierType *mask);
129 static gint gdk_input_win32_grab_pointer (GdkWindow * window,
131 GdkEventMask event_mask,
132 GdkWindow *confine_to,
134 static void gdk_input_win32_ungrab_pointer (guint32 time);
135 static void gdk_input_win32_configure_event (GdkEventConfigure *event,
137 static void gdk_input_win32_enter_event (GdkEventCrossing *xevent,
139 static gint gdk_input_win32_other_event (GdkEvent *event,
141 static gint gdk_input_win32_enable_window (GdkWindow *window,
142 GdkDevicePrivate *gdkdev);
143 static gint gdk_input_win32_disable_window (GdkWindow *window,
144 GdkDevicePrivate *gdkdev);
146 static GdkInputWindow *gdk_input_window_find (GdkWindow *window);
148 static GdkInputWindow *gdk_input_window_find_within (GdkWindow *window);
150 static GdkDevicePrivate *gdk_input_find_dev_from_ctx (HCTX hctx,
152 #endif /* HAVE_WINTAB */
154 /* Local variables */
156 static GList *gdk_input_devices;
157 static GList *gdk_input_windows;
158 static GList *wintab_contexts;
160 static gint gdk_input_root_width;
161 static gint gdk_input_root_height;
163 static GdkWindow *wintab_window;
165 static guint32 last_moved_cursor_id;
167 static GdkAxisUse gdk_input_core_axes[] = { GDK_AXIS_X, GDK_AXIS_Y };
169 static GdkDeviceInfo gdk_input_core_info =
180 /* Global variables */
182 GdkInputVTable gdk_input_vtable;
183 gint gdk_input_ignore_core;
184 gint gdk_input_ignore_wintab = FALSE;
189 print_lc(LOGCONTEXT *lc)
191 g_print ("lcName = %s\n", lc->lcName);
192 g_print ("lcOptions =");
193 if (lc->lcOptions & CXO_SYSTEM) g_print (" CXO_SYSTEM");
194 if (lc->lcOptions & CXO_PEN) g_print (" CXO_PEN");
195 if (lc->lcOptions & CXO_MESSAGES) g_print (" CXO_MESSAGES");
196 if (lc->lcOptions & CXO_MARGIN) g_print (" CXO_MARGIN");
197 if (lc->lcOptions & CXO_MGNINSIDE) g_print (" CXO_MGNINSIDE");
198 if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
199 if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
201 g_print ("lcStatus =");
202 if (lc->lcStatus & CXS_DISABLED) g_print (" CXS_DISABLED");
203 if (lc->lcStatus & CXS_OBSCURED) g_print (" CXS_OBSCURED");
204 if (lc->lcStatus & CXS_ONTOP) g_print (" CXS_ONTOP");
206 g_print ("lcLocks =");
207 if (lc->lcLocks & CXL_INSIZE) g_print (" CXL_INSIZE");
208 if (lc->lcLocks & CXL_INASPECT) g_print (" CXL_INASPECT");
209 if (lc->lcLocks & CXL_SENSITIVITY) g_print (" CXL_SENSITIVITY");
210 if (lc->lcLocks & CXL_MARGIN) g_print (" CXL_MARGIN");
212 g_print ("lcMsgBase = %#x, lcDevice = %#x, lcPktRate = %d\n",
213 lc->lcMsgBase, lc->lcDevice, lc->lcPktRate);
214 g_print ("lcPktData =");
215 if (lc->lcPktData & PK_CONTEXT) g_print (" PK_CONTEXT");
216 if (lc->lcPktData & PK_STATUS) g_print (" PK_STATUS");
217 if (lc->lcPktData & PK_TIME) g_print (" PK_TIME");
218 if (lc->lcPktData & PK_CHANGED) g_print (" PK_CHANGED");
219 if (lc->lcPktData & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
220 if (lc->lcPktData & PK_CURSOR) g_print (" PK_CURSOR");
221 if (lc->lcPktData & PK_BUTTONS) g_print (" PK_BUTTONS");
222 if (lc->lcPktData & PK_X) g_print (" PK_X");
223 if (lc->lcPktData & PK_Y) g_print (" PK_Y");
224 if (lc->lcPktData & PK_Z) g_print (" PK_Z");
225 if (lc->lcPktData & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
226 if (lc->lcPktData & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
227 if (lc->lcPktData & PK_ORIENTATION) g_print (" PK_ORIENTATION");
228 if (lc->lcPktData & PK_ROTATION) g_print (" PK_ROTATION");
230 g_print ("lcPktMode =");
231 if (lc->lcPktMode & PK_CONTEXT) g_print (" PK_CONTEXT");
232 if (lc->lcPktMode & PK_STATUS) g_print (" PK_STATUS");
233 if (lc->lcPktMode & PK_TIME) g_print (" PK_TIME");
234 if (lc->lcPktMode & PK_CHANGED) g_print (" PK_CHANGED");
235 if (lc->lcPktMode & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
236 if (lc->lcPktMode & PK_CURSOR) g_print (" PK_CURSOR");
237 if (lc->lcPktMode & PK_BUTTONS) g_print (" PK_BUTTONS");
238 if (lc->lcPktMode & PK_X) g_print (" PK_X");
239 if (lc->lcPktMode & PK_Y) g_print (" PK_Y");
240 if (lc->lcPktMode & PK_Z) g_print (" PK_Z");
241 if (lc->lcPktMode & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
242 if (lc->lcPktMode & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
243 if (lc->lcPktMode & PK_ORIENTATION) g_print (" PK_ORIENTATION");
244 if (lc->lcPktMode & PK_ROTATION) g_print (" PK_ROTATION");
246 g_print ("lcMoveMask =");
247 if (lc->lcMoveMask & PK_CONTEXT) g_print (" PK_CONTEXT");
248 if (lc->lcMoveMask & PK_STATUS) g_print (" PK_STATUS");
249 if (lc->lcMoveMask & PK_TIME) g_print (" PK_TIME");
250 if (lc->lcMoveMask & PK_CHANGED) g_print (" PK_CHANGED");
251 if (lc->lcMoveMask & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
252 if (lc->lcMoveMask & PK_CURSOR) g_print (" PK_CURSOR");
253 if (lc->lcMoveMask & PK_BUTTONS) g_print (" PK_BUTTONS");
254 if (lc->lcMoveMask & PK_X) g_print (" PK_X");
255 if (lc->lcMoveMask & PK_Y) g_print (" PK_Y");
256 if (lc->lcMoveMask & PK_Z) g_print (" PK_Z");
257 if (lc->lcMoveMask & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
258 if (lc->lcMoveMask & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
259 if (lc->lcMoveMask & PK_ORIENTATION) g_print (" PK_ORIENTATION");
260 if (lc->lcMoveMask & PK_ROTATION) g_print (" PK_ROTATION");
262 g_print ("lcBtnDnMask = %#x, lcBtnUpMask = %#x\n",
263 lc->lcBtnDnMask, lc->lcBtnUpMask);
264 g_print ("lcInOrgX = %d, lcInOrgY = %d, lcInOrgZ = %d\n",
265 lc->lcInOrgX, lc->lcInOrgY, lc->lcInOrgZ);
266 g_print ("lcInExtX = %d, lcInExtY = %d, lcInExtZ = %d\n",
267 lc->lcInExtX, lc->lcInExtY, lc->lcInExtZ);
268 g_print ("lcOutOrgX = %d, lcOutOrgY = %d, lcOutOrgZ = %d\n",
269 lc->lcOutOrgX, lc->lcOutOrgY, lc->lcOutOrgZ);
270 g_print ("lcOutExtX = %d, lcOutExtY = %d, lcOutExtZ = %d\n",
271 lc->lcOutExtX, lc->lcOutExtY, lc->lcOutExtZ);
272 g_print ("lcSensX = %g, lcSensY = %g, lcSensZ = %g\n",
273 lc->lcSensX / 65536., lc->lcSensY / 65536., lc->lcSensZ / 65536.);
274 g_print ("lcSysMode = %d\n", lc->lcSysMode);
275 g_print ("lcSysOrgX = %d, lcSysOrgY = %d\n",
276 lc->lcSysOrgX, lc->lcSysOrgY);
277 g_print ("lcSysExtX = %d, lcSysExtY = %d\n",
278 lc->lcSysExtX, lc->lcSysExtY);
279 g_print ("lcSysSensX = %g, lcSysSensY = %g\n",
280 lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.);
286 gdk_input_init (void)
288 guint32 deviceid_counter = 0;
290 GdkDevicePrivate *gdkdev;
291 GdkWindowPrivate *window_private;
294 LOGCONTEXT defcontext;
296 UINT ndevices, ncursors, ncsrtypes, firstcsr, hardware;
298 AXIS axis_x, axis_y, axis_npressure, axis_or[3];
301 char devname[100], csrname[100];
303 gdk_input_devices = NULL;
304 wintab_contexts = NULL;
306 if (!gdk_input_ignore_wintab &&
309 WTInfo (WTI_INTERFACE, IFC_SPECVERSION, &specversion);
310 GDK_NOTE (MISC, g_print ("Wintab interface version %d.%d\n",
311 HIBYTE (specversion), LOBYTE (specversion)));
313 WTInfo (WTI_DEFSYSCTX, 0, &defcontext);
315 GDK_NOTE (MISC, (g_print("DEFSYSCTX:\n"), print_lc(&defcontext)));
318 WTInfo (WTI_DEFCONTEXT, 0, &defcontext);
320 GDK_NOTE (MISC, (g_print("DEFCONTEXT:\n"), print_lc(&defcontext)));
323 WTInfo (WTI_INTERFACE, IFC_NDEVICES, &ndevices);
324 WTInfo (WTI_INTERFACE, IFC_NCURSORS, &ncursors);
326 GDK_NOTE (MISC, g_print ("NDEVICES: %d, NCURSORS: %d\n",
327 ndevices, ncursors));
329 /* Create a dummy window to receive wintab events */
330 wa.wclass = GDK_INPUT_OUTPUT;
331 wa.event_mask = GDK_ALL_EVENTS_MASK;
336 wa.window_type = GDK_WINDOW_TOPLEVEL;
337 if ((wintab_window = gdk_window_new (NULL, &wa, GDK_WA_X|GDK_WA_Y)) == NULL)
339 g_warning ("gdk_input_init: gdk_window_new failed");
342 gdk_window_ref (wintab_window);
343 window_private = (GdkWindowPrivate *) wintab_window;
345 for (devix = 0; devix < ndevices; devix++)
349 WTInfo (WTI_DEVICES + devix, DVC_NAME, devname);
351 WTInfo (WTI_DEVICES + devix, DVC_NCSRTYPES, &ncsrtypes);
352 WTInfo (WTI_DEVICES + devix, DVC_FIRSTCSR, &firstcsr);
353 WTInfo (WTI_DEVICES + devix, DVC_HARDWARE, &hardware);
354 WTInfo (WTI_DEVICES + devix, DVC_X, &axis_x);
355 WTInfo (WTI_DEVICES + devix, DVC_Y, &axis_y);
356 WTInfo (WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure);
357 WTInfo (WTI_DEVICES + devix, DVC_ORIENTATION, axis_or);
359 if (HIBYTE (specversion) > 1 || LOBYTE (specversion) >= 1)
361 WTInfo (WTI_DDCTXS + devix, CTX_NAME, lc.lcName);
362 WTInfo (WTI_DDCTXS + devix, CTX_OPTIONS, &lc.lcOptions);
363 lc.lcOptions |= CXO_MESSAGES;
365 lc.lcOptions |= CXO_SYSTEM;
368 WTInfo (WTI_DDCTXS + devix, CTX_LOCKS, &lc.lcLocks);
369 lc.lcMsgBase = WT_DEFBASE;
372 lc.lcPktData = PACKETDATA;
373 lc.lcPktMode = PK_BUTTONS; /* We want buttons in relative mode */
374 lc.lcMoveMask = PACKETDATA;
375 lc.lcBtnDnMask = lc.lcBtnUpMask = ~0;
376 WTInfo (WTI_DDCTXS + devix, CTX_INORGX, &lc.lcInOrgX);
377 WTInfo (WTI_DDCTXS + devix, CTX_INORGY, &lc.lcInOrgY);
378 WTInfo (WTI_DDCTXS + devix, CTX_INORGZ, &lc.lcInOrgZ);
379 WTInfo (WTI_DDCTXS + devix, CTX_INEXTX, &lc.lcInExtX);
380 WTInfo (WTI_DDCTXS + devix, CTX_INEXTY, &lc.lcInExtY);
381 WTInfo (WTI_DDCTXS + devix, CTX_INEXTZ, &lc.lcInExtZ);
382 lc.lcOutOrgX = axis_x.axMin;
383 lc.lcOutOrgY = axis_y.axMin;
384 lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
385 lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
386 lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
387 WTInfo (WTI_DDCTXS + devix, CTX_SENSX, &lc.lcSensX);
388 WTInfo (WTI_DDCTXS + devix, CTX_SENSY, &lc.lcSensY);
389 WTInfo (WTI_DDCTXS + devix, CTX_SENSZ, &lc.lcSensZ);
390 WTInfo (WTI_DDCTXS + devix, CTX_SYSMODE, &lc.lcSysMode);
391 lc.lcSysOrgX = lc.lcSysOrgY = 0;
392 WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTX, &lc.lcSysExtX);
393 WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTY, &lc.lcSysExtY);
394 WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSX, &lc.lcSysSensX);
395 WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSY, &lc.lcSysSensY);
400 lc.lcOptions |= CXO_MESSAGES;
401 lc.lcMsgBase = WT_DEFBASE;
403 lc.lcPktData = PACKETDATA;
404 lc.lcPktMode = PACKETMODE;
405 lc.lcMoveMask = PACKETDATA;
406 lc.lcBtnUpMask = lc.lcBtnDnMask = ~0;
408 lc.lcOutExtY = -lc.lcOutExtY; /* Y grows downward */
410 lc.lcOutOrgX = axis_x.axMin;
411 lc.lcOutOrgY = axis_y.axMin;
412 lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
413 lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
414 lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
418 GDK_NOTE (MISC, (g_print("context for device %d:\n", devix),
421 hctx = g_new (HCTX, 1);
422 if ((*hctx = WTOpen (window_private->xwindow, &lc, TRUE)) == NULL)
424 g_warning ("gdk_input_init: WTOpen failed");
427 GDK_NOTE (MISC, g_print ("opened Wintab device %d %#x\n",
430 wintab_contexts = g_list_append (wintab_contexts, hctx);
432 WTEnable (*hctx, TRUE);
434 WTOverlap (*hctx, TRUE);
437 GDK_NOTE (MISC, (g_print("context for device %d after WTOpen:\n", devix),
440 for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes; cursorix++)
443 WTInfo (WTI_CURSORS + cursorix, CSR_ACTIVE, &active);
446 gdkdev = g_new (GdkDevicePrivate, 1);
447 WTInfo (WTI_CURSORS + cursorix, CSR_NAME, csrname);
448 gdkdev->info.name = g_strconcat (devname, " ", csrname, NULL);
449 gdkdev->info.deviceid = deviceid_counter++;
450 gdkdev->info.source = GDK_SOURCE_PEN;
451 gdkdev->info.mode = GDK_MODE_SCREEN;
453 gdkdev->info.has_cursor = TRUE;
455 gdkdev->info.has_cursor = FALSE;
457 gdkdev->hctx = *hctx;
458 gdkdev->cursor = cursorix;
459 WTInfo (WTI_CURSORS + cursorix, CSR_PKTDATA, &gdkdev->pktdata);
460 gdkdev->info.num_axes = 0;
461 if (gdkdev->pktdata & PK_X)
462 gdkdev->info.num_axes++;
463 if (gdkdev->pktdata & PK_Y)
464 gdkdev->info.num_axes++;
465 if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
466 gdkdev->info.num_axes++;
467 /* The wintab driver for the Wacom ArtPad II reports
468 * PK_ORIENTATION in CSR_PKTDATA, but the tablet doesn't
469 * actually sense tilt. Catch this by noticing that the
470 * orientation axis's azimuth resolution is zero.
472 if ((gdkdev->pktdata & PK_ORIENTATION)
473 && axis_or[0].axResolution == 0)
474 gdkdev->pktdata &= ~PK_ORIENTATION;
476 if (gdkdev->pktdata & PK_ORIENTATION)
477 gdkdev->info.num_axes += 2; /* x and y tilt */
478 WTInfo (WTI_CURSORS + cursorix, CSR_NPBTNMARKS, &gdkdev->npbtnmarks);
479 gdkdev->axes = g_new (GdkAxisInfo, gdkdev->info.num_axes);
480 gdkdev->info.axes = g_new (GdkAxisUse, gdkdev->info.num_axes);
481 gdkdev->last_axis_data = g_new (gint, gdkdev->info.num_axes);
483 for (k = 0; k < GDK_AXIS_LAST; k++)
484 gdkdev->axis_for_use[k] = -1;
487 if (gdkdev->pktdata & PK_X)
489 gdkdev->axes[k].xresolution =
490 gdkdev->axes[k].resolution = axis_x.axResolution / 65535.;
491 gdkdev->axes[k].xmin_value =
492 gdkdev->axes[k].min_value = axis_x.axMin;
493 gdkdev->axes[k].xmax_value =
494 gdkdev->axes[k].max_value = axis_x.axMax;
495 gdkdev->info.axes[k] = GDK_AXIS_X;
496 gdkdev->axis_for_use[GDK_AXIS_X] = k;
499 if (gdkdev->pktdata & PK_Y)
501 gdkdev->axes[k].xresolution =
502 gdkdev->axes[k].resolution = axis_y.axResolution / 65535.;
503 gdkdev->axes[k].xmin_value =
504 gdkdev->axes[k].min_value = axis_y.axMin;
505 gdkdev->axes[k].xmax_value =
506 gdkdev->axes[k].max_value = axis_y.axMax;
507 gdkdev->info.axes[k] = GDK_AXIS_Y;
508 gdkdev->axis_for_use[GDK_AXIS_Y] = k;
511 if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
513 gdkdev->axes[k].xresolution =
514 gdkdev->axes[k].resolution = axis_npressure.axResolution / 65535.;
515 gdkdev->axes[k].xmin_value =
516 gdkdev->axes[k].min_value = axis_npressure.axMin;
517 gdkdev->axes[k].xmax_value =
518 gdkdev->axes[k].max_value = axis_npressure.axMax;
519 gdkdev->info.axes[k] = GDK_AXIS_PRESSURE;
520 gdkdev->axis_for_use[GDK_AXIS_PRESSURE] = k;
523 if (gdkdev->pktdata & PK_ORIENTATION)
527 gdkdev->orientation_axes[0] = axis_or[0];
528 gdkdev->orientation_axes[1] = axis_or[1];
529 for (axis = GDK_AXIS_XTILT; axis <= GDK_AXIS_YTILT; axis++)
531 /* Wintab gives us aximuth and altitude, which
532 * we convert to x and y tilt in the -1000..1000 range
534 gdkdev->axes[k].xresolution =
535 gdkdev->axes[k].resolution = 1000;
536 gdkdev->axes[k].xmin_value =
537 gdkdev->axes[k].min_value = -1000;
538 gdkdev->axes[k].xmax_value =
539 gdkdev->axes[k].max_value = 1000;
540 gdkdev->info.axes[k] = axis;
541 gdkdev->axis_for_use[axis] = k;
545 gdkdev->info.num_keys = 0;
546 gdkdev->info.keys = NULL;
548 (g_print ("device: %d (%d) %s axes: %d\n",
549 gdkdev->info.deviceid, cursorix,
551 gdkdev->info.num_axes),
552 g_print ("axes: X:%d, Y:%d, PRESSURE:%d, "
553 "XTILT:%d, YTILT:%d\n",
554 gdkdev->axis_for_use[GDK_AXIS_X],
555 gdkdev->axis_for_use[GDK_AXIS_Y],
556 gdkdev->axis_for_use[GDK_AXIS_PRESSURE],
557 gdkdev->axis_for_use[GDK_AXIS_XTILT],
558 gdkdev->axis_for_use[GDK_AXIS_YTILT])));
559 for (i = 0; i < gdkdev->info.num_axes; i++)
561 g_print ("...axis %d: %d--%d@%d (%d--%d@%d)\n",
563 gdkdev->axes[i].xmin_value,
564 gdkdev->axes[i].xmax_value,
565 gdkdev->axes[i].xresolution,
566 gdkdev->axes[i].min_value,
567 gdkdev->axes[i].max_value,
568 gdkdev->axes[i].resolution));
569 gdk_input_devices = g_list_append (gdk_input_devices,
574 #endif /* HAVE_WINTAB */
576 if (deviceid_counter > 0)
579 gdk_input_vtable.set_mode = gdk_input_win32_set_mode;
580 gdk_input_vtable.set_axes = NULL;
581 gdk_input_vtable.set_key = NULL;
582 gdk_input_vtable.motion_events = NULL;
583 gdk_input_vtable.get_pointer = gdk_input_win32_get_pointer;
584 gdk_input_vtable.grab_pointer = gdk_input_win32_grab_pointer;
585 gdk_input_vtable.ungrab_pointer = gdk_input_win32_ungrab_pointer;
586 gdk_input_vtable.configure_event = gdk_input_win32_configure_event;
587 gdk_input_vtable.enter_event = gdk_input_win32_enter_event;
588 gdk_input_vtable.other_event = gdk_input_win32_other_event;
589 gdk_input_vtable.enable_window = gdk_input_win32_enable_window;
590 gdk_input_vtable.disable_window = gdk_input_win32_disable_window;
592 gdk_input_root_width = gdk_screen_width ();
593 gdk_input_root_height = gdk_screen_height ();
594 gdk_input_ignore_core = FALSE;
596 g_assert_not_reached ();
601 gdk_input_vtable.set_mode = NULL;
602 gdk_input_vtable.set_axes = NULL;
603 gdk_input_vtable.set_key = NULL;
604 gdk_input_vtable.motion_events = NULL;
605 gdk_input_vtable.get_pointer = gdk_input_none_get_pointer;
606 gdk_input_vtable.grab_pointer = NULL;
607 gdk_input_vtable.ungrab_pointer = NULL;
608 gdk_input_vtable.configure_event = NULL;
609 gdk_input_vtable.enter_event = NULL;
610 gdk_input_vtable.other_event = NULL;
611 gdk_input_vtable.enable_window = NULL;
612 gdk_input_vtable.disable_window = NULL;
613 gdk_input_ignore_core = FALSE;
616 gdk_input_devices = g_list_append (gdk_input_devices, &gdk_input_core_info);
620 gdk_input_set_mode (guint32 deviceid,
623 if (deviceid == GDK_CORE_POINTER)
626 if (gdk_input_vtable.set_mode)
627 return gdk_input_vtable.set_mode (deviceid, mode);
633 gdk_input_set_axes (guint32 deviceid,
637 GdkDevicePrivate *gdkdev = gdk_input_find_device (deviceid);
638 g_return_if_fail (gdkdev != NULL);
640 if (deviceid == GDK_CORE_POINTER)
643 for (i = GDK_AXIS_IGNORE; i < GDK_AXIS_LAST; i++)
645 gdkdev->axis_for_use[i] = -1;
648 for (i = 0; i < gdkdev->info.num_axes; i++)
650 gdkdev->info.axes[i] = axes[i];
651 gdkdev->axis_for_use[axes[i]] = i;
656 gdk_input_none_get_pointer (GdkWindow *window,
663 GdkModifierType *mask)
667 gdk_window_get_pointer (window, &x_int, &y_int, mask);
684 gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
685 GdkInputWindow *input_window,
693 GdkWindowPrivate *window_private;
694 gint x_axis, y_axis, pressure_axis, xtilt_axis, ytilt_axis;
695 gdouble device_width, device_height;
696 gdouble x_offset, y_offset, x_scale, y_scale;
698 window_private = (GdkWindowPrivate *) input_window->window;
700 x_axis = gdkdev->axis_for_use[GDK_AXIS_X];
701 y_axis = gdkdev->axis_for_use[GDK_AXIS_Y];
702 pressure_axis = gdkdev->axis_for_use[GDK_AXIS_PRESSURE];
703 xtilt_axis = gdkdev->axis_for_use[GDK_AXIS_XTILT];
704 ytilt_axis = gdkdev->axis_for_use[GDK_AXIS_YTILT];
706 device_width = gdkdev->axes[x_axis].max_value -
707 gdkdev->axes[x_axis].min_value;
708 device_height = gdkdev->axes[y_axis].max_value -
709 gdkdev->axes[y_axis].min_value;
711 if (gdkdev->info.mode == GDK_MODE_SCREEN)
713 x_scale = gdk_input_root_width / device_width;
714 y_scale = gdk_input_root_height / device_height;
716 x_offset = -input_window->root_x;
717 y_offset = -input_window->root_y;
719 else /* GDK_MODE_WINDOW */
721 double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
722 (device_width*gdkdev->axes[x_axis].resolution);
724 if (device_aspect * window_private->width >= window_private->height)
726 /* device taller than window */
727 x_scale = window_private->width / device_width;
728 y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
729 / gdkdev->axes[y_axis].resolution;
732 y_offset = -(device_height * y_scale -
733 window_private->height)/2;
737 /* window taller than device */
738 y_scale = window_private->height / device_height;
739 x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
740 / gdkdev->axes[x_axis].resolution;
743 x_offset = -(device_width * x_scale - window_private->width)/2;
748 *x = x_offset + x_scale*axis_data[x_axis];
750 *y = y_offset + y_scale*axis_data[y_axis];
754 if (pressure_axis != -1)
755 *pressure = ((double)axis_data[pressure_axis]
756 - gdkdev->axes[pressure_axis].min_value)
757 / (gdkdev->axes[pressure_axis].max_value
758 - gdkdev->axes[pressure_axis].min_value);
765 if (xtilt_axis != -1)
767 *xtilt = 2. * (double)(axis_data[xtilt_axis] -
768 (gdkdev->axes[xtilt_axis].min_value +
769 gdkdev->axes[xtilt_axis].max_value)/2) /
770 (gdkdev->axes[xtilt_axis].max_value -
771 gdkdev->axes[xtilt_axis].min_value);
779 if (ytilt_axis != -1)
781 *ytilt = 2. * (double)(axis_data[ytilt_axis] -
782 (gdkdev->axes[ytilt_axis].min_value +
783 gdkdev->axes[ytilt_axis].max_value)/2) /
784 (gdkdev->axes[ytilt_axis].max_value -
785 gdkdev->axes[ytilt_axis].min_value);
793 gdk_input_win32_get_pointer (GdkWindow *window,
800 GdkModifierType *mask)
802 GdkDevicePrivate *gdkdev;
803 GdkInputWindow *input_window;
807 if (deviceid == GDK_CORE_POINTER)
809 gdk_window_get_pointer (window, &x_int, &y_int, mask);
824 gdk_window_get_pointer (window, NULL, NULL, mask);
826 gdkdev = gdk_input_find_device (deviceid);
827 g_return_if_fail (gdkdev != NULL);
829 input_window = gdk_input_window_find (window);
830 g_return_if_fail (input_window != NULL);
832 gdk_input_translate_coordinates (gdkdev, input_window,
833 gdkdev->last_axis_data,
839 *mask |= ((gdkdev->last_buttons & 0x1F) << 8);
845 gdk_input_get_root_relative_geometry (HWND w,
851 GetWindowRect (w, &rect);
860 gdk_input_win32_set_mode (guint32 deviceid,
864 GdkDevicePrivate *gdkdev;
865 GdkInputMode old_mode;
866 GdkInputWindow *input_window;
868 if (deviceid == GDK_CORE_POINTER)
871 gdkdev = gdk_input_find_device (deviceid);
872 g_return_val_if_fail (gdkdev != NULL, FALSE);
873 old_mode = gdkdev->info.mode;
875 if (old_mode == mode)
878 gdkdev->info.mode = mode;
880 if (mode == GDK_MODE_WINDOW)
882 gdkdev->info.has_cursor = FALSE;
883 for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
885 input_window = (GdkInputWindow *)tmp_list->data;
886 if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
887 gdk_input_win32_enable_window (input_window->window, gdkdev);
889 if (old_mode != GDK_MODE_DISABLED)
890 gdk_input_win32_disable_window (input_window->window, gdkdev);
893 else if (mode == GDK_MODE_SCREEN)
895 gdkdev->info.has_cursor = TRUE;
896 for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
897 gdk_input_win32_enable_window (((GdkInputWindow *)tmp_list->data)->window,
900 else /* mode == GDK_MODE_DISABLED */
902 for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
904 input_window = (GdkInputWindow *)tmp_list->data;
905 if (old_mode != GDK_MODE_WINDOW ||
906 input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
907 gdk_input_win32_disable_window (input_window->window, gdkdev);
915 gdk_input_win32_configure_event (GdkEventConfigure *event,
918 GdkInputWindow *input_window;
921 input_window = gdk_input_window_find (window);
922 g_return_if_fail (window != NULL);
924 gdk_input_get_root_relative_geometry
925 ((((GdkWindowPrivate*) window)->xwindow), &root_x, &root_y);
927 input_window->root_x = root_x;
928 input_window->root_y = root_y;
932 gdk_input_win32_enter_event (GdkEventCrossing *event,
935 GdkInputWindow *input_window;
938 input_window = gdk_input_window_find (window);
939 g_return_if_fail (window != NULL);
941 gdk_input_get_root_relative_geometry
942 ((((GdkWindowPrivate*) window)->xwindow), &root_x, &root_y);
944 input_window->root_x = root_x;
945 input_window->root_y = root_y;
949 decode_tilt (gint *axis_data,
953 /* As I don't have a tilt-sensing tablet,
954 * I cannot test this code.
959 az = TWOPI * packet->pkOrientation.orAzimuth /
960 (axes[0].axResolution / 65536.);
961 el = TWOPI * packet->pkOrientation.orAltitude /
962 (axes[1].axResolution / 65536.);
965 axis_data[0] = cos (az) * cos (el) * 1000;
967 axis_data[1] = sin (az) * cos (el) * 1000;
970 static GdkDevicePrivate *
971 gdk_input_find_dev_from_ctx (HCTX hctx,
974 GList *tmp_list = gdk_input_devices;
975 GdkDevicePrivate *gdkdev;
979 gdkdev = (GdkDevicePrivate *) (tmp_list->data);
980 if (gdkdev->hctx == hctx && gdkdev->cursor == cursor)
982 tmp_list = tmp_list->next;
987 gdk_input_win32_other_event (GdkEvent *event,
990 GdkWindow *current_window;
991 GdkInputWindow *input_window;
993 GdkWindowPrivate *window_private;
994 GdkDevicePrivate *gdkdev;
995 GdkEventMask masktest;
1002 if (event->any.window != wintab_window)
1003 g_warning ("gdk_input_win32_other_event: not wintab_window?");
1006 window = gdk_window_at_pointer (&x, &y);
1008 window = (GdkWindow *) &gdk_root_parent;
1010 gdk_window_ref (window);
1012 window_private = (GdkWindowPrivate *) window;
1014 GDK_NOTE (EVENTS, g_print ("gdk_input_win32_other_event: window=%#x (%d,%d)\n", window_private->xwindow, x, y));
1017 /* ??? This code is pretty bogus */
1018 current_window = gdk_window_lookup (GetActiveWindow ());
1019 if (current_window == NULL)
1022 input_window = gdk_input_window_find_within (current_window);
1023 if (input_window == NULL)
1027 if (xevent->message == WT_PACKET)
1029 if (!WTPacket ((HCTX) xevent->lParam, xevent->wParam, &packet))
1033 switch (xevent->message)
1036 if (window_private == &gdk_root_parent)
1038 GDK_NOTE (EVENTS, g_print ("...is root\n"));
1042 if ((gdkdev = gdk_input_find_dev_from_ctx ((HCTX) xevent->lParam,
1043 packet.pkCursor)) == NULL)
1046 if (gdkdev->info.mode == GDK_MODE_DISABLED)
1050 if (gdkdev->pktdata & PK_X)
1051 gdkdev->last_axis_data[k++] = packet.pkX;
1052 if (gdkdev->pktdata & PK_Y)
1053 gdkdev->last_axis_data[k++] = packet.pkY;
1054 if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
1055 gdkdev->last_axis_data[k++] = packet.pkNormalPressure;
1056 if (gdkdev->pktdata & PK_ORIENTATION)
1058 decode_tilt (gdkdev->last_axis_data + k,
1059 gdkdev->orientation_axes, &packet);
1063 g_assert (k == gdkdev->info.num_axes);
1065 if (HIWORD (packet.pkButtons) != TBN_NONE)
1067 /* Gdk buttons are numbered 1.. */
1068 event->button.button = 1 + LOWORD (packet.pkButtons);
1070 if (HIWORD (packet.pkButtons) == TBN_UP)
1072 event->any.type = GDK_BUTTON_RELEASE;
1073 masktest = GDK_BUTTON_RELEASE_MASK;
1074 gdkdev->button_state &= ~(1 << LOWORD (packet.pkButtons));
1078 event->any.type = GDK_BUTTON_PRESS;
1079 masktest = GDK_BUTTON_PRESS_MASK;
1080 gdkdev->button_state |= 1 << LOWORD (packet.pkButtons);
1085 event->any.type = GDK_MOTION_NOTIFY;
1086 masktest = GDK_POINTER_MOTION_MASK;
1087 if (gdkdev->button_state & (1 << 0))
1088 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK;
1089 if (gdkdev->button_state & (1 << 1))
1090 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK;
1091 if (gdkdev->button_state & (1 << 2))
1092 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK;
1095 /* Now we can check if the window wants the event, and
1096 * propagate if necessary.
1099 if (!window_private->extension_events_selected
1100 || !(window_private->extension_events & masktest))
1102 GDK_NOTE (EVENTS, g_print ("...not selected\n"));
1104 if (window_private->parent == (GdkWindow *) &gdk_root_parent)
1109 ClientToScreen (window_private->xwindow, &pt);
1110 gdk_window_unref (window);
1111 window = window_private->parent;
1112 gdk_window_ref (window);
1113 window_private = (GdkWindowPrivate *) window;
1114 ScreenToClient (window_private->xwindow, &pt);
1117 GDK_NOTE (EVENTS, g_print ("...propagating to %#x, (%d,%d)\n", window_private->xwindow, x, y));
1121 input_window = gdk_input_window_find (window);
1123 g_assert (input_window != NULL);
1125 if (gdkdev->info.mode == GDK_MODE_WINDOW
1126 && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
1129 event->any.window = window;
1131 if (event->any.type == GDK_BUTTON_PRESS
1132 || event->any.type == GDK_BUTTON_RELEASE)
1134 event->button.time = xevent->time;
1135 event->button.source = gdkdev->info.source;
1136 last_moved_cursor_id =
1137 event->button.deviceid = gdkdev->info.deviceid;
1141 /* Buttons 1 to 3 will come in as WM_[LMR]BUTTON{DOWN,UP} */
1142 if (event->button.button <= 3)
1146 gdk_input_translate_coordinates (gdkdev, input_window,
1147 gdkdev->last_axis_data,
1148 &event->button.x, &event->button.y,
1149 &event->button.pressure,
1150 &event->button.xtilt,
1151 &event->button.ytilt);
1153 event->button.state = ((gdkdev->button_state << 8)
1154 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1155 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1156 | GDK_BUTTON5_MASK));
1157 GDK_NOTE (EVENTS, g_print ("WINTAB button %s: %d %d %g,%g %g %g,%g\n",
1158 (event->button.type == GDK_BUTTON_PRESS ?
1159 "press" : "release"),
1160 event->button.deviceid,
1161 event->button.button,
1162 event->button.x, event->button.y,
1163 event->button.pressure,
1164 event->button.xtilt, event->button.ytilt));
1168 event->motion.time = xevent->time;
1169 last_moved_cursor_id =
1170 event->motion.deviceid = gdkdev->info.deviceid;
1171 event->motion.is_hint = FALSE;
1172 event->motion.source = gdkdev->info.source;
1174 gdk_input_translate_coordinates (gdkdev, input_window,
1175 gdkdev->last_axis_data,
1176 &event->motion.x, &event->motion.y,
1177 &event->motion.pressure,
1178 &event->motion.xtilt,
1179 &event->motion.ytilt);
1181 event->motion.state = ((gdkdev->button_state << 8)
1182 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1183 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1184 | GDK_BUTTON5_MASK));
1186 GDK_NOTE (EVENTS, g_print ("WINTAB motion: %d %g,%g %g %g,%g\n",
1187 event->motion.deviceid,
1188 event->motion.x, event->motion.y,
1189 event->motion.pressure,
1190 event->motion.xtilt, event->motion.ytilt));
1192 /* Check for missing release or press events for the normal
1193 * pressure button. At least on my ArtPadII I sometimes miss a
1196 if ((gdkdev->pktdata & PK_NORMAL_PRESSURE
1197 && (event->motion.state & GDK_BUTTON1_MASK)
1198 && packet.pkNormalPressure <= MAX (0, gdkdev->npbtnmarks[0] - 2))
1199 || (gdkdev->pktdata & PK_NORMAL_PRESSURE
1200 && !(event->motion.state & GDK_BUTTON1_MASK)
1201 && packet.pkNormalPressure > gdkdev->npbtnmarks[1] + 2))
1203 GdkEvent *event2 = gdk_event_copy (event);
1204 if (event->motion.state & GDK_BUTTON1_MASK)
1206 event2->button.type = GDK_BUTTON_RELEASE;
1207 gdkdev->button_state &= ~1;
1211 event2->button.type = GDK_BUTTON_PRESS;
1212 gdkdev->button_state |= 1;
1214 event2->button.state = ((gdkdev->button_state << 8)
1215 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1216 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1217 | GDK_BUTTON5_MASK));
1218 event2->button.button = 1;
1219 GDK_NOTE (EVENTS, g_print ("WINTAB synthesized button %s: %d %d %g,%g %g\n",
1220 (event2->button.type == GDK_BUTTON_PRESS ?
1221 "press" : "release"),
1222 event2->button.deviceid,
1223 event2->button.button,
1224 event2->button.x, event2->button.y,
1225 event2->button.pressure));
1226 gdk_event_queue_append (event2);
1232 if (LOWORD (xevent->lParam) == 0)
1234 event->proximity.type = GDK_PROXIMITY_OUT;
1235 gdk_input_ignore_core = FALSE;
1239 event->proximity.type = GDK_PROXIMITY_IN;
1240 gdk_input_ignore_core = TRUE;
1242 event->proximity.time = xevent->time;
1243 event->proximity.source = GDK_SOURCE_PEN;
1244 event->proximity.deviceid = last_moved_cursor_id;
1246 GDK_NOTE (EVENTS, g_print ("WINTAB proximity %s: %d\n",
1247 (event->proximity.type == GDK_PROXIMITY_IN ?
1249 event->proximity.deviceid));
1256 gdk_input_win32_enable_window (GdkWindow *window,
1257 GdkDevicePrivate *gdkdev)
1259 GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
1261 window_private->extension_events_selected = TRUE;
1266 gdk_input_win32_disable_window (GdkWindow *window,
1267 GdkDevicePrivate *gdkdev)
1269 GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
1271 window_private->extension_events_selected = FALSE;
1276 gdk_input_win32_grab_pointer (GdkWindow *window,
1278 GdkEventMask event_mask,
1279 GdkWindow *confine_to,
1282 GdkInputWindow *input_window, *new_window;
1283 gboolean need_ungrab;
1284 GdkDevicePrivate *gdkdev;
1288 tmp_list = gdk_input_windows;
1290 need_ungrab = FALSE;
1292 GDK_NOTE (MISC, g_print ("gdk_input_win32_grab_pointer: %#x %d %#x\n",
1293 ((GdkWindowPrivate *) window)->xwindow,
1296 ((GdkWindowPrivate *) confine_to)->xwindow :
1301 input_window = (GdkInputWindow *)tmp_list->data;
1303 if (input_window->window == window)
1304 new_window = input_window;
1305 else if (input_window->grabbed)
1307 input_window->grabbed = FALSE;
1311 tmp_list = tmp_list->next;
1316 new_window->grabbed = TRUE;
1318 tmp_list = gdk_input_devices;
1321 gdkdev = (GdkDevicePrivate *)tmp_list->data;
1322 if (gdkdev->info.deviceid != GDK_CORE_POINTER)
1326 gdk_input_find_events (window, gdkdev,
1328 event_classes, &num_classes);
1329 result = XGrabDevice (GDK_DISPLAY(), gdkdev->xdevice,
1330 GDK_WINDOW_XWINDOW (window),
1331 owner_events, num_classes, event_classes,
1332 GrabModeAsync, GrabModeAsync, time);
1334 /* FIXME: if failure occurs on something other than the first
1335 device, things will be badly inconsistent */
1336 if (result != Success)
1340 tmp_list = tmp_list->next;
1345 tmp_list = gdk_input_devices;
1348 gdkdev = (GdkDevicePrivate *)tmp_list->data;
1349 if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
1350 ((gdkdev->button_state != 0) || need_ungrab))
1354 XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1356 gdkdev->button_state = 0;
1359 tmp_list = tmp_list->next;
1368 gdk_input_win32_ungrab_pointer (guint32 time)
1370 GdkInputWindow *input_window;
1371 GdkDevicePrivate *gdkdev;
1374 GDK_NOTE (MISC, g_print ("gdk_input_win32_ungrab_pointer\n"));
1376 tmp_list = gdk_input_windows;
1379 input_window = (GdkInputWindow *)tmp_list->data;
1380 if (input_window->grabbed)
1382 tmp_list = tmp_list->next;
1385 if (tmp_list) /* we found a grabbed window */
1387 input_window->grabbed = FALSE;
1389 tmp_list = gdk_input_devices;
1392 gdkdev = (GdkDevicePrivate *)tmp_list->data;
1395 if (gdkdev->info.deviceid != GDK_CORE_POINTER && gdkdev->xdevice)
1396 XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1398 tmp_list = tmp_list->next;
1403 #endif /* HAVE_WINTAB */
1406 gdk_input_list_devices (void)
1408 return gdk_input_devices;
1412 gdk_input_set_source (guint32 deviceid,
1413 GdkInputSource source)
1415 GdkDevicePrivate *gdkdev = gdk_input_find_device (deviceid);
1416 g_return_if_fail (gdkdev != NULL);
1418 gdkdev->info.source = source;
1421 void gdk_input_set_key (guint32 deviceid,
1424 GdkModifierType modifiers)
1426 if (deviceid != GDK_CORE_POINTER && gdk_input_vtable.set_key)
1427 gdk_input_vtable.set_key (deviceid, index, keyval, modifiers);
1431 gdk_input_motion_events (GdkWindow *window,
1435 gint *nevents_return)
1437 GdkWindowPrivate *window_private;
1438 GdkTimeCoord *coords;
1441 g_return_val_if_fail (window != NULL, NULL);
1442 window_private = (GdkWindowPrivate *) window;
1443 if (window_private->destroyed)
1446 *nevents_return = 0;
1447 return NULL; /* ??? */
1451 gdk_input_enable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
1453 if (gdk_input_vtable.enable_window)
1454 return gdk_input_vtable.enable_window (window, gdkdev);
1460 gdk_input_disable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
1462 if (gdk_input_vtable.disable_window)
1463 return gdk_input_vtable.disable_window(window,gdkdev);
1469 static GdkInputWindow *
1470 gdk_input_window_find (GdkWindow *window)
1474 for (tmp_list=gdk_input_windows; tmp_list; tmp_list=tmp_list->next)
1475 if (((GdkInputWindow *)(tmp_list->data))->window == window)
1476 return (GdkInputWindow *)(tmp_list->data);
1478 return NULL; /* Not found */
1483 static GdkInputWindow *
1484 gdk_input_window_find_within (GdkWindow *window)
1487 GdkWindowPrivate *window_private;
1488 GdkWindowPrivate *tmp_private;
1489 GdkInputWindow *candidate = NULL;
1491 window_private = (GdkWindowPrivate *) window;
1493 for (tmp_list=gdk_input_windows; tmp_list; tmp_list=tmp_list->next)
1495 (GdkWindowPrivate *) tmp_private =
1496 (GdkWindowPrivate *) (((GdkInputWindow *)(tmp_list->data))->window);
1497 if (tmp_private == window_private
1498 || IsChild (window_private->xwindow, tmp_private->xwindow))
1501 return NULL; /* Multiple hits */
1502 candidate = (GdkInputWindow *)(tmp_list->data);
1511 /* FIXME: this routine currently needs to be called between creation
1512 and the corresponding configure event (because it doesn't get the
1513 root_relative_geometry). This should work with
1514 gtk_window_set_extension_events, but will likely fail in other
1518 gdk_input_set_extension_events (GdkWindow *window,
1520 GdkExtensionMode mode)
1522 GdkWindowPrivate *window_private;
1526 g_return_if_fail (window != NULL);
1527 window_private = (GdkWindowPrivate *) window;
1528 if (window_private->destroyed)
1531 if (mode == GDK_EXTENSION_EVENTS_NONE)
1536 iw = g_new (GdkInputWindow,1);
1538 iw->window = window;
1541 iw->grabbed = FALSE;
1543 gdk_input_windows = g_list_append (gdk_input_windows, iw);
1544 window_private->extension_events = mask;
1546 /* Add enter window events to the event mask */
1547 gdk_window_set_events (window,
1548 gdk_window_get_events (window) |
1549 GDK_ENTER_NOTIFY_MASK);
1553 iw = gdk_input_window_find (window);
1556 gdk_input_windows = g_list_remove (gdk_input_windows, iw);
1560 window_private->extension_events = 0;
1563 for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
1565 GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
1567 if (gdkdev->info.deviceid != GDK_CORE_POINTER)
1569 if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
1570 && (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL))
1571 gdk_input_enable_window (window, gdkdev);
1573 gdk_input_disable_window (window, gdkdev);
1579 gdk_input_window_destroy (GdkWindow *window)
1581 GdkInputWindow *input_window;
1583 input_window = gdk_input_window_find (window);
1584 g_return_if_fail (input_window != NULL);
1586 gdk_input_windows = g_list_remove (gdk_input_windows,input_window);
1587 g_free (input_window);
1591 gdk_input_exit (void)
1595 GdkDevicePrivate *gdkdev;
1597 for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
1599 gdkdev = (GdkDevicePrivate *)(tmp_list->data);
1600 if (gdkdev->info.deviceid != GDK_CORE_POINTER)
1602 gdk_input_win32_set_mode (gdkdev->info.deviceid, GDK_MODE_DISABLED);
1603 g_free (gdkdev->info.name);
1604 g_free (gdkdev->last_axis_data);
1605 g_free (gdkdev->info.axes);
1606 g_free (gdkdev->info.keys);
1607 g_free (gdkdev->axes);
1612 g_list_free (gdk_input_devices);
1614 for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
1616 g_free (tmp_list->data);
1618 g_list_free (gdk_input_windows);
1619 gdk_input_windows = NULL;
1621 gdk_window_unref (wintab_window);
1622 wintab_window = NULL;
1625 for (tmp_list = wintab_contexts; tmp_list; tmp_list = tmp_list->next)
1627 HCTX *hctx = (HCTX *) tmp_list->data;
1631 /* For some reason WTEnable and/or WTClose tend to crash here.
1632 * Protect with __try/__except to avoid a message box.
1633 * When compiling with gcc, we cannot use __try/__except, so
1634 * don't call WTClose. I think this means that we'll
1635 * eventually run out of Wintab contexts, sigh.
1639 WTEnable (*hctx, FALSE);
1641 result = WTClose (*hctx);
1643 __except (/* GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? */
1644 EXCEPTION_EXECUTE_HANDLER /*:
1645 EXCEPTION_CONTINUE_SEARCH */) {
1649 g_warning ("gdk_input_exit: Closing Wintab context %#x failed", *hctx);
1650 #endif /* _MSC_VER */
1654 g_list_free (wintab_contexts);
1655 wintab_contexts = NULL;
1659 static GdkDevicePrivate *
1660 gdk_input_find_device (guint32 id)
1662 GList *tmp_list = gdk_input_devices;
1663 GdkDevicePrivate *gdkdev;
1667 gdkdev = (GdkDevicePrivate *) (tmp_list->data);
1668 if (gdkdev->info.deviceid == id)
1670 tmp_list = tmp_list->next;
1676 gdk_input_window_get_pointer (GdkWindow *window,
1683 GdkModifierType *mask)
1685 if (gdk_input_vtable.get_pointer)
1686 gdk_input_vtable.get_pointer (window, deviceid, x, y, pressure,
1687 xtilt, ytilt, mask);