[PATCH 1/3] user32: Don't finish tracking when the menu borders or scroll arrows are clicked.
Huw Davies
huw at codeweavers.com
Thu Mar 30 04:58:31 CDT 2017
Signed-off-by: Huw Davies <huw at codeweavers.com>
---
dlls/user32/menu.c | 119 +++++++++++++++++++++++++++++++++++------------------
1 file changed, 78 insertions(+), 41 deletions(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 79bef6428f..dd6206361a 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -665,6 +665,14 @@ MENU_AdjustMenuItemRect(const POPUPMENU *menu, LPRECT rect)
OffsetRect( rect, menu->items_rect.left, menu->items_rect.top - scroll_offset );
}
+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 */
+};
/***********************************************************************
* MENU_FindItemByCoords
@@ -672,30 +680,61 @@ MENU_AdjustMenuItemRect(const POPUPMENU *menu, LPRECT rect)
* 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 MENUITEM *MENU_FindItemByCoords( const POPUPMENU *menu,
- POINT pt, UINT *pos )
+static enum hittest MENU_FindItemByCoords( const POPUPMENU *menu, POINT pt, UINT *pos )
{
MENUITEM *item;
UINT i;
RECT rect;
+ enum hittest ht = ht_border;
+
+ *pos = NO_SELECTED_ITEM;
+
+ if (!GetWindowRect(menu->hWnd, &rect) || !PtInRect(&rect, pt))
+ return ht_nowhere;
- if (!GetWindowRect(menu->hWnd, &rect)) return NULL;
if (GetWindowLongW( 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;
MENU_AdjustMenuItemRect(menu, &rect);
- if (PtInRect(&rect, pt))
- {
- if (pos) *pos = i;
- return item;
- }
+ if (PtInRect(&rect, pt))
+ {
+ *pos = i;
+ if (ht != ht_scroll_up && ht != ht_scroll_down) ht = ht_item;
+ break;
+ }
}
- return NULL;
+
+ return ht;
}
@@ -2549,29 +2588,28 @@ static BOOL MENU_ButtonDown( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags )
if (hPtMenu)
{
- UINT id = 0;
- POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
- MENUITEM *item;
+ UINT pos;
+ POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
+ enum hittest ht = ht_nowhere;
- if( IS_SYSTEM_MENU(ptmenu) )
- item = ptmenu->items;
- else
- item = MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
+ if( IS_SYSTEM_MENU(ptmenu) )
+ pos = 0;
+ else
+ ht = MENU_FindItemByCoords( ptmenu, pmt->pt, &pos );
- if( item )
- {
- if( ptmenu->FocusedItem != id )
- MENU_SwitchTracking( pmt, hPtMenu, id, wFlags );
+ if (pos != NO_SELECTED_ITEM)
+ {
+ if (ptmenu->FocusedItem != pos)
+ MENU_SwitchTracking( pmt, hPtMenu, pos, wFlags );
- /* If the popup menu is not already "popped" */
- if(!(item->fState & MF_MOUSESELECT ))
- {
- pmt->hCurrentMenu = MENU_ShowSubPopup( pmt->hOwnerWnd, hPtMenu, FALSE, wFlags );
- }
+ /* If the popup menu is not already "popped" */
+ if (!(ptmenu->items[pos].fState & MF_MOUSESELECT))
+ pmt->hCurrentMenu = MENU_ShowSubPopup( pmt->hOwnerWnd, hPtMenu, FALSE, wFlags );
+ }
- return TRUE;
- }
- /* Else the click was on the menu bar, finish the tracking */
+ /* A click on an item or anywhere on a popup keeps tracking going */
+ if (ht == ht_item || ((ptmenu->wFlags & MF_POPUP) && ht != ht_nowhere))
+ return TRUE;
}
return FALSE;
}
@@ -2590,20 +2628,19 @@ static INT MENU_ButtonUp( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags)
if (hPtMenu)
{
- UINT id = 0;
+ UINT pos;
POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
- MENUITEM *item;
if( IS_SYSTEM_MENU(ptmenu) )
- item = ptmenu->items;
- else
- item = MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
+ pos = 0;
+ else if (MENU_FindItemByCoords( ptmenu, pmt->pt, &pos ) != ht_item)
+ pos = NO_SELECTED_ITEM;
- if( item && (ptmenu->FocusedItem == id ))
+ if (pos != NO_SELECTED_ITEM && (ptmenu->FocusedItem == pos))
{
- debug_print_menuitem ("FocusedItem: ", item, "");
+ debug_print_menuitem ("FocusedItem: ", &ptmenu->items[pos], "");
- if( !(item->fType & MF_POPUP) )
+ if (!(ptmenu->items[pos].fType & MF_POPUP))
{
INT executedMenuId = MENU_ExecFocusedItem( pmt, hPtMenu, wFlags);
if (executedMenuId == -1 || executedMenuId == -2) return -1;
@@ -2638,8 +2675,8 @@ static BOOL MENU_MouseMove( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags )
ptmenu = MENU_GetMenu( hPtMenu );
if( IS_SYSTEM_MENU(ptmenu) )
id = 0;
- else
- MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
+ else if (MENU_FindItemByCoords( ptmenu, pmt->pt, &id ) != ht_item)
+ id = NO_SELECTED_ITEM;
}
if( id == NO_SELECTED_ITEM )
@@ -2650,8 +2687,8 @@ static BOOL MENU_MouseMove( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags )
}
else if( ptmenu->FocusedItem != id )
{
- MENU_SwitchTracking( pmt, hPtMenu, id, wFlags );
- pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hPtMenu, FALSE, wFlags);
+ MENU_SwitchTracking( pmt, hPtMenu, id, wFlags );
+ pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hPtMenu, FALSE, wFlags);
}
return TRUE;
}
@@ -5254,7 +5291,7 @@ INT WINAPI MenuItemFromPoint(HWND hWnd, HMENU hMenu, POINT ptScreen)
/*FIXME: Do we have to handle hWnd here? */
if (!menu) return -1;
- if (!MENU_FindItemByCoords(menu, ptScreen, &pos)) return -1;
+ if (MENU_FindItemByCoords( menu, ptScreen, &pos ) != ht_item) return -1;
return pos;
}
--
2.12.0
More information about the wine-patches
mailing list