strmbase: Implement BaseControlWindow.
[wine/multimedia.git] / dlls / winex11.drv / wintab.c
blobba3373218093ee2cc33cae22d124bc4ca435a612
1 /*
2 * X11 tablet driver
4 * Copyright 2003 CodeWeavers (Aric Stewart)
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdlib.h>
25 #include <stdarg.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winnls.h"
30 #include "x11drv.h"
31 #include "wine/library.h"
32 #include "wine/unicode.h"
33 #include "wine/debug.h"
34 #include "wintab.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(wintab32);
38 #define WT_MAX_NAME_LEN 256
40 typedef struct tagWTI_CURSORS_INFO
42 WCHAR NAME[WT_MAX_NAME_LEN];
43 /* a displayable zero-terminated string containing the name of the
44 * cursor.
46 BOOL ACTIVE;
47 /* whether the cursor is currently connected. */
48 WTPKT PKTDATA;
49 /* a bit mask indicating the packet data items supported when this
50 * cursor is connected.
52 BYTE BUTTONS;
53 /* the number of buttons on this cursor. */
54 BYTE BUTTONBITS;
55 /* the number of bits of raw button data returned by the hardware.*/
56 DWORD cchBTNNAMES;
57 WCHAR *BTNNAMES;
58 /* a list of zero-terminated strings containing the names of the
59 * cursor's buttons. The number of names in the list is the same as the
60 * number of buttons on the cursor. The names are separated by a single
61 * zero character; the list is terminated by two zero characters.
63 BYTE BUTTONMAP[32];
64 /* a 32 byte array of logical button numbers, one for each physical
65 * button.
67 BYTE SYSBTNMAP[32];
68 /* a 32 byte array of button action codes, one for each logical
69 * button.
71 BYTE NPBUTTON;
72 /* the physical button number of the button that is controlled by normal
73 * pressure.
75 UINT NPBTNMARKS[2];
76 /* an array of two UINTs, specifying the button marks for the normal
77 * pressure button. The first UINT contains the release mark; the second
78 * contains the press mark.
80 UINT *NPRESPONSE;
81 /* an array of UINTs describing the pressure response curve for normal
82 * pressure.
84 BYTE TPBUTTON;
85 /* the physical button number of the button that is controlled by
86 * tangential pressure.
88 UINT TPBTNMARKS[2];
89 /* an array of two UINTs, specifying the button marks for the tangential
90 * pressure button. The first UINT contains the release mark; the second
91 * contains the press mark.
93 UINT *TPRESPONSE;
94 /* an array of UINTs describing the pressure response curve for
95 * tangential pressure.
97 DWORD PHYSID;
98 /* a manufacturer-specific physical identifier for the cursor. This
99 * value will distinguish the physical cursor from others on the same
100 * device. This physical identifier allows applications to bind
101 * functions to specific physical cursors, even if category numbers
102 * change and multiple, otherwise identical, physical cursors are
103 * present.
105 UINT MODE;
106 /* the cursor mode number of this cursor type, if this cursor type has
107 * the CRC_MULTIMODE capability.
109 UINT MINPKTDATA;
110 /* the minimum set of data available from a physical cursor in this
111 * cursor type, if this cursor type has the CRC_AGGREGATE capability.
113 UINT MINBUTTONS;
114 /* the minimum number of buttons of physical cursors in the cursor type,
115 * if this cursor type has the CRC_AGGREGATE capability.
117 UINT CAPABILITIES;
118 /* flags indicating cursor capabilities, as defined below:
119 CRC_MULTIMODE
120 Indicates this cursor type describes one of several modes of a
121 single physical cursor. Consecutive cursor type categories
122 describe the modes; the CSR_MODE data item gives the mode number
123 of each cursor type.
124 CRC_AGGREGATE
125 Indicates this cursor type describes several physical cursors
126 that cannot be distinguished by software.
127 CRC_INVERT
128 Indicates this cursor type describes the physical cursor in its
129 inverted orientation; the previous consecutive cursor type
130 category describes the normal orientation.
132 UINT TYPE;
133 /* Manufacturer Unique id for the item type */
134 } WTI_CURSORS_INFO, *LPWTI_CURSORS_INFO;
137 typedef struct tagWTI_DEVICES_INFO
139 WCHAR NAME[WT_MAX_NAME_LEN];
140 /* a displayable null- terminated string describing the device,
141 * manufacturer, and revision level.
143 UINT HARDWARE;
144 /* flags indicating hardware and driver capabilities, as defined
145 * below:
146 HWC_INTEGRATED:
147 Indicates that the display and digitizer share the same surface.
148 HWC_TOUCH
149 Indicates that the cursor must be in physical contact with the
150 device to report position.
151 HWC_HARDPROX
152 Indicates that device can generate events when the cursor is
153 entering and leaving the physical detection range.
154 HWC_PHYSID_CURSORS
155 Indicates that device can uniquely identify the active cursor in
156 hardware.
158 UINT NCSRTYPES;
159 /* the number of supported cursor types.*/
160 UINT FIRSTCSR;
161 /* the first cursor type number for the device. */
162 UINT PKTRATE;
163 /* the maximum packet report rate in Hertz. */
164 WTPKT PKTDATA;
165 /* a bit mask indicating which packet data items are always available.*/
166 WTPKT PKTMODE;
167 /* a bit mask indicating which packet data items are physically
168 * relative, i.e., items for which the hardware can only report change,
169 * not absolute measurement.
171 WTPKT CSRDATA;
172 /* a bit mask indicating which packet data items are only available when
173 * certain cursors are connected. The individual cursor descriptions
174 * must be consulted to determine which cursors return which data.
176 INT XMARGIN;
177 INT YMARGIN;
178 INT ZMARGIN;
179 /* the size of tablet context margins in tablet native coordinates, in
180 * the x, y, and z directions, respectively.
182 AXIS X;
183 AXIS Y;
184 AXIS Z;
185 /* the tablet's range and resolution capabilities, in the x, y, and z
186 * axes, respectively.
188 AXIS NPRESSURE;
189 AXIS TPRESSURE;
190 /* the tablet's range and resolution capabilities, for the normal and
191 * tangential pressure inputs, respectively.
193 AXIS ORIENTATION[3];
194 /* a 3-element array describing the tablet's orientation range and
195 * resolution capabilities.
197 AXIS ROTATION[3];
198 /* a 3-element array describing the tablet's rotation range and
199 * resolution capabilities.
201 WCHAR PNPID[WT_MAX_NAME_LEN];
202 /* a null-terminated string containing the devices Plug and Play ID.*/
203 } WTI_DEVICES_INFO, *LPWTI_DEVICES_INFO;
206 /***********************************************************************
207 * WACOM WINTAB EXTENSIONS TO SUPPORT CSR_TYPE
208 * In Wintab 1.2, a CSR_TYPE feature was added. This adds the
209 * ability to return a type of cursor on a tablet.
210 * Unfortunately, we cannot get the cursor type directly from X,
211 * and it is not specified directly anywhere. So we virtualize
212 * the type here. (This is unfortunate, the kernel module has
213 * the exact type, but we have no way of getting that module to
214 * pass us that type).
216 * Reference linuxwacom driver project wcmCommon.c function
217 * idtotype for a much larger list of CSR_TYPE.
219 * http://linuxwacom.cvs.sourceforge.net/linuxwacom/linuxwacom-prod/src/xdrv/wcmCommon.c?view=markup
221 * The WTI_CURSORS_INFO.TYPE data is supposed to be used like this:
222 * (cursor.TYPE & 0x0F06) == target_cursor_type
223 * Reference: Section Unique ID
224 * http://www.wacomeng.com/devsupport/ibmpc/gddevpc.html
226 #define CSR_TYPE_PEN 0x822
227 #define CSR_TYPE_ERASER 0x82a
228 #define CSR_TYPE_MOUSE_2D 0x007
229 #define CSR_TYPE_MOUSE_4D 0x094
230 /* CSR_TYPE_OTHER is a special value! assumed no real world significance
231 * if a stylus type or eraser type eventually have this value
232 * it'll be a bug. As of 2008 05 21 we can be sure because
233 * linux wacom lists all the known values and this isn't one of them */
234 #define CSR_TYPE_OTHER 0x000
236 typedef struct tagWTPACKET {
237 HCTX pkContext;
238 UINT pkStatus;
239 LONG pkTime;
240 WTPKT pkChanged;
241 UINT pkSerialNumber;
242 UINT pkCursor;
243 DWORD pkButtons;
244 DWORD pkX;
245 DWORD pkY;
246 DWORD pkZ;
247 UINT pkNormalPressure;
248 UINT pkTangentPressure;
249 ORIENTATION pkOrientation;
250 ROTATION pkRotation; /* 1.1 */
251 } WTPACKET, *LPWTPACKET;
254 #ifdef SONAME_LIBXI
256 #include <X11/Xlib.h>
257 #include <X11/extensions/XInput.h>
259 static int motion_type;
260 static int button_press_type;
261 static int button_release_type;
262 static int key_press_type;
263 static int key_release_type;
264 static int proximity_in_type;
265 static int proximity_out_type;
267 static HWND hwndTabletDefault;
268 static WTPACKET gMsgPacket;
269 static DWORD gSerial;
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 = wine_dlopen(SONAME_LIBXI, RTLD_NOW, NULL, 0);
330 if (xinput_handle)
332 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xinput_handle, #f, NULL, 0)) == 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_whitelist[] = {
398 "wacom",
399 "wizardpen",
400 "acecad",
401 "tablet",
402 "cursor",
403 "stylus",
404 "eraser",
405 "pad",
406 NULL
409 for (i=0; tablet_cursor_whitelist[i] != NULL; i++) {
410 if (name && match_token(name, tablet_cursor_whitelist[i]))
411 return TRUE;
412 if (type && match_token(type, tablet_cursor_whitelist[i]))
413 return TRUE;
415 return FALSE;
418 static BOOL is_stylus(const char *name, const char *type)
420 int i;
421 static const char* tablet_stylus_whitelist[] = {
422 "stylus",
423 "wizardpen",
424 "acecad",
425 NULL
428 for (i=0; tablet_stylus_whitelist[i] != NULL; i++) {
429 if (name && match_token(name, tablet_stylus_whitelist[i]))
430 return TRUE;
431 if (type && match_token(type, tablet_stylus_whitelist[i]))
432 return TRUE;
435 return FALSE;
438 static BOOL is_eraser(const char *name, const char *type)
440 if (name && match_token(name, "eraser"))
441 return TRUE;
442 if (type && match_token(type, "eraser"))
443 return TRUE;
444 return FALSE;
447 /* cursors are placed in gSysCursor rows depending on their type
448 * see CURSORMAX comments for more detail */
449 static BOOL add_system_cursor(LPWTI_CURSORS_INFO cursor)
451 UINT offset = 0;
453 if (cursor->TYPE == CSR_TYPE_PEN)
454 offset = 1;
455 else if (cursor->TYPE == CSR_TYPE_ERASER)
456 offset = 2;
458 for (; offset < CURSORMAX; offset += 3)
460 if (!gSysCursor[offset].ACTIVE)
462 gSysCursor[offset] = *cursor;
463 ++gNumCursors;
464 return TRUE;
468 return FALSE;
471 static void disable_system_cursors(void)
473 UINT i;
475 for (i = 0; i < CURSORMAX; ++i)
477 gSysCursor[i].ACTIVE = 0;
480 gNumCursors = 0;
484 /***********************************************************************
485 * X11DRV_LoadTabletInfo (X11DRV.@)
487 BOOL CDECL X11DRV_LoadTabletInfo(HWND hwnddefault)
489 const WCHAR SZ_CONTEXT_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','C','o','n','t','e','x','t',0};
490 const WCHAR SZ_DEVICE_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','D','e','v','i','c','e',0};
491 const WCHAR SZ_NON_PLUGINPLAY[] = {'n','o','n','-','p','l','u','g','i','n','p','l','a','y',0};
493 struct x11drv_thread_data *data = x11drv_init_thread_data();
494 int num_devices;
495 int loop;
496 XDeviceInfo *devices;
497 XDeviceInfo *target = NULL;
498 BOOL axis_read_complete= FALSE;
500 XAnyClassPtr any;
501 XButtonInfoPtr Button;
502 XValuatorInfoPtr Val;
503 XAxisInfoPtr Axis;
505 XDevice *opendevice;
507 if (!X11DRV_XInput_Init())
509 ERR("Unable to initialize the XInput library.\n");
510 return FALSE;
513 hwndTabletDefault = hwnddefault;
515 /* Do base initialization */
516 strcpyW(gSysContext.lcName, SZ_CONTEXT_NAME);
517 strcpyW(gSysDevice.NAME, SZ_DEVICE_NAME);
519 gSysContext.lcOptions = CXO_SYSTEM;
520 gSysContext.lcLocks = CXL_INSIZE | CXL_INASPECT | CXL_MARGIN |
521 CXL_SENSITIVITY | CXL_SYSOUT;
523 gSysContext.lcMsgBase= WT_DEFBASE;
524 gSysContext.lcDevice = 0;
525 gSysContext.lcPktData =
526 PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
527 PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
528 gSysContext.lcMoveMask=
529 PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
530 gSysContext.lcStatus = CXS_ONTOP;
531 gSysContext.lcPktRate = 100;
532 gSysContext.lcBtnDnMask = 0xffffffff;
533 gSysContext.lcBtnUpMask = 0xffffffff;
534 gSysContext.lcSensX = 65536;
535 gSysContext.lcSensY = 65536;
536 gSysContext.lcSensX = 65536;
537 gSysContext.lcSensZ = 65536;
538 gSysContext.lcSysSensX= 65536;
539 gSysContext.lcSysSensY= 65536;
541 /* initialize cursors */
542 disable_system_cursors();
544 /* Device Defaults */
545 gSysDevice.HARDWARE = HWC_HARDPROX|HWC_PHYSID_CURSORS;
546 gSysDevice.FIRSTCSR= 0;
547 gSysDevice.PKTRATE = 100;
548 gSysDevice.PKTDATA =
549 PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
550 PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
551 strcpyW(gSysDevice.PNPID, SZ_NON_PLUGINPLAY);
553 wine_tsx11_lock();
555 devices = pXListInputDevices(data->display, &num_devices);
556 if (!devices)
558 WARN("XInput Extensions reported as not available\n");
559 wine_tsx11_unlock();
560 return FALSE;
562 TRACE("XListInputDevices reports %d devices\n", num_devices);
563 for (loop=0; loop < num_devices; loop++)
565 int class_loop;
566 char *device_type = devices[loop].type ? XGetAtomName(data->display, devices[loop].type) : NULL;
567 WTI_CURSORS_INFO cursor;
569 TRACE("Device %i: [id %d|name %s|type %s|num_classes %d|use %d]\n",
570 loop, (int) devices[loop].id, devices[loop].name, device_type ? device_type : "",
571 devices[loop].num_classes, devices[loop].use );
573 switch (devices[loop].use)
575 case IsXExtensionDevice:
576 #ifdef IsXExtensionPointer
577 case IsXExtensionPointer:
578 #endif
579 #ifdef IsXExtensionKeyboard
580 case IsXExtensionKeyboard:
581 #endif
582 TRACE("Is XExtension: Device, Keyboard, or Pointer\n");
583 target = &devices[loop];
585 if (strlen(target->name) >= WT_MAX_NAME_LEN)
587 ERR("Input device '%s' name too long - skipping\n", wine_dbgstr_a(target->name));
588 break;
591 X11DRV_expect_error(data->display, Tablet_ErrorHandler, NULL);
592 opendevice = pXOpenDevice(data->display,target->id);
593 if (!X11DRV_check_error() && opendevice)
595 unsigned char map[32];
596 int i;
597 int shft = 0;
599 X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
600 cursor.BUTTONS = pXGetDeviceButtonMapping(data->display, opendevice, map, 32);
601 if (X11DRV_check_error() || cursor.BUTTONS <= 0)
603 TRACE("No buttons, Non Tablet Device\n");
604 pXCloseDevice(data->display, opendevice);
605 break;
608 for (i=0; i< cursor.BUTTONS; i++,shft++)
610 cursor.BUTTONMAP[i] = map[i];
611 cursor.SYSBTNMAP[i] = (1<<shft);
613 pXCloseDevice(data->display, opendevice);
615 else
617 WARN("Unable to open device %s\n",target->name);
618 break;
620 MultiByteToWideChar(CP_UNIXCP, 0, target->name, -1, cursor.NAME, WT_MAX_NAME_LEN);
622 if (! is_tablet_cursor(target->name, device_type))
624 WARN("Skipping device %d [name %s|type %s]; not apparently a tablet cursor type device. If this is wrong, please report it to wine-devel@winehq.org\n",
625 loop, devices[loop].name, device_type ? device_type : "");
626 break;
629 cursor.ACTIVE = 1;
630 cursor.PKTDATA = PK_TIME | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y |
631 PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE |
632 PK_ORIENTATION;
634 cursor.PHYSID = target->id;
635 cursor.NPBUTTON = 1;
636 cursor.NPBTNMARKS[0] = 0 ;
637 cursor.NPBTNMARKS[1] = 1 ;
638 cursor.CAPABILITIES = CRC_MULTIMODE;
640 /* prefer finding TYPE_PEN(most capable) */
641 if (is_stylus(target->name, device_type))
642 cursor.TYPE = CSR_TYPE_PEN;
643 else if (is_eraser(target->name, device_type))
644 cursor.TYPE = CSR_TYPE_ERASER;
645 else
646 cursor.TYPE = CSR_TYPE_OTHER;
648 any = target->inputclassinfo;
650 for (class_loop = 0; class_loop < target->num_classes; class_loop++)
652 switch (any->class)
655 case ValuatorClass:
656 Val = (XValuatorInfoPtr) any;
657 TRACE(" ValidatorInput %d: [class %d|length %d|num_axes %d|mode %d|motion_buffer %ld]\n",
658 class_loop, (int) Val->class, Val->length, Val->num_axes, Val->mode, Val->motion_buffer);
659 if (TRACE_ON(wintab32))
660 trace_axes(Val);
662 /* FIXME: This is imperfect; we compute our devices capabilities based upon the
663 ** first pen type device we find. However, a more correct implementation
664 ** would require acquiring a wide variety of tablets and running through
665 ** the various inputs to see what the values are. Odds are that a
666 ** more 'correct' algorithm would condense to this one anyway.
668 if (!axis_read_complete && cursor.TYPE == CSR_TYPE_PEN)
670 Axis = (XAxisInfoPtr) ((char *) Val + sizeof
671 (XValuatorInfo));
673 if (Val->num_axes>=1)
675 /* Axis 1 is X */
676 gSysDevice.X.axMin = Axis->min_value;
677 gSysDevice.X.axMax= Axis->max_value;
678 gSysDevice.X.axUnits = TU_INCHES;
679 gSysDevice.X.axResolution = Axis->resolution;
680 gSysContext.lcInOrgX = Axis->min_value;
681 gSysContext.lcSysOrgX = Axis->min_value;
682 gSysContext.lcInExtX = Axis->max_value;
683 gSysContext.lcSysExtX = Axis->max_value;
684 Axis++;
686 if (Val->num_axes>=2)
688 /* Axis 2 is Y */
689 gSysDevice.Y.axMin = Axis->min_value;
690 gSysDevice.Y.axMax= Axis->max_value;
691 gSysDevice.Y.axUnits = TU_INCHES;
692 gSysDevice.Y.axResolution = Axis->resolution;
693 gSysContext.lcInOrgY = Axis->min_value;
694 gSysContext.lcSysOrgY = Axis->min_value;
695 gSysContext.lcInExtY = Axis->max_value;
696 gSysContext.lcSysExtY = Axis->max_value;
697 Axis++;
699 if (Val->num_axes>=3)
701 /* Axis 3 is Normal Pressure */
702 gSysDevice.NPRESSURE.axMin = Axis->min_value;
703 gSysDevice.NPRESSURE.axMax= Axis->max_value;
704 gSysDevice.NPRESSURE.axUnits = TU_INCHES;
705 gSysDevice.NPRESSURE.axResolution =
706 Axis->resolution;
707 Axis++;
709 if (Val->num_axes >= 5)
711 /* Axis 4 and 5 are X and Y tilt */
712 XAxisInfoPtr XAxis = Axis;
713 Axis++;
714 if (max (abs(Axis->max_value),
715 abs(XAxis->max_value)))
717 gSysDevice.ORIENTATION[0].axMin = 0;
718 gSysDevice.ORIENTATION[0].axMax = 3600;
719 gSysDevice.ORIENTATION[0].axUnits = TU_CIRCLE;
720 gSysDevice.ORIENTATION[0].axResolution
721 = CASTFIX32(3600);
722 gSysDevice.ORIENTATION[1].axMin = -1000;
723 gSysDevice.ORIENTATION[1].axMax = 1000;
724 gSysDevice.ORIENTATION[1].axUnits = TU_CIRCLE;
725 gSysDevice.ORIENTATION[1].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 = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*cchBuf);
743 for (i = 0; i < cursor.BUTTONS; i++)
745 /* FIXME - these names are probably incorrect */
746 int cch = strlenW(cursor.NAME) + 1;
747 while (cch > cchBuf - cchPos - 1) /* we want one extra byte for the last NUL */
749 cchBuf *= 2;
750 cursor.BTNNAMES = HeapReAlloc(GetProcessHeap(), 0, cursor.BTNNAMES, sizeof(WCHAR)*cchBuf);
753 strcpyW(cursor.BTNNAMES + cchPos, cursor.NAME);
754 cchPos += cch;
756 cursor.BTNNAMES[cchPos++] = 0;
757 cursor.BTNNAMES = HeapReAlloc(GetProcessHeap(), 0, 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)
773 gSysDevice.NCSRTYPES = gNumCursors;
774 else
776 disable_system_cursors();
777 WARN("Did not find a valid stylus, unable to determine system context parameters. Wintab is disabled.\n");
780 wine_tsx11_unlock();
781 return TRUE;
784 static int figure_deg(int x, int y)
786 float angle;
788 angle = atan2((float)y, (float)x);
789 angle += M_PI_2;
790 if (angle <= 0)
791 angle += 2 * M_PI;
793 return (0.5 + (angle * 1800.0 / M_PI));
796 static int get_button_state(int curnum)
798 return button_state[curnum];
801 static void set_button_state(int curnum, XID deviceid)
803 struct x11drv_thread_data *data = x11drv_thread_data();
804 XDevice *device;
805 XDeviceState *state;
806 XInputClass *class;
807 int loop;
808 int rc = 0;
810 wine_tsx11_lock();
811 device = pXOpenDevice(data->display,deviceid);
812 state = pXQueryDeviceState(data->display,device);
814 if (state)
816 class = state->data;
817 for (loop = 0; loop < state->num_classes; loop++)
819 if (class->class == ButtonClass)
821 int loop2;
822 XButtonState *button_state = (XButtonState*)class;
823 for (loop2 = 0; loop2 < button_state->num_buttons; loop2++)
825 if (button_state->buttons[loop2 / 8] & (1 << (loop2 % 8)))
827 rc |= (1<<loop2);
831 class = (XInputClass *) ((char *) class + class->length);
834 pXFreeDeviceState(state);
835 wine_tsx11_unlock();
836 button_state[curnum] = rc;
839 static int cursor_from_device(DWORD deviceid, LPWTI_CURSORS_INFO *cursorp)
841 int i;
842 for (i = 0; i < CURSORMAX; i++)
843 if (gSysCursor[i].ACTIVE && gSysCursor[i].PHYSID == deviceid)
845 *cursorp = &gSysCursor[i];
846 return i;
849 ERR("Could not map device id %d to a cursor\n", (int) deviceid);
850 return -1;
853 static void motion_event( HWND hwnd, XEvent *event )
855 XDeviceMotionEvent *motion = (XDeviceMotionEvent *)event;
856 LPWTI_CURSORS_INFO cursor;
857 int curnum = cursor_from_device(motion->deviceid, &cursor);
858 if (curnum < 0)
859 return;
861 memset(&gMsgPacket,0,sizeof(WTPACKET));
863 TRACE("Received tablet motion event (%p); device id %d, cursor num %d\n",hwnd, (int) motion->deviceid, curnum);
865 /* Set cursor to inverted if cursor is the eraser */
866 gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
867 gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(motion->time);
868 gMsgPacket.pkSerialNumber = gSerial++;
869 gMsgPacket.pkCursor = curnum;
870 gMsgPacket.pkX = motion->axis_data[0];
871 gMsgPacket.pkY = motion->axis_data[1];
872 gMsgPacket.pkOrientation.orAzimuth = figure_deg(motion->axis_data[3],motion->axis_data[4]);
873 gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max
874 (abs(motion->axis_data[3]),
875 abs(motion->axis_data[4])))
876 * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
877 gMsgPacket.pkNormalPressure = motion->axis_data[2];
878 gMsgPacket.pkButtons = get_button_state(curnum);
879 SendMessageW(hwndTabletDefault,WT_PACKET,gMsgPacket.pkSerialNumber,(LPARAM)hwnd);
882 static void button_event( HWND hwnd, XEvent *event )
884 XDeviceButtonEvent *button = (XDeviceButtonEvent *) event;
885 LPWTI_CURSORS_INFO cursor;
886 int curnum = cursor_from_device(button->deviceid, &cursor);
887 if (curnum < 0)
888 return;
890 memset(&gMsgPacket,0,sizeof(WTPACKET));
892 TRACE("Received tablet button %s event\n", (event->type == button_press_type)?"press":"release");
894 /* Set cursor to inverted if cursor is the eraser */
895 gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
896 set_button_state(curnum, button->deviceid);
897 gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(button->time);
898 gMsgPacket.pkSerialNumber = gSerial++;
899 gMsgPacket.pkCursor = curnum;
900 gMsgPacket.pkX = button->axis_data[0];
901 gMsgPacket.pkY = button->axis_data[1];
902 gMsgPacket.pkOrientation.orAzimuth = figure_deg(button->axis_data[3],button->axis_data[4]);
903 gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(button->axis_data[3]),
904 abs(button->axis_data[4])))
905 * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
906 gMsgPacket.pkNormalPressure = button->axis_data[2];
907 gMsgPacket.pkButtons = get_button_state(curnum);
908 SendMessageW(hwndTabletDefault,WT_PACKET,gMsgPacket.pkSerialNumber,(LPARAM)hwnd);
911 static void key_event( HWND hwnd, XEvent *event )
913 if (event->type == key_press_type)
914 FIXME("Received tablet key press event\n");
915 else
916 FIXME("Received tablet key release event\n");
919 static void proximity_event( HWND hwnd, XEvent *event )
921 XProximityNotifyEvent *proximity = (XProximityNotifyEvent *) event;
922 LPWTI_CURSORS_INFO cursor;
923 int curnum = cursor_from_device(proximity->deviceid, &cursor);
924 LPARAM proximity_info;
926 TRACE("hwnd=%p\n", hwnd);
928 if (curnum < 0)
929 return;
931 memset(&gMsgPacket,0,sizeof(WTPACKET));
933 /* Set cursor to inverted if cursor is the eraser */
934 gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
935 gMsgPacket.pkStatus |= (event->type==proximity_out_type)?TPS_PROXIMITY:0;
936 gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(proximity->time);
937 gMsgPacket.pkSerialNumber = gSerial++;
938 gMsgPacket.pkCursor = curnum;
939 gMsgPacket.pkX = proximity->axis_data[0];
940 gMsgPacket.pkY = proximity->axis_data[1];
941 gMsgPacket.pkOrientation.orAzimuth = figure_deg(proximity->axis_data[3],proximity->axis_data[4]);
942 gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(proximity->axis_data[3]),
943 abs(proximity->axis_data[4])))
944 * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
945 gMsgPacket.pkNormalPressure = proximity->axis_data[2];
946 gMsgPacket.pkButtons = get_button_state(curnum);
948 /* FIXME: LPARAM loword is true when cursor entering context, false when leaving context
949 * This needs to be handled here or in wintab32. Using the proximity_in_type is not correct
950 * but kept for now.
951 * LPARAM hiword is "non-zero when the cursor is leaving or entering hardware proximity"
952 * WPARAM contains context handle.
953 * HWND to HCTX is handled by wintab32.
955 proximity_info = MAKELPARAM((event->type == proximity_in_type),
956 (event->type == proximity_in_type) || (event->type == proximity_out_type));
957 SendMessageW(hwndTabletDefault, WT_PROXIMITY, (WPARAM)hwnd, proximity_info);
960 /***********************************************************************
961 * X11DRV_AttachEventQueueToTablet (X11DRV.@)
963 int CDECL X11DRV_AttachEventQueueToTablet(HWND hOwner)
965 struct x11drv_thread_data *data = x11drv_init_thread_data();
966 int num_devices;
967 int loop;
968 int cur_loop;
969 XDeviceInfo *devices;
970 XDeviceInfo *target = NULL;
971 XDevice *the_device;
972 XEventClass event_list[7];
973 Window win = X11DRV_get_whole_window( hOwner );
975 if (!win || !xinput_handle) return 0;
977 TRACE("Creating context for window %p (%lx) %i cursors\n", hOwner, win, gNumCursors);
979 wine_tsx11_lock();
980 devices = pXListInputDevices(data->display, &num_devices);
982 X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
983 for (cur_loop=0; cur_loop < CURSORMAX; cur_loop++)
985 char cursorNameA[WT_MAX_NAME_LEN];
986 int event_number=0;
988 if (!gSysCursor[cur_loop].ACTIVE) continue;
990 /* the cursor name fits in the buffer because too long names are skipped */
991 WideCharToMultiByte(CP_UNIXCP, 0, gSysCursor[cur_loop].NAME, -1, cursorNameA, WT_MAX_NAME_LEN, NULL, NULL);
992 for (loop=0; loop < num_devices; loop ++)
993 if (strcmp(devices[loop].name, cursorNameA) == 0)
994 target = &devices[loop];
995 if (!target) {
996 WARN("Cursor Name %s not found in list of targets.\n", cursorNameA);
997 continue;
1000 TRACE("Opening cursor %i id %i\n",cur_loop,(INT)target->id);
1002 the_device = pXOpenDevice(data->display, target->id);
1004 if (!the_device)
1006 WARN("Unable to Open device\n");
1007 continue;
1010 if (the_device->num_classes > 0)
1012 DeviceKeyPress(the_device, key_press_type, event_list[event_number]);
1013 if (key_press_type) event_number++;
1014 DeviceKeyRelease(the_device, key_release_type, event_list[event_number]);
1015 if (key_release_type) event_number++;
1016 DeviceButtonPress(the_device, button_press_type, event_list[event_number]);
1017 if (button_press_type) event_number++;
1018 DeviceButtonRelease(the_device, button_release_type, event_list[event_number]);
1019 if (button_release_type) event_number++;
1020 DeviceMotionNotify(the_device, motion_type, event_list[event_number]);
1021 if (motion_type) event_number++;
1022 ProximityIn(the_device, proximity_in_type, event_list[event_number]);
1023 if (proximity_in_type) event_number++;
1024 ProximityOut(the_device, proximity_out_type, event_list[event_number]);
1025 if (proximity_out_type) event_number++;
1027 if (key_press_type)
1028 X11DRV_register_event_handler( key_press_type, key_event, "XInput KeyPress" );
1029 if (key_release_type)
1030 X11DRV_register_event_handler( key_release_type, key_event, "XInput KeyRelease" );
1031 if (button_press_type)
1032 X11DRV_register_event_handler( button_press_type, button_event, "XInput ButtonPress" );
1033 if (button_release_type)
1034 X11DRV_register_event_handler( button_release_type, button_event, "XInput ButtonRelease" );
1035 if (motion_type)
1036 X11DRV_register_event_handler( motion_type, motion_event, "XInput MotionNotify" );
1037 if (proximity_in_type)
1038 X11DRV_register_event_handler( proximity_in_type, proximity_event, "XInput ProximityIn" );
1039 if (proximity_out_type)
1040 X11DRV_register_event_handler( proximity_out_type, proximity_event, "XInput ProximityOut" );
1042 pXSelectExtensionEvent(data->display, win, event_list, event_number);
1045 XSync(data->display, False);
1046 X11DRV_check_error();
1048 if (NULL != devices) pXFreeDeviceList(devices);
1049 wine_tsx11_unlock();
1050 return 0;
1053 /***********************************************************************
1054 * X11DRV_GetCurrentPacket (X11DRV.@)
1056 int CDECL X11DRV_GetCurrentPacket(LPWTPACKET packet)
1058 *packet = gMsgPacket;
1059 return 1;
1063 static inline int CopyTabletData(LPVOID target, LPCVOID src, INT size)
1066 * It is valid to call CopyTabletData with NULL.
1067 * This handles the WTInfo() case where lpOutput is null.
1069 if(target != NULL)
1070 memcpy(target,src,size);
1071 return(size);
1074 /***********************************************************************
1075 * X11DRV_WTInfoW (X11DRV.@)
1077 UINT CDECL X11DRV_WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
1080 * It is valid to call WTInfoA with lpOutput == NULL, as per standard.
1081 * lpOutput == NULL signifies the user only wishes
1082 * to find the size of the data.
1083 * NOTE:
1084 * From now on use CopyTabletData to fill lpOutput. memcpy will break
1085 * the code.
1087 int rc = 0;
1088 LPWTI_CURSORS_INFO tgtcursor;
1089 TRACE("(%u, %u, %p)\n", wCategory, nIndex, lpOutput);
1091 if (!xinput_handle) return 0;
1093 switch(wCategory)
1095 case 0:
1096 /* return largest necessary buffer */
1097 TRACE("%i cursors\n",gNumCursors);
1098 if (gNumCursors>0)
1100 FIXME("Return proper size\n");
1101 rc = 200;
1103 break;
1104 case WTI_INTERFACE:
1105 switch (nIndex)
1107 WORD version;
1108 UINT num;
1109 case IFC_WINTABID:
1111 static const WCHAR driver[] = {'W','i','n','e',' ','W','i','n','t','a','b',' ','1','.','1',0};
1112 rc = CopyTabletData(lpOutput, driver, (strlenW(driver) + 1) * sizeof(WCHAR));
1113 break;
1115 case IFC_SPECVERSION:
1116 version = (0x01) | (0x01 << 8);
1117 rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
1118 break;
1119 case IFC_IMPLVERSION:
1120 version = (0x00) | (0x01 << 8);
1121 rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
1122 break;
1123 case IFC_NDEVICES:
1124 num = 1;
1125 rc = CopyTabletData(lpOutput, &num,sizeof(num));
1126 break;
1127 case IFC_NCURSORS:
1128 num = gNumCursors;
1129 rc = CopyTabletData(lpOutput, &num,sizeof(num));
1130 break;
1131 default:
1132 FIXME("WTI_INTERFACE unhandled index %i\n",nIndex);
1133 rc = 0;
1135 break;
1136 case WTI_DEFSYSCTX:
1137 case WTI_DDCTXS:
1138 case WTI_DEFCONTEXT:
1139 switch (nIndex)
1141 case 0:
1142 /* report 0 if wintab is disabled */
1143 if (0 == gNumCursors)
1144 rc = 0;
1145 else
1146 rc = CopyTabletData(lpOutput, &gSysContext,
1147 sizeof(LOGCONTEXTW));
1148 break;
1149 case CTX_NAME:
1150 rc = CopyTabletData(lpOutput, gSysContext.lcName,
1151 (strlenW(gSysContext.lcName)+1) * sizeof(WCHAR));
1152 break;
1153 case CTX_OPTIONS:
1154 rc = CopyTabletData(lpOutput, &gSysContext.lcOptions,
1155 sizeof(UINT));
1156 break;
1157 case CTX_STATUS:
1158 rc = CopyTabletData(lpOutput, &gSysContext.lcStatus,
1159 sizeof(UINT));
1160 break;
1161 case CTX_LOCKS:
1162 rc= CopyTabletData (lpOutput, &gSysContext.lcLocks,
1163 sizeof(UINT));
1164 break;
1165 case CTX_MSGBASE:
1166 rc = CopyTabletData(lpOutput, &gSysContext.lcMsgBase,
1167 sizeof(UINT));
1168 break;
1169 case CTX_DEVICE:
1170 rc = CopyTabletData(lpOutput, &gSysContext.lcDevice,
1171 sizeof(UINT));
1172 break;
1173 case CTX_PKTRATE:
1174 rc = CopyTabletData(lpOutput, &gSysContext.lcPktRate,
1175 sizeof(UINT));
1176 break;
1177 case CTX_PKTDATA:
1178 rc = CopyTabletData(lpOutput, &gSysContext.lcPktData,
1179 sizeof(WTPKT));
1180 break;
1181 case CTX_PKTMODE:
1182 rc = CopyTabletData(lpOutput, &gSysContext.lcPktMode,
1183 sizeof(WTPKT));
1184 break;
1185 case CTX_MOVEMASK:
1186 rc = CopyTabletData(lpOutput, &gSysContext.lcMoveMask,
1187 sizeof(WTPKT));
1188 break;
1189 case CTX_BTNDNMASK:
1190 rc = CopyTabletData(lpOutput, &gSysContext.lcBtnDnMask,
1191 sizeof(DWORD));
1192 break;
1193 case CTX_BTNUPMASK:
1194 rc = CopyTabletData(lpOutput, &gSysContext.lcBtnUpMask,
1195 sizeof(DWORD));
1196 break;
1197 case CTX_INORGX:
1198 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgX,
1199 sizeof(LONG));
1200 break;
1201 case CTX_INORGY:
1202 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgY,
1203 sizeof(LONG));
1204 break;
1205 case CTX_INORGZ:
1206 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgZ,
1207 sizeof(LONG));
1208 break;
1209 case CTX_INEXTX:
1210 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtX,
1211 sizeof(LONG));
1212 break;
1213 case CTX_INEXTY:
1214 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtY,
1215 sizeof(LONG));
1216 break;
1217 case CTX_INEXTZ:
1218 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtZ,
1219 sizeof(LONG));
1220 break;
1221 case CTX_OUTORGX:
1222 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgX,
1223 sizeof(LONG));
1224 break;
1225 case CTX_OUTORGY:
1226 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgY,
1227 sizeof(LONG));
1228 break;
1229 case CTX_OUTORGZ:
1230 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgZ,
1231 sizeof(LONG));
1232 break;
1233 case CTX_OUTEXTX:
1234 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtX,
1235 sizeof(LONG));
1236 break;
1237 case CTX_OUTEXTY:
1238 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtY,
1239 sizeof(LONG));
1240 break;
1241 case CTX_OUTEXTZ:
1242 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtZ,
1243 sizeof(LONG));
1244 break;
1245 case CTX_SENSX:
1246 rc = CopyTabletData(lpOutput, &gSysContext.lcSensX,
1247 sizeof(LONG));
1248 break;
1249 case CTX_SENSY:
1250 rc = CopyTabletData(lpOutput, &gSysContext.lcSensY,
1251 sizeof(LONG));
1252 break;
1253 case CTX_SENSZ:
1254 rc = CopyTabletData(lpOutput, &gSysContext.lcSensZ,
1255 sizeof(LONG));
1256 break;
1257 case CTX_SYSMODE:
1258 rc = CopyTabletData(lpOutput, &gSysContext.lcSysMode,
1259 sizeof(LONG));
1260 break;
1261 case CTX_SYSORGX:
1262 rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgX,
1263 sizeof(LONG));
1264 break;
1265 case CTX_SYSORGY:
1266 rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgY,
1267 sizeof(LONG));
1268 break;
1269 case CTX_SYSEXTX:
1270 rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtX,
1271 sizeof(LONG));
1272 break;
1273 case CTX_SYSEXTY:
1274 rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtY,
1275 sizeof(LONG));
1276 break;
1277 case CTX_SYSSENSX:
1278 rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensX,
1279 sizeof(LONG));
1280 break;
1281 case CTX_SYSSENSY:
1282 rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensY,
1283 sizeof(LONG));
1284 break;
1285 default:
1286 FIXME("WTI_DEFSYSCTX unhandled index %i\n",nIndex);
1287 rc = 0;
1289 break;
1290 case WTI_CURSORS:
1291 case WTI_CURSORS+1:
1292 case WTI_CURSORS+2:
1293 case WTI_CURSORS+3:
1294 case WTI_CURSORS+4:
1295 case WTI_CURSORS+5:
1296 case WTI_CURSORS+6:
1297 case WTI_CURSORS+7:
1298 case WTI_CURSORS+8:
1299 case WTI_CURSORS+9:
1300 case WTI_CURSORS+10:
1301 case WTI_CURSORS+11:
1302 /* CURSORMAX == 12 */
1303 /* FIXME: dynamic cursor support */
1304 /* Apps will poll different slots to detect what cursors are available
1305 * if there isn't a cursor for this slot return 0 */
1306 if (!gSysCursor[wCategory - WTI_CURSORS].ACTIVE)
1307 rc = 0;
1308 else
1310 tgtcursor = &gSysCursor[wCategory - WTI_CURSORS];
1311 switch (nIndex)
1313 case CSR_NAME:
1314 rc = CopyTabletData(lpOutput, tgtcursor->NAME,
1315 (strlenW(tgtcursor->NAME)+1) * sizeof(WCHAR));
1316 break;
1317 case CSR_ACTIVE:
1318 rc = CopyTabletData(lpOutput,&tgtcursor->ACTIVE,
1319 sizeof(BOOL));
1320 break;
1321 case CSR_PKTDATA:
1322 rc = CopyTabletData(lpOutput,&tgtcursor->PKTDATA,
1323 sizeof(WTPKT));
1324 break;
1325 case CSR_BUTTONS:
1326 rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONS,
1327 sizeof(BYTE));
1328 break;
1329 case CSR_BUTTONBITS:
1330 rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONBITS,
1331 sizeof(BYTE));
1332 break;
1333 case CSR_BTNNAMES:
1334 FIXME("Button Names not returned correctly\n");
1335 rc = CopyTabletData(lpOutput,&tgtcursor->BTNNAMES,
1336 tgtcursor->cchBTNNAMES*sizeof(WCHAR));
1337 break;
1338 case CSR_BUTTONMAP:
1339 rc = CopyTabletData(lpOutput,tgtcursor->BUTTONMAP,
1340 sizeof(BYTE)*32);
1341 break;
1342 case CSR_SYSBTNMAP:
1343 rc = CopyTabletData(lpOutput,tgtcursor->SYSBTNMAP,
1344 sizeof(BYTE)*32);
1345 break;
1346 case CSR_NPBTNMARKS:
1347 rc = CopyTabletData(lpOutput,tgtcursor->NPBTNMARKS,
1348 sizeof(UINT)*2);
1349 break;
1350 case CSR_NPBUTTON:
1351 rc = CopyTabletData(lpOutput,&tgtcursor->NPBUTTON,
1352 sizeof(BYTE));
1353 break;
1354 case CSR_NPRESPONSE:
1355 FIXME("Not returning CSR_NPRESPONSE correctly\n");
1356 rc = 0;
1357 break;
1358 case CSR_TPBUTTON:
1359 rc = CopyTabletData(lpOutput,&tgtcursor->TPBUTTON,
1360 sizeof(BYTE));
1361 break;
1362 case CSR_TPBTNMARKS:
1363 rc = CopyTabletData(lpOutput,tgtcursor->TPBTNMARKS,
1364 sizeof(UINT)*2);
1365 break;
1366 case CSR_TPRESPONSE:
1367 FIXME("Not returning CSR_TPRESPONSE correctly\n");
1368 rc = 0;
1369 break;
1370 case CSR_PHYSID:
1372 DWORD id;
1373 id = tgtcursor->PHYSID;
1374 rc = CopyTabletData(lpOutput,&id,sizeof(DWORD));
1376 break;
1377 case CSR_MODE:
1378 rc = CopyTabletData(lpOutput,&tgtcursor->MODE,sizeof(UINT));
1379 break;
1380 case CSR_MINPKTDATA:
1381 rc = CopyTabletData(lpOutput,&tgtcursor->MINPKTDATA,
1382 sizeof(UINT));
1383 break;
1384 case CSR_MINBUTTONS:
1385 rc = CopyTabletData(lpOutput,&tgtcursor->MINBUTTONS,
1386 sizeof(UINT));
1387 break;
1388 case CSR_CAPABILITIES:
1389 rc = CopyTabletData(lpOutput,&tgtcursor->CAPABILITIES,
1390 sizeof(UINT));
1391 break;
1392 case CSR_TYPE:
1393 rc = CopyTabletData(lpOutput,&tgtcursor->TYPE,
1394 sizeof(UINT));
1395 break;
1396 default:
1397 FIXME("WTI_CURSORS unhandled index %i\n",nIndex);
1398 rc = 0;
1401 break;
1402 case WTI_DEVICES:
1403 switch (nIndex)
1405 case DVC_NAME:
1406 rc = CopyTabletData(lpOutput,gSysDevice.NAME,
1407 (strlenW(gSysDevice.NAME)+1) * sizeof(WCHAR));
1408 break;
1409 case DVC_HARDWARE:
1410 rc = CopyTabletData(lpOutput,&gSysDevice.HARDWARE,
1411 sizeof(UINT));
1412 break;
1413 case DVC_NCSRTYPES:
1414 rc = CopyTabletData(lpOutput,&gSysDevice.NCSRTYPES,
1415 sizeof(UINT));
1416 break;
1417 case DVC_FIRSTCSR:
1418 rc = CopyTabletData(lpOutput,&gSysDevice.FIRSTCSR,
1419 sizeof(UINT));
1420 break;
1421 case DVC_PKTRATE:
1422 rc = CopyTabletData(lpOutput,&gSysDevice.PKTRATE,
1423 sizeof(UINT));
1424 break;
1425 case DVC_PKTDATA:
1426 rc = CopyTabletData(lpOutput,&gSysDevice.PKTDATA,
1427 sizeof(WTPKT));
1428 break;
1429 case DVC_PKTMODE:
1430 rc = CopyTabletData(lpOutput,&gSysDevice.PKTMODE,
1431 sizeof(WTPKT));
1432 break;
1433 case DVC_CSRDATA:
1434 rc = CopyTabletData(lpOutput,&gSysDevice.CSRDATA,
1435 sizeof(WTPKT));
1436 break;
1437 case DVC_XMARGIN:
1438 rc = CopyTabletData(lpOutput,&gSysDevice.XMARGIN,
1439 sizeof(INT));
1440 break;
1441 case DVC_YMARGIN:
1442 rc = CopyTabletData(lpOutput,&gSysDevice.YMARGIN,
1443 sizeof(INT));
1444 break;
1445 case DVC_ZMARGIN:
1446 rc = 0; /* unsupported */
1448 rc = CopyTabletData(lpOutput,&gSysDevice.ZMARGIN,
1449 sizeof(INT));
1451 break;
1452 case DVC_X:
1453 rc = CopyTabletData(lpOutput,&gSysDevice.X,
1454 sizeof(AXIS));
1455 break;
1456 case DVC_Y:
1457 rc = CopyTabletData(lpOutput,&gSysDevice.Y,
1458 sizeof(AXIS));
1459 break;
1460 case DVC_Z:
1461 rc = 0; /* unsupported */
1463 rc = CopyTabletData(lpOutput,&gSysDevice.Z,
1464 sizeof(AXIS));
1466 break;
1467 case DVC_NPRESSURE:
1468 rc = CopyTabletData(lpOutput,&gSysDevice.NPRESSURE,
1469 sizeof(AXIS));
1470 break;
1471 case DVC_TPRESSURE:
1472 rc = 0; /* unsupported */
1474 rc = CopyTabletData(lpOutput,&gSysDevice.TPRESSURE,
1475 sizeof(AXIS));
1477 break;
1478 case DVC_ORIENTATION:
1479 rc = CopyTabletData(lpOutput,gSysDevice.ORIENTATION,
1480 sizeof(AXIS)*3);
1481 break;
1482 case DVC_ROTATION:
1483 rc = 0; /* unsupported */
1485 rc = CopyTabletData(lpOutput,&gSysDevice.ROTATION,
1486 sizeof(AXIS)*3);
1488 break;
1489 case DVC_PNPID:
1490 rc = CopyTabletData(lpOutput,gSysDevice.PNPID,
1491 (strlenW(gSysDevice.PNPID)+1)*sizeof(WCHAR));
1492 break;
1493 default:
1494 FIXME("WTI_DEVICES unhandled index %i\n",nIndex);
1495 rc = 0;
1497 break;
1498 default:
1499 FIXME("Unhandled Category %i\n",wCategory);
1501 return rc;
1504 #else /* SONAME_LIBXI */
1506 /***********************************************************************
1507 * AttachEventQueueToTablet (X11DRV.@)
1509 int CDECL X11DRV_AttachEventQueueToTablet(HWND hOwner)
1511 return 0;
1514 /***********************************************************************
1515 * GetCurrentPacket (X11DRV.@)
1517 int CDECL X11DRV_GetCurrentPacket(LPWTPACKET packet)
1519 return 0;
1522 /***********************************************************************
1523 * LoadTabletInfo (X11DRV.@)
1525 BOOL CDECL X11DRV_LoadTabletInfo(HWND hwnddefault)
1527 return FALSE;
1530 /***********************************************************************
1531 * WTInfoW (X11DRV.@)
1533 UINT CDECL X11DRV_WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
1535 return 0;
1538 #endif /* SONAME_LIBXI */