1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_a11y_TextLeafRange_h__
8 #define mozilla_a11y_TextLeafRange_h__
12 #include "AccAttributes.h"
13 #include "nsDirection.h"
14 #include "nsIAccessibleText.h"
25 class LocalAccessible
;
28 * Represents a point within accessible text.
29 * This is stored as a leaf Accessible and an offset into that Accessible.
30 * For an empty Accessible, the offset will always be 0.
31 * This will eventually replace TextPoint. Unlike TextPoint, this does not
32 * use HyperTextAccessible offsets.
34 class TextLeafPoint final
{
36 TextLeafPoint(Accessible
* aAcc
, int32_t aOffset
);
39 * Constructs an invalid TextPoint (mAcc is null).
40 * A TextLeafPoint in this state will evaluate to false.
41 * mAcc can be set later. Alternatively, this can be used to indicate an error
42 * (e.g. if a requested point couldn't be found).
44 TextLeafPoint() : mAcc(nullptr), mOffset(0) {}
47 * Construct a TextLeafPoint representing the caret.
48 * The actual offset used for the caret differs depending on whether the
49 * caret is at the end of a line and the query being made. Thus, mOffset on
50 * the returned TextLeafPoint is not a valid offset.
52 static TextLeafPoint
GetCaret(Accessible
* aAcc
) {
53 return TextLeafPoint(aAcc
, nsIAccessibleText::TEXT_OFFSET_CARET
);
59 bool operator==(const TextLeafPoint
& aPoint
) const {
60 return mAcc
== aPoint
.mAcc
&& mOffset
== aPoint
.mOffset
;
63 bool operator!=(const TextLeafPoint
& aPoint
) const {
64 return !(*this == aPoint
);
67 bool operator<(const TextLeafPoint
& aPoint
) const;
69 bool operator<=(const TextLeafPoint
& aPoint
) const;
72 * A valid TextLeafPoint evaluates to true. An invalid TextLeafPoint
75 explicit operator bool() const { return !!mAcc
; }
77 bool IsCaret() const {
78 return mOffset
== nsIAccessibleText::TEXT_OFFSET_CARET
;
81 bool IsCaretAtEndOfLine() const;
84 * Get a TextLeafPoint at the actual caret offset.
85 * This should only be called on a TextLeafPoint created with GetCaret.
86 * If aAdjustAtEndOfLine is true, the point will be adjusted if the caret is
87 * at the end of a line so that word and line boundaries can be calculated
90 TextLeafPoint
ActualizeCaret(bool aAdjustAtEndOfLine
= true) const;
92 enum class BoundaryFlags
: uint32_t {
93 eDefaultBoundaryFlags
= 0,
94 // Return point unchanged if it is at the given boundary type.
95 eIncludeOrigin
= 1 << 0,
96 // If current point is in editable, return point within samme editable.
97 eStopInEditable
= 1 << 1,
98 // Skip over list items in searches and don't consider them line or
100 eIgnoreListItemMarker
= 1 << 2,
104 * Find a boundary (word start, line start, etc.) in a specific direction.
105 * If no boundary is found, the start/end of the document is returned
106 * (depending on the direction).
108 TextLeafPoint
FindBoundary(
109 AccessibleTextBoundary aBoundaryType
, nsDirection aDirection
,
110 BoundaryFlags aFlags
= BoundaryFlags::eDefaultBoundaryFlags
) const;
113 * These two functions find a line start boundary within the same
114 * LocalAccessible as this. That is, they do not cross Accessibles. If no
115 * boundary is found, an invalid TextLeafPoint is returned.
116 * These are used by FindBoundary. Most callers will want FindBoundary
119 TextLeafPoint
FindPrevLineStartSameLocalAcc(bool aIncludeOrigin
) const;
120 TextLeafPoint
FindNextLineStartSameLocalAcc(bool aIncludeOrigin
) const;
123 * These two functions find a word start boundary within the same
124 * Accessible as this. That is, they do not cross Accessibles. If no
125 * boundary is found, an invalid TextLeafPoint is returned.
126 * These are used by FindBoundary. Most callers will want FindBoundary
129 TextLeafPoint
FindPrevWordStartSameAcc(bool aIncludeOrigin
) const;
130 TextLeafPoint
FindNextWordStartSameAcc(bool aIncludeOrigin
) const;
133 * Get the text attributes at this point.
134 * If aIncludeDefaults is true, default attributes on the HyperTextAccessible
137 already_AddRefed
<AccAttributes
> GetTextAttributes(
138 bool aIncludeDefaults
= true) const;
141 * Get Get the text attributes at this point in a LocalAccessible.
142 * This is used by GetTextAttributes. Most callers will want GetTextAttributes
145 already_AddRefed
<AccAttributes
> GetTextAttributesLocalAcc(
146 bool aIncludeDefaults
= true) const;
149 * Get the offsets of all spelling errors in a given LocalAccessible. This
150 * should only be used when pushing the cache. Most callers will want
151 * FindTextAttrsStart instead.
153 static nsTArray
<int32_t> GetSpellingErrorOffsets(LocalAccessible
* aAcc
);
156 * Queue a cache update for a spelling error in a given DOM range.
158 static void UpdateCachedSpellingError(dom::Document
* aDocument
,
159 const nsRange
& aRange
);
162 * Find the start of a run of text attributes in a specific direction.
163 * A text attributes run is a span of text where the attributes are the same.
164 * If no boundary is found, the start/end of the container is returned
165 * (depending on the direction).
166 * If aIncludeorigin is true and this is at a boundary, this will be
167 * returned unchanged.
169 TextLeafPoint
FindTextAttrsStart(nsDirection aDirection
,
170 bool aIncludeOrigin
= false) const;
173 * Returns a rect (in dev pixels) describing position and size of
174 * the character at mOffset in mAcc. This rect is screen-relative.
175 * This function only works on remote accessibles, and assumes caching
178 LayoutDeviceIntRect
CharBounds();
181 * Returns true if the given point (in screen coords) is contained
182 * in the char bounds of the current TextLeafPoint. Returns false otherwise.
183 * If the current point is an empty container, we use the acc's bounds instead
184 * of char bounds. Because this depends on CharBounds, this function only
185 * works on remote accessibles, and assumes caching is enabled.
187 bool ContainsPoint(int32_t aX
, int32_t aY
);
189 bool IsLineFeedChar() const { return GetChar() == '\n'; }
191 bool IsSpace() const;
193 bool IsParagraphStart(bool aIgnoreListItemMarker
= false) const {
194 return mOffset
== 0 &&
195 FindParagraphSameAcc(eDirPrevious
, true, aIgnoreListItemMarker
);
199 * Translate given TextLeafPoint into a DOM point.
201 MOZ_CAN_RUN_SCRIPT
std::pair
<nsIContent
*, int32_t> ToDOMPoint(
202 bool aIncludeGenerated
= true) const;
205 bool IsEmptyLastLine() const;
207 bool IsDocEdge(nsDirection aDirection
) const;
209 bool IsLeafAfterListItemMarker() const;
211 char16_t
GetChar() const;
213 TextLeafPoint
FindLineStartSameRemoteAcc(nsDirection aDirection
,
214 bool aIncludeOrigin
) const;
217 * Helper which just calls the appropriate function based on whether mAcc
220 TextLeafPoint
FindLineStartSameAcc(nsDirection aDirection
,
222 bool aIgnoreListItemMarker
= false) const;
224 TextLeafPoint
FindLineEnd(nsDirection aDirection
, BoundaryFlags aFlags
) const;
225 TextLeafPoint
FindWordEnd(nsDirection aDirection
, BoundaryFlags aFlags
) const;
227 TextLeafPoint
FindParagraphSameAcc(nsDirection aDirection
,
229 bool aIgnoreListItemMarker
= false) const;
231 bool IsInSpellingError() const;
234 * Find a spelling error boundary in the same Accessible. This function
235 * searches for either start or end points, since either means a change in
238 TextLeafPoint
FindSpellingErrorSameAcc(nsDirection aDirection
,
239 bool aIncludeOrigin
) const;
241 // Return the point immediately succeeding or preceding this leaf depending
242 // on given direction.
243 TextLeafPoint
NeighborLeafPoint(nsDirection aDirection
, bool aIsEditable
,
244 bool aIgnoreListItemMarker
) const;
247 * This function assumes mAcc is a LocalAccessible.
248 * It iterates the continuations of mAcc's primary frame until it locates
249 * the continuation containing mOffset (a rendered offset). It then uses
250 * GetScreenRectInAppUnits to compute screen coords for the frame, resizing
251 * such that the resulting rect contains only one character.
253 LayoutDeviceIntRect
ComputeBoundsFromFrame() const;
256 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(TextLeafPoint::BoundaryFlags
)
259 * Represents a range of accessible text.
260 * This will eventually replace TextRange.
262 class TextLeafRange final
{
264 TextLeafRange(const TextLeafPoint
& aStart
, const TextLeafPoint
& aEnd
)
265 : mStart(aStart
), mEnd(aEnd
) {}
266 explicit TextLeafRange(const TextLeafPoint
& aStart
)
267 : mStart(aStart
), mEnd(aStart
) {}
268 explicit TextLeafRange() {}
271 * A valid TextLeafRange evaluates to true. An invalid TextLeafRange
272 * evaluates to false.
274 explicit operator bool() const { return !!mStart
&& !!mEnd
; }
276 bool operator!=(const TextLeafRange
& aOther
) const {
277 return mEnd
!= aOther
.mEnd
|| mStart
!= aOther
.mStart
;
280 bool operator==(const TextLeafRange
& aOther
) const {
281 return mEnd
== aOther
.mEnd
&& mStart
== aOther
.mStart
;
284 TextLeafPoint
Start() const { return mStart
; }
285 void SetStart(const TextLeafPoint
& aStart
) { mStart
= aStart
; }
286 TextLeafPoint
End() const { return mEnd
; }
287 void SetEnd(const TextLeafPoint
& aEnd
) { mEnd
= aEnd
; }
289 bool Crop(Accessible
* aContainer
);
292 * Returns a union rect (in dev pixels) of all character bounds in this range.
293 * This rect is screen-relative and inclusive of mEnd. This function only
294 * works on remote accessibles, and assumes caching is enabled.
296 LayoutDeviceIntRect
Bounds() const;
299 * Set range as DOM selection.
300 * aSelectionNum is the selection index to use. If aSelectionNum is
301 * out of bounds for current selection ranges, or is -1, a new selection
304 MOZ_CAN_RUN_SCRIPT
bool SetSelection(int32_t aSelectionNum
) const;
306 MOZ_CAN_RUN_SCRIPT
void ScrollIntoView(uint32_t aScrollType
) const;
309 TextLeafPoint mStart
;
314 * A TextLeafRange iterator will iterate through single leaf segments of the
320 Iterator(Iterator
&& aOther
)
321 : mRange(aOther
.mRange
),
322 mSegmentStart(aOther
.mSegmentStart
),
323 mSegmentEnd(aOther
.mSegmentEnd
) {}
325 static Iterator
BeginIterator(const TextLeafRange
& aRange
);
327 static Iterator
EndIterator(const TextLeafRange
& aRange
);
329 Iterator
& operator++();
331 bool operator!=(const Iterator
& aOther
) const {
332 return mRange
!= aOther
.mRange
|| mSegmentStart
!= aOther
.mSegmentStart
||
333 mSegmentEnd
!= aOther
.mSegmentEnd
;
336 TextLeafRange
operator*() {
337 return TextLeafRange(mSegmentStart
, mSegmentEnd
);
341 explicit Iterator(const TextLeafRange
& aRange
) : mRange(aRange
) {}
344 Iterator(const Iterator
&) = delete;
345 Iterator
& operator=(const Iterator
&) = delete;
346 Iterator
& operator=(const Iterator
&&) = delete;
348 const TextLeafRange
& mRange
;
349 TextLeafPoint mSegmentStart
;
350 TextLeafPoint mSegmentEnd
;
353 Iterator
begin() const { return Iterator::BeginIterator(*this); }
354 Iterator
end() const { return Iterator::EndIterator(*this); }
358 } // namespace mozilla