Commit ae2b3563 authored by Alexandre Julliard's avatar Alexandre Julliard

winex11: Implement cursor clipping using a pointer grab.

parent 21e86f60
...@@ -258,6 +258,7 @@ void X11DRV_resize_desktop( unsigned int width, unsigned int height ) ...@@ -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.right - virtual_screen_rect.left,
virtual_screen_rect.bottom - virtual_screen_rect.top, virtual_screen_rect.bottom - virtual_screen_rect.top,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE ); SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE );
X11DRV_ClipCursor( NULL );
SendMessageTimeoutW( HWND_BROADCAST, WM_DISPLAYCHANGE, screen_bpp, SendMessageTimeoutW( HWND_BROADCAST, WM_DISPLAYCHANGE, screen_bpp,
MAKELPARAM( width, height ), SMTO_ABORTIFHUNG, 2000, NULL ); MAKELPARAM( width, height ), SMTO_ABORTIFHUNG, 2000, NULL );
} }
......
...@@ -95,6 +95,7 @@ static const UINT button_up_flags[NB_BUTTONS] = ...@@ -95,6 +95,7 @@ static const UINT button_up_flags[NB_BUTTONS] =
static HWND cursor_window; static HWND cursor_window;
static DWORD last_time_modified; static DWORD last_time_modified;
static XContext cursor_context; static XContext cursor_context;
static RECT clip_rect;
static Cursor create_cursor( HANDLE handle ); static Cursor create_cursor( HANDLE handle );
...@@ -216,11 +217,18 @@ void sync_window_cursor( struct x11drv_win_data *data ) ...@@ -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, static void send_mouse_input( HWND hwnd, UINT flags, Window window, int x, int y,
unsigned int state, DWORD mouse_data, Time time ) 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; POINT pt;
INPUT input; 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) if (window == data->whole_window)
{ {
...@@ -270,6 +278,7 @@ static void send_mouse_input( HWND hwnd, UINT flags, Window window, int x, int y ...@@ -270,6 +278,7 @@ static void send_mouse_input( HWND hwnd, UINT flags, Window window, int x, int y
SERVER_END_REQ; SERVER_END_REQ;
} }
done:
input.type = INPUT_MOUSE; input.type = INPUT_MOUSE;
input.u.mi.dx = pt.x; input.u.mi.dx = pt.x;
input.u.mi.dy = pt.y; input.u.mi.dy = pt.y;
...@@ -911,6 +920,49 @@ BOOL CDECL X11DRV_GetCursorPos(LPPOINT pos) ...@@ -911,6 +920,49 @@ BOOL CDECL X11DRV_GetCursorPos(LPPOINT pos)
return ret; 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 * X11DRV_ButtonPress
......
...@@ -68,6 +68,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(x11drv); ...@@ -68,6 +68,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
#define SWP_AGG_NOPOSCHANGE (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOZORDER) #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 */ /* X context to associate a hwnd to an X window */
XContext winContext = 0; XContext winContext = 0;
...@@ -82,6 +85,7 @@ static const char foreign_window_prop[] = "__wine_x11_foreign_window"; ...@@ -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 whole_window_prop[] = "__wine_x11_whole_window";
static const char client_window_prop[]= "__wine_x11_client_window"; static const char client_window_prop[]= "__wine_x11_client_window";
static const char icon_window_prop[] = "__wine_x11_icon_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 fbconfig_id_prop[] = "__wine_x11_fbconfig_id";
static const char gl_drawable_prop[] = "__wine_x11_gl_drawable"; static const char gl_drawable_prop[] = "__wine_x11_gl_drawable";
static const char pixmap_prop[] = "__wine_x11_pixmap"; static const char pixmap_prop[] = "__wine_x11_pixmap";
...@@ -1962,13 +1966,35 @@ BOOL CDECL X11DRV_CreateDesktopWindow( HWND hwnd ) ...@@ -1962,13 +1966,35 @@ BOOL CDECL X11DRV_CreateDesktopWindow( HWND hwnd )
*/ */
BOOL CDECL X11DRV_CreateWindow( 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 */ /* create the cursor clipping window */
if (!create_desktop_win_data( display, hwnd )) return FALSE; 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; return TRUE;
} }
......
...@@ -77,6 +77,7 @@ ...@@ -77,6 +77,7 @@
@ cdecl SetCursor(long) X11DRV_SetCursor @ cdecl SetCursor(long) X11DRV_SetCursor
@ cdecl GetCursorPos(ptr) X11DRV_GetCursorPos @ cdecl GetCursorPos(ptr) X11DRV_GetCursorPos
@ cdecl SetCursorPos(long long) X11DRV_SetCursorPos @ cdecl SetCursorPos(long long) X11DRV_SetCursorPos
@ cdecl ClipCursor(ptr) X11DRV_ClipCursor
@ cdecl GetScreenSaveActive() X11DRV_GetScreenSaveActive @ cdecl GetScreenSaveActive() X11DRV_GetScreenSaveActive
@ cdecl SetScreenSaveActive(long) X11DRV_SetScreenSaveActive @ cdecl SetScreenSaveActive(long) X11DRV_SetScreenSaveActive
@ cdecl ChangeDisplaySettingsEx(ptr ptr long long long) X11DRV_ChangeDisplaySettingsEx @ cdecl ChangeDisplaySettingsEx(ptr ptr long long long) X11DRV_ChangeDisplaySettingsEx
......
...@@ -585,6 +585,7 @@ static inline size_t get_property_size( int format, unsigned long count ) ...@@ -585,6 +585,7 @@ static inline size_t get_property_size( int format, unsigned long count )
extern Visual *visual; extern Visual *visual;
extern Window root_window; extern Window root_window;
extern Window clip_window;
extern unsigned int screen_width; extern unsigned int screen_width;
extern unsigned int screen_height; extern unsigned int screen_height;
extern unsigned int screen_bpp; extern unsigned int screen_bpp;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment