server: Store the cursor clip rectangle in the server.
This commit is contained in:
parent
183c41b49a
commit
02e8174067
|
@ -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;
|
||||
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\n", wine_dbgstr_rect(rect) );
|
||||
|
||||
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 ))
|
||||
CURSOR_ClipRect = virt;
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue