From 0eb19126e5c0efe7e5e0cbd4811c19523601973a Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 22 Apr 2011 16:22:09 +0200 Subject: [PATCH] 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. --- dlls/winex11.drv/event.c | 2 +- dlls/winex11.drv/mouse.c | 55 ++++++++++++++++++++++++++++++--------- dlls/winex11.drv/window.c | 2 ++ dlls/winex11.drv/x11drv.h | 5 ++-- 4 files changed, 49 insertions(+), 15 deletions(-) diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 75e7d8da1e2..b338236f99b 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -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; } diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 2768d8e629e..4e622d7d94a 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -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; } diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 0a25afbf952..ba544cdd87d 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -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; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index cbc563b5e30..2187d72d713 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -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,