зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1686164: Implement ignoreWithParent for context menu items and submenus. r=eeejay
Differential Revision: https://phabricator.services.mozilla.com/D101652
This commit is contained in:
Родитель
21d7cbaac5
Коммит
1baf91ec07
|
@ -87,10 +87,10 @@
|
|||
- (NSString*)moxLabel;
|
||||
|
||||
// override
|
||||
- (NSArray*)moxChildren;
|
||||
- (NSArray*)moxVisibleChildren;
|
||||
|
||||
// override
|
||||
- (NSArray*)moxVisibleChildren;
|
||||
- (BOOL)moxIgnoreWithParent:(mozAccessible*)parent;
|
||||
|
||||
// override
|
||||
- (id)moxTitleUIElement;
|
||||
|
@ -101,6 +101,8 @@
|
|||
// override
|
||||
- (void)expire;
|
||||
|
||||
- (BOOL)isOpened;
|
||||
|
||||
@end
|
||||
|
||||
@interface mozMenuItemAccessible : mozSelectableChildAccessible
|
||||
|
@ -108,6 +110,9 @@
|
|||
// override
|
||||
- (NSString*)moxLabel;
|
||||
|
||||
// override
|
||||
- (BOOL)moxIgnoreWithParent:(mozAccessible*)parent;
|
||||
|
||||
// override
|
||||
- (NSString*)moxMenuItemMarkChar;
|
||||
|
||||
|
|
|
@ -154,25 +154,36 @@ using namespace mozilla::a11y;
|
|||
return @"";
|
||||
}
|
||||
|
||||
- (NSArray*)moxChildren {
|
||||
// We differ from Webkit and Apple-native menus here; they expose
|
||||
// all children regardless of whether or not the menu is open.
|
||||
// In testing, VoiceOver doesn't seem to actually care what happens
|
||||
// here as long as AXVisibleChildren is exposed correctly, so
|
||||
// we expose children only when the menu is open to avoid
|
||||
// changing ignoreWithParent/ignoreChild and/or isAccessibilityElement
|
||||
if (mIsOpened) {
|
||||
return [super moxChildren];
|
||||
- (BOOL)moxIgnoreWithParent:(mozAccessible*)parent {
|
||||
// This helps us generate the correct moxChildren array for
|
||||
// a sub menu -- that returned array should contain all
|
||||
// menu items, regardless of if they are visible or not.
|
||||
// Because moxChildren does ignore filtering, and because
|
||||
// our base ignore method filters out invisible accessibles,
|
||||
// we override this method.
|
||||
if ([parent geckoAccessible].Role() == roles::PARENT_MENUITEM) {
|
||||
// We are a submenu. If our parent menu item is in an open menu
|
||||
// we should not be ignored
|
||||
id grandparent = [parent moxUnignoredParent];
|
||||
if (grandparent && [grandparent isKindOfClass:[mozMenuAccessible class]]) {
|
||||
mozMenuAccessible* parentMenu = (mozMenuAccessible*)grandparent;
|
||||
if ([parentMenu isOpened]) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
|
||||
// Otherwise, we call into our superclass's ignore method
|
||||
// to handle menus that are not submenus
|
||||
return [super moxIgnoreWithParent:parent];
|
||||
}
|
||||
|
||||
- (NSArray*)moxVisibleChildren {
|
||||
// VO expects us to expose two lists of children on menus: all children
|
||||
// (done above in moxChildren), and children which are visible (here).
|
||||
// In our code, these are essentially the same list, since at the time of
|
||||
// wiritng we filter for visibility in isAccessibilityElement before
|
||||
// passing anything to VO.
|
||||
// (done in moxChildren), and children which are visible (here).
|
||||
// We implement ignoreWithParent for both menus and menu items
|
||||
// to ensure moxChildren returns a complete list of children regardless
|
||||
// of visibility, see comments in those methods for additional info.
|
||||
return [[self moxChildren]
|
||||
filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(
|
||||
mozAccessible* child,
|
||||
|
@ -188,8 +199,7 @@ using namespace mozilla::a11y;
|
|||
|
||||
- (id)moxTitleUIElement {
|
||||
id parent = [self moxUnignoredParent];
|
||||
if ([parent isKindOfClass:[mozAccessible class]] &&
|
||||
[parent geckoAccessible].Role() == roles::PARENT_MENUITEM) {
|
||||
if ([parent isKindOfClass:[mozAccessible class]]) {
|
||||
return parent;
|
||||
}
|
||||
|
||||
|
@ -216,6 +226,10 @@ using namespace mozilla::a11y;
|
|||
[super expire];
|
||||
}
|
||||
|
||||
- (BOOL)isOpened {
|
||||
return mIsOpened;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation mozMenuItemAccessible
|
||||
|
@ -224,6 +238,29 @@ using namespace mozilla::a11y;
|
|||
return @"";
|
||||
}
|
||||
|
||||
- (BOOL)moxIgnoreWithParent:(mozAccessible*)parent {
|
||||
// This helps us generate the correct moxChildren array for
|
||||
// a mozMenuAccessible; the returned array should contain all
|
||||
// menu items, regardless of if they are visible or not.
|
||||
// Because moxChildren does ignore filtering, and because
|
||||
// our base ignore method filters out invisible accessibles,
|
||||
// we override this method.
|
||||
id grandparent = [parent moxUnignoredParent];
|
||||
if (grandparent && [grandparent isKindOfClass:[mozAccessible class]]) {
|
||||
mozAccessible* acc = static_cast<mozAccessible*>(grandparent);
|
||||
if ([acc geckoAccessible].Role() == roles::PARENT_MENUITEM) {
|
||||
mozMenuAccessible* parentMenu = (mozMenuAccessible*)parent;
|
||||
// if we are a menu item in a submenu, display only when
|
||||
// parent menu item is open
|
||||
return [parentMenu moxIgnoreWithParent:acc];
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we call into our superclass's method to handle
|
||||
// menuitems that are not within submenus
|
||||
return [super moxIgnoreWithParent:parent];
|
||||
}
|
||||
|
||||
- (NSString*)moxMenuItemMarkChar {
|
||||
Accessible* acc = mGeckoAccessible.AsAccessible();
|
||||
if (acc && acc->IsContent() &&
|
||||
|
|
|
@ -206,7 +206,8 @@ add_task(async () => {
|
|||
{ type: "contextmenu" },
|
||||
browser
|
||||
);
|
||||
await BrowserTestUtils.waitForPopupEvent(menu, "shown");
|
||||
await waitForMacEvent("AXMenuOpened");
|
||||
|
||||
menu = await getMacAccessible(menu);
|
||||
const menuChildren = menu.getAttributeValue("AXChildren");
|
||||
// menu contains 12 items and 3 splitters for 15 items total
|
||||
|
@ -236,24 +237,21 @@ add_task(async () => {
|
|||
// submenus are at indicies 1 and 10
|
||||
// first check they have no children when hidden
|
||||
is(
|
||||
menuChildren[1].getAttributeValue("AXChildren").length,
|
||||
0,
|
||||
"Submenu 1 has no chldren when hidden"
|
||||
menuChildren[1].getAttributeValue("AXVisibleChildren"),
|
||||
null,
|
||||
"Submenu 1 has no visible chldren when hidden"
|
||||
);
|
||||
is(
|
||||
menuChildren[11].getAttributeValue("AXChildren").length,
|
||||
0,
|
||||
"Submenu 2 has no chldren when hidden"
|
||||
menuChildren[11].getAttributeValue("AXVisibleChildren"),
|
||||
null,
|
||||
"Submenu 2 has no visible chldren when hidden"
|
||||
);
|
||||
|
||||
// focus the first submenu
|
||||
const contextMenu = document.getElementById(
|
||||
"context-openlinkinusercontext-menu"
|
||||
);
|
||||
EventUtils.synthesizeKey("KEY_ArrowDown");
|
||||
EventUtils.synthesizeKey("KEY_ArrowDown");
|
||||
EventUtils.synthesizeKey("KEY_ArrowRight");
|
||||
await BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
|
||||
await waitForMacEvent("AXMenuOpened");
|
||||
|
||||
// verify submenu-menuitem's attributes
|
||||
is(
|
||||
|
|
Загрузка…
Ссылка в новой задаче