1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 * Copyright (C) 1998-2002 Tor Lillqvist
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser 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-2000. 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 "gdkinternals.h"
37 #include "gdkprivate-win32.h"
38 #include "gdkinput-win32.h"
42 #define PACKETDATA (PK_CONTEXT | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION)
43 #define PACKETMODE (PK_BUTTONS)
46 /* If USE_SYSCONTEXT is on, we open the Wintab device (hmm, what if
47 * there are several?) as a system pointing device, i.e. it controls
48 * the normal Windows cursor. This seems much more natural.
50 #define USE_SYSCONTEXT 1 /* The code for the other choice is not
54 #define DEBUG_WINTAB 1 /* Verbose debug messages enabled */
58 #if defined(HAVE_WINTAB) || defined(HAVE_WHATEVER_OTHER)
59 #define HAVE_SOME_XINPUT
62 #define TWOPI (2.*G_PI)
64 /* Forward declarations */
67 static GdkInputWindow *gdk_input_window_find_within (GdkWindow *window);
72 static GdkDevicePrivate *gdk_input_find_dev_from_ctx (HCTX hctx,
74 static GList *wintab_contexts = NULL;
76 static GdkWindow *wintab_window = NULL;
78 #endif /* HAVE_WINTAB */
80 #ifdef HAVE_SOME_XINPUT
82 static GdkWindow *x_grab_window = NULL; /* Window that currently holds
83 * the extended inputs grab
85 static GdkEventMask x_grab_mask;
86 static gboolean x_grab_owner_events;
88 #endif /* HAVE_SOME_XINPUT */
92 static GdkDevicePrivate *
93 gdk_input_find_dev_from_ctx (HCTX hctx,
96 GList *tmp_list = _gdk_input_devices;
97 GdkDevicePrivate *gdkdev;
101 gdkdev = (GdkDevicePrivate *) (tmp_list->data);
102 if (gdkdev->hctx == hctx && gdkdev->cursor == cursor)
104 tmp_list = tmp_list->next;
112 print_lc(LOGCONTEXT *lc)
114 g_print ("lcName = %s\n", lc->lcName);
115 g_print ("lcOptions =");
116 if (lc->lcOptions & CXO_SYSTEM) g_print (" CXO_SYSTEM");
117 if (lc->lcOptions & CXO_PEN) g_print (" CXO_PEN");
118 if (lc->lcOptions & CXO_MESSAGES) g_print (" CXO_MESSAGES");
119 if (lc->lcOptions & CXO_MARGIN) g_print (" CXO_MARGIN");
120 if (lc->lcOptions & CXO_MGNINSIDE) g_print (" CXO_MGNINSIDE");
121 if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
123 g_print ("lcStatus =");
124 if (lc->lcStatus & CXS_DISABLED) g_print (" CXS_DISABLED");
125 if (lc->lcStatus & CXS_OBSCURED) g_print (" CXS_OBSCURED");
126 if (lc->lcStatus & CXS_ONTOP) g_print (" CXS_ONTOP");
128 g_print ("lcLocks =");
129 if (lc->lcLocks & CXL_INSIZE) g_print (" CXL_INSIZE");
130 if (lc->lcLocks & CXL_INASPECT) g_print (" CXL_INASPECT");
131 if (lc->lcLocks & CXL_SENSITIVITY) g_print (" CXL_SENSITIVITY");
132 if (lc->lcLocks & CXL_MARGIN) g_print (" CXL_MARGIN");
134 g_print ("lcMsgBase = %#x, lcDevice = %#x, lcPktRate = %d\n",
135 lc->lcMsgBase, lc->lcDevice, lc->lcPktRate);
136 g_print ("lcPktData =");
137 if (lc->lcPktData & PK_CONTEXT) g_print (" PK_CONTEXT");
138 if (lc->lcPktData & PK_STATUS) g_print (" PK_STATUS");
139 if (lc->lcPktData & PK_TIME) g_print (" PK_TIME");
140 if (lc->lcPktData & PK_CHANGED) g_print (" PK_CHANGED");
141 if (lc->lcPktData & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
142 if (lc->lcPktData & PK_CURSOR) g_print (" PK_CURSOR");
143 if (lc->lcPktData & PK_BUTTONS) g_print (" PK_BUTTONS");
144 if (lc->lcPktData & PK_X) g_print (" PK_X");
145 if (lc->lcPktData & PK_Y) g_print (" PK_Y");
146 if (lc->lcPktData & PK_Z) g_print (" PK_Z");
147 if (lc->lcPktData & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
148 if (lc->lcPktData & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
149 if (lc->lcPktData & PK_ORIENTATION) g_print (" PK_ORIENTATION");
150 if (lc->lcPktData & PK_ROTATION) g_print (" PK_ROTATION");
152 g_print ("lcPktMode =");
153 if (lc->lcPktMode & PK_CONTEXT) g_print (" PK_CONTEXT");
154 if (lc->lcPktMode & PK_STATUS) g_print (" PK_STATUS");
155 if (lc->lcPktMode & PK_TIME) g_print (" PK_TIME");
156 if (lc->lcPktMode & PK_CHANGED) g_print (" PK_CHANGED");
157 if (lc->lcPktMode & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
158 if (lc->lcPktMode & PK_CURSOR) g_print (" PK_CURSOR");
159 if (lc->lcPktMode & PK_BUTTONS) g_print (" PK_BUTTONS");
160 if (lc->lcPktMode & PK_X) g_print (" PK_X");
161 if (lc->lcPktMode & PK_Y) g_print (" PK_Y");
162 if (lc->lcPktMode & PK_Z) g_print (" PK_Z");
163 if (lc->lcPktMode & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
164 if (lc->lcPktMode & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
165 if (lc->lcPktMode & PK_ORIENTATION) g_print (" PK_ORIENTATION");
166 if (lc->lcPktMode & PK_ROTATION) g_print (" PK_ROTATION");
168 g_print ("lcMoveMask =");
169 if (lc->lcMoveMask & PK_CONTEXT) g_print (" PK_CONTEXT");
170 if (lc->lcMoveMask & PK_STATUS) g_print (" PK_STATUS");
171 if (lc->lcMoveMask & PK_TIME) g_print (" PK_TIME");
172 if (lc->lcMoveMask & PK_CHANGED) g_print (" PK_CHANGED");
173 if (lc->lcMoveMask & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
174 if (lc->lcMoveMask & PK_CURSOR) g_print (" PK_CURSOR");
175 if (lc->lcMoveMask & PK_BUTTONS) g_print (" PK_BUTTONS");
176 if (lc->lcMoveMask & PK_X) g_print (" PK_X");
177 if (lc->lcMoveMask & PK_Y) g_print (" PK_Y");
178 if (lc->lcMoveMask & PK_Z) g_print (" PK_Z");
179 if (lc->lcMoveMask & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
180 if (lc->lcMoveMask & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
181 if (lc->lcMoveMask & PK_ORIENTATION) g_print (" PK_ORIENTATION");
182 if (lc->lcMoveMask & PK_ROTATION) g_print (" PK_ROTATION");
184 g_print ("lcBtnDnMask = %#x, lcBtnUpMask = %#x\n",
185 (guint) lc->lcBtnDnMask, (guint) lc->lcBtnUpMask);
186 g_print ("lcInOrgX = %ld, lcInOrgY = %ld, lcInOrgZ = %ld\n",
187 lc->lcInOrgX, lc->lcInOrgY, lc->lcInOrgZ);
188 g_print ("lcInExtX = %ld, lcInExtY = %ld, lcInExtZ = %ld\n",
189 lc->lcInExtX, lc->lcInExtY, lc->lcInExtZ);
190 g_print ("lcOutOrgX = %ld, lcOutOrgY = %ld, lcOutOrgZ = %ld\n",
191 lc->lcOutOrgX, lc->lcOutOrgY, lc->lcOutOrgZ);
192 g_print ("lcOutExtX = %ld, lcOutExtY = %ld, lcOutExtZ = %ld\n",
193 lc->lcOutExtX, lc->lcOutExtY, lc->lcOutExtZ);
194 g_print ("lcSensX = %g, lcSensY = %g, lcSensZ = %g\n",
195 lc->lcSensX / 65536., lc->lcSensY / 65536., lc->lcSensZ / 65536.);
196 g_print ("lcSysMode = %d\n", lc->lcSysMode);
197 g_print ("lcSysOrgX = %d, lcSysOrgY = %d\n",
198 lc->lcSysOrgX, lc->lcSysOrgY);
199 g_print ("lcSysExtX = %d, lcSysExtY = %d\n",
200 lc->lcSysExtX, lc->lcSysExtY);
201 g_print ("lcSysSensX = %g, lcSysSensY = %g\n",
202 lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.);
208 _gdk_input_wintab_init_check (void)
210 static gboolean wintab_initialized = FALSE;
211 GdkDevicePrivate *gdkdev;
214 LOGCONTEXT defcontext;
216 UINT ndevices, ncursors, ncsrtypes, firstcsr, hardware;
218 AXIS axis_x, axis_y, axis_npressure, axis_or[3];
221 char devname[100], csrname[100];
223 if (wintab_initialized)
226 wintab_initialized = TRUE;
228 wintab_contexts = NULL;
230 if (!_gdk_input_ignore_wintab &&
233 WTInfo (WTI_INTERFACE, IFC_SPECVERSION, &specversion);
234 GDK_NOTE (INPUT, g_print ("Wintab interface version %d.%d\n",
235 HIBYTE (specversion), LOBYTE (specversion)));
237 WTInfo (WTI_DEFSYSCTX, 0, &defcontext);
239 GDK_NOTE (INPUT, (g_print("DEFSYSCTX:\n"), print_lc(&defcontext)));
242 WTInfo (WTI_DEFCONTEXT, 0, &defcontext);
244 GDK_NOTE (INPUT, (g_print("DEFCONTEXT:\n"), print_lc(&defcontext)));
247 WTInfo (WTI_INTERFACE, IFC_NDEVICES, &ndevices);
248 WTInfo (WTI_INTERFACE, IFC_NCURSORS, &ncursors);
250 GDK_NOTE (INPUT, g_print ("NDEVICES: %d, NCURSORS: %d\n",
251 ndevices, ncursors));
253 /* Create a dummy window to receive wintab events */
254 wa.wclass = GDK_INPUT_OUTPUT;
255 wa.event_mask = GDK_ALL_EVENTS_MASK;
260 wa.window_type = GDK_WINDOW_TOPLEVEL;
261 if ((wintab_window = gdk_window_new (NULL, &wa, GDK_WA_X|GDK_WA_Y)) == NULL)
263 g_warning ("gdk_input_wintab_init: gdk_window_new failed");
266 g_object_ref (wintab_window);
268 for (devix = 0; devix < ndevices; devix++)
272 WTInfo (WTI_DEVICES + devix, DVC_NAME, devname);
274 WTInfo (WTI_DEVICES + devix, DVC_NCSRTYPES, &ncsrtypes);
275 WTInfo (WTI_DEVICES + devix, DVC_FIRSTCSR, &firstcsr);
276 WTInfo (WTI_DEVICES + devix, DVC_HARDWARE, &hardware);
277 WTInfo (WTI_DEVICES + devix, DVC_X, &axis_x);
278 WTInfo (WTI_DEVICES + devix, DVC_Y, &axis_y);
279 WTInfo (WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure);
280 WTInfo (WTI_DEVICES + devix, DVC_ORIENTATION, axis_or);
282 if (HIBYTE (specversion) > 1 || LOBYTE (specversion) >= 1)
284 WTInfo (WTI_DDCTXS + devix, CTX_NAME, lc.lcName);
285 WTInfo (WTI_DDCTXS + devix, CTX_OPTIONS, &lc.lcOptions);
286 lc.lcOptions |= CXO_MESSAGES;
288 lc.lcOptions |= CXO_SYSTEM;
291 WTInfo (WTI_DDCTXS + devix, CTX_LOCKS, &lc.lcLocks);
292 lc.lcMsgBase = WT_DEFBASE;
295 lc.lcPktData = PACKETDATA;
296 lc.lcPktMode = PK_BUTTONS; /* We want buttons in relative mode */
297 lc.lcMoveMask = PACKETDATA;
298 lc.lcBtnDnMask = lc.lcBtnUpMask = ~0;
299 WTInfo (WTI_DDCTXS + devix, CTX_INORGX, &lc.lcInOrgX);
300 WTInfo (WTI_DDCTXS + devix, CTX_INORGY, &lc.lcInOrgY);
301 WTInfo (WTI_DDCTXS + devix, CTX_INORGZ, &lc.lcInOrgZ);
302 WTInfo (WTI_DDCTXS + devix, CTX_INEXTX, &lc.lcInExtX);
303 WTInfo (WTI_DDCTXS + devix, CTX_INEXTY, &lc.lcInExtY);
304 WTInfo (WTI_DDCTXS + devix, CTX_INEXTZ, &lc.lcInExtZ);
305 lc.lcOutOrgX = axis_x.axMin;
306 lc.lcOutOrgY = axis_y.axMin;
307 lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
308 lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
309 lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
310 WTInfo (WTI_DDCTXS + devix, CTX_SENSX, &lc.lcSensX);
311 WTInfo (WTI_DDCTXS + devix, CTX_SENSY, &lc.lcSensY);
312 WTInfo (WTI_DDCTXS + devix, CTX_SENSZ, &lc.lcSensZ);
313 WTInfo (WTI_DDCTXS + devix, CTX_SYSMODE, &lc.lcSysMode);
314 WTInfo (WTI_DDCTXS + devix, CTX_SYSORGX, &lc.lcSysOrgX);
315 WTInfo (WTI_DDCTXS + devix, CTX_SYSORGY, &lc.lcSysOrgY);
316 WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTX, &lc.lcSysExtX);
317 WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTY, &lc.lcSysExtY);
318 WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSX, &lc.lcSysSensX);
319 WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSY, &lc.lcSysSensY);
324 lc.lcOptions |= CXO_MESSAGES;
325 lc.lcMsgBase = WT_DEFBASE;
327 lc.lcPktData = PACKETDATA;
328 lc.lcPktMode = PACKETMODE;
329 lc.lcMoveMask = PACKETDATA;
330 lc.lcBtnUpMask = lc.lcBtnDnMask = ~0;
332 lc.lcOutExtY = -lc.lcOutExtY; /* Y grows downward */
334 lc.lcOutOrgX = axis_x.axMin;
335 lc.lcOutOrgY = axis_y.axMin;
336 lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
337 lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
338 lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
342 GDK_NOTE (INPUT, (g_print("context for device %d:\n", devix),
345 hctx = g_new (HCTX, 1);
346 if ((*hctx = WTOpen (GDK_WINDOW_HWND (wintab_window), &lc, TRUE)) == NULL)
348 g_warning ("gdk_input_wintab_init: WTOpen failed");
351 GDK_NOTE (INPUT, g_print ("opened Wintab device %d %p\n",
354 wintab_contexts = g_list_append (wintab_contexts, hctx);
356 WTEnable (*hctx, TRUE);
358 WTOverlap (*hctx, TRUE);
361 GDK_NOTE (INPUT, (g_print("context for device %d after WTOpen:\n", devix),
364 /* Increase packet queue size to reduce the risk of lost packets */
365 /* According to the specs, if the function fails we must try again */
366 /* with a smaller queue size */
367 GDK_NOTE (INPUT, g_print("Attempting to increase queue size\n"));
368 for (i = 128; i >= 1; i >>= 1)
370 if (WTQueueSizeSet(*hctx, i))
372 GDK_NOTE (INPUT, g_print("Queue size set to %d\n", i));
377 GDK_NOTE (INPUT, g_print("Whoops, no queue size could be set\n"));
378 for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes; cursorix++)
381 WTInfo (WTI_CURSORS + cursorix, CSR_ACTIVE, &active);
384 gdkdev = g_object_new (GDK_TYPE_DEVICE, NULL);
385 WTInfo (WTI_CURSORS + cursorix, CSR_NAME, csrname);
386 gdkdev->info.name = g_strconcat (devname, " ", csrname, NULL);
387 gdkdev->info.source = GDK_SOURCE_PEN;
388 gdkdev->info.mode = GDK_MODE_SCREEN;
390 gdkdev->info.has_cursor = TRUE;
392 gdkdev->info.has_cursor = FALSE;
394 gdkdev->hctx = *hctx;
395 gdkdev->cursor = cursorix;
396 WTInfo (WTI_CURSORS + cursorix, CSR_PKTDATA, &gdkdev->pktdata);
397 gdkdev->info.num_axes = 0;
398 if (gdkdev->pktdata & PK_X)
399 gdkdev->info.num_axes++;
400 if (gdkdev->pktdata & PK_Y)
401 gdkdev->info.num_axes++;
402 if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
403 gdkdev->info.num_axes++;
404 /* The wintab driver for the Wacom ArtPad II reports
405 * PK_ORIENTATION in CSR_PKTDATA, but the tablet doesn't
406 * actually sense tilt. Catch this by noticing that the
407 * orientation axis's azimuth resolution is zero.
409 if ((gdkdev->pktdata & PK_ORIENTATION)
410 && axis_or[0].axResolution == 0)
411 gdkdev->pktdata &= ~PK_ORIENTATION;
413 if (gdkdev->pktdata & PK_ORIENTATION)
414 gdkdev->info.num_axes += 2; /* x and y tilt */
415 WTInfo (WTI_CURSORS + cursorix, CSR_NPBTNMARKS, &gdkdev->npbtnmarks);
416 gdkdev->info.axes = g_new (GdkDeviceAxis, gdkdev->info.num_axes);
417 gdkdev->axes = g_new (GdkAxisInfo, gdkdev->info.num_axes);
418 gdkdev->last_axis_data = g_new (gint, gdkdev->info.num_axes);
421 if (gdkdev->pktdata & PK_X)
423 gdkdev->axes[k].xresolution =
424 gdkdev->axes[k].resolution = axis_x.axResolution / 65535.;
425 gdkdev->axes[k].xmin_value =
426 gdkdev->axes[k].min_value = axis_x.axMin;
427 gdkdev->axes[k].xmax_value =
428 gdkdev->axes[k].max_value = axis_x.axMax;
429 gdkdev->info.axes[k].use = GDK_AXIS_X;
430 gdkdev->info.axes[k].min = axis_x.axMin;
431 gdkdev->info.axes[k].max = axis_x.axMax;
434 if (gdkdev->pktdata & PK_Y)
436 gdkdev->axes[k].xresolution =
437 gdkdev->axes[k].resolution = axis_y.axResolution / 65535.;
438 gdkdev->axes[k].xmin_value =
439 gdkdev->axes[k].min_value = axis_y.axMin;
440 gdkdev->axes[k].xmax_value =
441 gdkdev->axes[k].max_value = axis_y.axMax;
442 gdkdev->info.axes[k].use = GDK_AXIS_Y;
443 gdkdev->info.axes[k].min = axis_y.axMin;
444 gdkdev->info.axes[k].max = axis_y.axMax;
447 if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
449 gdkdev->axes[k].xresolution =
450 gdkdev->axes[k].resolution = axis_npressure.axResolution / 65535.;
451 gdkdev->axes[k].xmin_value =
452 gdkdev->axes[k].min_value = axis_npressure.axMin;
453 gdkdev->axes[k].xmax_value =
454 gdkdev->axes[k].max_value = axis_npressure.axMax;
455 gdkdev->info.axes[k].use = GDK_AXIS_PRESSURE;
456 /* GIMP seems to expect values in the range 0-1 */
457 gdkdev->info.axes[k].min = 0.0; /*axis_npressure.axMin;*/
458 gdkdev->info.axes[k].max = 1.0; /*axis_npressure.axMax;*/
461 if (gdkdev->pktdata & PK_ORIENTATION)
465 gdkdev->orientation_axes[0] = axis_or[0];
466 gdkdev->orientation_axes[1] = axis_or[1];
467 for (axis = GDK_AXIS_XTILT; axis <= GDK_AXIS_YTILT; axis++)
469 /* Wintab gives us aximuth and altitude, which
470 * we convert to x and y tilt in the -1000..1000 range
472 gdkdev->axes[k].xresolution =
473 gdkdev->axes[k].resolution = 1000;
474 gdkdev->axes[k].xmin_value =
475 gdkdev->axes[k].min_value = -1000;
476 gdkdev->axes[k].xmax_value =
477 gdkdev->axes[k].max_value = 1000;
478 gdkdev->info.axes[k].use = axis;
479 gdkdev->info.axes[k].min = -1000;
480 gdkdev->info.axes[k].max = 1000;
484 gdkdev->info.num_keys = 0;
485 gdkdev->info.keys = NULL;
487 g_print ("device: (%d) %s axes: %d\n",
490 gdkdev->info.num_axes));
491 for (i = 0; i < gdkdev->info.num_axes; i++)
493 g_print ("...axis %d: %d--%d@%d (%d--%d@%d)\n",
495 gdkdev->axes[i].xmin_value,
496 gdkdev->axes[i].xmax_value,
497 gdkdev->axes[i].xresolution,
498 gdkdev->axes[i].min_value,
499 gdkdev->axes[i].max_value,
500 gdkdev->axes[i].resolution));
501 _gdk_input_devices = g_list_append (_gdk_input_devices,
509 decode_tilt (gint *axis_data,
513 /* As I don't have a tilt-sensing tablet,
514 * I cannot test this code.
519 az = TWOPI * packet->pkOrientation.orAzimuth /
520 (axes[0].axResolution / 65536.);
521 el = TWOPI * packet->pkOrientation.orAltitude /
522 (axes[1].axResolution / 65536.);
525 axis_data[0] = cos (az) * cos (el) * 1000;
527 axis_data[1] = sin (az) * cos (el) * 1000;
532 static GdkInputWindow *
533 gdk_input_window_find_within (GdkWindow *window)
537 GdkInputWindow *candidate = NULL;
539 for (list = _gdk_input_windows; list != NULL; list = list->next)
541 tmpw = ((GdkInputWindow *) (tmp_list->data))->window;
543 || IsChild (GDK_WINDOW_HWND (window), GDK_WINDOW_HWND (tmpw)))
546 return NULL; /* Multiple hits */
547 candidate = (GdkInputWindow *) (list->data);
554 #endif /* USE_SYSCONTEXT */
556 #endif /* HAVE_WINTAB */
559 gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
560 GdkInputWindow *input_window,
566 GdkWindowImplWin32 *impl, *root_impl;
572 double device_width, device_height;
573 double x_offset, y_offset, x_scale, y_scale;
575 impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (input_window->window)->impl);
577 for (i=0; i<gdkdev->info.num_axes; i++)
579 switch (gdkdev->info.axes[i].use)
592 device_width = gdkdev->axes[x_axis].max_value -
593 gdkdev->axes[x_axis].min_value;
594 device_height = gdkdev->axes[y_axis].max_value -
595 gdkdev->axes[y_axis].min_value;
597 if (gdkdev->info.mode == GDK_MODE_SCREEN)
599 root_impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (_gdk_parent_root)->impl);
600 x_scale = root_impl->width / device_width;
601 y_scale = root_impl->height / device_height;
603 x_offset = - input_window->root_x;
604 y_offset = - input_window->root_y;
606 else /* GDK_MODE_WINDOW */
608 double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
609 (device_width*gdkdev->axes[x_axis].resolution);
611 if (device_aspect * impl->width >= impl->height)
613 /* device taller than window */
614 x_scale = impl->width / device_width;
615 y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
616 / gdkdev->axes[y_axis].resolution;
619 y_offset = -(device_height * y_scale -
624 /* window taller than device */
625 y_scale = impl->height / device_height;
626 x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
627 / gdkdev->axes[x_axis].resolution;
630 x_offset = - (device_width * x_scale - impl->width)/2;
634 for (i=0; i<gdkdev->info.num_axes; i++)
636 switch (gdkdev->info.axes[i].use)
639 axis_out[i] = x_offset + x_scale*axis_data[x_axis];
641 *x_out = axis_out[i];
644 axis_out[i] = y_offset + y_scale*axis_data[y_axis];
646 *y_out = axis_out[i];
650 (gdkdev->info.axes[i].max * (axis_data[i] - gdkdev->axes[i].min_value) +
651 gdkdev->info.axes[i].min * (gdkdev->axes[i].max_value - axis_data[i])) /
652 (gdkdev->axes[i].max_value - gdkdev->axes[i].min_value);
659 gdk_input_get_root_relative_geometry (HWND w,
665 GetWindowRect (w, &rect);
668 *x_ret = rect.left + _gdk_offset_x;
670 *y_ret = rect.top + _gdk_offset_y;
674 _gdk_input_configure_event (GdkWindow *window)
676 GdkInputWindow *input_window;
679 input_window = _gdk_input_window_find (window);
680 g_return_if_fail (window != NULL);
682 gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window),
685 input_window->root_x = root_x;
686 input_window->root_y = root_y;
690 _gdk_input_enter_event (GdkWindow *window)
692 GdkInputWindow *input_window;
695 input_window = _gdk_input_window_find (window);
696 g_return_if_fail (window != NULL);
698 gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window), &root_x, &root_y);
700 input_window->root_x = root_x;
701 input_window->root_y = root_y;
705 * Get the currently active keyboard modifiers (ignoring the mouse buttons)
706 * We could use gdk_window_get_pointer but that function does a lot of other
707 * expensive things besides getting the modifiers. This code is somewhat based
708 * on build_pointer_event_state from gdkevents-win32.c
711 get_modifier_key_state (void)
716 /* High-order bit is up/down, low order bit is toggled/untoggled */
717 if (GetKeyState (VK_CONTROL) < 0)
718 state |= GDK_CONTROL_MASK;
719 if (GetKeyState (VK_SHIFT) < 0)
720 state |= GDK_SHIFT_MASK;
721 if (GetKeyState (VK_MENU) < 0)
722 state |= GDK_MOD1_MASK;
723 if (GetKeyState (VK_CAPITAL) & 0x1)
724 state |= GDK_LOCK_MASK;
730 _gdk_input_other_event (GdkEvent *event,
736 GdkWindow *current_window;
739 GdkWindowObject *obj, *grab_obj;
740 GdkInputWindow *input_window;
741 GdkDevicePrivate *gdkdev = NULL;
742 GdkEventMask masktest;
750 if (event->any.window != wintab_window)
752 g_warning ("_gdk_input_other_event: not wintab_window?");
757 window = gdk_window_at_pointer (&x, &y);
759 window = _gdk_parent_root;
761 g_object_ref (window);
762 display = gdk_drawable_get_display (window);
764 GDK_NOTE (EVENTS_OR_INPUT,
765 g_print ("gdk_input_win32_other_event: window=%p (%d,%d)\n",
766 GDK_WINDOW_HWND (window), x, y));
769 /* ??? This code is pretty bogus */
770 current_window = gdk_win32_handle_table_lookup (GetActiveWindow ());
771 if (current_window == NULL)
774 input_window = gdk_input_window_find_within (current_window);
775 if (input_window == NULL)
779 if (msg->message == WT_PACKET)
781 if (!WTPacket ((HCTX) msg->lParam, msg->wParam, &packet))
785 obj = GDK_WINDOW_OBJECT (window);
787 switch (msg->message)
790 /* Don't produce any button or motion events while a window is being
791 * moved or resized, see bug #151090. */
792 if (_sizemove_in_progress)
794 GDK_NOTE (EVENTS_OR_INPUT, g_print ("...ignored when moving/sizing\n"));
797 if (window == _gdk_parent_root && x_grab_window == NULL)
799 GDK_NOTE (EVENTS_OR_INPUT, g_print ("...is root\n"));
803 if ((gdkdev = gdk_input_find_dev_from_ctx ((HCTX) msg->lParam,
804 packet.pkCursor)) == NULL)
807 if (gdkdev->info.mode == GDK_MODE_DISABLED)
811 if (gdkdev->pktdata & PK_X)
812 gdkdev->last_axis_data[k++] = packet.pkX;
813 if (gdkdev->pktdata & PK_Y)
814 gdkdev->last_axis_data[k++] = packet.pkY;
815 if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
816 gdkdev->last_axis_data[k++] = packet.pkNormalPressure;
817 if (gdkdev->pktdata & PK_ORIENTATION)
819 decode_tilt (gdkdev->last_axis_data + k,
820 gdkdev->orientation_axes, &packet);
824 g_assert (k == gdkdev->info.num_axes);
826 if (HIWORD (packet.pkButtons) != TBN_NONE)
828 /* Gdk buttons are numbered 1.. */
829 event->button.button = 1 + LOWORD (packet.pkButtons);
831 if (HIWORD (packet.pkButtons) == TBN_UP)
833 event->any.type = GDK_BUTTON_RELEASE;
834 masktest = GDK_BUTTON_RELEASE_MASK;
835 gdkdev->button_state &= ~(1 << LOWORD (packet.pkButtons));
839 event->any.type = GDK_BUTTON_PRESS;
840 masktest = GDK_BUTTON_PRESS_MASK;
841 gdkdev->button_state |= 1 << LOWORD (packet.pkButtons);
846 event->any.type = GDK_MOTION_NOTIFY;
847 masktest = GDK_POINTER_MOTION_MASK;
848 if (gdkdev->button_state & (1 << 0))
849 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK;
850 if (gdkdev->button_state & (1 << 1))
851 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK;
852 if (gdkdev->button_state & (1 << 2))
853 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK;
856 /* See if input is grabbed */
857 /* FIXME: x_grab_owner_events should probably be handled somehow */
858 if (x_grab_window != NULL)
860 grab_obj = GDK_WINDOW_OBJECT (x_grab_window);
861 if (!GDK_WINDOW_IMPL_WIN32 (grab_obj->impl)->extension_events_selected
862 || !(grab_obj->extension_events & masktest)
863 || !(x_grab_mask && masktest))
865 GDK_NOTE (EVENTS_OR_INPUT,
866 g_print ("...grabber doesn't want it\n"));
869 GDK_NOTE (EVENTS_OR_INPUT, g_print ("...to grabber\n"));
871 g_object_ref(x_grab_window);
872 g_object_unref(window);
873 window = x_grab_window;
876 /* Now we can check if the window wants the event, and
877 * propagate if necessary.
880 if (!GDK_WINDOW_IMPL_WIN32 (obj->impl)->extension_events_selected
881 || !(obj->extension_events & masktest))
883 GDK_NOTE (EVENTS_OR_INPUT, g_print ("...not selected\n"));
885 if (obj->parent == GDK_WINDOW_OBJECT (_gdk_parent_root))
888 /* It is not good to propagate the extended events up to the parent
889 * if this window wants normal (not extended) motion/button events */
890 if (obj->event_mask & masktest)
892 GDK_NOTE (EVENTS_OR_INPUT,
893 g_print ("...wants ordinary event, ignoring this\n"));
899 ClientToScreen (GDK_WINDOW_HWND (window), &pt);
900 g_object_unref (window);
901 window = (GdkWindow *) obj->parent;
902 obj = GDK_WINDOW_OBJECT (window);
903 g_object_ref (window);
904 ScreenToClient (GDK_WINDOW_HWND (window), &pt);
907 GDK_NOTE (EVENTS_OR_INPUT, g_print ("...propagating to %p (%d,%d)\n",
908 GDK_WINDOW_HWND (window), x, y));
912 input_window = _gdk_input_window_find (window);
914 g_assert (input_window != NULL);
916 if (gdkdev->info.mode == GDK_MODE_WINDOW
917 && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
920 event->any.window = window;
921 key_state = get_modifier_key_state ();
922 if (event->any.type == GDK_BUTTON_PRESS
923 || event->any.type == GDK_BUTTON_RELEASE)
925 event->button.time = _gdk_win32_get_next_tick (msg->time);
926 event->button.device = &gdkdev->info;
930 /* Buttons 1 to 3 will come in as WM_[LMR]BUTTON{DOWN,UP} */
931 if (event->button.button <= 3)
935 event->button.axes = g_new(gdouble, gdkdev->info.num_axes);
937 gdk_input_translate_coordinates (gdkdev, input_window,
938 gdkdev->last_axis_data,
943 /* Also calculate root coordinates. Note that input_window->root_x
944 is in GDK root coordinates. */
945 event->button.x_root = event->button.x + input_window->root_x;
946 event->button.y_root = event->button.y + input_window->root_y;
948 event->button.state = ((gdkdev->button_state << 8)
949 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
950 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
953 GDK_NOTE (EVENTS_OR_INPUT,
954 g_print ("WINTAB button %s:%d %g,%g\n",
955 (event->button.type == GDK_BUTTON_PRESS ?
956 "press" : "release"),
957 event->button.button,
958 event->button.x, event->button.y));
962 event->motion.time = _gdk_win32_get_next_tick (msg->time);
963 event->motion.is_hint = FALSE;
964 event->motion.device = &gdkdev->info;
966 event->motion.axes = g_new(gdouble, gdkdev->info.num_axes);
968 gdk_input_translate_coordinates (gdkdev, input_window,
969 gdkdev->last_axis_data,
974 /* Also calculate root coordinates. Note that input_window->root_x
975 is in GDK root coordinates. */
976 event->motion.x_root = event->motion.x + input_window->root_x;
977 event->motion.y_root = event->motion.y + input_window->root_y;
979 event->motion.state = ((gdkdev->button_state << 8)
980 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
981 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
985 GDK_NOTE (EVENTS_OR_INPUT,
986 g_print ("WINTAB motion: %g,%g\n",
987 event->motion.x, event->motion.y));
989 /* Check for missing release or press events for the normal
990 * pressure button. At least on my ArtPadII I sometimes miss a
993 if ((gdkdev->pktdata & PK_NORMAL_PRESSURE
994 && (event->motion.state & GDK_BUTTON1_MASK)
995 && packet.pkNormalPressure <= MAX (0, (gint) gdkdev->npbtnmarks[0] - 2))
996 || (gdkdev->pktdata & PK_NORMAL_PRESSURE
997 && !(event->motion.state & GDK_BUTTON1_MASK)
998 && packet.pkNormalPressure > gdkdev->npbtnmarks[1] + 2))
1000 GdkEvent *event2 = gdk_event_copy (event);
1001 if (event->motion.state & GDK_BUTTON1_MASK)
1003 event2->button.type = GDK_BUTTON_RELEASE;
1004 gdkdev->button_state &= ~1;
1008 event2->button.type = GDK_BUTTON_PRESS;
1009 gdkdev->button_state |= 1;
1011 event2->button.state = ((gdkdev->button_state << 8)
1012 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1013 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1014 | GDK_BUTTON5_MASK))
1016 event2->button.button = 1;
1017 GDK_NOTE (EVENTS_OR_INPUT,
1018 g_print ("WINTAB synthesized button %s: %d %g,%gg\n",
1019 (event2->button.type == GDK_BUTTON_PRESS ?
1020 "press" : "release"),
1021 event2->button.button,
1024 _gdk_event_queue_append (display, event2);
1030 if (LOWORD (msg->lParam) == 0)
1032 event->proximity.type = GDK_PROXIMITY_OUT;
1033 _gdk_input_ignore_core = FALSE;
1037 event->proximity.type = GDK_PROXIMITY_IN;
1038 _gdk_input_ignore_core = TRUE;
1040 event->proximity.time = _gdk_win32_get_next_tick (msg->time);
1041 event->proximity.device = &gdkdev->info;
1043 GDK_NOTE (EVENTS_OR_INPUT,
1044 g_print ("WINTAB proximity %s\n",
1045 (event->proximity.type == GDK_PROXIMITY_IN ?
1054 _gdk_input_enable_window (GdkWindow *window,
1055 GdkDevicePrivate *gdkdev)
1057 #ifdef HAVE_SOME_XINPUT
1058 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1060 impl->extension_events_selected = TRUE;
1067 _gdk_input_disable_window (GdkWindow *window,
1068 GdkDevicePrivate *gdkdev)
1070 #ifdef HAVE_SOME_XINPUT
1071 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1073 impl->extension_events_selected = FALSE;
1080 _gdk_input_grab_pointer (GdkWindow *window,
1082 GdkEventMask event_mask,
1083 GdkWindow *confine_to,
1086 #ifdef HAVE_SOME_XINPUT
1087 GdkInputWindow *input_window, *new_window;
1088 gboolean need_ungrab;
1089 GdkDevicePrivate *gdkdev;
1092 tmp_list = _gdk_input_windows;
1094 need_ungrab = FALSE;
1096 GDK_NOTE (INPUT, g_print ("gdk_input_win32_grab_pointer: %p %d %p\n",
1097 GDK_WINDOW_HWND (window),
1099 (confine_to ? GDK_WINDOW_HWND (confine_to) : 0)));
1103 input_window = (GdkInputWindow *)tmp_list->data;
1105 if (input_window->window == window)
1106 new_window = input_window;
1107 else if (input_window->grabbed)
1109 input_window->grabbed = FALSE;
1113 tmp_list = tmp_list->next;
1118 new_window->grabbed = TRUE;
1119 x_grab_window = window;
1120 x_grab_mask = event_mask;
1121 x_grab_owner_events = owner_events;
1123 /* FIXME: Do we need to handle confine_to and time? */
1125 tmp_list = _gdk_input_devices;
1128 gdkdev = (GdkDevicePrivate *)tmp_list->data;
1129 if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx)
1133 gdk_input_common_find_events (window, gdkdev,
1135 event_classes, &num_classes);
1137 result = XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
1138 GDK_WINDOW_XWINDOW (window),
1139 owner_events, num_classes, event_classes,
1140 GrabModeAsync, GrabModeAsync, time);
1142 /* FIXME: if failure occurs on something other than the first
1143 device, things will be badly inconsistent */
1144 if (result != Success)
1148 tmp_list = tmp_list->next;
1153 x_grab_window = NULL;
1154 tmp_list = _gdk_input_devices;
1157 gdkdev = (GdkDevicePrivate *)tmp_list->data;
1158 if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx &&
1159 ((gdkdev->button_state != 0) || need_ungrab))
1163 XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1165 gdkdev->button_state = 0;
1168 tmp_list = tmp_list->next;
1173 return GDK_GRAB_SUCCESS;
1177 _gdk_input_ungrab_pointer (guint32 time)
1179 #ifdef HAVE_SOME_XINPUT
1180 GdkInputWindow *input_window;
1181 GdkDevicePrivate *gdkdev;
1184 GDK_NOTE (INPUT, g_print ("gdk_input_win32_ungrab_pointer\n"));
1186 tmp_list = _gdk_input_windows;
1189 input_window = (GdkInputWindow *)tmp_list->data;
1190 if (input_window->grabbed)
1192 tmp_list = tmp_list->next;
1195 if (tmp_list) /* we found a grabbed window */
1197 input_window->grabbed = FALSE;
1199 tmp_list = _gdk_input_devices;
1202 gdkdev = (GdkDevicePrivate *)tmp_list->data;
1205 if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
1206 XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1208 tmp_list = tmp_list->next;
1211 x_grab_window = NULL;
1216 _gdk_device_get_history (GdkDevice *device,
1220 GdkTimeCoord ***events,
1227 gdk_device_get_state (GdkDevice *device,
1230 GdkModifierType *mask)
1232 g_return_if_fail (device != NULL);
1233 g_return_if_fail (GDK_IS_WINDOW (window));
1235 if (GDK_IS_CORE (device))
1239 gdk_window_get_pointer (window, &x_int, &y_int, mask);
1249 GdkDevicePrivate *gdkdev;
1250 GdkInputWindow *input_window;
1252 gdkdev = (GdkDevicePrivate *)device;
1253 /* For now just use the last known button and axis state of the device.
1254 * Since graphical tablets send an insane amount of motion events each
1255 * second, the info should be fairly up to date */
1258 gdk_window_get_pointer (window, NULL, NULL, mask);
1259 *mask &= 0xFF; /* Mask away core pointer buttons */
1260 *mask |= ((gdkdev->button_state << 8)
1261 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
1262 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
1263 | GDK_BUTTON5_MASK));
1265 input_window = _gdk_input_window_find (window);
1266 g_return_if_fail (input_window != NULL);
1267 /* For some reason, input_window is sometimes NULL when I use The GIMP 2
1268 * (bug #141543?). Avoid crashing if debugging is disabled. */
1269 if (axes && gdkdev->last_axis_data && input_window)
1270 gdk_input_translate_coordinates (gdkdev, input_window,
1271 gdkdev->last_axis_data,
1278 _gdk_input_set_tablet_active (void)
1283 /* Bring the contexts to the top of the overlap order when one of the
1284 * application's windows is activated */
1286 if (!wintab_contexts)
1287 return; /* No tablet devices found, or Wintab not initialized yet */
1289 GDK_NOTE (INPUT, g_print ("_gdk_input_set_tablet_active: "
1290 "Bringing Wintab contexts to the top of the overlap order\n"));
1292 tmp_list = wintab_contexts;
1295 hctx = (HCTX *) (tmp_list->data);
1296 WTOverlap (*hctx, TRUE);
1297 tmp_list = tmp_list->next;
1300 #endif /* HAVE_WINTAB */
1303 _gdk_input_init (GdkDisplay *display)
1305 _gdk_input_ignore_core = FALSE;
1306 _gdk_input_devices = NULL;
1308 _gdk_init_input_core (display);
1310 #ifdef WINTAB_NO_LAZY_INIT
1311 /* Normally, Wintab is only initialized when the application performs
1312 * an action that requires it, such as enabling extended input events
1313 * for a window or enumerating the devices.
1315 _gdk_input_wintab_init_check ();
1316 #endif /* WINTAB_NO_LAZY_INIT */
1317 #endif /* HAVE_WINTAB */
1319 _gdk_input_devices = g_list_append (_gdk_input_devices, display->core_pointer);