server: Add support for sending and receiving WM_POINTER* messages.

This commit is contained in:
Rémi Bernon 2021-10-04 20:57:55 +02:00 committed by Alexandre Julliard
parent 48f8db6c30
commit 61d1c18957
4 changed files with 88 additions and 5 deletions

View file

@ -1997,7 +1997,6 @@ static void test_hid_touch_screen(void)
bus_send_hid_input( file, &desc, &touch_single, sizeof(touch_single) );
res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER );
todo_wine
ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res );
res = msg_wait_for_events( 1, &touchdown_event, 10 );
@ -2049,7 +2048,6 @@ static void test_hid_touch_screen(void)
bus_wait_hid_input( file, &desc, 5000 );
res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER );
todo_wine
ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res );
memset( rawbuffer, 0, sizeof(rawbuffer) );
@ -2088,11 +2086,9 @@ static void test_hid_touch_screen(void)
bus_send_hid_input( file, &desc, &touch_multiple, sizeof(touch_multiple) );
res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER );
todo_wine
ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res );
bus_send_hid_input( file, &desc, &touch_release, sizeof(touch_release) );
res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER );
todo_wine
ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res );
rawinput = (RAWINPUT *)rawbuffer;

View file

@ -633,6 +633,7 @@ static inline int filter_contains_hw_range( unsigned int first, unsigned int las
/* get the QS_* bit corresponding to a given hardware message */
static inline int get_hardware_msg_bit( unsigned int message )
{
if (message >= WM_POINTERUPDATE && message <= WM_POINTERLEAVE) return QS_POINTER;
if (message == WM_INPUT_DEVICE_CHANGE || message == WM_INPUT) return QS_RAWINPUT;
if (message == WM_MOUSEMOVE || message == WM_NCMOUSEMOVE) return QS_MOUSEMOVE;
if (message >= WM_KEYFIRST && message <= WM_KEYLAST) return QS_KEY;
@ -1614,6 +1615,7 @@ static user_handle_t find_hardware_message_window( struct desktop *desktop, stru
*msg_code = msg->msg;
switch (get_hardware_msg_bit( msg->msg ))
{
case QS_POINTER:
case QS_RAWINPUT:
if (!(win = msg->win) && input) win = input->focus;
break;
@ -2216,12 +2218,72 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
return wait;
}
struct pointer
{
struct list entry;
struct desktop *desktop;
user_handle_t win;
int primary;
hw_input_t input;
};
static void queue_pointer_message( struct pointer *pointer )
{
struct hw_msg_source source = { IMDT_UNAVAILABLE, IMDT_TOUCH };
struct desktop *desktop = pointer->desktop;
const hw_input_t *input = &pointer->input;
unsigned int wparam = input->hw.wparam;
user_handle_t win = pointer->win;
rectangle_t top_rect;
struct message *msg;
int x, y;
get_top_window_rectangle( desktop, &top_rect );
x = LOWORD(input->hw.lparam) * (top_rect.right - top_rect.left) / 65535;
y = HIWORD(input->hw.lparam) * (top_rect.bottom - top_rect.top) / 65535;
if (pointer->primary) wparam |= POINTER_MESSAGE_FLAG_PRIMARY << 16;
if (!(msg = alloc_hardware_message( 0, source, get_tick_count(), 0 ))) return;
msg->win = get_user_full_handle( win );
msg->msg = input->hw.msg;
msg->wparam = wparam;
msg->lparam = MAKELONG(x, y);
msg->x = desktop->cursor.x;
msg->y = desktop->cursor.y;
queue_hardware_message( desktop, msg, 1 );
if (input->hw.msg == WM_POINTERUP)
{
list_remove( &pointer->entry );
free( pointer );
}
}
static struct pointer *find_pointer_from_id( struct desktop *desktop, unsigned int id )
{
struct pointer *pointer;
LIST_FOR_EACH_ENTRY( pointer, &desktop->pointers, struct pointer, entry )
if (LOWORD(pointer->input.hw.wparam) == id) return pointer;
pointer = mem_alloc( sizeof(struct pointer) );
pointer->desktop = desktop;
pointer->primary = list_empty( &desktop->pointers );
list_add_tail( &desktop->pointers, &pointer->entry );
return pointer;
}
/* queue a hardware message for a custom type of event */
static void queue_custom_hardware_message( struct desktop *desktop, user_handle_t win,
unsigned int origin, const hw_input_t *input )
{
struct hw_msg_source source = { IMDT_UNAVAILABLE, origin };
struct thread *foreground;
struct pointer *pointer;
struct message *msg;
switch (input->hw.msg)
@ -2246,6 +2308,16 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_
return;
}
if (input->hw.msg == WM_POINTERDOWN || input->hw.msg == WM_POINTERUP || input->hw.msg == WM_POINTERUPDATE)
{
pointer = find_pointer_from_id( desktop, LOWORD(input->hw.wparam) );
pointer->input = *input;
pointer->win = win;
queue_pointer_message( pointer );
return;
}
if (!(msg = alloc_hardware_message( 0, source, get_tick_count(), 0 ))) return;
msg->win = get_user_full_handle( win );
@ -2394,7 +2466,7 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user
data->hw_id = msg->unique_id;
set_reply_data( msg->data, msg->data_size );
if ((get_hardware_msg_bit( msg->msg ) == QS_RAWINPUT && (flags & PM_REMOVE)) ||
if ((get_hardware_msg_bit( msg->msg ) & (QS_RAWINPUT | QS_POINTER) && (flags & PM_REMOVE)) ||
is_internal_hardware_message( msg->msg ))
release_hardware_message( current->queue, data->hw_id );
return 1;
@ -2572,6 +2644,17 @@ void post_win_event( struct thread *thread, unsigned int event,
}
}
void free_pointers( struct desktop *desktop )
{
struct pointer *pointer, *next;
LIST_FOR_EACH_ENTRY_SAFE( pointer, next, &desktop->pointers, struct pointer, entry )
{
list_remove( &pointer->entry );
free( pointer );
}
}
/* free all hotkeys on a desktop, optionally filtering by window */
void free_hotkeys( struct desktop *desktop, user_handle_t window )
{

View file

@ -75,6 +75,7 @@ struct desktop
struct window *msg_window; /* HWND_MESSAGE top window */
struct hook_table *global_hooks; /* table of global hooks on this desktop */
struct list hotkeys; /* list of registered hotkeys */
struct list pointers; /* list of active pointers */
struct timeout_user *close_timeout; /* timeout before closing the desktop */
struct thread_input *foreground_input; /* thread input of foreground thread */
unsigned int users; /* processes and threads using this desktop */
@ -125,6 +126,7 @@ extern void post_win_event( struct thread *thread, unsigned int event,
const WCHAR *module, data_size_t module_size,
user_handle_t handle );
extern void free_hotkeys( struct desktop *desktop, user_handle_t window );
extern void free_pointers( struct desktop *desktop );
extern void set_rawinput_process( struct process *process, int enable );
/* region functions */

View file

@ -296,6 +296,7 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned
memset( desktop->keystate, 0, sizeof(desktop->keystate) );
list_add_tail( &winstation->desktops, &desktop->entry );
list_init( &desktop->hotkeys );
list_init( &desktop->pointers );
}
else
{
@ -357,6 +358,7 @@ static void desktop_destroy( struct object *obj )
}
free_hotkeys( desktop, 0 );
free_pointers( desktop );
if (desktop->top_window) free_window_handle( desktop->top_window );
if (desktop->msg_window) free_window_handle( desktop->msg_window );
if (desktop->global_hooks) release_object( desktop->global_hooks );