diff --git a/accessible/mac/GeckoTextMarker.mm b/accessible/mac/GeckoTextMarker.mm index cd6e0c279815..ba3a6e623176 100644 --- a/accessible/mac/GeckoTextMarker.mm +++ b/accessible/mac/GeckoTextMarker.mm @@ -436,27 +436,28 @@ NSAttributedString* GeckoTextMarkerRange::AttributedText() const { : mRange; nsAutoString text; - RefPtr currentRun = nullptr; + RefPtr currentRun = range.Start().GetTextAttributes(); Accessible* runAcc = range.Start().mAcc; for (TextLeafRange segment : range) { TextLeafPoint start = segment.Start(); - if (start.mAcc->IsTextField() && start.mAcc->ChildCount() == 0) { - continue; - } - if (!currentRun) { - // This is the first segment that isn't an empty input. - currentRun = start.GetTextAttributes(); - } TextLeafPoint attributesNext; do { - attributesNext = start.FindTextAttrsStart(eDirNext, false); + if (start.mAcc->IsText()) { + attributesNext = start.FindTextAttrsStart(eDirNext, false); + } else { + // If this segment isn't a text leaf, but another kind of inline element + // like a control, just consider this full segment one "attributes run". + attributesNext = segment.End(); + } if (attributesNext == start) { // XXX: FindTextAttrsStart should not return the same point. break; } RefPtr attributes = start.GetTextAttributes(); - MOZ_ASSERT(attributes); - if (attributes && !attributes->Equal(currentRun)) { + if (!currentRun || !attributes || !attributes->Equal(currentRun)) { + // If currentRun is null this is a non-text control and we will + // append a run with no text or attributes, just an AXAttachment + // referencing this accessible. AppendTextToAttributedString(str, runAcc, text, currentRun); text.Truncate(); currentRun = attributes; diff --git a/accessible/mac/MacUtils.mm b/accessible/mac/MacUtils.mm index f10534116360..5534e8fcc8b6 100644 --- a/accessible/mac/MacUtils.mm +++ b/accessible/mac/MacUtils.mm @@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #import "MacUtils.h" +#include "mozAccessible.h" #include "LocalAccessible.h" #include "DocAccessible.h" @@ -83,6 +84,12 @@ static NSColor* ColorFromColor(const Color& aColor) { NSDictionary* StringAttributesFromAccAttributes(AccAttributes* aAttributes, Accessible* aContainer) { if (!aAttributes) { + if (mozAccessible* mozAcc = GetNativeFromGeckoAccessible(aContainer)) { + // If we don't have attributes provided this is probably a control like + // a button or empty entry. Just provide the accessible as an + // AXAttachment. + return @{@"AXAttachment" : mozAcc}; + } return @{}; } diff --git a/accessible/tests/browser/mac/browser_attributed_text.js b/accessible/tests/browser/mac/browser_attributed_text.js index 6f6200751c62..afd4d2c4dcf0 100644 --- a/accessible/tests/browser/mac/browser_attributed_text.js +++ b/accessible/tests/browser/mac/browser_attributed_text.js @@ -115,30 +115,51 @@ addAccessibleTask( ); // Test getting a span of attributed text that includes an empty input element. -addAccessibleTask(`hello world`, async (browser, accDoc) => { - let macDoc = accDoc.nativeInterface.QueryInterface( - Ci.nsIAccessibleMacInterface - ); +addAccessibleTask( + `hello world`, + async (browser, accDoc) => { + let macDoc = accDoc.nativeInterface.QueryInterface( + Ci.nsIAccessibleMacInterface + ); - let range = macDoc.getParameterizedAttributeValue( - "AXTextMarkerRangeForUnorderedTextMarkers", - [ - macDoc.getAttributeValue("AXStartTextMarker"), - macDoc.getAttributeValue("AXEndTextMarker"), - ] - ); + let range = macDoc.getParameterizedAttributeValue( + "AXTextMarkerRangeForUnorderedTextMarkers", + [ + macDoc.getAttributeValue("AXStartTextMarker"), + macDoc.getAttributeValue("AXEndTextMarker"), + ] + ); - let attributedText = macDoc.getParameterizedAttributeValue( - "AXAttributedStringForTextMarkerRange", - range - ); + let attributedText = macDoc.getParameterizedAttributeValue( + "AXAttributedStringForTextMarkerRange", + range + ); - let text = macDoc.getParameterizedAttributeValue( - "AXStringForTextMarkerRange", - range - ); + let text = macDoc.getParameterizedAttributeValue( + "AXStringForTextMarkerRange", + range + ); - is(attributedText.length, 1, "Empty input does not break up attribute run."); - is(attributedText[0].string, `hello world `, "Attributed string is correct"); - is(text, `hello world `, "Unattributed string is correct"); -}); + is( + attributedText.length, + 4, + "Should be 4 attribute runs for 2 texts, input and button" + ); + is(attributedText[0].string, `hello `, "Attributed string is correct"); + ok( + !attributedText[0].AXAttachment, + "Regular string attributes run doesn't have attachment" + ); + is( + attributedText[1].AXAttachment.getAttributeValue("AXRole"), + "AXTextField", + "Entry text attribute run has correct attachment" + ); + is( + attributedText[3].AXAttachment.getAttributeValue("AXRole"), + "AXButton", + "Button text attribute run has correct attachment" + ); + is(text, `hello world${kEmbedChar}`, "Unattributed string is correct"); + } +);