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
#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;
}
......
......@@ -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;
}
......
......@@ -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 */
......@@ -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
......@@ -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;
}
......@@ -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 */
......
......@@ -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] = {
......
......@@ -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 */
......@@ -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;
......
......@@ -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 );
}
}
......
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