[PATCH 1/8] win32u: Move NtUserMenuItemFromPoint implementation from user32.
Jacek Caban
wine at gitlab.winehq.org
Wed Jun 15 06:44:32 CDT 2022
From: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
---
dlls/user32/menu.c | 14 +-----
dlls/win32u/menu.c | 101 +++++++++++++++++++++++++++++++++++++---
dlls/win32u/syscall.c | 1 +
dlls/win32u/win32u.spec | 2 +-
dlls/wow64win/syscall.h | 1 +
dlls/wow64win/user.c | 10 ++++
include/ntuser.h | 1 +
7 files changed, 110 insertions(+), 20 deletions(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 73aee6b849d..a06ef21c634 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -4321,19 +4321,9 @@ DWORD WINAPI GetMenuContextHelpId( HMENU menu )
/**********************************************************************
* MenuItemFromPoint (USER32.@)
*/
-INT WINAPI MenuItemFromPoint(HWND hWnd, HMENU hMenu, POINT ptScreen)
+INT WINAPI MenuItemFromPoint( HWND hwnd, HMENU menu, POINT pt )
{
- POPUPMENU *menu = grab_menu_ptr(hMenu);
- UINT pos;
-
- /*FIXME: Do we have to handle hWnd here? */
- if (!menu) return -1;
-
- if (MENU_FindItemByCoords( menu, ptScreen, &pos ) != ht_item)
- pos = -1;
-
- release_menu_ptr(menu);
- return pos;
+ return NtUserMenuItemFromPoint( hwnd, menu, pt.x, pt.y );
}
diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c
index 8367af32395..d84af186da9 100644
--- a/dlls/win32u/menu.c
+++ b/dlls/win32u/menu.c
@@ -40,6 +40,15 @@ struct accelerator
ACCEL table[1];
};
+enum hittest
+{
+ ht_nowhere, /* outside the menu */
+ ht_border, /* anywhere that's not an item or a scroll arrow */
+ ht_item, /* a menu item */
+ ht_scroll_up, /* scroll up arrow */
+ ht_scroll_down /* scroll down arrow */
+};
+
/* maximum allowed depth of any branch in the menu tree.
* This value is slightly larger than in windows (25) to
* stay on the safe side. */
@@ -424,6 +433,76 @@ static UINT find_submenu( HMENU *handle_ptr, HMENU target )
return NO_SELECTED_ITEM;
}
+/* Adjust menu item rectangle according to scrolling state */
+static void adjust_menu_item_rect( const POPUPMENU *menu, RECT *rect )
+{
+ INT scroll_offset = menu->bScrolling ? menu->nScrollPos : 0;
+ OffsetRect( rect, menu->items_rect.left, menu->items_rect.top - scroll_offset );
+}
+
+/***********************************************************************
+ * find_item_by_coords
+ *
+ * Find the item at the specified coordinates (screen coords). Does
+ * not work for child windows and therefore should not be called for
+ * an arbitrary system menu.
+ *
+ * Returns a hittest code. *pos will contain the position of the
+ * item or NO_SELECTED_ITEM. If the hittest code is ht_scroll_up
+ * or ht_scroll_down then *pos will contain the position of the
+ * item that's just outside the items_rect - ie, the one that would
+ * be scrolled completely into view.
+ */
+static enum hittest find_item_by_coords( const POPUPMENU *menu, POINT pt, UINT *pos )
+{
+ enum hittest ht = ht_border;
+ MENUITEM *item;
+ RECT rect;
+ UINT i;
+
+ *pos = NO_SELECTED_ITEM;
+
+ if (!get_window_rect( menu->hWnd, &rect, get_thread_dpi() ) || !PtInRect( &rect, pt ))
+ return ht_nowhere;
+
+ if (get_window_long( menu->hWnd, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL) pt.x = rect.right - 1 - pt.x;
+ else pt.x -= rect.left;
+ pt.y -= rect.top;
+
+ if (!PtInRect( &menu->items_rect, pt ))
+ {
+ if (!menu->bScrolling || pt.x < menu->items_rect.left || pt.x >= menu->items_rect.right)
+ return ht_border;
+
+ /* On a scroll arrow. Update pt so that it points to the item just outside items_rect */
+ if (pt.y < menu->items_rect.top)
+ {
+ ht = ht_scroll_up;
+ pt.y = menu->items_rect.top - 1;
+ }
+ else
+ {
+ ht = ht_scroll_down;
+ pt.y = menu->items_rect.bottom;
+ }
+ }
+
+ item = menu->items;
+ for (i = 0; i < menu->nItems; i++, item++)
+ {
+ rect = item->rect;
+ adjust_menu_item_rect( menu, &rect );
+ if (PtInRect( &rect, pt ))
+ {
+ *pos = i;
+ if (ht != ht_scroll_up && ht != ht_scroll_down) ht = ht_item;
+ break;
+ }
+ }
+
+ return ht;
+}
+
/* see GetMenu */
HMENU get_menu( HWND hwnd )
{
@@ -1040,6 +1119,21 @@ static HMENU get_sub_menu( HMENU handle, INT pos )
return submenu;
}
+/**********************************************************************
+ * NtUserMenuItemFromPoint (win32u.@)
+ */
+INT WINAPI NtUserMenuItemFromPoint( HWND hwnd, HMENU handle, int x, int y )
+{
+ POINT pt = { .x = x, .y = y };
+ POPUPMENU *menu;
+ UINT pos;
+
+ if (!(menu = grab_menu_ptr(handle))) return -1;
+ if (find_item_by_coords( menu, pt, &pos ) != ht_item) pos = -1;
+ release_menu_ptr(menu);
+ return pos;
+}
+
/**********************************************************************
* NtUserGetSystemMenu (win32u.@)
*/
@@ -1823,13 +1917,6 @@ got_bitmap:
NtGdiDeleteObjectApp( mem_hdc );
}
-/* Adjust menu item rectangle according to scrolling state */
-static void adjust_menu_item_rect( const POPUPMENU *menu, RECT *rect )
-{
- INT scroll_offset = menu->bScrolling ? menu->nScrollPos : 0;
- OffsetRect( rect, menu->items_rect.left, menu->items_rect.top - scroll_offset );
-}
-
/* Draw a single menu item */
static void draw_menu_item( HWND hwnd, POPUPMENU *menu, HWND owner, HDC hdc,
MENUITEM *item, BOOL menu_bar, UINT odaction )
diff --git a/dlls/win32u/syscall.c b/dlls/win32u/syscall.c
index ac13580308d..a926049f0ed 100644
--- a/dlls/win32u/syscall.c
+++ b/dlls/win32u/syscall.c
@@ -151,6 +151,7 @@ static void * const syscalls[] =
NtUserInternalGetWindowText,
NtUserKillTimer,
NtUserLockWindowUpdate,
+ NtUserMenuItemFromPoint,
NtUserNotifyWinEvent,
NtUserOpenDesktop,
NtUserOpenInputDesktop,
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec
index 4dfebaa9d2d..f296f162fff 100644
--- a/dlls/win32u/win32u.spec
+++ b/dlls/win32u/win32u.spec
@@ -1078,7 +1078,7 @@
@ stub NtUserMapPointsByVisualIdentifier
@ stdcall NtUserMapVirtualKeyEx(long long long)
@ stub NtUserMarkWindowForRawMouse
-@ stub NtUserMenuItemFromPoint
+@ stdcall -syscall NtUserMenuItemFromPoint(long long long long)
@ stdcall NtUserMessageCall(long long long long long long long)
@ stub NtUserMinInitialize
@ stub NtUserMinMaximize
diff --git a/dlls/wow64win/syscall.h b/dlls/wow64win/syscall.h
index e30d367cda7..7c9627a6121 100644
--- a/dlls/wow64win/syscall.h
+++ b/dlls/wow64win/syscall.h
@@ -138,6 +138,7 @@
SYSCALL_ENTRY( NtUserInternalGetWindowText ) \
SYSCALL_ENTRY( NtUserKillTimer ) \
SYSCALL_ENTRY( NtUserLockWindowUpdate ) \
+ SYSCALL_ENTRY( NtUserMenuItemFromPoint ) \
SYSCALL_ENTRY( NtUserNotifyWinEvent ) \
SYSCALL_ENTRY( NtUserOpenDesktop ) \
SYSCALL_ENTRY( NtUserOpenInputDesktop ) \
diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c
index c2d134626f1..51c0a5d0ed8 100644
--- a/dlls/wow64win/user.c
+++ b/dlls/wow64win/user.c
@@ -736,6 +736,16 @@ NTSTATUS WINAPI wow64_NtUserGetMenuItemRect( UINT *args )
return NtUserGetMenuItemRect( hwnd, handle, item, rect );
}
+NTSTATUS WINAPI wow64_NtUserMenuItemFromPoint( UINT *args )
+{
+ HWND hwnd = get_handle( &args );
+ HMENU handle = get_handle( &args );
+ int x = get_ulong( &args );
+ int y = get_ulong( &args );
+
+ return NtUserMenuItemFromPoint( hwnd, handle, x, y );
+}
+
NTSTATUS WINAPI wow64_NtUserSetMenuContextHelpId( UINT *args )
{
HMENU menu = get_handle( &args );
diff --git a/include/ntuser.h b/include/ntuser.h
index 5f744c24906..0415ba076a5 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -620,6 +620,7 @@ BOOL WINAPI NtUserIsClipboardFormatAvailable( UINT format );
BOOL WINAPI NtUserKillTimer( HWND hwnd, UINT_PTR id );
BOOL WINAPI NtUserLockWindowUpdate( HWND hwnd );
UINT WINAPI NtUserMapVirtualKeyEx( UINT code, UINT type, HKL layout );
+INT WINAPI NtUserMenuItemFromPoint( HWND hwnd, HMENU handle, int x, int y );
LRESULT WINAPI NtUserMessageCall( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
void *result_info, DWORD type, BOOL ansi );
BOOL WINAPI NtUserMoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy, BOOL repaint );
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/250
More information about the wine-devel
mailing list