Module: wine Branch: master Commit: 25906eedd8679fdb474976563f4a05a92e11bbd6 URL: https://gitlab.winehq.org/wine/wine/-/commit/25906eedd8679fdb474976563f4a05a...
Author: Rémi Bernon rbernon@codeweavers.com Date: Sat Jun 10 12:52:01 2023 +0200
server: Introduce and send new WM_WINE_SETCURSOR hardware message.
---
dlls/win32u/cursoricon.c | 6 ++++ dlls/win32u/message.c | 5 ++++ dlls/win32u/win32u_private.h | 1 + include/ntuser.h | 1 + server/queue.c | 69 ++++++++++++++++++++++++++++++-------------- 5 files changed, 60 insertions(+), 22 deletions(-)
diff --git a/dlls/win32u/cursoricon.c b/dlls/win32u/cursoricon.c index ae9dc6f6b8b..409f1346ca0 100644 --- a/dlls/win32u/cursoricon.c +++ b/dlls/win32u/cursoricon.c @@ -74,6 +74,12 @@ static struct cursoricon_object *get_icon_ptr( HICON handle ) return obj; }
+BOOL process_wine_setcursor( HWND hwnd, HWND window, HCURSOR handle ) +{ + TRACE( "hwnd %p, window %p, hcursor %p\n", hwnd, window, handle ); + return TRUE; +} + /*********************************************************************** * NtUserShowCursor (win32u.@) */ diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index e10350fcd3b..cb44e0037d9 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -1274,6 +1274,9 @@ static LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPAR case WM_WINE_CLIPCURSOR: if (wparam && lparam) return clip_fullscreen_window( hwnd, FALSE ); return process_wine_clipcursor( hwnd, wparam, lparam ); + case WM_WINE_SETCURSOR: + FIXME( "Unexpected non-hardware WM_WINE_SETCURSOR message\n" ); + return FALSE; case WM_WINE_UPDATEWINDOWSTATE: update_window_state( hwnd ); return 0; @@ -1769,6 +1772,8 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar ret = process_mouse_message( msg, hw_id, msg_data->info, hwnd_filter, first, last, remove ); else if (msg->message == WM_WINE_CLIPCURSOR) process_wine_clipcursor( msg->hwnd, msg->wParam, msg->lParam ); + else if (msg->message == WM_WINE_SETCURSOR) + process_wine_setcursor( msg->hwnd, (HWND)msg->wParam, (HCURSOR)msg->lParam ); else ERR( "unknown message type %x\n", msg->message ); SetThreadDpiAwarenessContext( context ); diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 44baf546182..3bd41a4ffa8 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -38,6 +38,7 @@ extern UINT enum_clipboard_formats( UINT format ) DECLSPEC_HIDDEN; extern void release_clipboard_owner( HWND hwnd ) DECLSPEC_HIDDEN;
/* cursoricon.c */ +extern BOOL process_wine_setcursor( HWND hwnd, HWND window, HCURSOR handle ) DECLSPEC_HIDDEN; extern HICON alloc_cursoricon_handle( BOOL is_icon ) DECLSPEC_HIDDEN; extern ULONG_PTR get_icon_param( HICON handle ) DECLSPEC_HIDDEN; extern ULONG_PTR set_icon_param( HICON handle, ULONG_PTR param ) DECLSPEC_HIDDEN; diff --git a/include/ntuser.h b/include/ntuser.h index 13c0147f9a4..31317026cd8 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -483,6 +483,7 @@ enum wine_internal_message WM_WINE_KEYBOARD_LL_HOOK, WM_WINE_MOUSE_LL_HOOK, WM_WINE_CLIPCURSOR, + WM_WINE_SETCURSOR, WM_WINE_UPDATEWINDOWSTATE, WM_WINE_FIRST_DRIVER_MSG = 0x80001000, /* range of messages reserved for the USER driver */ WM_WINE_LAST_DRIVER_MSG = 0x80001fff diff --git a/server/queue.c b/server/queue.c index 7428685f94f..ec8ddcbee5c 100644 --- a/server/queue.c +++ b/server/queue.c @@ -404,10 +404,42 @@ static struct message *alloc_hardware_message( lparam_t info, struct hw_msg_sour return msg; }
+static int is_cursor_clipped( struct desktop *desktop ) +{ + rectangle_t top_rect, clip_rect = desktop->cursor.clip; + get_top_window_rectangle( desktop, &top_rect ); + return !is_rect_equal( &clip_rect, &top_rect ); +} + +static void queue_cursor_message( struct desktop *desktop, user_handle_t win, unsigned int message, + lparam_t wparam, lparam_t lparam ) +{ + static const struct hw_msg_source source = { IMDT_UNAVAILABLE, IMO_SYSTEM }; + struct thread_input *input; + struct message *msg; + + if (!(msg = alloc_hardware_message( 0, source, get_tick_count(), 0 ))) return; + + msg->msg = message; + msg->wparam = wparam; + msg->lparam = lparam; + msg->x = desktop->cursor.x; + msg->y = desktop->cursor.y; + if (!(msg->win = win) && (input = desktop->foreground_input)) msg->win = input->active; + queue_hardware_message( desktop, msg, 1 ); +} + static int update_desktop_cursor_window( struct desktop *desktop, user_handle_t win ) { int updated = win != desktop->cursor.win; + user_handle_t handle = desktop->cursor.handle; desktop->cursor.win = win; + if (updated) + { + /* 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 ); + } return updated; }
@@ -433,7 +465,15 @@ static int update_desktop_cursor_pos( struct desktop *desktop, user_handle_t win
static void update_desktop_cursor_handle( struct desktop *desktop, user_handle_t handle ) { + int updated = desktop->cursor.handle != handle; + user_handle_t win = desktop->cursor.win; desktop->cursor.handle = handle; + if (updated) + { + /* 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 ); + } }
/* set the cursor position and queue the corresponding mouse message */ @@ -467,23 +507,6 @@ static void get_message_defaults( struct msg_queue *queue, int *x, int *y, unsig *time = get_tick_count(); }
-static void queue_clip_cursor_msg( struct desktop *desktop, lparam_t wparam, lparam_t lparam ) -{ - static const struct hw_msg_source source = { IMDT_UNAVAILABLE, IMO_SYSTEM }; - struct thread_input *input; - struct message *msg; - - if (!(msg = alloc_hardware_message( 0, source, get_tick_count(), 0 ))) return; - - msg->msg = WM_WINE_CLIPCURSOR; - msg->wparam = wparam; - msg->lparam = lparam; - msg->x = desktop->cursor.x; - msg->y = desktop->cursor.y; - if ((input = desktop->foreground_input)) msg->win = input->active; - queue_hardware_message( desktop, msg, 1 ); -} - /* set the cursor clip rectangle */ void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect, int reset ) { @@ -512,7 +535,7 @@ void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect, int r if (reset) post_desktop_message( desktop, WM_WINE_CLIPCURSOR, TRUE, FALSE );
/* notify foreground thread, of reset, or to apply new cursor clipping rect */ - queue_clip_cursor_msg( desktop, rect == NULL, reset ); + queue_cursor_message( desktop, 0, WM_WINE_CLIPCURSOR, rect == NULL, reset ); }
/* change the foreground input and reset the cursor clip rect */ @@ -598,6 +621,7 @@ static inline int get_hardware_msg_bit( unsigned int message ) 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; return QS_MOUSEBUTTON; }
@@ -650,13 +674,13 @@ static int merge_mousemove( struct thread_input *input, const struct message *ms return 1; }
-/* try to merge a WM_WINE_CLIPCURSOR message with the last in the list; return 1 if successful */ -static int merge_wine_clipcursor( struct thread_input *input, const struct message *msg ) +/* try to merge a unique message with the last in the list; return 1 if successful */ +static int merge_unique_message( struct thread_input *input, unsigned int message, const struct message *msg ) { struct message *prev;
LIST_FOR_EACH_ENTRY_REV( prev, &input->msg_list, struct message, entry ) - if (prev->msg == WM_WINE_CLIPCURSOR) break; + if (prev->msg == message) break; if (&prev->entry == &input->msg_list) return 0;
if (prev->result) return 0; @@ -679,7 +703,8 @@ static int merge_wine_clipcursor( struct thread_input *input, const struct messa static int merge_message( struct thread_input *input, const struct message *msg ) { if (msg->msg == WM_MOUSEMOVE) return merge_mousemove( input, msg ); - if (msg->msg == WM_WINE_CLIPCURSOR) return merge_wine_clipcursor( input, msg ); + if (msg->msg == WM_WINE_CLIPCURSOR) return merge_unique_message( input, WM_WINE_CLIPCURSOR, msg ); + if (msg->msg == WM_WINE_SETCURSOR) return merge_unique_message( input, WM_WINE_SETCURSOR, msg ); return 0; }