user32: Scale coordinates in MapWindowPoints() based on DPI awareness.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2018-08-24 12:12:44 +02:00
parent c5a6925676
commit 8de1b2c2ce
8 changed files with 64 additions and 28 deletions

View File

@ -3221,6 +3221,29 @@ UINT get_thread_dpi(void)
}
}
/**********************************************************************
* map_dpi_point
*/
POINT map_dpi_point( POINT pt, UINT dpi_from, UINT dpi_to )
{
if (dpi_from && dpi_to && dpi_from != dpi_to)
{
pt.x = MulDiv( pt.x, dpi_to, dpi_from );
pt.y = MulDiv( pt.y, dpi_to, dpi_from );
}
return pt;
}
/**********************************************************************
* point_win_to_thread_dpi
*/
POINT point_win_to_thread_dpi( HWND hwnd, POINT pt )
{
UINT dpi = get_thread_dpi();
if (!dpi) dpi = get_win_monitor_dpi( hwnd );
return map_dpi_point( pt, GetDpiForWindow( hwnd ), dpi );
}
/**********************************************************************
* map_dpi_rect
*/

View File

@ -131,6 +131,8 @@ extern void WINPOS_SysCommandSizeMove( HWND hwnd, WPARAM wParam ) DECLSPEC_HIDDE
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 POINT map_dpi_point( POINT pt, UINT dpi_from, UINT dpi_to ) DECLSPEC_HIDDEN;
extern POINT point_win_to_thread_dpi( HWND hwnd, POINT pt ) 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,

View File

@ -446,6 +446,7 @@ static BOOL WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, BOOL *mirrored, POI
}
}
if (wndPtr && wndPtr != WND_DESKTOP) WIN_ReleasePtr( wndPtr );
offset = point_win_to_thread_dpi( hwndFrom, offset );
}
}
@ -460,15 +461,16 @@ static BOOL WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, BOOL *mirrored, POI
if (wndPtr == WND_OTHER_PROCESS) goto other_process;
if (wndPtr != WND_DESKTOP)
{
POINT pt = { 0, 0 };
if (wndPtr->dwExStyle & WS_EX_LAYOUTRTL)
{
mirror_to = TRUE;
offset.x -= wndPtr->client_rect.right - wndPtr->client_rect.left;
pt.x += wndPtr->client_rect.right - wndPtr->client_rect.left;
}
while (wndPtr->parent)
{
offset.x -= wndPtr->client_rect.left;
offset.y -= wndPtr->client_rect.top;
pt.x += wndPtr->client_rect.left;
pt.y += wndPtr->client_rect.top;
hwnd = wndPtr->parent;
WIN_ReleasePtr( wndPtr );
if (!(wndPtr = WIN_GetPtr( hwnd ))) break;
@ -481,6 +483,9 @@ static BOOL WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, BOOL *mirrored, POI
}
}
if (wndPtr && wndPtr != WND_DESKTOP) WIN_ReleasePtr( wndPtr );
pt = point_win_to_thread_dpi( hwndTo, pt );
offset.x -= pt.x;
offset.y -= pt.y;
}
}
@ -494,6 +499,7 @@ static BOOL WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, BOOL *mirrored, POI
{
req->from = wine_server_user_handle( hwndFrom );
req->to = wine_server_user_handle( hwndTo );
req->dpi = get_thread_dpi();
if ((ret = !wine_server_call_err( req )))
{
ret_offset->x = reply->x;

View File

@ -3743,7 +3743,7 @@ struct get_windows_offset_request
struct request_header __header;
user_handle_t from;
user_handle_t to;
char __pad_20[4];
int dpi;
};
struct get_windows_offset_reply
{
@ -6533,6 +6533,6 @@ union generic_reply
struct terminate_job_reply terminate_job_reply;
};
#define SERVER_PROTOCOL_VERSION 557
#define SERVER_PROTOCOL_VERSION 558
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -2685,6 +2685,7 @@ enum coords_relative
@REQ(get_windows_offset)
user_handle_t from; /* handle to the first window */
user_handle_t to; /* handle to the second window */
int dpi; /* DPI to map to, or zero for per-monitor DPI */
@REPLY
int x; /* x coordinate offset */
int y; /* y coordinate offset */

View File

@ -1786,6 +1786,7 @@ C_ASSERT( FIELD_OFFSET(struct set_window_text_request, handle) == 12 );
C_ASSERT( sizeof(struct set_window_text_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_windows_offset_request, from) == 12 );
C_ASSERT( FIELD_OFFSET(struct get_windows_offset_request, to) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_windows_offset_request, dpi) == 20 );
C_ASSERT( sizeof(struct get_windows_offset_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct get_windows_offset_reply, x) == 8 );
C_ASSERT( FIELD_OFFSET(struct get_windows_offset_reply, y) == 12 );

View File

@ -3259,6 +3259,7 @@ static void dump_get_windows_offset_request( const struct get_windows_offset_req
{
fprintf( stderr, " from=%08x", req->from );
fprintf( stderr, ", to=%08x", req->to );
fprintf( stderr, ", dpi=%d", req->dpi );
}
static void dump_get_windows_offset_reply( const struct get_windows_offset_reply *req )

View File

@ -630,6 +630,16 @@ static inline void inc_window_paint_count( struct window *win, int incr )
if (win->thread) inc_queue_paint_count( win->thread, incr );
}
/* map a point between different DPI scaling levels */
static void map_dpi_point( struct window *win, int *x, int *y, unsigned int from, unsigned int to )
{
if (!from) from = get_monitor_dpi( win );
if (!to) to = get_monitor_dpi( win );
if (from == to) return;
*x = scale_dpi( *x, from, to );
*y = scale_dpi( *y, from, to );
}
/* 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 )
{
@ -2401,38 +2411,30 @@ DECL_HANDLER(set_window_text)
DECL_HANDLER(get_windows_offset)
{
struct window *win;
int mirror_from = 0, mirror_to = 0;
int x, y, mirror_from = 0, mirror_to = 0;
reply->x = reply->y = 0;
if (req->from)
{
if (!(win = get_window( req->from ))) return;
if (win->ex_style & WS_EX_LAYOUTRTL)
{
mirror_from = 1;
reply->x += win->client_rect.right - win->client_rect.left;
}
while (win && !is_desktop_window(win))
{
reply->x += win->client_rect.left;
reply->y += win->client_rect.top;
win = win->parent;
}
if (win->ex_style & WS_EX_LAYOUTRTL) mirror_from = 1;
x = mirror_from ? win->client_rect.right - win->client_rect.left : 0;
y = 0;
client_to_screen( win, &x, &y );
map_dpi_point( win, &x, &y, win->dpi, req->dpi );
reply->x += x;
reply->y += y;
}
if (req->to)
{
if (!(win = get_window( req->to ))) return;
if (win->ex_style & WS_EX_LAYOUTRTL)
{
mirror_to = 1;
reply->x -= win->client_rect.right - win->client_rect.left;
}
while (win && !is_desktop_window(win))
{
reply->x -= win->client_rect.left;
reply->y -= win->client_rect.top;
win = win->parent;
}
if (win->ex_style & WS_EX_LAYOUTRTL) mirror_to = 1;
x = mirror_to ? win->client_rect.right - win->client_rect.left : 0;
y = 0;
client_to_screen( win, &x, &y );
map_dpi_point( win, &x, &y, win->dpi, req->dpi );
reply->x -= x;
reply->y -= y;
}
if (mirror_from) reply->x = -reply->x;
reply->mirror = mirror_from ^ mirror_to;