janitorial: Remove links to any microsoft site.
[wine] / dlls / winex11.drv / wintab.c
1 /*
2  * X11 tablet driver
3  *
4  * Copyright 2003 CodeWeavers (Aric Stewart)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <stdlib.h>
25 #include <stdarg.h>
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winnls.h"
30 #include "x11drv.h"
31 #include "wine/library.h"
32 #include "wine/unicode.h"
33 #include "wine/debug.h"
34 #include "wintab.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(wintab32);
37
38 #define WT_MAX_NAME_LEN 256
39
40 typedef struct tagWTI_CURSORS_INFO
41 {
42     WCHAR   NAME[WT_MAX_NAME_LEN];
43         /* a displayable zero-terminated string containing the name of the
44          * cursor.
45          */
46     BOOL    ACTIVE;
47         /* whether the cursor is currently connected. */
48     WTPKT   PKTDATA;
49         /* a bit mask indicating the packet data items supported when this
50          * cursor is connected.
51          */
52     BYTE    BUTTONS;
53         /* the number of buttons on this cursor. */
54     BYTE    BUTTONBITS;
55         /* the number of bits of raw button data returned by the hardware.*/
56     DWORD   cchBTNNAMES;
57     WCHAR   *BTNNAMES;
58         /* a list of zero-terminated strings containing the names of the
59          * cursor's buttons. The number of names in the list is the same as the
60          * number of buttons on the cursor. The names are separated by a single
61          * zero character; the list is terminated by two zero characters.
62          */
63     BYTE    BUTTONMAP[32];
64         /* a 32 byte array of logical button numbers, one for each physical
65          * button.
66          */
67     BYTE    SYSBTNMAP[32];
68         /* a 32 byte array of button action codes, one for each logical
69          * button.
70          */
71     BYTE    NPBUTTON;
72         /* the physical button number of the button that is controlled by normal
73          * pressure.
74          */
75     UINT    NPBTNMARKS[2];
76         /* an array of two UINTs, specifying the button marks for the normal
77          * pressure button. The first UINT contains the release mark; the second
78          * contains the press mark.
79          */
80     UINT    *NPRESPONSE;
81         /* an array of UINTs describing the pressure response curve for normal
82          * pressure.
83          */
84     BYTE    TPBUTTON;
85         /* the physical button number of the button that is controlled by
86          * tangential pressure.
87          */
88     UINT    TPBTNMARKS[2];
89         /* an array of two UINTs, specifying the button marks for the tangential
90          * pressure button. The first UINT contains the release mark; the second
91          * contains the press mark.
92          */
93     UINT    *TPRESPONSE;
94         /* an array of UINTs describing the pressure response curve for
95          * tangential pressure.
96          */
97     DWORD   PHYSID;
98          /* a manufacturer-specific physical identifier for the cursor. This
99           * value will distinguish the physical cursor from others on the same
100           * device. This physical identifier allows applications to bind
101           * functions to specific physical cursors, even if category numbers
102           * change and multiple, otherwise identical, physical cursors are
103           * present.
104           */
105     UINT    MODE;
106         /* the cursor mode number of this cursor type, if this cursor type has
107          * the CRC_MULTIMODE capability.
108          */
109     UINT    MINPKTDATA;
110         /* the minimum set of data available from a physical cursor in this
111          * cursor type, if this cursor type has the CRC_AGGREGATE capability.
112          */
113     UINT    MINBUTTONS;
114         /* the minimum number of buttons of physical cursors in the cursor type,
115          * if this cursor type has the CRC_AGGREGATE capability.
116          */
117     UINT    CAPABILITIES;
118         /* flags indicating cursor capabilities, as defined below:
119             CRC_MULTIMODE
120                 Indicates this cursor type describes one of several modes of a
121                 single physical cursor. Consecutive cursor type categories
122                 describe the modes; the CSR_MODE data item gives the mode number
123                 of each cursor type.
124             CRC_AGGREGATE
125                 Indicates this cursor type describes several physical cursors
126                 that cannot be distinguished by software.
127             CRC_INVERT
128                 Indicates this cursor type describes the physical cursor in its
129                 inverted orientation; the previous consecutive cursor type
130                 category describes the normal orientation.
131          */
132     UINT    TYPE;
133         /* Manufacturer Unique id for the item type */
134 } WTI_CURSORS_INFO, *LPWTI_CURSORS_INFO;
135
136
137 typedef struct tagWTI_DEVICES_INFO
138 {
139     WCHAR   NAME[WT_MAX_NAME_LEN];
140         /* a displayable null- terminated string describing the device,
141          * manufacturer, and revision level.
142          */
143     UINT    HARDWARE;
144         /* flags indicating hardware and driver capabilities, as defined
145          * below:
146             HWC_INTEGRATED:
147                 Indicates that the display and digitizer share the same surface.
148             HWC_TOUCH
149                 Indicates that the cursor must be in physical contact with the
150                 device to report position.
151             HWC_HARDPROX
152                 Indicates that device can generate events when the cursor is
153                 entering and leaving the physical detection range.
154             HWC_PHYSID_CURSORS
155                 Indicates that device can uniquely identify the active cursor in
156                 hardware.
157          */
158     UINT    NCSRTYPES;
159         /* the number of supported cursor types.*/
160     UINT    FIRSTCSR;
161         /* the first cursor type number for the device. */
162     UINT    PKTRATE;
163         /* the maximum packet report rate in Hertz. */
164     WTPKT   PKTDATA;
165         /* a bit mask indicating which packet data items are always available.*/
166     WTPKT   PKTMODE;
167         /* a bit mask indicating which packet data items are physically
168          * relative, i.e., items for which the hardware can only report change,
169          * not absolute measurement.
170          */
171     WTPKT   CSRDATA;
172         /* a bit mask indicating which packet data items are only available when
173          * certain cursors are connected. The individual cursor descriptions
174          * must be consulted to determine which cursors return which data.
175          */
176     INT     XMARGIN;
177     INT     YMARGIN;
178     INT     ZMARGIN;
179         /* the size of tablet context margins in tablet native coordinates, in
180          * the x, y, and z directions, respectively.
181          */
182     AXIS    X;
183     AXIS    Y;
184     AXIS    Z;
185         /* the tablet's range and resolution capabilities, in the x, y, and z
186          * axes, respectively.
187          */
188     AXIS    NPRESSURE;
189     AXIS    TPRESSURE;
190         /* the tablet's range and resolution capabilities, for the normal and
191          * tangential pressure inputs, respectively.
192          */
193     AXIS    ORIENTATION[3];
194         /* a 3-element array describing the tablet's orientation range and
195          * resolution capabilities.
196          */
197     AXIS    ROTATION[3];
198         /* a 3-element array describing the tablet's rotation range and
199          * resolution capabilities.
200          */
201     WCHAR   PNPID[WT_MAX_NAME_LEN];
202         /* a null-terminated string containing the devices Plug and Play ID.*/
203 }   WTI_DEVICES_INFO, *LPWTI_DEVICES_INFO;
204
205
206 /***********************************************************************
207  * WACOM WINTAB EXTENSIONS TO SUPPORT CSR_TYPE
208  *   In Wintab 1.2, a CSR_TYPE feature was added.  This adds the
209  *   ability to return a type of cursor on a tablet.
210  *   Unfortunately, we cannot get the cursor type directly from X,
211  *   and it is not specified directly anywhere.  So we virtualize
212  *   the type here.  (This is unfortunate, the kernel module has
213  *   the exact type, but we have no way of getting that module to
214  *   pass us that type).
215  */
216
217 #define CSR_TYPE_PEN        0x822
218 #define CSR_TYPE_ERASER     0x82a
219 #define CSR_TYPE_MOUSE_2D   0x007
220 #define CSR_TYPE_MOUSE_4D   0x094
221
222
223 typedef struct tagWTPACKET {
224         HCTX pkContext;
225         UINT pkStatus;
226         LONG pkTime;
227         WTPKT pkChanged;
228         UINT pkSerialNumber;
229         UINT pkCursor;
230         DWORD pkButtons;
231         DWORD pkX;
232         DWORD pkY;
233         DWORD pkZ;
234         UINT pkNormalPressure;
235         UINT pkTangentPressure;
236         ORIENTATION pkOrientation;
237         ROTATION pkRotation; /* 1.1 */
238 } WTPACKET, *LPWTPACKET;
239
240
241 #ifdef SONAME_LIBXI
242
243 #include <X11/Xlib.h>
244 #include <X11/extensions/XInput.h>
245
246 static int           motion_type;
247 static int           button_press_type;
248 static int           button_release_type;
249 static int           key_press_type;
250 static int           key_release_type;
251 static int           proximity_in_type;
252 static int           proximity_out_type;
253
254 static HWND          hwndTabletDefault;
255 static WTPACKET      gMsgPacket;
256 static DWORD         gSerial;
257 static INT           button_state[10];
258
259 #define             CURSORMAX 10
260
261 static LOGCONTEXTW      gSysContext;
262 static WTI_DEVICES_INFO gSysDevice;
263 static WTI_CURSORS_INFO gSysCursor[CURSORMAX];
264 static INT              gNumCursors;
265
266
267 /* XInput stuff */
268 static void *xinput_handle;
269
270 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
271 MAKE_FUNCPTR(XListInputDevices)
272 MAKE_FUNCPTR(XFreeDeviceList)
273 MAKE_FUNCPTR(XOpenDevice)
274 MAKE_FUNCPTR(XQueryDeviceState)
275 MAKE_FUNCPTR(XGetDeviceButtonMapping)
276 MAKE_FUNCPTR(XCloseDevice)
277 MAKE_FUNCPTR(XSelectExtensionEvent)
278 MAKE_FUNCPTR(XFreeDeviceState)
279 #undef MAKE_FUNCPTR
280
281 static INT X11DRV_XInput_Init(void)
282 {
283     xinput_handle = wine_dlopen(SONAME_LIBXI, RTLD_NOW, NULL, 0);
284     if (xinput_handle)
285     {
286 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xinput_handle, #f, NULL, 0)) == NULL) goto sym_not_found;
287         LOAD_FUNCPTR(XListInputDevices)
288         LOAD_FUNCPTR(XFreeDeviceList)
289         LOAD_FUNCPTR(XOpenDevice)
290         LOAD_FUNCPTR(XGetDeviceButtonMapping)
291         LOAD_FUNCPTR(XCloseDevice)
292         LOAD_FUNCPTR(XSelectExtensionEvent)
293         LOAD_FUNCPTR(XQueryDeviceState)
294         LOAD_FUNCPTR(XFreeDeviceState)
295 #undef LOAD_FUNCPTR
296         return 1;
297     }
298 sym_not_found:
299     return 0;
300 }
301
302 static int Tablet_ErrorHandler(Display *dpy, XErrorEvent *event, void* arg)
303 {
304     return 1;
305 }
306
307 static int find_cursor_by_type(int cursor_type, int exclude)
308 {
309     int i;
310     for (i = 0; i < gNumCursors; i++)
311         if (i != exclude)
312             if (gSysCursor[i].TYPE == cursor_type)
313                 return i;
314
315     return -1;
316 }
317
318 static void swap_cursors(int a, int b)
319 {
320     WTI_CURSORS_INFO temp;
321     temp = gSysCursor[a];
322     gSysCursor[a] = gSysCursor[b];
323     gSysCursor[b] = temp;
324 }
325
326 /* Adobe Photoshop 7.0 relies on the eraser being cursor #2 or #5, and it assumes the stylus is 1.
327 **   If the X configuration is not set up that way, make it
328 */
329 static void Tablet_FixupCursors(void)
330 {
331     if (gNumCursors >= 1)
332         if (gSysCursor[1].TYPE != CSR_TYPE_PEN)
333         {
334             int stylus;
335             stylus = find_cursor_by_type(CSR_TYPE_PEN, 1);
336             if (stylus >= 0)
337             {
338                 swap_cursors(1, stylus);
339                 TRACE("Swapped cursor %d with stylus slot (1) for compatibility with older programs\n", stylus);
340             }
341         }
342
343     if (gNumCursors >= 2)
344         if (gSysCursor[2].TYPE != CSR_TYPE_ERASER)
345         {
346             int eraser;
347             eraser = find_cursor_by_type(CSR_TYPE_ERASER, 2);
348             if (eraser >= 0)
349             {
350                 swap_cursors(2, eraser);
351                 TRACE("Swapped cursor %d with eraser slot (2) for compatibility with older programs\n", eraser);
352             }
353         }
354 }
355
356 static void trace_axes(XValuatorInfoPtr val)
357 {
358     int i;
359     XAxisInfoPtr axis;
360
361     for (i = 0, axis = val->axes ; i < val->num_axes; i++, axis++)
362         TRACE("        Axis %d: [resolution %d|min_value %d|max_value %d]\n", i, axis->resolution, axis->min_value, axis->max_value);
363 }
364
365 BOOL match_token(const char *haystack, const char *needle)
366 {
367     const char *p, *q;
368     for (p = haystack; *p; )
369     {
370         while (*p && isspace(*p))
371             p++;
372         if (! *p)
373             break;
374
375         for (q = needle; *q && *p && tolower(*p) == tolower(*q); q++)
376             p++;
377         if (! *q && (isspace(*p) || !*p))
378             return TRUE;
379
380         while (*p && ! isspace(*p))
381             p++;
382     }
383     return FALSE;
384 }
385
386 /*    Determining if an X device is a Tablet style device is an imperfect science.
387 **  We rely on common conventions around device names as well as the type reported
388 **  by Wacom tablets.  This code will likely need to be expanded for alternate tablet types
389 */
390
391 #define IS_TABLET_CURSOR(n, t)   (is_wacom((n), (t)) || is_cursor((n), (t)) || is_stylus((n), (t)) || is_eraser((n), (t)) || is_pad((n), (t)))
392
393 static BOOL is_wacom(const char *name, const char *type)
394 {
395     if (name && match_token(name, "wacom"))
396         return TRUE;
397     if (type && match_token(type, "wacom"))
398         return TRUE;
399     return FALSE;
400 }
401
402 static BOOL is_cursor(const char *name, const char *type)
403 {
404     if (name && match_token(name, "cursor"))
405         return TRUE;
406     if (type && match_token(type, "cursor"))
407         return TRUE;
408     return FALSE;
409 }
410
411 static BOOL is_stylus(const char *name, const char *type)
412 {
413     if (name && match_token(name, "stylus"))
414         return TRUE;
415     if (type && match_token(type, "stylus"))
416         return TRUE;
417     return FALSE;
418 }
419
420 static BOOL is_eraser(const char *name, const char *type)
421 {
422     if (name && match_token(name, "eraser"))
423         return TRUE;
424     if (type && match_token(type, "eraser"))
425         return TRUE;
426     return FALSE;
427 }
428
429 static BOOL is_pad(const char *name, const char *type)
430 {
431     if (name && match_token(name, "pad"))
432         return TRUE;
433     if (type && match_token(type, "pad"))
434         return TRUE;
435     return FALSE;
436 }
437
438
439 /***********************************************************************
440  *             X11DRV_LoadTabletInfo (X11DRV.@)
441  */
442 void X11DRV_LoadTabletInfo(HWND hwnddefault)
443 {
444     const WCHAR SZ_CONTEXT_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','C','o','n','t','e','x','t',0};
445     const WCHAR SZ_DEVICE_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','D','e','v','i','c','e',0};
446     const WCHAR SZ_NON_PLUGINPLAY[] = {'n','o','n','-','p','l','u','g','i','n','p','l','a','y',0};
447
448     struct x11drv_thread_data *data = x11drv_thread_data();
449     int num_devices;
450     int loop;
451     int cursor_target;
452     XDeviceInfo *devices;
453     XDeviceInfo *target = NULL;
454     BOOL    axis_read_complete= FALSE;
455
456     XAnyClassPtr        any;
457     XButtonInfoPtr      Button;
458     XValuatorInfoPtr    Val;
459     XAxisInfoPtr        Axis;
460
461     XDevice *opendevice;
462
463     if (!X11DRV_XInput_Init())
464     {
465         ERR("Unable to initialize the XInput library.\n");
466         return;
467     }
468
469     hwndTabletDefault = hwnddefault;
470
471     /* Do base initialization */
472     strcpyW(gSysContext.lcName, SZ_CONTEXT_NAME);
473     strcpyW(gSysDevice.NAME, SZ_DEVICE_NAME);
474
475     gSysContext.lcOptions = CXO_SYSTEM;
476     gSysContext.lcLocks = CXL_INSIZE | CXL_INASPECT | CXL_MARGIN |
477                                CXL_SENSITIVITY | CXL_SYSOUT;
478
479     gSysContext.lcMsgBase= WT_DEFBASE;
480     gSysContext.lcDevice = 0;
481     gSysContext.lcPktData =
482         PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
483         PK_BUTTONS |  PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
484     gSysContext.lcMoveMask=
485         PK_BUTTONS |  PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
486     gSysContext.lcStatus = CXS_ONTOP;
487     gSysContext.lcPktRate = 100;
488     gSysContext.lcBtnDnMask = 0xffffffff;
489     gSysContext.lcBtnUpMask = 0xffffffff;
490     gSysContext.lcSensX = 65536;
491     gSysContext.lcSensY = 65536;
492     gSysContext.lcSensX = 65536;
493     gSysContext.lcSensZ = 65536;
494     gSysContext.lcSysSensX= 65536;
495     gSysContext.lcSysSensY= 65536;
496
497     /* Device Defaults */
498     gSysDevice.HARDWARE = HWC_HARDPROX|HWC_PHYSID_CURSORS;
499     gSysDevice.FIRSTCSR= 0;
500     gSysDevice.PKTRATE = 100;
501     gSysDevice.PKTDATA =
502         PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
503         PK_BUTTONS |  PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
504     strcpyW(gSysDevice.PNPID, SZ_NON_PLUGINPLAY);
505
506     wine_tsx11_lock();
507
508     cursor_target = -1;
509     devices = pXListInputDevices(data->display, &num_devices);
510     if (!devices)
511     {
512         WARN("XInput Extensions reported as not avalable\n");
513         wine_tsx11_unlock();
514         return;
515     }
516     TRACE("XListInputDevices reports %d devices\n", num_devices);
517     for (loop=0; loop < num_devices; loop++)
518     {
519         int class_loop;
520         char *device_type = devices[loop].type ? XGetAtomName(data->display, devices[loop].type) : NULL;
521
522         TRACE("Device %i:  [id %d|name %s|type %s|num_classes %d|use %s]\n",
523                 loop, (int) devices[loop].id, devices[loop].name, device_type ? device_type : "",
524                 devices[loop].num_classes,
525                 devices[loop].use == IsXKeyboard ? "IsXKeyboard" :
526                     devices[loop].use == IsXPointer ? "IsXPointer" :
527                     devices[loop].use == IsXExtensionDevice ? "IsXExtensionDevice" :
528                     "Unknown"
529                 );
530
531         if (devices[loop].use == IsXExtensionDevice)
532         {
533             LPWTI_CURSORS_INFO cursor;
534
535             TRACE("Is Extension Device\n");
536             cursor_target++;
537             target = &devices[loop];
538             cursor = &gSysCursor[cursor_target];
539
540             if (strlen(target->name) >= WT_MAX_NAME_LEN)
541             {
542                 ERR("Input device '%s' name too long - skipping\n", wine_dbgstr_a(target->name));
543                 cursor_target--;
544                 XFree(device_type);
545                 continue;
546             }
547
548             X11DRV_expect_error(data->display, Tablet_ErrorHandler, NULL);
549             opendevice = pXOpenDevice(data->display,target->id);
550             if (!X11DRV_check_error() && opendevice)
551             {
552                 unsigned char map[32];
553                 int i;
554                 int shft = 0;
555
556                 X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
557                 cursor->BUTTONS = pXGetDeviceButtonMapping(data->display, opendevice, map, 32);
558                 if (X11DRV_check_error() || cursor->BUTTONS <= 0)
559                 {
560                     TRACE("No buttons, Non Tablet Device\n");
561                     pXCloseDevice(data->display, opendevice);
562                     cursor_target --;
563                     XFree(device_type);
564                     continue;
565                 }
566
567                 for (i=0; i< cursor->BUTTONS; i++,shft++)
568                 {
569                     cursor->BUTTONMAP[i] = map[i];
570                     cursor->SYSBTNMAP[i] = (1<<shft);
571                 }
572                 pXCloseDevice(data->display, opendevice);
573             }
574             else
575             {
576                 WARN("Unable to open device %s\n",target->name);
577                 cursor_target --;
578                 XFree(device_type);
579                 continue;
580             }
581             MultiByteToWideChar(CP_UNIXCP, 0, target->name, -1, cursor->NAME, WT_MAX_NAME_LEN);
582
583             if (! IS_TABLET_CURSOR(target->name, device_type))
584             {
585                 WARN("Skipping device %d [name %s|type %s]; not apparently a tablet cursor type device\n",
586                      loop, devices[loop].name, device_type ? device_type : "");
587                 XFree(device_type);
588                 cursor_target --;
589                 continue;
590             }
591
592             cursor->ACTIVE = 1;
593             cursor->PKTDATA = PK_TIME | PK_CURSOR | PK_BUTTONS |  PK_X | PK_Y |
594                               PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE |
595                               PK_ORIENTATION;
596
597             cursor->PHYSID = target->id;
598             cursor->NPBUTTON = 1;
599             cursor->NPBTNMARKS[0] = 0 ;
600             cursor->NPBTNMARKS[1] = 1 ;
601             cursor->CAPABILITIES = CRC_MULTIMODE;
602             if (is_stylus(target->name, device_type))
603                 cursor->TYPE = CSR_TYPE_PEN;
604             if (is_eraser(target->name, device_type))
605                 cursor->TYPE = CSR_TYPE_ERASER;
606
607
608             any = target->inputclassinfo;
609
610             for (class_loop = 0; class_loop < target->num_classes; class_loop++)
611             {
612                 switch (any->class)
613                 {
614
615                     case ValuatorClass:
616                         Val = (XValuatorInfoPtr) any;
617                         TRACE("    ValidatorInput %d: [class %d|length %d|num_axes %d|mode %d|motion_buffer %ld]\n",
618                                 class_loop, (int) Val->class, Val->length, Val->num_axes, Val->mode, Val->motion_buffer);
619                         if (TRACE_ON(wintab32))
620                             trace_axes(Val);
621
622                         /* FIXME:  This is imperfect; we compute our devices capabilities based upon the
623                         **         first pen type device we find.  However, a more correct implementation
624                         **         would require acquiring a wide variety of tablets and running through
625                         **         the various inputs to see what the values are.  Odds are that a
626                         **         more 'correct' algorithm would condense to this one anyway.
627                         */
628                         if (!axis_read_complete && Val->num_axes >= 5 && cursor->TYPE == CSR_TYPE_PEN)
629                         {
630                             Axis = (XAxisInfoPtr) ((char *) Val + sizeof
631                                 (XValuatorInfo));
632
633                             if (Val->num_axes>=1)
634                             {
635                                 /* Axis 1 is X */
636                                 gSysDevice.X.axMin = Axis->min_value;
637                                 gSysDevice.X.axMax= Axis->max_value;
638                                 gSysDevice.X.axUnits = TU_INCHES;
639                                 gSysDevice.X.axResolution = Axis->resolution;
640                                 gSysContext.lcInOrgX = Axis->min_value;
641                                 gSysContext.lcSysOrgX = Axis->min_value;
642                                 gSysContext.lcInExtX = Axis->max_value;
643                                 gSysContext.lcSysExtX = Axis->max_value;
644                                 Axis++;
645                             }
646                             if (Val->num_axes>=2)
647                             {
648                                 /* Axis 2 is Y */
649                                 gSysDevice.Y.axMin = Axis->min_value;
650                                 gSysDevice.Y.axMax= Axis->max_value;
651                                 gSysDevice.Y.axUnits = TU_INCHES;
652                                 gSysDevice.Y.axResolution = Axis->resolution;
653                                 gSysContext.lcInOrgY = Axis->min_value;
654                                 gSysContext.lcSysOrgY = Axis->min_value;
655                                 gSysContext.lcInExtY = Axis->max_value;
656                                 gSysContext.lcSysExtY = Axis->max_value;
657                                 Axis++;
658                             }
659                             if (Val->num_axes>=3)
660                             {
661                                 /* Axis 3 is Normal Pressure */
662                                 gSysDevice.NPRESSURE.axMin = Axis->min_value;
663                                 gSysDevice.NPRESSURE.axMax= Axis->max_value;
664                                 gSysDevice.NPRESSURE.axUnits = TU_INCHES;
665                                 gSysDevice.NPRESSURE.axResolution =
666                                                         Axis->resolution;
667                                 Axis++;
668                             }
669                             if (Val->num_axes >= 5)
670                             {
671                                 /* Axis 4 and 5 are X and Y tilt */
672                                 XAxisInfoPtr        XAxis = Axis;
673                                 Axis++;
674                                 if (max (abs(Axis->max_value),
675                                          abs(XAxis->max_value)))
676                                 {
677                                     gSysDevice.ORIENTATION[0].axMin = 0;
678                                     gSysDevice.ORIENTATION[0].axMax = 3600;
679                                     gSysDevice.ORIENTATION[0].axUnits = TU_CIRCLE;
680                                     gSysDevice.ORIENTATION[0].axResolution
681                                                                 = CASTFIX32(3600);
682                                     gSysDevice.ORIENTATION[1].axMin = -1000;
683                                     gSysDevice.ORIENTATION[1].axMax = 1000;
684                                     gSysDevice.ORIENTATION[1].axUnits = TU_CIRCLE;
685                                     gSysDevice.ORIENTATION[1].axResolution
686                                                                 = CASTFIX32(3600);
687                                     Axis++;
688                                 }
689                             }
690                             axis_read_complete = TRUE;
691                         }
692                         break;
693                     case ButtonClass:
694                     {
695                         int cchBuf = 512;
696                         int cchPos = 0;
697                         int i;
698
699                         Button = (XButtonInfoPtr) any;
700                         TRACE("    ButtonInput %d: [class %d|length %d|num_buttons %d]\n",
701                                 class_loop, (int) Button->class, Button->length, Button->num_buttons);
702                         cursor->BTNNAMES = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*cchBuf);
703                         for (i = 0; i < cursor->BUTTONS; i++)
704                         {
705                             /* FIXME - these names are probably incorrect */
706                             int cch = strlenW(cursor->NAME) + 1;
707                             while (cch > cchBuf - cchPos - 1) /* we want one extra byte for the last NUL */
708                             {
709                                 cchBuf *= 2;
710                                 cursor->BTNNAMES = HeapReAlloc(GetProcessHeap(), 0, cursor->BTNNAMES, sizeof(WCHAR)*cchBuf);
711                             }
712
713                             strcpyW(cursor->BTNNAMES + cchPos, cursor->NAME);
714                             cchPos += cch;
715                         }
716                         cursor->BTNNAMES[cchPos++] = 0;
717                         cursor->BTNNAMES = HeapReAlloc(GetProcessHeap(), 0, cursor->BTNNAMES, sizeof(WCHAR)*cchPos);
718                         cursor->cchBTNNAMES = cchPos;
719                     }
720                     break;
721                 }
722                 any = (XAnyClassPtr) ((char*) any + any->length);
723             }
724         }
725
726         XFree(device_type);
727
728     }
729     pXFreeDeviceList(devices);
730
731     if (axis_read_complete)
732     {
733         gSysDevice.NCSRTYPES = cursor_target+1;
734         gNumCursors = cursor_target+1;
735         Tablet_FixupCursors();
736     }
737     else
738         WARN("Did not find a valid stylus cursor with >= 5 axes, returning 0 valid devices.\n");
739
740     wine_tsx11_unlock();
741 }
742
743 static int figure_deg(int x, int y)
744 {
745     int rc;
746
747     if (y != 0)
748     {
749         rc = (int) 10 * (atan( (FLOAT)abs(y) / (FLOAT)abs(x)) / (3.1415 / 180));
750         if (y>0)
751         {
752             if (x>0)
753                 rc += 900;
754             else
755                 rc = 2700 - rc;
756         }
757         else
758         {
759             if (x>0)
760                 rc = 900 - rc;
761             else
762                 rc += 2700;
763         }
764     }
765     else
766     {
767         if (x >= 0)
768             rc = 900;
769         else
770             rc = 2700;
771     }
772
773     return rc;
774 }
775
776 static int get_button_state(int curnum)
777 {
778     return button_state[curnum];
779 }
780
781 static void set_button_state(int curnum, XID deviceid)
782 {
783     struct x11drv_thread_data *data = x11drv_thread_data();
784     XDevice *device;
785     XDeviceState *state;
786     XInputClass  *class;
787     int loop;
788     int rc = 0;
789
790     wine_tsx11_lock();
791     device = pXOpenDevice(data->display,deviceid);
792     state = pXQueryDeviceState(data->display,device);
793
794     if (state)
795     {
796         class = state->data;
797         for (loop = 0; loop < state->num_classes; loop++)
798         {
799             if (class->class == ButtonClass)
800             {
801                 int loop2;
802                 XButtonState *button_state =  (XButtonState*)class;
803                 for (loop2 = 0; loop2 < button_state->num_buttons; loop2++)
804                 {
805                     if (button_state->buttons[loop2 / 8] & (1 << (loop2 % 8)))
806                     {
807                         rc |= (1<<loop2);
808                     }
809                 }
810             }
811             class = (XInputClass *) ((char *) class + class->length);
812         }
813     }
814     pXFreeDeviceState(state);
815     wine_tsx11_unlock();
816     button_state[curnum] = rc;
817 }
818
819 static int cursor_from_device(DWORD deviceid, LPWTI_CURSORS_INFO *cursorp)
820 {
821     int i;
822     for (i = 0; i < gNumCursors; i++)
823         if (gSysCursor[i].PHYSID == deviceid)
824         {
825             *cursorp = &gSysCursor[i];
826             return i;
827         }
828
829     ERR("Could not map device id %d to a cursor\n", (int) deviceid);
830     return -1;
831 }
832
833 static void motion_event( HWND hwnd, XEvent *event )
834 {
835     XDeviceMotionEvent *motion = (XDeviceMotionEvent *)event;
836     LPWTI_CURSORS_INFO cursor;
837     int curnum = cursor_from_device(motion->deviceid, &cursor);
838     if (curnum < 0)
839         return;
840
841     memset(&gMsgPacket,0,sizeof(WTPACKET));
842
843     TRACE("Received tablet motion event (%p); device id %d, cursor num %d\n",hwnd, (int) motion->deviceid, curnum);
844
845     /* Set cursor to inverted if cursor is the eraser */
846     gMsgPacket.pkStatus = (cursor->TYPE  == CSR_TYPE_ERASER ? TPS_INVERT:0);
847     gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(motion->time);
848     gMsgPacket.pkSerialNumber = gSerial++;
849     gMsgPacket.pkCursor = curnum;
850     gMsgPacket.pkX = motion->axis_data[0];
851     gMsgPacket.pkY = motion->axis_data[1];
852     gMsgPacket.pkOrientation.orAzimuth = figure_deg(motion->axis_data[3],motion->axis_data[4]);
853     gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max
854                                             (abs(motion->axis_data[3]),
855                                              abs(motion->axis_data[4])))
856                                            * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
857     gMsgPacket.pkNormalPressure = motion->axis_data[2];
858     gMsgPacket.pkButtons = get_button_state(curnum);
859     SendMessageW(hwndTabletDefault,WT_PACKET,0,(LPARAM)hwnd);
860 }
861
862 static void button_event( HWND hwnd, XEvent *event )
863 {
864     XDeviceButtonEvent *button = (XDeviceButtonEvent *) event;
865     LPWTI_CURSORS_INFO cursor;
866     int curnum = cursor_from_device(button->deviceid, &cursor);
867     if (curnum < 0)
868         return;
869
870     memset(&gMsgPacket,0,sizeof(WTPACKET));
871
872     TRACE("Received tablet button %s event\n", (event->type == button_press_type)?"press":"release");
873
874     /* Set cursor to inverted if cursor is the eraser */
875     gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
876     set_button_state(curnum, button->deviceid);
877     gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(button->time);
878     gMsgPacket.pkSerialNumber = gSerial++;
879     gMsgPacket.pkCursor = curnum;
880     gMsgPacket.pkX = button->axis_data[0];
881     gMsgPacket.pkY = button->axis_data[1];
882     gMsgPacket.pkOrientation.orAzimuth = figure_deg(button->axis_data[3],button->axis_data[4]);
883     gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(button->axis_data[3]),
884                                                             abs(button->axis_data[4])))
885                                            * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
886     gMsgPacket.pkNormalPressure = button->axis_data[2];
887     gMsgPacket.pkButtons = get_button_state(curnum);
888     SendMessageW(hwndTabletDefault,WT_PACKET,0,(LPARAM)hwnd);
889 }
890
891 static void key_event( HWND hwnd, XEvent *event )
892 {
893     if (event->type == key_press_type)
894         FIXME("Received tablet key press event\n");
895     else
896         FIXME("Received tablet key release event\n");
897 }
898
899 static void proximity_event( HWND hwnd, XEvent *event )
900 {
901     XProximityNotifyEvent *proximity = (XProximityNotifyEvent *) event;
902     LPWTI_CURSORS_INFO cursor;
903     int curnum = cursor_from_device(proximity->deviceid, &cursor);
904     if (curnum < 0)
905         return;
906
907     memset(&gMsgPacket,0,sizeof(WTPACKET));
908
909     TRACE("Received tablet proximity event\n");
910     /* Set cursor to inverted if cursor is the eraser */
911     gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
912     gMsgPacket.pkStatus |= (event->type==proximity_out_type)?TPS_PROXIMITY:0;
913     gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(proximity->time);
914     gMsgPacket.pkSerialNumber = gSerial++;
915     gMsgPacket.pkCursor = curnum;
916     gMsgPacket.pkX = proximity->axis_data[0];
917     gMsgPacket.pkY = proximity->axis_data[1];
918     gMsgPacket.pkOrientation.orAzimuth = figure_deg(proximity->axis_data[3],proximity->axis_data[4]);
919     gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(proximity->axis_data[3]),
920                                                             abs(proximity->axis_data[4])))
921                                            * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
922     gMsgPacket.pkNormalPressure = proximity->axis_data[2];
923     gMsgPacket.pkButtons = get_button_state(curnum);
924
925     SendMessageW(hwndTabletDefault, WT_PROXIMITY, (event->type == proximity_in_type), (LPARAM)hwnd);
926 }
927
928 /***********************************************************************
929  *              X11DRV_AttachEventQueueToTablet (X11DRV.@)
930  */
931 int X11DRV_AttachEventQueueToTablet(HWND hOwner)
932 {
933     struct x11drv_thread_data *data = x11drv_thread_data();
934     int             num_devices;
935     int             loop;
936     int             cur_loop;
937     XDeviceInfo     *devices;
938     XDeviceInfo     *target = NULL;
939     XDevice         *the_device;
940     XEventClass     event_list[7];
941     Window          win = X11DRV_get_whole_window( hOwner );
942
943     if (!win) return 0;
944
945     TRACE("Creating context for window %p (%lx)  %i cursors\n", hOwner, win, gNumCursors);
946
947     wine_tsx11_lock();
948     devices = pXListInputDevices(data->display, &num_devices);
949
950     X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
951     for (cur_loop=0; cur_loop < gNumCursors; cur_loop++)
952     {
953         char   cursorNameA[WT_MAX_NAME_LEN];
954         int    event_number=0;
955
956         /* the cursor name fits in the buffer because too long names are skipped */
957         WideCharToMultiByte(CP_UNIXCP, 0, gSysCursor[cur_loop].NAME, -1, cursorNameA, WT_MAX_NAME_LEN, NULL, NULL);
958         for (loop=0; loop < num_devices; loop ++)
959             if (strcmp(devices[loop].name, cursorNameA) == 0)
960                 target = &devices[loop];
961
962         TRACE("Opening cursor %i id %i\n",cur_loop,(INT)target->id);
963
964         the_device = pXOpenDevice(data->display, target->id);
965
966         if (!the_device)
967         {
968             WARN("Unable to Open device\n");
969             continue;
970         }
971
972         if (the_device->num_classes > 0)
973         {
974             DeviceKeyPress(the_device, key_press_type, event_list[event_number]);
975             if (key_press_type) event_number++;
976             DeviceKeyRelease(the_device, key_release_type, event_list[event_number]);
977             if (key_release_type) event_number++;
978             DeviceButtonPress(the_device, button_press_type, event_list[event_number]);
979             if (button_press_type) event_number++;
980             DeviceButtonRelease(the_device, button_release_type, event_list[event_number]);
981             if (button_release_type) event_number++;
982             DeviceMotionNotify(the_device, motion_type, event_list[event_number]);
983             if (motion_type) event_number++;
984             ProximityIn(the_device, proximity_in_type, event_list[event_number]);
985             if (proximity_in_type) event_number++;
986             ProximityOut(the_device, proximity_out_type, event_list[event_number]);
987             if (proximity_out_type) event_number++;
988
989             if (key_press_type) X11DRV_register_event_handler( key_press_type, key_event );
990             if (key_release_type) X11DRV_register_event_handler( key_release_type, key_event );
991             if (button_press_type) X11DRV_register_event_handler( button_press_type, button_event );
992             if (button_release_type) X11DRV_register_event_handler( button_release_type, button_event );
993             if (motion_type) X11DRV_register_event_handler( motion_type, motion_event );
994             if (proximity_in_type) X11DRV_register_event_handler( proximity_in_type, proximity_event );
995             if (proximity_out_type) X11DRV_register_event_handler( proximity_out_type, proximity_event );
996
997             pXSelectExtensionEvent(data->display, win, event_list, event_number);
998         }
999     }
1000     XSync(data->display, False);
1001     X11DRV_check_error();
1002
1003     if (NULL != devices) pXFreeDeviceList(devices);
1004     wine_tsx11_unlock();
1005     return 0;
1006 }
1007
1008 /***********************************************************************
1009  *              X11DRV_GetCurrentPacket (X11DRV.@)
1010  */
1011 int X11DRV_GetCurrentPacket(LPWTPACKET *packet)
1012 {
1013     memcpy(packet,&gMsgPacket,sizeof(WTPACKET));
1014     return 1;
1015 }
1016
1017
1018 static inline int CopyTabletData(LPVOID target, LPCVOID src, INT size)
1019 {
1020     /*
1021      * It is valid to call CopyTabletData with NULL.
1022      * This handles the WTInfo() case where lpOutput is null.
1023      */
1024     if(target != NULL)
1025         memcpy(target,src,size);
1026     return(size);
1027 }
1028
1029 /***********************************************************************
1030  *              X11DRV_WTInfoW (X11DRV.@)
1031  */
1032 UINT X11DRV_WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
1033 {
1034     /*
1035      * It is valid to call WTInfoA with lpOutput == NULL, as per standard.
1036      * lpOutput == NULL signifies the user only wishes
1037      * to find the size of the data.
1038      * NOTE:
1039      * From now on use CopyTabletData to fill lpOutput. memcpy will break
1040      * the code.
1041      */
1042     int rc = 0;
1043     LPWTI_CURSORS_INFO  tgtcursor;
1044     TRACE("(%u, %u, %p)\n", wCategory, nIndex, lpOutput);
1045
1046     switch(wCategory)
1047     {
1048         case 0:
1049             /* return largest necessary buffer */
1050             TRACE("%i cursors\n",gNumCursors);
1051             if (gNumCursors>0)
1052             {
1053                 FIXME("Return proper size\n");
1054                 rc = 200;
1055             }
1056             break;
1057         case WTI_INTERFACE:
1058             switch (nIndex)
1059             {
1060                 WORD version;
1061                 UINT num;
1062                 case IFC_WINTABID:
1063                 {
1064                     static const WCHAR driver[] = {'W','i','n','e',' ','W','i','n','t','a','b',' ','1','.','1',0};
1065                     rc = CopyTabletData(lpOutput, driver, (strlenW(driver) + 1) * sizeof(WCHAR));
1066                     break;
1067                 }
1068                 case IFC_SPECVERSION:
1069                     version = (0x01) | (0x01 << 8);
1070                     rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
1071                     break;
1072                 case IFC_IMPLVERSION:
1073                     version = (0x00) | (0x01 << 8);
1074                     rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
1075                     break;
1076                 case IFC_NDEVICES:
1077                     num = 1;
1078                     rc = CopyTabletData(lpOutput, &num,sizeof(num));
1079                     break;
1080                 case IFC_NCURSORS:
1081                     num = gNumCursors;
1082                     rc = CopyTabletData(lpOutput, &num,sizeof(num));
1083                     break;
1084                 default:
1085                     FIXME("WTI_INTERFACE unhandled index %i\n",nIndex);
1086                     rc = 0;
1087             }
1088             break;
1089         case WTI_DEFSYSCTX:
1090         case WTI_DDCTXS:
1091         case WTI_DEFCONTEXT:
1092             switch (nIndex)
1093             {
1094                 case 0:
1095                     rc = CopyTabletData(lpOutput, &gSysContext,
1096                             sizeof(LOGCONTEXTW));
1097                     break;
1098                 case CTX_NAME:
1099                     rc = CopyTabletData(lpOutput, &gSysContext.lcName,
1100                          (strlenW(gSysContext.lcName)+1) * sizeof(WCHAR));
1101                     break;
1102                 case CTX_OPTIONS:
1103                     rc = CopyTabletData(lpOutput, &gSysContext.lcOptions,
1104                                         sizeof(UINT));
1105                     break;
1106                 case CTX_STATUS:
1107                     rc = CopyTabletData(lpOutput, &gSysContext.lcStatus,
1108                                         sizeof(UINT));
1109                     break;
1110                 case CTX_LOCKS:
1111                     rc= CopyTabletData (lpOutput, &gSysContext.lcLocks,
1112                                         sizeof(UINT));
1113                     break;
1114                 case CTX_MSGBASE:
1115                     rc = CopyTabletData(lpOutput, &gSysContext.lcMsgBase,
1116                                         sizeof(UINT));
1117                     break;
1118                 case CTX_DEVICE:
1119                     rc = CopyTabletData(lpOutput, &gSysContext.lcDevice,
1120                                         sizeof(UINT));
1121                     break;
1122                 case CTX_PKTRATE:
1123                     rc = CopyTabletData(lpOutput, &gSysContext.lcPktRate,
1124                                         sizeof(UINT));
1125                     break;
1126                 case CTX_PKTDATA:
1127                     rc = CopyTabletData(lpOutput, &gSysContext.lcPktData,
1128                                         sizeof(WTPKT));
1129                     break;
1130                 case CTX_PKTMODE:
1131                     rc = CopyTabletData(lpOutput, &gSysContext.lcPktMode,
1132                                         sizeof(WTPKT));
1133                     break;
1134                 case CTX_MOVEMASK:
1135                     rc = CopyTabletData(lpOutput, &gSysContext.lcMoveMask,
1136                                         sizeof(WTPKT));
1137                     break;
1138                 case CTX_BTNDNMASK:
1139                     rc = CopyTabletData(lpOutput, &gSysContext.lcBtnDnMask,
1140                                         sizeof(DWORD));
1141                     break;
1142                 case CTX_BTNUPMASK:
1143                     rc = CopyTabletData(lpOutput, &gSysContext.lcBtnUpMask,
1144                                         sizeof(DWORD));
1145                     break;
1146                 case CTX_INORGX:
1147                     rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgX,
1148                                         sizeof(LONG));
1149                     break;
1150                 case CTX_INORGY:
1151                     rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgY,
1152                                         sizeof(LONG));
1153                     break;
1154                 case CTX_INORGZ:
1155                     rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgZ,
1156                                         sizeof(LONG));
1157                     break;
1158                 case CTX_INEXTX:
1159                     rc = CopyTabletData(lpOutput, &gSysContext.lcInExtX,
1160                                         sizeof(LONG));
1161                     break;
1162                 case CTX_INEXTY:
1163                      rc = CopyTabletData(lpOutput, &gSysContext.lcInExtY,
1164                                         sizeof(LONG));
1165                     break;
1166                 case CTX_INEXTZ:
1167                      rc = CopyTabletData(lpOutput, &gSysContext.lcInExtZ,
1168                                         sizeof(LONG));
1169                     break;
1170                 case CTX_OUTORGX:
1171                      rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgX,
1172                                         sizeof(LONG));
1173                     break;
1174                 case CTX_OUTORGY:
1175                       rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgY,
1176                                         sizeof(LONG));
1177                     break;
1178                 case CTX_OUTORGZ:
1179                        rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgZ,
1180                                         sizeof(LONG));
1181                     break;
1182                case CTX_OUTEXTX:
1183                       rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtX,
1184                                         sizeof(LONG));
1185                     break;
1186                 case CTX_OUTEXTY:
1187                        rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtY,
1188                                         sizeof(LONG));
1189                     break;
1190                 case CTX_OUTEXTZ:
1191                        rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtZ,
1192                                         sizeof(LONG));
1193                     break;
1194                 case CTX_SENSX:
1195                         rc = CopyTabletData(lpOutput, &gSysContext.lcSensX,
1196                                         sizeof(LONG));
1197                     break;
1198                 case CTX_SENSY:
1199                         rc = CopyTabletData(lpOutput, &gSysContext.lcSensY,
1200                                         sizeof(LONG));
1201                     break;
1202                 case CTX_SENSZ:
1203                         rc = CopyTabletData(lpOutput, &gSysContext.lcSensZ,
1204                                         sizeof(LONG));
1205                     break;
1206                 case CTX_SYSMODE:
1207                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysMode,
1208                                         sizeof(LONG));
1209                     break;
1210                 case CTX_SYSORGX:
1211                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgX,
1212                                         sizeof(LONG));
1213                     break;
1214                 case CTX_SYSORGY:
1215                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgY,
1216                                         sizeof(LONG));
1217                     break;
1218                 case CTX_SYSEXTX:
1219                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtX,
1220                                         sizeof(LONG));
1221                     break;
1222                 case CTX_SYSEXTY:
1223                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtY,
1224                                         sizeof(LONG));
1225                     break;
1226                 case CTX_SYSSENSX:
1227                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensX,
1228                                         sizeof(LONG));
1229                     break;
1230                 case CTX_SYSSENSY:
1231                        rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensY,
1232                                         sizeof(LONG));
1233                     break;
1234                 default:
1235                     FIXME("WTI_DEFSYSCTX unhandled index %i\n",nIndex);
1236                     rc = 0;
1237             }
1238             break;
1239         case WTI_CURSORS:
1240         case WTI_CURSORS+1:
1241         case WTI_CURSORS+2:
1242         case WTI_CURSORS+3:
1243         case WTI_CURSORS+4:
1244         case WTI_CURSORS+5:
1245         case WTI_CURSORS+6:
1246         case WTI_CURSORS+7:
1247         case WTI_CURSORS+8:
1248         case WTI_CURSORS+9:
1249             if (wCategory - WTI_CURSORS >= gNumCursors)
1250             {
1251                 rc = 0;
1252                 WARN("Requested cursor information for nonexistent cursor %d; only %d cursors\n",
1253                         wCategory - WTI_CURSORS, gNumCursors);
1254             }
1255             else
1256             {
1257                 tgtcursor = &gSysCursor[wCategory - WTI_CURSORS];
1258                 switch (nIndex)
1259                 {
1260                     case CSR_NAME:
1261                         rc = CopyTabletData(lpOutput, &tgtcursor->NAME,
1262                                             (strlenW(tgtcursor->NAME)+1) * sizeof(WCHAR));
1263                         break;
1264                     case CSR_ACTIVE:
1265                         rc = CopyTabletData(lpOutput,&tgtcursor->ACTIVE,
1266                                             sizeof(BOOL));
1267                         break;
1268                     case CSR_PKTDATA:
1269                         rc = CopyTabletData(lpOutput,&tgtcursor->PKTDATA,
1270                                             sizeof(WTPKT));
1271                         break;
1272                     case CSR_BUTTONS:
1273                         rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONS,
1274                                             sizeof(BYTE));
1275                         break;
1276                     case CSR_BUTTONBITS:
1277                         rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONBITS,
1278                                             sizeof(BYTE));
1279                         break;
1280                     case CSR_BTNNAMES:
1281                         FIXME("Button Names not returned correctly\n");
1282                         rc = CopyTabletData(lpOutput,&tgtcursor->BTNNAMES,
1283                                             tgtcursor->cchBTNNAMES*sizeof(WCHAR));
1284                         break;
1285                     case CSR_BUTTONMAP:
1286                         rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONMAP,
1287                                             sizeof(BYTE)*32);
1288                         break;
1289                     case CSR_SYSBTNMAP:
1290                         rc = CopyTabletData(lpOutput,&tgtcursor->SYSBTNMAP,
1291                                             sizeof(BYTE)*32);
1292                         break;
1293                     case CSR_NPBTNMARKS:
1294                         rc = CopyTabletData(lpOutput,&tgtcursor->NPBTNMARKS,
1295                                             sizeof(UINT)*2);
1296                         break;
1297                     case CSR_NPBUTTON:
1298                         rc = CopyTabletData(lpOutput,&tgtcursor->NPBUTTON,
1299                                             sizeof(BYTE));
1300                         break;
1301                     case CSR_NPRESPONSE:
1302                         FIXME("Not returning CSR_NPRESPONSE correctly\n");
1303                         rc = 0;
1304                         break;
1305                     case CSR_TPBUTTON:
1306                         rc = CopyTabletData(lpOutput,&tgtcursor->TPBUTTON,
1307                                             sizeof(BYTE));
1308                         break;
1309                     case CSR_TPBTNMARKS:
1310                         rc = CopyTabletData(lpOutput,&tgtcursor->TPBTNMARKS,
1311                                             sizeof(UINT)*2);
1312                         break;
1313                     case CSR_TPRESPONSE:
1314                         FIXME("Not returning CSR_TPRESPONSE correctly\n");
1315                         rc = 0;
1316                         break;
1317                     case CSR_PHYSID:
1318                     {
1319                         DWORD id;
1320                         id = tgtcursor->PHYSID;
1321                         rc = CopyTabletData(lpOutput,&id,sizeof(DWORD));
1322                     }
1323                         break;
1324                     case CSR_MODE:
1325                         rc = CopyTabletData(lpOutput,&tgtcursor->MODE,sizeof(UINT));
1326                         break;
1327                     case CSR_MINPKTDATA:
1328                         rc = CopyTabletData(lpOutput,&tgtcursor->MINPKTDATA,
1329                             sizeof(UINT));
1330                         break;
1331                     case CSR_MINBUTTONS:
1332                         rc = CopyTabletData(lpOutput,&tgtcursor->MINBUTTONS,
1333                             sizeof(UINT));
1334                         break;
1335                     case CSR_CAPABILITIES:
1336                         rc = CopyTabletData(lpOutput,&tgtcursor->CAPABILITIES,
1337                             sizeof(UINT));
1338                         break;
1339                     case CSR_TYPE:
1340                         rc = CopyTabletData(lpOutput,&tgtcursor->TYPE,
1341                             sizeof(UINT));
1342                         break;
1343                     default:
1344                         FIXME("WTI_CURSORS unhandled index %i\n",nIndex);
1345                         rc = 0;
1346                 }
1347             }
1348             break;
1349         case WTI_DEVICES:
1350             switch (nIndex)
1351             {
1352                 case DVC_NAME:
1353                     rc = CopyTabletData(lpOutput,gSysDevice.NAME,
1354                                         (strlenW(gSysDevice.NAME)+1) * sizeof(WCHAR));
1355                     break;
1356                 case DVC_HARDWARE:
1357                     rc = CopyTabletData(lpOutput,&gSysDevice.HARDWARE,
1358                                         sizeof(UINT));
1359                     break;
1360                 case DVC_NCSRTYPES:
1361                     rc = CopyTabletData(lpOutput,&gSysDevice.NCSRTYPES,
1362                                         sizeof(UINT));
1363                     break;
1364                 case DVC_FIRSTCSR:
1365                     rc = CopyTabletData(lpOutput,&gSysDevice.FIRSTCSR,
1366                                         sizeof(UINT));
1367                     break;
1368                 case DVC_PKTRATE:
1369                     rc = CopyTabletData(lpOutput,&gSysDevice.PKTRATE,
1370                                         sizeof(UINT));
1371                     break;
1372                 case DVC_PKTDATA:
1373                     rc = CopyTabletData(lpOutput,&gSysDevice.PKTDATA,
1374                                         sizeof(WTPKT));
1375                     break;
1376                 case DVC_PKTMODE:
1377                     rc = CopyTabletData(lpOutput,&gSysDevice.PKTMODE,
1378                                         sizeof(WTPKT));
1379                     break;
1380                 case DVC_CSRDATA:
1381                     rc = CopyTabletData(lpOutput,&gSysDevice.CSRDATA,
1382                                         sizeof(WTPKT));
1383                     break;
1384                 case DVC_XMARGIN:
1385                     rc = CopyTabletData(lpOutput,&gSysDevice.XMARGIN,
1386                                         sizeof(INT));
1387                     break;
1388                 case DVC_YMARGIN:
1389                     rc = CopyTabletData(lpOutput,&gSysDevice.YMARGIN,
1390                                         sizeof(INT));
1391                     break;
1392                 case DVC_ZMARGIN:
1393                     rc = 0; /* unsupported */
1394                     /*
1395                     rc = CopyTabletData(lpOutput,&gSysDevice.ZMARGIN,
1396                                         sizeof(INT));
1397                     */
1398                     break;
1399                 case DVC_X:
1400                     rc = CopyTabletData(lpOutput,&gSysDevice.X,
1401                                         sizeof(AXIS));
1402                     break;
1403                 case DVC_Y:
1404                     rc = CopyTabletData(lpOutput,&gSysDevice.Y,
1405                                         sizeof(AXIS));
1406                     break;
1407                 case DVC_Z:
1408                     rc = 0; /* unsupported */
1409                     /*
1410                     rc = CopyTabletData(lpOutput,&gSysDevice.Z,
1411                                         sizeof(AXIS));
1412                     */
1413                     break;
1414                 case DVC_NPRESSURE:
1415                     rc = CopyTabletData(lpOutput,&gSysDevice.NPRESSURE,
1416                                         sizeof(AXIS));
1417                     break;
1418                 case DVC_TPRESSURE:
1419                     rc = 0; /* unsupported */
1420                     /*
1421                     rc = CopyTabletData(lpOutput,&gSysDevice.TPRESSURE,
1422                                         sizeof(AXIS));
1423                     */
1424                     break;
1425                 case DVC_ORIENTATION:
1426                     rc = CopyTabletData(lpOutput,&gSysDevice.ORIENTATION,
1427                                         sizeof(AXIS)*3);
1428                     break;
1429                 case DVC_ROTATION:
1430                     rc = 0; /* unsupported */
1431                     /*
1432                     rc = CopyTabletData(lpOutput,&gSysDevice.ROTATION,
1433                                         sizeof(AXIS)*3);
1434                     */
1435                     break;
1436                 case DVC_PNPID:
1437                     rc = CopyTabletData(lpOutput,gSysDevice.PNPID,
1438                                         (strlenW(gSysDevice.PNPID)+1)*sizeof(WCHAR));
1439                     break;
1440                 default:
1441                     FIXME("WTI_DEVICES unhandled index %i\n",nIndex);
1442                     rc = 0;
1443             }
1444             break;
1445         default:
1446             FIXME("Unhandled Category %i\n",wCategory);
1447     }
1448     return rc;
1449 }
1450
1451 #else /* SONAME_LIBXI */
1452
1453 /***********************************************************************
1454  *              AttachEventQueueToTablet (X11DRV.@)
1455  */
1456 int X11DRV_AttachEventQueueToTablet(HWND hOwner)
1457 {
1458     return 0;
1459 }
1460
1461 /***********************************************************************
1462  *              GetCurrentPacket (X11DRV.@)
1463  */
1464 int X11DRV_GetCurrentPacket(LPWTPACKET *packet)
1465 {
1466     return 0;
1467 }
1468
1469 /***********************************************************************
1470  *              LoadTabletInfo (X11DRV.@)
1471  */
1472 void X11DRV_LoadTabletInfo(HWND hwnddefault)
1473 {
1474 }
1475
1476 /***********************************************************************
1477  *              WTInfoW (X11DRV.@)
1478  */
1479 UINT X11DRV_WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
1480 {
1481     return 0;
1482 }
1483
1484 #endif /* SONAME_LIBXI */