ROOT  6.05/03
Reference Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
gdkinput-win32.c
Go to the documentation of this file.
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  * Copyright (C) 1999 Tor Lillqvist
4  *
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.
9  *
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.
14  *
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.
19  */
20 
21 /*
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/.
26  */
27 
28 #include "config.h"
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <math.h>
33 
34 #include "gdk.h"
35 #include "gdkinput.h"
36 #include "gdkprivate.h"
37 #include "gdkwin32.h"
38 
39 #ifdef HAVE_WINTAB
40 #include "d:\development\wtkit\include\wintab.h"
41 #define PACKETDATA (PK_CONTEXT | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION)
42 #define PACKETMODE (PK_BUTTONS)
43 #include "d:\development\wtkit\include\pktdef.h"
44 #endif
45 
46 #include "gdkinputprivate.h"
47 
48 struct _GdkDevicePrivate {
49  GdkDeviceInfo info;
50 
51  /* information about the axes */
52  GdkAxisInfo *axes;
53 
54  /* reverse lookup on axis use type */
55  gint axis_for_use[GDK_AXIS_LAST];
56 
57  /* true if we need to select a different set of events, but
58  * can't because this is the core pointer
59  */
60  gint needs_update;
61 
62  /* State of buttons */
63  gint button_state;
64 
65  gint *last_axis_data;
66  gint last_buttons;
67 #ifdef HAVE_WINTAB
68  /* WINTAB stuff: */
69  HCTX hctx;
70  /* Cursor number */
71  UINT cursor;
72  /* The cursor's CSR_PKTDATA */
73  WTPKT pktdata;
74  /* CSR_NPBTNMARKS */
75  UINT npbtnmarks[2];
76  /* Azimuth and altitude axis */
77  AXIS orientation_axes[2];
78 #endif
79 };
80 
81 #ifndef G_PI
82 #define G_PI 3.14159265358979323846
83 #endif
84 
85 /* If USE_SYSCONTEXT is on, we open the Wintab device (hmm, what if
86  * there are several?) as a system pointing device, i.e. it controls
87  * the normal Windows cursor. This seems much more natural.
88  */
89 #define USE_SYSCONTEXT 1 /* The code for the other choice is not
90  * good at all.
91  */
92 
93 #ifdef HAVE_WINTAB
94 #define DEBUG_WINTAB 1
95 #endif
96 
97 #define TWOPI (2.*G_PI)
98 
99 /* Forward declarations */
100 
101 static gint gdk_input_enable_window(GdkWindow * window,
102  GdkDevicePrivate * gdkdev);
103 static gint gdk_input_disable_window(GdkWindow * window,
104  GdkDevicePrivate * gdkdev);
105 static void gdk_input_none_get_pointer(GdkWindow * window,
106  guint32 deviceid,
107  gdouble * x,
108  gdouble * y,
109  gdouble * pressure,
110  gdouble * xtilt,
111  gdouble * ytilt,
112  GdkModifierType * mask);
113 
115 
116 #ifdef HAVE_WINTAB
117 
118 static gint gdk_input_win32_set_mode(guint32 deviceid, GdkInputMode mode);
119 static void gdk_input_win32_get_pointer(GdkWindow * window,
120  guint32 deviceid,
121  gdouble * x,
122  gdouble * y,
123  gdouble * pressure,
124  gdouble * xtilt,
125  gdouble * ytilt,
126  GdkModifierType * mask);
127 static gint gdk_input_win32_grab_pointer(GdkWindow * window,
128  gint owner_events,
129  GdkEventMask event_mask,
130  GdkWindow * confine_to,
131  guint32 time);
132 static void gdk_input_win32_ungrab_pointer(guint32 time);
133 static void gdk_input_win32_configure_event(GdkEventConfigure * event,
134  GdkWindow * window);
135 static void gdk_input_win32_enter_event(GdkEventCrossing * xevent,
136  GdkWindow * window);
137 static gint gdk_input_win32_other_event(GdkEvent * event, MSG * xevent);
138 static gint gdk_input_win32_enable_window(GdkWindow * window,
139  GdkDevicePrivate * gdkdev);
140 static gint gdk_input_win32_disable_window(GdkWindow * window,
141  GdkDevicePrivate * gdkdev);
142 
144 #if !USE_SYSCONTEXT
145 static GdkInputWindow *gdk_input_window_find_within(GdkWindow * window);
146 #endif
147 static GdkDevicePrivate *gdk_input_find_dev_from_ctx(HCTX hctx, UINT id);
148 #endif /* HAVE_WINTAB */
149 
150 /* Local variables */
151 
155 
158 
160 
162 
164 
165 static GdkDeviceInfo gdk_input_core_info = {
167  "Core Pointer",
170  TRUE,
171  2,
172  gdk_input_core_axes
173 };
174 
175 /* Global variables */
176 
180 
181 #if DEBUG_WINTAB
182 
183 static void print_lc(LOGCONTEXT * lc)
184 {
185  g_print("lcName = %s\n", lc->lcName);
186  g_print("lcOptions =");
187  if (lc->lcOptions & CXO_SYSTEM)
188  g_print(" CXO_SYSTEM");
189  if (lc->lcOptions & CXO_PEN)
190  g_print(" CXO_PEN");
191  if (lc->lcOptions & CXO_MESSAGES)
192  g_print(" CXO_MESSAGES");
193  if (lc->lcOptions & CXO_MARGIN)
194  g_print(" CXO_MARGIN");
195  if (lc->lcOptions & CXO_MGNINSIDE)
196  g_print(" CXO_MGNINSIDE");
197  if (lc->lcOptions & CXO_CSRMESSAGES)
198  g_print(" CXO_CSRMESSAGES");
199  if (lc->lcOptions & CXO_CSRMESSAGES)
200  g_print(" CXO_CSRMESSAGES");
201  g_print("\n");
202  g_print("lcStatus =");
203  if (lc->lcStatus & CXS_DISABLED)
204  g_print(" CXS_DISABLED");
205  if (lc->lcStatus & CXS_OBSCURED)
206  g_print(" CXS_OBSCURED");
207  if (lc->lcStatus & CXS_ONTOP)
208  g_print(" CXS_ONTOP");
209  g_print("\n");
210  g_print("lcLocks =");
211  if (lc->lcLocks & CXL_INSIZE)
212  g_print(" CXL_INSIZE");
213  if (lc->lcLocks & CXL_INASPECT)
214  g_print(" CXL_INASPECT");
215  if (lc->lcLocks & CXL_SENSITIVITY)
216  g_print(" CXL_SENSITIVITY");
217  if (lc->lcLocks & CXL_MARGIN)
218  g_print(" CXL_MARGIN");
219  g_print("\n");
220  g_print("lcMsgBase = %#x, lcDevice = %#x, lcPktRate = %d\n",
221  lc->lcMsgBase, lc->lcDevice, lc->lcPktRate);
222  g_print("lcPktData =");
223  if (lc->lcPktData & PK_CONTEXT)
224  g_print(" PK_CONTEXT");
225  if (lc->lcPktData & PK_STATUS)
226  g_print(" PK_STATUS");
227  if (lc->lcPktData & PK_TIME)
228  g_print(" PK_TIME");
229  if (lc->lcPktData & PK_CHANGED)
230  g_print(" PK_CHANGED");
231  if (lc->lcPktData & PK_SERIAL_NUMBER)
232  g_print(" PK_SERIAL_NUMBER");
233  if (lc->lcPktData & PK_CURSOR)
234  g_print(" PK_CURSOR");
235  if (lc->lcPktData & PK_BUTTONS)
236  g_print(" PK_BUTTONS");
237  if (lc->lcPktData & PK_X)
238  g_print(" PK_X");
239  if (lc->lcPktData & PK_Y)
240  g_print(" PK_Y");
241  if (lc->lcPktData & PK_Z)
242  g_print(" PK_Z");
243  if (lc->lcPktData & PK_NORMAL_PRESSURE)
244  g_print(" PK_NORMAL_PRESSURE");
245  if (lc->lcPktData & PK_TANGENT_PRESSURE)
246  g_print(" PK_TANGENT_PRESSURE");
247  if (lc->lcPktData & PK_ORIENTATION)
248  g_print(" PK_ORIENTATION");
249  if (lc->lcPktData & PK_ROTATION)
250  g_print(" PK_ROTATION");
251  g_print("\n");
252  g_print("lcPktMode =");
253  if (lc->lcPktMode & PK_CONTEXT)
254  g_print(" PK_CONTEXT");
255  if (lc->lcPktMode & PK_STATUS)
256  g_print(" PK_STATUS");
257  if (lc->lcPktMode & PK_TIME)
258  g_print(" PK_TIME");
259  if (lc->lcPktMode & PK_CHANGED)
260  g_print(" PK_CHANGED");
261  if (lc->lcPktMode & PK_SERIAL_NUMBER)
262  g_print(" PK_SERIAL_NUMBER");
263  if (lc->lcPktMode & PK_CURSOR)
264  g_print(" PK_CURSOR");
265  if (lc->lcPktMode & PK_BUTTONS)
266  g_print(" PK_BUTTONS");
267  if (lc->lcPktMode & PK_X)
268  g_print(" PK_X");
269  if (lc->lcPktMode & PK_Y)
270  g_print(" PK_Y");
271  if (lc->lcPktMode & PK_Z)
272  g_print(" PK_Z");
273  if (lc->lcPktMode & PK_NORMAL_PRESSURE)
274  g_print(" PK_NORMAL_PRESSURE");
275  if (lc->lcPktMode & PK_TANGENT_PRESSURE)
276  g_print(" PK_TANGENT_PRESSURE");
277  if (lc->lcPktMode & PK_ORIENTATION)
278  g_print(" PK_ORIENTATION");
279  if (lc->lcPktMode & PK_ROTATION)
280  g_print(" PK_ROTATION");
281  g_print("\n");
282  g_print("lcMoveMask =");
283  if (lc->lcMoveMask & PK_CONTEXT)
284  g_print(" PK_CONTEXT");
285  if (lc->lcMoveMask & PK_STATUS)
286  g_print(" PK_STATUS");
287  if (lc->lcMoveMask & PK_TIME)
288  g_print(" PK_TIME");
289  if (lc->lcMoveMask & PK_CHANGED)
290  g_print(" PK_CHANGED");
291  if (lc->lcMoveMask & PK_SERIAL_NUMBER)
292  g_print(" PK_SERIAL_NUMBER");
293  if (lc->lcMoveMask & PK_CURSOR)
294  g_print(" PK_CURSOR");
295  if (lc->lcMoveMask & PK_BUTTONS)
296  g_print(" PK_BUTTONS");
297  if (lc->lcMoveMask & PK_X)
298  g_print(" PK_X");
299  if (lc->lcMoveMask & PK_Y)
300  g_print(" PK_Y");
301  if (lc->lcMoveMask & PK_Z)
302  g_print(" PK_Z");
303  if (lc->lcMoveMask & PK_NORMAL_PRESSURE)
304  g_print(" PK_NORMAL_PRESSURE");
305  if (lc->lcMoveMask & PK_TANGENT_PRESSURE)
306  g_print(" PK_TANGENT_PRESSURE");
307  if (lc->lcMoveMask & PK_ORIENTATION)
308  g_print(" PK_ORIENTATION");
309  if (lc->lcMoveMask & PK_ROTATION)
310  g_print(" PK_ROTATION");
311  g_print("\n");
312  g_print("lcBtnDnMask = %#x, lcBtnUpMask = %#x\n",
313  lc->lcBtnDnMask, lc->lcBtnUpMask);
314  g_print("lcInOrgX = %d, lcInOrgY = %d, lcInOrgZ = %d\n",
315  lc->lcInOrgX, lc->lcInOrgY, lc->lcInOrgZ);
316  g_print("lcInExtX = %d, lcInExtY = %d, lcInExtZ = %d\n",
317  lc->lcInExtX, lc->lcInExtY, lc->lcInExtZ);
318  g_print("lcOutOrgX = %d, lcOutOrgY = %d, lcOutOrgZ = %d\n",
319  lc->lcOutOrgX, lc->lcOutOrgY, lc->lcOutOrgZ);
320  g_print("lcOutExtX = %d, lcOutExtY = %d, lcOutExtZ = %d\n",
321  lc->lcOutExtX, lc->lcOutExtY, lc->lcOutExtZ);
322  g_print("lcSensX = %g, lcSensY = %g, lcSensZ = %g\n",
323  lc->lcSensX / 65536., lc->lcSensY / 65536.,
324  lc->lcSensZ / 65536.);
325  g_print("lcSysMode = %d\n", lc->lcSysMode);
326  g_print("lcSysOrgX = %d, lcSysOrgY = %d\n",
327  lc->lcSysOrgX, lc->lcSysOrgY);
328  g_print("lcSysExtX = %d, lcSysExtY = %d\n",
329  lc->lcSysExtX, lc->lcSysExtY);
330  g_print("lcSysSensX = %g, lcSysSensY = %g\n",
331  lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.);
332 }
333 
334 #endif
335 
336 void gdk_input_init(void)
337 {
338  guint32 deviceid_counter = 0;
339 #ifdef HAVE_WINTAB
340  GdkDevicePrivate *gdkdev;
341  GdkWindowAttr wa;
342  WORD specversion;
343  LOGCONTEXT defcontext;
344  HCTX *hctx;
345  UINT ndevices, ncursors, ncsrtypes, firstcsr, hardware;
346  BOOL active;
347  AXIS axis_x, axis_y, axis_npressure, axis_or[3];
348  int i, j, k;
349  int devix, cursorix;
350  char devname[100], csrname[100];
351 
352  gdk_input_devices = NULL;
353  wintab_contexts = NULL;
354 
355  if (!gdk_input_ignore_wintab && WTInfo(0, 0, NULL)) {
356  WTInfo(WTI_INTERFACE, IFC_SPECVERSION, &specversion);
357  GDK_NOTE(MISC, g_print("Wintab interface version %d.%d\n",
358  HIBYTE(specversion), LOBYTE(specversion)));
359 #if USE_SYSCONTEXT
360  WTInfo(WTI_DEFSYSCTX, 0, &defcontext);
361 #if DEBUG_WINTAB
362  GDK_NOTE(MISC, (g_print("DEFSYSCTX:\n"), print_lc(&defcontext)));
363 #endif
364 #else
365  WTInfo(WTI_DEFCONTEXT, 0, &defcontext);
366 #if DEBUG_WINTAB
367  GDK_NOTE(MISC, (g_print("DEFCONTEXT:\n"), print_lc(&defcontext)));
368 #endif
369 #endif
370  WTInfo(WTI_INTERFACE, IFC_NDEVICES, &ndevices);
371  WTInfo(WTI_INTERFACE, IFC_NCURSORS, &ncursors);
372 #if DEBUG_WINTAB
373  GDK_NOTE(MISC, g_print("NDEVICES: %d, NCURSORS: %d\n",
374  ndevices, ncursors));
375 #endif
376  /* Create a dummy window to receive wintab events */
379  wa.width = 2;
380  wa.height = 2;
381  wa.x = -100;
382  wa.y = -100;
384  if ((wintab_window =
385  gdk_window_new(NULL, &wa, GDK_WA_X | GDK_WA_Y)) == NULL) {
386  g_warning("gdk_input_init: gdk_window_new failed");
387  return;
388  }
389  gdk_window_ref(wintab_window);
390 
391  for (devix = 0; devix < ndevices; devix++) {
392  LOGCONTEXT lc;
393 
394  WTInfo(WTI_DEVICES + devix, DVC_NAME, devname);
395 
396  WTInfo(WTI_DEVICES + devix, DVC_NCSRTYPES, &ncsrtypes);
397  WTInfo(WTI_DEVICES + devix, DVC_FIRSTCSR, &firstcsr);
398  WTInfo(WTI_DEVICES + devix, DVC_HARDWARE, &hardware);
399  WTInfo(WTI_DEVICES + devix, DVC_X, &axis_x);
400  WTInfo(WTI_DEVICES + devix, DVC_Y, &axis_y);
401  WTInfo(WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure);
402  WTInfo(WTI_DEVICES + devix, DVC_ORIENTATION, axis_or);
403 
404  if (HIBYTE(specversion) > 1 || LOBYTE(specversion) >= 1) {
405  WTInfo(WTI_DDCTXS + devix, CTX_NAME, lc.lcName);
406  WTInfo(WTI_DDCTXS + devix, CTX_OPTIONS, &lc.lcOptions);
407  lc.lcOptions |= CXO_MESSAGES;
408 #if USE_SYSCONTEXT
409  lc.lcOptions |= CXO_SYSTEM;
410 #endif
411  lc.lcStatus = 0;
412  WTInfo(WTI_DDCTXS + devix, CTX_LOCKS, &lc.lcLocks);
413  lc.lcMsgBase = WT_DEFBASE;
414  lc.lcDevice = devix;
415  lc.lcPktRate = 50;
416  lc.lcPktData = PACKETDATA;
417  lc.lcPktMode = PK_BUTTONS; /* We want buttons in relative mode */
418  lc.lcMoveMask = PACKETDATA;
419  lc.lcBtnDnMask = lc.lcBtnUpMask = ~0;
420  WTInfo(WTI_DDCTXS + devix, CTX_INORGX, &lc.lcInOrgX);
421  WTInfo(WTI_DDCTXS + devix, CTX_INORGY, &lc.lcInOrgY);
422  WTInfo(WTI_DDCTXS + devix, CTX_INORGZ, &lc.lcInOrgZ);
423  WTInfo(WTI_DDCTXS + devix, CTX_INEXTX, &lc.lcInExtX);
424  WTInfo(WTI_DDCTXS + devix, CTX_INEXTY, &lc.lcInExtY);
425  WTInfo(WTI_DDCTXS + devix, CTX_INEXTZ, &lc.lcInExtZ);
426  lc.lcOutOrgX = axis_x.axMin;
427  lc.lcOutOrgY = axis_y.axMin;
428  lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
429  lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
430  lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
431  WTInfo(WTI_DDCTXS + devix, CTX_SENSX, &lc.lcSensX);
432  WTInfo(WTI_DDCTXS + devix, CTX_SENSY, &lc.lcSensY);
433  WTInfo(WTI_DDCTXS + devix, CTX_SENSZ, &lc.lcSensZ);
434  WTInfo(WTI_DDCTXS + devix, CTX_SYSMODE, &lc.lcSysMode);
435  lc.lcSysOrgX = lc.lcSysOrgY = 0;
436  WTInfo(WTI_DDCTXS + devix, CTX_SYSEXTX, &lc.lcSysExtX);
437  WTInfo(WTI_DDCTXS + devix, CTX_SYSEXTY, &lc.lcSysExtY);
438  WTInfo(WTI_DDCTXS + devix, CTX_SYSSENSX, &lc.lcSysSensX);
439  WTInfo(WTI_DDCTXS + devix, CTX_SYSSENSY, &lc.lcSysSensY);
440  } else {
441  lc = defcontext;
442  lc.lcOptions |= CXO_MESSAGES;
443  lc.lcMsgBase = WT_DEFBASE;
444  lc.lcPktRate = 50;
445  lc.lcPktData = PACKETDATA;
446  lc.lcPktMode = PACKETMODE;
447  lc.lcMoveMask = PACKETDATA;
448  lc.lcBtnUpMask = lc.lcBtnDnMask = ~0;
449 #if 0
450  lc.lcOutExtY = -lc.lcOutExtY; /* Y grows downward */
451 #else
452  lc.lcOutOrgX = axis_x.axMin;
453  lc.lcOutOrgY = axis_y.axMin;
454  lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
455  lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
456  lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
457 #endif
458  }
459 #if DEBUG_WINTAB
460  GDK_NOTE(MISC, (g_print("context for device %d:\n", devix),
461  print_lc(&lc)));
462 #endif
463  hctx = g_new(HCTX, 1);
464  if ((*hctx =
465  WTOpen(GDK_DRAWABLE_XID(wintab_window), &lc,
466  TRUE)) == NULL) {
467  g_warning("gdk_input_init: WTOpen failed");
468  g_free(hctx);
469  return;
470  }
471  GDK_NOTE(MISC, g_print("opened Wintab device %d %#x\n",
472  devix, *hctx));
473 
474  wintab_contexts = g_list_append(wintab_contexts, hctx);
475 #if 0
476  WTEnable(*hctx, TRUE);
477 #endif
478  WTOverlap(*hctx, TRUE);
479 
480 #if DEBUG_WINTAB
481  GDK_NOTE(MISC,
482  (g_print("context for device %d after WTOpen:\n", devix),
483  print_lc(&lc)));
484 #endif
485  for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes;
486  cursorix++) {
487  active = FALSE;
488  WTInfo(WTI_CURSORS + cursorix, CSR_ACTIVE, &active);
489  if (!active)
490  continue;
491  gdkdev = g_new(GdkDevicePrivate, 1);
492  WTInfo(WTI_CURSORS + cursorix, CSR_NAME, csrname);
493  gdkdev->info.name = g_strconcat(devname, " ", csrname, NULL);
494  gdkdev->info.deviceid = deviceid_counter++;
495  gdkdev->info.source = GDK_SOURCE_PEN;
496  gdkdev->info.mode = GDK_MODE_SCREEN;
497 #if USE_SYSCONTEXT
498  gdkdev->info.has_cursor = TRUE;
499 #else
500  gdkdev->info.has_cursor = FALSE;
501 #endif
502  gdkdev->hctx = *hctx;
503  gdkdev->cursor = cursorix;
504  WTInfo(WTI_CURSORS + cursorix, CSR_PKTDATA, &gdkdev->pktdata);
505  gdkdev->info.num_axes = 0;
506  if (gdkdev->pktdata & PK_X)
507  gdkdev->info.num_axes++;
508  if (gdkdev->pktdata & PK_Y)
509  gdkdev->info.num_axes++;
510  if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
511  gdkdev->info.num_axes++;
512  /* The wintab driver for the Wacom ArtPad II reports
513  * PK_ORIENTATION in CSR_PKTDATA, but the tablet doesn't
514  * actually sense tilt. Catch this by noticing that the
515  * orientation axis's azimuth resolution is zero.
516  */
517  if ((gdkdev->pktdata & PK_ORIENTATION)
518  && axis_or[0].axResolution == 0)
519  gdkdev->pktdata &= ~PK_ORIENTATION;
520 
521  if (gdkdev->pktdata & PK_ORIENTATION)
522  gdkdev->info.num_axes += 2; /* x and y tilt */
523  WTInfo(WTI_CURSORS + cursorix, CSR_NPBTNMARKS,
524  &gdkdev->npbtnmarks);
525  gdkdev->axes = g_new(GdkAxisInfo, gdkdev->info.num_axes);
526  gdkdev->info.axes = g_new(GdkAxisUse, gdkdev->info.num_axes);
527  gdkdev->last_axis_data = g_new(gint, gdkdev->info.num_axes);
528 
529  for (k = 0; k < GDK_AXIS_LAST; k++)
530  gdkdev->axis_for_use[k] = -1;
531 
532  k = 0;
533  if (gdkdev->pktdata & PK_X) {
534  gdkdev->axes[k].xresolution =
535  gdkdev->axes[k].resolution =
536  axis_x.axResolution / 65535.;
537  gdkdev->axes[k].xmin_value = gdkdev->axes[k].min_value =
538  axis_x.axMin;
539  gdkdev->axes[k].xmax_value = gdkdev->axes[k].max_value =
540  axis_x.axMax;
541  gdkdev->info.axes[k] = GDK_AXIS_X;
542  gdkdev->axis_for_use[GDK_AXIS_X] = k;
543  k++;
544  }
545  if (gdkdev->pktdata & PK_Y) {
546  gdkdev->axes[k].xresolution =
547  gdkdev->axes[k].resolution =
548  axis_y.axResolution / 65535.;
549  gdkdev->axes[k].xmin_value = gdkdev->axes[k].min_value =
550  axis_y.axMin;
551  gdkdev->axes[k].xmax_value = gdkdev->axes[k].max_value =
552  axis_y.axMax;
553  gdkdev->info.axes[k] = GDK_AXIS_Y;
554  gdkdev->axis_for_use[GDK_AXIS_Y] = k;
555  k++;
556  }
557  if (gdkdev->pktdata & PK_NORMAL_PRESSURE) {
558  gdkdev->axes[k].xresolution =
559  gdkdev->axes[k].resolution =
560  axis_npressure.axResolution / 65535.;
561  gdkdev->axes[k].xmin_value = gdkdev->axes[k].min_value =
562  axis_npressure.axMin;
563  gdkdev->axes[k].xmax_value = gdkdev->axes[k].max_value =
564  axis_npressure.axMax;
565  gdkdev->info.axes[k] = GDK_AXIS_PRESSURE;
566  gdkdev->axis_for_use[GDK_AXIS_PRESSURE] = k;
567  k++;
568  }
569  if (gdkdev->pktdata & PK_ORIENTATION) {
570  GdkAxisUse axis;
571 
572  gdkdev->orientation_axes[0] = axis_or[0];
573  gdkdev->orientation_axes[1] = axis_or[1];
574  for (axis = GDK_AXIS_XTILT; axis <= GDK_AXIS_YTILT; axis++) {
575  /* Wintab gives us aximuth and altitude, which
576  * we convert to x and y tilt in the -1000..1000 range
577  */
578  gdkdev->axes[k].xresolution =
579  gdkdev->axes[k].resolution = 1000;
580  gdkdev->axes[k].xmin_value =
581  gdkdev->axes[k].min_value = -1000;
582  gdkdev->axes[k].xmax_value =
583  gdkdev->axes[k].max_value = 1000;
584  gdkdev->info.axes[k] = axis;
585  gdkdev->axis_for_use[axis] = k;
586  k++;
587  }
588  }
589  gdkdev->info.num_keys = 0;
590  gdkdev->info.keys = NULL;
591  GDK_NOTE(EVENTS,
592  (g_print("device: %d (%d) %s axes: %d\n",
593  gdkdev->info.deviceid, cursorix,
594  gdkdev->info.name,
595  gdkdev->info.num_axes),
596  g_print("axes: X:%d, Y:%d, PRESSURE:%d, "
597  "XTILT:%d, YTILT:%d\n",
598  gdkdev->axis_for_use[GDK_AXIS_X],
599  gdkdev->axis_for_use[GDK_AXIS_Y],
600  gdkdev->axis_for_use[GDK_AXIS_PRESSURE],
601  gdkdev->axis_for_use[GDK_AXIS_XTILT],
602  gdkdev->axis_for_use[GDK_AXIS_YTILT])));
603  for (i = 0; i < gdkdev->info.num_axes; i++)
604  GDK_NOTE(EVENTS,
605  g_print("...axis %d: %d--%d@%d (%d--%d@%d)\n",
606  i,
607  gdkdev->axes[i].xmin_value,
608  gdkdev->axes[i].xmax_value,
609  gdkdev->axes[i].xresolution,
610  gdkdev->axes[i].min_value,
611  gdkdev->axes[i].max_value,
612  gdkdev->axes[i].resolution));
613  gdk_input_devices = g_list_append(gdk_input_devices, gdkdev);
614  }
615  }
616  }
617 #endif /* HAVE_WINTAB */
618 
619  if (deviceid_counter > 0) {
620 #ifdef HAVE_WINTAB
621  gdk_input_vtable.set_mode = gdk_input_win32_set_mode;
622  gdk_input_vtable.set_axes = NULL;
623  gdk_input_vtable.set_key = NULL;
624  gdk_input_vtable.motion_events = NULL;
625  gdk_input_vtable.get_pointer = gdk_input_win32_get_pointer;
626  gdk_input_vtable.grab_pointer = gdk_input_win32_grab_pointer;
627  gdk_input_vtable.ungrab_pointer = gdk_input_win32_ungrab_pointer;
628  gdk_input_vtable.configure_event = gdk_input_win32_configure_event;
629  gdk_input_vtable.enter_event = gdk_input_win32_enter_event;
630  gdk_input_vtable.other_event = gdk_input_win32_other_event;
631  gdk_input_vtable.enable_window = gdk_input_win32_enable_window;
632  gdk_input_vtable.disable_window = gdk_input_win32_disable_window;
633 
634  gdk_input_root_width = gdk_screen_width();
635  gdk_input_root_height = gdk_screen_height();
636  gdk_input_ignore_core = FALSE;
637 #else
639 #endif
640  } else {
641  gdk_input_vtable.set_mode = NULL;
642  gdk_input_vtable.set_axes = NULL;
643  gdk_input_vtable.set_key = NULL;
644  gdk_input_vtable.motion_events = NULL;
645  gdk_input_vtable.get_pointer = gdk_input_none_get_pointer;
646  gdk_input_vtable.grab_pointer = NULL;
647  gdk_input_vtable.ungrab_pointer = NULL;
648  gdk_input_vtable.configure_event = NULL;
649  gdk_input_vtable.enter_event = NULL;
650  gdk_input_vtable.other_event = NULL;
651  gdk_input_vtable.enable_window = NULL;
652  gdk_input_vtable.disable_window = NULL;
653  gdk_input_ignore_core = FALSE;
654  }
655 
656  gdk_input_devices =
657  g_list_append(gdk_input_devices, &gdk_input_core_info);
658 }
659 
661 {
662  if (deviceid == GDK_CORE_POINTER)
663  return FALSE;
664 
665  if (gdk_input_vtable.set_mode)
666  return gdk_input_vtable.set_mode(deviceid, mode);
667  else
668  return FALSE;
669 }
670 
671 void gdk_input_set_axes(guint32 deviceid, GdkAxisUse * axes)
672 {
673  int i;
674  GdkDevicePrivate *gdkdev = gdk_input_find_device(deviceid);
675  g_return_if_fail(gdkdev != NULL);
676 
677  if (deviceid == GDK_CORE_POINTER)
678  return;
679 
680  for (i = GDK_AXIS_IGNORE; i < GDK_AXIS_LAST; i++) {
681  gdkdev->axis_for_use[i] = -1;
682  }
683 
684  for (i = 0; i < gdkdev->info.num_axes; i++) {
685  gdkdev->info.axes[i] = axes[i];
686  gdkdev->axis_for_use[axes[i]] = i;
687  }
688 }
689 
690 static void
692  guint32 deviceid,
693  gdouble * x,
694  gdouble * y,
695  gdouble * pressure,
696  gdouble * xtilt,
697  gdouble * ytilt, GdkModifierType * mask)
698 {
699  gint x_int, y_int;
700 
701  gdk_window_get_pointer(window, &x_int, &y_int, mask);
702 
703  if (x)
704  *x = x_int;
705  if (y)
706  *y = y_int;
707  if (pressure)
708  *pressure = 0.5;
709  if (xtilt)
710  *xtilt = 0;
711  if (ytilt)
712  *ytilt = 0;
713 }
714 
715 #ifdef HAVE_WINTAB
716 
717 static void
718 gdk_input_translate_coordinates(GdkDevicePrivate * gdkdev,
719  GdkInputWindow * input_window,
720  gint * axis_data,
721  gdouble * x,
722  gdouble * y,
723  gdouble * pressure,
724  gdouble * xtilt, gdouble * ytilt)
725 {
726  GdkDrawablePrivate *window_private;
727  gint x_axis, y_axis, pressure_axis, xtilt_axis, ytilt_axis;
728  gdouble device_width, device_height;
729  gdouble x_offset, y_offset, x_scale, y_scale;
730 
731  window_private = (GdkDrawablePrivate *) input_window->window;
732 
733  x_axis = gdkdev->axis_for_use[GDK_AXIS_X];
734  y_axis = gdkdev->axis_for_use[GDK_AXIS_Y];
735  pressure_axis = gdkdev->axis_for_use[GDK_AXIS_PRESSURE];
736  xtilt_axis = gdkdev->axis_for_use[GDK_AXIS_XTILT];
737  ytilt_axis = gdkdev->axis_for_use[GDK_AXIS_YTILT];
738 
739  device_width = gdkdev->axes[x_axis].max_value -
740  gdkdev->axes[x_axis].min_value;
741  device_height = gdkdev->axes[y_axis].max_value -
742  gdkdev->axes[y_axis].min_value;
743 
744  if (gdkdev->info.mode == GDK_MODE_SCREEN) {
745  x_scale = gdk_input_root_width / device_width;
746  y_scale = gdk_input_root_height / device_height;
747 
748  x_offset = -input_window->root_x;
749  y_offset = -input_window->root_y;
750  } else { /* GDK_MODE_WINDOW */
751 
752  double device_aspect =
753  (device_height * gdkdev->axes[y_axis].resolution) /
754  (device_width * gdkdev->axes[x_axis].resolution);
755 
756  if (device_aspect * window_private->width >= window_private->height) {
757  /* device taller than window */
758  x_scale = window_private->width / device_width;
759  y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
760  / gdkdev->axes[y_axis].resolution;
761 
762  x_offset = 0;
763  y_offset = -(device_height * y_scale -
764  window_private->height) / 2;
765  } else {
766  /* window taller than device */
767  y_scale = window_private->height / device_height;
768  x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
769  / gdkdev->axes[x_axis].resolution;
770 
771  y_offset = 0;
772  x_offset = -(device_width * x_scale - window_private->width) / 2;
773  }
774  }
775 
776  if (x)
777  *x = x_offset + x_scale * axis_data[x_axis];
778  if (y)
779  *y = y_offset + y_scale * axis_data[y_axis];
780 
781  if (pressure) {
782  if (pressure_axis != -1)
783  *pressure = ((double) axis_data[pressure_axis]
784  - gdkdev->axes[pressure_axis].min_value)
785  / (gdkdev->axes[pressure_axis].max_value
786  - gdkdev->axes[pressure_axis].min_value);
787  else
788  *pressure = 0.5;
789  }
790 
791  if (xtilt) {
792  if (xtilt_axis != -1) {
793  *xtilt = 2. * (double) (axis_data[xtilt_axis] -
794  (gdkdev->axes[xtilt_axis].min_value +
795  gdkdev->axes[xtilt_axis].max_value) /
796  2) / (gdkdev->axes[xtilt_axis].max_value -
797  gdkdev->axes[xtilt_axis].min_value);
798  } else
799  *xtilt = 0;
800  }
801 
802  if (ytilt) {
803  if (ytilt_axis != -1) {
804  *ytilt = 2. * (double) (axis_data[ytilt_axis] -
805  (gdkdev->axes[ytilt_axis].min_value +
806  gdkdev->axes[ytilt_axis].max_value) /
807  2) / (gdkdev->axes[ytilt_axis].max_value -
808  gdkdev->axes[ytilt_axis].min_value);
809  } else
810  *ytilt = 0;
811  }
812 }
813 
814 static void
815 gdk_input_win32_get_pointer(GdkWindow * window,
816  guint32 deviceid,
817  gdouble * x,
818  gdouble * y,
819  gdouble * pressure,
820  gdouble * xtilt,
821  gdouble * ytilt, GdkModifierType * mask)
822 {
823  GdkDevicePrivate *gdkdev;
824  GdkInputWindow *input_window;
825  gint x_int, y_int;
826  gint i;
827 
828  if (deviceid == GDK_CORE_POINTER) {
829  gdk_window_get_pointer(window, &x_int, &y_int, mask);
830  if (x)
831  *x = x_int;
832  if (y)
833  *y = y_int;
834  if (pressure)
835  *pressure = 0.5;
836  if (xtilt)
837  *xtilt = 0;
838  if (ytilt)
839  *ytilt = 0;
840  } else {
841  if (mask)
842  gdk_window_get_pointer(window, NULL, NULL, mask);
843 
844  gdkdev = gdk_input_find_device(deviceid);
845  g_return_if_fail(gdkdev != NULL);
846 
847  input_window = gdk_input_window_find(window);
848  g_return_if_fail(input_window != NULL);
849 
850  gdk_input_translate_coordinates(gdkdev, input_window,
851  gdkdev->last_axis_data,
852  x, y, pressure, xtilt, ytilt);
853  if (mask) {
854  *mask &= 0xFF;
855  *mask |= ((gdkdev->last_buttons & 0x1F) << 8);
856  }
857  }
858 }
859 
860 static void
861 gdk_input_get_root_relative_geometry(HWND w, int *x_ret, int *y_ret)
862 {
863  RECT rect;
864 
865  GetWindowRect(w, &rect);
866 
867  if (x_ret)
868  *x_ret = rect.left;
869  if (y_ret)
870  *y_ret = rect.top;
871 }
872 
873 static gint gdk_input_win32_set_mode(guint32 deviceid, GdkInputMode mode)
874 {
875  GList *tmp_list;
876  GdkDevicePrivate *gdkdev;
877  GdkInputMode old_mode;
878  GdkInputWindow *input_window;
879 
880  if (deviceid == GDK_CORE_POINTER)
881  return FALSE;
882 
883  gdkdev = gdk_input_find_device(deviceid);
884  g_return_val_if_fail(gdkdev != NULL, FALSE);
885  old_mode = gdkdev->info.mode;
886 
887  if (old_mode == mode)
888  return TRUE;
889 
890  gdkdev->info.mode = mode;
891 
892  if (mode == GDK_MODE_WINDOW) {
893  gdkdev->info.has_cursor = FALSE;
894  for (tmp_list = gdk_input_windows; tmp_list;
895  tmp_list = tmp_list->next) {
896  input_window = (GdkInputWindow *) tmp_list->data;
897  if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
898  gdk_input_win32_enable_window(input_window->window, gdkdev);
899  else if (old_mode != GDK_MODE_DISABLED)
900  gdk_input_win32_disable_window(input_window->window, gdkdev);
901  }
902  } else if (mode == GDK_MODE_SCREEN) {
903  gdkdev->info.has_cursor = TRUE;
904  for (tmp_list = gdk_input_windows; tmp_list;
905  tmp_list = tmp_list->next)
906  gdk_input_win32_enable_window(((GdkInputWindow *) tmp_list->
907  data)->window, gdkdev);
908  } else { /* mode == GDK_MODE_DISABLED */
909 
910  for (tmp_list = gdk_input_windows; tmp_list;
911  tmp_list = tmp_list->next) {
912  input_window = (GdkInputWindow *) tmp_list->data;
913  if (old_mode != GDK_MODE_WINDOW ||
914  input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
915  gdk_input_win32_disable_window(input_window->window, gdkdev);
916  }
917  }
918 
919  return TRUE;
920 }
921 
922 static void
923 gdk_input_win32_configure_event(GdkEventConfigure * event,
924  GdkWindow * window)
925 {
926  GdkInputWindow *input_window;
927  gint root_x, root_y;
928 
929  input_window = gdk_input_window_find(window);
930  g_return_if_fail(window != NULL);
931 
932  gdk_input_get_root_relative_geometry
933  (GDK_DRAWABLE_XID(window), &root_x, &root_y);
934 
935  input_window->root_x = root_x;
936  input_window->root_y = root_y;
937 }
938 
939 static void
940 gdk_input_win32_enter_event(GdkEventCrossing * event, GdkWindow * window)
941 {
942  GdkInputWindow *input_window;
943  gint root_x, root_y;
944 
945  input_window = gdk_input_window_find(window);
946  g_return_if_fail(window != NULL);
947 
948  gdk_input_get_root_relative_geometry
949  (GDK_DRAWABLE_XID(window), &root_x, &root_y);
950 
951  input_window->root_x = root_x;
952  input_window->root_y = root_y;
953 }
954 
955 static void decode_tilt(gint * axis_data, AXIS * axes, PACKET * packet)
956 {
957  /* As I don't have a tilt-sensing tablet,
958  * I cannot test this code.
959  */
960 
961  double az, el;
962 
963  az = TWOPI * packet->pkOrientation.orAzimuth /
964  (axes[0].axResolution / 65536.);
965  el = TWOPI * packet->pkOrientation.orAltitude /
966  (axes[1].axResolution / 65536.);
967 
968  /* X tilt */
969  axis_data[0] = cos(az) * cos(el) * 1000;
970  /* Y tilt */
971  axis_data[1] = sin(az) * cos(el) * 1000;
972 }
973 
974 static GdkDevicePrivate *gdk_input_find_dev_from_ctx(HCTX hctx,
975  UINT cursor)
976 {
977  GList *tmp_list = gdk_input_devices;
978  GdkDevicePrivate *gdkdev;
979 
980  while (tmp_list) {
981  gdkdev = (GdkDevicePrivate *) (tmp_list->data);
982  if (gdkdev->hctx == hctx && gdkdev->cursor == cursor)
983  return gdkdev;
984  tmp_list = tmp_list->next;
985  }
986  return NULL;
987 }
988 
989 static gint gdk_input_win32_other_event(GdkEvent * event, MSG * xevent)
990 {
991  GdkWindow *current_window;
992  GdkInputWindow *input_window;
993  GdkWindow *window;
994  GdkDevicePrivate *gdkdev;
995  GdkEventMask masktest;
996  POINT pt;
997  PACKET packet;
998  gint return_val;
999  gint k;
1000  gint x, y;
1001 
1002  if (event->any.window != wintab_window) {
1003  g_warning("gdk_input_win32_other_event: not wintab_window?");
1004  return FALSE;
1005  }
1006 #if USE_SYSCONTEXT
1007  window = gdk_window_at_pointer(&x, &y);
1008  if (window == NULL)
1009  window = gdk_parent_root;
1010 
1011  gdk_window_ref(window);
1012 
1013  GDK_NOTE(EVENTS,
1014  g_print("gdk_input_win32_other_event: window=%#x (%d,%d)\n",
1015  GDK_DRAWABLE_XID(window), x, y));
1016 
1017 #else
1018  /* ??? This code is pretty bogus */
1019  current_window = gdk_window_lookup(GetActiveWindow());
1020  if (current_window == NULL)
1021  return FALSE;
1022 
1023  input_window = gdk_input_window_find_within(current_window);
1024  if (input_window == NULL)
1025  return FALSE;
1026 #endif
1027 
1028  if (xevent->message == WT_PACKET) {
1029  if (!WTPacket((HCTX) xevent->lParam, xevent->wParam, &packet))
1030  return FALSE;
1031  }
1032 
1033  switch (xevent->message) {
1034  case WT_PACKET:
1035  if (window == gdk_parent_root) {
1036  GDK_NOTE(EVENTS, g_print("...is root\n"));
1037  return FALSE;
1038  }
1039 
1040  if ((gdkdev = gdk_input_find_dev_from_ctx((HCTX) xevent->lParam,
1041  packet.pkCursor)) == NULL)
1042  return FALSE;
1043 
1044  if (gdkdev->info.mode == GDK_MODE_DISABLED)
1045  return FALSE;
1046 
1047  k = 0;
1048  if (gdkdev->pktdata & PK_X)
1049  gdkdev->last_axis_data[k++] = packet.pkX;
1050  if (gdkdev->pktdata & PK_Y)
1051  gdkdev->last_axis_data[k++] = packet.pkY;
1052  if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
1053  gdkdev->last_axis_data[k++] = packet.pkNormalPressure;
1054  if (gdkdev->pktdata & PK_ORIENTATION) {
1055  decode_tilt(gdkdev->last_axis_data + k,
1056  gdkdev->orientation_axes, &packet);
1057  k += 2;
1058  }
1059 
1060  g_assert(k == gdkdev->info.num_axes);
1061 
1062  if (HIWORD(packet.pkButtons) != TBN_NONE) {
1063  /* Gdk buttons are numbered 1.. */
1064  event->button.button = 1 + LOWORD(packet.pkButtons);
1065 
1066  if (HIWORD(packet.pkButtons) == TBN_UP) {
1067  event->any.type = GDK_BUTTON_RELEASE;
1068  masktest = GDK_BUTTON_RELEASE_MASK;
1069  gdkdev->button_state &= ~(1 << LOWORD(packet.pkButtons));
1070  } else {
1071  event->any.type = GDK_BUTTON_PRESS;
1072  masktest = GDK_BUTTON_PRESS_MASK;
1073  gdkdev->button_state |= 1 << LOWORD(packet.pkButtons);
1074  }
1075  } else {
1076  event->any.type = GDK_MOTION_NOTIFY;
1077  masktest = GDK_POINTER_MOTION_MASK;
1078  if (gdkdev->button_state & (1 << 0))
1080  if (gdkdev->button_state & (1 << 1))
1082  if (gdkdev->button_state & (1 << 2))
1084  }
1085 
1086  /* Now we can check if the window wants the event, and
1087  * propagate if necessary.
1088  */
1089  dijkstra:
1090  if (!GDK_WINDOW_WIN32DATA(window)->extension_events_selected
1091  || !(((GdkWindowPrivate *) window)->extension_events & masktest))
1092  {
1093  GDK_NOTE(EVENTS, g_print("...not selected\n"));
1094 
1095  if (((GdkWindowPrivate *) window)->parent == gdk_parent_root)
1096  return FALSE;
1097 
1098  pt.x = x;
1099  pt.y = y;
1100  ClientToScreen(GDK_DRAWABLE_XID(window), &pt);
1101  gdk_window_unref(window);
1102  window = ((GdkWindowPrivate *) window)->parent;
1103  gdk_window_ref(window);
1104  ScreenToClient(GDK_DRAWABLE_XID(window), &pt);
1105  x = pt.x;
1106  y = pt.y;
1107  GDK_NOTE(EVENTS, g_print("...propagating to %#x, (%d,%d)\n",
1108  GDK_DRAWABLE_XID(window), x, y));
1109  goto dijkstra;
1110  }
1111 
1112  input_window = gdk_input_window_find(window);
1113 
1114  g_assert(input_window != NULL);
1115 
1116  if (gdkdev->info.mode == GDK_MODE_WINDOW
1117  && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
1118  return FALSE;
1119 
1120  event->any.window = window;
1121 
1122  if (event->any.type == GDK_BUTTON_PRESS
1123  || event->any.type == GDK_BUTTON_RELEASE) {
1124  event->button.time = xevent->time;
1125  event->button.source = gdkdev->info.source;
1126  last_moved_cursor_id =
1127  event->button.deviceid = gdkdev->info.deviceid;
1128 
1129 #if 0
1130 #if USE_SYSCONTEXT
1131  /* Buttons 1 to 3 will come in as WM_[LMR]BUTTON{DOWN,UP} */
1132  if (event->button.button <= 3)
1133  return FALSE;
1134 #endif
1135 #endif
1136  gdk_input_translate_coordinates(gdkdev, input_window,
1137  gdkdev->last_axis_data,
1138  &event->button.x,
1139  &event->button.y,
1140  &event->button.pressure,
1141  &event->button.xtilt,
1142  &event->button.ytilt);
1143 
1144  event->button.state = ((gdkdev->button_state << 8)
1147  | GDK_BUTTON5_MASK));
1148  GDK_NOTE(EVENTS,
1149  g_print("WINTAB button %s: %d %d %g,%g %g %g,%g\n",
1150  (event->button.type ==
1151  GDK_BUTTON_PRESS ? "press" : "release"),
1152  event->button.deviceid, event->button.button,
1153  event->button.x, event->button.y,
1154  event->button.pressure, event->button.xtilt,
1155  event->button.ytilt));
1156  } else {
1157  event->motion.time = xevent->time;
1158  last_moved_cursor_id =
1159  event->motion.deviceid = gdkdev->info.deviceid;
1160  event->motion.is_hint = FALSE;
1161  event->motion.source = gdkdev->info.source;
1162 
1163  gdk_input_translate_coordinates(gdkdev, input_window,
1164  gdkdev->last_axis_data,
1165  &event->motion.x,
1166  &event->motion.y,
1167  &event->motion.pressure,
1168  &event->motion.xtilt,
1169  &event->motion.ytilt);
1170 
1171  event->motion.state = ((gdkdev->button_state << 8)
1174  | GDK_BUTTON5_MASK));
1175 
1176  GDK_NOTE(EVENTS, g_print("WINTAB motion: %d %g,%g %g %g,%g\n",
1177  event->motion.deviceid,
1178  event->motion.x, event->motion.y,
1179  event->motion.pressure,
1180  event->motion.xtilt,
1181  event->motion.ytilt));
1182 
1183  /* Check for missing release or press events for the normal
1184  * pressure button. At least on my ArtPadII I sometimes miss a
1185  * release event?
1186  */
1187  if ((gdkdev->pktdata & PK_NORMAL_PRESSURE
1188  && (event->motion.state & GDK_BUTTON1_MASK)
1189  && packet.pkNormalPressure <= MAX(0,
1190  gdkdev->npbtnmarks[0] - 2))
1191  || (gdkdev->pktdata & PK_NORMAL_PRESSURE
1192  && !(event->motion.state & GDK_BUTTON1_MASK)
1193  && packet.pkNormalPressure > gdkdev->npbtnmarks[1] + 2)) {
1194  GdkEvent *event2 = gdk_event_copy(event);
1195  if (event->motion.state & GDK_BUTTON1_MASK) {
1196  event2->button.type = GDK_BUTTON_RELEASE;
1197  gdkdev->button_state &= ~1;
1198  } else {
1199  event2->button.type = GDK_BUTTON_PRESS;
1200  gdkdev->button_state |= 1;
1201  }
1202  event2->button.state = ((gdkdev->button_state << 8)
1204  | GDK_BUTTON3_MASK |
1206  GDK_BUTTON5_MASK));
1207  event2->button.button = 1;
1208  GDK_NOTE(EVENTS,
1209  g_print
1210  ("WINTAB synthesized button %s: %d %d %g,%g %g\n",
1211  (event2->button.type ==
1212  GDK_BUTTON_PRESS ? "press" : "release"),
1213  event2->button.deviceid, event2->button.button,
1214  event2->button.x, event2->button.y,
1215  event2->button.pressure));
1216  gdk_event_queue_append(event2);
1217  }
1218  }
1219  return TRUE;
1220 
1221  case WT_PROXIMITY:
1222  if (LOWORD(xevent->lParam) == 0) {
1223  event->proximity.type = GDK_PROXIMITY_OUT;
1224  gdk_input_ignore_core = FALSE;
1225  } else {
1226  event->proximity.type = GDK_PROXIMITY_IN;
1227  gdk_input_ignore_core = TRUE;
1228  }
1229  event->proximity.time = xevent->time;
1230  event->proximity.source = GDK_SOURCE_PEN;
1231  event->proximity.deviceid = last_moved_cursor_id;
1232 
1233  GDK_NOTE(EVENTS, g_print("WINTAB proximity %s: %d\n",
1234  (event->proximity.type == GDK_PROXIMITY_IN ?
1235  "in" : "out"), event->proximity.deviceid));
1236  return TRUE;
1237  }
1238  return FALSE;
1239 }
1240 
1241 static gint
1242 gdk_input_win32_enable_window(GdkWindow * window,
1243  GdkDevicePrivate * gdkdev)
1244 {
1245  GDK_WINDOW_WIN32DATA(window)->extension_events_selected = TRUE;
1246  return TRUE;
1247 }
1248 
1249 static gint
1250 gdk_input_win32_disable_window(GdkWindow * window,
1251  GdkDevicePrivate * gdkdev)
1252 {
1253  GDK_WINDOW_WIN32DATA(window)->extension_events_selected = FALSE;
1254  return TRUE;
1255 }
1256 
1257 static gint
1258 gdk_input_win32_grab_pointer(GdkWindow * window,
1259  gint owner_events,
1260  GdkEventMask event_mask,
1261  GdkWindow * confine_to, guint32 time)
1262 {
1263  GdkInputWindow *input_window, *new_window;
1264  gboolean need_ungrab;
1265  GdkDevicePrivate *gdkdev;
1266  GList *tmp_list;
1267  gint result;
1268 
1269  tmp_list = gdk_input_windows;
1270  new_window = NULL;
1271  need_ungrab = FALSE;
1272 
1273  GDK_NOTE(MISC, g_print("gdk_input_win32_grab_pointer: %#x %d %#x\n",
1274  GDK_DRAWABLE_XID(window),
1275  owner_events,
1276  (confine_to ? GDK_DRAWABLE_XID(confine_to) :
1277  0)));
1278 
1279  while (tmp_list) {
1280  input_window = (GdkInputWindow *) tmp_list->data;
1281 
1282  if (input_window->window == window)
1283  new_window = input_window;
1284  else if (input_window->grabbed) {
1285  input_window->grabbed = FALSE;
1286  need_ungrab = TRUE;
1287  }
1288 
1289  tmp_list = tmp_list->next;
1290  }
1291 
1292  if (new_window) {
1293  new_window->grabbed = TRUE;
1294 
1295  tmp_list = gdk_input_devices;
1296  while (tmp_list) {
1297  gdkdev = (GdkDevicePrivate *) tmp_list->data;
1298  if (gdkdev->info.deviceid != GDK_CORE_POINTER) {
1299 #if 0
1300  /* XXX */
1301  gdk_input_find_events(window, gdkdev,
1302  event_mask, event_classes, &num_classes);
1303  result = XGrabDevice(GDK_DISPLAY(), gdkdev->xdevice,
1304  GDK_WINDOW_XWINDOW(window),
1305  owner_events, num_classes, event_classes,
1306  GrabModeAsync, GrabModeAsync, time);
1307 
1308  /* FIXME: if failure occurs on something other than the first
1309  device, things will be badly inconsistent */
1310  if (result != Success)
1311  return result;
1312 #endif
1313  }
1314  tmp_list = tmp_list->next;
1315  }
1316  } else {
1317  tmp_list = gdk_input_devices;
1318  while (tmp_list) {
1319  gdkdev = (GdkDevicePrivate *) tmp_list->data;
1320  if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
1321  ((gdkdev->button_state != 0) || need_ungrab)) {
1322 #if 0
1323  /* XXX */
1324  XUngrabDevice(gdk_display, gdkdev->xdevice, time);
1325 #endif
1326  gdkdev->button_state = 0;
1327  }
1328 
1329  tmp_list = tmp_list->next;
1330  }
1331  }
1332 
1333  return Success;
1334 
1335 }
1336 
1337 static void gdk_input_win32_ungrab_pointer(guint32 time)
1338 {
1339  GdkInputWindow *input_window;
1340  GdkDevicePrivate *gdkdev;
1341  GList *tmp_list;
1342 
1343  GDK_NOTE(MISC, g_print("gdk_input_win32_ungrab_pointer\n"));
1344 
1345  tmp_list = gdk_input_windows;
1346  while (tmp_list) {
1347  input_window = (GdkInputWindow *) tmp_list->data;
1348  if (input_window->grabbed)
1349  break;
1350  tmp_list = tmp_list->next;
1351  }
1352 
1353  if (tmp_list) { /* we found a grabbed window */
1354  input_window->grabbed = FALSE;
1355 
1356  tmp_list = gdk_input_devices;
1357  while (tmp_list) {
1358  gdkdev = (GdkDevicePrivate *) tmp_list->data;
1359 #if 0
1360  /* XXX */
1361  if (gdkdev->info.deviceid != GDK_CORE_POINTER && gdkdev->xdevice)
1362  XUngrabDevice(gdk_display, gdkdev->xdevice, time);
1363 #endif
1364  tmp_list = tmp_list->next;
1365  }
1366  }
1367 }
1368 
1369 #endif /* HAVE_WINTAB */
1370 
1372 {
1373  return gdk_input_devices;
1374 }
1375 
1377 {
1378  GdkDevicePrivate *gdkdev = gdk_input_find_device(deviceid);
1379  g_return_if_fail(gdkdev != NULL);
1380 
1381  gdkdev->info.source = source;
1382 }
1383 
1385  guint index,
1386  guint keyval, GdkModifierType modifiers)
1387 {
1388  if (deviceid != GDK_CORE_POINTER && gdk_input_vtable.set_key)
1389  gdk_input_vtable.set_key(deviceid, index, keyval, modifiers);
1390 }
1391 
1393  guint32 deviceid,
1394  guint32 start,
1395  guint32 stop, gint * nevents_return)
1396 {
1397  g_return_val_if_fail(window != NULL, NULL);
1398  if (GDK_DRAWABLE_DESTROYED(window))
1399  return NULL;
1400 
1401  *nevents_return = 0;
1402  return NULL; /* ??? */
1403 }
1404 
1405 static gint
1407 {
1408  if (gdk_input_vtable.enable_window)
1409  return gdk_input_vtable.enable_window(window, gdkdev);
1410  else
1411  return TRUE;
1412 }
1413 
1414 static gint
1416 {
1417  if (gdk_input_vtable.disable_window)
1418  return gdk_input_vtable.disable_window(window, gdkdev);
1419  else
1420  return TRUE;
1421 }
1422 
1423 
1425 {
1426  GList *tmp_list;
1427 
1428  for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
1429  if (((GdkInputWindow *) (tmp_list->data))->window == window)
1430  return (GdkInputWindow *) (tmp_list->data);
1431 
1432  return NULL; /* Not found */
1433 }
1434 
1435 #if !USE_SYSCONTEXT
1436 
1437 static GdkInputWindow *gdk_input_window_find_within(GdkWindow * window)
1438 {
1439  GList *list;
1440  GdkWindow *tmpw;
1441  GdkInputWindow *candidate = NULL;
1442 
1443  for (list = gdk_input_windows; list != NULL; list = list->next) {
1444  tmpw = ((GdkInputWindow *) (tmp_list->data))->window;
1445  if (tmpw == window
1446  || IsChild(GDK_DRAWABLE_XID(window), GDK_DRAWABLE_XID(tmpw))) {
1447  if (candidate)
1448  return NULL; /* Multiple hits */
1449  candidate = (GdkInputWindow *) (list->data);
1450  }
1451  }
1452 
1453  return candidate;
1454 }
1455 
1456 #endif
1457 
1458 /* FIXME: this routine currently needs to be called between creation
1459  and the corresponding configure event (because it doesn't get the
1460  root_relative_geometry). This should work with
1461  gtk_window_set_extension_events, but will likely fail in other
1462  cases */
1463 
1464 void
1466  gint mask, GdkExtensionMode mode)
1467 {
1468  GdkWindowPrivate *window_private;
1469  GList *tmp_list;
1470  GdkInputWindow *iw;
1471 
1472  g_return_if_fail(window != NULL);
1473  if (GDK_DRAWABLE_DESTROYED(window))
1474  return;
1475  window_private = (GdkWindowPrivate *) window;
1476 
1477  if (mode == GDK_EXTENSION_EVENTS_NONE)
1478  mask = 0;
1479 
1480  if (mask != 0) {
1481  iw = g_new(GdkInputWindow, 1);
1482 
1483  iw->window = window;
1484  iw->mode = mode;
1485 
1486  iw->grabbed = FALSE;
1487 
1488  gdk_input_windows = g_list_append(gdk_input_windows, iw);
1489  window_private->extension_events = mask;
1490 
1491  /* Add enter window events to the event mask */
1492  gdk_window_set_events(window,
1493  gdk_window_get_events(window) |
1495  } else {
1496  iw = gdk_input_window_find(window);
1497  if (iw) {
1498  gdk_input_windows = g_list_remove(gdk_input_windows, iw);
1499  g_free(iw);
1500  }
1501 
1502  window_private->extension_events = 0;
1503  }
1504 
1505  for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next) {
1506  GdkDevicePrivate *gdkdev = (GdkDevicePrivate *) (tmp_list->data);
1507 
1508  if (gdkdev->info.deviceid != GDK_CORE_POINTER) {
1509  if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
1510  && (gdkdev->info.has_cursor
1511  || mode == GDK_EXTENSION_EVENTS_ALL))
1512  gdk_input_enable_window(window, gdkdev);
1513  else
1514  gdk_input_disable_window(window, gdkdev);
1515  }
1516  }
1517 }
1518 
1520 {
1521  GdkInputWindow *input_window;
1522 
1523  input_window = gdk_input_window_find(window);
1524  g_return_if_fail(input_window != NULL);
1525 
1526  gdk_input_windows = g_list_remove(gdk_input_windows, input_window);
1527  g_free(input_window);
1528 }
1529 
1530 void gdk_input_exit(void)
1531 {
1532 #ifdef HAVE_WINTAB
1533  GList *tmp_list;
1534  GdkDevicePrivate *gdkdev;
1535 
1536  for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next) {
1537  gdkdev = (GdkDevicePrivate *) (tmp_list->data);
1538  if (gdkdev->info.deviceid != GDK_CORE_POINTER) {
1539  gdk_input_win32_set_mode(gdkdev->info.deviceid,
1541  g_free(gdkdev->info.name);
1542  g_free(gdkdev->last_axis_data);
1543  g_free(gdkdev->info.axes);
1544  g_free(gdkdev->info.keys);
1545  g_free(gdkdev->axes);
1546  g_free(gdkdev);
1547  }
1548  }
1549 
1550  g_list_free(gdk_input_devices);
1551 
1552  for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next) {
1553  g_free(tmp_list->data);
1554  }
1555  g_list_free(gdk_input_windows);
1556  gdk_input_windows = NULL;
1557 
1558  gdk_window_unref(wintab_window);
1559  wintab_window = NULL;
1560 
1561 #if 1
1562  for (tmp_list = wintab_contexts; tmp_list; tmp_list = tmp_list->next) {
1563  HCTX *hctx = (HCTX *) tmp_list->data;
1564  BOOL result;
1565 
1566 #ifdef _MSC_VER
1567  /* For some reason WTEnable and/or WTClose tend to crash here.
1568  * Protect with __try/__except to avoid a message box.
1569  * When compiling with gcc, we cannot use __try/__except, so
1570  * don't call WTClose. I think this means that we'll
1571  * eventually run out of Wintab contexts, sigh.
1572  */
1573  __try {
1574 #if 0
1575  WTEnable(*hctx, FALSE);
1576 #endif
1577  result = WTClose(*hctx);
1578  }
1579  __except( /* GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? */
1580  EXCEPTION_EXECUTE_HANDLER /*:
1581  EXCEPTION_CONTINUE_SEARCH */ ) {
1582  result = FALSE;
1583  }
1584  if (!result)
1585  g_warning("gdk_input_exit: Closing Wintab context %#x failed",
1586  *hctx);
1587 #endif /* _MSC_VER */
1588  g_free(hctx);
1589  }
1590 #endif
1591  g_list_free(wintab_contexts);
1592  wintab_contexts = NULL;
1593 #endif
1594 }
1595 
1597 {
1598  GList *tmp_list = gdk_input_devices;
1599  GdkDevicePrivate *gdkdev;
1600 
1601  while (tmp_list) {
1602  gdkdev = (GdkDevicePrivate *) (tmp_list->data);
1603  if (gdkdev->info.deviceid == id)
1604  return gdkdev;
1605  tmp_list = tmp_list->next;
1606  }
1607  return NULL;
1608 }
1609 
1610 void
1612  guint32 deviceid,
1613  gdouble * x,
1614  gdouble * y,
1615  gdouble * pressure,
1616  gdouble * xtilt,
1617  gdouble * ytilt, GdkModifierType * mask)
1618 {
1619  if (gdk_input_vtable.get_pointer)
1620  gdk_input_vtable.get_pointer(window, deviceid, x, y, pressure,
1621  xtilt, ytilt, mask);
1622 }
GdkTimeCoord *(* motion_events)(GdkWindow *window, guint32 deviceid, guint32 start, guint32 stop, gint *nevents_return)
GList * gdk_input_list_devices(void)
GdkModifierType
Definition: gdktypes.h:102
#define GDK_DRAWABLE_DESTROYED(d)
Definition: gdkprivate.h:48
GdkWindow * window
Definition: gdkevents.h:186
unsigned int guint
Definition: g_types.h:51
gint event_mask
Definition: gdkwindow.h:87
#define Success
gint(* grab_pointer)(GdkWindow *window, gint owner_events, GdkEventMask event_mask, GdkWindow *confine_to, guint32 time)
void g_list_free(GList *list)
Definition: glist.c:155
GdkWindow * gdk_parent_root
Definition: gdkglobals.c:33
GdkEventMotion motion
Definition: gdkevents.h:369
#define gdk_window_ref
Definition: gdkcompat.h:25
#define g_return_val_if_fail(expr, val)
Definition: gmessages.h:300
gint(* set_mode)(guint32 deviceid, GdkInputMode mode)
GdkEventMask gdk_window_get_events(GdkWindow *window)
double gdouble
Definition: g_types.h:54
GdkEventType type
Definition: gdkevents.h:185
#define GDK_NOTE(type, action)
Definition: gdkprivate.h:276
GdkInputSource
Definition: gdkinput.h:20
static void gdk_input_none_get_pointer(GdkWindow *window, guint32 deviceid, gdouble *x, gdouble *y, gdouble *pressure, gdouble *xtilt, gdouble *ytilt, GdkModifierType *mask)
gint16 width
Definition: gdkwindow.h:89
GdkEventType type
Definition: gdkevents.h:330
void(* ungrab_pointer)(guint32 time)
gint(* disable_window)(GdkWindow *window, GdkDevicePrivate *gdkdev)
static GdkAxisUse gdk_input_core_axes[]
void gdk_input_window_destroy(GdkWindow *window)
#define GDK_WINDOW_WIN32DATA(win)
GdkEventButton button
Definition: gdkevents.h:370
GdkEventType type
Definition: gdkevents.h:230
double cos(double)
GdkWindow * gdk_window_new(GdkWindow *parent, GdkWindowAttr *attributes, gint attributes_mask)
GdkExtensionMode mode
Double_t x[n]
Definition: legend1.C:17
GdkExtensionMode
Definition: gdkinput.h:14
unsigned int guint32
static HWND active
void gdk_input_exit(void)
gint gboolean
Definition: g_types.h:45
GdkInputVTable gdk_input_vtable
void gdk_input_set_source(guint32 deviceid, GdkInputSource source)
void gdk_event_queue_append(GdkEvent *event)
Definition: gdkevents.c:143
static GList * wintab_contexts
if(pyself &&pyself!=Py_None)
gint gdk_screen_height(void)
void gdk_input_set_extension_events(GdkWindow *window, gint mask, GdkExtensionMode mode)
gdouble ytilt
Definition: gdkevents.h:221
double sin(double)
GList * g_list_append(GList *list, gpointer data)
Definition: glist.c:241
void(* enter_event)(GdkEventCrossing *event, GdkWindow *window)
gint(* other_event)(GdkEvent *event, MSG *xevent)
static GdkWindow * wintab_window
#define GDK_WINDOW_XWINDOW
Definition: gdkwin32.h:50
#define g_return_if_fail(expr)
Definition: gmessages.h:288
gint gdk_input_ignore_core
#define g_new(struct_type, n_structs)
Definition: gmem.h:60
int gint
Definition: g_types.h:44
static gint gdk_input_root_height
typedef BOOL(WINAPI *PFN_TrackMouseEvent)(LPTRACKMOUSEEVENT)
TPaveText * pt
GdkWindowClass wclass
Definition: gdkwindow.h:91
static guint32 last_moved_cursor_id
#define FALSE
Definition: gmacros.h:126
#define g_assert_not_reached()
Definition: gmessages.h:219
GdkAxisUse
Definition: gdkinput.h:33
GdkInputMode
Definition: gdkinput.h:27
gdouble pressure
Definition: gdkevents.h:219
void(* set_axes)(guint32 deviceid, GdkAxisUse *axes)
void(* configure_event)(GdkEventConfigure *event, GdkWindow *window)
gdouble pressure
Definition: gdkevents.h:236
GdkWindow * gdk_window_at_pointer(gint *win_x, gint *win_y)
gdouble ytilt
Definition: gdkevents.h:238
void gdk_input_set_key(guint32 deviceid, guint index, guint keyval, GdkModifierType modifiers)
gint16 height
Definition: gdkwindow.h:90
#define MAX(a, b)
Definition: gmacros.h:134
gchar * g_strconcat(const gchar *string1,...)
Definition: gstrfuncs.c:223
void gdk_input_set_axes(guint32 deviceid, GdkAxisUse *axes)
gchar data[7]
void g_free(gpointer mem)
Definition: gmem.c:183
gint gdk_input_ignore_wintab
guint32 deviceid
Definition: gdkevents.h:242
GdkDrawableType window_type
Definition: gdkwindow.h:94
static gint gdk_input_enable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
Double_t y[n]
Definition: legend1.C:17
GdkTimeCoord * gdk_input_motion_events(GdkWindow *window, guint32 deviceid, guint32 start, guint32 stop, gint *nevents_return)
static GList * gdk_input_windows
typedefG_BEGIN_DECLS struct _GList GList
Definition: glist.h:34
static gint gdk_input_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
GdkEventProximity proximity
Definition: gdkevents.h:378
#define gdk_window_lookup(xid)
Definition: gdkprivate.h:50
GdkEventAny any
Definition: gdkevents.h:365
#define GDK_CORE_POINTER
Definition: gdktypes.h:57
GdkEvent * gdk_event_copy(GdkEvent *event)
Definition: gdkevents.c:278
#define g_assert(expr)
Definition: gmessages.h:210
static GList * gdk_input_devices
GList * g_list_remove(GList *list, gconstpointer data)
Definition: glist.c:389
void gdk_input_window_get_pointer(GdkWindow *window, guint32 deviceid, gdouble *x, gdouble *y, gdouble *pressure, gdouble *xtilt, gdouble *ytilt, GdkModifierType *mask)
static void g_warning(const gchar *format,...)
Definition: gmessages.h:155
static GdkInputWindow * gdk_input_window_find(GdkWindow *window)
void(* get_pointer)(GdkWindow *window, guint32 deviceid, gdouble *x, gdouble *y, gdouble *pressure, gdouble *xtilt, gdouble *ytilt, GdkModifierType *mask)
struct _GdkDevicePrivate GdkDevicePrivate
void gdk_window_set_events(GdkWindow *window, GdkEventMask event_mask)
#define TRUE
Definition: gmacros.h:130
#define NULL
Definition: Rtypes.h:82
gdouble xtilt
Definition: gdkevents.h:220
#define TWOPI
double result[121]
#define GDK_DRAWABLE_XID(win)
Definition: gdkwin32.h:42
gint gdk_input_set_mode(guint32 deviceid, GdkInputMode mode)
void g_print(const gchar *format,...)
Definition: gmessages.c:788
static gint gdk_input_root_width
gint(* enable_window)(GdkWindow *window, GdkDevicePrivate *gdkdev)
gdouble xtilt
Definition: gdkevents.h:237
GdkWindow * gdk_window_get_pointer(GdkWindow *window, gint *x, gint *y, GdkModifierType *mask)
#define gdk_window_unref
Definition: gdkcompat.h:26
GdkWindow * window
#define GDK_DISPLAY()
Definition: gdkwin32.h:41
gint gdk_screen_width(void)
void(* set_key)(guint32 deviceid, guint index, guint keyval, GdkModifierType modifiers)
static GdkDevicePrivate * gdk_input_find_device(guint32 deviceid)
guint32 deviceid
Definition: gdkevents.h:225
GdkEventMask
Definition: gdkevents.h:113
void gdk_input_init(void)