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 void X11DRV_LoadTabletInfo(HWND hwnddefault
)
367 const WCHAR SZ_CONTEXT_NAME
[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','C','o','n','t','e','x','t',0};
368 const WCHAR SZ_DEVICE_NAME
[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','D','e','v','i','c','e',0};
369 const WCHAR SZ_NON_PLUGINPLAY
[] = {'n','o','n','-','p','l','u','g','i','n','p','l','a','y',0};
371 struct x11drv_thread_data
*data
= x11drv_thread_data();
375 XDeviceInfo
*devices
;
376 XDeviceInfo
*target
= NULL
;
377 BOOL axis_read_complete
= FALSE
;
380 XButtonInfoPtr Button
;
381 XValuatorInfoPtr Val
;
386 if (!X11DRV_XInput_Init())
388 ERR("Unable to initialized the XInput library.\n");
392 hwndTabletDefault
= hwnddefault
;
394 /* Do base initializaion */
395 strcpyW(gSysContext
.lcName
, SZ_CONTEXT_NAME
);
396 strcpyW(gSysDevice
.NAME
, SZ_DEVICE_NAME
);
398 gSysContext
.lcOptions
= CXO_SYSTEM
;
399 gSysContext
.lcLocks
= CXL_INSIZE
| CXL_INASPECT
| CXL_MARGIN
|
400 CXL_SENSITIVITY
| CXL_SYSOUT
;
402 gSysContext
.lcMsgBase
= WT_DEFBASE
;
403 gSysContext
.lcDevice
= 0;
404 gSysContext
.lcPktData
=
405 PK_CONTEXT
| PK_STATUS
| PK_SERIAL_NUMBER
| PK_TIME
| PK_CURSOR
|
406 PK_BUTTONS
| PK_X
| PK_Y
| PK_NORMAL_PRESSURE
| PK_ORIENTATION
;
407 gSysContext
.lcMoveMask
=
408 PK_BUTTONS
| PK_X
| PK_Y
| PK_NORMAL_PRESSURE
| PK_ORIENTATION
;
409 gSysContext
.lcStatus
= CXS_ONTOP
;
410 gSysContext
.lcPktRate
= 100;
411 gSysContext
.lcBtnDnMask
= 0xffffffff;
412 gSysContext
.lcBtnUpMask
= 0xffffffff;
413 gSysContext
.lcSensX
= 65536;
414 gSysContext
.lcSensY
= 65536;
415 gSysContext
.lcSensX
= 65536;
416 gSysContext
.lcSensZ
= 65536;
417 gSysContext
.lcSysSensX
= 65536;
418 gSysContext
.lcSysSensY
= 65536;
420 /* Device Defaults */
421 gSysDevice
.HARDWARE
= HWC_HARDPROX
|HWC_PHYSID_CURSORS
;
422 gSysDevice
.FIRSTCSR
= 0;
423 gSysDevice
.PKTRATE
= 100;
425 PK_CONTEXT
| PK_STATUS
| PK_SERIAL_NUMBER
| PK_TIME
| PK_CURSOR
|
426 PK_BUTTONS
| PK_X
| PK_Y
| PK_NORMAL_PRESSURE
| PK_ORIENTATION
;
427 strcpyW(gSysDevice
.PNPID
, SZ_NON_PLUGINPLAY
);
432 devices
= pXListInputDevices(data
->display
, &num_devices
);
435 WARN("XInput Extenstions reported as not avalable\n");
439 for (loop
=0; loop
< num_devices
; loop
++)
443 TRACE("Device %i: [id %d|name %s|type %s|num_classes %d|use %s]\n",
444 loop
, (int) devices
[loop
].id
, devices
[loop
].name
,
445 XGetAtomName(data
->display
, devices
[loop
].type
),
446 devices
[loop
].num_classes
,
447 devices
[loop
].use
== IsXKeyboard
? "IsXKeyboard" :
448 devices
[loop
].use
== IsXPointer
? "IsXPointer" :
449 devices
[loop
].use
== IsXExtensionDevice
? "IsXExtensionDevice" :
452 if (devices
[loop
].use
== IsXExtensionDevice
)
454 LPWTI_CURSORS_INFO cursor
;
456 TRACE("Is Extension Device\n");
458 target
= &devices
[loop
];
459 cursor
= &gSysCursor
[cursor_target
];
461 if (strlen(target
->name
) >= WT_MAX_NAME_LEN
)
463 ERR("Input device '%s' name too long - skipping\n", wine_dbgstr_a(target
->name
));
468 X11DRV_expect_error(data
->display
, Tablet_ErrorHandler
, NULL
);
469 opendevice
= pXOpenDevice(data
->display
,target
->id
);
470 if (!X11DRV_check_error() && opendevice
)
472 unsigned char map
[32];
476 X11DRV_expect_error(data
->display
,Tablet_ErrorHandler
,NULL
);
477 cursor
->BUTTONS
= pXGetDeviceButtonMapping(data
->display
, opendevice
, map
, 32);
478 if (X11DRV_check_error() || cursor
->BUTTONS
<= 0)
480 TRACE("No buttons, Non Tablet Device\n");
481 pXCloseDevice(data
->display
, opendevice
);
486 for (i
=0; i
< cursor
->BUTTONS
; i
++,shft
++)
488 cursor
->BUTTONMAP
[i
] = map
[i
];
489 cursor
->SYSBTNMAP
[i
] = (1<<shft
);
491 pXCloseDevice(data
->display
, opendevice
);
495 WARN("Unable to open device %s\n",target
->name
);
499 MultiByteToWideChar(CP_UNIXCP
, 0, target
->name
, -1, cursor
->NAME
, WT_MAX_NAME_LEN
);
502 cursor
->PKTDATA
= PK_TIME
| PK_CURSOR
| PK_BUTTONS
| PK_X
| PK_Y
|
503 PK_NORMAL_PRESSURE
| PK_TANGENT_PRESSURE
|
506 cursor
->PHYSID
= target
->id
;
507 cursor
->NPBUTTON
= 1;
508 cursor
->NPBTNMARKS
[0] = 0 ;
509 cursor
->NPBTNMARKS
[1] = 1 ;
510 cursor
->CAPABILITIES
= CRC_MULTIMODE
;
511 if (strcasecmp(target
->name
,"stylus")==0)
512 cursor
->TYPE
= CSR_TYPE_PEN
;
513 if (strcasecmp(target
->name
,"eraser")==0)
514 cursor
->TYPE
= CSR_TYPE_ERASER
;
517 any
= (XAnyClassPtr
) (target
->inputclassinfo
);
519 for (class_loop
= 0; class_loop
< target
->num_classes
; class_loop
++)
525 Val
= (XValuatorInfoPtr
) any
;
526 TRACE(" ValidatorInput %d: [class %d|length %d|num_axes %d|mode %d|motion_buffer %ld]\n",
527 class_loop
, (int) Val
->class, Val
->length
, Val
->num_axes
, Val
->mode
, Val
->motion_buffer
);
528 if (TRACE_ON(wintab32
))
531 /* FIXME: This is imperfect; we compute our devices capabilities based upon the
532 ** first pen type device we find. However, a more correct implementation
533 ** would require acquiring a wide variety of tablets and running through
534 ** the various inputs to see what the values are. Odds are that a
535 ** more 'correct' algorithm would condense to this one anyway.
537 if (!axis_read_complete
&& Val
->num_axes
>= 5 && cursor
->TYPE
== CSR_TYPE_PEN
)
539 Axis
= (XAxisInfoPtr
) ((char *) Val
+ sizeof
542 if (Val
->num_axes
>=1)
545 gSysDevice
.X
.axMin
= Axis
->min_value
;
546 gSysDevice
.X
.axMax
= Axis
->max_value
;
547 gSysDevice
.X
.axUnits
= TU_INCHES
;
548 gSysDevice
.X
.axResolution
= Axis
->resolution
;
549 gSysContext
.lcInOrgX
= Axis
->min_value
;
550 gSysContext
.lcSysOrgX
= Axis
->min_value
;
551 gSysContext
.lcInExtX
= Axis
->max_value
;
552 gSysContext
.lcSysExtX
= Axis
->max_value
;
555 if (Val
->num_axes
>=2)
558 gSysDevice
.Y
.axMin
= Axis
->min_value
;
559 gSysDevice
.Y
.axMax
= Axis
->max_value
;
560 gSysDevice
.Y
.axUnits
= TU_INCHES
;
561 gSysDevice
.Y
.axResolution
= Axis
->resolution
;
562 gSysContext
.lcInOrgY
= Axis
->min_value
;
563 gSysContext
.lcSysOrgY
= Axis
->min_value
;
564 gSysContext
.lcInExtY
= Axis
->max_value
;
565 gSysContext
.lcSysExtY
= Axis
->max_value
;
568 if (Val
->num_axes
>=3)
570 /* Axis 3 is Normal Pressure */
571 gSysDevice
.NPRESSURE
.axMin
= Axis
->min_value
;
572 gSysDevice
.NPRESSURE
.axMax
= Axis
->max_value
;
573 gSysDevice
.NPRESSURE
.axUnits
= TU_INCHES
;
574 gSysDevice
.NPRESSURE
.axResolution
=
578 if (Val
->num_axes
>= 5)
580 /* Axis 4 and 5 are X and Y tilt */
581 XAxisInfoPtr XAxis
= Axis
;
583 if (max (abs(Axis
->max_value
),
584 abs(XAxis
->max_value
)))
586 gSysDevice
.ORIENTATION
[0].axMin
= 0;
587 gSysDevice
.ORIENTATION
[0].axMax
= 3600;
588 gSysDevice
.ORIENTATION
[0].axUnits
= TU_CIRCLE
;
589 gSysDevice
.ORIENTATION
[0].axResolution
591 gSysDevice
.ORIENTATION
[1].axMin
= -1000;
592 gSysDevice
.ORIENTATION
[1].axMax
= 1000;
593 gSysDevice
.ORIENTATION
[1].axUnits
= TU_CIRCLE
;
594 gSysDevice
.ORIENTATION
[1].axResolution
599 axis_read_complete
= TRUE
;
608 Button
= (XButtonInfoPtr
) any
;
609 TRACE(" ButtonInput %d: [class %d|length %d|num_buttons %d]\n",
610 class_loop
, (int) Button
->class, Button
->length
, Button
->num_buttons
);
611 cursor
->BTNNAMES
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*cchBuf
);
612 for (i
= 0; i
< cursor
->BUTTONS
; i
++)
614 /* FIXME - these names are probably incorrect */
615 int cch
= strlenW(cursor
->NAME
) + 1;
616 while (cch
> cchBuf
- cchPos
- 1) /* we want one extra byte for the last NUL */
619 cursor
->BTNNAMES
= HeapReAlloc(GetProcessHeap(), 0, cursor
->BTNNAMES
, sizeof(WCHAR
)*cchBuf
);
622 strcpyW(cursor
->BTNNAMES
+ cchPos
, cursor
->NAME
);
625 cursor
->BTNNAMES
[cchPos
++] = 0;
626 cursor
->BTNNAMES
= HeapReAlloc(GetProcessHeap(), 0, cursor
->BTNNAMES
, sizeof(WCHAR
)*cchPos
);
627 cursor
->cchBTNNAMES
= cchPos
;
631 any
= (XAnyClassPtr
) ((char*) any
+ any
->length
);
635 pXFreeDeviceList(devices
);
636 gSysDevice
.NCSRTYPES
= cursor_target
+1;
637 gNumCursors
= cursor_target
+1;
638 Tablet_FixupCursors();
642 static int figure_deg(int x
, int y
)
648 rc
= (int) 10 * (atan( (FLOAT
)abs(y
) / (FLOAT
)abs(x
)) / (3.1415 / 180));
675 static int get_button_state(int curnum
)
677 return button_state
[curnum
];
680 static void set_button_state(int curnum
, XID deviceid
)
682 struct x11drv_thread_data
*data
= x11drv_thread_data();
690 device
= pXOpenDevice(data
->display
,deviceid
);
691 state
= pXQueryDeviceState(data
->display
,device
);
696 for (loop
= 0; loop
< state
->num_classes
; loop
++)
698 if (class->class == ButtonClass
)
701 XButtonState
*button_state
= (XButtonState
*)class;
702 for (loop2
= 0; loop2
< button_state
->num_buttons
; loop2
++)
704 if (button_state
->buttons
[loop2
/ 8] & (1 << (loop2
% 8)))
710 class = (XInputClass
*) ((char *) class + class->length
);
713 pXFreeDeviceState(state
);
715 button_state
[curnum
] = rc
;
718 static int cursor_from_device(DWORD deviceid
, LPWTI_CURSORS_INFO
*cursorp
)
721 for (i
= 0; i
< gNumCursors
; i
++)
722 if (gSysCursor
[i
].PHYSID
== deviceid
)
724 *cursorp
= &gSysCursor
[i
];
728 ERR("Could not map device id %d to a cursor\n", (int) deviceid
);
732 static void motion_event( HWND hwnd
, XEvent
*event
)
734 XDeviceMotionEvent
*motion
= (XDeviceMotionEvent
*)event
;
735 LPWTI_CURSORS_INFO cursor
;
736 int curnum
= cursor_from_device(motion
->deviceid
, &cursor
);
740 memset(&gMsgPacket
,0,sizeof(WTPACKET
));
742 TRACE("Received tablet motion event (%p); device id %d, cursor num %d\n",hwnd
, (int) motion
->deviceid
, curnum
);
744 /* Set cursor to inverted if cursor is the eraser */
745 gMsgPacket
.pkStatus
= (cursor
->TYPE
== CSR_TYPE_ERASER
? TPS_INVERT
:0);
746 gMsgPacket
.pkTime
= EVENT_x11_time_to_win32_time(motion
->time
);
747 gMsgPacket
.pkSerialNumber
= gSerial
++;
748 gMsgPacket
.pkCursor
= curnum
;
749 gMsgPacket
.pkX
= motion
->axis_data
[0];
750 gMsgPacket
.pkY
= motion
->axis_data
[1];
751 gMsgPacket
.pkOrientation
.orAzimuth
= figure_deg(motion
->axis_data
[3],motion
->axis_data
[4]);
752 gMsgPacket
.pkOrientation
.orAltitude
= ((1000 - 15 * max
753 (abs(motion
->axis_data
[3]),
754 abs(motion
->axis_data
[4])))
755 * (gMsgPacket
.pkStatus
& TPS_INVERT
?-1:1));
756 gMsgPacket
.pkNormalPressure
= motion
->axis_data
[2];
757 gMsgPacket
.pkButtons
= get_button_state(curnum
);
758 SendMessageW(hwndTabletDefault
,WT_PACKET
,0,(LPARAM
)hwnd
);
761 static void button_event( HWND hwnd
, XEvent
*event
)
763 XDeviceButtonEvent
*button
= (XDeviceButtonEvent
*) event
;
764 LPWTI_CURSORS_INFO cursor
;
765 int curnum
= cursor_from_device(button
->deviceid
, &cursor
);
769 memset(&gMsgPacket
,0,sizeof(WTPACKET
));
771 TRACE("Received tablet button %s event\n", (event
->type
== button_press_type
)?"press":"release");
773 /* Set cursor to inverted if cursor is the eraser */
774 gMsgPacket
.pkStatus
= (cursor
->TYPE
== CSR_TYPE_ERASER
? TPS_INVERT
:0);
775 set_button_state(curnum
, button
->deviceid
);
776 gMsgPacket
.pkTime
= EVENT_x11_time_to_win32_time(button
->time
);
777 gMsgPacket
.pkSerialNumber
= gSerial
++;
778 gMsgPacket
.pkCursor
= curnum
;
779 gMsgPacket
.pkX
= button
->axis_data
[0];
780 gMsgPacket
.pkY
= button
->axis_data
[1];
781 gMsgPacket
.pkOrientation
.orAzimuth
= figure_deg(button
->axis_data
[3],button
->axis_data
[4]);
782 gMsgPacket
.pkOrientation
.orAltitude
= ((1000 - 15 * max(abs(button
->axis_data
[3]),
783 abs(button
->axis_data
[4])))
784 * (gMsgPacket
.pkStatus
& TPS_INVERT
?-1:1));
785 gMsgPacket
.pkNormalPressure
= button
->axis_data
[2];
786 gMsgPacket
.pkButtons
= get_button_state(curnum
);
787 SendMessageW(hwndTabletDefault
,WT_PACKET
,0,(LPARAM
)hwnd
);
790 static void key_event( HWND hwnd
, XEvent
*event
)
792 if (event
->type
== key_press_type
)
793 FIXME("Received tablet key press event\n");
795 FIXME("Received tablet key release event\n");
798 static void proximity_event( HWND hwnd
, XEvent
*event
)
800 XProximityNotifyEvent
*proximity
= (XProximityNotifyEvent
*) event
;
801 LPWTI_CURSORS_INFO cursor
;
802 int curnum
= cursor_from_device(proximity
->deviceid
, &cursor
);
806 memset(&gMsgPacket
,0,sizeof(WTPACKET
));
808 TRACE("Received tablet proximity event\n");
809 /* Set cursor to inverted if cursor is the eraser */
810 gMsgPacket
.pkStatus
= (cursor
->TYPE
== CSR_TYPE_ERASER
? TPS_INVERT
:0);
811 gMsgPacket
.pkStatus
|= (event
->type
==proximity_out_type
)?TPS_PROXIMITY
:0;
812 gMsgPacket
.pkTime
= EVENT_x11_time_to_win32_time(proximity
->time
);
813 gMsgPacket
.pkSerialNumber
= gSerial
++;
814 gMsgPacket
.pkCursor
= curnum
;
815 gMsgPacket
.pkX
= proximity
->axis_data
[0];
816 gMsgPacket
.pkY
= proximity
->axis_data
[1];
817 gMsgPacket
.pkOrientation
.orAzimuth
= figure_deg(proximity
->axis_data
[3],proximity
->axis_data
[4]);
818 gMsgPacket
.pkOrientation
.orAltitude
= ((1000 - 15 * max(abs(proximity
->axis_data
[3]),
819 abs(proximity
->axis_data
[4])))
820 * (gMsgPacket
.pkStatus
& TPS_INVERT
?-1:1));
821 gMsgPacket
.pkNormalPressure
= proximity
->axis_data
[2];
822 gMsgPacket
.pkButtons
= get_button_state(curnum
);
824 SendMessageW(hwndTabletDefault
, WT_PROXIMITY
, (event
->type
== proximity_in_type
), (LPARAM
)hwnd
);
827 int X11DRV_AttachEventQueueToTablet(HWND hOwner
)
829 struct x11drv_thread_data
*data
= x11drv_thread_data();
833 XDeviceInfo
*devices
;
834 XDeviceInfo
*target
= NULL
;
836 XEventClass event_list
[7];
837 Window win
= X11DRV_get_whole_window( hOwner
);
841 TRACE("Creating context for window %p (%lx) %i cursors\n", hOwner
, win
, gNumCursors
);
844 devices
= pXListInputDevices(data
->display
, &num_devices
);
846 X11DRV_expect_error(data
->display
,Tablet_ErrorHandler
,NULL
);
847 for (cur_loop
=0; cur_loop
< gNumCursors
; cur_loop
++)
849 char cursorNameA
[WT_MAX_NAME_LEN
];
852 /* the cursor name fits in the buffer because too long names are skipped */
853 WideCharToMultiByte(CP_UNIXCP
, 0, gSysCursor
[cur_loop
].NAME
, -1, cursorNameA
, WT_MAX_NAME_LEN
, NULL
, NULL
);
854 for (loop
=0; loop
< num_devices
; loop
++)
855 if (strcmp(devices
[loop
].name
, cursorNameA
) == 0)
856 target
= &devices
[loop
];
858 TRACE("Opening cursor %i id %i\n",cur_loop
,(INT
)target
->id
);
860 the_device
= pXOpenDevice(data
->display
, target
->id
);
864 WARN("Unable to Open device\n");
868 if (the_device
->num_classes
> 0)
870 DeviceKeyPress(the_device
, key_press_type
, event_list
[event_number
]);
871 if (key_press_type
) event_number
++;
872 DeviceKeyRelease(the_device
, key_release_type
, event_list
[event_number
]);
873 if (key_release_type
) event_number
++;
874 DeviceButtonPress(the_device
, button_press_type
, event_list
[event_number
]);
875 if (button_press_type
) event_number
++;
876 DeviceButtonRelease(the_device
, button_release_type
, event_list
[event_number
]);
877 if (button_release_type
) event_number
++;
878 DeviceMotionNotify(the_device
, motion_type
, event_list
[event_number
]);
879 if (motion_type
) event_number
++;
880 ProximityIn(the_device
, proximity_in_type
, event_list
[event_number
]);
881 if (proximity_in_type
) event_number
++;
882 ProximityOut(the_device
, proximity_out_type
, event_list
[event_number
]);
883 if (proximity_out_type
) event_number
++;
885 if (key_press_type
) X11DRV_register_event_handler( key_press_type
, key_event
);
886 if (key_release_type
) X11DRV_register_event_handler( key_release_type
, key_event
);
887 if (button_press_type
) X11DRV_register_event_handler( button_press_type
, button_event
);
888 if (button_release_type
) X11DRV_register_event_handler( button_release_type
, button_event
);
889 if (motion_type
) X11DRV_register_event_handler( motion_type
, motion_event
);
890 if (proximity_in_type
) X11DRV_register_event_handler( proximity_in_type
, proximity_event
);
891 if (proximity_out_type
) X11DRV_register_event_handler( proximity_out_type
, proximity_event
);
893 pXSelectExtensionEvent(data
->display
, win
, event_list
, event_number
);
896 XSync(data
->display
, False
);
897 X11DRV_check_error();
899 if (NULL
!= devices
) pXFreeDeviceList(devices
);
904 int X11DRV_GetCurrentPacket(LPWTPACKET
*packet
)
906 memcpy(packet
,&gMsgPacket
,sizeof(WTPACKET
));
911 static inline int CopyTabletData(LPVOID target
, LPCVOID src
, INT size
)
914 * It is valid to call CopyTabletData with NULL.
915 * This handles the WTInfo() case where lpOutput is null.
918 memcpy(target
,src
,size
);
922 /***********************************************************************
923 * X11DRV_WTInfoW (X11DRV.@)
925 UINT
X11DRV_WTInfoW(UINT wCategory
, UINT nIndex
, LPVOID lpOutput
)
928 * It is valid to call WTInfoA with lpOutput == NULL, as per standard.
929 * lpOutput == NULL signifies the user only wishes
930 * to find the size of the data.
932 * From now on use CopyTabletData to fill lpOutput. memcpy will break
936 LPWTI_CURSORS_INFO tgtcursor
;
937 TRACE("(%u, %u, %p)\n", wCategory
, nIndex
, lpOutput
);
942 /* return largest necessary buffer */
943 TRACE("%i cursors\n",gNumCursors
);
946 FIXME("Return proper size\n");
957 static const WCHAR driver
[] = {'W','i','n','e',' ','W','i','n','t','a','b',' ','1','.','1',0};
958 rc
= CopyTabletData(lpOutput
, driver
, (strlenW(driver
) + 1) * sizeof(WCHAR
));
961 case IFC_SPECVERSION
:
962 version
= (0x01) | (0x01 << 8);
963 rc
= CopyTabletData(lpOutput
, &version
,sizeof(WORD
));
965 case IFC_IMPLVERSION
:
966 version
= (0x00) | (0x01 << 8);
967 rc
= CopyTabletData(lpOutput
, &version
,sizeof(WORD
));
971 rc
= CopyTabletData(lpOutput
, &num
,sizeof(num
));
975 rc
= CopyTabletData(lpOutput
, &num
,sizeof(num
));
978 FIXME("WTI_INTERFACE unhandled index %i\n",nIndex
);
988 rc
= CopyTabletData(lpOutput
, &gSysContext
,
989 sizeof(LOGCONTEXTW
));
992 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcName
,
993 (strlenW(gSysContext
.lcName
)+1) * sizeof(WCHAR
));
996 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOptions
,
1000 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcStatus
,
1004 rc
= CopyTabletData (lpOutput
, &gSysContext
.lcLocks
,
1008 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcMsgBase
,
1012 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcDevice
,
1016 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcPktRate
,
1020 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcPktData
,
1024 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcPktMode
,
1028 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcMoveMask
,
1032 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcBtnDnMask
,
1036 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcBtnUpMask
,
1040 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInOrgX
,
1044 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInOrgY
,
1048 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInOrgZ
,
1052 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInExtX
,
1056 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInExtY
,
1060 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcInExtZ
,
1064 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutOrgX
,
1068 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutOrgY
,
1072 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutOrgZ
,
1076 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutExtX
,
1080 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutExtY
,
1084 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcOutExtZ
,
1088 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSensX
,
1092 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSensY
,
1096 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSensZ
,
1100 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysMode
,
1104 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysOrgX
,
1108 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysOrgY
,
1112 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysExtX
,
1116 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysExtY
,
1120 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysSensX
,
1124 rc
= CopyTabletData(lpOutput
, &gSysContext
.lcSysSensY
,
1128 FIXME("WTI_DEFSYSCTX unhandled index %i\n",nIndex
);
1142 if (wCategory
- WTI_CURSORS
>= gNumCursors
)
1145 WARN("Requested cursor information for non existent cursor %d; only %d cursors\n",
1146 wCategory
- WTI_CURSORS
, gNumCursors
);
1150 tgtcursor
= &gSysCursor
[wCategory
- WTI_CURSORS
];
1154 rc
= CopyTabletData(lpOutput
, &tgtcursor
->NAME
,
1155 (strlenW(tgtcursor
->NAME
)+1) * sizeof(WCHAR
));
1158 rc
= CopyTabletData(lpOutput
,&tgtcursor
->ACTIVE
,
1162 rc
= CopyTabletData(lpOutput
,&tgtcursor
->PKTDATA
,
1166 rc
= CopyTabletData(lpOutput
,&tgtcursor
->BUTTONS
,
1169 case CSR_BUTTONBITS
:
1170 rc
= CopyTabletData(lpOutput
,&tgtcursor
->BUTTONBITS
,
1174 FIXME("Button Names not returned correctly\n");
1175 rc
= CopyTabletData(lpOutput
,&tgtcursor
->BTNNAMES
,
1176 tgtcursor
->cchBTNNAMES
*sizeof(WCHAR
));
1179 rc
= CopyTabletData(lpOutput
,&tgtcursor
->BUTTONMAP
,
1183 rc
= CopyTabletData(lpOutput
,&tgtcursor
->SYSBTNMAP
,
1186 case CSR_NPBTNMARKS
:
1187 rc
= CopyTabletData(lpOutput
,&tgtcursor
->NPBTNMARKS
,
1191 rc
= CopyTabletData(lpOutput
,&tgtcursor
->NPBUTTON
,
1194 case CSR_NPRESPONSE
:
1195 FIXME("Not returning CSR_NPRESPONSE correctly\n");
1199 rc
= CopyTabletData(lpOutput
,&tgtcursor
->TPBUTTON
,
1202 case CSR_TPBTNMARKS
:
1203 rc
= CopyTabletData(lpOutput
,&tgtcursor
->TPBTNMARKS
,
1206 case CSR_TPRESPONSE
:
1207 FIXME("Not returning CSR_TPRESPONSE correctly\n");
1213 id
= tgtcursor
->PHYSID
;
1214 rc
= CopyTabletData(lpOutput
,&id
,sizeof(DWORD
));
1218 rc
= CopyTabletData(lpOutput
,&tgtcursor
->MODE
,sizeof(UINT
));
1220 case CSR_MINPKTDATA
:
1221 rc
= CopyTabletData(lpOutput
,&tgtcursor
->MINPKTDATA
,
1224 case CSR_MINBUTTONS
:
1225 rc
= CopyTabletData(lpOutput
,&tgtcursor
->MINBUTTONS
,
1228 case CSR_CAPABILITIES
:
1229 rc
= CopyTabletData(lpOutput
,&tgtcursor
->CAPABILITIES
,
1233 rc
= CopyTabletData(lpOutput
,&tgtcursor
->TYPE
,
1237 FIXME("WTI_CURSORS unhandled index %i\n",nIndex
);
1246 rc
= CopyTabletData(lpOutput
,gSysDevice
.NAME
,
1247 (strlenW(gSysDevice
.NAME
)+1) * sizeof(WCHAR
));
1250 rc
= CopyTabletData(lpOutput
,&gSysDevice
.HARDWARE
,
1254 rc
= CopyTabletData(lpOutput
,&gSysDevice
.NCSRTYPES
,
1258 rc
= CopyTabletData(lpOutput
,&gSysDevice
.FIRSTCSR
,
1262 rc
= CopyTabletData(lpOutput
,&gSysDevice
.PKTRATE
,
1266 rc
= CopyTabletData(lpOutput
,&gSysDevice
.PKTDATA
,
1270 rc
= CopyTabletData(lpOutput
,&gSysDevice
.PKTMODE
,
1274 rc
= CopyTabletData(lpOutput
,&gSysDevice
.CSRDATA
,
1278 rc
= CopyTabletData(lpOutput
,&gSysDevice
.XMARGIN
,
1282 rc
= CopyTabletData(lpOutput
,&gSysDevice
.YMARGIN
,
1286 rc
= 0; /* unsupported */
1288 rc = CopyTabletData(lpOutput,&gSysDevice.ZMARGIN,
1293 rc
= CopyTabletData(lpOutput
,&gSysDevice
.X
,
1297 rc
= CopyTabletData(lpOutput
,&gSysDevice
.Y
,
1301 rc
= 0; /* unsupported */
1303 rc = CopyTabletData(lpOutput,&gSysDevice.Z,
1308 rc
= CopyTabletData(lpOutput
,&gSysDevice
.NPRESSURE
,
1312 rc
= 0; /* unsupported */
1314 rc = CopyTabletData(lpOutput,&gSysDevice.TPRESSURE,
1318 case DVC_ORIENTATION
:
1319 rc
= CopyTabletData(lpOutput
,&gSysDevice
.ORIENTATION
,
1323 rc
= 0; /* unsupported */
1325 rc = CopyTabletData(lpOutput,&gSysDevice.ROTATION,
1330 rc
= CopyTabletData(lpOutput
,gSysDevice
.PNPID
,
1331 (strlenW(gSysDevice
.PNPID
)+1)*sizeof(WCHAR
));
1334 FIXME("WTI_DEVICES unhandled index %i\n",nIndex
);
1339 FIXME("Unhandled Category %i\n",wCategory
);
1344 #else /* SONAME_LIBXI */
1346 /***********************************************************************
1347 * AttachEventQueueToTablet (X11DRV.@)
1349 int X11DRV_AttachEventQueueToTablet(HWND hOwner
)
1354 /***********************************************************************
1355 * GetCurrentPacket (X11DRV.@)
1357 int X11DRV_GetCurrentPacket(LPWTPACKET
*packet
)
1362 /***********************************************************************
1363 * LoadTabletInfo (X11DRV.@)
1365 void X11DRV_LoadTabletInfo(HWND hwnddefault
)
1369 /***********************************************************************
1370 * WTInfoW (X11DRV.@)
1372 UINT
X11DRV_WTInfoW(UINT wCategory
, UINT nIndex
, LPVOID lpOutput
)
1377 #endif /* SONAME_LIBXI */