Module: wine Branch: master Commit: ae2b356361be4d9d25d82bc62d0fbb130aea4f0b URL: http://source.winehq.org/git/wine.git/?a=commit;h=ae2b356361be4d9d25d82bc62d...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Apr 5 11:50:45 2011 +0200
winex11: Implement cursor clipping using a pointer grab.
---
dlls/winex11.drv/desktop.c | 1 + dlls/winex11.drv/mouse.c | 56 +++++++++++++++++++++++++++++++++++- dlls/winex11.drv/window.c | 34 +++++++++++++++++++-- dlls/winex11.drv/winex11.drv.spec | 1 + dlls/winex11.drv/x11drv.h | 1 + 5 files changed, 87 insertions(+), 6 deletions(-)
diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index 4a36e46..eefc74c 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -258,6 +258,7 @@ void X11DRV_resize_desktop( unsigned int width, unsigned int height ) virtual_screen_rect.right - virtual_screen_rect.left, virtual_screen_rect.bottom - virtual_screen_rect.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE ); + X11DRV_ClipCursor( NULL ); SendMessageTimeoutW( HWND_BROADCAST, WM_DISPLAYCHANGE, screen_bpp, MAKELPARAM( width, height ), SMTO_ABORTIFHUNG, 2000, NULL ); } diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 1a2d618..2b793e1 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -95,6 +95,7 @@ static const UINT button_up_flags[NB_BUTTONS] = static HWND cursor_window; static DWORD last_time_modified; static XContext cursor_context; +static RECT clip_rect; static Cursor create_cursor( HANDLE handle );
@@ -216,11 +217,18 @@ void sync_window_cursor( struct x11drv_win_data *data ) static void send_mouse_input( HWND hwnd, UINT flags, Window window, int x, int y, unsigned int state, DWORD mouse_data, Time time ) { - struct x11drv_win_data *data = X11DRV_get_win_data( hwnd ); + struct x11drv_win_data *data; POINT pt; INPUT input;
- if (!data) return; + if (!hwnd && window == clip_window) + { + pt.x = x + clip_rect.left; + pt.y = y + clip_rect.top; + goto done; + } + + if (!(data = X11DRV_get_win_data( hwnd ))) return;
if (window == data->whole_window) { @@ -270,6 +278,7 @@ static void send_mouse_input( HWND hwnd, UINT flags, Window window, int x, int y SERVER_END_REQ; }
+done: input.type = INPUT_MOUSE; input.u.mi.dx = pt.x; input.u.mi.dy = pt.y; @@ -911,6 +920,49 @@ BOOL CDECL X11DRV_GetCursorPos(LPPOINT pos) return ret; }
+/*********************************************************************** + * ClipCursor (X11DRV.@) + */ +BOOL CDECL X11DRV_ClipCursor( LPCRECT clip ) +{ + Display *display = thread_init_display(); + + if (!clip_window) return TRUE; + + /* we are clipping if the clip rectangle is smaller than the screen */ + if (clip && (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 */ + + TRACE( "clipping to %s\n", wine_dbgstr_rect(clip) ); + wine_tsx11_lock(); + XUnmapWindow( display, clip_window ); + XMoveResizeWindow( display, clip_window, + clip->left - virtual_screen_rect.left, clip->top - virtual_screen_rect.top, + clip->right - clip->left, clip->bottom - clip->top ); + XMapWindow( display, clip_window ); + if (!XGrabPointer( display, clip_window, False, + PointerMotionMask | ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, clip_window, None, CurrentTime )) + { + wine_tsx11_unlock(); + clip_rect = *clip; + return TRUE; + } + wine_tsx11_unlock(); + } + + /* release the grab if any */ + TRACE( "no longer clipping\n" ); + wine_tsx11_lock(); + XUnmapWindow( display, clip_window ); + wine_tsx11_unlock(); + return TRUE; +}
/*********************************************************************** * X11DRV_ButtonPress diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index e2ffccc..1fcadb5 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -68,6 +68,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
#define SWP_AGG_NOPOSCHANGE (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOZORDER)
+/* cursor clipping window */ +Window clip_window = 0; + /* X context to associate a hwnd to an X window */ XContext winContext = 0;
@@ -82,6 +85,7 @@ static const char foreign_window_prop[] = "__wine_x11_foreign_window"; static const char whole_window_prop[] = "__wine_x11_whole_window"; static const char client_window_prop[]= "__wine_x11_client_window"; static const char icon_window_prop[] = "__wine_x11_icon_window"; +static const char clip_window_prop[] = "__wine_x11_clip_window"; static const char fbconfig_id_prop[] = "__wine_x11_fbconfig_id"; static const char gl_drawable_prop[] = "__wine_x11_gl_drawable"; static const char pixmap_prop[] = "__wine_x11_pixmap"; @@ -1962,13 +1966,35 @@ BOOL CDECL X11DRV_CreateDesktopWindow( HWND hwnd ) */ BOOL CDECL X11DRV_CreateWindow( HWND hwnd ) { - if (hwnd == GetDesktopWindow() && root_window != DefaultRootWindow( gdi_display )) + Display *display = thread_init_display(); + + if (hwnd == GetDesktopWindow()) { - Display *display = thread_init_display(); + XSetWindowAttributes attr; + + if (root_window != DefaultRootWindow( gdi_display )) + { + /* the desktop win data can't be created lazily */ + if (!create_desktop_win_data( display, hwnd )) return FALSE; + }
- /* the desktop win data can't be created lazily */ - if (!create_desktop_win_data( display, hwnd )) return FALSE; + /* create the cursor clipping window */ + attr.override_redirect = TRUE; + attr.event_mask = StructureNotifyMask; + wine_tsx11_lock(); + clip_window = XCreateWindow( display, root_window, 0, 0, 1, 1, 0, 0, + InputOnly, visual, CWOverrideRedirect | CWEventMask, &attr ); + wine_tsx11_unlock(); + SetPropA( hwnd, clip_window_prop, (HANDLE)clip_window ); } + else if (!clip_window) + { + clip_window = (Window)GetPropA( GetDesktopWindow(), clip_window_prop ); + wine_tsx11_lock(); + XSelectInput( display, clip_window, StructureNotifyMask ); + wine_tsx11_unlock(); + } + return TRUE; }
diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec index 85177c5..f5c45d1 100644 --- a/dlls/winex11.drv/winex11.drv.spec +++ b/dlls/winex11.drv/winex11.drv.spec @@ -77,6 +77,7 @@ @ cdecl SetCursor(long) X11DRV_SetCursor @ cdecl GetCursorPos(ptr) X11DRV_GetCursorPos @ cdecl SetCursorPos(long long) X11DRV_SetCursorPos +@ cdecl ClipCursor(ptr) X11DRV_ClipCursor @ cdecl GetScreenSaveActive() X11DRV_GetScreenSaveActive @ cdecl SetScreenSaveActive(long) X11DRV_SetScreenSaveActive @ cdecl ChangeDisplaySettingsEx(ptr ptr long long long) X11DRV_ChangeDisplaySettingsEx diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index e51a614..a746d08 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -585,6 +585,7 @@ static inline size_t get_property_size( int format, unsigned long count )
extern Visual *visual; extern Window root_window; +extern Window clip_window; extern unsigned int screen_width; extern unsigned int screen_height; extern unsigned int screen_bpp;