mapi32: Implement FGetComponentPath.
[wine] / dlls / x11drv / 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
26 #include "windef.h"
27 #include "x11drv.h"
28 #include "wine/library.h"
29 #include "wine/debug.h"
30 #include "wintab.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(wintab32);
33
34 typedef struct tagWTI_CURSORS_INFO
35 {
36     CHAR   NAME[256];
37         /* a displayable zero-terminated string containing the name of the
38          * cursor.
39          */
40     BOOL    ACTIVE;
41         /* whether the cursor is currently connected. */
42     WTPKT   PKTDATA;
43         /* a bit mask indicating the packet data items supported when this
44          * cursor is connected.
45          */
46     BYTE    BUTTONS;
47         /* the number of buttons on this cursor. */
48     BYTE    BUTTONBITS;
49         /* the number of bits of raw button data returned by the hardware.*/
50     CHAR   BTNNAMES[1024]; /* FIXME: make this dynamic */
51         /* a list of zero-terminated strings containing the names of the
52          * cursor's buttons. The number of names in the list is the same as the
53          * number of buttons on the cursor. The names are separated by a single
54          * zero character; the list is terminated by two zero characters.
55          */
56     BYTE    BUTTONMAP[32];
57         /* a 32 byte array of logical button numbers, one for each physical
58          * button.
59          */
60     BYTE    SYSBTNMAP[32];
61         /* a 32 byte array of button action codes, one for each logical
62          * button.
63          */
64     BYTE    NPBUTTON;
65         /* the physical button number of the button that is controlled by normal
66          * pressure.
67          */
68     UINT    NPBTNMARKS[2];
69         /* an array of two UINTs, specifying the button marks for the normal
70          * pressure button. The first UINT contains the release mark; the second
71          * contains the press mark.
72          */
73     UINT    *NPRESPONSE;
74         /* an array of UINTs describing the pressure response curve for normal
75          * pressure.
76          */
77     BYTE    TPBUTTON;
78         /* the physical button number of the button that is controlled by
79          * tangential pressure.
80          */
81     UINT    TPBTNMARKS[2];
82         /* an array of two UINTs, specifying the button marks for the tangential
83          * pressure button. The first UINT contains the release mark; the second
84          * contains the press mark.
85          */
86     UINT    *TPRESPONSE;
87         /* an array of UINTs describing the pressure response curve for
88          * tangential pressure.
89          */
90     DWORD   PHYSID;
91          /* a manufacturer-specific physical identifier for the cursor. This
92           * value will distinguish the physical cursor from others on the same
93           * device. This physical identifier allows applications to bind
94           * functions to specific physical cursors, even if category numbers
95           * change and multiple, otherwise identical, physical cursors are
96           * present.
97           */
98     UINT    MODE;
99         /* the cursor mode number of this cursor type, if this cursor type has
100          * the CRC_MULTIMODE capability.
101          */
102     UINT    MINPKTDATA;
103         /* the minimum set of data available from a physical cursor in this
104          * cursor type, if this cursor type has the CRC_AGGREGATE capability.
105          */
106     UINT    MINBUTTONS;
107         /* the minimum number of buttons of physical cursors in the cursor type,
108          * if this cursor type has the CRC_AGGREGATE capability.
109          */
110     UINT    CAPABILITIES;
111         /* flags indicating cursor capabilities, as defined below:
112             CRC_MULTIMODE
113                 Indicates this cursor type describes one of several modes of a
114                 single physical cursor. Consecutive cursor type categories
115                 describe the modes; the CSR_MODE data item gives the mode number
116                 of each cursor type.
117             CRC_AGGREGATE
118                 Indicates this cursor type describes several physical cursors
119                 that cannot be distinguished by software.
120             CRC_INVERT
121                 Indicates this cursor type describes the physical cursor in its
122                 inverted orientation; the previous consecutive cursor type
123                 category describes the normal orientation.
124          */
125     UINT    TYPE;
126         /* Manufacturer Unique id for the item type */
127 } WTI_CURSORS_INFO, *LPWTI_CURSORS_INFO;
128
129
130 typedef struct tagWTI_DEVICES_INFO
131 {
132     CHAR   NAME[256];
133         /* a displayable null- terminated string describing the device,
134          * manufacturer, and revision level.
135          */
136     UINT    HARDWARE;
137         /* flags indicating hardware and driver capabilities, as defined
138          * below:
139             HWC_INTEGRATED:
140                 Indicates that the display and digitizer share the same surface.
141             HWC_TOUCH
142                 Indicates that the cursor must be in physical contact with the
143                 device to report position.
144             HWC_HARDPROX
145                 Indicates that device can generate events when the cursor is
146                 entering and leaving the physical detection range.
147             HWC_PHYSID_CURSORS
148                 Indicates that device can uniquely identify the active cursor in
149                 hardware.
150          */
151     UINT    NCSRTYPES;
152         /* the number of supported cursor types.*/
153     UINT    FIRSTCSR;
154         /* the first cursor type number for the device. */
155     UINT    PKTRATE;
156         /* the maximum packet report rate in Hertz. */
157     WTPKT   PKTDATA;
158         /* a bit mask indicating which packet data items are always available.*/
159     WTPKT   PKTMODE;
160         /* a bit mask indicating which packet data items are physically
161          * relative, i.e., items for which the hardware can only report change,
162          * not absolute measurement.
163          */
164     WTPKT   CSRDATA;
165         /* a bit mask indicating which packet data items are only available when
166          * certain cursors are connected. The individual cursor descriptions
167          * must be consulted to determine which cursors return which data.
168          */
169     INT     XMARGIN;
170     INT     YMARGIN;
171     INT     ZMARGIN;
172         /* the size of tablet context margins in tablet native coordinates, in
173          * the x, y, and z directions, respectively.
174          */
175     AXIS    X;
176     AXIS    Y;
177     AXIS    Z;
178         /* the tablet's range and resolution capabilities, in the x, y, and z
179          * axes, respectively.
180          */
181     AXIS    NPRESSURE;
182     AXIS    TPRESSURE;
183         /* the tablet's range and resolution capabilities, for the normal and
184          * tangential pressure inputs, respectively.
185          */
186     AXIS    ORIENTATION[3];
187         /* a 3-element array describing the tablet's orientation range and
188          * resolution capabilities.
189          */
190     AXIS    ROTATION[3];
191         /* a 3-element array describing the tablet's rotation range and
192          * resolution capabilities.
193          */
194     CHAR   PNPID[256];
195         /* a null-terminated string containing the devices Plug and Play ID.*/
196 }   WTI_DEVICES_INFO, *LPWTI_DEVICES_INFO;
197
198 typedef struct tagWTPACKET {
199         HCTX pkContext;
200         UINT pkStatus;
201         LONG pkTime;
202         WTPKT pkChanged;
203         UINT pkSerialNumber;
204         UINT pkCursor;
205         DWORD pkButtons;
206         DWORD pkX;
207         DWORD pkY;
208         DWORD pkZ;
209         UINT pkNormalPressure;
210         UINT pkTangentPressure;
211         ORIENTATION pkOrientation;
212         ROTATION pkRotation; /* 1.1 */
213 } WTPACKET, *LPWTPACKET;
214
215
216 #ifdef HAVE_X11_EXTENSIONS_XINPUT_H
217
218 #include <X11/Xlib.h>
219 #include <X11/extensions/XInput.h>
220
221 static int           motion_type;
222 static int           button_press_type;
223 static int           button_release_type;
224 static int           key_press_type;
225 static int           key_release_type;
226 static int           proximity_in_type;
227 static int           proximity_out_type;
228
229 static HWND          hwndTabletDefault;
230 static WTPACKET      gMsgPacket;
231 static DWORD         gSerial;
232 static INT           button_state[10];
233
234 #define             CURSORMAX 10
235
236 static LOGCONTEXTA      gSysContext;
237 static WTI_DEVICES_INFO gSysDevice;
238 static WTI_CURSORS_INFO gSysCursor[CURSORMAX];
239 static INT              gNumCursors;
240
241
242 #ifndef SONAME_LIBXI
243 #define SONAME_LIBXI "libXi.so"
244 #endif
245
246 /* XInput stuff */
247 static void *xinput_handle;
248
249 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
250 MAKE_FUNCPTR(XListInputDevices)
251 MAKE_FUNCPTR(XFreeDeviceList)
252 MAKE_FUNCPTR(XOpenDevice)
253 MAKE_FUNCPTR(XQueryDeviceState)
254 MAKE_FUNCPTR(XGetDeviceButtonMapping)
255 MAKE_FUNCPTR(XCloseDevice)
256 MAKE_FUNCPTR(XSelectExtensionEvent)
257 MAKE_FUNCPTR(XFreeDeviceState)
258 #undef MAKE_FUNCPTR
259
260 static INT X11DRV_XInput_Init(void)
261 {
262     xinput_handle = wine_dlopen(SONAME_LIBXI, RTLD_NOW, NULL, 0);
263     if (xinput_handle)
264     {
265 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xinput_handle, #f, NULL, 0)) == NULL) goto sym_not_found;
266         LOAD_FUNCPTR(XListInputDevices)
267         LOAD_FUNCPTR(XFreeDeviceList)
268         LOAD_FUNCPTR(XOpenDevice)
269         LOAD_FUNCPTR(XGetDeviceButtonMapping)
270         LOAD_FUNCPTR(XCloseDevice)
271         LOAD_FUNCPTR(XSelectExtensionEvent)
272         LOAD_FUNCPTR(XQueryDeviceState)
273         LOAD_FUNCPTR(XFreeDeviceState)
274 #undef LOAD_FUNCPTR
275         return 1;
276     }
277 sym_not_found:
278     return 0;
279 }
280
281 static int Tablet_ErrorHandler(Display *dpy, XErrorEvent *event, void* arg)
282 {
283     return 1;
284 }
285
286 void X11DRV_LoadTabletInfo(HWND hwnddefault)
287 {
288     struct x11drv_thread_data *data = x11drv_thread_data();
289     int num_devices;
290     int loop;
291     int cursor_target;
292     XDeviceInfo *devices;
293     XDeviceInfo *target = NULL;
294     BOOL    axis_read_complete= FALSE;
295
296     XAnyClassPtr        any;
297     XButtonInfoPtr      Button;
298     XValuatorInfoPtr    Val;
299     XAxisInfoPtr        Axis;
300
301     XDevice *opendevice;
302
303     if (!X11DRV_XInput_Init())
304     {
305         ERR("Unable to initialized the XInput library.\n");
306         return;
307     }
308
309     hwndTabletDefault = hwnddefault;
310
311     /* Do base initializaion */
312     strcpy(gSysContext.lcName, "Wine Tablet Context");
313     strcpy(gSysDevice.NAME,"Wine Tablet Device");
314
315     gSysContext.lcOptions = CXO_SYSTEM;
316     gSysContext.lcLocks = CXL_INSIZE | CXL_INASPECT | CXL_MARGIN |
317                                CXL_SENSITIVITY | CXL_SYSOUT;
318
319     gSysContext.lcMsgBase= WT_DEFBASE;
320     gSysContext.lcDevice = 0;
321     gSysContext.lcPktData =
322         PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
323         PK_BUTTONS |  PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
324     gSysContext.lcMoveMask=
325         PK_BUTTONS |  PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
326     gSysContext.lcStatus = CXS_ONTOP;
327     gSysContext.lcPktRate = 100;
328     gSysContext.lcBtnDnMask = 0xffffffff;
329     gSysContext.lcBtnUpMask = 0xffffffff;
330     gSysContext.lcSensX = 65536;
331     gSysContext.lcSensY = 65536;
332     gSysContext.lcSensX = 65536;
333     gSysContext.lcSensZ = 65536;
334     gSysContext.lcSysSensX= 65536;
335     gSysContext.lcSysSensY= 65536;
336
337     /* Device Defaults */
338     gSysDevice.HARDWARE = HWC_HARDPROX|HWC_PHYSID_CURSORS;
339     gSysDevice.FIRSTCSR= 0;
340     gSysDevice.PKTRATE = 100;
341     gSysDevice.PKTDATA =
342         PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
343         PK_BUTTONS |  PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
344     strcpy(gSysDevice.PNPID,"non-pluginplay");
345
346     wine_tsx11_lock();
347
348     cursor_target = -1;
349     devices = pXListInputDevices(data->display, &num_devices);
350     if (!devices)
351     {
352         WARN("XInput Extenstions reported as not avalable\n");
353         wine_tsx11_unlock();
354         return;
355     }
356     for (loop=0; loop < num_devices; loop++)
357     {
358         int class_loop;
359
360         TRACE("Trying device %i(%s)\n",loop,devices[loop].name);
361         if (devices[loop].use == IsXExtensionDevice)
362         {
363             LPWTI_CURSORS_INFO cursor;
364
365             TRACE("Is Extension Device\n");
366             cursor_target++;
367             target = &devices[loop];
368             cursor = &gSysCursor[cursor_target];
369
370             opendevice = pXOpenDevice(data->display,target->id);
371             if (opendevice)
372             {
373                 unsigned char map[32];
374                 int i;
375                 int shft = 0;
376
377                 X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
378                 pXGetDeviceButtonMapping(data->display, opendevice, map, 32);
379                 if (X11DRV_check_error())
380                 {
381                     TRACE("No buttons, Non Tablet Device\n");
382                     pXCloseDevice(data->display, opendevice);
383                     cursor_target --;
384                     continue;
385                 }
386
387                 for (i=0; i< cursor->BUTTONS; i++,shft++)
388                 {
389                     cursor->BUTTONMAP[i] = map[i];
390                     cursor->SYSBTNMAP[i] = (1<<shft);
391                 }
392                 pXCloseDevice(data->display, opendevice);
393             }
394             else
395             {
396                 WARN("Unable to open device %s\n",target->name);
397                 cursor_target --;
398                 continue;
399             }
400
401             strcpy(cursor->NAME,target->name);
402
403             cursor->ACTIVE = 1;
404             cursor->PKTDATA = PK_TIME | PK_CURSOR | PK_BUTTONS |  PK_X | PK_Y |
405                               PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE |
406                               PK_ORIENTATION;
407
408             cursor->PHYSID = cursor_target;
409             cursor->NPBUTTON = 1;
410             cursor->NPBTNMARKS[0] = 0 ;
411             cursor->NPBTNMARKS[1] = 1 ;
412             cursor->CAPABILITIES = CRC_MULTIMODE;
413             if (strcasecmp(cursor->NAME,"stylus")==0)
414                 cursor->TYPE = 0x4825;
415             if (strcasecmp(cursor->NAME,"eraser")==0)
416                 cursor->TYPE = 0xc85a;
417
418
419             any = (XAnyClassPtr) (target->inputclassinfo);
420
421             for (class_loop = 0; class_loop < target->num_classes; class_loop++)
422             {
423                 switch (any->class)
424                 {
425                     case ValuatorClass:
426                         if (!axis_read_complete)
427                         {
428                             Val = (XValuatorInfoPtr) any;
429                             Axis = (XAxisInfoPtr) ((char *) Val + sizeof
430                                 (XValuatorInfo));
431
432                             if (Val->num_axes>=1)
433                             {
434                                 /* Axis 1 is X */
435                                 gSysDevice.X.axMin = Axis->min_value;
436                                 gSysDevice.X.axMax= Axis->max_value;
437                                 gSysDevice.X.axUnits = TU_INCHES;
438                                 gSysDevice.X.axResolution = Axis->resolution;
439                                 gSysContext.lcInOrgX = Axis->min_value;
440                                 gSysContext.lcSysOrgX = Axis->min_value;
441                                 gSysContext.lcInExtX = Axis->max_value;
442                                 gSysContext.lcSysExtX = Axis->max_value;
443                                 Axis++;
444                             }
445                             if (Val->num_axes>=2)
446                             {
447                                 /* Axis 2 is Y */
448                                 gSysDevice.Y.axMin = Axis->min_value;
449                                 gSysDevice.Y.axMax= Axis->max_value;
450                                 gSysDevice.Y.axUnits = TU_INCHES;
451                                 gSysDevice.Y.axResolution = Axis->resolution;
452                                 gSysContext.lcInOrgY = Axis->min_value;
453                                 gSysContext.lcSysOrgY = Axis->min_value;
454                                 gSysContext.lcInExtY = Axis->max_value;
455                                 gSysContext.lcSysExtY = Axis->max_value;
456                                 Axis++;
457                             }
458                             if (Val->num_axes>=3)
459                             {
460                                 /* Axis 3 is Normal Pressure */
461                                 gSysDevice.NPRESSURE.axMin = Axis->min_value;
462                                 gSysDevice.NPRESSURE.axMax= Axis->max_value;
463                                 gSysDevice.NPRESSURE.axUnits = TU_INCHES;
464                                 gSysDevice.NPRESSURE.axResolution =
465                                                         Axis->resolution;
466                                 Axis++;
467                             }
468                             if (Val->num_axes >= 5)
469                             {
470                                 /* Axis 4 and 5 are X and Y tilt */
471                                 XAxisInfoPtr        XAxis = Axis;
472                                 Axis++;
473                                 if (max (abs(Axis->max_value),
474                                          abs(XAxis->max_value)))
475                                 {
476                                     gSysDevice.ORIENTATION[0].axMin = 0;
477                                     gSysDevice.ORIENTATION[0].axMax = 3600;
478                                     gSysDevice.ORIENTATION[0].axUnits = TU_CIRCLE;
479                                     gSysDevice.ORIENTATION[0].axResolution
480                                                                 = CASTFIX32(3600);
481                                     gSysDevice.ORIENTATION[1].axMin = -1000;
482                                     gSysDevice.ORIENTATION[1].axMax = 1000;
483                                     gSysDevice.ORIENTATION[1].axUnits = TU_CIRCLE;
484                                     gSysDevice.ORIENTATION[1].axResolution
485                                                                 = CASTFIX32(3600);
486                                     Axis++;
487                                 }
488                             }
489                             axis_read_complete = TRUE;
490                         }
491                         break;
492                     case ButtonClass:
493                     {
494                         CHAR *ptr = cursor->BTNNAMES;
495                         int i;
496
497                         Button = (XButtonInfoPtr) any;
498                         cursor->BUTTONS = Button->num_buttons;
499                         for (i = 0; i < cursor->BUTTONS; i++)
500                         {
501                             strcpy(ptr,cursor->NAME);
502                             ptr+=8;
503                         }
504                     }
505                     break;
506                 }
507                 any = (XAnyClassPtr) ((char*) any + any->length);
508             }
509         }
510     }
511     pXFreeDeviceList(devices);
512     wine_tsx11_unlock();
513     gSysDevice.NCSRTYPES = cursor_target+1;
514     gNumCursors = cursor_target+1;
515 }
516
517 static int figure_deg(int x, int y)
518 {
519     int rc;
520
521     if (y != 0)
522     {
523         rc = (int) 10 * (atan( (FLOAT)abs(y) / (FLOAT)abs(x)) / (3.1415 / 180));
524         if (y>0)
525         {
526             if (x>0)
527                 rc += 900;
528             else
529                 rc = 2700 - rc;
530         }
531         else
532         {
533             if (x>0)
534                 rc = 900 - rc;
535             else
536                 rc += 2700;
537         }
538     }
539     else
540     {
541         if (x >= 0)
542             rc = 900;
543         else
544             rc = 2700;
545     }
546
547     return rc;
548 }
549
550 static int get_button_state(int deviceid)
551 {
552     return button_state[deviceid];
553 }
554
555 static void set_button_state(XID deviceid)
556 {
557     struct x11drv_thread_data *data = x11drv_thread_data();
558     XDevice *device;
559     XDeviceState *state;
560     XInputClass  *class;
561     int loop;
562     int rc = 0;
563
564     wine_tsx11_lock();
565     device = pXOpenDevice(data->display,deviceid);
566     state = pXQueryDeviceState(data->display,device);
567
568     if (state)
569     {
570         class = state->data;
571         for (loop = 0; loop < state->num_classes; loop++)
572         {
573             if (class->class == ButtonClass)
574             {
575                 int loop2;
576                 XButtonState *button_state =  (XButtonState*)class;
577                 for (loop2 = 1; loop2 <= button_state->num_buttons; loop2++)
578                 {
579                     if (button_state->buttons[loop2 / 8] & (1 << (loop2 % 8)))
580                     {
581                         rc |= (1<<(loop2-1));
582                     }
583                 }
584             }
585             class = (XInputClass *) ((char *) class + class->length);
586         }
587     }
588     pXFreeDeviceState(state);
589     wine_tsx11_unlock();
590     button_state[deviceid] = rc;
591 }
592
593 static void motion_event( HWND hwnd, XEvent *event )
594 {
595     XDeviceMotionEvent *motion = (XDeviceMotionEvent *)event;
596     LPWTI_CURSORS_INFO cursor = &gSysCursor[motion->deviceid];
597
598     memset(&gMsgPacket,0,sizeof(WTPACKET));
599
600     TRACE("Received tablet motion event (%p)\n",hwnd);
601
602     /* Set cursor to inverted if cursor is the eraser */
603     gMsgPacket.pkStatus = (cursor->TYPE == 0xc85a ?TPS_INVERT:0);
604     gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(motion->time);
605     gMsgPacket.pkSerialNumber = gSerial++;
606     gMsgPacket.pkCursor = motion->deviceid;
607     gMsgPacket.pkX = motion->axis_data[0];
608     gMsgPacket.pkY = motion->axis_data[1];
609     gMsgPacket.pkOrientation.orAzimuth = figure_deg(motion->axis_data[3],motion->axis_data[4]);
610     gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max
611                                             (abs(motion->axis_data[3]),
612                                              abs(motion->axis_data[4])))
613                                            * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
614     gMsgPacket.pkNormalPressure = motion->axis_data[2];
615     gMsgPacket.pkButtons = get_button_state(motion->deviceid);
616     SendMessageW(hwndTabletDefault,WT_PACKET,0,(LPARAM)hwnd);
617 }
618
619 static void button_event( HWND hwnd, XEvent *event )
620 {
621     XDeviceButtonEvent *button = (XDeviceButtonEvent *) event;
622     LPWTI_CURSORS_INFO cursor = &gSysCursor[button->deviceid];
623
624     memset(&gMsgPacket,0,sizeof(WTPACKET));
625
626     TRACE("Received tablet button %s event\n", (event->type == button_press_type)?"press":"release");
627
628     /* Set cursor to inverted if cursor is the eraser */
629     gMsgPacket.pkStatus = (cursor->TYPE == 0xc85a ?TPS_INVERT:0);
630     set_button_state(button->deviceid);
631     gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(button->time);
632     gMsgPacket.pkSerialNumber = gSerial++;
633     gMsgPacket.pkCursor = button->deviceid;
634     gMsgPacket.pkX = button->axis_data[0];
635     gMsgPacket.pkY = button->axis_data[1];
636     gMsgPacket.pkOrientation.orAzimuth = figure_deg(button->axis_data[3],button->axis_data[4]);
637     gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(button->axis_data[3]),
638                                                             abs(button->axis_data[4])))
639                                            * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
640     gMsgPacket.pkNormalPressure = button->axis_data[2];
641     gMsgPacket.pkButtons = get_button_state(button->deviceid);
642     SendMessageW(hwndTabletDefault,WT_PACKET,0,(LPARAM)hwnd);
643 }
644
645 static void key_event( HWND hwnd, XEvent *event )
646 {
647     if (event->type == key_press_type)
648         FIXME("Received tablet key press event\n");
649     else
650         FIXME("Received tablet key release event\n");
651 }
652
653 static void proximity_event( HWND hwnd, XEvent *event )
654 {
655     XProximityNotifyEvent *proximity = (XProximityNotifyEvent *) event;
656     LPWTI_CURSORS_INFO cursor = &gSysCursor[proximity->deviceid];
657
658     memset(&gMsgPacket,0,sizeof(WTPACKET));
659
660     TRACE("Received tablet proximity event\n");
661     /* Set cursor to inverted if cursor is the eraser */
662     gMsgPacket.pkStatus = (cursor->TYPE == 0xc85a ?TPS_INVERT:0);
663     gMsgPacket.pkStatus |= (event->type==proximity_out_type)?TPS_PROXIMITY:0;
664     gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(proximity->time);
665     gMsgPacket.pkSerialNumber = gSerial++;
666     gMsgPacket.pkCursor = proximity->deviceid;
667     gMsgPacket.pkX = proximity->axis_data[0];
668     gMsgPacket.pkY = proximity->axis_data[1];
669     gMsgPacket.pkOrientation.orAzimuth = figure_deg(proximity->axis_data[3],proximity->axis_data[4]);
670     gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(proximity->axis_data[3]),
671                                                             abs(proximity->axis_data[4])))
672                                            * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
673     gMsgPacket.pkNormalPressure = proximity->axis_data[2];
674     gMsgPacket.pkButtons = get_button_state(proximity->deviceid);
675
676     SendMessageW(hwndTabletDefault, WT_PROXIMITY, (event->type == proximity_in_type), (LPARAM)hwnd);
677 }
678
679 int X11DRV_AttachEventQueueToTablet(HWND hOwner)
680 {
681     struct x11drv_thread_data *data = x11drv_thread_data();
682     int             num_devices;
683     int             loop;
684     int             cur_loop;
685     XDeviceInfo     *devices;
686     XDeviceInfo     *target = NULL;
687     XDevice         *the_device;
688     XEventClass     event_list[7];
689     Window          win = X11DRV_get_whole_window( hOwner );
690
691     if (!win) return 0;
692
693     TRACE("Creating context for window %p (%lx)  %i cursors\n", hOwner, win, gNumCursors);
694
695     wine_tsx11_lock();
696     devices = pXListInputDevices(data->display, &num_devices);
697
698     X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
699     for (cur_loop=0; cur_loop < gNumCursors; cur_loop++)
700     {
701         int    event_number=0;
702
703         for (loop=0; loop < num_devices; loop ++)
704             if (strcmp(devices[loop].name,gSysCursor[cur_loop].NAME)==0)
705                 target = &devices[loop];
706
707         TRACE("Opening cursor %i id %i\n",cur_loop,(INT)target->id);
708
709         the_device = pXOpenDevice(data->display, target->id);
710
711         if (!the_device)
712         {
713             WARN("Unable to Open device\n");
714             continue;
715         }
716
717         if (the_device->num_classes > 0)
718         {
719             DeviceKeyPress(the_device, key_press_type, event_list[event_number]);
720             if (event_list[event_number]) event_number++;
721             DeviceKeyRelease(the_device, key_release_type, event_list[event_number]);
722             if (event_list[event_number]) event_number++;
723             DeviceButtonPress(the_device, button_press_type, event_list[event_number]);
724             if (event_list[event_number]) event_number++;
725             DeviceButtonRelease(the_device, button_release_type, event_list[event_number]);
726             if (event_list[event_number]) event_number++;
727             DeviceMotionNotify(the_device, motion_type, event_list[event_number]);
728             if (event_list[event_number]) event_number++;
729             ProximityIn(the_device, proximity_in_type, event_list[event_number]);
730             if (event_list[event_number]) event_number++;
731             ProximityOut(the_device, proximity_out_type, event_list[event_number]);
732             if (event_list[event_number]) event_number++;
733
734             if (key_press_type) X11DRV_register_event_handler( key_press_type, key_event );
735             if (key_release_type) X11DRV_register_event_handler( key_release_type, key_event );
736             if (button_press_type) X11DRV_register_event_handler( button_press_type, button_event );
737             if (button_release_type) X11DRV_register_event_handler( button_release_type, button_event );
738             if (motion_type) X11DRV_register_event_handler( motion_type, motion_event );
739             if (proximity_in_type) X11DRV_register_event_handler( proximity_in_type, proximity_event );
740             if (proximity_out_type) X11DRV_register_event_handler( proximity_out_type, proximity_event );
741
742             pXSelectExtensionEvent(data->display, win, event_list, event_number);
743         }
744     }
745     XSync(data->display, False);
746     X11DRV_check_error();
747
748     if (NULL != devices) pXFreeDeviceList(devices);
749     wine_tsx11_unlock();
750     return 0;
751 }
752
753 int X11DRV_GetCurrentPacket(LPWTPACKET *packet)
754 {
755     memcpy(packet,&gMsgPacket,sizeof(WTPACKET));
756     return 1;
757 }
758
759
760 int static inline CopyTabletData(LPVOID target, LPVOID src, INT size)
761 {
762     /*
763      * It is valid to call CopyTabletData with NULL.
764      * This handles the WTInfo() case where lpOutput is null.
765      */
766     if(target != NULL)
767         memcpy(target,src,size);
768     return(size);
769 }
770
771 /***********************************************************************
772  *              X11DRV_WTInfoA (X11DRV.@)
773  */
774 UINT X11DRV_WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
775 {
776     /*
777      * It is valid to call WTInfoA with lpOutput == NULL, as per standard.
778      * lpOutput == NULL signifies the user only wishes
779      * to find the size of the data.
780      * NOTE:
781      * From now on use CopyTabletData to fill lpOutput. memcpy will break
782      * the code.
783      */
784     int rc = 0;
785     LPWTI_CURSORS_INFO  tgtcursor;
786     TRACE("(%u, %u, %p)\n", wCategory, nIndex, lpOutput);
787
788     switch(wCategory)
789     {
790         case 0:
791             /* return largest necessary buffer */
792             TRACE("%i cursors\n",gNumCursors);
793             if (gNumCursors>0)
794             {
795                 FIXME("Return proper size\n");
796                 rc = 200;
797             }
798             break;
799         case WTI_INTERFACE:
800             switch (nIndex)
801             {
802                 WORD version;
803                 case IFC_WINTABID:
804                     strcpy(lpOutput,"Wine Wintab 1.1");
805                     rc = 16;
806                     break;
807                 case IFC_SPECVERSION:
808                     version = (0x01) | (0x01 << 8);
809                     rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
810                     break;
811                 case IFC_IMPLVERSION:
812                     version = (0x00) | (0x01 << 8);
813                     rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
814                     break;
815                 default:
816                     FIXME("WTI_INTERFACE unhandled index %i\n",nIndex);
817                     rc = 0;
818
819             }
820         case WTI_DEFSYSCTX:
821         case WTI_DDCTXS:
822         case WTI_DEFCONTEXT:
823             switch (nIndex)
824             {
825                 case 0:
826                     rc = CopyTabletData(lpOutput, &gSysContext,
827                             sizeof(LOGCONTEXTA));
828                     break;
829                 case CTX_NAME:
830                     rc = CopyTabletData(lpOutput, &gSysContext.lcName,
831                          strlen(gSysContext.lcName)+1);
832                     break;
833                 case CTX_OPTIONS:
834                     rc = CopyTabletData(lpOutput, &gSysContext.lcOptions,
835                                         sizeof(UINT));
836                     break;
837                 case CTX_STATUS:
838                     rc = CopyTabletData(lpOutput, &gSysContext.lcStatus,
839                                         sizeof(UINT));
840                     break;
841                 case CTX_LOCKS:
842                     rc= CopyTabletData (lpOutput, &gSysContext.lcLocks,
843                                         sizeof(UINT));
844                     break;
845                 case CTX_MSGBASE:
846                     rc = CopyTabletData(lpOutput, &gSysContext.lcMsgBase,
847                                         sizeof(UINT));
848                     break;
849                 case CTX_DEVICE:
850                     rc = CopyTabletData(lpOutput, &gSysContext.lcDevice,
851                                         sizeof(UINT));
852                     break;
853                 case CTX_PKTRATE:
854                     rc = CopyTabletData(lpOutput, &gSysContext.lcPktRate,
855                                         sizeof(UINT));
856                     break;
857                 case CTX_PKTMODE:
858                     rc = CopyTabletData(lpOutput, &gSysContext.lcPktMode,
859                                         sizeof(WTPKT));
860                     break;
861                 case CTX_MOVEMASK:
862                     rc = CopyTabletData(lpOutput, &gSysContext.lcMoveMask,
863                                         sizeof(WTPKT));
864                     break;
865                 case CTX_BTNDNMASK:
866                     rc = CopyTabletData(lpOutput, &gSysContext.lcBtnDnMask,
867                                         sizeof(DWORD));
868                     break;
869                 case CTX_BTNUPMASK:
870                     rc = CopyTabletData(lpOutput, &gSysContext.lcBtnUpMask,
871                                         sizeof(DWORD));
872                     break;
873                 case CTX_INORGX:
874                     rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgX,
875                                         sizeof(LONG));
876                     break;
877                 case CTX_INORGY:
878                     rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgY,
879                                         sizeof(LONG));
880                     break;
881                 case CTX_INORGZ:
882                     rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgZ,
883                                         sizeof(LONG));
884                     break;
885                 case CTX_INEXTX:
886                     rc = CopyTabletData(lpOutput, &gSysContext.lcInExtX,
887                                         sizeof(LONG));
888                     break;
889                 case CTX_INEXTY:
890                      rc = CopyTabletData(lpOutput, &gSysContext.lcInExtY,
891                                         sizeof(LONG));
892                     break;
893                 case CTX_INEXTZ:
894                      rc = CopyTabletData(lpOutput, &gSysContext.lcInExtZ,
895                                         sizeof(LONG));
896                     break;
897                 case CTX_OUTORGX:
898                      rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgX,
899                                         sizeof(LONG));
900                     break;
901                 case CTX_OUTORGY:
902                       rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgY,
903                                         sizeof(LONG));
904                     break;
905                 case CTX_OUTORGZ:
906                        rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgZ,
907                                         sizeof(LONG));
908                     break;
909                case CTX_OUTEXTX:
910                       rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtX,
911                                         sizeof(LONG));
912                     break;
913                 case CTX_OUTEXTY:
914                        rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtY,
915                                         sizeof(LONG));
916                     break;
917                 case CTX_OUTEXTZ:
918                        rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtZ,
919                                         sizeof(LONG));
920                     break;
921                 case CTX_SENSX:
922                         rc = CopyTabletData(lpOutput, &gSysContext.lcSensX,
923                                         sizeof(LONG));
924                     break;
925                 case CTX_SENSY:
926                         rc = CopyTabletData(lpOutput, &gSysContext.lcSensY,
927                                         sizeof(LONG));
928                     break;
929                 case CTX_SENSZ:
930                         rc = CopyTabletData(lpOutput, &gSysContext.lcSensZ,
931                                         sizeof(LONG));
932                     break;
933                 case CTX_SYSMODE:
934                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysMode,
935                                         sizeof(LONG));
936                     break;
937                 case CTX_SYSORGX:
938                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgX,
939                                         sizeof(LONG));
940                     break;
941                 case CTX_SYSORGY:
942                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgY,
943                                         sizeof(LONG));
944                     break;
945                 case CTX_SYSEXTX:
946                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtX,
947                                         sizeof(LONG));
948                     break;
949                 case CTX_SYSEXTY:
950                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtY,
951                                         sizeof(LONG));
952                     break;
953                 case CTX_SYSSENSX:
954                         rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensX,
955                                         sizeof(LONG));
956                     break;
957                 case CTX_SYSSENSY:
958                        rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensY,
959                                         sizeof(LONG));
960                     break;
961                 default:
962                     FIXME("WTI_DEFSYSCTX unhandled index %i\n",nIndex);
963                     rc = 0;
964             }
965             break;
966         case WTI_CURSORS:
967         case WTI_CURSORS+1:
968         case WTI_CURSORS+2:
969         case WTI_CURSORS+3:
970         case WTI_CURSORS+4:
971         case WTI_CURSORS+5:
972         case WTI_CURSORS+6:
973         case WTI_CURSORS+7:
974         case WTI_CURSORS+8:
975         case WTI_CURSORS+9:
976             tgtcursor = &gSysCursor[wCategory - WTI_CURSORS];
977             switch (nIndex)
978             {
979                 case CSR_NAME:
980                     rc = CopyTabletData(lpOutput, &tgtcursor->NAME,
981                                         strlen(tgtcursor->NAME)+1);
982                     break;
983                 case CSR_ACTIVE:
984                     rc = CopyTabletData(lpOutput,&tgtcursor->ACTIVE,
985                                         sizeof(BOOL));
986                     break;
987                 case CSR_PKTDATA:
988                     rc = CopyTabletData(lpOutput,&tgtcursor->PKTDATA,
989                                         sizeof(WTPKT));
990                     break;
991                 case CSR_BUTTONS:
992                     rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONS,
993                                         sizeof(BYTE));
994                     break;
995                 case CSR_BUTTONBITS:
996                     rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONBITS,
997                                         sizeof(BYTE));
998                     break;
999                 case CSR_BTNNAMES:
1000                     FIXME("Button Names not returned correctly\n");
1001                     rc = CopyTabletData(lpOutput,&tgtcursor->BTNNAMES,
1002                                         strlen(tgtcursor->BTNNAMES)+1);
1003                     break;
1004                 case CSR_BUTTONMAP:
1005                     rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONMAP,
1006                                         sizeof(BYTE)*32);
1007                     break;
1008                 case CSR_SYSBTNMAP:
1009                     rc = CopyTabletData(lpOutput,&tgtcursor->SYSBTNMAP,
1010                                         sizeof(BYTE)*32);
1011                     break;
1012                 case CSR_NPBTNMARKS:
1013                     rc = CopyTabletData(lpOutput,&tgtcursor->NPBTNMARKS,
1014                                         sizeof(UINT)*2);
1015                     break;
1016                 case CSR_NPBUTTON:
1017                     rc = CopyTabletData(lpOutput,&tgtcursor->NPBUTTON,
1018                                         sizeof(BYTE));
1019                     break;
1020                 case CSR_NPRESPONSE:
1021                     FIXME("Not returning CSR_NPRESPONSE correctly\n");
1022                     rc = 0;
1023                     break;
1024                 case CSR_TPBUTTON:
1025                     rc = CopyTabletData(lpOutput,&tgtcursor->TPBUTTON,
1026                                         sizeof(BYTE));
1027                     break;
1028                 case CSR_TPBTNMARKS:
1029                     rc = CopyTabletData(lpOutput,&tgtcursor->TPBTNMARKS,
1030                                         sizeof(UINT)*2);
1031                     break;
1032                 case CSR_TPRESPONSE:
1033                     FIXME("Not returning CSR_TPRESPONSE correctly\n");
1034                     rc = 0;
1035                     break;
1036                 case CSR_PHYSID:
1037                 {
1038                     DWORD id;
1039                     id = tgtcursor->PHYSID;
1040                     id += (wCategory - WTI_CURSORS);
1041                     rc = CopyTabletData(lpOutput,&id,sizeof(DWORD));
1042                 }
1043                     break;
1044                 case CSR_MODE:
1045                     rc = CopyTabletData(lpOutput,&tgtcursor->MODE,sizeof(UINT));
1046                     break;
1047                 case CSR_MINPKTDATA:
1048                     rc = CopyTabletData(lpOutput,&tgtcursor->MINPKTDATA,
1049                         sizeof(UINT));
1050                     break;
1051                 case CSR_MINBUTTONS:
1052                     rc = CopyTabletData(lpOutput,&tgtcursor->MINBUTTONS,
1053                         sizeof(UINT));
1054                     break;
1055                 case CSR_CAPABILITIES:
1056                     rc = CopyTabletData(lpOutput,&tgtcursor->CAPABILITIES,
1057                         sizeof(UINT));
1058                     break;
1059                 case CSR_TYPE:
1060                     rc = CopyTabletData(lpOutput,&tgtcursor->TYPE,
1061                         sizeof(UINT));
1062                     break;
1063                 default:
1064                     FIXME("WTI_CURSORS unhandled index %i\n",nIndex);
1065                     rc = 0;
1066             }
1067             break;
1068         case WTI_DEVICES:
1069             switch (nIndex)
1070             {
1071                 case DVC_NAME:
1072                     rc = CopyTabletData(lpOutput,gSysDevice.NAME,
1073                                         strlen(gSysDevice.NAME)+1);
1074                     break;
1075                 case DVC_HARDWARE:
1076                     rc = CopyTabletData(lpOutput,&gSysDevice.HARDWARE,
1077                                         sizeof(UINT));
1078                     break;
1079                 case DVC_NCSRTYPES:
1080                     rc = CopyTabletData(lpOutput,&gSysDevice.NCSRTYPES,
1081                                         sizeof(UINT));
1082                     break;
1083                 case DVC_FIRSTCSR:
1084                     rc = CopyTabletData(lpOutput,&gSysDevice.FIRSTCSR,
1085                                         sizeof(UINT));
1086                     break;
1087                 case DVC_PKTRATE:
1088                     rc = CopyTabletData(lpOutput,&gSysDevice.PKTRATE,
1089                                         sizeof(UINT));
1090                     break;
1091                 case DVC_PKTDATA:
1092                     rc = CopyTabletData(lpOutput,&gSysDevice.PKTDATA,
1093                                         sizeof(WTPKT));
1094                     break;
1095                 case DVC_PKTMODE:
1096                     rc = CopyTabletData(lpOutput,&gSysDevice.PKTMODE,
1097                                         sizeof(WTPKT));
1098                     break;
1099                 case DVC_CSRDATA:
1100                     rc = CopyTabletData(lpOutput,&gSysDevice.CSRDATA,
1101                                         sizeof(WTPKT));
1102                     break;
1103                 case DVC_XMARGIN:
1104                     rc = CopyTabletData(lpOutput,&gSysDevice.XMARGIN,
1105                                         sizeof(INT));
1106                     break;
1107                 case DVC_YMARGIN:
1108                     rc = CopyTabletData(lpOutput,&gSysDevice.YMARGIN,
1109                                         sizeof(INT));
1110                     break;
1111                 case DVC_ZMARGIN:
1112                     rc = 0; /* unsupported */
1113                     /*
1114                     rc = CopyTabletData(lpOutput,&gSysDevice.ZMARGIN,
1115                                         sizeof(INT));
1116                     */
1117                     break;
1118                 case DVC_X:
1119                     rc = CopyTabletData(lpOutput,&gSysDevice.X,
1120                                         sizeof(AXIS));
1121                     break;
1122                 case DVC_Y:
1123                     rc = CopyTabletData(lpOutput,&gSysDevice.Y,
1124                                         sizeof(AXIS));
1125                     break;
1126                 case DVC_Z:
1127                     rc = 0; /* unsupported */
1128                     /*
1129                     rc = CopyTabletData(lpOutput,&gSysDevice.Z,
1130                                         sizeof(AXIS));
1131                     */
1132                     break;
1133                 case DVC_NPRESSURE:
1134                     rc = CopyTabletData(lpOutput,&gSysDevice.NPRESSURE,
1135                                         sizeof(AXIS));
1136                     break;
1137                 case DVC_TPRESSURE:
1138                     rc = 0; /* unsupported */
1139                     /*
1140                     rc = CopyTabletData(lpOutput,&gSysDevice.TPRESSURE,
1141                                         sizeof(AXIS));
1142                     */
1143                     break;
1144                 case DVC_ORIENTATION:
1145                     rc = CopyTabletData(lpOutput,&gSysDevice.ORIENTATION,
1146                                         sizeof(AXIS)*3);
1147                     break;
1148                 case DVC_ROTATION:
1149                     rc = 0; /* unsupported */
1150                     /*
1151                     rc = CopyTabletData(lpOutput,&gSysDevice.ROTATION,
1152                                         sizeof(AXIS)*3);
1153                     */
1154                     break;
1155                 case DVC_PNPID:
1156                     rc = CopyTabletData(lpOutput,gSysDevice.PNPID,
1157                                         strlen(gSysDevice.PNPID)+1);
1158                     break;
1159                 default:
1160                     FIXME("WTI_DEVICES unhandled index %i\n",nIndex);
1161                     rc = 0;
1162             }
1163             break;
1164         default:
1165             FIXME("Unhandled Category %i\n",wCategory);
1166     }
1167     return rc;
1168 }
1169
1170 #else /* HAVE_X11_EXTENSIONS_XINPUT_H */
1171
1172 /***********************************************************************
1173  *              AttachEventQueueToTablet (X11DRV.@)
1174  */
1175 int X11DRV_AttachEventQueueToTablet(HWND hOwner)
1176 {
1177     return 0;
1178 }
1179
1180 /***********************************************************************
1181  *              GetCurrentPacket (X11DRV.@)
1182  */
1183 int X11DRV_GetCurrentPacket(LPWTPACKET *packet)
1184 {
1185     return 0;
1186 }
1187
1188 /***********************************************************************
1189  *              LoadTabletInfo (X11DRV.@)
1190  */
1191 void X11DRV_LoadTabletInfo(HWND hwnddefault)
1192 {
1193 }
1194
1195 /***********************************************************************
1196  *              WTInfoA (X11DRV.@)
1197  */
1198 UINT X11DRV_WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
1199 {
1200     return 0;
1201 }
1202
1203 #endif /* HAVE_X11_EXTENSIONS_XINPUT_H */