diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 0c3155ddf9e..1a20438b6bc 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -4658,6 +4658,24 @@ struct free_user_handle_reply }; + +struct set_cursor_request +{ + struct request_header __header; + unsigned int flags; + user_handle_t handle; + int show_count; +}; +struct set_cursor_reply +{ + struct reply_header __header; + user_handle_t prev_handle; + int prev_count; +}; +#define SET_CURSOR_HANDLE 0x01 +#define SET_CURSOR_COUNT 0x02 + + enum request { REQ_new_process, @@ -4901,6 +4919,7 @@ enum request REQ_set_window_layered_info, REQ_alloc_user_handle, REQ_free_user_handle, + REQ_set_cursor, REQ_NB_REQUESTS }; @@ -5149,6 +5168,7 @@ union generic_request struct set_window_layered_info_request set_window_layered_info_request; struct alloc_user_handle_request alloc_user_handle_request; struct free_user_handle_request free_user_handle_request; + struct set_cursor_request set_cursor_request; }; union generic_reply { @@ -5395,8 +5415,9 @@ union generic_reply struct set_window_layered_info_reply set_window_layered_info_reply; struct alloc_user_handle_reply alloc_user_handle_reply; struct free_user_handle_reply free_user_handle_reply; + struct set_cursor_reply set_cursor_reply; }; -#define SERVER_PROTOCOL_VERSION 396 +#define SERVER_PROTOCOL_VERSION 397 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index e9c5cba1809..0aa8f6c1ec8 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3250,3 +3250,16 @@ enum message_type @REQ(free_user_handle) user_handle_t handle; /* handle to free*/ @END + + +/* Set/get the current cursor */ +@REQ(set_cursor) + unsigned int flags; /* flags for fields to set (see below) */ + user_handle_t handle; /* handle to the cursor */ + int show_count; /* show count increment/decrement */ +@REPLY + user_handle_t prev_handle; /* previous handle */ + int prev_count; /* previous show count */ +@END +#define SET_CURSOR_HANDLE 0x01 +#define SET_CURSOR_COUNT 0x02 diff --git a/server/queue.c b/server/queue.c index becdbda051f..c49c3e138c6 100644 --- a/server/queue.c +++ b/server/queue.c @@ -103,6 +103,8 @@ struct thread_input rectangle_t caret_rect; /* caret rectangle */ int caret_hide; /* caret hide count */ int caret_state; /* caret on/off state */ + user_handle_t cursor; /* current cursor */ + int cursor_count; /* cursor show count */ struct list msg_list; /* list of hardware messages */ unsigned char keystate[256]; /* state of each key */ }; @@ -118,6 +120,7 @@ struct msg_queue int paint_count; /* pending paint messages count */ int quit_message; /* is there a pending quit message? */ int exit_code; /* exit code of pending quit message */ + int cursor_count; /* per-queue cursor show count */ struct list msg_list[NB_MSG_KINDS]; /* lists of messages */ struct list send_result; /* stack of sent messages waiting for result */ struct list callback_result; /* list of callback messages waiting for result */ @@ -223,11 +226,13 @@ static struct thread_input *create_thread_input( struct thread *thread ) if ((input = alloc_object( &thread_input_ops ))) { - input->focus = 0; - input->capture = 0; - input->active = 0; - input->menu_owner = 0; - input->move_size = 0; + input->focus = 0; + input->capture = 0; + input->active = 0; + input->menu_owner = 0; + input->move_size = 0; + input->cursor = 0; + input->cursor_count = 0; list_init( &input->msg_list ); set_caret_window( input, 0 ); memset( input->keystate, 0, sizeof(input->keystate) ); @@ -263,6 +268,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ queue->changed_mask = 0; queue->paint_count = 0; queue->quit_message = 0; + queue->cursor_count = 0; queue->recv_result = NULL; queue->next_timer_id = 0x7fff; queue->timeout = NULL; @@ -293,14 +299,20 @@ void free_msg_queue( struct thread *thread ) /* change the thread input data of a given thread */ static int assign_thread_input( struct thread *thread, struct thread_input *new_input ) { - if (!thread->queue) + struct msg_queue *queue = thread->queue; + + if (!queue) { thread->queue = create_msg_queue( thread, new_input ); return thread->queue != NULL; } - - if (thread->queue->input) release_object( thread->queue->input ); - thread->queue->input = (struct thread_input *)grab_object( new_input ); + if (queue->input) + { + queue->input->cursor_count -= queue->cursor_count; + release_object( queue->input ); + } + queue->input = (struct thread_input *)grab_object( new_input ); + new_input->cursor_count += queue->cursor_count; return 1; } @@ -852,7 +864,11 @@ static void msg_queue_destroy( struct object *obj ) free( timer ); } if (queue->timeout) remove_timeout_user( queue->timeout ); - if (queue->input) release_object( queue->input ); + if (queue->input) + { + queue->input->cursor_count -= queue->cursor_count; + release_object( queue->input ); + } if (queue->hooks) release_object( queue->hooks ); if (queue->fd) release_object( queue->fd ); } @@ -2230,3 +2246,32 @@ DECL_HANDLER(get_last_input_time) { reply->time = last_input_time; } + +/* set/get the current cursor */ +DECL_HANDLER(set_cursor) +{ + struct msg_queue *queue = get_current_queue(); + struct thread_input *input; + + if (!queue) return; + input = queue->input; + + reply->prev_handle = input->cursor; + reply->prev_count = input->cursor_count; + + if (req->flags & SET_CURSOR_HANDLE) + { + if (req->handle && !get_user_object( req->handle, USER_CLIENT )) + { + set_win32_error( ERROR_INVALID_CURSOR_HANDLE ); + return; + } + input->cursor = req->handle; + } + + if (req->flags & SET_CURSOR_COUNT) + { + queue->cursor_count += req->show_count; + input->cursor_count += req->show_count; + } +} diff --git a/server/request.h b/server/request.h index 11382d8f7f0..7667264b96d 100644 --- a/server/request.h +++ b/server/request.h @@ -352,6 +352,7 @@ DECL_HANDLER(get_window_layered_info); DECL_HANDLER(set_window_layered_info); DECL_HANDLER(alloc_user_handle); DECL_HANDLER(free_user_handle); +DECL_HANDLER(set_cursor); #ifdef WANT_REQUEST_HANDLERS @@ -599,6 +600,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_set_window_layered_info, (req_handler)req_alloc_user_handle, (req_handler)req_free_user_handle, + (req_handler)req_set_cursor, }; C_ASSERT( sizeof(affinity_t) == 8 ); @@ -1908,6 +1910,12 @@ C_ASSERT( FIELD_OFFSET(struct alloc_user_handle_reply, handle) == 8 ); C_ASSERT( sizeof(struct alloc_user_handle_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct free_user_handle_request, handle) == 12 ); C_ASSERT( sizeof(struct free_user_handle_request) == 16 ); +C_ASSERT( FIELD_OFFSET(struct set_cursor_request, flags) == 12 ); +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_reply, prev_handle) == 8 ); +C_ASSERT( FIELD_OFFSET(struct set_cursor_reply, prev_count) == 12 ); +C_ASSERT( sizeof(struct set_cursor_reply) == 16 ); #endif /* WANT_REQUEST_HANDLERS */ diff --git a/server/trace.c b/server/trace.c index 4b13ed57a84..914d8f1ca83 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3807,6 +3807,19 @@ static void dump_free_user_handle_request( const struct free_user_handle_request fprintf( stderr, " handle=%08x", req->handle ); } +static void dump_set_cursor_request( const struct set_cursor_request *req ) +{ + fprintf( stderr, " flags=%08x", req->flags ); + fprintf( stderr, ", handle=%08x", req->handle ); + fprintf( stderr, ", show_count=%d", req->show_count ); +} + +static void dump_set_cursor_reply( const struct set_cursor_reply *req ) +{ + fprintf( stderr, " prev_handle=%08x", req->prev_handle ); + fprintf( stderr, ", prev_count=%d", req->prev_count ); +} + static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_new_process_request, (dump_func)dump_get_new_process_info_request, @@ -4049,6 +4062,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_set_window_layered_info_request, (dump_func)dump_alloc_user_handle_request, (dump_func)dump_free_user_handle_request, + (dump_func)dump_set_cursor_request, }; static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { @@ -4293,6 +4307,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { NULL, (dump_func)dump_alloc_user_handle_reply, NULL, + (dump_func)dump_set_cursor_reply, }; static const char * const req_names[REQ_NB_REQUESTS] = { @@ -4537,6 +4552,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "set_window_layered_info", "alloc_user_handle", "free_user_handle", + "set_cursor", }; static const struct @@ -4568,6 +4584,7 @@ static const struct { "ERROR_CLASS_DOES_NOT_EXIST", 0xc0010000 | ERROR_CLASS_DOES_NOT_EXIST }, { "ERROR_CLASS_HAS_WINDOWS", 0xc0010000 | ERROR_CLASS_HAS_WINDOWS }, { "ERROR_CLIPBOARD_NOT_OPEN", 0xc0010000 | ERROR_CLIPBOARD_NOT_OPEN }, + { "ERROR_INVALID_CURSOR_HANDLE", 0xc0010000 | ERROR_INVALID_CURSOR_HANDLE }, { "ERROR_INVALID_INDEX", 0xc0010000 | ERROR_INVALID_INDEX }, { "ERROR_INVALID_WINDOW_HANDLE", 0xc0010000 | ERROR_INVALID_WINDOW_HANDLE }, { "FILE_DELETED", STATUS_FILE_DELETED },