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/.
35 #include "gdkinternals.h"
36 #include "gdkprivate-win32.h"
37 #include "gdkinput-win32.h"
41 #define PACKETDATA (PK_CONTEXT | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION)
42 #define PACKETMODE (PK_BUTTONS)
45 /* If USE_SYSCONTEXT is on, we open the Wintab device (hmm, what if
46 * there are several?) as a system pointing device, i.e. it controls
47 * the normal Windows cursor. This seems much more natural.
49 #define USE_SYSCONTEXT 1 /* The code for the other choice is not
53 #define DEBUG_WINTAB 1 /* Verbose debug messages enabled */
57 #if defined(HAVE_WINTAB) || defined(HAVE_WHATEVER_OTHER)
58 #define HAVE_SOME_XINPUT
61 #define TWOPI (2.*G_PI)
63 /* Forward declarations */
66 static GdkInputWindow *gdk_input_window_find_within (GdkWindow *window);
71 static GdkDevicePrivate *gdk_input_find_dev_from_ctx (HCTX hctx,
73 static GList *wintab_contexts;
75 static GdkWindow *wintab_window;
77 #endif /* HAVE_WINTAB */
80 gdk_device_get_history (GdkDevice *device,
84 GdkTimeCoord ***events,
87 GdkTimeCoord **coords;
90 g_return_val_if_fail (window != NULL, FALSE);
91 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
92 g_return_val_if_fail (events != NULL, FALSE);
93 g_return_val_if_fail (n_events != NULL, FALSE);
98 if (GDK_WINDOW_DESTROYED (window))
101 if (GDK_IS_CORE (device))
104 return _gdk_device_get_history (device, window, start, stop, events, n_events);
109 static GdkDevicePrivate *
110 gdk_input_find_dev_from_ctx (HCTX hctx,
113 GList *tmp_list = gdk_input_devices;
114 GdkDevicePrivate *gdkdev;
118 gdkdev = (GdkDevicePrivate *) (tmp_list->data);
119 if (gdkdev->hctx == hctx && gdkdev->cursor == cursor)
121 tmp_list = tmp_list->next;
129 print_lc(LOGCONTEXT *lc)
131 g_print ("lcName = %s\n", lc->lcName);
132 g_print ("lcOptions =");
133 if (lc->lcOptions & CXO_SYSTEM) g_print (" CXO_SYSTEM");
134 if (lc->lcOptions & CXO_PEN) g_print (" CXO_PEN");
135 if (lc->lcOptions & CXO_MESSAGES) g_print (" CXO_MESSAGES");
136 if (lc->lcOptions & CXO_MARGIN) g_print (" CXO_MARGIN");
137 if (lc->lcOptions & CXO_MGNINSIDE) g_print (" CXO_MGNINSIDE");
138 if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
139 if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
141 g_print ("lcStatus =");
142 if (lc->lcStatus & CXS_DISABLED) g_print (" CXS_DISABLED");
143 if (lc->lcStatus & CXS_OBSCURED) g_print (" CXS_OBSCURED");
144 if (lc->lcStatus & CXS_ONTOP) g_print (" CXS_ONTOP");
146 g_print ("lcLocks =");
147 if (lc->lcLocks & CXL_INSIZE) g_print (" CXL_INSIZE");
148 if (lc->lcLocks & CXL_INASPECT) g_print (" CXL_INASPECT");
149 if (lc->lcLocks & CXL_SENSITIVITY) g_print (" CXL_SENSITIVITY");
150 if (lc->lcLocks & CXL_MARGIN) g_print (" CXL_MARGIN");
152 g_print ("lcMsgBase = %#x, lcDevice = %#x, lcPktRate = %d\n",
153 lc->lcMsgBase, lc->lcDevice, lc->lcPktRate);
154 g_print ("lcPktData =");
155 if (lc->lcPktData & PK_CONTEXT) g_print (" PK_CONTEXT");
156 if (lc->lcPktData & PK_STATUS) g_print (" PK_STATUS");
157 if (lc->lcPktData & PK_TIME) g_print (" PK_TIME");
158 if (lc->lcPktData & PK_CHANGED) g_print (" PK_CHANGED");
159 if (lc->lcPktData & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
160 if (lc->lcPktData & PK_CURSOR) g_print (" PK_CURSOR");
161 if (lc->lcPktData & PK_BUTTONS) g_print (" PK_BUTTONS");
162 if (lc->lcPktData & PK_X) g_print (" PK_X");
163 if (lc->lcPktData & PK_Y) g_print (" PK_Y");
164 if (lc->lcPktData & PK_Z) g_print (" PK_Z");
165 if (lc->lcPktData & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
166 if (lc->lcPktData & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
167 if (lc->lcPktData & PK_ORIENTATION) g_print (" PK_ORIENTATION");
168 if (lc->lcPktData & PK_ROTATION) g_print (" PK_ROTATION");
170 g_print ("lcPktMode =");
171 if (lc->lcPktMode & PK_CONTEXT) g_print (" PK_CONTEXT");
172 if (lc->lcPktMode & PK_STATUS) g_print (" PK_STATUS");
173 if (lc->lcPktMode & PK_TIME) g_print (" PK_TIME");
174 if (lc->lcPktMode & PK_CHANGED) g_print (" PK_CHANGED");
175 if (lc->lcPktMode & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
176 if (lc->lcPktMode & PK_CURSOR) g_print (" PK_CURSOR");
177 if (lc->lcPktMode & PK_BUTTONS) g_print (" PK_BUTTONS");
178 if (lc->lcPktMode & PK_X) g_print (" PK_X");
179 if (lc->lcPktMode & PK_Y) g_print (" PK_Y");
180 if (lc->lcPktMode & PK_Z) g_print (" PK_Z");
181 if (lc->lcPktMode & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
182 if (lc->lcPktMode & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
183 if (lc->lcPktMode & PK_ORIENTATION) g_print (" PK_ORIENTATION");
184 if (lc->lcPktMode & PK_ROTATION) g_print (" PK_ROTATION");
186 g_print ("lcMoveMask =");
187 if (lc->lcMoveMask & PK_CONTEXT) g_print (" PK_CONTEXT");
188 if (lc->lcMoveMask & PK_STATUS) g_print (" PK_STATUS");
189 if (lc->lcMoveMask & PK_TIME) g_print (" PK_TIME");
190 if (lc->lcMoveMask & PK_CHANGED) g_print (" PK_CHANGED");
191 if (lc->lcMoveMask & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
192 if (lc->lcMoveMask & PK_CURSOR) g_print (" PK_CURSOR");
193 if (lc->lcMoveMask & PK_BUTTONS) g_print (" PK_BUTTONS");
194 if (lc->lcMoveMask & PK_X) g_print (" PK_X");
195 if (lc->lcMoveMask & PK_Y) g_print (" PK_Y");
196 if (lc->lcMoveMask & PK_Z) g_print (" PK_Z");
197 if (lc->lcMoveMask & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
198 if (lc->lcMoveMask & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
199 if (lc->lcMoveMask & PK_ORIENTATION) g_print (" PK_ORIENTATION");
200 if (lc->lcMoveMask & PK_ROTATION) g_print (" PK_ROTATION");
202 g_print ("lcBtnDnMask = %#x, lcBtnUpMask = %#x\n",
203 lc->lcBtnDnMask, lc->lcBtnUpMask);
204 g_print ("lcInOrgX = %d, lcInOrgY = %d, lcInOrgZ = %d\n",
205 lc->lcInOrgX, lc->lcInOrgY, lc->lcInOrgZ);
206 g_print ("lcInExtX = %d, lcInExtY = %d, lcInExtZ = %d\n",
207 lc->lcInExtX, lc->lcInExtY, lc->lcInExtZ);
208 g_print ("lcOutOrgX = %d, lcOutOrgY = %d, lcOutOrgZ = %d\n",
209 lc->lcOutOrgX, lc->lcOutOrgY, lc->lcOutOrgZ);
210 g_print ("lcOutExtX = %d, lcOutExtY = %d, lcOutExtZ = %d\n",
211 lc->lcOutExtX, lc->lcOutExtY, lc->lcOutExtZ);
212 g_print ("lcSensX = %g, lcSensY = %g, lcSensZ = %g\n",
213 lc->lcSensX / 65536., lc->lcSensY / 65536., lc->lcSensZ / 65536.);
214 g_print ("lcSysMode = %d\n", lc->lcSysMode);
215 g_print ("lcSysOrgX = %d, lcSysOrgY = %d\n",
216 lc->lcSysOrgX, lc->lcSysOrgY);
217 g_print ("lcSysExtX = %d, lcSysExtY = %d\n",
218 lc->lcSysExtX, lc->lcSysExtY);
219 g_print ("lcSysSensX = %g, lcSysSensY = %g\n",
220 lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.);
226 gdk_input_wintab_init (void)
228 GdkDevicePrivate *gdkdev;
231 LOGCONTEXT defcontext;
233 UINT ndevices, ncursors, ncsrtypes, firstcsr, hardware;
235 AXIS axis_x, axis_y, axis_npressure, axis_or[3];
238 char devname[100], csrname[100];
240 gdk_input_devices = NULL;
241 wintab_contexts = NULL;
243 if (!gdk_input_ignore_wintab &&
246 WTInfo (WTI_INTERFACE, IFC_SPECVERSION, &specversion);
247 GDK_NOTE (MISC, g_print ("Wintab interface version %d.%d\n",
248 HIBYTE (specversion), LOBYTE (specversion)));
250 WTInfo (WTI_DEFSYSCTX, 0, &defcontext);
252 GDK_NOTE (MISC, (g_print("DEFSYSCTX:\n"), print_lc(&defcontext)));
255 WTInfo (WTI_DEFCONTEXT, 0, &defcontext);
257 GDK_NOTE (MISC, (g_print("DEFCONTEXT:\n"), print_lc(&defcontext)));
260 WTInfo (WTI_INTERFACE, IFC_NDEVICES, &ndevices);
261 WTInfo (WTI_INTERFACE, IFC_NCURSORS, &ncursors);
263 GDK_NOTE (MISC, g_print ("NDEVICES: %d, NCURSORS: %d\n",
264 ndevices, ncursors));
266 /* Create a dummy window to receive wintab events */
267 wa.wclass = GDK_INPUT_OUTPUT;
268 wa.event_mask = GDK_ALL_EVENTS_MASK;
273 wa.window_type = GDK_WINDOW_TOPLEVEL;
274 if ((wintab_window = gdk_window_new (NULL, &wa, GDK_WA_X|GDK_WA_Y)) == NULL)
276 g_warning ("gdk_input_init: gdk_window_new failed");
279 gdk_drawable_ref (wintab_window);
281 for (devix = 0; devix < ndevices; devix++)
285 WTInfo (WTI_DEVICES + devix, DVC_NAME, devname);
287 WTInfo (WTI_DEVICES + devix, DVC_NCSRTYPES, &ncsrtypes);
288 WTInfo (WTI_DEVICES + devix, DVC_FIRSTCSR, &firstcsr);
289 WTInfo (WTI_DEVICES + devix, DVC_HARDWARE, &hardware);
290 WTInfo (WTI_DEVICES + devix, DVC_X, &axis_x);
291 WTInfo (WTI_DEVICES + devix, DVC_Y, &axis_y);
292 WTInfo (WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure);
293 WTInfo (WTI_DEVICES + devix, DVC_ORIENTATION, axis_or);
295 if (HIBYTE (specversion) > 1 || LOBYTE (specversion) >= 1)
297 WTInfo (WTI_DDCTXS + devix, CTX_NAME, lc.lcName);
298 WTInfo (WTI_DDCTXS + devix, CTX_OPTIONS, &lc.lcOptions);
299 lc.lcOptions |= CXO_MESSAGES;
301 lc.lcOptions |= CXO_SYSTEM;
304 WTInfo (WTI_DDCTXS + devix, CTX_LOCKS, &lc.lcLocks);
305 lc.lcMsgBase = WT_DEFBASE;
308 lc.lcPktData = PACKETDATA;
309 lc.lcPktMode = PK_BUTTONS; /* We want buttons in relative mode */
310 lc.lcMoveMask = PACKETDATA;
311 lc.lcBtnDnMask = lc.lcBtnUpMask = ~0;
312 WTInfo (WTI_DDCTXS + devix, CTX_INORGX, &lc.lcInOrgX);
313 WTInfo (WTI_DDCTXS + devix, CTX_INORGY, &lc.lcInOrgY);
314 WTInfo (WTI_DDCTXS + devix, CTX_INORGZ, &lc.lcInOrgZ);
315 WTInfo (WTI_DDCTXS + devix, CTX_INEXTX, &lc.lcInExtX);
316 WTInfo (WTI_DDCTXS + devix, CTX_INEXTY, &lc.lcInExtY);
317 WTInfo (WTI_DDCTXS + devix, CTX_INEXTZ, &lc.lcInExtZ);
318 lc.lcOutOrgX = axis_x.axMin;
319 lc.lcOutOrgY = axis_y.axMin;
320 lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
321 lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
322 lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
323 WTInfo (WTI_DDCTXS + devix, CTX_SENSX, &lc.lcSensX);
324 WTInfo (WTI_DDCTXS + devix, CTX_SENSY, &lc.lcSensY);
325 WTInfo (WTI_DDCTXS + devix, CTX_SENSZ, &lc.lcSensZ);
326 WTInfo (WTI_DDCTXS + devix, CTX_SYSMODE, &lc.lcSysMode);
327 lc.lcSysOrgX = lc.lcSysOrgY = 0;
328 WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTX, &lc.lcSysExtX);
329 WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTY, &lc.lcSysExtY);
330 WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSX, &lc.lcSysSensX);
331 WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSY, &lc.lcSysSensY);
336 lc.lcOptions |= CXO_MESSAGES;
337 lc.lcMsgBase = WT_DEFBASE;
339 lc.lcPktData = PACKETDATA;
340 lc.lcPktMode = PACKETMODE;
341 lc.lcMoveMask = PACKETDATA;
342 lc.lcBtnUpMask = lc.lcBtnDnMask = ~0;
344 lc.lcOutExtY = -lc.lcOutExtY; /* Y grows downward */
346 lc.lcOutOrgX = axis_x.axMin;
347 lc.lcOutOrgY = axis_y.axMin;
348 lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
349 lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
350 lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
354 GDK_NOTE (MISC, (g_print("context for device %d:\n", devix),
357 hctx = g_new (HCTX, 1);
358 if ((*hctx = WTOpen (GDK_WINDOW_HWND (wintab_window), &lc, TRUE)) == NULL)
360 g_warning ("gdk_input_init: WTOpen failed");
363 GDK_NOTE (MISC, g_print ("opened Wintab device %d %#x\n",
366 wintab_contexts = g_list_append (wintab_contexts, hctx);
368 WTEnable (*hctx, TRUE);
370 WTOverlap (*hctx, TRUE);
373 GDK_NOTE (MISC, (g_print("context for device %d after WTOpen:\n", devix),
376 for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes; cursorix++)
379 WTInfo (WTI_CURSORS + cursorix, CSR_ACTIVE, &active);
382 gdkdev = g_new (GdkDevicePrivate, 1);
383 WTInfo (WTI_CURSORS + cursorix, CSR_NAME, csrname);
384 gdkdev->info.name = g_strconcat (devname, " ", csrname, NULL);
385 gdkdev->info.source = GDK_SOURCE_PEN;
386 gdkdev->info.mode = GDK_MODE_SCREEN;
388 gdkdev->info.has_cursor = TRUE;
390 gdkdev->info.has_cursor = FALSE;
392 gdkdev->hctx = *hctx;
393 gdkdev->cursor = cursorix;
394 WTInfo (WTI_CURSORS + cursorix, CSR_PKTDATA, &gdkdev->pktdata);
395 gdkdev->info.num_axes = 0;
396 if (gdkdev->pktdata & PK_X)
397 gdkdev->info.num_axes++;
398 if (gdkdev->pktdata & PK_Y)
399 gdkdev->info.num_axes++;
400 if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
401 gdkdev->info.num_axes++;
402 /* The wintab driver for the Wacom ArtPad II reports
403 * PK_ORIENTATION in CSR_PKTDATA, but the tablet doesn't
404 * actually sense tilt. Catch this by noticing that the
405 * orientation axis's azimuth resolution is zero.
407 if ((gdkdev->pktdata & PK_ORIENTATION)
408 && axis_or[0].axResolution == 0)
409 gdkdev->pktdata &= ~PK_ORIENTATION;
411 if (gdkdev->pktdata & PK_ORIENTATION)
412 gdkdev->info.num_axes += 2; /* x and y tilt */
413 WTInfo (WTI_CURSORS + cursorix, CSR_NPBTNMARKS, &gdkdev->npbtnmarks);
414 gdkdev->info.axes = g_new (GdkDeviceAxis, gdkdev->info.num_axes);
415 gdkdev->axes = g_new (GdkAxisInfo, gdkdev->info.num_axes);
416 gdkdev->last_axis_data = g_new (gint, gdkdev->info.num_axes);
419 if (gdkdev->pktdata & PK_X)
421 gdkdev->axes[k].xresolution =
422 gdkdev->axes[k].resolution = axis_x.axResolution / 65535.;
423 gdkdev->axes[k].xmin_value =
424 gdkdev->axes[k].min_value = axis_x.axMin;
425 gdkdev->axes[k].xmax_value =
426 gdkdev->axes[k].max_value = axis_x.axMax;
427 gdkdev->info.axes[k].use = GDK_AXIS_X;
428 gdkdev->info.axes[k].min = axis_x.axMin;
429 gdkdev->info.axes[k].min = axis_x.axMax;
432 if (gdkdev->pktdata & PK_Y)
434 gdkdev->axes[k].xresolution =
435 gdkdev->axes[k].resolution = axis_y.axResolution / 65535.;
436 gdkdev->axes[k].xmin_value =
437 gdkdev->axes[k].min_value = axis_y.axMin;
438 gdkdev->axes[k].xmax_value =
439 gdkdev->axes[k].max_value = axis_y.axMax;
440 gdkdev->info.axes[k].use = GDK_AXIS_Y;
441 gdkdev->info.axes[k].min = axis_y.axMin;
442 gdkdev->info.axes[k].min = axis_y.axMax;
445 if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
447 gdkdev->axes[k].xresolution =
448 gdkdev->axes[k].resolution = axis_npressure.axResolution / 65535.;
449 gdkdev->axes[k].xmin_value =
450 gdkdev->axes[k].min_value = axis_npressure.axMin;
451 gdkdev->axes[k].xmax_value =
452 gdkdev->axes[k].max_value = axis_npressure.axMax;
453 gdkdev->info.axes[k].use = GDK_AXIS_PRESSURE;
454 gdkdev->info.axes[k].min = axis_npressure.axMin;
455 gdkdev->info.axes[k].min = axis_npressure.axMax;
458 if (gdkdev->pktdata & PK_ORIENTATION)
462 gdkdev->orientation_axes[0] = axis_or[0];
463 gdkdev->orientation_axes[1] = axis_or[1];
464 for (axis = GDK_AXIS_XTILT; axis <= GDK_AXIS_YTILT; axis++)
466 /* Wintab gives us aximuth and altitude, which
467 * we convert to x and y tilt in the -1000..1000 range
469 gdkdev->axes[k].xresolution =
470 gdkdev->axes[k].resolution = 1000;
471 gdkdev->axes[k].xmin_value =
472 gdkdev->axes[k].min_value = -1000;
473 gdkdev->axes[k].xmax_value =
474 gdkdev->axes[k].max_value = 1000;
475 gdkdev->info.axes[k].use = axis;
476 gdkdev->info.axes[k].min = -1000;
477 gdkdev->info.axes[k].min = 1000;
481 gdkdev->info.num_keys = 0;
482 gdkdev->info.keys = NULL;
484 g_print ("device: (%d) %s axes: %d\n",
487 gdkdev->info.num_axes));
488 for (i = 0; i < gdkdev->info.num_axes; i++)
490 g_print ("...axis %d: %d--%d@%d (%d--%d@%d)\n",
492 gdkdev->axes[i].xmin_value,
493 gdkdev->axes[i].xmax_value,
494 gdkdev->axes[i].xresolution,
495 gdkdev->axes[i].min_value,
496 gdkdev->axes[i].max_value,
497 gdkdev->axes[i].resolution));
498 gdk_input_devices = g_list_append (gdk_input_devices,
506 decode_tilt (gint *axis_data,
510 /* As I don't have a tilt-sensing tablet,
511 * I cannot test this code.
516 az = TWOPI * packet->pkOrientation.orAzimuth /
517 (axes[0].axResolution / 65536.);
518 el = TWOPI * packet->pkOrientation.orAltitude /
519 (axes[1].axResolution / 65536.);
522 axis_data[0] = cos (az) * cos (el) * 1000;
524 axis_data[1] = sin (az) * cos (el) * 1000;
529 static GdkInputWindow *
530 gdk_input_window_find_within (GdkWindow *window)
534 GdkInputWindow *candidate = NULL;
536 for (list = gdk_input_windows; list != NULL; list = list->next)
538 tmpw = ((GdkInputWindow *) (tmp_list->data))->window;
540 || IsChild (GDK_WINDOW_HWND (window), GDK_WINDOW_HWND (tmpw)))
543 return NULL; /* Multiple hits */
544 candidate = (GdkInputWindow *) (list->data);
551 #endif /* USE_SYSCONTEXT */
553 #endif /* HAVE_WINTAB */
556 gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
557 GdkInputWindow *input_window,
563 GdkWindowImplWin32 *impl;
569 double device_width, device_height;
570 double x_offset, y_offset, x_scale, y_scale;
572 impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (input_window->window)->impl);
574 for (i=0; i<gdkdev->info.num_axes; i++)
576 switch (gdkdev->info.axes[i].use)
589 device_width = gdkdev->axes[x_axis].max_value -
590 gdkdev->axes[x_axis].min_value;
591 device_height = gdkdev->axes[y_axis].max_value -
592 gdkdev->axes[y_axis].min_value;
594 if (gdkdev->info.mode == GDK_MODE_SCREEN)
596 x_scale = gdk_screen_width() / device_width;
597 y_scale = gdk_screen_height() / device_height;
599 x_offset = - input_window->root_x;
600 y_offset = - input_window->root_y;
602 else /* GDK_MODE_WINDOW */
604 double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
605 (device_width*gdkdev->axes[x_axis].resolution);
607 if (device_aspect * impl->width >= impl->height)
609 /* device taller than window */
610 x_scale = impl->width / device_width;
611 y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
612 / gdkdev->axes[y_axis].resolution;
615 y_offset = -(device_height * y_scale -
620 /* window taller than device */
621 y_scale = impl->height / device_height;
622 x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
623 / gdkdev->axes[x_axis].resolution;
626 x_offset = - (device_width * x_scale - impl->width)/2;
630 for (i=0; i<gdkdev->info.num_axes; i++)
632 switch (gdkdev->info.axes[i].use)
635 axis_out[i] = x_offset + x_scale*axis_data[x_axis];
637 *x_out = axis_out[i];
640 axis_out[i] = y_offset + y_scale*axis_data[y_axis];
642 *y_out = axis_out[i];
646 (gdkdev->info.axes[i].max * (axis_data[i] - gdkdev->axes[i].min_value) +
647 gdkdev->info.axes[i].min * (gdkdev->axes[i].max_value - axis_data[i])) /
648 (gdkdev->axes[i].max_value - gdkdev->axes[i].min_value);
655 gdk_input_get_root_relative_geometry (HWND w,
661 GetWindowRect (w, &rect);
670 gdk_input_motion_events (GdkWindow *window,
674 gint *nevents_return)
676 g_return_val_if_fail (window != NULL, NULL);
677 if (GDK_WINDOW_DESTROYED (window))
681 return NULL; /* ??? */
685 _gdk_input_configure_event (GdkEventConfigure *event,
688 GdkInputWindow *input_window;
691 input_window = gdk_input_window_find (window);
692 g_return_if_fail (window != NULL);
694 gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window),
697 input_window->root_x = root_x;
698 input_window->root_y = root_y;
702 _gdk_input_enter_event (GdkEventCrossing *event,
705 GdkInputWindow *input_window;
708 input_window = gdk_input_window_find (window);
709 g_return_if_fail (window != NULL);
711 gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window), &root_x, &root_y);
713 input_window->root_x = root_x;
714 input_window->root_y = root_y;
718 _gdk_input_other_event (GdkEvent *event,
723 GdkWindow *current_window;
724 GdkWindowObject *obj;
725 GdkWindowImplWin32 *impl;
726 GdkInputWindow *input_window;
727 GdkDevicePrivate *gdkdev;
728 GdkEventMask masktest;
736 if (event->any.window != wintab_window)
738 g_warning ("_gdk_input_other_event: not wintab_window?");
743 window = gdk_window_at_pointer (&x, &y);
745 window = gdk_parent_root;
747 gdk_drawable_ref (window);
750 g_print ("gdk_input_win32_other_event: window=%#x (%d,%d)\n",
751 GDK_WINDOW_HWND (window), x, y));
754 /* ??? This code is pretty bogus */
755 current_window = gdk_win32_handle_table_lookup (GetActiveWindow ());
756 if (current_window == NULL)
759 input_window = gdk_input_window_find_within (current_window);
760 if (input_window == NULL)
764 if (msg->message == WT_PACKET)
766 if (!WTPacket ((HCTX) msg->lParam, msg->wParam, &packet))
770 obj = GDK_WINDOW_OBJECT (window);
771 impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
773 switch (msg->message)
776 if (window == gdk_parent_root)
778 GDK_NOTE (EVENTS, g_print ("...is root\n"));
782 if ((gdkdev = gdk_input_find_dev_from_ctx ((HCTX) msg->lParam,
783 packet.pkCursor)) == NULL)
786 if (gdkdev->info.mode == GDK_MODE_DISABLED)
790 if (gdkdev->pktdata & PK_X)
791 gdkdev->last_axis_data[k++] = packet.pkX;
792 if (gdkdev->pktdata & PK_Y)
793 gdkdev->last_axis_data[k++] = packet.pkY;
794 if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
795 gdkdev->last_axis_data[k++] = packet.pkNormalPressure;
796 if (gdkdev->pktdata & PK_ORIENTATION)
798 decode_tilt (gdkdev->last_axis_data + k,
799 gdkdev->orientation_axes, &packet);
803 g_assert (k == gdkdev->info.num_axes);
805 if (HIWORD (packet.pkButtons) != TBN_NONE)
807 /* Gdk buttons are numbered 1.. */
808 event->button.button = 1 + LOWORD (packet.pkButtons);
810 if (HIWORD (packet.pkButtons) == TBN_UP)
812 event->any.type = GDK_BUTTON_RELEASE;
813 masktest = GDK_BUTTON_RELEASE_MASK;
814 gdkdev->button_state &= ~(1 << LOWORD (packet.pkButtons));
818 event->any.type = GDK_BUTTON_PRESS;
819 masktest = GDK_BUTTON_PRESS_MASK;
820 gdkdev->button_state |= 1 << LOWORD (packet.pkButtons);
825 event->any.type = GDK_MOTION_NOTIFY;
826 masktest = GDK_POINTER_MOTION_MASK;
827 if (gdkdev->button_state & (1 << 0))
828 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK;
829 if (gdkdev->button_state & (1 << 1))
830 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK;
831 if (gdkdev->button_state & (1 << 2))
832 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK;
835 /* Now we can check if the window wants the event, and
836 * propagate if necessary.
839 if (!impl->extension_events_selected
840 || !(obj->extension_events & masktest))
842 GDK_NOTE (EVENTS, g_print ("...not selected\n"));
844 if (obj->parent == GDK_WINDOW_OBJECT (gdk_parent_root))
849 ClientToScreen (GDK_WINDOW_HWND (window), &pt);
850 gdk_drawable_unref (window);
851 window = (GdkWindow *) obj->parent;
852 obj = GDK_WINDOW_OBJECT (window);
853 gdk_drawable_ref (window);
854 ScreenToClient (GDK_WINDOW_HWND (window), &pt);
857 GDK_NOTE (EVENTS, g_print ("...propagating to %#x, (%d,%d)\n",
858 GDK_WINDOW_HWND (window), x, y));
862 input_window = gdk_input_window_find (window);
864 g_assert (input_window != NULL);
866 if (gdkdev->info.mode == GDK_MODE_WINDOW
867 && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
870 event->any.window = window;
872 if (event->any.type == GDK_BUTTON_PRESS
873 || event->any.type == GDK_BUTTON_RELEASE)
875 event->button.time = msg->time;
876 event->button.device = &gdkdev->info;
880 /* Buttons 1 to 3 will come in as WM_[LMR]BUTTON{DOWN,UP} */
881 if (event->button.button <= 3)
885 gdk_input_translate_coordinates (gdkdev, input_window,
886 gdkdev->last_axis_data,
891 event->button.state = ((gdkdev->button_state << 8)
892 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
893 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
894 | GDK_BUTTON5_MASK));
895 GDK_NOTE (EVENTS, g_print ("WINTAB button %s:%d %g,%g %g %g,%g\n",
896 (event->button.type == GDK_BUTTON_PRESS ?
897 "press" : "release"),
898 event->button.button,
899 event->button.x, event->button.y));
903 event->motion.time = msg->time;
904 event->motion.is_hint = FALSE;
905 event->motion.device = &gdkdev->info;
907 gdk_input_translate_coordinates (gdkdev, input_window,
908 gdkdev->last_axis_data,
913 event->motion.state = ((gdkdev->button_state << 8)
914 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
915 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
916 | GDK_BUTTON5_MASK));
918 GDK_NOTE (EVENTS, g_print ("WINTAB motion: %g,%g\n",
919 event->motion.x, event->motion.y));
921 /* Check for missing release or press events for the normal
922 * pressure button. At least on my ArtPadII I sometimes miss a
925 if ((gdkdev->pktdata & PK_NORMAL_PRESSURE
926 && (event->motion.state & GDK_BUTTON1_MASK)
927 && packet.pkNormalPressure <= MAX (0, gdkdev->npbtnmarks[0] - 2))
928 || (gdkdev->pktdata & PK_NORMAL_PRESSURE
929 && !(event->motion.state & GDK_BUTTON1_MASK)
930 && packet.pkNormalPressure > gdkdev->npbtnmarks[1] + 2))
932 GdkEvent *event2 = gdk_event_copy (event);
933 if (event->motion.state & GDK_BUTTON1_MASK)
935 event2->button.type = GDK_BUTTON_RELEASE;
936 gdkdev->button_state &= ~1;
940 event2->button.type = GDK_BUTTON_PRESS;
941 gdkdev->button_state |= 1;
943 event2->button.state = ((gdkdev->button_state << 8)
944 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
945 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
946 | GDK_BUTTON5_MASK));
947 event2->button.button = 1;
948 GDK_NOTE (EVENTS, g_print ("WINTAB synthesized button %s: %d %g,%gg\n",
949 (event2->button.type == GDK_BUTTON_PRESS ?
950 "press" : "release"),
951 event2->button.button,
954 gdk_event_queue_append (event2);
960 if (LOWORD (msg->lParam) == 0)
962 event->proximity.type = GDK_PROXIMITY_OUT;
963 gdk_input_ignore_core = FALSE;
967 event->proximity.type = GDK_PROXIMITY_IN;
968 gdk_input_ignore_core = TRUE;
970 event->proximity.time = msg->time;
971 event->proximity.device = &gdkdev->info;
973 GDK_NOTE (EVENTS, g_print ("WINTAB proximity %s\n",
974 (event->proximity.type == GDK_PROXIMITY_IN ?
983 _gdk_input_enable_window (GdkWindow *window,
984 GdkDevicePrivate *gdkdev)
986 #ifdef HAVE_SOME_XINPUT
987 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
989 impl->extension_events_selected = TRUE;
996 _gdk_input_disable_window (GdkWindow *window,
997 GdkDevicePrivate *gdkdev)
999 #ifdef HAVE_SOME_XINPUT
1000 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1002 impl->extension_events_selected = FALSE;
1009 _gdk_input_grab_pointer (GdkWindow *window,
1011 GdkEventMask event_mask,
1012 GdkWindow *confine_to,
1015 #ifdef HAVE_SOME_XINPUT
1016 GdkInputWindow *input_window, *new_window;
1017 gboolean need_ungrab;
1018 GdkDevicePrivate *gdkdev;
1022 tmp_list = gdk_input_windows;
1024 need_ungrab = FALSE;
1026 GDK_NOTE (MISC, g_print ("gdk_input_win32_grab_pointer: %#x %d %#x\n",
1027 GDK_WINDOW_HWND (window),
1029 (confine_to ? GDK_WINDOW_HWND (confine_to) : 0)));
1033 input_window = (GdkInputWindow *)tmp_list->data;
1035 if (input_window->window == window)
1036 new_window = input_window;
1037 else if (input_window->grabbed)
1039 input_window->grabbed = FALSE;
1043 tmp_list = tmp_list->next;
1048 new_window->grabbed = TRUE;
1050 tmp_list = gdk_input_devices;
1053 gdkdev = (GdkDevicePrivate *)tmp_list->data;
1054 if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx)
1058 gdk_input_common_find_events (window, gdkdev,
1060 event_classes, &num_classes);
1062 result = XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
1063 GDK_WINDOW_XWINDOW (window),
1064 owner_events, num_classes, event_classes,
1065 GrabModeAsync, GrabModeAsync, time);
1067 /* FIXME: if failure occurs on something other than the first
1068 device, things will be badly inconsistent */
1069 if (result != Success)
1073 tmp_list = tmp_list->next;
1078 tmp_list = gdk_input_devices;
1081 gdkdev = (GdkDevicePrivate *)tmp_list->data;
1082 if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx &&
1083 ((gdkdev->button_state != 0) || need_ungrab))
1087 XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1089 gdkdev->button_state = 0;
1092 tmp_list = tmp_list->next;
1097 return GDK_GRAB_SUCCESS;
1101 _gdk_input_ungrab_pointer (guint32 time)
1103 #ifdef HAVE_SOME_XINPUT
1104 GdkInputWindow *input_window;
1105 GdkDevicePrivate *gdkdev;
1108 GDK_NOTE (MISC, g_print ("gdk_input_win32_ungrab_pointer\n"));
1110 tmp_list = gdk_input_windows;
1113 input_window = (GdkInputWindow *)tmp_list->data;
1114 if (input_window->grabbed)
1116 tmp_list = tmp_list->next;
1119 if (tmp_list) /* we found a grabbed window */
1121 input_window->grabbed = FALSE;
1123 tmp_list = gdk_input_devices;
1126 gdkdev = (GdkDevicePrivate *)tmp_list->data;
1129 if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
1130 XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1132 tmp_list = tmp_list->next;
1139 _gdk_input_window_none_event (GdkEvent *event,
1146 _gdk_device_get_history (GdkDevice *device,
1150 GdkTimeCoord ***events,
1157 gdk_input_init (void)
1159 gdk_input_ignore_core = FALSE;
1160 gdk_input_devices = NULL;
1163 gdk_input_wintab_init ();
1164 #endif /* HAVE_WINTAB */
1166 gdk_input_devices = g_list_append (gdk_input_devices, &gdk_input_core_info);