From 02e8174067216e085e2f6a0d1dbbfabad74491b3 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 25 Feb 2011 11:31:47 +0100 Subject: [PATCH] server: Store the cursor clip rectangle in the server. --- dlls/user32/cursoricon.c | 58 +++++++++++++++++++++++----------- dlls/winex11.drv/mouse.c | 17 +++------- include/wine/server_protocol.h | 5 ++- server/protocol.def | 3 ++ server/queue.c | 24 ++++++++++---- server/request.h | 6 ++-- server/trace.c | 2 ++ server/user.h | 12 +++++++ server/window.c | 22 ++++++------- server/winstation.c | 4 +++ 10 files changed, 101 insertions(+), 52 deletions(-) diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index d014711789..d007c6eaf5 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -71,8 +71,6 @@ typedef struct #include "poppack.h" -static RECT CURSOR_ClipRect; /* Cursor clipping rect */ - static HDC screen_dc; static const WCHAR DISPLAYW[] = {'D','I','S','P','L','A','Y',0}; @@ -1526,21 +1524,32 @@ HCURSOR WINAPI GetCursor(void) */ BOOL WINAPI DECLSPEC_HOTPATCH ClipCursor( const RECT *rect ) { - RECT virt; - - SetRect( &virt, 0, 0, GetSystemMetrics( SM_CXVIRTUALSCREEN ), - GetSystemMetrics( SM_CYVIRTUALSCREEN ) ); - OffsetRect( &virt, GetSystemMetrics( SM_XVIRTUALSCREEN ), - GetSystemMetrics( SM_YVIRTUALSCREEN ) ); - - TRACE( "Clipping to: %s was: %s screen: %s\n", wine_dbgstr_rect(rect), - wine_dbgstr_rect(&CURSOR_ClipRect), wine_dbgstr_rect(&virt) ); + BOOL ret; + RECT new_rect; - if (!IntersectRect( &CURSOR_ClipRect, &virt, rect )) - CURSOR_ClipRect = virt; + TRACE( "Clipping to %s\n", wine_dbgstr_rect(rect) ); - USER_Driver->pClipCursor( rect ); - return TRUE; + SERVER_START_REQ( set_cursor ) + { + req->flags = SET_CURSOR_CLIP; + if (rect) + { + req->clip.left = rect->left; + req->clip.top = rect->top; + req->clip.right = rect->right; + req->clip.bottom = rect->bottom; + } + if ((ret = !wine_server_call( req ))) + { + new_rect.left = reply->new_clip.left; + new_rect.top = reply->new_clip.top; + new_rect.right = reply->new_clip.right; + new_rect.bottom = reply->new_clip.bottom; + } + } + SERVER_END_REQ; + if (ret) USER_Driver->pClipCursor( &new_rect ); + return ret; } @@ -1549,10 +1558,23 @@ BOOL WINAPI DECLSPEC_HOTPATCH ClipCursor( const RECT *rect ) */ BOOL WINAPI DECLSPEC_HOTPATCH GetClipCursor( RECT *rect ) { - /* If this is first time - initialize the rect */ - if (IsRectEmpty( &CURSOR_ClipRect )) ClipCursor( NULL ); + BOOL ret; - return CopyRect( rect, &CURSOR_ClipRect ); + if (!rect) return FALSE; + + SERVER_START_REQ( set_cursor ) + { + req->flags = 0; + if ((ret = !wine_server_call( req ))) + { + rect->left = reply->new_clip.left; + rect->top = reply->new_clip.top; + rect->right = reply->new_clip.right; + rect->bottom = reply->new_clip.bottom; + } + } + SERVER_END_REQ; + return ret; } diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 794056bfa2..4060018a94 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -425,6 +425,7 @@ void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y, if ((injected_flags & LLMHF_INJECTED) && ((flags & MOUSEEVENTF_ABSOLUTE) || x || y)) /* we have to actually move the cursor */ { + clip_point_to_rect( &cursor_clip, &pt ); X11DRV_SetCursorPos( pt.x, pt.y ); } else @@ -1084,25 +1085,15 @@ void CDECL X11DRV_SetCursor( HCURSOR handle ) BOOL CDECL X11DRV_SetCursorPos( INT x, INT y ) { Display *display = thread_init_display(); - POINT pt; TRACE( "warping to (%d,%d)\n", x, y ); wine_tsx11_lock(); - if (cursor_pos.x == x && cursor_pos.y == y) - { - wine_tsx11_unlock(); - /* We still need to generate WM_MOUSEMOVE */ - queue_raw_mouse_message( WM_MOUSEMOVE, 0, x, y, 0, GetCurrentTime(), 0, 0 ); - return TRUE; - } - - pt.x = x; pt.y = y; - clip_point_to_rect( &cursor_clip, &pt); XWarpPointer( display, root_window, root_window, 0, 0, 0, 0, - pt.x - virtual_screen_rect.left, pt.y - virtual_screen_rect.top ); + x - virtual_screen_rect.left, y - virtual_screen_rect.top ); XFlush( display ); /* avoids bad mouse lag in games that do their own mouse warping */ - cursor_pos = pt; + cursor_pos.x = x; + cursor_pos.y = y; wine_tsx11_unlock(); return TRUE; } diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 63a6d9d912..66f1cdb713 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -4771,6 +4771,7 @@ struct set_cursor_request int show_count; int x; int y; + rectangle_t clip; }; struct set_cursor_reply { @@ -4779,10 +4780,12 @@ struct set_cursor_reply int prev_count; int new_x; int new_y; + rectangle_t new_clip; }; #define SET_CURSOR_HANDLE 0x01 #define SET_CURSOR_COUNT 0x02 #define SET_CURSOR_POS 0x04 +#define SET_CURSOR_CLIP 0x08 enum request @@ -5530,6 +5533,6 @@ union generic_reply struct set_cursor_reply set_cursor_reply; }; -#define SERVER_PROTOCOL_VERSION 413 +#define SERVER_PROTOCOL_VERSION 414 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index be644b5625..e38857d58a 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3292,12 +3292,15 @@ enum coords_relative int show_count; /* show count increment/decrement */ int x; /* cursor position */ int y; + rectangle_t clip; /* cursor clip rectangle */ @REPLY user_handle_t prev_handle; /* previous handle */ int prev_count; /* previous show count */ int new_x; /* new position */ int new_y; + rectangle_t new_clip; /* new clip rectangle */ @END #define SET_CURSOR_HANDLE 0x01 #define SET_CURSOR_COUNT 0x02 #define SET_CURSOR_POS 0x04 +#define SET_CURSOR_CLIP 0x08 diff --git a/server/queue.c b/server/queue.c index 20e0fc00c0..16486cdf86 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1264,6 +1264,13 @@ static user_handle_t find_hardware_message_window( struct thread_input *input, s return win; } +/* set the cursor position, clipping to the cursor clip rect */ +static void set_cursor_pos( struct desktop *desktop, int x, int y ) +{ + desktop->cursor_x = min( max( x, desktop->cursor_clip.left ), desktop->cursor_clip.right - 1 ); + desktop->cursor_y = min( max( y, desktop->cursor_clip.top ), desktop->cursor_clip.bottom - 1 ); +} + /* queue a hardware message into a given thread input */ static void queue_hardware_message( struct desktop *desktop, struct thread_input *input, struct message *msg ) @@ -1273,11 +1280,7 @@ static void queue_hardware_message( struct desktop *desktop, struct thread_input unsigned int msg_code; struct hardware_msg_data *data = msg->data; - if (msg->msg == WM_MOUSEMOVE) - { - desktop->cursor_x = data->x; - desktop->cursor_y = data->y; - } + if (msg->msg == WM_MOUSEMOVE) set_cursor_pos( desktop, data->x, data->y ); data->x = desktop->cursor_x; data->y = desktop->cursor_y; last_input_time = get_tick_count(); @@ -2302,10 +2305,17 @@ DECL_HANDLER(set_cursor) } if (req->flags & SET_CURSOR_POS) { - input->desktop->cursor_x = req->x; - input->desktop->cursor_y = req->y; + set_cursor_pos( input->desktop, req->x, req->y ); + } + if (req->flags & SET_CURSOR_CLIP) + { + rectangle_t top_rect; + get_top_window_rectangle( input->desktop, &top_rect ); + if (!intersect_rect( &input->desktop->cursor_clip, &top_rect, &req->clip )) + input->desktop->cursor_clip = top_rect; } reply->new_x = input->desktop->cursor_x; reply->new_y = input->desktop->cursor_y; + reply->new_clip = input->desktop->cursor_clip; } diff --git a/server/request.h b/server/request.h index f1894c0eae..67ec84434a 100644 --- a/server/request.h +++ b/server/request.h @@ -2102,12 +2102,14 @@ C_ASSERT( FIELD_OFFSET(struct set_cursor_request, handle) == 16 ); C_ASSERT( FIELD_OFFSET(struct set_cursor_request, show_count) == 20 ); C_ASSERT( FIELD_OFFSET(struct set_cursor_request, x) == 24 ); C_ASSERT( FIELD_OFFSET(struct set_cursor_request, y) == 28 ); -C_ASSERT( sizeof(struct set_cursor_request) == 32 ); +C_ASSERT( FIELD_OFFSET(struct set_cursor_request, clip) == 32 ); +C_ASSERT( sizeof(struct set_cursor_request) == 48 ); C_ASSERT( FIELD_OFFSET(struct set_cursor_reply, prev_handle) == 8 ); C_ASSERT( FIELD_OFFSET(struct set_cursor_reply, prev_count) == 12 ); C_ASSERT( FIELD_OFFSET(struct set_cursor_reply, new_x) == 16 ); C_ASSERT( FIELD_OFFSET(struct set_cursor_reply, new_y) == 20 ); -C_ASSERT( sizeof(struct set_cursor_reply) == 24 ); +C_ASSERT( FIELD_OFFSET(struct set_cursor_reply, new_clip) == 24 ); +C_ASSERT( sizeof(struct set_cursor_reply) == 40 ); #endif /* WANT_REQUEST_HANDLERS */ diff --git a/server/trace.c b/server/trace.c index 5305caca63..7ea8ceeb07 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3873,6 +3873,7 @@ static void dump_set_cursor_request( const struct set_cursor_request *req ) fprintf( stderr, ", show_count=%d", req->show_count ); fprintf( stderr, ", x=%d", req->x ); fprintf( stderr, ", y=%d", req->y ); + dump_rectangle( ", clip=", &req->clip ); } static void dump_set_cursor_reply( const struct set_cursor_reply *req ) @@ -3881,6 +3882,7 @@ static void dump_set_cursor_reply( const struct set_cursor_reply *req ) fprintf( stderr, ", prev_count=%d", req->prev_count ); fprintf( stderr, ", new_x=%d", req->new_x ); fprintf( stderr, ", new_y=%d", req->new_y ); + dump_rectangle( ", new_clip=", &req->new_clip ); } static const dump_func req_dumpers[REQ_NB_REQUESTS] = { diff --git a/server/user.h b/server/user.h index 4d39e408a4..8fc19e925f 100644 --- a/server/user.h +++ b/server/user.h @@ -65,6 +65,7 @@ struct desktop unsigned int users; /* processes and threads using this desktop */ int cursor_x; /* cursor position */ int cursor_y; + rectangle_t cursor_clip; /* cursor clip rectangle */ }; /* user handles functions */ @@ -133,6 +134,7 @@ extern int rect_in_region( struct region *region, const rectangle_t *rect ); /* window functions */ extern struct process *get_top_window_owner( struct desktop *desktop ); +extern void get_top_window_rectangle( struct desktop *desktop, rectangle_t *rect ); extern void close_desktop_window( struct desktop *desktop ); extern void destroy_window( struct window *win ); extern void destroy_thread_windows( struct thread *thread ); @@ -177,4 +179,14 @@ static inline void mirror_rect( const rectangle_t *client_rect, rectangle_t *rec rect->right = width - tmp; } +/* compute the intersection of two rectangles; return 0 if the result is empty */ +static inline int intersect_rect( rectangle_t *dst, const rectangle_t *src1, const rectangle_t *src2 ) +{ + dst->left = max( src1->left, src2->left ); + dst->top = max( src1->top, src2->top ); + dst->right = min( src1->right, src2->right ); + dst->bottom = min( src1->bottom, src2->bottom ); + return (dst->left < dst->right && dst->top < dst->bottom); +} + #endif /* __WINE_SERVER_USER_H */ diff --git a/server/window.c b/server/window.c index 635dd9ba9b..5d211ebc01 100644 --- a/server/window.c +++ b/server/window.c @@ -394,6 +394,14 @@ struct process *get_top_window_owner( struct desktop *desktop ) return win->thread->process; } +/* get the top window size of a given desktop */ +void get_top_window_rectangle( struct desktop *desktop, rectangle_t *rect ) +{ + struct window *win = desktop->top_window; + if (!win) rect->left = rect->top = rect->right = rect->bottom = 0; + else *rect = win->window_rect; +} + /* attempt to close the desktop window when the last process using it is gone */ void close_desktop_window( struct desktop *desktop ) { @@ -888,17 +896,6 @@ static struct region *clip_children( struct window *parent, struct window *last, } -/* compute the intersection of two rectangles; return 0 if the result is empty */ -static inline int intersect_rect( rectangle_t *dst, const rectangle_t *src1, const rectangle_t *src2 ) -{ - dst->left = max( src1->left, src2->left ); - dst->top = max( src1->top, src2->top ); - dst->right = min( src1->right, src2->right ); - dst->bottom = min( src1->bottom, src2->bottom ); - return (dst->left < dst->right && dst->top < dst->bottom); -} - - /* offset the coordinates of a rectangle */ static inline void offset_rect( rectangle_t *rect, int offset_x, int offset_y ) { @@ -1555,6 +1552,9 @@ static void set_window_pos( struct window *win, struct window *previous, } } + /* reset cursor clip rectangle when the desktop changes size */ + if (win == win->desktop->top_window) win->desktop->cursor_clip = *window_rect; + /* if the window is not visible, everything is easy */ if (!visible) return; diff --git a/server/winstation.c b/server/winstation.c index 3d1ac3ce9e..f23dcfecb4 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -234,6 +234,10 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned desktop->users = 0; desktop->cursor_x = 0; desktop->cursor_y = 0; + desktop->cursor_clip.left = 0; + desktop->cursor_clip.top = 0; + desktop->cursor_clip.right = 0; + desktop->cursor_clip.bottom = 0; list_add_tail( &winstation->desktops, &desktop->entry ); } } -- 2.32.0.93.g670b81a890