Skip to content

Commit

Permalink
Update On Thu Jan 30 19:52:43 CET 2025
Browse files Browse the repository at this point in the history
  • Loading branch information
bolucat committed Jan 30, 2025
1 parent 76acc80 commit 247692f
Show file tree
Hide file tree
Showing 462 changed files with 8,325 additions and 3,224 deletions.
103 changes: 103 additions & 0 deletions accessible/tests/browser/windows/uia/browser_textPatterns.js
Original file line number Diff line number Diff line change
Expand Up @@ -2106,3 +2106,106 @@ addUiaTask(
// The IA2 -> UIA proxy doesn't support RemoveFromSelection correctly.
{ uiaEnabled: true, uiaDisabled: false }
);

/**
* Test the TextRange pattern's FindAttribute method.
*/
addUiaTask(
`
<div id="font-weight-container">a <span tabindex="0"><b>bcd</b></span><b> ef</b> ghi</div>
`,
async function testTextRangeFindAttribute(_browser, _docAcc) {
info("Constructing range on bold text run");
await runPython(`
global doc, docText, range, fontWeightContainerAcc
doc = getDocUia()
docText = getUiaPattern(doc, "Text")
fontWeightContainerAcc = findUiaByDomId(doc, "font-weight-container")
range = docText.RangeFromChild(fontWeightContainerAcc)
`);
is(
await runPython(`range.GetText(-1)`),
"a bcd ef ghi",
"range text correct"
);

info("Finding first font-weight 400 text range");
await runPython(`
global subrange
subrange = range.FindAttribute(UIA_FontWeightAttributeId, 400, False)
`);
is(await runPython(`subrange.GetText(-1)`), "a ", "range text correct");

info("Finding first font-weight 700 text range");
await runPython(`
global subrange
subrange = range.FindAttribute(UIA_FontWeightAttributeId, 700, False)
`);
is(await runPython(`subrange.GetText(-1)`), "bcd ef", "range text correct");

info("Finding last font-weight 700 text range");
await runPython(`
global subrange
subrange = range.FindAttribute(UIA_FontWeightAttributeId, 700, True)
`);
is(await runPython(`subrange.GetText(-1)`), "bcd ef", "range text correct");

info("Finding last font-weight 400 text range");
await runPython(`
global subrange
subrange = range.FindAttribute(UIA_FontWeightAttributeId, 400, True)
`);
is(await runPython(`subrange.GetText(-1)`), " ghi", "range text correct");

// The IA2 -> UIA proxy gets things below this wrong.
if (!gIsUiaEnabled) {
return;
}
info("Moving range to the middle of a text attribute run");
is(
await runPython(
`range.MoveEndpointByUnit(TextPatternRangeEndpoint_Start, TextUnit_Character, 4)`
),
4,
"MoveEndpointByUnit return correct"
);
is(await runPython(`range.GetText(-1)`), "cd ef ghi", "range text correct");

info(
"Finding first font-weight 700 text range (range starts in middle of text attribute run)"
);
await runPython(`
global subrange
subrange = range.FindAttribute(UIA_FontWeightAttributeId, 700, False)
`);
is(await runPython(`subrange.GetText(-1)`), "cd ef", "range text correct");

await runPython(`
global range
range = docText.RangeFromChild(fontWeightContainerAcc)
`);
is(
await runPython(`range.GetText(-1)`),
"a bcd ef ghi",
"range text correct"
);
is(
await runPython(
`range.MoveEndpointByUnit(TextPatternRangeEndpoint_End, TextUnit_Character, -5)`
),
-5,
"MoveEndpointByUnit return correct"
);
is(await runPython(`range.GetText(-1)`), "a bcd e", "range text correct");

info(
"Finding last font-weight 700 text range (range ends in middle of text attribute run)"
);
await runPython(`
global subrange
subrange = range.FindAttribute(UIA_FontWeightAttributeId, 700, True)
`);
is(await runPython(`subrange.GetText(-1)`), "bcd e", "range text correct");
},
{ uiaEnabled: true, uiaDisabled: true }
);
167 changes: 140 additions & 27 deletions accessible/windows/uia/UiaTextRange.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "nsIAccessibleTypes.h"
#include "TextLeafRange.h"
#include <comdef.h>
#include <propvarutil.h>
#include <unordered_set>

