diff --git a/dlls/user32/sysparams.c b/dlls/user32/sysparams.c index b6679c5deba..2dc5cb2f240 100644 --- a/dlls/user32/sysparams.c +++ b/dlls/user32/sysparams.c @@ -3236,6 +3236,16 @@ RECT map_dpi_rect( RECT rect, UINT dpi_from, UINT dpi_to ) return rect; } +/********************************************************************** + * rect_win_to_thread_dpi + */ +RECT rect_win_to_thread_dpi( HWND hwnd, RECT rect ) +{ + UINT dpi = get_thread_dpi(); + if (!dpi) dpi = get_win_monitor_dpi( hwnd ); + return map_dpi_rect( rect, GetDpiForWindow( hwnd ), dpi ); +} + /********************************************************************** * SetProcessDpiAwarenessContext (USER32.@) */ diff --git a/dlls/user32/win.c b/dlls/user32/win.c index c7a3b06c3a2..d9ef15148cb 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -844,6 +844,7 @@ BOOL WIN_GetRectangles( HWND hwnd, enum coords_relative relative, RECT *rectWind { rect.right = 100; rect.bottom = 100; + rect = rect_win_to_thread_dpi( hwnd, rect ); } else { @@ -921,8 +922,8 @@ BOOL WIN_GetRectangles( HWND hwnd, enum coords_relative relative, RECT *rectWind } break; } - if (rectWindow) *rectWindow = window_rect; - if (rectClient) *rectClient = client_rect; + if (rectWindow) *rectWindow = rect_win_to_thread_dpi( hwnd, window_rect ); + if (rectClient) *rectClient = rect_win_to_thread_dpi( hwnd, client_rect ); WIN_ReleasePtr( win ); return TRUE; } @@ -932,6 +933,7 @@ other_process: { req->handle = wine_server_user_handle( hwnd ); req->relative = relative; + req->dpi = get_thread_dpi(); if ((ret = !wine_server_call_err( req ))) { if (rectWindow) diff --git a/dlls/user32/win.h b/dlls/user32/win.h index 226e3e9c00a..3fff0fc4ceb 100644 --- a/dlls/user32/win.h +++ b/dlls/user32/win.h @@ -132,6 +132,7 @@ extern UINT get_monitor_dpi( HMONITOR monitor ) DECLSPEC_HIDDEN; extern UINT get_win_monitor_dpi( HWND hwnd ) DECLSPEC_HIDDEN; extern UINT get_thread_dpi(void) DECLSPEC_HIDDEN; extern RECT map_dpi_rect( RECT rect, UINT dpi_from, UINT dpi_to ) DECLSPEC_HIDDEN; +extern RECT rect_win_to_thread_dpi( HWND hwnd, RECT rect ) DECLSPEC_HIDDEN; extern BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, const RECT *valid_rects ) DECLSPEC_HIDDEN; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index c636bacb35e..9c5decae40a 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -3692,7 +3692,7 @@ struct get_window_rectangles_request struct request_header __header; user_handle_t handle; int relative; - char __pad_20[4]; + int dpi; }; struct get_window_rectangles_reply { @@ -6533,6 +6533,6 @@ union generic_reply struct terminate_job_reply terminate_job_reply; }; -#define SERVER_PROTOCOL_VERSION 556 +#define SERVER_PROTOCOL_VERSION 557 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index c8bb3b11004..43f5f015d14 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2651,6 +2651,7 @@ enum message_type @REQ(get_window_rectangles) user_handle_t handle; /* handle to the window */ int relative; /* coords relative to (see below) */ + int dpi; /* DPI to map to, or zero for per-monitor DPI */ @REPLY rectangle_t window; /* window rectangle */ rectangle_t client; /* client rectangle */ diff --git a/server/request.h b/server/request.h index d3028f0b1d7..c3aed96780e 100644 --- a/server/request.h +++ b/server/request.h @@ -1773,6 +1773,7 @@ C_ASSERT( FIELD_OFFSET(struct set_window_pos_reply, needs_update) == 20 ); C_ASSERT( sizeof(struct set_window_pos_reply) == 24 ); C_ASSERT( FIELD_OFFSET(struct get_window_rectangles_request, handle) == 12 ); C_ASSERT( FIELD_OFFSET(struct get_window_rectangles_request, relative) == 16 ); +C_ASSERT( FIELD_OFFSET(struct get_window_rectangles_request, dpi) == 20 ); C_ASSERT( sizeof(struct get_window_rectangles_request) == 24 ); C_ASSERT( FIELD_OFFSET(struct get_window_rectangles_reply, window) == 8 ); C_ASSERT( FIELD_OFFSET(struct get_window_rectangles_reply, client) == 24 ); diff --git a/server/trace.c b/server/trace.c index 68e47d49b89..1d773fb690a 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3229,6 +3229,7 @@ static void dump_get_window_rectangles_request( const struct get_window_rectangl { fprintf( stderr, " handle=%08x", req->handle ); fprintf( stderr, ", relative=%d", req->relative ); + fprintf( stderr, ", dpi=%d", req->dpi ); } static void dump_get_window_rectangles_reply( const struct get_window_rectangles_reply *req ) diff --git a/server/user.h b/server/user.h index 1236b0e14e4..fe3aa0977dd 100644 --- a/server/user.h +++ b/server/user.h @@ -198,6 +198,20 @@ static inline int point_in_rect( const rectangle_t *rect, int x, int y ) return (x >= rect->left && x < rect->right && y >= rect->top && y < rect->bottom); } +static inline int scale_dpi( int val, unsigned int dpi_from, unsigned int dpi_to ) +{ + if (val >= 0) return (val * dpi_to + (dpi_from / 2)) / dpi_from; + return (val * dpi_to - (dpi_from / 2)) / dpi_from; +} + +static inline void scale_dpi_rect( rectangle_t *rect, unsigned int dpi_from, unsigned int dpi_to ) +{ + rect->left = scale_dpi( rect->left, dpi_from, dpi_to ); + rect->top = scale_dpi( rect->top, dpi_from, dpi_to ); + rect->right = scale_dpi( rect->right, dpi_from, dpi_to ); + rect->bottom = scale_dpi( rect->bottom, dpi_from, dpi_to ); +} + /* offset the coordinates of a rectangle */ static inline void offset_rect( rectangle_t *rect, int offset_x, int offset_y ) { diff --git a/server/window.c b/server/window.c index e58d7e46d68..c286a0ab22f 100644 --- a/server/window.c +++ b/server/window.c @@ -630,6 +630,15 @@ static inline void inc_window_paint_count( struct window *win, int incr ) if (win->thread) inc_queue_paint_count( win->thread, incr ); } +/* map a window rectangle between different DPI scaling levels */ +static void map_dpi_rect( struct window *win, rectangle_t *rect, unsigned int from, unsigned int to ) +{ + if (!from) from = get_monitor_dpi( win ); + if (!to) to = get_monitor_dpi( win ); + if (from == to) return; + scale_dpi_rect( rect, from, to ); +} + /* check if window and all its ancestors are visible */ static int is_visible( const struct window *win ) { @@ -2349,6 +2358,8 @@ DECL_HANDLER(get_window_rectangles) set_error( STATUS_INVALID_PARAMETER ); break; } + map_dpi_rect( win, &reply->window, win->dpi, req->dpi ); + map_dpi_rect( win, &reply->client, win->dpi, req->dpi ); }