Jacek Caban : win32u: Move NtUserWindowFromPoint implementation from user32.

Alexandre Julliard julliard at winehq.org
Thu Mar 10 16:10:15 CST 2022


Module: wine
Branch: master
Commit: c45af8f3533e6418eb6cedb786031b40125b8831
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=c45af8f3533e6418eb6cedb786031b40125b8831

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu Mar 10 14:31:55 2022 +0100

win32u: Move NtUserWindowFromPoint implementation from user32.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/user32/winpos.c         |   3 +-
 dlls/win32u/gdiobj.c         |   1 +
 dlls/win32u/win32u.spec      |   2 +-
 dlls/win32u/win32u_private.h |   1 +
 dlls/win32u/window.c         | 107 ++++++++++++++++++++++++++++++++++++++++++-
 dlls/win32u/wrappers.c       |   6 +++
 include/ntuser.h             |   1 +
 7 files changed, 116 insertions(+), 5 deletions(-)

diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index d144c53f4e4..2d2c83f503c 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -233,8 +233,7 @@ HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
  */
 HWND WINAPI WindowFromPoint( POINT pt )
 {
-    INT hittest;
-    return WINPOS_WindowFromPoint( 0, pt, &hittest );
+    return NtUserWindowFromPoint( pt.x, pt.y );
 }
 
 
diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c
index bb4daf54279..e5c320f8bcc 100644
--- a/dlls/win32u/gdiobj.c
+++ b/dlls/win32u/gdiobj.c
@@ -1198,6 +1198,7 @@ static struct unix_funcs unix_funcs =
     NtUserUnregisterClass,
     NtUserUnregisterHotKey,
     NtUserVkKeyScanEx,
+    NtUserWindowFromPoint,
 
     GetDCHook,
     SetDCHook,
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec
index 9e426b40e48..f011feb3ec7 100644
--- a/dlls/win32u/win32u.spec
+++ b/dlls/win32u/win32u.spec
@@ -1311,7 +1311,7 @@
 @ stub NtUserWaitMessage
 @ stub NtUserWindowFromDC
 @ stub NtUserWindowFromPhysicalPoint
-@ stub NtUserWindowFromPoint
+@ stdcall NtUserWindowFromPoint(long long)
 @ stub NtUserYieldTask
 @ stub NtValidateCompositionSurfaceHandle
 @ stub NtVisualCaptureBits
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index a3fbf8a8a4c..9db06e1dd76 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -247,6 +247,7 @@ struct unix_funcs
                                                struct client_menu_name *client_menu_name );
     BOOL     (WINAPI *pNtUserUnregisterHotKey)( HWND hwnd, INT id );
     WORD     (WINAPI *pNtUserVkKeyScanEx)( WCHAR chr, HKL layout );
