2004-01-09 01:03:00 +01:00
/*
* X11 tablet driver
*
* Copyright 2003 CodeWeavers ( Aric Stewart )
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
2006-05-18 14:49:52 +02:00
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA
2004-01-09 01:03:00 +01:00
*/
# include "config.h"
# include "wine/port.h"
# include <stdlib.h>
2007-09-20 22:01:06 +02:00
# include <stdarg.h>
2004-01-09 01:03:00 +01:00
# include "windef.h"
2007-09-20 22:01:06 +02:00
# include "winbase.h"
# include "winnls.h"
2004-01-09 01:03:00 +01:00
# include "x11drv.h"
2007-09-20 22:01:06 +02:00
# include "wine/unicode.h"
2004-01-09 01:03:00 +01:00
# include "wine/debug.h"
# include "wintab.h"
WINE_DEFAULT_DEBUG_CHANNEL ( wintab32 ) ;
2007-09-20 22:01:06 +02:00
# define WT_MAX_NAME_LEN 256
2004-01-09 01:03:00 +01:00
typedef struct tagWTI_CURSORS_INFO
{
2007-09-20 22:01:06 +02:00
WCHAR NAME [ WT_MAX_NAME_LEN ] ;
2004-01-09 01:03:00 +01:00
/* a displayable zero-terminated string containing the name of the
* cursor .
*/
BOOL ACTIVE ;
/* whether the cursor is currently connected. */
WTPKT PKTDATA ;
/* a bit mask indicating the packet data items supported when this
* cursor is connected .
*/
BYTE BUTTONS ;
/* the number of buttons on this cursor. */
BYTE BUTTONBITS ;
/* the number of bits of raw button data returned by the hardware.*/
2007-09-20 22:01:06 +02:00
DWORD cchBTNNAMES ;
WCHAR * BTNNAMES ;
2004-01-09 01:03:00 +01:00
/* a list of zero-terminated strings containing the names of the
* cursor ' s buttons . The number of names in the list is the same as the
* number of buttons on the cursor . The names are separated by a single
* zero character ; the list is terminated by two zero characters .
*/
BYTE BUTTONMAP [ 32 ] ;
/* a 32 byte array of logical button numbers, one for each physical
* button .
*/
BYTE SYSBTNMAP [ 32 ] ;
/* a 32 byte array of button action codes, one for each logical
* button .
*/
BYTE NPBUTTON ;
/* the physical button number of the button that is controlled by normal
* pressure .
*/
UINT NPBTNMARKS [ 2 ] ;
/* an array of two UINTs, specifying the button marks for the normal
* pressure button . The first UINT contains the release mark ; the second
* contains the press mark .
*/
UINT * NPRESPONSE ;
/* an array of UINTs describing the pressure response curve for normal
* pressure .
*/
BYTE TPBUTTON ;
/* the physical button number of the button that is controlled by
* tangential pressure .
*/
UINT TPBTNMARKS [ 2 ] ;
/* an array of two UINTs, specifying the button marks for the tangential
* pressure button . The first UINT contains the release mark ; the second
* contains the press mark .
*/
UINT * TPRESPONSE ;
/* an array of UINTs describing the pressure response curve for
* tangential pressure .
*/
DWORD PHYSID ;
/* a manufacturer-specific physical identifier for the cursor. This
* value will distinguish the physical cursor from others on the same
* device . This physical identifier allows applications to bind
* functions to specific physical cursors , even if category numbers
* change and multiple , otherwise identical , physical cursors are
* present .
*/
UINT MODE ;
/* the cursor mode number of this cursor type, if this cursor type has
* the CRC_MULTIMODE capability .
*/
UINT MINPKTDATA ;
/* the minimum set of data available from a physical cursor in this
* cursor type , if this cursor type has the CRC_AGGREGATE capability .
*/
UINT MINBUTTONS ;
/* the minimum number of buttons of physical cursors in the cursor type,
* if this cursor type has the CRC_AGGREGATE capability .
*/
UINT CAPABILITIES ;
/* flags indicating cursor capabilities, as defined below:
CRC_MULTIMODE
Indicates this cursor type describes one of several modes of a
single physical cursor . Consecutive cursor type categories
describe the modes ; the CSR_MODE data item gives the mode number
of each cursor type .
CRC_AGGREGATE
Indicates this cursor type describes several physical cursors
that cannot be distinguished by software .
CRC_INVERT
Indicates this cursor type describes the physical cursor in its
inverted orientation ; the previous consecutive cursor type
category describes the normal orientation .
*/
UINT TYPE ;
/* Manufacturer Unique id for the item type */
} WTI_CURSORS_INFO , * LPWTI_CURSORS_INFO ;
typedef struct tagWTI_DEVICES_INFO
{
2007-09-20 22:01:06 +02:00
WCHAR NAME [ WT_MAX_NAME_LEN ] ;
2004-01-09 01:03:00 +01:00
/* a displayable null- terminated string describing the device,
* manufacturer , and revision level .
*/
UINT HARDWARE ;
/* flags indicating hardware and driver capabilities, as defined
* below :
HWC_INTEGRATED :
Indicates that the display and digitizer share the same surface .
HWC_TOUCH
Indicates that the cursor must be in physical contact with the
device to report position .
HWC_HARDPROX
Indicates that device can generate events when the cursor is
entering and leaving the physical detection range .
HWC_PHYSID_CURSORS
Indicates that device can uniquely identify the active cursor in
hardware .
*/
UINT NCSRTYPES ;
/* the number of supported cursor types.*/
UINT FIRSTCSR ;
/* the first cursor type number for the device. */
UINT PKTRATE ;
/* the maximum packet report rate in Hertz. */
WTPKT PKTDATA ;
/* a bit mask indicating which packet data items are always available.*/
WTPKT PKTMODE ;
/* a bit mask indicating which packet data items are physically
* relative , i . e . , items for which the hardware can only report change ,
* not absolute measurement .
*/
WTPKT CSRDATA ;
/* a bit mask indicating which packet data items are only available when
* certain cursors are connected . The individual cursor descriptions
* must be consulted to determine which cursors return which data .
*/
INT XMARGIN ;
INT YMARGIN ;
INT ZMARGIN ;
/* the size of tablet context margins in tablet native coordinates, in
* the x , y , and z directions , respectively .
*/
AXIS X ;
AXIS Y ;
AXIS Z ;
/* the tablet's range and resolution capabilities, in the x, y, and z
* axes , respectively .
*/
AXIS NPRESSURE ;
AXIS TPRESSURE ;
/* the tablet's range and resolution capabilities, for the normal and
* tangential pressure inputs , respectively .
*/
AXIS ORIENTATION [ 3 ] ;
/* a 3-element array describing the tablet's orientation range and
* resolution capabilities .
*/
AXIS ROTATION [ 3 ] ;
/* a 3-element array describing the tablet's rotation range and
* resolution capabilities .
*/
2007-09-20 22:01:06 +02:00
WCHAR PNPID [ WT_MAX_NAME_LEN ] ;
2004-01-09 01:03:00 +01:00
/* a null-terminated string containing the devices Plug and Play ID.*/
} WTI_DEVICES_INFO , * LPWTI_DEVICES_INFO ;
2007-12-24 22:10:43 +01:00
/***********************************************************************
* WACOM WINTAB EXTENSIONS TO SUPPORT CSR_TYPE
* In Wintab 1.2 , a CSR_TYPE feature was added . This adds the
* ability to return a type of cursor on a tablet .
* Unfortunately , we cannot get the cursor type directly from X ,
* and it is not specified directly anywhere . So we virtualize
* the type here . ( This is unfortunate , the kernel module has
* the exact type , but we have no way of getting that module to
* pass us that type ) .
2008-05-31 22:34:57 +02:00
*
* Reference linuxwacom driver project wcmCommon . c function
* idtotype for a much larger list of CSR_TYPE .
*
* http : //linuxwacom.cvs.sourceforge.net/linuxwacom/linuxwacom-prod/src/xdrv/wcmCommon.c?view=markup
*
* The WTI_CURSORS_INFO . TYPE data is supposed to be used like this :
* ( cursor . TYPE & 0x0F06 ) = = target_cursor_type
* Reference : Section Unique ID
* http : //www.wacomeng.com/devsupport/ibmpc/gddevpc.html
2007-12-24 22:10:43 +01:00
*/
# define CSR_TYPE_PEN 0x822
# define CSR_TYPE_ERASER 0x82a
# define CSR_TYPE_MOUSE_2D 0x007
# define CSR_TYPE_MOUSE_4D 0x094
2011-08-02 22:20:32 +02:00
/* CSR_TYPE_OTHER is a special value! assumed no real world significance
2008-05-31 22:51:46 +02:00
* if a stylus type or eraser type eventually have this value
* it ' ll be a bug . As of 2008 05 21 we can be sure because
* linux wacom lists all the known values and this isn ' t one of them */
# define CSR_TYPE_OTHER 0x000
2007-12-24 22:10:43 +01:00
2004-01-09 01:03:00 +01:00
typedef struct tagWTPACKET {
HCTX pkContext ;
UINT pkStatus ;
LONG pkTime ;
WTPKT pkChanged ;
UINT pkSerialNumber ;
UINT pkCursor ;
DWORD pkButtons ;
DWORD pkX ;
DWORD pkY ;
DWORD pkZ ;
UINT pkNormalPressure ;
UINT pkTangentPressure ;
ORIENTATION pkOrientation ;
ROTATION pkRotation ; /* 1.1 */
} WTPACKET , * LPWTPACKET ;
2007-07-09 22:42:49 +02:00
# ifdef SONAME_LIBXI
2004-01-09 01:03:00 +01:00
# include <X11/Xlib.h>
# include <X11/extensions/XInput.h>
2005-02-26 18:49:38 +01:00
static int motion_type ;
static int button_press_type ;
static int button_release_type ;
static int key_press_type ;
static int key_release_type ;
static int proximity_in_type ;
static int proximity_out_type ;
2004-01-09 01:03:00 +01:00
static HWND hwndTabletDefault ;
static WTPACKET gMsgPacket ;
static DWORD gSerial ;
2019-04-10 05:42:53 +02:00
static WTPACKET last_packet ;
2004-01-09 01:03:00 +01:00
2008-05-31 22:34:57 +02:00
/* Reference: http://www.wacomeng.com/devsupport/ibmpc/gddevpc.html
*
* Cursors come in sets of 3 normally
* Cursor # 0 = puck device 1
* Cursor # 1 = stylus device 1
* Cursor # 2 = eraser device 1
* Cursor # 3 = puck device 2
* Cursor # 4 = stylus device 2
* Cursor # 5 = eraser device 2
* etc . . . .
*
* A dual tracking / multimode tablet is one
* that supports 2 independent cursors of the same or
* different types simultaneously on a single tablet .
* This makes our cursor layout potentially like this
* Cursor # 0 = puck 1 device 1
* Cursor # 1 = stylus 1 device 1
* Cursor # 2 = eraser 1 device 1
* Cursor # 3 = puck 2 device 1
* Cursor # 4 = stylus 2 device 1
* Cursor # 5 = eraser 2 device 1
* Cursor # 6 = puck 1 device 2
* etc . . . . .
*
* So with multimode tablets we could potentially need
2011-08-02 22:20:32 +02:00
* 2 slots of the same type per tablet i . e .
* you are using 2 styluses at once so they would
2008-05-31 22:34:57 +02:00
* get placed in Cursors # 1 and Cursor # 4
*
* Now say someone has 2 multimode tablets with 2 erasers each
* now we would need Cursor # 2 , # 5 , # 8 , # 11
* So to support that we need CURSORMAX of 12 ( 0 to 11 )
2008-07-10 00:25:28 +02:00
* FIXME : we don ' t support more than 4 regular tablets or 2 multimode tablets */
2008-05-31 23:48:19 +02:00
# define CURSORMAX 12
2008-09-11 22:14:22 +02:00
static INT button_state [ CURSORMAX ] ;
2004-01-09 01:03:00 +01:00
2007-09-20 22:01:06 +02:00
static LOGCONTEXTW gSysContext ;
2004-01-09 01:03:00 +01:00
static WTI_DEVICES_INFO gSysDevice ;
static WTI_CURSORS_INFO gSysCursor [ CURSORMAX ] ;
2008-05-31 23:16:23 +02:00
static INT gNumCursors ; /* do NOT use this to iterate through gSysCursor slots */
2004-01-09 01:03:00 +01:00
/* XInput stuff */
static void * xinput_handle ;
# define MAKE_FUNCPTR(f) static typeof(f) * p##f;
MAKE_FUNCPTR ( XListInputDevices )
2005-03-10 12:48:28 +01:00
MAKE_FUNCPTR ( XFreeDeviceList )
2004-01-09 01:03:00 +01:00
MAKE_FUNCPTR ( XOpenDevice )
MAKE_FUNCPTR ( XQueryDeviceState )
MAKE_FUNCPTR ( XGetDeviceButtonMapping )
MAKE_FUNCPTR ( XCloseDevice )
MAKE_FUNCPTR ( XSelectExtensionEvent )
MAKE_FUNCPTR ( XFreeDeviceState )
# undef MAKE_FUNCPTR
static INT X11DRV_XInput_Init ( void )
{
2020-04-06 22:43:15 +02:00
xinput_handle = dlopen ( SONAME_LIBXI , RTLD_NOW ) ;
2004-01-09 01:03:00 +01:00
if ( xinput_handle )
{
2020-04-06 22:43:15 +02:00
# define LOAD_FUNCPTR(f) if((p##f = dlsym(xinput_handle, #f)) == NULL) goto sym_not_found
LOAD_FUNCPTR ( XListInputDevices ) ;
LOAD_FUNCPTR ( XFreeDeviceList ) ;
LOAD_FUNCPTR ( XOpenDevice ) ;
LOAD_FUNCPTR ( XGetDeviceButtonMapping ) ;
LOAD_FUNCPTR ( XCloseDevice ) ;
LOAD_FUNCPTR ( XSelectExtensionEvent ) ;
LOAD_FUNCPTR ( XQueryDeviceState ) ;
LOAD_FUNCPTR ( XFreeDeviceState ) ;
2004-01-09 01:03:00 +01:00
# undef LOAD_FUNCPTR
return 1 ;
}
sym_not_found :
return 0 ;
}
2004-01-30 23:56:06 +01:00
static int Tablet_ErrorHandler ( Display * dpy , XErrorEvent * event , void * arg )
{
return 1 ;
}
2007-12-23 17:55:50 +01:00
static void trace_axes ( XValuatorInfoPtr val )
{
int i ;
XAxisInfoPtr axis ;
for ( i = 0 , axis = val - > axes ; i < val - > num_axes ; i + + , axis + + )
TRACE ( " Axis %d: [resolution %d|min_value %d|max_value %d] \n " , i , axis - > resolution , axis - > min_value , axis - > max_value ) ;
}
2008-12-03 12:10:32 +01:00
static BOOL match_token ( const char * haystack , const char * needle )
2007-12-31 16:49:19 +01:00
{
const char * p , * q ;
for ( p = haystack ; * p ; )
{
while ( * p & & isspace ( * p ) )
p + + ;
if ( ! * p )
break ;
for ( q = needle ; * q & & * p & & tolower ( * p ) = = tolower ( * q ) ; q + + )
p + + ;
if ( ! * q & & ( isspace ( * p ) | | ! * p ) )
return TRUE ;
while ( * p & & ! isspace ( * p ) )
p + + ;
}
return FALSE ;
}
/* Determining if an X device is a Tablet style device is an imperfect science.
* * We rely on common conventions around device names as well as the type reported
* * by Wacom tablets . This code will likely need to be expanded for alternate tablet types
2008-05-31 22:34:57 +02:00
* *
* * Wintab refers to any device that interacts with the tablet as a cursor ,
* * ( stylus , eraser , tablet mouse , airbrush , etc )
* * this is not to be confused with wacom x11 configuration " cursor " device .
* * Wacoms x11 config " cursor " refers to its device slot ( which we mirror with
* * our gSysCursors ) for puck like devices ( tablet mice essentially ) .
2007-12-31 16:49:19 +01:00
*/
2008-03-13 16:56:05 +01:00
static BOOL is_tablet_cursor ( const char * name , const char * type )
2007-12-31 16:49:19 +01:00
{
2008-03-13 16:56:05 +01:00
int i ;
static const char * tablet_cursor_whitelist [ ] = {
" wacom " ,
" wizardpen " ,
" acecad " ,
" tablet " ,
" cursor " ,
" stylus " ,
" eraser " ,
" pad " ,
NULL
} ;
for ( i = 0 ; tablet_cursor_whitelist [ i ] ! = NULL ; i + + ) {
if ( name & & match_token ( name , tablet_cursor_whitelist [ i ] ) )
return TRUE ;
if ( type & & match_token ( type , tablet_cursor_whitelist [ i ] ) )
return TRUE ;
}
2007-12-31 16:49:19 +01:00
return FALSE ;
}
2014-03-31 15:54:10 +02:00
static UINT get_cursor_type ( const char * name , const char * type )
2007-12-31 16:49:19 +01:00
{
2008-04-17 16:48:50 +02:00
int i ;
static const char * tablet_stylus_whitelist [ ] = {
" stylus " ,
" wizardpen " ,
2008-05-26 19:09:17 +02:00
" acecad " ,
2013-05-16 02:59:36 +02:00
" pen " ,
2008-04-17 16:48:50 +02:00
NULL
} ;
2014-03-31 15:54:10 +02:00
/* First check device type to avoid cases where name is "Pen and Eraser" and type is "ERASER" */
2008-04-17 16:48:50 +02:00
for ( i = 0 ; tablet_stylus_whitelist [ i ] ! = NULL ; i + + ) {
if ( type & & match_token ( type , tablet_stylus_whitelist [ i ] ) )
2014-03-31 15:54:10 +02:00
return CSR_TYPE_PEN ;
2008-04-17 16:48:50 +02:00
}
2007-12-31 16:49:19 +01:00
if ( type & & match_token ( type , " eraser " ) )
2014-03-31 15:54:10 +02:00
return CSR_TYPE_ERASER ;
for ( i = 0 ; tablet_stylus_whitelist [ i ] ! = NULL ; i + + ) {
if ( name & & match_token ( name , tablet_stylus_whitelist [ i ] ) )
return CSR_TYPE_PEN ;
}
if ( name & & match_token ( name , " eraser " ) )
return CSR_TYPE_ERASER ;
return CSR_TYPE_OTHER ;
2007-12-31 16:49:19 +01:00
}
2008-05-31 23:48:19 +02:00
/* cursors are placed in gSysCursor rows depending on their type
* see CURSORMAX comments for more detail */
static BOOL add_system_cursor ( LPWTI_CURSORS_INFO cursor )
{
UINT offset = 0 ;
if ( cursor - > TYPE = = CSR_TYPE_PEN )
offset = 1 ;
else if ( cursor - > TYPE = = CSR_TYPE_ERASER )
offset = 2 ;
for ( ; offset < CURSORMAX ; offset + = 3 )
{
if ( ! gSysCursor [ offset ] . ACTIVE )
{
gSysCursor [ offset ] = * cursor ;
+ + gNumCursors ;
return TRUE ;
}
}
return FALSE ;
}
2008-05-31 23:16:23 +02:00
static void disable_system_cursors ( void )
{
UINT i ;
for ( i = 0 ; i < CURSORMAX ; + + i )
{
gSysCursor [ i ] . ACTIVE = 0 ;
}
gNumCursors = 0 ;
}
2007-12-31 16:49:19 +01:00
2008-02-04 23:59:55 +01:00
/***********************************************************************
* X11DRV_LoadTabletInfo ( X11DRV . @ )
*/
2011-03-03 09:26:33 +01:00
BOOL CDECL X11DRV_LoadTabletInfo ( HWND hwnddefault )
2004-01-09 01:03:00 +01:00
{
2018-12-03 00:07:56 +01:00
static const WCHAR SZ_CONTEXT_NAME [ ] = { ' W ' , ' i ' , ' n ' , ' e ' , ' ' , ' T ' , ' a ' , ' b ' , ' l ' , ' e ' , ' t ' , ' ' , ' C ' , ' o ' , ' n ' , ' t ' , ' e ' , ' x ' , ' t ' , 0 } ;
static const WCHAR SZ_DEVICE_NAME [ ] = { ' W ' , ' i ' , ' n ' , ' e ' , ' ' , ' T ' , ' a ' , ' b ' , ' l ' , ' e ' , ' t ' , ' ' , ' D ' , ' e ' , ' v ' , ' i ' , ' c ' , ' e ' , 0 } ;
2018-12-03 00:07:57 +01:00
static const WCHAR SZ_NON_PLUG_N_PLAY [ ] = { ' n ' , ' o ' , ' n ' , ' - ' , ' p ' , ' l ' , ' u ' , ' g ' , ' - ' , ' n ' , ' - ' , ' p ' , ' l ' , ' a ' , ' y ' , 0 } ;
2007-09-20 22:01:06 +02:00
2008-06-26 15:08:08 +02:00
struct x11drv_thread_data * data = x11drv_init_thread_data ( ) ;
2004-01-09 01:03:00 +01:00
int num_devices ;
int loop ;
XDeviceInfo * devices ;
XDeviceInfo * target = NULL ;
BOOL axis_read_complete = FALSE ;
XAnyClassPtr any ;
XButtonInfoPtr Button ;
XValuatorInfoPtr Val ;
XAxisInfoPtr Axis ;
XDevice * opendevice ;
if ( ! X11DRV_XInput_Init ( ) )
{
2008-01-04 20:37:14 +01:00
ERR ( " Unable to initialize the XInput library. \n " ) ;
2011-03-03 09:26:33 +01:00
return FALSE ;
2004-01-09 01:03:00 +01:00
}
hwndTabletDefault = hwnddefault ;
2008-01-04 20:37:14 +01:00
/* Do base initialization */
2007-09-20 22:01:06 +02:00
strcpyW ( gSysContext . lcName , SZ_CONTEXT_NAME ) ;
strcpyW ( gSysDevice . NAME , SZ_DEVICE_NAME ) ;
2004-01-09 01:03:00 +01:00
2005-01-24 14:33:23 +01:00
gSysContext . lcOptions = CXO_SYSTEM ;
2004-01-09 01:03:00 +01:00
gSysContext . lcLocks = CXL_INSIZE | CXL_INASPECT | CXL_MARGIN |
CXL_SENSITIVITY | CXL_SYSOUT ;
gSysContext . lcMsgBase = WT_DEFBASE ;
gSysContext . lcDevice = 0 ;
gSysContext . lcPktData =
PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER | PK_TIME | PK_CURSOR |
PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION ;
gSysContext . lcMoveMask =
PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION ;
gSysContext . lcStatus = CXS_ONTOP ;
gSysContext . lcPktRate = 100 ;
gSysContext . lcBtnDnMask = 0xffffffff ;
gSysContext . lcBtnUpMask = 0xffffffff ;
gSysContext . lcSensX = 65536 ;
gSysContext . lcSensY = 65536 ;
gSysContext . lcSensX = 65536 ;
gSysContext . lcSensZ = 65536 ;
gSysContext . lcSysSensX = 65536 ;
gSysContext . lcSysSensY = 65536 ;
2019-11-25 08:03:00 +01:00
gSysContext . lcSysExtX = GetSystemMetrics ( SM_CXVIRTUALSCREEN ) ;
gSysContext . lcSysExtY = GetSystemMetrics ( SM_CYVIRTUALSCREEN ) ;
2004-01-09 01:03:00 +01:00
2008-05-31 23:16:23 +02:00
/* initialize cursors */
disable_system_cursors ( ) ;
2004-01-09 01:03:00 +01:00
/* Device Defaults */
gSysDevice . HARDWARE = HWC_HARDPROX | HWC_PHYSID_CURSORS ;
gSysDevice . FIRSTCSR = 0 ;
gSysDevice . PKTRATE = 100 ;
gSysDevice . PKTDATA =
PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER | PK_TIME | PK_CURSOR |
PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION ;
2018-12-03 00:07:57 +01:00
strcpyW ( gSysDevice . PNPID , SZ_NON_PLUG_N_PLAY ) ;
2004-01-09 01:03:00 +01:00
devices = pXListInputDevices ( data - > display , & num_devices ) ;
if ( ! devices )
{
2011-03-03 09:26:33 +01:00
WARN ( " XInput Extensions reported as not available \n " ) ;
return FALSE ;
2004-01-09 01:03:00 +01:00
}
2007-12-30 18:41:54 +01:00
TRACE ( " XListInputDevices reports %d devices \n " , num_devices ) ;
2004-01-09 01:03:00 +01:00
for ( loop = 0 ; loop < num_devices ; loop + + )
{
int class_loop ;
2008-01-17 15:23:37 +01:00
char * device_type = devices [ loop ] . type ? XGetAtomName ( data - > display , devices [ loop ] . type ) : NULL ;
2008-05-31 23:48:19 +02:00
WTI_CURSORS_INFO cursor ;
2004-01-09 01:03:00 +01:00
2008-04-25 16:46:17 +02:00
TRACE ( " Device %i: [id %d|name %s|type %s|num_classes %d|use %d] \n " ,
2016-03-14 10:38:02 +01:00
loop , ( int ) devices [ loop ] . id , devices [ loop ] . name , debugstr_a ( device_type ) ,
2008-04-25 16:46:17 +02:00
devices [ loop ] . num_classes , devices [ loop ] . use ) ;
2004-01-09 01:03:00 +01:00
2008-04-25 16:46:17 +02:00
switch ( devices [ loop ] . use )
{
case IsXExtensionDevice :
# ifdef IsXExtensionPointer
case IsXExtensionPointer :
# endif
2008-05-27 07:22:09 +02:00
# ifdef IsXExtensionKeyboard
case IsXExtensionKeyboard :
# endif
TRACE ( " Is XExtension: Device, Keyboard, or Pointer \n " ) ;
2004-01-09 01:03:00 +01:00
target = & devices [ loop ] ;
2007-09-20 22:01:06 +02:00
if ( strlen ( target - > name ) > = WT_MAX_NAME_LEN )
{
ERR ( " Input device '%s' name too long - skipping \n " , wine_dbgstr_a ( target - > name ) ) ;
2008-04-25 16:46:17 +02:00
break ;
2007-09-20 22:01:06 +02:00
}
2007-02-04 17:43:39 +01:00
X11DRV_expect_error ( data - > display , Tablet_ErrorHandler , NULL ) ;
2004-01-09 01:03:00 +01:00
opendevice = pXOpenDevice ( data - > display , target - > id ) ;
2007-02-04 17:43:39 +01:00
if ( ! X11DRV_check_error ( ) & & opendevice )
2004-01-09 01:03:00 +01:00
{
unsigned char map [ 32 ] ;
int i ;
int shft = 0 ;
2004-01-30 23:56:06 +01:00
X11DRV_expect_error ( data - > display , Tablet_ErrorHandler , NULL ) ;
2008-05-31 23:48:19 +02:00
cursor . BUTTONS = pXGetDeviceButtonMapping ( data - > display , opendevice , map , 32 ) ;
if ( X11DRV_check_error ( ) | | cursor . BUTTONS < = 0 )
2004-01-30 23:56:06 +01:00
{
TRACE ( " No buttons, Non Tablet Device \n " ) ;
pXCloseDevice ( data - > display , opendevice ) ;
2008-04-25 16:46:17 +02:00
break ;
2004-01-30 23:56:06 +01:00
}
2004-01-09 01:03:00 +01:00
2008-05-31 23:48:19 +02:00
for ( i = 0 ; i < cursor . BUTTONS ; i + + , shft + + )
2004-01-09 01:03:00 +01:00
{
2008-05-31 23:48:19 +02:00
cursor . BUTTONMAP [ i ] = map [ i ] ;
cursor . SYSBTNMAP [ i ] = ( 1 < < shft ) ;
2004-01-09 01:03:00 +01:00
}
pXCloseDevice ( data - > display , opendevice ) ;
}
else
{
WARN ( " Unable to open device %s \n " , target - > name ) ;
2008-04-25 16:46:17 +02:00
break ;
2004-01-09 01:03:00 +01:00
}
2008-05-31 23:48:19 +02:00
MultiByteToWideChar ( CP_UNIXCP , 0 , target - > name , - 1 , cursor . NAME , WT_MAX_NAME_LEN ) ;
2004-01-09 01:03:00 +01:00
2008-03-13 16:56:05 +01:00
if ( ! is_tablet_cursor ( target - > name , device_type ) )
2007-12-31 16:49:19 +01:00
{
2008-03-18 11:29:47 +01:00
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 " ,
2016-03-14 10:38:02 +01:00
loop , devices [ loop ] . name , debugstr_a ( device_type ) ) ;
2008-04-25 16:46:17 +02:00
break ;
2007-12-31 16:49:19 +01:00
}
2008-05-31 23:48:19 +02:00
cursor . ACTIVE = 1 ;
cursor . PKTDATA = PK_TIME | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y |
2004-01-09 01:03:00 +01:00
PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE |
PK_ORIENTATION ;
2008-05-31 23:48:19 +02:00
cursor . PHYSID = target - > id ;
cursor . NPBUTTON = 1 ;
cursor . NPBTNMARKS [ 0 ] = 0 ;
cursor . NPBTNMARKS [ 1 ] = 1 ;
cursor . CAPABILITIES = CRC_MULTIMODE ;
2008-05-31 22:51:46 +02:00
2014-03-31 15:54:10 +02:00
cursor . TYPE = get_cursor_type ( target - > name , device_type ) ;
2004-01-09 01:03:00 +01:00
2008-02-02 18:27:19 +01:00
any = target - > inputclassinfo ;
2004-01-09 01:03:00 +01:00
for ( class_loop = 0 ; class_loop < target - > num_classes ; class_loop + + )
{
switch ( any - > class )
{
2007-12-23 17:55:50 +01:00
2004-01-09 01:03:00 +01:00
case ValuatorClass :
2007-12-23 17:55:50 +01:00
Val = ( XValuatorInfoPtr ) any ;
TRACE ( " ValidatorInput %d: [class %d|length %d|num_axes %d|mode %d|motion_buffer %ld] \n " ,
class_loop , ( int ) Val - > class , Val - > length , Val - > num_axes , Val - > mode , Val - > motion_buffer ) ;
if ( TRACE_ON ( wintab32 ) )
trace_axes ( Val ) ;
2007-12-23 17:56:03 +01:00
/* FIXME: This is imperfect; we compute our devices capabilities based upon the
* * first pen type device we find . However , a more correct implementation
* * would require acquiring a wide variety of tablets and running through
* * the various inputs to see what the values are . Odds are that a
* * more ' correct ' algorithm would condense to this one anyway .
*/
2008-05-31 23:48:19 +02:00
if ( ! axis_read_complete & & cursor . TYPE = = CSR_TYPE_PEN )
2004-01-09 01:03:00 +01:00
{
Axis = ( XAxisInfoPtr ) ( ( char * ) Val + sizeof
( XValuatorInfo ) ) ;
if ( Val - > num_axes > = 1 )
{
/* Axis 1 is X */
gSysDevice . X . axMin = Axis - > min_value ;
gSysDevice . X . axMax = Axis - > max_value ;
2005-01-24 14:33:23 +01:00
gSysDevice . X . axUnits = TU_INCHES ;
2004-01-09 01:03:00 +01:00
gSysDevice . X . axResolution = Axis - > resolution ;
gSysContext . lcInOrgX = Axis - > min_value ;
2019-11-25 08:03:00 +01:00
gSysContext . lcOutOrgX = Axis - > min_value ;
2004-01-09 01:03:00 +01:00
gSysContext . lcInExtX = Axis - > max_value ;
2019-11-25 08:03:00 +01:00
gSysContext . lcOutExtX = Axis - > max_value ;
2004-01-09 01:03:00 +01:00
Axis + + ;
}
if ( Val - > num_axes > = 2 )
{
/* Axis 2 is Y */
gSysDevice . Y . axMin = Axis - > min_value ;
gSysDevice . Y . axMax = Axis - > max_value ;
2005-01-24 14:33:23 +01:00
gSysDevice . Y . axUnits = TU_INCHES ;
2004-01-09 01:03:00 +01:00
gSysDevice . Y . axResolution = Axis - > resolution ;
gSysContext . lcInOrgY = Axis - > min_value ;
2019-11-25 08:03:00 +01:00
gSysContext . lcOutOrgY = Axis - > min_value ;
2004-01-09 01:03:00 +01:00
gSysContext . lcInExtY = Axis - > max_value ;
2019-11-25 08:03:00 +01:00
gSysContext . lcOutExtY = Axis - > max_value ;
2004-01-09 01:03:00 +01:00
Axis + + ;
}
if ( Val - > num_axes > = 3 )
{
/* Axis 3 is Normal Pressure */
gSysDevice . NPRESSURE . axMin = Axis - > min_value ;
gSysDevice . NPRESSURE . axMax = Axis - > max_value ;
2005-01-24 14:33:23 +01:00
gSysDevice . NPRESSURE . axUnits = TU_INCHES ;
2004-01-09 01:03:00 +01:00
gSysDevice . NPRESSURE . axResolution =
Axis - > resolution ;
Axis + + ;
}
if ( Val - > num_axes > = 5 )
{
/* Axis 4 and 5 are X and Y tilt */
XAxisInfoPtr XAxis = Axis ;
Axis + + ;
if ( max ( abs ( Axis - > max_value ) ,
abs ( XAxis - > max_value ) ) )
{
gSysDevice . ORIENTATION [ 0 ] . axMin = 0 ;
gSysDevice . ORIENTATION [ 0 ] . axMax = 3600 ;
2005-01-24 14:33:23 +01:00
gSysDevice . ORIENTATION [ 0 ] . axUnits = TU_CIRCLE ;
gSysDevice . ORIENTATION [ 0 ] . axResolution
= CASTFIX32 ( 3600 ) ;
2004-01-09 01:03:00 +01:00
gSysDevice . ORIENTATION [ 1 ] . axMin = - 1000 ;
gSysDevice . ORIENTATION [ 1 ] . axMax = 1000 ;
2005-01-24 14:33:23 +01:00
gSysDevice . ORIENTATION [ 1 ] . axUnits = TU_CIRCLE ;
gSysDevice . ORIENTATION [ 1 ] . axResolution
= CASTFIX32 ( 3600 ) ;
2019-04-23 05:39:41 +02:00
gSysDevice . ORIENTATION [ 2 ] . axMin = 0 ;
gSysDevice . ORIENTATION [ 2 ] . axMax = 3600 ;
gSysDevice . ORIENTATION [ 2 ] . axUnits = TU_CIRCLE ;
gSysDevice . ORIENTATION [ 2 ] . axResolution
= CASTFIX32 ( 3600 ) ;
2004-01-09 01:03:00 +01:00
Axis + + ;
}
}
axis_read_complete = TRUE ;
}
break ;
case ButtonClass :
{
2007-09-20 22:01:06 +02:00
int cchBuf = 512 ;
int cchPos = 0 ;
2004-01-09 01:03:00 +01:00
int i ;
Button = ( XButtonInfoPtr ) any ;
2007-12-24 20:35:13 +01:00
TRACE ( " ButtonInput %d: [class %d|length %d|num_buttons %d] \n " ,
class_loop , ( int ) Button - > class , Button - > length , Button - > num_buttons ) ;
2008-05-31 23:48:19 +02:00
cursor . BTNNAMES = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( WCHAR ) * cchBuf ) ;
for ( i = 0 ; i < cursor . BUTTONS ; i + + )
2004-01-09 01:03:00 +01:00
{
2007-09-20 22:01:06 +02:00
/* FIXME - these names are probably incorrect */
2008-05-31 23:48:19 +02:00
int cch = strlenW ( cursor . NAME ) + 1 ;
2007-09-20 22:01:06 +02:00
while ( cch > cchBuf - cchPos - 1 ) /* we want one extra byte for the last NUL */
{
cchBuf * = 2 ;
2008-05-31 23:48:19 +02:00
cursor . BTNNAMES = HeapReAlloc ( GetProcessHeap ( ) , 0 , cursor . BTNNAMES , sizeof ( WCHAR ) * cchBuf ) ;
2007-09-20 22:01:06 +02:00
}
2008-05-31 23:48:19 +02:00
strcpyW ( cursor . BTNNAMES + cchPos , cursor . NAME ) ;
2007-09-20 22:01:06 +02:00
cchPos + = cch ;
2004-01-09 01:03:00 +01:00
}
2008-05-31 23:48:19 +02:00
cursor . BTNNAMES [ cchPos + + ] = 0 ;
cursor . BTNNAMES = HeapReAlloc ( GetProcessHeap ( ) , 0 , cursor . BTNNAMES , sizeof ( WCHAR ) * cchPos ) ;
cursor . cchBTNNAMES = cchPos ;
2004-01-09 01:03:00 +01:00
}
break ;
2008-05-31 23:48:19 +02:00
} /* switch any->class */
2004-01-09 01:03:00 +01:00
any = ( XAnyClassPtr ) ( ( char * ) any + any - > length ) ;
2008-05-31 23:48:19 +02:00
} /* for class_loop */
if ( ! add_system_cursor ( & cursor ) )
FIXME ( " Skipping this cursor due to lack of system cursor slots. \n " ) ;
2008-04-25 16:46:17 +02:00
break ;
2008-05-31 23:48:19 +02:00
} /* switch devices.use */
2007-12-31 16:49:19 +01:00
XFree ( device_type ) ;
2008-05-31 23:48:19 +02:00
} /* for XListInputDevices */
2005-03-10 12:48:28 +01:00
pXFreeDeviceList ( devices ) ;
2007-12-31 17:00:13 +01:00
2018-10-22 00:46:32 +02:00
if ( ! axis_read_complete )
2007-12-31 17:00:13 +01:00
{
2008-05-31 23:48:19 +02:00
disable_system_cursors ( ) ;
WARN ( " Did not find a valid stylus, unable to determine system context parameters. Wintab is disabled. \n " ) ;
2018-10-22 00:46:32 +02:00
return FALSE ;
2007-12-31 17:00:13 +01:00
}
2018-10-22 00:46:32 +02:00
gSysDevice . NCSRTYPES = gNumCursors ;
2011-03-03 09:26:33 +01:00
return TRUE ;
2004-01-09 01:03:00 +01:00
}
static int figure_deg ( int x , int y )
{
2008-03-06 21:33:09 +01:00
float angle ;
2004-01-09 01:03:00 +01:00
2008-03-06 21:33:09 +01:00
angle = atan2 ( ( float ) y , ( float ) x ) ;
angle + = M_PI_2 ;
if ( angle < = 0 )
angle + = 2 * M_PI ;
2004-01-09 01:03:00 +01:00
2008-03-06 21:33:09 +01:00
return ( 0.5 + ( angle * 1800.0 / M_PI ) ) ;
2004-01-09 01:03:00 +01:00
}
2007-12-23 17:55:19 +01:00
static int get_button_state ( int curnum )
2004-01-09 01:03:00 +01:00
{
2007-12-23 17:55:19 +01:00
return button_state [ curnum ] ;
2004-01-09 01:03:00 +01:00
}
2007-12-23 17:55:19 +01:00
static void set_button_state ( int curnum , XID deviceid )
2004-01-09 01:03:00 +01:00
{
struct x11drv_thread_data * data = x11drv_thread_data ( ) ;
XDevice * device ;
XDeviceState * state ;
XInputClass * class ;
int loop ;
int rc = 0 ;
device = pXOpenDevice ( data - > display , deviceid ) ;
state = pXQueryDeviceState ( data - > display , device ) ;
if ( state )
{
class = state - > data ;
for ( loop = 0 ; loop < state - > num_classes ; loop + + )
{
if ( class - > class = = ButtonClass )
{
int loop2 ;
XButtonState * button_state = ( XButtonState * ) class ;
2007-08-30 21:41:37 +02:00
for ( loop2 = 0 ; loop2 < button_state - > num_buttons ; loop2 + + )
2004-01-09 01:03:00 +01:00
{
if ( button_state - > buttons [ loop2 / 8 ] & ( 1 < < ( loop2 % 8 ) ) )
{
2007-08-30 21:41:37 +02:00
rc | = ( 1 < < loop2 ) ;
2004-01-09 01:03:00 +01:00
}
}
}
class = ( XInputClass * ) ( ( char * ) class + class - > length ) ;
}
}
pXFreeDeviceState ( state ) ;
2007-12-23 17:55:19 +01:00
button_state [ curnum ] = rc ;
}
static int cursor_from_device ( DWORD deviceid , LPWTI_CURSORS_INFO * cursorp )
{
int i ;
2008-05-31 23:16:23 +02:00
for ( i = 0 ; i < CURSORMAX ; i + + )
if ( gSysCursor [ i ] . ACTIVE & & gSysCursor [ i ] . PHYSID = = deviceid )
2007-12-23 17:55:19 +01:00
{
* cursorp = & gSysCursor [ i ] ;
return i ;
}
ERR ( " Could not map device id %d to a cursor \n " , ( int ) deviceid ) ;
return - 1 ;
2004-01-09 01:03:00 +01:00
}
2019-04-10 05:42:53 +02:00
static DWORD get_changed_state ( WTPACKET * pkt )
{
DWORD change = 0 ;
if ( pkt - > pkX ! = last_packet . pkX )
change | = PK_X ;
if ( pkt - > pkY ! = last_packet . pkY )
change | = PK_Y ;
if ( pkt - > pkZ ! = last_packet . pkZ )
change | = PK_Z ;
if ( pkt - > pkSerialNumber ! = last_packet . pkSerialNumber )
change | = PK_SERIAL_NUMBER ;
if ( pkt - > pkTime ! = last_packet . pkTime )
change | = PK_TIME ;
if ( pkt - > pkNormalPressure ! = last_packet . pkNormalPressure )
change | = PK_NORMAL_PRESSURE ;
if ( pkt - > pkTangentPressure ! = last_packet . pkTangentPressure )
change | = PK_TANGENT_PRESSURE ;
if ( pkt - > pkCursor ! = last_packet . pkCursor )
change | = PK_CURSOR ;
if ( pkt - > pkButtons ! = last_packet . pkButtons )
change | = PK_BUTTONS ;
if ( pkt - > pkOrientation . orAzimuth ! = last_packet . pkOrientation . orAzimuth | |
pkt - > pkOrientation . orAltitude ! = last_packet . pkOrientation . orAltitude | |
pkt - > pkOrientation . orTwist ! = last_packet . pkOrientation . orTwist )
change | = PK_ORIENTATION ;
if ( pkt - > pkRotation . roPitch ! = last_packet . pkRotation . roPitch | |
pkt - > pkRotation . roRoll ! = last_packet . pkRotation . roRoll | |
pkt - > pkRotation . roYaw ! = last_packet . pkRotation . roYaw )
change | = PK_ROTATION ;
return change ;
}
2016-08-23 15:13:26 +02:00
static BOOL motion_event ( HWND hwnd , XEvent * event )
2004-01-09 01:03:00 +01:00
{
2005-02-26 18:49:38 +01:00
XDeviceMotionEvent * motion = ( XDeviceMotionEvent * ) event ;
2007-12-23 17:55:19 +01:00
LPWTI_CURSORS_INFO cursor ;
int curnum = cursor_from_device ( motion - > deviceid , & cursor ) ;
if ( curnum < 0 )
2016-08-23 15:13:26 +02:00
return FALSE ;
2005-02-26 18:49:38 +01:00
2004-01-09 01:03:00 +01:00
memset ( & gMsgPacket , 0 , sizeof ( WTPACKET ) ) ;
2007-12-23 17:55:19 +01:00
TRACE ( " Received tablet motion event (%p); device id %d, cursor num %d \n " , hwnd , ( int ) motion - > deviceid , curnum ) ;
2005-02-26 18:49:38 +01:00
/* Set cursor to inverted if cursor is the eraser */
2007-12-24 22:10:43 +01:00
gMsgPacket . pkStatus = ( cursor - > TYPE = = CSR_TYPE_ERASER ? TPS_INVERT : 0 ) ;
2005-02-26 18:49:38 +01:00
gMsgPacket . pkTime = EVENT_x11_time_to_win32_time ( motion - > time ) ;
gMsgPacket . pkSerialNumber = gSerial + + ;
2007-12-23 17:55:19 +01:00
gMsgPacket . pkCursor = curnum ;
2005-02-26 18:49:38 +01:00
gMsgPacket . pkX = motion - > axis_data [ 0 ] ;
gMsgPacket . pkY = motion - > axis_data [ 1 ] ;
gMsgPacket . pkOrientation . orAzimuth = figure_deg ( motion - > axis_data [ 3 ] , motion - > axis_data [ 4 ] ) ;
gMsgPacket . pkOrientation . orAltitude = ( ( 1000 - 15 * max
( abs ( motion - > axis_data [ 3 ] ) ,
abs ( motion - > axis_data [ 4 ] ) ) )
* ( gMsgPacket . pkStatus & TPS_INVERT ? - 1 : 1 ) ) ;
gMsgPacket . pkNormalPressure = motion - > axis_data [ 2 ] ;
2007-12-23 17:55:19 +01:00
gMsgPacket . pkButtons = get_button_state ( curnum ) ;
2019-04-10 05:42:53 +02:00
gMsgPacket . pkChanged = get_changed_state ( & gMsgPacket ) ;
2008-05-07 05:12:56 +02:00
SendMessageW ( hwndTabletDefault , WT_PACKET , gMsgPacket . pkSerialNumber , ( LPARAM ) hwnd ) ;
2019-04-10 05:42:53 +02:00
last_packet = gMsgPacket ;
2016-08-23 15:13:26 +02:00
return TRUE ;
2005-02-26 18:49:38 +01:00
}
2016-08-23 15:13:26 +02:00
static BOOL button_event ( HWND hwnd , XEvent * event )
2005-02-26 18:49:38 +01:00
{
XDeviceButtonEvent * button = ( XDeviceButtonEvent * ) event ;
2007-12-23 17:55:19 +01:00
LPWTI_CURSORS_INFO cursor ;
int curnum = cursor_from_device ( button - > deviceid , & cursor ) ;
if ( curnum < 0 )
2016-08-23 15:13:26 +02:00
return FALSE ;
2005-02-26 18:49:38 +01:00
memset ( & gMsgPacket , 0 , sizeof ( WTPACKET ) ) ;
TRACE ( " Received tablet button %s event \n " , ( event - > type = = button_press_type ) ? " press " : " release " ) ;
/* Set cursor to inverted if cursor is the eraser */
2007-12-24 22:10:43 +01:00
gMsgPacket . pkStatus = ( cursor - > TYPE = = CSR_TYPE_ERASER ? TPS_INVERT : 0 ) ;
2007-12-23 17:55:19 +01:00
set_button_state ( curnum , button - > deviceid ) ;
2005-02-26 18:49:38 +01:00
gMsgPacket . pkTime = EVENT_x11_time_to_win32_time ( button - > time ) ;
gMsgPacket . pkSerialNumber = gSerial + + ;
2007-12-23 17:55:19 +01:00
gMsgPacket . pkCursor = curnum ;
2019-11-20 08:23:22 +01:00
if ( button - > axes_count > 0 ) {
gMsgPacket . pkX = button - > axis_data [ 0 ] ;
gMsgPacket . pkY = button - > axis_data [ 1 ] ;
gMsgPacket . pkOrientation . orAzimuth = figure_deg ( button - > axis_data [ 3 ] , button - > axis_data [ 4 ] ) ;
gMsgPacket . pkOrientation . orAltitude = ( ( 1000 - 15 * max ( abs ( button - > axis_data [ 3 ] ) ,
abs ( button - > axis_data [ 4 ] ) ) )
* ( gMsgPacket . pkStatus & TPS_INVERT ? - 1 : 1 ) ) ;
gMsgPacket . pkNormalPressure = button - > axis_data [ 2 ] ;
} else {
gMsgPacket . pkX = last_packet . pkX ;
gMsgPacket . pkY = last_packet . pkY ;
gMsgPacket . pkOrientation = last_packet . pkOrientation ;
gMsgPacket . pkNormalPressure = last_packet . pkNormalPressure ;
}
2007-12-23 17:55:19 +01:00
gMsgPacket . pkButtons = get_button_state ( curnum ) ;
2019-04-10 05:42:53 +02:00
gMsgPacket . pkChanged = get_changed_state ( & gMsgPacket ) ;
2008-05-07 05:12:56 +02:00
SendMessageW ( hwndTabletDefault , WT_PACKET , gMsgPacket . pkSerialNumber , ( LPARAM ) hwnd ) ;
2019-04-10 05:42:53 +02:00
last_packet = gMsgPacket ;
2016-08-23 15:13:26 +02:00
return TRUE ;
2005-02-26 18:49:38 +01:00
}
2016-08-23 15:13:26 +02:00
static BOOL key_event ( HWND hwnd , XEvent * event )
2005-02-26 18:49:38 +01:00
{
if ( event - > type = = key_press_type )
2004-01-09 01:03:00 +01:00
FIXME ( " Received tablet key press event \n " ) ;
else
2005-02-26 18:49:38 +01:00
FIXME ( " Received tablet key release event \n " ) ;
2016-08-23 15:13:26 +02:00
return FALSE ;
2005-02-26 18:49:38 +01:00
}
2004-01-09 01:03:00 +01:00
2016-08-23 15:13:26 +02:00
static BOOL proximity_event ( HWND hwnd , XEvent * event )
2005-02-26 18:49:38 +01:00
{
XProximityNotifyEvent * proximity = ( XProximityNotifyEvent * ) event ;
2007-12-23 17:55:19 +01:00
LPWTI_CURSORS_INFO cursor ;
int curnum = cursor_from_device ( proximity - > deviceid , & cursor ) ;
2008-05-07 22:58:49 +02:00
LPARAM proximity_info ;
TRACE ( " hwnd=%p \n " , hwnd ) ;
2007-12-23 17:55:19 +01:00
if ( curnum < 0 )
2016-08-23 15:13:26 +02:00
return FALSE ;
2005-02-26 18:49:38 +01:00
memset ( & gMsgPacket , 0 , sizeof ( WTPACKET ) ) ;
/* Set cursor to inverted if cursor is the eraser */
2007-12-24 22:10:43 +01:00
gMsgPacket . pkStatus = ( cursor - > TYPE = = CSR_TYPE_ERASER ? TPS_INVERT : 0 ) ;
2005-02-26 18:49:38 +01:00
gMsgPacket . pkStatus | = ( event - > type = = proximity_out_type ) ? TPS_PROXIMITY : 0 ;
gMsgPacket . pkTime = EVENT_x11_time_to_win32_time ( proximity - > time ) ;
gMsgPacket . pkSerialNumber = gSerial + + ;
2007-12-23 17:55:19 +01:00
gMsgPacket . pkCursor = curnum ;
2005-02-26 18:49:38 +01:00
gMsgPacket . pkX = proximity - > axis_data [ 0 ] ;
gMsgPacket . pkY = proximity - > axis_data [ 1 ] ;
gMsgPacket . pkOrientation . orAzimuth = figure_deg ( proximity - > axis_data [ 3 ] , proximity - > axis_data [ 4 ] ) ;
gMsgPacket . pkOrientation . orAltitude = ( ( 1000 - 15 * max ( abs ( proximity - > axis_data [ 3 ] ) ,
abs ( proximity - > axis_data [ 4 ] ) ) )
* ( gMsgPacket . pkStatus & TPS_INVERT ? - 1 : 1 ) ) ;
gMsgPacket . pkNormalPressure = proximity - > axis_data [ 2 ] ;
2007-12-23 17:55:19 +01:00
gMsgPacket . pkButtons = get_button_state ( curnum ) ;
2005-02-26 18:49:38 +01:00
2008-05-07 22:58:49 +02:00
/* FIXME: LPARAM loword is true when cursor entering context, false when leaving context
* This needs to be handled here or in wintab32 . Using the proximity_in_type is not correct
* but kept for now .
* LPARAM hiword is " non-zero when the cursor is leaving or entering hardware proximity "
* WPARAM contains context handle .
* HWND to HCTX is handled by wintab32 .
*/
proximity_info = MAKELPARAM ( ( event - > type = = proximity_in_type ) ,
( event - > type = = proximity_in_type ) | | ( event - > type = = proximity_out_type ) ) ;
SendMessageW ( hwndTabletDefault , WT_PROXIMITY , ( WPARAM ) hwnd , proximity_info ) ;
2016-08-23 15:13:26 +02:00
return TRUE ;
2004-01-09 01:03:00 +01:00
}
2008-02-04 23:59:55 +01:00
/***********************************************************************
* X11DRV_AttachEventQueueToTablet ( X11DRV . @ )
*/
2008-12-16 14:30:37 +01:00
int CDECL X11DRV_AttachEventQueueToTablet ( HWND hOwner )
2004-01-09 01:03:00 +01:00
{
2008-06-26 15:08:08 +02:00
struct x11drv_thread_data * data = x11drv_init_thread_data ( ) ;
2004-01-09 01:03:00 +01:00
int num_devices ;
int loop ;
int cur_loop ;
XDeviceInfo * devices ;
XDeviceInfo * target = NULL ;
XDevice * the_device ;
XEventClass event_list [ 7 ] ;
Window win = X11DRV_get_whole_window ( hOwner ) ;
2011-03-03 09:26:33 +01:00
if ( ! win | | ! xinput_handle ) return 0 ;
2004-01-09 01:03:00 +01:00
TRACE ( " Creating context for window %p (%lx) %i cursors \n " , hOwner , win , gNumCursors ) ;
devices = pXListInputDevices ( data - > display , & num_devices ) ;
2005-03-10 12:48:28 +01:00
X11DRV_expect_error ( data - > display , Tablet_ErrorHandler , NULL ) ;
2008-05-31 23:16:23 +02:00
for ( cur_loop = 0 ; cur_loop < CURSORMAX ; cur_loop + + )
2004-01-09 01:03:00 +01:00
{
2007-09-20 22:01:06 +02:00
char cursorNameA [ WT_MAX_NAME_LEN ] ;
2004-01-09 01:03:00 +01:00
int event_number = 0 ;
2008-05-31 23:16:23 +02:00
if ( ! gSysCursor [ cur_loop ] . ACTIVE ) continue ;
2007-09-20 22:01:06 +02:00
/* the cursor name fits in the buffer because too long names are skipped */
WideCharToMultiByte ( CP_UNIXCP , 0 , gSysCursor [ cur_loop ] . NAME , - 1 , cursorNameA , WT_MAX_NAME_LEN , NULL , NULL ) ;
2004-01-09 01:03:00 +01:00
for ( loop = 0 ; loop < num_devices ; loop + + )
2007-09-20 22:01:06 +02:00
if ( strcmp ( devices [ loop ] . name , cursorNameA ) = = 0 )
2004-01-09 01:03:00 +01:00
target = & devices [ loop ] ;
2009-12-04 09:48:53 +01:00
if ( ! target ) {
WARN ( " Cursor Name %s not found in list of targets. \n " , cursorNameA ) ;
continue ;
}
2004-01-09 01:03:00 +01:00
TRACE ( " Opening cursor %i id %i \n " , cur_loop , ( INT ) target - > id ) ;
the_device = pXOpenDevice ( data - > display , target - > id ) ;
if ( ! the_device )
{
WARN ( " Unable to Open device \n " ) ;
continue ;
}
if ( the_device - > num_classes > 0 )
{
2005-02-26 18:49:38 +01:00
DeviceKeyPress ( the_device , key_press_type , event_list [ event_number ] ) ;
2007-12-23 17:56:16 +01:00
if ( key_press_type ) event_number + + ;
2005-02-26 18:49:38 +01:00
DeviceKeyRelease ( the_device , key_release_type , event_list [ event_number ] ) ;
2007-12-23 17:56:16 +01:00
if ( key_release_type ) event_number + + ;
2005-02-26 18:49:38 +01:00
DeviceButtonPress ( the_device , button_press_type , event_list [ event_number ] ) ;
2007-12-23 17:56:16 +01:00
if ( button_press_type ) event_number + + ;
2005-02-26 18:49:38 +01:00
DeviceButtonRelease ( the_device , button_release_type , event_list [ event_number ] ) ;
2007-12-23 17:56:16 +01:00
if ( button_release_type ) event_number + + ;
2005-02-26 18:49:38 +01:00
DeviceMotionNotify ( the_device , motion_type , event_list [ event_number ] ) ;
2007-12-23 17:56:16 +01:00
if ( motion_type ) event_number + + ;
2005-02-26 18:49:38 +01:00
ProximityIn ( the_device , proximity_in_type , event_list [ event_number ] ) ;
2007-12-23 17:56:16 +01:00
if ( proximity_in_type ) event_number + + ;
2005-02-26 18:49:38 +01:00
ProximityOut ( the_device , proximity_out_type , event_list [ event_number ] ) ;
2007-12-23 17:56:16 +01:00
if ( proximity_out_type ) event_number + + ;
2005-02-26 18:49:38 +01:00
2011-04-06 13:26:42 +02:00
if ( key_press_type )
X11DRV_register_event_handler ( key_press_type , key_event , " XInput KeyPress " ) ;
if ( key_release_type )
X11DRV_register_event_handler ( key_release_type , key_event , " XInput KeyRelease " ) ;
if ( button_press_type )
X11DRV_register_event_handler ( button_press_type , button_event , " XInput ButtonPress " ) ;
if ( button_release_type )
X11DRV_register_event_handler ( button_release_type , button_event , " XInput ButtonRelease " ) ;
if ( motion_type )
X11DRV_register_event_handler ( motion_type , motion_event , " XInput MotionNotify " ) ;
if ( proximity_in_type )
X11DRV_register_event_handler ( proximity_in_type , proximity_event , " XInput ProximityIn " ) ;
if ( proximity_out_type )
X11DRV_register_event_handler ( proximity_out_type , proximity_event , " XInput ProximityOut " ) ;
2005-02-26 18:49:38 +01:00
2005-03-10 12:48:28 +01:00
pXSelectExtensionEvent ( data - > display , win , event_list , event_number ) ;
2004-01-09 01:03:00 +01:00
}
}
2005-03-10 12:48:28 +01:00
XSync ( data - > display , False ) ;
X11DRV_check_error ( ) ;
2004-01-09 01:03:00 +01:00
2005-03-10 12:48:28 +01:00
if ( NULL ! = devices ) pXFreeDeviceList ( devices ) ;
2004-01-09 01:03:00 +01:00
return 0 ;
}
2008-02-04 23:59:55 +01:00
/***********************************************************************
* X11DRV_GetCurrentPacket ( X11DRV . @ )
*/
2008-12-16 14:30:37 +01:00
int CDECL X11DRV_GetCurrentPacket ( LPWTPACKET packet )
2004-01-09 01:03:00 +01:00
{
2008-03-22 18:10:01 +01:00
* packet = gMsgPacket ;
2004-01-09 01:03:00 +01:00
return 1 ;
}
2007-09-20 22:01:06 +02:00
static inline int CopyTabletData ( LPVOID target , LPCVOID src , INT size )
2004-01-09 01:03:00 +01:00
{
2004-10-21 21:53:02 +02:00
/*
* It is valid to call CopyTabletData with NULL .
* This handles the WTInfo ( ) case where lpOutput is null .
*/
if ( target ! = NULL )
memcpy ( target , src , size ) ;
2004-01-09 01:03:00 +01:00
return ( size ) ;
}
/***********************************************************************
2007-09-20 22:01:06 +02:00
* X11DRV_WTInfoW ( X11DRV . @ )
2004-01-09 01:03:00 +01:00
*/
2008-12-16 14:30:37 +01:00
UINT CDECL X11DRV_WTInfoW ( UINT wCategory , UINT nIndex , LPVOID lpOutput )
2004-01-09 01:03:00 +01:00
{
2004-10-21 21:53:02 +02:00
/*
* It is valid to call WTInfoA with lpOutput = = NULL , as per standard .
* lpOutput = = NULL signifies the user only wishes
* to find the size of the data .
* NOTE :
* From now on use CopyTabletData to fill lpOutput . memcpy will break
* the code .
*/
2004-01-09 01:03:00 +01:00
int rc = 0 ;
LPWTI_CURSORS_INFO tgtcursor ;
TRACE ( " (%u, %u, %p) \n " , wCategory , nIndex , lpOutput ) ;
2011-03-03 09:26:33 +01:00
if ( ! xinput_handle ) return 0 ;
2004-01-09 01:03:00 +01:00
switch ( wCategory )
{
case 0 :
/* return largest necessary buffer */
TRACE ( " %i cursors \n " , gNumCursors ) ;
if ( gNumCursors > 0 )
{
FIXME ( " Return proper size \n " ) ;
2005-01-09 17:42:53 +01:00
rc = 200 ;
2004-01-09 01:03:00 +01:00
}
break ;
case WTI_INTERFACE :
switch ( nIndex )
{
WORD version ;
2007-12-24 20:34:46 +01:00
UINT num ;
2004-01-09 01:03:00 +01:00
case IFC_WINTABID :
2007-09-20 22:01:06 +02:00
{
static const WCHAR driver [ ] = { ' W ' , ' i ' , ' n ' , ' e ' , ' ' , ' W ' , ' i ' , ' n ' , ' t ' , ' a ' , ' b ' , ' ' , ' 1 ' , ' . ' , ' 1 ' , 0 } ;
rc = CopyTabletData ( lpOutput , driver , ( strlenW ( driver ) + 1 ) * sizeof ( WCHAR ) ) ;
2004-01-09 01:03:00 +01:00
break ;
2007-09-20 22:01:06 +02:00
}
2004-01-09 01:03:00 +01:00
case IFC_SPECVERSION :
version = ( 0x01 ) | ( 0x01 < < 8 ) ;
rc = CopyTabletData ( lpOutput , & version , sizeof ( WORD ) ) ;
break ;
case IFC_IMPLVERSION :
version = ( 0x00 ) | ( 0x01 < < 8 ) ;
rc = CopyTabletData ( lpOutput , & version , sizeof ( WORD ) ) ;
break ;
2007-12-24 20:34:46 +01:00
case IFC_NDEVICES :
num = 1 ;
rc = CopyTabletData ( lpOutput , & num , sizeof ( num ) ) ;
break ;
case IFC_NCURSORS :
num = gNumCursors ;
rc = CopyTabletData ( lpOutput , & num , sizeof ( num ) ) ;
break ;
2004-01-09 01:03:00 +01:00
default :
FIXME ( " WTI_INTERFACE unhandled index %i \n " , nIndex ) ;
rc = 0 ;
}
2007-09-19 20:03:46 +02:00
break ;
2004-01-09 01:03:00 +01:00
case WTI_DEFSYSCTX :
case WTI_DDCTXS :
case WTI_DEFCONTEXT :
switch ( nIndex )
{
case 0 :
2009-11-26 07:16:03 +01:00
/* report 0 if wintab is disabled */
if ( 0 = = gNumCursors )
rc = 0 ;
else
rc = CopyTabletData ( lpOutput , & gSysContext ,
sizeof ( LOGCONTEXTW ) ) ;
2004-01-09 01:03:00 +01:00
break ;
case CTX_NAME :
2008-07-12 21:37:27 +02:00
rc = CopyTabletData ( lpOutput , gSysContext . lcName ,
2007-09-20 22:01:06 +02:00
( strlenW ( gSysContext . lcName ) + 1 ) * sizeof ( WCHAR ) ) ;
2004-01-09 01:03:00 +01:00
break ;
case CTX_OPTIONS :
rc = CopyTabletData ( lpOutput , & gSysContext . lcOptions ,
sizeof ( UINT ) ) ;
break ;
case CTX_STATUS :
rc = CopyTabletData ( lpOutput , & gSysContext . lcStatus ,
sizeof ( UINT ) ) ;
break ;
case CTX_LOCKS :
rc = CopyTabletData ( lpOutput , & gSysContext . lcLocks ,
sizeof ( UINT ) ) ;
break ;
case CTX_MSGBASE :
rc = CopyTabletData ( lpOutput , & gSysContext . lcMsgBase ,
sizeof ( UINT ) ) ;
break ;
case CTX_DEVICE :
rc = CopyTabletData ( lpOutput , & gSysContext . lcDevice ,
sizeof ( UINT ) ) ;
break ;
case CTX_PKTRATE :
rc = CopyTabletData ( lpOutput , & gSysContext . lcPktRate ,
sizeof ( UINT ) ) ;
break ;
2007-09-19 20:04:52 +02:00
case CTX_PKTDATA :
rc = CopyTabletData ( lpOutput , & gSysContext . lcPktData ,
sizeof ( WTPKT ) ) ;
break ;
2004-01-09 01:03:00 +01:00
case CTX_PKTMODE :
rc = CopyTabletData ( lpOutput , & gSysContext . lcPktMode ,
sizeof ( WTPKT ) ) ;
break ;
case CTX_MOVEMASK :
rc = CopyTabletData ( lpOutput , & gSysContext . lcMoveMask ,
sizeof ( WTPKT ) ) ;
break ;
case CTX_BTNDNMASK :
rc = CopyTabletData ( lpOutput , & gSysContext . lcBtnDnMask ,
sizeof ( DWORD ) ) ;
break ;
case CTX_BTNUPMASK :
rc = CopyTabletData ( lpOutput , & gSysContext . lcBtnUpMask ,
sizeof ( DWORD ) ) ;
break ;
case CTX_INORGX :
rc = CopyTabletData ( lpOutput , & gSysContext . lcInOrgX ,
sizeof ( LONG ) ) ;
break ;
case CTX_INORGY :
rc = CopyTabletData ( lpOutput , & gSysContext . lcInOrgY ,
sizeof ( LONG ) ) ;
break ;
case CTX_INORGZ :
rc = CopyTabletData ( lpOutput , & gSysContext . lcInOrgZ ,
sizeof ( LONG ) ) ;
break ;
case CTX_INEXTX :
rc = CopyTabletData ( lpOutput , & gSysContext . lcInExtX ,
sizeof ( LONG ) ) ;
break ;
case CTX_INEXTY :
rc = CopyTabletData ( lpOutput , & gSysContext . lcInExtY ,
sizeof ( LONG ) ) ;
break ;
case CTX_INEXTZ :
rc = CopyTabletData ( lpOutput , & gSysContext . lcInExtZ ,
sizeof ( LONG ) ) ;
break ;
case CTX_OUTORGX :
rc = CopyTabletData ( lpOutput , & gSysContext . lcOutOrgX ,
sizeof ( LONG ) ) ;
break ;
case CTX_OUTORGY :
rc = CopyTabletData ( lpOutput , & gSysContext . lcOutOrgY ,
sizeof ( LONG ) ) ;
break ;
case CTX_OUTORGZ :
rc = CopyTabletData ( lpOutput , & gSysContext . lcOutOrgZ ,
sizeof ( LONG ) ) ;
break ;
case CTX_OUTEXTX :
rc = CopyTabletData ( lpOutput , & gSysContext . lcOutExtX ,
sizeof ( LONG ) ) ;
break ;
case CTX_OUTEXTY :
rc = CopyTabletData ( lpOutput , & gSysContext . lcOutExtY ,
sizeof ( LONG ) ) ;
break ;
case CTX_OUTEXTZ :
rc = CopyTabletData ( lpOutput , & gSysContext . lcOutExtZ ,
sizeof ( LONG ) ) ;
break ;
case CTX_SENSX :
rc = CopyTabletData ( lpOutput , & gSysContext . lcSensX ,
sizeof ( LONG ) ) ;
break ;
case CTX_SENSY :
rc = CopyTabletData ( lpOutput , & gSysContext . lcSensY ,
sizeof ( LONG ) ) ;
break ;
case CTX_SENSZ :
rc = CopyTabletData ( lpOutput , & gSysContext . lcSensZ ,
sizeof ( LONG ) ) ;
break ;
case CTX_SYSMODE :
rc = CopyTabletData ( lpOutput , & gSysContext . lcSysMode ,
sizeof ( LONG ) ) ;
break ;
case CTX_SYSORGX :
rc = CopyTabletData ( lpOutput , & gSysContext . lcSysOrgX ,
sizeof ( LONG ) ) ;
break ;
case CTX_SYSORGY :
rc = CopyTabletData ( lpOutput , & gSysContext . lcSysOrgY ,
sizeof ( LONG ) ) ;
break ;
case CTX_SYSEXTX :
rc = CopyTabletData ( lpOutput , & gSysContext . lcSysExtX ,
sizeof ( LONG ) ) ;
break ;
case CTX_SYSEXTY :
rc = CopyTabletData ( lpOutput , & gSysContext . lcSysExtY ,
sizeof ( LONG ) ) ;
break ;
case CTX_SYSSENSX :
rc = CopyTabletData ( lpOutput , & gSysContext . lcSysSensX ,
sizeof ( LONG ) ) ;
break ;
case CTX_SYSSENSY :
rc = CopyTabletData ( lpOutput , & gSysContext . lcSysSensY ,
sizeof ( LONG ) ) ;
break ;
default :
FIXME ( " WTI_DEFSYSCTX unhandled index %i \n " , nIndex ) ;
rc = 0 ;
}
break ;
case WTI_CURSORS :
case WTI_CURSORS + 1 :
case WTI_CURSORS + 2 :
case WTI_CURSORS + 3 :
case WTI_CURSORS + 4 :
case WTI_CURSORS + 5 :
case WTI_CURSORS + 6 :
case WTI_CURSORS + 7 :
case WTI_CURSORS + 8 :
case WTI_CURSORS + 9 :
2008-05-31 23:48:19 +02:00
case WTI_CURSORS + 10 :
case WTI_CURSORS + 11 :
/* CURSORMAX == 12 */
/* FIXME: dynamic cursor support */
2008-05-31 23:16:23 +02:00
/* Apps will poll different slots to detect what cursors are available
* if there isn ' t a cursor for this slot return 0 */
if ( ! gSysCursor [ wCategory - WTI_CURSORS ] . ACTIVE )
2007-12-24 20:34:34 +01:00
rc = 0 ;
else
{
tgtcursor = & gSysCursor [ wCategory - WTI_CURSORS ] ;
switch ( nIndex )
2004-01-09 01:03:00 +01:00
{
2007-12-24 20:34:34 +01:00
case CSR_NAME :
2008-07-12 21:37:27 +02:00
rc = CopyTabletData ( lpOutput , tgtcursor - > NAME ,
2007-12-24 20:34:34 +01:00
( strlenW ( tgtcursor - > NAME ) + 1 ) * sizeof ( WCHAR ) ) ;
break ;
case CSR_ACTIVE :
rc = CopyTabletData ( lpOutput , & tgtcursor - > ACTIVE ,
sizeof ( BOOL ) ) ;
break ;
case CSR_PKTDATA :
rc = CopyTabletData ( lpOutput , & tgtcursor - > PKTDATA ,
sizeof ( WTPKT ) ) ;
break ;
case CSR_BUTTONS :
rc = CopyTabletData ( lpOutput , & tgtcursor - > BUTTONS ,
sizeof ( BYTE ) ) ;
break ;
case CSR_BUTTONBITS :
rc = CopyTabletData ( lpOutput , & tgtcursor - > BUTTONBITS ,
sizeof ( BYTE ) ) ;
break ;
case CSR_BTNNAMES :
FIXME ( " Button Names not returned correctly \n " ) ;
rc = CopyTabletData ( lpOutput , & tgtcursor - > BTNNAMES ,
tgtcursor - > cchBTNNAMES * sizeof ( WCHAR ) ) ;
break ;
case CSR_BUTTONMAP :
2008-07-12 21:37:27 +02:00
rc = CopyTabletData ( lpOutput , tgtcursor - > BUTTONMAP ,
2007-12-24 20:34:34 +01:00
sizeof ( BYTE ) * 32 ) ;
break ;
case CSR_SYSBTNMAP :
2008-07-12 21:37:27 +02:00
rc = CopyTabletData ( lpOutput , tgtcursor - > SYSBTNMAP ,
2007-12-24 20:34:34 +01:00
sizeof ( BYTE ) * 32 ) ;
break ;
case CSR_NPBTNMARKS :
2008-07-12 21:37:27 +02:00
rc = CopyTabletData ( lpOutput , tgtcursor - > NPBTNMARKS ,
2007-12-24 20:34:34 +01:00
sizeof ( UINT ) * 2 ) ;
break ;
case CSR_NPBUTTON :
rc = CopyTabletData ( lpOutput , & tgtcursor - > NPBUTTON ,
sizeof ( BYTE ) ) ;
break ;
case CSR_NPRESPONSE :
FIXME ( " Not returning CSR_NPRESPONSE correctly \n " ) ;
rc = 0 ;
break ;
case CSR_TPBUTTON :
rc = CopyTabletData ( lpOutput , & tgtcursor - > TPBUTTON ,
sizeof ( BYTE ) ) ;
break ;
case CSR_TPBTNMARKS :
2008-07-12 21:37:27 +02:00
rc = CopyTabletData ( lpOutput , tgtcursor - > TPBTNMARKS ,
2007-12-24 20:34:34 +01:00
sizeof ( UINT ) * 2 ) ;
break ;
case CSR_TPRESPONSE :
FIXME ( " Not returning CSR_TPRESPONSE correctly \n " ) ;
rc = 0 ;
break ;
case CSR_PHYSID :
{
DWORD id ;
id = tgtcursor - > PHYSID ;
rc = CopyTabletData ( lpOutput , & id , sizeof ( DWORD ) ) ;
}
break ;
case CSR_MODE :
rc = CopyTabletData ( lpOutput , & tgtcursor - > MODE , sizeof ( UINT ) ) ;
break ;
case CSR_MINPKTDATA :
rc = CopyTabletData ( lpOutput , & tgtcursor - > MINPKTDATA ,
sizeof ( UINT ) ) ;
break ;
case CSR_MINBUTTONS :
rc = CopyTabletData ( lpOutput , & tgtcursor - > MINBUTTONS ,
sizeof ( UINT ) ) ;
break ;
case CSR_CAPABILITIES :
rc = CopyTabletData ( lpOutput , & tgtcursor - > CAPABILITIES ,
sizeof ( UINT ) ) ;
break ;
case CSR_TYPE :
rc = CopyTabletData ( lpOutput , & tgtcursor - > TYPE ,
sizeof ( UINT ) ) ;
break ;
default :
FIXME ( " WTI_CURSORS unhandled index %i \n " , nIndex ) ;
rc = 0 ;
2004-01-09 01:03:00 +01:00
}
}
break ;
case WTI_DEVICES :
switch ( nIndex )
{
case DVC_NAME :
rc = CopyTabletData ( lpOutput , gSysDevice . NAME ,
2007-09-20 22:01:06 +02:00
( strlenW ( gSysDevice . NAME ) + 1 ) * sizeof ( WCHAR ) ) ;
2004-01-09 01:03:00 +01:00
break ;
case DVC_HARDWARE :
rc = CopyTabletData ( lpOutput , & gSysDevice . HARDWARE ,
sizeof ( UINT ) ) ;
break ;
case DVC_NCSRTYPES :
rc = CopyTabletData ( lpOutput , & gSysDevice . NCSRTYPES ,
sizeof ( UINT ) ) ;
break ;
case DVC_FIRSTCSR :
rc = CopyTabletData ( lpOutput , & gSysDevice . FIRSTCSR ,
sizeof ( UINT ) ) ;
break ;
case DVC_PKTRATE :
rc = CopyTabletData ( lpOutput , & gSysDevice . PKTRATE ,
sizeof ( UINT ) ) ;
break ;
case DVC_PKTDATA :
rc = CopyTabletData ( lpOutput , & gSysDevice . PKTDATA ,
sizeof ( WTPKT ) ) ;
break ;
case DVC_PKTMODE :
rc = CopyTabletData ( lpOutput , & gSysDevice . PKTMODE ,
sizeof ( WTPKT ) ) ;
break ;
case DVC_CSRDATA :
rc = CopyTabletData ( lpOutput , & gSysDevice . CSRDATA ,
sizeof ( WTPKT ) ) ;
break ;
case DVC_XMARGIN :
rc = CopyTabletData ( lpOutput , & gSysDevice . XMARGIN ,
sizeof ( INT ) ) ;
break ;
case DVC_YMARGIN :
rc = CopyTabletData ( lpOutput , & gSysDevice . YMARGIN ,
sizeof ( INT ) ) ;
break ;
case DVC_ZMARGIN :
rc = 0 ; /* unsupported */
/*
rc = CopyTabletData ( lpOutput , & gSysDevice . ZMARGIN ,
sizeof ( INT ) ) ;
*/
break ;
case DVC_X :
rc = CopyTabletData ( lpOutput , & gSysDevice . X ,
sizeof ( AXIS ) ) ;
break ;
case DVC_Y :
rc = CopyTabletData ( lpOutput , & gSysDevice . Y ,
sizeof ( AXIS ) ) ;
break ;
case DVC_Z :
rc = 0 ; /* unsupported */
/*
rc = CopyTabletData ( lpOutput , & gSysDevice . Z ,
sizeof ( AXIS ) ) ;
*/
break ;
case DVC_NPRESSURE :
rc = CopyTabletData ( lpOutput , & gSysDevice . NPRESSURE ,
sizeof ( AXIS ) ) ;
break ;
case DVC_TPRESSURE :
rc = 0 ; /* unsupported */
/*
rc = CopyTabletData ( lpOutput , & gSysDevice . TPRESSURE ,
sizeof ( AXIS ) ) ;
*/
break ;
case DVC_ORIENTATION :
2008-07-12 21:37:27 +02:00
rc = CopyTabletData ( lpOutput , gSysDevice . ORIENTATION ,
2004-10-21 21:53:02 +02:00
sizeof ( AXIS ) * 3 ) ;
2004-01-09 01:03:00 +01:00
break ;
case DVC_ROTATION :
rc = 0 ; /* unsupported */
/*
2004-10-21 21:53:02 +02:00
rc = CopyTabletData ( lpOutput , & gSysDevice . ROTATION ,
sizeof ( AXIS ) * 3 ) ;
2004-01-09 01:03:00 +01:00
*/
break ;
case DVC_PNPID :
rc = CopyTabletData ( lpOutput , gSysDevice . PNPID ,
2007-09-20 22:01:06 +02:00
( strlenW ( gSysDevice . PNPID ) + 1 ) * sizeof ( WCHAR ) ) ;
2004-01-09 01:03:00 +01:00
break ;
default :
FIXME ( " WTI_DEVICES unhandled index %i \n " , nIndex ) ;
rc = 0 ;
}
break ;
default :
FIXME ( " Unhandled Category %i \n " , wCategory ) ;
}
return rc ;
}
2007-07-09 22:42:49 +02:00
# else /* SONAME_LIBXI */
2004-01-09 01:03:00 +01:00
2004-02-20 21:19:23 +01:00
/***********************************************************************
* AttachEventQueueToTablet ( X11DRV . @ )
*/
2008-12-16 14:30:37 +01:00
int CDECL X11DRV_AttachEventQueueToTablet ( HWND hOwner )
2004-01-09 01:03:00 +01:00
{
return 0 ;
}
2004-02-20 21:19:23 +01:00
/***********************************************************************
* GetCurrentPacket ( X11DRV . @ )
*/
2008-12-16 14:30:37 +01:00
int CDECL X11DRV_GetCurrentPacket ( LPWTPACKET packet )
2004-01-09 01:03:00 +01:00
{
return 0 ;
}
2004-02-20 21:19:23 +01:00
/***********************************************************************
* LoadTabletInfo ( X11DRV . @ )
*/
2011-03-03 09:26:33 +01:00
BOOL CDECL X11DRV_LoadTabletInfo ( HWND hwnddefault )
2004-01-09 01:03:00 +01:00
{
2011-03-03 09:26:33 +01:00
return FALSE ;
2004-01-09 01:03:00 +01:00
}
2004-02-20 21:19:23 +01:00
/***********************************************************************
2007-09-20 22:01:06 +02:00
* WTInfoW ( X11DRV . @ )
2004-02-20 21:19:23 +01:00
*/
2008-12-16 14:30:37 +01:00
UINT CDECL X11DRV_WTInfoW ( UINT wCategory , UINT nIndex , LPVOID lpOutput )
2004-01-09 01:03:00 +01:00
{
return 0 ;
}
2007-07-09 22:42:49 +02:00
# endif /* SONAME_LIBXI */