push 9fcdc0d7acf404e32ebbdf911b92222c6b0dee73
[wine/hacks.git] / dlls / winex11.drv / wintab.c
blob5eecd264b1d36d94a7322e600c035561c52d203f
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;
206 /***********************************************************************
207 * WACOM WINTAB EXTENSIONS TO SUPPORT CSR_TYPE
208 * In Wintab 1.2, a CSR_TYPE feature was added. This adds the
209 * ability to return a type of cursor on a tablet.
210 * Unfortunately, we cannot get the cursor type directly from X,
211 * and it is not specified directly anywhere. So we virtualize
212 * the type here. (This is unfortunate, the kernel module has
213 * the exact type, but we have no way of getting that module to
214 * pass us that type).
217 #define CSR_TYPE_PEN 0x822
218 #define CSR_TYPE_ERASER 0x82a
219 #define CSR_TYPE_MOUSE_2D 0x007
220 #define CSR_TYPE_MOUSE_4D 0x094
223 typedef struct tagWTPACKET {
224 HCTX pkContext;
225 UINT pkStatus;
226 LONG pkTime;
227 WTPKT pkChanged;
228 UINT pkSerialNumber;
229 UINT pkCursor;
230 DWORD pkButtons;
231 DWORD pkX;
232 DWORD pkY;
233 DWORD pkZ;
234 UINT pkNormalPressure;
235 UINT pkTangentPressure;
236 ORIENTATION pkOrientation;
237 ROTATION pkRotation; /* 1.1 */
238 } WTPACKET, *LPWTPACKET;
241 #ifdef SONAME_LIBXI
243 #include <X11/Xlib.h>
244 #include <X11/extensions/XInput.h>
246 static int motion_type;
247 static int button_press_type;
248 static int button_release_type;
249 static int key_press_type;
250 static int key_release_type;
251 static int proximity_in_type;
252 static int proximity_out_type;
254 static HWND hwndTabletDefault;
255 static WTPACKET gMsgPacket;
256 static DWORD gSerial;
257 static INT button_state[10];
259 #define CURSORMAX 10
261 static LOGCONTEXTW gSysContext;
262 static WTI_DEVICES_INFO gSysDevice;
263 static WTI_CURSORS_INFO gSysCursor[CURSORMAX];
264 static INT gNumCursors;
267 /* XInput stuff */
268 static void *xinput_handle;
270 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
271 MAKE_FUNCPTR(XListInputDevices)
272 MAKE_FUNCPTR(XFreeDeviceList)
273 MAKE_FUNCPTR(XOpenDevice)
274 MAKE_FUNCPTR(XQueryDeviceState)
275 MAKE_FUNCPTR(XGetDeviceButtonMapping)
276 MAKE_FUNCPTR(XCloseDevice)
277 MAKE_FUNCPTR(XSelectExtensionEvent)
278 MAKE_FUNCPTR(XFreeDeviceState)
279 #undef MAKE_FUNCPTR
281 static INT X11DRV_XInput_Init(void)
283 xinput_handle = wine_dlopen(SONAME_LIBXI, RTLD_NOW, NULL, 0);
284 if (xinput_handle)
286 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xinput_handle, #f, NULL, 0)) == NULL) goto sym_not_found;
287 LOAD_FUNCPTR(XListInputDevices)
288 LOAD_FUNCPTR(XFreeDeviceList)
289 LOAD_FUNCPTR(XOpenDevice)
290 LOAD_FUNCPTR(XGetDeviceButtonMapping)
291 LOAD_FUNCPTR(XCloseDevice)
292 LOAD_FUNCPTR(XSelectExtensionEvent)
293 LOAD_FUNCPTR(XQueryDeviceState)
294 LOAD_FUNCPTR(XFreeDeviceState)
295 #undef LOAD_FUNCPTR
296 return 1;
298 sym_not_found:
299 return 0;
302 static int Tablet_ErrorHandler(Display *dpy, XErrorEvent *event, void* arg)
304 return 1;
307 static int find_cursor_by_type(int cursor_type, int exclude)
309 int i;
310 for (i = 0; i < gNumCursors; i++)
311 if (i != exclude)
312 if (gSysCursor[i].TYPE == cursor_type)
313 return i;
315 return -1;
318 static void swap_cursors(int a, int b)
320 WTI_CURSORS_INFO temp;
321 temp = gSysCursor[a];
322 gSysCursor[a] = gSysCursor[b];
323 gSysCursor[b] = temp;
326 /* Adobe Photoshop 7.0 relies on the eraser being cursor #2 or #5, and it assumes the stylus is 1.
327 ** If the X configuration is not set up that way, make it
329 static void Tablet_FixupCursors(void)
331 if (gNumCursors >= 1)
332 if (gSysCursor[1].TYPE != CSR_TYPE_PEN)
334 int stylus;
335 stylus = find_cursor_by_type(CSR_TYPE_PEN, 1);
336 if (stylus >= 0)
338 swap_cursors(1, stylus);
339 TRACE("Swapped cursor %d with stylus slot (1) for compatibility with older programs\n", stylus);
343 if (gNumCursors >= 2)
344 if (gSysCursor[2].TYPE != CSR_TYPE_ERASER)
346 int eraser;
347 eraser = find_cursor_by_type(CSR_TYPE_ERASER, 2);
348 if (eraser >= 0)
350 swap_cursors(2, eraser);
351 TRACE("Swapped cursor %d with eraser slot (2) for compatibility with older programs\n", eraser);
356 static void trace_axes(XValuatorInfoPtr val)
358 int i;
359 XAxisInfoPtr axis;
361 for (i = 0, axis = val->axes ; i < val->num_axes; i++, axis++)
362 TRACE(" Axis %d: [resolution %d|min_value %d|max_value %d]\n", i, axis->resolution, axis->min_value, axis->max_value);
365 BOOL match_token(const char *haystack, const char *needle)
367 const char *p, *q;
368 for (p = haystack; *p; )
370 while (*p && isspace(*p))
371 p++;
372 if (! *p)
373 break;
375 for (q = needle; *q && *p && tolower(*p) == tolower(*q); q++)
376 p++;
377 if (! *q && (isspace(*p) || !*p))
378 return TRUE;
380 while (*p && ! isspace(*p))
381 p++;
383 return FALSE;
386 /* Determining if an X device is a Tablet style device is an imperfect science.
387 ** We rely on common conventions around device names as well as the type reported
388 ** by Wacom tablets. This code will likely need to be expanded for alternate tablet types
391 static BOOL is_tablet_cursor(const char *name, const char *type)
393 int i;
394 static const char *tablet_cursor_whitelist[] = {
395 "wacom",
396 "wizardpen",
397 "acecad",
398 "tablet",
399 "cursor",
400 "stylus",
401 "eraser",
402 "pad",
403 NULL
406 for (i=0; tablet_cursor_whitelist[i] != NULL; i++) {
407 if (name && match_token(name, tablet_cursor_whitelist[i]))
408 return TRUE;
409 if (type && match_token(type, tablet_cursor_whitelist[i]))
410 return TRUE;
412 return FALSE;
415 static BOOL is_stylus(const char *name, const char *type)
417 int i;
418 static const char* tablet_stylus_whitelist[] = {
419 "stylus",
420 "wizardpen",
421 "acecad",
422 NULL
425 for (i=0; tablet_stylus_whitelist[i] != NULL; i++) {
426 if (name && match_token(name, tablet_stylus_whitelist[i]))
427 return TRUE;
428 if (type && match_token(type, tablet_stylus_whitelist[i]))
429 return TRUE;
432 return FALSE;
435 static BOOL is_eraser(const char *name, const char *type)
437 if (name && match_token(name, "eraser"))
438 return TRUE;
439 if (type && match_token(type, "eraser"))
440 return TRUE;
441 return FALSE;
445 /***********************************************************************
446 * X11DRV_LoadTabletInfo (X11DRV.@)
448 void X11DRV_LoadTabletInfo(HWND hwnddefault)
450 const WCHAR SZ_CONTEXT_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','C','o','n','t','e','x','t',0};
451 const WCHAR SZ_DEVICE_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','D','e','v','i','c','e',0};
452 const WCHAR SZ_NON_PLUGINPLAY[] = {'n','o','n','-','p','l','u','g','i','n','p','l','a','y',0};
454 struct x11drv_thread_data *data = x11drv_thread_data();
455 int num_devices;
456 int loop;
457 int cursor_target;
458 XDeviceInfo *devices;
459 XDeviceInfo *target = NULL;
460 BOOL axis_read_complete= FALSE;
462 XAnyClassPtr any;
463 XButtonInfoPtr Button;
464 XValuatorInfoPtr Val;
465 XAxisInfoPtr Axis;
467 XDevice *opendevice;
469 if (!X11DRV_XInput_Init())
471 ERR("Unable to initialize the XInput library.\n");
472 return;
475 hwndTabletDefault = hwnddefault;
477 /* Do base initialization */
478 strcpyW(gSysContext.lcName, SZ_CONTEXT_NAME);
479 strcpyW(gSysDevice.NAME, SZ_DEVICE_NAME);
481 gSysContext.lcOptions = CXO_SYSTEM;
482 gSysContext.lcLocks = CXL_INSIZE | CXL_INASPECT | CXL_MARGIN |
483 CXL_SENSITIVITY | CXL_SYSOUT;
485 gSysContext.lcMsgBase= WT_DEFBASE;
486 gSysContext.lcDevice = 0;
487 gSysContext.lcPktData =
488 PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
489 PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
490 gSysContext.lcMoveMask=
491 PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
492 gSysContext.lcStatus = CXS_ONTOP;
493 gSysContext.lcPktRate = 100;
494 gSysContext.lcBtnDnMask = 0xffffffff;
495 gSysContext.lcBtnUpMask = 0xffffffff;
496 gSysContext.lcSensX = 65536;
497 gSysContext.lcSensY = 65536;
498 gSysContext.lcSensX = 65536;
499 gSysContext.lcSensZ = 65536;
500 gSysContext.lcSysSensX= 65536;
501 gSysContext.lcSysSensY= 65536;
503 /* Device Defaults */
504 gSysDevice.HARDWARE = HWC_HARDPROX|HWC_PHYSID_CURSORS;
505 gSysDevice.FIRSTCSR= 0;
506 gSysDevice.PKTRATE = 100;
507 gSysDevice.PKTDATA =
508 PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
509 PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
510 strcpyW(gSysDevice.PNPID, SZ_NON_PLUGINPLAY);
512 wine_tsx11_lock();
514 cursor_target = -1;
515 devices = pXListInputDevices(data->display, &num_devices);
516 if (!devices)
518 WARN("XInput Extensions reported as not avalable\n");
519 wine_tsx11_unlock();
520 return;
522 TRACE("XListInputDevices reports %d devices\n", num_devices);
523 for (loop=0; loop < num_devices; loop++)
525 int class_loop;
526 char *device_type = devices[loop].type ? XGetAtomName(data->display, devices[loop].type) : NULL;
527 LPWTI_CURSORS_INFO cursor;
529 TRACE("Device %i: [id %d|name %s|type %s|num_classes %d|use %d]\n",
530 loop, (int) devices[loop].id, devices[loop].name, device_type ? device_type : "",
531 devices[loop].num_classes, devices[loop].use );
533 switch (devices[loop].use)
535 case IsXExtensionDevice:
536 #ifdef IsXExtensionPointer
537 case IsXExtensionPointer:
538 #endif
539 #ifdef IsXExtensionKeyboard
540 case IsXExtensionKeyboard:
541 #endif
542 TRACE("Is XExtension: Device, Keyboard, or Pointer\n");
543 cursor_target++;
544 target = &devices[loop];
545 cursor = &gSysCursor[cursor_target];
547 if (strlen(target->name) >= WT_MAX_NAME_LEN)
549 ERR("Input device '%s' name too long - skipping\n", wine_dbgstr_a(target->name));
550 cursor_target--;
551 break;
554 X11DRV_expect_error(data->display, Tablet_ErrorHandler, NULL);
555 opendevice = pXOpenDevice(data->display,target->id);
556 if (!X11DRV_check_error() && opendevice)
558 unsigned char map[32];
559 int i;
560 int shft = 0;
562 X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
563 cursor->BUTTONS = pXGetDeviceButtonMapping(data->display, opendevice, map, 32);
564 if (X11DRV_check_error() || cursor->BUTTONS <= 0)
566 TRACE("No buttons, Non Tablet Device\n");
567 pXCloseDevice(data->display, opendevice);
568 cursor_target --;
569 break;
572 for (i=0; i< cursor->BUTTONS; i++,shft++)
574 cursor->BUTTONMAP[i] = map[i];
575 cursor->SYSBTNMAP[i] = (1<<shft);
577 pXCloseDevice(data->display, opendevice);
579 else
581 WARN("Unable to open device %s\n",target->name);
582 cursor_target --;
583 break;
585 MultiByteToWideChar(CP_UNIXCP, 0, target->name, -1, cursor->NAME, WT_MAX_NAME_LEN);
587 if (! is_tablet_cursor(target->name, device_type))
589 WARN("Skipping device %d [name %s|type %s]; not apparently a tablet cursor type device. If this is wrong, please report it to wine-devel@winehq.org\n",
590 loop, devices[loop].name, device_type ? device_type : "");
591 cursor_target --;
592 break;
595 cursor->ACTIVE = 1;
596 cursor->PKTDATA = PK_TIME | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y |
597 PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE |
598 PK_ORIENTATION;
600 cursor->PHYSID = target->id;
601 cursor->NPBUTTON = 1;
602 cursor->NPBTNMARKS[0] = 0 ;
603 cursor->NPBTNMARKS[1] = 1 ;
604 cursor->CAPABILITIES = CRC_MULTIMODE;
605 if (is_stylus(target->name, device_type))
606 cursor->TYPE = CSR_TYPE_PEN;
607 if (is_eraser(target->name, device_type))
608 cursor->TYPE = CSR_TYPE_ERASER;
611 any = target->inputclassinfo;
613 for (class_loop = 0; class_loop < target->num_classes; class_loop++)
615 switch (any->class)
618 case ValuatorClass:
619 Val = (XValuatorInfoPtr) any;
620 TRACE(" ValidatorInput %d: [class %d|length %d|num_axes %d|mode %d|motion_buffer %ld]\n",
621 class_loop, (int) Val->class, Val->length, Val->num_axes, Val->mode, Val->motion_buffer);
622 if (TRACE_ON(wintab32))
623 trace_axes(Val);
625 /* FIXME: This is imperfect; we compute our devices capabilities based upon the
626 ** first pen type device we find. However, a more correct implementation
627 ** would require acquiring a wide variety of tablets and running through
628 ** the various inputs to see what the values are. Odds are that a
629 ** more 'correct' algorithm would condense to this one anyway.
631 if (!axis_read_complete && cursor->TYPE == CSR_TYPE_PEN)
633 Axis = (XAxisInfoPtr) ((char *) Val + sizeof
634 (XValuatorInfo));
636 if (Val->num_axes>=1)
638 /* Axis 1 is X */
639 gSysDevice.X.axMin = Axis->min_value;
640 gSysDevice.X.axMax= Axis->max_value;
641 gSysDevice.X.axUnits = TU_INCHES;
642 gSysDevice.X.axResolution = Axis->resolution;
643 gSysContext.lcInOrgX = Axis->min_value;
644 gSysContext.lcSysOrgX = Axis->min_value;
645 gSysContext.lcInExtX = Axis->max_value;
646 gSysContext.lcSysExtX = Axis->max_value;
647 Axis++;
649 if (Val->num_axes>=2)
651 /* Axis 2 is Y */
652 gSysDevice.Y.axMin = Axis->min_value;
653 gSysDevice.Y.axMax= Axis->max_value;
654 gSysDevice.Y.axUnits = TU_INCHES;
655 gSysDevice.Y.axResolution = Axis->resolution;
656 gSysContext.lcInOrgY = Axis->min_value;
657 gSysContext.lcSysOrgY = Axis->min_value;
658 gSysContext.lcInExtY = Axis->max_value;
659 gSysContext.lcSysExtY = Axis->max_value;
660 Axis++;
662 if (Val->num_axes>=3)
664 /* Axis 3 is Normal Pressure */
665 gSysDevice.NPRESSURE.axMin = Axis->min_value;
666 gSysDevice.NPRESSURE.axMax= Axis->max_value;
667 gSysDevice.NPRESSURE.axUnits = TU_INCHES;
668 gSysDevice.NPRESSURE.axResolution =
669 Axis->resolution;
670 Axis++;
672 if (Val->num_axes >= 5)
674 /* Axis 4 and 5 are X and Y tilt */
675 XAxisInfoPtr XAxis = Axis;
676 Axis++;
677 if (max (abs(Axis->max_value),
678 abs(XAxis->max_value)))
680 gSysDevice.ORIENTATION[0].axMin = 0;
681 gSysDevice.ORIENTATION[0].axMax = 3600;
682 gSysDevice.ORIENTATION[0].axUnits = TU_CIRCLE;
683 gSysDevice.ORIENTATION[0].axResolution
684 = CASTFIX32(3600);
685 gSysDevice.ORIENTATION[1].axMin = -1000;
686 gSysDevice.ORIENTATION[1].axMax = 1000;
687 gSysDevice.ORIENTATION[1].axUnits = TU_CIRCLE;
688 gSysDevice.ORIENTATION[1].axResolution
689 = CASTFIX32(3600);
690 Axis++;
693 axis_read_complete = TRUE;
695 break;
696 case ButtonClass:
698 int cchBuf = 512;
699 int cchPos = 0;
700 int i;
702 Button = (XButtonInfoPtr) any;
703 TRACE(" ButtonInput %d: [class %d|length %d|num_buttons %d]\n",
704 class_loop, (int) Button->class, Button->length, Button->num_buttons);
705 cursor->BTNNAMES = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*cchBuf);
706 for (i = 0; i < cursor->BUTTONS; i++)
708 /* FIXME - these names are probably incorrect */
709 int cch = strlenW(cursor->NAME) + 1;
710 while (cch > cchBuf - cchPos - 1) /* we want one extra byte for the last NUL */
712 cchBuf *= 2;
713 cursor->BTNNAMES = HeapReAlloc(GetProcessHeap(), 0, cursor->BTNNAMES, sizeof(WCHAR)*cchBuf);
716 strcpyW(cursor->BTNNAMES + cchPos, cursor->NAME);
717 cchPos += cch;
719 cursor->BTNNAMES[cchPos++] = 0;
720 cursor->BTNNAMES = HeapReAlloc(GetProcessHeap(), 0, cursor->BTNNAMES, sizeof(WCHAR)*cchPos);
721 cursor->cchBTNNAMES = cchPos;
723 break;
725 any = (XAnyClassPtr) ((char*) any + any->length);
727 break;
730 XFree(device_type);
732 pXFreeDeviceList(devices);
734 if (axis_read_complete)
736 gSysDevice.NCSRTYPES = cursor_target+1;
737 gNumCursors = cursor_target+1;
738 Tablet_FixupCursors();
740 else
741 WARN("Did not find a valid stylus cursor with >= 5 axes, returning 0 valid devices.\n");
743 wine_tsx11_unlock();
746 static int figure_deg(int x, int y)
748 float angle;
750 angle = atan2((float)y, (float)x);
751 angle += M_PI_2;
752 if (angle <= 0)
753 angle += 2 * M_PI;
755 return (0.5 + (angle * 1800.0 / M_PI));
758 static int get_button_state(int curnum)
760 return button_state[curnum];
763 static void set_button_state(int curnum, XID deviceid)
765 struct x11drv_thread_data *data = x11drv_thread_data();
766 XDevice *device;
767 XDeviceState *state;
768 XInputClass *class;
769 int loop;
770 int rc = 0;
772 wine_tsx11_lock();
773 device = pXOpenDevice(data->display,deviceid);
774 state = pXQueryDeviceState(data->display,device);
776 if (state)
778 class = state->data;
779 for (loop = 0; loop < state->num_classes; loop++)
781 if (class->class == ButtonClass)
783 int loop2;
784 XButtonState *button_state = (XButtonState*)class;
785 for (loop2 = 0; loop2 < button_state->num_buttons; loop2++)
787 if (button_state->buttons[loop2 / 8] & (1 << (loop2 % 8)))
789 rc |= (1<<loop2);
793 class = (XInputClass *) ((char *) class + class->length);
796 pXFreeDeviceState(state);
797 wine_tsx11_unlock();
798 button_state[curnum] = rc;
801 static int cursor_from_device(DWORD deviceid, LPWTI_CURSORS_INFO *cursorp)
803 int i;
804 for (i = 0; i < gNumCursors; i++)
805 if (gSysCursor[i].PHYSID == deviceid)
807 *cursorp = &gSysCursor[i];
808 return i;
811 ERR("Could not map device id %d to a cursor\n", (int) deviceid);
812 return -1;
815 static void motion_event( HWND hwnd, XEvent *event )
817 XDeviceMotionEvent *motion = (XDeviceMotionEvent *)event;
818 LPWTI_CURSORS_INFO cursor;
819 int curnum = cursor_from_device(motion->deviceid, &cursor);
820 if (curnum < 0)
821 return;
823 memset(&gMsgPacket,0,sizeof(WTPACKET));
825 TRACE("Received tablet motion event (%p); device id %d, cursor num %d\n",hwnd, (int) motion->deviceid, curnum);
827 /* Set cursor to inverted if cursor is the eraser */
828 gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
829 gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(motion->time);
830 gMsgPacket.pkSerialNumber = gSerial++;
831 gMsgPacket.pkCursor = curnum;
832 gMsgPacket.pkX = motion->axis_data[0];
833 gMsgPacket.pkY = motion->axis_data[1];
834 gMsgPacket.pkOrientation.orAzimuth = figure_deg(motion->axis_data[3],motion->axis_data[4]);
835 gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max
836 (abs(motion->axis_data[3]),
837 abs(motion->axis_data[4])))
838 * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
839 gMsgPacket.pkNormalPressure = motion->axis_data[2];
840 gMsgPacket.pkButtons = get_button_state(curnum);
841 SendMessageW(hwndTabletDefault,WT_PACKET,gMsgPacket.pkSerialNumber,(LPARAM)hwnd);
844 static void button_event( HWND hwnd, XEvent *event )
846 XDeviceButtonEvent *button = (XDeviceButtonEvent *) event;
847 LPWTI_CURSORS_INFO cursor;
848 int curnum = cursor_from_device(button->deviceid, &cursor);
849 if (curnum < 0)
850 return;
852 memset(&gMsgPacket,0,sizeof(WTPACKET));
854 TRACE("Received tablet button %s event\n", (event->type == button_press_type)?"press":"release");
856 /* Set cursor to inverted if cursor is the eraser */
857 gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
858 set_button_state(curnum, button->deviceid);
859 gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(button->time);
860 gMsgPacket.pkSerialNumber = gSerial++;
861 gMsgPacket.pkCursor = curnum;
862 gMsgPacket.pkX = button->axis_data[0];
863 gMsgPacket.pkY = button->axis_data[1];
864 gMsgPacket.pkOrientation.orAzimuth = figure_deg(button->axis_data[3],button->axis_data[4]);
865 gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(button->axis_data[3]),
866 abs(button->axis_data[4])))
867 * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
868 gMsgPacket.pkNormalPressure = button->axis_data[2];
869 gMsgPacket.pkButtons = get_button_state(curnum);
870 SendMessageW(hwndTabletDefault,WT_PACKET,gMsgPacket.pkSerialNumber,(LPARAM)hwnd);
873 static void key_event( HWND hwnd, XEvent *event )
875 if (event->type == key_press_type)
876 FIXME("Received tablet key press event\n");
877 else
878 FIXME("Received tablet key release event\n");
881 static void proximity_event( HWND hwnd, XEvent *event )
883 XProximityNotifyEvent *proximity = (XProximityNotifyEvent *) event;
884 LPWTI_CURSORS_INFO cursor;
885 int curnum = cursor_from_device(proximity->deviceid, &cursor);
886 LPARAM proximity_info;
888 TRACE("hwnd=%p\n", hwnd);
890 if (curnum < 0)
891 return;
893 memset(&gMsgPacket,0,sizeof(WTPACKET));
895 /* Set cursor to inverted if cursor is the eraser */
896 gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
897 gMsgPacket.pkStatus |= (event->type==proximity_out_type)?TPS_PROXIMITY:0;
898 gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(proximity->time);
899 gMsgPacket.pkSerialNumber = gSerial++;
900 gMsgPacket.pkCursor = curnum;
901 gMsgPacket.pkX = proximity->axis_data[0];
902 gMsgPacket.pkY = proximity->axis_data[1];
903 gMsgPacket.pkOrientation.orAzimuth = figure_deg(proximity->axis_data[3],proximity->axis_data[4]);
904 gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(proximity->axis_data[3]),
905 abs(proximity->axis_data[4])))
906 * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
907 gMsgPacket.pkNormalPressure = proximity->axis_data[2];
908 gMsgPacket.pkButtons = get_button_state(curnum);
910 /* FIXME: LPARAM loword is true when cursor entering context, false when leaving context
911 * This needs to be handled here or in wintab32. Using the proximity_in_type is not correct
912 * but kept for now.
913 * LPARAM hiword is "non-zero when the cursor is leaving or entering hardware proximity"
914 * WPARAM contains context handle.
915 * HWND to HCTX is handled by wintab32.
917 proximity_info = MAKELPARAM((event->type == proximity_in_type),
918 (event->type == proximity_in_type) || (event->type == proximity_out_type));
919 SendMessageW(hwndTabletDefault, WT_PROXIMITY, (WPARAM)hwnd, proximity_info);
922 /***********************************************************************
923 * X11DRV_AttachEventQueueToTablet (X11DRV.@)
925 int X11DRV_AttachEventQueueToTablet(HWND hOwner)
927 struct x11drv_thread_data *data = x11drv_thread_data();
928 int num_devices;
929 int loop;
930 int cur_loop;
931 XDeviceInfo *devices;
932 XDeviceInfo *target = NULL;
933 XDevice *the_device;
934 XEventClass event_list[7];
935 Window win = X11DRV_get_whole_window( hOwner );
937 if (!win) return 0;
939 TRACE("Creating context for window %p (%lx) %i cursors\n", hOwner, win, gNumCursors);
941 wine_tsx11_lock();
942 devices = pXListInputDevices(data->display, &num_devices);
944 X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
945 for (cur_loop=0; cur_loop < gNumCursors; cur_loop++)
947 char cursorNameA[WT_MAX_NAME_LEN];
948 int event_number=0;
950 /* the cursor name fits in the buffer because too long names are skipped */
951 WideCharToMultiByte(CP_UNIXCP, 0, gSysCursor[cur_loop].NAME, -1, cursorNameA, WT_MAX_NAME_LEN, NULL, NULL);
952 for (loop=0; loop < num_devices; loop ++)
953 if (strcmp(devices[loop].name, cursorNameA) == 0)
954 target = &devices[loop];
956 TRACE("Opening cursor %i id %i\n",cur_loop,(INT)target->id);
958 the_device = pXOpenDevice(data->display, target->id);
960 if (!the_device)
962 WARN("Unable to Open device\n");
963 continue;
966 if (the_device->num_classes > 0)
968 DeviceKeyPress(the_device, key_press_type, event_list[event_number]);
969 if (key_press_type) event_number++;
970 DeviceKeyRelease(the_device, key_release_type, event_list[event_number]);
971 if (key_release_type) event_number++;
972 DeviceButtonPress(the_device, button_press_type, event_list[event_number]);
973 if (button_press_type) event_number++;
974 DeviceButtonRelease(the_device, button_release_type, event_list[event_number]);
975 if (button_release_type) event_number++;
976 DeviceMotionNotify(the_device, motion_type, event_list[event_number]);
977 if (motion_type) event_number++;
978 ProximityIn(the_device, proximity_in_type, event_list[event_number]);
979 if (proximity_in_type) event_number++;
980 ProximityOut(the_device, proximity_out_type, event_list[event_number]);
981 if (proximity_out_type) event_number++;
983 if (key_press_type) X11DRV_register_event_handler( key_press_type, key_event );
984 if (key_release_type) X11DRV_register_event_handler( key_release_type, key_event );
985 if (button_press_type) X11DRV_register_event_handler( button_press_type, button_event );
986 if (button_release_type) X11DRV_register_event_handler( button_release_type, button_event );
987 if (motion_type) X11DRV_register_event_handler( motion_type, motion_event );
988 if (proximity_in_type) X11DRV_register_event_handler( proximity_in_type, proximity_event );
989 if (proximity_out_type) X11DRV_register_event_handler( proximity_out_type, proximity_event );
991 pXSelectExtensionEvent(data->display, win, event_list, event_number);
994 XSync(data->display, False);
995 X11DRV_check_error();
997 if (NULL != devices) pXFreeDeviceList(devices);
998 wine_tsx11_unlock();
999 return 0;
1002 /***********************************************************************
1003 * X11DRV_GetCurrentPacket (X11DRV.@)
1005 int X11DRV_GetCurrentPacket(LPWTPACKET packet)
1007 *packet = gMsgPacket;
1008 return 1;
1012 static inline int CopyTabletData(LPVOID target, LPCVOID src, INT size)
1015 * It is valid to call CopyTabletData with NULL.
1016 * This handles the WTInfo() case where lpOutput is null.
1018 if(target != NULL)
1019 memcpy(target,src,size);
1020 return(size);
1023 /***********************************************************************
1024 * X11DRV_WTInfoW (X11DRV.@)
1026 UINT X11DRV_WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
1029 * It is valid to call WTInfoA with lpOutput == NULL, as per standard.
1030 * lpOutput == NULL signifies the user only wishes
1031 * to find the size of the data.
1032 * NOTE:
1033 * From now on use CopyTabletData to fill lpOutput. memcpy will break
1034 * the code.
1036 int rc = 0;
1037 LPWTI_CURSORS_INFO tgtcursor;
1038 TRACE("(%u, %u, %p)\n", wCategory, nIndex, lpOutput);
1040 switch(wCategory)
1042 case 0:
1043 /* return largest necessary buffer */
1044 TRACE("%i cursors\n",gNumCursors);
1045 if (gNumCursors>0)
1047 FIXME("Return proper size\n");
1048 rc = 200;
1050 break;
1051 case WTI_INTERFACE:
1052 switch (nIndex)
1054 WORD version;
1055 UINT num;
1056 case IFC_WINTABID:
1058 static const WCHAR driver[] = {'W','i','n','e',' ','W','i','n','t','a','b',' ','1','.','1',0};
1059 rc = CopyTabletData(lpOutput, driver, (strlenW(driver) + 1) * sizeof(WCHAR));
1060 break;
1062 case IFC_SPECVERSION:
1063 version = (0x01) | (0x01 << 8);
1064 rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
1065 break;
1066 case IFC_IMPLVERSION:
1067 version = (0x00) | (0x01 << 8);
1068 rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
1069 break;
1070 case IFC_NDEVICES:
1071 num = 1;
1072 rc = CopyTabletData(lpOutput, &num,sizeof(num));
1073 break;
1074 case IFC_NCURSORS:
1075 num = gNumCursors;
1076 rc = CopyTabletData(lpOutput, &num,sizeof(num));
1077 break;
1078 default:
1079 FIXME("WTI_INTERFACE unhandled index %i\n",nIndex);
1080 rc = 0;
1082 break;
1083 case WTI_DEFSYSCTX:
1084 case WTI_DDCTXS:
1085 case WTI_DEFCONTEXT:
1086 switch (nIndex)
1088 case 0:
1089 rc = CopyTabletData(lpOutput, &gSysContext,
1090 sizeof(LOGCONTEXTW));
1091 break;
1092 case CTX_NAME:
1093 rc = CopyTabletData(lpOutput, &gSysContext.lcName,
1094 (strlenW(gSysContext.lcName)+1) * sizeof(WCHAR));
1095 break;
1096 case CTX_OPTIONS:
1097 rc = CopyTabletData(lpOutput, &gSysContext.lcOptions,
1098 sizeof(UINT));
1099 break;
1100 case CTX_STATUS:
1101 rc = CopyTabletData(lpOutput, &gSysContext.lcStatus,
1102 sizeof(UINT));
1103 break;
1104 case CTX_LOCKS:
1105 rc= CopyTabletData (lpOutput, &gSysContext.lcLocks,
1106 sizeof(UINT));
1107 break;
1108 case CTX_MSGBASE:
1109 rc = CopyTabletData(lpOutput, &gSysContext.lcMsgBase,
1110 sizeof(UINT));
1111 break;
1112 case CTX_DEVICE:
1113 rc = CopyTabletData(lpOutput, &gSysContext.lcDevice,
1114 sizeof(UINT));
1115 break;
1116 case CTX_PKTRATE:
1117 rc = CopyTabletData(lpOutput, &gSysContext.lcPktRate,
1118 sizeof(UINT));
1119 break;
1120 case CTX_PKTDATA:
1121 rc = CopyTabletData(lpOutput, &gSysContext.lcPktData,
1122 sizeof(WTPKT));
1123 break;
1124 case CTX_PKTMODE:
1125 rc = CopyTabletData(lpOutput, &gSysContext.lcPktMode,
1126 sizeof(WTPKT));
1127 break;
1128 case CTX_MOVEMASK:
1129 rc = CopyTabletData(lpOutput, &gSysContext.lcMoveMask,
1130 sizeof(WTPKT));
1131 break;
1132 case CTX_BTNDNMASK:
1133 rc = CopyTabletData(lpOutput, &gSysContext.lcBtnDnMask,
1134 sizeof(DWORD));
1135 break;
1136 case CTX_BTNUPMASK:
1137 rc = CopyTabletData(lpOutput, &gSysContext.lcBtnUpMask,
1138 sizeof(DWORD));
1139 break;
1140 case CTX_INORGX:
1141 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgX,
1142 sizeof(LONG));
1143 break;
1144 case CTX_INORGY:
1145 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgY,
1146 sizeof(LONG));
1147 break;
1148 case CTX_INORGZ:
1149 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgZ,
1150 sizeof(LONG));
1151 break;
1152 case CTX_INEXTX:
1153 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtX,
1154 sizeof(LONG));
1155 break;
1156 case CTX_INEXTY:
1157 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtY,
1158 sizeof(LONG));
1159 break;
1160 case CTX_INEXTZ:
1161 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtZ,
1162 sizeof(LONG));
1163 break;
1164 case CTX_OUTORGX:
1165 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgX,
1166 sizeof(LONG));
1167 break;
1168 case CTX_OUTORGY:
1169 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgY,
1170 sizeof(LONG));
1171 break;
1172 case CTX_OUTORGZ:
1173 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgZ,
1174 sizeof(LONG));
1175 break;
1176 case CTX_OUTEXTX:
1177 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtX,
1178 sizeof(LONG));
1179 break;
1180 case CTX_OUTEXTY:
1181 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtY,
1182 sizeof(LONG));
1183 break;
1184 case CTX_OUTEXTZ:
1185 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtZ,
1186 sizeof(LONG));
1187 break;
1188 case CTX_SENSX:
1189 rc = CopyTabletData(lpOutput, &gSysContext.lcSensX,
1190 sizeof(LONG));
1191 break;
1192 case CTX_SENSY:
1193 rc = CopyTabletData(lpOutput, &gSysContext.lcSensY,
1194 sizeof(LONG));
1195 break;
1196 case CTX_SENSZ:
1197 rc = CopyTabletData(lpOutput, &gSysContext.lcSensZ,
1198 sizeof(LONG));
1199 break;
1200 case CTX_SYSMODE:
1201 rc = CopyTabletData(lpOutput, &gSysContext.lcSysMode,
1202 sizeof(LONG));
1203 break;
1204 case CTX_SYSORGX:
1205 rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgX,
1206 sizeof(LONG));
1207 break;
1208 case CTX_SYSORGY:
1209 rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgY,
1210 sizeof(LONG));
1211 break;
1212 case CTX_SYSEXTX:
1213 rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtX,
1214 sizeof(LONG));
1215 break;
1216 case CTX_SYSEXTY:
1217 rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtY,
1218 sizeof(LONG));
1219 break;
1220 case CTX_SYSSENSX:
1221 rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensX,
1222 sizeof(LONG));
1223 break;
1224 case CTX_SYSSENSY:
1225 rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensY,
1226 sizeof(LONG));
1227 break;
1228 default:
1229 FIXME("WTI_DEFSYSCTX unhandled index %i\n",nIndex);
1230 rc = 0;
1232 break;
1233 case WTI_CURSORS:
1234 case WTI_CURSORS+1:
1235 case WTI_CURSORS+2:
1236 case WTI_CURSORS+3:
1237 case WTI_CURSORS+4:
1238 case WTI_CURSORS+5:
1239 case WTI_CURSORS+6:
1240 case WTI_CURSORS+7:
1241 case WTI_CURSORS+8:
1242 case WTI_CURSORS+9:
1243 if (wCategory - WTI_CURSORS >= gNumCursors)
1245 rc = 0;
1246 WARN("Requested cursor information for nonexistent cursor %d; only %d cursors\n",
1247 wCategory - WTI_CURSORS, gNumCursors);
1249 else
1251 tgtcursor = &gSysCursor[wCategory - WTI_CURSORS];
1252 switch (nIndex)
1254 case CSR_NAME:
1255 rc = CopyTabletData(lpOutput, &tgtcursor->NAME,
1256 (strlenW(tgtcursor->NAME)+1) * sizeof(WCHAR));
1257 break;
1258 case CSR_ACTIVE:
1259 rc = CopyTabletData(lpOutput,&tgtcursor->ACTIVE,
1260 sizeof(BOOL));
1261 break;
1262 case CSR_PKTDATA:
1263 rc = CopyTabletData(lpOutput,&tgtcursor->PKTDATA,
1264 sizeof(WTPKT));
1265 break;
1266 case CSR_BUTTONS:
1267 rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONS,
1268 sizeof(BYTE));
1269 break;
1270 case CSR_BUTTONBITS:
1271 rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONBITS,
1272 sizeof(BYTE));
1273 break;
1274 case CSR_BTNNAMES:
1275 FIXME("Button Names not returned correctly\n");
1276 rc = CopyTabletData(lpOutput,&tgtcursor->BTNNAMES,
1277 tgtcursor->cchBTNNAMES*sizeof(WCHAR));
1278 break;
1279 case CSR_BUTTONMAP:
1280 rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONMAP,
1281 sizeof(BYTE)*32);
1282 break;
1283 case CSR_SYSBTNMAP:
1284 rc = CopyTabletData(lpOutput,&tgtcursor->SYSBTNMAP,
1285 sizeof(BYTE)*32);
1286 break;
1287 case CSR_NPBTNMARKS:
1288 rc = CopyTabletData(lpOutput,&tgtcursor->NPBTNMARKS,
1289 sizeof(UINT)*2);
1290 break;
1291 case CSR_NPBUTTON:
1292 rc = CopyTabletData(lpOutput,&tgtcursor->NPBUTTON,
1293 sizeof(BYTE));
1294 break;
1295 case CSR_NPRESPONSE:
1296 FIXME("Not returning CSR_NPRESPONSE correctly\n");
1297 rc = 0;
1298 break;
1299 case CSR_TPBUTTON:
1300 rc = CopyTabletData(lpOutput,&tgtcursor->TPBUTTON,
1301 sizeof(BYTE));
1302 break;
1303 case CSR_TPBTNMARKS:
1304 rc = CopyTabletData(lpOutput,&tgtcursor->TPBTNMARKS,
1305 sizeof(UINT)*2);
1306 break;
1307 case CSR_TPRESPONSE:
1308 FIXME("Not returning CSR_TPRESPONSE correctly\n");
1309 rc = 0;
1310 break;
1311 case CSR_PHYSID:
1313 DWORD id;
1314 id = tgtcursor->PHYSID;
1315 rc = CopyTabletData(lpOutput,&id,sizeof(DWORD));
1317 break;
1318 case CSR_MODE:
1319 rc = CopyTabletData(lpOutput,&tgtcursor->MODE,sizeof(UINT));
1320 break;
1321 case CSR_MINPKTDATA:
1322 rc = CopyTabletData(lpOutput,&tgtcursor->MINPKTDATA,
1323 sizeof(UINT));
1324 break;
1325 case CSR_MINBUTTONS:
1326 rc = CopyTabletData(lpOutput,&tgtcursor->MINBUTTONS,
1327 sizeof(UINT));
1328 break;
1329 case CSR_CAPABILITIES:
1330 rc = CopyTabletData(lpOutput,&tgtcursor->CAPABILITIES,
1331 sizeof(UINT));
1332 break;
1333 case CSR_TYPE:
1334 rc = CopyTabletData(lpOutput,&tgtcursor->TYPE,
1335 sizeof(UINT));
1336 break;
1337 default:
1338 FIXME("WTI_CURSORS unhandled index %i\n",nIndex);
1339 rc = 0;
1342 break;
1343 case WTI_DEVICES:
1344 switch (nIndex)
1346 case DVC_NAME:
1347 rc = CopyTabletData(lpOutput,gSysDevice.NAME,
1348 (strlenW(gSysDevice.NAME)+1) * sizeof(WCHAR));
1349 break;
1350 case DVC_HARDWARE:
1351 rc = CopyTabletData(lpOutput,&gSysDevice.HARDWARE,
1352 sizeof(UINT));
1353 break;
1354 case DVC_NCSRTYPES:
1355 rc = CopyTabletData(lpOutput,&gSysDevice.NCSRTYPES,
1356 sizeof(UINT));
1357 break;
1358 case DVC_FIRSTCSR:
1359 rc = CopyTabletData(lpOutput,&gSysDevice.FIRSTCSR,
1360 sizeof(UINT));
1361 break;
1362 case DVC_PKTRATE:
1363 rc = CopyTabletData(lpOutput,&gSysDevice.PKTRATE,
1364 sizeof(UINT));
1365 break;
1366 case DVC_PKTDATA:
1367 rc = CopyTabletData(lpOutput,&gSysDevice.PKTDATA,
1368 sizeof(WTPKT));
1369 break;
1370 case DVC_PKTMODE:
1371 rc = CopyTabletData(lpOutput,&gSysDevice.PKTMODE,
1372 sizeof(WTPKT));
1373 break;
1374 case DVC_CSRDATA:
1375 rc = CopyTabletData(lpOutput,&gSysDevice.CSRDATA,
1376 sizeof(WTPKT));
1377 break;
1378 case DVC_XMARGIN:
1379 rc = CopyTabletData(lpOutput,&gSysDevice.XMARGIN,
1380 sizeof(INT));
1381 break;
1382 case DVC_YMARGIN:
1383 rc = CopyTabletData(lpOutput,&gSysDevice.YMARGIN,
1384 sizeof(INT));
1385 break;
1386 case DVC_ZMARGIN:
1387 rc = 0; /* unsupported */
1389 rc = CopyTabletData(lpOutput,&gSysDevice.ZMARGIN,
1390 sizeof(INT));
1392 break;
1393 case DVC_X:
1394 rc = CopyTabletData(lpOutput,&gSysDevice.X,
1395 sizeof(AXIS));
1396 break;
1397 case DVC_Y:
1398 rc = CopyTabletData(lpOutput,&gSysDevice.Y,
1399 sizeof(AXIS));
1400 break;
1401 case DVC_Z:
1402 rc = 0; /* unsupported */
1404 rc = CopyTabletData(lpOutput,&gSysDevice.Z,
1405 sizeof(AXIS));
1407 break;
1408 case DVC_NPRESSURE:
1409 rc = CopyTabletData(lpOutput,&gSysDevice.NPRESSURE,
1410 sizeof(AXIS));
1411 break;
1412 case DVC_TPRESSURE:
1413 rc = 0; /* unsupported */
1415 rc = CopyTabletData(lpOutput,&gSysDevice.TPRESSURE,
1416 sizeof(AXIS));
1418 break;
1419 case DVC_ORIENTATION:
1420 rc = CopyTabletData(lpOutput,&gSysDevice.ORIENTATION,
1421 sizeof(AXIS)*3);
1422 break;
1423 case DVC_ROTATION:
1424 rc = 0; /* unsupported */
1426 rc = CopyTabletData(lpOutput,&gSysDevice.ROTATION,
1427 sizeof(AXIS)*3);
1429 break;
1430 case DVC_PNPID:
1431 rc = CopyTabletData(lpOutput,gSysDevice.PNPID,
1432 (strlenW(gSysDevice.PNPID)+1)*sizeof(WCHAR));
1433 break;
1434 default:
1435 FIXME("WTI_DEVICES unhandled index %i\n",nIndex);
1436 rc = 0;
1438 break;
1439 default:
1440 FIXME("Unhandled Category %i\n",wCategory);
1442 return rc;
1445 #else /* SONAME_LIBXI */
1447 /***********************************************************************
1448 * AttachEventQueueToTablet (X11DRV.@)
1450 int X11DRV_AttachEventQueueToTablet(HWND hOwner)
1452 return 0;
1455 /***********************************************************************
1456 * GetCurrentPacket (X11DRV.@)
1458 int X11DRV_GetCurrentPacket(LPWTPACKET packet)
1460 return 0;
1463 /***********************************************************************
1464 * LoadTabletInfo (X11DRV.@)
1466 void X11DRV_LoadTabletInfo(HWND hwnddefault)
1470 /***********************************************************************
1471 * WTInfoW (X11DRV.@)
1473 UINT X11DRV_WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
1475 return 0;
1478 #endif /* SONAME_LIBXI */