-- v4: server: Process internal messages when checking queue status. server: Check for internal hardware messages before others. win32u: Use a structure to pass peek_message arguments. server: Send WM_WINE_SETCURSOR message only when necessary. server: Send WM_WINE_CLIPCURSOR message only when necessary. winex11: Accept key and mouse events with QS_RAWINPUT.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 8b02361aaff..379b27b3f70 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -229,14 +229,14 @@ static Bool filter_event( Display *display, XEvent *event, char *arg ) case KeyRelease: case KeymapNotify: case MappingNotify: - return (mask & (QS_KEY|QS_HOTKEY)) != 0; + return (mask & (QS_KEY | QS_HOTKEY | QS_RAWINPUT)) != 0; case ButtonPress: case ButtonRelease: - return (mask & QS_MOUSEBUTTON) != 0; + return (mask & (QS_MOUSEBUTTON | QS_RAWINPUT)) != 0; case MotionNotify: case EnterNotify: case LeaveNotify: - return (mask & QS_MOUSEMOVE) != 0; + return (mask & (QS_MOUSEMOVE | QS_RAWINPUT)) != 0; case Expose: return (mask & QS_PAINT) != 0; case FocusIn:
From: Rémi Bernon rbernon@codeweavers.com
--- server/queue.c | 9 +++++++-- server/user.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/server/queue.c b/server/queue.c index 0e8653bedf0..5eb6c1edafb 100644 --- a/server/queue.c +++ b/server/queue.c @@ -527,6 +527,7 @@ static void get_message_defaults( struct msg_queue *queue, int *x, int *y, unsig void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect, unsigned int flags, int reset ) { rectangle_t top_rect; + unsigned int old_flags; int x, y;
get_top_window_rectangle( desktop, &top_rect ); @@ -542,6 +543,9 @@ void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect, unsig } else desktop->cursor.clip = top_rect;
+ old_flags = desktop->cursor.clip_flags; + desktop->cursor.clip_flags = flags; + /* 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 ); @@ -550,8 +554,9 @@ void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect, unsig /* request clip cursor rectangle reset to the desktop thread */ if (reset) post_desktop_message( desktop, WM_WINE_CLIPCURSOR, flags, FALSE );
- /* notify foreground thread, of reset, or to apply new cursor clipping rect */ - queue_cursor_message( desktop, 0, WM_WINE_CLIPCURSOR, flags, reset ); + /* notify foreground thread of reset, clipped, or released cursor rect */ + if (reset || flags != SET_CURSOR_NOCLIP || old_flags != SET_CURSOR_NOCLIP) + queue_cursor_message( desktop, 0, WM_WINE_CLIPCURSOR, flags, reset ); }
/* change the foreground input and reset the cursor clip rect */ diff --git a/server/user.h b/server/user.h index 309a0966104..d805a179d16 100644 --- a/server/user.h +++ b/server/user.h @@ -59,6 +59,7 @@ struct global_cursor int x; /* cursor position */ int y; rectangle_t clip; /* cursor clip rectangle */ + unsigned int clip_flags; /* last cursor clip flags */ unsigned int last_change; /* time of last position change */ user_handle_t win; /* window that contains the cursor */ };
From: Rémi Bernon rbernon@codeweavers.com
--- server/queue.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/server/queue.c b/server/queue.c index 5eb6c1edafb..5ae54e743a4 100644 --- a/server/queue.c +++ b/server/queue.c @@ -481,11 +481,11 @@ static int update_desktop_cursor_pos( struct desktop *desktop, user_handle_t win return updated; }
-static void update_desktop_cursor_handle( struct desktop *desktop, struct thread_input *input ) +static void update_desktop_cursor_handle( struct desktop *desktop, struct thread_input *input, user_handle_t handle ) { if (input == get_desktop_cursor_thread_input( desktop )) { - user_handle_t handle = input->cursor_count < 0 ? 0 : input->cursor, win = desktop->cursor.win; + user_handle_t win = desktop->cursor.win; /* when clipping send the message to the foreground window as well, as some driver have an artificial overlay window */ if (is_cursor_clipped( desktop )) queue_cursor_message( desktop, 0, WM_WINE_SETCURSOR, win, handle ); queue_cursor_message( desktop, win, WM_WINE_SETCURSOR, win, handle ); @@ -3636,12 +3636,14 @@ DECL_HANDLER(get_last_input_time) DECL_HANDLER(set_cursor) { struct msg_queue *queue = get_current_queue(); + user_handle_t prev_cursor, new_cursor; struct thread_input *input; struct desktop *desktop;
if (!queue) return; input = queue->input; desktop = input->desktop; + prev_cursor = input->cursor_count < 0 ? 0 : input->cursor;
reply->prev_handle = input->cursor; reply->prev_count = input->cursor_count; @@ -3666,8 +3668,8 @@ DECL_HANDLER(set_cursor) if (req->flags & SET_CURSOR_CLIP) set_clip_rectangle( desktop, &req->clip, req->flags, 0 ); if (req->flags & SET_CURSOR_NOCLIP) set_clip_rectangle( desktop, NULL, SET_CURSOR_NOCLIP, 0 );
- if (req->flags & (SET_CURSOR_HANDLE | SET_CURSOR_COUNT)) - update_desktop_cursor_handle( desktop, input ); + new_cursor = input->cursor_count < 0 ? 0 : input->cursor; + if (prev_cursor != new_cursor) update_desktop_cursor_handle( desktop, input, new_cursor );
reply->new_x = desktop->cursor.x; reply->new_y = desktop->cursor.y;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/message.c | 49 ++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 12 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index f7f751ef883..6c2335dedee 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2691,6 +2691,15 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar return ret; }
+struct peek_message_filter +{ + HWND hwnd; + UINT first; + UINT last; + UINT mask; + UINT flags; +}; + /*********************************************************************** * peek_message * @@ -2698,9 +2707,11 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar * available; -1 on error. * All pending sent messages are processed before returning. */ -static int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags, UINT changed_mask ) +static int peek_message( MSG *msg, const struct peek_message_filter *filter ) { LRESULT result; + HWND hwnd = filter->hwnd; + UINT first = filter->first, last = filter->last, flags = filter->flags; struct user_thread_info *thread_info = get_user_thread_info(); INPUT_MESSAGE_SOURCE prev_source = thread_info->client_info.msg_source; struct received_message_info info; @@ -2728,8 +2739,8 @@ static int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags, req->get_first = first; req->get_last = last; req->hw_id = hw_id; - req->wake_mask = changed_mask & (QS_SENDMESSAGE | QS_SMRESULT); - req->changed_mask = changed_mask; + req->wake_mask = filter->mask & (QS_SENDMESSAGE | QS_SMRESULT); + req->changed_mask = filter->mask; wine_server_set_reply( req, buffer, buffer_size ); if (!(res = wine_server_call( req ))) { @@ -2754,8 +2765,8 @@ static int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags, free( buffer ); if (res == STATUS_PENDING) { - thread_info->wake_mask = changed_mask & (QS_SENDMESSAGE | QS_SMRESULT); - thread_info->changed_mask = changed_mask; + thread_info->wake_mask = filter->mask & (QS_SENDMESSAGE | QS_SMRESULT); + thread_info->changed_mask = filter->mask; return 0; } if (res != STATUS_BUFFER_OVERFLOW) @@ -2900,8 +2911,17 @@ static int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags, } } else - peek_message( msg, info.msg.hwnd, info.msg.message, - info.msg.message, flags | PM_REMOVE, changed_mask ); + { + struct peek_message_filter new_filter = + { + .hwnd = info.msg.hwnd, + .flags = flags | PM_REMOVE, + .first = info.msg.message, + .last = info.msg.message, + .mask = filter->mask, + }; + peek_message( msg, &new_filter ); + } continue; } if (info.msg.message >= WM_DDE_FIRST && info.msg.message <= WM_DDE_LAST) @@ -2952,7 +2972,7 @@ static int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags, info.msg.wParam, info.msg.lParam );
/* if some PM_QS* flags were specified, only handle sent messages from now on */ - if (HIWORD(flags) && !changed_mask) flags = PM_QS_SENDMESSAGE | LOWORD(flags); + if (HIWORD(flags) && !filter->mask) flags = PM_QS_SENDMESSAGE | LOWORD(flags); } }
@@ -2963,8 +2983,9 @@ static int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags, */ static void process_sent_messages(void) { + struct peek_message_filter filter = {.flags = PM_REMOVE | PM_QS_SENDMESSAGE}; MSG msg; - peek_message( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE, 0 ); + peek_message( &msg, &filter ); }
/*********************************************************************** @@ -3187,13 +3208,14 @@ BOOL WINAPI NtUserWaitMessage(void) */ BOOL WINAPI NtUserPeekMessage( MSG *msg_out, HWND hwnd, UINT first, UINT last, UINT flags ) { + struct peek_message_filter filter = {.hwnd = hwnd, .first = first, .last = last, .flags = flags}; MSG msg; int ret;
user_check_not_lock(); check_for_driver_events( 0 );
- ret = peek_message( &msg, hwnd, first, last, flags, 0 ); + ret = peek_message( &msg, &filter ); if (ret < 0) return FALSE;
if (!ret) @@ -3201,7 +3223,7 @@ BOOL WINAPI NtUserPeekMessage( MSG *msg_out, HWND hwnd, UINT first, UINT last, U flush_window_surfaces( TRUE ); ret = wait_message( 0, NULL, 0, QS_ALLINPUT, 0 ); /* if we received driver events, check again for a pending message */ - if (ret == WAIT_TIMEOUT || peek_message( &msg, hwnd, first, last, flags, 0 ) <= 0) return FALSE; + if (ret == WAIT_TIMEOUT || peek_message( &msg, &filter ) <= 0) return FALSE; }
check_for_driver_events( msg.message ); @@ -3224,6 +3246,7 @@ BOOL WINAPI NtUserPeekMessage( MSG *msg_out, HWND hwnd, UINT first, UINT last, U */ BOOL WINAPI NtUserGetMessage( MSG *msg, HWND hwnd, UINT first, UINT last ) { + struct peek_message_filter filter = {.hwnd = hwnd, .first = first, .last = last}; HANDLE server_queue = get_server_queue_handle(); unsigned int mask = QS_POSTMESSAGE | QS_SENDMESSAGE; /* Always selected */ int ret; @@ -3242,7 +3265,9 @@ BOOL WINAPI NtUserGetMessage( MSG *msg, HWND hwnd, UINT first, UINT last ) } else mask = QS_ALLINPUT;
- while (!(ret = peek_message( msg, hwnd, first, last, PM_REMOVE | (mask << 16), mask ))) + filter.mask = mask; + filter.flags = PM_REMOVE | (mask << 16); + while (!(ret = peek_message( msg, &filter ))) { wait_objects( 1, &server_queue, INFINITE, mask & (QS_SENDMESSAGE | QS_SMRESULT), mask, 0 ); }
From: Rémi Bernon rbernon@codeweavers.com
--- server/queue.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/server/queue.c b/server/queue.c index 5ae54e743a4..c884e9f7f55 100644 --- a/server/queue.c +++ b/server/queue.c @@ -2988,6 +2988,12 @@ DECL_HANDLER(get_message) }
if (!queue) return; + + /* check for any hardware internal message */ + if (get_hardware_message( current, req->hw_id, get_win, WM_WINE_FIRST_DRIVER_MSG, + WM_WINE_LAST_DRIVER_MSG, req->flags, reply )) + return; + queue->last_get_msg = current_time; if (!filter) filter = QS_ALLINPUT;
@@ -3028,11 +3034,6 @@ DECL_HANDLER(get_message) get_hardware_message( current, req->hw_id, get_win, req->get_first, req->get_last, req->flags, reply )) return;
- /* check for any internal driver message */ - if (get_hardware_message( current, req->hw_id, get_win, WM_WINE_FIRST_DRIVER_MSG, - WM_WINE_LAST_DRIVER_MSG, req->flags, reply )) - return; - /* now check for WM_PAINT */ if ((filter & QS_PAINT) && queue->paint_count &&
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/tests/device8.c | 11 +++++++++++ dlls/win32u/input.c | 9 +++++++++ dlls/win32u/message.c | 13 +++---------- dlls/win32u/ntuser_private.h | 11 +++++++++++ server/protocol.def | 1 + server/queue.c | 6 ++++++ 6 files changed, 41 insertions(+), 10 deletions(-)
diff --git a/dlls/dinput/tests/device8.c b/dlls/dinput/tests/device8.c index 7fb0ef538e0..6bfc88f01cc 100644 --- a/dlls/dinput/tests/device8.c +++ b/dlls/dinput/tests/device8.c @@ -2038,6 +2038,9 @@ static void test_hid_touch_screen(void) ret = RegisterRawInputDevices( &rawdevice, 1, sizeof(RAWINPUTDEVICE) ); ok( ret, "RegisterRawInputDevices failed, error %lu\n", GetLastError() );
+ res = GetQueueStatus( QS_RAWINPUT ); + ok( res == 0, "got res %#lx\n", res ); + bus_send_hid_input( file, &desc, &touch_multiple, sizeof(touch_multiple) ); bus_wait_hid_input( file, &desc, 5000 ); bus_send_hid_input( file, &desc, &touch_release, sizeof(touch_release) ); @@ -2046,6 +2049,10 @@ static void test_hid_touch_screen(void) res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER ); ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res );
+ res = GetQueueStatus( QS_RAWINPUT ); + ok( LOWORD(res) == QS_RAWINPUT, "got res %#lx\n", res ); + ok( HIWORD(res) == QS_RAWINPUT, "got res %#lx\n", res ); + memset( rawbuffer, 0, sizeof(rawbuffer) ); rawinput = (RAWINPUT *)rawbuffer; rawbuffer_size = sizeof(rawbuffer); @@ -2064,6 +2071,10 @@ static void test_hid_touch_screen(void) ok( !memcmp( rawinput->data.hid.bRawData, touch_multiple.report_buf, desc.caps.InputReportByteLength ), "got unexpected report data\n" );
+ res = GetQueueStatus( QS_RAWINPUT ); + ok( LOWORD(res) == 0, "got res %#lx\n", res ); + ok( HIWORD(res) == 0, "got res %#lx\n", res ); + rawdevice.dwFlags = RIDEV_REMOVE; rawdevice.hwndTarget = 0; ret = RegisterRawInputDevices( &rawdevice, 1, sizeof(RAWINPUTDEVICE) ); diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 4a7c04f66c5..1886ff979d7 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -791,8 +791,17 @@ BOOL WINAPI NtUserGetCursorInfo( CURSORINFO *info )
static void check_for_events( UINT flags ) { + struct peek_message_filter filter = + { + .internal = TRUE, + .flags = PM_REMOVE, + }; + MSG msg; + if (!user_driver->pProcessEvents( flags )) flush_window_surfaces( TRUE ); + + peek_message( &msg, &filter ); }
/********************************************************************** diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 6c2335dedee..84625f82964 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2691,15 +2691,6 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar return ret; }
-struct peek_message_filter -{ - HWND hwnd; - UINT first; - UINT last; - UINT mask; - UINT flags; -}; - /*********************************************************************** * peek_message * @@ -2707,7 +2698,7 @@ struct peek_message_filter * available; -1 on error. * All pending sent messages are processed before returning. */ -static int peek_message( MSG *msg, const struct peek_message_filter *filter ) +int peek_message( MSG *msg, const struct peek_message_filter *filter ) { LRESULT result; HWND hwnd = filter->hwnd; @@ -2734,6 +2725,7 @@ static int peek_message( MSG *msg, const struct peek_message_filter *filter )
SERVER_START_REQ( get_message ) { + req->internal = filter->internal; req->flags = flags; req->get_win = wine_server_user_handle( hwnd ); req->get_first = first; @@ -2919,6 +2911,7 @@ static int peek_message( MSG *msg, const struct peek_message_filter *filter ) .first = info.msg.message, .last = info.msg.message, .mask = filter->mask, + .internal = filter->internal, }; peek_message( msg, &new_filter ); } diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 3b6cab5bdc9..bb2169998b6 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -238,6 +238,17 @@ extern void free_dce( struct dce *dce, HWND hwnd ); extern void invalidate_dce( WND *win, const RECT *extra_rect );
/* message.c */ +struct peek_message_filter +{ + HWND hwnd; + UINT first; + UINT last; + UINT mask; + UINT flags; + BOOL internal; +}; + +extern int peek_message( MSG *msg, const struct peek_message_filter *filter ); extern BOOL set_keyboard_auto_repeat( BOOL enable );
/* systray.c */ diff --git a/server/protocol.def b/server/protocol.def index 13aea96e796..d76390ce308 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2149,6 +2149,7 @@ enum message_type unsigned int hw_id; /* id of the previous hardware message (or 0) */ unsigned int wake_mask; /* wakeup bits mask */ unsigned int changed_mask; /* changed bits mask */ + unsigned int internal; /* get internal messages only */ @REPLY user_handle_t win; /* window handle */ unsigned int msg; /* message code */ diff --git a/server/queue.c b/server/queue.c index c884e9f7f55..ed099b3b989 100644 --- a/server/queue.c +++ b/server/queue.c @@ -2994,6 +2994,12 @@ DECL_HANDLER(get_message) WM_WINE_LAST_DRIVER_MSG, req->flags, reply )) return;
+ if (req->internal) /* check for internal messages only, leave queue flags unchanged */ + { + set_error( STATUS_PENDING ); + return; + } + queue->last_get_msg = current_time; if (!filter) filter = QS_ALLINPUT;
Added back the dinput tests.
@rbernon Doesn't apply to this MR. There is a regression in Wine, due to the input system in games there are stators, as I remember you made changes to user32, and the problem is probably caused by these changes. https://bugs.winehq.org/show_bug.cgi?id=56460
I wasn't checking the whole thing about the patches, but WRT the issue it is supposed to solve it works and I am approving it on this basis.
This merge request was approved by Paul Gofman.