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