winex11: Store a message window with the desktop when the cursor is clipped.

This ensures that the thread can be notified when the clip rectangle is reset.
This commit is contained in:
Alexandre Julliard 2011-04-22 16:22:09 +02:00
parent 8aa1a26886
commit 0eb19126e5
4 changed files with 49 additions and 15 deletions

View File

@ -795,7 +795,7 @@ static void X11DRV_MapNotify( HWND hwnd, XEvent *event )
*/
static void X11DRV_UnmapNotify( HWND hwnd, XEvent *event )
{
if (event->xany.window == x11drv_thread_data()->clip_window) clipping_window_unmapped();
if (event->xany.window == x11drv_thread_data()->clip_window) clipping_cursor = 0;
}

View File

@ -348,24 +348,50 @@ static void disable_xinput2(void)
}
/***********************************************************************
* clipping_window_unmapped
*
* Turn off clipping when the window got unmapped.
* create_clipping_msg_window
*/
void clipping_window_unmapped(void)
static HWND create_clipping_msg_window(void)
{
struct x11drv_thread_data *data = x11drv_thread_data();
static const WCHAR class_name[] = {'_','_','x','1','1','d','r','v','_','c','l','i','p','_','c','l','a','s','s',0};
static ATOM clip_class;
clipping_cursor = 0;
if (data->xi2_state == xi_enabled)
if (!clip_class)
{
RECT rect;
GetClipCursor( &rect );
if (EqualRect( &rect, &clip_rect )) return; /* still clipped */
disable_xinput2();
WNDCLASSW class;
ATOM atom;
memset( &class, 0, sizeof(class) );
class.lpfnWndProc = DefWindowProcW;
class.hInstance = GetModuleHandleW(0);
class.lpszClassName = class_name;
if ((atom = RegisterClassW( &class ))) clip_class = atom;
}
return CreateWindowW( class_name, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, GetModuleHandleW(0), NULL );
}
/***********************************************************************
* clip_cursor_notify
*
* Notification function called upon receiving a WM_X11DRV_CLIP_CURSOR.
*/
LRESULT clip_cursor_notify( HWND hwnd, HWND new_clip_hwnd )
{
if (hwnd == GetDesktopWindow()) /* change the clip window stored in the desktop process */
{
static HWND clip_hwnd;
HWND prev = clip_hwnd;
clip_hwnd = new_clip_hwnd;
if (prev || new_clip_hwnd) TRACE( "clip hwnd changed from %p to %p\n", prev, new_clip_hwnd );
if (prev) SendNotifyMessageW( prev, WM_X11DRV_CLIP_CURSOR, 0, 0 );
}
else /* this is a notification that clipping has been reset */
{
disable_xinput2();
DestroyWindow( hwnd );
}
return 0;
}
/***********************************************************************
* send_mouse_input
@ -1100,6 +1126,9 @@ BOOL CDECL X11DRV_ClipCursor( LPCRECT clip )
if (grab_pointer)
{
HWND msg_hwnd = create_clipping_msg_window();
if (!msg_hwnd) return TRUE;
TRACE( "clipping to %s\n", wine_dbgstr_rect(clip) );
wine_tsx11_lock();
XUnmapWindow( display, clip_window );
@ -1118,8 +1147,10 @@ BOOL CDECL X11DRV_ClipCursor( LPCRECT clip )
enable_xinput2();
sync_window_cursor( clip_window );
clip_rect = *clip;
SendMessageW( GetDesktopWindow(), WM_X11DRV_CLIP_CURSOR, 0, (LPARAM)msg_hwnd );
return TRUE;
}
DestroyWindow( msg_hwnd );
}
}
@ -1129,7 +1160,7 @@ BOOL CDECL X11DRV_ClipCursor( LPCRECT clip )
XUnmapWindow( display, clip_window );
wine_tsx11_unlock();
clipping_cursor = 0;
disable_xinput2();
SendMessageW( GetDesktopWindow(), WM_X11DRV_CLIP_CURSOR, 0, 0 );
return TRUE;
}

View File

@ -2719,6 +2719,8 @@ LRESULT CDECL X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
if ((data = X11DRV_get_win_data( hwnd )) && data->whole_window)
set_window_cursor( data->whole_window, (HCURSOR)lp );
return 0;
case WM_X11DRV_CLIP_CURSOR:
return clip_cursor_notify( hwnd, (HWND)lp );
default:
FIXME( "got window msg %x hwnd %p wp %lx lp %lx\n", msg, hwnd, wp, lp );
return 0;

View File

@ -744,7 +744,8 @@ enum x11drv_window_messages
WM_X11DRV_SET_WIN_FORMAT,
WM_X11DRV_SET_WIN_REGION,
WM_X11DRV_RESIZE_DESKTOP,
WM_X11DRV_SET_CURSOR
WM_X11DRV_SET_CURSOR,
WM_X11DRV_CLIP_CURSOR
};
/* _NET_WM_STATE properties that we keep track of */
@ -826,7 +827,7 @@ extern void X11DRV_ResetSelectionOwner(void);
extern void CDECL X11DRV_SetFocus( HWND hwnd );
extern void set_window_cursor( Window window, HCURSOR handle );
extern void sync_window_cursor( Window window );
extern void clipping_window_unmapped(void);
extern LRESULT clip_cursor_notify( HWND hwnd, HWND new_clip_hwnd );
extern BOOL CDECL X11DRV_ClipCursor( LPCRECT clip );
extern void X11DRV_InitKeyboard( Display *display );
extern DWORD CDECL X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, DWORD timeout,