-- v6: win32u: Avoid changing thread DPI context in process_hardware_message. win32u: Factor hardware message point DPI mapping together. win32u: Use map_window_points with explicit DPI over screen_to_client. win32u: Split hardware message window lookup to a separate helper. win32u: Use per-monitor DPI window_from_point in process_mouse_message. win32u: Parameterize window_from_point dpi. server: Pass window's per-monitor DPI in set_window_pos.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/window.c | 4 ++++ server/protocol.def | 1 + server/window.c | 20 ++++++++++---------- 3 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index caa3b3aa323..193e7212e02 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1793,6 +1793,7 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, BOOL ret, needs_surface, needs_update = FALSE; RECT visible_rect = *window_rect, old_visible_rect, old_window_rect, old_client_rect, extra_rects[3]; struct window_surface *old_surface, *new_surface = NULL; + UINT monitor_dpi;
needs_surface = user_driver->pWindowPosChanging( hwnd, swp_flags, window_rect, client_rect, &visible_rect );
@@ -1834,11 +1835,14 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, valid_rects = NULL; }
+ monitor_dpi = get_monitor_dpi( monitor_from_rect( window_rect, MONITOR_DEFAULTTONEAREST, get_thread_dpi() ) ); + SERVER_START_REQ( set_window_pos ) { req->handle = wine_server_user_handle( hwnd ); req->previous = wine_server_user_handle( insert_after ); req->swp_flags = swp_flags; + req->monitor_dpi = monitor_dpi; req->window = wine_server_rectangle( *window_rect ); req->client = wine_server_rectangle( *client_rect ); if (!EqualRect( window_rect, &visible_rect ) || new_surface || valid_rects) diff --git a/server/protocol.def b/server/protocol.def index 25184641082..173368df6eb 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2526,6 +2526,7 @@ enum message_type @REQ(set_window_pos) unsigned short swp_flags; /* SWP_* flags */ unsigned short paint_flags; /* paint flags (see below) */ + unsigned int monitor_dpi; /* DPI of the window's monitor */ user_handle_t handle; /* handle to the window */ user_handle_t previous; /* previous window in Z order */ rectangle_t window; /* window rectangle (in parent coords) */ diff --git a/server/window.c b/server/window.c index 4ebfec3da12..b5e40bdd6f5 100644 --- a/server/window.c +++ b/server/window.c @@ -84,6 +84,7 @@ struct window unsigned int alpha; /* alpha value for a layered window */ unsigned int layered_flags; /* flags for a layered window */ unsigned int dpi_context; /* DPI awareness context */ + unsigned int monitor_dpi; /* DPI of the window monitor */ lparam_t user_data; /* user-specific data */ WCHAR *text; /* window caption text */ data_size_t text_len; /* length of window caption */ @@ -244,20 +245,17 @@ static inline void update_pixel_format_flags( struct window *win ) win->paint_flags |= PAINT_PIXEL_FORMAT_CHILD; }
-static unsigned int get_window_dpi( struct window *win ) +/* get the per-monitor DPI for a window */ +static unsigned int get_monitor_dpi( struct window *win ) { - unsigned int dpi; - if ((dpi = NTUSER_DPI_CONTEXT_GET_DPI( win->dpi_context ))) return dpi; - /* FIXME: return the window monitor DPI? */ - return USER_DEFAULT_SCREEN_DPI; + while (win->parent && !is_desktop_window( win->parent )) win = win->parent; + return win->monitor_dpi; }
-/* get the per-monitor DPI for a window */ -static unsigned int get_monitor_dpi( struct window *win ) +static unsigned int get_window_dpi( struct window *win ) { - /* FIXME: we return the desktop window DPI for now */ - while (!is_desktop_window( win )) win = win->parent; - return get_window_dpi( win ); + if (NTUSER_DPI_CONTEXT_IS_MONITOR_AWARE( win->dpi_context )) return get_monitor_dpi( win ); + return NTUSER_DPI_CONTEXT_GET_DPI( win->dpi_context ); }
/* link a window at the right place in the siblings list */ @@ -577,6 +575,7 @@ static struct window *create_window( struct window *parent, struct window *owner win->is_layered = 0; win->is_orphan = 0; win->dpi_context = NTUSER_DPI_PER_MONITOR_AWARE; + win->monitor_dpi = USER_DEFAULT_SCREEN_DPI; win->user_data = 0; win->text = NULL; win->text_len = 0; @@ -2475,6 +2474,7 @@ DECL_HANDLER(set_window_pos) win->paint_flags = (win->paint_flags & ~PAINT_CLIENT_FLAGS) | (req->paint_flags & PAINT_CLIENT_FLAGS); if (win->paint_flags & PAINT_HAS_PIXEL_FORMAT) update_pixel_format_flags( win );
+ win->monitor_dpi = req->monitor_dpi; set_window_pos( win, previous, flags, &window_rect, &client_rect, &visible_rect, &surface_rect, &valid_rect );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/input.c | 4 ++-- dlls/win32u/message.c | 5 +++-- dlls/win32u/win32u_private.h | 2 +- dlls/win32u/window.c | 13 ++++++------- 4 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 5b25086cb6f..0d9fe0f1d38 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -1607,7 +1607,7 @@ void update_mouse_tracking_info( HWND hwnd ) TRACE( "hwnd %p\n", hwnd );
get_cursor_pos( &pos ); - hwnd = window_from_point( hwnd, pos, &hittest ); + hwnd = window_from_point( hwnd, pos, &hittest, get_thread_dpi() );
TRACE( "point %s hwnd %p hittest %d\n", wine_dbgstr_point(&pos), hwnd, hittest );
@@ -1703,7 +1703,7 @@ BOOL WINAPI NtUserTrackMouseEvent( TRACKMOUSEEVENT *info ) NtUserSystemParametersInfo( SPI_GETMOUSEHOVERTIME, 0, &hover_time, 0 );
get_cursor_pos( &pos ); - hwnd = window_from_point( info->hwndTrack, pos, &hittest ); + hwnd = window_from_point( info->hwndTrack, pos, &hittest, get_thread_dpi() ); TRACE( "point %s hwnd %p hittest %d\n", wine_dbgstr_point(&pos), hwnd, hittest );
if (info->dwFlags & ~(TME_CANCEL | TME_HOVER | TME_LEAVE | TME_NONCLIENT)) diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index d1f49ca3ed9..049773fe7e3 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2424,15 +2424,16 @@ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, H else { HWND orig = msg->hwnd; + UINT dpi = get_thread_dpi();
- msg->hwnd = window_from_point( msg->hwnd, msg->pt, &hittest ); + msg->hwnd = window_from_point( msg->hwnd, msg->pt, &hittest, dpi ); if (!msg->hwnd) /* As a heuristic, try the next window if it's the owner of orig */ { HWND next = get_window_relative( orig, GW_HWNDNEXT );
if (next && get_window_relative( orig, GW_OWNER ) == next && is_current_thread_window( next )) - msg->hwnd = window_from_point( next, msg->pt, &hittest ); + msg->hwnd = window_from_point( next, msg->pt, &hittest, dpi ); } }
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 96517ef081a..8e33370ee48 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -252,7 +252,7 @@ extern BOOL set_window_pos( WINDOWPOS *winpos, int parent_x, int parent_y ); extern ULONG set_window_style( HWND hwnd, ULONG set_bits, ULONG clear_bits ); extern BOOL show_owned_popups( HWND owner, BOOL show ); extern void update_window_state( HWND hwnd ); -extern HWND window_from_point( HWND hwnd, POINT pt, INT *hittest ); +extern HWND window_from_point( HWND hwnd, POINT pt, INT *hittest, UINT dpi ); extern HWND get_shell_window(void); extern HWND get_progman_window(void); extern HWND set_progman_window( HWND hwnd ); diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 193e7212e02..532bbb6bfec 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -2195,7 +2195,7 @@ done: * Point is in screen coordinates. * Returned list must be freed by caller. */ -static HWND *list_children_from_point( HWND hwnd, POINT pt ) +static HWND *list_children_from_point( HWND hwnd, POINT pt, UINT dpi ) { int i, size = 128; HWND *list; @@ -2211,7 +2211,7 @@ static HWND *list_children_from_point( HWND hwnd, POINT pt ) req->parent = wine_server_user_handle( hwnd ); req->x = pt.x; req->y = pt.y; - req->dpi = get_thread_dpi(); + req->dpi = dpi; wine_server_set_reply( req, list, (size-1) * sizeof(user_handle_t) ); if (!wine_server_call( req )) count = reply->count; } @@ -2236,19 +2236,18 @@ static HWND *list_children_from_point( HWND hwnd, POINT pt ) * * Find the window and hittest for a given point. */ -HWND window_from_point( HWND hwnd, POINT pt, INT *hittest ) +HWND window_from_point( HWND hwnd, POINT pt, INT *hittest, UINT dpi ) { int i, res; HWND ret, *list; POINT win_pt; - int dpi;
if (!hwnd) hwnd = get_desktop_window(); - if (!(dpi = get_thread_dpi())) dpi = get_win_monitor_dpi( hwnd ); + if (!dpi) dpi = get_win_monitor_dpi( hwnd );
*hittest = HTNOWHERE;
- if (!(list = list_children_from_point( hwnd, pt ))) return 0; + if (!(list = list_children_from_point( hwnd, pt, dpi ))) return 0;
/* now determine the hittest */
@@ -2290,7 +2289,7 @@ HWND WINAPI NtUserWindowFromPoint( LONG x, LONG y ) { POINT pt = { .x = x, .y = y }; INT hittest; - return window_from_point( 0, pt, &hittest ); + return window_from_point( 0, pt, &hittest, get_thread_dpi() ); }
/*******************************************************************
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/message.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 049773fe7e3..9117979422f 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2424,16 +2424,15 @@ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, H else { HWND orig = msg->hwnd; - UINT dpi = get_thread_dpi();
- msg->hwnd = window_from_point( msg->hwnd, msg->pt, &hittest, dpi ); + msg->hwnd = window_from_point( msg->hwnd, msg->pt, &hittest, 0 /* per-monitor DPI */ ); if (!msg->hwnd) /* As a heuristic, try the next window if it's the owner of orig */ { HWND next = get_window_relative( orig, GW_HWNDNEXT );
if (next && get_window_relative( orig, GW_OWNER ) == next && is_current_thread_window( next )) - msg->hwnd = window_from_point( next, msg->pt, &hittest, dpi ); + msg->hwnd = window_from_point( next, msg->pt, &hittest, 0 /* per-monitor DPI */ ); } }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/message.c | 63 +++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 32 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 9117979422f..7ff38a923fa 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2393,49 +2393,43 @@ static BOOL process_keyboard_message( MSG *msg, UINT hw_id, HWND hwnd_filter, return TRUE; }
+static HWND find_hardware_message_window( MSG *msg, GUITHREADINFO *info, INT *hittest ) +{ + HWND target; + + if (!is_mouse_message( msg->message )) return msg->hwnd; + + /* find the window to dispatch this mouse message to */ + + if ((target = info->hwndCapture)) *hittest = HTCLIENT; + else if (!(target = window_from_point( msg->hwnd, msg->pt, hittest, 0 /* per-monitor DPI */ ))) + { + /* As a heuristic, try the next window if it's the owner of orig */ + HWND next = get_window_relative( msg->hwnd, GW_HWNDNEXT ); + if (next && get_window_relative( msg->hwnd, GW_OWNER ) == next && is_current_thread_window( next )) + target = window_from_point( next, msg->pt, hittest, 0 /* per-monitor DPI */ ); + } + + return target; +} + /*********************************************************************** * process_mouse_message * * returns TRUE if the contents of 'msg' should be passed to the application */ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, HWND hwnd_filter, - UINT first, UINT last, BOOL remove ) + UINT first, UINT last, BOOL remove, GUITHREADINFO *info, INT hittest ) { static MSG clk_msg;
POINT pt; UINT message; - INT hittest; EVENTMSG event; - GUITHREADINFO info; MOUSEHOOKSTRUCTEX hook; BOOL eat_msg; WPARAM wparam;
- /* find the window to dispatch this mouse message to */ - - info.cbSize = sizeof(info); - NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info ); - if (info.hwndCapture) - { - hittest = HTCLIENT; - msg->hwnd = info.hwndCapture; - } - else - { - HWND orig = msg->hwnd; - - msg->hwnd = window_from_point( msg->hwnd, msg->pt, &hittest, 0 /* per-monitor DPI */ ); - if (!msg->hwnd) /* As a heuristic, try the next window if it's the owner of orig */ - { - HWND next = get_window_relative( orig, GW_HWNDNEXT ); - - if (next && get_window_relative( orig, GW_OWNER ) == next && - is_current_thread_window( next )) - msg->hwnd = window_from_point( next, msg->pt, &hittest, 0 /* per-monitor DPI */ ); - } - } - if (!msg->hwnd || !is_current_thread_window( msg->hwnd )) { accept_hardware_message( hw_id ); @@ -2470,7 +2464,7 @@ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, H { /* coordinates don't get translated while tracking a menu */ /* FIXME: should differentiate popups and top-level menus */ - if (!(info.flags & GUI_INMENUMODE)) + if (!(info->flags & GUI_INMENUMODE)) screen_to_client( msg->hwnd, &pt ); } } @@ -2489,7 +2483,7 @@ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, H * note that ...MOUSEMOVEs can slip in between * ...BUTTONDOWN and ...BUTTONDBLCLK messages */
- if ((info.flags & (GUI_INMENUMODE|GUI_INMOVESIZE)) || + if ((info->flags & (GUI_INMENUMODE|GUI_INMOVESIZE)) || hittest != HTCLIENT || (get_class_long( msg->hwnd, GCL_STYLE, FALSE ) & CS_DBLCLKS)) { @@ -2546,7 +2540,7 @@ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, H
if (remove) accept_hardware_message( hw_id );
- if (!remove || info.hwndCapture) + if (!remove || info->hwndCapture) { msg->message = message; return TRUE; @@ -2567,7 +2561,7 @@ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, H
/* Activate the window if needed */
- if (msg->hwnd != info.hwndActive) + if (msg->hwnd != info->hwndActive) { HWND hwndTop = NtUserGetAncestor( msg->hwnd, GA_ROOT );
@@ -2616,12 +2610,17 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar HWND hwnd_filter, UINT first, UINT last, BOOL remove ) { struct ntuser_thread_info *thread_info = NtUserGetThreadInfo(); + GUITHREADINFO info = {.cbSize = sizeof(info)}; UINT context; BOOL ret = FALSE; + INT hittest;
thread_info->msg_source.deviceType = msg_data->source.device; thread_info->msg_source.originId = msg_data->source.origin;
+ NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info ); + msg->hwnd = find_hardware_message_window( msg, &info, &hittest ); + /* hardware messages are always in physical coords */ context = set_thread_dpi_awareness_context( NTUSER_DPI_PER_MONITOR_AWARE );
@@ -2630,7 +2629,7 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar else if (is_keyboard_message( msg->message )) ret = process_keyboard_message( msg, hw_id, hwnd_filter, first, last, remove ); else if (is_mouse_message( msg->message )) - ret = process_mouse_message( msg, hw_id, msg_data->info, hwnd_filter, first, last, remove ); + ret = process_mouse_message( msg, hw_id, msg_data->info, hwnd_filter, first, last, remove, &info, hittest ); else if (msg->message >= WM_POINTERUPDATE && msg->message <= WM_POINTERLEAVE) ret = process_pointer_message( msg, hw_id, msg_data ); else if (msg->message == WM_WINE_CLIPCURSOR)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/message.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 7ff38a923fa..210885d59d1 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2460,12 +2460,11 @@ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, H message += WM_NCMOUSEMOVE - WM_MOUSEMOVE; wparam = hittest; } - else + /* coordinates don't get translated while tracking a menu */ + /* FIXME: should differentiate popups and top-level menus */ + else if (!(info->flags & GUI_INMENUMODE)) { - /* coordinates don't get translated while tracking a menu */ - /* FIXME: should differentiate popups and top-level menus */ - if (!(info->flags & GUI_INMENUMODE)) - screen_to_client( msg->hwnd, &pt ); + map_window_points( 0, msg->hwnd, &pt, 1, get_dpi_for_window( msg->hwnd ) ); } } msg->lParam = MAKELONG( pt.x, pt.y );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/message.c | 4 +--- dlls/win32u/rawinput.c | 1 - 2 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 210885d59d1..c0f6cb2e7ec 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2305,7 +2305,6 @@ static void send_parent_notify( HWND hwnd, WORD event, WORD idChild, POINT pt ) */ static BOOL process_pointer_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data ) { - msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt ); return TRUE; }
@@ -2384,7 +2383,6 @@ static BOOL process_keyboard_message( MSG *msg, UINT hw_id, HWND hwnd_filter, call_hooks( WH_CBT, HCBT_KEYSKIPPED, LOWORD(msg->wParam), msg->lParam, 0 ); return FALSE; } - msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt );
if (remove && (msg->message == WM_KEYDOWN || msg->message == WM_KEYUP)) if (ImmProcessKey( msg->hwnd, NtUserGetKeyboardLayout(0), msg->wParam, msg->lParam, 0 )) @@ -2436,7 +2434,6 @@ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, H return FALSE; }
- msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt ); set_thread_dpi_awareness_context( get_window_dpi_awareness_context( msg->hwnd ));
/* FIXME: is this really the right place for this hook? */ @@ -2619,6 +2616,7 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar
NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info ); msg->hwnd = find_hardware_message_window( msg, &info, &hittest ); + msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt );
/* hardware messages are always in physical coords */ context = set_thread_dpi_awareness_context( NTUSER_DPI_PER_MONITOR_AWARE ); diff --git a/dlls/win32u/rawinput.c b/dlls/win32u/rawinput.c index 62b1707dbfe..7af2de1cb73 100644 --- a/dlls/win32u/rawinput.c +++ b/dlls/win32u/rawinput.c @@ -597,7 +597,6 @@ BOOL process_rawinput_message( MSG *msg, UINT hw_id, const struct hardware_msg_d msg->lParam = (LPARAM)hw_id; }
- msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt ); return TRUE; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/message.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index c0f6cb2e7ec..d70edf0bc48 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2434,8 +2434,6 @@ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, H return FALSE; }
- set_thread_dpi_awareness_context( get_window_dpi_awareness_context( msg->hwnd )); - /* FIXME: is this really the right place for this hook? */ event.message = msg->message; event.time = msg->time; @@ -2607,7 +2605,6 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar { struct ntuser_thread_info *thread_info = NtUserGetThreadInfo(); GUITHREADINFO info = {.cbSize = sizeof(info)}; - UINT context; BOOL ret = FALSE; INT hittest;
@@ -2618,9 +2615,6 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar msg->hwnd = find_hardware_message_window( msg, &info, &hittest ); msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt );
- /* hardware messages are always in physical coords */ - context = set_thread_dpi_awareness_context( NTUSER_DPI_PER_MONITOR_AWARE ); - if (msg->message == WM_INPUT || msg->message == WM_INPUT_DEVICE_CHANGE) ret = process_rawinput_message( msg, hw_id, msg_data ); else if (is_keyboard_message( msg->message )) @@ -2635,7 +2629,7 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar process_wine_setcursor( msg->hwnd, (HWND)msg->wParam, (HCURSOR)msg->lParam ); else ERR( "unknown message type %x\n", msg->message ); - set_thread_dpi_awareness_context( context ); + return ret; }
v4: Fix broken mouse input when process is per-monitor DPI aware. It was caused by inconsistency between win32u (which is using system DPI for per-monitor window DPI), and wineserver which is using the default DPI. Passing the per-monitor window DPI to wineserver when they are moved fixes it, although we still use the system DPI value for now.