localspl: Add unixname port extension.
[wine.git] / dlls / winex11.drv / wintab.c
blob6f1437f14c628550f768ed31d87b1454e0bd6a36
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 #if 0
22 #pragma makedep unix
23 #endif
25 #include "config.h"
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <math.h>
30 #include <dlfcn.h>
32 #include "windef.h"
33 #include "winbase.h"
34 #include "x11drv.h"
35 #include "wine/debug.h"
36 #include "wintab.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(wintab32);
40 #define WT_MAX_NAME_LEN 256
42 typedef struct tagWTI_CURSORS_INFO
44 WCHAR NAME[WT_MAX_NAME_LEN];
45 /* a displayable zero-terminated string containing the name of the
46 * cursor.
48 BOOL ACTIVE;
49 /* whether the cursor is currently connected. */
50 WTPKT PKTDATA;
51 /* a bit mask indicating the packet data items supported when this
52 * cursor is connected.
54 BYTE BUTTONS;
55 /* the number of buttons on this cursor. */
56 BYTE BUTTONBITS;
57 /* the number of bits of raw button data returned by the hardware.*/
58 DWORD cchBTNNAMES;
59 WCHAR *BTNNAMES;
60 /* a list of zero-terminated strings containing the names of the
61 * cursor's buttons. The number of names in the list is the same as the
62 * number of buttons on the cursor. The names are separated by a single
63 * zero character; the list is terminated by two zero characters.
65 BYTE BUTTONMAP[32];
66 /* a 32 byte array of logical button numbers, one for each physical
67 * button.
69 BYTE SYSBTNMAP[32];
70 /* a 32 byte array of button action codes, one for each logical
71 * button.
73 BYTE NPBUTTON;
74 /* the physical button number of the button that is controlled by normal
75 * pressure.
77 UINT NPBTNMARKS[2];
78 /* an array of two UINTs, specifying the button marks for the normal
79 * pressure button. The first UINT contains the release mark; the second
80 * contains the press mark.
82 UINT *NPRESPONSE;
83 /* an array of UINTs describing the pressure response curve for normal
84 * pressure.
86 BYTE TPBUTTON;
87 /* the physical button number of the button that is controlled by
88 * tangential pressure.
90 UINT TPBTNMARKS[2];
91 /* an array of two UINTs, specifying the button marks for the tangential
92 * pressure button. The first UINT contains the release mark; the second
93 * contains the press mark.
95 UINT *TPRESPONSE;
96 /* an array of UINTs describing the pressure response curve for
97 * tangential pressure.
99 DWORD PHYSID;
100 /* a manufacturer-specific physical identifier for the cursor. This
101 * value will distinguish the physical cursor from others on the same
102 * device. This physical identifier allows applications to bind
103 * functions to specific physical cursors, even if category numbers
104 * change and multiple, otherwise identical, physical cursors are
105 * present.
107 UINT MODE;
108 /* the cursor mode number of this cursor type, if this cursor type has
109 * the CRC_MULTIMODE capability.
111 UINT MINPKTDATA;
112 /* the minimum set of data available from a physical cursor in this
113 * cursor type, if this cursor type has the CRC_AGGREGATE capability.
115 UINT MINBUTTONS;
116 /* the minimum number of buttons of physical cursors in the cursor type,
117 * if this cursor type has the CRC_AGGREGATE capability.
119 UINT CAPABILITIES;
120 /* flags indicating cursor capabilities, as defined below:
121 CRC_MULTIMODE
122 Indicates this cursor type describes one of several modes of a
123 single physical cursor. Consecutive cursor type categories
124 describe the modes; the CSR_MODE data item gives the mode number
125 of each cursor type.
126 CRC_AGGREGATE
127 Indicates this cursor type describes several physical cursors
128 that cannot be distinguished by software.
129 CRC_INVERT
130 Indicates this cursor type describes the physical cursor in its
131 inverted orientation; the previous consecutive cursor type
132 category describes the normal orientation.
134 UINT TYPE;
135 /* Manufacturer Unique id for the item type */
136 } WTI_CURSORS_INFO, *LPWTI_CURSORS_INFO;
139 typedef struct tagWTI_DEVICES_INFO
141 WCHAR NAME[WT_MAX_NAME_LEN];
142 /* a displayable null- terminated string describing the device,
143 * manufacturer, and revision level.
145 UINT HARDWARE;
146 /* flags indicating hardware and driver capabilities, as defined
147 * below:
148 HWC_INTEGRATED:
149 Indicates that the display and digitizer share the same surface.
150 HWC_TOUCH
151 Indicates that the cursor must be in physical contact with the
152 device to report position.
153 HWC_HARDPROX
154 Indicates that device can generate events when the cursor is
155 entering and leaving the physical detection range.
156 HWC_PHYSID_CURSORS
157 Indicates that device can uniquely identify the active cursor in
158 hardware.
160 UINT NCSRTYPES;
161 /* the number of supported cursor types.*/
162 UINT FIRSTCSR;
163 /* the first cursor type number for the device. */
164 UINT PKTRATE;
165 /* the maximum packet report rate in Hertz. */
166 WTPKT PKTDATA;
167 /* a bit mask indicating which packet data items are always available.*/
168 WTPKT PKTMODE;
169 /* a bit mask indicating which packet data items are physically
170 * relative, i.e., items for which the hardware can only report change,
171 * not absolute measurement.
173 WTPKT CSRDATA;
174 /* a bit mask indicating which packet data items are only available when
175 * certain cursors are connected. The individual cursor descriptions
176 * must be consulted to determine which cursors return which data.
178 INT XMARGIN;
179 INT YMARGIN;
180 INT ZMARGIN;
181 /* the size of tablet context margins in tablet native coordinates, in
182 * the x, y, and z directions, respectively.
184 AXIS X;
185 AXIS Y;
186 AXIS Z;
187 /* the tablet's range and resolution capabilities, in the x, y, and z
188 * axes, respectively.
190 AXIS NPRESSURE;
191 AXIS TPRESSURE;
192 /* the tablet's range and resolution capabilities, for the normal and
193 * tangential pressure inputs, respectively.
195 AXIS ORIENTATION[3];
196 /* a 3-element array describing the tablet's orientation range and
197 * resolution capabilities.
199 AXIS ROTATION[3];
200 /* a 3-element array describing the tablet's rotation range and
201 * resolution capabilities.
203 WCHAR PNPID[WT_MAX_NAME_LEN];
204 /* a null-terminated string containing the devices Plug and Play ID.*/
205 } WTI_DEVICES_INFO, *LPWTI_DEVICES_INFO;
208 /***********************************************************************
209 * WACOM WINTAB EXTENSIONS TO SUPPORT CSR_TYPE
210 * In Wintab 1.2, a CSR_TYPE feature was added. This adds the
211 * ability to return a type of cursor on a tablet.
212 * Unfortunately, we cannot get the cursor type directly from X,
213 * and it is not specified directly anywhere. So we virtualize
214 * the type here. (This is unfortunate, the kernel module has
215 * the exact type, but we have no way of getting that module to
216 * pass us that type).
218 * Reference linuxwacom driver project wcmCommon.c function
219 * idtotype for a much larger list of CSR_TYPE.
221 * http://linuxwacom.cvs.sourceforge.net/linuxwacom/linuxwacom-prod/src/xdrv/wcmCommon.c?view=markup
223 * The WTI_CURSORS_INFO.TYPE data is supposed to be used like this:
224 * (cursor.TYPE & 0x0F06) == target_cursor_type
225 * Reference: Section Unique ID
226 * http://www.wacomeng.com/devsupport/ibmpc/gddevpc.html
228 #define CSR_TYPE_PEN 0x822
229 #define CSR_TYPE_ERASER 0x82a
230 #define CSR_TYPE_MOUSE_2D 0x007
231 #define CSR_TYPE_MOUSE_4D 0x094
232 /* CSR_TYPE_OTHER is a special value! assumed no real world significance
233 * if a stylus type or eraser type eventually have this value
234 * it'll be a bug. As of 2008 05 21 we can be sure because
235 * linux wacom lists all the known values and this isn't one of them */
236 #define CSR_TYPE_OTHER 0x000
238 typedef struct tagWTPACKET {
239 HCTX pkContext;
240 UINT pkStatus;
241 LONG pkTime;
242 WTPKT pkChanged;
243 UINT pkSerialNumber;
244 UINT pkCursor;
245 DWORD pkButtons;
246 DWORD pkX;
247 DWORD pkY;
248 DWORD pkZ;
249 UINT pkNormalPressure;
250 UINT pkTangentPressure;
251 ORIENTATION pkOrientation;
252 ROTATION pkRotation; /* 1.1 */
253 } WTPACKET, *LPWTPACKET;
256 #ifdef SONAME_LIBXI
258 #include <X11/Xlib.h>
259 #include <X11/extensions/XInput.h>
261 static int motion_type;
262 static int button_press_type;
263 static int button_release_type;
264 static int key_press_type;
265 static int key_release_type;
266 static int proximity_in_type;
267 static int proximity_out_type;
269 static HWND hwndTabletDefault;
270 static WTPACKET gMsgPacket;
271 static DWORD gSerial;
272 static WTPACKET last_packet;
274 /* Reference: http://www.wacomeng.com/devsupport/ibmpc/gddevpc.html
276 * Cursors come in sets of 3 normally
277 * Cursor #0 = puck device 1
278 * Cursor #1 = stylus device 1
279 * Cursor #2 = eraser device 1
280 * Cursor #3 = puck device 2
281 * Cursor #4 = stylus device 2
282 * Cursor #5 = eraser device 2
283 * etc....
285 * A dual tracking/multimode tablet is one
286 * that supports 2 independent cursors of the same or
287 * different types simultaneously on a single tablet.
288 * This makes our cursor layout potentially like this
289 * Cursor #0 = puck 1 device 1
290 * Cursor #1 = stylus 1 device 1
291 * Cursor #2 = eraser 1 device 1
292 * Cursor #3 = puck 2 device 1
293 * Cursor #4 = stylus 2 device 1
294 * Cursor #5 = eraser 2 device 1
295 * Cursor #6 = puck 1 device 2
296 * etc.....
298 * So with multimode tablets we could potentially need
299 * 2 slots of the same type per tablet i.e.
300 * you are using 2 styluses at once so they would
301 * get placed in Cursors #1 and Cursor #4
303 * Now say someone has 2 multimode tablets with 2 erasers each
304 * now we would need Cursor #2, #5, #8, #11
305 * So to support that we need CURSORMAX of 12 (0 to 11)
306 * FIXME: we don't support more than 4 regular tablets or 2 multimode tablets */
307 #define CURSORMAX 12
308 static INT button_state[CURSORMAX];
310 static LOGCONTEXTW gSysContext;
311 static WTI_DEVICES_INFO gSysDevice;
312 static WTI_CURSORS_INFO gSysCursor[CURSORMAX];
313 static INT gNumCursors; /* do NOT use this to iterate through gSysCursor slots */
316 /* XInput stuff */
317 static void *xinput_handle;
319 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
320 MAKE_FUNCPTR(XListInputDevices)
321 MAKE_FUNCPTR(XFreeDeviceList)
322 MAKE_FUNCPTR(XOpenDevice)
323 MAKE_FUNCPTR(XQueryDeviceState)
324 MAKE_FUNCPTR(XGetDeviceButtonMapping)
325 MAKE_FUNCPTR(XCloseDevice)
326 MAKE_FUNCPTR(XSelectExtensionEvent)
327 MAKE_FUNCPTR(XFreeDeviceState)
328 #undef MAKE_FUNCPTR
330 static INT X11DRV_XInput_Init(void)
332 xinput_handle = dlopen(SONAME_LIBXI, RTLD_NOW);
333 if (xinput_handle)
335 #define LOAD_FUNCPTR(f) if((p##f = dlsym(xinput_handle, #f)) == NULL) goto sym_not_found
336 LOAD_FUNCPTR(XListInputDevices);
337 LOAD_FUNCPTR(XFreeDeviceList);
338 LOAD_FUNCPTR(XOpenDevice);
339 LOAD_FUNCPTR(XGetDeviceButtonMapping);
340 LOAD_FUNCPTR(XCloseDevice);
341 LOAD_FUNCPTR(XSelectExtensionEvent);
342 LOAD_FUNCPTR(XQueryDeviceState);
343 LOAD_FUNCPTR(XFreeDeviceState);
344 #undef LOAD_FUNCPTR
345 return 1;
347 sym_not_found:
348 return 0;
351 static int Tablet_ErrorHandler(Display *dpy, XErrorEvent *event, void* arg)
353 return 1;
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 static 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 == ':' || !*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
390 ** Wintab refers to any device that interacts with the tablet as a cursor,
391 ** (stylus, eraser, tablet mouse, airbrush, etc)
392 ** this is not to be confused with wacom x11 configuration "cursor" device.
393 ** Wacoms x11 config "cursor" refers to its device slot (which we mirror with
394 ** our gSysCursors) for puck like devices (tablet mice essentially).
397 static BOOL is_tablet_cursor(const char *name, const char *type)
399 int i;
400 static const char *tablet_cursor_allowlist[] = {
401 "wacom",
402 "wizardpen",
403 "acecad",
404 "tablet",
405 "cursor",
406 "stylus",
407 "eraser",
408 "pad",
409 NULL
412 for (i=0; tablet_cursor_allowlist[i] != NULL; i++) {
413 if (name && match_token(name, tablet_cursor_allowlist[i]))
414 return TRUE;
415 if (type && match_token(type, tablet_cursor_allowlist[i]))
416 return TRUE;
418 return FALSE;
421 static UINT get_cursor_type(const char *name, const char *type)
423 int i;
424 static const char* tablet_stylus_allowlist[] = {
425 "stylus",
426 "wizardpen",
427 "acecad",
428 "pen",
429 NULL
432 /* First check device type to avoid cases where name is "Pen and Eraser" and type is "ERASER" */
433 for (i=0; tablet_stylus_allowlist[i] != NULL; i++) {
434 if (type && match_token(type, tablet_stylus_allowlist[i]))
435 return CSR_TYPE_PEN;
437 if (type && match_token(type, "eraser"))
438 return CSR_TYPE_ERASER;
439 for (i=0; tablet_stylus_allowlist[i] != NULL; i++) {
440 if (name && match_token(name, tablet_stylus_allowlist[i]))
441 return CSR_TYPE_PEN;
443 if (name && match_token(name, "eraser"))
444 return CSR_TYPE_ERASER;
446 return CSR_TYPE_OTHER;
449 /* cursors are placed in gSysCursor rows depending on their type
450 * see CURSORMAX comments for more detail */
451 static BOOL add_system_cursor(LPWTI_CURSORS_INFO cursor)
453 UINT offset = 0;
455 if (cursor->TYPE == CSR_TYPE_PEN)
456 offset = 1;
457 else if (cursor->TYPE == CSR_TYPE_ERASER)
458 offset = 2;
460 for (; offset < CURSORMAX; offset += 3)
462 if (!gSysCursor[offset].ACTIVE)
464 gSysCursor[offset] = *cursor;
465 ++gNumCursors;
466 return TRUE;
470 return FALSE;
473 static void disable_system_cursors(void)
475 UINT i;
477 for (i = 0; i < CURSORMAX; ++i)
479 gSysCursor[i].ACTIVE = 0;
482 gNumCursors = 0;
486 /***********************************************************************
487 * x11drv_tablet_load_info
489 NTSTATUS x11drv_tablet_load_info( void *hwnd )
491 static const WCHAR SZ_CONTEXT_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','C','o','n','t','e','x','t',0};
492 static const WCHAR SZ_DEVICE_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','D','e','v','i','c','e',0};
493 static const WCHAR SZ_NON_PLUG_N_PLAY[] = {'n','o','n','-','p','l','u','g','-','n','-','p','l','a','y',0};
495 struct x11drv_thread_data *data = x11drv_init_thread_data();
496 int num_devices;
497 int loop;
498 XDeviceInfo *devices;
499 XDeviceInfo *target = NULL;
500 BOOL axis_read_complete= FALSE;
502 XAnyClassPtr any;
503 XButtonInfoPtr Button;
504 XValuatorInfoPtr Val;
505 XAxisInfoPtr Axis;
507 XDevice *opendevice;
509 if (!X11DRV_XInput_Init())
511 ERR("Unable to initialize the XInput library.\n");
512 return FALSE;
515 hwndTabletDefault = hwnd;
517 /* Do base initialization */
518 wcscpy(gSysContext.lcName, SZ_CONTEXT_NAME);
519 wcscpy(gSysDevice.NAME, SZ_DEVICE_NAME);
521 gSysContext.lcOptions = CXO_SYSTEM;
522 gSysContext.lcLocks = CXL_INSIZE | CXL_INASPECT | CXL_MARGIN |
523 CXL_SENSITIVITY | CXL_SYSOUT;
525 gSysContext.lcMsgBase= WT_DEFBASE;
526 gSysContext.lcDevice = 0;
527 gSysContext.lcPktData =
528 PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
529 PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
530 gSysContext.lcMoveMask=
531 PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
532 gSysContext.lcStatus = CXS_ONTOP;
533 gSysContext.lcPktRate = 100;
534 gSysContext.lcBtnDnMask = 0xffffffff;
535 gSysContext.lcBtnUpMask = 0xffffffff;
536 gSysContext.lcSensX = 65536;
537 gSysContext.lcSensY = 65536;
538 gSysContext.lcSensX = 65536;
539 gSysContext.lcSensZ = 65536;
540 gSysContext.lcSysSensX= 65536;
541 gSysContext.lcSysSensY= 65536;
542 gSysContext.lcSysExtX = NtUserGetSystemMetrics( SM_CXVIRTUALSCREEN );
543 gSysContext.lcSysExtY = NtUserGetSystemMetrics( SM_CYVIRTUALSCREEN );
545 /* initialize cursors */
546 disable_system_cursors();
548 /* Device Defaults */
549 gSysDevice.HARDWARE = HWC_HARDPROX|HWC_PHYSID_CURSORS;
550 gSysDevice.FIRSTCSR= 0;
551 gSysDevice.PKTRATE = 100;
552 gSysDevice.PKTDATA =
553 PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
554 PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
555 wcscpy(gSysDevice.PNPID, SZ_NON_PLUG_N_PLAY);
557 devices = pXListInputDevices(data->display, &num_devices);
558 if (!devices)
560 WARN("XInput Extensions reported as not available\n");
561 return FALSE;
563 TRACE("XListInputDevices reports %d devices\n", num_devices);
564 for (loop=0; loop < num_devices; loop++)
566 int class_loop;
567 char *device_type = devices[loop].type ? XGetAtomName(data->display, devices[loop].type) : NULL;
568 WTI_CURSORS_INFO cursor;
570 TRACE("Device %i: [id %d|name %s|type %s|num_classes %d|use %d]\n",
571 loop, (int) devices[loop].id, devices[loop].name, debugstr_a(device_type),
572 devices[loop].num_classes, devices[loop].use );
574 switch (devices[loop].use)
576 case IsXExtensionDevice:
577 #ifdef IsXExtensionPointer
578 case IsXExtensionPointer:
579 #endif
580 #ifdef IsXExtensionKeyboard
581 case IsXExtensionKeyboard:
582 #endif
583 TRACE("Is XExtension: Device, Keyboard, or Pointer\n");
584 target = &devices[loop];
586 if (strlen(target->name) >= WT_MAX_NAME_LEN)
588 ERR("Input device '%s' name too long - skipping\n", wine_dbgstr_a(target->name));
589 break;
592 X11DRV_expect_error(data->display, Tablet_ErrorHandler, NULL);
593 opendevice = pXOpenDevice(data->display,target->id);
594 if (!X11DRV_check_error() && opendevice)
596 unsigned char map[32];
597 int i;
598 int shft = 0;
600 X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
601 cursor.BUTTONS = pXGetDeviceButtonMapping(data->display, opendevice, map, 32);
602 if (X11DRV_check_error() || cursor.BUTTONS <= 0)
604 TRACE("No buttons, Non Tablet Device\n");
605 pXCloseDevice(data->display, opendevice);
606 break;
609 for (i=0; i< cursor.BUTTONS; i++,shft++)
611 cursor.BUTTONMAP[i] = map[i];
612 cursor.SYSBTNMAP[i] = (1<<shft);
614 pXCloseDevice(data->display, opendevice);
616 else
618 WARN("Unable to open device %s\n",target->name);
619 break;
621 ntdll_umbstowcs(target->name, strlen(target->name) + 1, cursor.NAME, WT_MAX_NAME_LEN);
623 if (! is_tablet_cursor(target->name, device_type))
625 WARN("Skipping device %d [name %s|type %s]; not apparently a tablet cursor type device\n",
626 loop, devices[loop].name, debugstr_a(device_type));
627 break;
630 cursor.ACTIVE = 1;
631 cursor.PKTDATA = PK_TIME | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y |
632 PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE |
633 PK_ORIENTATION;
635 cursor.PHYSID = target->id;
636 cursor.NPBUTTON = 1;
637 cursor.NPBTNMARKS[0] = 0 ;
638 cursor.NPBTNMARKS[1] = 1 ;
639 cursor.CAPABILITIES = CRC_MULTIMODE;
641 cursor.TYPE = get_cursor_type(target->name, device_type);
643 any = target->inputclassinfo;
645 for (class_loop = 0; class_loop < target->num_classes; class_loop++)
647 switch (any->class)
650 case ValuatorClass:
651 Val = (XValuatorInfoPtr) any;
652 TRACE(" ValidatorInput %d: [class %d|length %d|num_axes %d|mode %d|motion_buffer %ld]\n",
653 class_loop, (int) Val->class, Val->length, Val->num_axes, Val->mode, Val->motion_buffer);
654 if (TRACE_ON(wintab32))
655 trace_axes(Val);
657 /* FIXME: This is imperfect; we compute our devices capabilities based upon the
658 ** first pen type device we find. However, a more correct implementation
659 ** would require acquiring a wide variety of tablets and running through
660 ** the various inputs to see what the values are. Odds are that a
661 ** more 'correct' algorithm would condense to this one anyway.
663 if (!axis_read_complete && cursor.TYPE == CSR_TYPE_PEN)
665 Axis = (XAxisInfoPtr) ((char *) Val + sizeof
666 (XValuatorInfo));
668 if (Val->num_axes>=1)
670 /* Axis 1 is X */
671 gSysDevice.X.axMin = Axis->min_value;
672 gSysDevice.X.axMax= Axis->max_value;
673 gSysDevice.X.axUnits = TU_INCHES;
674 gSysDevice.X.axResolution = Axis->resolution;
675 gSysContext.lcInOrgX = Axis->min_value;
676 gSysContext.lcOutOrgX = Axis->min_value;
677 gSysContext.lcInExtX = Axis->max_value;
678 gSysContext.lcOutExtX = Axis->max_value;
679 Axis++;
681 if (Val->num_axes>=2)
683 /* Axis 2 is Y */
684 gSysDevice.Y.axMin = Axis->min_value;
685 gSysDevice.Y.axMax= Axis->max_value;
686 gSysDevice.Y.axUnits = TU_INCHES;
687 gSysDevice.Y.axResolution = Axis->resolution;
688 gSysContext.lcInOrgY = Axis->min_value;
689 gSysContext.lcOutOrgY = Axis->min_value;
690 gSysContext.lcInExtY = Axis->max_value;
691 gSysContext.lcOutExtY = Axis->max_value;
692 Axis++;
694 if (Val->num_axes>=3)
696 /* Axis 3 is Normal Pressure */
697 gSysDevice.NPRESSURE.axMin = Axis->min_value;
698 gSysDevice.NPRESSURE.axMax= Axis->max_value;
699 gSysDevice.NPRESSURE.axUnits = TU_INCHES;
700 gSysDevice.NPRESSURE.axResolution =
701 Axis->resolution;
702 Axis++;
704 if (Val->num_axes >= 5)
706 /* Axis 4 and 5 are X and Y tilt */
707 XAxisInfoPtr XAxis = Axis;
708 Axis++;
709 if (max (abs(Axis->max_value),
710 abs(XAxis->max_value)))
712 gSysDevice.ORIENTATION[0].axMin = 0;
713 gSysDevice.ORIENTATION[0].axMax = 3600;
714 gSysDevice.ORIENTATION[0].axUnits = TU_CIRCLE;
715 gSysDevice.ORIENTATION[0].axResolution
716 = CASTFIX32(3600);
717 gSysDevice.ORIENTATION[1].axMin = -1000;
718 gSysDevice.ORIENTATION[1].axMax = 1000;
719 gSysDevice.ORIENTATION[1].axUnits = TU_CIRCLE;
720 gSysDevice.ORIENTATION[1].axResolution
721 = CASTFIX32(3600);
722 gSysDevice.ORIENTATION[2].axMin = 0;
723 gSysDevice.ORIENTATION[2].axMax = 3600;
724 gSysDevice.ORIENTATION[2].axUnits = TU_CIRCLE;
725 gSysDevice.ORIENTATION[2].axResolution
726 = CASTFIX32(3600);
727 Axis++;
730 axis_read_complete = TRUE;
732 break;
733 case ButtonClass:
735 int cchBuf = 512;
736 int cchPos = 0;
737 int i;
739 Button = (XButtonInfoPtr) any;
740 TRACE(" ButtonInput %d: [class %d|length %d|num_buttons %d]\n",
741 class_loop, (int) Button->class, Button->length, Button->num_buttons);
742 cursor.BTNNAMES = malloc( sizeof(WCHAR) * cchBuf );
743 for (i = 0; i < cursor.BUTTONS; i++)
745 /* FIXME - these names are probably incorrect */
746 int cch = wcslen(cursor.NAME) + 1;
747 while (cch > cchBuf - cchPos - 1) /* we want one extra byte for the last NUL */
749 cchBuf *= 2;
750 cursor.BTNNAMES = realloc( cursor.BTNNAMES, sizeof(WCHAR) * cchBuf );
753 wcscpy(cursor.BTNNAMES + cchPos, cursor.NAME);
754 cchPos += cch;
756 cursor.BTNNAMES[cchPos++] = 0;
757 cursor.BTNNAMES = realloc( cursor.BTNNAMES, sizeof(WCHAR)*cchPos );
758 cursor.cchBTNNAMES = cchPos;
760 break;
761 } /* switch any->class */
762 any = (XAnyClassPtr) ((char*) any + any->length);
763 } /* for class_loop */
764 if (!add_system_cursor(&cursor))
765 FIXME("Skipping this cursor due to lack of system cursor slots.\n");
766 break;
767 } /* switch devices.use */
768 XFree(device_type);
769 } /* for XListInputDevices */
770 pXFreeDeviceList(devices);
772 if (!axis_read_complete)
774 disable_system_cursors();
775 WARN("Did not find a valid stylus, unable to determine system context parameters. Wintab is disabled.\n");
776 return FALSE;
779 gSysDevice.NCSRTYPES = gNumCursors;
780 return TRUE;
783 static int figure_deg(int x, int y)
785 float angle;
787 angle = atan2((float)y, (float)x);
788 angle += M_PI_2;
789 if (angle <= 0)
790 angle += 2 * M_PI;
792 return (0.5 + (angle * 1800.0 / M_PI));
795 static int get_button_state(int curnum)
797 return button_state[curnum];
800 static void set_button_state(int curnum, XID deviceid)
802 struct x11drv_thread_data *data = x11drv_thread_data();
803 XDevice *device;
804 XDeviceState *state;
805 XInputClass *class;
806 int loop;
807 int rc = 0;
809 device = pXOpenDevice(data->display,deviceid);
810 state = pXQueryDeviceState(data->display,device);
812 if (state)
814 class = state->data;
815 for (loop = 0; loop < state->num_classes; loop++)
817 if (class->class == ButtonClass)
819 int loop2;
820 XButtonState *button_state = (XButtonState*)class;
821 for (loop2 = 0; loop2 < button_state->num_buttons; loop2++)
823 if (button_state->buttons[loop2 / 8] & (1 << (loop2 % 8)))
825 rc |= (1<<loop2);
829 class = (XInputClass *) ((char *) class + class->length);
832 pXFreeDeviceState(state);
833 button_state[curnum] = rc;
836 static int cursor_from_device(DWORD deviceid, LPWTI_CURSORS_INFO *cursorp)
838 int i;
839 for (i = 0; i < CURSORMAX; i++)
840 if (gSysCursor[i].ACTIVE && gSysCursor[i].PHYSID == deviceid)
842 *cursorp = &gSysCursor[i];
843 return i;
846 ERR("Could not map device id %d to a cursor\n", (int) deviceid);
847 return -1;
850 static DWORD get_changed_state( WTPACKET *pkt)
852 DWORD change = 0;
854 if (pkt->pkX != last_packet.pkX)
855 change |= PK_X;
856 if (pkt->pkY != last_packet.pkY)
857 change |= PK_Y;
858 if (pkt->pkZ != last_packet.pkZ)
859 change |= PK_Z;
860 if (pkt->pkSerialNumber != last_packet.pkSerialNumber)
861 change |= PK_SERIAL_NUMBER;
862 if (pkt->pkTime != last_packet.pkTime)
863 change |= PK_TIME;
864 if (pkt->pkNormalPressure != last_packet.pkNormalPressure)
865 change |= PK_NORMAL_PRESSURE;
866 if (pkt->pkTangentPressure != last_packet.pkTangentPressure)
867 change |= PK_TANGENT_PRESSURE;
868 if (pkt->pkCursor != last_packet.pkCursor)
869 change |= PK_CURSOR;
870 if (pkt->pkButtons != last_packet.pkButtons)
871 change |= PK_BUTTONS;
872 if (pkt->pkOrientation.orAzimuth != last_packet.pkOrientation.orAzimuth ||
873 pkt->pkOrientation.orAltitude != last_packet.pkOrientation.orAltitude ||
874 pkt->pkOrientation.orTwist != last_packet.pkOrientation.orTwist)
875 change |= PK_ORIENTATION;
876 if (pkt->pkRotation.roPitch != last_packet.pkRotation.roPitch ||
877 pkt->pkRotation.roRoll != last_packet.pkRotation.roRoll ||
878 pkt->pkRotation.roYaw != last_packet.pkRotation.roYaw)
879 change |= PK_ROTATION;
881 return change;
884 static BOOL motion_event( HWND hwnd, XEvent *event )
886 XDeviceMotionEvent *motion = (XDeviceMotionEvent *)event;
887 LPWTI_CURSORS_INFO cursor;
888 int curnum = cursor_from_device(motion->deviceid, &cursor);
889 if (curnum < 0)
890 return FALSE;
892 memset(&gMsgPacket,0,sizeof(WTPACKET));
894 TRACE("Received tablet motion event (%p); device id %d, cursor num %d\n",hwnd, (int) motion->deviceid, curnum);
896 /* Set cursor to inverted if cursor is the eraser */
897 gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
898 gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(motion->time);
899 gMsgPacket.pkSerialNumber = gSerial++;
900 gMsgPacket.pkCursor = curnum;
901 gMsgPacket.pkX = motion->axis_data[0];
902 gMsgPacket.pkY = motion->axis_data[1];
903 gMsgPacket.pkOrientation.orAzimuth = figure_deg(motion->axis_data[3],motion->axis_data[4]);
904 gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max
905 (abs(motion->axis_data[3]),
906 abs(motion->axis_data[4])))
907 * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
908 gMsgPacket.pkNormalPressure = motion->axis_data[2];
909 gMsgPacket.pkButtons = get_button_state(curnum);
910 gMsgPacket.pkChanged = get_changed_state(&gMsgPacket);
911 send_message( hwndTabletDefault, WT_PACKET, gMsgPacket.pkSerialNumber, (LPARAM)hwnd );
912 last_packet = gMsgPacket;
913 return TRUE;
916 static BOOL button_event( HWND hwnd, XEvent *event )
918 XDeviceButtonEvent *button = (XDeviceButtonEvent *) event;
919 LPWTI_CURSORS_INFO cursor;
920 int curnum = cursor_from_device(button->deviceid, &cursor);
921 if (curnum < 0)
922 return FALSE;
924 memset(&gMsgPacket,0,sizeof(WTPACKET));
926 TRACE("Received tablet button %s event\n", (event->type == button_press_type)?"press":"release");
928 /* Set cursor to inverted if cursor is the eraser */
929 gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
930 set_button_state(curnum, button->deviceid);
931 gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(button->time);
932 gMsgPacket.pkSerialNumber = gSerial++;
933 gMsgPacket.pkCursor = curnum;
934 if (button->axes_count > 0) {
935 gMsgPacket.pkX = button->axis_data[0];
936 gMsgPacket.pkY = button->axis_data[1];
937 gMsgPacket.pkOrientation.orAzimuth = figure_deg(button->axis_data[3],button->axis_data[4]);
938 gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(button->axis_data[3]),
939 abs(button->axis_data[4])))
940 * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
941 gMsgPacket.pkNormalPressure = button->axis_data[2];
942 } else {
943 gMsgPacket.pkX = last_packet.pkX;
944 gMsgPacket.pkY = last_packet.pkY;
945 gMsgPacket.pkOrientation = last_packet.pkOrientation;
946 gMsgPacket.pkNormalPressure = last_packet.pkNormalPressure;
948 gMsgPacket.pkButtons = get_button_state(curnum);
949 gMsgPacket.pkChanged = get_changed_state(&gMsgPacket);
950 send_message( hwndTabletDefault, WT_PACKET, gMsgPacket.pkSerialNumber, (LPARAM)hwnd );
951 last_packet = gMsgPacket;
952 return TRUE;
955 static BOOL key_event( HWND hwnd, XEvent *event )
957 if (event->type == key_press_type)
958 FIXME("Received tablet key press event\n");
959 else
960 FIXME("Received tablet key release event\n");
961 return FALSE;
964 static BOOL proximity_event( HWND hwnd, XEvent *event )
966 XProximityNotifyEvent *proximity = (XProximityNotifyEvent *) event;
967 LPWTI_CURSORS_INFO cursor;
968 int curnum = cursor_from_device(proximity->deviceid, &cursor);
969 LPARAM proximity_info;
971 TRACE("hwnd=%p\n", hwnd);
973 if (curnum < 0)
974 return FALSE;
976 memset(&gMsgPacket,0,sizeof(WTPACKET));
978 /* Set cursor to inverted if cursor is the eraser */
979 gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
980 gMsgPacket.pkStatus |= (event->type==proximity_out_type)?TPS_PROXIMITY:0;
981 gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(proximity->time);
982 gMsgPacket.pkSerialNumber = gSerial++;
983 gMsgPacket.pkCursor = curnum;
984 gMsgPacket.pkX = proximity->axis_data[0];
985 gMsgPacket.pkY = proximity->axis_data[1];
986 gMsgPacket.pkOrientation.orAzimuth = figure_deg(proximity->axis_data[3],proximity->axis_data[4]);
987 gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(proximity->axis_data[3]),
988 abs(proximity->axis_data[4])))
989 * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
990 gMsgPacket.pkNormalPressure = proximity->axis_data[2];
991 gMsgPacket.pkButtons = get_button_state(curnum);
993 /* FIXME: LPARAM loword is true when cursor entering context, false when leaving context
994 * This needs to be handled here or in wintab32. Using the proximity_in_type is not correct
995 * but kept for now.
996 * LPARAM hiword is "non-zero when the cursor is leaving or entering hardware proximity"
997 * WPARAM contains context handle.
998 * HWND to HCTX is handled by wintab32.
1000 proximity_info = MAKELPARAM((event->type == proximity_in_type),
1001 (event->type == proximity_in_type) || (event->type == proximity_out_type));
1002 send_message( hwndTabletDefault, WT_PROXIMITY, (WPARAM)hwnd, proximity_info );
1003 return TRUE;
1006 /***********************************************************************
1007 * x11drv_tablet_attach_queue
1009 NTSTATUS x11drv_tablet_attach_queue( void *owner )
1011 struct x11drv_thread_data *data = x11drv_init_thread_data();
1012 int num_devices;
1013 int loop;
1014 int cur_loop;
1015 XDeviceInfo *devices;
1016 XDeviceInfo *target = NULL;
1017 XDevice *the_device;
1018 XEventClass event_list[7];
1019 Window win = X11DRV_get_whole_window( owner );
1021 if (!win || !xinput_handle) return 0;
1023 TRACE("Creating context for window %p (%lx) %i cursors\n", owner, win, gNumCursors);
1025 devices = pXListInputDevices(data->display, &num_devices);
1027 X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
1028 for (cur_loop=0; cur_loop < CURSORMAX; cur_loop++)
1030 char cursorNameA[WT_MAX_NAME_LEN];
1031 int event_number=0;
1033 if (!gSysCursor[cur_loop].ACTIVE) continue;
1035 /* the cursor name fits in the buffer because too long names are skipped */
1036 ntdll_wcstoumbs(gSysCursor[cur_loop].NAME, wcslen(gSysCursor[cur_loop].NAME) + 1,
1037 cursorNameA, WT_MAX_NAME_LEN, FALSE);
1038 for (loop=0; loop < num_devices; loop ++)
1039 if (strcmp(devices[loop].name, cursorNameA) == 0)
1040 target = &devices[loop];
1041 if (!target) {
1042 WARN("Cursor Name %s not found in list of targets.\n", cursorNameA);
1043 continue;
1046 TRACE("Opening cursor %i id %i\n",cur_loop,(INT)target->id);
1048 the_device = pXOpenDevice(data->display, target->id);
1050 if (!the_device)
1052 WARN("Unable to Open device\n");
1053 continue;
1056 if (the_device->num_classes > 0)
1058 DeviceKeyPress(the_device, key_press_type, event_list[event_number]);
1059 if (key_press_type) event_number++;
1060 DeviceKeyRelease(the_device, key_release_type, event_list[event_number]);
1061 if (key_release_type) event_number++;
1062 DeviceButtonPress(the_device, button_press_type, event_list[event_number]);
1063 if (button_press_type) event_number++;
1064 DeviceButtonRelease(the_device, button_release_type, event_list[event_number]);
1065 if (button_release_type) event_number++;
1066 DeviceMotionNotify(the_device, motion_type, event_list[event_number]);
1067 if (motion_type) event_number++;
1068 ProximityIn(the_device, proximity_in_type, event_list[event_number]);
1069 if (proximity_in_type) event_number++;
1070 ProximityOut(the_device, proximity_out_type, event_list[event_number]);
1071 if (proximity_out_type) event_number++;
1073 if (key_press_type)
1074 X11DRV_register_event_handler( key_press_type, key_event, "XInput KeyPress" );
1075 if (key_release_type)
1076 X11DRV_register_event_handler( key_release_type, key_event, "XInput KeyRelease" );
1077 if (button_press_type)
1078 X11DRV_register_event_handler( button_press_type, button_event, "XInput ButtonPress" );
1079 if (button_release_type)
1080 X11DRV_register_event_handler( button_release_type, button_event, "XInput ButtonRelease" );
1081 if (motion_type)
1082 X11DRV_register_event_handler( motion_type, motion_event, "XInput MotionNotify" );
1083 if (proximity_in_type)
1084 X11DRV_register_event_handler( proximity_in_type, proximity_event, "XInput ProximityIn" );
1085 if (proximity_out_type)
1086 X11DRV_register_event_handler( proximity_out_type, proximity_event, "XInput ProximityOut" );
1088 pXSelectExtensionEvent(data->display, win, event_list, event_number);
1091 XSync(data->display, False);
1092 X11DRV_check_error();
1094 if (NULL != devices) pXFreeDeviceList(devices);
1095 return 0;
1098 /***********************************************************************
1099 * x11drv_tablet_get_packet
1101 NTSTATUS x11drv_tablet_get_packet( void *packet )
1103 *(WTPACKET *)packet = gMsgPacket;
1104 return 1;
1108 static inline int CopyTabletData(LPVOID target, LPCVOID src, INT size)
1111 * It is valid to call CopyTabletData with NULL.
1112 * This handles the WTInfo() case where lpOutput is null.
1114 if(target != NULL)
1115 memcpy(target,src,size);
1116 return(size);
1119 /***********************************************************************
1120 * x11drv_tablet_info
1122 NTSTATUS x11drv_tablet_info( void *arg )
1124 struct tablet_info_params *params = arg;
1125 UINT wCategory = params->category;
1126 UINT nIndex = params->index;
1127 void *lpOutput = params->output;
1130 * It is valid to call WTInfoA with lpOutput == NULL, as per standard.
1131 * lpOutput == NULL signifies the user only wishes
1132 * to find the size of the data.
1133 * NOTE:
1134 * From now on use CopyTabletData to fill lpOutput. memcpy will break
1135 * the code.
1137 int rc = 0;
1138 LPWTI_CURSORS_INFO tgtcursor;
1139 TRACE("(%u, %u, %p)\n", wCategory, nIndex, lpOutput);
1141 if (!xinput_handle) return 0;
1143 switch(wCategory)
1145 case 0:
1146 /* return largest necessary buffer */
1147 TRACE("%i cursors\n",gNumCursors);
1148 if (gNumCursors>0)
1150 FIXME("Return proper size\n");
1151 rc = 200;
1153 break;
1154 case WTI_INTERFACE:
1155 switch (nIndex)
1157 WORD version;
1158 UINT num;
1159 case IFC_WINTABID:
1161 static const WCHAR driver[] = {'W','i','n','e',' ','W','i','n','t','a','b',' ','1','.','1',0};
1162 rc = CopyTabletData(lpOutput, driver, (wcslen(driver) + 1) * sizeof(WCHAR));
1163 break;
1165 case IFC_SPECVERSION:
1166 version = (0x01) | (0x01 << 8);
1167 rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
1168 break;
1169 case IFC_IMPLVERSION:
1170 version = (0x00) | (0x01 << 8);
1171 rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
1172 break;
1173 case IFC_NDEVICES:
1174 num = 1;
1175 rc = CopyTabletData(lpOutput, &num,sizeof(num));
1176 break;
1177 case IFC_NCURSORS:
1178 num = gNumCursors;
1179 rc = CopyTabletData(lpOutput, &num,sizeof(num));
1180 break;
1181 default:
1182 FIXME("WTI_INTERFACE unhandled index %i\n",nIndex);
1183 rc = 0;
1185 break;
1186 case WTI_DEFSYSCTX:
1187 case WTI_DDCTXS:
1188 case WTI_DEFCONTEXT:
1189 switch (nIndex)
1191 case 0:
1192 /* report 0 if wintab is disabled */
1193 if (0 == gNumCursors)
1194 rc = 0;
1195 else
1196 rc = CopyTabletData(lpOutput, &gSysContext,
1197 sizeof(LOGCONTEXTW));
1198 break;
1199 case CTX_NAME:
1200 rc = CopyTabletData(lpOutput, gSysContext.lcName,
1201 (wcslen(gSysContext.lcName)+1) * sizeof(WCHAR));
1202 break;
1203 case CTX_OPTIONS:
1204 rc = CopyTabletData(lpOutput, &gSysContext.lcOptions,
1205 sizeof(UINT));
1206 break;
1207 case CTX_STATUS:
1208 rc = CopyTabletData(lpOutput, &gSysContext.lcStatus,
1209 sizeof(UINT));
1210 break;
1211 case CTX_LOCKS:
1212 rc= CopyTabletData (lpOutput, &gSysContext.lcLocks,
1213 sizeof(UINT));
1214 break;
1215 case CTX_MSGBASE:
1216 rc = CopyTabletData(lpOutput, &gSysContext.lcMsgBase,
1217 sizeof(UINT));
1218 break;
1219 case CTX_DEVICE:
1220 rc = CopyTabletData(lpOutput, &gSysContext.lcDevice,
1221 sizeof(UINT));
1222 break;
1223 case CTX_PKTRATE:
1224 rc = CopyTabletData(lpOutput, &gSysContext.lcPktRate,
1225 sizeof(UINT));
1226 break;
1227 case CTX_PKTDATA:
1228 rc = CopyTabletData(lpOutput, &gSysContext.lcPktData,
1229 sizeof(WTPKT));
1230 break;
1231 case CTX_PKTMODE:
1232 rc = CopyTabletData(lpOutput, &gSysContext.lcPktMode,
1233 sizeof(WTPKT));
1234 break;
1235 case CTX_MOVEMASK:
1236 rc = CopyTabletData(lpOutput, &gSysContext.lcMoveMask,
1237 sizeof(WTPKT));
1238 break;
1239 case CTX_BTNDNMASK:
1240 rc = CopyTabletData(lpOutput, &gSysContext.lcBtnDnMask,
1241 sizeof(DWORD));
1242 break;
1243 case CTX_BTNUPMASK:
1244 rc = CopyTabletData(lpOutput, &gSysContext.lcBtnUpMask,
1245 sizeof(DWORD));
1246 break;
1247 case CTX_INORGX:
1248 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgX,
1249 sizeof(LONG));
1250 break;
1251 case CTX_INORGY:
1252 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgY,
1253 sizeof(LONG));
1254 break;
1255 case CTX_INORGZ:
1256 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgZ,
1257 sizeof(LONG));
1258 break;
1259 case CTX_INEXTX:
1260 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtX,
1261 sizeof(LONG));
1262 break;
1263 case CTX_INEXTY:
1264 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtY,
1265 sizeof(LONG));
1266 break;
1267 case CTX_INEXTZ:
1268 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtZ,
1269 sizeof(LONG));
1270 break;
1271 case CTX_OUTORGX:
1272 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgX,
1273 sizeof(LONG));
1274 break;
1275 case CTX_OUTORGY:
1276 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgY,
1277 sizeof(LONG));
1278 break;
1279 case CTX_OUTORGZ:
1280 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgZ,
1281 sizeof(LONG));
1282 break;
1283 case CTX_OUTEXTX:
1284 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtX,
1285 sizeof(LONG));
1286 break;
1287 case CTX_OUTEXTY:
1288 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtY,
1289 sizeof(LONG));
1290 break;
1291 case CTX_OUTEXTZ:
1292 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtZ,
1293 sizeof(LONG));
1294 break;
1295 case CTX_SENSX:
1296 rc = CopyTabletData(lpOutput, &gSysContext.lcSensX,
1297 sizeof(LONG));
1298 break;
1299 case CTX_SENSY:
1300 rc = CopyTabletData(lpOutput, &gSysContext.lcSensY,
1301 sizeof(LONG));
1302 break;
1303 case CTX_SENSZ:
1304 rc = CopyTabletData(lpOutput, &gSysContext.lcSensZ,
1305 sizeof(LONG));
1306 break;
1307 case CTX_SYSMODE:
1308 rc = CopyTabletData(lpOutput, &gSysContext.lcSysMode,
1309 sizeof(LONG));
1310 break;
1311 case CTX_SYSORGX:
1312 rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgX,
1313 sizeof(LONG));
1314 break;
1315 case CTX_SYSORGY:
1316 rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgY,
1317 sizeof(LONG));
1318 break;
1319 case CTX_SYSEXTX:
1320 rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtX,
1321 sizeof(LONG));
1322 break;
1323 case CTX_SYSEXTY:
1324 rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtY,
1325 sizeof(LONG));
1326 break;
1327 case CTX_SYSSENSX:
1328 rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensX,
1329 sizeof(LONG));
1330 break;
1331 case CTX_SYSSENSY:
1332 rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensY,
1333 sizeof(LONG));
1334 break;
1335 default:
1336 FIXME("WTI_DEFSYSCTX unhandled index %i\n",nIndex);
1337 rc = 0;
1339 break;
1340 case WTI_CURSORS:
1341 case WTI_CURSORS+1:
1342 case WTI_CURSORS+2:
1343 case WTI_CURSORS+3:
1344 case WTI_CURSORS+4:
1345 case WTI_CURSORS+5:
1346 case WTI_CURSORS+6:
1347 case WTI_CURSORS+7:
1348 case WTI_CURSORS+8:
1349 case WTI_CURSORS+9:
1350 case WTI_CURSORS+10:
1351 case WTI_CURSORS+11:
1352 /* CURSORMAX == 12 */
1353 /* FIXME: dynamic cursor support */
1354 /* Apps will poll different slots to detect what cursors are available
1355 * if there isn't a cursor for this slot return 0 */
1356 if (!gSysCursor[wCategory - WTI_CURSORS].ACTIVE)
1357 rc = 0;
1358 else
1360 tgtcursor = &gSysCursor[wCategory - WTI_CURSORS];
1361 switch (nIndex)
1363 case CSR_NAME:
1364 rc = CopyTabletData(lpOutput, tgtcursor->NAME,
1365 (wcslen(tgtcursor->NAME)+1) * sizeof(WCHAR));
1366 break;
1367 case CSR_ACTIVE:
1368 rc = CopyTabletData(lpOutput,&tgtcursor->ACTIVE,
1369 sizeof(BOOL));
1370 break;
1371 case CSR_PKTDATA:
1372 rc = CopyTabletData(lpOutput,&tgtcursor->PKTDATA,
1373 sizeof(WTPKT));
1374 break;
1375 case CSR_BUTTONS:
1376 rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONS,
1377 sizeof(BYTE));
1378 break;
1379 case CSR_BUTTONBITS:
1380 rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONBITS,
1381 sizeof(BYTE));
1382 break;
1383 case CSR_BTNNAMES:
1384 FIXME("Button Names not returned correctly\n");
1385 rc = CopyTabletData(lpOutput,&tgtcursor->BTNNAMES,
1386 tgtcursor->cchBTNNAMES*sizeof(WCHAR));
1387 break;
1388 case CSR_BUTTONMAP:
1389 rc = CopyTabletData(lpOutput,tgtcursor->BUTTONMAP,
1390 sizeof(BYTE)*32);
1391 break;
1392 case CSR_SYSBTNMAP:
1393 rc = CopyTabletData(lpOutput,tgtcursor->SYSBTNMAP,
1394 sizeof(BYTE)*32);
1395 break;
1396 case CSR_NPBTNMARKS:
1397 rc = CopyTabletData(lpOutput,tgtcursor->NPBTNMARKS,
1398 sizeof(UINT)*2);
1399 break;
1400 case CSR_NPBUTTON:
1401 rc = CopyTabletData(lpOutput,&tgtcursor->NPBUTTON,
1402 sizeof(BYTE));
1403 break;
1404 case CSR_NPRESPONSE:
1405 FIXME("Not returning CSR_NPRESPONSE correctly\n");
1406 rc = 0;
1407 break;
1408 case CSR_TPBUTTON:
1409 rc = CopyTabletData(lpOutput,&tgtcursor->TPBUTTON,
1410 sizeof(BYTE));
1411 break;
1412 case CSR_TPBTNMARKS:
1413 rc = CopyTabletData(lpOutput,tgtcursor->TPBTNMARKS,
1414 sizeof(UINT)*2);
1415 break;
1416 case CSR_TPRESPONSE:
1417 FIXME("Not returning CSR_TPRESPONSE correctly\n");
1418 rc = 0;
1419 break;
1420 case CSR_PHYSID:
1422 DWORD id;
1423 id = tgtcursor->PHYSID;
1424 rc = CopyTabletData(lpOutput,&id,sizeof(DWORD));
1426 break;
1427 case CSR_MODE:
1428 rc = CopyTabletData(lpOutput,&tgtcursor->MODE,sizeof(UINT));
1429 break;
1430 case CSR_MINPKTDATA:
1431 rc = CopyTabletData(lpOutput,&tgtcursor->MINPKTDATA,
1432 sizeof(UINT));
1433 break;
1434 case CSR_MINBUTTONS:
1435 rc = CopyTabletData(lpOutput,&tgtcursor->MINBUTTONS,
1436 sizeof(UINT));
1437 break;
1438 case CSR_CAPABILITIES:
1439 rc = CopyTabletData(lpOutput,&tgtcursor->CAPABILITIES,
1440 sizeof(UINT));
1441 break;
1442 case CSR_TYPE:
1443 rc = CopyTabletData(lpOutput,&tgtcursor->TYPE,
1444 sizeof(UINT));
1445 break;
1446 default:
1447 FIXME("WTI_CURSORS unhandled index %i\n",nIndex);
1448 rc = 0;
1451 break;
1452 case WTI_DEVICES:
1453 switch (nIndex)
1455 case DVC_NAME:
1456 rc = CopyTabletData(lpOutput,gSysDevice.NAME,
1457 (wcslen(gSysDevice.NAME)+1) * sizeof(WCHAR));
1458 break;
1459 case DVC_HARDWARE:
1460 rc = CopyTabletData(lpOutput,&gSysDevice.HARDWARE,
1461 sizeof(UINT));
1462 break;
1463 case DVC_NCSRTYPES:
1464 rc = CopyTabletData(lpOutput,&gSysDevice.NCSRTYPES,
1465 sizeof(UINT));
1466 break;
1467 case DVC_FIRSTCSR:
1468 rc = CopyTabletData(lpOutput,&gSysDevice.FIRSTCSR,
1469 sizeof(UINT));
1470 break;
1471 case DVC_PKTRATE:
1472 rc = CopyTabletData(lpOutput,&gSysDevice.PKTRATE,
1473 sizeof(UINT));
1474 break;
1475 case DVC_PKTDATA:
1476 rc = CopyTabletData(lpOutput,&gSysDevice.PKTDATA,
1477 sizeof(WTPKT));
1478 break;
1479 case DVC_PKTMODE:
1480 rc = CopyTabletData(lpOutput,&gSysDevice.PKTMODE,
1481 sizeof(WTPKT));
1482 break;
1483 case DVC_CSRDATA:
1484 rc = CopyTabletData(lpOutput,&gSysDevice.CSRDATA,
1485 sizeof(WTPKT));
1486 break;
1487 case DVC_XMARGIN:
1488 rc = CopyTabletData(lpOutput,&gSysDevice.XMARGIN,
1489 sizeof(INT));
1490 break;
1491 case DVC_YMARGIN:
1492 rc = CopyTabletData(lpOutput,&gSysDevice.YMARGIN,
1493 sizeof(INT));
1494 break;
1495 case DVC_ZMARGIN:
1496 rc = 0; /* unsupported */
1498 rc = CopyTabletData(lpOutput,&gSysDevice.ZMARGIN,
1499 sizeof(INT));
1501 break;
1502 case DVC_X:
1503 rc = CopyTabletData(lpOutput,&gSysDevice.X,
1504 sizeof(AXIS));
1505 break;
1506 case DVC_Y:
1507 rc = CopyTabletData(lpOutput,&gSysDevice.Y,
1508 sizeof(AXIS));
1509 break;
1510 case DVC_Z:
1511 rc = 0; /* unsupported */
1513 rc = CopyTabletData(lpOutput,&gSysDevice.Z,
1514 sizeof(AXIS));
1516 break;
1517 case DVC_NPRESSURE:
1518 rc = CopyTabletData(lpOutput,&gSysDevice.NPRESSURE,
1519 sizeof(AXIS));
1520 break;
1521 case DVC_TPRESSURE:
1522 rc = 0; /* unsupported */
1524 rc = CopyTabletData(lpOutput,&gSysDevice.TPRESSURE,
1525 sizeof(AXIS));
1527 break;
1528 case DVC_ORIENTATION:
1529 rc = CopyTabletData(lpOutput,gSysDevice.ORIENTATION,
1530 sizeof(AXIS)*3);
1531 break;
1532 case DVC_ROTATION:
1533 rc = 0; /* unsupported */
1535 rc = CopyTabletData(lpOutput,&gSysDevice.ROTATION,
1536 sizeof(AXIS)*3);
1538 break;
1539 case DVC_PNPID:
1540 rc = CopyTabletData(lpOutput,gSysDevice.PNPID,
1541 (wcslen(gSysDevice.PNPID)+1)*sizeof(WCHAR));
1542 break;
1543 default:
1544 FIXME("WTI_DEVICES unhandled index %i\n",nIndex);
1545 rc = 0;
1547 break;
1548 default:
1549 FIXME("Unhandled Category %i\n",wCategory);
1551 return rc;
1554 #else /* SONAME_LIBXI */
1556 /***********************************************************************
1557 * x11drv_tablet_attach_queue
1559 NTSTATUS x11drv_tablet_attach_queue( void *owner )
1561 return 0;
1564 /***********************************************************************
1565 * x11drv_tablet_get_packet
1567 NTSTATUS x11drv_tablet_get_packet( void *arg )
1569 return 0;
1572 /***********************************************************************
1573 * x11drv_tablet_load_info
1575 NTSTATUS x11drv_tablet_load_info( void *arg )
1577 return FALSE;
1580 /***********************************************************************
1581 * x11drv_tablet_info
1583 NTSTATUS x11drv_tablet_info( void *arg )
1585 return 0;
1588 #endif /* SONAME_LIBXI */