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;
76 static GdkWindow *wintab_window;
78 #endif /* HAVE_WINTAB */
82 static GdkDevicePrivate *
83 gdk_input_find_dev_from_ctx (HCTX hctx,
86 GList *tmp_list = _gdk_input_devices;
87 GdkDevicePrivate *gdkdev;
91 gdkdev = (GdkDevicePrivate *) (tmp_list->data);
92 if (gdkdev->hctx == hctx && gdkdev->cursor == cursor)
94 tmp_list = tmp_list->next;
102 print_lc(LOGCONTEXT *lc)
104 g_print ("lcName = %s\n", lc->lcName);
105 g_print ("lcOptions =");
106 if (lc->lcOptions & CXO_SYSTEM) g_print (" CXO_SYSTEM");
107 if (lc->lcOptions & CXO_PEN) g_print (" CXO_PEN");
108 if (lc->lcOptions & CXO_MESSAGES) g_print (" CXO_MESSAGES");
109 if (lc->lcOptions & CXO_MARGIN) g_print (" CXO_MARGIN");
110 if (lc->lcOptions & CXO_MGNINSIDE) g_print (" CXO_MGNINSIDE");
111 if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
112 if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
114 g_print ("lcStatus =");
115 if (lc->lcStatus & CXS_DISABLED) g_print (" CXS_DISABLED");
116 if (lc->lcStatus & CXS_OBSCURED) g_print (" CXS_OBSCURED");
117 if (lc->lcStatus & CXS_ONTOP) g_print (" CXS_ONTOP");
119 g_print ("lcLocks =");
120 if (lc->lcLocks & CXL_INSIZE) g_print (" CXL_INSIZE");
121 if (lc->lcLocks & CXL_INASPECT) g_print (" CXL_INASPECT");
122 if (lc->lcLocks & CXL_SENSITIVITY) g_print (" CXL_SENSITIVITY");
123 if (lc->lcLocks & CXL_MARGIN) g_print (" CXL_MARGIN");
125 g_print ("lcMsgBase = %#x, lcDevice = %#x, lcPktRate = %d\n",
126 lc->lcMsgBase, lc->lcDevice, lc->lcPktRate);
127 g_print ("lcPktData =");
128 if (lc->lcPktData & PK_CONTEXT) g_print (" PK_CONTEXT");
129 if (lc->lcPktData & PK_STATUS) g_print (" PK_STATUS");
130 if (lc->lcPktData & PK_TIME) g_print (" PK_TIME");
131 if (lc->lcPktData & PK_CHANGED) g_print (" PK_CHANGED");
132 if (lc->lcPktData & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
133 if (lc->lcPktData & PK_CURSOR) g_print (" PK_CURSOR");
134 if (lc->lcPktData & PK_BUTTONS) g_print (" PK_BUTTONS");
135 if (lc->lcPktData & PK_X) g_print (" PK_X");
136 if (lc->lcPktData & PK_Y) g_print (" PK_Y");
137 if (lc->lcPktData & PK_Z) g_print (" PK_Z");
138 if (lc->lcPktData & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
139 if (lc->lcPktData & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
140 if (lc->lcPktData & PK_ORIENTATION) g_print (" PK_ORIENTATION");
141 if (lc->lcPktData & PK_ROTATION) g_print (" PK_ROTATION");
143 g_print ("lcPktMode =");
144 if (lc->lcPktMode & PK_CONTEXT) g_print (" PK_CONTEXT");
145 if (lc->lcPktMode & PK_STATUS) g_print (" PK_STATUS");
146 if (lc->lcPktMode & PK_TIME) g_print (" PK_TIME");
147 if (lc->lcPktMode & PK_CHANGED) g_print (" PK_CHANGED");
148 if (lc->lcPktMode & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
149 if (lc->lcPktMode & PK_CURSOR) g_print (" PK_CURSOR");
150 if (lc->lcPktMode & PK_BUTTONS) g_print (" PK_BUTTONS");
151 if (lc->lcPktMode & PK_X) g_print (" PK_X");
152 if (lc->lcPktMode & PK_Y) g_print (" PK_Y");
153 if (lc->lcPktMode & PK_Z) g_print (" PK_Z");
154 if (lc->lcPktMode & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
155 if (lc->lcPktMode & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
156 if (lc->lcPktMode & PK_ORIENTATION) g_print (" PK_ORIENTATION");
157 if (lc->lcPktMode & PK_ROTATION) g_print (" PK_ROTATION");
159 g_print ("lcMoveMask =");
160 if (lc->lcMoveMask & PK_CONTEXT) g_print (" PK_CONTEXT");
161 if (lc->lcMoveMask & PK_STATUS) g_print (" PK_STATUS");
162 if (lc->lcMoveMask & PK_TIME) g_print (" PK_TIME");
163 if (lc->lcMoveMask & PK_CHANGED) g_print (" PK_CHANGED");
164 if (lc->lcMoveMask & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
165 if (lc->lcMoveMask & PK_CURSOR) g_print (" PK_CURSOR");
166 if (lc->lcMoveMask & PK_BUTTONS) g_print (" PK_BUTTONS");
167 if (lc->lcMoveMask & PK_X) g_print (" PK_X");
168 if (lc->lcMoveMask & PK_Y) g_print (" PK_Y");
169 if (lc->lcMoveMask & PK_Z) g_print (" PK_Z");
170 if (lc->lcMoveMask & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
171 if (lc->lcMoveMask & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
172 if (lc->lcMoveMask & PK_ORIENTATION) g_print (" PK_ORIENTATION");
173 if (lc->lcMoveMask & PK_ROTATION) g_print (" PK_ROTATION");
175 g_print ("lcBtnDnMask = %#x, lcBtnUpMask = %#x\n",
176 (guint) lc->lcBtnDnMask, (guint) lc->lcBtnUpMask);
177 g_print ("lcInOrgX = %ld, lcInOrgY = %ld, lcInOrgZ = %ld\n",
178 lc->lcInOrgX, lc->lcInOrgY, lc->lcInOrgZ);
179 g_print ("lcInExtX = %ld, lcInExtY = %ld, lcInExtZ = %ld\n",
180 lc->lcInExtX, lc->lcInExtY, lc->lcInExtZ);
181 g_print ("lcOutOrgX = %ld, lcOutOrgY = %ld, lcOutOrgZ = %ld\n",
182 lc->lcOutOrgX, lc->lcOutOrgY, lc->lcOutOrgZ);
183 g_print ("lcOutExtX = %ld, lcOutExtY = %ld, lcOutExtZ = %ld\n",
184 lc->lcOutExtX, lc->lcOutExtY, lc->lcOutExtZ);
185 g_print ("lcSensX = %g, lcSensY = %g, lcSensZ = %g\n",
186 lc->lcSensX / 65536., lc->lcSensY / 65536., lc->lcSensZ / 65536.);
187 g_print ("lcSysMode = %d\n", lc->lcSysMode);
188 g_print ("lcSysOrgX = %d, lcSysOrgY = %d\n",
189 lc->lcSysOrgX, lc->lcSysOrgY);
190 g_print ("lcSysExtX = %d, lcSysExtY = %d\n",
191 lc->lcSysExtX, lc->lcSysExtY);
192 g_print ("lcSysSensX = %g, lcSysSensY = %g\n",
193 lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.);
199 gdk_input_wintab_init (void)
201 GdkDevicePrivate *gdkdev;
204 LOGCONTEXT defcontext;
206 UINT ndevices, ncursors, ncsrtypes, firstcsr, hardware;
208 AXIS axis_x, axis_y, axis_npressure, axis_or[3];
211 char devname[100], csrname[100];
213 _gdk_input_devices = NULL;
214 wintab_contexts = NULL;
216 if (!gdk_input_ignore_wintab &&
219 WTInfo (WTI_INTERFACE, IFC_SPECVERSION, &specversion);
220 GDK_NOTE (INPUT, g_print ("Wintab interface version %d.%d\n",
221 HIBYTE (specversion), LOBYTE (specversion)));
223 WTInfo (WTI_DEFSYSCTX, 0, &defcontext);
225 GDK_NOTE (INPUT, (g_print("DEFSYSCTX:\n"), print_lc(&defcontext)));
228 WTInfo (WTI_DEFCONTEXT, 0, &defcontext);
230 GDK_NOTE (INPUT, (g_print("DEFCONTEXT:\n"), print_lc(&defcontext)));
233 WTInfo (WTI_INTERFACE, IFC_NDEVICES, &ndevices);
234 WTInfo (WTI_INTERFACE, IFC_NCURSORS, &ncursors);
236 GDK_NOTE (INPUT, g_print ("NDEVICES: %d, NCURSORS: %d\n",
237 ndevices, ncursors));
239 /* Create a dummy window to receive wintab events */
240 wa.wclass = GDK_INPUT_OUTPUT;
241 wa.event_mask = GDK_ALL_EVENTS_MASK;
246 wa.window_type = GDK_WINDOW_TOPLEVEL;
247 if ((wintab_window = gdk_window_new (NULL, &wa, GDK_WA_X|GDK_WA_Y)) == NULL)
249 g_warning ("_gdk_input_init: gdk_window_new failed");
252 gdk_drawable_ref (wintab_window);
254 for (devix = 0; devix < ndevices; devix++)
258 WTInfo (WTI_DEVICES + devix, DVC_NAME, devname);
260 WTInfo (WTI_DEVICES + devix, DVC_NCSRTYPES, &ncsrtypes);
261 WTInfo (WTI_DEVICES + devix, DVC_FIRSTCSR, &firstcsr);
262 WTInfo (WTI_DEVICES + devix, DVC_HARDWARE, &hardware);
263 WTInfo (WTI_DEVICES + devix, DVC_X, &axis_x);
264 WTInfo (WTI_DEVICES + devix, DVC_Y, &axis_y);
265 WTInfo (WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure);
266 WTInfo (WTI_DEVICES + devix, DVC_ORIENTATION, axis_or);
268 if (HIBYTE (specversion) > 1 || LOBYTE (specversion) >= 1)
270 WTInfo (WTI_DDCTXS + devix, CTX_NAME, lc.lcName);
271 WTInfo (WTI_DDCTXS + devix, CTX_OPTIONS, &lc.lcOptions);
272 lc.lcOptions |= CXO_MESSAGES;
274 lc.lcOptions |= CXO_SYSTEM;
277 WTInfo (WTI_DDCTXS + devix, CTX_LOCKS, &lc.lcLocks);
278 lc.lcMsgBase = WT_DEFBASE;
281 lc.lcPktData = PACKETDATA;
282 lc.lcPktMode = PK_BUTTONS; /* We want buttons in relative mode */
283 lc.lcMoveMask = PACKETDATA;
284 lc.lcBtnDnMask = lc.lcBtnUpMask = ~0;
285 WTInfo (WTI_DDCTXS + devix, CTX_INORGX, &lc.lcInOrgX);
286 WTInfo (WTI_DDCTXS + devix, CTX_INORGY, &lc.lcInOrgY);
287 WTInfo (WTI_DDCTXS + devix, CTX_INORGZ, &lc.lcInOrgZ);
288 WTInfo (WTI_DDCTXS + devix, CTX_INEXTX, &lc.lcInExtX);
289 WTInfo (WTI_DDCTXS + devix, CTX_INEXTY, &lc.lcInExtY);
290 WTInfo (WTI_DDCTXS + devix, CTX_INEXTZ, &lc.lcInExtZ);
291 lc.lcOutOrgX = axis_x.axMin;
292 lc.lcOutOrgY = axis_y.axMin;
293 lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
294 lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
295 lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
296 WTInfo (WTI_DDCTXS + devix, CTX_SENSX, &lc.lcSensX);
297 WTInfo (WTI_DDCTXS + devix, CTX_SENSY, &lc.lcSensY);
298 WTInfo (WTI_DDCTXS + devix, CTX_SENSZ, &lc.lcSensZ);
299 WTInfo (WTI_DDCTXS + devix, CTX_SYSMODE, &lc.lcSysMode);
300 lc.lcSysOrgX = lc.lcSysOrgY = 0;
301 WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTX, &lc.lcSysExtX);
302 WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTY, &lc.lcSysExtY);
303 WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSX, &lc.lcSysSensX);
304 WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSY, &lc.lcSysSensY);
309 lc.lcOptions |= CXO_MESSAGES;
310 lc.lcMsgBase = WT_DEFBASE;
312 lc.lcPktData = PACKETDATA;
313 lc.lcPktMode = PACKETMODE;
314 lc.lcMoveMask = PACKETDATA;
315 lc.lcBtnUpMask = lc.lcBtnDnMask = ~0;
317 lc.lcOutExtY = -lc.lcOutExtY; /* Y grows downward */
319 lc.lcOutOrgX = axis_x.axMin;
320 lc.lcOutOrgY = axis_y.axMin;
321 lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
322 lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
323 lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
327 GDK_NOTE (INPUT, (g_print("context for device %d:\n", devix),
330 hctx = g_new (HCTX, 1);
331 if ((*hctx = WTOpen (GDK_WINDOW_HWND (wintab_window), &lc, TRUE)) == NULL)
333 g_warning ("_gdk_input_init: WTOpen failed");
336 GDK_NOTE (INPUT, g_print ("opened Wintab device %d %p\n",
339 wintab_contexts = g_list_append (wintab_contexts, hctx);
341 WTEnable (*hctx, TRUE);
343 WTOverlap (*hctx, TRUE);
346 GDK_NOTE (INPUT, (g_print("context for device %d after WTOpen:\n", devix),
349 for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes; cursorix++)
352 WTInfo (WTI_CURSORS + cursorix, CSR_ACTIVE, &active);
355 gdkdev = g_object_new (GDK_TYPE_DEVICE, NULL);
356 WTInfo (WTI_CURSORS + cursorix, CSR_NAME, csrname);
357 gdkdev->info.name = g_strconcat (devname, " ", csrname, NULL);
358 gdkdev->info.source = GDK_SOURCE_PEN;
359 gdkdev->info.mode = GDK_MODE_SCREEN;
361 gdkdev->info.has_cursor = TRUE;
363 gdkdev->info.has_cursor = FALSE;
365 gdkdev->hctx = *hctx;
366 gdkdev->cursor = cursorix;
367 WTInfo (WTI_CURSORS + cursorix, CSR_PKTDATA, &gdkdev->pktdata);
368 gdkdev->info.num_axes = 0;
369 if (gdkdev->pktdata & PK_X)
370 gdkdev->info.num_axes++;
371 if (gdkdev->pktdata & PK_Y)
372 gdkdev->info.num_axes++;
373 if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
374 gdkdev->info.num_axes++;
375 /* The wintab driver for the Wacom ArtPad II reports
376 * PK_ORIENTATION in CSR_PKTDATA, but the tablet doesn't
377 * actually sense tilt. Catch this by noticing that the
378 * orientation axis's azimuth resolution is zero.
380 if ((gdkdev->pktdata & PK_ORIENTATION)
381 && axis_or[0].axResolution == 0)
382 gdkdev->pktdata &= ~PK_ORIENTATION;
384 if (gdkdev->pktdata & PK_ORIENTATION)
385 gdkdev->info.num_axes += 2; /* x and y tilt */
386 WTInfo (WTI_CURSORS + cursorix, CSR_NPBTNMARKS, &gdkdev->npbtnmarks);
387 gdkdev->info.axes = g_new (GdkDeviceAxis, gdkdev->info.num_axes);
388 gdkdev->axes = g_new (GdkAxisInfo, gdkdev->info.num_axes);
389 gdkdev->last_axis_data = g_new (gint, gdkdev->info.num_axes);
392 if (gdkdev->pktdata & PK_X)
394 gdkdev->axes[k].xresolution =
395 gdkdev->axes[k].resolution = axis_x.axResolution / 65535.;
396 gdkdev->axes[k].xmin_value =
397 gdkdev->axes[k].min_value = axis_x.axMin;
398 gdkdev->axes[k].xmax_value =
399 gdkdev->axes[k].max_value = axis_x.axMax;
400 gdkdev->info.axes[k].use = GDK_AXIS_X;
401 gdkdev->info.axes[k].min = axis_x.axMin;
402 gdkdev->info.axes[k].min = axis_x.axMax;
405 if (gdkdev->pktdata & PK_Y)
407 gdkdev->axes[k].xresolution =
408 gdkdev->axes[k].resolution = axis_y.axResolution / 65535.;
409 gdkdev->axes[k].xmin_value =
410 gdkdev->axes[k].min_value = axis_y.axMin;
411 gdkdev->axes[k].xmax_value =
412 gdkdev->axes[k].max_value = axis_y.axMax;
413 gdkdev->info.axes[k].use = GDK_AXIS_Y;
414 gdkdev->info.axes[k].min = axis_y.axMin;
415 gdkdev->info.axes[k].min = axis_y.axMax;
418 if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
420 gdkdev->axes[k].xresolution =
421 gdkdev->axes[k].resolution = axis_npressure.axResolution / 65535.;
422 gdkdev->axes[k].xmin_value =
423 gdkdev->axes[k].min_value = axis_npressure.axMin;
424 gdkdev->axes[k].xmax_value =
425 gdkdev->axes[k].max_value = axis_npressure.axMax;
426 gdkdev->info.axes[k].use = GDK_AXIS_PRESSURE;
427 gdkdev->info.axes[k].min = axis_npressure.axMin;
428 gdkdev->info.axes[k].min = axis_npressure.axMax;
431 if (gdkdev->pktdata & PK_ORIENTATION)
435 gdkdev->orientation_axes[0] = axis_or[0];
436 gdkdev->orientation_axes[1] = axis_or[1];
437 for (axis = GDK_AXIS_XTILT; axis <= GDK_AXIS_YTILT; axis++)
439 /* Wintab gives us aximuth and altitude, which
440 * we convert to x and y tilt in the -1000..1000 range
442 gdkdev->axes[k].xresolution =
443 gdkdev->axes[k].resolution = 1000;
444 gdkdev->axes[k].xmin_value =
445 gdkdev->axes[k].min_value = -1000;
446 gdkdev->axes[k].xmax_value =
447 gdkdev->axes[k].max_value = 1000;
448 gdkdev->info.axes[k].use = axis;
449 gdkdev->info.axes[k].min = -1000;
450 gdkdev->info.axes[k].min = 1000;
454 gdkdev->info.num_keys = 0;
455 gdkdev->info.keys = NULL;
457 g_print ("device: (%d) %s axes: %d\n",
460 gdkdev->info.num_axes));
461 for (i = 0; i < gdkdev->info.num_axes; i++)
463 g_print ("...axis %d: %d--%d@%d (%d--%d@%d)\n",
465 gdkdev->axes[i].xmin_value,
466 gdkdev->axes[i].xmax_value,
467 gdkdev->axes[i].xresolution,
468 gdkdev->axes[i].min_value,
469 gdkdev->axes[i].max_value,
470 gdkdev->axes[i].resolution));
471 _gdk_input_devices = g_list_append (_gdk_input_devices,
479 decode_tilt (gint *axis_data,
483 /* As I don't have a tilt-sensing tablet,
484 * I cannot test this code.
489 az = TWOPI * packet->pkOrientation.orAzimuth /
490 (axes[0].axResolution / 65536.);
491 el = TWOPI * packet->pkOrientation.orAltitude /
492 (axes[1].axResolution / 65536.);
495 axis_data[0] = cos (az) * cos (el) * 1000;
497 axis_data[1] = sin (az) * cos (el) * 1000;
502 static GdkInputWindow *
503 gdk_input_window_find_within (GdkWindow *window)
507 GdkInputWindow *candidate = NULL;
509 for (list = _gdk_input_windows; list != NULL; list = list->next)
511 tmpw = ((GdkInputWindow *) (tmp_list->data))->window;
513 || IsChild (GDK_WINDOW_HWND (window), GDK_WINDOW_HWND (tmpw)))
516 return NULL; /* Multiple hits */
517 candidate = (GdkInputWindow *) (list->data);
524 #endif /* USE_SYSCONTEXT */
526 #endif /* HAVE_WINTAB */
529 gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
530 GdkInputWindow *input_window,
536 GdkWindowImplWin32 *impl;
542 double device_width, device_height;
543 double x_offset, y_offset, x_scale, y_scale;
545 impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (input_window->window)->impl);
547 for (i=0; i<gdkdev->info.num_axes; i++)
549 switch (gdkdev->info.axes[i].use)
562 device_width = gdkdev->axes[x_axis].max_value -
563 gdkdev->axes[x_axis].min_value;
564 device_height = gdkdev->axes[y_axis].max_value -
565 gdkdev->axes[y_axis].min_value;
567 if (gdkdev->info.mode == GDK_MODE_SCREEN)
569 x_scale = gdk_screen_width() / device_width;
570 y_scale = gdk_screen_height() / device_height;
572 x_offset = - input_window->root_x;
573 y_offset = - input_window->root_y;
575 else /* GDK_MODE_WINDOW */
577 double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
578 (device_width*gdkdev->axes[x_axis].resolution);
580 if (device_aspect * impl->width >= impl->height)
582 /* device taller than window */
583 x_scale = impl->width / device_width;
584 y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
585 / gdkdev->axes[y_axis].resolution;
588 y_offset = -(device_height * y_scale -
593 /* window taller than device */
594 y_scale = impl->height / device_height;
595 x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
596 / gdkdev->axes[x_axis].resolution;
599 x_offset = - (device_width * x_scale - impl->width)/2;
603 for (i=0; i<gdkdev->info.num_axes; i++)
605 switch (gdkdev->info.axes[i].use)
608 axis_out[i] = x_offset + x_scale*axis_data[x_axis];
610 *x_out = axis_out[i];
613 axis_out[i] = y_offset + y_scale*axis_data[y_axis];
615 *y_out = axis_out[i];
619 (gdkdev->info.axes[i].max * (axis_data[i] - gdkdev->axes[i].min_value) +
620 gdkdev->info.axes[i].min * (gdkdev->axes[i].max_value - axis_data[i])) /
621 (gdkdev->axes[i].max_value - gdkdev->axes[i].min_value);
628 gdk_input_get_root_relative_geometry (HWND w,
634 GetWindowRect (w, &rect);
643 gdk_input_motion_events (GdkWindow *window,
647 gint *nevents_return)
649 g_return_val_if_fail (window != NULL, NULL);
650 if (GDK_WINDOW_DESTROYED (window))
654 return NULL; /* ??? */
658 _gdk_input_configure_event (GdkEventConfigure *event,
661 GdkInputWindow *input_window;
664 input_window = gdk_input_window_find (window);
665 g_return_if_fail (window != NULL);
667 gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window),
670 input_window->root_x = root_x;
671 input_window->root_y = root_y;
675 _gdk_input_enter_event (GdkEventCrossing *event,
678 GdkInputWindow *input_window;
681 input_window = gdk_input_window_find (window);
682 g_return_if_fail (window != NULL);
684 gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window), &root_x, &root_y);
686 input_window->root_x = root_x;
687 input_window->root_y = root_y;
691 _gdk_input_other_event (GdkEvent *event,
697 GdkWindow *current_window;
700 GdkWindowObject *obj;
701 GdkWindowImplWin32 *impl;
702 GdkInputWindow *input_window;
703 GdkDevicePrivate *gdkdev = NULL;
704 GdkEventMask masktest;
711 if (event->any.window != wintab_window)
713 g_warning ("_gdk_input_other_event: not wintab_window?");
718 window = gdk_window_at_pointer (&x, &y);
720 window = _gdk_parent_root;
722 gdk_drawable_ref (window);
723 display = gdk_drawable_get_display (window);
725 GDK_NOTE (EVENTS_OR_INPUT,
726 g_print ("gdk_input_win32_other_event: window=%p (%d,%d)\n",
727 GDK_WINDOW_HWND (window), x, y));
730 /* ??? This code is pretty bogus */
731 current_window = gdk_win32_handle_table_lookup (GetActiveWindow ());
732 if (current_window == NULL)
735 input_window = gdk_input_window_find_within (current_window);
736 if (input_window == NULL)
740 if (msg->message == WT_PACKET)
742 if (!WTPacket ((HCTX) msg->lParam, msg->wParam, &packet))
746 obj = GDK_WINDOW_OBJECT (window);
747 impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
749 switch (msg->message)
752 if (window == _gdk_parent_root)
754 GDK_NOTE (EVENTS_OR_INPUT, g_print ("...is root\n"));
758 if ((gdkdev = gdk_input_find_dev_from_ctx ((HCTX) msg->lParam,
759 packet.pkCursor)) == NULL)
762 if (gdkdev->info.mode == GDK_MODE_DISABLED)
766 if (gdkdev->pktdata & PK_X)
767 gdkdev->last_axis_data[k++] = packet.pkX;
768 if (gdkdev->pktdata & PK_Y)
769 gdkdev->last_axis_data[k++] = packet.pkY;
770 if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
771 gdkdev->last_axis_data[k++] = packet.pkNormalPressure;
772 if (gdkdev->pktdata & PK_ORIENTATION)
774 decode_tilt (gdkdev->last_axis_data + k,
775 gdkdev->orientation_axes, &packet);
779 g_assert (k == gdkdev->info.num_axes);
781 if (HIWORD (packet.pkButtons) != TBN_NONE)
783 /* Gdk buttons are numbered 1.. */
784 event->button.button = 1 + LOWORD (packet.pkButtons);
786 if (HIWORD (packet.pkButtons) == TBN_UP)
788 event->any.type = GDK_BUTTON_RELEASE;
789 masktest = GDK_BUTTON_RELEASE_MASK;
790 gdkdev->button_state &= ~(1 << LOWORD (packet.pkButtons));
794 event->any.type = GDK_BUTTON_PRESS;
795 masktest = GDK_BUTTON_PRESS_MASK;
796 gdkdev->button_state |= 1 << LOWORD (packet.pkButtons);
801 event->any.type = GDK_MOTION_NOTIFY;
802 masktest = GDK_POINTER_MOTION_MASK;
803 if (gdkdev->button_state & (1 << 0))
804 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK;
805 if (gdkdev->button_state & (1 << 1))
806 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK;
807 if (gdkdev->button_state & (1 << 2))
808 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK;
811 /* Now we can check if the window wants the event, and
812 * propagate if necessary.
815 if (!impl->extension_events_selected
816 || !(obj->extension_events & masktest))
818 GDK_NOTE (EVENTS_OR_INPUT, g_print ("...not selected\n"));
820 if (obj->parent == GDK_WINDOW_OBJECT (_gdk_parent_root))
825 ClientToScreen (GDK_WINDOW_HWND (window), &pt);
826 gdk_drawable_unref (window);
827 window = (GdkWindow *) obj->parent;
828 obj = GDK_WINDOW_OBJECT (window);
829 gdk_drawable_ref (window);
830 ScreenToClient (GDK_WINDOW_HWND (window), &pt);
833 GDK_NOTE (EVENTS_OR_INPUT, g_print ("...propagating to %p (%d,%d)\n",
834 GDK_WINDOW_HWND (window), x, y));
838 input_window = gdk_input_window_find (window);
840 g_assert (input_window != NULL);
842 if (gdkdev->info.mode == GDK_MODE_WINDOW
843 && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
846 event->any.window = window;
848 if (event->any.type == GDK_BUTTON_PRESS
849 || event->any.type == GDK_BUTTON_RELEASE)
851 event->button.time = msg->time;
852 event->button.device = &gdkdev->info;
856 /* Buttons 1 to 3 will come in as WM_[LMR]BUTTON{DOWN,UP} */
857 if (event->button.button <= 3)
861 gdk_input_translate_coordinates (gdkdev, input_window,
862 gdkdev->last_axis_data,
867 event->button.state = ((gdkdev->button_state << 8)
868 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
869 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
870 | GDK_BUTTON5_MASK));
871 GDK_NOTE (EVENTS_OR_INPUT,
872 g_print ("WINTAB button %s:%d %g,%g\n",
873 (event->button.type == GDK_BUTTON_PRESS ?
874 "press" : "release"),
875 event->button.button,
876 event->button.x, event->button.y));
880 event->motion.time = msg->time;
881 event->motion.is_hint = FALSE;
882 event->motion.device = &gdkdev->info;
884 gdk_input_translate_coordinates (gdkdev, input_window,
885 gdkdev->last_axis_data,
890 event->motion.state = ((gdkdev->button_state << 8)
891 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
892 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
893 | GDK_BUTTON5_MASK));
895 GDK_NOTE (EVENTS_OR_INPUT,
896 g_print ("WINTAB motion: %g,%g\n",
897 event->motion.x, event->motion.y));
899 /* Check for missing release or press events for the normal
900 * pressure button. At least on my ArtPadII I sometimes miss a
903 if ((gdkdev->pktdata & PK_NORMAL_PRESSURE
904 && (event->motion.state & GDK_BUTTON1_MASK)
905 && packet.pkNormalPressure <= MAX (0, gdkdev->npbtnmarks[0] - 2))
906 || (gdkdev->pktdata & PK_NORMAL_PRESSURE
907 && !(event->motion.state & GDK_BUTTON1_MASK)
908 && packet.pkNormalPressure > gdkdev->npbtnmarks[1] + 2))
910 GdkEvent *event2 = gdk_event_copy (event);
911 if (event->motion.state & GDK_BUTTON1_MASK)
913 event2->button.type = GDK_BUTTON_RELEASE;
914 gdkdev->button_state &= ~1;
918 event2->button.type = GDK_BUTTON_PRESS;
919 gdkdev->button_state |= 1;
921 event2->button.state = ((gdkdev->button_state << 8)
922 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
923 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
924 | GDK_BUTTON5_MASK));
925 event2->button.button = 1;
926 GDK_NOTE (EVENTS_OR_INPUT,
927 g_print ("WINTAB synthesized button %s: %d %g,%gg\n",
928 (event2->button.type == GDK_BUTTON_PRESS ?
929 "press" : "release"),
930 event2->button.button,
933 _gdk_event_queue_append (display, event2);
939 if (LOWORD (msg->lParam) == 0)
941 event->proximity.type = GDK_PROXIMITY_OUT;
942 _gdk_input_ignore_core = FALSE;
946 event->proximity.type = GDK_PROXIMITY_IN;
947 _gdk_input_ignore_core = TRUE;
949 event->proximity.time = msg->time;
950 event->proximity.device = &gdkdev->info;
952 GDK_NOTE (EVENTS_OR_INPUT,
953 g_print ("WINTAB proximity %s\n",
954 (event->proximity.type == GDK_PROXIMITY_IN ?
963 _gdk_input_enable_window (GdkWindow *window,
964 GdkDevicePrivate *gdkdev)
966 #ifdef HAVE_SOME_XINPUT
967 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
969 impl->extension_events_selected = TRUE;
976 _gdk_input_disable_window (GdkWindow *window,
977 GdkDevicePrivate *gdkdev)
979 #ifdef HAVE_SOME_XINPUT
980 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
982 impl->extension_events_selected = FALSE;
989 _gdk_input_grab_pointer (GdkWindow *window,
991 GdkEventMask event_mask,
992 GdkWindow *confine_to,
995 #ifdef HAVE_SOME_XINPUT
996 GdkInputWindow *input_window, *new_window;
997 gboolean need_ungrab;
998 GdkDevicePrivate *gdkdev;
1001 tmp_list = _gdk_input_windows;
1003 need_ungrab = FALSE;
1005 GDK_NOTE (INPUT, g_print ("gdk_input_win32_grab_pointer: %p %d %p\n",
1006 GDK_WINDOW_HWND (window),
1008 (confine_to ? GDK_WINDOW_HWND (confine_to) : 0)));
1012 input_window = (GdkInputWindow *)tmp_list->data;
1014 if (input_window->window == window)
1015 new_window = input_window;
1016 else if (input_window->grabbed)
1018 input_window->grabbed = FALSE;
1022 tmp_list = tmp_list->next;
1027 new_window->grabbed = TRUE;
1029 tmp_list = _gdk_input_devices;
1032 gdkdev = (GdkDevicePrivate *)tmp_list->data;
1033 if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx)
1037 gdk_input_common_find_events (window, gdkdev,
1039 event_classes, &num_classes);
1041 result = XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
1042 GDK_WINDOW_XWINDOW (window),
1043 owner_events, num_classes, event_classes,
1044 GrabModeAsync, GrabModeAsync, time);
1046 /* FIXME: if failure occurs on something other than the first
1047 device, things will be badly inconsistent */
1048 if (result != Success)
1052 tmp_list = tmp_list->next;
1057 tmp_list = _gdk_input_devices;
1060 gdkdev = (GdkDevicePrivate *)tmp_list->data;
1061 if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx &&
1062 ((gdkdev->button_state != 0) || need_ungrab))
1066 XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1068 gdkdev->button_state = 0;
1071 tmp_list = tmp_list->next;
1076 return GDK_GRAB_SUCCESS;
1080 _gdk_input_ungrab_pointer (guint32 time)
1082 #ifdef HAVE_SOME_XINPUT
1083 GdkInputWindow *input_window;
1084 GdkDevicePrivate *gdkdev;
1087 GDK_NOTE (INPUT, g_print ("gdk_input_win32_ungrab_pointer\n"));
1089 tmp_list = _gdk_input_windows;
1092 input_window = (GdkInputWindow *)tmp_list->data;
1093 if (input_window->grabbed)
1095 tmp_list = tmp_list->next;
1098 if (tmp_list) /* we found a grabbed window */
1100 input_window->grabbed = FALSE;
1102 tmp_list = _gdk_input_devices;
1105 gdkdev = (GdkDevicePrivate *)tmp_list->data;
1108 if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
1109 XUngrabDevice (gdk_display, gdkdev->xdevice, time);
1111 tmp_list = tmp_list->next;
1118 _gdk_input_window_none_event (GdkEvent *event,
1125 _gdk_device_get_history (GdkDevice *device,
1129 GdkTimeCoord ***events,
1136 gdk_device_get_state (GdkDevice *device,
1139 GdkModifierType *mask)
1141 g_return_if_fail (device != NULL);
1142 g_return_if_fail (GDK_IS_WINDOW (window));
1144 if (GDK_IS_CORE (device))
1148 gdk_window_get_pointer (window, &x_int, &y_int, mask);
1158 GdkDevicePrivate *gdkdev;
1159 GdkInputWindow *input_window;
1162 gdk_window_get_pointer (window, NULL, NULL, mask);
1164 gdkdev = (GdkDevicePrivate *)device;
1165 input_window = gdk_input_window_find (window);
1166 g_return_if_fail (input_window != NULL);
1169 state = XQueryDeviceState (gdk_display, gdkdev->xdevice);
1170 input_class = state->data;
1171 for (i = 0; i < state->num_classes; i++)
1173 switch (input_class->class)
1177 gdk_input_translate_coordinates (gdkdev, input_window,
1178 ((XValuatorState *)input_class)->valuators,
1186 if (((XButtonState *)input_class)->num_buttons > 0)
1187 *mask |= ((XButtonState *)input_class)->buttons[0] << 7;
1188 /* GDK_BUTTON1_MASK = 1 << 8, and button n is stored
1189 * in bit 1<<(n%8) in byte n/8. n = 1,2,... */
1193 input_class = (XInputClass *)(((char *)input_class)+input_class->length);
1195 XFreeDeviceState (state);
1201 _gdk_input_init (void)
1203 _gdk_input_ignore_core = FALSE;
1204 _gdk_input_devices = NULL;
1206 _gdk_init_input_core ();
1208 gdk_input_wintab_init ();
1209 #endif /* HAVE_WINTAB */
1211 _gdk_input_devices = g_list_append (_gdk_input_devices, display->core_pointer);