Packets from eraser cursors are marked as inverted, matching behavior
[wine/multimedia.git] / dlls / x11drv / wintab.c
blob7166b04e4aac00043d5bff2a3f888d679dfc805a
1 /*
2 * X11 tablet driver
4 * Copyright 2003 CodeWeavers (Aric Stewart)
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.
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.
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdlib.h>
26 #include "windef.h"
27 #include "x11drv.h"
28 #include "wine/library.h"
29 #include "wine/debug.h"
30 #include "wintab.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(wintab32);
33 WINE_DECLARE_DEBUG_CHANNEL(event);
35 typedef struct tagWTI_CURSORS_INFO
37 CHAR NAME[256];
38 /* a displayable zero-terminated string containing the name of the
39 * cursor.
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.
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.
57 BYTE BUTTONMAP[32];
58 /* a 32 byte array of logical button numbers, one for each physical
59 * button.
61 BYTE SYSBTNMAP[32];
62 /* a 32 byte array of button action codes, one for each logical
63 * button.
65 BYTE NPBUTTON;
66 /* the physical button number of the button that is controlled by normal
67 * pressure.
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.
74 UINT *NPRESPONSE;
75 /* an array of UINTs describing the pressure response curve for normal
76 * pressure.
78 BYTE TPBUTTON;
79 /* the physical button number of the button that is controlled by
80 * tangential pressure.
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.
87 UINT *TPRESPONSE;
88 /* an array of UINTs describing the pressure response curve for
89 * tangential pressure.
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.
99 UINT MODE;
100 /* the cursor mode number of this cursor type, if this cursor type has
101 * the CRC_MULTIMODE capability.
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.
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.
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.
126 UINT TYPE;
127 /* Manufacturer Unique id for the item type */
128 } WTI_CURSORS_INFO, *LPWTI_CURSORS_INFO;
131 typedef struct tagWTI_DEVICES_INFO
133 CHAR NAME[256];
134 /* a displayable null- terminated string describing the device,
135 * manufacturer, and revision level.
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.
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.
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.
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.
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.
182 AXIS NPRESSURE;
183 AXIS TPRESSURE;
184 /* the tablet's range and resolution capabilities, for the normal and
185 * tangential pressure inputs, respectively.
187 AXIS ORIENTATION[3];
188 /* a 3-element array describing the tablet's orientation range and
189 * resolution capabilities.
191 AXIS ROTATION[3];
192 /* a 3-element array describing the tablet's rotation range and
193 * resolution capabilities.
195 CHAR PNPID[256];
196 /* a null-terminated string containing the devices Plug and Play ID.*/
197 } WTI_DEVICES_INFO, *LPWTI_DEVICES_INFO;
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;
217 #ifdef HAVE_X11_EXTENSIONS_XINPUT_H
219 #include <X11/Xlib.h>
220 #include <X11/extensions/XInput.h>
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;
230 static HWND hwndTabletDefault;
231 static WTPACKET gMsgPacket;
232 static DWORD gSerial;
233 static INT button_state[10];
235 #define CURSORMAX 10
237 static LOGCONTEXTA gSysContext;
238 static WTI_DEVICES_INFO gSysDevice;
239 static WTI_CURSORS_INFO gSysCursor[CURSORMAX];
240 static INT gNumCursors;
243 #ifndef SONAME_LIBXI
244 #define SONAME_LIBXI "libXi.so"
245 #endif
247 /* XInput stuff */
248 static void *xinput_handle;
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
260 static INT X11DRV_XInput_Init(void)
262 xinput_handle = wine_dlopen(SONAME_LIBXI, RTLD_NOW, NULL, 0);
263 if (xinput_handle)
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;
276 sym_not_found:
277 return 0;
280 static int Tablet_ErrorHandler(Display *dpy, XErrorEvent *event, void* arg)
282 return 1;
285 void X11DRV_LoadTabletInfo(HWND hwnddefault)
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;
295 XAnyClassPtr any;
296 XButtonInfoPtr Button;
297 XValuatorInfoPtr Val;
298 XAxisInfoPtr Axis;
300 XDevice *opendevice;
302 if (!X11DRV_XInput_Init())
304 ERR("Unable to initialized the XInput library.\n");
305 return;
308 hwndTabletDefault = hwnddefault;
310 /* Do base initializaion */
311 strcpy(gSysContext.lcName, "Wine Tablet Context");
312 strcpy(gSysDevice.NAME,"Wine Tablet Device");
314 gSysContext.lcOptions = CXO_SYSTEM;
315 gSysContext.lcLocks = CXL_INSIZE | CXL_INASPECT | CXL_MARGIN |
316 CXL_SENSITIVITY | CXL_SYSOUT;
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;
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");
345 wine_tsx11_lock();
347 cursor_target = -1;
348 devices = pXListInputDevices(data->display, &num_devices);
349 if (!devices)
351 WARN("XInput Extenstions reported as not avalable\n");
352 wine_tsx11_unlock();
353 return;
355 for (loop=0; loop < num_devices; loop++)
357 int class_loop;
359 TRACE("Trying device %i(%s)\n",loop,devices[loop].name);
360 if (devices[loop].use == IsXExtensionDevice)
362 LPWTI_CURSORS_INFO cursor;
364 TRACE("Is Extension Device\n");
365 cursor_target++;
366 target = &devices[loop];
367 cursor = &gSysCursor[cursor_target];
369 opendevice = pXOpenDevice(data->display,target->id);
370 if (opendevice)
372 unsigned char map[32];
373 int i;
374 int shft = 0;
376 X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
377 pXGetDeviceButtonMapping(data->display, opendevice, map, 32);
378 if (X11DRV_check_error())
380 TRACE("No buttons, Non Tablet Device\n");
381 pXCloseDevice(data->display, opendevice);
382 cursor_target --;
383 continue;
386 for (i=0; i< cursor->BUTTONS; i++,shft++)
388 cursor->BUTTONMAP[i] = map[i];
389 cursor->SYSBTNMAP[i] = (1<<shft);
391 pXCloseDevice(data->display, opendevice);
393 else
395 WARN("Unable to open device %s\n",target->name);
396 cursor_target --;
397 continue;
400 strcpy(cursor->NAME,target->name);
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;
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;
418 any = (XAnyClassPtr) (target->inputclassinfo);
420 for (class_loop = 0; class_loop < target->num_classes; class_loop++)
422 switch (any->class)
424 case ValuatorClass:
425 if (!axis_read_complete)
427 Val = (XValuatorInfoPtr) any;
428 Axis = (XAxisInfoPtr) ((char *) Val + sizeof
429 (XValuatorInfo));
431 if (Val->num_axes>=1)
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++;
444 if (Val->num_axes>=2)
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++;
457 if (Val->num_axes>=3)
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++;
467 if (Val->num_axes >= 5)
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)))
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++;
488 axis_read_complete = TRUE;
490 break;
491 case ButtonClass:
493 CHAR *ptr = cursor->BTNNAMES;
494 int i;
496 Button = (XButtonInfoPtr) any;
497 cursor->BUTTONS = Button->num_buttons;
498 for (i = 0; i < cursor->BUTTONS; i++)
500 strcpy(ptr,cursor->NAME);
501 ptr+=8;
504 break;
506 any = (XAnyClassPtr) ((char*) any + any->length);
510 wine_tsx11_unlock();
511 gSysDevice.NCSRTYPES = cursor_target+1;
512 gNumCursors = cursor_target+1;
515 static int figure_deg(int x, int y)
517 int rc;
519 if (y != 0)
521 rc = (int) 10 * (atan( (FLOAT)abs(y) / (FLOAT)abs(x)) / (3.1415 / 180));
522 if (y>0)
524 if (x>0)
525 rc += 900;
526 else
527 rc = 2700 - rc;
529 else
531 if (x>0)
532 rc = 900 - rc;
533 else
534 rc += 2700;
537 else
539 if (x >= 0)
540 rc = 900;
541 else
542 rc = 2700;
545 return rc;
548 static int get_button_state(int deviceid)
550 return button_state[deviceid];
553 static void set_button_state(XID deviceid)
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;
562 wine_tsx11_lock();
563 device = pXOpenDevice(data->display,deviceid);
564 state = pXQueryDeviceState(data->display,device);
566 if (state)
568 class = state->data;
569 for (loop = 0; loop < state->num_classes; loop++)
571 if (class->class == ButtonClass)
573 int loop2;
574 XButtonState *button_state = (XButtonState*)class;
575 for (loop2 = 1; loop2 <= button_state->num_buttons; loop2++)
577 if (button_state->buttons[loop2 / 8] & (1 << (loop2 % 8)))
579 rc |= (1<<(loop2-1));
583 class = (XInputClass *) ((char *) class + class->length);
586 pXFreeDeviceState(state);
587 wine_tsx11_unlock();
588 button_state[deviceid] = rc;
591 int X11DRV_ProcessTabletEvent(HWND hwnd, XEvent *event)
593 memset(&gMsgPacket,0,sizeof(WTPACKET));
595 if(event->type == motion_type)
597 XDeviceMotionEvent *motion = (XDeviceMotionEvent *)event;
598 LPWTI_CURSORS_INFO cursor = &gSysCursor[motion->deviceid];
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 = 1000 - 15 * max
612 (abs(motion->axis_data[3]),abs(motion->axis_data[4]));
613 gMsgPacket.pkNormalPressure = motion->axis_data[2];
614 gMsgPacket.pkButtons = get_button_state(motion->deviceid);
615 SendMessageW(hwndTabletDefault,WT_PACKET,0,(LPARAM)hwnd);
617 else if ((event->type == button_press_type)||(event->type ==
618 button_release_type))
620 XDeviceButtonEvent *button = (XDeviceButtonEvent *) event;
621 LPWTI_CURSORS_INFO cursor = &gSysCursor[button->deviceid];
623 TRACE_(event)("Received tablet button event\n");
624 TRACE("Received tablet button %s event\n", (event->type ==
625 button_press_type)?"press":"release");
627 /* Set cursor to inverted if cursor is the eraser */
628 gMsgPacket.pkStatus = (cursor->TYPE == 0xc85a ?TPS_INVERT:0);
629 set_button_state(button->deviceid);
630 gMsgPacket.pkTime = button->time;
631 gMsgPacket.pkSerialNumber = gSerial++;
632 gMsgPacket.pkCursor = button->deviceid;
633 gMsgPacket.pkX = button->axis_data[0];
634 gMsgPacket.pkY = button->axis_data[1];
635 gMsgPacket.pkOrientation.orAzimuth =
636 figure_deg(button->axis_data[3],button->axis_data[4]);
637 gMsgPacket.pkOrientation.orAltitude = 1000 - 15 * max
638 (abs(button->axis_data[3]),abs(button->axis_data[4]));
639 gMsgPacket.pkNormalPressure = button->axis_data[2];
640 gMsgPacket.pkButtons = get_button_state(button->deviceid);
641 SendMessageW(hwndTabletDefault,WT_PACKET,0,(LPARAM)hwnd);
643 else if (event->type == key_press_type)
645 TRACE_(event)("Received tablet key press event\n");
646 FIXME("Received tablet key press event\n");
648 else if (event->type == key_release_type)
650 TRACE_(event)("Received tablet key release event\n");
651 FIXME("Received tablet key release event\n");
653 else if ((event->type == proximity_in_type) ||
654 (event->type == proximity_out_type))
656 XProximityNotifyEvent *proximity = (XProximityNotifyEvent *) event;
657 LPWTI_CURSORS_INFO cursor = &gSysCursor[proximity->deviceid];
659 TRACE_(event)("Received tablet proximity event\n");
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 = 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 =
670 figure_deg(proximity->axis_data[3],proximity->axis_data[4]);
671 gMsgPacket.pkOrientation.orAltitude = 1000 - 15 * max
672 (abs(proximity->axis_data[3]),abs(proximity->axis_data[4]));
673 gMsgPacket.pkNormalPressure = proximity->axis_data[2];
674 gMsgPacket.pkButtons = get_button_state(proximity->deviceid);
676 SendMessageW(hwndTabletDefault, WT_PROXIMITY,
677 (event->type==proximity_out_type)?0:1, (LPARAM)hwnd);
679 else
680 return 0;
682 return 1;
685 int X11DRV_AttachEventQueueToTablet(HWND hOwner)
687 struct x11drv_thread_data *data = x11drv_thread_data();
688 int num_devices;
689 int loop;
690 int cur_loop;
691 XDeviceInfo *devices;
692 XDeviceInfo *target = NULL;
693 XDevice *the_device;
694 XInputClassInfo *ip;
695 XEventClass event_list[7];
696 Window win = X11DRV_get_whole_window( hOwner );
698 if (!win) return 0;
700 TRACE("Creating context for window %p (%lx) %i cursors\n", hOwner, win, gNumCursors);
702 wine_tsx11_lock();
703 devices = pXListInputDevices(data->display, &num_devices);
705 for (cur_loop=0; cur_loop < gNumCursors; cur_loop++)
707 int event_number=0;
709 for (loop=0; loop < num_devices; loop ++)
710 if (strcmp(devices[loop].name,gSysCursor[cur_loop].NAME)==0)
711 target = &devices[loop];
713 TRACE("Opening cursor %i id %i\n",cur_loop,(INT)target->id);
715 the_device = pXOpenDevice(data->display, target->id);
717 if (!the_device)
719 WARN("Unable to Open device\n");
720 continue;
723 if (the_device->num_classes > 0)
725 for (ip = the_device->classes, loop=0; loop < target->num_classes;
726 ip++, loop++)
728 switch(ip->input_class)
730 case KeyClass:
731 DeviceKeyPress(the_device, key_press_type,
732 event_list[event_number]);
733 event_number++;
734 DeviceKeyRelease(the_device, key_release_type,
735 event_list[event_number]);
736 event_number++;
737 break;
738 case ButtonClass:
739 DeviceButtonPress(the_device, button_press_type,
740 event_list[event_number]);
741 event_number++;
742 DeviceButtonRelease(the_device, button_release_type,
743 event_list[event_number]);
744 event_number++;
745 break;
746 case ValuatorClass:
747 DeviceMotionNotify(the_device, motion_type,
748 event_list[event_number]);
749 event_number++;
750 ProximityIn(the_device, proximity_in_type,
751 event_list[event_number]);
752 event_number++;
753 ProximityOut(the_device, proximity_out_type,
754 event_list[event_number]);
755 event_number++;
756 break;
757 default:
758 ERR("unknown class\n");
759 break;
762 if (pXSelectExtensionEvent(data->display, win, event_list, event_number))
764 ERR( "error selecting extended events\n");
765 goto end;
770 end:
771 wine_tsx11_unlock();
772 return 0;
775 int X11DRV_GetCurrentPacket(LPWTPACKET *packet)
777 memcpy(packet,&gMsgPacket,sizeof(WTPACKET));
778 return 1;
782 int static inline CopyTabletData(LPVOID target, LPVOID src, INT size)
785 * It is valid to call CopyTabletData with NULL.
786 * This handles the WTInfo() case where lpOutput is null.
788 if(target != NULL)
789 memcpy(target,src,size);
790 return(size);
793 /***********************************************************************
794 * X11DRV_WTInfoA (X11DRV.@)
796 UINT X11DRV_WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
799 * It is valid to call WTInfoA with lpOutput == NULL, as per standard.
800 * lpOutput == NULL signifies the user only wishes
801 * to find the size of the data.
802 * NOTE:
803 * From now on use CopyTabletData to fill lpOutput. memcpy will break
804 * the code.
806 int rc = 0;
807 LPWTI_CURSORS_INFO tgtcursor;
808 TRACE("(%u, %u, %p)\n", wCategory, nIndex, lpOutput);
810 switch(wCategory)
812 case 0:
813 /* return largest necessary buffer */
814 TRACE("%i cursors\n",gNumCursors);
815 if (gNumCursors>0)
817 FIXME("Return proper size\n");
818 rc = 200;
820 break;
821 case WTI_INTERFACE:
822 switch (nIndex)
824 WORD version;
825 case IFC_WINTABID:
826 strcpy(lpOutput,"Wine Wintab 1.1");
827 rc = 16;
828 break;
829 case IFC_SPECVERSION:
830 version = (0x01) | (0x01 << 8);
831 rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
832 break;
833 case IFC_IMPLVERSION:
834 version = (0x00) | (0x01 << 8);
835 rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
836 break;
837 default:
838 FIXME("WTI_INTERFACE unhandled index %i\n",nIndex);
839 rc = 0;
842 case WTI_DEFSYSCTX:
843 case WTI_DDCTXS:
844 case WTI_DEFCONTEXT:
845 switch (nIndex)
847 case 0:
848 rc = CopyTabletData(lpOutput, &gSysContext,
849 sizeof(LOGCONTEXTA));
850 break;
851 case CTX_NAME:
852 rc = CopyTabletData(lpOutput, &gSysContext.lcName,
853 strlen(gSysContext.lcName)+1);
854 break;
855 case CTX_OPTIONS:
856 rc = CopyTabletData(lpOutput, &gSysContext.lcOptions,
857 sizeof(UINT));
858 break;
859 case CTX_STATUS:
860 rc = CopyTabletData(lpOutput, &gSysContext.lcStatus,
861 sizeof(UINT));
862 break;
863 case CTX_LOCKS:
864 rc= CopyTabletData (lpOutput, &gSysContext.lcLocks,
865 sizeof(UINT));
866 break;
867 case CTX_MSGBASE:
868 rc = CopyTabletData(lpOutput, &gSysContext.lcMsgBase,
869 sizeof(UINT));
870 break;
871 case CTX_DEVICE:
872 rc = CopyTabletData(lpOutput, &gSysContext.lcDevice,
873 sizeof(UINT));
874 break;
875 case CTX_PKTRATE:
876 rc = CopyTabletData(lpOutput, &gSysContext.lcPktRate,
877 sizeof(UINT));
878 break;
879 case CTX_PKTMODE:
880 rc = CopyTabletData(lpOutput, &gSysContext.lcPktMode,
881 sizeof(WTPKT));
882 break;
883 case CTX_MOVEMASK:
884 rc = CopyTabletData(lpOutput, &gSysContext.lcMoveMask,
885 sizeof(WTPKT));
886 break;
887 case CTX_BTNDNMASK:
888 rc = CopyTabletData(lpOutput, &gSysContext.lcBtnDnMask,
889 sizeof(DWORD));
890 break;
891 case CTX_BTNUPMASK:
892 rc = CopyTabletData(lpOutput, &gSysContext.lcBtnUpMask,
893 sizeof(DWORD));
894 break;
895 case CTX_INORGX:
896 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgX,
897 sizeof(LONG));
898 break;
899 case CTX_INORGY:
900 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgY,
901 sizeof(LONG));
902 break;
903 case CTX_INORGZ:
904 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgZ,
905 sizeof(LONG));
906 break;
907 case CTX_INEXTX:
908 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtX,
909 sizeof(LONG));
910 break;
911 case CTX_INEXTY:
912 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtY,
913 sizeof(LONG));
914 break;
915 case CTX_INEXTZ:
916 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtZ,
917 sizeof(LONG));
918 break;
919 case CTX_OUTORGX:
920 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgX,
921 sizeof(LONG));
922 break;
923 case CTX_OUTORGY:
924 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgY,
925 sizeof(LONG));
926 break;
927 case CTX_OUTORGZ:
928 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgZ,
929 sizeof(LONG));
930 break;
931 case CTX_OUTEXTX:
932 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtX,
933 sizeof(LONG));
934 break;
935 case CTX_OUTEXTY:
936 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtY,
937 sizeof(LONG));
938 break;
939 case CTX_OUTEXTZ:
940 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtZ,
941 sizeof(LONG));
942 break;
943 case CTX_SENSX:
944 rc = CopyTabletData(lpOutput, &gSysContext.lcSensX,
945 sizeof(LONG));
946 break;
947 case CTX_SENSY:
948 rc = CopyTabletData(lpOutput, &gSysContext.lcSensY,
949 sizeof(LONG));
950 break;
951 case CTX_SENSZ:
952 rc = CopyTabletData(lpOutput, &gSysContext.lcSensZ,
953 sizeof(LONG));
954 break;
955 case CTX_SYSMODE:
956 rc = CopyTabletData(lpOutput, &gSysContext.lcSysMode,
957 sizeof(LONG));
958 break;
959 case CTX_SYSORGX:
960 rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgX,
961 sizeof(LONG));
962 break;
963 case CTX_SYSORGY:
964 rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgY,
965 sizeof(LONG));
966 break;
967 case CTX_SYSEXTX:
968 rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtX,
969 sizeof(LONG));
970 break;
971 case CTX_SYSEXTY:
972 rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtY,
973 sizeof(LONG));
974 break;
975 case CTX_SYSSENSX:
976 rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensX,
977 sizeof(LONG));
978 break;
979 case CTX_SYSSENSY:
980 rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensY,
981 sizeof(LONG));
982 break;
983 default:
984 FIXME("WTI_DEFSYSCTX unhandled index %i\n",nIndex);
985 rc = 0;
987 break;
988 case WTI_CURSORS:
989 case WTI_CURSORS+1:
990 case WTI_CURSORS+2:
991 case WTI_CURSORS+3:
992 case WTI_CURSORS+4:
993 case WTI_CURSORS+5:
994 case WTI_CURSORS+6:
995 case WTI_CURSORS+7:
996 case WTI_CURSORS+8:
997 case WTI_CURSORS+9:
998 case WTI_CURSORS+10:
999 tgtcursor = &gSysCursor[wCategory - WTI_CURSORS];
1000 switch (nIndex)
1002 case CSR_NAME:
1003 rc = CopyTabletData(lpOutput, &tgtcursor->NAME,
1004 strlen(tgtcursor->NAME)+1);
1005 break;
1006 case CSR_ACTIVE:
1007 rc = CopyTabletData(lpOutput,&tgtcursor->ACTIVE,
1008 sizeof(BOOL));
1009 break;
1010 case CSR_PKTDATA:
1011 rc = CopyTabletData(lpOutput,&tgtcursor->PKTDATA,
1012 sizeof(WTPKT));
1013 break;
1014 case CSR_BUTTONS:
1015 rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONS,
1016 sizeof(BYTE));
1017 break;
1018 case CSR_BUTTONBITS:
1019 rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONBITS,
1020 sizeof(BYTE));
1021 break;
1022 case CSR_BTNNAMES:
1023 FIXME("Button Names not returned correctly\n");
1024 rc = CopyTabletData(lpOutput,&tgtcursor->BTNNAMES,
1025 strlen(tgtcursor->BTNNAMES)+1);
1026 break;
1027 case CSR_BUTTONMAP:
1028 rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONMAP,
1029 sizeof(BYTE)*32);
1030 break;
1031 case CSR_SYSBTNMAP:
1032 rc = CopyTabletData(lpOutput,&tgtcursor->SYSBTNMAP,
1033 sizeof(BYTE)*32);
1034 break;
1035 case CSR_NPBTNMARKS:
1036 rc = CopyTabletData(lpOutput,&tgtcursor->NPBTNMARKS,
1037 sizeof(UINT)*2);
1038 break;
1039 case CSR_NPBUTTON:
1040 rc = CopyTabletData(lpOutput,&tgtcursor->NPBUTTON,
1041 sizeof(BYTE));
1042 break;
1043 case CSR_NPRESPONSE:
1044 FIXME("Not returning CSR_NPRESPONSE correctly\n");
1045 rc = 0;
1046 break;
1047 case CSR_TPBUTTON:
1048 rc = CopyTabletData(lpOutput,&tgtcursor->TPBUTTON,
1049 sizeof(BYTE));
1050 break;
1051 case CSR_TPBTNMARKS:
1052 rc = CopyTabletData(lpOutput,&tgtcursor->TPBTNMARKS,
1053 sizeof(UINT)*2);
1054 break;
1055 case CSR_TPRESPONSE:
1056 FIXME("Not returning CSR_TPRESPONSE correctly\n");
1057 rc = 0;
1058 break;
1059 case CSR_PHYSID:
1061 DWORD id;
1062 id = tgtcursor->PHYSID;
1063 id += (wCategory - WTI_CURSORS);
1064 rc = CopyTabletData(lpOutput,&id,sizeof(DWORD));
1066 break;
1067 case CSR_MODE:
1068 rc = CopyTabletData(lpOutput,&tgtcursor->MODE,sizeof(UINT));
1069 break;
1070 case CSR_MINPKTDATA:
1071 rc = CopyTabletData(lpOutput,&tgtcursor->MINPKTDATA,
1072 sizeof(UINT));
1073 break;
1074 case CSR_MINBUTTONS:
1075 rc = CopyTabletData(lpOutput,&tgtcursor->MINBUTTONS,
1076 sizeof(UINT));
1077 break;
1078 case CSR_CAPABILITIES:
1079 rc = CopyTabletData(lpOutput,&tgtcursor->CAPABILITIES,
1080 sizeof(UINT));
1081 break;
1082 case CSR_TYPE:
1083 rc = CopyTabletData(lpOutput,&tgtcursor->TYPE,
1084 sizeof(UINT));
1085 break;
1086 default:
1087 FIXME("WTI_CURSORS unhandled index %i\n",nIndex);
1088 rc = 0;
1090 break;
1091 case WTI_DEVICES:
1092 switch (nIndex)
1094 case DVC_NAME:
1095 rc = CopyTabletData(lpOutput,gSysDevice.NAME,
1096 strlen(gSysDevice.NAME)+1);
1097 break;
1098 case DVC_HARDWARE:
1099 rc = CopyTabletData(lpOutput,&gSysDevice.HARDWARE,
1100 sizeof(UINT));
1101 break;
1102 case DVC_NCSRTYPES:
1103 rc = CopyTabletData(lpOutput,&gSysDevice.NCSRTYPES,
1104 sizeof(UINT));
1105 break;
1106 case DVC_FIRSTCSR:
1107 rc = CopyTabletData(lpOutput,&gSysDevice.FIRSTCSR,
1108 sizeof(UINT));
1109 break;
1110 case DVC_PKTRATE:
1111 rc = CopyTabletData(lpOutput,&gSysDevice.PKTRATE,
1112 sizeof(UINT));
1113 break;
1114 case DVC_PKTDATA:
1115 rc = CopyTabletData(lpOutput,&gSysDevice.PKTDATA,
1116 sizeof(WTPKT));
1117 break;
1118 case DVC_PKTMODE:
1119 rc = CopyTabletData(lpOutput,&gSysDevice.PKTMODE,
1120 sizeof(WTPKT));
1121 break;
1122 case DVC_CSRDATA:
1123 rc = CopyTabletData(lpOutput,&gSysDevice.CSRDATA,
1124 sizeof(WTPKT));
1125 break;
1126 case DVC_XMARGIN:
1127 rc = CopyTabletData(lpOutput,&gSysDevice.XMARGIN,
1128 sizeof(INT));
1129 break;
1130 case DVC_YMARGIN:
1131 rc = CopyTabletData(lpOutput,&gSysDevice.YMARGIN,
1132 sizeof(INT));
1133 break;
1134 case DVC_ZMARGIN:
1135 rc = 0; /* unsupported */
1137 rc = CopyTabletData(lpOutput,&gSysDevice.ZMARGIN,
1138 sizeof(INT));
1140 break;
1141 case DVC_X:
1142 rc = CopyTabletData(lpOutput,&gSysDevice.X,
1143 sizeof(AXIS));
1144 break;
1145 case DVC_Y:
1146 rc = CopyTabletData(lpOutput,&gSysDevice.Y,
1147 sizeof(AXIS));
1148 break;
1149 case DVC_Z:
1150 rc = 0; /* unsupported */
1152 rc = CopyTabletData(lpOutput,&gSysDevice.Z,
1153 sizeof(AXIS));
1155 break;
1156 case DVC_NPRESSURE:
1157 rc = CopyTabletData(lpOutput,&gSysDevice.NPRESSURE,
1158 sizeof(AXIS));
1159 break;
1160 case DVC_TPRESSURE:
1161 rc = 0; /* unsupported */
1163 rc = CopyTabletData(lpOutput,&gSysDevice.TPRESSURE,
1164 sizeof(AXIS));
1166 break;
1167 case DVC_ORIENTATION:
1168 rc = CopyTabletData(lpOutput,&gSysDevice.ORIENTATION,
1169 sizeof(AXIS)*3);
1170 break;
1171 case DVC_ROTATION:
1172 rc = 0; /* unsupported */
1174 rc = CopyTabletData(lpOutput,&gSysDevice.ROTATION,
1175 sizeof(AXIS)*3);
1177 break;
1178 case DVC_PNPID:
1179 rc = CopyTabletData(lpOutput,gSysDevice.PNPID,
1180 strlen(gSysDevice.PNPID)+1);
1181 break;
1182 default:
1183 FIXME("WTI_DEVICES unhandled index %i\n",nIndex);
1184 rc = 0;
1186 break;
1187 default:
1188 FIXME("Unhandled Category %i\n",wCategory);
1190 return rc;
1193 #else /* HAVE_X11_EXTENSIONS_XINPUT_H */
1195 int X11DRV_ProcessTabletEvent(HWND hwnd, XEvent *event)
1197 return 0;
1200 /***********************************************************************
1201 * AttachEventQueueToTablet (X11DRV.@)
1203 int X11DRV_AttachEventQueueToTablet(HWND hOwner)
1205 return 0;
1208 /***********************************************************************
1209 * GetCurrentPacket (X11DRV.@)
1211 int X11DRV_GetCurrentPacket(LPWTPACKET *packet)
1213 return 0;
1216 /***********************************************************************
1217 * LoadTabletInfo (X11DRV.@)
1219 void X11DRV_LoadTabletInfo(HWND hwnddefault)
1223 /***********************************************************************
1224 * WTInfoA (X11DRV.@)
1226 UINT X11DRV_WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput)
1228 return 0;
1231 #endif /* HAVE_X11_EXTENSIONS_XINPUT_H */