Alexandre Julliard : winex11: Implement cursor clipping using a pointer grab.
Alexandre Julliard
julliard at winehq.org
Tue Apr 5 11:23:31 CDT 2011
Module: wine
Branch: master
Commit: ae2b356361be4d9d25d82bc62d0fbb130aea4f0b
URL: http://source.winehq.org/git/wine.git/?a=commit;h=ae2b356361be4d9d25d82bc62d0fbb130aea4f0b
Author: Alexandre Julliard <julliard at 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;
More information about the wine-cvs
mailing list