зеркало из https://github.com/mozilla/pjs.git
bug 345759 - Spell as you type not accessible, r=aaronlev, r=Olli.Pettay, sr=neil
This commit is contained in:
Родитель
5be0106a1f
Коммит
4cae867614
|
@ -44,8 +44,9 @@
|
|||
typedef long nsAccessibleTextBoundary;
|
||||
|
||||
interface nsIAccessible;
|
||||
interface nsIPersistentProperties;
|
||||
|
||||
[scriptable, uuid(caa4f543-070e-4705-8428-2e53575c41bb)]
|
||||
[scriptable, uuid(0f4633b1-550c-4b50-8c04-0eb1005eef2f)]
|
||||
interface nsIAccessibleText : nsISupports
|
||||
{
|
||||
// In parameters for character offsets:
|
||||
|
@ -102,13 +103,24 @@ interface nsIAccessibleText : nsISupports
|
|||
wchar getCharacterAtOffset (in long offset);
|
||||
|
||||
/**
|
||||
* Get the accessible and start/end offsets around the given offset.
|
||||
* This accessible get return the DOM node and layout frame
|
||||
* with the uniform attributes for this range of text
|
||||
* Get the accessible start/end offsets around the given offset,
|
||||
* return the text attributes for this range of text.
|
||||
*
|
||||
* @param includeDefAttrs [in] points whether text attributes applied to
|
||||
* the entire accessible should be included or not.
|
||||
* @param offset [in] text offset
|
||||
* @param rangeStartOffset [out] start offset of the range of text
|
||||
* @param rangeEndOffset [out] end offset of the range of text
|
||||
*/
|
||||
nsIAccessible getAttributeRange (in long offset,
|
||||
out long rangeStartOffset,
|
||||
out long rangeEndOffset);
|
||||
nsIPersistentProperties getTextAttributes(in boolean includeDefAttrs,
|
||||
in long offset,
|
||||
out long rangeStartOffset,
|
||||
out long rangeEndOffset);
|
||||
|
||||
/**
|
||||
* Return the text attributes that apply to the entire accessible.
|
||||
*/
|
||||
readonly attribute nsIPersistentProperties defaultTextAttributes;
|
||||
|
||||
/**
|
||||
* Returns the bounding box of the specified position.
|
||||
|
@ -223,11 +235,6 @@ interface nsIAccessibleText : nsISupports
|
|||
(since not every text component will allow every operation):
|
||||
setSelectionBounds, addSelection, removeSelection, setCaretOffset.
|
||||
|
||||
getRangeAttributes defined to return an nsISupports
|
||||
interface instead of a pango specific data structure.
|
||||
It may be that some other return type is more appropriate
|
||||
for mozilla text attributes.
|
||||
|
||||
we assume that all text components support the idea of
|
||||
a caret offset, whether visible or "virtual". If this
|
||||
isn't the case, caretOffset can be made readonly and
|
||||
|
|
|
@ -786,13 +786,50 @@ getRoleCB(AtkObject *aAtkObj)
|
|||
return aAtkObj->role;
|
||||
}
|
||||
|
||||
AtkAttributeSet*
|
||||
ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes)
|
||||
{
|
||||
if (!aAttributes)
|
||||
return nsnull;
|
||||
|
||||
AtkAttributeSet *objAttributeSet = nsnull;
|
||||
nsCOMPtr<nsISimpleEnumerator> propEnum;
|
||||
nsresult rv = aAttributes->Enumerate(getter_AddRefs(propEnum));
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
PRBool hasMore;
|
||||
while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
|
||||
nsCOMPtr<nsISupports> sup;
|
||||
rv = propEnum->GetNext(getter_AddRefs(sup));
|
||||
NS_ENSURE_SUCCESS(rv, objAttributeSet);
|
||||
|
||||
nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(sup));
|
||||
NS_ENSURE_TRUE(propElem, objAttributeSet);
|
||||
|
||||
nsCAutoString name;
|
||||
rv = propElem->GetKey(name);
|
||||
NS_ENSURE_SUCCESS(rv, objAttributeSet);
|
||||
|
||||
nsAutoString value;
|
||||
rv = propElem->GetValue(value);
|
||||
NS_ENSURE_SUCCESS(rv, objAttributeSet);
|
||||
|
||||
AtkAttribute *objAttr = (AtkAttribute *)g_malloc(sizeof(AtkAttribute));
|
||||
objAttr->name = g_strdup(name.get());
|
||||
objAttr->value = g_strdup(NS_ConvertUTF16toUTF8(value).get());
|
||||
objAttributeSet = g_slist_prepend(objAttributeSet, objAttr);
|
||||
}
|
||||
|
||||
//libspi will free it
|
||||
return objAttributeSet;
|
||||
}
|
||||
|
||||
AtkAttributeSet *
|
||||
GetAttributeSet(nsIAccessible* aAccessible)
|
||||
{
|
||||
AtkAttributeSet *objAttributeSet = nsnull;
|
||||
nsCOMPtr<nsIPersistentProperties> attributes;
|
||||
aAccessible->GetAttributes(getter_AddRefs(attributes));
|
||||
|
||||
|
||||
if (attributes) {
|
||||
// Deal with attributes that we only need to expose in ATK
|
||||
PRUint32 state;
|
||||
|
@ -804,33 +841,10 @@ GetAttributeSet(nsIAccessible* aAccessible)
|
|||
oldValueUnused);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> propEnum;
|
||||
nsresult rv = attributes->Enumerate(getter_AddRefs(propEnum));
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
PRBool hasMore;
|
||||
while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
|
||||
nsCOMPtr<nsISupports> sup;
|
||||
rv = propEnum->GetNext(getter_AddRefs(sup));
|
||||
nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(sup));
|
||||
NS_ENSURE_TRUE(propElem, nsnull);
|
||||
|
||||
nsCAutoString name;
|
||||
rv = propElem->GetKey(name);
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
nsAutoString value;
|
||||
rv = propElem->GetValue(value);
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
AtkAttribute *objAttribute = (AtkAttribute *)g_malloc(sizeof(AtkAttribute));
|
||||
objAttribute->name = g_strdup(name.get());
|
||||
objAttribute->value = g_strdup(NS_ConvertUTF16toUTF8(value).get());
|
||||
objAttributeSet = g_slist_prepend(objAttributeSet, objAttribute);
|
||||
}
|
||||
return ConvertToAtkAttributeSet(attributes);
|
||||
}
|
||||
|
||||
return objAttributeSet;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
AtkAttributeSet *
|
||||
|
@ -1197,6 +1211,13 @@ nsAccessibleWrap::FirePlatformEvent(nsIAccessibleEvent *aEvent)
|
|||
caretOffset);
|
||||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED:
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TEXT_ATTRIBUTE_CHANGED\n"));
|
||||
|
||||
g_signal_emit_by_name(atkObj,
|
||||
"text-attributes-changed");
|
||||
break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_TABLE_MODEL_CHANGED:
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_MODEL_CHANGED\n"));
|
||||
g_signal_emit_by_name(atkObj, "model_changed");
|
||||
|
|
|
@ -41,8 +41,9 @@
|
|||
|
||||
#include "nsMaiInterfaceText.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
|
||||
AtkAttributeSet * GetAttributeSet(nsIAccessible* aAccessible);
|
||||
AtkAttributeSet* ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes);
|
||||
|
||||
void
|
||||
textInterfaceInitCB(AtkTextIface *aIface)
|
||||
|
@ -245,6 +246,9 @@ getRunAttributesCB(AtkText *aText, gint aOffset,
|
|||
gint *aStartOffset,
|
||||
gint *aEndOffset)
|
||||
{
|
||||
*aStartOffset = -1;
|
||||
*aEndOffset = -1;
|
||||
|
||||
nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
|
||||
if (!accWrap)
|
||||
return nsnull;
|
||||
|
@ -254,24 +258,37 @@ getRunAttributesCB(AtkText *aText, gint aOffset,
|
|||
getter_AddRefs(accText));
|
||||
NS_ENSURE_TRUE(accText, nsnull);
|
||||
|
||||
nsCOMPtr<nsIAccessible> accessibleWithAttrs;
|
||||
nsCOMPtr<nsIPersistentProperties> attributes;
|
||||
PRInt32 startOffset = 0, endOffset = 0;
|
||||
nsresult rv =
|
||||
accText->GetAttributeRange(aOffset, &startOffset, &endOffset,
|
||||
getter_AddRefs(accessibleWithAttrs));
|
||||
nsresult rv = accText->GetTextAttributes(PR_FALSE, aOffset,
|
||||
&startOffset, &endOffset,
|
||||
getter_AddRefs(attributes));
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
*aStartOffset = startOffset;
|
||||
*aEndOffset = endOffset;
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
|
||||
return GetAttributeSet(accessibleWithAttrs);
|
||||
return ConvertToAtkAttributeSet(attributes);
|
||||
}
|
||||
|
||||
AtkAttributeSet *
|
||||
getDefaultAttributesCB(AtkText *aText)
|
||||
{
|
||||
/* not supported ??? */
|
||||
return nsnull;
|
||||
nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
|
||||
if (!accWrap)
|
||||
return nsnull;
|
||||
|
||||
nsCOMPtr<nsIAccessibleText> accText;
|
||||
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
|
||||
getter_AddRefs(accText));
|
||||
NS_ENSURE_TRUE(accText, nsnull);
|
||||
|
||||
nsCOMPtr<nsIPersistentProperties> attributes;
|
||||
nsresult rv = accText->GetDefaultTextAttributes(getter_AddRefs(attributes));
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
|
||||
return ConvertToAtkAttributeSet(attributes);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -90,6 +90,7 @@ CPPSRCS = \
|
|||
nsApplicationAccessible.cpp \
|
||||
nsCaretAccessible.cpp \
|
||||
nsTextAccessible.cpp \
|
||||
nsTextUtils.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
|
|
|
@ -876,10 +876,7 @@ nsAccessNode::GetLanguage(nsAString& aLanguage)
|
|||
}
|
||||
}
|
||||
|
||||
nsIContent *walkUp = content;
|
||||
while (walkUp && !walkUp->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::lang, aLanguage)) {
|
||||
walkUp = walkUp->GetParent();
|
||||
}
|
||||
nsAccUtils::GetLanguageFor(content, nsnull, aLanguage);
|
||||
|
||||
if (aLanguage.IsEmpty()) { // Nothing found, so use document's language
|
||||
nsIDocument *doc = content->GetOwnerDoc();
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAccessibilityAtoms.h"
|
||||
#include "nsAccessibilityUtils.h"
|
||||
|
||||
#include "nsIAccessibleTypes.h"
|
||||
#include "nsIAccessNode.h"
|
||||
#include "nsIContent.h"
|
||||
|
|
|
@ -149,7 +149,7 @@ ACCESSIBILITY_ATOM(tooltip, "tooltip") // XUL
|
|||
ACCESSIBILITY_ATOM(tr, "tr")
|
||||
ACCESSIBILITY_ATOM(ul, "ul")
|
||||
|
||||
// Alphabetical list of attributes
|
||||
// Alphabetical list of attributes (DOM)
|
||||
ACCESSIBILITY_ATOM(acceltext, "acceltext")
|
||||
ACCESSIBILITY_ATOM(accesskey, "accesskey")
|
||||
ACCESSIBILITY_ATOM(alt, "alt")
|
||||
|
@ -186,6 +186,10 @@ ACCESSIBILITY_ATOM(tooltiptext, "tooltiptext")
|
|||
ACCESSIBILITY_ATOM(type, "type")
|
||||
ACCESSIBILITY_ATOM(value, "value")
|
||||
|
||||
// Alphabetical list of text attributes (AT API)
|
||||
ACCESSIBILITY_ATOM(invalid, "invalid")
|
||||
ACCESSIBILITY_ATOM(language, "language")
|
||||
|
||||
// ARIA (DHTML accessibility) attributes
|
||||
// Also add to nsARIAMap.cpp and nsARIAMap.h
|
||||
// ARIA role attribute
|
||||
|
|
|
@ -340,6 +340,24 @@ nsAccUtils::FireAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible,
|
|||
return pAccessible->FireAccessibleEvent(event);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMElement>
|
||||
nsAccUtils::GetDOMElementFor(nsIDOMNode *aNode)
|
||||
{
|
||||
nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
|
||||
|
||||
nsIDOMElement *element = nsnull;
|
||||
if (node->IsNodeOfType(nsINode::eELEMENT))
|
||||
CallQueryInterface(node, &element);
|
||||
else if (node->IsNodeOfType(nsINode::eTEXT))
|
||||
CallQueryInterface(node->GetNodeParent(), &element);
|
||||
else if (node->IsNodeOfType(nsINode::eDOCUMENT)) {
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(node));
|
||||
domDoc->GetDocumentElement(&element);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsAccUtils::IsAncestorOf(nsIDOMNode *aPossibleAncestorNode,
|
||||
nsIDOMNode *aPossibleDescendantNode)
|
||||
|
@ -921,6 +939,19 @@ nsAccUtils::FindDescendantPointingToIDImpl(nsCString& aIdWithSpaces,
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsAccUtils::GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
|
||||
nsAString& aLanguage)
|
||||
{
|
||||
aLanguage.Truncate();
|
||||
|
||||
nsIContent *walkUp = aContent;
|
||||
while (walkUp && walkUp != aRootContent &&
|
||||
!walkUp->GetAttr(kNameSpaceID_None,
|
||||
nsAccessibilityAtoms::lang, aLanguage))
|
||||
walkUp = walkUp->GetParent();
|
||||
}
|
||||
|
||||
nsRoleMapEntry*
|
||||
nsAccUtils::GetRoleMapEntry(nsIDOMNode *aNode)
|
||||
{
|
||||
|
|
|
@ -138,6 +138,16 @@ public:
|
|||
static nsresult FireAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible,
|
||||
PRBool aIsAsynch = PR_FALSE);
|
||||
|
||||
/**
|
||||
* Return DOM element related with the given node, i.e.
|
||||
* a) itself if it is DOM element
|
||||
* b) parent element if it is text node
|
||||
* c) document element if it is document node.
|
||||
*
|
||||
* @param aNode [in] the given DOM node
|
||||
*/
|
||||
static already_AddRefed<nsIDOMElement> GetDOMElementFor(nsIDOMNode *aNode);
|
||||
|
||||
/**
|
||||
* Is the first passed in node an ancestor of the second?
|
||||
* Note: A node is not considered to be the ancestor of itself.
|
||||
|
@ -302,6 +312,16 @@ public:
|
|||
*/
|
||||
static PRBool IsXLink(nsIContent *aContent);
|
||||
|
||||
/**
|
||||
* Returns language for the given node.
|
||||
*
|
||||
* @param aContent [in] the given node
|
||||
* @param aRootContent [in] container of the given node
|
||||
* @param aLanguage [out] language
|
||||
*/
|
||||
static void GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
|
||||
nsAString& aLanguage);
|
||||
|
||||
/**
|
||||
* Get the role map entry for a given DOM node. This will use the first
|
||||
* ARIA role if the role attribute provides a space delimited list of roles.
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#define _nsAccessible_H_
|
||||
|
||||
#include "nsAccessNodeWrap.h"
|
||||
#include "nsAccessibilityUtils.h"
|
||||
|
||||
#include "nsIAccessible.h"
|
||||
#include "nsPIAccessible.h"
|
||||
|
|
|
@ -47,8 +47,8 @@
|
|||
#include "nsIFrame.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsRootAccessible.h"
|
||||
#include "nsISelectionController.h"
|
||||
#include "nsISelectionPrivate.h"
|
||||
#include "nsISelection2.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIWidget.h"
|
||||
|
@ -78,13 +78,31 @@ void nsCaretAccessible::Shutdown()
|
|||
|
||||
nsresult nsCaretAccessible::ClearControlSelectionListener()
|
||||
{
|
||||
mCurrentControl = nsnull;
|
||||
mCurrentControlSelection = nsnull;
|
||||
nsCOMPtr<nsISelectionController> controller =
|
||||
GetSelectionControllerForNode(mCurrentControl);
|
||||
|
||||
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryReferent(mCurrentControlSelection));
|
||||
if (!selPrivate) {
|
||||
mCurrentControl = nsnull;
|
||||
|
||||
if (!controller)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Remove 'this' registered as selection listener for the normal selection.
|
||||
nsCOMPtr<nsISelection> normalSel;
|
||||
controller->GetSelection(nsISelectionController::SELECTION_NORMAL,
|
||||
getter_AddRefs(normalSel));
|
||||
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(normalSel));
|
||||
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv = selPrivate->RemoveSelectionListener(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Remove 'this' registered as selection listener for the spellcheck
|
||||
// selection.
|
||||
nsCOMPtr<nsISelection> spellcheckSel;
|
||||
controller->GetSelection(nsISelectionController::SELECTION_SPELLCHECK,
|
||||
getter_AddRefs(spellcheckSel));
|
||||
selPrivate = do_QueryInterface(spellcheckSel);
|
||||
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
|
||||
|
||||
return selPrivate->RemoveSelectionListener(this);
|
||||
}
|
||||
|
@ -99,39 +117,29 @@ nsresult nsCaretAccessible::SetControlSelectionListener(nsIDOMNode *aCurrentNode
|
|||
mLastTextAccessible = nsnull;
|
||||
|
||||
// When focus moves such that the caret is part of a new frame selection
|
||||
// this removes the old selection listener and attaches a new one for the current focus
|
||||
nsCOMPtr<nsIPresShell> presShell =
|
||||
mRootAccessible->GetPresShellFor(aCurrentNode);
|
||||
if (!presShell)
|
||||
return NS_ERROR_FAILURE;
|
||||
// this removes the old selection listener and attaches a new one for
|
||||
// the current focus.
|
||||
nsCOMPtr<nsISelectionController> controller =
|
||||
GetSelectionControllerForNode(mCurrentControl);
|
||||
NS_ENSURE_TRUE(controller, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = presShell->GetDocument();
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aCurrentNode));
|
||||
// The control selection listener is only for form controls, not for the document
|
||||
// When there is no document, the content will be null
|
||||
if (!content) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIFrame *frame = presShell->GetPrimaryFrameFor(content);
|
||||
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
|
||||
|
||||
nsPresContext *presContext = presShell->GetPresContext();
|
||||
NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsISelectionController> selCon;
|
||||
frame->GetSelectionController(presContext, getter_AddRefs(selCon));
|
||||
NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsISelection> domSel;
|
||||
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel));
|
||||
|
||||
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(domSel));
|
||||
// Register 'this' as selection listener for the normal selection.
|
||||
nsCOMPtr<nsISelection> normalSel;
|
||||
controller->GetSelection(nsISelectionController::SELECTION_NORMAL,
|
||||
getter_AddRefs(normalSel));
|
||||
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(normalSel));
|
||||
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
|
||||
|
||||
mCurrentControlSelection = do_GetWeakReference(domSel);
|
||||
nsresult rv = selPrivate->AddSelectionListener(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Register 'this' as selection listener for the spellcheck selection.
|
||||
nsCOMPtr<nsISelection> spellcheckSel;
|
||||
controller->GetSelection(nsISelectionController::SELECTION_SPELLCHECK,
|
||||
getter_AddRefs(spellcheckSel));
|
||||
selPrivate = do_QueryInterface(spellcheckSel);
|
||||
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
|
||||
|
||||
return selPrivate->AddSelectionListener(this);
|
||||
}
|
||||
|
||||
|
@ -148,6 +156,15 @@ nsCaretAccessible::AddDocSelectionListener(nsIPresShell *aShell)
|
|||
nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(domSel);
|
||||
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv = selPrivate->AddSelectionListener(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsISelection> spellcheckSel;
|
||||
selCon->GetSelection(nsISelectionController::SELECTION_SPELLCHECK,
|
||||
getter_AddRefs(spellcheckSel));
|
||||
selPrivate = do_QueryInterface(spellcheckSel);
|
||||
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
|
||||
|
||||
return selPrivate->AddSelectionListener(this);
|
||||
}
|
||||
|
||||
|
@ -162,10 +179,39 @@ nsCaretAccessible::RemoveDocSelectionListener(nsIPresShell *aShell)
|
|||
nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(domSel);
|
||||
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
|
||||
|
||||
selPrivate->RemoveSelectionListener(this);
|
||||
|
||||
nsCOMPtr<nsISelection> spellcheckSel;
|
||||
selCon->GetSelection(nsISelectionController::SELECTION_SPELLCHECK,
|
||||
getter_AddRefs(spellcheckSel));
|
||||
selPrivate = do_QueryInterface(spellcheckSel);
|
||||
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
|
||||
|
||||
return selPrivate->RemoveSelectionListener(this);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel, PRInt16 aReason)
|
||||
NS_IMETHODIMP
|
||||
nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc,
|
||||
nsISelection *aSel,
|
||||
PRInt16 aReason)
|
||||
{
|
||||
nsCOMPtr<nsISelection2> sel2(do_QueryInterface(aSel));
|
||||
|
||||
PRInt16 type = 0;
|
||||
sel2->GetType(&type);
|
||||
|
||||
if (type == nsISelectionController::SELECTION_NORMAL)
|
||||
return NormalSelectionChanged(aDoc, aSel);
|
||||
|
||||
if (type == nsISelectionController::SELECTION_SPELLCHECK)
|
||||
return SpellcheckSelectionChanged(aDoc, aSel);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCaretAccessible::NormalSelectionChanged(nsIDOMDocument *aDoc,
|
||||
nsISelection *aSel)
|
||||
{
|
||||
NS_ENSURE_TRUE(mRootAccessible, NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -247,6 +293,38 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns
|
|||
return mRootAccessible->FireDelayedAccessibleEvent(event);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCaretAccessible::SpellcheckSelectionChanged(nsIDOMDocument *aDoc,
|
||||
nsISelection *aSel)
|
||||
{
|
||||
// XXX: fire an event for accessible of focus node of the selection. If
|
||||
// spellchecking is enabled then we will fire the number of events for
|
||||
// the same accessible for newly appended range of the selection (for every
|
||||
// misspelled word). If spellchecking is disabled (for example,
|
||||
// @spellcheck="false" on html:body) then we won't fire any event.
|
||||
nsCOMPtr<nsIDOMNode> targetNode;
|
||||
aSel->GetFocusNode(getter_AddRefs(targetNode));
|
||||
if (!targetNode)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIAccessibleDocument> docAccessible =
|
||||
nsAccessNode::GetDocAccessibleFor(targetNode);
|
||||
NS_ENSURE_STATE(docAccessible);
|
||||
|
||||
nsCOMPtr<nsIAccessible> containerAccessible;
|
||||
nsresult rv =
|
||||
docAccessible->GetAccessibleInParentChain(targetNode, PR_TRUE,
|
||||
getter_AddRefs(containerAccessible));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAccessibleEvent> event =
|
||||
new nsAccEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED,
|
||||
containerAccessible, nsnull);
|
||||
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return mRootAccessible->FireAccessibleEvent(event);
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsCaretAccessible::GetCaretRect(nsIWidget **aOutWidget)
|
||||
{
|
||||
|
@ -317,3 +395,35 @@ nsCaretAccessible::GetCaretRect(nsIWidget **aOutWidget)
|
|||
return caretRect;
|
||||
}
|
||||
|
||||
already_AddRefed<nsISelectionController>
|
||||
nsCaretAccessible::GetSelectionControllerForNode(nsIDOMNode *aNode)
|
||||
{
|
||||
if (!aNode)
|
||||
return nsnull;
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = mRootAccessible->GetPresShellFor(aNode);
|
||||
if (!presShell)
|
||||
return nsnull;
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = presShell->GetDocument();
|
||||
if (!doc)
|
||||
return nsnull;
|
||||
|
||||
// Get selection controller only for form controls, not for the document.
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
|
||||
if (!content)
|
||||
return nsnull;
|
||||
|
||||
nsIFrame *frame = presShell->GetPrimaryFrameFor(content);
|
||||
if (!frame)
|
||||
return nsnull;
|
||||
|
||||
nsPresContext *presContext = presShell->GetPresContext();
|
||||
if (!presContext)
|
||||
return nsnull;
|
||||
|
||||
nsISelectionController *controller = nsnull;
|
||||
frame->GetSelectionController(presContext, &controller);
|
||||
return controller;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "nsIAccessibleText.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsISelectionListener.h"
|
||||
#include "nsISelectionController.h"
|
||||
#include "nsRect.h"
|
||||
|
||||
class nsRootAccessible;
|
||||
|
@ -120,17 +121,23 @@ public:
|
|||
|
||||
nsRect GetCaretRect(nsIWidget **aOutWidget);
|
||||
|
||||
protected:
|
||||
nsresult NormalSelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel);
|
||||
nsresult SpellcheckSelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel);
|
||||
|
||||
already_AddRefed<nsISelectionController>
|
||||
GetSelectionControllerForNode(nsIDOMNode *aNode);
|
||||
|
||||
private:
|
||||
// The currently focused control -- never a document.
|
||||
// We listen to selection for one control at a time (the focused one)
|
||||
// Document selection is handled separately via additional listeners on all active documents
|
||||
// The current control is set via SetControlSelectionListener()
|
||||
nsCOMPtr<nsIDOMNode> mCurrentControl; // Selection controller for the currently focused control
|
||||
nsCOMPtr<nsIWeakReference> mCurrentControlSelection;
|
||||
|
||||
// Info for the the last selection event
|
||||
// If it was on a control, then mLastUsedSelection == mCurrentControlSelection
|
||||
// Otherwise, it's for a document where the selection changed
|
||||
// Info for the the last selection event.
|
||||
// If it was on a control, then it's control's selection. Otherwise, it's for
|
||||
// a document where the selection changed.
|
||||
nsCOMPtr<nsIWeakReference> mLastUsedSelection; // Weak ref to nsISelection
|
||||
nsCOMPtr<nsIAccessibleText> mLastTextAccessible;
|
||||
PRInt32 mLastCaretOffset;
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
#include "nsAccessibilityAtoms.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "nsAccessibleTreeWalker.h"
|
||||
#include "nsTextUtils.h"
|
||||
|
||||
#include "nsPIAccessNode.h"
|
||||
#include "nsIClipboard.h"
|
||||
#include "nsContentCID.h"
|
||||
|
@ -50,6 +52,7 @@
|
|||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIDOMDocumentView.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsIDOMNSRange.h"
|
||||
#include "nsIDOMWindowInternal.h"
|
||||
#include "nsIDOMXULDocument.h"
|
||||
#include "nsIEditingSession.h"
|
||||
|
@ -671,7 +674,7 @@ nsresult nsHyperTextAccessible::DOMPointToHypertextOffset(nsIDOMNode* aNode, PRI
|
|||
// Start offset, inclusive
|
||||
// Make sure the offset lands on the embedded object character in order to indicate
|
||||
// the true inner offset is inside the subtree for that link
|
||||
addTextOffset = (TextLength(descendantAccessible) == addTextOffset) ? 1 : 0;
|
||||
addTextOffset = (TextLength(descendantAccessible) == static_cast<PRInt32>(addTextOffset)) ? 1 : 0;
|
||||
}
|
||||
descendantAccessible = parentAccessible;
|
||||
}
|
||||
|
@ -698,6 +701,18 @@ nsresult nsHyperTextAccessible::DOMPointToHypertextOffset(nsIDOMNode* aNode, PRI
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHyperTextAccessible::HypertextOffsetToDOMPoint(PRInt32 aHTOffset,
|
||||
nsIDOMNode **aNode,
|
||||
PRInt32 *aOffset)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> endNode;
|
||||
PRInt32 endOffset;
|
||||
|
||||
return HypertextOffsetsToDOMRange(aHTOffset, aHTOffset, aNode, aOffset,
|
||||
getter_AddRefs(endNode), &endOffset);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHyperTextAccessible::HypertextOffsetsToDOMRange(PRInt32 aStartHTOffset,
|
||||
PRInt32 aEndHTOffset,
|
||||
|
@ -888,11 +903,15 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
|
|||
// otherwise screen readers will announce the wrong line as the user presses up or down arrow and land
|
||||
// at the end of a line.
|
||||
nsCOMPtr<nsISelection> domSel;
|
||||
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
|
||||
nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
|
||||
nsnull, getter_AddRefs(domSel));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSel));
|
||||
nsCOMPtr<nsFrameSelection> frameSelection;
|
||||
rv = privateSelection->GetFrameSelection(getter_AddRefs(frameSelection));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (frameSelection->GetHint() == nsFrameSelection::HINTLEFT) {
|
||||
-- aOffset; // We are at the start of a line
|
||||
}
|
||||
|
@ -1071,31 +1090,103 @@ NS_IMETHODIMP nsHyperTextAccessible::GetTextAfterOffset(PRInt32 aOffset, nsAcces
|
|||
return GetTextHelper(eGetAfter, aBoundaryType, aOffset, aStartOffset, aEndOffset, aText);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHyperTextAccessible::GetAttributeRange(PRInt32 aOffset, PRInt32 *aRangeStartOffset,
|
||||
PRInt32 *aRangeEndOffset, nsIAccessible **aAccessibleWithAttrs)
|
||||
// nsIPersistentProperties
|
||||
// nsIAccessibleText::getTextAttributes(in boolean includeDefAttrs,
|
||||
// in long offset,
|
||||
// out long rangeStartOffset,
|
||||
// out long rangeEndOffset);
|
||||
NS_IMETHODIMP
|
||||
nsHyperTextAccessible::GetTextAttributes(PRBool aIncludeDefAttrs,
|
||||
PRInt32 aOffset,
|
||||
PRInt32 *aStartOffset,
|
||||
PRInt32 *aEndOffset,
|
||||
nsIPersistentProperties **aAttributes)
|
||||
{
|
||||
// Return the range of text with common attributes around aOffset
|
||||
*aRangeStartOffset = *aRangeEndOffset = 0;
|
||||
*aAccessibleWithAttrs = nsnull;
|
||||
// 1. First we get spell check, then language, then the set of CSS-based
|
||||
// attributes.
|
||||
// 2. As we get each new attribute, we pass the current start and end offsets
|
||||
// as in/out parameters. In other words, as attributes are collected,
|
||||
// the attribute range itself can only stay the same or get smaller.
|
||||
//
|
||||
// Example:
|
||||
// Current: range 5-10
|
||||
// Adding: range 7-12
|
||||
// Result: range 7-10
|
||||
|
||||
if (!mDOMNode) {
|
||||
NS_ENSURE_ARG_POINTER(aStartOffset);
|
||||
*aStartOffset = 0;
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aEndOffset);
|
||||
nsresult rv = GetCharacterCount(aEndOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aAttributes);
|
||||
*aAttributes = nsnull;
|
||||
|
||||
nsCOMPtr<nsIPersistentProperties> attributes =
|
||||
do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
|
||||
NS_ENSURE_TRUE(attributes, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
NS_ADDREF(*aAttributes = attributes);
|
||||
|
||||
if (!mDOMNode)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
|
||||
while (NextChild(accessible)) {
|
||||
PRInt32 length = TextLength(accessible);
|
||||
NS_ENSURE_TRUE(length >= 0, NS_ERROR_FAILURE);
|
||||
if (*aRangeStartOffset + length > aOffset) {
|
||||
*aRangeEndOffset = *aRangeStartOffset + length;
|
||||
NS_ADDREF(*aAccessibleWithAttrs = accessible);
|
||||
return NS_OK;
|
||||
}
|
||||
*aRangeStartOffset += length;
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
PRInt32 nodeOffset = 0;
|
||||
rv = HypertextOffsetToDOMPoint(aOffset, getter_AddRefs(node), &nodeOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
// Set 'misspelled' text attribute.
|
||||
rv = GetSpellTextAttribute(node, nodeOffset, aStartOffset, aEndOffset,
|
||||
*aAttributes);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(node));
|
||||
if (content && content->IsNodeOfType(nsINode::eELEMENT))
|
||||
node = do_QueryInterface(content->GetChildAt(nodeOffset));
|
||||
|
||||
if (!node)
|
||||
return NS_OK;
|
||||
|
||||
// Set 'lang' text attribute.
|
||||
rv = GetLangTextAttributes(aIncludeDefAttrs, node,
|
||||
aStartOffset, aEndOffset, *aAttributes);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Set CSS based text attributes.
|
||||
rv = GetCSSTextAttributes(aIncludeDefAttrs, node,
|
||||
aStartOffset, aEndOffset, *aAttributes);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// nsIPersistentProperties
|
||||
// nsIAccessibleText::defaultTextAttributes
|
||||
NS_IMETHODIMP
|
||||
nsHyperTextAccessible::GetDefaultTextAttributes(nsIPersistentProperties **aAttributes)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aAttributes);
|
||||
*aAttributes = nsnull;
|
||||
|
||||
nsCOMPtr<nsIPersistentProperties> attributes =
|
||||
do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
|
||||
NS_ENSURE_TRUE(attributes, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
NS_ADDREF(*aAttributes = attributes);
|
||||
|
||||
if (!mDOMNode)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> element = nsAccUtils::GetDOMElementFor(mDOMNode);
|
||||
|
||||
nsCSSTextAttr textAttr(PR_TRUE, element, nsnull);
|
||||
while (textAttr.iterate()) {
|
||||
nsCAutoString name;
|
||||
nsAutoString value, oldValue;
|
||||
if (textAttr.get(name, value))
|
||||
attributes->SetStringProperty(name, value, oldValue);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -1474,7 +1565,8 @@ nsresult nsHyperTextAccessible::SetSelectionRange(PRInt32 aStartPos, PRInt32 aEn
|
|||
// ranges remaining from previous selection
|
||||
nsCOMPtr<nsISelection> domSel;
|
||||
nsCOMPtr<nsISelectionController> selCon;
|
||||
GetSelections(getter_AddRefs(selCon), getter_AddRefs(domSel));
|
||||
GetSelections(nsISelectionController::SELECTION_NORMAL,
|
||||
getter_AddRefs(selCon), getter_AddRefs(domSel));
|
||||
if (domSel) {
|
||||
PRInt32 numRanges;
|
||||
domSel->GetRangeCount(&numRanges);
|
||||
|
@ -1509,7 +1601,8 @@ NS_IMETHODIMP nsHyperTextAccessible::GetCaretOffset(PRInt32 *aCaretOffset)
|
|||
*aCaretOffset = 0;
|
||||
|
||||
nsCOMPtr<nsISelection> domSel;
|
||||
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
|
||||
nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
|
||||
nsnull, getter_AddRefs(domSel));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> caretNode;
|
||||
|
@ -1527,7 +1620,8 @@ PRInt32 nsHyperTextAccessible::GetCaretLineNumber()
|
|||
// Provide the line number for the caret, relative to the
|
||||
// currently focused node. Use a 1-based index
|
||||
nsCOMPtr<nsISelection> domSel;
|
||||
GetSelections(nsnull, getter_AddRefs(domSel));
|
||||
GetSelections(nsISelectionController::SELECTION_NORMAL, nsnull,
|
||||
getter_AddRefs(domSel));
|
||||
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSel));
|
||||
NS_ENSURE_TRUE(privateSelection, -1);
|
||||
nsCOMPtr<nsFrameSelection> frameSelection;
|
||||
|
@ -1590,9 +1684,11 @@ PRInt32 nsHyperTextAccessible::GetCaretLineNumber()
|
|||
return lineNumber;
|
||||
}
|
||||
|
||||
nsresult nsHyperTextAccessible::GetSelections(nsISelectionController **aSelCon,
|
||||
nsISelection **aDomSel,
|
||||
nsCOMArray<nsIDOMRange>* aRanges)
|
||||
nsresult
|
||||
nsHyperTextAccessible::GetSelections(PRInt16 aType,
|
||||
nsISelectionController **aSelCon,
|
||||
nsISelection **aDomSel,
|
||||
nsCOMArray<nsIDOMRange>* aRanges)
|
||||
{
|
||||
if (!mDOMNode) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -1610,7 +1706,6 @@ nsresult nsHyperTextAccessible::GetSelections(nsISelectionController **aSelCon,
|
|||
nsCOMPtr<nsISelection> domSel;
|
||||
nsCOMPtr<nsISelectionController> selCon;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> startNode;
|
||||
nsCOMPtr<nsIEditor> editor;
|
||||
GetAssociatedEditor(getter_AddRefs(editor));
|
||||
nsCOMPtr<nsIPlaintextEditor> peditor(do_QueryInterface(editor));
|
||||
|
@ -1619,18 +1714,7 @@ nsresult nsHyperTextAccessible::GetSelections(nsISelectionController **aSelCon,
|
|||
// This is for form controls which have their own
|
||||
// selection controller separate from the document, for example
|
||||
// HTML:input, HTML:textarea, XUL:textbox, etc.
|
||||
if (aSelCon) {
|
||||
editor->GetSelectionController(getter_AddRefs(selCon));
|
||||
NS_ENSURE_TRUE(*aSelCon, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
editor->GetSelection(getter_AddRefs(domSel));
|
||||
NS_ENSURE_TRUE(domSel, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> editorRoot;
|
||||
editor->GetRootElement(getter_AddRefs(editorRoot));
|
||||
startNode = do_QueryInterface(editorRoot);
|
||||
NS_ENSURE_STATE(startNode);
|
||||
editor->GetSelectionController(getter_AddRefs(selCon));
|
||||
}
|
||||
else {
|
||||
// Case 2: rich content subtree (can be rich editor)
|
||||
|
@ -1641,13 +1725,11 @@ nsresult nsHyperTextAccessible::GetSelections(nsISelectionController **aSelCon,
|
|||
// Get the selection and selection controller
|
||||
frame->GetSelectionController(GetPresContext(),
|
||||
getter_AddRefs(selCon));
|
||||
NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
|
||||
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
|
||||
getter_AddRefs(domSel));
|
||||
NS_ENSURE_TRUE(domSel, NS_ERROR_FAILURE);
|
||||
|
||||
startNode = mDOMNode;
|
||||
}
|
||||
NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
|
||||
|
||||
selCon->GetSelection(aType, getter_AddRefs(domSel));
|
||||
NS_ENSURE_TRUE(domSel, NS_ERROR_FAILURE);
|
||||
|
||||
if (aSelCon) {
|
||||
NS_ADDREF(*aSelCon = selCon);
|
||||
|
@ -1655,10 +1737,19 @@ nsresult nsHyperTextAccessible::GetSelections(nsISelectionController **aSelCon,
|
|||
if (aDomSel) {
|
||||
NS_ADDREF(*aDomSel = domSel);
|
||||
}
|
||||
|
||||
if (aRanges) {
|
||||
nsCOMPtr<nsISelection2> selection2(do_QueryInterface(domSel));
|
||||
NS_ENSURE_TRUE(selection2, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> startNode(mDOMNode);
|
||||
if (peditor) {
|
||||
nsCOMPtr<nsIDOMElement> editorRoot;
|
||||
editor->GetRootElement(getter_AddRefs(editorRoot));
|
||||
startNode = do_QueryInterface(editorRoot);
|
||||
}
|
||||
NS_ENSURE_STATE(startNode);
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
nsresult rv = startNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -1692,7 +1783,8 @@ NS_IMETHODIMP nsHyperTextAccessible::GetSelectionCount(PRInt32 *aSelectionCount)
|
|||
{
|
||||
nsCOMPtr<nsISelection> domSel;
|
||||
nsCOMArray<nsIDOMRange> ranges;
|
||||
nsresult rv = GetSelections(nsnull, nsnull, &ranges);
|
||||
nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
|
||||
nsnull, nsnull, &ranges);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aSelectionCount = ranges.Count();
|
||||
|
@ -1709,7 +1801,8 @@ NS_IMETHODIMP nsHyperTextAccessible::GetSelectionBounds(PRInt32 aSelectionNum, P
|
|||
|
||||
nsCOMPtr<nsISelection> domSel;
|
||||
nsCOMArray<nsIDOMRange> ranges;
|
||||
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel), &ranges);
|
||||
nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
|
||||
nsnull, getter_AddRefs(domSel), &ranges);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 rangeCount = ranges.Count();
|
||||
|
@ -1762,7 +1855,8 @@ nsHyperTextAccessible::SetSelectionBounds(PRInt32 aSelectionNum,
|
|||
PRInt32 aEndOffset)
|
||||
{
|
||||
nsCOMPtr<nsISelection> domSel;
|
||||
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
|
||||
nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
|
||||
nsnull, getter_AddRefs(domSel));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Caret is a collapsed selection
|
||||
|
@ -1810,7 +1904,8 @@ nsHyperTextAccessible::SetSelectionBounds(PRInt32 aSelectionNum,
|
|||
NS_IMETHODIMP nsHyperTextAccessible::AddSelection(PRInt32 aStartOffset, PRInt32 aEndOffset)
|
||||
{
|
||||
nsCOMPtr<nsISelection> domSel;
|
||||
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
|
||||
nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
|
||||
nsnull, getter_AddRefs(domSel));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 rangeCount;
|
||||
|
@ -1825,7 +1920,8 @@ NS_IMETHODIMP nsHyperTextAccessible::AddSelection(PRInt32 aStartOffset, PRInt32
|
|||
NS_IMETHODIMP nsHyperTextAccessible::RemoveSelection(PRInt32 aSelectionNum)
|
||||
{
|
||||
nsCOMPtr<nsISelection> domSel;
|
||||
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
|
||||
nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
|
||||
nsnull, getter_AddRefs(domSel));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 rangeCount;
|
||||
|
@ -2037,3 +2133,352 @@ nsHyperTextAccessible::GetDOMPointByFrameOffset(nsIFrame *aFrame,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsHyperTextAccessible
|
||||
nsresult
|
||||
nsHyperTextAccessible::DOMRangeBoundToHypertextOffset(nsIDOMRange *aRange,
|
||||
PRBool aIsStartBound,
|
||||
PRBool aIsStartHTOffset,
|
||||
PRInt32 *aHTOffset)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
PRInt32 nodeOffset = 0;
|
||||
|
||||
nsresult rv;
|
||||
if (aIsStartBound) {
|
||||
rv = aRange->GetStartContainer(getter_AddRefs(node));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aRange->GetStartOffset(&nodeOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
rv = aRange->GetEndContainer(getter_AddRefs(node));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aRange->GetEndOffset(&nodeOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAccessible> startAcc;
|
||||
rv = DOMPointToHypertextOffset(node, nodeOffset, aHTOffset,
|
||||
getter_AddRefs(startAcc));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aIsStartHTOffset && !startAcc)
|
||||
*aHTOffset = 0;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsHyperTextAccessible
|
||||
nsresult
|
||||
nsHyperTextAccessible::GetSpellTextAttribute(nsIDOMNode *aNode,
|
||||
PRInt32 aNodeOffset,
|
||||
PRInt32 *aHTStartOffset,
|
||||
PRInt32 *aHTEndOffset,
|
||||
nsIPersistentProperties *aAttributes)
|
||||
{
|
||||
nsCOMArray<nsIDOMRange> ranges;
|
||||
nsresult rv = GetSelections(nsISelectionController::SELECTION_SPELLCHECK,
|
||||
nsnull, nsnull, &ranges);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 rangeCount = ranges.Count();
|
||||
if (!rangeCount)
|
||||
return NS_OK;
|
||||
|
||||
for (PRInt32 index = 0; index < rangeCount; index++) {
|
||||
nsCOMPtr<nsIDOMRange> range = ranges[index];
|
||||
nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
|
||||
NS_ENSURE_STATE(nsrange);
|
||||
|
||||
PRInt16 result;
|
||||
rv = nsrange->ComparePoint(aNode, aNodeOffset, &result);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (result == 1) { // range is before point
|
||||
PRInt32 startHTOffset = 0;
|
||||
rv = DOMRangeBoundToHypertextOffset(range, PR_FALSE, PR_TRUE,
|
||||
&startHTOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (startHTOffset > *aHTStartOffset)
|
||||
*aHTStartOffset = startHTOffset;
|
||||
|
||||
} else if (result == -1) { // range is after point
|
||||
PRInt32 endHTOffset = 0;
|
||||
rv = DOMRangeBoundToHypertextOffset(range, PR_TRUE, PR_FALSE,
|
||||
&endHTOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (endHTOffset < *aHTEndOffset)
|
||||
*aHTEndOffset = endHTOffset;
|
||||
|
||||
} else { // point is in range
|
||||
PRInt32 startHTOffset = 0;
|
||||
rv = DOMRangeBoundToHypertextOffset(range, PR_TRUE, PR_TRUE,
|
||||
&startHTOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 endHTOffset = 0;
|
||||
rv = DOMRangeBoundToHypertextOffset(range, PR_FALSE, PR_FALSE,
|
||||
&endHTOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (startHTOffset > *aHTStartOffset)
|
||||
*aHTStartOffset = startHTOffset;
|
||||
if (endHTOffset < *aHTEndOffset)
|
||||
*aHTEndOffset = endHTOffset;
|
||||
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::invalid,
|
||||
NS_LITERAL_STRING("spelling"));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsHyperTextAccessible
|
||||
nsresult
|
||||
nsHyperTextAccessible::GetLangTextAttributes(PRBool aIncludeDefAttrs,
|
||||
nsIDOMNode *aSourceNode,
|
||||
PRInt32 *aStartHTOffset,
|
||||
PRInt32 *aEndHTOffset,
|
||||
nsIPersistentProperties *aAttributes)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement> sourceElm(nsAccUtils::GetDOMElementFor(aSourceNode));
|
||||
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(sourceElm));
|
||||
nsCOMPtr<nsIContent> rootContent(do_QueryInterface(mDOMNode));
|
||||
|
||||
nsAutoString lang;
|
||||
nsAccUtils::GetLanguageFor(content, rootContent, lang);
|
||||
|
||||
nsAutoString rootLang;
|
||||
nsresult rv = GetLanguage(rootLang);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Expose 'language' text attribute if the DOM 'lang' attribute is
|
||||
// presented and it's different from the 'lang' attribute on the root
|
||||
// element or we should include default values of text attribute.
|
||||
const nsAString& resultLang = lang.IsEmpty() ? rootLang : lang;
|
||||
if (!resultLang.IsEmpty() && (aIncludeDefAttrs || lang != rootLang))
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::language,
|
||||
resultLang);
|
||||
|
||||
nsLangTextAttr textAttr(lang, rootContent);
|
||||
return GetRangeForTextAttr(aSourceNode, &textAttr,
|
||||
aStartHTOffset, aEndHTOffset);
|
||||
}
|
||||
|
||||
// nsHyperTextAccessible
|
||||
nsresult
|
||||
nsHyperTextAccessible::GetCSSTextAttributes(PRBool aIncludeDefAttrs,
|
||||
nsIDOMNode *aSourceNode,
|
||||
PRInt32 *aStartHTOffset,
|
||||
PRInt32 *aEndHTOffset,
|
||||
nsIPersistentProperties *aAttributes)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement> sourceElm(nsAccUtils::GetDOMElementFor(aSourceNode));
|
||||
nsCOMPtr<nsIDOMElement> rootElm(nsAccUtils::GetDOMElementFor(mDOMNode));
|
||||
|
||||
nsCSSTextAttr textAttr(aIncludeDefAttrs, sourceElm, rootElm);
|
||||
while (textAttr.iterate()) {
|
||||
nsCAutoString name;
|
||||
nsAutoString value, oldValue;
|
||||
if (textAttr.get(name, value))
|
||||
aAttributes->SetStringProperty(name, value, oldValue);
|
||||
|
||||
nsresult rv = GetRangeForTextAttr(aSourceNode, &textAttr,
|
||||
aStartHTOffset, aEndHTOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsHyperTextAccessible
|
||||
nsresult
|
||||
nsHyperTextAccessible::GetRangeForTextAttr(nsIDOMNode *aNode,
|
||||
nsTextAttr *aComparer,
|
||||
PRInt32 *aStartHTOffset,
|
||||
PRInt32 *aEndHTOffset)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement> rootElm(nsAccUtils::GetDOMElementFor(mDOMNode));
|
||||
NS_ENSURE_STATE(rootElm);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> tmpNode(aNode);
|
||||
nsCOMPtr<nsIDOMNode> currNode(aNode);
|
||||
|
||||
// Navigate backwards and forwards from current node to the root node to
|
||||
// calculate range bounds for the text attribute. Navigation sequence is the
|
||||
// following:
|
||||
// 1. Navigate through the siblings.
|
||||
// 2. If the traversed sibling has children then navigate from its leaf child
|
||||
// to it through whole tree of the traversed sibling.
|
||||
// 3. Get the parent and cycle algorithm until the root node.
|
||||
|
||||
// Navigate backwards (find the start offset).
|
||||
while (currNode && currNode != rootElm) {
|
||||
nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(currNode));
|
||||
NS_ENSURE_STATE(currElm);
|
||||
|
||||
if (currNode != aNode && !aComparer->equal(currElm)) {
|
||||
PRInt32 startHTOffset = 0;
|
||||
nsCOMPtr<nsIAccessible> startAcc;
|
||||
nsresult rv = DOMPointToHypertextOffset(tmpNode, -1, &startHTOffset,
|
||||
getter_AddRefs(startAcc));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!startAcc)
|
||||
startHTOffset = 0;
|
||||
|
||||
if (startHTOffset > *aStartHTOffset)
|
||||
*aStartHTOffset = startHTOffset;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
currNode->GetPreviousSibling(getter_AddRefs(tmpNode));
|
||||
if (tmpNode) {
|
||||
// Navigate through the subtree of traversed children to calculate
|
||||
// left bound of the range.
|
||||
FindStartOffsetInSubtree(tmpNode, currNode, aComparer, aStartHTOffset);
|
||||
}
|
||||
|
||||
currNode->GetParentNode(getter_AddRefs(tmpNode));
|
||||
currNode.swap(tmpNode);
|
||||
}
|
||||
|
||||
// Navigate forwards (find the end offset).
|
||||
PRBool moveIntoSubtree = PR_TRUE;
|
||||
currNode = aNode;
|
||||
while (currNode && currNode != rootElm) {
|
||||
nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(currNode));
|
||||
NS_ENSURE_STATE(currElm);
|
||||
|
||||
// Stop new end offset searching if the given text attribute changes its
|
||||
// value.
|
||||
if (!aComparer->equal(currElm)) {
|
||||
PRInt32 endHTOffset = 0;
|
||||
nsresult rv = DOMPointToHypertextOffset(currNode, -1, &endHTOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (endHTOffset < *aEndHTOffset)
|
||||
*aEndHTOffset = endHTOffset;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (moveIntoSubtree) {
|
||||
// Navigate through subtree of traversed node. We use 'moveIntoSubtree'
|
||||
// flag to avoid traversing the same subtree twice.
|
||||
currNode->GetFirstChild(getter_AddRefs(tmpNode));
|
||||
if (tmpNode)
|
||||
FindEndOffsetInSubtree(tmpNode, aComparer, aEndHTOffset);
|
||||
}
|
||||
|
||||
currNode->GetNextSibling(getter_AddRefs(tmpNode));
|
||||
moveIntoSubtree = PR_TRUE;
|
||||
if (!tmpNode) {
|
||||
currNode->GetParentNode(getter_AddRefs(tmpNode));
|
||||
moveIntoSubtree = PR_FALSE;
|
||||
}
|
||||
|
||||
currNode.swap(tmpNode);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsHyperTextAccessible::FindEndOffsetInSubtree(nsIDOMNode *aCurrNode,
|
||||
nsTextAttr *aComparer,
|
||||
PRInt32 *aHTOffset)
|
||||
{
|
||||
if (!aCurrNode)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(aCurrNode));
|
||||
NS_ENSURE_STATE(currElm);
|
||||
|
||||
// If the given text attribute (pointed by nsTextAttr object) changes its
|
||||
// value on the traversed element then fit the end of range.
|
||||
if (!aComparer->equal(currElm)) {
|
||||
PRInt32 endHTOffset = 0;
|
||||
nsresult rv = DOMPointToHypertextOffset(aCurrNode, -1, &endHTOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (endHTOffset < *aHTOffset)
|
||||
*aHTOffset = endHTOffset;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// Deeply traverse into the tree to fit the end of range.
|
||||
nsCOMPtr<nsIDOMNode> nextNode;
|
||||
aCurrNode->GetFirstChild(getter_AddRefs(nextNode));
|
||||
if (nextNode) {
|
||||
PRBool res = FindEndOffsetInSubtree(nextNode, aComparer, aHTOffset);
|
||||
if (res)
|
||||
return res;
|
||||
}
|
||||
|
||||
aCurrNode->GetNextSibling(getter_AddRefs(nextNode));
|
||||
if (nextNode) {
|
||||
if (FindEndOffsetInSubtree(nextNode, aComparer, aHTOffset))
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHyperTextAccessible::FindStartOffsetInSubtree(nsIDOMNode *aCurrNode,
|
||||
nsIDOMNode *aPrevNode,
|
||||
nsTextAttr *aComparer,
|
||||
PRInt32 *aHTOffset)
|
||||
{
|
||||
if (!aCurrNode)
|
||||
return PR_FALSE;
|
||||
|
||||
// Find the closest element back to the traversed element.
|
||||
nsCOMPtr<nsIDOMNode> nextNode;
|
||||
aCurrNode->GetLastChild(getter_AddRefs(nextNode));
|
||||
if (nextNode) {
|
||||
if (FindStartOffsetInSubtree(nextNode, aPrevNode, aComparer, aHTOffset))
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(aCurrNode));
|
||||
NS_ENSURE_STATE(currElm);
|
||||
|
||||
// If the given text attribute (pointed by nsTextAttr object) changes its
|
||||
// value on the traversed element then fit the start of range.
|
||||
if (!aComparer->equal(currElm)) {
|
||||
PRInt32 startHTOffset = 0;
|
||||
nsCOMPtr<nsIAccessible> startAcc;
|
||||
nsresult rv = DOMPointToHypertextOffset(aPrevNode, -1, &startHTOffset,
|
||||
getter_AddRefs(startAcc));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!startAcc)
|
||||
startHTOffset = 0;
|
||||
|
||||
if (startHTOffset > *aHTOffset)
|
||||
*aHTOffset = startHTOffset;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// Moving backwards to find the start of range.
|
||||
aCurrNode->GetPreviousSibling(getter_AddRefs(nextNode));
|
||||
if (nextNode) {
|
||||
if (FindStartOffsetInSubtree(nextNode, aCurrNode, aComparer, aHTOffset))
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
#include "nsIAccessibleHyperText.h"
|
||||
#include "nsIAccessibleEditableText.h"
|
||||
#include "nsAccessibleEventData.h"
|
||||
#include "nsTextUtils.h"
|
||||
|
||||
#include "nsFrameSelection.h"
|
||||
#include "nsISelectionController.h"
|
||||
|
||||
|
@ -64,7 +66,6 @@ const PRUnichar kForcedNewLineChar = '\n';
|
|||
{ 0xa9, 0x2e, 0x95, 0x23, 0x97, 0x05, 0xf3, 0x0b } \
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Special Accessible that knows how contain both text and embedded objects
|
||||
*/
|
||||
|
@ -81,8 +82,11 @@ public:
|
|||
NS_DECL_NSIACCESSIBLEEDITABLETEXT
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_HYPERTEXTACCESSIBLE_IMPL_CID)
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetRole(PRUint32 *aRole);
|
||||
NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
|
||||
void CacheChildren();
|
||||
|
||||
|
@ -124,6 +128,17 @@ public:
|
|||
nsIAccessible **aFinalAccessible = nsnull,
|
||||
PRBool aIsEndOffset = PR_FALSE);
|
||||
|
||||
/**
|
||||
* Turn a hypertext offsets into DOM point.
|
||||
*
|
||||
* @param aHTOffset [in] the given start hypertext offset
|
||||
* @param aNode [out] start node
|
||||
* @param aOffset [out] offset inside the start node
|
||||
*/
|
||||
nsresult HypertextOffsetToDOMPoint(PRInt32 aHTOffset,
|
||||
nsIDOMNode **aNode,
|
||||
PRInt32 *aOffset);
|
||||
|
||||
/**
|
||||
* Turn a start and end hypertext offsets into DOM range.
|
||||
*
|
||||
|
@ -211,15 +226,23 @@ protected:
|
|||
|
||||
// Selection helpers
|
||||
|
||||
/**
|
||||
* Get the relevant selection interfaces and ranges for the current hyper text
|
||||
* @param aSelCon The selection controller for the current hyper text, or nsnull if not needed
|
||||
* @param aDomSel The selection interface for the current hyper text, or nsnull if not needed
|
||||
* @param aRanges The selected ranges within the current subtree, or nsnull if not needed
|
||||
/**
|
||||
* Get the relevant selection interfaces and ranges for the current hyper
|
||||
* text.
|
||||
*
|
||||
* @param aType [in] the selection type
|
||||
* @param aSelCon [out, optional] the selection controller for the current
|
||||
* hyper text
|
||||
* @param aDomSel [out, optional] the selection interface for the current
|
||||
* hyper text
|
||||
* @param aRanges [out, optional] the selected ranges within the current
|
||||
* subtree
|
||||
*/
|
||||
nsresult GetSelections(nsISelectionController **aSelCon,
|
||||
nsresult GetSelections(PRInt16 aType,
|
||||
nsISelectionController **aSelCon,
|
||||
nsISelection **aDomSel = nsnull,
|
||||
nsCOMArray<nsIDOMRange>* aRanges = nsnull);
|
||||
|
||||
nsresult SetSelectionRange(PRInt32 aStartPos, PRInt32 aEndPos);
|
||||
|
||||
/**
|
||||
|
@ -233,6 +256,125 @@ protected:
|
|||
nsresult GetDOMPointByFrameOffset(nsIFrame *aFrame, PRInt32 aOffset,
|
||||
nsIAccessible *aAccessible,
|
||||
nsIDOMNode **aNode, PRInt32 *aNodeOffset);
|
||||
|
||||
|
||||
/**
|
||||
* Return hyper text offset for the specified bound of the given DOM range.
|
||||
* If the bound is outside of the hyper text then offset value is either
|
||||
* 0 or number of characters of hyper text, it depends on type of requested
|
||||
* offset. The method is a wrapper for DOMPointToHypertextOffset.
|
||||
*
|
||||
* @param aRange [in] the given range
|
||||
* @param aIsStartBound [in] specifies whether the required range bound is
|
||||
* start bound
|
||||
* @param aIsStartOffset [in] the offset type, used when the range bound is
|
||||
* outside of hyper text
|
||||
* @param aHTOffset [out] the result offset
|
||||
*/
|
||||
nsresult DOMRangeBoundToHypertextOffset(nsIDOMRange *aRange,
|
||||
PRBool aIsStartBound,
|
||||
PRBool aIsStartOffset,
|
||||
PRInt32 *aHTOffset);
|
||||
|
||||
/**
|
||||
* Set 'misspelled' text attribute and return range offsets where the
|
||||
* attibute is stretched. If the text is not misspelled at the given offset
|
||||
* then we expose only range offsets where text is not misspelled. The method
|
||||
* is used by GetTextAttributes() method.
|
||||
*
|
||||
* @param aIncludeDefAttrs [in] points whether text attributes having default
|
||||
* values of attributes should be included
|
||||
* @param aSourceNode [in] the node we start to traverse from
|
||||
* @param aStartOffset [in, out] the start offset
|
||||
* @param aEndOffset [in, out] the end offset
|
||||
* @param aAttributes [out] result attributes
|
||||
*/
|
||||
nsresult GetSpellTextAttribute(nsIDOMNode *aNode, PRInt32 aNodeOffset,
|
||||
PRInt32 *aStartOffset,
|
||||
PRInt32 *aEndOffset,
|
||||
nsIPersistentProperties *aAttributes);
|
||||
|
||||
/**
|
||||
* Set 'lang' text attribute and return range offsets where attibute is
|
||||
* stretched. The method is used by GetTextAttributes() method.
|
||||
*
|
||||
* @param aIncludeDefAttrs [in] points whether text attributes having default
|
||||
* values of attributes should be included
|
||||
* @param aSourceNode [in] the node we start to traverse from
|
||||
* @param aStartOffset [in, out] the start offset
|
||||
* @param aEndOffset [in, out] the end offset
|
||||
* @param aAttributes [out] result attributes
|
||||
*/
|
||||
nsresult GetLangTextAttributes(PRBool aIncludeDefAttrs,
|
||||
nsIDOMNode *aSourceNode,
|
||||
PRInt32 *aStartOffset,
|
||||
PRInt32 *aEndOffset,
|
||||
nsIPersistentProperties *aAttributes);
|
||||
|
||||
/**
|
||||
* Set CSS based text attribute and return range offsets where attibutes are
|
||||
* stretched. The method is used by GetTextAttributes() method.
|
||||
*
|
||||
* @param aIncludeDefAttrs [in] points whether text attributes having default
|
||||
* values of attributes should be included
|
||||
* @param aSourceNode [in] the node we start to traverse from
|
||||
* @param aStartOffset [in, out] the start offset
|
||||
* @param aEndOffset [in, out] the end offset
|
||||
* @param aAttributes [out] result attributes
|
||||
*/
|
||||
nsresult GetCSSTextAttributes(PRBool aIncludeDefAttrs,
|
||||
nsIDOMNode *aSourceNode,
|
||||
PRInt32 *aStartOffset,
|
||||
PRInt32 *aEndOffset,
|
||||
nsIPersistentProperties *aAttributes);
|
||||
|
||||
/**
|
||||
* Calculates range (start and end offsets) of text where the text attribute
|
||||
* (pointed by nsTextAttr object) is stretched. New offsets may be smaller if
|
||||
* the given text attribute changes its value before or after the given
|
||||
* offsets.
|
||||
*
|
||||
* @param aNode [in] the node we start to traverse from
|
||||
* @param aComparer [in] object used to describe the text attribute
|
||||
* @param aStartHTOffset [in, out] the start offset
|
||||
* @param aEndHTOffset [in, out] the end offset
|
||||
*/
|
||||
nsresult GetRangeForTextAttr(nsIDOMNode *aNode,
|
||||
nsTextAttr *aComparer,
|
||||
PRInt32 *aStartHTOffset,
|
||||
PRInt32 *aEndHTOffset);
|
||||
|
||||
/**
|
||||
* Find new end offset for text attributes navigating through the tree. New
|
||||
* end offset may be smaller if the given text attribute (pointed by
|
||||
* nsTextAttr object) changes its value before the given end offset.
|
||||
*
|
||||
* @param aCurrNode [in] the first node of the tree
|
||||
* @param aComparer [in] object used to describe the text attribute
|
||||
* @param aHTOffset [in, out] the end offset
|
||||
* @return true if the end offset has been changed
|
||||
*/
|
||||
PRBool FindEndOffsetInSubtree(nsIDOMNode *aCurrNode,
|
||||
nsTextAttr *aComparer,
|
||||
PRInt32 *aHTOffset);
|
||||
|
||||
/**
|
||||
* Find the start offset for text attributes navigating through the tree. New
|
||||
* start offset may be bigger if the given text attribute (pointed by
|
||||
* nsTextAttr object) changes its value after the given start offset.
|
||||
*
|
||||
* @param aCurrNode [in] the node navigating through thee thee is started
|
||||
* from
|
||||
* @param aPrevNode [in] the previous node placed before the start node
|
||||
* @param aComparer [in] object used to describe the text attribute
|
||||
* @param aHTOffset [in, out] the start offset
|
||||
* @return true if the start offset has been changed
|
||||
*/
|
||||
PRBool FindStartOffsetInSubtree(nsIDOMNode *aCurrNode,
|
||||
nsIDOMNode *aPrevNode,
|
||||
nsTextAttr *aComparer,
|
||||
PRInt32 *aHTOffset);
|
||||
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsHyperTextAccessible,
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "nsIAccessibleTypes.h"
|
||||
#include "nsIWinAccessNode.h"
|
||||
#include "nsAccessNodeWrap.h"
|
||||
#include "nsAccessibleWrap.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
|
@ -108,32 +109,26 @@ __try {
|
|||
|
||||
GET_NSIACCESSIBLETEXT
|
||||
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
PRInt32 startOffset = 0, endOffset = 0;
|
||||
textAcc->GetAttributeRange(aOffset, &startOffset, &endOffset,
|
||||
getter_AddRefs(accessible));
|
||||
if (!accessible)
|
||||
return E_FAIL;
|
||||
|
||||
nsCOMPtr<nsIWinAccessNode> winAccessNode(do_QueryInterface(accessible));
|
||||
if (!winAccessNode)
|
||||
return E_FAIL;
|
||||
|
||||
void *instancePtr = 0;
|
||||
winAccessNode->QueryNativeInterface(IID_IAccessible2, &instancePtr);
|
||||
if (!instancePtr)
|
||||
return E_FAIL;
|
||||
|
||||
IAccessible2 *pAccessible2 = static_cast<IAccessible2*>(instancePtr);
|
||||
HRESULT hr = pAccessible2->get_attributes(aTextAttributes);
|
||||
pAccessible2->Release();
|
||||
nsCOMPtr<nsIPersistentProperties> attributes;
|
||||
nsresult rv = textAcc->GetTextAttributes(PR_TRUE, aOffset,
|
||||
&startOffset, &endOffset,
|
||||
getter_AddRefs(attributes));
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
HRESULT hr = nsAccessibleWrap::ConvertToIA2Attributes(attributes,
|
||||
aTextAttributes);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
*aStartOffset = startOffset;
|
||||
*aEndOffset = endOffset;
|
||||
return hr;
|
||||
|
||||
return S_OK;
|
||||
|
||||
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
|
||||
return E_NOTIMPL;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
|
|
|
@ -1584,60 +1584,7 @@ __try {
|
|||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
if (!attributes)
|
||||
return S_FALSE;
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> propEnum;
|
||||
attributes->Enumerate(getter_AddRefs(propEnum));
|
||||
if (!propEnum)
|
||||
return E_FAIL;
|
||||
|
||||
nsAutoString strAttrs;
|
||||
|
||||
const char kCharsToEscape[] = ":;=,\\";
|
||||
|
||||
PRBool hasMore = PR_FALSE;
|
||||
while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
|
||||
nsCOMPtr<nsISupports> propSupports;
|
||||
propEnum->GetNext(getter_AddRefs(propSupports));
|
||||
|
||||
nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(propSupports));
|
||||
if (!propElem)
|
||||
return E_FAIL;
|
||||
|
||||
nsCAutoString name;
|
||||
rv = propElem->GetKey(name);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
PRUint32 offset = 0;
|
||||
while ((offset = name.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
|
||||
name.Insert('\\', offset);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
nsAutoString value;
|
||||
rv = propElem->GetValue(value);
|
||||
if (NS_FAILED(rv))
|
||||
return E_FAIL;
|
||||
|
||||
offset = 0;
|
||||
while ((offset = value.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
|
||||
value.Insert('\\', offset);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
AppendUTF8toUTF16(name, strAttrs);
|
||||
strAttrs.Append(':');
|
||||
strAttrs.Append(value);
|
||||
strAttrs.Append(';');
|
||||
}
|
||||
|
||||
if (strAttrs.IsEmpty())
|
||||
return S_FALSE;
|
||||
|
||||
*aAttributes = ::SysAllocStringLen(strAttrs.get(), strAttrs.Length());
|
||||
return *aAttributes ? S_OK : E_OUTOFMEMORY;
|
||||
return ConvertToIA2Attributes(attributes, aAttributes);
|
||||
|
||||
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
|
||||
return E_FAIL;
|
||||
|
@ -1829,6 +1776,69 @@ nsAccessibleWrap::GetHWNDFor(nsIAccessible *aAccessible)
|
|||
return hWnd;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
nsAccessibleWrap::ConvertToIA2Attributes(nsIPersistentProperties *aAttributes,
|
||||
BSTR *aIA2Attributes)
|
||||
{
|
||||
*aIA2Attributes = NULL;
|
||||
|
||||
// The format is name:value;name:value; with \ for escaping these
|
||||
// characters ":;=,\".
|
||||
|
||||
if (!aAttributes)
|
||||
return S_FALSE;
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> propEnum;
|
||||
aAttributes->Enumerate(getter_AddRefs(propEnum));
|
||||
if (!propEnum)
|
||||
return E_FAIL;
|
||||
|
||||
nsAutoString strAttrs;
|
||||
|
||||
const char kCharsToEscape[] = ":;=,\\";
|
||||
|
||||
PRBool hasMore = PR_FALSE;
|
||||
while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
|
||||
nsCOMPtr<nsISupports> propSupports;
|
||||
propEnum->GetNext(getter_AddRefs(propSupports));
|
||||
|
||||
nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(propSupports));
|
||||
if (!propElem)
|
||||
return E_FAIL;
|
||||
|
||||
nsCAutoString name;
|
||||
if (NS_FAILED(propElem->GetKey(name)))
|
||||
return E_FAIL;
|
||||
|
||||
PRUint32 offset = 0;
|
||||
while ((offset = name.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
|
||||
name.Insert('\\', offset);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
nsAutoString value;
|
||||
if (NS_FAILED(propElem->GetValue(value)))
|
||||
return E_FAIL;
|
||||
|
||||
offset = 0;
|
||||
while ((offset = value.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
|
||||
value.Insert('\\', offset);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
AppendUTF8toUTF16(name, strAttrs);
|
||||
strAttrs.Append(':');
|
||||
strAttrs.Append(value);
|
||||
strAttrs.Append(';');
|
||||
}
|
||||
|
||||
if (strAttrs.IsEmpty())
|
||||
return S_FALSE;
|
||||
|
||||
*aIA2Attributes = ::SysAllocStringLen(strAttrs.get(), strAttrs.Length());
|
||||
return *aIA2Attributes ? S_OK : E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
IDispatch *nsAccessibleWrap::NativeAccessible(nsIAccessible *aXPAccessible)
|
||||
{
|
||||
if (!aXPAccessible) {
|
||||
|
|
|
@ -296,6 +296,8 @@ class nsAccessibleWrap : public nsAccessible,
|
|||
// Helper methods
|
||||
static PRInt32 GetChildIDFor(nsIAccessible* aAccessible);
|
||||
static HWND GetHWNDFor(nsIAccessible *aAccessible);
|
||||
static HRESULT ConvertToIA2Attributes(nsIPersistentProperties *aAttributes,
|
||||
BSTR *aIA2Attributes);
|
||||
|
||||
/**
|
||||
* System caret support: update the Windows caret position.
|
||||
|
|
|
@ -69,6 +69,7 @@ _TEST_FILES =\
|
|||
test_nsIAccessibleHyperText.html \
|
||||
test_nsIAccessibleImage.html \
|
||||
test_nsOuterDocAccessible.html \
|
||||
test_textattrs.html \
|
||||
test_textboxes.html \
|
||||
test_textboxes.xul \
|
||||
testTextboxes.js \
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Brett Wilson <brettw@gmail.com>
|
||||
* Alexander Surkov <surkov.alexander@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -47,9 +48,18 @@ interface nsIDOMRange;
|
|||
|
||||
[ptr] native RangeArray(nsCOMArray<nsIDOMRange>);
|
||||
|
||||
[scriptable, uuid(b515878d-3b06-433b-bc9e-5c53d2fa3eff)]
|
||||
[scriptable, uuid(5d21d5fe-3691-4716-a334-4691eea54d29)]
|
||||
interface nsISelection2 : nsISelection
|
||||
{
|
||||
/**
|
||||
* Returns the type of the selection (see nsISelectionController for
|
||||
* available constants).
|
||||
*/
|
||||
readonly attribute short type;
|
||||
|
||||
/**
|
||||
* Return array of ranges intersecting with the given DOM interval.
|
||||
*/
|
||||
void GetRangesForInterval(
|
||||
in nsIDOMNode beginNode, in PRInt32 beginOffset,
|
||||
in nsIDOMNode endNode, in PRInt32 endOffset,
|
||||
|
|
|
@ -4696,6 +4696,15 @@ nsTypedSelection::MoveIndexToNextMismatch(PRInt32* aIndex, nsIDOMNode* aNode,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTypedSelection::GetType(PRInt16 *aType)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aType);
|
||||
*aType = mType;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsTypedSelection::GetRangesForInterval
|
||||
//
|
||||
// XPCOM wrapper for the COMArray version
|
||||
|
|
Загрузка…
Ссылка в новой задаче