diff --git a/accessible/public/moz.build b/accessible/public/moz.build index 9c6446b8f37..4fb6304efed 100644 --- a/accessible/public/moz.build +++ b/accessible/public/moz.build @@ -29,6 +29,7 @@ XPIDL_SOURCES += [ 'nsIAccessibleTableChangeEvent.idl', 'nsIAccessibleText.idl', 'nsIAccessibleTextChangeEvent.idl', + 'nsIAccessibleTextRange.idl', 'nsIAccessibleTypes.idl', 'nsIAccessibleValue.idl', 'nsIAccessibleVirtualCursorChangeEvent.idl', diff --git a/accessible/public/nsIAccessibleText.idl b/accessible/public/nsIAccessibleText.idl index d271ced3108..13f5e136289 100644 --- a/accessible/public/nsIAccessibleText.idl +++ b/accessible/public/nsIAccessibleText.idl @@ -9,9 +9,11 @@ typedef long AccessibleTextBoundary; interface nsIAccessible; +interface nsIArray; interface nsIPersistentProperties; +interface nsIAccessibleTextRange; -[scriptable, uuid(1e63dd8b-173d-4a68-8ade-fd671abbe1ee)] +[scriptable, uuid(88789f40-54c9-494a-846d-3acaaf4cf46a)] interface nsIAccessibleText : nsISupports { // In parameters for character offsets: @@ -189,6 +191,34 @@ interface nsIAccessibleText : nsISupports void scrollSubstringToPoint(in long startIndex, in long endIndex, in unsigned long coordinateType, in long x, in long y); + + /** + * Return a range that encloses this text control or otherwise the document + * this text accessible belongs to. + */ + readonly attribute nsIAccessibleTextRange enclosingRange; + + /** + * Return an array of disjoint ranges for selected text within the text control + * or otherwise the document this accessible belongs to. + */ + readonly attribute nsIArray selectionRanges; + + /** + * Return an array of disjoint ranges of visible text within the text control + * or otherwise the document this accessible belongs to. + */ + readonly attribute nsIArray visibleRanges; + + /** + * Return a range containing the given accessible. + */ + nsIAccessibleTextRange getRangeByChild(in nsIAccessible child); + + /** + * Return a range containing an accessible at the given point. + */ + nsIAccessibleTextRange getRangeAtPoint(in long x, in long y); }; /* diff --git a/accessible/public/nsIAccessibleTextRange.idl b/accessible/public/nsIAccessibleTextRange.idl new file mode 100644 index 00000000000..3e272e89a1b --- /dev/null +++ b/accessible/public/nsIAccessibleTextRange.idl @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +interface nsIAccessible; + +/** + * A range representing a piece of text in the document. + */ +[scriptable, uuid(6fe17c33-6709-4d7a-9ba0-3d448c4b3ef4)] +interface nsIAccessibleTextRange : nsISupports +{ + readonly attribute nsIAccessible startContainer; + readonly attribute long startOffset; + readonly attribute nsIAccessible endContainer; + readonly attribute long endOffset; + + /** + * Return text within the range. + */ + readonly attribute AString text; +}; diff --git a/accessible/src/base/TextRange.cpp b/accessible/src/base/TextRange.cpp new file mode 100644 index 00000000000..76ea49eecea --- /dev/null +++ b/accessible/src/base/TextRange.cpp @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "TextRange.h" + +#include "HyperTextAccessible.h" + +using namespace mozilla::a11y; + +TextRange::TextRange(HyperTextAccessible* aRoot, + Accessible* aStartContainer, int32_t aStartOffset, + Accessible* aEndContainer, int32_t aEndOffset) : + mRoot(aRoot), mStartContainer(aStartContainer), mEndContainer(aEndContainer), + mStartOffset(aStartOffset), mEndOffset(aEndOffset) +{ +} + +void +TextRange::Text(nsAString& aText) const +{ + +} diff --git a/accessible/src/base/TextRange.h b/accessible/src/base/TextRange.h new file mode 100644 index 00000000000..0d3591f9321 --- /dev/null +++ b/accessible/src/base/TextRange.h @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_a11y_TextRange_h__ +#define mozilla_a11y_TextRange_h__ + +#include "mozilla/Move.h" +#include "nsAutoPtr.h" + +namespace mozilla { +namespace a11y { + +class Accessible; +class HyperTextAccessible; + +/** + * Represents a text range within the text control or document. + */ +class TextRange MOZ_FINAL +{ +public: + TextRange(HyperTextAccessible* aRoot, + Accessible* aStartContainer, int32_t aStartOffset, + Accessible* aEndContainer, int32_t aEndOffset); + TextRange() {} + TextRange(TextRange&& aRange) : + mRoot(Move(aRange.mRoot)), mStartContainer(Move(aRange.mStartContainer)), + mEndContainer(Move(aRange.mEndContainer)), + mStartOffset(aRange.mStartOffset), mEndOffset(aRange.mEndOffset) {} + + Accessible* StartContainer() const { return mStartContainer; } + int32_t StartOffset() const { return mStartOffset; } + Accessible* EndContainer() const { return mEndContainer; } + int32_t EndOffset() const { return mEndOffset; } + + /** + * Return text enclosed by the range. + */ + void Text(nsAString& aText) const; + + /** + * Return true if this TextRange object represents an actual range of text. + */ + bool IsValid() const { return mRoot; } + +private: + friend class HyperTextAccessible; + + TextRange(const TextRange&) MOZ_DELETE; + TextRange& operator=(const TextRange&) MOZ_DELETE; + + const nsRefPtr mRoot; + nsRefPtr mStartContainer; + nsRefPtr mEndContainer; + int32_t mStartOffset; + int32_t mEndOffset; +}; + + +} // namespace a11y +} // namespace mozilla + +#endif diff --git a/accessible/src/base/moz.build b/accessible/src/base/moz.build index cef7fc56f6c..8b58f01a681 100644 --- a/accessible/src/base/moz.build +++ b/accessible/src/base/moz.build @@ -47,6 +47,7 @@ UNIFIED_SOURCES += [ 'SelectionManager.cpp', 'StyleInfo.cpp', 'TextAttrs.cpp', + 'TextRange.cpp', 'TextUpdater.cpp', 'TreeWalker.cpp', ] diff --git a/accessible/src/generic/HyperTextAccessible.cpp b/accessible/src/generic/HyperTextAccessible.cpp index 031a037f8dc..584981b5fd0 100644 --- a/accessible/src/generic/HyperTextAccessible.cpp +++ b/accessible/src/generic/HyperTextAccessible.cpp @@ -14,6 +14,7 @@ #include "Role.h" #include "States.h" #include "TextAttrs.h" +#include "TextRange.h" #include "TreeWalker.h" #include "nsCaret.h" @@ -1504,6 +1505,33 @@ HyperTextAccessible::ScrollSubstringToPoint(int32_t aStartOffset, } } +void +HyperTextAccessible::EnclosingRange(a11y::TextRange& aRange) const +{ +} + +void +HyperTextAccessible::SelectionRanges(nsTArray* aRanges) const +{ +} + +void +HyperTextAccessible::VisibleRanges(nsTArray* aRanges) const +{ +} + +void +HyperTextAccessible::RangeByChild(Accessible* aChild, + a11y::TextRange& aRange) const +{ +} + +void +HyperTextAccessible::RangeAtPoint(int32_t aX, int32_t aY, + a11y::TextRange& aRange) const +{ +} + //////////////////////////////////////////////////////////////////////////////// // Accessible public diff --git a/accessible/src/generic/HyperTextAccessible.h b/accessible/src/generic/HyperTextAccessible.h index 726414926e1..04bb152389a 100644 --- a/accessible/src/generic/HyperTextAccessible.h +++ b/accessible/src/generic/HyperTextAccessible.h @@ -16,6 +16,8 @@ namespace mozilla { namespace a11y { +class TextRange; + struct DOMPoint { DOMPoint() : node(nullptr), idx(0) { } DOMPoint(nsINode* aNode, int32_t aIdx) : node(aNode), idx(aIdx) { } @@ -361,6 +363,34 @@ public: uint32_t aCoordinateType, int32_t aX, int32_t aY); + /** + * Return a range that encloses the text control or the document this + * accessible belongs to. + */ + void EnclosingRange(TextRange& aRange) const; + + /** + * Return an array of disjoint ranges for selected text within the text control + * or the document this accessible belongs to. + */ + void SelectionRanges(nsTArray* aRanges) const; + + /** + * Return an array of disjoint ranges of visible text within the text control + * or the document this accessible belongs to. + */ + void VisibleRanges(nsTArray* aRanges) const; + + /** + * Return a range containing the given accessible. + */ + void RangeByChild(Accessible* aChild, TextRange& aRange) const; + + /** + * Return a range containing an accessible at the given point. + */ + void RangeAtPoint(int32_t aX, int32_t aY, TextRange& aRange) const; + ////////////////////////////////////////////////////////////////////////////// // EditableTextAccessible diff --git a/accessible/src/xpcom/moz.build b/accessible/src/xpcom/moz.build index 3f964b45023..787ff508458 100644 --- a/accessible/src/xpcom/moz.build +++ b/accessible/src/xpcom/moz.build @@ -16,6 +16,7 @@ UNIFIED_SOURCES += [ 'xpcAccessibleSelectable.cpp', 'xpcAccessibleTable.cpp', 'xpcAccessibleTableCell.cpp', + 'xpcAccessibleTextRange.cpp', 'xpcAccessibleValue.cpp', ] diff --git a/accessible/src/xpcom/xpcAccessibleHyperText.cpp b/accessible/src/xpcom/xpcAccessibleHyperText.cpp index 7de17843b7e..8e19a855b59 100644 --- a/accessible/src/xpcom/xpcAccessibleHyperText.cpp +++ b/accessible/src/xpcom/xpcAccessibleHyperText.cpp @@ -7,8 +7,11 @@ #include "xpcAccessibleHyperText.h" #include "HyperTextAccessible-inl.h" +#include "TextRange.h" +#include "xpcAccessibleTextRange.h" #include "nsIPersistentProperties2.h" +#include "nsIMutableArray.h" using namespace mozilla::a11y; @@ -363,6 +366,119 @@ xpcAccessibleHyperText::ScriptableScrollSubstringToPoint(int32_t aStartOffset, return NS_OK; } +NS_IMETHODIMP +xpcAccessibleHyperText::GetEnclosingRange(nsIAccessibleTextRange** aRange) +{ + NS_ENSURE_ARG_POINTER(aRange); + *aRange = nullptr; + + HyperTextAccessible* text = static_cast(this); + if (text->IsDefunct()) + return NS_ERROR_FAILURE; + + nsRefPtr range = new xpcAccessibleTextRange; + text->EnclosingRange(range->mRange); + NS_ASSERTION(range->mRange.IsValid(), + "Should always have an enclosing range!"); + + range.forget(aRange); + + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibleHyperText::GetSelectionRanges(nsIArray** aRanges) +{ + NS_ENSURE_ARG_POINTER(aRanges); + *aRanges = nullptr; + + HyperTextAccessible* text = static_cast(this); + if (text->IsDefunct()) + return NS_ERROR_FAILURE; + + nsresult rv = NS_OK; + nsCOMPtr xpcRanges = + do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoTArray ranges; + text->SelectionRanges(&ranges); + uint32_t len = ranges.Length(); + for (uint32_t idx = 0; idx < len; idx++) + xpcRanges->AppendElement(new xpcAccessibleTextRange(Move(ranges[idx])), + false); + + xpcRanges.forget(aRanges); + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibleHyperText::GetVisibleRanges(nsIArray** aRanges) +{ + NS_ENSURE_ARG_POINTER(aRanges); + *aRanges = nullptr; + + HyperTextAccessible* text = static_cast(this); + if (text->IsDefunct()) + return NS_ERROR_FAILURE; + + nsresult rv = NS_OK; + nsCOMPtr xpcRanges = + do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsTArray ranges; + text->VisibleRanges(&ranges); + uint32_t len = ranges.Length(); + for (uint32_t idx = 0; idx < len; idx++) + xpcRanges->AppendElement(new xpcAccessibleTextRange(Move(ranges[idx])), + false); + + xpcRanges.forget(aRanges); + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibleHyperText::GetRangeByChild(nsIAccessible* aChild, + nsIAccessibleTextRange** aRange) +{ + NS_ENSURE_ARG_POINTER(aRange); + *aRange = nullptr; + + HyperTextAccessible* text = static_cast(this); + if (text->IsDefunct()) + return NS_ERROR_FAILURE; + + nsRefPtr child = do_QueryObject(aChild); + if (child) { + nsRefPtr range = new xpcAccessibleTextRange; + text->RangeByChild(child, range->mRange); + if (range->mRange.IsValid()) + range.forget(aRange); + } + + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibleHyperText::GetRangeAtPoint(int32_t aX, int32_t aY, + nsIAccessibleTextRange** aRange) +{ + NS_ENSURE_ARG_POINTER(aRange); + *aRange = nullptr; + + HyperTextAccessible* text = static_cast(this); + if (text->IsDefunct()) + return NS_ERROR_FAILURE; + + nsRefPtr range = new xpcAccessibleTextRange; + text->RangeAtPoint(aX, aY, range->mRange); + if (range->mRange.IsValid()) + range.forget(aRange); + + return NS_OK; +} + //////////////////////////////////////////////////////////////////////////////// // nsIAccessibleEditableText diff --git a/accessible/src/xpcom/xpcAccessibleTextRange.cpp b/accessible/src/xpcom/xpcAccessibleTextRange.cpp new file mode 100644 index 00000000000..6c9f3f6cfc2 --- /dev/null +++ b/accessible/src/xpcom/xpcAccessibleTextRange.cpp @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xpcAccessibleTextRange.h" + +#include "HyperTextAccessible.h" +#include "TextRange.h" + +using namespace mozilla; +using namespace mozilla::a11y; + +// nsISupports +NS_IMPL_ISUPPORTS1(xpcAccessibleTextRange, nsIAccessibleTextRange) + +// nsIAccessibleTextRange + +NS_IMETHODIMP +xpcAccessibleTextRange::GetStartContainer(nsIAccessible** aAnchor) +{ + NS_ENSURE_ARG_POINTER(aAnchor); + *aAnchor = static_cast(mRange.StartContainer()); + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibleTextRange::GetStartOffset(int32_t* aOffset) +{ + NS_ENSURE_ARG_POINTER(aOffset); + *aOffset = mRange.StartOffset(); + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibleTextRange::GetEndContainer(nsIAccessible** aAnchor) +{ + NS_ENSURE_ARG_POINTER(aAnchor); + *aAnchor = static_cast(mRange.EndContainer()); + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibleTextRange::GetEndOffset(int32_t* aOffset) +{ + NS_ENSURE_ARG_POINTER(aOffset); + *aOffset = mRange.EndOffset(); + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibleTextRange::GetText(nsAString& aText) +{ + nsAutoString text; + mRange.Text(text); + aText.Assign(text); + + return NS_OK; +} diff --git a/accessible/src/xpcom/xpcAccessibleTextRange.h b/accessible/src/xpcom/xpcAccessibleTextRange.h new file mode 100644 index 00000000000..5873efd6b32 --- /dev/null +++ b/accessible/src/xpcom/xpcAccessibleTextRange.h @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_a11y_xpcAccessibleTextRange_h_ +#define mozilla_a11y_xpcAccessibleTextRange_h_ + +#include "nsIAccessibleTextRange.h" +#include "TextRange.h" + +#include "mozilla/Move.h" + +namespace mozilla { +namespace a11y { + +class TextRange; + +class xpcAccessibleTextRange MOZ_FINAL : public nsIAccessibleTextRange +{ +public: + NS_DECL_ISUPPORTS + + NS_IMETHOD GetStartContainer(nsIAccessible** aAnchor) MOZ_FINAL MOZ_OVERRIDE; + NS_IMETHOD GetStartOffset(int32_t* aOffset) MOZ_FINAL MOZ_OVERRIDE; + NS_IMETHOD GetEndContainer(nsIAccessible** aAnchor) MOZ_FINAL MOZ_OVERRIDE; + NS_IMETHOD GetEndOffset(int32_t* aOffset) MOZ_FINAL MOZ_OVERRIDE; + NS_IMETHOD GetText(nsAString& aText) MOZ_FINAL MOZ_OVERRIDE; + +private: + xpcAccessibleTextRange(TextRange&& aRange) : + mRange(Forward(aRange)) {} + xpcAccessibleTextRange() {} + friend class xpcAccessibleHyperText; + + xpcAccessibleTextRange(const xpcAccessibleTextRange&) MOZ_DELETE; + xpcAccessibleTextRange& operator =(const xpcAccessibleTextRange&) MOZ_DELETE; + + TextRange mRange; +}; + +} // namespace a11y +} // namespace mozilla + +#endif