Module: wine Branch: master Commit: 54ca1ab607d3ff22a1f57a9561430f64c75f0916 URL: https://gitlab.winehq.org/wine/wine/-/commit/54ca1ab607d3ff22a1f57a9561430f6...
Author: Rémi Bernon rbernon@codeweavers.com Date: Wed Jun 26 14:25:56 2024 +0200
win32u: Simplify the logic for driver messages polling.
As we don't need to make a server request to check for the queue status anymore, we can stop relying on ProcessEvent return status, and only call it often enough, before and after checking for messages.
We keep a throttle here though, as now that PeekMessage returns very quickly when no message is found, calling it in a tight loop triggers a large number of calls into the drivers instead.
---
dlls/win32u/message.c | 41 +++++++++++++++++------------------------ dlls/win32u/ntuser_private.h | 2 +- 2 files changed, 18 insertions(+), 25 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 5f8cb95d731..ba348cd3782 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -3038,19 +3038,14 @@ static HANDLE get_server_queue_handle(void) }
/* check for driver events if we detect that the app is not properly consuming messages */ -static inline void check_for_driver_events( UINT msg ) +static inline void check_for_driver_events(void) { - if (get_user_thread_info()->message_count > 200) + if (get_user_thread_info()->last_driver_time != NtGetTickCount()) { flush_window_surfaces( FALSE ); user_driver->pProcessEvents( QS_ALLINPUT ); + get_user_thread_info()->last_driver_time = NtGetTickCount(); } - else if (msg == WM_TIMER || msg == WM_SYSTIMER) - { - /* driver events should have priority over timers, so make sure we'll check for them soon */ - get_user_thread_info()->message_count += 100; - } - else get_user_thread_info()->message_count++; }
/* helper for kernel32->ntdll timeout format conversion */ @@ -3075,8 +3070,8 @@ static DWORD wait_message( DWORD count, const HANDLE *handles, DWORD timeout, DW lock = *(DWORD *)ret_ptr; }
- if (user_driver->pProcessEvents( mask )) ret = count ? count - 1 : 0; - else if (count) + if (user_driver->pProcessEvents( mask )) ret = count - 1; + else { ret = NtWaitForMultipleObjects( count, handles, !(flags & MWMO_WAITALL), !!(flags & MWMO_ALERTABLE), get_nt_timeout( &time, timeout )); @@ -3087,10 +3082,9 @@ static DWORD wait_message( DWORD count, const HANDLE *handles, DWORD timeout, DW ret = WAIT_FAILED; } } - else ret = WAIT_TIMEOUT;
if (ret == WAIT_TIMEOUT && !count && !timeout) NtYieldExecution(); - if ((mask & QS_INPUT) == QS_INPUT) get_user_thread_info()->message_count = 0; + if (ret == count - 1) get_user_thread_info()->last_driver_time = NtGetTickCount();
if (enable_thunk_lock) KeUserModeCallback( NtUserThunkLock, &lock, sizeof(lock), &ret_ptr, &ret_len ); @@ -3247,20 +3241,19 @@ BOOL WINAPI NtUserPeekMessage( MSG *msg_out, HWND hwnd, UINT first, UINT last, U int ret;
user_check_not_lock(); - check_for_driver_events( 0 ); - - ret = peek_message( &msg, &filter ); - if (ret < 0) return FALSE; + check_for_driver_events();
- if (!ret) + if ((ret = peek_message( &msg, &filter )) <= 0) { - 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, &filter ) <= 0) return FALSE; + if (!ret) + { + flush_window_surfaces( TRUE ); + NtYieldExecution(); + } + return FALSE; }
- check_for_driver_events( msg.message ); + check_for_driver_events();
/* copy back our internal safe copy of message data to msg_out. * msg_out is a variable from the *program*, so it can't be used @@ -3286,7 +3279,7 @@ BOOL WINAPI NtUserGetMessage( MSG *msg, HWND hwnd, UINT first, UINT last ) int ret;
user_check_not_lock(); - check_for_driver_events( 0 ); + check_for_driver_events();
if (first || last) { @@ -3307,7 +3300,7 @@ BOOL WINAPI NtUserGetMessage( MSG *msg, HWND hwnd, UINT first, UINT last ) } if (ret < 0) return -1;
- check_for_driver_events( msg->message ); + check_for_driver_events();
return msg->message != WM_QUIT; } diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index a6e61e1751b..a361e1d73a5 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -109,7 +109,7 @@ struct user_thread_info struct ntuser_thread_info client_info; /* Data shared with client */ HANDLE server_queue; /* Handle to server-side queue */ DWORD last_getmsg_time; /* Get/PeekMessage last request time */ - WORD message_count; /* Get/PeekMessage loop counter */ + DWORD last_driver_time; /* Get/PeekMessage driver event time */ WORD hook_call_depth; /* Number of recursively called hook procs */ WORD hook_unicode; /* Is current hook unicode? */ HHOOK hook; /* Current hook */