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