From: Vincent Povirk Subject: [5/5] winex11.drv: Use a dedicated window for mouse capture. Message-Id: Date: Wed, 16 Apr 2014 14:13:02 -0500 From 5762b43eca7ade336dd9ca02f88211999e72542d Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Thu, 6 Mar 2014 15:30:46 -0600 Subject: [PATCH 05/11] winex11.drv: Use a dedicated window for mouse capture. --- dlls/winex11.drv/mouse.c | 63 ++++++++++++++++++++++++++++++++++++++++++----- dlls/winex11.drv/window.c | 35 +++----------------------- dlls/winex11.drv/x11drv.h | 1 + 3 files changed, 61 insertions(+), 38 deletions(-) diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index f1e58fe..0ae0758 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -535,18 +535,25 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU if (!hwnd) { struct x11drv_thread_data *thread_data = x11drv_thread_data(); - HWND clip_hwnd = thread_data->clip_hwnd; + HWND cursor_hwnd; - if (!clip_hwnd) return; - if (thread_data->clip_window != window) return; - if (InterlockedExchangePointer( (void **)&cursor_window, clip_hwnd ) != clip_hwnd || + if (thread_data->clip_window == window) + { + if (!thread_data->clip_hwnd) return; + cursor_hwnd = thread_data->clip_hwnd; + input->u.mi.dx += clip_rect.left; + input->u.mi.dy += clip_rect.top; + } + else if (thread_data->grab_window == window) + cursor_hwnd = GetCapture(); + else + return; + if (InterlockedExchangePointer( (void **)&cursor_window, cursor_hwnd ) != cursor_hwnd || input->u.mi.time - last_cursor_change > 100) { sync_window_cursor( window ); last_cursor_change = input->u.mi.time; } - input->u.mi.dx += clip_rect.left; - input->u.mi.dy += clip_rect.top; __wine_send_input( hwnd, input ); return; } @@ -1421,6 +1428,50 @@ BOOL CDECL X11DRV_ClipCursor( LPCRECT clip ) return TRUE; } + +/*********************************************************************** + * SetCapture (X11DRV.@) + */ +void CDECL X11DRV_SetCapture( HWND hwnd, UINT flags ) +{ + struct x11drv_thread_data *thread_data = x11drv_thread_data(); + + if (!thread_data) return; + if (!(flags & (GUI_INMOVESIZE | GUI_INMENUMODE))) return; + + if (hwnd) + { + if (!thread_data->capture_window) + { + XSetWindowAttributes attr; + + attr.override_redirect = TRUE; + attr.event_mask = StructureNotifyMask | FocusChangeMask; + thread_data->capture_window = XCreateWindow( thread_data->display, + root_window, 0, 0, 1, 1, 0, 0, InputOnly, default_visual.visual, + CWOverrideRedirect | CWEventMask, &attr ); + + if (!thread_data->capture_window) return; + } + + XFlush( gdi_display ); + XMapWindow( thread_data->display, thread_data->capture_window ); + XGrabPointer( thread_data->display, thread_data->capture_window, False, + PointerMotionMask | ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, None, CurrentTime ); + sync_window_cursor( thread_data->capture_window ); + InterlockedExchangePointer( (void **)&cursor_window, hwnd ); + thread_data->grab_window = thread_data->capture_window; + } + else if (thread_data->capture_window) /* release capture */ + { + XFlush( gdi_display ); + XUnmapWindow( thread_data->display, thread_data->capture_window ); + XFlush( thread_data->display ); + thread_data->grab_window = None; + } +} + /*********************************************************************** * move_resize_window */ diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index a9caa0d..c150cae 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2060,37 +2060,6 @@ BOOL CDECL X11DRV_ScrollDC( HDC hdc, INT dx, INT dy, HRGN update ) } -/*********************************************************************** - * SetCapture (X11DRV.@) - */ -void CDECL X11DRV_SetCapture( HWND hwnd, UINT flags ) -{ - struct x11drv_thread_data *thread_data = x11drv_thread_data(); - - if (!thread_data) return; - if (!(flags & (GUI_INMOVESIZE | GUI_INMENUMODE))) return; - - if (hwnd) - { - Window grab_win = X11DRV_get_whole_window( GetAncestor( hwnd, GA_ROOT ) ); - - if (!grab_win) return; - XFlush( gdi_display ); - XGrabPointer( thread_data->display, grab_win, False, - PointerMotionMask | ButtonPressMask | ButtonReleaseMask, - GrabModeAsync, GrabModeAsync, None, None, CurrentTime ); - thread_data->grab_window = grab_win; - } - else /* release capture */ - { - XFlush( gdi_display ); - XUngrabPointer( thread_data->display, CurrentTime ); - XFlush( thread_data->display ); - thread_data->grab_window = None; - } -} - - /***************************************************************** * SetParent (X11DRV.@) */ @@ -2603,7 +2572,9 @@ LRESULT CDECL X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) X11DRV_resize_desktop( LOWORD(lp), HIWORD(lp) ); return 0; case WM_X11DRV_SET_CURSOR: - if ((data = get_win_data( hwnd ))) + if (x11drv_thread_data()->grab_window) + set_window_cursor( x11drv_thread_data()->grab_window, (HCURSOR)lp ); + else if ((data = get_win_data( hwnd ))) { if (data->whole_window) set_window_cursor( data->whole_window, (HCURSOR)lp ); release_win_data( data ); diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 7a3374d..b0b6ba9 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -311,6 +311,7 @@ struct x11drv_thread_data Display *display; XEvent *current_event; /* event currently being processed */ Window grab_window; /* window that currently grabs the mouse */ + Window capture_window; /* window used for capture */ HWND last_focus; /* last window that had focus */ XIM xim; /* input method */ HWND last_xic_hwnd; /* last xic window */ -- 1.8.3.2