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