From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/tests/device8.c | 4 -- server/queue.c | 85 ++++++++++++++++++++++++++++++++++++- server/user.h | 2 + server/winstation.c | 2 + 4 files changed, 88 insertions(+), 5 deletions(-)
diff --git a/dlls/dinput/tests/device8.c b/dlls/dinput/tests/device8.c index caf85fc370f..41e560a7e62 100644 --- a/dlls/dinput/tests/device8.c +++ b/dlls/dinput/tests/device8.c @@ -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; diff --git a/server/queue.c b/server/queue.c index ef40d30aedf..0b9430c5f4d 100644 --- a/server/queue.c +++ b/server/queue.c @@ -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 ) { diff --git a/server/user.h b/server/user.h index b4cf618f87e..309a0966104 100644 --- a/server/user.h +++ b/server/user.h @@ -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 */ diff --git a/server/winstation.c b/server/winstation.c index 373a1f7ba92..4672cf65e56 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -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 );