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