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
)
417 if (name
&& match_token(name
, "stylus"))
419 if (type
&& match_token(type
, "stylus"))
424 static BOOL
is_eraser(const char *name
, const char *type
)
426 if (name
&& match_token(name
, "eraser"))
428 if (type
&& match_token(type
, "eraser"))
434 /***********************************************************************
435 * X11DRV_LoadTabletInfo (X11DRV.@)
437 void X11DRV_LoadTabletInfo(HWND hwnddefault
)
439 const WCHAR SZ_CONTEXT_NAME
[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','C','o','n','t','e','x','t',0};
440 const WCHAR SZ_DEVICE_NAME
[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','D','e','v','i','c','e',0};
441 const WCHAR SZ_NON_PLUGINPLAY
[] = {'n','o','n','-','p','l','u','g','i','n','p','l','a','y',0};
443 struct x11drv_thread_data
*data
= x11drv_thread_data();
447 XDeviceInfo
*devices
;
448 XDeviceInfo
*target
= NULL
;
449 BOOL axis_read_complete
= FALSE
;
452 XButtonInfoPtr Button
;
453 XValuatorInfoPtr Val
;
458 if (!X11DRV_XInput_Init())
460 ERR("Unable to initialize the XInput library.\n");
464 hwndTabletDefault
= hwnddefault
;
466 /* Do base initialization */
467 strcpyW(gSysContext
.lcName
, SZ_CONTEXT_NAME
);
468 strcpyW(gSysDevice
.NAME
, SZ_DEVICE_NAME
);
470 gSysContext
.lcOptions
= CXO_SYSTEM
;
471 gSysContext
.lcLocks
= CXL_INSIZE
| CXL_INASPECT
| CXL_MARGIN
|
472 CXL_SENSITIVITY
| CXL_SYSOUT
;
474 gSysContext
.lcMsgBase
= WT_DEFBASE
;
475 gSysContext
.lcDevice
= 0;
476 gSysContext
.lcPktData
=
477 PK_CONTEXT
| PK_STATUS
| PK_SERIAL_NUMBER
| PK_TIME
| PK_CURSOR
|
478 PK_BUTTONS
| PK_X
| PK_Y
| PK_NORMAL_PRESSURE
| PK_ORIENTATION
;
479 gSysContext
.lcMoveMask
=
480 PK_BUTTONS
| PK_X
| PK_Y
| PK_NORMAL_PRESSURE
| PK_ORIENTATION
;
481 gSysContext
.lcStatus
= CXS_ONTOP
;
482 gSysContext
.lcPktRate
= 100;
483 gSysContext
.lcBtnDnMask
= 0xffffffff;
484 gSysContext
.lcBtnUpMask
= 0xffffffff;
485 gSysContext
.lcSensX
= 65536;
486 gSysContext
.lcSensY
= 65536;
487 gSysContext
.lcSensX
= 65536;
488 gSysContext
.lcSensZ
= 65536;
489 gSysContext
.lcSysSensX
= 65536;
490 gSysContext
.lcSysSensY
= 65536;
492 /* Device Defaults */
493 gSysDevice
.HARDWARE
= HWC_HARDPROX
|HWC_PHYSID_CURSORS
;
494 gSysDevice
.FIRSTCSR
= 0;
495 gSysDevice
.PKTRATE
= 100;
497 PK_CONTEXT
| PK_STATUS
| PK_SERIAL_NUMBER
| PK_TIME
| PK_CURSOR
|
498 PK_BUTTONS
| PK_X
| PK_Y
| PK_NORMAL_PRESSURE
| PK_ORIENTATION
;
499 strcpyW(gSysDevice
.PNPID
, SZ_NON_PLUGINPLAY
);
504 devices
= pXListInputDevices(data
->display
, &num_devices
);
507 WARN("XInput Extensions reported as not avalable\n");
511 TRACE("XListInputDevices reports %d devices\n", num_devices
);
512 for (loop
=0; loop
< num_devices
; loop
++)
515 char *device_type
= devices
[loop
].type
? XGetAtomName(data
->display
, devices
[loop
].type
) : NULL
;
517 TRACE("Device %i: [id %d|name %s|type %s|num_classes %d|use %s]\n",
518 loop
, (int) devices
[loop
].id
, devices
[loop
].name
, device_type
? device_type
: "",
519 devices
[loop
].num_classes
,
520 devices
[loop
].use
== IsXKeyboard
? "IsXKeyboard" :
521 devices
[loop
].use
== IsXPointer
? "IsXPointer" :
522 devices
[loop
].use
== IsXExtensionDevice
? "IsXExtensionDevice" :
526 if (devices
[loop
].use
== IsXExtensionDevice
)
528 LPWTI_CURSORS_INFO cursor
;
530 TRACE("Is Extension Device\n");
532 target
= &devices
[loop
];
533 cursor
= &gSysCursor
[cursor_target
];
535 if (strlen(target
->name
) >= WT_MAX_NAME_LEN
)
537 ERR("Input device '%s' name too long - skipping\n", wine_dbgstr_a(target
->name
));
543 X11DRV_expect_error(data
->display
, Tablet_ErrorHandler
, NULL
);
544 opendevice
= pXOpenDevice(data
->display
,target
->id
);
545 if (!X11DRV_check_error() && opendevice
)
547 unsigned char map
[32];
551 X11DRV_expect_error(data
->display
,Tablet_ErrorHandler
,NULL
);
552 cursor
->BUTTONS
= pXGetDeviceButtonMapping(data
->display
, opendevice
, map
, 32);
553 if (X11DRV_check_error() || cursor
->BUTTONS
<= 0)
555 TRACE("No buttons, Non Tablet Device\n");
556 pXCloseDevice(data
->display
, opendevice
);
562 for (i
=0; i
< cursor
->BUTTONS
; i
++,shft
++)
564 cursor
->BUTTONMAP
[i
] = map
[i
];
565 cursor
->SYSBTNMAP
[i
] = (1<<shft
);
567 pXCloseDevice(data
->display
, opendevice
);
571 WARN("Unable to open device %s\n",target
->name
);
576 MultiByteToWideChar(CP_UNIXCP
, 0, target
->name
, -1, cursor
->NAME
, WT_MAX_NAME_LEN
);
578 if (! is_tablet_cursor(target
->name
, device_type
))
580 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",
581 loop
, devices
[loop
].name
, device_type
? device_type
: "");
588 cursor
->PKTDATA
= PK_TIME
| PK_CURSOR
| PK_BUTTONS
| PK_X
| PK_Y
|
589 PK_NORMAL_PRESSURE
| PK_TANGENT_PRESSURE
|
592 cursor
->PHYSID
= target
->id
;
593 cursor
->NPBUTTON
= 1;
594 cursor
->NPBTNMARKS
[0] = 0 ;
595 cursor
->NPBTNMARKS
[1] = 1 ;
596 cursor
->CAPABILITIES
= CRC_MULTIMODE
;
597 if (is_stylus(target
->name
, device_type
))
598 cursor
->TYPE
= CSR_TYPE_PEN
;
599 if (is_eraser(target
->name
, device_type
))
600 cursor
->TYPE
= CSR_TYPE_ERASER
;
603 any
= target
->inputclassinfo
;
605 for (class_loop
= 0; class_loop
< target
->num_classes
; class_loop
++)
611 Val
= (XValuatorInfoPtr
) any
;
612 TRACE(" ValidatorInput %d: [class %d|length %d|num_axes %d|mode %d|motion_buffer %ld]\n",
613 class_loop
, (int) Val
->class, Val
->length
, Val
->num_axes
, Val
->mode
, Val
->motion_buffer
);
614 if (TRACE_ON(wintab32
))
617 /* FIXME: This is imperfect; we compute our devices capabilities based upon the
618 ** first pen type device we find. However, a more correct implementation
619 ** would require acquiring a wide variety of tablets and running through
620 ** the various inputs to see what the values are. Odds are that a
621 ** more 'correct' algorithm would condense to this one anyway.
623 if (!axis_read_complete
&& Val
->num_axes
>= 5 && cursor
->TYPE
== CSR_TYPE_PEN
)
625 Axis
= (XAxisInfoPtr
) ((char *) Val
+ sizeof
628 if (Val
->num_axes
>=1)
631 gSysDevice
.X
.axMin
= Axis
->min_value
;
632 gSysDevice
.X
.axMax
= Axis
->max_value
;
633 gSysDevice
.X
.axUnits
= TU_INCHES
;
634 gSysDevice
.X
.axResolution
= Axis
->resolution
;
635 gSysContext
.lcInOrgX
= Axis
->min_value
;
636 gSysContext
.lcSysOrgX
= Axis
->min_value
;
637 gSysContext
.lcInExtX
= Axis
->max_value
;
638 gSysContext
.lcSysExtX
= Axis
->max_value
;
641 if (Val
->num_axes
>=2)
644 gSysDevice
.Y
.axMin
= Axis
->min_value
;
645 gSysDevice
.Y
.axMax
= Axis
->max_value
;
646 gSysDevice
.Y
.axUnits
= TU_INCHES
;
647 gSysDevice
.Y
.axResolution
= Axis
->resolution
;
648 gSysContext
.lcInOrgY
= Axis
->min_value
;
649 gSysContext
.lcSysOrgY
= Axis
->min_value
;
650 gSysContext
.lcInExtY
= Axis
->max_value
;
651 gSysContext
.lcSysExtY
= Axis
->max_value
;
654 if (Val
->num_axes
>=3)
656 /* Axis 3 is Normal Pressure */
657 gSysDevice
.NPRESSURE
.axMin
= Axis
->min_value
;
658 gSysDevice
.NPRESSURE
.axMax
= Axis
->max_value
;
659 gSysDevice
.NPRESSURE
.axUnits
= TU_INCHES
;
660 gSysDevice
.NPRESSURE
.axResolution
=
664 if (Val
->num_axes
>= 5)
666 /* Axis 4 and 5 are X and Y tilt */
667 XAxisInfoPtr XAxis
= Axis
;
669 if (max (abs(Axis
->max_value
),
670 abs(XAxis
->max_value
)))
672 gSysDevice
.ORIENTATION
[0].axMin
= 0;
673 gSysDevice
.ORIENTATION
[0].axMax
= 3600;
674 gSysDevice
.ORIENTATION
[0].axUnits
= TU_CIRCLE
;
675 gSysDevice
.ORIENTATION
[0].axResolution
677 gSysDevice
.ORIENTATION
[1].axMin
= -1000;
678 gSysDevice
.ORIENTATION
[1].axMax
= 1000;
679 gSysDevice
.ORIENTATION
[1].axUnits
= TU_CIRCLE
;
680 gSysDevice
.ORIENTATION
[1].axResolution
685 axis_read_complete
= TRUE
;
694 Button
= (XButtonInfoPtr
) any
;
695 TRACE(" ButtonInput %d: [class %d|length %d|num_buttons %d]\n",
696 class_loop
, (int) Button
->class, Button
->length
, Button
->num_buttons
);
697 cursor
->BTNNAMES
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*cchBuf
);
698 for (i
= 0; i
< cursor
->BUTTONS
; i
++)
700 /* FIXME - these names are probably incorrect */
701 int cch
= strlenW(cursor
->NAME
) + 1;
702 while (cch
> cchBuf
- cchPos
- 1) /* we want one extra byte for the last NUL */
705 cursor
->BTNNAMES
= HeapReAlloc(GetProcessHeap(), 0, cursor
->BTNNAMES
, sizeof(WCHAR
)*cchBuf
);
708 strcpyW(cursor
->BTNNAMES
+ cchPos
, cursor
->NAME
);
711 cursor
->BTNNAMES
[cchPos
++] = 0;
712 cursor
->BTNNAMES
= HeapReAlloc(GetProcessHeap(), 0, cursor
->BTNNAMES
, sizeof(WCHAR
)*cchPos
);
713 cursor
->cchBTNNAMES
= cchPos
;
717 any
= (XAnyClassPtr
) ((char*) any
+ any
->length
);
724 pXFreeDeviceList(devices
);
726 if (axis_read_complete
)
728 gSysDevice
.NCSRTYPES
= cursor_target
+1;
729 gNumCursors
= cursor_target
+1;
730 Tablet_FixupCursors();
733 WARN("Did not find a valid stylus cursor with >= 5 axes, returning 0 valid devices.\n");
738 static int figure_deg(int x
, int y
)
742 angle
= atan2((float)y
, (float)x
);
747 return (0.5 + (angle
* 1800.0 / M_PI
));
750 static int get_button_state(int curnum
)
752 return button_state
[curnum
];
755 static void set_button_state(int curnum
, XID deviceid
)
757 struct x11drv_thread_data
*data
= x11drv_thread_data();
765 device
= pXOpenDevice(data
->display
,deviceid
);
766 state
= pXQueryDeviceState(data
->display
,device
);
771 for (loop
= 0; loop
< state
->num_classes
; loop
++)
773 if (class->class == ButtonClass
)
776 XButtonState
*button_state
= (XButtonState
*)class;
777 for (loop2
= 0; loop2
< button_state
->num_buttons
; loop2
++)
779 if (button_state
->buttons
[loop2
/ 8] & (1 << (loop2
% 8)))
785 class = (XInputClass
*) ((char *) class + class->length
);
788 pXFreeDeviceState(state
);
790 button_state
[curnum
] = rc
;
793 static int cursor_from_device(DWORD deviceid
, LPWTI_CURSORS_INFO
*cursorp
)
796 for (i
= 0; i
< gNumCursors
; i
++)
797 if (gSysCursor
[i
].PHYSID
== deviceid
)
799 *cursorp
= &gSysCursor
[i
];
803 ERR("Could not map device id %d to a cursor\n", (int) deviceid
);
807 static void motion_event( HWND hwnd
, XEvent
*event
)
809 XDeviceMotionEvent
*motion
= (XDeviceMotionEvent
*)event
;
810 LPWTI_CURSORS_INFO cursor
;
811 int curnum
= cursor_from_device(motion
->deviceid
, &cursor
);
815 memset(&gMsgPacket
,0,sizeof(WTPACKET
));
817 TRACE("Received tablet motion event (%p); device id %d, cursor num %d\n",hwnd
, (int) motion
->deviceid
, curnum
);
819 /* Set cursor to inverted if cursor is the eraser */
820 gMsgPacket
.pkStatus
= (cursor
->TYPE
== CSR_TYPE_ERASER
? TPS_INVERT
:0);
821 gMsgPacket
.pkTime
= EVENT_x11_time_to_win32_time(motion
->time
);
822 gMsgPacket
.pkSerialNumber
= gSerial
++;
823 gMsgPacket
.pkCursor
= curnum
;
824 gMsgPacket
.pkX
= motion
->axis_data
[0];
825 gMsgPacket
.pkY
= motion
->axis_data
[1];
826 gMsgPacket
.pkOrientation
.orAzimuth
= figure_deg(motion
->axis_data
[3],motion
->axis_data
[4]);
827 gMsgPacket
.pkOrientation
.orAltitude
= ((1000 - 15 * max
828 (abs(motion
->axis_data
[3]),
829 abs(motion
->axis_data
[4])))
830 * (gMsgPacket
.pkStatus
& TPS_INVERT
?-1:1));
831 gMsgPacket
.pkNormalPressure
= motion
->axis_data
[2];
832 gMsgPacket
.pkButtons
= get_button_state(curnum
);
833 SendMessageW(hwndTabletDefault
,WT_PACKET
,0,(LPARAM
)hwnd
);
836 static void button_event( HWND hwnd
, XEvent
*event
)
838 XDeviceButtonEvent
*button
= (XDeviceButtonEvent
*) event
;
839 LPWTI_CURSORS_INFO cursor
;
840 int curnum
= cursor_from_device(button
->deviceid
, &cursor
);
844 memset(&gMsgPacket
,0,sizeof(WTPACKET
));
846 TRACE("Received tablet button %s event\n", (event
->type
== button_press_type
)?"press":"release");
848 /* Set cursor to inverted if cursor is the eraser */
849 gMsgPacket
.pkStatus
= (cursor
->TYPE
== CSR_TYPE_ERASER
? TPS_INVERT
:0);
850 set_button_state(curnum
, button
->deviceid
);
851 gMsgPacket
.pkTime
= EVENT_x11_time_to_win32_time(button
->time
);
852 gMsgPacket
.pkSerialNumber
= gSerial
++;
853 gMsgPacket
.pkCursor
= curnum
;
854 gMsgPacket
.pkX
= button
->axis_data
[0];
855 gMsgPacket
.pkY
= button
->axis_data
[1];
856 gMsgPacket
.pkOrientation
.orAzimuth
= figure_deg(button
->axis_data
[3],button
->axis_data
[4]);
857 gMsgPacket
.pkOrientation
.orAltitude
= ((1000 - 15 * max(abs(button
->axis_data
[3]),
858 abs(button
->axis_data
[4])))
859 * (gMsgPacket
.pkStatus
& TPS_INVERT
?-1:1));
860 gMsgPacket
.pkNormalPressure
= button
->axis_data
[2];
861 gMsgPacket
.pkButtons
= get_button_state(curnum
);
862 SendMessageW(hwndTabletDefault
,WT_PACKET
,0,(LPARAM
)hwnd
);
865 static void key_event( HWND hwnd
, XEvent
*event
)
867 if (event
->type
== key_press_type
)
868 FIXME("Received tablet key press event\n");
870 FIXME("Received tablet key release event\n");
873 static void proximity_event( HWND hwnd
, XEvent
*event
)
875 XProximityNotifyEvent
*proximity
= (XProximityNotifyEvent
*) event
;
876 LPWTI_CURSORS_INFO cursor
;
877 int curnum
= cursor_from_device(proximity
->deviceid
, &cursor
);
881 memset(&gMsgPacket
,0,sizeof(WTPACKET
));
883 TRACE("Received tablet proximity event\n");
884 /* Set cursor to inverted if cursor is the eraser */
885 gMsgPacket
.pkStatus
= (cursor
->TYPE
== CSR_TYPE_ERASER
? TPS_INVERT
:0);
886 gMsgPacket
.pkStatus
|= (event
->type
==proximity_out_type
)?TPS_PROXIMITY
:0;
887 gMsgPacket
.pkTime
= EVENT_x11_time_to_win32_time(proximity
->time
);
888 gMsgPacket
.pkSerialNumber
= gSerial
++;
889 gMsgPacket
.pkCursor
= curnum
;
890 gMsgPacket
.pkX
= proximity
->axis_data
[0];
891 gMsgPacket
.pkY
= proximity
->axis_data
[1];
892 gMsgPacket
.pkOrientation
.orAzimuth
= figure_deg(proximity
->axis_data
[3],proximity
->axis_data
[4]);
893 gMsgPacket
.pkOrientation
.orAltitude
= ((1000 - 15 * max(abs(proximity
->axis_data
[3]),
894 abs(proximity
->axis_data
[4])))
895 * (gMsgPacket
.pkStatus
& TPS_INVERT
?-1:1));
896 gMsgPacket
.pkNormalPressure
= proximity
->axis_data
[2];
897 gMsgPacket
.pkButtons
= get_button_state(curnum
);
899 SendMessageW(hwndTabletDefault
, WT_PROXIMITY
, (event
->type
== proximity_in_type
), (LPARAM
)hwnd
);
902 /***********************************************************************
903 * X11DRV_AttachEventQueueToTablet (X11DRV.@)
905 int X11DRV_AttachEventQueueToTablet(HWND hOwner
)
907 struct x11drv_thread_data
*data
= x11drv_thread_data();
911 XDeviceInfo
*devices
;
912 XDeviceInfo
*target
= NULL
;
914 XEventClass event_list
[7];
915 Window win
= X11DRV_get_whole_window( hOwner
);
919 TRACE("Creating context for window %p (%lx) %i cursors\n", hOwner
, win
, gNumCursors
);
922 devices
= pXListInputDevices(data
->display
, &num_devices
);
924 X11DRV_expect_error(data
->display
,Tablet_ErrorHandler
,NULL
);
925 for (cur_loop
=0; cur_loop
< gNumCursors
; cur_loop
++)
927 char cursorNameA
[WT_MAX_NAME_LEN
];
930 /* the cursor name fits in the buffer because too long names are skipped */
931 WideCharToMultiByte(CP_UNIXCP
, 0, gSysCursor
[cur_loop
].NAME
, -1, cursorNameA
, WT_MAX_NAME_LEN
, NULL
, NULL
);
932 for (loop
=0; loop
< num_devices
; loop
++)
933 if (strcmp(devices
[loop
].name
, cursorNameA
) == 0)
934 target
= &devices
[loop
];
936 TRACE("Opening cursor %i id %i\n",cur_loop
,(INT
)target
->id
);
938 the_device
= pXOpenDevice(data
->display
, target
->id
);
942 WARN("Unable to Open device\n");
946 if (the_device
->num_classes
> 0)
948 DeviceKeyPress(the_device
, key_press_type
, event_list
[event_number
]);
949 if (key_press_type
) event_number
++;
950 DeviceKeyRelease(the_device
, key_release_type
, event_list
[event_number
]);
951 if (key_release_type
) event_number
++;
952 DeviceButtonPress(the_device
, button_press_type
, event_list
[event_number
]);
953 if (button_press_type
) event_number
++;
954 DeviceButtonRelease(the_device
, button_release_type
, event_list
[event_number
]);
955 if (button_release_type
) event_number
++;
956 DeviceMotionNotify(the_device
, motion_type
, event_list
[event_number
]);
957 if (motion_type
) event_number
++;
958 ProximityIn(the_device
, proximity_in_type
, event_list
[event_number
]);
959 if (proximity_in_type
) event_number
++;
960 ProximityOut(the_device
, proximity_out_type
, event_list
[event_number
]);
961 if (proximity_out_type
) event_number
++;
963 if (key_press_type
) X11DRV_register_event_handler( key_press_type
, key_event
);
964 if (key_release_type
) X11DRV_register_event_handler( key_release_type
, key_event
);
965 if (button_press_type
) X11DRV_register_event_handler( button_press_type
, button_event
);
966 if (button_release_type
) X11DRV_register_event_handler( button_release_type
, button_event
);
967 if (motion_type
) X11DRV_register_event_handler( motion_type
, motion_event
);
968 if (proximity_in_type
) X11DRV_register_event_handler( proximity_in_type
, proximity_event
);
969 if (proximity_out_type
) X11DRV_register_event_handler( proximity_out_type
, proximity_event
);
971 pXSelectExtensionEvent(data
->display
, win
, event_list
, event_number
);
974 XSync(data
->display
, False
);
975 X11DRV_check_error();
977 if (NULL
!= devices
) pXFreeDeviceList(devices
);
982 /***********************************************************************
983 * X11DRV_GetCurrentPacket (X11DRV.@)
985 int X11DRV_GetCurrentPacket(LPWTPACKET packet
)
987 *packet
= gMsgPacket
;
992 static inline int CopyTabletData(LPVOID target
, LPCVOID src
, INT size
)
995 * It is valid to call CopyTabletData with NULL.
996 * This handles the WTInfo() case where lpOutput is null.
999 memcpy(target
,src
,size
);
1003 /***********************************************************************
1004 * X11DRV_WTInfoW (X11DRV.@)
1006 UINT
X11DRV_WTInfoW(UINT wCategory
, UINT nIndex
, LPVOID lpOutput
)
1009 * It is valid to call WTInfoA with lpOutput == NULL, as per standard.
1010 * lpOutput == NULL signifies the user only wishes
1011 * to find the size of the data.
1013 * From now on use CopyTabletData to fill lpOutput. memcpy will break
1017 LPWTI_CURSORS_INFO tgtcursor
;
1018 TRACE("(%u, %u, %p)\n", wCategory
, nIndex
, lpOutput
);
1023 /* return largest necessary buffer */
1024 TRACE("%i cursors\n",gNumCursors
);
1027 FIXME("Return proper size\n");
1038 static const WCHAR driver
[] = {'W','i','n','e',' ','W','i','n','t','a','b',' ','1','.','1',0};
1039 rc
= CopyTabletData(lpOutput
, driver
, (strlenW(driver
) + 1) * sizeof(WCHAR
));
1042 case IFC_SPECVERSION
:
1043 version
= (0x01) | (0x01 << 8);
1044 rc
= CopyTabletData(lpOutput
, &version
,sizeof(WORD
));
1046 case IFC_IMPLVERSION
:
1047 version
= (0x00) | (0x01 << 8);
1048 rc
= CopyTabletData(lpOutput
, &version
,sizeof(WORD
));
1052 rc
= CopyTabletData(lpOutput
, &num
,sizeof(num
));
1056 rc
= CopyTabletData(lpOutput
, &num
,sizeof(num
));
1059 FIXME("WTI_INTERFACE unhandled index %i\n",nIndex
);
1065 case WTI_DEFCONTEXT
:
1069 rc
= CopyTabletData(lpOutput
, &gSysContext
,
1070 sizeof(LOGCONTEXTW
));
1073 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcName
,
1074 (strlenW(gSysContext
.lcName
)+1) * sizeof(WCHAR
));
1077 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOptions
,
1081 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcStatus
,
1085 rc
= CopyTabletData (lpOutput
, &gSysContext
.lcLocks
,
1089 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcMsgBase
,
1093 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcDevice
,
1097 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcPktRate
,
1101 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcPktData
,
1105 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcPktMode
,
1109 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcMoveMask
,
1113 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcBtnDnMask
,
1117 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcBtnUpMask
,
1121 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInOrgX
,
1125 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInOrgY
,
1129 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInOrgZ
,
1133 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInExtX
,
1137 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInExtY
,
1141 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInExtZ
,
1145 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutOrgX
,
1149 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutOrgY
,
1153 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutOrgZ
,
1157 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutExtX
,
1161 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutExtY
,
1165 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutExtZ
,
1169 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSensX
,
1173 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSensY
,
1177 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSensZ
,
1181 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysMode
,
1185 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysOrgX
,
1189 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysOrgY
,
1193 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysExtX
,
1197 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysExtY
,
1201 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysSensX
,
1205 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysSensY
,
1209 FIXME("WTI_DEFSYSCTX unhandled index %i\n",nIndex
);
1223 if (wCategory
- WTI_CURSORS
>= gNumCursors
)
1226 WARN("Requested cursor information for nonexistent cursor %d; only %d cursors\n",
1227 wCategory
- WTI_CURSORS
, gNumCursors
);
1231 tgtcursor
= &gSysCursor
[wCategory
- WTI_CURSORS
];
1235 rc
= CopyTabletData(lpOutput
, &tgtcursor
->NAME
,
1236 (strlenW(tgtcursor
->NAME
)+1) * sizeof(WCHAR
));
1239 rc
= CopyTabletData(lpOutput
,&tgtcursor
->ACTIVE
,
1243 rc
= CopyTabletData(lpOutput
,&tgtcursor
->PKTDATA
,
1247 rc
= CopyTabletData(lpOutput
,&tgtcursor
->BUTTONS
,
1250 case CSR_BUTTONBITS
:
1251 rc
= CopyTabletData(lpOutput
,&tgtcursor
->BUTTONBITS
,
1255 FIXME("Button Names not returned correctly\n");
1256 rc
= CopyTabletData(lpOutput
,&tgtcursor
->BTNNAMES
,
1257 tgtcursor
->cchBTNNAMES
*sizeof(WCHAR
));
1260 rc
= CopyTabletData(lpOutput
,&tgtcursor
->BUTTONMAP
,
1264 rc
= CopyTabletData(lpOutput
,&tgtcursor
->SYSBTNMAP
,
1267 case CSR_NPBTNMARKS
:
1268 rc
= CopyTabletData(lpOutput
,&tgtcursor
->NPBTNMARKS
,
1272 rc
= CopyTabletData(lpOutput
,&tgtcursor
->NPBUTTON
,
1275 case CSR_NPRESPONSE
:
1276 FIXME("Not returning CSR_NPRESPONSE correctly\n");
1280 rc
= CopyTabletData(lpOutput
,&tgtcursor
->TPBUTTON
,
1283 case CSR_TPBTNMARKS
:
1284 rc
= CopyTabletData(lpOutput
,&tgtcursor
->TPBTNMARKS
,
1287 case CSR_TPRESPONSE
:
1288 FIXME("Not returning CSR_TPRESPONSE correctly\n");
1294 id
= tgtcursor
->PHYSID
;
1295 rc
= CopyTabletData(lpOutput
,&id
,sizeof(DWORD
));
1299 rc
= CopyTabletData(lpOutput
,&tgtcursor
->MODE
,sizeof(UINT
));
1301 case CSR_MINPKTDATA
:
1302 rc
= CopyTabletData(lpOutput
,&tgtcursor
->MINPKTDATA
,
1305 case CSR_MINBUTTONS
:
1306 rc
= CopyTabletData(lpOutput
,&tgtcursor
->MINBUTTONS
,
1309 case CSR_CAPABILITIES
:
1310 rc
= CopyTabletData(lpOutput
,&tgtcursor
->CAPABILITIES
,
1314 rc
= CopyTabletData(lpOutput
,&tgtcursor
->TYPE
,
1318 FIXME("WTI_CURSORS unhandled index %i\n",nIndex
);
1327 rc
= CopyTabletData(lpOutput
,gSysDevice
.NAME
,
1328 (strlenW(gSysDevice
.NAME
)+1) * sizeof(WCHAR
));
1331 rc
= CopyTabletData(lpOutput
,&gSysDevice
.HARDWARE
,
1335 rc
= CopyTabletData(lpOutput
,&gSysDevice
.NCSRTYPES
,
1339 rc
= CopyTabletData(lpOutput
,&gSysDevice
.FIRSTCSR
,
1343 rc
= CopyTabletData(lpOutput
,&gSysDevice
.PKTRATE
,
1347 rc
= CopyTabletData(lpOutput
,&gSysDevice
.PKTDATA
,
1351 rc
= CopyTabletData(lpOutput
,&gSysDevice
.PKTMODE
,
1355 rc
= CopyTabletData(lpOutput
,&gSysDevice
.CSRDATA
,
1359 rc
= CopyTabletData(lpOutput
,&gSysDevice
.XMARGIN
,
1363 rc
= CopyTabletData(lpOutput
,&gSysDevice
.YMARGIN
,
1367 rc
= 0; /* unsupported */
1369 rc = CopyTabletData(lpOutput,&gSysDevice.ZMARGIN,
1374 rc
= CopyTabletData(lpOutput
,&gSysDevice
.X
,
1378 rc
= CopyTabletData(lpOutput
,&gSysDevice
.Y
,
1382 rc
= 0; /* unsupported */
1384 rc = CopyTabletData(lpOutput,&gSysDevice.Z,
1389 rc
= CopyTabletData(lpOutput
,&gSysDevice
.NPRESSURE
,
1393 rc
= 0; /* unsupported */
1395 rc = CopyTabletData(lpOutput,&gSysDevice.TPRESSURE,
1399 case DVC_ORIENTATION
:
1400 rc
= CopyTabletData(lpOutput
,&gSysDevice
.ORIENTATION
,
1404 rc
= 0; /* unsupported */
1406 rc = CopyTabletData(lpOutput,&gSysDevice.ROTATION,
1411 rc
= CopyTabletData(lpOutput
,gSysDevice
.PNPID
,
1412 (strlenW(gSysDevice
.PNPID
)+1)*sizeof(WCHAR
));
1415 FIXME("WTI_DEVICES unhandled index %i\n",nIndex
);
1420 FIXME("Unhandled Category %i\n",wCategory
);
1425 #else /* SONAME_LIBXI */
1427 /***********************************************************************
1428 * AttachEventQueueToTablet (X11DRV.@)
1430 int X11DRV_AttachEventQueueToTablet(HWND hOwner
)
1435 /***********************************************************************
1436 * GetCurrentPacket (X11DRV.@)
1438 int X11DRV_GetCurrentPacket(LPWTPACKET packet
)
1443 /***********************************************************************
1444 * LoadTabletInfo (X11DRV.@)
1446 void X11DRV_LoadTabletInfo(HWND hwnddefault
)
1450 /***********************************************************************
1451 * WTInfoW (X11DRV.@)
1453 UINT
X11DRV_WTInfoW(UINT wCategory
, UINT nIndex
, LPVOID lpOutput
)
1458 #endif /* SONAME_LIBXI */