Module: wine Branch: master Commit: a59c7cc8596b658d3c0854a737528cf60947ac1f URL: http://source.winehq.org/git/wine.git/?a=commit;h=a59c7cc8596b658d3c0854a737...
Author: Alexandre Julliard julliard@winehq.org Date: Wed May 11 12:30:03 2011 +0200
winex11: Automatically clip the pointer when the foreground window is full-screen.
---
dlls/winex11.drv/desktop.c | 1 + dlls/winex11.drv/event.c | 6 +++- dlls/winex11.drv/mouse.c | 74 +++++++++++++++++++++++++++++++++---------- dlls/winex11.drv/x11drv.h | 2 + 4 files changed, 65 insertions(+), 18 deletions(-)
diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index b78306d..b45f786 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -200,6 +200,7 @@ static BOOL CALLBACK update_windows_on_desktop_resize( HWND hwnd, LPARAM lparam DefaultScreen(display), mask, &changes ); wine_tsx11_unlock(); } + if (hwnd == GetForegroundWindow()) clip_fullscreen_window( hwnd ); return TRUE; }
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 52d4b81..d2ab40a 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -714,7 +714,11 @@ static void X11DRV_FocusIn( HWND hwnd, XEvent *xev ) XSetICFocus( xic ); wine_tsx11_unlock(); } - if (use_take_focus) return; /* ignore FocusIn if we are using take focus */ + if (use_take_focus) + { + if (hwnd == GetForegroundWindow()) clip_fullscreen_window( hwnd ); + return; + }
if (!can_activate_window(hwnd)) { diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 06805a7..a4b846b 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -373,7 +373,7 @@ static HWND create_clipping_msg_window(void) * * Start a pointer grab on the clip window. */ -static BOOL grab_clipping_window( const RECT *clip ) +static BOOL grab_clipping_window( const RECT *clip, BOOL only_with_xinput ) { struct x11drv_thread_data *data = x11drv_thread_data(); Window clip_window; @@ -390,7 +390,8 @@ static BOOL grab_clipping_window( const RECT *clip ) }
/* don't clip to 1x1 rectangle if we don't have XInput */ - if (data->xi2_state != xi_enabled && clip->right - clip->left == 1 && clip->bottom - clip->top == 1) + if (clip->right - clip->left == 1 && clip->bottom - clip->top == 1) only_with_xinput = TRUE; + if (only_with_xinput && data->xi2_state != xi_enabled) { WARN( "XInput2 not supported, refusing to clip to %s\n", wine_dbgstr_rect(clip) ); if (msg_hwnd) DestroyWindow( msg_hwnd ); @@ -480,6 +481,7 @@ LRESULT clip_cursor_notify( HWND hwnd, HWND new_clip_hwnd ) else if (hwnd == data->clip_hwnd) /* this is a notification that clipping has been reset */ { data->clip_hwnd = 0; + data->clip_reset = GetTickCount(); disable_xinput2(); DestroyWindow( hwnd ); } @@ -490,12 +492,39 @@ LRESULT clip_cursor_notify( HWND hwnd, HWND new_clip_hwnd ) 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 grab_clipping_window( &clip, FALSE ); } return 0; }
/*********************************************************************** + * clip_fullscreen_window + * + * Turn on clipping if the active window is fullscreen. + */ +BOOL clip_fullscreen_window( HWND hwnd ) +{ + struct x11drv_win_data *data; + RECT rect; + DWORD style; + + if (hwnd == GetDesktopWindow()) return FALSE; + if (!(data = X11DRV_get_win_data( hwnd ))) return FALSE; + style = GetWindowLongW( hwnd, GWL_STYLE ); + if (!(style & WS_VISIBLE)) return FALSE; + if ((style & (WS_POPUP | WS_CHILD)) == WS_CHILD) return FALSE; + /* maximized windows don't count as full screen */ + if ((style & WS_MAXIMIZE) && (style & WS_CAPTION) == WS_CAPTION) return FALSE; + if (!is_window_rect_fullscreen( &data->whole_rect )) return FALSE; + if (GetTickCount() - x11drv_thread_data()->clip_reset < 1000) return FALSE; + SetRect( &rect, 0, 0, screen_width, screen_height ); + if (!EqualRect( &rect, &virtual_screen_rect )) return FALSE; + if (root_window != DefaultRootWindow( gdi_display )) return FALSE; + TRACE( "win %p clipping fullscreen\n", hwnd ); + return grab_clipping_window( &rect, TRUE ); +} + +/*********************************************************************** * send_mouse_input * * Update the various window states on a mouse event. @@ -540,7 +569,12 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU last_cursor_change = GetTickCount(); }
- if (hwnd != GetDesktopWindow()) hwnd = GetAncestor( hwnd, GA_ROOT ); + if (hwnd != GetDesktopWindow()) + { + hwnd = GetAncestor( hwnd, GA_ROOT ); + if ((input->u.mi.dwFlags & (MOUSEEVENTF_LEFTDOWN|MOUSEEVENTF_RIGHTDOWN)) && hwnd == GetForegroundWindow()) + clip_fullscreen_window( hwnd ); + }
/* update the wine server Z-order */
@@ -1221,25 +1255,31 @@ BOOL CDECL X11DRV_ClipCursor( LPCRECT clip ) if (GetWindowThreadProcessId( GetDesktopWindow(), NULL ) == GetCurrentThreadId()) return TRUE; /* don't clip in the desktop process */
- /* we are clipping if the clip rectangle is smaller than the screen */ - 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 (grab_pointer) { - DWORD tid, pid; HWND foreground = GetForegroundWindow();
- /* forward request to the foreground window if it's in a different thread */ - tid = GetWindowThreadProcessId( foreground, &pid ); - if (tid && tid != GetCurrentThreadId() && pid == GetCurrentProcessId()) + /* we are clipping if the clip rectangle is smaller than the screen */ + 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) { - TRACE( "forwarding clip request to %p\n", foreground ); - if (SendMessageW( foreground, WM_X11DRV_CLIP_CURSOR, 0, 0 )) return TRUE; + DWORD tid, pid; + + /* 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, FALSE )) return TRUE; + } + else /* if currently clipping, check if we should switch to fullscreen clipping */ + { + struct x11drv_thread_data *data = x11drv_thread_data(); + if (data && data->clip_hwnd && clip_fullscreen_window( foreground )) return TRUE; } - else if (grab_clipping_window( clip )) return TRUE; } - ungrab_clipping_window(); return TRUE; } diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 8e756b2..b7011da 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -552,6 +552,7 @@ struct x11drv_thread_data Window selection_wnd; /* window used for selection interactions */ Window clip_window; /* window used for cursor clipping */ HWND clip_hwnd; /* message window stored in desktop while clipping is active */ + DWORD clip_reset; /* time when clipping was last reset */ HKL kbd_layout; /* active keyboard layout */ enum { xi_unavailable = -1, xi_unknown, xi_disabled, xi_enabled } xi2_state; /* XInput2 state */ }; @@ -844,6 +845,7 @@ extern void sync_window_cursor( Window window ); extern LRESULT clip_cursor_notify( HWND hwnd, HWND new_clip_hwnd ); extern void ungrab_clipping_window(void); extern void reset_clipping_window(void); +extern BOOL clip_fullscreen_window( HWND hwnd ); extern void X11DRV_InitKeyboard( Display *display ); extern DWORD CDECL X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, DWORD timeout, DWORD mask, DWORD flags );