HyperTextAccessible-inl.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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/. */
  5. #ifndef mozilla_a11y_HyperTextAccessible_inl_h__
  6. #define mozilla_a11y_HyperTextAccessible_inl_h__
  7. #include "HyperTextAccessible.h"
  8. #include "nsAccUtils.h"
  9. #include "nsIClipboard.h"
  10. #include "nsIEditor.h"
  11. #include "nsIPersistentProperties2.h"
  12. #include "nsIPlaintextEditor.h"
  13. #include "nsFrameSelection.h"
  14. namespace mozilla {
  15. namespace a11y {
  16. inline bool
  17. HyperTextAccessible::IsValidOffset(int32_t aOffset)
  18. {
  19. index_t offset = ConvertMagicOffset(aOffset);
  20. return offset.IsValid() && offset <= CharacterCount();
  21. }
  22. inline bool
  23. HyperTextAccessible::IsValidRange(int32_t aStartOffset, int32_t aEndOffset)
  24. {
  25. index_t startOffset = ConvertMagicOffset(aStartOffset);
  26. index_t endOffset = ConvertMagicOffset(aEndOffset);
  27. return startOffset.IsValid() && endOffset.IsValid() &&
  28. startOffset <= endOffset && endOffset <= CharacterCount();
  29. }
  30. inline void
  31. HyperTextAccessible::SetCaretOffset(int32_t aOffset)
  32. {
  33. SetSelectionRange(aOffset, aOffset);
  34. // XXX: Force cache refresh until a good solution for AT emulation of user
  35. // input is implemented (AccessFu caret movement).
  36. SelectionMgr()->UpdateCaretOffset(this, aOffset);
  37. }
  38. inline bool
  39. HyperTextAccessible::AddToSelection(int32_t aStartOffset, int32_t aEndOffset)
  40. {
  41. dom::Selection* domSel = DOMSelection();
  42. return domSel &&
  43. SetSelectionBoundsAt(domSel->RangeCount(), aStartOffset, aEndOffset);
  44. }
  45. inline void
  46. HyperTextAccessible::ReplaceText(const nsAString& aText)
  47. {
  48. // We need to call DeleteText() even if there is no contents because we need
  49. // to ensure to move focus to the editor via SetSelectionRange() called in
  50. // DeleteText().
  51. DeleteText(0, CharacterCount());
  52. nsCOMPtr<nsIEditor> editor = GetEditor();
  53. nsCOMPtr<nsIPlaintextEditor> plaintextEditor(do_QueryInterface(editor));
  54. if (!plaintextEditor) {
  55. return;
  56. }
  57. // DeleteText() may cause inserting <br> element in some cases. Let's
  58. // select all again and replace whole contents.
  59. editor->SelectAll();
  60. plaintextEditor->InsertText(aText);
  61. }
  62. inline void
  63. HyperTextAccessible::InsertText(const nsAString& aText, int32_t aPosition)
  64. {
  65. nsCOMPtr<nsIEditor> editor = GetEditor();
  66. nsCOMPtr<nsIPlaintextEditor> peditor(do_QueryInterface(editor));
  67. if (peditor) {
  68. SetSelectionRange(aPosition, aPosition);
  69. peditor->InsertText(aText);
  70. }
  71. }
  72. inline void
  73. HyperTextAccessible::CopyText(int32_t aStartPos, int32_t aEndPos)
  74. {
  75. nsCOMPtr<nsIEditor> editor = GetEditor();
  76. if (editor) {
  77. SetSelectionRange(aStartPos, aEndPos);
  78. editor->Copy();
  79. }
  80. }
  81. inline void
  82. HyperTextAccessible::CutText(int32_t aStartPos, int32_t aEndPos)
  83. {
  84. nsCOMPtr<nsIEditor> editor = GetEditor();
  85. if (editor) {
  86. SetSelectionRange(aStartPos, aEndPos);
  87. editor->Cut();
  88. }
  89. }
  90. inline void
  91. HyperTextAccessible::DeleteText(int32_t aStartPos, int32_t aEndPos)
  92. {
  93. nsCOMPtr<nsIEditor> editor = GetEditor();
  94. if (editor) {
  95. SetSelectionRange(aStartPos, aEndPos);
  96. editor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
  97. }
  98. }
  99. inline void
  100. HyperTextAccessible::PasteText(int32_t aPosition)
  101. {
  102. nsCOMPtr<nsIEditor> editor = GetEditor();
  103. if (editor) {
  104. SetSelectionRange(aPosition, aPosition);
  105. editor->Paste(nsIClipboard::kGlobalClipboard);
  106. }
  107. }
  108. inline index_t
  109. HyperTextAccessible::ConvertMagicOffset(int32_t aOffset) const
  110. {
  111. if (aOffset == nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT)
  112. return CharacterCount();
  113. if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET)
  114. return CaretOffset();
  115. return aOffset;
  116. }
  117. inline uint32_t
  118. HyperTextAccessible::AdjustCaretOffset(uint32_t aOffset) const
  119. {
  120. // It is the same character offset when the caret is visually at the very
  121. // end of a line or the start of a new line (soft line break). Getting text
  122. // at the line should provide the line with the visual caret, otherwise
  123. // screen readers will announce the wrong line as the user presses up or
  124. // down arrow and land at the end of a line.
  125. if (aOffset > 0 && IsCaretAtEndOfLine())
  126. return aOffset - 1;
  127. return aOffset;
  128. }
  129. inline bool
  130. HyperTextAccessible::IsCaretAtEndOfLine() const
  131. {
  132. RefPtr<nsFrameSelection> frameSelection = FrameSelection();
  133. return frameSelection &&
  134. frameSelection->GetHint() == CARET_ASSOCIATE_BEFORE;
  135. }
  136. inline already_AddRefed<nsFrameSelection>
  137. HyperTextAccessible::FrameSelection() const
  138. {
  139. nsIFrame* frame = GetFrame();
  140. return frame ? frame->GetFrameSelection() : nullptr;
  141. }
  142. inline dom::Selection*
  143. HyperTextAccessible::DOMSelection() const
  144. {
  145. RefPtr<nsFrameSelection> frameSelection = FrameSelection();
  146. return frameSelection ? frameSelection->GetSelection(SelectionType::eNormal) :
  147. nullptr;
  148. }
  149. } // namespace a11y
  150. } // namespace mozilla
  151. #endif