diff --git a/server/queue.c b/server/queue.c index c869daadb0c..1e2647aac27 100644 --- a/server/queue.c +++ b/server/queue.c @@ -449,8 +449,25 @@ static void get_message_defaults( struct msg_queue *queue, int *x, int *y, unsig *time = get_tick_count(); } +static void queue_clip_cursor_msg( struct desktop *desktop, lparam_t wparam, lparam_t lparam ) +{ + static const struct hw_msg_source source = { IMDT_UNAVAILABLE, IMO_SYSTEM }; + struct thread_input *input; + struct message *msg; + + if (!(msg = alloc_hardware_message( 0, source, get_tick_count(), 0 ))) return; + + msg->msg = WM_WINE_CLIPCURSOR; + msg->wparam = wparam; + msg->lparam = lparam; + msg->x = desktop->cursor.x; + msg->y = desktop->cursor.y; + if ((input = desktop->foreground_input)) msg->win = input->active; + queue_hardware_message( desktop, msg, 1 ); +} + /* set the cursor clip rectangle */ -void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect, int send_clip_msg ) +void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect, int reset ) { rectangle_t top_rect; int x, y; @@ -468,12 +485,16 @@ void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect, int s } else desktop->cursor.clip = top_rect; - if (send_clip_msg) post_desktop_message( desktop, WM_WINE_CLIPCURSOR, rect == NULL, 0 ); - /* warp the mouse to be inside the clip rect */ x = max( min( desktop->cursor.x, desktop->cursor.clip.right - 1 ), desktop->cursor.clip.left ); y = max( min( desktop->cursor.y, desktop->cursor.clip.bottom - 1 ), desktop->cursor.clip.top ); if (x != desktop->cursor.x || y != desktop->cursor.y) set_cursor_pos( desktop, x, y ); + + /* request clip cursor rectangle reset to the desktop thread */ + if (reset) post_desktop_message( desktop, WM_WINE_CLIPCURSOR, TRUE, FALSE ); + + /* notify foreground thread, of reset, or to apply new cursor clipping rect */ + queue_clip_cursor_msg( desktop, rect == NULL, reset ); } /* change the foreground input and reset the cursor clip rect */ @@ -558,6 +579,7 @@ static inline int get_hardware_msg_bit( struct message *msg ) if (msg->msg == WM_INPUT_DEVICE_CHANGE || msg->msg == WM_INPUT) return QS_RAWINPUT; if (msg->msg == WM_MOUSEMOVE || msg->msg == WM_NCMOUSEMOVE) return QS_MOUSEMOVE; if (msg->msg >= WM_KEYFIRST && msg->msg <= WM_KEYLAST) return QS_KEY; + if (msg->msg == WM_WINE_CLIPCURSOR) return QS_RAWINPUT; return QS_MOUSEBUTTON; } @@ -610,10 +632,36 @@ static int merge_mousemove( struct thread_input *input, const struct message *ms return 1; } +/* try to merge a WM_WINE_CLIPCURSOR message with the last in the list; return 1 if successful */ +static int merge_wine_clipcursor( struct thread_input *input, const struct message *msg ) +{ + struct message *prev; + + LIST_FOR_EACH_ENTRY_REV( prev, &input->msg_list, struct message, entry ) + if (prev->msg == WM_WINE_CLIPCURSOR) break; + if (&prev->entry == &input->msg_list) return 0; + + if (prev->result) return 0; + if (prev->win != msg->win) return 0; + if (prev->type != msg->type) return 0; + + /* now we can merge it */ + prev->wparam = msg->wparam; + prev->lparam = msg->lparam; + prev->x = msg->x; + prev->y = msg->y; + prev->time = msg->time; + list_remove( &prev->entry ); + list_add_tail( &input->msg_list, &prev->entry ); + + return 1; +} + /* try to merge a message with the messages in the list; return 1 if successful */ static int merge_message( struct thread_input *input, const struct message *msg ) { if (msg->msg == WM_MOUSEMOVE) return merge_mousemove( input, msg ); + if (msg->msg == WM_WINE_CLIPCURSOR) return merge_wine_clipcursor( input, msg ); return 0; } diff --git a/server/user.h b/server/user.h index dde7a3308d7..a18c94ec89d 100644 --- a/server/user.h +++ b/server/user.h @@ -109,7 +109,7 @@ extern void queue_cleanup_window( struct thread *thread, user_handle_t win ); extern int init_thread_queue( struct thread *thread ); extern int attach_thread_input( struct thread *thread_from, struct thread *thread_to ); extern void detach_thread_input( struct thread *thread_from ); -extern void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect, int send_clip_msg ); +extern void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect, int reset ); extern void post_message( user_handle_t win, unsigned int message, lparam_t wparam, lparam_t lparam ); extern void send_notify_message( user_handle_t win, unsigned int message,