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 )
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 );
}
......
......@@ -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
......
......@@ -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;
}
......
......@@ -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
......
......@@ -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;
......
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