Module: wine Branch: master Commit: c45af8f3533e6418eb6cedb786031b40125b8831 URL: https://source.winehq.org/git/wine.git/?a=commit;h=c45af8f3533e6418eb6cedb78...
Author: Jacek Caban jacek@codeweavers.com Date: Thu Mar 10 14:31:55 2022 +0100
win32u: Move NtUserWindowFromPoint implementation from user32.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Huw Davies huw@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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_ */