/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- * Copyright (C) 1998-2002 Tor Lillqvist
+ * Copyright (C) 1998-2007 Tor Lillqvist
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
-#include "config.h"
+#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include "gdkprivate-win32.h"
#include "gdkinput-win32.h"
-#ifdef HAVE_WINTAB
-
#define PACKETDATA (PK_CONTEXT | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION)
-#define PACKETMODE (PK_BUTTONS)
+/* We want everything in absolute mode */
+#define PACKETMODE (0)
#include <pktdef.h>
-/* If USE_SYSCONTEXT is on, we open the Wintab device (hmm, what if
- * there are several?) as a system pointing device, i.e. it controls
- * the normal Windows cursor. This seems much more natural.
- */
-#define USE_SYSCONTEXT 1 /* The code for the other choice is not
- * good at all.
- */
-
#define DEBUG_WINTAB 1 /* Verbose debug messages enabled */
-#endif
-
-#if defined(HAVE_WINTAB) || defined(HAVE_WHATEVER_OTHER)
-#define HAVE_SOME_XINPUT
-#endif
+#define PROXIMITY_OUT_DELAY 200 /* In milliseconds, see set_ignore_core */
#define TWOPI (2.*G_PI)
/* Forward declarations */
-#if !USE_SYSCONTEXT
-static GdkInputWindow *gdk_input_window_find_within (GdkWindow *window);
-#endif
-
-#ifdef HAVE_WINTAB
-
static GdkDevicePrivate *gdk_input_find_dev_from_ctx (HCTX hctx,
UINT id);
-static GList *wintab_contexts;
-
-static GdkWindow *wintab_window;
-
-#endif /* HAVE_WINTAB */
-
-#ifdef HAVE_WINTAB
+static GList *wintab_contexts = NULL;
+
+static GdkWindow *wintab_window = NULL;
+
+static GdkWindow *x_grab_window = NULL; /* Window that currently holds
+ * the extended inputs grab
+ */
+static GdkEventMask x_grab_mask;
+static gboolean x_grab_owner_events;
+
+typedef UINT (WINAPI *t_WTInfoA) (UINT a, UINT b, LPVOID c);
+typedef BOOL (WINAPI *t_WTEnable) (HCTX a, BOOL b);
+typedef HCTX (WINAPI *t_WTOpenA) (HWND a, LPLOGCONTEXTA b, BOOL c);
+typedef BOOL (WINAPI *t_WTOverlap) (HCTX a, BOOL b);
+typedef BOOL (WINAPI *t_WTPacket) (HCTX a, UINT b, LPVOID c);
+typedef int (WINAPI *t_WTQueueSizeSet) (HCTX a, int b);
+
+static t_WTInfoA p_WTInfoA;
+static t_WTEnable p_WTEnable;
+static t_WTOpenA p_WTOpenA;
+static t_WTOverlap p_WTOverlap;
+static t_WTPacket p_WTPacket;
+static t_WTQueueSizeSet p_WTQueueSizeSet;
static GdkDevicePrivate *
gdk_input_find_dev_from_ctx (HCTX hctx,
if (lc->lcOptions & CXO_MARGIN) g_print (" CXO_MARGIN");
if (lc->lcOptions & CXO_MGNINSIDE) g_print (" CXO_MGNINSIDE");
if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
- if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
g_print ("\n");
g_print ("lcStatus =");
if (lc->lcStatus & CXS_DISABLED) g_print (" CXS_DISABLED");
lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.);
}
+static void
+print_cursor (int index)
+{
+ int size;
+ int i;
+ char *name;
+ BOOL active;
+ WTPKT wtpkt;
+ BYTE buttons;
+ BYTE buttonbits;
+ char *btnnames;
+ char *p;
+ BYTE buttonmap[32];
+ BYTE sysbtnmap[32];
+ BYTE npbutton;
+ UINT npbtnmarks[2];
+ UINT *npresponse;
+ BYTE tpbutton;
+ UINT tpbtnmarks[2];
+ UINT *tpresponse;
+ DWORD physid;
+ UINT mode;
+ UINT minpktdata;
+ UINT minbuttons;
+ UINT capabilities;
+
+ size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_NAME, NULL);
+ name = g_malloc (size + 1);
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_NAME, name);
+ g_print ("NAME: %s\n", name);
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_ACTIVE, &active);
+ g_print ("ACTIVE: %s\n", active ? "YES" : "NO");
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_PKTDATA, &wtpkt);
+ g_print ("PKTDATA: %#x:", (guint) wtpkt);
+#define BIT(x) if (wtpkt & PK_##x) g_print (" " #x)
+ BIT (CONTEXT);
+ BIT (STATUS);
+ BIT (TIME);
+ BIT (CHANGED);
+ BIT (SERIAL_NUMBER);
+ BIT (BUTTONS);
+ BIT (X);
+ BIT (Y);
+ BIT (Z);
+ BIT (NORMAL_PRESSURE);
+ BIT (TANGENT_PRESSURE);
+ BIT (ORIENTATION);
+ BIT (ROTATION);
+#undef BIT
+ g_print ("\n");
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONS, &buttons);
+ g_print ("BUTTONS: %d\n", buttons);
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONBITS, &buttonbits);
+ g_print ("BUTTONBITS: %d\n", buttonbits);
+ size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_BTNNAMES, NULL);
+ g_print ("BTNNAMES:");
+ if (size > 0)
+ {
+ btnnames = g_malloc (size + 1);
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_BTNNAMES, btnnames);
+ p = btnnames;
+ while (*p)
+ {
+ g_print (" %s", p);
+ p += strlen (p) + 1;
+ }
+ }
+ g_print ("\n");
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONMAP, buttonmap);
+ g_print ("BUTTONMAP:");
+ for (i = 0; i < buttons; i++)
+ g_print (" %d", buttonmap[i]);
+ g_print ("\n");
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_SYSBTNMAP, sysbtnmap);
+ g_print ("SYSBTNMAP:");
+ for (i = 0; i < buttons; i++)
+ g_print (" %d", sysbtnmap[i]);
+ g_print ("\n");
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPBUTTON, &npbutton);
+ g_print ("NPBUTTON: %d\n", npbutton);
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPBTNMARKS, npbtnmarks);
+ g_print ("NPBTNMARKS: %d %d\n", npbtnmarks[0], npbtnmarks[1]);
+ size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPRESPONSE, NULL);
+ g_print ("NPRESPONSE:");
+ if (size > 0)
+ {
+ npresponse = g_malloc (size);
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPRESPONSE, npresponse);
+ for (i = 0; i < size / sizeof (UINT); i++)
+ g_print (" %d", npresponse[i]);
+ }
+ g_print ("\n");
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPBUTTON, &tpbutton);
+ g_print ("TPBUTTON: %d\n", tpbutton);
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPBTNMARKS, tpbtnmarks);
+ g_print ("TPBTNMARKS: %d %d\n", tpbtnmarks[0], tpbtnmarks[1]);
+ size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPRESPONSE, NULL);
+ g_print ("TPRESPONSE:");
+ if (size > 0)
+ {
+ tpresponse = g_malloc (size);
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPRESPONSE, tpresponse);
+ for (i = 0; i < size / sizeof (UINT); i++)
+ g_print (" %d", tpresponse[i]);
+ }
+ g_print ("\n");
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_PHYSID, &physid);
+ g_print ("PHYSID: %#x\n", (guint) physid);
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_CAPABILITIES, &capabilities);
+ g_print ("CAPABILITIES: %#x:", capabilities);
+#define BIT(x) if (capabilities & CRC_##x) g_print (" " #x)
+ BIT (MULTIMODE);
+ BIT (AGGREGATE);
+ BIT (INVERT);
+#undef BIT
+ g_print ("\n");
+ if (capabilities & CRC_MULTIMODE)
+ {
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_MODE, &mode);
+ g_print ("MODE: %d\n", mode);
+ }
+ if (capabilities & CRC_AGGREGATE)
+ {
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_MINPKTDATA, &minpktdata);
+ g_print ("MINPKTDATA: %d\n", minpktdata);
+ (*p_WTInfoA) (WTI_CURSORS + index, CSR_MINBUTTONS, &minbuttons);
+ g_print ("MINBUTTONS: %d\n", minbuttons);
+ }
+}
#endif
-static void
-gdk_input_wintab_init (void)
+void
+_gdk_input_wintab_init_check (void)
{
+ static gboolean wintab_initialized = FALSE;
GdkDevicePrivate *gdkdev;
GdkWindowAttr wa;
WORD specversion;
- LOGCONTEXT defcontext;
HCTX *hctx;
UINT ndevices, ncursors, ncsrtypes, firstcsr, hardware;
BOOL active;
+ DWORD physid;
AXIS axis_x, axis_y, axis_npressure, axis_or[3];
int i, k;
int devix, cursorix;
char devname[100], csrname[100];
+ BOOL defcontext_done;
+ HMODULE wintab32;
- _gdk_input_devices = NULL;
+ if (wintab_initialized)
+ return;
+
+ wintab_initialized = TRUE;
+
wintab_contexts = NULL;
- if (!_gdk_input_ignore_wintab &&
- WTInfo (0, 0, NULL))
- {
- WTInfo (WTI_INTERFACE, IFC_SPECVERSION, &specversion);
- GDK_NOTE (INPUT, g_print ("Wintab interface version %d.%d\n",
- HIBYTE (specversion), LOBYTE (specversion)));
-#if USE_SYSCONTEXT
- WTInfo (WTI_DEFSYSCTX, 0, &defcontext);
+ if (_gdk_input_ignore_wintab)
+ return;
+
+ if ((wintab32 = LoadLibrary ("wintab32.dll")) == NULL)
+ return;
+
+ if ((p_WTInfoA = (t_WTInfoA) GetProcAddress (wintab32, "WTInfoA")) == NULL)
+ return;
+ if ((p_WTEnable = (t_WTEnable) GetProcAddress (wintab32, "WTEnable")) == NULL)
+ return;
+ if ((p_WTOpenA = (t_WTOpenA) GetProcAddress (wintab32, "WTOpenA")) == NULL)
+ return;
+ if ((p_WTOverlap = (t_WTOverlap) GetProcAddress (wintab32, "WTOverlap")) == NULL)
+ return;
+ if ((p_WTPacket = (t_WTPacket) GetProcAddress (wintab32, "WTPacket")) == NULL)
+ return;
+ if ((p_WTQueueSizeSet = (t_WTQueueSizeSet) GetProcAddress (wintab32, "WTQueueSizeSet")) == NULL)
+ return;
+
+ if (!(*p_WTInfoA) (0, 0, NULL))
+ return;
+
+ (*p_WTInfoA) (WTI_INTERFACE, IFC_SPECVERSION, &specversion);
+ GDK_NOTE (INPUT, g_print ("Wintab interface version %d.%d\n",
+ HIBYTE (specversion), LOBYTE (specversion)));
+ (*p_WTInfoA) (WTI_INTERFACE, IFC_NDEVICES, &ndevices);
+ (*p_WTInfoA) (WTI_INTERFACE, IFC_NCURSORS, &ncursors);
#if DEBUG_WINTAB
- GDK_NOTE (INPUT, (g_print("DEFSYSCTX:\n"), print_lc(&defcontext)));
+ GDK_NOTE (INPUT, g_print ("NDEVICES: %d, NCURSORS: %d\n",
+ ndevices, ncursors));
#endif
-#else
- WTInfo (WTI_DEFCONTEXT, 0, &defcontext);
+ /* Create a dummy window to receive wintab events */
+ wa.wclass = GDK_INPUT_OUTPUT;
+ wa.event_mask = GDK_ALL_EVENTS_MASK;
+ wa.width = 2;
+ wa.height = 2;
+ wa.x = -100;
+ wa.y = -100;
+ wa.window_type = GDK_WINDOW_TOPLEVEL;
+ if ((wintab_window = gdk_window_new (NULL, &wa, GDK_WA_X|GDK_WA_Y)) == NULL)
+ {
+ g_warning ("gdk_input_wintab_init: gdk_window_new failed");
+ return;
+ }
+ g_object_ref (wintab_window);
+
+ for (devix = 0; devix < ndevices; devix++)
+ {
+ LOGCONTEXT lc;
+
+ /* We open the Wintab device (hmm, what if there are several?) as a
+ * system pointing device, i.e. it controls the normal Windows
+ * cursor. This seems much more natural.
+ */
+
+ (*p_WTInfoA) (WTI_DEVICES + devix, DVC_NAME, devname);
+
+ (*p_WTInfoA) (WTI_DEVICES + devix, DVC_NCSRTYPES, &ncsrtypes);
+ (*p_WTInfoA) (WTI_DEVICES + devix, DVC_FIRSTCSR, &firstcsr);
+ (*p_WTInfoA) (WTI_DEVICES + devix, DVC_HARDWARE, &hardware);
+ (*p_WTInfoA) (WTI_DEVICES + devix, DVC_X, &axis_x);
+ (*p_WTInfoA) (WTI_DEVICES + devix, DVC_Y, &axis_y);
+ (*p_WTInfoA) (WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure);
+ (*p_WTInfoA) (WTI_DEVICES + devix, DVC_ORIENTATION, axis_or);
+
+ defcontext_done = FALSE;
+ if (HIBYTE (specversion) > 1 || LOBYTE (specversion) >= 1)
+ {
+ /* Try to get device-specific default context */
+ /* Some drivers, e.g. Aiptek, don't provide this info */
+ if ((*p_WTInfoA) (WTI_DSCTXS + devix, 0, &lc) > 0)
+ defcontext_done = TRUE;
#if DEBUG_WINTAB
- GDK_NOTE (INPUT, (g_print("DEFCONTEXT:\n"), print_lc(&defcontext)));
+ if (defcontext_done)
+ GDK_NOTE (INPUT, (g_print("Using device-specific default context\n")));
+ else
+ GDK_NOTE (INPUT, (g_print("Note: Driver did not provide device specific default context info despite claiming to support version 1.1\n")));
#endif
+ }
+
+ if (!defcontext_done)
+ (*p_WTInfoA) (WTI_DEFSYSCTX, 0, &lc);
+#if DEBUG_WINTAB
+ GDK_NOTE (INPUT, (g_print("Default context:\n"), print_lc(&lc)));
#endif
- WTInfo (WTI_INTERFACE, IFC_NDEVICES, &ndevices);
- WTInfo (WTI_INTERFACE, IFC_NCURSORS, &ncursors);
+ lc.lcOptions |= CXO_MESSAGES;
+ lc.lcStatus = 0;
+ lc.lcMsgBase = WT_DEFBASE;
+ lc.lcPktRate = 50;
+ lc.lcPktData = PACKETDATA;
+ lc.lcPktMode = PACKETMODE;
+ lc.lcMoveMask = PACKETDATA;
+ lc.lcBtnUpMask = lc.lcBtnDnMask = ~0;
+ lc.lcOutOrgX = axis_x.axMin;
+ lc.lcOutOrgY = axis_y.axMin;
+ lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
+ lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
+ lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
#if DEBUG_WINTAB
- GDK_NOTE (INPUT, g_print ("NDEVICES: %d, NCURSORS: %d\n",
- ndevices, ncursors));
+ GDK_NOTE (INPUT, (g_print("context for device %d:\n", devix),
+ print_lc(&lc)));
#endif
- /* Create a dummy window to receive wintab events */
- wa.wclass = GDK_INPUT_OUTPUT;
- wa.event_mask = GDK_ALL_EVENTS_MASK;
- wa.width = 2;
- wa.height = 2;
- wa.x = -100;
- wa.y = -100;
- wa.window_type = GDK_WINDOW_TOPLEVEL;
- if ((wintab_window = gdk_window_new (NULL, &wa, GDK_WA_X|GDK_WA_Y)) == NULL)
+ hctx = g_new (HCTX, 1);
+ if ((*hctx = (*p_WTOpenA) (GDK_WINDOW_HWND (wintab_window), &lc, TRUE)) == NULL)
{
- g_warning ("gdk_input_wintab_init: gdk_window_new failed");
+ g_warning ("gdk_input_wintab_init: WTOpen failed");
return;
}
- g_object_ref (wintab_window);
+ GDK_NOTE (INPUT, g_print ("opened Wintab device %d %p\n",
+ devix, *hctx));
- for (devix = 0; devix < ndevices; devix++)
- {
- LOGCONTEXT lc;
+ wintab_contexts = g_list_append (wintab_contexts, hctx);
+#if 0
+ (*p_WTEnable) (*hctx, TRUE);
+#endif
+ (*p_WTOverlap) (*hctx, TRUE);
- WTInfo (WTI_DEVICES + devix, DVC_NAME, devname);
-
- WTInfo (WTI_DEVICES + devix, DVC_NCSRTYPES, &ncsrtypes);
- WTInfo (WTI_DEVICES + devix, DVC_FIRSTCSR, &firstcsr);
- WTInfo (WTI_DEVICES + devix, DVC_HARDWARE, &hardware);
- WTInfo (WTI_DEVICES + devix, DVC_X, &axis_x);
- WTInfo (WTI_DEVICES + devix, DVC_Y, &axis_y);
- WTInfo (WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure);
- WTInfo (WTI_DEVICES + devix, DVC_ORIENTATION, axis_or);
-
- if (HIBYTE (specversion) > 1 || LOBYTE (specversion) >= 1)
+#if DEBUG_WINTAB
+ GDK_NOTE (INPUT, (g_print("context for device %d after WTOpen:\n", devix),
+ print_lc(&lc)));
+#endif
+ /* Increase packet queue size to reduce the risk of lost packets.
+ * According to the specs, if the function fails we must try again
+ * with a smaller queue size.
+ */
+ GDK_NOTE (INPUT, g_print("Attempting to increase queue size\n"));
+ for (i = 32; i >= 1; i >>= 1)
+ {
+ if ((*p_WTQueueSizeSet) (*hctx, i))
{
- WTInfo (WTI_DDCTXS + devix, CTX_NAME, lc.lcName);
- WTInfo (WTI_DDCTXS + devix, CTX_OPTIONS, &lc.lcOptions);
- lc.lcOptions |= CXO_MESSAGES;
-#if USE_SYSCONTEXT
- lc.lcOptions |= CXO_SYSTEM;
+ GDK_NOTE (INPUT, g_print("Queue size set to %d\n", i));
+ break;
+ }
+ }
+ if (!i)
+ GDK_NOTE (INPUT, g_print("Whoops, no queue size could be set\n"));
+ for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes; cursorix++)
+ {
+#ifdef DEBUG_WINTAB
+ GDK_NOTE (INPUT, (g_print("Cursor %d:\n", cursorix), print_cursor (cursorix)));
#endif
- lc.lcStatus = 0;
- WTInfo (WTI_DDCTXS + devix, CTX_LOCKS, &lc.lcLocks);
- lc.lcMsgBase = WT_DEFBASE;
- lc.lcDevice = devix;
- lc.lcPktRate = 50;
- lc.lcPktData = PACKETDATA;
- lc.lcPktMode = PK_BUTTONS; /* We want buttons in relative mode */
- lc.lcMoveMask = PACKETDATA;
- lc.lcBtnDnMask = lc.lcBtnUpMask = ~0;
- WTInfo (WTI_DDCTXS + devix, CTX_INORGX, &lc.lcInOrgX);
- WTInfo (WTI_DDCTXS + devix, CTX_INORGY, &lc.lcInOrgY);
- WTInfo (WTI_DDCTXS + devix, CTX_INORGZ, &lc.lcInOrgZ);
- WTInfo (WTI_DDCTXS + devix, CTX_INEXTX, &lc.lcInExtX);
- WTInfo (WTI_DDCTXS + devix, CTX_INEXTY, &lc.lcInExtY);
- WTInfo (WTI_DDCTXS + devix, CTX_INEXTZ, &lc.lcInExtZ);
- lc.lcOutOrgX = axis_x.axMin;
- lc.lcOutOrgY = axis_y.axMin;
- lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
- lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
- lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
- WTInfo (WTI_DDCTXS + devix, CTX_SENSX, &lc.lcSensX);
- WTInfo (WTI_DDCTXS + devix, CTX_SENSY, &lc.lcSensY);
- WTInfo (WTI_DDCTXS + devix, CTX_SENSZ, &lc.lcSensZ);
- WTInfo (WTI_DDCTXS + devix, CTX_SYSMODE, &lc.lcSysMode);
- lc.lcSysOrgX = lc.lcSysOrgY = 0;
- WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTX, &lc.lcSysExtX);
- WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTY, &lc.lcSysExtY);
- WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSX, &lc.lcSysSensX);
- WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSY, &lc.lcSysSensY);
+ active = FALSE;
+ (*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_ACTIVE, &active);
+ if (!active)
+ continue;
+
+ /* Wacom tablets seem to report cursors corresponding to
+ * nonexistent pens or pucks. At least my ArtPad II reports
+ * six cursors: a puck, pressure stylus and eraser stylus,
+ * and then the same three again. I only have a
+ * pressure-sensitive pen. The puck instances, and the
+ * second instances of the styluses report physid zero. So
+ * at least for Wacom, skip cursors with physid zero.
+ */
+ (*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_PHYSID, &physid);
+ if (strcmp (devname, "WACOM Tablet") == 0 && physid == 0)
+ continue;
+
+ gdkdev = g_object_new (GDK_TYPE_DEVICE, NULL);
+ (*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_NAME, csrname);
+ gdkdev->info.name = g_strconcat (devname, " ", csrname, NULL);
+ gdkdev->info.source = GDK_SOURCE_PEN;
+ gdkdev->info.mode = GDK_MODE_SCREEN;
+ gdkdev->info.has_cursor = TRUE;
+ gdkdev->hctx = *hctx;
+ gdkdev->cursor = cursorix;
+ (*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_PKTDATA, &gdkdev->pktdata);
+ gdkdev->info.num_axes = 0;
+ if (gdkdev->pktdata & PK_X)
+ gdkdev->info.num_axes++;
+ if (gdkdev->pktdata & PK_Y)
+ gdkdev->info.num_axes++;
+ if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
+ gdkdev->info.num_axes++;
+ /* The wintab driver for the Wacom ArtPad II reports
+ * PK_ORIENTATION in CSR_PKTDATA, but the tablet doesn't
+ * actually sense tilt. Catch this by noticing that the
+ * orientation axis's azimuth resolution is zero.
+ */
+ if ((gdkdev->pktdata & PK_ORIENTATION)
+ && axis_or[0].axResolution == 0)
+ gdkdev->pktdata &= ~PK_ORIENTATION;
+
+ if (gdkdev->pktdata & PK_ORIENTATION)
+ gdkdev->info.num_axes += 2; /* x and y tilt */
+ (*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_NPBTNMARKS, &gdkdev->npbtnmarks);
+ gdkdev->info.axes = g_new (GdkDeviceAxis, gdkdev->info.num_axes);
+ gdkdev->axes = g_new (GdkAxisInfo, gdkdev->info.num_axes);
+ gdkdev->last_axis_data = g_new (gint, gdkdev->info.num_axes);
+
+ k = 0;
+ if (gdkdev->pktdata & PK_X)
+ {
+ gdkdev->axes[k].xresolution =
+ gdkdev->axes[k].resolution = axis_x.axResolution / 65535.;
+ gdkdev->axes[k].xmin_value =
+ gdkdev->axes[k].min_value = axis_x.axMin;
+ gdkdev->axes[k].xmax_value =
+ gdkdev->axes[k].max_value = axis_x.axMax;
+ gdkdev->info.axes[k].use = GDK_AXIS_X;
+ gdkdev->info.axes[k].min = axis_x.axMin;
+ gdkdev->info.axes[k].max = axis_x.axMax;
+ k++;
}
- else
+ if (gdkdev->pktdata & PK_Y)
{
- lc = defcontext;
- lc.lcOptions |= CXO_MESSAGES;
- lc.lcMsgBase = WT_DEFBASE;
- lc.lcPktRate = 50;
- lc.lcPktData = PACKETDATA;
- lc.lcPktMode = PACKETMODE;
- lc.lcMoveMask = PACKETDATA;
- lc.lcBtnUpMask = lc.lcBtnDnMask = ~0;
-#if 0
- lc.lcOutExtY = -lc.lcOutExtY; /* Y grows downward */
-#else
- lc.lcOutOrgX = axis_x.axMin;
- lc.lcOutOrgY = axis_y.axMin;
- lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
- lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
- lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
-#endif
+ gdkdev->axes[k].xresolution =
+ gdkdev->axes[k].resolution = axis_y.axResolution / 65535.;
+ gdkdev->axes[k].xmin_value =
+ gdkdev->axes[k].min_value = axis_y.axMin;
+ gdkdev->axes[k].xmax_value =
+ gdkdev->axes[k].max_value = axis_y.axMax;
+ gdkdev->info.axes[k].use = GDK_AXIS_Y;
+ gdkdev->info.axes[k].min = axis_y.axMin;
+ gdkdev->info.axes[k].max = axis_y.axMax;
+ k++;
}
-#if DEBUG_WINTAB
- GDK_NOTE (INPUT, (g_print("context for device %d:\n", devix),
- print_lc(&lc)));
-#endif
- hctx = g_new (HCTX, 1);
- if ((*hctx = WTOpen (GDK_WINDOW_HWND (wintab_window), &lc, TRUE)) == NULL)
+ if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
{
- g_warning ("gdk_input_wintab_init: WTOpen failed");
- return;
+ gdkdev->axes[k].xresolution =
+ gdkdev->axes[k].resolution = axis_npressure.axResolution / 65535.;
+ gdkdev->axes[k].xmin_value =
+ gdkdev->axes[k].min_value = axis_npressure.axMin;
+ gdkdev->axes[k].xmax_value =
+ gdkdev->axes[k].max_value = axis_npressure.axMax;
+ gdkdev->info.axes[k].use = GDK_AXIS_PRESSURE;
+ /* GIMP seems to expect values in the range 0-1 */
+ gdkdev->info.axes[k].min = 0.0; /*axis_npressure.axMin;*/
+ gdkdev->info.axes[k].max = 1.0; /*axis_npressure.axMax;*/
+ k++;
}
- GDK_NOTE (INPUT, g_print ("opened Wintab device %d %p\n",
- devix, *hctx));
-
- wintab_contexts = g_list_append (wintab_contexts, hctx);
-#if 0
- WTEnable (*hctx, TRUE);
-#endif
- WTOverlap (*hctx, TRUE);
-
-#if DEBUG_WINTAB
- GDK_NOTE (INPUT, (g_print("context for device %d after WTOpen:\n", devix),
- print_lc(&lc)));
-#endif
- for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes; cursorix++)
+ if (gdkdev->pktdata & PK_ORIENTATION)
{
- active = FALSE;
- WTInfo (WTI_CURSORS + cursorix, CSR_ACTIVE, &active);
- if (!active)
- continue;
- gdkdev = g_object_new (GDK_TYPE_DEVICE, NULL);
- WTInfo (WTI_CURSORS + cursorix, CSR_NAME, csrname);
- gdkdev->info.name = g_strconcat (devname, " ", csrname, NULL);
- gdkdev->info.source = GDK_SOURCE_PEN;
- gdkdev->info.mode = GDK_MODE_SCREEN;
-#if USE_SYSCONTEXT
- gdkdev->info.has_cursor = TRUE;
-#else
- gdkdev->info.has_cursor = FALSE;
-#endif
- gdkdev->hctx = *hctx;
- gdkdev->cursor = cursorix;
- WTInfo (WTI_CURSORS + cursorix, CSR_PKTDATA, &gdkdev->pktdata);
- gdkdev->info.num_axes = 0;
- if (gdkdev->pktdata & PK_X)
- gdkdev->info.num_axes++;
- if (gdkdev->pktdata & PK_Y)
- gdkdev->info.num_axes++;
- if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
- gdkdev->info.num_axes++;
- /* The wintab driver for the Wacom ArtPad II reports
- * PK_ORIENTATION in CSR_PKTDATA, but the tablet doesn't
- * actually sense tilt. Catch this by noticing that the
- * orientation axis's azimuth resolution is zero.
- */
- if ((gdkdev->pktdata & PK_ORIENTATION)
- && axis_or[0].axResolution == 0)
- gdkdev->pktdata &= ~PK_ORIENTATION;
-
- if (gdkdev->pktdata & PK_ORIENTATION)
- gdkdev->info.num_axes += 2; /* x and y tilt */
- WTInfo (WTI_CURSORS + cursorix, CSR_NPBTNMARKS, &gdkdev->npbtnmarks);
- gdkdev->info.axes = g_new (GdkDeviceAxis, gdkdev->info.num_axes);
- gdkdev->axes = g_new (GdkAxisInfo, gdkdev->info.num_axes);
- gdkdev->last_axis_data = g_new (gint, gdkdev->info.num_axes);
+ GdkAxisUse axis;
- k = 0;
- if (gdkdev->pktdata & PK_X)
- {
- gdkdev->axes[k].xresolution =
- gdkdev->axes[k].resolution = axis_x.axResolution / 65535.;
- gdkdev->axes[k].xmin_value =
- gdkdev->axes[k].min_value = axis_x.axMin;
- gdkdev->axes[k].xmax_value =
- gdkdev->axes[k].max_value = axis_x.axMax;
- gdkdev->info.axes[k].use = GDK_AXIS_X;
- gdkdev->info.axes[k].min = axis_x.axMin;
- gdkdev->info.axes[k].min = axis_x.axMax;
- k++;
- }
- if (gdkdev->pktdata & PK_Y)
+ gdkdev->orientation_axes[0] = axis_or[0];
+ gdkdev->orientation_axes[1] = axis_or[1];
+ for (axis = GDK_AXIS_XTILT; axis <= GDK_AXIS_YTILT; axis++)
{
+ /* Wintab gives us aximuth and altitude, which
+ * we convert to x and y tilt in the -1000..1000 range
+ */
gdkdev->axes[k].xresolution =
- gdkdev->axes[k].resolution = axis_y.axResolution / 65535.;
+ gdkdev->axes[k].resolution = 1000;
gdkdev->axes[k].xmin_value =
- gdkdev->axes[k].min_value = axis_y.axMin;
+ gdkdev->axes[k].min_value = -1000;
gdkdev->axes[k].xmax_value =
- gdkdev->axes[k].max_value = axis_y.axMax;
- gdkdev->info.axes[k].use = GDK_AXIS_Y;
- gdkdev->info.axes[k].min = axis_y.axMin;
- gdkdev->info.axes[k].min = axis_y.axMax;
+ gdkdev->axes[k].max_value = 1000;
+ gdkdev->info.axes[k].use = axis;
+ gdkdev->info.axes[k].min = -1000;
+ gdkdev->info.axes[k].max = 1000;
k++;
}
- if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
- {
- gdkdev->axes[k].xresolution =
- gdkdev->axes[k].resolution = axis_npressure.axResolution / 65535.;
- gdkdev->axes[k].xmin_value =
- gdkdev->axes[k].min_value = axis_npressure.axMin;
- gdkdev->axes[k].xmax_value =
- gdkdev->axes[k].max_value = axis_npressure.axMax;
- gdkdev->info.axes[k].use = GDK_AXIS_PRESSURE;
- gdkdev->info.axes[k].min = axis_npressure.axMin;
- gdkdev->info.axes[k].min = axis_npressure.axMax;
- k++;
- }
- if (gdkdev->pktdata & PK_ORIENTATION)
- {
- GdkAxisUse axis;
-
- gdkdev->orientation_axes[0] = axis_or[0];
- gdkdev->orientation_axes[1] = axis_or[1];
- for (axis = GDK_AXIS_XTILT; axis <= GDK_AXIS_YTILT; axis++)
- {
- /* Wintab gives us aximuth and altitude, which
- * we convert to x and y tilt in the -1000..1000 range
- */
- gdkdev->axes[k].xresolution =
- gdkdev->axes[k].resolution = 1000;
- gdkdev->axes[k].xmin_value =
- gdkdev->axes[k].min_value = -1000;
- gdkdev->axes[k].xmax_value =
- gdkdev->axes[k].max_value = 1000;
- gdkdev->info.axes[k].use = axis;
- gdkdev->info.axes[k].min = -1000;
- gdkdev->info.axes[k].min = 1000;
- k++;
- }
- }
- gdkdev->info.num_keys = 0;
- gdkdev->info.keys = NULL;
- GDK_NOTE (INPUT,
- g_print ("device: (%d) %s axes: %d\n",
- cursorix,
- gdkdev->info.name,
- gdkdev->info.num_axes));
- for (i = 0; i < gdkdev->info.num_axes; i++)
- GDK_NOTE (INPUT,
- g_print ("...axis %d: %d--%d@%d (%d--%d@%d)\n",
- i,
- gdkdev->axes[i].xmin_value,
- gdkdev->axes[i].xmax_value,
- gdkdev->axes[i].xresolution,
- gdkdev->axes[i].min_value,
- gdkdev->axes[i].max_value,
- gdkdev->axes[i].resolution));
- _gdk_input_devices = g_list_append (_gdk_input_devices,
- gdkdev);
}
+ gdkdev->info.num_keys = 0;
+ gdkdev->info.keys = NULL;
+ GDK_NOTE (INPUT, g_print ("device: (%d) %s axes: %d\n",
+ cursorix,
+ gdkdev->info.name,
+ gdkdev->info.num_axes));
+ for (i = 0; i < gdkdev->info.num_axes; i++)
+ GDK_NOTE (INPUT, g_print ("... axis %d: %d--%d@%d (%d--%d@%d)\n",
+ i,
+ gdkdev->axes[i].xmin_value,
+ gdkdev->axes[i].xmax_value,
+ gdkdev->axes[i].xresolution,
+ gdkdev->axes[i].min_value,
+ gdkdev->axes[i].max_value,
+ gdkdev->axes[i].resolution));
+ _gdk_input_devices = g_list_append (_gdk_input_devices,
+ gdkdev);
}
}
}
axis_data[1] = sin (az) * cos (el) * 1000;
}
-#if !USE_SYSCONTEXT
-
-static GdkInputWindow *
-gdk_input_window_find_within (GdkWindow *window)
-{
- GList *list;
- GdkWindow *tmpw;
- GdkInputWindow *candidate = NULL;
-
- for (list = _gdk_input_windows; list != NULL; list = list->next)
- {
- tmpw = ((GdkInputWindow *) (tmp_list->data))->window;
- if (tmpw == window
- || IsChild (GDK_WINDOW_HWND (window), GDK_WINDOW_HWND (tmpw)))
- {
- if (candidate)
- return NULL; /* Multiple hits */
- candidate = (GdkInputWindow *) (list->data);
- }
- }
-
- return candidate;
-}
-
-#endif /* USE_SYSCONTEXT */
-
-#endif /* HAVE_WINTAB */
-
static void
gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
GdkInputWindow *input_window,
gdouble *x_out,
gdouble *y_out)
{
- GdkWindowImplWin32 *impl;
+ GdkWindowImplWin32 *impl, *root_impl;
int i;
int x_axis = 0;
if (gdkdev->info.mode == GDK_MODE_SCREEN)
{
- x_scale = GetSystemMetrics (SM_CXSCREEN) / device_width;
- y_scale = GetSystemMetrics (SM_CYSCREEN) / device_height;
+ root_impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (_gdk_root)->impl);
+ x_scale = root_impl->width / device_width;
+ y_scale = root_impl->height / device_height;
x_offset = - input_window->root_x;
y_offset = - input_window->root_y;
GetWindowRect (w, &rect);
if (x_ret)
- *x_ret = rect.left;
+ *x_ret = rect.left + _gdk_offset_x;
if (y_ret)
- *y_ret = rect.top;
-}
-
-GdkTimeCoord *
-gdk_input_motion_events (GdkWindow *window,
- guint32 deviceid,
- guint32 start,
- guint32 stop,
- gint *nevents_return)
-{
- g_return_val_if_fail (window != NULL, NULL);
- if (GDK_WINDOW_DESTROYED (window))
- return NULL;
-
- *nevents_return = 0;
- return NULL; /* ??? */
+ *y_ret = rect.top + _gdk_offset_y;
}
void
input_window->root_y = root_y;
}
+/*
+ * Get the currently active keyboard modifiers (ignoring the mouse buttons)
+ * We could use gdk_window_get_pointer but that function does a lot of other
+ * expensive things besides getting the modifiers. This code is somewhat based
+ * on build_pointer_event_state from gdkevents-win32.c
+ */
+static guint
+get_modifier_key_state (void)
+{
+ guint state;
+
+ state = 0;
+ /* High-order bit is up/down, low order bit is toggled/untoggled */
+ if (GetKeyState (VK_CONTROL) < 0)
+ state |= GDK_CONTROL_MASK;
+ if (GetKeyState (VK_SHIFT) < 0)
+ state |= GDK_SHIFT_MASK;
+ if (GetKeyState (VK_MENU) < 0)
+ state |= GDK_MOD1_MASK;
+ if (GetKeyState (VK_CAPITAL) & 0x1)
+ state |= GDK_LOCK_MASK;
+
+ return state;
+}
+
+static guint ignore_core_timer = 0;
+
+static gboolean
+ignore_core_timefunc (gpointer data)
+{
+ /* The delay has passed */
+ _gdk_input_ignore_core = FALSE;
+ ignore_core_timer = 0;
+
+ return FALSE; /* remove timeout */
+}
+
+/*
+ * Set or unset the _gdk_input_ignore_core variable that tells GDK
+ * to ignore events for the core pointer when the tablet is in proximity
+ * The unsetting is delayed slightly so that if a tablet event arrives
+ * just after proximity out, it does not cause a core pointer event
+ * which e.g. causes GIMP to switch tools.
+ */
+static void
+set_ignore_core (gboolean ignore)
+{
+ if (ignore)
+ {
+ _gdk_input_ignore_core = TRUE;
+ /* Remove any pending clear */
+ if (ignore_core_timer)
+ {
+ g_source_remove (ignore_core_timer);
+ ignore_core_timer = 0;
+ }
+ }
+ else
+ if (!ignore_core_timer)
+ ignore_core_timer = gdk_threads_add_timeout (PROXIMITY_OUT_DELAY,
+ ignore_core_timefunc, NULL);
+}
+
gboolean
_gdk_input_other_event (GdkEvent *event,
MSG *msg,
GdkWindow *window)
{
-#ifdef HAVE_WINTAB
-#if !USE_SYSCONTEXT
- GdkWindow *current_window;
-#endif
GdkDisplay *display;
- GdkWindowObject *obj;
- GdkWindowImplWin32 *impl;
+ GdkWindowObject *obj, *grab_obj;
GdkInputWindow *input_window;
GdkDevicePrivate *gdkdev = NULL;
GdkEventMask masktest;
+ guint key_state;
POINT pt;
PACKET packet;
gint k;
gint x, y;
+ guint translated_buttons, button_diff, button_mask;
+ /* Translation from tablet button state to GDK button state for
+ * buttons 1-3 - swap button 2 and 3.
+ */
+ static guint button_map[8] = {0, 1, 4, 5, 2, 3, 6, 7};
if (event->any.window != wintab_window)
{
return FALSE;
}
-#if USE_SYSCONTEXT
window = gdk_window_at_pointer (&x, &y);
if (window == NULL)
- window = _gdk_parent_root;
+ window = _gdk_root;
g_object_ref (window);
display = gdk_drawable_get_display (window);
GDK_NOTE (EVENTS_OR_INPUT,
- g_print ("gdk_input_win32_other_event: window=%p (%d,%d)\n",
+ g_print ("gdk_input_win32_other_event: window=%p %+d%+d\n",
GDK_WINDOW_HWND (window), x, y));
-#else
- /* ??? This code is pretty bogus */
- current_window = gdk_win32_handle_table_lookup (GetActiveWindow ());
- if (current_window == NULL)
- return FALSE;
-
- input_window = gdk_input_window_find_within (current_window);
- if (input_window == NULL)
- return FALSE;
-#endif
-
if (msg->message == WT_PACKET)
{
- if (!WTPacket ((HCTX) msg->lParam, msg->wParam, &packet))
+ if (!(*p_WTPacket) ((HCTX) msg->lParam, msg->wParam, &packet))
return FALSE;
}
obj = GDK_WINDOW_OBJECT (window);
- impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
switch (msg->message)
{
case WT_PACKET:
- if (window == _gdk_parent_root)
+ /* Don't produce any button or motion events while a window is being
+ * moved or resized, see bug #151090.
+ */
+ if (_sizemove_in_progress)
+ {
+ GDK_NOTE (EVENTS_OR_INPUT, g_print ("... ignored when moving/sizing\n"));
+ return FALSE;
+ }
+ if (window == _gdk_root && x_grab_window == NULL)
{
- GDK_NOTE (EVENTS_OR_INPUT, g_print ("...is root\n"));
+ GDK_NOTE (EVENTS_OR_INPUT, g_print ("... is root\n"));
return FALSE;
}
g_assert (k == gdkdev->info.num_axes);
- if (HIWORD (packet.pkButtons) != TBN_NONE)
+ translated_buttons = button_map[packet.pkButtons & 0x07] | (packet.pkButtons & ~0x07);
+
+ if (translated_buttons != gdkdev->button_state)
{
+ /* At least one button has changed state so produce a button event
+ * If more than one button has changed state (unlikely),
+ * just care about the first and act on the next the next time
+ * we get a packet
+ */
+ button_diff = translated_buttons ^ gdkdev->button_state;
+
/* Gdk buttons are numbered 1.. */
- event->button.button = 1 + LOWORD (packet.pkButtons);
+ event->button.button = 1;
- if (HIWORD (packet.pkButtons) == TBN_UP)
+ for (button_mask = 1; button_mask != 0x80000000;
+ button_mask <<= 1, event->button.button++)
+ {
+ if (button_diff & button_mask)
+ {
+ /* Found a button that has changed state */
+ break;
+ }
+ }
+
+ if (!(translated_buttons & button_mask))
{
event->any.type = GDK_BUTTON_RELEASE;
masktest = GDK_BUTTON_RELEASE_MASK;
- gdkdev->button_state &= ~(1 << LOWORD (packet.pkButtons));
}
else
{
event->any.type = GDK_BUTTON_PRESS;
masktest = GDK_BUTTON_PRESS_MASK;
- gdkdev->button_state |= 1 << LOWORD (packet.pkButtons);
}
+ gdkdev->button_state ^= button_mask;
}
else
{
masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK;
}
+ /* See if input is grabbed */
+ /* FIXME: x_grab_owner_events should probably be handled somehow */
+ if (x_grab_window != NULL)
+ {
+ grab_obj = GDK_WINDOW_OBJECT (x_grab_window);
+ if (!GDK_WINDOW_IMPL_WIN32 (grab_obj->impl)->extension_events_selected
+ || !(grab_obj->extension_events & masktest)
+ || !(x_grab_mask && masktest))
+ {
+ GDK_NOTE (EVENTS_OR_INPUT,
+ g_print ("... grabber doesn't want it\n"));
+ return FALSE;
+ }
+ GDK_NOTE (EVENTS_OR_INPUT, g_print ("... to grabber\n"));
+
+ g_object_ref(x_grab_window);
+ g_object_unref(window);
+ window = x_grab_window;
+ obj = grab_obj;
+ }
/* Now we can check if the window wants the event, and
* propagate if necessary.
*/
- dijkstra:
- if (!impl->extension_events_selected
+ loop:
+ if (!GDK_WINDOW_IMPL_WIN32 (obj->impl)->extension_events_selected
|| !(obj->extension_events & masktest))
{
- GDK_NOTE (EVENTS_OR_INPUT, g_print ("...not selected\n"));
+ GDK_NOTE (EVENTS_OR_INPUT, g_print ("... not selected\n"));
- if (obj->parent == GDK_WINDOW_OBJECT (_gdk_parent_root))
+ if (obj->parent == GDK_WINDOW_OBJECT (_gdk_root))
return FALSE;
+
+ /* It is not good to propagate the extended events up to the parent
+ * if this window wants normal (not extended) motion/button events */
+ if (obj->event_mask & masktest)
+ {
+ GDK_NOTE (EVENTS_OR_INPUT,
+ g_print ("... wants ordinary event, ignoring this\n"));
+ return FALSE;
+ }
pt.x = x;
pt.y = y;
ScreenToClient (GDK_WINDOW_HWND (window), &pt);
x = pt.x;
y = pt.y;
- GDK_NOTE (EVENTS_OR_INPUT, g_print ("...propagating to %p (%d,%d)\n",
+ GDK_NOTE (EVENTS_OR_INPUT, g_print ("... propagating to %p %+d%+d\n",
GDK_WINDOW_HWND (window), x, y));
- goto dijkstra;
+ goto loop;
}
input_window = _gdk_input_window_find (window);
return FALSE;
event->any.window = window;
-
+ key_state = get_modifier_key_state ();
if (event->any.type == GDK_BUTTON_PRESS
|| event->any.type == GDK_BUTTON_RELEASE)
{
event->button.time = _gdk_win32_get_next_tick (msg->time);
event->button.device = &gdkdev->info;
-#if 0
-#if USE_SYSCONTEXT
- /* Buttons 1 to 3 will come in as WM_[LMR]BUTTON{DOWN,UP} */
- if (event->button.button <= 3)
- return FALSE;
-#endif
-#endif
+ event->button.axes = g_new(gdouble, gdkdev->info.num_axes);
+
gdk_input_translate_coordinates (gdkdev, input_window,
gdkdev->last_axis_data,
event->button.axes,
&event->button.x,
&event->button.y);
+ /* Also calculate root coordinates. Note that input_window->root_x
+ is in GDK root coordinates. */
+ event->button.x_root = event->button.x + input_window->root_x;
+ event->button.y_root = event->button.y + input_window->root_y;
+
event->button.state = ((gdkdev->button_state << 8)
& (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
| GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
- | GDK_BUTTON5_MASK));
+ | GDK_BUTTON5_MASK))
+ | key_state;
GDK_NOTE (EVENTS_OR_INPUT,
g_print ("WINTAB button %s:%d %g,%g\n",
(event->button.type == GDK_BUTTON_PRESS ?
event->motion.is_hint = FALSE;
event->motion.device = &gdkdev->info;
+ event->motion.axes = g_new(gdouble, gdkdev->info.num_axes);
+
gdk_input_translate_coordinates (gdkdev, input_window,
gdkdev->last_axis_data,
event->motion.axes,
&event->motion.x,
&event->motion.y);
+ /* Also calculate root coordinates. Note that input_window->root_x
+ is in GDK root coordinates. */
+ event->motion.x_root = event->motion.x + input_window->root_x;
+ event->motion.y_root = event->motion.y + input_window->root_y;
+
event->motion.state = ((gdkdev->button_state << 8)
& (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
| GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
- | GDK_BUTTON5_MASK));
+ | GDK_BUTTON5_MASK))
+ | key_state;
GDK_NOTE (EVENTS_OR_INPUT,
g_print ("WINTAB motion: %g,%g\n",
event->motion.x, event->motion.y));
-
- /* Check for missing release or press events for the normal
- * pressure button. At least on my ArtPadII I sometimes miss a
- * release event?
- */
- if ((gdkdev->pktdata & PK_NORMAL_PRESSURE
- && (event->motion.state & GDK_BUTTON1_MASK)
- && packet.pkNormalPressure <= MAX (0, gdkdev->npbtnmarks[0] - 2))
- || (gdkdev->pktdata & PK_NORMAL_PRESSURE
- && !(event->motion.state & GDK_BUTTON1_MASK)
- && packet.pkNormalPressure > gdkdev->npbtnmarks[1] + 2))
- {
- GdkEvent *event2 = gdk_event_copy (event);
- if (event->motion.state & GDK_BUTTON1_MASK)
- {
- event2->button.type = GDK_BUTTON_RELEASE;
- gdkdev->button_state &= ~1;
- }
- else
- {
- event2->button.type = GDK_BUTTON_PRESS;
- gdkdev->button_state |= 1;
- }
- event2->button.state = ((gdkdev->button_state << 8)
- & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
- | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
- | GDK_BUTTON5_MASK));
- event2->button.button = 1;
- GDK_NOTE (EVENTS_OR_INPUT,
- g_print ("WINTAB synthesized button %s: %d %g,%gg\n",
- (event2->button.type == GDK_BUTTON_PRESS ?
- "press" : "release"),
- event2->button.button,
- event2->button.x,
- event2->button.y));
- _gdk_event_queue_append (display, event2);
- }
}
return TRUE;
if (LOWORD (msg->lParam) == 0)
{
event->proximity.type = GDK_PROXIMITY_OUT;
- _gdk_input_ignore_core = FALSE;
+ set_ignore_core (FALSE);
}
else
{
event->proximity.type = GDK_PROXIMITY_IN;
- _gdk_input_ignore_core = TRUE;
+ set_ignore_core (TRUE);
}
event->proximity.time = _gdk_win32_get_next_tick (msg->time);
event->proximity.device = &gdkdev->info;
"in" : "out")));
return TRUE;
}
-#endif
return FALSE;
}
_gdk_input_enable_window (GdkWindow *window,
GdkDevicePrivate *gdkdev)
{
-#ifdef HAVE_SOME_XINPUT
GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
impl->extension_events_selected = TRUE;
-#endif
return TRUE;
}
_gdk_input_disable_window (GdkWindow *window,
GdkDevicePrivate *gdkdev)
{
-#ifdef HAVE_SOME_XINPUT
GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
impl->extension_events_selected = FALSE;
-#endif
return TRUE;
}
GdkWindow *confine_to,
guint32 time)
{
-#ifdef HAVE_SOME_XINPUT
GdkInputWindow *input_window, *new_window;
gboolean need_ungrab;
GdkDevicePrivate *gdkdev;
if (new_window)
{
new_window->grabbed = TRUE;
+ x_grab_window = window;
+ x_grab_mask = event_mask;
+ x_grab_owner_events = owner_events;
+
+ /* FIXME: Do we need to handle confine_to and time? */
tmp_list = _gdk_input_devices;
while (tmp_list)
}
else
{
+ x_grab_window = NULL;
+#if 0
tmp_list = _gdk_input_devices;
while (tmp_list)
{
tmp_list = tmp_list->next;
}
- }
#endif
+ }
return GDK_GRAB_SUCCESS;
}
void
_gdk_input_ungrab_pointer (guint32 time)
{
-#ifdef HAVE_SOME_XINPUT
GdkInputWindow *input_window;
GdkDevicePrivate *gdkdev;
GList *tmp_list;
tmp_list = tmp_list->next;
}
}
-#endif
+ x_grab_window = NULL;
}
gboolean
GdkDevicePrivate *gdkdev;
GdkInputWindow *input_window;
- if (mask)
- gdk_window_get_pointer (window, NULL, NULL, mask);
-
gdkdev = (GdkDevicePrivate *)device;
+ /* For now just use the last known button and axis state of the device.
+ * Since graphical tablets send an insane amount of motion events each
+ * second, the info should be fairly up to date */
+ if (mask)
+ {
+ gdk_window_get_pointer (window, NULL, NULL, mask);
+ *mask &= 0xFF; /* Mask away core pointer buttons */
+ *mask |= ((gdkdev->button_state << 8)
+ & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
+ | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
+ | GDK_BUTTON5_MASK));
+ }
input_window = _gdk_input_window_find (window);
g_return_if_fail (input_window != NULL);
+ /* For some reason, input_window is sometimes NULL when I use The GIMP 2
+ * (bug #141543?). Avoid crashing if debugging is disabled. */
+ if (axes && gdkdev->last_axis_data && input_window)
+ gdk_input_translate_coordinates (gdkdev, input_window,
+ gdkdev->last_axis_data,
+ axes, NULL, NULL);
+ }
+}
-#if 0 /* FIXME */
- state = XQueryDeviceState (gdk_display, gdkdev->xdevice);
- input_class = state->data;
- for (i = 0; i < state->num_classes; i++)
- {
- switch (input_class->class)
- {
- case ValuatorClass:
- if (axes)
- gdk_input_translate_coordinates (gdkdev, input_window,
- ((XValuatorState *)input_class)->valuators,
- axes, NULL, NULL);
- break;
-
- case ButtonClass:
- if (mask)
- {
- *mask &= 0xFF;
- if (((XButtonState *)input_class)->num_buttons > 0)
- *mask |= ((XButtonState *)input_class)->buttons[0] << 7;
- /* GDK_BUTTON1_MASK = 1 << 8, and button n is stored
- * in bit 1<<(n%8) in byte n/8. n = 1,2,... */
- }
- break;
- }
- input_class = (XInputClass *)(((char *)input_class)+input_class->length);
- }
- XFreeDeviceState (state);
-#endif
+void
+_gdk_input_set_tablet_active (void)
+{
+ GList *tmp_list;
+ HCTX *hctx;
+
+ /* Bring the contexts to the top of the overlap order when one of the
+ * application's windows is activated */
+
+ if (!wintab_contexts)
+ return; /* No tablet devices found, or Wintab not initialized yet */
+
+ GDK_NOTE (INPUT, g_print ("_gdk_input_set_tablet_active: "
+ "Bringing Wintab contexts to the top of the overlap order\n"));
+
+ tmp_list = wintab_contexts;
+ while (tmp_list)
+ {
+ hctx = (HCTX *) (tmp_list->data);
+ (*p_WTOverlap) (*hctx, TRUE);
+ tmp_list = tmp_list->next;
}
}
_gdk_input_devices = NULL;
_gdk_init_input_core (display);
-#ifdef HAVE_WINTAB
- gdk_input_wintab_init ();
-#endif /* HAVE_WINTAB */
+#ifdef WINTAB_NO_LAZY_INIT
+ /* Normally, Wintab is only initialized when the application performs
+ * an action that requires it, such as enabling extended input events
+ * for a window or enumerating the devices.
+ */
+ _gdk_input_wintab_init_check ();
+#endif /* WINTAB_NO_LAZY_INIT */
_gdk_input_devices = g_list_append (_gdk_input_devices, display->core_pointer);
}