Loading accessible/public/nsIAccessibleText.idl +9 −1 Original line number Diff line number Diff line Loading @@ -46,7 +46,7 @@ typedef long nsAccessibleCoordType; interface nsIAccessible; [scriptable, uuid(E44D3FA6-9CB2-432A-8BDB-69D72B6ADA00)] [scriptable, uuid(c3a9526c-4834-4237-822c-c02ef5b6b8b1)] interface nsIAccessibleText : nsISupports { const nsAccessibleTextBoundary BOUNDARY_CHAR = 0; Loading Loading @@ -111,6 +111,14 @@ interface nsIAccessibleText : nsISupports out long height, in nsAccessibleCoordType coordType); void getRangeExtents (in long startOffset, in long endOffset, out long x, out long y, out long width, out long height, in nsAccessibleCoordType coordType); long getOffsetAtPoint (in long x, in long y, in nsAccessibleCoordType coordType); Loading accessible/src/atk/nsAccessibleWrap.h +6 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,12 @@ #define USE_ATK_EMBED_RELATIONS #endif // ATK 1.3.0 or later #if ATK_MAJOR_VERSION >=2 || \ (ATK_MAJOR_VERSION == 1 && ATK_MINOR_VERSION >= 3) #define USE_ATK_GET_RANGE_EXTENTS #endif // ATK 1.3.3 or later #if ATK_MAJOR_VERSION >=2 || \ (ATK_MAJOR_VERSION == 1 && ATK_MINOR_VERSION >= 4) || \ Loading accessible/src/atk/nsMaiInterfaceText.cpp +34 −1 Original line number Diff line number Diff line Loading @@ -58,6 +58,9 @@ textInterfaceInitCB(AtkTextIface *aIface) aIface->get_run_attributes = getRunAttributesCB; aIface->get_default_attributes = getDefaultAttributesCB; aIface->get_character_extents = getCharacterExtentsCB; #ifdef USE_ATK_GET_RANGE_EXTENTS aIface->get_range_extents = getRangeExtentsCB; #endif aIface->get_character_count = getCharacterCountCB; aIface->get_offset_at_point = getOffsetAtPointCB; aIface->get_n_selections = getTextSelectionCountCB; Loading Loading @@ -272,7 +275,7 @@ getCharacterExtentsCB(AtkText *aText, gint aOffset, AtkCoordType aCoords) { nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText)); if(!accWrap) if(!accWrap || !aX || !aY || !aWidth || !aHeight) return; nsCOMPtr<nsIAccessibleText> accText; Loading @@ -294,6 +297,36 @@ getCharacterExtentsCB(AtkText *aText, gint aOffset, "MaiInterfaceText::GetCharacterExtents, failed\n"); } #ifdef USE_ATK_GET_RANGE_EXTENTS void getRangeExtentsCB(AtkText *aText, gint aStartOffset, gint aEndOffset, AtkCoordType aCoords, AtkTextRectangle *aRect) { nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText)); if(!accWrap || !aRect) return; nsCOMPtr<nsIAccessibleText> accText; accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText), getter_AddRefs(accText)); if (!accText) return; PRInt32 extY = 0, extX = 0; PRInt32 extWidth = 0, extHeight = 0; nsresult rv = accText->GetRangeExtents(aStartOffset, aEndOffset, &extX, &extY, &extWidth, &extHeight, aCoords); aRect->x = extX; aRect->y = extY; aRect->width = extWidth; aRect->height = extHeight; NS_ASSERTION(NS_SUCCEEDED(rv), "MaiInterfaceText::GetRangeExtents, failed\n"); } #endif gint getCharacterCountCB(AtkText *aText) { Loading accessible/src/atk/nsMaiInterfaceText.h +5 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,11 @@ void getCharacterExtentsCB(AtkText *aText, gint aOffset, gint *aX, gint *aY, gint *aWidth, gint *aHeight, AtkCoordType aCoords); #ifdef USE_ATK_GET_RANGE_EXTENTS void getRangeExtentsCB(AtkText *aText, gint aStartOffset, gint aEndOffset, AtkCoordType aCoords, AtkTextRectangle *aRect); #endif gint getCharacterCountCB(AtkText *aText); gint getOffsetAtPointCB(AtkText *aText, gint aX, gint aY, Loading accessible/src/html/nsHyperTextAccessible.cpp +190 −101 Original line number Diff line number Diff line Loading @@ -194,14 +194,79 @@ NS_IMETHODIMP nsHyperTextAccessible::GetExtState(PRUint32 *aExtState) return rv; } // Substring must be entirely within the same text node nsIntRect nsHyperTextAccessible::GetBoundsForString(nsIFrame *aFrame, PRInt32 aStartOffset, PRInt32 aLength) { nsIntRect screenRect; nsIFrame *frame; PRInt32 startOffsetInFrame; nsresult rv = aFrame->GetChildFrameContainingOffset(aStartOffset, PR_FALSE, &startOffsetInFrame, &frame); NS_ENSURE_SUCCESS(rv, screenRect); nsIPresShell *shell = frame->GetPresContext()->GetPresShell(); NS_ENSURE_TRUE(shell, screenRect); nsCOMPtr<nsIRenderingContext> rc; shell->CreateRenderingContext(frame, getter_AddRefs(rc)); NS_ENSURE_TRUE(rc, screenRect); const nsStyleFont *font = frame->GetStyleFont(); const nsStyleVisibility *visibility = frame->GetStyleVisibility(); rv = rc->SetFont(font->mFont, visibility->mLangGroup); NS_ENSURE_SUCCESS(rv, screenRect); nsPresContext *context = shell->GetPresContext(); float t2p = context->TwipsToPixels(); while (frame && aLength > 0) { // Start with this frame's screen rect, which we will // shrink based on the substring we care about within it. // We will then add that frame to the total screenRect we // are returning. nsIntRect frameScreenRect = frame->GetScreenRectExternal(); // Get the length of the substring in this frame that we want the bounds for PRInt32 startFrameTextOffset, endFrameTextOffset; frame->GetOffsets(startFrameTextOffset, endFrameTextOffset); PRInt32 frameTotalTextLength = endFrameTextOffset - startFrameTextOffset; PRInt32 frameSubStringLength = PR_MIN(frameTotalTextLength - startOffsetInFrame, aLength); // Add the point where the string starts to the frameScreenRect nsPoint frameTextStartPoint; rv = frame->GetPointFromOffset(context, rc, aStartOffset, &frameTextStartPoint); NS_ENSURE_SUCCESS(rv, nsRect()); frameScreenRect.x += NSTwipsToIntPixels(frameTextStartPoint.x, t2p); // Use the point for the end offset to calculate the width nsPoint frameTextEndPoint; rv = frame->GetPointFromOffset(context, rc, aStartOffset + frameSubStringLength, &frameTextEndPoint); NS_ENSURE_SUCCESS(rv, nsRect()); frameScreenRect.width = NSTwipsToIntPixels(frameTextEndPoint.x - frameTextStartPoint.x, t2p); screenRect.UnionRect(frameScreenRect, screenRect); // Get ready to loop back for next frame continuation aStartOffset += frameSubStringLength; startOffsetInFrame = 0; aLength -= frameSubStringLength; frame = frame->GetNextContinuation(); } return screenRect; } /* * Gets the specified text. */ nsIFrame* nsHyperTextAccessible::GetPosAndText(PRInt32& aStartOffset, PRInt32& aEndOffset, nsAString *aText, nsIFrame **aEndFrame) nsIFrame* nsHyperTextAccessible::GetPosAndText(PRInt32& aStartOffset, PRInt32& aEndOffset, nsAString *aText, nsIFrame **aEndFrame, nsIntRect *aBoundsRect) { PRInt32 startOffset = aStartOffset; PRInt32 endOffset = aEndOffset; // Clear out parameters and set up loop if (aText) { aText->Truncate(); } Loading @@ -217,8 +282,15 @@ nsIFrame* nsHyperTextAccessible::GetPosAndText(PRInt32& aStartOffset, PRInt32& a if (aEndFrame) { *aEndFrame = nsnull; } if (aBoundsRect) { aBoundsRect->Empty(); } nsIntRect unionRect; nsCOMPtr<nsIAccessible> accessible; // Loop through children and collect valid offsets, text and bounds // depending on what we need for out parameters while (NextChild(accessible)) { nsCOMPtr<nsPIAccessNode> accessNode(do_QueryInterface(accessible)); nsIFrame *frame = accessNode->GetFrame(); Loading Loading @@ -259,6 +331,10 @@ nsIFrame* nsHyperTextAccessible::GetPosAndText(PRInt32& aStartOffset, PRInt32& a } *aText += newText; } if (aBoundsRect) { aBoundsRect->UnionRect(*aBoundsRect, GetBoundsForString(frame, startOffset, substringEndOffset - startOffset)); } if (!startFrame) { startFrame = frame; aStartOffset = startOffset; Loading @@ -277,10 +353,15 @@ nsIFrame* nsHyperTextAccessible::GetPosAndText(PRInt32& aStartOffset, PRInt32& a -- startOffset; } else { if (aText && endOffset > 0) { if (endOffset > 0) { if (aText) { *aText += (frame->GetType() == nsAccessibilityAtoms::brFrame) ? kForcedNewLineChar : kEmbeddedObjectChar; } if (aBoundsRect) { aBoundsRect->UnionRect(*aBoundsRect, frame->GetScreenRectExternal()); } } if (!startFrame) { startFrame = frame; aStartOffset = 0; Loading @@ -288,8 +369,8 @@ nsIFrame* nsHyperTextAccessible::GetPosAndText(PRInt32& aStartOffset, PRInt32& a } -- endOffset; } if (!endOffset) { break; if (endOffset <= 0 && startFrame) { break; // If we don't have startFrame yet, get that in next loop iteration } } Loading Loading @@ -361,25 +442,40 @@ nsresult nsHyperTextAccessible::DOMPointToOffset(nsIDOMNode* aNode, PRInt32 aNod aNode->GetNodeType(&nodeType); if (nodeType != nsIDOMNode::TEXT_NODE) { // If not text, aNodeOffset is a child if (aNode != mDOMNode) { #ifdef DEBUG_A11Y // This should only happen in the empty plaintext case, when there is no text child yet // XXX What's with this check, the assertion is commented out, why? nsCOMPtr<nsIEditor> editor = GetEditor(); nsCOMPtr<nsIPlaintextEditor> plaintextEditor = do_QueryInterface(editor); // NS_ASSERTION(plaintextEditor, "DOM Point is not in this nsHyperTextAccessible"); #endif return NS_OK; // No text content yet, because textfield is blank, offset must be 0 } // aNode != mDOMNode for nsDocAccessible case, where // aNode is for <body> and mDOMNode is doc element nsCOMPtr<nsINode> hyperTextNode(do_QueryInterface(aNode)); NS_ENSURE_TRUE(hyperTextNode, NS_ERROR_FAILURE); nsCOMPtr<nsIAccessible> childAccessible; // Find first accessible child starting at aNodeOffset. We need to do this because // the node at aNodeOffset might not be an accessible while (!childAccessible) { nsIContent *childContent = hyperTextNode->GetChildAt(aNodeOffset ++); nsCOMPtr<nsIDOMNode> childNode(do_QueryInterface(childContent)); if (!childNode) { break; // Caret at end of hyper text } GetAccService()->GetAccessibleFor(childNode, getter_AddRefs(childAccessible)); } // Loop through, adding offsets until we reach childAccessible // If childAccessible is null we will end up adding up the entire length of // the hypertext, which is good -- it just means our offset node // came after the last accessible child's node nsCOMPtr<nsIAccessible> accessible; while (NextChild(accessible)) { if (aNodeOffset -- == 0) { nsCOMPtr<nsIAccessibleHyperLink> hyperLink = do_QueryInterface(accessible); NS_ENSURE_TRUE(hyperLink, NS_ERROR_FAILURE); return hyperLink->GetStartIndex(aResult); while (NextChild(accessible) && accessible != childAccessible) { if (Role(accessible) == ROLE_TEXT_LEAF) { nsCOMPtr<nsPIAccessNode> accessNode(do_QueryInterface(accessible)); nsIFrame *frame = accessNode->GetFrame(); if (frame) { *aResult += frame->GetContent()->TextLength(); } } else { ++ *aResult; // Embedded object or <br> } } return NS_ERROR_FAILURE; // Child not found return NS_OK; } // This is text, and aNodeOffset is the nth character in the text Loading Loading @@ -440,17 +536,14 @@ PRInt32 nsHyperTextAccessible::GetRelativeOffset(nsIPresShell *aPresShell, nsIFr } nsCOMPtr<nsIDOMNode> resultNode = do_QueryInterface(resultContent); PRInt32 hyperTextOffset; if (resultContent && NS_SUCCEEDED(DOMPointToOffset(resultNode, resultOffset, &hyperTextOffset))) { if (aAmount == eSelectLine && !aNeedsStart && hyperTextOffset > 0) { -- hyperTextOffset; // We want the end of the previous line in this case } } else if (aDirection == eDirNext) { if (!resultContent || NS_FAILED(DOMPointToOffset(resultNode, resultOffset, &hyperTextOffset))) { if (aDirection == eDirNext) { GetCharacterCount(&hyperTextOffset); } else { hyperTextOffset = 0; } } return hyperTextOffset; } Loading Loading @@ -486,6 +579,14 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe return NS_ERROR_FAILURE; } if (aBoundaryType == BOUNDARY_LINE_END) { // When our position is right on the line boundary and our // boundary type is BOUNDARY_LINE_END, we must start // our calculation from the beginning of the next line endOffset = startOffset = aOffset + 1; startFrame = GetPosAndText(startOffset, endOffset); } nsSelectionAmount amount; PRBool needsStart = PR_FALSE; switch (aBoundaryType) Loading @@ -504,10 +605,15 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe amount = eSelectWord; break; case BOUNDARY_LINE_START: needsStart = PR_TRUE; // Newlines are considered at the end of a line, // Since getting the BOUNDARY_LINE_START gets the text from the line-start // to the next line-start, the newline is included at the end of the string amount = eSelectLine; break; case BOUNDARY_LINE_END: // Newlines are considered at the end of a line, // Since getting the BOUNDARY_END_START gets the text from the line-end // to the next line-end, the newline is included at the beginning of the string amount = eSelectLine; break; case BOUNDARY_SENTENCE_START: Loading Loading @@ -537,10 +643,22 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe // If aType == eGetAt we'll change both the start and end offset from // the original offset startOffset = (aType == eGetAfter) ? aOffset : GetRelativeOffset(presShell, startFrame, startOffset, amount, eDirPrevious, needsStart); *aStartOffset = startOffset; PRInt32 startForwardSearchOffset; if (aType == eGetAfter) { startForwardSearchOffset = startOffset = aOffset; } else { startOffset = GetRelativeOffset(presShell, startFrame, startOffset + (amount == eSelectLine), amount, eDirPrevious, needsStart); startForwardSearchOffset = startOffset; if (amount == eSelectLine) { ++ startForwardSearchOffset; if (aBoundaryType == BOUNDARY_LINE_END && startOffset > 0) { // Start line fixup: include \n at start of string -- startOffset; } } } if (aType == eGetBefore) { endOffset = aOffset; Loading @@ -548,21 +666,30 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe else { // Start moving forward from the start so that we don't get // 2 words/lines/sentences if the offset occured on whitespace boundary // Use temp so that startOffset is not modified PRInt32 tempOffset = startOffset; if (aBoundaryType == BOUNDARY_LINE_START) { ++ tempOffset; } endOffset = tempOffset; nsIFrame *endFrame = GetPosAndText(tempOffset, endOffset); endOffset = startForwardSearchOffset; // Passed by reference nsIFrame *endFrame = GetPosAndText(startForwardSearchOffset, endOffset); if (!endFrame) { return NS_ERROR_FAILURE; } endOffset = GetRelativeOffset(presShell, endFrame, endOffset, amount, eDirNext, needsStart); if (aBoundaryType == BOUNDARY_LINE_START) { PRInt32 textLength = (endFrame->GetType() == nsAccessibilityAtoms::textFrame) ? endFrame->GetContent()->TextLength() : 1; PRInt32 startFrameOffsetUnused, endFrameOffset; endFrame->GetOffsets(startFrameOffsetUnused, endFrameOffset); if (textLength == endFrameOffset) { nsIFrame *nextSibling = endFrame->GetNextSibling(); if (nextSibling && nextSibling->GetType() == nsAccessibilityAtoms::brFrame) { // End line fixup: include \n for <br> at start of string, // just as whitespace would be included if wrapped without <br> ++ endOffset; } } } } *aStartOffset = startOffset; *aEndOffset = endOffset; return GetPosAndText(startOffset, endOffset, &aText) ? NS_OK : NS_ERROR_FAILURE; Loading Loading @@ -635,68 +762,32 @@ NS_IMETHODIMP nsHyperTextAccessible::GetCharacterExtents(PRInt32 aOffset, PRInt3 PRInt32 *aWidth, PRInt32 *aHeight, nsAccessibleCoordType aCoordType) { *aX = *aY = *aWidth = *aHeight = 0; nsCOMPtr<nsIPresShell> shell = GetPresShell(); NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE); nsAutoString firstChar; // Will convert aOffset into offset into corresponding descendant frame PRInt32 endOffset = aOffset + 1; nsIFrame *frame = GetPosAndText(aOffset, endOffset, &firstChar); if (!frame) { return NS_ERROR_FAILURE; return GetRangeExtents(aOffset, aOffset + 1, aX, aY, aWidth, aHeight, aCoordType); } nsIntRect frameScreenRect = frame->GetScreenRectExternal(); if (firstChar.First() != kEmbeddedObjectChar) { nsresult rv = frame->GetChildFrameContainingOffset(aOffset, PR_FALSE, &aOffset, &frame); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIRenderingContext> rc; shell->CreateRenderingContext(frame, getter_AddRefs(rc)); NS_ENSURE_TRUE(rc, NS_ERROR_FAILURE); const nsStyleFont *font = frame->GetStyleFont(); const nsStyleVisibility *visibility = frame->GetStyleVisibility(); rv = rc->SetFont(font->mFont, visibility->mLangGroup); NS_ENSURE_SUCCESS(rv, rv); nsIFontMetrics *fm; rv = rc->GetFontMetrics(fm); NS_ENSURE_SUCCESS(rv, rv); nsPresContext *context = shell->GetPresContext(); float t2p = context->TwipsToPixels(); //Getting width nscoord tmpWidth; if (NS_SUCCEEDED(rc->GetWidth(firstChar.First(), tmpWidth))) { *aWidth = NSTwipsToIntPixels(tmpWidth, t2p); } //Getting height nscoord tmpHeight; if (NS_SUCCEEDED(fm->GetHeight(tmpHeight))) { *aHeight = NSTwipsToIntPixels(tmpHeight, t2p); /* * Given a start & end offset, the x, y, width, and height values are filled appropriately. */ NS_IMETHODIMP nsHyperTextAccessible::GetRangeExtents(PRInt32 aStartOffset, PRInt32 aEndOffset, PRInt32 *aX, PRInt32 *aY, PRInt32 *aWidth, PRInt32 *aHeight, nsAccessibleCoordType aCoordType) { nsIntRect boundsRect; nsIFrame *endFrameUnused; if (!GetPosAndText(aStartOffset, aEndOffset, nsnull, &endFrameUnused, &boundsRect)) { return NS_ERROR_FAILURE; } //add the width of the string before current char nsPoint pt; rv = frame->GetPointFromOffset(context, rc, aOffset, &pt); NS_ENSURE_SUCCESS(rv, rv); frameScreenRect.x += NSTwipsToIntPixels(pt.x, t2p); } else { *aWidth = frameScreenRect.width; *aHeight = frameScreenRect.height; } *aX = boundsRect.x; *aY = boundsRect.y; *aWidth = boundsRect.width; *aHeight = boundsRect.height; *aX = frameScreenRect.x; *aY = frameScreenRect.y; if (aCoordType == COORD_TYPE_WINDOW) { //co-ord type = window nsCOMPtr<nsIPresShell> shell = GetPresShell(); NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE); nsCOMPtr<nsIDocument> doc = shell->GetDocument(); nsCOMPtr<nsIDOMDocumentView> docView(do_QueryInterface(doc)); NS_ENSURE_TRUE(docView, NS_ERROR_FAILURE); Loading Loading @@ -1103,8 +1194,6 @@ NS_IMETHODIMP nsHyperTextAccessible::WillDeleteSelection(nsISelection *aSelectio // <input> & <textarea> fires this event while deleting text // <editor> fires WillDeleteText/WillDeleteNode instead // XXX Deal with > 1 selections // XXX selectionStart is too large for backspace presses, it should be 1 smaller, // however that must be fixed in the editor code { PRInt32 selectionStart, selectionEnd; GetSelectionBounds(0, &selectionStart, &selectionEnd); Loading Loading
accessible/public/nsIAccessibleText.idl +9 −1 Original line number Diff line number Diff line Loading @@ -46,7 +46,7 @@ typedef long nsAccessibleCoordType; interface nsIAccessible; [scriptable, uuid(E44D3FA6-9CB2-432A-8BDB-69D72B6ADA00)] [scriptable, uuid(c3a9526c-4834-4237-822c-c02ef5b6b8b1)] interface nsIAccessibleText : nsISupports { const nsAccessibleTextBoundary BOUNDARY_CHAR = 0; Loading Loading @@ -111,6 +111,14 @@ interface nsIAccessibleText : nsISupports out long height, in nsAccessibleCoordType coordType); void getRangeExtents (in long startOffset, in long endOffset, out long x, out long y, out long width, out long height, in nsAccessibleCoordType coordType); long getOffsetAtPoint (in long x, in long y, in nsAccessibleCoordType coordType); Loading
accessible/src/atk/nsAccessibleWrap.h +6 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,12 @@ #define USE_ATK_EMBED_RELATIONS #endif // ATK 1.3.0 or later #if ATK_MAJOR_VERSION >=2 || \ (ATK_MAJOR_VERSION == 1 && ATK_MINOR_VERSION >= 3) #define USE_ATK_GET_RANGE_EXTENTS #endif // ATK 1.3.3 or later #if ATK_MAJOR_VERSION >=2 || \ (ATK_MAJOR_VERSION == 1 && ATK_MINOR_VERSION >= 4) || \ Loading
accessible/src/atk/nsMaiInterfaceText.cpp +34 −1 Original line number Diff line number Diff line Loading @@ -58,6 +58,9 @@ textInterfaceInitCB(AtkTextIface *aIface) aIface->get_run_attributes = getRunAttributesCB; aIface->get_default_attributes = getDefaultAttributesCB; aIface->get_character_extents = getCharacterExtentsCB; #ifdef USE_ATK_GET_RANGE_EXTENTS aIface->get_range_extents = getRangeExtentsCB; #endif aIface->get_character_count = getCharacterCountCB; aIface->get_offset_at_point = getOffsetAtPointCB; aIface->get_n_selections = getTextSelectionCountCB; Loading Loading @@ -272,7 +275,7 @@ getCharacterExtentsCB(AtkText *aText, gint aOffset, AtkCoordType aCoords) { nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText)); if(!accWrap) if(!accWrap || !aX || !aY || !aWidth || !aHeight) return; nsCOMPtr<nsIAccessibleText> accText; Loading @@ -294,6 +297,36 @@ getCharacterExtentsCB(AtkText *aText, gint aOffset, "MaiInterfaceText::GetCharacterExtents, failed\n"); } #ifdef USE_ATK_GET_RANGE_EXTENTS void getRangeExtentsCB(AtkText *aText, gint aStartOffset, gint aEndOffset, AtkCoordType aCoords, AtkTextRectangle *aRect) { nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText)); if(!accWrap || !aRect) return; nsCOMPtr<nsIAccessibleText> accText; accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText), getter_AddRefs(accText)); if (!accText) return; PRInt32 extY = 0, extX = 0; PRInt32 extWidth = 0, extHeight = 0; nsresult rv = accText->GetRangeExtents(aStartOffset, aEndOffset, &extX, &extY, &extWidth, &extHeight, aCoords); aRect->x = extX; aRect->y = extY; aRect->width = extWidth; aRect->height = extHeight; NS_ASSERTION(NS_SUCCEEDED(rv), "MaiInterfaceText::GetRangeExtents, failed\n"); } #endif gint getCharacterCountCB(AtkText *aText) { Loading
accessible/src/atk/nsMaiInterfaceText.h +5 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,11 @@ void getCharacterExtentsCB(AtkText *aText, gint aOffset, gint *aX, gint *aY, gint *aWidth, gint *aHeight, AtkCoordType aCoords); #ifdef USE_ATK_GET_RANGE_EXTENTS void getRangeExtentsCB(AtkText *aText, gint aStartOffset, gint aEndOffset, AtkCoordType aCoords, AtkTextRectangle *aRect); #endif gint getCharacterCountCB(AtkText *aText); gint getOffsetAtPointCB(AtkText *aText, gint aX, gint aY, Loading
accessible/src/html/nsHyperTextAccessible.cpp +190 −101 Original line number Diff line number Diff line Loading @@ -194,14 +194,79 @@ NS_IMETHODIMP nsHyperTextAccessible::GetExtState(PRUint32 *aExtState) return rv; } // Substring must be entirely within the same text node nsIntRect nsHyperTextAccessible::GetBoundsForString(nsIFrame *aFrame, PRInt32 aStartOffset, PRInt32 aLength) { nsIntRect screenRect; nsIFrame *frame; PRInt32 startOffsetInFrame; nsresult rv = aFrame->GetChildFrameContainingOffset(aStartOffset, PR_FALSE, &startOffsetInFrame, &frame); NS_ENSURE_SUCCESS(rv, screenRect); nsIPresShell *shell = frame->GetPresContext()->GetPresShell(); NS_ENSURE_TRUE(shell, screenRect); nsCOMPtr<nsIRenderingContext> rc; shell->CreateRenderingContext(frame, getter_AddRefs(rc)); NS_ENSURE_TRUE(rc, screenRect); const nsStyleFont *font = frame->GetStyleFont(); const nsStyleVisibility *visibility = frame->GetStyleVisibility(); rv = rc->SetFont(font->mFont, visibility->mLangGroup); NS_ENSURE_SUCCESS(rv, screenRect); nsPresContext *context = shell->GetPresContext(); float t2p = context->TwipsToPixels(); while (frame && aLength > 0) { // Start with this frame's screen rect, which we will // shrink based on the substring we care about within it. // We will then add that frame to the total screenRect we // are returning. nsIntRect frameScreenRect = frame->GetScreenRectExternal(); // Get the length of the substring in this frame that we want the bounds for PRInt32 startFrameTextOffset, endFrameTextOffset; frame->GetOffsets(startFrameTextOffset, endFrameTextOffset); PRInt32 frameTotalTextLength = endFrameTextOffset - startFrameTextOffset; PRInt32 frameSubStringLength = PR_MIN(frameTotalTextLength - startOffsetInFrame, aLength); // Add the point where the string starts to the frameScreenRect nsPoint frameTextStartPoint; rv = frame->GetPointFromOffset(context, rc, aStartOffset, &frameTextStartPoint); NS_ENSURE_SUCCESS(rv, nsRect()); frameScreenRect.x += NSTwipsToIntPixels(frameTextStartPoint.x, t2p); // Use the point for the end offset to calculate the width nsPoint frameTextEndPoint; rv = frame->GetPointFromOffset(context, rc, aStartOffset + frameSubStringLength, &frameTextEndPoint); NS_ENSURE_SUCCESS(rv, nsRect()); frameScreenRect.width = NSTwipsToIntPixels(frameTextEndPoint.x - frameTextStartPoint.x, t2p); screenRect.UnionRect(frameScreenRect, screenRect); // Get ready to loop back for next frame continuation aStartOffset += frameSubStringLength; startOffsetInFrame = 0; aLength -= frameSubStringLength; frame = frame->GetNextContinuation(); } return screenRect; } /* * Gets the specified text. */ nsIFrame* nsHyperTextAccessible::GetPosAndText(PRInt32& aStartOffset, PRInt32& aEndOffset, nsAString *aText, nsIFrame **aEndFrame) nsIFrame* nsHyperTextAccessible::GetPosAndText(PRInt32& aStartOffset, PRInt32& aEndOffset, nsAString *aText, nsIFrame **aEndFrame, nsIntRect *aBoundsRect) { PRInt32 startOffset = aStartOffset; PRInt32 endOffset = aEndOffset; // Clear out parameters and set up loop if (aText) { aText->Truncate(); } Loading @@ -217,8 +282,15 @@ nsIFrame* nsHyperTextAccessible::GetPosAndText(PRInt32& aStartOffset, PRInt32& a if (aEndFrame) { *aEndFrame = nsnull; } if (aBoundsRect) { aBoundsRect->Empty(); } nsIntRect unionRect; nsCOMPtr<nsIAccessible> accessible; // Loop through children and collect valid offsets, text and bounds // depending on what we need for out parameters while (NextChild(accessible)) { nsCOMPtr<nsPIAccessNode> accessNode(do_QueryInterface(accessible)); nsIFrame *frame = accessNode->GetFrame(); Loading Loading @@ -259,6 +331,10 @@ nsIFrame* nsHyperTextAccessible::GetPosAndText(PRInt32& aStartOffset, PRInt32& a } *aText += newText; } if (aBoundsRect) { aBoundsRect->UnionRect(*aBoundsRect, GetBoundsForString(frame, startOffset, substringEndOffset - startOffset)); } if (!startFrame) { startFrame = frame; aStartOffset = startOffset; Loading @@ -277,10 +353,15 @@ nsIFrame* nsHyperTextAccessible::GetPosAndText(PRInt32& aStartOffset, PRInt32& a -- startOffset; } else { if (aText && endOffset > 0) { if (endOffset > 0) { if (aText) { *aText += (frame->GetType() == nsAccessibilityAtoms::brFrame) ? kForcedNewLineChar : kEmbeddedObjectChar; } if (aBoundsRect) { aBoundsRect->UnionRect(*aBoundsRect, frame->GetScreenRectExternal()); } } if (!startFrame) { startFrame = frame; aStartOffset = 0; Loading @@ -288,8 +369,8 @@ nsIFrame* nsHyperTextAccessible::GetPosAndText(PRInt32& aStartOffset, PRInt32& a } -- endOffset; } if (!endOffset) { break; if (endOffset <= 0 && startFrame) { break; // If we don't have startFrame yet, get that in next loop iteration } } Loading Loading @@ -361,25 +442,40 @@ nsresult nsHyperTextAccessible::DOMPointToOffset(nsIDOMNode* aNode, PRInt32 aNod aNode->GetNodeType(&nodeType); if (nodeType != nsIDOMNode::TEXT_NODE) { // If not text, aNodeOffset is a child if (aNode != mDOMNode) { #ifdef DEBUG_A11Y // This should only happen in the empty plaintext case, when there is no text child yet // XXX What's with this check, the assertion is commented out, why? nsCOMPtr<nsIEditor> editor = GetEditor(); nsCOMPtr<nsIPlaintextEditor> plaintextEditor = do_QueryInterface(editor); // NS_ASSERTION(plaintextEditor, "DOM Point is not in this nsHyperTextAccessible"); #endif return NS_OK; // No text content yet, because textfield is blank, offset must be 0 } // aNode != mDOMNode for nsDocAccessible case, where // aNode is for <body> and mDOMNode is doc element nsCOMPtr<nsINode> hyperTextNode(do_QueryInterface(aNode)); NS_ENSURE_TRUE(hyperTextNode, NS_ERROR_FAILURE); nsCOMPtr<nsIAccessible> childAccessible; // Find first accessible child starting at aNodeOffset. We need to do this because // the node at aNodeOffset might not be an accessible while (!childAccessible) { nsIContent *childContent = hyperTextNode->GetChildAt(aNodeOffset ++); nsCOMPtr<nsIDOMNode> childNode(do_QueryInterface(childContent)); if (!childNode) { break; // Caret at end of hyper text } GetAccService()->GetAccessibleFor(childNode, getter_AddRefs(childAccessible)); } // Loop through, adding offsets until we reach childAccessible // If childAccessible is null we will end up adding up the entire length of // the hypertext, which is good -- it just means our offset node // came after the last accessible child's node nsCOMPtr<nsIAccessible> accessible; while (NextChild(accessible)) { if (aNodeOffset -- == 0) { nsCOMPtr<nsIAccessibleHyperLink> hyperLink = do_QueryInterface(accessible); NS_ENSURE_TRUE(hyperLink, NS_ERROR_FAILURE); return hyperLink->GetStartIndex(aResult); while (NextChild(accessible) && accessible != childAccessible) { if (Role(accessible) == ROLE_TEXT_LEAF) { nsCOMPtr<nsPIAccessNode> accessNode(do_QueryInterface(accessible)); nsIFrame *frame = accessNode->GetFrame(); if (frame) { *aResult += frame->GetContent()->TextLength(); } } else { ++ *aResult; // Embedded object or <br> } } return NS_ERROR_FAILURE; // Child not found return NS_OK; } // This is text, and aNodeOffset is the nth character in the text Loading Loading @@ -440,17 +536,14 @@ PRInt32 nsHyperTextAccessible::GetRelativeOffset(nsIPresShell *aPresShell, nsIFr } nsCOMPtr<nsIDOMNode> resultNode = do_QueryInterface(resultContent); PRInt32 hyperTextOffset; if (resultContent && NS_SUCCEEDED(DOMPointToOffset(resultNode, resultOffset, &hyperTextOffset))) { if (aAmount == eSelectLine && !aNeedsStart && hyperTextOffset > 0) { -- hyperTextOffset; // We want the end of the previous line in this case } } else if (aDirection == eDirNext) { if (!resultContent || NS_FAILED(DOMPointToOffset(resultNode, resultOffset, &hyperTextOffset))) { if (aDirection == eDirNext) { GetCharacterCount(&hyperTextOffset); } else { hyperTextOffset = 0; } } return hyperTextOffset; } Loading Loading @@ -486,6 +579,14 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe return NS_ERROR_FAILURE; } if (aBoundaryType == BOUNDARY_LINE_END) { // When our position is right on the line boundary and our // boundary type is BOUNDARY_LINE_END, we must start // our calculation from the beginning of the next line endOffset = startOffset = aOffset + 1; startFrame = GetPosAndText(startOffset, endOffset); } nsSelectionAmount amount; PRBool needsStart = PR_FALSE; switch (aBoundaryType) Loading @@ -504,10 +605,15 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe amount = eSelectWord; break; case BOUNDARY_LINE_START: needsStart = PR_TRUE; // Newlines are considered at the end of a line, // Since getting the BOUNDARY_LINE_START gets the text from the line-start // to the next line-start, the newline is included at the end of the string amount = eSelectLine; break; case BOUNDARY_LINE_END: // Newlines are considered at the end of a line, // Since getting the BOUNDARY_END_START gets the text from the line-end // to the next line-end, the newline is included at the beginning of the string amount = eSelectLine; break; case BOUNDARY_SENTENCE_START: Loading Loading @@ -537,10 +643,22 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe // If aType == eGetAt we'll change both the start and end offset from // the original offset startOffset = (aType == eGetAfter) ? aOffset : GetRelativeOffset(presShell, startFrame, startOffset, amount, eDirPrevious, needsStart); *aStartOffset = startOffset; PRInt32 startForwardSearchOffset; if (aType == eGetAfter) { startForwardSearchOffset = startOffset = aOffset; } else { startOffset = GetRelativeOffset(presShell, startFrame, startOffset + (amount == eSelectLine), amount, eDirPrevious, needsStart); startForwardSearchOffset = startOffset; if (amount == eSelectLine) { ++ startForwardSearchOffset; if (aBoundaryType == BOUNDARY_LINE_END && startOffset > 0) { // Start line fixup: include \n at start of string -- startOffset; } } } if (aType == eGetBefore) { endOffset = aOffset; Loading @@ -548,21 +666,30 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe else { // Start moving forward from the start so that we don't get // 2 words/lines/sentences if the offset occured on whitespace boundary // Use temp so that startOffset is not modified PRInt32 tempOffset = startOffset; if (aBoundaryType == BOUNDARY_LINE_START) { ++ tempOffset; } endOffset = tempOffset; nsIFrame *endFrame = GetPosAndText(tempOffset, endOffset); endOffset = startForwardSearchOffset; // Passed by reference nsIFrame *endFrame = GetPosAndText(startForwardSearchOffset, endOffset); if (!endFrame) { return NS_ERROR_FAILURE; } endOffset = GetRelativeOffset(presShell, endFrame, endOffset, amount, eDirNext, needsStart); if (aBoundaryType == BOUNDARY_LINE_START) { PRInt32 textLength = (endFrame->GetType() == nsAccessibilityAtoms::textFrame) ? endFrame->GetContent()->TextLength() : 1; PRInt32 startFrameOffsetUnused, endFrameOffset; endFrame->GetOffsets(startFrameOffsetUnused, endFrameOffset); if (textLength == endFrameOffset) { nsIFrame *nextSibling = endFrame->GetNextSibling(); if (nextSibling && nextSibling->GetType() == nsAccessibilityAtoms::brFrame) { // End line fixup: include \n for <br> at start of string, // just as whitespace would be included if wrapped without <br> ++ endOffset; } } } } *aStartOffset = startOffset; *aEndOffset = endOffset; return GetPosAndText(startOffset, endOffset, &aText) ? NS_OK : NS_ERROR_FAILURE; Loading Loading @@ -635,68 +762,32 @@ NS_IMETHODIMP nsHyperTextAccessible::GetCharacterExtents(PRInt32 aOffset, PRInt3 PRInt32 *aWidth, PRInt32 *aHeight, nsAccessibleCoordType aCoordType) { *aX = *aY = *aWidth = *aHeight = 0; nsCOMPtr<nsIPresShell> shell = GetPresShell(); NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE); nsAutoString firstChar; // Will convert aOffset into offset into corresponding descendant frame PRInt32 endOffset = aOffset + 1; nsIFrame *frame = GetPosAndText(aOffset, endOffset, &firstChar); if (!frame) { return NS_ERROR_FAILURE; return GetRangeExtents(aOffset, aOffset + 1, aX, aY, aWidth, aHeight, aCoordType); } nsIntRect frameScreenRect = frame->GetScreenRectExternal(); if (firstChar.First() != kEmbeddedObjectChar) { nsresult rv = frame->GetChildFrameContainingOffset(aOffset, PR_FALSE, &aOffset, &frame); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIRenderingContext> rc; shell->CreateRenderingContext(frame, getter_AddRefs(rc)); NS_ENSURE_TRUE(rc, NS_ERROR_FAILURE); const nsStyleFont *font = frame->GetStyleFont(); const nsStyleVisibility *visibility = frame->GetStyleVisibility(); rv = rc->SetFont(font->mFont, visibility->mLangGroup); NS_ENSURE_SUCCESS(rv, rv); nsIFontMetrics *fm; rv = rc->GetFontMetrics(fm); NS_ENSURE_SUCCESS(rv, rv); nsPresContext *context = shell->GetPresContext(); float t2p = context->TwipsToPixels(); //Getting width nscoord tmpWidth; if (NS_SUCCEEDED(rc->GetWidth(firstChar.First(), tmpWidth))) { *aWidth = NSTwipsToIntPixels(tmpWidth, t2p); } //Getting height nscoord tmpHeight; if (NS_SUCCEEDED(fm->GetHeight(tmpHeight))) { *aHeight = NSTwipsToIntPixels(tmpHeight, t2p); /* * Given a start & end offset, the x, y, width, and height values are filled appropriately. */ NS_IMETHODIMP nsHyperTextAccessible::GetRangeExtents(PRInt32 aStartOffset, PRInt32 aEndOffset, PRInt32 *aX, PRInt32 *aY, PRInt32 *aWidth, PRInt32 *aHeight, nsAccessibleCoordType aCoordType) { nsIntRect boundsRect; nsIFrame *endFrameUnused; if (!GetPosAndText(aStartOffset, aEndOffset, nsnull, &endFrameUnused, &boundsRect)) { return NS_ERROR_FAILURE; } //add the width of the string before current char nsPoint pt; rv = frame->GetPointFromOffset(context, rc, aOffset, &pt); NS_ENSURE_SUCCESS(rv, rv); frameScreenRect.x += NSTwipsToIntPixels(pt.x, t2p); } else { *aWidth = frameScreenRect.width; *aHeight = frameScreenRect.height; } *aX = boundsRect.x; *aY = boundsRect.y; *aWidth = boundsRect.width; *aHeight = boundsRect.height; *aX = frameScreenRect.x; *aY = frameScreenRect.y; if (aCoordType == COORD_TYPE_WINDOW) { //co-ord type = window nsCOMPtr<nsIPresShell> shell = GetPresShell(); NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE); nsCOMPtr<nsIDocument> doc = shell->GetDocument(); nsCOMPtr<nsIDOMDocumentView> docView(do_QueryInterface(doc)); NS_ENSURE_TRUE(docView, NS_ERROR_FAILURE); Loading Loading @@ -1103,8 +1194,6 @@ NS_IMETHODIMP nsHyperTextAccessible::WillDeleteSelection(nsISelection *aSelectio // <input> & <textarea> fires this event while deleting text // <editor> fires WillDeleteText/WillDeleteNode instead // XXX Deal with > 1 selections // XXX selectionStart is too large for backspace presses, it should be 1 smaller, // however that must be fixed in the editor code { PRInt32 selectionStart, selectionEnd; GetSelectionBounds(0, &selectionStart, &selectionEnd); Loading