winex11: Retrieve raw mouse events through XInput2 while the cursor is clipped.
This commit is contained in:
parent
338fe8b9ac
commit
bd3ec1a973
|
@ -795,7 +795,7 @@ static void X11DRV_MapNotify( HWND hwnd, XEvent *event )
|
||||||
*/
|
*/
|
||||||
static void X11DRV_UnmapNotify( HWND hwnd, XEvent *event )
|
static void X11DRV_UnmapNotify( HWND hwnd, XEvent *event )
|
||||||
{
|
{
|
||||||
if (event->xany.window == clip_window) clipping_cursor = 0;
|
if (event->xany.window == clip_window) clipping_window_unmapped();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,17 @@ static XContext cursor_context;
|
||||||
static RECT clip_rect;
|
static RECT clip_rect;
|
||||||
static Cursor create_cursor( HANDLE handle );
|
static Cursor create_cursor( HANDLE handle );
|
||||||
|
|
||||||
|
#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
|
||||||
|
static BOOL xinput2_available;
|
||||||
|
static int xinput2_opcode;
|
||||||
|
static int xinput2_core_pointer;
|
||||||
|
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
|
||||||
|
MAKE_FUNCPTR(XIFreeDeviceInfo);
|
||||||
|
MAKE_FUNCPTR(XIQueryDevice);
|
||||||
|
MAKE_FUNCPTR(XIQueryVersion);
|
||||||
|
MAKE_FUNCPTR(XISelectEvents);
|
||||||
|
#undef MAKE_FUNCPTR
|
||||||
|
#endif
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* X11DRV_Xcursor_Init
|
* X11DRV_Xcursor_Init
|
||||||
|
@ -238,6 +249,124 @@ void sync_window_cursor( Window window )
|
||||||
set_window_cursor( window, cursor );
|
set_window_cursor( window, cursor );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* enable_xinput2
|
||||||
|
*/
|
||||||
|
static void enable_xinput2(void)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
|
||||||
|
struct x11drv_thread_data *data = x11drv_thread_data();
|
||||||
|
XIDeviceInfo *devices;
|
||||||
|
XIEventMask mask;
|
||||||
|
unsigned char mask_bits[XIMaskLen(XI_LASTEVENT)];
|
||||||
|
int i, count;
|
||||||
|
|
||||||
|
if (!xinput2_available) return;
|
||||||
|
|
||||||
|
if (data->xi2_state == xi_unknown)
|
||||||
|
{
|
||||||
|
int major = 2, minor = 0;
|
||||||
|
wine_tsx11_lock();
|
||||||
|
if (!pXIQueryVersion( data->display, &major, &minor )) data->xi2_state = xi_disabled;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data->xi2_state = xi_unavailable;
|
||||||
|
WARN( "X Input 2 not available\n" );
|
||||||
|
}
|
||||||
|
wine_tsx11_unlock();
|
||||||
|
}
|
||||||
|
if (data->xi2_state == xi_unavailable) return;
|
||||||
|
|
||||||
|
wine_tsx11_lock();
|
||||||
|
devices = pXIQueryDevice( data->display, XIAllDevices, &count );
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
if (devices[i].use != XIMasterPointer) continue;
|
||||||
|
TRACE( "Using %u (%s) as core pointer\n",
|
||||||
|
devices[i].deviceid, debugstr_a(devices[i].name) );
|
||||||
|
xinput2_core_pointer = devices[i].deviceid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mask.mask = mask_bits;
|
||||||
|
mask.mask_len = sizeof(mask_bits);
|
||||||
|
memset( mask_bits, 0, sizeof(mask_bits) );
|
||||||
|
|
||||||
|
XISetMask( mask_bits, XI_RawButtonPress );
|
||||||
|
XISetMask( mask_bits, XI_RawButtonRelease );
|
||||||
|
XISetMask( mask_bits, XI_RawMotion );
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
if (devices[i].use == XISlavePointer && devices[i].attachment == xinput2_core_pointer)
|
||||||
|
{
|
||||||
|
TRACE( "Device %u (%s) is attached to the core pointer\n",
|
||||||
|
devices[i].deviceid, debugstr_a(devices[i].name) );
|
||||||
|
mask.deviceid = devices[i].deviceid;
|
||||||
|
pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 );
|
||||||
|
data->xi2_state = xi_enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pXIFreeDeviceInfo( devices );
|
||||||
|
wine_tsx11_unlock();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* disable_xinput2
|
||||||
|
*/
|
||||||
|
static void disable_xinput2(void)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
|
||||||
|
struct x11drv_thread_data *data = x11drv_thread_data();
|
||||||
|
XIEventMask mask;
|
||||||
|
XIDeviceInfo *devices;
|
||||||
|
int i, count;
|
||||||
|
|
||||||
|
if (data->xi2_state != xi_enabled) return;
|
||||||
|
|
||||||
|
TRACE( "disabling\n" );
|
||||||
|
data->xi2_state = xi_disabled;
|
||||||
|
|
||||||
|
mask.mask = NULL;
|
||||||
|
mask.mask_len = 0;
|
||||||
|
|
||||||
|
wine_tsx11_lock();
|
||||||
|
devices = pXIQueryDevice( data->display, XIAllDevices, &count );
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
if (devices[i].use == XISlavePointer && devices[i].attachment == xinput2_core_pointer)
|
||||||
|
{
|
||||||
|
mask.deviceid = devices[i].deviceid;
|
||||||
|
pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pXIFreeDeviceInfo( devices );
|
||||||
|
wine_tsx11_unlock();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* clipping_window_unmapped
|
||||||
|
*
|
||||||
|
* Turn off clipping when the window got unmapped.
|
||||||
|
*/
|
||||||
|
void clipping_window_unmapped(void)
|
||||||
|
{
|
||||||
|
struct x11drv_thread_data *data = x11drv_thread_data();
|
||||||
|
|
||||||
|
clipping_cursor = 0;
|
||||||
|
if (data->xi2_state == xi_enabled)
|
||||||
|
{
|
||||||
|
RECT rect;
|
||||||
|
GetClipCursor( &rect );
|
||||||
|
if (EqualRect( &rect, &clip_rect )) return; /* still clipped */
|
||||||
|
disable_xinput2();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* send_mouse_input
|
* send_mouse_input
|
||||||
*
|
*
|
||||||
|
@ -254,7 +383,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU
|
||||||
{
|
{
|
||||||
input->u.mi.dx += clip_rect.left;
|
input->u.mi.dx += clip_rect.left;
|
||||||
input->u.mi.dy += clip_rect.top;
|
input->u.mi.dy += clip_rect.top;
|
||||||
__wine_send_input( hwnd, input );
|
if (x11drv_thread_data()->xi2_state != xi_enabled) __wine_send_input( hwnd, input );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -913,14 +1042,16 @@ void CDECL X11DRV_SetCursor( HCURSOR handle )
|
||||||
*/
|
*/
|
||||||
BOOL CDECL X11DRV_SetCursorPos( INT x, INT y )
|
BOOL CDECL X11DRV_SetCursorPos( INT x, INT y )
|
||||||
{
|
{
|
||||||
Display *display = thread_init_display();
|
struct x11drv_thread_data *data = x11drv_init_thread_data();
|
||||||
|
|
||||||
|
if (data->xi2_state == xi_enabled) return TRUE;
|
||||||
|
|
||||||
TRACE( "warping to (%d,%d)\n", x, y );
|
TRACE( "warping to (%d,%d)\n", x, y );
|
||||||
|
|
||||||
wine_tsx11_lock();
|
wine_tsx11_lock();
|
||||||
XWarpPointer( display, root_window, root_window, 0, 0, 0, 0,
|
XWarpPointer( data->display, root_window, root_window, 0, 0, 0, 0,
|
||||||
x - virtual_screen_rect.left, y - virtual_screen_rect.top );
|
x - virtual_screen_rect.left, y - virtual_screen_rect.top );
|
||||||
XFlush( display ); /* avoids bad mouse lag in games that do their own mouse warping */
|
XFlush( data->display ); /* avoids bad mouse lag in games that do their own mouse warping */
|
||||||
wine_tsx11_unlock();
|
wine_tsx11_unlock();
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -983,6 +1114,7 @@ BOOL CDECL X11DRV_ClipCursor( LPCRECT clip )
|
||||||
|
|
||||||
if (clipping_cursor)
|
if (clipping_cursor)
|
||||||
{
|
{
|
||||||
|
enable_xinput2();
|
||||||
sync_window_cursor( clip_window );
|
sync_window_cursor( clip_window );
|
||||||
clip_rect = *clip;
|
clip_rect = *clip;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -996,6 +1128,7 @@ BOOL CDECL X11DRV_ClipCursor( LPCRECT clip )
|
||||||
XUnmapWindow( display, clip_window );
|
XUnmapWindow( display, clip_window );
|
||||||
wine_tsx11_unlock();
|
wine_tsx11_unlock();
|
||||||
clipping_cursor = 0;
|
clipping_cursor = 0;
|
||||||
|
disable_xinput2();
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1174,6 +1307,42 @@ static void X11DRV_RawMotion( XIRawEvent *event )
|
||||||
#endif /* HAVE_X11_EXTENSIONS_XINPUT2_H */
|
#endif /* HAVE_X11_EXTENSIONS_XINPUT2_H */
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* X11DRV_XInput2_Init
|
||||||
|
*/
|
||||||
|
void X11DRV_XInput2_Init(void)
|
||||||
|
{
|
||||||
|
#if defined(SONAME_LIBXI) && defined(HAVE_X11_EXTENSIONS_XINPUT2_H)
|
||||||
|
int event, error;
|
||||||
|
void *libxi_handle = wine_dlopen( SONAME_LIBXI, RTLD_NOW, NULL, 0 );
|
||||||
|
|
||||||
|
if (!libxi_handle)
|
||||||
|
{
|
||||||
|
WARN( "couldn't load %s\n", SONAME_LIBXI );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#define LOAD_FUNCPTR(f) \
|
||||||
|
if (!(p##f = wine_dlsym( libxi_handle, #f, NULL, 0))) \
|
||||||
|
{ \
|
||||||
|
WARN("Failed to load %s.\n", #f); \
|
||||||
|
return; \
|
||||||
|
}
|
||||||
|
|
||||||
|
LOAD_FUNCPTR(XIFreeDeviceInfo);
|
||||||
|
LOAD_FUNCPTR(XIQueryDevice);
|
||||||
|
LOAD_FUNCPTR(XIQueryVersion);
|
||||||
|
LOAD_FUNCPTR(XISelectEvents);
|
||||||
|
#undef LOAD_FUNCPTR
|
||||||
|
|
||||||
|
wine_tsx11_lock();
|
||||||
|
xinput2_available = XQueryExtension( gdi_display, "XInputExtension", &xinput2_opcode, &event, &error );
|
||||||
|
wine_tsx11_unlock();
|
||||||
|
#else
|
||||||
|
TRACE( "X Input 2 support not compiled in.\n" );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* X11DRV_GenericEvent
|
* X11DRV_GenericEvent
|
||||||
*/
|
*/
|
||||||
|
@ -1183,6 +1352,7 @@ void X11DRV_GenericEvent( HWND hwnd, XEvent *xev )
|
||||||
XGenericEventCookie *event = &xev->xcookie;
|
XGenericEventCookie *event = &xev->xcookie;
|
||||||
|
|
||||||
if (!event->data) return;
|
if (!event->data) return;
|
||||||
|
if (event->extension != xinput2_opcode) return;
|
||||||
|
|
||||||
switch (event->evtype)
|
switch (event->evtype)
|
||||||
{
|
{
|
||||||
|
|
|
@ -258,6 +258,7 @@ extern void X11DRV_OpenGL_Cleanup(void);
|
||||||
extern void X11DRV_Xcursor_Init(void);
|
extern void X11DRV_Xcursor_Init(void);
|
||||||
extern void X11DRV_BITMAP_Init(void);
|
extern void X11DRV_BITMAP_Init(void);
|
||||||
extern void X11DRV_FONT_Init( int log_pixels_x, int log_pixels_y );
|
extern void X11DRV_FONT_Init( int log_pixels_x, int log_pixels_y );
|
||||||
|
extern void X11DRV_XInput2_Init(void);
|
||||||
|
|
||||||
extern int bitmap_info_size( const BITMAPINFO * info, WORD coloruse );
|
extern int bitmap_info_size( const BITMAPINFO * info, WORD coloruse );
|
||||||
extern XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth );
|
extern XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth );
|
||||||
|
@ -550,6 +551,7 @@ struct x11drv_thread_data
|
||||||
XFontSet font_set; /* international text drawing font set */
|
XFontSet font_set; /* international text drawing font set */
|
||||||
Window selection_wnd; /* window used for selection interactions */
|
Window selection_wnd; /* window used for selection interactions */
|
||||||
HKL kbd_layout; /* active keyboard layout */
|
HKL kbd_layout; /* active keyboard layout */
|
||||||
|
enum { xi_unavailable = -1, xi_unknown, xi_disabled, xi_enabled } xi2_state; /* XInput2 state */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct x11drv_thread_data *x11drv_init_thread_data(void);
|
extern struct x11drv_thread_data *x11drv_init_thread_data(void);
|
||||||
|
@ -823,6 +825,7 @@ extern void X11DRV_ResetSelectionOwner(void);
|
||||||
extern void CDECL X11DRV_SetFocus( HWND hwnd );
|
extern void CDECL X11DRV_SetFocus( HWND hwnd );
|
||||||
extern void set_window_cursor( Window window, HCURSOR handle );
|
extern void set_window_cursor( Window window, HCURSOR handle );
|
||||||
extern void sync_window_cursor( Window window );
|
extern void sync_window_cursor( Window window );
|
||||||
|
extern void clipping_window_unmapped(void);
|
||||||
extern BOOL CDECL X11DRV_ClipCursor( LPCRECT clip );
|
extern BOOL CDECL X11DRV_ClipCursor( LPCRECT clip );
|
||||||
extern void X11DRV_InitKeyboard( Display *display );
|
extern void X11DRV_InitKeyboard( Display *display );
|
||||||
extern DWORD CDECL X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, DWORD timeout,
|
extern DWORD CDECL X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, DWORD timeout,
|
||||||
|
|
|
@ -595,6 +595,7 @@ static BOOL process_attach(void)
|
||||||
#ifdef SONAME_LIBXCOMPOSITE
|
#ifdef SONAME_LIBXCOMPOSITE
|
||||||
X11DRV_XComposite_Init();
|
X11DRV_XComposite_Init();
|
||||||
#endif
|
#endif
|
||||||
|
X11DRV_XInput2_Init();
|
||||||
|
|
||||||
#ifdef HAVE_XKB
|
#ifdef HAVE_XKB
|
||||||
if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL );
|
if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL );
|
||||||
|
|
Loading…
Reference in New Issue