kernelbase: Reject SORT_DIGITSASNUMBERS in CompareStringA().
[wine.git] / dlls / winex11.drv / wintab.c
blob5cfc2b3a38d015377b19de74be0fcda946e8ca90
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/unicode.h"
32 #include "wine/debug.h"
33 #include "wintab.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(wintab32);
37 #define WT_MAX_NAME_LEN 256
39 typedef struct tagWTI_CURSORS_INFO
41 WCHAR NAME[WT_MAX_NAME_LEN];
42 /* a displayable zero-terminated string containing the name of the
43 * cursor.
45 BOOL ACTIVE;
46 /* whether the cursor is currently connected. */
47 WTPKT PKTDATA;
48 /* a bit mask indicating the packet data items supported when this
49 * cursor is connected.
51 BYTE BUTTONS;
52 /* the number of buttons on this cursor. */
53 BYTE BUTTONBITS;
54 /* the number of bits of raw button data returned by the hardware.*/
55 DWORD cchBTNNAMES;
56 WCHAR *BTNNAMES;
57 /* a list of zero-terminated strings containing the names of the
58 * cursor's buttons. The number of names in the list is the same as the
59 * number of buttons on the cursor. The names are separated by a single
60 * zero character; the list is terminated by two zero characters.
62 BYTE BUTTONMAP[32];
63 /* a 32 byte array of logical button numbers, one for each physical
64 * button.
66 BYTE SYSBTNMAP[32];
67 /* a 32 byte array of button action codes, one for each logical
68 * button.
70 BYTE NPBUTTON;
71 /* the physical button number of the button that is controlled by normal
72 * pressure.
74 UINT NPBTNMARKS[2];
75 /* an array of two UINTs, specifying the button marks for the normal
76 * pressure button. The first UINT contains the release mark; the second
77 * contains the press mark.
79 UINT *NPRESPONSE;
80 /* an array of UINTs describing the pressure response curve for normal
81 * pressure.
83 BYTE TPBUTTON;
84 /* the physical button number of the button that is controlled by
85 * tangential pressure.
87 UINT TPBTNMARKS[2];
88 /* an array of two UINTs, specifying the button marks for the tangential
89 * pressure button. The first UINT contains the release mark; the second
90 * contains the press mark.
92 UINT *TPRESPONSE;
93 /* an array of UINTs describing the pressure response curve for
94 * tangential pressure.
96 DWORD PHYSID;
97 /* a manufacturer-specific physical identifier for the cursor. This
98 * value will distinguish the physical cursor from others on the same
99 * device. This physical identifier allows applications to bind
100 * functions to specific physical cursors, even if category numbers
101 * change and multiple, otherwise identical, physical cursors are
102 * present.
104 UINT MODE;
105 /* the cursor mode number of this cursor type, if this cursor type has
106 * the CRC_MULTIMODE capability.
108 UINT MINPKTDATA;
109 /* the minimum set of data available from a physical cursor in this
110 * cursor type, if this cursor type has the CRC_AGGREGATE capability.
112 UINT MINBUTTONS;
113 /* the minimum number of buttons of physical cursors in the cursor type,
114 * if this cursor type has the CRC_AGGREGATE capability.
116 UINT CAPABILITIES;
117 /* flags indicating cursor capabilities, as defined below:
118 CRC_MULTIMODE
119 Indicates this cursor type describes one of several modes of a
120 single physical cursor. Consecutive cursor type categories
121 describe the modes; the CSR_MODE data item gives the mode number
122 of each cursor type.
123 CRC_AGGREGATE
124 Indicates this cursor type describes several physical cursors
125 that cannot be distinguished by software.
126 CRC_INVERT
127 Indicates this cursor type describes the physical cursor in its
128 inverted orientation; the previous consecutive cursor type
129 category describes the normal orientation.
131 UINT TYPE;
132 /* Manufacturer Unique id for the item type */
133 } WTI_CURSORS_INFO, *LPWTI_CURSORS_INFO;
136 typedef struct tagWTI_DEVICES_INFO
138 WCHAR NAME[WT_MAX_NAME_LEN];
139 /* a displayable null- terminated string describing the device,
140 * manufacturer, and revision level.
142 UINT HARDWARE;
143 /* flags indicating hardware and driver capabilities, as defined
144 * below:
145 HWC_INTEGRATED:
146 Indicates that the display and digitizer share the same surface.
147 HWC_TOUCH
148 Indicates that the cursor must be in physical contact with the
149 device to report position.
150 HWC_HARDPROX
151 Indicates that device can generate events when the cursor is
152 entering and leaving the physical detection range.
153 HWC_PHYSID_CURSORS
154 Indicates that device can uniquely identify the active cursor in
155 hardware.
157 UINT NCSRTYPES;
158 /* the number of supported cursor types.*/
159 UINT FIRSTCSR;
160 /* the first cursor type number for the device. */
161 UINT PKTRATE;
162 /* the maximum packet report rate in Hertz. */
163 WTPKT PKTDATA;
164 /* a bit mask indicating which packet data items are always available.*/
165 WTPKT PKTMODE;
166 /* a bit mask indicating which packet data items are physically
167 * relative, i.e., items for which the hardware can only report change,
168 * not absolute measurement.
170 WTPKT CSRDATA;
171 /* a bit mask indicating which packet data items are only available when
172 * certain cursors are connected. The individual cursor descriptions
173 * must be consulted to determine which cursors return which data.
175 INT XMARGIN;
176 INT YMARGIN;
177 INT ZMARGIN;
178 /* the size of tablet context margins in tablet native coordinates, in
179 * the x, y, and z directions, respectively.
181 AXIS X;
182 AXIS Y;
183 AXIS Z;
184 /* the tablet's range and resolution capabilities, in the x, y, and z
185 * axes, respectively.
187 AXIS NPRESSURE;
188 AXIS TPRESSURE;
189 /* the tablet's range and resolution capabilities, for the normal and
190 * tangential pressure inputs, respectively.
192 AXIS ORIENTATION[3];
193 /* a 3-element array describing the tablet's orientation range and
194 * resolution capabilities.
196 AXIS ROTATION[3];
197 /* a 3-element array describing the tablet's rotation range and
198 * resolution capabilities.
200 WCHAR PNPID[WT_MAX_NAME_LEN];
201 /* a null-terminated string containing the devices Plug and Play ID.*/
202 } WTI_DEVICES_INFO, *LPWTI_DEVICES_INFO;
205 /***********************************************************************
206 * WACOM WINTAB EXTENSIONS TO SUPPORT CSR_TYPE
207 * In Wintab 1.2, a CSR_TYPE feature was added. This adds the
208 * ability to return a type of cursor on a tablet.
209 * Unfortunately, we cannot get the cursor type directly from X,
210 * and it is not specified directly anywhere. So we virtualize
211 * the type here. (This is unfortunate, the kernel module has
212 * the exact type, but we have no way of getting that module to
213 * pass us that type).
215 * Reference linuxwacom driver project wcmCommon.c function
216 * idtotype for a much larger list of CSR_TYPE.
218 * http://linuxwacom.cvs.sourceforge.net/linuxwacom/linuxwacom-prod/src/xdrv/wcmCommon.c?view=markup
220 * The WTI_CURSORS_INFO.TYPE data is supposed to be used like this:
221 * (cursor.TYPE & 0x0F06) == target_cursor_type
222 * Reference: Section Unique ID
223 * http://www.wacomeng.com/devsupport/ibmpc/gddevpc.html
225 #define CSR_TYPE_PEN 0x822
226 #define CSR_TYPE_ERASER 0x82a
227 #define CSR_TYPE_MOUSE_2D 0x007
228 #define CSR_TYPE_MOUSE_4D 0x094
229 /* CSR_TYPE_OTHER is a special value! assumed no real world significance
230 * if a stylus type or eraser type eventually have this value
231 * it'll be a bug. As of 2008 05 21 we can be sure because
232 * linux wacom lists all the known values and this isn't one of them */
233 #define CSR_TYPE_OTHER 0x000
235 typedef struct tagWTPACKET {
236 HCTX pkContext;
237 UINT pkStatus;
238 LONG pkTime;
239 WTPKT pkChanged;
240 UINT pkSerialNumber;
241 UINT pkCursor;
242 DWORD pkButtons;
243 DWORD pkX;
244 DWORD pkY;
245 DWORD pkZ;
246 UINT pkNormalPressure;
247 UINT pkTangentPressure;
248 ORIENTATION pkOrientation;
249 ROTATION pkRotation; /* 1.1 */
250 } WTPACKET, *LPWTPACKET;
253 #ifdef SONAME_LIBXI
255 #include <X11/Xlib.h>
256 #include <X11/extensions/XInput.h>
258 static int motion_type;
259 static int button_press_type;
260 static int button_release_type;
261 static int key_press_type;
262 static int key_release_type;
263 static int proximity_in_type;
264 static int proximity_out_type;
266 static HWND hwndTabletDefault;
267 static WTPACKET gMsgPacket;
268 static DWORD gSerial;
269 static WTPACKET last_packet;
271 /* Reference: http://www.wacomeng.com/devsupport/ibmpc/gddevpc.html
273 * Cursors come in sets of 3 normally
274 * Cursor #0 = puck device 1
275 * Cursor #1 = stylus device 1
276 * Cursor #2 = eraser device 1
277 * Cursor #3 = puck device 2
278 * Cursor #4 = stylus device 2
279 * Cursor #5 = eraser device 2
280 * etc....
282 * A dual tracking/multimode tablet is one
283 * that supports 2 independent cursors of the same or
284 * different types simultaneously on a single tablet.
285 * This makes our cursor layout potentially like this
286 * Cursor #0 = puck 1 device 1
287 * Cursor #1 = stylus 1 device 1
288 * Cursor #2 = eraser 1 device 1
289 * Cursor #3 = puck 2 device 1
290 * Cursor #4 = stylus 2 device 1
291 * Cursor #5 = eraser 2 device 1
292 * Cursor #6 = puck 1 device 2
293 * etc.....
295 * So with multimode tablets we could potentially need
296 * 2 slots of the same type per tablet i.e.
297 * you are using 2 styluses at once so they would
298 * get placed in Cursors #1 and Cursor #4
300 * Now say someone has 2 multimode tablets with 2 erasers each
301 * now we would need Cursor #2, #5, #8, #11
302 * So to support that we need CURSORMAX of 12 (0 to 11)
303 * FIXME: we don't support more than 4 regular tablets or 2 multimode tablets */
304 #define CURSORMAX 12
305 static INT button_state[CURSORMAX];
307 static LOGCONTEXTW gSysContext;
308 static WTI_DEVICES_INFO gSysDevice;
309 static WTI_CURSORS_INFO gSysCursor[CURSORMAX];
310 static INT gNumCursors; /* do NOT use this to iterate through gSysCursor slots */
313 /* XInput stuff */
314 static void *xinput_handle;
316 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
317 MAKE_FUNCPTR(XListInputDevices)
318 MAKE_FUNCPTR(XFreeDeviceList)
319 MAKE_FUNCPTR(XOpenDevice)
320 MAKE_FUNCPTR(XQueryDeviceState)
321 MAKE_FUNCPTR(XGetDeviceButtonMapping)
322 MAKE_FUNCPTR(XCloseDevice)
323 MAKE_FUNCPTR(XSelectExtensionEvent)
324 MAKE_FUNCPTR(XFreeDeviceState)
325 #undef MAKE_FUNCPTR
327 static INT X11DRV_XInput_Init(void)
329 xinput_handle = dlopen(SONAME_LIBXI, RTLD_NOW);
330 if (xinput_handle)
332 #define LOAD_FUNCPTR(f) if((p##f = dlsym(xinput_handle, #f)) == NULL) goto sym_not_found
333 LOAD_FUNCPTR(XListInputDevices);
334 LOAD_FUNCPTR(XFreeDeviceList);
335 LOAD_FUNCPTR(XOpenDevice);
336 LOAD_FUNCPTR(XGetDeviceButtonMapping);
337 LOAD_FUNCPTR(XCloseDevice);
338 LOAD_FUNCPTR(XSelectExtensionEvent);
339 LOAD_FUNCPTR(XQueryDeviceState);
340 LOAD_FUNCPTR(XFreeDeviceState);
341 #undef LOAD_FUNCPTR
342 return 1;
344 sym_not_found:
345 return 0;
348 static int Tablet_ErrorHandler(Display *dpy, XErrorEvent *event, void* arg)
350 return 1;
353 static void trace_axes(XValuatorInfoPtr val)
355 int i;
356 XAxisInfoPtr axis;
358 for (i = 0, axis = val->axes ; i < val->num_axes; i++, axis++)
359 TRACE(" Axis %d: [resolution %d|min_value %d|max_value %d]\n", i, axis->resolution, axis->min_value, axis->max_value);
362 static BOOL match_token(const char *haystack, const char *needle)
364 const char *p, *q;
365 for (p = haystack; *p; )
367 while (*p && isspace(*p))
368 p++;
369 if (! *p)
370 break;
372 for (q = needle; *q && *p && tolower(*p) == tolower(*q); q++)
373 p++;
374 if (! *q && (isspace(*p) || !*p))
375 return TRUE;
377 while (*p && ! isspace(*p))
378 p++;
380 return FALSE;
383 /* Determining if an X device is a Tablet style device is an imperfect science.
384 ** We rely on common conventions around device names as well as the type reported
385 ** by Wacom tablets. This code will likely need to be expanded for alternate tablet types
387 ** Wintab refers to any device that interacts with the tablet as a cursor,
388 ** (stylus, eraser, tablet mouse, airbrush, etc)
389 ** this is not to be confused with wacom x11 configuration "cursor" device.
390 ** Wacoms x11 config "cursor" refers to its device slot (which we mirror with
391 ** our gSysCursors) for puck like devices (tablet mice essentially).
394 static BOOL is_tablet_cursor(const char *name, const char *type)
396 int i;
397 static const char *tablet_cursor_allowlist[] = {
398 "wacom",
399 "wizardpen",
400 "acecad",
401 "tablet",
402 "cursor",
403 "stylus",
404 "eraser",
405 "pad",
406 NULL
409 for (i=0; tablet_cursor_allowlist[i] != NULL; i++) {
410 if (name && match_token(name, tablet_cursor_allowlist[i]))
411 return TRUE;
412 if (type && match_token(type, tablet_cursor_allowlist[i]))
413 return TRUE;
415 return FALSE;
418 static UINT get_cursor_type(const char *name, const char *type)
420 int i;
421 static const char* tablet_stylus_allowlist[] = {
422 "stylus",
423 "wizardpen",
424 "acecad",
425 "pen",
426 NULL
429 /* First check device type to avoid cases where name is "Pen and Eraser" and type is "ERASER" */
430 for (i=0; tablet_stylus_allowlist[i] != NULL; i++) {
431 if (type && match_token(type, tablet_stylus_allowlist[i]))
432 return CSR_TYPE_PEN;
434 if (type && match_token(type, "eraser"))
435 return CSR_TYPE_ERASER;
436 for (i=0; tablet_stylus_allowlist[i] != NULL; i++) {
437 if (name && match_token(name, tablet_stylus_allowlist[i]))
438 return CSR_TYPE_PEN;
440 if (name && match_token(name, "eraser"))
441 return CSR_TYPE_ERASER;
443 return CSR_TYPE_OTHER;
446 /* cursors are placed in gSysCursor rows depending on their type
447 * see CURSORMAX comments for more detail */
448 static BOOL add_system_cursor(LPWTI_CURSORS_INFO cursor)
450 UINT offset = 0;
452 if (cursor->TYPE == CSR_TYPE_PEN)
453 offset = 1;
454 else if (cursor->TYPE == CSR_TYPE_ERASER)
455 offset = 2;
457 for (; offset < CURSORMAX; offset += 3)
459 if (!gSysCursor[offset].ACTIVE)
461 gSysCursor[offset] = *cursor;
462 ++gNumCursors;
463 return TRUE;
467 return FALSE;
470 static void disable_system_cursors(void)
472 UINT i;
474 for (i = 0; i < CURSORMAX; ++i)
476 gSysCursor[i].ACTIVE = 0;
479 gNumCursors = 0;
483 /***********************************************************************
484 * X11DRV_LoadTabletInfo (X11DRV.@)
486 BOOL CDECL X11DRV_LoadTabletInfo(HWND hwnddefault)
488 static const WCHAR SZ_CONTEXT_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','C','o','n','t','e','x','t',0};
489 static const WCHAR SZ_DEVICE_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','D','e','v','i','c','e',0};
490 static const WCHAR SZ_NON_PLUG_N_PLAY[] = {'n','o','n','-','p','l','u','g','-','n','-','p','l','a','y',0};
492 struct x11drv_thread_data *data = x11drv_init_thread_data();
493 int num_devices;
494 int loop;
495 XDeviceInfo *devices;
496 XDeviceInfo *target = NULL;
497 BOOL axis_read_complete= FALSE;
499 XAnyClassPtr any;
500 XButtonInfoPtr Button;
501 XValuatorInfoPtr Val;
502 XAxisInfoPtr Axis;
504 XDevice *opendevice;
506 if (!X11DRV_XInput_Init())
508 ERR("Unable to initialize the XInput library.\n");
509 return FALSE;
512 hwndTabletDefault = hwnddefault;
514 /* Do base initialization */
515 strcpyW(gSysContext.lcName, SZ_CONTEXT_NAME);
516 strcpyW(gSysDevice.NAME, SZ_DEVICE_NAME);
518 gSysContext.lcOptions = CXO_SYSTEM;
519 gSysContext.lcLocks = CXL_INSIZE | CXL_INASPECT | CXL_MARGIN |
520 CXL_SENSITIVITY | CXL_SYSOUT;
522 gSysContext.lcMsgBase= WT_DEFBASE;
523 gSysContext.lcDevice = 0;
524 gSysContext.lcPktData =
525 PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
526 PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
527 gSysContext.lcMoveMask=
528 PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
529 gSysContext.lcStatus = CXS_ONTOP;
530 gSysContext.lcPktRate = 100;
531 gSysContext.lcBtnDnMask = 0xffffffff;
532 gSysContext.lcBtnUpMask = 0xffffffff;
533 gSysContext.lcSensX = 65536;
534 gSysContext.lcSensY = 65536;
535 gSysContext.lcSensX = 65536;
536 gSysContext.lcSensZ = 65536;
537 gSysContext.lcSysSensX= 65536;
538 gSysContext.lcSysSensY= 65536;
539 gSysContext.lcSysExtX = GetSystemMetrics(SM_CXVIRTUALSCREEN);
540 gSysContext.lcSysExtY = GetSystemMetrics(SM_CYVIRTUALSCREEN);
542 /* initialize cursors */
543 disable_system_cursors();
545 /* Device Defaults */
546 gSysDevice.HARDWARE = HWC_HARDPROX|HWC_PHYSID_CURSORS;
547 gSysDevice.FIRSTCSR= 0;
548 gSysDevice.PKTRATE = 100;
549 gSysDevice.PKTDATA =
550 PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
551 PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
552 strcpyW(gSysDevice.PNPID, SZ_NON_PLUG_N_PLAY);
554 devices = pXListInputDevices(data->display, &num_devices);
555 if (!devices)
557 WARN("XInput Extensions reported as not available\n");
558 return FALSE;
560 TRACE("XListInputDevices reports %d devices\n", num_devices);
561 for (loop=0; loop < num_devices; loop++)
563 int class_loop;
564 char *device_type = devices[loop].type ? XGetAtomName(data->display, devices[loop].type) : NULL;
565 WTI_CURSORS_INFO cursor;
567 TRACE("Device %i: [id %d|name %s|type %s|num_classes %d|use %d]\n",
568 loop, (int) devices[loop].id, devices[loop].name, debugstr_a(device_type),
569 devices[loop].num_classes, devices[loop].use );
571 switch (devices[loop].use)
573 case IsXExtensionDevice:
574 #ifdef IsXExtensionPointer
575 case IsXExtensionPointer:
576 #endif
577 #ifdef IsXExtensionKeyboard
578 case IsXExtensionKeyboard:
579 #endif
580 TRACE("Is XExtension: Device, Keyboard, or Pointer\n");
581 target = &devices[loop];
583 if (strlen(target->name) >= WT_MAX_NAME_LEN)
585 ERR("Input device '%s' name too long - skipping\n", wine_dbgstr_a(target->name));
586 break;
589 X11DRV_expect_error(data->display, Tablet_ErrorHandler, NULL);
590 opendevice = pXOpenDevice(data->display,target->id);
591 if (!X11DRV_check_error() && opendevice)
593 unsigned char map[32];
594 int i;
595 int shft = 0;
597 X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
598 cursor.BUTTONS = pXGetDeviceButtonMapping(data->display, opendevice, map, 32);
599 if (X11DRV_check_error() || cursor.BUTTONS <= 0)
601 TRACE("No buttons, Non Tablet Device\n");
602 pXCloseDevice(data->display, opendevice);
603 break;
606 for (i=0; i< cursor.BUTTONS; i++,shft++)
608 cursor.BUTTONMAP[i] = map[i];
609 cursor.SYSBTNMAP[i] = (1<<shft);
611 pXCloseDevice(data->display, opendevice);
613 else
615 WARN("Unable to open device %s\n",target->name);
616 break;
618 MultiByteToWideChar(CP_UNIXCP, 0, target->name, -1, cursor.NAME, WT_MAX_NAME_LEN);
620 if (! is_tablet_cursor(target->name, device_type))
622 WARN("Skipping device %d [name %s|type %s]; not apparently a tablet cursor type device\n",
623 loop, devices[loop].name, debugstr_a(device_type));
624 break;
627 cursor.ACTIVE = 1;
628 cursor.PKTDATA = PK_TIME | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y |
629 PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE |
630 PK_ORIENTATION;
632 cursor.PHYSID = target->id;
633 cursor.NPBUTTON = 1;
634 cursor.NPBTNMARKS[0] = 0 ;
635 cursor.NPBTNMARKS[1] = 1 ;
636 cursor.CAPABILITIES = CRC_MULTIMODE;
638 cursor.TYPE = get_cursor_type(target->name, device_type);
640 any = target->inputclassinfo;
642 for (class_loop = 0; class_loop < target->num_classes; class_loop++)
644 switch (any->class)
647 case ValuatorClass:
648 Val = (XValuatorInfoPtr) any;
649 TRACE(" ValidatorInput %d: [class %d|length %d|num_axes %d|mode %d|motion_buffer %ld]\n",
650 class_loop, (int) Val->class, Val->length, Val->num_axes, Val->mode, Val->motion_buffer);
651 if (TRACE_ON(wintab32))
652 trace_axes(Val);
654 /* FIXME: This is imperfect; we compute our devices capabilities based upon the
655 ** first pen type device we find. However, a more correct implementation
656 ** would require acquiring a wide variety of tablets and running through
657 ** the various inputs to see what the values are. Odds are that a
658 ** more 'correct' algorithm would condense to this one anyway.
660 if (!axis_read_complete && cursor.TYPE == CSR_TYPE_PEN)
662 Axis = (XAxisInfoPtr) ((char *) Val + sizeof
663 (XValuatorInfo));
665 if (Val->num_axes>=1)
667 /* Axis 1 is X */
668 gSysDevice.X.axMin = Axis->min_value;
669 gSysDevice.X.axMax= Axis->max_value;
670 gSysDevice.X.axUnits = TU_INCHES;
671 gSysDevice.X.axResolution = Axis->resolution;
672 gSysContext.lcInOrgX = Axis->min_value;
673 gSysContext.lcOutOrgX = Axis->min_value;
674 gSysContext.lcInExtX = Axis->max_value;
675 gSysContext.lcOutExtX = Axis->max_value;
676 Axis++;
678 if (Val->num_axes>=2)
680 /* Axis 2 is Y */
681 gSysDevice.Y.axMin = Axis->min_value;
682 gSysDevice.Y.axMax= Axis->max_value;
683 gSysDevice.Y.axUnits = TU_INCHES;
684 gSysDevice.Y.axResolution = Axis->resolution;
685 gSysContext.lcInOrgY = Axis->min_value;
686 gSysContext.lcOutOrgY = Axis->min_value;
687 gSysContext.lcInExtY = Axis->max_value;
688 gSysContext.lcOutExtY = Axis->max_value;
689 Axis++;
691 if (Val->num_axes>=3)
693 /* Axis 3 is Normal Pressure */
694 gSysDevice.NPRESSURE.axMin = Axis->min_value;
695 gSysDevice.NPRESSURE.axMax= Axis->max_value;
696 gSysDevice.NPRESSURE.axUnits = TU_INCHES;
697 gSysDevice.NPRESSURE.axResolution =
698 Axis->resolution;
699 Axis++;
701 if (Val->num_axes >= 5)
703 /* Axis 4 and 5 are X and Y tilt */
704 XAxisInfoPtr XAxis = Axis;
705 Axis++;
706 if (max (abs(Axis->max_value),
707 abs(XAxis->max_value)))
709 gSysDevice.ORIENTATION[0].axMin = 0;
710 gSysDevice.ORIENTATION[0].axMax = 3600;
711 gSysDevice.ORIENTATION[0].axUnits = TU_CIRCLE;
712 gSysDevice.ORIENTATION[0].axResolution
713 = CASTFIX32(3600);
714 gSysDevice.ORIENTATION[1].axMin = -1000;
715 gSysDevice.ORIENTATION[1].axMax = 1000;
716 gSysDevice.ORIENTATION[1].axUnits = TU_CIRCLE;
717 gSysDevice.ORIENTATION[1].axResolution
718 = CASTFIX32(3600);
719 gSysDevice.ORIENTATION[2].axMin = 0;
720 gSysDevice.ORIENTATION[2].axMax = 3600;
721 gSysDevice.ORIENTATION[2].axUnits = TU_CIRCLE;
722 gSysDevice.ORIENTATION[2].axResolution
723 = CASTFIX32(3600);
724 Axis++;
727 axis_read_complete = TRUE;
729 break;
730 case ButtonClass:
732 int cchBuf = 512;
733 int cchPos = 0;
734 int i;
736 Button = (XButtonInfoPtr) any;
737 TRACE(" ButtonInput %d: [class %d|length %d|num_buttons %d]\n",
738 class_loop, (int) Button->class, Button->length, Button->num_buttons);
739 cursor.BTNNAMES = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*cchBuf);
740 for (i = 0; i < cursor.BUTTONS; i++)
742 /* FIXME - these names are probably incorrect */
743 int cch = strlenW(cursor.NAME) + 1;
744 while (cch > cchBuf - cchPos - 1) /* we want one extra byte for the last NUL */
746 cchBuf *= 2;
747 cursor.BTNNAMES = HeapReAlloc(GetProcessHeap(), 0, cursor.BTNNAMES, sizeof(WCHAR)*cchBuf);
750 strcpyW(cursor.BTNNAMES + cchPos, cursor.NAME);
751 cchPos += cch;
753 cursor.BTNNAMES[cchPos++] = 0;
754 cursor.BTNNAMES = HeapReAlloc(GetProcessHeap(), 0, cursor.BTNNAMES, sizeof(WCHAR)*cchPos);
755 cursor.cchBTNNAMES = cchPos;
757 break;
758 } /* switch any->class */
759 any = (XAnyClassPtr) ((char*) any + any->length);
760 } /* for class_loop */
761 if (!add_system_cursor(&cursor))
762 FIXME("Skipping this cursor due to lack of system cursor slots.\n");
763 break;
764 } /* switch devices.use */
765 XFree(device_type);
766 } /* for XListInputDevices */
767 pXFreeDeviceList(devices);
769 if (!axis_read_complete)
771 disable_system_cursors();
772 WARN("Did not find a valid stylus, unable to determine system context parameters. Wintab is disabled.\n");
773 return FALSE;
776 gSysDevice.NCSRTYPES = gNumCursors;
777 return TRUE;
780 static int figure_deg(int x, int y)
782 float angle;
784 angle = atan2((float)y, (float)x);
785 angle += M_PI_2;
786 if (angle <= 0)
787 angle += 2 * M_PI;
789 return (0.5 + (angle * 1800.0 / M_PI));
792 static int get_button_state(int curnum)
794 return button_state[curnum];
797 static void set_button_state(int curnum, XID deviceid)
799 struct x11drv_thread_data *data = x11drv_thread_data();
800 XDevice *device;
801 XDeviceState *state;
802 XInputClass *class;
803 int loop;
804 int rc = 0;
806 device = pXOpenDevice(data->display,deviceid);
807 state = pXQueryDeviceState(data->display,device);
809 if (state)
811 class = state->data;
812 for (loop = 0; loop < state->num_classes; loop++)
814 if (class->class == ButtonClass)
816 int loop2;
817 XButtonState *button_state = (XButtonState*)class;
818 for (loop2 = 0; loop2 < button_state->num_buttons; loop2++)
820 if (button_state->buttons[loop2 / 8] & (1 << (loop2 % 8)))
822 rc |= (1<<loop2);
826 class = (XInputClass *) ((char *) class + class->length);
829 pXFreeDeviceState(state);
830 button_state[curnum] = rc;
833 static int cursor_from_device(DWORD deviceid, LPWTI_CURSORS_INFO *cursorp)
835 int i;
836 for (i = 0; i < CURSORMAX; i++)
837 if (gSysCursor[i].ACTIVE && gSysCursor[i].PHYSID == deviceid)
839 *cursorp = &gSysCursor[i];
840 return i;
843 ERR("Could not map device id %d to a cursor\n", (int) deviceid);
844 return -1;
847 static DWORD get_changed_state( WTPACKET *pkt)
849 DWORD change = 0;
851 if (pkt->pkX != last_packet.pkX)
852 change |= PK_X;
853 if (pkt->pkY != last_packet.pkY)
854 change |= PK_Y;
855 if (pkt->pkZ != last_packet.pkZ)
856 change |= PK_Z;
857 if (pkt->pkSerialNumber != last_packet.pkSerialNumber)
858 change |= PK_SERIAL_NUMBER;
859 if (pkt->pkTime != last_packet.pkTime)
860 change |= PK_TIME;
861 if (pkt->pkNormalPressure != last_packet.pkNormalPressure)
862 change |= PK_NORMAL_PRESSURE;
863 if (pkt->pkTangentPressure != last_packet.pkTangentPressure)
864 change |= PK_TANGENT_PRESSURE;
865 if (pkt->pkCursor != last_packet.pkCursor)
866 change |= PK_CURSOR;
867 if (pkt->pkButtons != last_packet.pkButtons)
868 change |= PK_BUTTONS;
869 if (pkt->pkOrientation.orAzimuth != last_packet.pkOrientation.orAzimuth ||
870 pkt->pkOrientation.orAltitude != last_packet.pkOrientation.orAltitude ||
871 pkt->pkOrientation.orTwist != last_packet.pkOrientation.orTwist)
872 change |= PK_ORIENTATION;
873 if (pkt->pkRotation.roPitch != last_packet.pkRotation.roPitch ||
874 pkt->pkRotation.roRoll != last_packet.pkRotation.roRoll ||
875 pkt->pkRotation.roYaw != last_packet.pkRotation.roYaw)
876 change |= PK_ROTATION;
878 return change;
881 static BOOL motion_event( HWND hwnd, XEvent *event )
883 XDeviceMotionEvent *motion = (XDeviceMotionEvent *)event;
884 LPWTI_CURSORS_INFO cursor;
885 int curnum = cursor_from_device(motion->deviceid, &cursor);
886 if (curnum < 0)
887 return FALSE;
889 memset(&gMsgPacket,0,sizeof(WTPACKET));
891 TRACE("Received tablet motion event (%p); device id %d, cursor num %d\n",hwnd, (int) motion->deviceid, curnum);
893 /* Set cursor to inverted if cursor is the eraser */
894 gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
895 gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(motion->time);
896 gMsgPacket.pkSerialNumber = gSerial++;
897 gMsgPacket.pkCursor = curnum;
898 gMsgPacket.pkX = motion->axis_data[0];
899 gMsgPacket.pkY = motion->axis_data[1];
900 gMsgPacket.pkOrientation.orAzimuth = figure_deg(motion->axis_data[3],motion->axis_data[4]);
901 gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max
902 (abs(motion->axis_data[3]),
903 abs(motion->axis_data[4])))
904 * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
905 gMsgPacket.pkNormalPressure = motion->axis_data[2];
906 gMsgPacket.pkButtons = get_button_state(curnum);
907 gMsgPacket.pkChanged = get_changed_state(&gMsgPacket);
908 SendMessageW(hwndTabletDefault,WT_PACKET,gMsgPacket.pkSerialNumber,(LPARAM)hwnd);
909 last_packet = gMsgPacket;
910 return TRUE;
913 static BOOL button_event( HWND hwnd, XEvent *event )
915 XDeviceButtonEvent *button = (XDeviceButtonEvent *) event;
916 LPWTI_CURSORS_INFO cursor;
917 int curnum = cursor_from_device(button->deviceid, &cursor);
918 if (curnum < 0)
919 return FALSE;
921 memset(&gMsgPacket,0,sizeof(WTPACKET));
923 TRACE("Received tablet button %s event\n", (event->type == button_press_type)?"press":"release");
925 /* Set cursor to inverted if cursor is the eraser */
926 gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
927 set_button_state(curnum, button->deviceid);
928 gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(button->time);
929 gMsgPacket.pkSerialNumber = gSerial++;
930 gMsgPacket.pkCursor = curnum;
931 if (button->axes_count > 0) {
932 gMsgPacket.pkX = button->axis_data[0];
933 gMsgPacket.pkY = button->axis_data[1];
934 gMsgPacket.pkOrientation.orAzimuth = figure_deg(button->axis_data[3],button->axis_data[4]);
935 gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(button->axis_data[3]),
936 abs(button->axis_data[4])))
937 * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
938 gMsgPacket.pkNormalPressure = button->axis_data[2];
939 } else {
940 gMsgPacket.pkX = last_packet.pkX;
941 gMsgPacket.pkY = last_packet.pkY;
942 gMsgPacket.pkOrientation = last_packet.pkOrientation;
943 gMsgPacket.pkNormalPressure = last_packet.pkNormalPressure;
945 gMsgPacket.pkButtons = get_button_state(curnum);
946 gMsgPacket.pkChanged = get_changed_state(&gMsgPacket);
947 SendMessageW(hwndTabletDefault,WT_PACKET,gMsgPacket.pkSerialNumber,(LPARAM)hwnd);
948 last_packet = gMsgPacket;
949 return TRUE;
952 static BOOL key_event( HWND hwnd, XEvent *event )
954 if (event->type == key_press_type)
955 FIXME("Received tablet key press event\n");
956 else
957 FIXME("Received tablet key release event\n");
958 return FALSE;
961 static BOOL proximity_event( HWND hwnd, XEvent *event )
963 XProximityNotifyEvent *proximity = (XProximityNotifyEvent *) event;
964 LPWTI_CURSORS_INFO cursor;
965 int curnum = cursor_from_device(proximity->deviceid, &cursor);
966 LPARAM proximity_info;
968 TRACE("hwnd=%p\n", hwnd);
970 if (curnum < 0)
971 return FALSE;
973 memset(&gMsgPacket,0,sizeof(WTPACKET));
975 /* Set cursor to inverted if cursor is the eraser */
976 gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
977 gMsgPacket.pkStatus |= (event->type==proximity_out_type)?TPS_PROXIMITY:0;
978 gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(proximity->time);
979 gMsgPacket.pkSerialNumber = gSerial++;
980 gMsgPacket.pkCursor = curnum;
981 gMsgPacket.pkX = proximity->axis_data[0];
982 gMsgPacket.pkY = proximity->axis_data[1];
983 gMsgPacket.pkOrientation.orAzimuth = figure_deg(proximity->axis_data[3],proximity->axis_data[4]);
984 gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(proximity->axis_data[3]),
985 abs(proximity->axis_data[4])))
986 * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
987 gMsgPacket.pkNormalPressure = proximity->axis_data[2];
988 gMsgPacket.pkButtons = get_button_state(curnum);
990 /* FIXME: LPARAM loword is true when cursor entering context, false when leaving context
991 * This needs to be handled here or in wintab32. Using the proximity_in_type is not correct
992 * but kept for now.
993 * LPARAM hiword is "non-zero when the cursor is leaving or entering hardware proximity"
994 * WPARAM contains context handle.
995 * HWND to HCTX is handled by wintab32.
997 proximity_info = MAKELPARAM((event->type == proximity_in_type),
998 (event->type == proximity_in_type) || (event->type == proximity_out_type));
999 SendMessageW(hwndTabletDefault, WT_PROXIMITY, (WPARAM)hwnd, proximity_info);
1000 return TRUE;
1003 /***********************************************************************
1004 * X11DRV_AttachEventQueueToTablet (X11DRV.@)
1006 int CDECL X11DRV_AttachEventQueueToTablet(HWND hOwner)
1008 struct x11drv_thread_data *data = x11drv_init_thread_data();
1009 int num_devices;
1010 int loop;
1011 int cur_loop;
1012 XDeviceInfo *devices;
1013 XDeviceInfo *target = NULL;
1014 XDevice *the_device;
1015 XEventClass event_list[7];
1016 Window win = X11DRV_get_whole_window( hOwner );
1018 if (!win || !xinput_handle) return 0;
1020 TRACE("Creating context for window %p (%lx) %i cursors\n", hOwner, win, gNumCursors);
1022 devices = pXListInputDevices(data->display, &num_devices);
1024 X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
1025 for (cur_loop=0; cur_loop < CURSORMAX; cur_loop++)
1027 char cursorNameA[WT_MAX_NAME_LEN];
1028 int event_number=0;
1030 if (!gSysCursor[cur_loop].ACTIVE) continue;
1032 /* the cursor name fits in the buffer because too long names are skipped */
1033 WideCharToMultiByte(CP_UNIXCP, 0, gSysCursor[cur_loop].NAME, -1, cursorNameA, WT_MAX_NAME_LEN, NULL, NULL);
1034 for (loop=0; loop < num_devices; loop ++)
1035 if (strcmp(devices[loop].name, cursorNameA) == 0)
1036 target = &devices[loop];
1037 if (!target) {
1038 WARN("Cursor Name %s not found in list of targets.\n", cursorNameA);
1039 continue;
1042 TRACE("Opening cursor %i id %i\n",cur_loop,(INT)target->id);
1044 the_device = pXOpenDevice(data->display, target->id);
1046 if (!the_device)
1048 WARN("Unable to Open device\n");
1049 continue;
1052 if (the_device->num_classes > 0)
1054 DeviceKeyPress(the_device, key_press_type, event_list[event_number]);
1055 if (key_press_type) event_number++;
1056 DeviceKeyRelease(the_device, key_release_type, event_list[event_number]);
1057 if (key_release_type) event_number++;
1058 DeviceButtonPress(the_device, button_press_type, event_list[event_number]);
1059 if (button_press_type) event_number++;
1060 DeviceButtonRelease(the_device, button_release_type, event_list[event_number]);
1061 if (button_release_type) event_number++;
1062 DeviceMotionNotify(the_device, motion_type, event_list[event_number]);
1063 if (motion_type) event_number++;
1064 ProximityIn(the_device, proximity_in_type, event_list[event_number]);
1065 if (proximity_in_type) event_number++;
1066 ProximityOut(the_device, proximity_out_type, event_list[event_number]);
1067 if (proximity_out_type) event_number++;
1069 if (key_press_type)
1070 X11DRV_register_event_handler( key_press_type, key_event, "XInput KeyPress" );
1071 if (key_release_type)
1072 X11DRV_register_event_handler( key_release_type, key_event, "XInput KeyRelease" );
1073 if (button_press_type)
1074 X11DRV_register_event_handler( button_press_type, button_event, "XInput ButtonPress" );
1075 if (button_release_type)
1076 X11DRV_register_event_handler( button_release_type, button_event, "XInput ButtonRelease" );
1077 if (motion_type)
1078 X11DRV_register_event_handler( motion_type, motion_event, "XInput MotionNotify" );
1079 if (proximity_in_type)
1080 X11DRV_register_event_handler( proximity_in_type, proximity_event, "XInput ProximityIn" );
1081 if (proximity_out_type)
1082 X11DRV_register_event_handler( proximity_out_type, proximity_event, "XInput ProximityOut" );
1084 pXSelectExtensionEvent(data->display, win, event_list, event_number);
1087 XSync(data->display, False);
1088 X11DRV_check_error();
1090 if (NULL != devices) pXFreeDeviceList(devices);
1091 return 0;
1094 /***********************************************************************
1095 * X11DRV_GetCurrentPacket (X11DRV.@)
1097 int CDECL X11DRV_GetCurrentPacket(LPWTPACKET packet)
1099 *packet = gMsgPacket;
1100 return 1;
1104 static inline int CopyTabletData(LPVOID target, LPCVOID src, INT size)
1107 * It is valid to call CopyTabletData with NULL.
1108 * This handles the WTInfo() case where lpOutput is null.
1110 if(target != NULL)
1111 memcpy(target,src,size);
1112 return(size);
1115 /***********************************************************************
1116 * X11DRV_WTInfoW (X11DRV.@)
1118 UINT CDECL X11DRV_WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
1121 * It is valid to call WTInfoA with lpOutput == NULL, as per standard.
1122 * lpOutput == NULL signifies the user only wishes
1123 * to find the size of the data.
1124 * NOTE:
1125 * From now on use CopyTabletData to fill lpOutput. memcpy will break
1126 * the code.
1128 int rc = 0;
1129 LPWTI_CURSORS_INFO tgtcursor;
1130 TRACE("(%u, %u, %p)\n", wCategory, nIndex, lpOutput);
1132 if (!xinput_handle) return 0;
1134 switch(wCategory)
1136 case 0:
1137 /* return largest necessary buffer */
1138 TRACE("%i cursors\n",gNumCursors);
1139 if (gNumCursors>0)
1141 FIXME("Return proper size\n");
1142 rc = 200;
1144 break;
1145 case WTI_INTERFACE:
1146 switch (nIndex)
1148 WORD version;
1149 UINT num;
1150 case IFC_WINTABID:
1152 static const WCHAR driver[] = {'W','i','n','e',' ','W','i','n','t','a','b',' ','1','.','1',0};
1153 rc = CopyTabletData(lpOutput, driver, (strlenW(driver) + 1) * sizeof(WCHAR));
1154 break;
1156 case IFC_SPECVERSION:
1157 version = (0x01) | (0x01 << 8);
1158 rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
1159 break;
1160 case IFC_IMPLVERSION:
1161 version = (0x00) | (0x01 << 8);
1162 rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
1163 break;
1164 case IFC_NDEVICES:
1165 num = 1;
1166 rc = CopyTabletData(lpOutput, &num,sizeof(num));
1167 break;
1168 case IFC_NCURSORS:
1169 num = gNumCursors;
1170 rc = CopyTabletData(lpOutput, &num,sizeof(num));
1171 break;
1172 default:
1173 FIXME("WTI_INTERFACE unhandled index %i\n",nIndex);
1174 rc = 0;
1176 break;
1177 case WTI_DEFSYSCTX:
1178 case WTI_DDCTXS:
1179 case WTI_DEFCONTEXT:
1180 switch (nIndex)
1182 case 0:
1183 /* report 0 if wintab is disabled */
1184 if (0 == gNumCursors)
1185 rc = 0;
1186 else
1187 rc = CopyTabletData(lpOutput, &gSysContext,
1188 sizeof(LOGCONTEXTW));
1189 break;
1190 case CTX_NAME:
1191 rc = CopyTabletData(lpOutput, gSysContext.lcName,
1192 (strlenW(gSysContext.lcName)+1) * sizeof(WCHAR));
1193 break;
1194 case CTX_OPTIONS:
1195 rc = CopyTabletData(lpOutput, &gSysContext.lcOptions,
1196 sizeof(UINT));
1197 break;
1198 case CTX_STATUS:
1199 rc = CopyTabletData(lpOutput, &gSysContext.lcStatus,
1200 sizeof(UINT));
1201 break;
1202 case CTX_LOCKS:
1203 rc= CopyTabletData (lpOutput, &gSysContext.lcLocks,
1204 sizeof(UINT));
1205 break;
1206 case CTX_MSGBASE:
1207 rc = CopyTabletData(lpOutput, &gSysContext.lcMsgBase,
1208 sizeof(UINT));
1209 break;
1210 case CTX_DEVICE:
1211 rc = CopyTabletData(lpOutput, &gSysContext.lcDevice,
1212 sizeof(UINT));
1213 break;
1214 case CTX_PKTRATE:
1215 rc = CopyTabletData(lpOutput, &gSysContext.lcPktRate,
1216 sizeof(UINT));
1217 break;
1218 case CTX_PKTDATA:
1219 rc = CopyTabletData(lpOutput, &gSysContext.lcPktData,
1220 sizeof(WTPKT));
1221 break;
1222 case CTX_PKTMODE:
1223 rc = CopyTabletData(lpOutput, &gSysContext.lcPktMode,
1224 sizeof(WTPKT));
1225 break;
1226 case CTX_MOVEMASK:
1227 rc = CopyTabletData(lpOutput, &gSysContext.lcMoveMask,
1228 sizeof(WTPKT));
1229 break;
1230 case CTX_BTNDNMASK:
1231 rc = CopyTabletData(lpOutput, &gSysContext.lcBtnDnMask,
1232 sizeof(DWORD));
1233 break;
1234 case CTX_BTNUPMASK:
1235 rc = CopyTabletData(lpOutput, &gSysContext.lcBtnUpMask,
1236 sizeof(DWORD));
1237 break;
1238 case CTX_INORGX:
1239 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgX,
1240 sizeof(LONG));
1241 break;
1242 case CTX_INORGY:
1243 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgY,
1244 sizeof(LONG));
1245 break;
1246 case CTX_INORGZ:
1247 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgZ,
1248 sizeof(LONG));
1249 break;
1250 case CTX_INEXTX:
1251 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtX,
1252 sizeof(LONG));
1253 break;
1254 case CTX_INEXTY:
1255 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtY,
1256 sizeof(LONG));
1257 break;
1258 case CTX_INEXTZ:
1259 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtZ,
1260 sizeof(LONG));
1261 break;
1262 case CTX_OUTORGX:
1263 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgX,
1264 sizeof(LONG));
1265 break;
1266 case CTX_OUTORGY:
1267 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgY,
1268 sizeof(LONG));
1269 break;
1270 case CTX_OUTORGZ:
1271 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgZ,
1272 sizeof(LONG));
1273 break;
1274 case CTX_OUTEXTX:
1275 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtX,
1276 sizeof(LONG));
1277 break;
1278 case CTX_OUTEXTY:
1279 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtY,
1280 sizeof(LONG));
1281 break;
1282 case CTX_OUTEXTZ:
1283 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtZ,
1284 sizeof(LONG));
1285 break;
1286 case CTX_SENSX:
1287 rc = CopyTabletData(lpOutput, &gSysContext.lcSensX,
1288 sizeof(LONG));
1289 break;
1290 case CTX_SENSY:
1291 rc = CopyTabletData(lpOutput, &gSysContext.lcSensY,
1292 sizeof(LONG));
1293 break;
1294 case CTX_SENSZ:
1295 rc = CopyTabletData(lpOutput, &gSysContext.lcSensZ,
1296 sizeof(LONG));
1297 break;
1298 case CTX_SYSMODE:
1299 rc = CopyTabletData(lpOutput, &gSysContext.lcSysMode,
1300 sizeof(LONG));
1301 break;
1302 case CTX_SYSORGX:
1303 rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgX,
1304 sizeof(LONG));
1305 break;
1306 case CTX_SYSORGY:
1307 rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgY,
1308 sizeof(LONG));
1309 break;
1310 case CTX_SYSEXTX:
1311 rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtX,
1312 sizeof(LONG));
1313 break;
1314 case CTX_SYSEXTY:
1315 rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtY,
1316 sizeof(LONG));
1317 break;
1318 case CTX_SYSSENSX:
1319 rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensX,
1320 sizeof(LONG));
1321 break;
1322 case CTX_SYSSENSY:
1323 rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensY,
1324 sizeof(LONG));
1325 break;
1326 default:
1327 FIXME("WTI_DEFSYSCTX unhandled index %i\n",nIndex);
1328 rc = 0;
1330 break;
1331 case WTI_CURSORS:
1332 case WTI_CURSORS+1:
1333 case WTI_CURSORS+2:
1334 case WTI_CURSORS+3:
1335 case WTI_CURSORS+4:
1336 case WTI_CURSORS+5:
1337 case WTI_CURSORS+6:
1338 case WTI_CURSORS+7:
1339 case WTI_CURSORS+8:
1340 case WTI_CURSORS+9:
1341 case WTI_CURSORS+10:
1342 case WTI_CURSORS+11:
1343 /* CURSORMAX == 12 */
1344 /* FIXME: dynamic cursor support */
1345 /* Apps will poll different slots to detect what cursors are available
1346 * if there isn't a cursor for this slot return 0 */
1347 if (!gSysCursor[wCategory - WTI_CURSORS].ACTIVE)
1348 rc = 0;
1349 else
1351 tgtcursor = &gSysCursor[wCategory - WTI_CURSORS];
1352 switch (nIndex)
1354 case CSR_NAME:
1355 rc = CopyTabletData(lpOutput, tgtcursor->NAME,
1356 (strlenW(tgtcursor->NAME)+1) * sizeof(WCHAR));
1357 break;
1358 case CSR_ACTIVE:
1359 rc = CopyTabletData(lpOutput,&tgtcursor->ACTIVE,
1360 sizeof(BOOL));
1361 break;
1362 case CSR_PKTDATA:
1363 rc = CopyTabletData(lpOutput,&tgtcursor->PKTDATA,
1364 sizeof(WTPKT));
1365 break;
1366 case CSR_BUTTONS:
1367 rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONS,
1368 sizeof(BYTE));
1369 break;
1370 case CSR_BUTTONBITS:
1371 rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONBITS,
1372 sizeof(BYTE));
1373 break;
1374 case CSR_BTNNAMES:
1375 FIXME("Button Names not returned correctly\n");
1376 rc = CopyTabletData(lpOutput,&tgtcursor->BTNNAMES,
1377 tgtcursor->cchBTNNAMES*sizeof(WCHAR));
1378 break;
1379 case CSR_BUTTONMAP:
1380 rc = CopyTabletData(lpOutput,tgtcursor->BUTTONMAP,
1381 sizeof(BYTE)*32);
1382 break;
1383 case CSR_SYSBTNMAP:
1384 rc = CopyTabletData(lpOutput,tgtcursor->SYSBTNMAP,
1385 sizeof(BYTE)*32);
1386 break;
1387 case CSR_NPBTNMARKS:
1388 rc = CopyTabletData(lpOutput,tgtcursor->NPBTNMARKS,
1389 sizeof(UINT)*2);
1390 break;
1391 case CSR_NPBUTTON:
1392 rc = CopyTabletData(lpOutput,&tgtcursor->NPBUTTON,
1393 sizeof(BYTE));
1394 break;
1395 case CSR_NPRESPONSE:
1396 FIXME("Not returning CSR_NPRESPONSE correctly\n");
1397 rc = 0;
1398 break;
1399 case CSR_TPBUTTON:
1400 rc = CopyTabletData(lpOutput,&tgtcursor->TPBUTTON,
1401 sizeof(BYTE));
1402 break;
1403 case CSR_TPBTNMARKS:
1404 rc = CopyTabletData(lpOutput,tgtcursor->TPBTNMARKS,
1405 sizeof(UINT)*2);
1406 break;
1407 case CSR_TPRESPONSE:
1408 FIXME("Not returning CSR_TPRESPONSE correctly\n");
1409 rc = 0;
1410 break;
1411 case CSR_PHYSID:
1413 DWORD id;
1414 id = tgtcursor->PHYSID;
1415 rc = CopyTabletData(lpOutput,&id,sizeof(DWORD));
1417 break;
1418 case CSR_MODE:
1419 rc = CopyTabletData(lpOutput,&tgtcursor->MODE,sizeof(UINT));
1420 break;
1421 case CSR_MINPKTDATA:
1422 rc = CopyTabletData(lpOutput,&tgtcursor->MINPKTDATA,
1423 sizeof(UINT));
1424 break;
1425 case CSR_MINBUTTONS:
1426 rc = CopyTabletData(lpOutput,&tgtcursor->MINBUTTONS,
1427 sizeof(UINT));
1428 break;
1429 case CSR_CAPABILITIES:
1430 rc = CopyTabletData(lpOutput,&tgtcursor->CAPABILITIES,
1431 sizeof(UINT));
1432 break;
1433 case CSR_TYPE:
1434 rc = CopyTabletData(lpOutput,&tgtcursor->TYPE,
1435 sizeof(UINT));
1436 break;
1437 default:
1438 FIXME("WTI_CURSORS unhandled index %i\n",nIndex);
1439 rc = 0;
1442 break;
1443 case WTI_DEVICES:
1444 switch (nIndex)
1446 case DVC_NAME:
1447 rc = CopyTabletData(lpOutput,gSysDevice.NAME,
1448 (strlenW(gSysDevice.NAME)+1) * sizeof(WCHAR));
1449 break;
1450 case DVC_HARDWARE:
1451 rc = CopyTabletData(lpOutput,&gSysDevice.HARDWARE,
1452 sizeof(UINT));
1453 break;
1454 case DVC_NCSRTYPES:
1455 rc = CopyTabletData(lpOutput,&gSysDevice.NCSRTYPES,
1456 sizeof(UINT));
1457 break;
1458 case DVC_FIRSTCSR:
1459 rc = CopyTabletData(lpOutput,&gSysDevice.FIRSTCSR,
1460 sizeof(UINT));
1461 break;
1462 case DVC_PKTRATE:
1463 rc = CopyTabletData(lpOutput,&gSysDevice.PKTRATE,
1464 sizeof(UINT));
1465 break;
1466 case DVC_PKTDATA:
1467 rc = CopyTabletData(lpOutput,&gSysDevice.PKTDATA,
1468 sizeof(WTPKT));
1469 break;
1470 case DVC_PKTMODE:
1471 rc = CopyTabletData(lpOutput,&gSysDevice.PKTMODE,
1472 sizeof(WTPKT));
1473 break;
1474 case DVC_CSRDATA:
1475 rc = CopyTabletData(lpOutput,&gSysDevice.CSRDATA,
1476 sizeof(WTPKT));
1477 break;
1478 case DVC_XMARGIN:
1479 rc = CopyTabletData(lpOutput,&gSysDevice.XMARGIN,
1480 sizeof(INT));
1481 break;
1482 case DVC_YMARGIN:
1483 rc = CopyTabletData(lpOutput,&gSysDevice.YMARGIN,
1484 sizeof(INT));
1485 break;
1486 case DVC_ZMARGIN:
1487 rc = 0; /* unsupported */
1489 rc = CopyTabletData(lpOutput,&gSysDevice.ZMARGIN,
1490 sizeof(INT));
1492 break;
1493 case DVC_X:
1494 rc = CopyTabletData(lpOutput,&gSysDevice.X,
1495 sizeof(AXIS));
1496 break;
1497 case DVC_Y:
1498 rc = CopyTabletData(lpOutput,&gSysDevice.Y,
1499 sizeof(AXIS));
1500 break;
1501 case DVC_Z:
1502 rc = 0; /* unsupported */
1504 rc = CopyTabletData(lpOutput,&gSysDevice.Z,
1505 sizeof(AXIS));
1507 break;
1508 case DVC_NPRESSURE:
1509 rc = CopyTabletData(lpOutput,&gSysDevice.NPRESSURE,
1510 sizeof(AXIS));
1511 break;
1512 case DVC_TPRESSURE:
1513 rc = 0; /* unsupported */
1515 rc = CopyTabletData(lpOutput,&gSysDevice.TPRESSURE,
1516 sizeof(AXIS));
1518 break;
1519 case DVC_ORIENTATION:
1520 rc = CopyTabletData(lpOutput,gSysDevice.ORIENTATION,
1521 sizeof(AXIS)*3);
1522 break;
1523 case DVC_ROTATION:
1524 rc = 0; /* unsupported */
1526 rc = CopyTabletData(lpOutput,&gSysDevice.ROTATION,
1527 sizeof(AXIS)*3);
1529 break;
1530 case DVC_PNPID:
1531 rc = CopyTabletData(lpOutput,gSysDevice.PNPID,
1532 (strlenW(gSysDevice.PNPID)+1)*sizeof(WCHAR));
1533 break;
1534 default:
1535 FIXME("WTI_DEVICES unhandled index %i\n",nIndex);
1536 rc = 0;
1538 break;
1539 default:
1540 FIXME("Unhandled Category %i\n",wCategory);
1542 return rc;
1545 #else /* SONAME_LIBXI */
1547 /***********************************************************************
1548 * AttachEventQueueToTablet (X11DRV.@)
1550 int CDECL X11DRV_AttachEventQueueToTablet(HWND hOwner)
1552 return 0;
1555 /***********************************************************************
1556 * GetCurrentPacket (X11DRV.@)
1558 int CDECL X11DRV_GetCurrentPacket(LPWTPACKET packet)
1560 return 0;
1563 /***********************************************************************
1564 * LoadTabletInfo (X11DRV.@)
1566 BOOL CDECL X11DRV_LoadTabletInfo(HWND hwnddefault)
1568 return FALSE;
1571 /***********************************************************************
1572 * WTInfoW (X11DRV.@)
1574 UINT CDECL X11DRV_WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
1576 return 0;
1579 #endif /* SONAME_LIBXI */