Bug 674558 - Implement the HTML5 selectionDirection property for text controls (input and textarea); r=bzbarsky

This commit is contained in:
Ehsan Akhgari 2011-07-28 13:51:22 -04:00
parent 1aec6a731e
commit 2f51d73796
13 changed files with 395 additions and 76 deletions

View File

@ -49,6 +49,7 @@ class nsIFrame;
class nsIPresShell;
struct nsTextRangeStyle;
struct nsPoint;
#include "nsIFrame.h"
%}
[ptr] native nsFrameSelection(nsFrameSelection);
@ -56,6 +57,7 @@ struct nsPoint;
[ptr] native nsIPresShell(nsIPresShell);
[ref] native constTextRangeStyleRef(const nsTextRangeStyle);
[ref] native nsPointRef(nsPoint);
native nsDirection(nsDirection);
[scriptable, uuid(98552206-ad7a-4d2d-8ce3-b6fa2389298b)]
interface nsISelectionPrivate : nsISupports
@ -128,5 +130,11 @@ interface nsISelectionPrivate : nsISupports
*/
[noscript] void setTextRangeStyle(in nsIDOMRange range,
in constTextRangeStyleRef textRangeStyle);
/**
* Get the direction of the selection.
*/
[noscript, notxpcom] nsDirection getSelectionDirection();
[noscript, notxpcom] void setSelectionDirection(in nsDirection aDirection);
};

View File