// Handle MinGW builds - see bug 1929755 for more info
Expand All @@ -20,6 +21,10 @@

namespace mozilla::a11y {

template <typename T>
HRESULT GetAttribute(TEXTATTRIBUTEID aAttributeId, T const& aRangeOrPoint,
VARIANT& aRetVal);

// Used internally to safely get a UiaTextRange from a COM pointer provided
// to us by a client.
// {74B8E664-4578-4B52-9CBC-30A7A8271AE8}
Expand Down Expand Up @@ -121,7 +126,7 @@ static NotNull<Accessible*> GetSelectionContainer(TextLeafRange& aRange) {

// UiaTextRange

UiaTextRange::UiaTextRange(TextLeafRange& aRange) {
UiaTextRange::UiaTextRange(const TextLeafRange& aRange) {
MOZ_ASSERT(aRange);
SetRange(aRange);
}
Expand Down Expand Up @@ -349,11 +354,94 @@ UiaTextRange::ExpandToEnclosingUnit(enum TextUnit aUnit) {
return S_OK;
}

// Search within the text range for the first subrange that has the given
// attribute value. The resulting range might span multiple text attribute runs.
// If aBackward, start the search from the end of the range.
STDMETHODIMP
UiaTextRange::FindAttribute(TEXTATTRIBUTEID aAttributeId, VARIANT aVal,
BOOL aBackward,
__RPC__deref_out_opt ITextRangeProvider** aRetVal) {
return E_NOTIMPL;
if (!aRetVal) {
return E_INVALIDARG;
}
*aRetVal = nullptr;
TextLeafRange range = GetRange();
if (!range) {
return CO_E_OBJNOTCONNECTED;
}
MOZ_ASSERT(range.Start() <= range.End(), "Range must be valid to proceed.");

VARIANT value{};

if (!aBackward) {
Maybe<TextLeafPoint> matchingRangeStart{};
// Begin with a range starting at the start of our original range and ending
// at the next attribute run start point.
TextLeafPoint startPoint = range.Start();
TextLeafPoint endPoint = startPoint;
endPoint = endPoint.FindTextAttrsStart(eDirNext);
do {
// Get the attribute value at the start point. Since we're moving through
// text attribute runs, we don't need to check the entire range; this
// point's attributes are those of the entire range.
GetAttribute(aAttributeId, startPoint, value);
// VariantCompare is not valid if types are different. Verify the type
// first so the result is well-defined.
if (aVal.vt == value.vt && VariantCompare(aVal, value) == 0) {
if (!matchingRangeStart) {
matchingRangeStart = Some(startPoint);
}
} else if (matchingRangeStart) {
// We fell out of a matching range. We're moving forward, so the
// matching range is [matchingRangeStart, startPoint).
RefPtr uiaRange = new UiaTextRange(
TextLeafRange{matchingRangeStart.value(), startPoint});
uiaRange.forget(aRetVal);
return S_OK;
}
startPoint = endPoint;
} while ((endPoint = endPoint.FindTextAttrsStart(eDirNext)) &&
endPoint <= range.End() && startPoint != endPoint);
if (matchingRangeStart) {
// We found a start point and reached the end of the range. The result is
// [matchingRangeStart, stopPoint].
RefPtr uiaRange = new UiaTextRange(
TextLeafRange{matchingRangeStart.value(), range.End()});
uiaRange.forget(aRetVal);
return S_OK;
}
} else {
Maybe<TextLeafPoint> matchingRangeEnd{};
TextLeafPoint endPoint = range.End();
TextLeafPoint startPoint = endPoint;
startPoint = startPoint.FindTextAttrsStart(eDirPrevious);
do {
GetAttribute(aAttributeId, startPoint, value);
if (aVal.vt == value.vt && VariantCompare(aVal, value) == 0) {
if (!matchingRangeEnd) {
matchingRangeEnd = Some(endPoint);
}
} else if (matchingRangeEnd) {
// We fell out of a matching range. We're moving backward, so the
// matching range is [endPoint, matchingRangeEnd).
RefPtr uiaRange =
new UiaTextRange(TextLeafRange{endPoint, matchingRangeEnd.value()});
uiaRange.forget(aRetVal);
return S_OK;
}
endPoint = startPoint;
} while ((startPoint = startPoint.FindTextAttrsStart(eDirPrevious)) &&
range.Start() <= startPoint);
if (matchingRangeEnd) {
// We found an end point and reached the start of the range. The result is
// [range.Start(), matchingRangeEnd).
RefPtr uiaRange = new UiaTextRange(
TextLeafRange{range.Start(), matchingRangeEnd.value()});
uiaRange.forget(aRetVal);
return S_OK;
}
}
return S_OK;
}

STDMETHODIMP
Expand Down Expand Up @@ -427,52 +515,77 @@ HRESULT GetAttribute(const TextLeafRange& aRange, VARIANT& aVariant) {
return Traits::WriteToVariant(aVariant, *val);
}

STDMETHODIMP
UiaTextRange::GetAttributeValue(TEXTATTRIBUTEID aAttributeId,
__RPC__out VARIANT* aRetVal) {
if (!aRetVal) {
return E_INVALIDARG;
}
VariantInit(aRetVal);
TextLeafRange range = GetRange();
if (!range) {
return CO_E_OBJNOTCONNECTED;
}
template <TEXTATTRIBUTEID Attr>
HRESULT GetAttribute(TextLeafPoint const& aPoint, VARIANT& aVariant) {
// Select the traits of the given TEXTATTRIBUTEID. This helps us choose the
// correct functions to call to handle each attribute.
using Traits = AttributeTraits<Attr>;
using AttrType = typename Traits::AttrType;

MOZ_ASSERT(range.Start() <= range.End(), "Range must be valid to proceed.");
// Get the value at the given point.
Maybe<AttrType> val = Traits::GetValue(aPoint);
if (!val) {
// Fall back to the UIA-specified default when we don't have an answer.
val = Some(Traits::DefaultValue());
}
// Write the value to the VARIANT output parameter.
return Traits::WriteToVariant(aVariant, *val);
}

// Dispatch to the proper GetAttribute template specialization for the given
// TEXTATTRIBUTEID. T may be a TextLeafPoint or TextLeafRange; this function
// will call the appropriate specialization and overload.
template <typename T>
HRESULT GetAttribute(TEXTATTRIBUTEID aAttributeId, T const& aRangeOrPoint,
VARIANT& aRetVal) {
switch (aAttributeId) {
case UIA_AnnotationTypesAttributeId:
return GetAttribute<UIA_AnnotationTypesAttributeId>(range, *aRetVal);
return GetAttribute<UIA_AnnotationTypesAttributeId>(aRangeOrPoint,
aRetVal);
case UIA_FontNameAttributeId:
return GetAttribute<UIA_FontNameAttributeId>(range, *aRetVal);
return GetAttribute<UIA_FontNameAttributeId>(aRangeOrPoint, aRetVal);
case UIA_FontSizeAttributeId:
return GetAttribute<UIA_FontSizeAttributeId>(range, *aRetVal);
return GetAttribute<UIA_FontSizeAttributeId>(aRangeOrPoint, aRetVal);
case UIA_FontWeightAttributeId:
return GetAttribute<UIA_FontWeightAttributeId>(range, *aRetVal);
return GetAttribute<UIA_FontWeightAttributeId>(aRangeOrPoint, aRetVal);
case UIA_IsHiddenAttributeId:
return GetAttribute<UIA_IsHiddenAttributeId>(range, *aRetVal);
return GetAttribute<UIA_IsHiddenAttributeId>(aRangeOrPoint, aRetVal);
case UIA_IsItalicAttributeId:
return GetAttribute<UIA_IsItalicAttributeId>(range, *aRetVal);
return GetAttribute<UIA_IsItalicAttributeId>(aRangeOrPoint, aRetVal);
case UIA_IsReadOnlyAttributeId:
return GetAttribute<UIA_IsReadOnlyAttributeId>(range, *aRetVal);
return GetAttribute<UIA_IsReadOnlyAttributeId>(aRangeOrPoint, aRetVal);
case UIA_StyleIdAttributeId:
return GetAttribute<UIA_StyleIdAttributeId>(range, *aRetVal);
return GetAttribute<UIA_StyleIdAttributeId>(aRangeOrPoint, aRetVal);
case UIA_IsSubscriptAttributeId:
return GetAttribute<UIA_IsSubscriptAttributeId>(range, *aRetVal);
return GetAttribute<UIA_IsSubscriptAttributeId>(aRangeOrPoint, aRetVal);
case UIA_IsSuperscriptAttributeId:
return GetAttribute<UIA_IsSuperscriptAttributeId>(range, *aRetVal);
return GetAttribute<UIA_IsSuperscriptAttributeId>(aRangeOrPoint, aRetVal);
default:
// If the attribute isn't supported, return "[t]he address of the value
// retrieved by the UiaGetReservedNotSupportedValue function."
aRetVal->vt = VT_UNKNOWN;
return UiaGetReservedNotSupportedValue(&aRetVal->punkVal);
aRetVal.vt = VT_UNKNOWN;
return UiaGetReservedNotSupportedValue(&aRetVal.punkVal);
break;
}

MOZ_ASSERT_UNREACHABLE("Unhandled UIA Attribute ID");
return S_OK;
}

STDMETHODIMP
UiaTextRange::GetAttributeValue(TEXTATTRIBUTEID aAttributeId,
__RPC__out VARIANT* aRetVal) {
if (!aRetVal) {
return E_INVALIDARG;
}
VariantInit(aRetVal);
TextLeafRange range = GetRange();
if (!range) {
return CO_E_OBJNOTCONNECTED;
}
MOZ_ASSERT(range.Start() <= range.End(), "Range must be valid to proceed.");
return GetAttribute(aAttributeId, range, *aRetVal);
}

STDMETHODIMP
UiaTextRange::GetBoundingRectangles(__RPC__deref_out_opt SAFEARRAY** aRetVal) {
if (!aRetVal) {
Expand Down
2 changes: 1 addition & 1 deletion accessible/windows/uia/UiaTextRange.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class TextLeafPoint;
*/
class UiaTextRange : public ITextRangeProvider {
public:
explicit UiaTextRange(TextLeafRange& aRange);
explicit UiaTextRange(const TextLeafRange& aRange);
virtual ~UiaTextRange() = default;

// IUnknown
Expand Down
6 changes: 1 addition & 5 deletions browser/app/profile/firefox.js
Original file line number Diff line number Diff line change
Expand Up @@ -2473,11 +2473,7 @@ pref("privacy.webrtc.deviceGracePeriodTimeoutMs", 3600000);
pref("privacy.webrtc.showIndicatorsOnMacos14AndAbove", true);

// Enable Smartblock embed placeholders
#ifdef NIGHTLY_BUILD
pref("extensions.webcompat.smartblockEmbeds.enabled", true);
#else
pref("extensions.webcompat.smartblockEmbeds.enabled", false);
#endif
pref("extensions.webcompat.smartblockEmbeds.enabled", true);

// Enable including the content in the window title.
// PBM users might want to disable this to avoid a possible source of disk
Expand Down
Loading

0 comments on commit 247692f

Please sign in to comment.