And set a QS_DRIVER bit when the queue fd is ready for reading, or clear it if it isn't, before waiting on it.
Clear the bit after waiting as we expect the client to process events before calling the server again and before we can poll it again.
From: Rémi Bernon rbernon@codeweavers.com
And set a QS_DRIVER bit when the queue fd is ready for reading, or clear it if it isn't, before waiting on it.
Clear the bit after waiting as we expect the client to process events before calling the server again and before we can poll it again. --- server/protocol.def | 1 + server/queue.c | 35 ++++++++++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/server/protocol.def b/server/protocol.def index c9c77b1cf17..452f3f163af 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1017,6 +1017,7 @@ typedef volatile struct unsigned int wake_bits; /* wakeup bits */ unsigned int changed_mask; /* changed wakeup mask */ unsigned int changed_bits; /* changed wakeup bits */ + unsigned int internal_bits; /* internal queue bits */ int hooks_count[NB_HOOKS]; /* active hooks count */ } queue_shm_t;
diff --git a/server/queue.c b/server/queue.c index 268c921a914..4ee01245757 100644 --- a/server/queue.c +++ b/server/queue.c @@ -46,6 +46,9 @@ #include "request.h" #include "user.h"
+#define QS_DRIVER 0x80000000 +#define QS_INTERNAL QS_DRIVER + #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE #define WM_NCMOUSELAST (WM_NCMOUSEFIRST+(WM_MOUSELAST-WM_MOUSEFIRST))
@@ -335,6 +338,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ shared->wake_bits = 0; shared->changed_mask = 0; shared->changed_bits = 0; + shared->internal_bits = 0; } SHARED_WRITE_END;
@@ -737,8 +741,10 @@ static inline int get_queue_status( struct msg_queue *queue ) static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits ) { queue_shm_t *queue_shm = queue->shared; + unsigned int internal = bits & QS_INTERNAL; + bits &= ~QS_INTERNAL;
- if (bits & (QS_KEY | QS_MOUSEBUTTON)) + if (!internal && (bits & (QS_KEY | QS_MOUSEBUTTON))) { if (!queue->keystate_lock) lock_input_keystate( queue->input ); queue->keystate_lock = 1; @@ -748,6 +754,7 @@ static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits ) { shared->wake_bits |= bits; shared->changed_bits |= bits; + shared->internal_bits |= internal; } SHARED_WRITE_END;
@@ -758,15 +765,19 @@ static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits ) static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits ) { queue_shm_t *queue_shm = queue->shared; + unsigned int internal = bits & QS_INTERNAL; + bits &= ~QS_INTERNAL;
SHARED_WRITE_BEGIN( queue_shm, queue_shm_t ) { shared->wake_bits &= ~bits; shared->changed_bits &= ~bits; + shared->internal_bits &= ~internal; + bits = shared->wake_bits; } SHARED_WRITE_END;
- if (!(queue_shm->wake_bits & (QS_KEY | QS_MOUSEBUTTON))) + if (!internal && !(bits & (QS_KEY | QS_MOUSEBUTTON))) { if (queue->keystate_lock) unlock_input_keystate( queue->input ); queue->keystate_lock = 0; @@ -1298,8 +1309,16 @@ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *ent
if (queue->fd) { - if (check_fd_events( queue->fd, POLLIN )) signal_queue_sync( queue ); - else set_fd_events( queue->fd, POLLIN ); + if (check_fd_events( queue->fd, POLLIN )) + { + set_queue_bits( queue, QS_DRIVER ); + signal_queue_sync( queue ); + } + else + { + clear_queue_bits( queue, QS_DRIVER ); + set_fd_events( queue->fd, POLLIN ); + } } add_queue( obj, entry ); return 1; @@ -1310,7 +1329,12 @@ static void msg_queue_remove_queue(struct object *obj, struct wait_queue_entry * struct msg_queue *queue = (struct msg_queue *)obj;
remove_queue( obj, entry ); - if (queue->fd) set_fd_events( queue->fd, 0 ); + if (queue->fd) + { + /* after waiting, assume that all events will be processed */ + clear_queue_bits( queue, QS_DRIVER ); + set_fd_events( queue->fd, 0 ); + } }
static void msg_queue_dump( struct object *obj, int verbose ) @@ -1387,6 +1411,7 @@ static void msg_queue_poll_event( struct fd *fd, int event )
if (event & (POLLERR | POLLHUP)) set_fd_events( fd, -1 ); else set_fd_events( queue->fd, 0 ); + set_queue_bits( queue, QS_DRIVER ); signal_queue_sync( queue ); }
From: Rémi Bernon rbernon@codeweavers.com
Removing the need to reset the sync after waiting, or in set_queue_mask, as its signal state will be refreshed every time a mask or bit is set or cleared. --- server/queue.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/server/queue.c b/server/queue.c index 4ee01245757..ffb1d441e60 100644 --- a/server/queue.c +++ b/server/queue.c @@ -154,7 +154,6 @@ static void msg_queue_dump( struct object *obj, int verbose ); static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry ); static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry *entry ); static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entry ); -static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ); static void msg_queue_destroy( struct object *obj ); static void msg_queue_poll_event( struct fd *fd, int event ); static void thread_input_dump( struct object *obj, int verbose ); @@ -169,7 +168,7 @@ static const struct object_ops msg_queue_ops = msg_queue_add_queue, /* add_queue */ msg_queue_remove_queue, /* remove_queue */ msg_queue_signaled, /* signaled */ - msg_queue_satisfied, /* satisfied */ + no_satisfied, /* satisfied */ no_signal, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ @@ -734,7 +733,8 @@ static inline int get_queue_status( struct msg_queue *queue ) { queue_shm_t *queue_shm = queue->shared; return (queue_shm->wake_bits & queue_shm->wake_mask) || - (queue_shm->changed_bits & queue_shm->changed_mask); + (queue_shm->changed_bits & queue_shm->changed_mask) || + queue_shm->internal_bits; }
/* set some queue bits */ @@ -1310,10 +1310,7 @@ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *ent if (queue->fd) { if (check_fd_events( queue->fd, POLLIN )) - { set_queue_bits( queue, QS_DRIVER ); - signal_queue_sync( queue ); - } else { clear_queue_bits( queue, QS_DRIVER ); @@ -1352,12 +1349,6 @@ static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entr return queue->signaled; }
-static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ) -{ - struct msg_queue *queue = (struct msg_queue *)obj; - reset_queue_sync( queue ); -} - static void msg_queue_destroy( struct object *obj ) { struct msg_queue *queue = (struct msg_queue *)obj; @@ -1412,7 +1403,6 @@ static void msg_queue_poll_event( struct fd *fd, int event ) if (event & (POLLERR | POLLHUP)) set_fd_events( fd, -1 ); else set_fd_events( queue->fd, 0 ); set_queue_bits( queue, QS_DRIVER ); - signal_queue_sync( queue ); }
static void thread_input_dump( struct object *obj, int verbose ) @@ -3461,7 +3451,8 @@ DECL_HANDLER(get_message) } SHARED_WRITE_END;
- reset_queue_sync( queue ); + if (!get_queue_status( queue )) reset_queue_sync( queue ); + else signal_queue_sync( queue ); set_error( STATUS_PENDING ); /* FIXME */ }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/message.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index df64e059177..392bde22fcb 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -3197,12 +3197,12 @@ static DWORD wait_message( DWORD count, const HANDLE *handles, DWORD timeout, DW params.restore = TRUE; }
- if (user_driver->pProcessEvents( mask )) ret = count - 1; + if (user_driver->pProcessEvents( QS_ALLINPUT )) ret = count - 1; else { ret = NtWaitForMultipleObjects( count, handles, !(flags & MWMO_WAITALL), !!(flags & MWMO_ALERTABLE), get_nt_timeout( &time, timeout )); - if (ret == count - 1) user_driver->pProcessEvents( mask ); + if (ret == count - 1) user_driver->pProcessEvents( QS_ALLINPUT ); else if (HIWORD(ret)) /* is it an error code? */ { RtlSetLastWin32Error( RtlNtStatusToDosError(ret) );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/dce.c | 2 +- dlls/win32u/input.c | 15 --------------- dlls/win32u/message.c | 32 ++++++++++++++++++++++++++++---- dlls/win32u/ntuser_private.h | 13 ++----------- 4 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index 1eb966d3fca..6ba5f1c7c44 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -1803,7 +1803,7 @@ BOOL WINAPI NtUserRedrawWindow( HWND hwnd, const RECT *rect, HRGN hrgn, UINT fla }
/* process pending expose events before painting */ - if (flags & RDW_UPDATENOW) user_driver->pProcessEvents( QS_PAINT ); + if (flags & RDW_UPDATENOW) process_driver_events( QS_PAINT );
if (rect && !hrgn) { diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index c718bd1cbbc..9668d70b040 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -787,21 +787,6 @@ BOOL WINAPI NtUserGetCursorInfo( CURSORINFO *info ) return TRUE; }
-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 ); -} - /********************************************************************** * GetAsyncKeyState (win32u.@) */ diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 392bde22fcb..dc316922581 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -83,6 +83,16 @@ static UINT64 get_tick_count(void)
#define MAX_PACK_COUNT 4
+struct peek_message_filter +{ + HWND hwnd; + UINT first; + UINT last; + UINT mask; + UINT flags; + BOOL internal; +}; + /* info about the message currently being received by the current thread */ struct received_message_info { @@ -2818,7 +2828,7 @@ static BOOL check_queue_bits( UINT wake_mask, UINT changed_mask, UINT signal_bit * available; -1 on error. * All pending sent messages are processed before returning. */ -int peek_message( MSG *msg, const struct peek_message_filter *filter ) +static int peek_message( MSG *msg, const struct peek_message_filter *filter ) { LRESULT result; HWND hwnd = filter->hwnd; @@ -3154,6 +3164,20 @@ static HANDLE get_server_queue_handle(void) return ret; }
+BOOL process_driver_events( UINT mask ) +{ + return user_driver->pProcessEvents( mask ); +} + +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 */ static inline LONGLONG get_driver_check_time(void) { @@ -3168,7 +3192,7 @@ static inline void check_for_driver_events(void) if (get_user_thread_info()->last_driver_time != get_driver_check_time()) { flush_window_surfaces( FALSE ); - user_driver->pProcessEvents( QS_ALLINPUT ); + process_driver_events( QS_ALLINPUT ); get_user_thread_info()->last_driver_time = get_driver_check_time(); } } @@ -3197,12 +3221,12 @@ static DWORD wait_message( DWORD count, const HANDLE *handles, DWORD timeout, DW params.restore = TRUE; }
- if (user_driver->pProcessEvents( QS_ALLINPUT )) ret = count - 1; + 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 )); - if (ret == count - 1) user_driver->pProcessEvents( QS_ALLINPUT ); + if (ret == count - 1) process_driver_events( QS_ALLINPUT ); else if (HIWORD(ret)) /* is it an error code? */ { RtlSetLastWin32Error( RtlNtStatusToDosError(ret) ); diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 2de11465f87..5e6e6d36cae 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -201,17 +201,8 @@ extern void free_dce( struct dce *dce, HWND hwnd ); extern void invalidate_dce( WND *win, const RECT *old_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 process_driver_events( UINT mask ); +extern void check_for_events( UINT flags );
/* systray.c */ extern LRESULT system_tray_call( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, void *data );