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 #define IS_TABLET_CURSOR(n, t) (is_wacom((n), (t)) || is_cursor((n), (t)) || is_stylus((n), (t)) || is_eraser((n), (t)) || is_pad((n), (t)))
393 static BOOL
is_wacom(const char *name
, const char *type
)
395 if (name
&& match_token(name
, "wacom"))
397 if (type
&& match_token(type
, "wacom"))
402 static BOOL
is_cursor(const char *name
, const char *type
)
404 if (name
&& match_token(name
, "cursor"))
406 if (type
&& match_token(type
, "cursor"))
411 static BOOL
is_stylus(const char *name
, const char *type
)
413 if (name
&& match_token(name
, "stylus"))
415 if (type
&& match_token(type
, "stylus"))
420 static BOOL
is_eraser(const char *name
, const char *type
)
422 if (name
&& match_token(name
, "eraser"))
424 if (type
&& match_token(type
, "eraser"))
429 static BOOL
is_pad(const char *name
, const char *type
)
431 if (name
&& match_token(name
, "pad"))
433 if (type
&& match_token(type
, "pad"))
439 /***********************************************************************
440 * X11DRV_LoadTabletInfo (X11DRV.@)
442 void X11DRV_LoadTabletInfo(HWND hwnddefault
)
444 const WCHAR SZ_CONTEXT_NAME
[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','C','o','n','t','e','x','t',0};
445 const WCHAR SZ_DEVICE_NAME
[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','D','e','v','i','c','e',0};
446 const WCHAR SZ_NON_PLUGINPLAY
[] = {'n','o','n','-','p','l','u','g','i','n','p','l','a','y',0};
448 struct x11drv_thread_data
*data
= x11drv_thread_data();
452 XDeviceInfo
*devices
;
453 XDeviceInfo
*target
= NULL
;
454 BOOL axis_read_complete
= FALSE
;
457 XButtonInfoPtr Button
;
458 XValuatorInfoPtr Val
;
463 if (!X11DRV_XInput_Init())
465 ERR("Unable to initialize the XInput library.\n");
469 hwndTabletDefault
= hwnddefault
;
471 /* Do base initialization */
472 strcpyW(gSysContext
.lcName
, SZ_CONTEXT_NAME
);
473 strcpyW(gSysDevice
.NAME
, SZ_DEVICE_NAME
);
475 gSysContext
.lcOptions
= CXO_SYSTEM
;
476 gSysContext
.lcLocks
= CXL_INSIZE
| CXL_INASPECT
| CXL_MARGIN
|
477 CXL_SENSITIVITY
| CXL_SYSOUT
;
479 gSysContext
.lcMsgBase
= WT_DEFBASE
;
480 gSysContext
.lcDevice
= 0;
481 gSysContext
.lcPktData
=
482 PK_CONTEXT
| PK_STATUS
| PK_SERIAL_NUMBER
| PK_TIME
| PK_CURSOR
|
483 PK_BUTTONS
| PK_X
| PK_Y
| PK_NORMAL_PRESSURE
| PK_ORIENTATION
;
484 gSysContext
.lcMoveMask
=
485 PK_BUTTONS
| PK_X
| PK_Y
| PK_NORMAL_PRESSURE
| PK_ORIENTATION
;
486 gSysContext
.lcStatus
= CXS_ONTOP
;
487 gSysContext
.lcPktRate
= 100;
488 gSysContext
.lcBtnDnMask
= 0xffffffff;
489 gSysContext
.lcBtnUpMask
= 0xffffffff;
490 gSysContext
.lcSensX
= 65536;
491 gSysContext
.lcSensY
= 65536;
492 gSysContext
.lcSensX
= 65536;
493 gSysContext
.lcSensZ
= 65536;
494 gSysContext
.lcSysSensX
= 65536;
495 gSysContext
.lcSysSensY
= 65536;
497 /* Device Defaults */
498 gSysDevice
.HARDWARE
= HWC_HARDPROX
|HWC_PHYSID_CURSORS
;
499 gSysDevice
.FIRSTCSR
= 0;
500 gSysDevice
.PKTRATE
= 100;
502 PK_CONTEXT
| PK_STATUS
| PK_SERIAL_NUMBER
| PK_TIME
| PK_CURSOR
|
503 PK_BUTTONS
| PK_X
| PK_Y
| PK_NORMAL_PRESSURE
| PK_ORIENTATION
;
504 strcpyW(gSysDevice
.PNPID
, SZ_NON_PLUGINPLAY
);
509 devices
= pXListInputDevices(data
->display
, &num_devices
);
512 WARN("XInput Extensions reported as not avalable\n");
516 TRACE("XListInputDevices reports %d devices\n", num_devices
);
517 for (loop
=0; loop
< num_devices
; loop
++)
520 char *device_type
= devices
[loop
].type
? XGetAtomName(data
->display
, devices
[loop
].type
) : NULL
;
522 TRACE("Device %i: [id %d|name %s|type %s|num_classes %d|use %s]\n",
523 loop
, (int) devices
[loop
].id
, devices
[loop
].name
, device_type
? device_type
: "",
524 devices
[loop
].num_classes
,
525 devices
[loop
].use
== IsXKeyboard
? "IsXKeyboard" :
526 devices
[loop
].use
== IsXPointer
? "IsXPointer" :
527 devices
[loop
].use
== IsXExtensionDevice
? "IsXExtensionDevice" :
531 if (devices
[loop
].use
== IsXExtensionDevice
)
533 LPWTI_CURSORS_INFO cursor
;
535 TRACE("Is Extension Device\n");
537 target
= &devices
[loop
];
538 cursor
= &gSysCursor
[cursor_target
];
540 if (strlen(target
->name
) >= WT_MAX_NAME_LEN
)
542 ERR("Input device '%s' name too long - skipping\n", wine_dbgstr_a(target
->name
));
548 X11DRV_expect_error(data
->display
, Tablet_ErrorHandler
, NULL
);
549 opendevice
= pXOpenDevice(data
->display
,target
->id
);
550 if (!X11DRV_check_error() && opendevice
)
552 unsigned char map
[32];
556 X11DRV_expect_error(data
->display
,Tablet_ErrorHandler
,NULL
);
557 cursor
->BUTTONS
= pXGetDeviceButtonMapping(data
->display
, opendevice
, map
, 32);
558 if (X11DRV_check_error() || cursor
->BUTTONS
<= 0)
560 TRACE("No buttons, Non Tablet Device\n");
561 pXCloseDevice(data
->display
, opendevice
);
567 for (i
=0; i
< cursor
->BUTTONS
; i
++,shft
++)
569 cursor
->BUTTONMAP
[i
] = map
[i
];
570 cursor
->SYSBTNMAP
[i
] = (1<<shft
);
572 pXCloseDevice(data
->display
, opendevice
);
576 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\n",
586 loop
, devices
[loop
].name
, device_type
? device_type
: "");
593 cursor
->PKTDATA
= PK_TIME
| PK_CURSOR
| PK_BUTTONS
| PK_X
| PK_Y
|
594 PK_NORMAL_PRESSURE
| PK_TANGENT_PRESSURE
|
597 cursor
->PHYSID
= target
->id
;
598 cursor
->NPBUTTON
= 1;
599 cursor
->NPBTNMARKS
[0] = 0 ;
600 cursor
->NPBTNMARKS
[1] = 1 ;
601 cursor
->CAPABILITIES
= CRC_MULTIMODE
;
602 if (is_stylus(target
->name
, device_type
))
603 cursor
->TYPE
= CSR_TYPE_PEN
;
604 if (is_eraser(target
->name
, device_type
))
605 cursor
->TYPE
= CSR_TYPE_ERASER
;
608 any
= target
->inputclassinfo
;
610 for (class_loop
= 0; class_loop
< target
->num_classes
; class_loop
++)
616 Val
= (XValuatorInfoPtr
) any
;
617 TRACE(" ValidatorInput %d: [class %d|length %d|num_axes %d|mode %d|motion_buffer %ld]\n",
618 class_loop
, (int) Val
->class, Val
->length
, Val
->num_axes
, Val
->mode
, Val
->motion_buffer
);
619 if (TRACE_ON(wintab32
))
622 /* FIXME: This is imperfect; we compute our devices capabilities based upon the
623 ** first pen type device we find. However, a more correct implementation
624 ** would require acquiring a wide variety of tablets and running through
625 ** the various inputs to see what the values are. Odds are that a
626 ** more 'correct' algorithm would condense to this one anyway.
628 if (!axis_read_complete
&& Val
->num_axes
>= 5 && cursor
->TYPE
== CSR_TYPE_PEN
)
630 Axis
= (XAxisInfoPtr
) ((char *) Val
+ sizeof
633 if (Val
->num_axes
>=1)
636 gSysDevice
.X
.axMin
= Axis
->min_value
;
637 gSysDevice
.X
.axMax
= Axis
->max_value
;
638 gSysDevice
.X
.axUnits
= TU_INCHES
;
639 gSysDevice
.X
.axResolution
= Axis
->resolution
;
640 gSysContext
.lcInOrgX
= Axis
->min_value
;
641 gSysContext
.lcSysOrgX
= Axis
->min_value
;
642 gSysContext
.lcInExtX
= Axis
->max_value
;
643 gSysContext
.lcSysExtX
= Axis
->max_value
;
646 if (Val
->num_axes
>=2)
649 gSysDevice
.Y
.axMin
= Axis
->min_value
;
650 gSysDevice
.Y
.axMax
= Axis
->max_value
;
651 gSysDevice
.Y
.axUnits
= TU_INCHES
;
652 gSysDevice
.Y
.axResolution
= Axis
->resolution
;
653 gSysContext
.lcInOrgY
= Axis
->min_value
;
654 gSysContext
.lcSysOrgY
= Axis
->min_value
;
655 gSysContext
.lcInExtY
= Axis
->max_value
;
656 gSysContext
.lcSysExtY
= Axis
->max_value
;
659 if (Val
->num_axes
>=3)
661 /* Axis 3 is Normal Pressure */
662 gSysDevice
.NPRESSURE
.axMin
= Axis
->min_value
;
663 gSysDevice
.NPRESSURE
.axMax
= Axis
->max_value
;
664 gSysDevice
.NPRESSURE
.axUnits
= TU_INCHES
;
665 gSysDevice
.NPRESSURE
.axResolution
=
669 if (Val
->num_axes
>= 5)
671 /* Axis 4 and 5 are X and Y tilt */
672 XAxisInfoPtr XAxis
= Axis
;
674 if (max (abs(Axis
->max_value
),
675 abs(XAxis
->max_value
)))
677 gSysDevice
.ORIENTATION
[0].axMin
= 0;
678 gSysDevice
.ORIENTATION
[0].axMax
= 3600;
679 gSysDevice
.ORIENTATION
[0].axUnits
= TU_CIRCLE
;
680 gSysDevice
.ORIENTATION
[0].axResolution
682 gSysDevice
.ORIENTATION
[1].axMin
= -1000;
683 gSysDevice
.ORIENTATION
[1].axMax
= 1000;
684 gSysDevice
.ORIENTATION
[1].axUnits
= TU_CIRCLE
;
685 gSysDevice
.ORIENTATION
[1].axResolution
690 axis_read_complete
= TRUE
;
699 Button
= (XButtonInfoPtr
) any
;
700 TRACE(" ButtonInput %d: [class %d|length %d|num_buttons %d]\n",
701 class_loop
, (int) Button
->class, Button
->length
, Button
->num_buttons
);
702 cursor
->BTNNAMES
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*cchBuf
);
703 for (i
= 0; i
< cursor
->BUTTONS
; i
++)
705 /* FIXME - these names are probably incorrect */
706 int cch
= strlenW(cursor
->NAME
) + 1;
707 while (cch
> cchBuf
- cchPos
- 1) /* we want one extra byte for the last NUL */
710 cursor
->BTNNAMES
= HeapReAlloc(GetProcessHeap(), 0, cursor
->BTNNAMES
, sizeof(WCHAR
)*cchBuf
);
713 strcpyW(cursor
->BTNNAMES
+ cchPos
, cursor
->NAME
);
716 cursor
->BTNNAMES
[cchPos
++] = 0;
717 cursor
->BTNNAMES
= HeapReAlloc(GetProcessHeap(), 0, cursor
->BTNNAMES
, sizeof(WCHAR
)*cchPos
);
718 cursor
->cchBTNNAMES
= cchPos
;
722 any
= (XAnyClassPtr
) ((char*) any
+ any
->length
);
729 pXFreeDeviceList(devices
);
731 if (axis_read_complete
)
733 gSysDevice
.NCSRTYPES
= cursor_target
+1;
734 gNumCursors
= cursor_target
+1;
735 Tablet_FixupCursors();
738 WARN("Did not find a valid stylus cursor with >= 5 axes, returning 0 valid devices.\n");
743 static int figure_deg(int x
, int y
)
749 rc
= (int) 10 * (atan( (FLOAT
)abs(y
) / (FLOAT
)abs(x
)) / (3.1415 / 180));
776 static int get_button_state(int curnum
)
778 return button_state
[curnum
];
781 static void set_button_state(int curnum
, XID deviceid
)
783 struct x11drv_thread_data
*data
= x11drv_thread_data();
791 device
= pXOpenDevice(data
->display
,deviceid
);
792 state
= pXQueryDeviceState(data
->display
,device
);
797 for (loop
= 0; loop
< state
->num_classes
; loop
++)
799 if (class->class == ButtonClass
)
802 XButtonState
*button_state
= (XButtonState
*)class;
803 for (loop2
= 0; loop2
< button_state
->num_buttons
; loop2
++)
805 if (button_state
->buttons
[loop2
/ 8] & (1 << (loop2
% 8)))
811 class = (XInputClass
*) ((char *) class + class->length
);
814 pXFreeDeviceState(state
);
816 button_state
[curnum
] = rc
;
819 static int cursor_from_device(DWORD deviceid
, LPWTI_CURSORS_INFO
*cursorp
)
822 for (i
= 0; i
< gNumCursors
; i
++)
823 if (gSysCursor
[i
].PHYSID
== deviceid
)
825 *cursorp
= &gSysCursor
[i
];
829 ERR("Could not map device id %d to a cursor\n", (int) deviceid
);
833 static void motion_event( HWND hwnd
, XEvent
*event
)
835 XDeviceMotionEvent
*motion
= (XDeviceMotionEvent
*)event
;
836 LPWTI_CURSORS_INFO cursor
;
837 int curnum
= cursor_from_device(motion
->deviceid
, &cursor
);
841 memset(&gMsgPacket
,0,sizeof(WTPACKET
));
843 TRACE("Received tablet motion event (%p); device id %d, cursor num %d\n",hwnd
, (int) motion
->deviceid
, curnum
);
845 /* Set cursor to inverted if cursor is the eraser */
846 gMsgPacket
.pkStatus
= (cursor
->TYPE
== CSR_TYPE_ERASER
? TPS_INVERT
:0);
847 gMsgPacket
.pkTime
= EVENT_x11_time_to_win32_time(motion
->time
);
848 gMsgPacket
.pkSerialNumber
= gSerial
++;
849 gMsgPacket
.pkCursor
= curnum
;
850 gMsgPacket
.pkX
= motion
->axis_data
[0];
851 gMsgPacket
.pkY
= motion
->axis_data
[1];
852 gMsgPacket
.pkOrientation
.orAzimuth
= figure_deg(motion
->axis_data
[3],motion
->axis_data
[4]);
853 gMsgPacket
.pkOrientation
.orAltitude
= ((1000 - 15 * max
854 (abs(motion
->axis_data
[3]),
855 abs(motion
->axis_data
[4])))
856 * (gMsgPacket
.pkStatus
& TPS_INVERT
?-1:1));
857 gMsgPacket
.pkNormalPressure
= motion
->axis_data
[2];
858 gMsgPacket
.pkButtons
= get_button_state(curnum
);
859 SendMessageW(hwndTabletDefault
,WT_PACKET
,0,(LPARAM
)hwnd
);
862 static void button_event( HWND hwnd
, XEvent
*event
)
864 XDeviceButtonEvent
*button
= (XDeviceButtonEvent
*) event
;
865 LPWTI_CURSORS_INFO cursor
;
866 int curnum
= cursor_from_device(button
->deviceid
, &cursor
);
870 memset(&gMsgPacket
,0,sizeof(WTPACKET
));
872 TRACE("Received tablet button %s event\n", (event
->type
== button_press_type
)?"press":"release");
874 /* Set cursor to inverted if cursor is the eraser */
875 gMsgPacket
.pkStatus
= (cursor
->TYPE
== CSR_TYPE_ERASER
? TPS_INVERT
:0);
876 set_button_state(curnum
, button
->deviceid
);
877 gMsgPacket
.pkTime
= EVENT_x11_time_to_win32_time(button
->time
);
878 gMsgPacket
.pkSerialNumber
= gSerial
++;
879 gMsgPacket
.pkCursor
= curnum
;
880 gMsgPacket
.pkX
= button
->axis_data
[0];
881 gMsgPacket
.pkY
= button
->axis_data
[1];
882 gMsgPacket
.pkOrientation
.orAzimuth
= figure_deg(button
->axis_data
[3],button
->axis_data
[4]);
883 gMsgPacket
.pkOrientation
.orAltitude
= ((1000 - 15 * max(abs(button
->axis_data
[3]),
884 abs(button
->axis_data
[4])))
885 * (gMsgPacket
.pkStatus
& TPS_INVERT
?-1:1));
886 gMsgPacket
.pkNormalPressure
= button
->axis_data
[2];
887 gMsgPacket
.pkButtons
= get_button_state(curnum
);
888 SendMessageW(hwndTabletDefault
,WT_PACKET
,0,(LPARAM
)hwnd
);
891 static void key_event( HWND hwnd
, XEvent
*event
)
893 if (event
->type
== key_press_type
)
894 FIXME("Received tablet key press event\n");
896 FIXME("Received tablet key release event\n");
899 static void proximity_event( HWND hwnd
, XEvent
*event
)
901 XProximityNotifyEvent
*proximity
= (XProximityNotifyEvent
*) event
;
902 LPWTI_CURSORS_INFO cursor
;
903 int curnum
= cursor_from_device(proximity
->deviceid
, &cursor
);
907 memset(&gMsgPacket
,0,sizeof(WTPACKET
));
909 TRACE("Received tablet proximity event\n");
910 /* Set cursor to inverted if cursor is the eraser */
911 gMsgPacket
.pkStatus
= (cursor
->TYPE
== CSR_TYPE_ERASER
? TPS_INVERT
:0);
912 gMsgPacket
.pkStatus
|= (event
->type
==proximity_out_type
)?TPS_PROXIMITY
:0;
913 gMsgPacket
.pkTime
= EVENT_x11_time_to_win32_time(proximity
->time
);
914 gMsgPacket
.pkSerialNumber
= gSerial
++;
915 gMsgPacket
.pkCursor
= curnum
;
916 gMsgPacket
.pkX
= proximity
->axis_data
[0];
917 gMsgPacket
.pkY
= proximity
->axis_data
[1];
918 gMsgPacket
.pkOrientation
.orAzimuth
= figure_deg(proximity
->axis_data
[3],proximity
->axis_data
[4]);
919 gMsgPacket
.pkOrientation
.orAltitude
= ((1000 - 15 * max(abs(proximity
->axis_data
[3]),
920 abs(proximity
->axis_data
[4])))
921 * (gMsgPacket
.pkStatus
& TPS_INVERT
?-1:1));
922 gMsgPacket
.pkNormalPressure
= proximity
->axis_data
[2];
923 gMsgPacket
.pkButtons
= get_button_state(curnum
);
925 SendMessageW(hwndTabletDefault
, WT_PROXIMITY
, (event
->type
== proximity_in_type
), (LPARAM
)hwnd
);
928 /***********************************************************************
929 * X11DRV_AttachEventQueueToTablet (X11DRV.@)
931 int X11DRV_AttachEventQueueToTablet(HWND hOwner
)
933 struct x11drv_thread_data
*data
= x11drv_thread_data();
937 XDeviceInfo
*devices
;
938 XDeviceInfo
*target
= NULL
;
940 XEventClass event_list
[7];
941 Window win
= X11DRV_get_whole_window( hOwner
);
945 TRACE("Creating context for window %p (%lx) %i cursors\n", hOwner
, win
, gNumCursors
);
948 devices
= pXListInputDevices(data
->display
, &num_devices
);
950 X11DRV_expect_error(data
->display
,Tablet_ErrorHandler
,NULL
);
951 for (cur_loop
=0; cur_loop
< gNumCursors
; cur_loop
++)
953 char cursorNameA
[WT_MAX_NAME_LEN
];
956 /* the cursor name fits in the buffer because too long names are skipped */
957 WideCharToMultiByte(CP_UNIXCP
, 0, gSysCursor
[cur_loop
].NAME
, -1, cursorNameA
, WT_MAX_NAME_LEN
, NULL
, NULL
);
958 for (loop
=0; loop
< num_devices
; loop
++)
959 if (strcmp(devices
[loop
].name
, cursorNameA
) == 0)
960 target
= &devices
[loop
];
962 TRACE("Opening cursor %i id %i\n",cur_loop
,(INT
)target
->id
);
964 the_device
= pXOpenDevice(data
->display
, target
->id
);
968 WARN("Unable to Open device\n");
972 if (the_device
->num_classes
> 0)
974 DeviceKeyPress(the_device
, key_press_type
, event_list
[event_number
]);
975 if (key_press_type
) event_number
++;
976 DeviceKeyRelease(the_device
, key_release_type
, event_list
[event_number
]);
977 if (key_release_type
) event_number
++;
978 DeviceButtonPress(the_device
, button_press_type
, event_list
[event_number
]);
979 if (button_press_type
) event_number
++;
980 DeviceButtonRelease(the_device
, button_release_type
, event_list
[event_number
]);
981 if (button_release_type
) event_number
++;
982 DeviceMotionNotify(the_device
, motion_type
, event_list
[event_number
]);
983 if (motion_type
) event_number
++;
984 ProximityIn(the_device
, proximity_in_type
, event_list
[event_number
]);
985 if (proximity_in_type
) event_number
++;
986 ProximityOut(the_device
, proximity_out_type
, event_list
[event_number
]);
987 if (proximity_out_type
) event_number
++;
989 if (key_press_type
) X11DRV_register_event_handler( key_press_type
, key_event
);
990 if (key_release_type
) X11DRV_register_event_handler( key_release_type
, key_event
);
991 if (button_press_type
) X11DRV_register_event_handler( button_press_type
, button_event
);
992 if (button_release_type
) X11DRV_register_event_handler( button_release_type
, button_event
);
993 if (motion_type
) X11DRV_register_event_handler( motion_type
, motion_event
);
994 if (proximity_in_type
) X11DRV_register_event_handler( proximity_in_type
, proximity_event
);
995 if (proximity_out_type
) X11DRV_register_event_handler( proximity_out_type
, proximity_event
);
997 pXSelectExtensionEvent(data
->display
, win
, event_list
, event_number
);
1000 XSync(data
->display
, False
);
1001 X11DRV_check_error();
1003 if (NULL
!= devices
) pXFreeDeviceList(devices
);
1004 wine_tsx11_unlock();
1008 /***********************************************************************
1009 * X11DRV_GetCurrentPacket (X11DRV.@)
1011 int X11DRV_GetCurrentPacket(LPWTPACKET
*packet
)
1013 memcpy(packet
,&gMsgPacket
,sizeof(WTPACKET
));
1018 static inline int CopyTabletData(LPVOID target
, LPCVOID src
, INT size
)
1021 * It is valid to call CopyTabletData with NULL.
1022 * This handles the WTInfo() case where lpOutput is null.
1025 memcpy(target
,src
,size
);
1029 /***********************************************************************
1030 * X11DRV_WTInfoW (X11DRV.@)
1032 UINT
X11DRV_WTInfoW(UINT wCategory
, UINT nIndex
, LPVOID lpOutput
)
1035 * It is valid to call WTInfoA with lpOutput == NULL, as per standard.
1036 * lpOutput == NULL signifies the user only wishes
1037 * to find the size of the data.
1039 * From now on use CopyTabletData to fill lpOutput. memcpy will break
1043 LPWTI_CURSORS_INFO tgtcursor
;
1044 TRACE("(%u, %u, %p)\n", wCategory
, nIndex
, lpOutput
);
1049 /* return largest necessary buffer */
1050 TRACE("%i cursors\n",gNumCursors
);
1053 FIXME("Return proper size\n");
1064 static const WCHAR driver
[] = {'W','i','n','e',' ','W','i','n','t','a','b',' ','1','.','1',0};
1065 rc
= CopyTabletData(lpOutput
, driver
, (strlenW(driver
) + 1) * sizeof(WCHAR
));
1068 case IFC_SPECVERSION
:
1069 version
= (0x01) | (0x01 << 8);
1070 rc
= CopyTabletData(lpOutput
, &version
,sizeof(WORD
));
1072 case IFC_IMPLVERSION
:
1073 version
= (0x00) | (0x01 << 8);
1074 rc
= CopyTabletData(lpOutput
, &version
,sizeof(WORD
));
1078 rc
= CopyTabletData(lpOutput
, &num
,sizeof(num
));
1082 rc
= CopyTabletData(lpOutput
, &num
,sizeof(num
));
1085 FIXME("WTI_INTERFACE unhandled index %i\n",nIndex
);
1091 case WTI_DEFCONTEXT
:
1095 rc
= CopyTabletData(lpOutput
, &gSysContext
,
1096 sizeof(LOGCONTEXTW
));
1099 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcName
,
1100 (strlenW(gSysContext
.lcName
)+1) * sizeof(WCHAR
));
1103 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOptions
,
1107 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcStatus
,
1111 rc
= CopyTabletData (lpOutput
, &gSysContext
.lcLocks
,
1115 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcMsgBase
,
1119 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcDevice
,
1123 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcPktRate
,
1127 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcPktData
,
1131 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcPktMode
,
1135 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcMoveMask
,
1139 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcBtnDnMask
,
1143 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcBtnUpMask
,
1147 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInOrgX
,
1151 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInOrgY
,
1155 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInOrgZ
,
1159 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInExtX
,
1163 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInExtY
,
1167 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInExtZ
,
1171 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutOrgX
,
1175 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutOrgY
,
1179 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutOrgZ
,
1183 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutExtX
,
1187 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutExtY
,
1191 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutExtZ
,
1195 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSensX
,
1199 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSensY
,
1203 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSensZ
,
1207 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysMode
,
1211 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysOrgX
,
1215 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysOrgY
,
1219 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysExtX
,
1223 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysExtY
,
1227 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysSensX
,
1231 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysSensY
,
1235 FIXME("WTI_DEFSYSCTX unhandled index %i\n",nIndex
);
1249 if (wCategory
- WTI_CURSORS
>= gNumCursors
)
1252 WARN("Requested cursor information for nonexistent cursor %d; only %d cursors\n",
1253 wCategory
- WTI_CURSORS
, gNumCursors
);
1257 tgtcursor
= &gSysCursor
[wCategory
- WTI_CURSORS
];
1261 rc
= CopyTabletData(lpOutput
, &tgtcursor
->NAME
,
1262 (strlenW(tgtcursor
->NAME
)+1) * sizeof(WCHAR
));
1265 rc
= CopyTabletData(lpOutput
,&tgtcursor
->ACTIVE
,
1269 rc
= CopyTabletData(lpOutput
,&tgtcursor
->PKTDATA
,
1273 rc
= CopyTabletData(lpOutput
,&tgtcursor
->BUTTONS
,
1276 case CSR_BUTTONBITS
:
1277 rc
= CopyTabletData(lpOutput
,&tgtcursor
->BUTTONBITS
,
1281 FIXME("Button Names not returned correctly\n");
1282 rc
= CopyTabletData(lpOutput
,&tgtcursor
->BTNNAMES
,
1283 tgtcursor
->cchBTNNAMES
*sizeof(WCHAR
));
1286 rc
= CopyTabletData(lpOutput
,&tgtcursor
->BUTTONMAP
,
1290 rc
= CopyTabletData(lpOutput
,&tgtcursor
->SYSBTNMAP
,
1293 case CSR_NPBTNMARKS
:
1294 rc
= CopyTabletData(lpOutput
,&tgtcursor
->NPBTNMARKS
,
1298 rc
= CopyTabletData(lpOutput
,&tgtcursor
->NPBUTTON
,
1301 case CSR_NPRESPONSE
:
1302 FIXME("Not returning CSR_NPRESPONSE correctly\n");
1306 rc
= CopyTabletData(lpOutput
,&tgtcursor
->TPBUTTON
,
1309 case CSR_TPBTNMARKS
:
1310 rc
= CopyTabletData(lpOutput
,&tgtcursor
->TPBTNMARKS
,
1313 case CSR_TPRESPONSE
:
1314 FIXME("Not returning CSR_TPRESPONSE correctly\n");
1320 id
= tgtcursor
->PHYSID
;
1321 rc
= CopyTabletData(lpOutput
,&id
,sizeof(DWORD
));
1325 rc
= CopyTabletData(lpOutput
,&tgtcursor
->MODE
,sizeof(UINT
));
1327 case CSR_MINPKTDATA
:
1328 rc
= CopyTabletData(lpOutput
,&tgtcursor
->MINPKTDATA
,
1331 case CSR_MINBUTTONS
:
1332 rc
= CopyTabletData(lpOutput
,&tgtcursor
->MINBUTTONS
,
1335 case CSR_CAPABILITIES
:
1336 rc
= CopyTabletData(lpOutput
,&tgtcursor
->CAPABILITIES
,
1340 rc
= CopyTabletData(lpOutput
,&tgtcursor
->TYPE
,
1344 FIXME("WTI_CURSORS unhandled index %i\n",nIndex
);
1353 rc
= CopyTabletData(lpOutput
,gSysDevice
.NAME
,
1354 (strlenW(gSysDevice
.NAME
)+1) * sizeof(WCHAR
));
1357 rc
= CopyTabletData(lpOutput
,&gSysDevice
.HARDWARE
,
1361 rc
= CopyTabletData(lpOutput
,&gSysDevice
.NCSRTYPES
,
1365 rc
= CopyTabletData(lpOutput
,&gSysDevice
.FIRSTCSR
,
1369 rc
= CopyTabletData(lpOutput
,&gSysDevice
.PKTRATE
,
1373 rc
= CopyTabletData(lpOutput
,&gSysDevice
.PKTDATA
,
1377 rc
= CopyTabletData(lpOutput
,&gSysDevice
.PKTMODE
,
1381 rc
= CopyTabletData(lpOutput
,&gSysDevice
.CSRDATA
,
1385 rc
= CopyTabletData(lpOutput
,&gSysDevice
.XMARGIN
,
1389 rc
= CopyTabletData(lpOutput
,&gSysDevice
.YMARGIN
,
1393 rc
= 0; /* unsupported */
1395 rc = CopyTabletData(lpOutput,&gSysDevice.ZMARGIN,
1400 rc
= CopyTabletData(lpOutput
,&gSysDevice
.X
,
1404 rc
= CopyTabletData(lpOutput
,&gSysDevice
.Y
,
1408 rc
= 0; /* unsupported */
1410 rc = CopyTabletData(lpOutput,&gSysDevice.Z,
1415 rc
= CopyTabletData(lpOutput
,&gSysDevice
.NPRESSURE
,
1419 rc
= 0; /* unsupported */
1421 rc = CopyTabletData(lpOutput,&gSysDevice.TPRESSURE,
1425 case DVC_ORIENTATION
:
1426 rc
= CopyTabletData(lpOutput
,&gSysDevice
.ORIENTATION
,
1430 rc
= 0; /* unsupported */
1432 rc = CopyTabletData(lpOutput,&gSysDevice.ROTATION,
1437 rc
= CopyTabletData(lpOutput
,gSysDevice
.PNPID
,
1438 (strlenW(gSysDevice
.PNPID
)+1)*sizeof(WCHAR
));
1441 FIXME("WTI_DEVICES unhandled index %i\n",nIndex
);
1446 FIXME("Unhandled Category %i\n",wCategory
);
1451 #else /* SONAME_LIBXI */
1453 /***********************************************************************
1454 * AttachEventQueueToTablet (X11DRV.@)
1456 int X11DRV_AttachEventQueueToTablet(HWND hOwner
)
1461 /***********************************************************************
1462 * GetCurrentPacket (X11DRV.@)
1464 int X11DRV_GetCurrentPacket(LPWTPACKET
*packet
)
1469 /***********************************************************************
1470 * LoadTabletInfo (X11DRV.@)
1472 void X11DRV_LoadTabletInfo(HWND hwnddefault
)
1476 /***********************************************************************
1477 * WTInfoW (X11DRV.@)
1479 UINT
X11DRV_WTInfoW(UINT wCategory
, UINT nIndex
, LPVOID lpOutput
)
1484 #endif /* SONAME_LIBXI */