gdkinput-win32.c

Go to the documentation of this file.
00001 /* GDK - The GIMP Drawing Kit
00002  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
00003  * Copyright (C) 1999 Tor Lillqvist
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Library General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Library General Public
00016  * License along with this library; if not, write to the
00017  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018  * Boston, MA 02111-1307, USA.
00019  */
00020 
00021 /*
00022  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
00023  * file for a list of people on the GTK+ Team.  See the ChangeLog
00024  * files for a list of changes.  These files are distributed with
00025  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
00026  */
00027 
00028 #include "config.h"
00029 
00030 #include <stdlib.h>
00031 #include <stdio.h>
00032 #include <math.h>
00033 
00034 #include "gdk.h"
00035 #include "gdkinput.h"
00036 #include "gdkprivate.h"
00037 #include "gdkwin32.h"
00038 
00039 #ifdef HAVE_WINTAB
00040 #include "d:\development\wtkit\include\wintab.h"
00041 #define PACKETDATA (PK_CONTEXT | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y  | PK_NORMAL_PRESSURE | PK_ORIENTATION)
00042 #define PACKETMODE (PK_BUTTONS)
00043 #include "d:\development\wtkit\include\pktdef.h"
00044 #endif
00045 
00046 #include "gdkinputprivate.h"
00047 
00048 struct _GdkDevicePrivate {
00049    GdkDeviceInfo info;
00050 
00051    /* information about the axes */
00052    GdkAxisInfo *axes;
00053 
00054    /* reverse lookup on axis use type */
00055    gint axis_for_use[GDK_AXIS_LAST];
00056 
00057    /* true if we need to select a different set of events, but
00058     * can't because this is the core pointer
00059     */
00060    gint needs_update;
00061 
00062    /* State of buttons */
00063    gint button_state;
00064 
00065    gint *last_axis_data;
00066    gint last_buttons;
00067 #ifdef HAVE_WINTAB
00068    /* WINTAB stuff: */
00069    HCTX hctx;
00070    /* Cursor number */
00071    UINT cursor;
00072    /* The cursor's CSR_PKTDATA */
00073    WTPKT pktdata;
00074    /* CSR_NPBTNMARKS */
00075    UINT npbtnmarks[2];
00076    /* Azimuth and altitude axis */
00077    AXIS orientation_axes[2];
00078 #endif
00079 };
00080 
00081 #ifndef G_PI
00082 #define G_PI 3.14159265358979323846
00083 #endif
00084 
00085 /* If USE_SYSCONTEXT is on, we open the Wintab device (hmm, what if
00086  * there are several?) as a system pointing device, i.e. it controls
00087  * the normal Windows cursor. This seems much more natural.
00088  */
00089 #define USE_SYSCONTEXT 1        /* The code for the other choice is not
00090                                  * good at all.
00091                                  */
00092 
00093 #ifdef HAVE_WINTAB
00094 #define DEBUG_WINTAB 1
00095 #endif
00096 
00097 #define TWOPI (2.*G_PI)
00098 
00099 /* Forward declarations */
00100 
00101 static gint gdk_input_enable_window(GdkWindow * window,
00102                                     GdkDevicePrivate * gdkdev);
00103 static gint gdk_input_disable_window(GdkWindow * window,
00104                                      GdkDevicePrivate * gdkdev);
00105 static void gdk_input_none_get_pointer(GdkWindow * window,
00106                                        guint32 deviceid,
00107                                        gdouble * x,
00108                                        gdouble * y,
00109                                        gdouble * pressure,
00110                                        gdouble * xtilt,
00111                                        gdouble * ytilt,
00112                                        GdkModifierType * mask);
00113 
00114 static GdkDevicePrivate *gdk_input_find_device(guint32 deviceid);
00115 
00116 #ifdef HAVE_WINTAB
00117 
00118 static gint gdk_input_win32_set_mode(guint32 deviceid, GdkInputMode mode);
00119 static void gdk_input_win32_get_pointer(GdkWindow * window,
00120                                         guint32 deviceid,
00121                                         gdouble * x,
00122                                         gdouble * y,
00123                                         gdouble * pressure,
00124                                         gdouble * xtilt,
00125                                         gdouble * ytilt,
00126                                         GdkModifierType * mask);
00127 static gint gdk_input_win32_grab_pointer(GdkWindow * window,
00128                                          gint owner_events,
00129                                          GdkEventMask event_mask,
00130                                          GdkWindow * confine_to,
00131                                          guint32 time);
00132 static void gdk_input_win32_ungrab_pointer(guint32 time);
00133 static void gdk_input_win32_configure_event(GdkEventConfigure * event,
00134                                             GdkWindow * window);
00135 static void gdk_input_win32_enter_event(GdkEventCrossing * xevent,
00136                                         GdkWindow * window);
00137 static gint gdk_input_win32_other_event(GdkEvent * event, MSG * xevent);
00138 static gint gdk_input_win32_enable_window(GdkWindow * window,
00139                                           GdkDevicePrivate * gdkdev);
00140 static gint gdk_input_win32_disable_window(GdkWindow * window,
00141                                            GdkDevicePrivate * gdkdev);
00142 
00143 static GdkInputWindow *gdk_input_window_find(GdkWindow * window);
00144 #if !USE_SYSCONTEXT
00145 static GdkInputWindow *gdk_input_window_find_within(GdkWindow * window);
00146 #endif
00147 static GdkDevicePrivate *gdk_input_find_dev_from_ctx(HCTX hctx, UINT id);
00148 #endif                          /* HAVE_WINTAB */
00149 
00150 /* Local variables */
00151 
00152 static GList *gdk_input_devices;
00153 static GList *gdk_input_windows;
00154 static GList *wintab_contexts;
00155 
00156 static gint gdk_input_root_width;
00157 static gint gdk_input_root_height;
00158 
00159 static GdkWindow *wintab_window;
00160 
00161 static guint32 last_moved_cursor_id;
00162 
00163 static GdkAxisUse gdk_input_core_axes[] = { GDK_AXIS_X, GDK_AXIS_Y };
00164 
00165 static GdkDeviceInfo gdk_input_core_info = {
00166    GDK_CORE_POINTER,
00167    "Core Pointer",
00168    GDK_SOURCE_MOUSE,
00169    GDK_MODE_SCREEN,
00170    TRUE,
00171    2,
00172    gdk_input_core_axes
00173 };
00174 
00175 /* Global variables  */
00176 
00177 GdkInputVTable gdk_input_vtable;
00178 gint gdk_input_ignore_core;
00179 gint gdk_input_ignore_wintab = FALSE;
00180 
00181 #if DEBUG_WINTAB
00182 
00183 static void print_lc(LOGCONTEXT * lc)
00184 {
00185    g_print("lcName = %s\n", lc->lcName);
00186    g_print("lcOptions =");
00187    if (lc->lcOptions & CXO_SYSTEM)
00188       g_print(" CXO_SYSTEM");
00189    if (lc->lcOptions & CXO_PEN)
00190       g_print(" CXO_PEN");
00191    if (lc->lcOptions & CXO_MESSAGES)
00192       g_print(" CXO_MESSAGES");
00193    if (lc->lcOptions & CXO_MARGIN)
00194       g_print(" CXO_MARGIN");
00195    if (lc->lcOptions & CXO_MGNINSIDE)
00196       g_print(" CXO_MGNINSIDE");
00197    if (lc->lcOptions & CXO_CSRMESSAGES)
00198       g_print(" CXO_CSRMESSAGES");
00199    if (lc->lcOptions & CXO_CSRMESSAGES)
00200       g_print(" CXO_CSRMESSAGES");
00201    g_print("\n");
00202    g_print("lcStatus =");
00203    if (lc->lcStatus & CXS_DISABLED)
00204       g_print(" CXS_DISABLED");
00205    if (lc->lcStatus & CXS_OBSCURED)
00206       g_print(" CXS_OBSCURED");
00207    if (lc->lcStatus & CXS_ONTOP)
00208       g_print(" CXS_ONTOP");
00209    g_print("\n");
00210    g_print("lcLocks =");
00211    if (lc->lcLocks & CXL_INSIZE)
00212       g_print(" CXL_INSIZE");
00213    if (lc->lcLocks & CXL_INASPECT)
00214       g_print(" CXL_INASPECT");
00215    if (lc->lcLocks & CXL_SENSITIVITY)
00216       g_print(" CXL_SENSITIVITY");
00217    if (lc->lcLocks & CXL_MARGIN)
00218       g_print(" CXL_MARGIN");
00219    g_print("\n");
00220    g_print("lcMsgBase = %#x, lcDevice = %#x, lcPktRate = %d\n",
00221            lc->lcMsgBase, lc->lcDevice, lc->lcPktRate);
00222    g_print("lcPktData =");
00223    if (lc->lcPktData & PK_CONTEXT)
00224       g_print(" PK_CONTEXT");
00225    if (lc->lcPktData & PK_STATUS)
00226       g_print(" PK_STATUS");
00227    if (lc->lcPktData & PK_TIME)
00228       g_print(" PK_TIME");
00229    if (lc->lcPktData & PK_CHANGED)
00230       g_print(" PK_CHANGED");
00231    if (lc->lcPktData & PK_SERIAL_NUMBER)
00232       g_print(" PK_SERIAL_NUMBER");
00233    if (lc->lcPktData & PK_CURSOR)
00234       g_print(" PK_CURSOR");
00235    if (lc->lcPktData & PK_BUTTONS)
00236       g_print(" PK_BUTTONS");
00237    if (lc->lcPktData & PK_X)
00238       g_print(" PK_X");
00239    if (lc->lcPktData & PK_Y)
00240       g_print(" PK_Y");
00241    if (lc->lcPktData & PK_Z)
00242       g_print(" PK_Z");
00243    if (lc->lcPktData & PK_NORMAL_PRESSURE)
00244       g_print(" PK_NORMAL_PRESSURE");
00245    if (lc->lcPktData & PK_TANGENT_PRESSURE)
00246       g_print(" PK_TANGENT_PRESSURE");
00247    if (lc->lcPktData & PK_ORIENTATION)
00248       g_print(" PK_ORIENTATION");
00249    if (lc->lcPktData & PK_ROTATION)
00250       g_print(" PK_ROTATION");
00251    g_print("\n");
00252    g_print("lcPktMode =");
00253    if (lc->lcPktMode & PK_CONTEXT)
00254       g_print(" PK_CONTEXT");
00255    if (lc->lcPktMode & PK_STATUS)
00256       g_print(" PK_STATUS");
00257    if (lc->lcPktMode & PK_TIME)
00258       g_print(" PK_TIME");
00259    if (lc->lcPktMode & PK_CHANGED)
00260       g_print(" PK_CHANGED");
00261    if (lc->lcPktMode & PK_SERIAL_NUMBER)
00262       g_print(" PK_SERIAL_NUMBER");
00263    if (lc->lcPktMode & PK_CURSOR)
00264       g_print(" PK_CURSOR");
00265    if (lc->lcPktMode & PK_BUTTONS)
00266       g_print(" PK_BUTTONS");
00267    if (lc->lcPktMode & PK_X)
00268       g_print(" PK_X");
00269    if (lc->lcPktMode & PK_Y)
00270       g_print(" PK_Y");
00271    if (lc->lcPktMode & PK_Z)
00272       g_print(" PK_Z");
00273    if (lc->lcPktMode & PK_NORMAL_PRESSURE)
00274       g_print(" PK_NORMAL_PRESSURE");
00275    if (lc->lcPktMode & PK_TANGENT_PRESSURE)
00276       g_print(" PK_TANGENT_PRESSURE");
00277    if (lc->lcPktMode & PK_ORIENTATION)
00278       g_print(" PK_ORIENTATION");
00279    if (lc->lcPktMode & PK_ROTATION)
00280       g_print(" PK_ROTATION");
00281    g_print("\n");
00282    g_print("lcMoveMask =");
00283    if (lc->lcMoveMask & PK_CONTEXT)
00284       g_print(" PK_CONTEXT");
00285    if (lc->lcMoveMask & PK_STATUS)
00286       g_print(" PK_STATUS");
00287    if (lc->lcMoveMask & PK_TIME)
00288       g_print(" PK_TIME");
00289    if (lc->lcMoveMask & PK_CHANGED)
00290       g_print(" PK_CHANGED");
00291    if (lc->lcMoveMask & PK_SERIAL_NUMBER)
00292       g_print(" PK_SERIAL_NUMBER");
00293    if (lc->lcMoveMask & PK_CURSOR)
00294       g_print(" PK_CURSOR");
00295    if (lc->lcMoveMask & PK_BUTTONS)
00296       g_print(" PK_BUTTONS");
00297    if (lc->lcMoveMask & PK_X)
00298       g_print(" PK_X");
00299    if (lc->lcMoveMask & PK_Y)
00300       g_print(" PK_Y");
00301    if (lc->lcMoveMask & PK_Z)
00302       g_print(" PK_Z");
00303    if (lc->lcMoveMask & PK_NORMAL_PRESSURE)
00304       g_print(" PK_NORMAL_PRESSURE");
00305    if (lc->lcMoveMask & PK_TANGENT_PRESSURE)
00306       g_print(" PK_TANGENT_PRESSURE");
00307    if (lc->lcMoveMask & PK_ORIENTATION)
00308       g_print(" PK_ORIENTATION");
00309    if (lc->lcMoveMask & PK_ROTATION)
00310       g_print(" PK_ROTATION");
00311    g_print("\n");
00312    g_print("lcBtnDnMask = %#x, lcBtnUpMask = %#x\n",
00313            lc->lcBtnDnMask, lc->lcBtnUpMask);
00314    g_print("lcInOrgX = %d, lcInOrgY = %d, lcInOrgZ = %d\n",
00315            lc->lcInOrgX, lc->lcInOrgY, lc->lcInOrgZ);
00316    g_print("lcInExtX = %d, lcInExtY = %d, lcInExtZ = %d\n",
00317            lc->lcInExtX, lc->lcInExtY, lc->lcInExtZ);
00318    g_print("lcOutOrgX = %d, lcOutOrgY = %d, lcOutOrgZ = %d\n",
00319            lc->lcOutOrgX, lc->lcOutOrgY, lc->lcOutOrgZ);
00320    g_print("lcOutExtX = %d, lcOutExtY = %d, lcOutExtZ = %d\n",
00321            lc->lcOutExtX, lc->lcOutExtY, lc->lcOutExtZ);
00322    g_print("lcSensX = %g, lcSensY = %g, lcSensZ = %g\n",
00323            lc->lcSensX / 65536., lc->lcSensY / 65536.,
00324            lc->lcSensZ / 65536.);
00325    g_print("lcSysMode = %d\n", lc->lcSysMode);
00326    g_print("lcSysOrgX = %d, lcSysOrgY = %d\n",
00327            lc->lcSysOrgX, lc->lcSysOrgY);
00328    g_print("lcSysExtX = %d, lcSysExtY = %d\n",
00329            lc->lcSysExtX, lc->lcSysExtY);
00330    g_print("lcSysSensX = %g, lcSysSensY = %g\n",
00331            lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.);
00332 }
00333 
00334 #endif
00335 
00336 void gdk_input_init(void)
00337 {
00338    guint32 deviceid_counter = 0;
00339 #ifdef HAVE_WINTAB
00340    GdkDevicePrivate *gdkdev;
00341    GdkWindowAttr wa;
00342    WORD specversion;
00343    LOGCONTEXT defcontext;
00344    HCTX *hctx;
00345    UINT ndevices, ncursors, ncsrtypes, firstcsr, hardware;
00346    BOOL active;
00347    AXIS axis_x, axis_y, axis_npressure, axis_or[3];
00348    int i, j, k;
00349    int devix, cursorix;
00350    char devname[100], csrname[100];
00351 
00352    gdk_input_devices = NULL;
00353    wintab_contexts = NULL;
00354 
00355    if (!gdk_input_ignore_wintab && WTInfo(0, 0, NULL)) {
00356       WTInfo(WTI_INTERFACE, IFC_SPECVERSION, &specversion);
00357       GDK_NOTE(MISC, g_print("Wintab interface version %d.%d\n",
00358                              HIBYTE(specversion), LOBYTE(specversion)));
00359 #if USE_SYSCONTEXT
00360       WTInfo(WTI_DEFSYSCTX, 0, &defcontext);
00361 #if DEBUG_WINTAB
00362       GDK_NOTE(MISC, (g_print("DEFSYSCTX:\n"), print_lc(&defcontext)));
00363 #endif
00364 #else
00365       WTInfo(WTI_DEFCONTEXT, 0, &defcontext);
00366 #if DEBUG_WINTAB
00367       GDK_NOTE(MISC, (g_print("DEFCONTEXT:\n"), print_lc(&defcontext)));
00368 #endif
00369 #endif
00370       WTInfo(WTI_INTERFACE, IFC_NDEVICES, &ndevices);
00371       WTInfo(WTI_INTERFACE, IFC_NCURSORS, &ncursors);
00372 #if DEBUG_WINTAB
00373       GDK_NOTE(MISC, g_print("NDEVICES: %d, NCURSORS: %d\n",
00374                              ndevices, ncursors));
00375 #endif
00376       /* Create a dummy window to receive wintab events */
00377       wa.wclass = GDK_INPUT_OUTPUT;
00378       wa.event_mask = GDK_ALL_EVENTS_MASK;
00379       wa.width = 2;
00380       wa.height = 2;
00381       wa.x = -100;
00382       wa.y = -100;
00383       wa.window_type = GDK_WINDOW_TOPLEVEL;
00384       if ((wintab_window =
00385            gdk_window_new(NULL, &wa, GDK_WA_X | GDK_WA_Y)) == NULL) {
00386          g_warning("gdk_input_init: gdk_window_new failed");
00387          return;
00388       }
00389       gdk_window_ref(wintab_window);
00390 
00391       for (devix = 0; devix < ndevices; devix++) {
00392          LOGCONTEXT lc;
00393 
00394          WTInfo(WTI_DEVICES + devix, DVC_NAME, devname);
00395 
00396          WTInfo(WTI_DEVICES + devix, DVC_NCSRTYPES, &ncsrtypes);
00397          WTInfo(WTI_DEVICES + devix, DVC_FIRSTCSR, &firstcsr);
00398          WTInfo(WTI_DEVICES + devix, DVC_HARDWARE, &hardware);
00399          WTInfo(WTI_DEVICES + devix, DVC_X, &axis_x);
00400          WTInfo(WTI_DEVICES + devix, DVC_Y, &axis_y);
00401          WTInfo(WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure);
00402          WTInfo(WTI_DEVICES + devix, DVC_ORIENTATION, axis_or);
00403 
00404          if (HIBYTE(specversion) > 1 || LOBYTE(specversion) >= 1) {
00405             WTInfo(WTI_DDCTXS + devix, CTX_NAME, lc.lcName);
00406             WTInfo(WTI_DDCTXS + devix, CTX_OPTIONS, &lc.lcOptions);
00407             lc.lcOptions |= CXO_MESSAGES;
00408 #if USE_SYSCONTEXT
00409             lc.lcOptions |= CXO_SYSTEM;
00410 #endif
00411             lc.lcStatus = 0;
00412             WTInfo(WTI_DDCTXS + devix, CTX_LOCKS, &lc.lcLocks);
00413             lc.lcMsgBase = WT_DEFBASE;
00414             lc.lcDevice = devix;
00415             lc.lcPktRate = 50;
00416             lc.lcPktData = PACKETDATA;
00417             lc.lcPktMode = PK_BUTTONS;  /* We want buttons in relative mode */
00418             lc.lcMoveMask = PACKETDATA;
00419             lc.lcBtnDnMask = lc.lcBtnUpMask = ~0;
00420             WTInfo(WTI_DDCTXS + devix, CTX_INORGX, &lc.lcInOrgX);
00421             WTInfo(WTI_DDCTXS + devix, CTX_INORGY, &lc.lcInOrgY);
00422             WTInfo(WTI_DDCTXS + devix, CTX_INORGZ, &lc.lcInOrgZ);
00423             WTInfo(WTI_DDCTXS + devix, CTX_INEXTX, &lc.lcInExtX);
00424             WTInfo(WTI_DDCTXS + devix, CTX_INEXTY, &lc.lcInExtY);
00425             WTInfo(WTI_DDCTXS + devix, CTX_INEXTZ, &lc.lcInExtZ);
00426             lc.lcOutOrgX = axis_x.axMin;
00427             lc.lcOutOrgY = axis_y.axMin;
00428             lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
00429             lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
00430             lc.lcOutExtY = -lc.lcOutExtY;       /* We want Y growing downward */
00431             WTInfo(WTI_DDCTXS + devix, CTX_SENSX, &lc.lcSensX);
00432             WTInfo(WTI_DDCTXS + devix, CTX_SENSY, &lc.lcSensY);
00433             WTInfo(WTI_DDCTXS + devix, CTX_SENSZ, &lc.lcSensZ);
00434             WTInfo(WTI_DDCTXS + devix, CTX_SYSMODE, &lc.lcSysMode);
00435             lc.lcSysOrgX = lc.lcSysOrgY = 0;
00436             WTInfo(WTI_DDCTXS + devix, CTX_SYSEXTX, &lc.lcSysExtX);
00437             WTInfo(WTI_DDCTXS + devix, CTX_SYSEXTY, &lc.lcSysExtY);
00438             WTInfo(WTI_DDCTXS + devix, CTX_SYSSENSX, &lc.lcSysSensX);
00439             WTInfo(WTI_DDCTXS + devix, CTX_SYSSENSY, &lc.lcSysSensY);
00440          } else {
00441             lc = defcontext;
00442             lc.lcOptions |= CXO_MESSAGES;
00443             lc.lcMsgBase = WT_DEFBASE;
00444             lc.lcPktRate = 50;
00445             lc.lcPktData = PACKETDATA;
00446             lc.lcPktMode = PACKETMODE;
00447             lc.lcMoveMask = PACKETDATA;
00448             lc.lcBtnUpMask = lc.lcBtnDnMask = ~0;
00449 #if 0
00450             lc.lcOutExtY = -lc.lcOutExtY;       /* Y grows downward */
00451 #else
00452             lc.lcOutOrgX = axis_x.axMin;
00453             lc.lcOutOrgY = axis_y.axMin;
00454             lc.lcOutExtX = axis_x.axMax - axis_x.axMin;
00455             lc.lcOutExtY = axis_y.axMax - axis_y.axMin;
00456             lc.lcOutExtY = -lc.lcOutExtY;       /* We want Y growing downward */
00457 #endif
00458          }
00459 #if DEBUG_WINTAB
00460          GDK_NOTE(MISC, (g_print("context for device %d:\n", devix),
00461                          print_lc(&lc)));
00462 #endif
00463          hctx = g_new(HCTX, 1);
00464          if ((*hctx =
00465               WTOpen(GDK_DRAWABLE_XID(wintab_window), &lc,
00466                      TRUE)) == NULL) {
00467             g_warning("gdk_input_init: WTOpen failed");
00468             return;
00469          }
00470          GDK_NOTE(MISC, g_print("opened Wintab device %d %#x\n",
00471                                 devix, *hctx));
00472 
00473          wintab_contexts = g_list_append(wintab_contexts, hctx);
00474 #if 0
00475          WTEnable(*hctx, TRUE);
00476 #endif
00477          WTOverlap(*hctx, TRUE);
00478 
00479 #if DEBUG_WINTAB
00480          GDK_NOTE(MISC,
00481                   (g_print("context for device %d after WTOpen:\n", devix),
00482                    print_lc(&lc)));
00483 #endif
00484          for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes;
00485               cursorix++) {
00486             active = FALSE;
00487             WTInfo(WTI_CURSORS + cursorix, CSR_ACTIVE, &active);
00488             if (!active)
00489                continue;
00490             gdkdev = g_new(GdkDevicePrivate, 1);
00491             WTInfo(WTI_CURSORS + cursorix, CSR_NAME, csrname);
00492             gdkdev->info.name = g_strconcat(devname, " ", csrname, NULL);
00493             gdkdev->info.deviceid = deviceid_counter++;
00494             gdkdev->info.source = GDK_SOURCE_PEN;
00495             gdkdev->info.mode = GDK_MODE_SCREEN;
00496 #if USE_SYSCONTEXT
00497             gdkdev->info.has_cursor = TRUE;
00498 #else
00499             gdkdev->info.has_cursor = FALSE;
00500 #endif
00501             gdkdev->hctx = *hctx;
00502             gdkdev->cursor = cursorix;
00503             WTInfo(WTI_CURSORS + cursorix, CSR_PKTDATA, &gdkdev->pktdata);
00504             gdkdev->info.num_axes = 0;
00505             if (gdkdev->pktdata & PK_X)
00506                gdkdev->info.num_axes++;
00507             if (gdkdev->pktdata & PK_Y)
00508                gdkdev->info.num_axes++;
00509             if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
00510                gdkdev->info.num_axes++;
00511             /* The wintab driver for the Wacom ArtPad II reports
00512              * PK_ORIENTATION in CSR_PKTDATA, but the tablet doesn't
00513              * actually sense tilt. Catch this by noticing that the
00514              * orientation axis's azimuth resolution is zero.
00515              */
00516             if ((gdkdev->pktdata & PK_ORIENTATION)
00517                 && axis_or[0].axResolution == 0)
00518                gdkdev->pktdata &= ~PK_ORIENTATION;
00519 
00520             if (gdkdev->pktdata & PK_ORIENTATION)
00521                gdkdev->info.num_axes += 2;      /* x and y tilt */
00522             WTInfo(WTI_CURSORS + cursorix, CSR_NPBTNMARKS,
00523                    &gdkdev->npbtnmarks);
00524             gdkdev->axes = g_new(GdkAxisInfo, gdkdev->info.num_axes);
00525             gdkdev->info.axes = g_new(GdkAxisUse, gdkdev->info.num_axes);
00526             gdkdev->last_axis_data = g_new(gint, gdkdev->info.num_axes);
00527 
00528             for (k = 0; k < GDK_AXIS_LAST; k++)
00529                gdkdev->axis_for_use[k] = -1;
00530 
00531             k = 0;
00532             if (gdkdev->pktdata & PK_X) {
00533                gdkdev->axes[k].xresolution =
00534                    gdkdev->axes[k].resolution =
00535                    axis_x.axResolution / 65535.;
00536                gdkdev->axes[k].xmin_value = gdkdev->axes[k].min_value =
00537                    axis_x.axMin;
00538                gdkdev->axes[k].xmax_value = gdkdev->axes[k].max_value =
00539                    axis_x.axMax;
00540                gdkdev->info.axes[k] = GDK_AXIS_X;
00541                gdkdev->axis_for_use[GDK_AXIS_X] = k;
00542                k++;
00543             }
00544             if (gdkdev->pktdata & PK_Y) {
00545                gdkdev->axes[k].xresolution =
00546                    gdkdev->axes[k].resolution =
00547                    axis_y.axResolution / 65535.;
00548                gdkdev->axes[k].xmin_value = gdkdev->axes[k].min_value =
00549                    axis_y.axMin;
00550                gdkdev->axes[k].xmax_value = gdkdev->axes[k].max_value =
00551                    axis_y.axMax;
00552                gdkdev->info.axes[k] = GDK_AXIS_Y;
00553                gdkdev->axis_for_use[GDK_AXIS_Y] = k;
00554                k++;
00555             }
00556             if (gdkdev->pktdata & PK_NORMAL_PRESSURE) {
00557                gdkdev->axes[k].xresolution =
00558                    gdkdev->axes[k].resolution =
00559                    axis_npressure.axResolution / 65535.;
00560                gdkdev->axes[k].xmin_value = gdkdev->axes[k].min_value =
00561                    axis_npressure.axMin;
00562                gdkdev->axes[k].xmax_value = gdkdev->axes[k].max_value =
00563                    axis_npressure.axMax;
00564                gdkdev->info.axes[k] = GDK_AXIS_PRESSURE;
00565                gdkdev->axis_for_use[GDK_AXIS_PRESSURE] = k;
00566                k++;
00567             }
00568             if (gdkdev->pktdata & PK_ORIENTATION) {
00569                GdkAxisUse axis;
00570 
00571                gdkdev->orientation_axes[0] = axis_or[0];
00572                gdkdev->orientation_axes[1] = axis_or[1];
00573                for (axis = GDK_AXIS_XTILT; axis <= GDK_AXIS_YTILT; axis++) {
00574                   /* Wintab gives us aximuth and altitude, which
00575                    * we convert to x and y tilt in the -1000..1000 range
00576                    */
00577                   gdkdev->axes[k].xresolution =
00578                       gdkdev->axes[k].resolution = 1000;
00579                   gdkdev->axes[k].xmin_value =
00580                       gdkdev->axes[k].min_value = -1000;
00581                   gdkdev->axes[k].xmax_value =
00582                       gdkdev->axes[k].max_value = 1000;
00583                   gdkdev->info.axes[k] = axis;
00584                   gdkdev->axis_for_use[axis] = k;
00585                   k++;
00586                }
00587             }
00588             gdkdev->info.num_keys = 0;
00589             gdkdev->info.keys = NULL;
00590             GDK_NOTE(EVENTS,
00591                      (g_print("device: %d (%d) %s axes: %d\n",
00592                               gdkdev->info.deviceid, cursorix,
00593                               gdkdev->info.name,
00594                               gdkdev->info.num_axes),
00595                       g_print("axes: X:%d, Y:%d, PRESSURE:%d, "
00596                               "XTILT:%d, YTILT:%d\n",
00597                               gdkdev->axis_for_use[GDK_AXIS_X],
00598                               gdkdev->axis_for_use[GDK_AXIS_Y],
00599                               gdkdev->axis_for_use[GDK_AXIS_PRESSURE],
00600                               gdkdev->axis_for_use[GDK_AXIS_XTILT],
00601                               gdkdev->axis_for_use[GDK_AXIS_YTILT])));
00602             for (i = 0; i < gdkdev->info.num_axes; i++)
00603                GDK_NOTE(EVENTS,
00604                         g_print("...axis %d: %d--%d@%d (%d--%d@%d)\n",
00605                                 i,
00606                                 gdkdev->axes[i].xmin_value,
00607                                 gdkdev->axes[i].xmax_value,
00608                                 gdkdev->axes[i].xresolution,
00609                                 gdkdev->axes[i].min_value,
00610                                 gdkdev->axes[i].max_value,
00611                                 gdkdev->axes[i].resolution));
00612             gdk_input_devices = g_list_append(gdk_input_devices, gdkdev);
00613          }
00614       }
00615    }
00616 #endif                          /* HAVE_WINTAB */
00617 
00618    if (deviceid_counter > 0) {
00619 #ifdef HAVE_WINTAB
00620       gdk_input_vtable.set_mode = gdk_input_win32_set_mode;
00621       gdk_input_vtable.set_axes = NULL;
00622       gdk_input_vtable.set_key = NULL;
00623       gdk_input_vtable.motion_events = NULL;
00624       gdk_input_vtable.get_pointer = gdk_input_win32_get_pointer;
00625       gdk_input_vtable.grab_pointer = gdk_input_win32_grab_pointer;
00626       gdk_input_vtable.ungrab_pointer = gdk_input_win32_ungrab_pointer;
00627       gdk_input_vtable.configure_event = gdk_input_win32_configure_event;
00628       gdk_input_vtable.enter_event = gdk_input_win32_enter_event;
00629       gdk_input_vtable.other_event = gdk_input_win32_other_event;
00630       gdk_input_vtable.enable_window = gdk_input_win32_enable_window;
00631       gdk_input_vtable.disable_window = gdk_input_win32_disable_window;
00632 
00633       gdk_input_root_width = gdk_screen_width();
00634       gdk_input_root_height = gdk_screen_height();
00635       gdk_input_ignore_core = FALSE;
00636 #else
00637       g_assert_not_reached();
00638 #endif
00639    } else {
00640       gdk_input_vtable.set_mode = NULL;
00641       gdk_input_vtable.set_axes = NULL;
00642       gdk_input_vtable.set_key = NULL;
00643       gdk_input_vtable.motion_events = NULL;
00644       gdk_input_vtable.get_pointer = gdk_input_none_get_pointer;
00645       gdk_input_vtable.grab_pointer = NULL;
00646       gdk_input_vtable.ungrab_pointer = NULL;
00647       gdk_input_vtable.configure_event = NULL;
00648       gdk_input_vtable.enter_event = NULL;
00649       gdk_input_vtable.other_event = NULL;
00650       gdk_input_vtable.enable_window = NULL;
00651       gdk_input_vtable.disable_window = NULL;
00652       gdk_input_ignore_core = FALSE;
00653    }
00654 
00655    gdk_input_devices =
00656        g_list_append(gdk_input_devices, &gdk_input_core_info);
00657 }
00658 
00659 gint gdk_input_set_mode(guint32 deviceid, GdkInputMode mode)
00660 {
00661    if (deviceid == GDK_CORE_POINTER)
00662       return FALSE;
00663 
00664    if (gdk_input_vtable.set_mode)
00665       return gdk_input_vtable.set_mode(deviceid, mode);
00666    else
00667       return FALSE;
00668 }
00669 
00670 void gdk_input_set_axes(guint32 deviceid, GdkAxisUse * axes)
00671 {
00672    int i;
00673    GdkDevicePrivate *gdkdev = gdk_input_find_device(deviceid);
00674    g_return_if_fail(gdkdev != NULL);
00675 
00676    if (deviceid == GDK_CORE_POINTER)
00677       return;
00678 
00679    for (i = GDK_AXIS_IGNORE; i < GDK_AXIS_LAST; i++) {
00680       gdkdev->axis_for_use[i] = -1;
00681    }
00682 
00683    for (i = 0; i < gdkdev->info.num_axes; i++) {
00684       gdkdev->info.axes[i] = axes[i];
00685       gdkdev->axis_for_use[axes[i]] = i;
00686    }
00687 }
00688 
00689 static void
00690 gdk_input_none_get_pointer(GdkWindow * window,
00691                            guint32 deviceid,
00692                            gdouble * x,
00693                            gdouble * y,
00694                            gdouble * pressure,
00695                            gdouble * xtilt,
00696                            gdouble * ytilt, GdkModifierType * mask)
00697 {
00698    gint x_int, y_int;
00699 
00700    gdk_window_get_pointer(window, &x_int, &y_int, mask);
00701 
00702    if (x)
00703       *x = x_int;
00704    if (y)
00705       *y = y_int;
00706    if (pressure)
00707       *pressure = 0.5;
00708    if (xtilt)
00709       *xtilt = 0;
00710    if (ytilt)
00711       *ytilt = 0;
00712 }
00713 
00714 #ifdef HAVE_WINTAB
00715 
00716 static void
00717 gdk_input_translate_coordinates(GdkDevicePrivate * gdkdev,
00718                                 GdkInputWindow * input_window,
00719                                 gint * axis_data,
00720                                 gdouble * x,
00721                                 gdouble * y,
00722                                 gdouble * pressure,
00723                                 gdouble * xtilt, gdouble * ytilt)
00724 {
00725    GdkDrawablePrivate *window_private;
00726    gint x_axis, y_axis, pressure_axis, xtilt_axis, ytilt_axis;
00727    gdouble device_width, device_height;
00728    gdouble x_offset, y_offset, x_scale, y_scale;
00729 
00730    window_private = (GdkDrawablePrivate *) input_window->window;
00731 
00732    x_axis = gdkdev->axis_for_use[GDK_AXIS_X];
00733    y_axis = gdkdev->axis_for_use[GDK_AXIS_Y];
00734    pressure_axis = gdkdev->axis_for_use[GDK_AXIS_PRESSURE];
00735    xtilt_axis = gdkdev->axis_for_use[GDK_AXIS_XTILT];
00736    ytilt_axis = gdkdev->axis_for_use[GDK_AXIS_YTILT];
00737 
00738    device_width = gdkdev->axes[x_axis].max_value -
00739        gdkdev->axes[x_axis].min_value;
00740    device_height = gdkdev->axes[y_axis].max_value -
00741        gdkdev->axes[y_axis].min_value;
00742 
00743    if (gdkdev->info.mode == GDK_MODE_SCREEN) {
00744       x_scale = gdk_input_root_width / device_width;
00745       y_scale = gdk_input_root_height / device_height;
00746 
00747       x_offset = -input_window->root_x;
00748       y_offset = -input_window->root_y;
00749    } else {                     /* GDK_MODE_WINDOW */
00750 
00751       double device_aspect =
00752           (device_height * gdkdev->axes[y_axis].resolution) /
00753           (device_width * gdkdev->axes[x_axis].resolution);
00754 
00755       if (device_aspect * window_private->width >= window_private->height) {
00756          /* device taller than window */
00757          x_scale = window_private->width / device_width;
00758          y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
00759              / gdkdev->axes[y_axis].resolution;
00760 
00761          x_offset = 0;
00762          y_offset = -(device_height * y_scale -
00763                       window_private->height) / 2;
00764       } else {
00765          /* window taller than device */
00766          y_scale = window_private->height / device_height;
00767          x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
00768              / gdkdev->axes[x_axis].resolution;
00769 
00770          y_offset = 0;
00771          x_offset = -(device_width * x_scale - window_private->width) / 2;
00772       }
00773    }
00774 
00775    if (x)
00776       *x = x_offset + x_scale * axis_data[x_axis];
00777    if (y)
00778       *y = y_offset + y_scale * axis_data[y_axis];
00779 
00780    if (pressure) {
00781       if (pressure_axis != -1)
00782          *pressure = ((double) axis_data[pressure_axis]
00783                       - gdkdev->axes[pressure_axis].min_value)
00784              / (gdkdev->axes[pressure_axis].max_value
00785                 - gdkdev->axes[pressure_axis].min_value);
00786       else
00787          *pressure = 0.5;
00788    }
00789 
00790    if (xtilt) {
00791       if (xtilt_axis != -1) {
00792          *xtilt = 2. * (double) (axis_data[xtilt_axis] -
00793                                  (gdkdev->axes[xtilt_axis].min_value +
00794                                   gdkdev->axes[xtilt_axis].max_value) /
00795                                  2) / (gdkdev->axes[xtilt_axis].max_value -
00796                                        gdkdev->axes[xtilt_axis].min_value);
00797       } else
00798          *xtilt = 0;
00799    }
00800 
00801    if (ytilt) {
00802       if (ytilt_axis != -1) {
00803          *ytilt = 2. * (double) (axis_data[ytilt_axis] -
00804                                  (gdkdev->axes[ytilt_axis].min_value +
00805                                   gdkdev->axes[ytilt_axis].max_value) /
00806                                  2) / (gdkdev->axes[ytilt_axis].max_value -
00807                                        gdkdev->axes[ytilt_axis].min_value);
00808       } else
00809          *ytilt = 0;
00810    }
00811 }
00812 
00813 static void
00814 gdk_input_win32_get_pointer(GdkWindow * window,
00815                             guint32 deviceid,
00816                             gdouble * x,
00817                             gdouble * y,
00818                             gdouble * pressure,
00819                             gdouble * xtilt,
00820                             gdouble * ytilt, GdkModifierType * mask)
00821 {
00822    GdkDevicePrivate *gdkdev;
00823    GdkInputWindow *input_window;
00824    gint x_int, y_int;
00825    gint i;
00826 
00827    if (deviceid == GDK_CORE_POINTER) {
00828       gdk_window_get_pointer(window, &x_int, &y_int, mask);
00829       if (x)
00830          *x = x_int;
00831       if (y)
00832          *y = y_int;
00833       if (pressure)
00834          *pressure = 0.5;
00835       if (xtilt)
00836          *xtilt = 0;
00837       if (ytilt)
00838          *ytilt = 0;
00839    } else {
00840       if (mask)
00841          gdk_window_get_pointer(window, NULL, NULL, mask);
00842 
00843       gdkdev = gdk_input_find_device(deviceid);
00844       g_return_if_fail(gdkdev != NULL);
00845 
00846       input_window = gdk_input_window_find(window);
00847       g_return_if_fail(input_window != NULL);
00848 
00849       gdk_input_translate_coordinates(gdkdev, input_window,
00850                                       gdkdev->last_axis_data,
00851                                       x, y, pressure, xtilt, ytilt);
00852       if (mask) {
00853          *mask &= 0xFF;
00854          *mask |= ((gdkdev->last_buttons & 0x1F) << 8);
00855       }
00856    }
00857 }
00858 
00859 static void
00860 gdk_input_get_root_relative_geometry(HWND w, int *x_ret, int *y_ret)
00861 {
00862    RECT rect;
00863 
00864    GetWindowRect(w, &rect);
00865 
00866    if (x_ret)
00867       *x_ret = rect.left;
00868    if (y_ret)
00869       *y_ret = rect.top;
00870 }
00871 
00872 static gint gdk_input_win32_set_mode(guint32 deviceid, GdkInputMode mode)
00873 {
00874    GList *tmp_list;
00875    GdkDevicePrivate *gdkdev;
00876    GdkInputMode old_mode;
00877    GdkInputWindow *input_window;
00878 
00879    if (deviceid == GDK_CORE_POINTER)
00880       return FALSE;
00881 
00882    gdkdev = gdk_input_find_device(deviceid);
00883    g_return_val_if_fail(gdkdev != NULL, FALSE);
00884    old_mode = gdkdev->info.mode;
00885 
00886    if (old_mode == mode)
00887       return TRUE;
00888 
00889    gdkdev->info.mode = mode;
00890 
00891    if (mode == GDK_MODE_WINDOW) {
00892       gdkdev->info.has_cursor = FALSE;
00893       for (tmp_list = gdk_input_windows; tmp_list;
00894            tmp_list = tmp_list->next) {
00895          input_window = (GdkInputWindow *) tmp_list->data;
00896          if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
00897             gdk_input_win32_enable_window(input_window->window, gdkdev);
00898          else if (old_mode != GDK_MODE_DISABLED)
00899             gdk_input_win32_disable_window(input_window->window, gdkdev);
00900       }
00901    } else if (mode == GDK_MODE_SCREEN) {
00902       gdkdev->info.has_cursor = TRUE;
00903       for (tmp_list = gdk_input_windows; tmp_list;
00904            tmp_list = tmp_list->next)
00905          gdk_input_win32_enable_window(((GdkInputWindow *) tmp_list->
00906                                         data)->window, gdkdev);
00907    } else {                     /* mode == GDK_MODE_DISABLED */
00908 
00909       for (tmp_list = gdk_input_windows; tmp_list;
00910            tmp_list = tmp_list->next) {
00911          input_window = (GdkInputWindow *) tmp_list->data;
00912          if (old_mode != GDK_MODE_WINDOW ||
00913              input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
00914             gdk_input_win32_disable_window(input_window->window, gdkdev);
00915       }
00916    }
00917 
00918    return TRUE;
00919 }
00920 
00921 static void
00922 gdk_input_win32_configure_event(GdkEventConfigure * event,
00923                                 GdkWindow * window)
00924 {
00925    GdkInputWindow *input_window;
00926    gint root_x, root_y;
00927 
00928    input_window = gdk_input_window_find(window);
00929    g_return_if_fail(window != NULL);
00930 
00931    gdk_input_get_root_relative_geometry
00932        (GDK_DRAWABLE_XID(window), &root_x, &root_y);
00933 
00934    input_window->root_x = root_x;
00935    input_window->root_y = root_y;
00936 }
00937 
00938 static void
00939 gdk_input_win32_enter_event(GdkEventCrossing * event, GdkWindow * window)
00940 {
00941    GdkInputWindow *input_window;
00942    gint root_x, root_y;
00943 
00944    input_window = gdk_input_window_find(window);
00945    g_return_if_fail(window != NULL);
00946 
00947    gdk_input_get_root_relative_geometry
00948        (GDK_DRAWABLE_XID(window), &root_x, &root_y);
00949 
00950    input_window->root_x = root_x;
00951    input_window->root_y = root_y;
00952 }
00953 
00954 static void decode_tilt(gint * axis_data, AXIS * axes, PACKET * packet)
00955 {
00956    /* As I don't have a tilt-sensing tablet,
00957     * I cannot test this code.
00958     */
00959 
00960    double az, el;
00961 
00962    az = TWOPI * packet->pkOrientation.orAzimuth /
00963        (axes[0].axResolution / 65536.);
00964    el = TWOPI * packet->pkOrientation.orAltitude /
00965        (axes[1].axResolution / 65536.);
00966 
00967    /* X tilt */
00968    axis_data[0] = cos(az) * cos(el) * 1000;
00969    /* Y tilt */
00970    axis_data[1] = sin(az) * cos(el) * 1000;
00971 }
00972 
00973 static GdkDevicePrivate *gdk_input_find_dev_from_ctx(HCTX hctx,
00974                                                      UINT cursor)
00975 {
00976    GList *tmp_list = gdk_input_devices;
00977    GdkDevicePrivate *gdkdev;
00978 
00979    while (tmp_list) {
00980       gdkdev = (GdkDevicePrivate *) (tmp_list->data);
00981       if (gdkdev->hctx == hctx && gdkdev->cursor == cursor)
00982          return gdkdev;
00983       tmp_list = tmp_list->next;
00984    }
00985    return NULL;
00986 }
00987 
00988 static gint gdk_input_win32_other_event(GdkEvent * event, MSG * xevent)
00989 {
00990    GdkWindow *current_window;
00991    GdkInputWindow *input_window;
00992    GdkWindow *window;
00993    GdkDevicePrivate *gdkdev;
00994    GdkEventMask masktest;
00995    POINT pt;
00996    PACKET packet;
00997    gint return_val;
00998    gint k;
00999    gint x, y;
01000 
01001    if (event->any.window != wintab_window) {
01002       g_warning("gdk_input_win32_other_event: not wintab_window?");
01003       return FALSE;
01004    }
01005 #if USE_SYSCONTEXT
01006    window = gdk_window_at_pointer(&x, &y);
01007    if (window == NULL)
01008       window = gdk_parent_root;
01009 
01010    gdk_window_ref(window);
01011 
01012    GDK_NOTE(EVENTS,
01013             g_print("gdk_input_win32_other_event: window=%#x (%d,%d)\n",
01014                     GDK_DRAWABLE_XID(window), x, y));
01015 
01016 #else
01017    /* ??? This code is pretty bogus */
01018    current_window = gdk_window_lookup(GetActiveWindow());
01019    if (current_window == NULL)
01020       return FALSE;
01021 
01022    input_window = gdk_input_window_find_within(current_window);
01023    if (input_window == NULL)
01024       return FALSE;
01025 #endif
01026 
01027    if (xevent->message == WT_PACKET) {
01028       if (!WTPacket((HCTX) xevent->lParam, xevent->wParam, &packet))
01029          return FALSE;
01030    }
01031 
01032    switch (xevent->message) {
01033    case WT_PACKET:
01034       if (window == gdk_parent_root) {
01035          GDK_NOTE(EVENTS, g_print("...is root\n"));
01036          return FALSE;
01037       }
01038 
01039       if ((gdkdev = gdk_input_find_dev_from_ctx((HCTX) xevent->lParam,
01040                                                 packet.pkCursor)) == NULL)
01041          return FALSE;
01042 
01043       if (gdkdev->info.mode == GDK_MODE_DISABLED)
01044          return FALSE;
01045 
01046       k = 0;
01047       if (gdkdev->pktdata & PK_X)
01048          gdkdev->last_axis_data[k++] = packet.pkX;
01049       if (gdkdev->pktdata & PK_Y)
01050          gdkdev->last_axis_data[k++] = packet.pkY;
01051       if (gdkdev->pktdata & PK_NORMAL_PRESSURE)
01052          gdkdev->last_axis_data[k++] = packet.pkNormalPressure;
01053       if (gdkdev->pktdata & PK_ORIENTATION) {
01054          decode_tilt(gdkdev->last_axis_data + k,
01055                      gdkdev->orientation_axes, &packet);
01056          k += 2;
01057       }
01058 
01059       g_assert(k == gdkdev->info.num_axes);
01060 
01061       if (HIWORD(packet.pkButtons) != TBN_NONE) {
01062          /* Gdk buttons are numbered 1.. */
01063          event->button.button = 1 + LOWORD(packet.pkButtons);
01064 
01065          if (HIWORD(packet.pkButtons) == TBN_UP) {
01066             event->any.type = GDK_BUTTON_RELEASE;
01067             masktest = GDK_BUTTON_RELEASE_MASK;
01068             gdkdev->button_state &= ~(1 << LOWORD(packet.pkButtons));
01069          } else {
01070             event->any.type = GDK_BUTTON_PRESS;
01071             masktest = GDK_BUTTON_PRESS_MASK;
01072             gdkdev->button_state |= 1 << LOWORD(packet.pkButtons);
01073          }
01074       } else {
01075          event->any.type = GDK_MOTION_NOTIFY;
01076          masktest = GDK_POINTER_MOTION_MASK;
01077          if (gdkdev->button_state & (1 << 0))
01078             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK;
01079          if (gdkdev->button_state & (1 << 1))
01080             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK;
01081          if (gdkdev->button_state & (1 << 2))
01082             masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK;
01083       }
01084 
01085       /* Now we can check if the window wants the event, and
01086        * propagate if necessary.
01087        */
01088     dijkstra:
01089       if (!GDK_WINDOW_WIN32DATA(window)->extension_events_selected
01090           || !(((GdkWindowPrivate *) window)->extension_events & masktest))
01091       {
01092          GDK_NOTE(EVENTS, g_print("...not selected\n"));
01093 
01094          if (((GdkWindowPrivate *) window)->parent == gdk_parent_root)
01095             return FALSE;
01096 
01097          pt.x = x;
01098          pt.y = y;
01099          ClientToScreen(GDK_DRAWABLE_XID(window), &pt);
01100          gdk_window_unref(window);
01101          window = ((GdkWindowPrivate *) window)->parent;
01102          gdk_window_ref(window);
01103          ScreenToClient(GDK_DRAWABLE_XID(window), &pt);
01104          x = pt.x;
01105          y = pt.y;
01106          GDK_NOTE(EVENTS, g_print("...propagating to %#x, (%d,%d)\n",
01107                                   GDK_DRAWABLE_XID(window), x, y));
01108          goto dijkstra;
01109       }
01110 
01111       input_window = gdk_input_window_find(window);
01112 
01113       g_assert(input_window != NULL);
01114 
01115       if (gdkdev->info.mode == GDK_MODE_WINDOW
01116           && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
01117          return FALSE;
01118 
01119       event->any.window = window;
01120 
01121       if (event->any.type == GDK_BUTTON_PRESS
01122           || event->any.type == GDK_BUTTON_RELEASE) {
01123          event->button.time = xevent->time;
01124          event->button.source = gdkdev->info.source;
01125          last_moved_cursor_id =
01126              event->button.deviceid = gdkdev->info.deviceid;
01127 
01128 #if 0
01129 #if USE_SYSCONTEXT
01130          /* Buttons 1 to 3 will come in as WM_[LMR]BUTTON{DOWN,UP} */
01131          if (event->button.button <= 3)
01132             return FALSE;
01133 #endif
01134 #endif
01135          gdk_input_translate_coordinates(gdkdev, input_window,
01136                                          gdkdev->last_axis_data,
01137                                          &event->button.x,
01138                                          &event->button.y,
01139                                          &event->button.pressure,
01140                                          &event->button.xtilt,
01141                                          &event->button.ytilt);
01142 
01143          event->button.state = ((gdkdev->button_state << 8)
01144                                 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
01145                                    | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
01146                                    | GDK_BUTTON5_MASK));
01147          GDK_NOTE(EVENTS,
01148                   g_print("WINTAB button %s: %d %d %g,%g %g %g,%g\n",
01149                           (event->button.type ==
01150                            GDK_BUTTON_PRESS ? "press" : "release"),
01151                           event->button.deviceid, event->button.button,
01152                           event->button.x, event->button.y,
01153                           event->button.pressure, event->button.xtilt,
01154                           event->button.ytilt));
01155       } else {
01156          event->motion.time = xevent->time;
01157          last_moved_cursor_id =
01158              event->motion.deviceid = gdkdev->info.deviceid;
01159          event->motion.is_hint = FALSE;
01160          event->motion.source = gdkdev->info.source;
01161 
01162          gdk_input_translate_coordinates(gdkdev, input_window,
01163                                          gdkdev->last_axis_data,
01164                                          &event->motion.x,
01165                                          &event->motion.y,
01166                                          &event->motion.pressure,
01167                                          &event->motion.xtilt,
01168                                          &event->motion.ytilt);
01169 
01170          event->motion.state = ((gdkdev->button_state << 8)
01171                                 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
01172                                    | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
01173                                    | GDK_BUTTON5_MASK));
01174 
01175          GDK_NOTE(EVENTS, g_print("WINTAB motion: %d %g,%g %g %g,%g\n",
01176                                   event->motion.deviceid,
01177                                   event->motion.x, event->motion.y,
01178                                   event->motion.pressure,
01179                                   event->motion.xtilt,
01180                                   event->motion.ytilt));
01181 
01182          /* Check for missing release or press events for the normal
01183           * pressure button. At least on my ArtPadII I sometimes miss a
01184           * release event?
01185           */
01186          if ((gdkdev->pktdata & PK_NORMAL_PRESSURE
01187               && (event->motion.state & GDK_BUTTON1_MASK)
01188               && packet.pkNormalPressure <= MAX(0,
01189                                                 gdkdev->npbtnmarks[0] - 2))
01190              || (gdkdev->pktdata & PK_NORMAL_PRESSURE
01191                  && !(event->motion.state & GDK_BUTTON1_MASK)
01192                  && packet.pkNormalPressure > gdkdev->npbtnmarks[1] + 2)) {
01193             GdkEvent *event2 = gdk_event_copy(event);
01194             if (event->motion.state & GDK_BUTTON1_MASK) {
01195                event2->button.type = GDK_BUTTON_RELEASE;
01196                gdkdev->button_state &= ~1;
01197             } else {
01198                event2->button.type = GDK_BUTTON_PRESS;
01199                gdkdev->button_state |= 1;
01200             }
01201             event2->button.state = ((gdkdev->button_state << 8)
01202                                     & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
01203                                        | GDK_BUTTON3_MASK |
01204                                        GDK_BUTTON4_MASK |
01205                                        GDK_BUTTON5_MASK));
01206             event2->button.button = 1;
01207             GDK_NOTE(EVENTS,
01208                      g_print
01209                      ("WINTAB synthesized button %s: %d %d %g,%g %g\n",
01210                       (event2->button.type ==
01211                        GDK_BUTTON_PRESS ? "press" : "release"),
01212                       event2->button.deviceid, event2->button.button,
01213                       event2->button.x, event2->button.y,
01214                       event2->button.pressure));
01215             gdk_event_queue_append(event2);
01216          }
01217       }
01218       return TRUE;
01219 
01220    case WT_PROXIMITY:
01221       if (LOWORD(xevent->lParam) == 0) {
01222          event->proximity.type = GDK_PROXIMITY_OUT;
01223          gdk_input_ignore_core = FALSE;
01224       } else {
01225          event->proximity.type = GDK_PROXIMITY_IN;
01226          gdk_input_ignore_core = TRUE;
01227       }
01228       event->proximity.time = xevent->time;
01229       event->proximity.source = GDK_SOURCE_PEN;
01230       event->proximity.deviceid = last_moved_cursor_id;
01231 
01232       GDK_NOTE(EVENTS, g_print("WINTAB proximity %s: %d\n",
01233                                (event->proximity.type == GDK_PROXIMITY_IN ?
01234                                 "in" : "out"), event->proximity.deviceid));
01235       return TRUE;
01236    }
01237    return FALSE;
01238 }
01239 
01240 static gint
01241 gdk_input_win32_enable_window(GdkWindow * window,
01242                               GdkDevicePrivate * gdkdev)
01243 {
01244    GDK_WINDOW_WIN32DATA(window)->extension_events_selected = TRUE;
01245    return TRUE;
01246 }
01247 
01248 static gint
01249 gdk_input_win32_disable_window(GdkWindow * window,
01250                                GdkDevicePrivate * gdkdev)
01251 {
01252    GDK_WINDOW_WIN32DATA(window)->extension_events_selected = FALSE;
01253    return TRUE;
01254 }
01255 
01256 static gint
01257 gdk_input_win32_grab_pointer(GdkWindow * window,
01258                              gint owner_events,
01259                              GdkEventMask event_mask,
01260                              GdkWindow * confine_to, guint32 time)
01261 {
01262    GdkInputWindow *input_window, *new_window;
01263    gboolean need_ungrab;
01264    GdkDevicePrivate *gdkdev;
01265    GList *tmp_list;
01266    gint result;
01267 
01268    tmp_list = gdk_input_windows;
01269    new_window = NULL;
01270    need_ungrab = FALSE;
01271 
01272    GDK_NOTE(MISC, g_print("gdk_input_win32_grab_pointer: %#x %d %#x\n",
01273                           GDK_DRAWABLE_XID(window),
01274                           owner_events,
01275                           (confine_to ? GDK_DRAWABLE_XID(confine_to) :
01276                            0)));
01277 
01278    while (tmp_list) {
01279       input_window = (GdkInputWindow *) tmp_list->data;
01280 
01281       if (input_window->window == window)
01282          new_window = input_window;
01283       else if (input_window->grabbed) {
01284          input_window->grabbed = FALSE;
01285          need_ungrab = TRUE;
01286       }
01287 
01288       tmp_list = tmp_list->next;
01289    }
01290 
01291    if (new_window) {
01292       new_window->grabbed = TRUE;
01293 
01294       tmp_list = gdk_input_devices;
01295       while (tmp_list) {
01296          gdkdev = (GdkDevicePrivate *) tmp_list->data;
01297          if (gdkdev->info.deviceid != GDK_CORE_POINTER) {
01298 #if 0
01299             /* XXX */
01300             gdk_input_find_events(window, gdkdev,
01301                                   event_mask, event_classes, &num_classes);
01302             result = XGrabDevice(GDK_DISPLAY(), gdkdev->xdevice,
01303                                  GDK_WINDOW_XWINDOW(window),
01304                                  owner_events, num_classes, event_classes,
01305                                  GrabModeAsync, GrabModeAsync, time);
01306 
01307             /* FIXME: if failure occurs on something other than the first
01308                device, things will be badly inconsistent */
01309             if (result != Success)
01310                return result;
01311 #endif
01312          }
01313          tmp_list = tmp_list->next;
01314       }
01315    } else {
01316       tmp_list = gdk_input_devices;
01317       while (tmp_list) {
01318          gdkdev = (GdkDevicePrivate *) tmp_list->data;
01319          if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
01320              ((gdkdev->button_state != 0) || need_ungrab)) {
01321 #if 0
01322             /* XXX */
01323             XUngrabDevice(gdk_display, gdkdev->xdevice, time);
01324 #endif
01325             gdkdev->button_state = 0;
01326          }
01327 
01328          tmp_list = tmp_list->next;
01329       }
01330    }
01331 
01332    return Success;
01333 
01334 }
01335 
01336 static void gdk_input_win32_ungrab_pointer(guint32 time)
01337 {
01338    GdkInputWindow *input_window;
01339    GdkDevicePrivate *gdkdev;
01340    GList *tmp_list;
01341 
01342    GDK_NOTE(MISC, g_print("gdk_input_win32_ungrab_pointer\n"));
01343 
01344    tmp_list = gdk_input_windows;
01345    while (tmp_list) {
01346       input_window = (GdkInputWindow *) tmp_list->data;
01347       if (input_window->grabbed)
01348          break;
01349       tmp_list = tmp_list->next;
01350    }
01351 
01352    if (tmp_list) {              /* we found a grabbed window */
01353       input_window->grabbed = FALSE;
01354 
01355       tmp_list = gdk_input_devices;
01356       while (tmp_list) {
01357          gdkdev = (GdkDevicePrivate *) tmp_list->data;
01358 #if 0
01359          /* XXX */
01360          if (gdkdev->info.deviceid != GDK_CORE_POINTER && gdkdev->xdevice)
01361             XUngrabDevice(gdk_display, gdkdev->xdevice, time);
01362 #endif
01363          tmp_list = tmp_list->next;
01364       }
01365    }
01366 }
01367 
01368 #endif                          /* HAVE_WINTAB */
01369 
01370 GList *gdk_input_list_devices(void)
01371 {
01372    return gdk_input_devices;
01373 }
01374 
01375 void gdk_input_set_source(guint32 deviceid, GdkInputSource source)
01376 {
01377    GdkDevicePrivate *gdkdev = gdk_input_find_device(deviceid);
01378    g_return_if_fail(gdkdev != NULL);
01379 
01380    gdkdev->info.source = source;
01381 }
01382 
01383 void gdk_input_set_key(guint32 deviceid,
01384                        guint index,
01385                        guint keyval, GdkModifierType modifiers)
01386 {
01387    if (deviceid != GDK_CORE_POINTER && gdk_input_vtable.set_key)
01388       gdk_input_vtable.set_key(deviceid, index, keyval, modifiers);
01389 }
01390 
01391 GdkTimeCoord *gdk_input_motion_events(GdkWindow * window,
01392                                       guint32 deviceid,
01393                                       guint32 start,
01394                                       guint32 stop, gint * nevents_return)
01395 {
01396    g_return_val_if_fail(window != NULL, NULL);
01397    if (GDK_DRAWABLE_DESTROYED(window))
01398       return NULL;
01399 
01400    *nevents_return = 0;
01401    return NULL;                 /* ??? */
01402 }
01403 
01404 static gint
01405 gdk_input_enable_window(GdkWindow * window, GdkDevicePrivate * gdkdev)
01406 {
01407    if (gdk_input_vtable.enable_window)
01408       return gdk_input_vtable.enable_window(window, gdkdev);
01409    else
01410       return TRUE;
01411 }
01412 
01413 static gint
01414 gdk_input_disable_window(GdkWindow * window, GdkDevicePrivate * gdkdev)
01415 {
01416    if (gdk_input_vtable.disable_window)
01417       return gdk_input_vtable.disable_window(window, gdkdev);
01418    else
01419       return TRUE;
01420 }
01421 
01422 
01423 static GdkInputWindow *gdk_input_window_find(GdkWindow * window)
01424 {
01425    GList *tmp_list;
01426 
01427    for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
01428       if (((GdkInputWindow *) (tmp_list->data))->window == window)
01429          return (GdkInputWindow *) (tmp_list->data);
01430 
01431    return NULL;                 /* Not found */
01432 }
01433 
01434 #if !USE_SYSCONTEXT
01435 
01436 static GdkInputWindow *gdk_input_window_find_within(GdkWindow * window)
01437 {
01438    GList *list;
01439    GdkWindow *tmpw;
01440    GdkInputWindow *candidate = NULL;
01441 
01442    for (list = gdk_input_windows; list != NULL; list = list->next) {
01443       tmpw = ((GdkInputWindow *) (tmp_list->data))->window;
01444       if (tmpw == window
01445           || IsChild(GDK_DRAWABLE_XID(window), GDK_DRAWABLE_XID(tmpw))) {
01446          if (candidate)
01447             return NULL;        /* Multiple hits */
01448          candidate = (GdkInputWindow *) (list->data);
01449       }
01450    }
01451 
01452    return candidate;
01453 }
01454 
01455 #endif
01456 
01457 /* FIXME: this routine currently needs to be called between creation
01458    and the corresponding configure event (because it doesn't get the
01459    root_relative_geometry).  This should work with
01460    gtk_window_set_extension_events, but will likely fail in other
01461    cases */
01462 
01463 void
01464 gdk_input_set_extension_events(GdkWindow * window,
01465                                gint mask, GdkExtensionMode mode)
01466 {
01467    GdkWindowPrivate *window_private;
01468    GList *tmp_list;
01469    GdkInputWindow *iw;
01470 
01471    g_return_if_fail(window != NULL);
01472    if (GDK_DRAWABLE_DESTROYED(window))
01473       return;
01474    window_private = (GdkWindowPrivate *) window;
01475 
01476    if (mode == GDK_EXTENSION_EVENTS_NONE)
01477       mask = 0;
01478 
01479    if (mask != 0) {
01480       iw = g_new(GdkInputWindow, 1);
01481 
01482       iw->window = window;
01483       iw->mode = mode;
01484 
01485       iw->grabbed = FALSE;
01486 
01487       gdk_input_windows = g_list_append(gdk_input_windows, iw);
01488       window_private->extension_events = mask;
01489 
01490       /* Add enter window events to the event mask */
01491       gdk_window_set_events(window,
01492                             gdk_window_get_events(window) |
01493                             GDK_ENTER_NOTIFY_MASK);
01494    } else {
01495       iw = gdk_input_window_find(window);
01496       if (iw) {
01497          gdk_input_windows = g_list_remove(gdk_input_windows, iw);
01498          g_free(iw);
01499       }
01500 
01501       window_private->extension_events = 0;
01502    }
01503 
01504    for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next) {
01505       GdkDevicePrivate *gdkdev = (GdkDevicePrivate *) (tmp_list->data);
01506 
01507       if (gdkdev->info.deviceid != GDK_CORE_POINTER) {
01508          if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
01509              && (gdkdev->info.has_cursor
01510                  || mode == GDK_EXTENSION_EVENTS_ALL))
01511             gdk_input_enable_window(window, gdkdev);
01512          else
01513             gdk_input_disable_window(window, gdkdev);
01514       }
01515    }
01516 }
01517 
01518 void gdk_input_window_destroy(GdkWindow * window)
01519 {
01520    GdkInputWindow *input_window;
01521 
01522    input_window = gdk_input_window_find(window);
01523    g_return_if_fail(input_window != NULL);
01524 
01525    gdk_input_windows = g_list_remove(gdk_input_windows, input_window);
01526    g_free(input_window);
01527 }
01528 
01529 void gdk_input_exit(void)
01530 {
01531 #ifdef HAVE_WINTAB
01532    GList *tmp_list;
01533    GdkDevicePrivate *gdkdev;
01534 
01535    for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next) {
01536       gdkdev = (GdkDevicePrivate *) (tmp_list->data);
01537       if (gdkdev->info.deviceid != GDK_CORE_POINTER) {
01538          gdk_input_win32_set_mode(gdkdev->info.deviceid,
01539                                   GDK_MODE_DISABLED);
01540          g_free(gdkdev->info.name);
01541          g_free(gdkdev->last_axis_data);
01542          g_free(gdkdev->info.axes);
01543          g_free(gdkdev->info.keys);
01544          g_free(gdkdev->axes);
01545          g_free(gdkdev);
01546       }
01547    }
01548 
01549    g_list_free(gdk_input_devices);
01550 
01551    for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next) {
01552       g_free(tmp_list->data);
01553    }
01554    g_list_free(gdk_input_windows);
01555    gdk_input_windows = NULL;
01556 
01557    gdk_window_unref(wintab_window);
01558    wintab_window = NULL;
01559 
01560 #if 1
01561    for (tmp_list = wintab_contexts; tmp_list; tmp_list = tmp_list->next) {
01562       HCTX *hctx = (HCTX *) tmp_list->data;
01563       BOOL result;
01564 
01565 #ifdef _MSC_VER
01566       /* For some reason WTEnable and/or WTClose tend to crash here.
01567        * Protect with __try/__except to avoid a message box.
01568        * When compiling with gcc, we cannot use __try/__except, so
01569        * don't call WTClose. I think this means that we'll
01570        * eventually run out of Wintab contexts, sigh.
01571        */
01572       __try {
01573 #if 0
01574          WTEnable(*hctx, FALSE);
01575 #endif
01576          result = WTClose(*hctx);
01577       }
01578       __except(                 /* GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? */
01579                  EXCEPTION_EXECUTE_HANDLER      /*: 
01580            EXCEPTION_CONTINUE_SEARCH */ ) {
01581          result = FALSE;
01582       }
01583       if (!result)
01584          g_warning("gdk_input_exit: Closing Wintab context %#x failed",
01585                    *hctx);
01586 #endif                          /* _MSC_VER */
01587       g_free(hctx);
01588    }
01589 #endif
01590    g_list_free(wintab_contexts);
01591    wintab_contexts = NULL;
01592 #endif
01593 }
01594 
01595 static GdkDevicePrivate *gdk_input_find_device(guint32 id)
01596 {
01597    GList *tmp_list = gdk_input_devices;
01598    GdkDevicePrivate *gdkdev;
01599 
01600    while (tmp_list) {
01601       gdkdev = (GdkDevicePrivate *) (tmp_list->data);
01602       if (gdkdev->info.deviceid == id)
01603          return gdkdev;
01604       tmp_list = tmp_list->next;
01605    }
01606    return NULL;
01607 }
01608 
01609 void
01610 gdk_input_window_get_pointer(GdkWindow * window,
01611                              guint32 deviceid,
01612                              gdouble * x,
01613                              gdouble * y,
01614                              gdouble * pressure,
01615                              gdouble * xtilt,
01616                              gdouble * ytilt, GdkModifierType * mask)
01617 {
01618    if (gdk_input_vtable.get_pointer)
01619       gdk_input_vtable.get_pointer(window, deviceid, x, y, pressure,
01620                                    xtilt, ytilt, mask);
01621 }

Generated on Tue Jul 5 14:14:40 2011 for ROOT_528-00b_version by  doxygen 1.5.1