diff --git a/accessible/src/base/FocusManager.cpp b/accessible/src/base/FocusManager.cpp index 792784fb9578..0b7e03bc1c3e 100644 --- a/accessible/src/base/FocusManager.cpp +++ b/accessible/src/base/FocusManager.cpp @@ -5,6 +5,7 @@ #include "FocusManager.h" #include "Accessible-inl.h" +#include "AccIterator.h" #include "DocAccessible-inl.h" #include "nsAccessibilityService.h" #include "nsAccUtils.h" @@ -288,8 +289,30 @@ FocusManager::ProcessFocusEvent(AccEvent* aEvent) // Fire menu start/end events for ARIA menus. if (target->ARIARole() == roles::MENUITEM) { // The focus was moved into menu. - Accessible* ARIAMenubar = - nsAccUtils::GetAncestorWithRole(target, roles::MENUBAR); + Accessible* ARIAMenubar = nullptr; + Accessible* child = target; + Accessible* parent = child->Parent(); + while (parent) { + nsRoleMapEntry* roleMap = parent->ARIARoleMap(); + if (roleMap) { + if (roleMap->Is(nsGkAtoms::menubar)) { + ARIAMenubar = parent; + break; + } + + // Go up in the parent chain of the menu hierarchy. + if (roleMap->Is(nsGkAtoms::menuitem) || roleMap->Is(nsGkAtoms::menu)) { + child = parent; + parent = child->Parent(); + continue; + } + } + + // If no required context role then check aria-owns relation. + RelatedAccIterator iter(child->Document(), child->GetContent(), + nsGkAtoms::aria_owns); + parent = iter.Next(); + } if (ARIAMenubar != mActiveARIAMenubar) { // Leaving ARIA menu. Fire menu_end event on current menubar. diff --git a/accessible/src/base/nsAccUtils.cpp b/accessible/src/base/nsAccUtils.cpp index 3b1bf2447022..4dcc70b08afa 100644 --- a/accessible/src/base/nsAccUtils.cpp +++ b/accessible/src/base/nsAccUtils.cpp @@ -210,22 +210,6 @@ nsAccUtils::GetARIAToken(dom::Element* aElement, nsIAtom* aAttr) return nullptr; } -Accessible* -nsAccUtils::GetAncestorWithRole(Accessible* aDescendant, uint32_t aRole) -{ - Accessible* document = aDescendant->Document(); - Accessible* parent = aDescendant; - while ((parent = parent->Parent())) { - uint32_t testRole = parent->Role(); - if (testRole == aRole) - return parent; - - if (parent == document) - break; - } - return nullptr; -} - Accessible* nsAccUtils::GetSelectableContainer(Accessible* aAccessible, uint64_t aState) { diff --git a/accessible/src/base/nsAccUtils.h b/accessible/src/base/nsAccUtils.h index 2f09a4f88bdc..6b939d2d9ec5 100644 --- a/accessible/src/base/nsAccUtils.h +++ b/accessible/src/base/nsAccUtils.h @@ -116,17 +116,6 @@ public: return GetAccService()->GetDocAccessible(docShell->GetPresShell()); } - /** - * Return ancestor in this document with the given role if it exists. - * - * @param aDescendant [in] descendant to start search with - * @param aRole [in] role to find matching ancestor for - * @return the ancestor accessible with the given role, or - * nullptr if no match is found - */ - static Accessible* GetAncestorWithRole(Accessible* aDescendant, - uint32_t aRole); - /** * Return single or multi selectable container for the given item. * diff --git a/accessible/tests/mochitest/events/test_aria_menu.html b/accessible/tests/mochitest/events/test_aria_menu.html index a361a72013c9..0259c5f57b7a 100644 --- a/accessible/tests/mochitest/events/test_aria_menu.html +++ b/accessible/tests/mochitest/events/test_aria_menu.html @@ -165,6 +165,10 @@ gQueue.push(new focusInsideMenu("menu-edit", "menubar")); gQueue.push(new blurMenu("menubar")); + gQueue.push(new focusMenu("menubar3", "mb3-mi-outside")); + gQueue.push(new showMenu("mb4-menu", document, kViaDisplayStyle)); + gQueue.push(new focusMenu("menubar4", "mb4-item1")); + gQueue.invoke(); // Will call SimpleTest.finish(); } @@ -178,22 +182,27 @@ - Mozilla Bug 606207 + Bug 606207 - Mozilla Bug 614829 + Bug 614829 - Mozilla Bug 615189 + Bug 615189 - Mozilla Bug 673958 + Bug 673958 + + + Bug 933322
@@ -227,6 +236,18 @@ + + +