forked from AuroraMiddleware/gtk
00c5e83871
1999-10-31 Tor Lillqvist <tml@iki.fi> * gdk/gdkkeysyms.h: Add new keysyms from X11R6.4 (including EuroSign). * gdk/gdktypes.h: Add note about wchar_t not necessarily being the same type as GdkWChar, especially on Win32. * gdk/win32/*.c: Change gdk_root_parent to be a pointer. * gdk/win32/*.c: Assume all strings are UTF-8. Convert to Unicode before passing to Windows GDI for drawing etc. Convert to the system default codepage before passing to Windows as window titles. * gdk/win32/gdkprivate.h: Add more fields to GdkWindowPrivate to support changing input locale on the fly. * gdk/win32/gdkevent.c: Support input language (keyboard locale) on-the-fly changes. Convert incoming characters from the current codepage to Unicode (and then to a UTF-8 multi-byte string) based on the current input language. Use keysym<->Unicode mapping tables and functions borrowed from xterm sources. Support IMEs (Input Method Editors) for CJK languages. On non-CJK editions of Win9x, use the ActiveX-based Active IMM (Input Method Manager) if available. IMEs and the Active IMM are available under the disguise of Chinese, Korean and Japanese support for IE and Outlook Express from "Windows Update" for Win98. On Win2k, the CJK support is present in all editions (as long as you install it). Call DispatchMessage from gdk_events_queue() (and thus gdk_WindowProc()), instead of duplicating the code in gdk_WindowProc(). Reworked the grab handling and propagation code, factored out duplicated code snippets into separate functions. Other cleanups, too. * gdk/win32/surrogate-dimm.h: Provide just the bits we need from the <dimm.h> header describing the Active IMM. * gdk/win32/gdkfont.c: Pretend to support fontsets, but so far just do the same as for "single" fonts. * gdk/win32/gdk.c: Call CoInitialize() (COM initialisation) from gdk_init_check, and CoUninitialize() from gdk_exit_func. Handle the new keysyms from gdkkeysyms.h. * gtk/gtkfontsel.c (Win32): Load the font for the preview as a fontset, so that gtkentry uses wide characters. * gtk/gtkrc.c (Win32): Get the locale with gwin_getlocale(). Call GTk+'s system directory "gtk+", not "gtk".
1686 lines
48 KiB
C
1686 lines
48 KiB
C
/* GDK - The GIMP Drawing Kit
|
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
|
* Copyright (C) 1999 Tor Lillqvist
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
/*
|
|
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
|
* file for a list of people on the GTK+ Team. See the ChangeLog
|
|
* files for a list of changes. These files are distributed with
|
|
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
|
|
#include "gdk.h"
|
|
#include "gdkinput.h"
|
|
#include "gdkprivate.h"
|
|
#include "gdkx.h"
|
|
|
|
#ifdef HAVE_WINTAB
|
|
#include <wintab.h>
|
|
#define PACKETDATA (PK_CONTEXT | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION)
|
|
#define PACKETMODE (PK_BUTTONS)
|
|
#include <pktdef.h>
|
|
#endif
|
|
|
|
#include "gdkinputprivate.h"
|
|
|
|
struct _GdkDevicePrivate {
|
|
GdkDeviceInfo info;
|
|
|
|
/* information about the axes */
|
|
GdkAxisInfo *axes;
|
|
|
|
/* reverse lookup on axis use type */
|
|
gint axis_for_use[GDK_AXIS_LAST];
|
|
|
|
/* true if we need to select a different set of events, but
|
|
* can't because this is the core pointer
|
|
*/
|
|
gint needs_update;
|
|
|
|
/* State of buttons */
|
|
gint button_state;
|
|
|
|
gint *last_axis_data;
|
|
gint last_buttons;
|
|
#ifdef HAVE_WINTAB
|
|
/* WINTAB stuff: */
|
|
HCTX hctx;
|
|
/* Cursor number */
|
|
UINT cursor;
|
|
/* The cursor's CSR_PKTDATA */
|
|
WTPKT pktdata;
|
|
/* CSR_NPBTNMARKS */
|
|
UINT npbtnmarks[2];
|
|
/* Azimuth and altitude axis */
|
|
AXIS orientation_axes[2];
|
|
#endif
|
|
};
|
|
|
|
#ifndef M_PI
|
|
#define M_PI 3.14159265358979323846
|
|
#endif
|
|
|
|
/* 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.
|
|
*/
|
|
|
|
#ifdef HAVE_WINTAB
|
|
#define DEBUG_WINTAB 1
|
|
#endif
|
|
|
|
#define TWOPI (2.*M_PI)
|
|
|
|
#define PING() g_print("%s: %d\n",__FILE__,__LINE__)
|
|
|
|
/* Forward declarations */
|
|
|
|
static gint gdk_input_enable_window (GdkWindow *window,
|
|
GdkDevicePrivate *gdkdev);
|
|
static gint gdk_input_disable_window (GdkWindow *window,
|
|
GdkDevicePrivate *gdkdev);
|
|
static void gdk_input_none_get_pointer (GdkWindow *window,
|
|
guint32 deviceid,
|
|
gdouble *x,
|
|
gdouble *y,
|
|
gdouble *pressure,
|
|
gdouble *xtilt,
|
|
gdouble *ytilt,
|
|
GdkModifierType *mask);
|
|
|
|
static GdkDevicePrivate *gdk_input_find_device (guint32 deviceid);
|
|
|
|
#ifdef HAVE_WINTAB
|
|
|
|
static gint gdk_input_win32_set_mode (guint32 deviceid,
|
|
GdkInputMode mode);
|
|
static void gdk_input_win32_get_pointer (GdkWindow *window,
|
|
guint32 deviceid,
|
|
gdouble *x,
|
|
gdouble *y,
|
|
gdouble *pressure,
|
|
gdouble *xtilt,
|
|
gdouble *ytilt,
|
|
GdkModifierType *mask);
|
|
static gint gdk_input_win32_grab_pointer (GdkWindow * window,
|
|
gint owner_events,
|
|
GdkEventMask event_mask,
|
|
GdkWindow *confine_to,
|
|
guint32 time);
|
|
static void gdk_input_win32_ungrab_pointer (guint32 time);
|
|
static void gdk_input_win32_configure_event (GdkEventConfigure *event,
|
|
GdkWindow *window);
|
|
static void gdk_input_win32_enter_event (GdkEventCrossing *xevent,
|
|
GdkWindow *window);
|
|
static gint gdk_input_win32_other_event (GdkEvent *event,
|
|
MSG *xevent);
|
|
static gint gdk_input_win32_enable_window (GdkWindow *window,
|
|
GdkDevicePrivate *gdkdev);
|
|
static gint gdk_input_win32_disable_window (GdkWindow *window,
|
|
GdkDevicePrivate *gdkdev);
|
|
|
|
static GdkInputWindow *gdk_input_window_find (GdkWindow *window);
|
|
#if !USE_SYSCONTEXT
|
|
static GdkInputWindow *gdk_input_window_find_within (GdkWindow *window);
|
|
#endif
|
|
static GdkDevicePrivate *gdk_input_find_dev_from_ctx (HCTX hctx,
|
|
UINT id);
|
|
#endif /* HAVE_WINTAB */
|
|
|
|
/* Local variables */
|
|
|
|
static GList *gdk_input_devices;
|
|
static GList *gdk_input_windows;
|
|
static GList *wintab_contexts;
|
|
|
|
static gint gdk_input_root_width;
|
|
static gint gdk_input_root_height;
|
|
|
|
static GdkWindow *wintab_window;
|
|
|
|
static guint32 last_moved_cursor_id;
|
|
|
|
static GdkAxisUse gdk_input_core_axes[] = { GDK_AXIS_X, GDK_AXIS_Y };
|
|
|
|
static GdkDeviceInfo gdk_input_core_info =
|
|
{
|
|
GDK_CORE_POINTER,
|
|
"Core Pointer",
|
|
GDK_SOURCE_MOUSE,
|
|
GDK_MODE_SCREEN,
|
|
TRUE,
|
|
2,
|
|
gdk_input_core_axes
|
|
};
|
|
|
|
/* Global variables */
|
|
|
|
GdkInputVTable gdk_input_vtable;
|
|
gint gdk_input_ignore_core;
|
|
gint gdk_input_ignore_wintab = FALSE;
|
|
|
|
#if DEBUG_WINTAB
|
|
|
|
static void
|
|
print_lc(LOGCONTEXT *lc)
|
|
{
|
|
g_print ("lcName = %s\n", lc->lcName);
|
|
g_print ("lcOptions =");
|
|
if (lc->lcOptions & CXO_SYSTEM) g_print (" CXO_SYSTEM");
|
|
if (lc->lcOptions & CXO_PEN) g_print (" CXO_PEN");
|
|
if (lc->lcOptions & CXO_MESSAGES) g_print (" CXO_MESSAGES");
|
|
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");
|
|
if (lc->lcStatus & CXS_OBSCURED) g_print (" CXS_OBSCURED");
|
|
if (lc->lcStatus & CXS_ONTOP) g_print (" CXS_ONTOP");
|
|
g_print ("\n");
|
|
g_print ("lcLocks =");
|
|
if (lc->lcLocks & CXL_INSIZE) g_print (" CXL_INSIZE");
|
|
if (lc->lcLocks & CXL_INASPECT) g_print (" CXL_INASPECT");
|
|
if (lc->lcLocks & CXL_SENSITIVITY) g_print (" CXL_SENSITIVITY");
|
|
if (lc->lcLocks & CXL_MARGIN) g_print (" CXL_MARGIN");
|
|
g_print ("\n");
|
|
g_print ("lcMsgBase = %#x, lcDevice = %#x, lcPktRate = %d\n",
|
|
lc->lcMsgBase, lc->lcDevice, lc->lcPktRate);
|
|
g_print ("lcPktData =");
|
|
if (lc->lcPktData & PK_CONTEXT) g_print (" PK_CONTEXT");
|
|
if (lc->lcPktData & PK_STATUS) g_print (" PK_STATUS");
|
|
if (lc->lcPktData & PK_TIME) g_print (" PK_TIME");
|
|
if (lc->lcPktData & PK_CHANGED) g_print (" PK_CHANGED");
|
|
if (lc->lcPktData & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
|
|
if (lc->lcPktData & PK_CURSOR) g_print (" PK_CURSOR");
|
|
if (lc->lcPktData & PK_BUTTONS) g_print (" PK_BUTTONS");
|
|
if (lc->lcPktData & PK_X) g_print (" PK_X");
|
|
if (lc->lcPktData & PK_Y) g_print (" PK_Y");
|
|
if (lc->lcPktData & PK_Z) g_print (" PK_Z");
|
|
if (lc->lcPktData & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
|
|
if (lc->lcPktData & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
|
|
if (lc->lcPktData & PK_ORIENTATION) g_print (" PK_ORIENTATION");
|
|
if (lc->lcPktData & PK_ROTATION) g_print (" PK_ROTATION");
|
|
g_print ("\n");
|
|
g_print ("lcPktMode =");
|
|
if (lc->lcPktMode & PK_CONTEXT) g_print (" PK_CONTEXT");
|
|
if (lc->lcPktMode & PK_STATUS) g_print (" PK_STATUS");
|
|
if (lc->lcPktMode & PK_TIME) g_print (" PK_TIME");
|
|
if (lc->lcPktMode & PK_CHANGED) g_print (" PK_CHANGED");
|
|
if (lc->lcPktMode & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
|
|
if (lc->lcPktMode & PK_CURSOR) g_print (" PK_CURSOR");
|
|
if (lc->lcPktMode & PK_BUTTONS) g_print (" PK_BUTTONS");
|
|
if (lc->lcPktMode & PK_X) g_print (" PK_X");
|
|
if (lc->lcPktMode & PK_Y) g_print (" PK_Y");
|
|
if (lc->lcPktMode & PK_Z) g_print (" PK_Z");
|
|
if (lc->lcPktMode & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
|
|
if (lc->lcPktMode & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
|
|
if (lc->lcPktMode & PK_ORIENTATION) g_print (" PK_ORIENTATION");
|
|
if (lc->lcPktMode & PK_ROTATION) g_print (" PK_ROTATION");
|
|
g_print ("\n");
|
|
g_print ("lcMoveMask =");
|
|
if (lc->lcMoveMask & PK_CONTEXT) g_print (" PK_CONTEXT");
|
|
if (lc->lcMoveMask & PK_STATUS) g_print (" PK_STATUS");
|
|
if (lc->lcMoveMask & PK_TIME) g_print (" PK_TIME");
|
|
if (lc->lcMoveMask & PK_CHANGED) g_print (" PK_CHANGED");
|
|
if (lc->lcMoveMask & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
|
|
if (lc->lcMoveMask & PK_CURSOR) g_print (" PK_CURSOR");
|
|
if (lc->lcMoveMask & PK_BUTTONS) g_print (" PK_BUTTONS");
|
|
if (lc->lcMoveMask & PK_X) g_print (" PK_X");
|
|
if (lc->lcMoveMask & PK_Y) g_print (" PK_Y");
|
|
if (lc->lcMoveMask & PK_Z) g_print (" PK_Z");
|
|
if (lc->lcMoveMask & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
|
|
if (lc->lcMoveMask & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
|
|
if (lc->lcMoveMask & PK_ORIENTATION) g_print (" PK_ORIENTATION");
|
|
if (lc->lcMoveMask & PK_ROTATION) g_print (" PK_ROTATION");
|
|
g_print ("\n");
|
|
g_print ("lcBtnDnMask = %#x, lcBtnUpMask = %#x\n",
|
|
lc->lcBtnDnMask, lc->lcBtnUpMask);
|
|
g_print ("lcInOrgX = %d, lcInOrgY = %d, lcInOrgZ = %d\n",
|
|
lc->lcInOrgX, lc->lcInOrgY, lc->lcInOrgZ);
|
|
g_print ("lcInExtX = %d, lcInExtY = %d, lcInExtZ = %d\n",
|
|
lc->lcInExtX, lc->lcInExtY, lc->lcInExtZ);
|
|
g_print ("lcOutOrgX = %d, lcOutOrgY = %d, lcOutOrgZ = %d\n",
|
|
lc->lcOutOrgX, lc->lcOutOrgY, lc->lcOutOrgZ);
|
|
g_print ("lcOutExtX = %d, lcOutExtY = %d, lcOutExtZ = %d\n",
|
|
lc->lcOutExtX, lc->lcOutExtY, lc->lcOutExtZ);
|
|
g_print ("lcSensX = %g, lcSensY = %g, lcSensZ = %g\n",
|
|
lc->lcSensX / 65536., lc->lcSensY / 65536., lc->lcSensZ / 65536.);
|
|
g_print ("lcSysMode = %d\n", lc->lcSysMode);
|
|
g_print ("lcSysOrgX = %d, lcSysOrgY = %d\n",
|
|
lc->lcSysOrgX, lc->lcSysOrgY);
|
|
g_print ("lcSysExtX = %d, lcSysExtY = %d\n",
|
|
lc->lcSysExtX, lc->lcSysExtY);
|
|
g_print ("lcSysSensX = %g, lcSysSensY = %g\n",
|
|
lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.);
|
|
}
|
|
|
|
#endif
|
|
|
|
void
|
|
gdk_input_init (void)
|
|
{
|
|
guint32 deviceid_counter = 0;
|
|
#ifdef HAVE_WINTAB
|
|
GdkDevicePrivate *gdkdev;
|
|
GdkDrawablePrivate *window_private;
|
|
GdkWindowAttr wa;
|
|
WORD specversion;
|
|
LOGCONTEXT defcontext;
|
|
HCTX *hctx;
|
|
UINT ndevices, ncursors, ncsrtypes, firstcsr, hardware;
|
|
BOOL active;
|
|
AXIS axis_x, axis_y, axis_npressure, axis_or[3];
|
|
int i, j, k;
|
|
int devix, cursorix;
|
|
char devname[100], csrname[100];
|
|
|
|
gdk_input_devices = NULL;
|
|
wintab_contexts = NULL;
|
|
|
|
if (!gdk_input_ignore_wintab &&
|
|
WTInfo (0, 0, NULL))
|
|
{
|
|
WTInfo (WTI_INTERFACE, IFC_SPECVERSION, &specversion);
|
|
GDK_NOTE (MISC, g_print ("Wintab interface version %d.%d\n",
|
|
HIBYTE (specversion), LOBYTE (specversion)));
|
|
#if USE_SYSCONTEXT
|
|
WTInfo (WTI_DEFSYSCTX, 0, &defcontext);
|
|
#if DEBUG_WINTAB
|
|
GDK_NOTE (MISC, (g_print("DEFSYSCTX:\n"), print_lc(&defcontext)));
|
|
#endif
|
|
#else
|
|
WTInfo (WTI_DEFCONTEXT, 0, &defcontext);
|
|
#if DEBUG_WINTAB
|
|
GDK_NOTE (MISC, (g_print("DEFCONTEXT:\n"), print_lc(&defcontext)));
|
|
#endif
|
|
#endif
|
|
WTInfo (WTI_INTERFACE, IFC_NDEVICES, &ndevices);
|
|
WTInfo (WTI_INTERFACE, IFC_NCURSORS, &ncursors);
|
|
#if DEBUG_WINTAB
|
|
GDK_NOTE (MISC, g_print ("NDEVICES: %d, NCURSORS: %d\n",
|
|
ndevices, ncursors));
|
|
#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)
|
|
{
|
|
g_warning ("gdk_input_init: gdk_window_new failed");
|
|
return;
|
|
}
|
|
gdk_window_ref (wintab_window);
|
|
window_private = (GdkDrawablePrivate *) wintab_window;
|
|
|
|
for (devix = 0; devix < ndevices; devix++)
|
|
{
|
|
LOGCONTEXT lc;
|
|
|
|
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)
|
|
{
|
|
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;
|
|
#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);
|
|
}
|
|
else
|
|
{
|
|
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
|
|
}
|
|
#if DEBUG_WINTAB
|
|
GDK_NOTE (MISC, (g_print("context for device %d:\n", devix),
|
|
print_lc(&lc)));
|
|
#endif
|
|
hctx = g_new (HCTX, 1);
|
|
if ((*hctx = WTOpen (window_private->xwindow, &lc, TRUE)) == NULL)
|
|
{
|
|
g_warning ("gdk_input_init: WTOpen failed");
|
|
return;
|
|
}
|
|
GDK_NOTE (MISC, g_print ("opened Wintab device %d %#x\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 (MISC, (g_print("context for device %d after WTOpen:\n", devix),
|
|
print_lc(&lc)));
|
|
#endif
|
|
for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes; cursorix++)
|
|
{
|
|
active = FALSE;
|
|
WTInfo (WTI_CURSORS + cursorix, CSR_ACTIVE, &active);
|
|
if (!active)
|
|
continue;
|
|
gdkdev = g_new (GdkDevicePrivate, 1);
|
|
WTInfo (WTI_CURSORS + cursorix, CSR_NAME, csrname);
|
|
gdkdev->info.name = g_strconcat (devname, " ", csrname, NULL);
|
|
gdkdev->info.deviceid = deviceid_counter++;
|
|
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->axes = g_new (GdkAxisInfo, gdkdev->info.num_axes);
|
|
gdkdev->info.axes = g_new (GdkAxisUse, gdkdev->info.num_axes);
|
|
gdkdev->last_axis_data = g_new (gint, gdkdev->info.num_axes);
|
|
|
|
for (k = 0; k < GDK_AXIS_LAST; k++)
|
|
gdkdev->axis_for_use[k] = -1;
|
|
|
|
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] = GDK_AXIS_X;
|
|
gdkdev->axis_for_use[GDK_AXIS_X] = k;
|
|
k++;
|
|
}
|
|
if (gdkdev->pktdata & PK_Y)
|
|
{
|
|
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] = GDK_AXIS_Y;
|
|
gdkdev->axis_for_use[GDK_AXIS_Y] = k;
|
|
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] = GDK_AXIS_PRESSURE;
|
|
gdkdev->axis_for_use[GDK_AXIS_PRESSURE] = k;
|
|
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] = axis;
|
|
gdkdev->axis_for_use[axis] = k;
|
|
k++;
|
|
}
|
|
}
|
|
gdkdev->info.num_keys = 0;
|
|
gdkdev->info.keys = NULL;
|
|
GDK_NOTE (EVENTS,
|
|
(g_print ("device: %d (%d) %s axes: %d\n",
|
|
gdkdev->info.deviceid, cursorix,
|
|
gdkdev->info.name,
|
|
gdkdev->info.num_axes),
|
|
g_print ("axes: X:%d, Y:%d, PRESSURE:%d, "
|
|
"XTILT:%d, YTILT:%d\n",
|
|
gdkdev->axis_for_use[GDK_AXIS_X],
|
|
gdkdev->axis_for_use[GDK_AXIS_Y],
|
|
gdkdev->axis_for_use[GDK_AXIS_PRESSURE],
|
|
gdkdev->axis_for_use[GDK_AXIS_XTILT],
|
|
gdkdev->axis_for_use[GDK_AXIS_YTILT])));
|
|
for (i = 0; i < gdkdev->info.num_axes; i++)
|
|
GDK_NOTE (EVENTS,
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
#endif /* HAVE_WINTAB */
|
|
|
|
if (deviceid_counter > 0)
|
|
{
|
|
#ifdef HAVE_WINTAB
|
|
gdk_input_vtable.set_mode = gdk_input_win32_set_mode;
|
|
gdk_input_vtable.set_axes = NULL;
|
|
gdk_input_vtable.set_key = NULL;
|
|
gdk_input_vtable.motion_events = NULL;
|
|
gdk_input_vtable.get_pointer = gdk_input_win32_get_pointer;
|
|
gdk_input_vtable.grab_pointer = gdk_input_win32_grab_pointer;
|
|
gdk_input_vtable.ungrab_pointer = gdk_input_win32_ungrab_pointer;
|
|
gdk_input_vtable.configure_event = gdk_input_win32_configure_event;
|
|
gdk_input_vtable.enter_event = gdk_input_win32_enter_event;
|
|
gdk_input_vtable.other_event = gdk_input_win32_other_event;
|
|
gdk_input_vtable.enable_window = gdk_input_win32_enable_window;
|
|
gdk_input_vtable.disable_window = gdk_input_win32_disable_window;
|
|
|
|
gdk_input_root_width = gdk_screen_width ();
|
|
gdk_input_root_height = gdk_screen_height ();
|
|
gdk_input_ignore_core = FALSE;
|
|
#else
|
|
g_assert_not_reached ();
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
gdk_input_vtable.set_mode = NULL;
|
|
gdk_input_vtable.set_axes = NULL;
|
|
gdk_input_vtable.set_key = NULL;
|
|
gdk_input_vtable.motion_events = NULL;
|
|
gdk_input_vtable.get_pointer = gdk_input_none_get_pointer;
|
|
gdk_input_vtable.grab_pointer = NULL;
|
|
gdk_input_vtable.ungrab_pointer = NULL;
|
|
gdk_input_vtable.configure_event = NULL;
|
|
gdk_input_vtable.enter_event = NULL;
|
|
gdk_input_vtable.other_event = NULL;
|
|
gdk_input_vtable.enable_window = NULL;
|
|
gdk_input_vtable.disable_window = NULL;
|
|
gdk_input_ignore_core = FALSE;
|
|
}
|
|
|
|
gdk_input_devices = g_list_append (gdk_input_devices, &gdk_input_core_info);
|
|
}
|
|
|
|
gint
|
|
gdk_input_set_mode (guint32 deviceid,
|
|
GdkInputMode mode)
|
|
{
|
|
if (deviceid == GDK_CORE_POINTER)
|
|
return FALSE;
|
|
|
|
if (gdk_input_vtable.set_mode)
|
|
return gdk_input_vtable.set_mode (deviceid, mode);
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
gdk_input_set_axes (guint32 deviceid,
|
|
GdkAxisUse *axes)
|
|
{
|
|
int i;
|
|
GdkDevicePrivate *gdkdev = gdk_input_find_device (deviceid);
|
|
g_return_if_fail (gdkdev != NULL);
|
|
|
|
if (deviceid == GDK_CORE_POINTER)
|
|
return;
|
|
|
|
for (i = GDK_AXIS_IGNORE; i < GDK_AXIS_LAST; i++)
|
|
{
|
|
gdkdev->axis_for_use[i] = -1;
|
|
}
|
|
|
|
for (i = 0; i < gdkdev->info.num_axes; i++)
|
|
{
|
|
gdkdev->info.axes[i] = axes[i];
|
|
gdkdev->axis_for_use[axes[i]] = i;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gdk_input_none_get_pointer (GdkWindow *window,
|
|
guint32 deviceid,
|
|
gdouble *x,
|
|
gdouble *y,
|
|
gdouble *pressure,
|
|
gdouble *xtilt,
|
|
gdouble *ytilt,
|
|
GdkModifierType *mask)
|
|
{
|
|
gint x_int, y_int;
|
|
|
|
gdk_window_get_pointer (window, &x_int, &y_int, mask);
|
|
|
|
if (x)
|
|
*x = x_int;
|
|
if (y)
|
|
*y = y_int;
|
|
if (pressure)
|
|
*pressure = 0.5;
|
|
if (xtilt)
|
|
*xtilt = 0;
|
|
if (ytilt)
|
|
*ytilt = 0;
|
|
}
|
|
|
|
#ifdef HAVE_WINTAB
|
|
|
|
static void
|
|
gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
|
|
GdkInputWindow *input_window,
|
|
gint *axis_data,
|
|
gdouble *x,
|
|
gdouble *y,
|
|
gdouble *pressure,
|
|
gdouble *xtilt,
|
|
gdouble *ytilt)
|
|
{
|
|
GdkDrawablePrivate *window_private;
|
|
gint x_axis, y_axis, pressure_axis, xtilt_axis, ytilt_axis;
|
|
gdouble device_width, device_height;
|
|
gdouble x_offset, y_offset, x_scale, y_scale;
|
|
|
|
window_private = (GdkDrawablePrivate *) input_window->window;
|
|
|
|
x_axis = gdkdev->axis_for_use[GDK_AXIS_X];
|
|
y_axis = gdkdev->axis_for_use[GDK_AXIS_Y];
|
|
pressure_axis = gdkdev->axis_for_use[GDK_AXIS_PRESSURE];
|
|
xtilt_axis = gdkdev->axis_for_use[GDK_AXIS_XTILT];
|
|
ytilt_axis = gdkdev->axis_for_use[GDK_AXIS_YTILT];
|
|
|
|
device_width = gdkdev->axes[x_axis].max_value -
|
|
gdkdev->axes[x_axis].min_value;
|
|
device_height = gdkdev->axes[y_axis].max_value -
|
|
gdkdev->axes[y_axis].min_value;
|
|
|
|
if (gdkdev->info.mode == GDK_MODE_SCREEN)
|
|
{
|
|
x_scale = gdk_input_root_width / device_width;
|
|
y_scale = gdk_input_root_height / device_height;
|
|
|
|
x_offset = -input_window->root_x;
|
|
y_offset = -input_window->root_y;
|
|
}
|
|
else /* GDK_MODE_WINDOW */
|
|
{
|
|
double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
|
|
(device_width*gdkdev->axes[x_axis].resolution);
|
|
|
|
if (device_aspect * window_private->width >= window_private->height)
|
|
{
|
|
/* device taller than window */
|
|
x_scale = window_private->width / device_width;
|
|
y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
|
|
/ gdkdev->axes[y_axis].resolution;
|
|
|
|
x_offset = 0;
|
|
y_offset = -(device_height * y_scale -
|
|
window_private->height)/2;
|
|
}
|
|
else
|
|
{
|
|
/* window taller than device */
|
|
y_scale = window_private->height / device_height;
|
|
x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
|
|
/ gdkdev->axes[x_axis].resolution;
|
|
|
|
y_offset = 0;
|
|
x_offset = -(device_width * x_scale - window_private->width)/2;
|
|
}
|
|
}
|
|
|
|
if (x)
|
|
*x = x_offset + x_scale*axis_data[x_axis];
|
|
if (y)
|
|
*y = y_offset + y_scale*axis_data[y_axis];
|
|
|
|
if (pressure)
|
|
{
|
|
if (pressure_axis != -1)
|
|
*pressure = ((double)axis_data[pressure_axis]
|
|
- gdkdev->axes[pressure_axis].min_value)
|
|
/ (gdkdev->axes[pressure_axis].max_value
|
|
- gdkdev->axes[pressure_axis].min_value);
|
|
else
|
|
*pressure = 0.5;
|
|
}
|
|
|
|
if (xtilt)
|
|
{
|
|
if (xtilt_axis != -1)
|
|
{
|
|
*xtilt = 2. * (double)(axis_data[xtilt_axis] -
|
|
(gdkdev->axes[xtilt_axis].min_value +
|
|
gdkdev->axes[xtilt_axis].max_value)/2) /
|
|
(gdkdev->axes[xtilt_axis].max_value -
|
|
gdkdev->axes[xtilt_axis].min_value);
|
|
}
|
|
else
|
|
*xtilt = 0;
|
|
}
|
|
|
|
if (ytilt)
|
|
{
|
|
if (ytilt_axis != -1)
|
|
{
|
|
*ytilt = 2. * (double)(axis_data[ytilt_axis] -
|
|
(gdkdev->axes[ytilt_axis].min_value +
|
|
gdkdev->axes[ytilt_axis].max_value)/2) /
|
|
(gdkdev->axes[ytilt_axis].max_value -
|
|
gdkdev->axes[ytilt_axis].min_value);
|
|
}
|
|
else
|
|
*ytilt = 0;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gdk_input_win32_get_pointer (GdkWindow *window,
|
|
guint32 deviceid,
|
|
gdouble *x,
|
|
gdouble *y,
|
|
gdouble *pressure,
|
|
gdouble *xtilt,
|
|
gdouble *ytilt,
|
|
GdkModifierType *mask)
|
|
{
|
|
GdkDevicePrivate *gdkdev;
|
|
GdkInputWindow *input_window;
|
|
gint x_int, y_int;
|
|
gint i;
|
|
|
|
if (deviceid == GDK_CORE_POINTER)
|
|
{
|
|
gdk_window_get_pointer (window, &x_int, &y_int, mask);
|
|
if (x)
|
|
*x = x_int;
|
|
if (y)
|
|
*y = y_int;
|
|
if (pressure)
|
|
*pressure = 0.5;
|
|
if (xtilt)
|
|
*xtilt = 0;
|
|
if (ytilt)
|
|
*ytilt = 0;
|
|
}
|
|
else
|
|
{
|
|
if (mask)
|
|
gdk_window_get_pointer (window, NULL, NULL, mask);
|
|
|
|
gdkdev = gdk_input_find_device (deviceid);
|
|
g_return_if_fail (gdkdev != NULL);
|
|
|
|
input_window = gdk_input_window_find (window);
|
|
g_return_if_fail (input_window != NULL);
|
|
|
|
gdk_input_translate_coordinates (gdkdev, input_window,
|
|
gdkdev->last_axis_data,
|
|
x, y, pressure,
|
|
xtilt, ytilt);
|
|
if (mask)
|
|
{
|
|
*mask &= 0xFF;
|
|
*mask |= ((gdkdev->last_buttons & 0x1F) << 8);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
gdk_input_get_root_relative_geometry (HWND w,
|
|
int *x_ret,
|
|
int *y_ret)
|
|
{
|
|
RECT rect;
|
|
|
|
GetWindowRect (w, &rect);
|
|
|
|
if (x_ret)
|
|
*x_ret = rect.left;
|
|
if (y_ret)
|
|
*y_ret = rect.top;
|
|
}
|
|
|
|
static gint
|
|
gdk_input_win32_set_mode (guint32 deviceid,
|
|
GdkInputMode mode)
|
|
{
|
|
GList *tmp_list;
|
|
GdkDevicePrivate *gdkdev;
|
|
GdkInputMode old_mode;
|
|
GdkInputWindow *input_window;
|
|
|
|
if (deviceid == GDK_CORE_POINTER)
|
|
return FALSE;
|
|
|
|
gdkdev = gdk_input_find_device (deviceid);
|
|
g_return_val_if_fail (gdkdev != NULL, FALSE);
|
|
old_mode = gdkdev->info.mode;
|
|
|
|
if (old_mode == mode)
|
|
return TRUE;
|
|
|
|
gdkdev->info.mode = mode;
|
|
|
|
if (mode == GDK_MODE_WINDOW)
|
|
{
|
|
gdkdev->info.has_cursor = FALSE;
|
|
for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
|
|
{
|
|
input_window = (GdkInputWindow *)tmp_list->data;
|
|
if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
|
|
gdk_input_win32_enable_window (input_window->window, gdkdev);
|
|
else
|
|
if (old_mode != GDK_MODE_DISABLED)
|
|
gdk_input_win32_disable_window (input_window->window, gdkdev);
|
|
}
|
|
}
|
|
else if (mode == GDK_MODE_SCREEN)
|
|
{
|
|
gdkdev->info.has_cursor = TRUE;
|
|
for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
|
|
gdk_input_win32_enable_window (((GdkInputWindow *)tmp_list->data)->window,
|
|
gdkdev);
|
|
}
|
|
else /* mode == GDK_MODE_DISABLED */
|
|
{
|
|
for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
|
|
{
|
|
input_window = (GdkInputWindow *)tmp_list->data;
|
|
if (old_mode != GDK_MODE_WINDOW ||
|
|
input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
|
|
gdk_input_win32_disable_window (input_window->window, gdkdev);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
gdk_input_win32_configure_event (GdkEventConfigure *event,
|
|
GdkWindow *window)
|
|
{
|
|
GdkInputWindow *input_window;
|
|
gint root_x, root_y;
|
|
|
|
input_window = gdk_input_window_find (window);
|
|
g_return_if_fail (window != NULL);
|
|
|
|
gdk_input_get_root_relative_geometry
|
|
(GDK_DRAWABLE_XID (window), &root_x, &root_y);
|
|
|
|
input_window->root_x = root_x;
|
|
input_window->root_y = root_y;
|
|
}
|
|
|
|
static void
|
|
gdk_input_win32_enter_event (GdkEventCrossing *event,
|
|
GdkWindow *window)
|
|
{
|
|
GdkInputWindow *input_window;
|
|
gint root_x, root_y;
|
|
|
|
input_window = gdk_input_window_find (window);
|
|
g_return_if_fail (window != NULL);
|
|
|
|
gdk_input_get_root_relative_geometry
|
|
(GDK_DRAWABLE_XID (window), &root_x, &root_y);
|
|
|
|
input_window->root_x = root_x;
|
|
input_window->root_y = root_y;
|
|
}
|
|
|
|
static void
|
|
decode_tilt (gint *axis_data,
|
|
AXIS *axes,
|
|
PACKET *packet)
|
|
{
|
|
/* As I don't have a tilt-sensing tablet,
|
|
* I cannot test this code.
|
|
*/
|
|
|
|
double az, el;
|
|
|
|
az = TWOPI * packet->pkOrientation.orAzimuth /
|
|
(axes[0].axResolution / 65536.);
|
|
el = TWOPI * packet->pkOrientation.orAltitude /
|
|
(axes[1].axResolution / 65536.);
|
|
|
|
/* X tilt */
|
|
axis_data[0] = cos (az) * cos (el) * 1000;
|
|
/* Y tilt */
|
|
axis_data[1] = sin (az) * cos (el) * 1000;
|
|
}
|
|
|
|
static GdkDevicePrivate *
|
|
gdk_input_find_dev_from_ctx (HCTX hctx,
|
|
UINT cursor)
|
|
{
|
|
GList *tmp_list = gdk_input_devices;
|
|
GdkDevicePrivate *gdkdev;
|
|
|
|
while (tmp_list)
|
|
{
|
|
gdkdev = (GdkDevicePrivate *) (tmp_list->data);
|
|
if (gdkdev->hctx == hctx && gdkdev->cursor == cursor)
|
|
return gdkdev;
|
|
tmp_list = tmp_list->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
static gint
|
|
gdk_input_win32_other_event (GdkEvent *event,
|
|
MSG *xevent)
|
|
{
|
|
GdkWindow *current_window;
|
|
GdkInputWindow *input_window;
|
|
GdkWindow *window;
|
|
GdkWindowPrivate *window_private;
|
|
GdkDevicePrivate *gdkdev;
|
|
GdkEventMask masktest;
|
|
POINT pt;
|
|
PACKET packet;
|
|
gint return_val;
|
|
gint k;
|
|
gint x, y;
|
|
|
|
if (event->any.window != wintab_window)
|
|
g_warning ("gdk_input_win32_other_event: not wintab_window?");
|
|
|
|
#if USE_SYSCONTEXT
|
|
window = gdk_window_at_pointer (&x, &y);
|
|
if (window == NULL)
|
|
window = (GdkWindow *) gdk_root_parent;
|
|
|
|
gdk_window_ref (window);
|
|
|
|
window_private = (GdkWindowPrivate *) window;
|
|
|
|
GDK_NOTE (EVENTS,
|
|
g_print ("gdk_input_win32_other_event: window=%#x (%d,%d)\n",
|
|
GDK_DRAWABLE_XID (window), x, y));
|
|
|
|
#else
|
|
/* ??? This code is pretty bogus */
|
|
current_window = gdk_window_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 (xevent->message == WT_PACKET)
|
|
{
|
|
if (!WTPacket ((HCTX) xevent->lParam, xevent->wParam, &packet))
|
|
return FALSE;
|
|
}
|
|
|
|
switch (xevent->message)
|
|
{
|
|
case WT_PACKET:
|
|
if (window_private == gdk_root_parent)
|
|
{
|
|
GDK_NOTE (EVENTS, g_print ("...is root\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
if ((gdkdev = gdk_input_find_dev_from_ctx ((HCTX) xevent->lParam,
|
|
packet.pkCursor)) == NULL)
|
|
return FALSE;
|
|
|
|
if (gdkdev->info.mode == GDK_MODE_DISABLED)
|
|
return FALSE;
|
|
|
|
k = 0;
|
|
if (gdkdev->pktdata & PK_X)
|
|
gdkdev->last_axis_data[k++] = packet.pkX;
|
|
if (gdkdev->pktdata & PK_Y)
|
|
gdkdev->last_axis_data[k++] = packet.pkY;
|
|
if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
|
|
gdkdev->last_axis_data[k++] = packet.pkNormalPressure;
|
|
if (gdkdev->pktdata & PK_ORIENTATION)
|
|
{
|
|
decode_tilt (gdkdev->last_axis_data + k,
|
|
gdkdev->orientation_axes, &packet);
|
|
k += 2;
|
|
}
|
|
|
|
g_assert (k == gdkdev->info.num_axes);
|
|
|
|
if (HIWORD (packet.pkButtons) != TBN_NONE)
|
|
{
|
|
/* Gdk buttons are numbered 1.. */
|
|
event->button.button = 1 + LOWORD (packet.pkButtons);
|
|
|
|
if (HIWORD (packet.pkButtons) == TBN_UP)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
event->any.type = GDK_MOTION_NOTIFY;
|
|
masktest = GDK_POINTER_MOTION_MASK;
|
|
if (gdkdev->button_state & (1 << 0))
|
|
masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK;
|
|
if (gdkdev->button_state & (1 << 1))
|
|
masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK;
|
|
if (gdkdev->button_state & (1 << 2))
|
|
masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK;
|
|
}
|
|
|
|
/* Now we can check if the window wants the event, and
|
|
* propagate if necessary.
|
|
*/
|
|
dijkstra:
|
|
if (!window_private->extension_events_selected
|
|
|| !(window_private->extension_events & masktest))
|
|
{
|
|
GDK_NOTE (EVENTS, g_print ("...not selected\n"));
|
|
|
|
if (window_private->parent == (GdkWindow *) gdk_root_parent)
|
|
return FALSE;
|
|
|
|
pt.x = x;
|
|
pt.y = y;
|
|
ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
|
|
gdk_window_unref (window);
|
|
window = window_private->parent;
|
|
gdk_window_ref (window);
|
|
window_private = (GdkWindowPrivate *) window;
|
|
ScreenToClient (GDK_DRAWABLE_XID (window), &pt);
|
|
x = pt.x;
|
|
y = pt.y;
|
|
GDK_NOTE (EVENTS, g_print ("...propagating to %#x, (%d,%d)\n",
|
|
GDK_DRAWABLE_XID (window), x, y));
|
|
goto dijkstra;
|
|
}
|
|
|
|
input_window = gdk_input_window_find (window);
|
|
|
|
g_assert (input_window != NULL);
|
|
|
|
if (gdkdev->info.mode == GDK_MODE_WINDOW
|
|
&& input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
|
|
return FALSE;
|
|
|
|
event->any.window = window;
|
|
|
|
if (event->any.type == GDK_BUTTON_PRESS
|
|
|| event->any.type == GDK_BUTTON_RELEASE)
|
|
{
|
|
event->button.time = xevent->time;
|
|
event->button.source = gdkdev->info.source;
|
|
last_moved_cursor_id =
|
|
event->button.deviceid = gdkdev->info.deviceid;
|
|
|
|
#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
|
|
gdk_input_translate_coordinates (gdkdev, input_window,
|
|
gdkdev->last_axis_data,
|
|
&event->button.x, &event->button.y,
|
|
&event->button.pressure,
|
|
&event->button.xtilt,
|
|
&event->button.ytilt);
|
|
|
|
event->button.state = ((gdkdev->button_state << 8)
|
|
& (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
|
|
| GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
|
|
| GDK_BUTTON5_MASK));
|
|
GDK_NOTE (EVENTS, g_print ("WINTAB button %s: %d %d %g,%g %g %g,%g\n",
|
|
(event->button.type == GDK_BUTTON_PRESS ?
|
|
"press" : "release"),
|
|
event->button.deviceid,
|
|
event->button.button,
|
|
event->button.x, event->button.y,
|
|
event->button.pressure,
|
|
event->button.xtilt, event->button.ytilt));
|
|
}
|
|
else
|
|
{
|
|
event->motion.time = xevent->time;
|
|
last_moved_cursor_id =
|
|
event->motion.deviceid = gdkdev->info.deviceid;
|
|
event->motion.is_hint = FALSE;
|
|
event->motion.source = gdkdev->info.source;
|
|
|
|
gdk_input_translate_coordinates (gdkdev, input_window,
|
|
gdkdev->last_axis_data,
|
|
&event->motion.x, &event->motion.y,
|
|
&event->motion.pressure,
|
|
&event->motion.xtilt,
|
|
&event->motion.ytilt);
|
|
|
|
event->motion.state = ((gdkdev->button_state << 8)
|
|
& (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
|
|
| GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
|
|
| GDK_BUTTON5_MASK));
|
|
|
|
GDK_NOTE (EVENTS, g_print ("WINTAB motion: %d %g,%g %g %g,%g\n",
|
|
event->motion.deviceid,
|
|
event->motion.x, event->motion.y,
|
|
event->motion.pressure,
|
|
event->motion.xtilt, event->motion.ytilt));
|
|
|
|
/* 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, g_print ("WINTAB synthesized button %s: %d %d %g,%g %g\n",
|
|
(event2->button.type == GDK_BUTTON_PRESS ?
|
|
"press" : "release"),
|
|
event2->button.deviceid,
|
|
event2->button.button,
|
|
event2->button.x, event2->button.y,
|
|
event2->button.pressure));
|
|
gdk_event_queue_append (event2);
|
|
}
|
|
}
|
|
return TRUE;
|
|
|
|
case WT_PROXIMITY:
|
|
if (LOWORD (xevent->lParam) == 0)
|
|
{
|
|
event->proximity.type = GDK_PROXIMITY_OUT;
|
|
gdk_input_ignore_core = FALSE;
|
|
}
|
|
else
|
|
{
|
|
event->proximity.type = GDK_PROXIMITY_IN;
|
|
gdk_input_ignore_core = TRUE;
|
|
}
|
|
event->proximity.time = xevent->time;
|
|
event->proximity.source = GDK_SOURCE_PEN;
|
|
event->proximity.deviceid = last_moved_cursor_id;
|
|
|
|
GDK_NOTE (EVENTS, g_print ("WINTAB proximity %s: %d\n",
|
|
(event->proximity.type == GDK_PROXIMITY_IN ?
|
|
"in" : "out"),
|
|
event->proximity.deviceid));
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static gint
|
|
gdk_input_win32_enable_window (GdkWindow *window,
|
|
GdkDevicePrivate *gdkdev)
|
|
{
|
|
GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
|
|
|
|
window_private->extension_events_selected = TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
static gint
|
|
gdk_input_win32_disable_window (GdkWindow *window,
|
|
GdkDevicePrivate *gdkdev)
|
|
{
|
|
GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
|
|
|
|
window_private->extension_events_selected = FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
static gint
|
|
gdk_input_win32_grab_pointer (GdkWindow *window,
|
|
gint owner_events,
|
|
GdkEventMask event_mask,
|
|
GdkWindow *confine_to,
|
|
guint32 time)
|
|
{
|
|
GdkInputWindow *input_window, *new_window;
|
|
gboolean need_ungrab;
|
|
GdkDevicePrivate *gdkdev;
|
|
GList *tmp_list;
|
|
gint result;
|
|
|
|
tmp_list = gdk_input_windows;
|
|
new_window = NULL;
|
|
need_ungrab = FALSE;
|
|
|
|
GDK_NOTE (MISC, g_print ("gdk_input_win32_grab_pointer: %#x %d %#x\n",
|
|
GDK_DRAWABLE_XID (window),
|
|
owner_events,
|
|
(confine_to ? GDK_DRAWABLE_XID (confine_to) : 0)));
|
|
|
|
while (tmp_list)
|
|
{
|
|
input_window = (GdkInputWindow *)tmp_list->data;
|
|
|
|
if (input_window->window == window)
|
|
new_window = input_window;
|
|
else if (input_window->grabbed)
|
|
{
|
|
input_window->grabbed = FALSE;
|
|
need_ungrab = TRUE;
|
|
}
|
|
|
|
tmp_list = tmp_list->next;
|
|
}
|
|
|
|
if (new_window)
|
|
{
|
|
new_window->grabbed = TRUE;
|
|
|
|
tmp_list = gdk_input_devices;
|
|
while (tmp_list)
|
|
{
|
|
gdkdev = (GdkDevicePrivate *)tmp_list->data;
|
|
if (gdkdev->info.deviceid != GDK_CORE_POINTER)
|
|
{
|
|
#if 0
|
|
/* XXX */
|
|
gdk_input_find_events (window, gdkdev,
|
|
event_mask,
|
|
event_classes, &num_classes);
|
|
result = XGrabDevice (GDK_DISPLAY(), gdkdev->xdevice,
|
|
GDK_WINDOW_XWINDOW (window),
|
|
owner_events, num_classes, event_classes,
|
|
GrabModeAsync, GrabModeAsync, time);
|
|
|
|
/* FIXME: if failure occurs on something other than the first
|
|
device, things will be badly inconsistent */
|
|
if (result != Success)
|
|
return result;
|
|
#endif
|
|
}
|
|
tmp_list = tmp_list->next;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tmp_list = gdk_input_devices;
|
|
while (tmp_list)
|
|
{
|
|
gdkdev = (GdkDevicePrivate *)tmp_list->data;
|
|
if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
|
|
((gdkdev->button_state != 0) || need_ungrab))
|
|
{
|
|
#if 0
|
|
/* XXX */
|
|
XUngrabDevice (gdk_display, gdkdev->xdevice, time);
|
|
#endif
|
|
gdkdev->button_state = 0;
|
|
}
|
|
|
|
tmp_list = tmp_list->next;
|
|
}
|
|
}
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
static void
|
|
gdk_input_win32_ungrab_pointer (guint32 time)
|
|
{
|
|
GdkInputWindow *input_window;
|
|
GdkDevicePrivate *gdkdev;
|
|
GList *tmp_list;
|
|
|
|
GDK_NOTE (MISC, g_print ("gdk_input_win32_ungrab_pointer\n"));
|
|
|
|
tmp_list = gdk_input_windows;
|
|
while (tmp_list)
|
|
{
|
|
input_window = (GdkInputWindow *)tmp_list->data;
|
|
if (input_window->grabbed)
|
|
break;
|
|
tmp_list = tmp_list->next;
|
|
}
|
|
|
|
if (tmp_list) /* we found a grabbed window */
|
|
{
|
|
input_window->grabbed = FALSE;
|
|
|
|
tmp_list = gdk_input_devices;
|
|
while (tmp_list)
|
|
{
|
|
gdkdev = (GdkDevicePrivate *)tmp_list->data;
|
|
#if 0
|
|
/* XXX */
|
|
if (gdkdev->info.deviceid != GDK_CORE_POINTER && gdkdev->xdevice)
|
|
XUngrabDevice (gdk_display, gdkdev->xdevice, time);
|
|
#endif
|
|
tmp_list = tmp_list->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* HAVE_WINTAB */
|
|
|
|
GList *
|
|
gdk_input_list_devices (void)
|
|
{
|
|
return gdk_input_devices;
|
|
}
|
|
|
|
void
|
|
gdk_input_set_source (guint32 deviceid,
|
|
GdkInputSource source)
|
|
{
|
|
GdkDevicePrivate *gdkdev = gdk_input_find_device (deviceid);
|
|
g_return_if_fail (gdkdev != NULL);
|
|
|
|
gdkdev->info.source = source;
|
|
}
|
|
|
|
void gdk_input_set_key (guint32 deviceid,
|
|
guint index,
|
|
guint keyval,
|
|
GdkModifierType modifiers)
|
|
{
|
|
if (deviceid != GDK_CORE_POINTER && gdk_input_vtable.set_key)
|
|
gdk_input_vtable.set_key (deviceid, index, keyval, modifiers);
|
|
}
|
|
|
|
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_DRAWABLE_DESTROYED (window))
|
|
return NULL;
|
|
|
|
*nevents_return = 0;
|
|
return NULL; /* ??? */
|
|
}
|
|
|
|
static gint
|
|
gdk_input_enable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
|
|
{
|
|
if (gdk_input_vtable.enable_window)
|
|
return gdk_input_vtable.enable_window (window, gdkdev);
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
static gint
|
|
gdk_input_disable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
|
|
{
|
|
if (gdk_input_vtable.disable_window)
|
|
return gdk_input_vtable.disable_window(window,gdkdev);
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static GdkInputWindow *
|
|
gdk_input_window_find (GdkWindow *window)
|
|
{
|
|
GList *tmp_list;
|
|
|
|
for (tmp_list=gdk_input_windows; tmp_list; tmp_list=tmp_list->next)
|
|
if (((GdkInputWindow *)(tmp_list->data))->window == window)
|
|
return (GdkInputWindow *)(tmp_list->data);
|
|
|
|
return NULL; /* Not found */
|
|
}
|
|
|
|
#if !USE_SYSCONTEXT
|
|
|
|
static GdkInputWindow *
|
|
gdk_input_window_find_within (GdkWindow *window)
|
|
{
|
|
GList *tmp_list;
|
|
GdkWindowPrivate *window_private;
|
|
GdkWindowPrivate *tmp_private;
|
|
GdkInputWindow *candidate = NULL;
|
|
|
|
window_private = (GdkWindowPrivate *) window;
|
|
|
|
for (tmp_list=gdk_input_windows; tmp_list; tmp_list=tmp_list->next)
|
|
{
|
|
(GdkWindowPrivate *) tmp_private =
|
|
(GdkWindowPrivate *) (((GdkInputWindow *)(tmp_list->data))->window);
|
|
if (tmp_private == window_private
|
|
|| IsChild (window_private->xwindow, tmp_private->xwindow))
|
|
{
|
|
if (candidate)
|
|
return NULL; /* Multiple hits */
|
|
candidate = (GdkInputWindow *)(tmp_list->data);
|
|
}
|
|
}
|
|
|
|
return candidate;
|
|
}
|
|
|
|
#endif
|
|
|
|
/* FIXME: this routine currently needs to be called between creation
|
|
and the corresponding configure event (because it doesn't get the
|
|
root_relative_geometry). This should work with
|
|
gtk_window_set_extension_events, but will likely fail in other
|
|
cases */
|
|
|
|
void
|
|
gdk_input_set_extension_events (GdkWindow *window,
|
|
gint mask,
|
|
GdkExtensionMode mode)
|
|
{
|
|
GdkWindowPrivate *window_private;
|
|
GList *tmp_list;
|
|
GdkInputWindow *iw;
|
|
|
|
g_return_if_fail (window != NULL);
|
|
if (GDK_DRAWABLE_DESTROYED (window))
|
|
return;
|
|
window_private = (GdkWindowPrivate *) window;
|
|
|
|
if (mode == GDK_EXTENSION_EVENTS_NONE)
|
|
mask = 0;
|
|
|
|
if (mask != 0)
|
|
{
|
|
iw = g_new (GdkInputWindow,1);
|
|
|
|
iw->window = window;
|
|
iw->mode = mode;
|
|
|
|
iw->grabbed = FALSE;
|
|
|
|
gdk_input_windows = g_list_append (gdk_input_windows, iw);
|
|
window_private->extension_events = mask;
|
|
|
|
/* Add enter window events to the event mask */
|
|
gdk_window_set_events (window,
|
|
gdk_window_get_events (window) |
|
|
GDK_ENTER_NOTIFY_MASK);
|
|
}
|
|
else
|
|
{
|
|
iw = gdk_input_window_find (window);
|
|
if (iw)
|
|
{
|
|
gdk_input_windows = g_list_remove (gdk_input_windows, iw);
|
|
g_free (iw);
|
|
}
|
|
|
|
window_private->extension_events = 0;
|
|
}
|
|
|
|
for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
|
|
{
|
|
GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
|
|
|
|
if (gdkdev->info.deviceid != GDK_CORE_POINTER)
|
|
{
|
|
if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
|
|
&& (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL))
|
|
gdk_input_enable_window (window, gdkdev);
|
|
else
|
|
gdk_input_disable_window (window, gdkdev);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
gdk_input_window_destroy (GdkWindow *window)
|
|
{
|
|
GdkInputWindow *input_window;
|
|
|
|
input_window = gdk_input_window_find (window);
|
|
g_return_if_fail (input_window != NULL);
|
|
|
|
gdk_input_windows = g_list_remove (gdk_input_windows,input_window);
|
|
g_free (input_window);
|
|
}
|
|
|
|
void
|
|
gdk_input_exit (void)
|
|
{
|
|
#ifdef HAVE_WINTAB
|
|
GList *tmp_list;
|
|
GdkDevicePrivate *gdkdev;
|
|
|
|
for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
|
|
{
|
|
gdkdev = (GdkDevicePrivate *)(tmp_list->data);
|
|
if (gdkdev->info.deviceid != GDK_CORE_POINTER)
|
|
{
|
|
gdk_input_win32_set_mode (gdkdev->info.deviceid, GDK_MODE_DISABLED);
|
|
g_free (gdkdev->info.name);
|
|
g_free (gdkdev->last_axis_data);
|
|
g_free (gdkdev->info.axes);
|
|
g_free (gdkdev->info.keys);
|
|
g_free (gdkdev->axes);
|
|
g_free (gdkdev);
|
|
}
|
|
}
|
|
|
|
g_list_free (gdk_input_devices);
|
|
|
|
for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
|
|
{
|
|
g_free (tmp_list->data);
|
|
}
|
|
g_list_free (gdk_input_windows);
|
|
gdk_input_windows = NULL;
|
|
|
|
gdk_window_unref (wintab_window);
|
|
wintab_window = NULL;
|
|
|
|
#if 1
|
|
for (tmp_list = wintab_contexts; tmp_list; tmp_list = tmp_list->next)
|
|
{
|
|
HCTX *hctx = (HCTX *) tmp_list->data;
|
|
BOOL result;
|
|
|
|
#ifdef _MSC_VER
|
|
/* For some reason WTEnable and/or WTClose tend to crash here.
|
|
* Protect with __try/__except to avoid a message box.
|
|
* When compiling with gcc, we cannot use __try/__except, so
|
|
* don't call WTClose. I think this means that we'll
|
|
* eventually run out of Wintab contexts, sigh.
|
|
*/
|
|
__try {
|
|
#if 0
|
|
WTEnable (*hctx, FALSE);
|
|
#endif
|
|
result = WTClose (*hctx);
|
|
}
|
|
__except (/* GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? */
|
|
EXCEPTION_EXECUTE_HANDLER /*:
|
|
EXCEPTION_CONTINUE_SEARCH */) {
|
|
result = FALSE;
|
|
}
|
|
if (!result)
|
|
g_warning ("gdk_input_exit: Closing Wintab context %#x failed", *hctx);
|
|
#endif /* _MSC_VER */
|
|
g_free (hctx);
|
|
}
|
|
#endif
|
|
g_list_free (wintab_contexts);
|
|
wintab_contexts = NULL;
|
|
#endif
|
|
}
|
|
|
|
static GdkDevicePrivate *
|
|
gdk_input_find_device (guint32 id)
|
|
{
|
|
GList *tmp_list = gdk_input_devices;
|
|
GdkDevicePrivate *gdkdev;
|
|
|
|
while (tmp_list)
|
|
{
|
|
gdkdev = (GdkDevicePrivate *) (tmp_list->data);
|
|
if (gdkdev->info.deviceid == id)
|
|
return gdkdev;
|
|
tmp_list = tmp_list->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
gdk_input_window_get_pointer (GdkWindow *window,
|
|
guint32 deviceid,
|
|
gdouble *x,
|
|
gdouble *y,
|
|
gdouble *pressure,
|
|
gdouble *xtilt,
|
|
gdouble *ytilt,
|
|
GdkModifierType *mask)
|
|
{
|
|
if (gdk_input_vtable.get_pointer)
|
|
gdk_input_vtable.get_pointer (window, deviceid, x, y, pressure,
|
|
xtilt, ytilt, mask);
|
|
}
|