Commit 02e81740 authored by Alexandre Julliard's avatar Alexandre Julliard

server: Store the cursor clip rectangle in the server.

parent 183c41b4
...@@ -71,8 +71,6 @@ typedef struct ...@@ -71,8 +71,6 @@ typedef struct
#include "poppack.h" #include "poppack.h"
static RECT CURSOR_ClipRect; /* Cursor clipping rect */
static HDC screen_dc; static HDC screen_dc;
static const WCHAR DISPLAYW[] = {'D','I','S','P','L','A','Y',0}; static const WCHAR DISPLAYW[] = {'D','I','S','P','L','A','Y',0};
...@@ -1526,21 +1524,32 @@ HCURSOR WINAPI GetCursor(void) ...@@ -1526,21 +1524,32 @@ HCURSOR WINAPI GetCursor(void)
*/ */
BOOL WINAPI DECLSPEC_HOTPATCH ClipCursor( const RECT *rect ) BOOL WINAPI DECLSPEC_HOTPATCH ClipCursor( const RECT *rect )
{ {
RECT virt; BOOL ret;
RECT new_rect;
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) );
if (!IntersectRect( &CURSOR_ClipRect, &virt, rect )) TRACE( "Clipping to %s\n", wine_dbgstr_rect(rect) );
CURSOR_ClipRect = virt;
USER_Driver->pClipCursor( rect ); SERVER_START_REQ( set_cursor )
return TRUE; {
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 ) ...@@ -1549,10 +1558,23 @@ BOOL WINAPI DECLSPEC_HOTPATCH ClipCursor( const RECT *rect )
*/ */
BOOL WINAPI DECLSPEC_HOTPATCH GetClipCursor( RECT *rect ) BOOL WINAPI DECLSPEC_HOTPATCH GetClipCursor( RECT *rect )
{ {
/* If this is first time - initialize the rect */ BOOL ret;
if (IsRectEmpty( &CURSOR_ClipRect )) ClipCursor( NULL );
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;
} }
......
...@@ -425,6 +425,7 @@ void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y, ...@@ -425,6 +425,7 @@ void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y,
if ((injected_flags & LLMHF_INJECTED) && if ((injected_flags & LLMHF_INJECTED) &&
((flags & MOUSEEVENTF_ABSOLUTE) || x || y)) /* we have to actually move the cursor */ ((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 ); X11DRV_SetCursorPos( pt.x, pt.y );
} }
else else
...@@ -1084,25 +1085,15 @@ void CDECL X11DRV_SetCursor( HCURSOR handle ) ...@@ -1084,25 +1085,15 @@ void CDECL X11DRV_SetCursor( HCURSOR handle )
BOOL CDECL X11DRV_SetCursorPos( INT x, INT y ) BOOL CDECL X11DRV_SetCursorPos( INT x, INT y )
{ {
Display *display = thread_init_display(); Display *display = thread_init_display();
POINT pt;
TRACE( "warping to (%d,%d)\n", x, y ); TRACE( "warping to (%d,%d)\n", x, y );
wine_tsx11_lock(); 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, 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 */ 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(); wine_tsx11_unlock();
return TRUE; return TRUE;
} }
......
...@@ -4771,6 +4771,7 @@ struct set_cursor_request ...@@ -4771,6 +4771,7 @@ struct set_cursor_request
int show_count; int show_count;
int x; int x;
int y; int y;
rectangle_t clip;
}; };
struct set_cursor_reply struct set_cursor_reply
{ {
...@@ -4779,10 +4780,12 @@ struct set_cursor_reply ...@@ -4779,10 +4780,12 @@ struct set_cursor_reply
int prev_count; int prev_count;
int new_x; int new_x;
int new_y; int new_y;
rectangle_t new_clip;
}; };
#define SET_CURSOR_HANDLE 0x01 #define SET_CURSOR_HANDLE 0x01
#define SET_CURSOR_COUNT 0x02 #define SET_CURSOR_COUNT 0x02
#define SET_CURSOR_POS 0x04 #define SET_CURSOR_POS 0x04
#define SET_CURSOR_CLIP 0x08
enum request enum request
...@@ -5530,6 +5533,6 @@ union generic_reply ...@@ -5530,6 +5533,6 @@ union generic_reply
struct set_cursor_reply set_cursor_reply; struct set_cursor_reply set_cursor_reply;
}; };
#define SERVER_PROTOCOL_VERSION 413 #define SERVER_PROTOCOL_VERSION 414
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
...@@ -3292,12 +3292,15 @@ enum coords_relative ...@@ -3292,12 +3292,15 @@ enum coords_relative
int show_count; /* show count increment/decrement */ int show_count; /* show count increment/decrement */
int x; /* cursor position */ int x; /* cursor position */
int y; int y;
rectangle_t clip; /* cursor clip rectangle */
@REPLY @REPLY
user_handle_t prev_handle; /* previous handle */ user_handle_t prev_handle; /* previous handle */
int prev_count; /* previous show count */ int prev_count; /* previous show count */
int new_x; /* new position */ int new_x; /* new position */
int new_y; int new_y;
rectangle_t new_clip; /* new clip rectangle */
@END @END
#define SET_CURSOR_HANDLE 0x01 #define SET_CURSOR_HANDLE 0x01
#define SET_CURSOR_COUNT 0x02 #define SET_CURSOR_COUNT 0x02
#define SET_CURSOR_POS 0x04 #define SET_CURSOR_POS 0x04
#define SET_CURSOR_CLIP 0x08
...@@ -1264,6 +1264,13 @@ static user_handle_t find_hardware_message_window( struct thread_input *input, s ...@@ -1264,6 +1264,13 @@ static user_handle_t find_hardware_message_window( struct thread_input *input, s
return win; 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 */ /* queue a hardware message into a given thread input */
static void queue_hardware_message( struct desktop *desktop, struct thread_input *input, static void queue_hardware_message( struct desktop *desktop, struct thread_input *input,
struct message *msg ) struct message *msg )
...@@ -1273,11 +1280,7 @@ static void queue_hardware_message( struct desktop *desktop, struct thread_input ...@@ -1273,11 +1280,7 @@ static void queue_hardware_message( struct desktop *desktop, struct thread_input
unsigned int msg_code; unsigned int msg_code;
struct hardware_msg_data *data = msg->data; struct hardware_msg_data *data = msg->data;
if (msg->msg == WM_MOUSEMOVE) if (msg->msg == WM_MOUSEMOVE) set_cursor_pos( desktop, data->x, data->y );
{
desktop->cursor_x = data->x;
desktop->cursor_y = data->y;
}
data->x = desktop->cursor_x; data->x = desktop->cursor_x;
data->y = desktop->cursor_y; data->y = desktop->cursor_y;
last_input_time = get_tick_count(); last_input_time = get_tick_count();
...@@ -2302,10 +2305,17 @@ DECL_HANDLER(set_cursor) ...@@ -2302,10 +2305,17 @@ DECL_HANDLER(set_cursor)
} }
if (req->flags & SET_CURSOR_POS) if (req->flags & SET_CURSOR_POS)
{ {
input->desktop->cursor_x = req->x; set_cursor_pos( input->desktop, req->x, req->y );
input->desktop->cursor_y = 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_x = input->desktop->cursor_x;
reply->new_y = input->desktop->cursor_y; reply->new_y = input->desktop->cursor_y;
reply->new_clip = input->desktop->cursor_clip;
} }
...@@ -2102,12 +2102,14 @@ C_ASSERT( FIELD_OFFSET(struct set_cursor_request, handle) == 16 ); ...@@ -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, show_count) == 20 );
C_ASSERT( FIELD_OFFSET(struct set_cursor_request, x) == 24 ); C_ASSERT( FIELD_OFFSET(struct set_cursor_request, x) == 24 );
C_ASSERT( FIELD_OFFSET(struct set_cursor_request, y) == 28 ); 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_handle) == 8 );
C_ASSERT( FIELD_OFFSET(struct set_cursor_reply, prev_count) == 12 ); 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_x) == 16 );
C_ASSERT( FIELD_OFFSET(struct set_cursor_reply, new_y) == 20 ); 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 */ #endif /* WANT_REQUEST_HANDLERS */
......
...@@ -3873,6 +3873,7 @@ static void dump_set_cursor_request( const struct set_cursor_request *req ) ...@@ -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, ", show_count=%d", req->show_count );
fprintf( stderr, ", x=%d", req->x ); fprintf( stderr, ", x=%d", req->x );
fprintf( stderr, ", y=%d", req->y ); fprintf( stderr, ", y=%d", req->y );
dump_rectangle( ", clip=", &req->clip );
} }
static void dump_set_cursor_reply( const struct set_cursor_reply *req ) 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 ) ...@@ -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, ", prev_count=%d", req->prev_count );
fprintf( stderr, ", new_x=%d", req->new_x ); fprintf( stderr, ", new_x=%d", req->new_x );
fprintf( stderr, ", new_y=%d", req->new_y ); fprintf( stderr, ", new_y=%d", req->new_y );
dump_rectangle( ", new_clip=", &req->new_clip );
} }
static const dump_func req_dumpers[REQ_NB_REQUESTS] = { static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
......
...@@ -65,6 +65,7 @@ struct desktop ...@@ -65,6 +65,7 @@ struct desktop
unsigned int users; /* processes and threads using this desktop */ unsigned int users; /* processes and threads using this desktop */
int cursor_x; /* cursor position */ int cursor_x; /* cursor position */
int cursor_y; int cursor_y;
rectangle_t cursor_clip; /* cursor clip rectangle */
}; };
/* user handles functions */ /* user handles functions */
...@@ -133,6 +134,7 @@ extern int rect_in_region( struct region *region, const rectangle_t *rect ); ...@@ -133,6 +134,7 @@ extern int rect_in_region( struct region *region, const rectangle_t *rect );
/* window functions */ /* window functions */
extern struct process *get_top_window_owner( struct desktop *desktop ); 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 close_desktop_window( struct desktop *desktop );
extern void destroy_window( struct window *win ); extern void destroy_window( struct window *win );
extern void destroy_thread_windows( struct thread *thread ); 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 ...@@ -177,4 +179,14 @@ static inline void mirror_rect( const rectangle_t *client_rect, rectangle_t *rec
rect->right = width - tmp; 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 */ #endif /* __WINE_SERVER_USER_H */
...@@ -394,6 +394,14 @@ struct process *get_top_window_owner( struct desktop *desktop ) ...@@ -394,6 +394,14 @@ struct process *get_top_window_owner( struct desktop *desktop )
return win->thread->process; 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 */ /* attempt to close the desktop window when the last process using it is gone */
void close_desktop_window( struct desktop *desktop ) void close_desktop_window( struct desktop *desktop )
{ {
...@@ -888,17 +896,6 @@ static struct region *clip_children( struct window *parent, struct window *last, ...@@ -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 */ /* offset the coordinates of a rectangle */
static inline void offset_rect( rectangle_t *rect, int offset_x, int offset_y ) 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, ...@@ -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 the window is not visible, everything is easy */
if (!visible) return; if (!visible) return;
......
...@@ -234,6 +234,10 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned ...@@ -234,6 +234,10 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned
desktop->users = 0; desktop->users = 0;
desktop->cursor_x = 0; desktop->cursor_x = 0;
desktop->cursor_y = 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 ); list_add_tail( &winstation->desktops, &desktop->entry );
} }
} }
......
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