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
22 #include "wine/port.h"
31 #include "wine/library.h"
32 #include "wine/unicode.h"
33 #include "wine/debug.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
47 /* whether the cursor is currently connected. */
49 /* a bit mask indicating the packet data items supported when this
50 * cursor is connected.
53 /* the number of buttons on this cursor. */
55 /* the number of bits of raw button data returned by the hardware.*/
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.
64 /* a 32 byte array of logical button numbers, one for each physical
68 /* a 32 byte array of button action codes, one for each logical
72 /* the physical button number of the button that is controlled by normal
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.
81 /* an array of UINTs describing the pressure response curve for normal
85 /* the physical button number of the button that is controlled by
86 * tangential pressure.
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.
94 /* an array of UINTs describing the pressure response curve for
95 * tangential pressure.
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
106 /* the cursor mode number of this cursor type, if this cursor type has
107 * the CRC_MULTIMODE capability.
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.
114 /* the minimum number of buttons of physical cursors in the cursor type,
115 * if this cursor type has the CRC_AGGREGATE capability.
118 /* flags indicating cursor capabilities, as defined below:
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
125 Indicates this cursor type describes several physical cursors
126 that cannot be distinguished by software.
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.
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.
144 /* flags indicating hardware and driver capabilities, as defined
147 Indicates that the display and digitizer share the same surface.
149 Indicates that the cursor must be in physical contact with the
150 device to report position.
152 Indicates that device can generate events when the cursor is
153 entering and leaving the physical detection range.
155 Indicates that device can uniquely identify the active cursor in
159 /* the number of supported cursor types.*/
161 /* the first cursor type number for the device. */
163 /* the maximum packet report rate in Hertz. */
165 /* a bit mask indicating which packet data items are always available.*/
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.
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.
179 /* the size of tablet context margins in tablet native coordinates, in
180 * the x, y, and z directions, respectively.
185 /* the tablet's range and resolution capabilities, in the x, y, and z
186 * axes, respectively.
190 /* the tablet's range and resolution capabilities, for the normal and
191 * tangential pressure inputs, respectively.
194 /* a 3-element array describing the tablet's orientation range and
195 * resolution capabilities.
198 /* a 3-element array describing the tablet's rotation range and
199 * resolution capabilities.
201 WCHAR PNPID[WT_MAX_NAME_LEN];
202 /* a null-terminated string containing the devices Plug and Play ID.*/
203 } WTI_DEVICES_INFO, *LPWTI_DEVICES_INFO;
206 /***********************************************************************
207 * WACOM WINTAB EXTENSIONS TO SUPPORT CSR_TYPE
208 * In Wintab 1.2, a CSR_TYPE feature was added. This adds the
209 * ability to return a type of cursor on a tablet.
210 * Unfortunately, we cannot get the cursor type directly from X,
211 * and it is not specified directly anywhere. So we virtualize
212 * the type here. (This is unfortunate, the kernel module has
213 * the exact type, but we have no way of getting that module to
214 * pass us that type).
217 #define CSR_TYPE_PEN 0x822
218 #define CSR_TYPE_ERASER 0x82a
219 #define CSR_TYPE_MOUSE_2D 0x007
220 #define CSR_TYPE_MOUSE_4D 0x094
223 typedef struct tagWTPACKET {
234 UINT pkNormalPressure;
235 UINT pkTangentPressure;
236 ORIENTATION pkOrientation;
237 ROTATION pkRotation; /* 1.1 */
238 } WTPACKET, *LPWTPACKET;
243 #include <X11/Xlib.h>
244 #include <X11/extensions/XInput.h>
246 static int motion_type;
247 static int button_press_type;
248 static int button_release_type;
249 static int key_press_type;
250 static int key_release_type;
251 static int proximity_in_type;
252 static int proximity_out_type;
254 static HWND hwndTabletDefault;
255 static WTPACKET gMsgPacket;
256 static DWORD gSerial;
257 static INT button_state[10];
261 static LOGCONTEXTW gSysContext;
262 static WTI_DEVICES_INFO gSysDevice;
263 static WTI_CURSORS_INFO gSysCursor[CURSORMAX];
264 static INT gNumCursors;
268 static void *xinput_handle;
270 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
271 MAKE_FUNCPTR(XListInputDevices)
272 MAKE_FUNCPTR(XFreeDeviceList)
273 MAKE_FUNCPTR(XOpenDevice)
274 MAKE_FUNCPTR(XQueryDeviceState)
275 MAKE_FUNCPTR(XGetDeviceButtonMapping)
276 MAKE_FUNCPTR(XCloseDevice)
277 MAKE_FUNCPTR(XSelectExtensionEvent)
278 MAKE_FUNCPTR(XFreeDeviceState)
281 static INT X11DRV_XInput_Init(void)
283 xinput_handle = wine_dlopen(SONAME_LIBXI, RTLD_NOW, NULL, 0);
286 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xinput_handle, #f, NULL, 0)) == NULL) goto sym_not_found;
287 LOAD_FUNCPTR(XListInputDevices)
288 LOAD_FUNCPTR(XFreeDeviceList)
289 LOAD_FUNCPTR(XOpenDevice)
290 LOAD_FUNCPTR(XGetDeviceButtonMapping)
291 LOAD_FUNCPTR(XCloseDevice)
292 LOAD_FUNCPTR(XSelectExtensionEvent)
293 LOAD_FUNCPTR(XQueryDeviceState)
294 LOAD_FUNCPTR(XFreeDeviceState)
302 static int Tablet_ErrorHandler(Display *dpy, XErrorEvent *event, void* arg)
307 static int find_cursor_by_type(int cursor_type, int exclude)
310 for (i = 0; i < gNumCursors; i++)
312 if (gSysCursor[i].TYPE == cursor_type)
318 static void swap_cursors(int a, int b)
320 WTI_CURSORS_INFO temp;
321 temp = gSysCursor[a];
322 gSysCursor[a] = gSysCursor[b];
323 gSysCursor[b] = temp;
326 /* Adobe Photoshop 7.0 relies on the eraser being cursor #2 or #5, and it assumes the stylus is 1.
327 ** If the X configuration is not set up that way, make it
329 static void Tablet_FixupCursors(void)
331 if (gNumCursors >= 1)
332 if (gSysCursor[1].TYPE != CSR_TYPE_PEN)
335 stylus = find_cursor_by_type(CSR_TYPE_PEN, 1);
338 swap_cursors(1, stylus);
339 TRACE("Swapped cursor %d with stylus slot (1) for compatibility with older programs\n", stylus);
343 if (gNumCursors >= 2)
344 if (gSysCursor[2].TYPE != CSR_TYPE_ERASER)
347 eraser = find_cursor_by_type(CSR_TYPE_ERASER, 2);
350 swap_cursors(2, eraser);
351 TRACE("Swapped cursor %d with eraser slot (2) for compatibility with older programs\n", eraser);
356 static void trace_axes(XValuatorInfoPtr val)
361 for (i = 0, axis = val->axes ; i < val->num_axes; i++, axis++)
362 TRACE(" Axis %d: [resolution %d|min_value %d|max_value %d]\n", i, axis->resolution, axis->min_value, axis->max_value);
365 BOOL match_token(const char *haystack, const char *needle)
368 for (p = haystack; *p; )
370 while (*p && isspace(*p))
375 for (q = needle; *q && *p && tolower(*p) == tolower(*q); q++)
377 if (! *q && (isspace(*p) || !*p))
380 while (*p && ! isspace(*p))
386 /* Determining if an X device is a Tablet style device is an imperfect science.
387 ** We rely on common conventions around device names as well as the type reported
388 ** by Wacom tablets. This code will likely need to be expanded for alternate tablet types
391 static BOOL is_tablet_cursor(const char *name, const char *type)
394 static const char *tablet_cursor_whitelist[] = {
406 for (i=0; tablet_cursor_whitelist[i] != NULL; i++) {
407 if (name && match_token(name, tablet_cursor_whitelist[i]))
409 if (type && match_token(type, tablet_cursor_whitelist[i]))
415 static BOOL is_stylus(const char *name, const char *type)
418 static const char* tablet_stylus_whitelist[] = {
424 for (i=0; tablet_stylus_whitelist[i] != NULL; i++) {
425 if (name && match_token(name, tablet_stylus_whitelist[i]))
427 if (type && match_token(type, tablet_stylus_whitelist[i]))
434 static BOOL is_eraser(const char *name, const char *type)
436 if (name && match_token(name, "eraser"))
438 if (type && match_token(type, "eraser"))
444 /***********************************************************************
445 * X11DRV_LoadTabletInfo (X11DRV.@)
447 void X11DRV_LoadTabletInfo(HWND hwnddefault)
449 const WCHAR SZ_CONTEXT_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','C','o','n','t','e','x','t',0};
450 const WCHAR SZ_DEVICE_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','D','e','v','i','c','e',0};
451 const WCHAR SZ_NON_PLUGINPLAY[] = {'n','o','n','-','p','l','u','g','i','n','p','l','a','y',0};
453 struct x11drv_thread_data *data = x11drv_thread_data();
457 XDeviceInfo *devices;
458 XDeviceInfo *target = NULL;
459 BOOL axis_read_complete= FALSE;
462 XButtonInfoPtr Button;
463 XValuatorInfoPtr Val;
468 if (!X11DRV_XInput_Init())
470 ERR("Unable to initialize the XInput library.\n");
474 hwndTabletDefault = hwnddefault;
476 /* Do base initialization */
477 strcpyW(gSysContext.lcName, SZ_CONTEXT_NAME);
478 strcpyW(gSysDevice.NAME, SZ_DEVICE_NAME);
480 gSysContext.lcOptions = CXO_SYSTEM;
481 gSysContext.lcLocks = CXL_INSIZE | CXL_INASPECT | CXL_MARGIN |
482 CXL_SENSITIVITY | CXL_SYSOUT;
484 gSysContext.lcMsgBase= WT_DEFBASE;
485 gSysContext.lcDevice = 0;
486 gSysContext.lcPktData =
487 PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
488 PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
489 gSysContext.lcMoveMask=
490 PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
491 gSysContext.lcStatus = CXS_ONTOP;
492 gSysContext.lcPktRate = 100;
493 gSysContext.lcBtnDnMask = 0xffffffff;
494 gSysContext.lcBtnUpMask = 0xffffffff;
495 gSysContext.lcSensX = 65536;
496 gSysContext.lcSensY = 65536;
497 gSysContext.lcSensX = 65536;
498 gSysContext.lcSensZ = 65536;
499 gSysContext.lcSysSensX= 65536;
500 gSysContext.lcSysSensY= 65536;
502 /* Device Defaults */
503 gSysDevice.HARDWARE = HWC_HARDPROX|HWC_PHYSID_CURSORS;
504 gSysDevice.FIRSTCSR= 0;
505 gSysDevice.PKTRATE = 100;
507 PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR |
508 PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION;
509 strcpyW(gSysDevice.PNPID, SZ_NON_PLUGINPLAY);
514 devices = pXListInputDevices(data->display, &num_devices);
517 WARN("XInput Extensions reported as not avalable\n");
521 TRACE("XListInputDevices reports %d devices\n", num_devices);
522 for (loop=0; loop < num_devices; loop++)
525 char *device_type = devices[loop].type ? XGetAtomName(data->display, devices[loop].type) : NULL;
526 LPWTI_CURSORS_INFO cursor;
528 TRACE("Device %i: [id %d|name %s|type %s|num_classes %d|use %d]\n",
529 loop, (int) devices[loop].id, devices[loop].name, device_type ? device_type : "",
530 devices[loop].num_classes, devices[loop].use );
532 switch (devices[loop].use)
534 case IsXExtensionDevice:
535 #ifdef IsXExtensionPointer
536 case IsXExtensionPointer:
538 TRACE("Is XExtension%s\n", (devices[loop].use == IsXExtensionDevice)? "Device":"Pointer");
540 target = &devices[loop];
541 cursor = &gSysCursor[cursor_target];
543 if (strlen(target->name) >= WT_MAX_NAME_LEN)
545 ERR("Input device '%s' name too long - skipping\n", wine_dbgstr_a(target->name));
550 X11DRV_expect_error(data->display, Tablet_ErrorHandler, NULL);
551 opendevice = pXOpenDevice(data->display,target->id);
552 if (!X11DRV_check_error() && opendevice)
554 unsigned char map[32];
558 X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
559 cursor->BUTTONS = pXGetDeviceButtonMapping(data->display, opendevice, map, 32);
560 if (X11DRV_check_error() || cursor->BUTTONS <= 0)
562 TRACE("No buttons, Non Tablet Device\n");
563 pXCloseDevice(data->display, opendevice);
568 for (i=0; i< cursor->BUTTONS; i++,shft++)
570 cursor->BUTTONMAP[i] = map[i];
571 cursor->SYSBTNMAP[i] = (1<<shft);
573 pXCloseDevice(data->display, opendevice);
577 WARN("Unable to open device %s\n",target->name);
581 MultiByteToWideChar(CP_UNIXCP, 0, target->name, -1, cursor->NAME, WT_MAX_NAME_LEN);
583 if (! is_tablet_cursor(target->name, device_type))
585 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",
586 loop, devices[loop].name, device_type ? device_type : "");
592 cursor->PKTDATA = PK_TIME | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y |
593 PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE |
596 cursor->PHYSID = target->id;
597 cursor->NPBUTTON = 1;
598 cursor->NPBTNMARKS[0] = 0 ;
599 cursor->NPBTNMARKS[1] = 1 ;
600 cursor->CAPABILITIES = CRC_MULTIMODE;
601 if (is_stylus(target->name, device_type))
602 cursor->TYPE = CSR_TYPE_PEN;
603 if (is_eraser(target->name, device_type))
604 cursor->TYPE = CSR_TYPE_ERASER;
607 any = target->inputclassinfo;
609 for (class_loop = 0; class_loop < target->num_classes; class_loop++)
615 Val = (XValuatorInfoPtr) any;
616 TRACE(" ValidatorInput %d: [class %d|length %d|num_axes %d|mode %d|motion_buffer %ld]\n",
617 class_loop, (int) Val->class, Val->length, Val->num_axes, Val->mode, Val->motion_buffer);
618 if (TRACE_ON(wintab32))
621 /* FIXME: This is imperfect; we compute our devices capabilities based upon the
622 ** first pen type device we find. However, a more correct implementation
623 ** would require acquiring a wide variety of tablets and running through
624 ** the various inputs to see what the values are. Odds are that a
625 ** more 'correct' algorithm would condense to this one anyway.
627 if (!axis_read_complete && cursor->TYPE == CSR_TYPE_PEN)
629 Axis = (XAxisInfoPtr) ((char *) Val + sizeof
632 if (Val->num_axes>=1)
635 gSysDevice.X.axMin = Axis->min_value;
636 gSysDevice.X.axMax= Axis->max_value;
637 gSysDevice.X.axUnits = TU_INCHES;
638 gSysDevice.X.axResolution = Axis->resolution;
639 gSysContext.lcInOrgX = Axis->min_value;
640 gSysContext.lcSysOrgX = Axis->min_value;
641 gSysContext.lcInExtX = Axis->max_value;
642 gSysContext.lcSysExtX = Axis->max_value;
645 if (Val->num_axes>=2)
648 gSysDevice.Y.axMin = Axis->min_value;
649 gSysDevice.Y.axMax= Axis->max_value;
650 gSysDevice.Y.axUnits = TU_INCHES;
651 gSysDevice.Y.axResolution = Axis->resolution;
652 gSysContext.lcInOrgY = Axis->min_value;
653 gSysContext.lcSysOrgY = Axis->min_value;
654 gSysContext.lcInExtY = Axis->max_value;
655 gSysContext.lcSysExtY = Axis->max_value;
658 if (Val->num_axes>=3)
660 /* Axis 3 is Normal Pressure */
661 gSysDevice.NPRESSURE.axMin = Axis->min_value;
662 gSysDevice.NPRESSURE.axMax= Axis->max_value;
663 gSysDevice.NPRESSURE.axUnits = TU_INCHES;
664 gSysDevice.NPRESSURE.axResolution =
668 if (Val->num_axes >= 5)
670 /* Axis 4 and 5 are X and Y tilt */
671 XAxisInfoPtr XAxis = Axis;
673 if (max (abs(Axis->max_value),
674 abs(XAxis->max_value)))
676 gSysDevice.ORIENTATION[0].axMin = 0;
677 gSysDevice.ORIENTATION[0].axMax = 3600;
678 gSysDevice.ORIENTATION[0].axUnits = TU_CIRCLE;
679 gSysDevice.ORIENTATION[0].axResolution
681 gSysDevice.ORIENTATION[1].axMin = -1000;
682 gSysDevice.ORIENTATION[1].axMax = 1000;
683 gSysDevice.ORIENTATION[1].axUnits = TU_CIRCLE;
684 gSysDevice.ORIENTATION[1].axResolution
689 axis_read_complete = TRUE;
698 Button = (XButtonInfoPtr) any;
699 TRACE(" ButtonInput %d: [class %d|length %d|num_buttons %d]\n",
700 class_loop, (int) Button->class, Button->length, Button->num_buttons);
701 cursor->BTNNAMES = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*cchBuf);
702 for (i = 0; i < cursor->BUTTONS; i++)
704 /* FIXME - these names are probably incorrect */
705 int cch = strlenW(cursor->NAME) + 1;
706 while (cch > cchBuf - cchPos - 1) /* we want one extra byte for the last NUL */
709 cursor->BTNNAMES = HeapReAlloc(GetProcessHeap(), 0, cursor->BTNNAMES, sizeof(WCHAR)*cchBuf);
712 strcpyW(cursor->BTNNAMES + cchPos, cursor->NAME);
715 cursor->BTNNAMES[cchPos++] = 0;
716 cursor->BTNNAMES = HeapReAlloc(GetProcessHeap(), 0, cursor->BTNNAMES, sizeof(WCHAR)*cchPos);
717 cursor->cchBTNNAMES = cchPos;
721 any = (XAnyClassPtr) ((char*) any + any->length);
728 pXFreeDeviceList(devices);
730 if (axis_read_complete)
732 gSysDevice.NCSRTYPES = cursor_target+1;
733 gNumCursors = cursor_target+1;
734 Tablet_FixupCursors();
737 WARN("Did not find a valid stylus cursor with >= 5 axes, returning 0 valid devices.\n");
742 static int figure_deg(int x, int y)
746 angle = atan2((float)y, (float)x);
751 return (0.5 + (angle * 1800.0 / M_PI));
754 static int get_button_state(int curnum)
756 return button_state[curnum];
759 static void set_button_state(int curnum, XID deviceid)
761 struct x11drv_thread_data *data = x11drv_thread_data();
769 device = pXOpenDevice(data->display,deviceid);
770 state = pXQueryDeviceState(data->display,device);
775 for (loop = 0; loop < state->num_classes; loop++)
777 if (class->class == ButtonClass)
780 XButtonState *button_state = (XButtonState*)class;
781 for (loop2 = 0; loop2 < button_state->num_buttons; loop2++)
783 if (button_state->buttons[loop2 / 8] & (1 << (loop2 % 8)))
789 class = (XInputClass *) ((char *) class + class->length);
792 pXFreeDeviceState(state);
794 button_state[curnum] = rc;
797 static int cursor_from_device(DWORD deviceid, LPWTI_CURSORS_INFO *cursorp)
800 for (i = 0; i < gNumCursors; i++)
801 if (gSysCursor[i].PHYSID == deviceid)
803 *cursorp = &gSysCursor[i];
807 ERR("Could not map device id %d to a cursor\n", (int) deviceid);
811 static void motion_event( HWND hwnd, XEvent *event )
813 XDeviceMotionEvent *motion = (XDeviceMotionEvent *)event;
814 LPWTI_CURSORS_INFO cursor;
815 int curnum = cursor_from_device(motion->deviceid, &cursor);
819 memset(&gMsgPacket,0,sizeof(WTPACKET));
821 TRACE("Received tablet motion event (%p); device id %d, cursor num %d\n",hwnd, (int) motion->deviceid, curnum);
823 /* Set cursor to inverted if cursor is the eraser */
824 gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
825 gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(motion->time);
826 gMsgPacket.pkSerialNumber = gSerial++;
827 gMsgPacket.pkCursor = curnum;
828 gMsgPacket.pkX = motion->axis_data[0];
829 gMsgPacket.pkY = motion->axis_data[1];
830 gMsgPacket.pkOrientation.orAzimuth = figure_deg(motion->axis_data[3],motion->axis_data[4]);
831 gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max
832 (abs(motion->axis_data[3]),
833 abs(motion->axis_data[4])))
834 * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
835 gMsgPacket.pkNormalPressure = motion->axis_data[2];
836 gMsgPacket.pkButtons = get_button_state(curnum);
837 SendMessageW(hwndTabletDefault,WT_PACKET,0,(LPARAM)hwnd);
840 static void button_event( HWND hwnd, XEvent *event )
842 XDeviceButtonEvent *button = (XDeviceButtonEvent *) event;
843 LPWTI_CURSORS_INFO cursor;
844 int curnum = cursor_from_device(button->deviceid, &cursor);
848 memset(&gMsgPacket,0,sizeof(WTPACKET));
850 TRACE("Received tablet button %s event\n", (event->type == button_press_type)?"press":"release");
852 /* Set cursor to inverted if cursor is the eraser */
853 gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
854 set_button_state(curnum, button->deviceid);
855 gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(button->time);
856 gMsgPacket.pkSerialNumber = gSerial++;
857 gMsgPacket.pkCursor = curnum;
858 gMsgPacket.pkX = button->axis_data[0];
859 gMsgPacket.pkY = button->axis_data[1];
860 gMsgPacket.pkOrientation.orAzimuth = figure_deg(button->axis_data[3],button->axis_data[4]);
861 gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(button->axis_data[3]),
862 abs(button->axis_data[4])))
863 * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
864 gMsgPacket.pkNormalPressure = button->axis_data[2];
865 gMsgPacket.pkButtons = get_button_state(curnum);
866 SendMessageW(hwndTabletDefault,WT_PACKET,0,(LPARAM)hwnd);
869 static void key_event( HWND hwnd, XEvent *event )
871 if (event->type == key_press_type)
872 FIXME("Received tablet key press event\n");
874 FIXME("Received tablet key release event\n");
877 static void proximity_event( HWND hwnd, XEvent *event )
879 XProximityNotifyEvent *proximity = (XProximityNotifyEvent *) event;
880 LPWTI_CURSORS_INFO cursor;
881 int curnum = cursor_from_device(proximity->deviceid, &cursor);
885 memset(&gMsgPacket,0,sizeof(WTPACKET));
887 TRACE("Received tablet proximity event\n");
888 /* Set cursor to inverted if cursor is the eraser */
889 gMsgPacket.pkStatus = (cursor->TYPE == CSR_TYPE_ERASER ? TPS_INVERT:0);
890 gMsgPacket.pkStatus |= (event->type==proximity_out_type)?TPS_PROXIMITY:0;
891 gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(proximity->time);
892 gMsgPacket.pkSerialNumber = gSerial++;
893 gMsgPacket.pkCursor = curnum;
894 gMsgPacket.pkX = proximity->axis_data[0];
895 gMsgPacket.pkY = proximity->axis_data[1];
896 gMsgPacket.pkOrientation.orAzimuth = figure_deg(proximity->axis_data[3],proximity->axis_data[4]);
897 gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(proximity->axis_data[3]),
898 abs(proximity->axis_data[4])))
899 * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
900 gMsgPacket.pkNormalPressure = proximity->axis_data[2];
901 gMsgPacket.pkButtons = get_button_state(curnum);
903 SendMessageW(hwndTabletDefault, WT_PROXIMITY, (event->type == proximity_in_type), (LPARAM)hwnd);
906 /***********************************************************************
907 * X11DRV_AttachEventQueueToTablet (X11DRV.@)
909 int X11DRV_AttachEventQueueToTablet(HWND hOwner)
911 struct x11drv_thread_data *data = x11drv_thread_data();
915 XDeviceInfo *devices;
916 XDeviceInfo *target = NULL;
918 XEventClass event_list[7];
919 Window win = X11DRV_get_whole_window( hOwner );
923 TRACE("Creating context for window %p (%lx) %i cursors\n", hOwner, win, gNumCursors);
926 devices = pXListInputDevices(data->display, &num_devices);
928 X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL);
929 for (cur_loop=0; cur_loop < gNumCursors; cur_loop++)
931 char cursorNameA[WT_MAX_NAME_LEN];
934 /* the cursor name fits in the buffer because too long names are skipped */
935 WideCharToMultiByte(CP_UNIXCP, 0, gSysCursor[cur_loop].NAME, -1, cursorNameA, WT_MAX_NAME_LEN, NULL, NULL);
936 for (loop=0; loop < num_devices; loop ++)
937 if (strcmp(devices[loop].name, cursorNameA) == 0)
938 target = &devices[loop];
940 TRACE("Opening cursor %i id %i\n",cur_loop,(INT)target->id);
942 the_device = pXOpenDevice(data->display, target->id);
946 WARN("Unable to Open device\n");
950 if (the_device->num_classes > 0)
952 DeviceKeyPress(the_device, key_press_type, event_list[event_number]);
953 if (key_press_type) event_number++;
954 DeviceKeyRelease(the_device, key_release_type, event_list[event_number]);
955 if (key_release_type) event_number++;
956 DeviceButtonPress(the_device, button_press_type, event_list[event_number]);
957 if (button_press_type) event_number++;
958 DeviceButtonRelease(the_device, button_release_type, event_list[event_number]);
959 if (button_release_type) event_number++;
960 DeviceMotionNotify(the_device, motion_type, event_list[event_number]);
961 if (motion_type) event_number++;
962 ProximityIn(the_device, proximity_in_type, event_list[event_number]);
963 if (proximity_in_type) event_number++;
964 ProximityOut(the_device, proximity_out_type, event_list[event_number]);
965 if (proximity_out_type) event_number++;
967 if (key_press_type) X11DRV_register_event_handler( key_press_type, key_event );
968 if (key_release_type) X11DRV_register_event_handler( key_release_type, key_event );
969 if (button_press_type) X11DRV_register_event_handler( button_press_type, button_event );
970 if (button_release_type) X11DRV_register_event_handler( button_release_type, button_event );
971 if (motion_type) X11DRV_register_event_handler( motion_type, motion_event );
972 if (proximity_in_type) X11DRV_register_event_handler( proximity_in_type, proximity_event );
973 if (proximity_out_type) X11DRV_register_event_handler( proximity_out_type, proximity_event );
975 pXSelectExtensionEvent(data->display, win, event_list, event_number);
978 XSync(data->display, False);
979 X11DRV_check_error();
981 if (NULL != devices) pXFreeDeviceList(devices);
986 /***********************************************************************
987 * X11DRV_GetCurrentPacket (X11DRV.@)
989 int X11DRV_GetCurrentPacket(LPWTPACKET packet)
991 *packet = gMsgPacket;
996 static inline int CopyTabletData(LPVOID target, LPCVOID src, INT size)
999 * It is valid to call CopyTabletData with NULL.
1000 * This handles the WTInfo() case where lpOutput is null.
1003 memcpy(target,src,size);
1007 /***********************************************************************
1008 * X11DRV_WTInfoW (X11DRV.@)
1010 UINT X11DRV_WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
1013 * It is valid to call WTInfoA with lpOutput == NULL, as per standard.
1014 * lpOutput == NULL signifies the user only wishes
1015 * to find the size of the data.
1017 * From now on use CopyTabletData to fill lpOutput. memcpy will break
1021 LPWTI_CURSORS_INFO tgtcursor;
1022 TRACE("(%u, %u, %p)\n", wCategory, nIndex, lpOutput);
1027 /* return largest necessary buffer */
1028 TRACE("%i cursors\n",gNumCursors);
1031 FIXME("Return proper size\n");
1042 static const WCHAR driver[] = {'W','i','n','e',' ','W','i','n','t','a','b',' ','1','.','1',0};
1043 rc = CopyTabletData(lpOutput, driver, (strlenW(driver) + 1) * sizeof(WCHAR));
1046 case IFC_SPECVERSION:
1047 version = (0x01) | (0x01 << 8);
1048 rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
1050 case IFC_IMPLVERSION:
1051 version = (0x00) | (0x01 << 8);
1052 rc = CopyTabletData(lpOutput, &version,sizeof(WORD));
1056 rc = CopyTabletData(lpOutput, &num,sizeof(num));
1060 rc = CopyTabletData(lpOutput, &num,sizeof(num));
1063 FIXME("WTI_INTERFACE unhandled index %i\n",nIndex);
1069 case WTI_DEFCONTEXT:
1073 rc = CopyTabletData(lpOutput, &gSysContext,
1074 sizeof(LOGCONTEXTW));
1077 rc = CopyTabletData(lpOutput, &gSysContext.lcName,
1078 (strlenW(gSysContext.lcName)+1) * sizeof(WCHAR));
1081 rc = CopyTabletData(lpOutput, &gSysContext.lcOptions,
1085 rc = CopyTabletData(lpOutput, &gSysContext.lcStatus,
1089 rc= CopyTabletData (lpOutput, &gSysContext.lcLocks,
1093 rc = CopyTabletData(lpOutput, &gSysContext.lcMsgBase,
1097 rc = CopyTabletData(lpOutput, &gSysContext.lcDevice,
1101 rc = CopyTabletData(lpOutput, &gSysContext.lcPktRate,
1105 rc = CopyTabletData(lpOutput, &gSysContext.lcPktData,
1109 rc = CopyTabletData(lpOutput, &gSysContext.lcPktMode,
1113 rc = CopyTabletData(lpOutput, &gSysContext.lcMoveMask,
1117 rc = CopyTabletData(lpOutput, &gSysContext.lcBtnDnMask,
1121 rc = CopyTabletData(lpOutput, &gSysContext.lcBtnUpMask,
1125 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgX,
1129 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgY,
1133 rc = CopyTabletData(lpOutput, &gSysContext.lcInOrgZ,
1137 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtX,
1141 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtY,
1145 rc = CopyTabletData(lpOutput, &gSysContext.lcInExtZ,
1149 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgX,
1153 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgY,
1157 rc = CopyTabletData(lpOutput, &gSysContext.lcOutOrgZ,
1161 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtX,
1165 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtY,
1169 rc = CopyTabletData(lpOutput, &gSysContext.lcOutExtZ,
1173 rc = CopyTabletData(lpOutput, &gSysContext.lcSensX,
1177 rc = CopyTabletData(lpOutput, &gSysContext.lcSensY,
1181 rc = CopyTabletData(lpOutput, &gSysContext.lcSensZ,
1185 rc = CopyTabletData(lpOutput, &gSysContext.lcSysMode,
1189 rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgX,
1193 rc = CopyTabletData(lpOutput, &gSysContext.lcSysOrgY,
1197 rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtX,
1201 rc = CopyTabletData(lpOutput, &gSysContext.lcSysExtY,
1205 rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensX,
1209 rc = CopyTabletData(lpOutput, &gSysContext.lcSysSensY,
1213 FIXME("WTI_DEFSYSCTX unhandled index %i\n",nIndex);
1227 if (wCategory - WTI_CURSORS >= gNumCursors)
1230 WARN("Requested cursor information for nonexistent cursor %d; only %d cursors\n",
1231 wCategory - WTI_CURSORS, gNumCursors);
1235 tgtcursor = &gSysCursor[wCategory - WTI_CURSORS];
1239 rc = CopyTabletData(lpOutput, &tgtcursor->NAME,
1240 (strlenW(tgtcursor->NAME)+1) * sizeof(WCHAR));
1243 rc = CopyTabletData(lpOutput,&tgtcursor->ACTIVE,
1247 rc = CopyTabletData(lpOutput,&tgtcursor->PKTDATA,
1251 rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONS,
1254 case CSR_BUTTONBITS:
1255 rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONBITS,
1259 FIXME("Button Names not returned correctly\n");
1260 rc = CopyTabletData(lpOutput,&tgtcursor->BTNNAMES,
1261 tgtcursor->cchBTNNAMES*sizeof(WCHAR));
1264 rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONMAP,
1268 rc = CopyTabletData(lpOutput,&tgtcursor->SYSBTNMAP,
1271 case CSR_NPBTNMARKS:
1272 rc = CopyTabletData(lpOutput,&tgtcursor->NPBTNMARKS,
1276 rc = CopyTabletData(lpOutput,&tgtcursor->NPBUTTON,
1279 case CSR_NPRESPONSE:
1280 FIXME("Not returning CSR_NPRESPONSE correctly\n");
1284 rc = CopyTabletData(lpOutput,&tgtcursor->TPBUTTON,
1287 case CSR_TPBTNMARKS:
1288 rc = CopyTabletData(lpOutput,&tgtcursor->TPBTNMARKS,
1291 case CSR_TPRESPONSE:
1292 FIXME("Not returning CSR_TPRESPONSE correctly\n");
1298 id = tgtcursor->PHYSID;
1299 rc = CopyTabletData(lpOutput,&id,sizeof(DWORD));
1303 rc = CopyTabletData(lpOutput,&tgtcursor->MODE,sizeof(UINT));
1305 case CSR_MINPKTDATA:
1306 rc = CopyTabletData(lpOutput,&tgtcursor->MINPKTDATA,
1309 case CSR_MINBUTTONS:
1310 rc = CopyTabletData(lpOutput,&tgtcursor->MINBUTTONS,
1313 case CSR_CAPABILITIES:
1314 rc = CopyTabletData(lpOutput,&tgtcursor->CAPABILITIES,
1318 rc = CopyTabletData(lpOutput,&tgtcursor->TYPE,
1322 FIXME("WTI_CURSORS unhandled index %i\n",nIndex);
1331 rc = CopyTabletData(lpOutput,gSysDevice.NAME,
1332 (strlenW(gSysDevice.NAME)+1) * sizeof(WCHAR));
1335 rc = CopyTabletData(lpOutput,&gSysDevice.HARDWARE,
1339 rc = CopyTabletData(lpOutput,&gSysDevice.NCSRTYPES,
1343 rc = CopyTabletData(lpOutput,&gSysDevice.FIRSTCSR,
1347 rc = CopyTabletData(lpOutput,&gSysDevice.PKTRATE,
1351 rc = CopyTabletData(lpOutput,&gSysDevice.PKTDATA,
1355 rc = CopyTabletData(lpOutput,&gSysDevice.PKTMODE,
1359 rc = CopyTabletData(lpOutput,&gSysDevice.CSRDATA,
1363 rc = CopyTabletData(lpOutput,&gSysDevice.XMARGIN,
1367 rc = CopyTabletData(lpOutput,&gSysDevice.YMARGIN,
1371 rc = 0; /* unsupported */
1373 rc = CopyTabletData(lpOutput,&gSysDevice.ZMARGIN,
1378 rc = CopyTabletData(lpOutput,&gSysDevice.X,
1382 rc = CopyTabletData(lpOutput,&gSysDevice.Y,
1386 rc = 0; /* unsupported */
1388 rc = CopyTabletData(lpOutput,&gSysDevice.Z,
1393 rc = CopyTabletData(lpOutput,&gSysDevice.NPRESSURE,
1397 rc = 0; /* unsupported */
1399 rc = CopyTabletData(lpOutput,&gSysDevice.TPRESSURE,
1403 case DVC_ORIENTATION:
1404 rc = CopyTabletData(lpOutput,&gSysDevice.ORIENTATION,
1408 rc = 0; /* unsupported */
1410 rc = CopyTabletData(lpOutput,&gSysDevice.ROTATION,
1415 rc = CopyTabletData(lpOutput,gSysDevice.PNPID,
1416 (strlenW(gSysDevice.PNPID)+1)*sizeof(WCHAR));
1419 FIXME("WTI_DEVICES unhandled index %i\n",nIndex);
1424 FIXME("Unhandled Category %i\n",wCategory);
1429 #else /* SONAME_LIBXI */
1431 /***********************************************************************
1432 * AttachEventQueueToTablet (X11DRV.@)
1434 int X11DRV_AttachEventQueueToTablet(HWND hOwner)
1439 /***********************************************************************
1440 * GetCurrentPacket (X11DRV.@)
1442 int X11DRV_GetCurrentPacket(LPWTPACKET packet)
1447 /***********************************************************************
1448 * LoadTabletInfo (X11DRV.@)
1450 void X11DRV_LoadTabletInfo(HWND hwnddefault)
1454 /***********************************************************************
1455 * WTInfoW (X11DRV.@)
1457 UINT X11DRV_WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput)
1462 #endif /* SONAME_LIBXI */