@ -2723,7 +2723,8 @@ nsHTMLInputElement::GetTextLength(PRInt32* aTextLength)
NS_IMETHODIMP
nsHTMLInputElement::SetSelectionRange(PRInt32 aSelectionStart,
PRInt32 aSelectionEnd)
PRInt32 aSelectionEnd,
const nsAString& aDirection)
{
nsresult rv = NS_ERROR_FAILURE;
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
@ -2731,7 +2732,15 @@ nsHTMLInputElement::SetSelectionRange(PRInt32 aSelectionStart,
if (formControlFrame) {
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
if (textControlFrame) {
rv = textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd);
// Default to forward, even if not specified.
// Note that we don't currently support directionless selections, so
// "none" is treated like "forward".
nsITextControlFrame::SelectionDirection dir = nsITextControlFrame::eForward;
if (aDirection.EqualsLiteral("backward")) {
dir = nsITextControlFrame::eBackward;
}
rv = textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd, dir);
if (NS_SUCCEEDED(rv)) {
rv = textControlFrame->ScrollSelectionIntoView();
}
@ -2753,20 +2762,17 @@ nsHTMLInputElement::GetSelectionStart(PRInt32* aSelectionStart)
NS_IMETHODIMP
nsHTMLInputElement::SetSelectionStart(PRInt32 aSelectionStart)
{
nsresult rv = NS_ERROR_FAILURE;
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
if (formControlFrame) {
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
if (textControlFrame) {
rv = textControlFrame->SetSelectionStart(aSelectionStart);
if (NS_SUCCEEDED(rv)) {
rv = textControlFrame->ScrollSelectionIntoView();
}
}
nsAutoString direction;
nsresult rv = GetSelectionDirection(direction);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 start, end;
rv = GetSelectionRange(&start, &end);
NS_ENSURE_SUCCESS(rv, rv);
start = aSelectionStart;
if (end < start) {
end = start;
}
return rv;
return SetSelectionRange(start, end, direction);
}
NS_IMETHODIMP
@ -2782,20 +2788,17 @@ nsHTMLInputElement::GetSelectionEnd(PRInt32* aSelectionEnd)
NS_IMETHODIMP
nsHTMLInputElement::SetSelectionEnd(PRInt32 aSelectionEnd)
{
nsresult rv = NS_ERROR_FAILURE;
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
if (formControlFrame) {
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
if (textControlFrame) {
rv = textControlFrame->SetSelectionEnd(aSelectionEnd);
if (NS_SUCCEEDED(rv)) {
rv = textControlFrame->ScrollSelectionIntoView();
}
}
nsAutoString direction;
nsresult rv = GetSelectionDirection(direction);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 start, end;
rv = GetSelectionRange(&start, &end);
NS_ENSURE_SUCCESS(rv, rv);
end = aSelectionEnd;
if (start > end) {
start = end;
}
return rv;
return SetSelectionRange(start, end, direction);
}
NS_IMETHODIMP
@ -2835,6 +2838,45 @@ nsHTMLInputElement::GetSelectionRange(PRInt32* aSelectionStart,
return rv;
}
NS_IMETHODIMP
nsHTMLInputElement::GetSelectionDirection(nsAString& aDirection)
{
nsresult rv = NS_ERROR_FAILURE;
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
if (formControlFrame) {
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
if (textControlFrame) {
nsITextControlFrame::SelectionDirection dir;
rv = textControlFrame->GetSelectionRange(nsnull, nsnull, &dir);
if (NS_SUCCEEDED(rv)) {
if (dir == nsITextControlFrame::eNone) {
aDirection.AssignLiteral("none");
} else if (dir == nsITextControlFrame::eForward) {
aDirection.AssignLiteral("forward");
} else if (dir == nsITextControlFrame::eBackward) {
aDirection.AssignLiteral("backward");
} else {
NS_NOTREACHED("Invalid SelectionDirection value");
}
}
}
}
return rv;
}
NS_IMETHODIMP
nsHTMLInputElement::SetSelectionDirection(const nsAString& aDirection) {
PRInt32 start, end;
nsresult rv = GetSelectionRange(&start, &end);
if (NS_SUCCEEDED(rv)) {
rv = SetSelectionRange(start, end, aDirection);
}
return rv;
}
NS_IMETHODIMP
nsHTMLInputElement::GetPhonetic(nsAString& aPhonetic)
{

View File

@ -829,20 +829,17 @@ nsHTMLTextAreaElement::GetSelectionStart(PRInt32 *aSelectionStart)
NS_IMETHODIMP
nsHTMLTextAreaElement::SetSelectionStart(PRInt32 aSelectionStart)
{
nsresult rv = NS_ERROR_FAILURE;
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
if (formControlFrame){
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
if (textControlFrame) {
rv = textControlFrame->SetSelectionStart(aSelectionStart);
if (NS_SUCCEEDED(rv)) {
rv = textControlFrame->ScrollSelectionIntoView();
}
}
nsAutoString direction;
nsresult rv = GetSelectionDirection(direction);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 start, end;
rv = GetSelectionRange(&start, &end);
NS_ENSURE_SUCCESS(rv, rv);
start = aSelectionStart;
if (end < start) {
end = start;
}
return rv;
return SetSelectionRange(start, end, direction);
}
NS_IMETHODIMP
@ -857,20 +854,17 @@ nsHTMLTextAreaElement::GetSelectionEnd(PRInt32 *aSelectionEnd)
NS_IMETHODIMP
nsHTMLTextAreaElement::SetSelectionEnd(PRInt32 aSelectionEnd)
{
nsresult rv = NS_ERROR_FAILURE;
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
if (formControlFrame) {
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
if (textControlFrame) {
rv = textControlFrame->SetSelectionEnd(aSelectionEnd);
if (NS_SUCCEEDED(rv)) {
rv = textControlFrame->ScrollSelectionIntoView();
}
}
nsAutoString direction;
nsresult rv = GetSelectionDirection(direction);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 start, end;
rv = GetSelectionRange(&start, &end);
NS_ENSURE_SUCCESS(rv, rv);
end = aSelectionEnd;
if (start > end) {
start = end;
}
return rv;
return SetSelectionRange(start, end, direction);
}
nsresult
@ -889,8 +883,49 @@ nsHTMLTextAreaElement::GetSelectionRange(PRInt32* aSelectionStart,
return rv;
}
nsresult
nsHTMLTextAreaElement::GetSelectionDirection(nsAString& aDirection)
{
nsresult rv = NS_ERROR_FAILURE;
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
if (formControlFrame) {
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
if (textControlFrame) {
nsITextControlFrame::SelectionDirection dir;
rv = textControlFrame->GetSelectionRange(nsnull, nsnull, &dir);
if (NS_SUCCEEDED(rv)) {
if (dir == nsITextControlFrame::eNone) {
aDirection.AssignLiteral("none");
} else if (dir == nsITextControlFrame::eForward) {
aDirection.AssignLiteral("forward");
} else if (dir == nsITextControlFrame::eBackward) {
aDirection.AssignLiteral("backward");
} else {
NS_NOTREACHED("Invalid SelectionDirection value");
}
}
}
}
return rv;
}
NS_IMETHODIMP
nsHTMLTextAreaElement::SetSelectionRange(PRInt32 aSelectionStart, PRInt32 aSelectionEnd)
nsHTMLTextAreaElement::SetSelectionDirection(const nsAString& aDirection) {
PRInt32 start, end;
nsresult rv = GetSelectionRange(&start, &end);
if (NS_SUCCEEDED(rv)) {
rv = SetSelectionRange(start, end, aDirection);
}
return rv;
}
NS_IMETHODIMP
nsHTMLTextAreaElement::SetSelectionRange(PRInt32 aSelectionStart,
PRInt32 aSelectionEnd,
const nsAString& aDirection)
{
nsresult rv = NS_ERROR_FAILURE;
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
@ -898,7 +933,15 @@ nsHTMLTextAreaElement::SetSelectionRange(PRInt32 aSelectionStart, PRInt32 aSelec
if (formControlFrame) {
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
if (textControlFrame) {
rv = textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd);
// Default to forward, even if not specified.
// Note that we don't currently support directionless selections, so
// "none" is treated like "forward".
nsITextControlFrame::SelectionDirection dir = nsITextControlFrame::eForward;
if (aDirection.EqualsLiteral("backward")) {
dir = nsITextControlFrame::eBackward;
}
rv = textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd, dir);
if (NS_SUCCEEDED(rv)) {
rv = textControlFrame->ScrollSelectionIntoView();
}

View File

@ -277,6 +277,7 @@ _TEST_FILES = \
test_bug664299.html \
test_bug666200.html \
test_bug666666.html \
test_bug674558.html \
test_restore_from_parser_fragment.html \
$(NULL)

View File

@ -0,0 +1,151 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=674558
-->
<head>
<title>Test for Bug 674558</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=674558">Mozilla Bug 674558</a>
<p id="display"></p>
<div id="content">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 674558 **/
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(function() {
function textAreaCtor() {
return document.createElement("textarea");
}
var ctors = [textAreaCtor];
["text", "password", "search"].forEach(function(type) {
ctors.push(function inputCtor() {
var input = document.createElement("input");
input.type = type;
return input;
});
});
for (var ctor in ctors) {
test(ctors[ctor]);
}
SimpleTest.finish();
});
function test(ctor) {
var elem = ctor();
ok(true, "Testing " + name(elem));
ok("selectionDirection" in elem, "elem should have the selectionDirection property");
var content = document.getElementById("content");
content.appendChild(elem);
elem.value = "foobar";
is(elem.selectionStart, 0, "Default value");
is(elem.selectionEnd, 0, "Default value");
is(elem.selectionDirection, "forward", "Default value");
elem.setSelectionRange(1, 3);
is(elem.selectionStart, 1, "Correct value");
is(elem.selectionEnd, 3, "Correct value");
is(elem.selectionDirection, "forward", "If not set, should default to forward");
// extend to right
elem.focus();
synthesizeKey("VK_RIGHT", {shiftKey: true});
is(elem.selectionStart, 1, "Value unchanged");
is(elem.selectionEnd, 4, "Correct value");
is(elem.selectionDirection, "forward", "Still forward");
// change the direction
elem.selectionDirection = "backward";
is(elem.selectionStart, 1, "Value unchanged");
is(elem.selectionEnd, 4, "Value unchanged");
is(elem.selectionDirection, "backward", "Correct value");
// extend to right again
synthesizeKey("VK_RIGHT", {shiftKey: true});
is(elem.selectionStart, 2, "Correct value");
is(elem.selectionEnd, 4, "Value unchanged");
is(elem.selectionDirection, "backward", "Still backward");
elem.selectionEnd = 5;
is(elem.selectionStart, 2, "Value unchanged");
is(elem.selectionEnd, 5, "Correct value");
is(elem.selectionDirection, "backward", "Still backward");
elem.selectionDirection = "none";
is(elem.selectionStart, 2, "Value unchanged");
is(elem.selectionEnd, 5, "Value unchanged");
is(elem.selectionDirection, "forward", "none not supported");
elem.selectionDirection = "backward";
is(elem.selectionStart, 2, "Value unchanged");
is(elem.selectionEnd, 5, "Value unchanged");
is(elem.selectionDirection, "backward", "Correct Value");
elem.selectionDirection = "invalid";
is(elem.selectionStart, 2, "Value unchanged");
is(elem.selectionEnd, 5, "Value unchanged");
is(elem.selectionDirection, "forward", "Treated as none");
elem.selectionDirection = "backward";
is(elem.selectionStart, 2, "Value unchanged");
is(elem.selectionEnd, 5, "Value unchanged");
is(elem.selectionDirection, "backward", "Correct Value");
elem.setSelectionRange(1, 4);
is(elem.selectionStart, 1, "Correct value");
is(elem.selectionEnd, 4, "Correct value");
is(elem.selectionDirection, "forward", "Correct value");
elem.setSelectionRange(1, 1);
synthesizeKey("VK_RIGHT", {shiftKey: true});
synthesizeKey("VK_RIGHT", {shiftKey: true});
synthesizeKey("VK_RIGHT", {shiftKey: true});
is(elem.selectionStart, 1, "Correct value");
is(elem.selectionEnd, 4, "Correct value");
is(elem.selectionDirection, "forward", "Correct value");
elem.setSelectionRange(5, 5);
synthesizeKey("VK_LEFT", {shiftKey: true});
synthesizeKey("VK_LEFT", {shiftKey: true});
synthesizeKey("VK_LEFT", {shiftKey: true});
is(elem.selectionStart, 2, "Correct value");
is(elem.selectionEnd, 5, "Correct value");
is(elem.selectionDirection, "backward", "Correct value");
}
function name(elem) {
var tag = elem.localName;
if (tag == "input") {
tag += "[type=" + elem.type + "]";
}
return tag;
}
</script>
</pre>
</body>
</html>

View File

@ -54,7 +54,7 @@ interface nsIDOMValidityState;
* http://www.whatwg.org/specs/web-apps/current-work/
*/
[scriptable, uuid(a59ba6b8-6f8b-4003-a8a4-184a51a05050)]
[scriptable, uuid(66819eba-89b5-4db4-8d27-6368c70761e8)]
interface nsIDOMHTMLInputElement : nsIDOMHTMLElement
{
attribute DOMString accept;
@ -107,8 +107,9 @@ interface nsIDOMHTMLInputElement : nsIDOMHTMLElement
void select();
attribute long selectionStart;
attribute long selectionEnd;
void setSelectionRange(in long selectionStart, in long selectionEnd);
void setSelectionRange(in long selectionStart, in long selectionEnd, [optional] in DOMString direction);
attribute DOMString selectionDirection;
attribute long tabIndex;
attribute DOMString useMap;

View File

@ -53,7 +53,7 @@ interface nsIDOMValidityState;
* http://www.whatwg.org/specs/web-apps/current-work/
*/
[scriptable, uuid(905edd3e-c0b3-4d54-8a2c-0eaab6ccb3cf)]
[scriptable, uuid(43e99aee-e41f-4935-a87d-f2dbafdbfddb)]
interface nsIDOMHTMLTextAreaElement : nsIDOMHTMLElement
{
attribute boolean autofocus;
@ -89,7 +89,8 @@ interface nsIDOMHTMLTextAreaElement : nsIDOMHTMLElement
void select();
attribute long selectionStart;
attribute long selectionEnd;
void setSelectionRange(in long selectionStart, in long selectionEnd);
void setSelectionRange(in long selectionStart, in long selectionEnd, [optional] in DOMString direction);
attribute DOMString selectionDirection;
// Defined on HTMLElement in the specification.
attribute long tabIndex;

View File

@ -258,6 +258,7 @@ members = [
'nsIDOMHTMLInputElement.textLength',
'nsIDOMHTMLInputElement.selectionStart',
'nsIDOMHTMLInputElement.selectionEnd',
'nsIDOMHTMLInputElement.selectionDirection',
'nsIDOMHTMLInputElement.setSelectionRange',
'nsIDOMHTMLLinkElement.disabled',
'nsIDOMHTMLOptionElement.index',
@ -317,6 +318,7 @@ members = [
'nsIDOMHTMLTextAreaElement.setSelectionRange',
'nsIDOMHTMLTextAreaElement.selectionStart',
'nsIDOMHTMLTextAreaElement.selectionEnd',
'nsIDOMHTMLTextAreaElement.selectionDirection',
'nsIDOMHTMLTextAreaElement.textLength',
'nsIDOMHTMLTextAreaElement.wrap',
'nsIDOMHTMLTitleElement.text',

View File

@ -50,6 +50,12 @@ class nsITextControlFrame : public nsIFormControlFrame
public:
NS_DECL_QUERYFRAME_TARGET(nsITextControlFrame)
enum SelectionDirection {
eNone,
eForward,
eBackward
};
NS_IMETHOD GetEditor(nsIEditor **aEditor) = 0;
NS_IMETHOD GetTextLength(PRInt32* aTextLength) = 0;
@ -62,8 +68,12 @@ public:
NS_IMETHOD SetSelectionStart(PRInt32 aSelectionStart) = 0;
NS_IMETHOD SetSelectionEnd(PRInt32 aSelectionEnd) = 0;
NS_IMETHOD SetSelectionRange(PRInt32 aSelectionStart, PRInt32 aSelectionEnd) = 0;
NS_IMETHOD GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd) = 0;
NS_IMETHOD SetSelectionRange(PRInt32 aSelectionStart,
PRInt32 aSelectionEnd,
SelectionDirection aDirection = eNone) = 0;
NS_IMETHOD GetSelectionRange(PRInt32* aSelectionStart,
PRInt32* aSelectionEnd,
SelectionDirection* aDirection = nsnull) = 0;
NS_IMETHOD GetOwnedSelectionController(nsISelectionController** aSelCon) = 0;
virtual nsFrameSelection* GetOwnedFrameSelection() = 0;

View File

@ -805,7 +805,8 @@ nsresult
nsTextControlFrame::SetSelectionInternal(nsIDOMNode *aStartNode,
PRInt32 aStartOffset,
nsIDOMNode *aEndNode,
PRInt32 aEndOffset)
PRInt32 aEndOffset,
nsITextControlFrame::SelectionDirection aDirection)
{
// Create a new range to represent the new selection.
// Note that we use a new range to avoid having to do
@ -830,10 +831,24 @@ nsTextControlFrame::SetSelectionInternal(nsIDOMNode *aStartNode,
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
nsCOMPtr<nsISelectionPrivate> selPriv = do_QueryInterface(selection, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsDirection direction;
if (aDirection == eNone) {
// Preserve the direction
direction = selPriv->GetSelectionDirection();
} else {
direction = (aDirection == eBackward) ? eDirPrevious : eDirNext;
}
rv = selection->RemoveAllRanges();
NS_ENSURE_SUCCESS(rv, rv);
rv = selection->AddRange(range); // NOTE: can destroy the world
NS_ENSURE_SUCCESS(rv, rv);
selPriv->SetSelectionDirection(direction);
return rv;
}
@ -906,7 +921,8 @@ nsTextControlFrame::SelectAllOrCollapseToEndOfText(PRBool aSelect)
}
nsresult
nsTextControlFrame::SetSelectionEndPoints(PRInt32 aSelStart, PRInt32 aSelEnd)
nsTextControlFrame::SetSelectionEndPoints(PRInt32 aSelStart, PRInt32 aSelEnd,
nsITextControlFrame::SelectionDirection aDirection)
{
NS_ASSERTION(aSelStart <= aSelEnd, "Invalid selection offsets!");
@ -936,11 +952,12 @@ nsTextControlFrame::SetSelectionEndPoints(PRInt32 aSelStart, PRInt32 aSelEnd)
NS_ENSURE_SUCCESS(rv, rv);
}
return SetSelectionInternal(startNode, startOffset, endNode, endOffset);
return SetSelectionInternal(startNode, startOffset, endNode, endOffset, aDirection);
}
NS_IMETHODIMP
nsTextControlFrame::SetSelectionRange(PRInt32 aSelStart, PRInt32 aSelEnd)
nsTextControlFrame::SetSelectionRange(PRInt32 aSelStart, PRInt32 aSelEnd,
nsITextControlFrame::SelectionDirection aDirection)
{
nsresult rv = EnsureEditorInitialized();
NS_ENSURE_SUCCESS(rv, rv);
@ -952,7 +969,7 @@ nsTextControlFrame::SetSelectionRange(PRInt32 aSelStart, PRInt32 aSelEnd)
aSelStart = aSelEnd;
}
return SetSelectionEndPoints(aSelStart, aSelEnd);
return SetSelectionEndPoints(aSelStart, aSelEnd, aDirection);
}
@ -1110,14 +1127,23 @@ nsTextControlFrame::OffsetToDOMPoint(PRInt32 aOffset,
}
NS_IMETHODIMP
nsTextControlFrame::GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd)
nsTextControlFrame::GetSelectionRange(PRInt32* aSelectionStart,
PRInt32* aSelectionEnd,
SelectionDirection* aDirection)
{
// make sure we have an editor
nsresult rv = EnsureEditorInitialized();
NS_ENSURE_SUCCESS(rv, rv);
*aSelectionStart = 0;
*aSelectionEnd = 0;
if (aSelectionStart) {
*aSelectionStart = 0;
}
if (aSelectionEnd) {
*aSelectionEnd = 0;
}
if (aDirection) {
*aDirection = eNone;
}
nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
NS_ASSERTION(txtCtrl, "Content not a text control element");
@ -1136,6 +1162,24 @@ nsTextControlFrame::GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelect
// We only operate on the first range in the selection!
if (aDirection) {
nsCOMPtr<nsISelectionPrivate> selPriv = do_QueryInterface(selection);
if (selPriv) {
nsDirection direction = selPriv->GetSelectionDirection();
if (direction == eDirNext) {
*aDirection = eForward;
} else if (direction == eDirPrevious) {
*aDirection = eBackward;
} else {
NS_NOTREACHED("Invalid nsDirection enum value");
}
}
}
if (!aSelectionStart || !aSelectionEnd) {
return NS_OK;
}
nsCOMPtr<nsIDOMRange> firstRange;
rv = selection->GetRangeAt(0, getter_AddRefs(firstRange));
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -145,8 +145,12 @@ public:
NS_IMETHOD CheckFireOnChange();
NS_IMETHOD SetSelectionStart(PRInt32 aSelectionStart);
NS_IMETHOD SetSelectionEnd(PRInt32 aSelectionEnd);
NS_IMETHOD SetSelectionRange(PRInt32 aSelectionStart, PRInt32 aSelectionEnd);
NS_IMETHOD GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd);
NS_IMETHOD SetSelectionRange(PRInt32 aSelectionStart,
PRInt32 aSelectionEnd,
SelectionDirection aDirection = eNone);
NS_IMETHOD GetSelectionRange(PRInt32* aSelectionStart,
PRInt32* aSelectionEnd,
SelectionDirection* aDirection = nsnull);
NS_IMETHOD GetOwnedSelectionController(nsISelectionController** aSelCon);
virtual nsFrameSelection* GetOwnedFrameSelection();
@ -390,9 +394,11 @@ protected:
private:
//helper methods
nsresult SetSelectionInternal(nsIDOMNode *aStartNode, PRInt32 aStartOffset,
nsIDOMNode *aEndNode, PRInt32 aEndOffset);
nsIDOMNode *aEndNode, PRInt32 aEndOffset,
SelectionDirection aDirection = eNone);
nsresult SelectAllOrCollapseToEndOfText(PRBool aSelect);
nsresult SetSelectionEndPoints(PRInt32 aSelStart, PRInt32 aSelEnd);
nsresult SetSelectionEndPoints(PRInt32 aSelStart, PRInt32 aSelEnd,
SelectionDirection aDirection = eNone);
// accessors for the notify on input flag
PRBool GetNotifyOnInput() const { return mNotifyOnInput; }

View File

@ -5996,6 +5996,16 @@ nsTypedSelection::SelectionLanguageChange(PRBool aLangRTL)
return NS_OK;
}
NS_IMETHODIMP_(nsDirection)
nsTypedSelection::GetSelectionDirection() {
return mDirection;
}
NS_IMETHODIMP_(void)
nsTypedSelection::SetSelectionDirection(nsDirection aDirection) {
mDirection = aDirection;
}
// nsAutoCopyListener

View File

@ -491,7 +491,7 @@ NS_IMETHODIMP
nsFormFillController::SelectTextRange(PRInt32 aStartIndex, PRInt32 aEndIndex)
{
if (mFocusedInput)
mFocusedInput->SetSelectionRange(aStartIndex, aEndIndex);
mFocusedInput->SetSelectionRange(aStartIndex, aEndIndex, EmptyString());
return NS_OK;
}