win32u: Move NtUserMenuItemFromPoint implementation from user32.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
This commit is contained in:
Jacek Caban 2022-06-11 02:14:02 +02:00 committed by Alexandre Julliard
parent 987d637e31
commit 95b76f5101
7 changed files with 110 additions and 20 deletions

View file

@ -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 );
}

View file

@ -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 )

View file

@ -151,6 +151,7 @@ static void * const syscalls[] =
NtUserInternalGetWindowText,
NtUserKillTimer,
NtUserLockWindowUpdate,
NtUserMenuItemFromPoint,
NtUserNotifyWinEvent,
NtUserOpenDesktop,
NtUserOpenInputDesktop,

View file

@ -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

View file

@ -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 ) \

View file

@ -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 );

View file

@ -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 );