Alexandre Julliard : user32: Scale coordinates in MapWindowPoints() based on DPI awareness.
Alexandre Julliard
julliard at winehq.org
Fri Aug 24 13:59:15 CDT 2018
Module: wine
Branch: master
Commit: 8de1b2c2ceda0a69257f4390540e2239ec592272
URL: https://source.winehq.org/git/wine.git/?a=commit;h=8de1b2c2ceda0a69257f4390540e2239ec592272
Author: Alexandre Julliard <julliard at winehq.org>
Date: Fri Aug 24 12:12:44 2018 +0200
user32: Scale coordinates in MapWindowPoints() based on DPI awareness.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/user32/sysparams.c | 23 ++++++++++++++++++++
dlls/user32/win.h | 2 ++
dlls/user32/winpos.c | 12 ++++++++---
include/wine/server_protocol.h | 4 ++--
server/protocol.def | 1 +
server/request.h | 1 +
server/trace.c | 1 +
server/window.c | 48 ++++++++++++++++++++++--------------------
8 files changed, 64 insertions(+), 28 deletions(-)
diff --git a/dlls/user32/sysparams.c b/dlls/user32/sysparams.c
index 2dc5cb2..a971062 100644
--- a/dlls/user32/sysparams.c
+++ b/dlls/user32/sysparams.c
@@ -3222,6 +3222,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
*/
RECT map_dpi_rect( RECT rect, UINT dpi_from, UINT dpi_to )
diff --git a/dlls/user32/win.h b/dlls/user32/win.h
index 3fff0fc..b912ef8 100644
--- a/dlls/user32/win.h
+++ b/dlls/user32/win.h
@@ -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,
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index e26dc6e..1dd9c12 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -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;
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 9c5deca..a888a63 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -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 */
diff --git a/server/protocol.def b/server/protocol.def
index 43f5f01..f1f4709 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -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 */
diff --git a/server/request.h b/server/request.h
index c3aed96..ddf8a68 100644
--- a/server/request.h
+++ b/server/request.h
@@ -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 );
diff --git a/server/trace.c b/server/trace.c
index 1d773fb..6886688 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -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 )
diff --git a/server/window.c b/server/window.c
index c286a0a..e45cf38 100644
--- a/server/window.c
+++ b/server/window.c
@@ -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;
More information about the wine-cvs
mailing list