+    HWND     (WINAPI *pNtUserWindowFromPoint)( LONG x, LONG y );
 
     /* Wine-specific functions */
     DWORD_PTR (WINAPI *pGetDCHook)( HDC hdc, DCHOOKPROC *proc );
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c
index e3564646d0a..e5907e8422d 100644
--- a/dlls/win32u/window.c
+++ b/dlls/win32u/window.c
@@ -1257,8 +1257,8 @@ int WINAPI NtUserSetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw )
 
     if (ret)
     {
-        UINT swp_flags = SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_FRAMECHANGED|
-            SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE;
+        UINT swp_flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED |
+            SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE;
         if (!redraw) swp_flags |= SWP_NOREDRAW;
         user_driver->pSetWindowRgn( hwnd, hrgn, redraw );
         NtUserSetWindowPos( hwnd, 0, 0, 0, 0, 0, swp_flags );
@@ -1309,6 +1309,109 @@ BOOL WINAPI NtUserGetLayeredWindowAttributes( HWND hwnd, COLORREF *key, BYTE *al
     return ret;
 }
 
+/***********************************************************************
+ *           list_children_from_point
+ *
+ * Get the list of children that can contain point from the server.
+ * Point is in screen coordinates.
+ * Returned list must be freed by caller.
+ */
+static HWND *list_children_from_point( HWND hwnd, POINT pt )
+{
+    int i, size = 128;
+    HWND *list;
+
+    for (;;)
+    {
+        int count = 0;
+
+        if (!(list = malloc( size * sizeof(HWND) ))) break;
+
+        SERVER_START_REQ( get_window_children_from_point )
+        {
+            req->parent = wine_server_user_handle( hwnd );
+            req->x = pt.x;
+            req->y = pt.y;
+            req->dpi = get_thread_dpi();
+            wine_server_set_reply( req, list, (size-1) * sizeof(user_handle_t) );
+            if (!wine_server_call( req )) count = reply->count;
+        }
+        SERVER_END_REQ;
+        if (count && count < size)
+        {
+            /* start from the end since HWND is potentially larger than user_handle_t */
+            for (i = count - 1; i >= 0; i--)
+                list[i] = wine_server_ptr_handle( ((user_handle_t *)list)[i] );
+            list[count] = 0;
+            return list;
+        }
+        free( list );
+        if (!count) break;
+        size = count + 1;  /* restart with a large enough buffer */
+    }
+    return NULL;
+}
+
+/***********************************************************************
+ *           window_from_point
+ *
+ * Find the window and hittest for a given point.
+ */
+static HWND window_from_point( HWND hwnd, POINT pt, INT *hittest )
+{
+    int i, res;
+    HWND ret, *list;
+    POINT win_pt;
+
+    if (!hwnd) hwnd = get_desktop_window();
+
+    *hittest = HTNOWHERE;
+
+    if (!(list = list_children_from_point( hwnd, pt ))) return 0;
+
+    /* now determine the hittest */
+
+    for (i = 0; list[i]; i++)
+    {
+        LONG style = get_window_long( list[i], GWL_STYLE );
+
+        /* If window is minimized or disabled, return at once */
+        if (style & WS_DISABLED)
+        {
+            *hittest = HTERROR;
+            break;
+        }
+        /* Send WM_NCCHITTEST (if same thread) */
+        if (!is_current_thread_window( list[i] ))
+        {
+            *hittest = HTCLIENT;
+            break;
+        }
+        win_pt = map_dpi_point( pt, get_thread_dpi(), get_dpi_for_window( list[i] ));
+        res = send_message( list[i], WM_NCHITTEST, 0, MAKELPARAM( win_pt.x, win_pt.y ));
+        if (res != HTTRANSPARENT)
+        {
+            *hittest = res;  /* Found the window */
+            break;
+        }
+        /* continue search with next window in z-order */
+    }
+    ret = list[i];
+    free( list );
+    TRACE( "scope %p (%d,%d) returning %p\n", hwnd, pt.x, pt.y, ret );
+    return ret;
+}
+
+/*******************************************************************
+ *           NtUserWindowFromPoint (win32u.@)
+ */
+HWND WINAPI NtUserWindowFromPoint( LONG x, LONG y )
+{
+    POINT pt = { .x = x, .y = y };
+    INT hittest;
+    return window_from_point( 0, pt, &hittest );
+}
+
 /*****************************************************************************
  *           NtUserBuildHwndList (win32u.@)
  */
diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c
index 99c01c326c3..b1c86949db2 100644
--- a/dlls/win32u/wrappers.c
+++ b/dlls/win32u/wrappers.c
@@ -1002,6 +1002,12 @@ WORD WINAPI NtUserVkKeyScanEx( WCHAR chr, HKL layout )
     return unix_funcs->pNtUserVkKeyScanEx( chr, layout );
 }
 
+HWND WINAPI NtUserWindowFromPoint( LONG x, LONG y )
+{
+    if (!unix_funcs) return 0;
+    return unix_funcs->pNtUserWindowFromPoint( x, y );
+}
+
 DWORD_PTR WINAPI GetDCHook( HDC hdc, DCHOOKPROC *proc )
 {
     if (!unix_funcs) return 0;
diff --git a/include/ntuser.h b/include/ntuser.h
index 3c5c73f5f48..e6c724fa683 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -389,5 +389,6 @@ BOOL    WINAPI NtUserUnregisterClass( UNICODE_STRING *name, HINSTANCE instance,
 BOOL    WINAPI NtUserUnregisterHotKey( HWND hwnd, INT id );
 WORD    WINAPI NtUserVkKeyScanEx( WCHAR chr, HKL layout );
 DWORD   WINAPI NtUserWaitForInputIdle( HANDLE process, DWORD timeout, BOOL wow );
+HWND    WINAPI NtUserWindowFromPoint( LONG x, LONG y );
 
 #endif /* _NTUSER_ */




More information about the wine-cvs mailing list