?? gdkinput-win32.c
字號:
/* GDK - The GIMP Drawing Kit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * Copyright (C) 1998-2002 Tor Lillqvist * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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-2000. 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 "gdkinternals.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)#include <pktdef.h>#define DEBUG_WINTAB 1 /* Verbose debug messages enabled */#define PROXIMITY_OUT_DELAY 200 /* In milliseconds, see set_ignore_core */#endif#if defined(HAVE_WINTAB) || defined(HAVE_WHATEVER_OTHER)#define HAVE_SOME_XINPUT#endif#define TWOPI (2.*G_PI)/* Forward declarations */#ifdef HAVE_WINTABstatic GdkDevicePrivate *gdk_input_find_dev_from_ctx (HCTX hctx, UINT id);static GList *wintab_contexts = NULL;static GdkWindow *wintab_window = NULL;#endif /* HAVE_WINTAB */#ifdef HAVE_SOME_XINPUTstatic GdkWindow *x_grab_window = NULL; /* Window that currently holds * the extended inputs grab */static GdkEventMask x_grab_mask;static gboolean x_grab_owner_events;#endif /* HAVE_SOME_XINPUT */#ifdef HAVE_WINTABstatic 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;}#if DEBUG_WINTABstatic voidprint_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"); 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", (guint) lc->lcBtnDnMask, (guint) lc->lcBtnUpMask); g_print ("lcInOrgX = %ld, lcInOrgY = %ld, lcInOrgZ = %ld\n", lc->lcInOrgX, lc->lcInOrgY, lc->lcInOrgZ); g_print ("lcInExtX = %ld, lcInExtY = %ld, lcInExtZ = %ld\n", lc->lcInExtX, lc->lcInExtY, lc->lcInExtZ); g_print ("lcOutOrgX = %ld, lcOutOrgY = %ld, lcOutOrgZ = %ld\n", lc->lcOutOrgX, lc->lcOutOrgY, lc->lcOutOrgZ); g_print ("lcOutExtX = %ld, lcOutExtY = %ld, lcOutExtZ = %ld\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.);}#endifvoid_gdk_input_wintab_init_check (void){ static gboolean wintab_initialized = FALSE; GdkDevicePrivate *gdkdev; GdkWindowAttr wa; WORD specversion; HCTX *hctx; UINT ndevices, ncursors, ncsrtypes, firstcsr, hardware; BOOL active; AXIS axis_x, axis_y, axis_npressure, axis_or[3]; int i, k; int devix, cursorix; char devname[100], csrname[100]; BOOL defcontext_done; 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))); WTInfo (WTI_INTERFACE, IFC_NDEVICES, &ndevices); WTInfo (WTI_INTERFACE, IFC_NCURSORS, &ncursors);#if DEBUG_WINTAB GDK_NOTE (INPUT, 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_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. */ 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); 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 (WTInfo (WTI_DSCTXS + devix, 0, &lc) > 0) defcontext_done = TRUE;#if DEBUG_WINTAB 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) WTInfo (WTI_DEFSYSCTX, 0, &lc);#if DEBUG_WINTAB GDK_NOTE (INPUT, (g_print("Default context:\n"), print_lc(&lc)));#endif 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("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) { g_warning ("gdk_input_wintab_init: WTOpen failed"); return; } 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 /* 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 = 128; i >= 1; i >>= 1) { if (WTQueueSizeSet(*hctx, i)) { 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++) { 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; gdkdev->info.has_cursor = TRUE; 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); 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++; } 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].use = GDK_AXIS_Y; gdkdev->info.axes[k].min = axis_y.axMin; gdkdev->info.axes[k].max = axis_y.axMax; 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; /* 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++; } 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
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -