Bug 405810. Expose line-number object attribute for caret in focused area. r=ginn, sr=roc, a=schrep

This commit is contained in:
aaronleventhal@moonset.net 2007-12-11 06:15:21 -08:00
parent ce30969640
commit 5bdcd1bb11
7 changed files with 99 additions and 20 deletions

View File

@ -190,3 +190,6 @@ ACCESSIBILITY_ATOM(role, "role")
// a form property used to obtain the default label
// of an HTML button from the button frame
ACCESSIBILITY_ATOM(defaultLabel, "defaultLabel")
// An atom used to set the line-number object attribute
ACCESSIBILITY_ATOM(lineNumber, "line-number")

View File

@ -2166,7 +2166,7 @@ nsAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
nsresult
nsAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
{
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mDOMNode));
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(GetRoleContent(mDOMNode)));
NS_ENSURE_TRUE(element, NS_ERROR_UNEXPECTED);
nsAutoString tagName;

View File

@ -510,15 +510,6 @@ NS_IMETHODIMP nsDocAccessible::GetParent(nsIAccessible **aParent)
return mParent ? nsAccessible::GetParent(aParent) : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsDocAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
{
NS_ENSURE_ARG_POINTER(aAttributes);
*aAttributes = nsnull;
return mDOMNode ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsDocAccessible::Init()
{
PutCacheEntry(gGlobalDocAccessibleCache, mDocument, this);

View File

@ -80,7 +80,6 @@ class nsDocAccessible : public nsHyperTextAccessibleWrap,
NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
NS_IMETHOD GetParent(nsIAccessible **aParent);
NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
NS_IMETHOD TakeFocus(void);
// ----- nsIScrollPositionListener ---------------------------

View File

@ -57,9 +57,10 @@
#include "nsIFontMetrics.h"
#include "nsIFrame.h"
#include "nsFrameSelection.h"
#include "nsIScrollableFrame.h"
#include "nsILineIterator.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIPlaintextEditor.h"
#include "nsIScrollableFrame.h"
#include "nsISelection2.h"
#include "nsISelectionPrivate.h"
#include "nsIServiceManager.h"
@ -863,9 +864,9 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
// at the end of a line.
nsCOMPtr<nsISelection> domSel;
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSel));
nsCOMPtr<nsFrameSelection> frameSelection;
rv = privateSelection->GetFrameSelection(getter_AddRefs(frameSelection));
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
@ -1075,7 +1076,7 @@ nsHyperTextAccessible::GetAttributesInternal(nsIPersistentProperties *aAttribute
nsresult rv = nsAccessibleWrap::GetAttributesInternal(aAttributes);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
nsCOMPtr<nsIContent> content(do_QueryInterface(GetRoleContent(mDOMNode)));
NS_ENSURE_TRUE(content, NS_ERROR_UNEXPECTED);
nsIAtom *tag = content->Tag();
@ -1109,6 +1110,16 @@ nsHyperTextAccessible::GetAttributesInternal(nsIPersistentProperties *aAttribute
oldValueUnused);
}
if (gLastFocusedNode == mDOMNode) {
PRInt32 lineNumber = GetCaretLineNumber();
if (lineNumber >= 1) {
nsAutoString strLineNumber;
strLineNumber.AppendInt(lineNumber);
nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::lineNumber,
strLineNumber);
}
}
return NS_OK;
}
@ -1470,6 +1481,74 @@ NS_IMETHODIMP nsHyperTextAccessible::GetCaretOffset(PRInt32 *aCaretOffset)
return DOMPointToHypertextOffset(caretNode, caretOffset, aCaretOffset);
}
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));
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSel));
NS_ENSURE_TRUE(privateSelection, -1);
nsCOMPtr<nsFrameSelection> frameSelection;
privateSelection->GetFrameSelection(getter_AddRefs(frameSelection));
NS_ENSURE_TRUE(frameSelection, -1);
nsCOMPtr<nsIDOMNode> caretNode;
domSel->GetFocusNode(getter_AddRefs(caretNode));
nsCOMPtr<nsIContent> caretContent = do_QueryInterface(caretNode);
if (!caretContent || !nsAccUtils::IsAncestorOf(mDOMNode, caretNode)) {
return -1;
}
PRInt32 caretOffset, returnOffsetUnused;
domSel->GetFocusOffset(&caretOffset);
nsFrameSelection::HINT hint = frameSelection->GetHint();
nsIFrame *caretFrame = frameSelection->GetFrameForNodeOffset(caretContent, caretOffset,
hint, &returnOffsetUnused);
NS_ENSURE_TRUE(caretFrame, -1);
PRInt32 lineNumber = 1;
nsCOMPtr<nsILineIterator> lineIterForCaret;
nsCOMPtr<nsIContent> hyperTextContent = do_QueryInterface(mDOMNode);
while (caretFrame) {
if (hyperTextContent == caretFrame->GetContent()) {
return lineNumber; // Must be in a single line hyper text, there is no line iterator
}
nsIFrame *parentFrame = caretFrame->GetParent();
if (!parentFrame)
break;
// Add lines for the sibling frames before the caret
nsIFrame *sibling = parentFrame->GetFirstChild(nsnull);
while (sibling && sibling != caretFrame) {
nsCOMPtr<nsILineIterator> lineIterForSibling = do_QueryInterface(sibling);
if (lineIterForSibling) {
PRInt32 addLines;
// For the frames before that grab all the lines
lineIterForSibling->GetNumLines(&addLines);
lineNumber += addLines;
}
sibling = sibling->GetNextSibling();
}
// Get the line number relative to the container with lines
if (!lineIterForCaret) { // Add the caret line just once
lineIterForCaret = do_QueryInterface(parentFrame);
if (lineIterForCaret) {
// Ancestor of caret
PRInt32 addLines;
lineIterForCaret->FindLineContaining(caretFrame, &addLines);
lineNumber += addLines;
}
}
caretFrame = parentFrame;
}
NS_NOTREACHED("DOM ancestry had this hypertext but frame ancestry didn't");
return lineNumber;
}
nsresult nsHyperTextAccessible::GetSelections(nsISelectionController **aSelCon,
nsISelection **aDomSel,
nsCOMArray<nsIDOMRange>* aRanges)

View File

@ -222,6 +222,13 @@ protected:
nsCOMArray<nsIDOMRange>* aRanges = nsnull);
nsresult SetSelectionRange(PRInt32 aStartPos, PRInt32 aEndPos);
/**
* Provide the line number for the caret, relative to the
* current DOM node.
* @return 1-based index for the line number with the caret
*/
PRInt32 GetCaretLineNumber();
// Helpers
nsresult GetDOMPointByFrameOffset(nsIFrame *aFrame, PRInt32 aOffset,
nsIAccessible *aAccessible,

View File

@ -360,10 +360,10 @@ public:
* @param aOffset offset into above node.
* @param aReturnOffset will contain offset into frame.
*/
nsIFrame* GetFrameForNodeOffset(nsIContent *aNode,
PRInt32 aOffset,
HINT aHint,
PRInt32 *aReturnOffset) const;
virtual nsIFrame* GetFrameForNodeOffset(nsIContent *aNode,
PRInt32 aOffset,
HINT aHint,
PRInt32 *aReturnOffset) const;
/**
* Scrolling then moving caret placement code in common to text areas and