rsaenh: Remove unused file-static variables.
[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  *   Reference linuxwacom driver project wcmCommon.c function
217  *   idtotype for a much larger list of CSR_TYPE.
218  *
219  *   http://linuxwacom.cvs.sourceforge.net/linuxwacom/linuxwacom-prod/src/xdrv/wcmCommon.c?view=markup
220  *
221  *   The WTI_CURSORS_INFO.TYPE data is supposed to be used like this:
222  *   (cursor.TYPE & 0x0F06) == target_cursor_type
223  *   Reference: Section Unique ID
224  *   http://www.wacomeng.com/devsupport/ibmpc/gddevpc.html
225  */
226 #define CSR_TYPE_PEN        0x822
227 #define CSR_TYPE_ERASER     0x82a
228 #define CSR_TYPE_MOUSE_2D   0x007
229 #define CSR_TYPE_MOUSE_4D   0x094
230 /* CSR_TYPE_OTHER is a special value! assumed no real world significance
231  * if a stylus type or eraser type eventually have this value
232  * it'll be a bug.  As of 2008 05 21 we can be sure because
233  * linux wacom lists all the known values and this isn't one of them */
234 #define CSR_TYPE_OTHER      0x000
235
236 typedef struct tagWTPACKET {
237         HCTX pkContext;
238         UINT pkStatus;
239         LONG pkTime;
240         WTPKT pkChanged;
241         UINT pkSerialNumber;
242         UINT pkCursor;
243         DWORD pkButtons;
244         DWORD pkX;
245         DWORD pkY;
246         DWORD pkZ;
247         UINT pkNormalPressure;
248         UINT pkTangentPressure;
249         ORIENTATION pkOrientation;
250         ROTATION pkRotation; /* 1.1 */
251 } WTPACKET, *LPWTPACKET;
252
253
254 #ifdef SONAME_LIBXI
255
256 #include <X11/Xlib.h>
257 #include <X11/extensions/XInput.h>
258
259 static int           motion_type;
260 static int           button_press_type;
261 static int           button_release_type;
262 static int           key_press_type;
263 static int           key_release_type;
264 static int           proximity_in_type;
265 static int           proximity_out_type;
266
267 static HWND          hwndTabletDefault;
268 static WTPACKET      gMsgPacket;
269 static DWORD         gSerial;
270
271 /* Reference: http://www.wacomeng.com/devsupport/ibmpc/gddevpc.html
272  *
273  * Cursors come in sets of 3 normally
274  * Cursor #0 = puck   device 1
275  * Cursor #1 = stylus device 1
276  * Cursor #2 = eraser device 1
277  * Cursor #3 = puck   device 2
278  * Cursor #4 = stylus device 2
279  * Cursor #5 = eraser device 2
280  * etc....
281  *
282  * A dual tracking/multimode tablet is one
283  * that supports 2 independent cursors of the same or
284  * different types simultaneously on a single tablet.
285  * This makes our cursor layout potentially like this
286  * Cursor #0 = puck   1 device 1
287  * Cursor #1 = stylus 1 device 1
288  * Cursor #2 = eraser 1 device 1
289  * Cursor #3 = puck   2 device 1
290  * Cursor #4 = stylus 2 device 1
291  * Cursor #5 = eraser 2 device 1
292  * Cursor #6 = puck   1 device 2
293  * etc.....
294  *
295  * So with multimode tablets we could potentially need
296  * 2 slots of the same type per tablet i.e.
297  * you are using 2 styluses at once so they would
298  * get placed in Cursors #1 and Cursor #4
299  *
300  * Now say someone has 2 multimode tablets with 2 erasers each
301  * now we would need Cursor #2, #5, #8, #11
302  * So to support that we need CURSORMAX of 12 (0 to 11)
303  * FIXME: we don't support more than 4 regular tablets or 2 multimode tablets */
304 #define             CURSORMAX 12
305 static INT           button_state[CURSORMAX];
306
307 static LOGCONTEXTW      gSysContext;
308 static WTI_DEVICES_INFO gSysDevice;
309 static WTI_CURSORS_INFO gSysCursor[CURSORMAX];
310 static INT              gNumCursors; /* do NOT use this to iterate through gSysCursor slots */
311
312
313 /* XInput stuff */
314 static void *xinput_handle;
315
316 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
317 MAKE_FUNCPTR(XListInputDevices)
318 MAKE_FUNCPTR(XFreeDeviceList)
319 MAKE_FUNCPTR(XOpenDevice)
320 MAKE_FUNCPTR(XQueryDeviceState)
321 MAKE_FUNCPTR(XGetDeviceButtonMapping)
322 MAKE_FUNCPTR(XCloseDevice)
323 MAKE_FUNCPTR(XSelectExtensionEvent)
324 MAKE_FUNCPTR(XFreeDeviceState)
325 #undef MAKE_FUNCPTR
326
327 static INT X11DRV_XInput_Init(void)
328 {
329     xinput_handle = wine_dlopen(SONAME_LIBXI, RTLD_NOW, NULL, 0);
330     if (xinput_handle)
331     {
332 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xinput_handle, #f, NULL, 0)) == NULL) goto sym_not_found;
333         LOAD_FUNCPTR(XListInputDevices)
334         LOAD_FUNCPTR(XFreeDeviceList)
335         LOAD_FUNCPTR(XOpenDevice)
336         LOAD_FUNCPTR(XGetDeviceButtonMapping)
337         LOAD_FUNCPTR(XCloseDevice)
338         LOAD_FUNCPTR(XSelectExtensionEvent)
339         LOAD_FUNCPTR(XQueryDeviceState)
340         LOAD_FUNCPTR(XFreeDeviceState)
341 #undef LOAD_FUNCPTR
342         return 1;
343     }
344 sym_not_found:
345     return 0;
346 }
347
348 static int Tablet_ErrorHandler(Display *dpy, XErrorEvent *event, void* arg)
349 {
350     return 1;
351 }
352
353 static void trace_axes(XValuatorInfoPtr val)
354 {
355     int i;
356     XAxisInfoPtr axis;
357
358     for (i = 0, axis = val->axes ; i < val->num_axes; i++, axis++)
359         TRACE("        Axis %d: [resolution %d|min_value %d|max_value %d]\n", i, axis->resolution, axis->min_value, axis->max_value);
360 }
361
362 static BOOL match_token(const char *haystack, const char *needle)
363 {
364     const char *p, *q;
365     for (p = haystack; *p; )
366     {
367         while (*p && isspace(*p))
368             p++;
369         if (! *p)
370             break;
371
372         for (q = needle; *q && *p && tolower(*p) == tolower(*q); q++)
373             p++;
374         if (! *q && (isspace(*p) || !*p))
375             return TRUE;
376
377         while (*p && ! isspace(*p))
378             p++;
379     }
380     return FALSE;
381 }
382
383 /*    Determining if an X device is a Tablet style device is an imperfect science.
384 **  We rely on common conventions around device names as well as the type reported
385 **  by Wacom tablets.  This code will likely need to be expanded for alternate tablet types
386 **
387 **    Wintab refers to any device that interacts with the tablet as a cursor,
388 **  (stylus, eraser, tablet mouse, airbrush, etc)
389 **  this is not to be confused with wacom x11 configuration "cursor" device.
390 **  Wacoms x11 config "cursor" refers to its device slot (which we mirror with
391 **  our gSysCursors) for puck like devices (tablet mice essentially).
392 */
393
394 static BOOL is_tablet_cursor(const char *name, const char *type)
395 {
396     int i;
397     static const char *tablet_cursor_whitelist[] = {
398         "wacom",
399         "wizardpen",
400         "acecad",
401         "tablet",
402         "cursor",
403         "stylus",
404         "eraser",
405         "pad",
406         NULL
407     };
408
409     for (i=0; tablet_cursor_whitelist[i] != NULL; i++) {
410         if (name && match_token(name, tablet_cursor_whitelist[i]))
411             return TRUE;
412         if (type && match_token(type, tablet_cursor_whitelist[i]))
413             return TRUE;
414     }
415     return FALSE;
416 }
417
418 static BOOL is_stylus(const char *name, const char *type)
419 {
420     int i;
421     static const char* tablet_stylus_whitelist[] = {
422         "stylus",
423         "wizardpen",
424         "acecad",
425         NULL
426     };
427
428     for (i=0; tablet_stylus_whitelist[i] != NULL; i++) {
429         if (name && match_token(name, tablet_stylus_whitelist[i]))
430             return TRUE;
431         if (type && match_token(type, tablet_stylus_whitelist[i]))
432             return TRUE;
433     }
434
435     return FALSE;
436 }
437
438 static BOOL is_eraser(const char *name, const char *type)
439 {
440     if (name && match_token(name, "eraser"))
441         return TRUE;
442     if (type && match_token(type, "eraser"))
443         return TRUE;
444     return FALSE;
445 }
446
447 /* cursors are placed in gSysCursor rows depending on their type
448  * see CURSORMAX comments for more detail */
449 static BOOL add_system_cursor(LPWTI_CURSORS_INFO cursor)
450 {
451     UINT offset = 0;
452
453     if (cursor->TYPE == CSR_TYPE_PEN)
454         offset = 1;
455     else if (cursor->TYPE == CSR_TYPE_ERASER)
456         offset = 2;
457
458     for (; offset < CURSORMAX; offset += 3)
459     {
460         if (!gSysCursor[offset].ACTIVE)
461         {
462             gSysCursor[offset] = *cursor;
463             ++gNumCursors;
464             return TRUE;
465         }
466     }
467
468     return FALSE;
469 }
470
471 static void disable_system_cursors(void)
472 {
473     UINT i;
474
475     for (i = 0; i < CURSORMAX; ++i)
476     {
477         gSysCursor[i].ACTIVE = 0;
478     }
479
480     gNumCursors = 0;
481 }
482
483
484 /***********************************************************************
485  *             X11DRV_LoadTabletInfo (X11DRV.@)
486  */
487 BOOL CDECL X11DRV_LoadTabletInfo(HWND hwnddefault)
488 {
489     const WCHAR SZ_CONTEXT_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','C','o','n','t','e','x','t',0};
490     const WCHAR SZ_DEVICE_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','D','e','v','i','c','e',0};
491     const WCHAR SZ_NON_PLUGINPLAY[] = {'n','o','n','-','p','l','u','g','i','n','p','l','a','y',0};
492
493     struct x11drv_thread_data *data = x11drv_init_thread_data();
494     int num_devices;
495     int loop;
496     XDeviceInfo *devices;
497     XDeviceInfo *target = NULL;
498     BOOL    axis_read_complete= FALSE;
499
500     XAnyClassPtr        any;
501     XButtonInfoPtr      Button;
502     XValuatorInfoPtr    Val;
503     XAxisInfoPtr        Axis;
504
505     XDevice *opendevice;
506
507     if (!X11DRV_XInput_Init())
508     {
509         ERR("Unable to initialize the XInput library.\n");
510         return FALSE;
511     }
512
513     hwndTabletDefault = hwnddefault;
514
515     /* Do base initialization */
516     strcpyW(gSysContext.lcName, SZ_CONTEXT_NAME);
517     strcpyW(gSysDevice.NAME, SZ_DEVICE_NAME);
518
519     gSysContext.lcOptions = CXO_SYSTEM;
520     gSysContext.lcLocks = CXL_INSIZE | CXL_INASPECT | CXL_MARGIN |
521                                CXL_SENSITIVITY | CXL_SYSOUT;
522
523     gSysContext.lcMsgBase= WT_DEFBASE;
524     gSysContext.lcDevice = 0;
525     gSysContext.lcPktData =
526         PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
527         PK_BUTTONS |  PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
528     gSysContext.lcMoveMask=
529         PK_BUTTONS |  PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
530     gSysContext.lcStatus = CXS_ONTOP;
531     gSysContext.lcPktRate = 100;
532     gSysContext.lcBtnDnMask = 0xffffffff;
533     gSysContext.lcBtnUpMask = 0xffffffff;
534     gSysContext.lcSensX = 65536;
535     gSysContext.lcSensY = 65536;
536     gSysContext.lcSensX = 65536;
537     gSysContext.lcSensZ = 65536;
538     gSysContext.lcSysSensX= 65536;
539     gSysContext.lcSysSensY= 65536;
540
541     /* initialize cursors */
542     disable_system_cursors();
543
544     /* Device Defaults */
545     gSysDevice.HARDWARE = HWC_HARDPROX|HWC_PHYSID_CURSORS;
546     gSysDevice.FIRSTCSR= 0;
547     gSysDevice.PKTRATE = 100;
548     gSysDevice.PKTDATA =
549         PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
550         PK_BUTTONS |  PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
551     strcpyW(gSysDevice.PNPID, SZ_NON_PLUGINPLAY);
552
553     wine_tsx11_lock();
554
555     devices = pXListInputDevices(data->display, &num_devices);
556     if (!devices)
557     {
558         WARN("XInput Extensions reported as not available\n");
559         wine_tsx11_unlock();
560         return FALSE;
561     }
562     TRACE("XListInputDevices reports %d devices\n", num_devices);
563     for (loop=0; loop < num_devices; loop++)
564     {
565         int class_loop;
566         char *device_type = devices[loop].type ? XGetAtomName(data->display, devices[loop].type) : NULL;
567         WTI_CURSORS_INFO cursor;
568
569         TRACE("Device %i:  [id %d|name %s|type %s|num_classes %d|use %d]\n",
570                 loop, (int) devices[loop].id, devices[loop].name, device_type ? device_type : "",
571                 devices[loop].num_classes, devices[loop].use );
572
573         switch (devices[loop].use)
574         {
575         case IsXExtensionDevice:
576 #ifdef IsXExtensionPointer
577         case IsXExtensionPointer:
578 #endif
579 #ifdef IsXExtensionKeyboard
580         case IsXExtensionKeyboard:
581 #endif
582             TRACE("Is XExtension: Device, Keyboard, or Pointer\n");
583             target = &devices[loop];
584
585             if (strlen(target->name) >= WT_MAX_NAME_LEN)
586             {
587                 ERR("Input device '%s' name too long - skipping\n", wine_dbgstr_a(target->name));
588                 break;
589             }
590
591             X11DRV_expect_error(data->display, Tablet_ErrorHandler, NULL);
592             opendevice = pXOpenDevice(data->display,target->id);
593             if (!X11DRV_check_error() && opendevice)
594             {
595                 unsigned char map[32];
596                 int i;
597                 int shft = 0;
598
599                 X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
600                 cursor.BUTTONS = pXGetDeviceButtonMapping(data->display, opendevice, map, 32);
601                 if (X11DRV_check_error() || cursor.BUTTONS <= 0)
602                 {
603                     TRACE("No buttons, Non Tablet Device\n");
604                     pXCloseDevice(data->display, opendevice);
605                     break;
606                 }
607
608                 for (i=0; i< cursor.BUTTONS; i++,shft++)
609                 {
610                     cursor.BUTTONMAP[i] = map[i];
611                     cursor.SYSBTNMAP[i] = (1<<shft);
612                 }
613                 pXCloseDevice(data->display, opendevice);
614             }
615             else
616             {
617                 WARN("Unable to open device %s\n",target->name);
618                 break;
619             }
620             MultiByteToWideChar(CP_UNIXCP, 0, target->name, -1, cursor.NAME, WT_MAX_NAME_LEN);
621
622             if (! is_tablet_cursor(target->name, device_type))
623             {
624                 WARN("Skipping device %d [name %s|type %s]; not apparently a tablet cursor type device.  If this is wrong, please report it to wine-devel@winehq.org\n",
625                      loop, devices[loop].name, device_type ? device_type : "");
626                 break;
627             }
628
629             cursor.ACTIVE = 1;
630             cursor.PKTDATA = PK_TIME | PK_CURSOR | PK_BUTTONS |  PK_X | PK_Y |
631                               PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE |
632                               PK_ORIENTATION;
633
634             cursor.PHYSID = target->id;
635             cursor.NPBUTTON = 1;
636             cursor.NPBTNMARKS[0] = 0 ;
637             cursor.NPBTNMARKS[1] = 1 ;
638             cursor.CAPABILITIES = CRC_MULTIMODE;
639
640             /* prefer finding TYPE_PEN(most capable) */
641             if (is_stylus(target->name, device_type))
642                 cursor.TYPE = CSR_TYPE_PEN;
643             else if (is_eraser(target->name, device_type))
644                 cursor.TYPE = CSR_TYPE_ERASER;
645             else
646                 cursor.TYPE = CSR_TYPE_OTHER;
647
648             any = target->inputclassinfo;
649
650             for (class_loop = 0; class_loop < target->num_classes; class_loop++)
651             {
652                 switch (any->class)
653                 {
654
655                     case ValuatorClass:
656                         Val = (XValuatorInfoPtr) any;
657                         TRACE("    ValidatorInput %d: [class %d|length %d|num_axes %d|mode %d|motion_buffer %ld]\n",
658                                 class_loop, (int) Val->class, Val->length, Val->num_axes, Val->mode, Val->motion_buffer);
659                         if (TRACE_ON(wintab32))
660                             trace_axes(Val);
661
662                         /* FIXME:  This is imperfect; we compute our devices capabilities based upon the
663                         **         first pen type device we find.  However, a more correct implementation
664                         **         would require acquiring a wide variety of tablets and running through
665                         **         the various inputs to see what the values are.  Odds are that a
666                         **         more 'correct' algorithm would condense to this one anyway.
667                         */
668                         if (!axis_read_complete && cursor.TYPE == CSR_TYPE_PEN)
669                         {
670                             Axis = (XAxisInfoPtr) ((char *) Val + sizeof
671                                 (XValuatorInfo));
672
673                             if (Val->num_axes>=1)
674                             {
675                                 /* Axis 1 is X */
676                                 gSysDevice.X.axMin = Axis->min_value;
677                                 gSysDevice.X.axMax= Axis->max_value;
678                                 gSysDevice.X.axUnits = TU_INCHES;
679                                 gSysDevice.X.axResolution = Axis->resolution;
680                                 gSysContext.lcInOrgX = Axis->min_value;
681                                 gSysContext.lcSysOrgX = Axis->min_value;
682                                 gSysContext.lcInExtX = Axis->max_value;
683                                 gSysContext.lcSysExtX = Axis->max_value;
684                                 Axis++;
685                             }
686                             if (Val->num_axes>=2)
687                             {
688                                 /* Axis 2 is Y */
689                                 gSysDevice.Y.axMin = Axis->min_value;
690                                 gSysDevice.Y.axMax= Axis->max_value;
691                                 gSysDevice.Y.axUnits = TU_INCHES;
692                                 gSysDevice.Y.axResolution = Axis->resolution;
693                                 gSysContext.lcInOrgY = Axis->min_value;
694                                 gSysContext.lcSysOrgY = Axis->min_value;
695                                 gSysContext.lcInExtY = Axis->max_value;
696                                 gSysContext.lcSysExtY = Axis->max_value;
697                                 Axis++;
698                             }
699                             if (Val->num_axes>=3)
700                             {
701                                 /* Axis 3 is Normal Pressure */
702                                 gSysDevice.NPRESSURE.axMin = Axis->min_value;
703                                 gSysDevice.NPRESSURE.axMax= Axis->max_value;
704                                 gSysDevice.NPRESSURE.axUnits = TU_INCHES;
705                                 gSysDevice.NPRESSURE.axResolution =
706                                                         Axis->resolution;
707                                 Axis++;
708                             }
709                             if (Val->num_axes >= 5)
710                             {
711                                 /* Axis 4 and 5 are X and Y tilt */
712                                 XAxisInfoPtr        XAxis = Axis;
713                                 Axis++;
714                                 if (max (abs(Axis->max_value),
715                                          abs(XAxis->max_value)))
716                                 {
717                                     gSysDevice.ORIENTATION[0].axMin = 0;
718                                     gSysDevice.ORIENTATION[0].axMax = 3600;
719                                     gSysDevice.ORIENTATION[0].axUnits = TU_CIRCLE;
720                                     gSysDevice.ORIENTATION[0].axResolution
721                                                                 = CASTFIX32(3600);
722                                     gSysDevice.ORIENTATION[1].axMin = -1000;
723                                     gSysDevice.ORIENTATION[1].axMax = 1000;
724                                     gSysDevice.ORIENTATION[1].axUnits = TU_CIRCLE;
725                                     gSysDevice.ORIENTATION[1].axResolution
726                                                                 = CASTFIX32(3600);
727                                     Axis++;
728                                 }
729                             }
730                             axis_read_complete = TRUE;
731                         }
732                         break;
733                     case ButtonClass:
734                     {
735                         int cchBuf = 512;
736                         int cchPos = 0;
737                         int i;
738
739                         Button = (XButtonInfoPtr) any;
740                         TRACE("    ButtonInput %d: [class %d|length %d|num_buttons %d]\n",
741                                 class_loop, (int) Button->class, Button->length, Button->num_buttons);
742                         cursor.BTNNAMES = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*cchBuf);
743                         for (i = 0; i < cursor.BUTTONS; i++)
744                         {
745                             /* FIXME - these names are probably incorrect */
746                             int cch = strlenW(cursor.NAME) + 1;
747                             while (cch > cchBuf - cchPos - 1) /* we want one extra byte for the last NUL */
748                             {
749                                 cchBuf *= 2;
750                                 cursor.BTNNAMES = HeapReAlloc(GetProcessHeap(), 0, cursor.BTNNAMES, sizeof(WCHAR)*cchBuf);
751                             }
752
753                             strcpyW(cursor.BTNNAMES + cchPos, cursor.NAME);
754                             cchPos += cch;
755                         }
756                         cursor.BTNNAMES[cchPos++] = 0;
757                         cursor.BTNNAMES = HeapReAlloc(GetProcessHeap(), 0, cursor.BTNNAMES, sizeof(WCHAR)*cchPos);
758                         cursor.cchBTNNAMES = cchPos;
759                     }
760                     break;
761                 } /* switch any->class */
762                 any = (XAnyClassPtr) ((char*) any + any->length);
763             } /* for class_loop */
764             if (!add_system_cursor(&cursor))
765                 FIXME("Skipping this cursor due to lack of system cursor slots.\n");
766             break;
767         } /* switch devices.use */
768         XFree(device_type);
769     } /* for XListInputDevices */
770     pXFreeDeviceList(devices);
771
772     if (axis_read_complete)
773         gSysDevice.NCSRTYPES = gNumCursors;
774     else
775     {
776         disable_system_cursors();
777         WARN("Did not find a valid stylus, unable to determine system context parameters. Wintab is disabled.\n");
778     }
779
780     wine_tsx11_unlock();
781     return TRUE;
782 }
783
784 static int figure_deg(int x, int y)
785 {
786     float angle;
787
788     angle = atan2((float)y, (float)x);
789     angle += M_PI_2;
790     if (angle <= 0)
791         angle += 2 * M_PI;
792
793     return (0.5 + (angle * 1800.0 / M_PI));
794 }
795
796 static int get_button_state(int curnum)
797 {
798     return button_state[curnum];
799 }
800
801 static void set_button_state(int curnum, XID deviceid)
802 {
803     struct x11drv_thread_data *data = x11drv_thread_data();
804     XDevice *device;
805     XDeviceState *state;
806     XInputClass  *class;
807     int loop;
808     int rc = 0;
809
810     wine_tsx11_lock();
811     device = pXOpenDevice(data->display,deviceid);
812     state = pXQueryDeviceState(data->display,device);
813
814     if (state)
815     {
816         class = state->data;
817         for (loop = 0; loop < state->num_classes; loop++)
818         {
819             if (class->class == ButtonClass)
820             {
821                 int loop2;
822                 XButtonState *button_state =  (XButtonState*)class;
823                 for (loop2 = 0; loop2 < button_state->num_buttons; loop2++)
824                 {
825                     if (button_state->buttons[loop2 / 8] & (1 << (loop2 % 8)))
826                     {
827                         rc |= (1<<loop2);
828                     }
829                 }
830             }
831             class = (XInputClass *) ((char *) class + class->length);
832         }
833     }
834     pXFreeDeviceState(state);
835     wine_tsx11_unlock();
836     button_state[curnum] = rc;
837 }
838
839 static int cursor_from_device(DWORD deviceid, LPWTI_CURSORS_INFO *cursorp)
840 {
841     int i;
842     for (i = 0; i < CURSORMAX; i++)
843         if (gSysCursor[i].ACTIVE && gSysCursor[i].PHYSID == deviceid)
844         {
845             *cursorp = &gSysCursor[i];
846             return i;
847         }
848
849     ERR("Could not map device id %d to a cursor\n", (int) deviceid);
850     return -1;
851 }
852
853 static void motion_event( HWND hwnd, XEvent *event )
854 {
855     XDeviceMotionEvent *motion = (XDeviceMotionEvent *)event;
856     LPWTI_CURSORS_INFO cursor;
857     int curnum = cursor_from_device(motion->deviceid, &cursor);
858     if (curnum < 0)
859         return;
860
861     memset(&gMsgPacket,0,sizeof(WTPACKET));
862
863     TRACE("Received tablet motion event (%p); device id %d, cursor num %d\n",hwnd, (int) motion->deviceid, curnum);
864
865     /* Set cursor to inverted if cursor is the eraser */
866     gMsgPacket.pkStatus = (cursor->TYPE  == CSR_TYPE_ERASER ? TPS_INVERT:0);
867     gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(motion->time);
868     gMsgPacket.pkSerialNumber = gSerial++;
869     gMsgPacket.pkCursor = curnum;
870     gMsgPacket.pkX = motion->axis_data[0];
871     gMsgPacket.pkY = motion->axis_data[1];
872     gMsgPacket.pkOrientation.orAzimuth = figure_deg(motion->axis_data[3],motion->axis_data[4]);
873     gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max
874                                             (abs(motion->axis_data[3]),
875                                              abs(motion->axis_data[4])))
876                                            * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
877     gMsgPacket.pkNormalPressure = motion->axis_data[2];
878     gMsgPacket.pkButtons = get_button_state(curnum);
879     SendMessageW(hwndTabletDefault,WT_PACKET,gMsgPacket.pkSerialNumber,(LPARAM)hwnd);
880 }
881
882 static void button_event( HWND hwnd, XEvent *event )
883 {
884     XDeviceButtonEvent *button = (XDeviceButtonEvent *) event;
885     LPWTI_CURSORS_INFO cursor;
886     int curnum = cursor_from_device(button->deviceid, &cursor);
887     if (curnum < 0)
888         return;
889
890     memset(&gMsgPacket,0,sizeof(WTPACKET));
891
892     TRACE("Received tablet button %s event\n", (event->type == button_press_type)?"press":"release");
893
894     /* Set cursor to inverted if cursor is the eraser */
895     gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
896     set_button_state(curnum, button->deviceid);
897     gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(button->time);
898     gMsgPacket.pkSerialNumber = gSerial++;
899     gMsgPacket.pkCursor = curnum;
900     gMsgPacket.pkX = button->axis_data[0];
901     gMsgPacket.pkY = button->axis_data[1];
902     gMsgPacket.pkOrientation.orAzimuth = figure_deg(button->axis_data[3],button->axis_data[4]);
903     gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(button->axis_data[3]),
904                                                             abs(button->axis_data[4])))
905                                            * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
906     gMsgPacket.pkNormalPressure = button->axis_data[2];
907     gMsgPacket.pkButtons = get_button_state(curnum);
908     SendMessageW(hwndTabletDefault,WT_PACKET,gMsgPacket.pkSerialNumber,(LPARAM)hwnd);
909 }
910
911 static void key_event( HWND hwnd, XEvent *event )
912 {
913     if (event->type == key_press_type)
914         FIXME("Received tablet key press event\n");
915     else
916         FIXME("Received tablet key release event\n");
917 }
918
919 static void proximity_event( HWND hwnd, XEvent *event )
920 {
921     XProximityNotifyEvent *proximity = (XProximityNotifyEvent *) event;
922     LPWTI_CURSORS_INFO cursor;
923     int curnum = cursor_from_device(proximity->deviceid, &cursor);
924     LPARAM proximity_info;
925
926     TRACE("hwnd=%p\n", hwnd);
927
928     if (curnum < 0)
929         return;
930
931     memset(&gMsgPacket,0,sizeof(WTPACKET));
932
933     /* Set cursor to inverted if cursor is the eraser */
934     gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
935     gMsgPacket.pkStatus |= (event->type==proximity_out_type)?TPS_PROXIMITY:0;
936     gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(proximity->time);
937     gMsgPacket.pkSerialNumber = gSerial++;
938     gMsgPacket.pkCursor = curnum;
939     gMsgPacket.pkX = proximity->axis_data[0];
940     gMsgPacket.pkY = proximity->axis_data[1];
941     gMsgPacket.pkOrientation.orAzimuth = figure_deg(proximity->axis_data[3],proximity->axis_data[4]);
942     gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(proximity->axis_data[3]),
943                                                             abs(proximity->axis_data[4])))
944                                            * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
945     gMsgPacket.pkNormalPressure = proximity->axis_data[2];
946     gMsgPacket.pkButtons = get_button_state(curnum);
947
948     /* FIXME: LPARAM loword is true when cursor entering context, false when leaving context
949      * This needs to be handled here or in wintab32.  Using the proximity_in_type is not correct
950      * but kept for now.
951      * LPARAM hiword is "non-zero when the cursor is leaving or entering hardware proximity"
952      * WPARAM contains context handle.
953      * HWND to HCTX is handled by wintab32.
954      */
955     proximity_info = MAKELPARAM((event->type == proximity_in_type),
956                      (event->type == proximity_in_type) || (event->type == proximity_out_type));
957     SendMessageW(hwndTabletDefault, WT_PROXIMITY, (WPARAM)hwnd, proximity_info);
958 }
959
960 /***********************************************************************
961  *              X11DRV_AttachEventQueueToTablet (X11DRV.@)
962  */
963 int CDECL X11DRV_AttachEventQueueToTablet(HWND hOwner)
964 {
965     struct x11drv_thread_data *data = x11drv_init_thread_data();
966     int             num_devices;
967     int             loop;
968     int             cur_loop;
969     XDeviceInfo     *devices;
970     XDeviceInfo     *target = NULL;
971     XDevice         *the_device;
972     XEventClass     event_list[7];
973     Window          win = X11DRV_get_whole_window( hOwner );
974
975     if (!win || !xinput_handle) return 0;
976
977     TRACE("Creating context for window %p (%lx)  %i cursors\n", hOwner, win, gNumCursors);
978
979     wine_tsx11_lock();
980     devices = pXListInputDevices(data->display, &num_devices);
981
982     X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
983     for (cur_loop=0; cur_loop < CURSORMAX; cur_loop++)
984     {
985         char   cursorNameA[WT_MAX_NAME_LEN];
986         int    event_number=0;
987
988         if (!gSysCursor[cur_loop].ACTIVE) continue;
989
990         /* the cursor name fits in the buffer because too long names are skipped */
991         WideCharToMultiByte(CP_UNIXCP, 0, gSysCursor[cur_loop].NAME, -1, cursorNameA, WT_MAX_NAME_LEN, NULL, NULL);
992         for (loop=0; loop < num_devices; loop ++)
993             if (strcmp(devices[loop].name, cursorNameA) == 0)
994                 target = &devices[loop];
995         if (!target) {
996             WARN("Cursor Name %s not found in list of targets.\n", cursorNameA);
997             continue;
998         }
999
1000         TRACE("Opening cursor %i id %i\n",cur_loop,(INT)target->id);
1001
1002         the_device = pXOpenDevice(data->display, target->id);
1003
1004         if (!the_device)
1005         {
1006             WARN("Unable to Open device\n");
1007             continue;
1008         }
1009
1010         if (the_device->num_classes > 0)
1011         {
1012             DeviceKeyPress(the_device, key_press_type, event_list[event_number]);
1013             if (key_press_type) event_number++;
1014             DeviceKeyRelease(the_device, key_release_type, event_list[event_number]);
1015             if (key_release_type) event_number++;
1016             DeviceButtonPress(the_device, button_press_type, event_list[event_number]);
1017             if (button_press_type) event_number++;
1018             DeviceButtonRelease(the_device, button_release_type, event_list[event_number]);
1019             if (button_release_type) event_number++;
1020             DeviceMotionNotify(the_device, motion_type, event_list[event_number]);
1021             if (motion_type) event_number++;
1022             ProximityIn(the_device, proximity_in_type, event_list[event_number]);
1023             if (proximity_in_type) event_number++;
1024             ProximityOut(the_device, proximity_out_type, event_list[event_number]);
1025             if (proximity_out_type) event_number++;
1026
1027             if (key_press_type)
1028                 X11DRV_register_event_handler( key_press_type, key_event, "XInput KeyPress" );
1029             if (key_release_type)
1030                 X11DRV_register_event_handler( key_release_type, key_event, "XInput KeyRelease" );
1031             if (button_press_type)
1032                 X11DRV_register_event_handler( button_press_type, button_event, "XInput ButtonPress" );
1033             if (button_release_type)
1034                 X11DRV_register_event_handler( button_release_type, button_event, "XInput ButtonRelease" );
1035             if (motion_type)
1036                 X11DRV_register_event_handler( motion_type, motion_event, "XInput MotionNotify" );
1037             if (proximity_in_type)
1038                 X11DRV_register_event_handler( proximity_in_type, proximity_event, "XInput ProximityIn" );
1039             if (proximity_out_type)
1040                 X11DRV_register_event_handler( proximity_out_type, proximity_event, "XInput ProximityOut" );
1041
1042             pXSelectExtensionEvent(data->display, win, event_list, event_number);
1043         }
1044     }
1045     XSync(data->display, False);
1046     X11DRV_check_error();
1047
1048     if (NULL != devices) pXFreeDeviceList(devices);
1049     wine_tsx11_unlock();
1050     return 0;
1051 }
1052
1053 /***********************************************************************
1054  *              X11DRV_GetCurrentPacket (X11DRV.@)
1055  */
1056 int CDECL X11DRV_GetCurrentPacket(LPWTPACKET packet)
1057 {
1058     *packet = gMsgPacket;
1059     return 1;
1060 }
1061
1062
1063 static inline int CopyTabletData(LPVOID target, LPCVOID src, INT size)
1064 {
1065     /*
1066      * It is valid to call CopyTabletData with NULL.
1067      * This handles the WTInfo() case where lpOutput is null.
1068      */
1069     if(target != NULL)
1070         memcpy(target,src,size);
1071     return(size);
1072 }
1073
1074 /***********************************************************************
1075  *              X11DRV_WTInfoW (X11DRV.@)
1076  */
1077 UINT CDECL X11DRV_WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
1078 {
1079     /*
1080      * It is valid to call WTInfoA with lpOutput == NULL, as per standard.
1081      * lpOutput == NULL signifies the user only wishes
1082      * to find the size of the data.
1083      * NOTE:
1084      * From now on use CopyTabletData to fill lpOutput. memcpy will break
1085      * the code.
1086      */
1087     int rc = 0;
1088     LPWTI_CURSORS_INFO  tgtcursor;
1089     TRACE("(%u, %u, %p)\n", wCategory, nIndex, lpOutput);
1090
1091     if (!xinput_handle) return 0;
1092
1093     switch(wCategory)
1094     {
1095         case 0:
1096             /* return largest necessary buffer */
1097             TRACE("%i cursors\n",gNumCursors);
1098             if (gNumCursors>0)
1099             {
1100                 FIXME("Return proper size\n");
1101                 rc = 200;
1102             }
1103             break;
1104         case WTI_INTERFACE:
1105             switch (nIndex)
1106             {
1107                 WORD version;
1108                 UINT num;
1109                 case IFC_WINTABID:
1110                 {
1111                     static const WCHAR driver[] = {'W','i','n','e',' ','W','i','n','t','a','b',' ','1','.','1',0};
1112                     rc = CopyTabletData(lpOutput, driver, (strlenW(driver) + 1) * sizeof(WCHAR));
1113                     break;
1114                 }
1115                 case IFC_SPECVERSION:
1116                     version = (0x01) | (0x01 << 8);
1117                     rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
1118                     break;
1119                 case IFC_IMPLVERSION:
1120                     version = (0x00) | (0x01 << 8);
1121                     rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
1122                     break;
1123                 case IFC_NDEVICES:
1124                     num = 1;
1125                     rc = CopyTabletData(lpOutput, &num,sizeof(num));
1126                     break;
1127                 case IFC_NCURSORS:
1128                     num = gNumCursors;
1129                     rc = CopyTabletData(lpOutput, &num,sizeof(num));
1130                     break;
1131                 default:
1132                     FIXME("WTI_INTERFACE unhandled index %i\n",nIndex);
1133                     rc = 0;
1134             }
1135             break;
1136         case WTI_DEFSYSCTX:
1137         case WTI_DDCTXS:
1138         case WTI_DEFCONTEXT:
1139             switch (nIndex)
1140             {
1141                 case 0:
1142                     /* report 0 if wintab is disabled */
1143                     if (0 == gNumCursors)
1144                         rc = 0;
1145                     else
1146                         rc = CopyTabletData(lpOutput, &gSysContext,
1147                                 sizeof(LOGCONTEXTW));
1148                     break;
1149                 case CTX_NAME:
1150                     rc = CopyTabletData(lpOutput, gSysContext.lcName,
1151                          (strlenW(gSysContext.lcName)+1) * sizeof(WCHAR));
1152                     break;
1153                 case CTX_OPTIONS:
1154                     rc = CopyTabletData(lpOutput, &gSysContext.lcOptions,
1155                                         sizeof(UINT));
1156                     break;
1157                 case CTX_STATUS:
1158                     rc = CopyTabletData(lpOutput, &gSysContext.lcStatus,
1159                                         sizeof(UINT));
1160                     break;
1161                 case CTX_LOCKS:
1162                     rc= CopyTabletData (lpOutput, &gSysContext.lcLocks,
1163                                         sizeof(UINT));
1164                     break;
1165                 case CTX_MSGBASE:
1166                     rc = CopyTabletData(lpOutput, &gSysContext.lcMsgBase,
1167                                         sizeof(UINT));
1168                     break;
1169                 case CTX_DEVICE:
1170                     rc = CopyTabletData(lpOutput, &gSysContext.lcDevice,
1171                                         sizeof(UINT));
1172                     break;
1173                 case CTX_PKTRATE:
1174                     rc = CopyTabletData(lpOutput, &gSysContext.lcPktRate,
1175                                         sizeof(UINT));
1176                     break;
1177                 case CTX_PKTDATA:
1178                     rc = CopyTabletData(lpOutput, &gSysContext.lcPktData,
1179                                         sizeof(WTPKT));
1180                     break;
1181                 case CTX_PKTMODE:
1182                     rc = CopyTabletData(lpOutput, &gSysContext.lcPktMode,
1183                                         sizeof(WTPKT));
1184                     break;
1185                 case CTX_MOVEMASK:
1186                     rc = CopyTabletData(lpOutput, &gSysContext.lcMoveMask,
1187                                         sizeof(WTPKT));
1188                     break;
1189                 case CTX_BTNDNMASK:
1190                     rc = CopyTabletData(lpOutput, &gSysContext.lcBtnDnMask,
1191                                         sizeof(DWORD));
1192                     break;
1193                 case CTX_BTNUPMASK:
1194                     rc = CopyTabletData(lpOutput, &gSysContext.lcBtnUpMask,
1195                                         sizeof(DWORD));
1196                     break;
1197                 case CTX_INORGX:
1198                     rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgX,
1199                                         sizeof(LONG));
1200                     break;
1201                 case CTX_INORGY:
1202                     rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgY,
1203                                         sizeof(LONG));
1204                     break;
1205                 case CTX_INORGZ:
1206                     rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgZ,
1207                                         sizeof(LONG));
1208                     break;
1209                 case CTX_INEXTX:
1210                     rc = CopyTabletData(lpOutput, &gSysContext.lcInExtX,
1211                                         sizeof(LONG));
1212                     break;
1213                 case CTX_INEXTY:
1214                      rc = CopyTabletData(lpOutput, &gSysContext.lcInExtY,
1215                                         sizeof(LONG));
1216                     break;
1217                 case CTX_INEXTZ:
1218                      rc = CopyTabletData(lpOutput, &gSysContext.lcInExtZ,
1219                                         sizeof(LONG));
1220                     break;
1221                 case CTX_OUTORGX:
1222                      rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgX,
1223                                         sizeof(LONG));
1224                     break;
1225                 case CTX_OUTORGY:
1226                       rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgY,
1227                                         sizeof(LONG));
1228                     break;
1229                 case CTX_OUTORGZ:
1230                        rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgZ,
1231                                         sizeof(LONG));
1232                     break;
1233                case CTX_OUTEXTX:
1234                       rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtX,
1235                                         sizeof(LONG));
1236                     break;
1237                 case CTX_OUTEXTY:
1238                        rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtY,
1239                                         sizeof(LONG));
1240                     break;
1241                 case CTX_OUTEXTZ:
1242                        rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtZ,
1243                                         sizeof(LONG));
1244                     break;
1245                 case CTX_SENSX:
1246                         rc = CopyTabletData(lpOutput, &gSysContext.lcSensX,
1247                                         sizeof(LONG));
1248                     break;
1249                 case CTX_SENSY:
1250                         rc = CopyTabletData(lpOutput, &gSysContext.lcSensY,
1251                                         sizeof(LONG));
1252                     break;
1253                 case CTX_SENSZ:
1254                         rc = CopyTabletData(lpOutput, &gSysContext.lcSensZ,
1255                                         sizeof(LONG));
1256                     break;
1257                 case CTX_SYSMODE:
1258                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysMode,
1259                                         sizeof(LONG));
1260                     break;
1261                 case CTX_SYSORGX:
1262                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgX,
1263                                         sizeof(LONG));
1264                     break;
1265                 case CTX_SYSORGY:
1266                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgY,
1267                                         sizeof(LONG));
1268                     break;
1269                 case CTX_SYSEXTX:
1270                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtX,
1271                                         sizeof(LONG));
1272                     break;
1273                 case CTX_SYSEXTY:
1274                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtY,
1275                                         sizeof(LONG));
1276                     break;
1277                 case CTX_SYSSENSX:
1278                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensX,
1279                                         sizeof(LONG));
1280                     break;
1281                 case CTX_SYSSENSY:
1282                        rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensY,
1283                                         sizeof(LONG));
1284                     break;
1285                 default:
1286                     FIXME("WTI_DEFSYSCTX unhandled index %i\n",nIndex);
1287                     rc = 0;
1288             }
1289             break;
1290         case WTI_CURSORS:
1291         case WTI_CURSORS+1:
1292         case WTI_CURSORS+2:
1293         case WTI_CURSORS+3:
1294         case WTI_CURSORS+4:
1295         case WTI_CURSORS+5:
1296         case WTI_CURSORS+6:
1297         case WTI_CURSORS+7:
1298         case WTI_CURSORS+8:
1299         case WTI_CURSORS+9:
1300         case WTI_CURSORS+10:
1301         case WTI_CURSORS+11:
1302         /* CURSORMAX == 12 */
1303         /* FIXME: dynamic cursor support */
1304             /* Apps will poll different slots to detect what cursors are available
1305              * if there isn't a cursor for this slot return 0 */
1306             if (!gSysCursor[wCategory - WTI_CURSORS].ACTIVE)
1307                 rc = 0;
1308             else
1309             {
1310                 tgtcursor = &gSysCursor[wCategory - WTI_CURSORS];
1311                 switch (nIndex)
1312                 {
1313                     case CSR_NAME:
1314                         rc = CopyTabletData(lpOutput, tgtcursor->NAME,
1315                                             (strlenW(tgtcursor->NAME)+1) * sizeof(WCHAR));
1316                         break;
1317                     case CSR_ACTIVE:
1318                         rc = CopyTabletData(lpOutput,&tgtcursor->ACTIVE,
1319                                             sizeof(BOOL));
1320                         break;
1321                     case CSR_PKTDATA:
1322                         rc = CopyTabletData(lpOutput,&tgtcursor->PKTDATA,
1323                                             sizeof(WTPKT));
1324                         break;
1325                     case CSR_BUTTONS:
1326                         rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONS,
1327                                             sizeof(BYTE));
1328                         break;
1329                     case CSR_BUTTONBITS:
1330                         rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONBITS,
1331                                             sizeof(BYTE));
1332                         break;
1333                     case CSR_BTNNAMES:
1334                         FIXME("Button Names not returned correctly\n");
1335                         rc = CopyTabletData(lpOutput,&tgtcursor->BTNNAMES,
1336                                             tgtcursor->cchBTNNAMES*sizeof(WCHAR));
1337                         break;
1338                     case CSR_BUTTONMAP:
1339                         rc = CopyTabletData(lpOutput,tgtcursor->BUTTONMAP,
1340                                             sizeof(BYTE)*32);
1341                         break;
1342                     case CSR_SYSBTNMAP:
1343                         rc = CopyTabletData(lpOutput,tgtcursor->SYSBTNMAP,
1344                                             sizeof(BYTE)*32);
1345                         break;
1346                     case CSR_NPBTNMARKS:
1347                         rc = CopyTabletData(lpOutput,tgtcursor->NPBTNMARKS,
1348                                             sizeof(UINT)*2);
1349                         break;
1350                     case CSR_NPBUTTON:
1351                         rc = CopyTabletData(lpOutput,&tgtcursor->NPBUTTON,
1352                                             sizeof(BYTE));
1353                         break;
1354                     case CSR_NPRESPONSE:
1355                         FIXME("Not returning CSR_NPRESPONSE correctly\n");
1356                         rc = 0;
1357                         break;
1358                     case CSR_TPBUTTON:
1359                         rc = CopyTabletData(lpOutput,&tgtcursor->TPBUTTON,
1360                                             sizeof(BYTE));
1361                         break;
1362                     case CSR_TPBTNMARKS:
1363                         rc = CopyTabletData(lpOutput,tgtcursor->TPBTNMARKS,
1364                                             sizeof(UINT)*2);
1365                         break;
1366                     case CSR_TPRESPONSE:
1367                         FIXME("Not returning CSR_TPRESPONSE correctly\n");
1368                         rc = 0;
1369                         break;
1370                     case CSR_PHYSID:
1371                     {
1372                         DWORD id;
1373                         id = tgtcursor->PHYSID;
1374                         rc = CopyTabletData(lpOutput,&id,sizeof(DWORD));
1375                     }
1376                         break;
1377                     case CSR_MODE:
1378                         rc = CopyTabletData(lpOutput,&tgtcursor->MODE,sizeof(UINT));
1379                         break;
1380                     case CSR_MINPKTDATA:
1381                         rc = CopyTabletData(lpOutput,&tgtcursor->MINPKTDATA,
1382                             sizeof(UINT));
1383                         break;
1384                     case CSR_MINBUTTONS:
1385                         rc = CopyTabletData(lpOutput,&tgtcursor->MINBUTTONS,
1386                             sizeof(UINT));
1387                         break;
1388                     case CSR_CAPABILITIES:
1389                         rc = CopyTabletData(lpOutput,&tgtcursor->CAPABILITIES,
1390                             sizeof(UINT));
1391                         break;
1392                     case CSR_TYPE:
1393                         rc = CopyTabletData(lpOutput,&tgtcursor->TYPE,
1394                             sizeof(UINT));
1395                         break;
1396                     default:
1397                         FIXME("WTI_CURSORS unhandled index %i\n",nIndex);
1398                         rc = 0;
1399                 }
1400             }
1401             break;
1402         case WTI_DEVICES:
1403             switch (nIndex)
1404             {
1405                 case DVC_NAME:
1406                     rc = CopyTabletData(lpOutput,gSysDevice.NAME,
1407                                         (strlenW(gSysDevice.NAME)+1) * sizeof(WCHAR));
1408                     break;
1409                 case DVC_HARDWARE:
1410                     rc = CopyTabletData(lpOutput,&gSysDevice.HARDWARE,
1411                                         sizeof(UINT));
1412                     break;
1413                 case DVC_NCSRTYPES:
1414                     rc = CopyTabletData(lpOutput,&gSysDevice.NCSRTYPES,
1415                                         sizeof(UINT));
1416                     break;
1417                 case DVC_FIRSTCSR:
1418                     rc = CopyTabletData(lpOutput,&gSysDevice.FIRSTCSR,
1419                                         sizeof(UINT));
1420                     break;
1421                 case DVC_PKTRATE:
1422                     rc = CopyTabletData(lpOutput,&gSysDevice.PKTRATE,
1423                                         sizeof(UINT));
1424                     break;
1425                 case DVC_PKTDATA:
1426                     rc = CopyTabletData(lpOutput,&gSysDevice.PKTDATA,
1427                                         sizeof(WTPKT));
1428                     break;
1429                 case DVC_PKTMODE:
1430                     rc = CopyTabletData(lpOutput,&gSysDevice.PKTMODE,
1431                                         sizeof(WTPKT));
1432                     break;
1433                 case DVC_CSRDATA:
1434                     rc = CopyTabletData(lpOutput,&gSysDevice.CSRDATA,
1435                                         sizeof(WTPKT));
1436                     break;
1437                 case DVC_XMARGIN:
1438                     rc = CopyTabletData(lpOutput,&gSysDevice.XMARGIN,
1439                                         sizeof(INT));
1440                     break;
1441                 case DVC_YMARGIN:
1442                     rc = CopyTabletData(lpOutput,&gSysDevice.YMARGIN,
1443                                         sizeof(INT));
1444                     break;
1445                 case DVC_ZMARGIN:
1446                     rc = 0; /* unsupported */
1447                     /*
1448                     rc = CopyTabletData(lpOutput,&gSysDevice.ZMARGIN,
1449                                         sizeof(INT));
1450                     */
1451                     break;
1452                 case DVC_X:
1453                     rc = CopyTabletData(lpOutput,&gSysDevice.X,
1454                                         sizeof(AXIS));
1455                     break;
1456                 case DVC_Y:
1457                     rc = CopyTabletData(lpOutput,&gSysDevice.Y,
1458                                         sizeof(AXIS));
1459                     break;
1460                 case DVC_Z:
1461                     rc = 0; /* unsupported */
1462                     /*
1463                     rc = CopyTabletData(lpOutput,&gSysDevice.Z,
1464                                         sizeof(AXIS));
1465                     */
1466                     break;
1467                 case DVC_NPRESSURE:
1468                     rc = CopyTabletData(lpOutput,&gSysDevice.NPRESSURE,
1469                                         sizeof(AXIS));
1470                     break;
1471                 case DVC_TPRESSURE:
1472                     rc = 0; /* unsupported */
1473                     /*
1474                     rc = CopyTabletData(lpOutput,&gSysDevice.TPRESSURE,
1475                                         sizeof(AXIS));
1476                     */
1477                     break;
1478                 case DVC_ORIENTATION:
1479                     rc = CopyTabletData(lpOutput,gSysDevice.ORIENTATION,
1480                                         sizeof(AXIS)*3);
1481                     break;
1482                 case DVC_ROTATION:
1483                     rc = 0; /* unsupported */
1484                     /*
1485                     rc = CopyTabletData(lpOutput,&gSysDevice.ROTATION,
1486                                         sizeof(AXIS)*3);
1487                     */
1488                     break;
1489                 case DVC_PNPID:
1490                     rc = CopyTabletData(lpOutput,gSysDevice.PNPID,
1491                                         (strlenW(gSysDevice.PNPID)+1)*sizeof(WCHAR));
1492                     break;
1493                 default:
1494                     FIXME("WTI_DEVICES unhandled index %i\n",nIndex);
1495                     rc = 0;
1496             }
1497             break;
1498         default:
1499             FIXME("Unhandled Category %i\n",wCategory);
1500     }
1501     return rc;
1502 }
1503
1504 #else /* SONAME_LIBXI */
1505
1506 /***********************************************************************
1507  *              AttachEventQueueToTablet (X11DRV.@)
1508  */
1509 int CDECL X11DRV_AttachEventQueueToTablet(HWND hOwner)
1510 {
1511     return 0;
1512 }
1513
1514 /***********************************************************************
1515  *              GetCurrentPacket (X11DRV.@)
1516  */
1517 int CDECL X11DRV_GetCurrentPacket(LPWTPACKET packet)
1518 {
1519     return 0;
1520 }
1521
1522 /***********************************************************************
1523  *              LoadTabletInfo (X11DRV.@)
1524  */
1525 BOOL CDECL X11DRV_LoadTabletInfo(HWND hwnddefault)
1526 {
1527     return FALSE;
1528 }
1529
1530 /***********************************************************************
1531  *              WTInfoW (X11DRV.@)
1532  */
1533 UINT CDECL X11DRV_WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
1534 {
1535     return 0;
1536 }
1537
1538 #endif /* SONAME_LIBXI */