From 4e0ffe1a178741739d8a0dff076b182d31f77073 Mon Sep 17 00:00:00 2001 From: Morgan Rae Reschenberg Date: Tue, 4 Jun 2024 20:42:45 +0000 Subject: [PATCH] Bug 1888310: Verify a11y-announcement is a child of ChildView instead of mozRootAccessible r=eeejay Previously we checked if the announcement was a child of the root acc directly, but it's not clear this worked reliably since we've done `GetObjectOrRepresentedView` for a while, which (should) return the view instead of the root acc. This patch also: - Dispatches the announcement from NSApp instead of NSWindow, since per chrome and safari notifs fired on non-main windows get dropped - Modifies the announcement priority from medium to high, so VO interrupts itself to speak this message (this makes the UX more consistent, since the text-inserted/text-deleted notifs from the URL bar seem to occasionally bookend the announcement) - Updates the browser_app.js test to NOT run in headless mode, since in headless mode NSApp isn't rendered to dispatch the notification. This test contains a task for AXAnnouncementRequested via a11yUtils.announce Differential Revision: https://phabricator.services.mozilla.com/D206083 --- accessible/mac/mozAccessible.mm | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/accessible/mac/mozAccessible.mm b/accessible/mac/mozAccessible.mm index 0609cc7afcbd..5cf9b9879ab1 100644 --- a/accessible/mac/mozAccessible.mm +++ b/accessible/mac/mozAccessible.mm @@ -879,10 +879,13 @@ struct RoleDescrComparator { // a random acc with the same ID) by checking: // - The gecko acc is local, our a11y-announcement lives in browser.xhtml // - The ID of the gecko acc is "a11y-announcement" - // - The native acc is a direct descendent of the root + // - The native acc is a direct descendent of the chrome window (ChildView in + // a non-headless context, mozRootAccessible in a headless context). if (mGeckoAccessible->IsLocal() && [[self moxDOMIdentifier] isEqualToString:@"a11y-announcement"] && - [[self moxParent] isKindOfClass:[mozRootAccessible class]]) { + ((gfxPlatform::IsHeadless() && + [[self moxParent] isKindOfClass:[mozRootAccessible class]]) || + [[self moxParent] isKindOfClass:[ChildView class]])) { // Our actual announcement should be stored as a child of the alert, // so we verify a child exists, and then query that child below. NSArray* children = [self moxChildren]; @@ -896,23 +899,24 @@ struct RoleDescrComparator { } else { key = [announcement moxTitle]; } - NSDictionary* info = @{ NSAccessibilityAnnouncementKey : key ? key : @(""), - NSAccessibilityPriorityKey : @(NSAccessibilityPriorityMedium) + // High priority means VO will stop what it is currently speaking + // to speak our announcement. + NSAccessibilityPriorityKey : @(NSAccessibilityPriorityHigh) }; - id window = [self moxWindow]; - // This sends events via nsIObserverService to be consumed by our // mochitests. Normally we'd fire these events through moxPostNotification - // which takes care of this, but because the window we fetch above isn't - // derrived from MOXAccessibleBase, we do this (and post the notification) - // manually. + // which takes care of this, but because NSApp isn't derived + // from MOXAccessibleBase, we do this (and post the notification) manually. + // We used to fire this on the window, but per Chrome and Safari these + // notifs get dropped if fired on any non-main window. We now fire on NSApp + // to avoid this. xpcAccessibleMacEvent::FireEvent( - window, NSAccessibilityAnnouncementRequestedNotification, info); + NSApp, NSAccessibilityAnnouncementRequestedNotification, info); NSAccessibilityPostNotificationWithUserInfo( - window, NSAccessibilityAnnouncementRequestedNotification, info); + NSApp, NSAccessibilityAnnouncementRequestedNotification, info); } }