BMenu: Fix crash and keyboard navigation on 'recent items' menus

* Prevents crash mentioned in Trac, but also enables keyboard navigation
  to 'recent items' menus such as "Open files..." in MediaPlayer and DiskProbe
* Check selected menu and submenu exist in menu tracking thread before accessing
* Update BMenu::AttachedToWindow to pass in keydown param to _AddDynamicItems

Fixes #9251
Change-Id: I3031b8e9c1b9dd4ef1187c5a6b8ab7925e3496d2
This commit is contained in:
David Murphy
2018-07-13 00:16:58 +00:00
committed by waddlesplash
parent e042d58907
commit e4433ad0fa
+19 -2
View File
@@ -388,7 +388,14 @@ BMenu::AttachedToWindow()
_GetOptionKey(sOptionKey); _GetOptionKey(sOptionKey);
_GetMenuKey(sMenuKey); _GetMenuKey(sMenuKey);
fAttachAborted = _AddDynamicItems(); // The menu should be added to the menu hierarchy and made visible if:
// * the mouse is over the menu,
// * the user has requested the menu via the keyboard.
// So if we don't pass keydown in here, keyboard navigation breaks since
// fAttachAborted will return false if the mouse isn't over the menu
bool keyDown = Supermenu() != NULL
? Supermenu()->fState == MENU_STATE_KEY_TO_SUBMENU : false;
fAttachAborted = _AddDynamicItems(keyDown);
if (!fAttachAborted) { if (!fAttachAborted) {
_CacheFontInfo(); _CacheFontInfo();
@@ -1661,8 +1668,16 @@ BMenu::_Track(int* action, long start)
// that our window gets any update message to // that our window gets any update message to
// redraw itself // redraw itself
UnlockLooper(); UnlockLooper();
int submenuAction = MENU_STATE_TRACKING;
// To prevent NULL access violation, ensure a menu has actually
// been selected and that it has a submenu. Because keyboard and
// mouse interactions set selected items differently, the menu
// tracking thread needs to be careful in triggering the navigation
// to the submenu.
if (fSelected != NULL) {
BMenu* submenu = fSelected->Submenu(); BMenu* submenu = fSelected->Submenu();
int submenuAction = MENU_STATE_TRACKING;
if (submenu != NULL) {
submenu->_SetStickyMode(_IsStickyMode()); submenu->_SetStickyMode(_IsStickyMode());
// The following call blocks until the submenu // The following call blocks until the submenu
@@ -1686,6 +1701,8 @@ BMenu::_Track(int* action, long start)
fState = MENU_STATE_TRACKING; fState = MENU_STATE_TRACKING;
} else } else
fState = MENU_STATE_TRACKING; fState = MENU_STATE_TRACKING;
}
}
if (!LockLooper()) if (!LockLooper())
break; break;
} else if ((item = _HitTestItems(location, B_ORIGIN)) != NULL) { } else if ((item = _HitTestItems(location, B_ORIGIN)) != NULL) {