1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef mozilla_a11y_HyperTextAccessible_h__
7 #define mozilla_a11y_HyperTextAccessible_h__
9 #include "AccessibleWrap.h"
10 #include "mozilla/a11y/HyperTextAccessibleBase.h"
11 #include "nsIAccessibleText.h"
12 #include "nsIAccessibleTypes.h"
13 #include "nsIFrame.h" // only for nsSelectionAmount
14 #include "nsISelectionController.h"
15 #include "nsDirection.h"
16 #include "WordMovementType.h"
18 class nsFrameSelection
;
35 DOMPoint() : node(nullptr), idx(0) {}
36 DOMPoint(nsINode
* aNode
, int32_t aIdx
) : node(aNode
), idx(aIdx
) {}
43 * Special Accessible that knows how contain both text and embedded objects
45 class HyperTextAccessible
: public AccessibleWrap
,
46 public HyperTextAccessibleBase
{
48 HyperTextAccessible(nsIContent
* aContent
, DocAccessible
* aDoc
);
50 NS_INLINE_DECL_REFCOUNTING_INHERITED(HyperTextAccessible
, AccessibleWrap
)
53 virtual already_AddRefed
<AccAttributes
> NativeAttributes() override
;
54 virtual mozilla::a11y::role
NativeRole() const override
;
55 virtual uint64_t NativeState() const override
;
57 virtual void Shutdown() override
;
58 virtual bool RemoveChild(LocalAccessible
* aAccessible
) override
;
59 virtual bool InsertChildAt(uint32_t aIndex
, LocalAccessible
* aChild
) override
;
60 virtual Relation
RelationByType(RelationType aType
) const override
;
62 // HyperTextAccessible (static helper method)
64 // Convert content offset to rendered text offset
65 nsresult
ContentToRenderedOffset(nsIFrame
* aFrame
, int32_t aContentOffset
,
66 uint32_t* aRenderedOffset
) const;
68 // Convert rendered text offset to content offset
69 nsresult
RenderedToContentOffset(nsIFrame
* aFrame
, uint32_t aRenderedOffset
,
70 int32_t* aContentOffset
) const;
72 //////////////////////////////////////////////////////////////////////////////
73 // HyperLinkAccessible
76 * Return link count within this hypertext accessible.
78 uint32_t LinkCount() { return EmbeddedChildCount(); }
81 * Return link accessible at the given index.
83 LocalAccessible
* LinkAt(uint32_t aIndex
) { return EmbeddedChildAt(aIndex
); }
85 //////////////////////////////////////////////////////////////////////////////
86 // HyperTextAccessible: DOM point to text offset conversions.
89 * Turn a DOM point (node and offset) into a character offset of this
90 * hypertext. Will look for closest match when the DOM node does not have
91 * an accessible object associated with it. Will return an offset for the end
92 * of the string if the node is not found.
94 * @param aNode [in] the node to look for
95 * @param aNodeOffset [in] the offset to look for
96 * if -1 just look directly for the node
97 * if >=0 and aNode is text, this represents a char
98 * offset if >=0 and aNode is not text, this represents a child node offset
99 * @param aIsEndOffset [in] if true, then this offset is not inclusive. The
100 * character indicated by the offset returned is at [offset - 1]. This means
101 * if the passed-in offset is really in a descendant, then the offset
102 * returned will come just after the relevant embedded object characer. If
103 * false, then the offset is inclusive. The character indicated by the offset
104 * returned is at [offset]. If the passed-in offset in inside a descendant,
105 * then the returned offset will be on the relevant embedded object char.
107 uint32_t DOMPointToOffset(nsINode
* aNode
, int32_t aNodeOffset
,
108 bool aIsEndOffset
= false) const;
111 * Transform the given a11y point into the offset relative this hypertext.
113 uint32_t TransformOffset(LocalAccessible
* aDescendant
, uint32_t aOffset
,
114 bool aIsEndOffset
) const;
117 * Convert the given offset into DOM point.
119 * If offset is at text leaf then DOM point is (text node, offsetInTextNode),
120 * if before embedded object then (parent node, indexInParent), if after then
121 * (parent node, indexInParent + 1).
123 DOMPoint
OffsetToDOMPoint(int32_t aOffset
) const;
125 //////////////////////////////////////////////////////////////////////////////
128 using HyperTextAccessibleBase::CharAt
;
130 char16_t
CharAt(int32_t aOffset
) {
131 nsAutoString charAtOffset
;
132 CharAt(aOffset
, charAtOffset
);
133 return charAtOffset
.CharAt(0);
137 * Return true if char at the given offset equals to given char.
139 bool IsCharAt(int32_t aOffset
, char16_t aChar
) {
140 return CharAt(aOffset
) == aChar
;
144 * Return true if terminal char is at the given offset.
146 bool IsLineEndCharAt(int32_t aOffset
) { return IsCharAt(aOffset
, '\n'); }
148 virtual void TextBeforeOffset(int32_t aOffset
,
149 AccessibleTextBoundary aBoundaryType
,
150 int32_t* aStartOffset
, int32_t* aEndOffset
,
151 nsAString
& aText
) override
;
152 virtual void TextAtOffset(int32_t aOffset
,
153 AccessibleTextBoundary aBoundaryType
,
154 int32_t* aStartOffset
, int32_t* aEndOffset
,
155 nsAString
& aText
) override
;
156 virtual void TextAfterOffset(int32_t aOffset
,
157 AccessibleTextBoundary aBoundaryType
,
158 int32_t* aStartOffset
, int32_t* aEndOffset
,
159 nsAString
& aText
) override
;
161 virtual already_AddRefed
<AccAttributes
> TextAttributes(
162 bool aIncludeDefAttrs
, int32_t aOffset
, int32_t* aStartOffset
,
163 int32_t* aEndOffset
) override
;
165 virtual already_AddRefed
<AccAttributes
> DefaultTextAttributes() override
;
167 // HyperTextAccessibleBase provides an overload which takes an Accessible.
168 using HyperTextAccessibleBase::GetChildOffset
;
169 virtual int32_t GetChildOffset(uint32_t aChildIndex
,
170 bool aInvalidateAfter
= false) const override
;
172 virtual int32_t GetChildIndexAtOffset(uint32_t aOffset
) const override
;
174 virtual LocalAccessible
* GetChildAtOffset(uint32_t aOffset
) const override
{
175 return LocalChildAt(GetChildIndexAtOffset(aOffset
));
179 * Return an offset at the given point.
181 int32_t OffsetAtPoint(int32_t aX
, int32_t aY
, uint32_t aCoordType
);
184 * Return a rect (in dev pixels) of the given text range relative given
187 LayoutDeviceIntRect
TextBounds(
188 int32_t aStartOffset
, int32_t aEndOffset
,
189 uint32_t aCoordType
=
190 nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE
);
193 * Return a rect (in dev pixels) for character at given offset relative given
196 LayoutDeviceIntRect
CharBounds(int32_t aOffset
, uint32_t aCoordType
) {
197 int32_t endOffset
= aOffset
== static_cast<int32_t>(CharacterCount())
200 return TextBounds(aOffset
, endOffset
, aCoordType
);
204 * Get/set caret offset, if no caret then -1.
206 virtual int32_t CaretOffset() const override
;
207 void SetCaretOffset(int32_t aOffset
);
210 * Provide the line number for the caret.
211 * @return 1-based index for the line number with the caret
213 int32_t CaretLineNumber();
216 * Return the caret rect and the widget containing the caret within this
219 * @param [out] the widget containing the caret
220 * @return the caret rect
222 mozilla::LayoutDeviceIntRect
GetCaretRect(nsIWidget
** aWidget
);
225 * Return true if caret is at end of line.
227 bool IsCaretAtEndOfLine() const;
229 virtual int32_t SelectionCount() override
;
231 virtual bool SelectionBoundsAt(int32_t aSelectionNum
, int32_t* aStartOffset
,
232 int32_t* aEndOffset
) override
;
235 * Changes the start and end offset of the specified selection.
236 * @return true if succeeded
238 // TODO: annotate this with `MOZ_CAN_RUN_SCRIPT` instead.
239 MOZ_CAN_RUN_SCRIPT_BOUNDARY
bool SetSelectionBoundsAt(int32_t aSelectionNum
,
240 int32_t aStartOffset
,
244 * Adds a selection bounded by the specified offsets.
245 * @return true if succeeded
247 bool AddToSelection(int32_t aStartOffset
, int32_t aEndOffset
);
250 * Removes the specified selection.
251 * @return true if succeeded
253 // TODO: annotate this with `MOZ_CAN_RUN_SCRIPT` instead.
254 MOZ_CAN_RUN_SCRIPT_BOUNDARY
bool RemoveFromSelection(int32_t aSelectionNum
);
257 * Scroll the given text range into view.
259 void ScrollSubstringTo(int32_t aStartOffset
, int32_t aEndOffset
,
260 uint32_t aScrollType
);
263 * Scroll the given text range to the given point.
265 void ScrollSubstringToPoint(int32_t aStartOffset
, int32_t aEndOffset
,
266 uint32_t aCoordinateType
, int32_t aX
, int32_t aY
);
269 * Return a range that encloses the text control or the document this
270 * accessible belongs to.
272 void EnclosingRange(TextRange
& aRange
) const;
274 virtual void SelectionRanges(nsTArray
<TextRange
>* aRanges
) const override
;
277 * Return an array of disjoint ranges of visible text within the text control
278 * or the document this accessible belongs to.
280 void VisibleRanges(nsTArray
<TextRange
>* aRanges
) const;
283 * Return a range containing the given accessible.
285 void RangeByChild(LocalAccessible
* aChild
, TextRange
& aRange
) const;
288 * Return a range containing an accessible at the given point.
290 void RangeAtPoint(int32_t aX
, int32_t aY
, TextRange
& aRange
) const;
292 //////////////////////////////////////////////////////////////////////////////
293 // EditableTextAccessible
295 MOZ_CAN_RUN_SCRIPT_BOUNDARY
void ReplaceText(const nsAString
& aText
);
296 MOZ_CAN_RUN_SCRIPT_BOUNDARY
void InsertText(const nsAString
& aText
,
298 void CopyText(int32_t aStartPos
, int32_t aEndPos
);
299 MOZ_CAN_RUN_SCRIPT_BOUNDARY
void CutText(int32_t aStartPos
, int32_t aEndPos
);
300 MOZ_CAN_RUN_SCRIPT_BOUNDARY
void DeleteText(int32_t aStartPos
,
303 void PasteText(int32_t aPosition
);
306 * Return the editor associated with the accessible.
307 * The result may be either TextEditor or HTMLEditor.
309 virtual already_AddRefed
<EditorBase
> GetEditor() const;
312 * Return DOM selection object for the accessible.
314 dom::Selection
* DOMSelection() const;
317 virtual ~HyperTextAccessible() {}
320 virtual ENameValueFlag
NativeName(nsString
& aName
) const override
;
322 // HyperTextAccessible
325 * Adjust an offset the caret stays at to get a text by line boundary.
327 uint32_t AdjustCaretOffset(uint32_t aOffset
) const;
330 * Return true if the given offset points to terminal empty line if any.
332 bool IsEmptyLastLineOffset(int32_t aOffset
) {
333 return aOffset
== static_cast<int32_t>(CharacterCount()) &&
334 IsLineEndCharAt(aOffset
- 1);
338 * Return an offset of the found word boundary.
340 uint32_t FindWordBoundary(uint32_t aOffset
, nsDirection aDirection
,
341 EWordMovementType aWordMovementType
);
344 * Used to get begin/end of previous/this/next line. Note: end of line
345 * is an offset right before '\n' character if any, the offset is right after
346 * '\n' character is begin of line. In case of wrap word breaks these offsets
349 enum EWhichLineBoundary
{
359 * Return an offset for requested line boundary. See constants above.
361 uint32_t FindLineBoundary(uint32_t aOffset
,
362 EWhichLineBoundary aWhichLineBoundary
);
365 * Find the start offset for a paragraph , taking into account
366 * inner block elements and line breaks.
368 int32_t FindParagraphStartOffset(uint32_t aOffset
);
371 * Find the end offset for a paragraph , taking into account
372 * inner block elements and line breaks.
374 int32_t FindParagraphEndOffset(uint32_t aOffset
);
377 * Return an offset corresponding to the given direction and selection amount
378 * relative the given offset. A helper used to find word or line boundaries.
380 uint32_t FindOffset(uint32_t aOffset
, nsDirection aDirection
,
381 nsSelectionAmount aAmount
,
382 EWordMovementType aWordMovementType
= eDefaultBehavior
);
385 * Return the boundaries (in dev pixels) of the substring in case of textual
386 * frame or frame boundaries in case of non textual frame, offsets are
389 LayoutDeviceIntRect
GetBoundsInFrame(nsIFrame
* aFrame
,
390 uint32_t aStartRenderedOffset
,
391 uint32_t aEndRenderedOffset
);
396 * Return frame selection object for the accessible.
398 already_AddRefed
<nsFrameSelection
> FrameSelection() const;
401 * Return selection ranges within the accessible subtree.
403 void GetSelectionDOMRanges(SelectionType aSelectionType
,
404 nsTArray
<nsRange
*>* aRanges
);
406 // TODO: annotate this with `MOZ_CAN_RUN_SCRIPT` instead.
407 MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult
SetSelectionRange(int32_t aStartPos
,
411 nsresult
GetDOMPointByFrameOffset(nsIFrame
* aFrame
, int32_t aOffset
,
412 LocalAccessible
* aAccessible
,
413 mozilla::a11y::DOMPoint
* aPoint
);
416 * Set 'misspelled' text attribute and return range offsets where the
417 * attibute is stretched. If the text is not misspelled at the given offset
418 * then we expose only range offsets where text is not misspelled. The method
419 * is used by TextAttributes() method.
421 * @param aIncludeDefAttrs [in] points whether text attributes having default
422 * values of attributes should be included
423 * @param aSourceNode [in] the node we start to traverse from
424 * @param aStartOffset [in, out] the start offset
425 * @param aEndOffset [in, out] the end offset
426 * @param aAttributes [out, optional] result attributes
428 void GetSpellTextAttr(nsINode
* aNode
, uint32_t aNodeOffset
,
429 uint32_t* aStartOffset
, uint32_t* aEndOffset
,
430 AccAttributes
* aAttributes
);
433 * Set xml-roles attributes for MathML elements.
436 void SetMathMLXMLRoles(AccAttributes
* aAttributes
);
438 // HyperTextAccessibleBase
439 virtual const Accessible
* Acc() const override
{ return this; }
443 * End text offsets array.
445 mutable nsTArray
<uint32_t> mOffsets
;
448 ////////////////////////////////////////////////////////////////////////////////
449 // LocalAccessible downcasting method
451 inline HyperTextAccessible
* LocalAccessible::AsHyperText() {
452 return IsHyperText() ? static_cast<HyperTextAccessible
*>(this) : nullptr;
455 inline HyperTextAccessibleBase
* LocalAccessible::AsHyperTextBase() {
456 return AsHyperText();
460 } // namespace mozilla