winex11: Grab the mouse in the thread that owns the foreground window if possible.

This commit is contained in:
Alexandre Julliard 2011-04-28 13:07:05 +02:00
parent 20e24bff70
commit 84f085fb91
1 changed files with 63 additions and 38 deletions

View File

@ -368,33 +368,6 @@ static HWND create_clipping_msg_window(void)
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 )
{
struct x11drv_thread_data *data = x11drv_thread_data();
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 if (hwnd == data->clip_hwnd) /* this is a notification that clipping has been reset */
{
data->clip_hwnd = 0;
disable_xinput2();
DestroyWindow( hwnd );
}
return 0;
}
/***********************************************************************
* grab_clipping_window
*
@ -402,11 +375,12 @@ LRESULT clip_cursor_notify( HWND hwnd, HWND new_clip_hwnd )
*/
static BOOL grab_clipping_window( const RECT *clip )
{
struct x11drv_thread_data *data = x11drv_init_thread_data();
Window clip_window = init_clip_window();
struct x11drv_thread_data *data = x11drv_thread_data();
Window clip_window;
HWND msg_hwnd = 0;
if (!clip_window) return TRUE;
if (!data) return FALSE;
if (!(clip_window = init_clip_window())) return TRUE;
/* create a clip message window unless we are already clipping */
if (!data->clip_hwnd)
@ -474,6 +448,42 @@ void ungrab_clipping_window(void)
SendMessageW( GetDesktopWindow(), WM_X11DRV_CLIP_CURSOR, 0, 0 );
}
/***********************************************************************
* clip_cursor_notify
*
* Notification function called upon receiving a WM_X11DRV_CLIP_CURSOR.
*/
LRESULT clip_cursor_notify( HWND hwnd, HWND new_clip_hwnd )
{
struct x11drv_thread_data *data = x11drv_thread_data();
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 if (hwnd == data->clip_hwnd) /* this is a notification that clipping has been reset */
{
data->clip_hwnd = 0;
disable_xinput2();
DestroyWindow( hwnd );
}
else if (hwnd == GetForegroundWindow()) /* request to clip */
{
RECT clip;
GetClipCursor( &clip );
if (clip.left > virtual_screen_rect.left || clip.right < virtual_screen_rect.right ||
clip.top > virtual_screen_rect.top || clip.bottom < virtual_screen_rect.bottom)
return grab_clipping_window( &clip );
}
return 0;
}
/***********************************************************************
* send_mouse_input
*
@ -1191,16 +1201,31 @@ BOOL CDECL X11DRV_GetCursorPos(LPPOINT pos)
*/
BOOL CDECL X11DRV_ClipCursor( LPCRECT clip )
{
if (!clip)
{
ungrab_clipping_window();
return TRUE;
}
if (X11DRV_get_win_data( GetDesktopWindow() )) return TRUE; /* don't clip in the desktop process */
/* we are clipping if the clip rectangle is smaller than the screen */
if (clip && (clip->left > virtual_screen_rect.left ||
if (grab_pointer && (clip->left > virtual_screen_rect.left ||
clip->right < virtual_screen_rect.right ||
clip->top > virtual_screen_rect.top ||
clip->bottom < virtual_screen_rect.bottom))
{
if (GetWindowThreadProcessId( GetDesktopWindow(), NULL ) == GetCurrentThreadId())
return TRUE; /* don't clip in the desktop process */
DWORD tid, pid;
HWND foreground = GetForegroundWindow();
if (grab_pointer && grab_clipping_window( clip )) return TRUE;
/* forward request to the foreground window if it's in a different thread */
tid = GetWindowThreadProcessId( foreground, &pid );
if (tid && tid != GetCurrentThreadId() && pid == GetCurrentProcessId())
{
TRACE( "forwarding clip request to %p\n", foreground );
if (SendMessageW( foreground, WM_X11DRV_CLIP_CURSOR, 0, 0 )) return TRUE;
}
else if (grab_clipping_window( clip )) return TRUE;
}
ungrab_clipping_window();