They don't produce any window messages and should be processed as soon as possible, without returning to the client side.
-- v2: server: Don't set QS_RAWINPUT for internal hardware messages. win32u: Process internal hardware messages while waiting. win32u: Keep waiting on the queue until it gets signaled. win32u: Use an absolute wait timeout in wait_message. win32u: Check QS_DRIVER bit before calling ProcessEvents.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/message.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index d61263f26e6..9e8f9d54af8 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -3179,7 +3179,7 @@ static HANDLE get_server_queue_handle(void) return ret; }
-static BOOL has_hardware_messages(void) +static BOOL check_internal_bits( UINT mask ) { struct object_lock lock = OBJECT_LOCK_INIT; const queue_shm_t *queue_shm; @@ -3187,7 +3187,7 @@ static BOOL has_hardware_messages(void) UINT status;
while ((status = get_shared_queue( &lock, &queue_shm )) == STATUS_PENDING) - signaled = queue_shm->internal_bits & QS_HARDWARE; + signaled = queue_shm->internal_bits & mask; if (status) return FALSE;
return signaled; @@ -3195,7 +3195,7 @@ static BOOL has_hardware_messages(void)
BOOL process_driver_events( UINT mask ) { - if (user_driver->pProcessEvents( mask )) + if (check_internal_bits( QS_DRIVER ) && user_driver->pProcessEvents( mask )) { SERVER_START_REQ( set_queue_mask ) { @@ -3205,7 +3205,7 @@ BOOL process_driver_events( UINT mask ) SERVER_END_REQ; }
- return has_hardware_messages(); + return check_internal_bits( QS_HARDWARE ); }
void check_for_events( UINT flags )
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/message.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 9e8f9d54af8..6f16a1ddb41 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -3248,11 +3248,17 @@ static inline LARGE_INTEGER *get_nt_timeout( LARGE_INTEGER *time, DWORD timeout static DWORD wait_message( DWORD count, const HANDLE *handles, DWORD timeout, DWORD mask, DWORD flags ) { struct thunk_lock_params params = {.dispatch.callback = thunk_lock_callback}; - LARGE_INTEGER time; - DWORD ret; + LARGE_INTEGER time, now, *abs; + DWORD ret = count - 1; void *ret_ptr; ULONG ret_len;
+ if ((abs = get_nt_timeout( &time, timeout ))) + { + NtQuerySystemTime( &now ); + abs->QuadPart = now.QuadPart - abs->QuadPart; + } + if (!KeUserDispatchCallback( ¶ms.dispatch, sizeof(params), &ret_ptr, &ret_len ) && ret_len == sizeof(params.locks)) { @@ -3263,8 +3269,7 @@ static DWORD wait_message( DWORD count, const HANDLE *handles, DWORD timeout, DW if (process_driver_events( QS_ALLINPUT )) ret = count - 1; else { - ret = NtWaitForMultipleObjects( count, handles, !(flags & MWMO_WAITALL), - !!(flags & MWMO_ALERTABLE), get_nt_timeout( &time, timeout )); + ret = NtWaitForMultipleObjects( count, handles, !(flags & MWMO_WAITALL), !!(flags & MWMO_ALERTABLE), abs ); if (ret == count - 1) process_driver_events( QS_ALLINPUT ); else if (HIWORD(ret)) /* is it an error code? */ {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/message.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 6f16a1ddb41..d80b4f8104c 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -3179,6 +3179,21 @@ static HANDLE get_server_queue_handle(void) return ret; }
+static BOOL is_queue_signaled(void) +{ + struct object_lock lock = OBJECT_LOCK_INIT; + const queue_shm_t *queue_shm; + BOOL signaled = FALSE; + UINT status; + + while ((status = get_shared_queue( &lock, &queue_shm )) == STATUS_PENDING) + signaled = (queue_shm->wake_bits & queue_shm->wake_mask) || + (queue_shm->changed_bits & queue_shm->changed_mask); + if (status) return FALSE; + + return signaled; +} + static BOOL check_internal_bits( UINT mask ) { struct object_lock lock = OBJECT_LOCK_INIT; @@ -3249,9 +3264,9 @@ static DWORD wait_message( DWORD count, const HANDLE *handles, DWORD timeout, DW { struct thunk_lock_params params = {.dispatch.callback = thunk_lock_callback}; LARGE_INTEGER time, now, *abs; - DWORD ret = count - 1; void *ret_ptr; ULONG ret_len; + DWORD ret;
if ((abs = get_nt_timeout( &time, timeout ))) { @@ -3269,13 +3284,13 @@ static DWORD wait_message( DWORD count, const HANDLE *handles, DWORD timeout, DW if (process_driver_events( QS_ALLINPUT )) ret = count - 1; else { - ret = NtWaitForMultipleObjects( count, handles, !(flags & MWMO_WAITALL), !!(flags & MWMO_ALERTABLE), abs ); - if (ret == count - 1) process_driver_events( QS_ALLINPUT ); - else if (HIWORD(ret)) /* is it an error code? */ - { - RtlSetLastWin32Error( RtlNtStatusToDosError(ret) ); - ret = WAIT_FAILED; - } + do ret = NtWaitForMultipleObjects( count, handles, !(flags & MWMO_WAITALL), !!(flags & MWMO_ALERTABLE), abs ); + while (ret == count - 1 && !process_driver_events( QS_ALLINPUT ) && !is_queue_signaled()); + } + if (HIWORD(ret)) /* is it an error code? */ + { + RtlSetLastWin32Error( RtlNtStatusToDosError(ret) ); + ret = WAIT_FAILED; }
if (ret == WAIT_TIMEOUT && !count && !timeout) NtYieldExecution();
From: Rémi Bernon rbernon@codeweavers.com
They don't produce any window messages and should be processed as soon as possible. --- dlls/win32u/message.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index d80b4f8104c..4b179619cf9 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2809,7 +2809,7 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar * returns FALSE if we need to make a server request to update the queue masks or bits */ static BOOL check_queue_bits( UINT wake_mask, UINT changed_mask, UINT signal_bits, UINT clear_bits, - UINT *wake_bits, UINT *changed_bits ) + UINT *wake_bits, UINT *changed_bits, BOOL internal ) { struct object_lock lock = OBJECT_LOCK_INIT; const queue_shm_t *queue_shm; @@ -2818,8 +2818,9 @@ static BOOL check_queue_bits( UINT wake_mask, UINT changed_mask, UINT signal_bit
while ((status = get_shared_queue( &lock, &queue_shm )) == STATUS_PENDING) { + if (internal) skip = !(queue_shm->internal_bits & QS_HARDWARE); /* if the masks need an update */ - if (queue_shm->wake_mask != wake_mask) skip = FALSE; + else if (queue_shm->wake_mask != wake_mask) skip = FALSE; else if (queue_shm->changed_mask != changed_mask) skip = FALSE; /* or if some bits need to be cleared, or queue is signaled */ else if (queue_shm->wake_bits & signal_bits) skip = FALSE; @@ -2884,7 +2885,7 @@ static int peek_message( MSG *msg, const struct peek_message_filter *filter ) wake_mask = filter->mask & (QS_SENDMESSAGE | QS_SMRESULT);
if (check_queue_bits( wake_mask, filter->mask, wake_mask | signal_bits, filter->mask | clear_bits, - &wake_bits, &changed_bits )) + &wake_bits, &changed_bits, filter->internal )) res = STATUS_PENDING; else SERVER_START_REQ( get_message ) { @@ -3220,16 +3221,21 @@ BOOL process_driver_events( UINT mask ) SERVER_END_REQ; }
+ /* process every pending internal hardware messages */ + if (check_internal_bits( QS_HARDWARE )) + { + struct peek_message_filter filter = {.internal = TRUE}; + MSG msg; + peek_message( &msg, &filter ); + } + + /* check for hardware messages requiring client dispatch */ return check_internal_bits( QS_HARDWARE ); }
void check_for_events( UINT flags ) { - struct peek_message_filter filter = {.internal = TRUE, .flags = PM_REMOVE}; - MSG msg; - if (!process_driver_events( flags )) flush_window_surfaces( TRUE ); - peek_message( &msg, &filter ); }
/* monotonic timer tick for throttling driver event checks */ @@ -3653,7 +3659,7 @@ static void wait_message_reply( UINT flags ) UINT wake_bits, changed_bits;
if (check_queue_bits( wake_mask, wake_mask, wake_mask, wake_mask, - &wake_bits, &changed_bits )) + &wake_bits, &changed_bits, FALSE )) wake_bits = wake_bits & wake_mask; else SERVER_START_REQ( set_queue_mask ) {
From: Rémi Bernon rbernon@codeweavers.com
--- server/queue.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-)
diff --git a/server/queue.c b/server/queue.c index 6b48a5dfdc8..9d9e76680f8 100644 --- a/server/queue.c +++ b/server/queue.c @@ -802,8 +802,7 @@ static inline int get_hardware_msg_bit( unsigned int message ) 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; - if (message == WM_WINE_CLIPCURSOR) return QS_RAWINPUT; - if (message == WM_WINE_SETCURSOR) return QS_RAWINPUT; + if (message >= WM_WINE_FIRST_DRIVER_MSG && message <= WM_WINE_LAST_DRIVER_MSG) return QS_HARDWARE; return QS_MOUSEBUTTON; }
@@ -2692,12 +2691,6 @@ static int check_hw_message_filter( user_handle_t win, unsigned int msg_code, } }
-/* is this message an internal driver notification message */ -static inline BOOL is_internal_hardware_message( unsigned int message ) -{ - return (message >= WM_WINE_FIRST_DRIVER_MSG && message <= WM_WINE_LAST_DRIVER_MSG); -} - /* find a hardware message for the given queue */ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user_handle_t filter_win, unsigned int first, unsigned int last, unsigned int flags, @@ -2802,9 +2795,10 @@ 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 | QS_POINTER) && (flags & PM_REMOVE)) || - is_internal_hardware_message( msg->msg )) - release_hardware_message( current->queue, data->hw_id ); + + if (msg_bit == QS_HARDWARE) flags |= PM_REMOVE; /* always remove internal hardware messages right away */ + else if (!(msg_bit & (QS_RAWINPUT | QS_POINTER))) flags &= ~PM_REMOVE; /* wait for accept_hardware_message request */ + if (flags & PM_REMOVE) release_hardware_message( current->queue, data->hw_id ); return 1; } /* nothing found, clear the hardware queue bits */
v2: Always wait before checking if queue is signaled, fixing the ole32 failing tests.