Bug 629878 - Part 2: Do not scroll the selection into view when restoring the selection offsets for a text control after a reframe; r=roc a=blocking-final+

Previously, we used to scroll the text control's selection into view after a
reframe.  This had two problems: it was not precise (in case the selection was
modified by the mouse, for example), and it lead to problems such as bug 629878
if the control's frame was reconstructed because of the control being moved
inside the DOM.

This patch disables that behavior by wrapping the selection scroll function
into nsITextControlFrame::ScrollSelectionIntoView, so that APIs such as
setSelectionRange on the text control's content node can still call it
explicitly (since they actually need this behavior), but other callers of
nsITextControlFrame::SetSelectionRange (such as the nsTextEditorState
object's selection offset restoring mechanism) don't get this behavior as
an undesired side-effect.
This commit is contained in:
Ehsan Akhgari 2011-02-04 19:29:29 -05:00
parent cbe552f50f
commit deae53f1e4
5 changed files with 53 additions and 17 deletions

View File

@ -2857,8 +2857,12 @@ nsHTMLInputElement::SetSelectionRange(PRInt32 aSelectionStart,
if (formControlFrame) {
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
if (textControlFrame)
if (textControlFrame) {
rv = textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd);
if (NS_SUCCEEDED(rv)) {
rv = textControlFrame->ScrollSelectionIntoView();
}
}
}
return rv;
@ -2881,8 +2885,12 @@ nsHTMLInputElement::SetSelectionStart(PRInt32 aSelectionStart)
if (formControlFrame) {
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
if (textControlFrame)
if (textControlFrame) {
rv = textControlFrame->SetSelectionStart(aSelectionStart);
if (NS_SUCCEEDED(rv)) {
rv = textControlFrame->ScrollSelectionIntoView();
}
}
}
return rv;
@ -2906,8 +2914,12 @@ nsHTMLInputElement::SetSelectionEnd(PRInt32 aSelectionEnd)
if (formControlFrame) {
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
if (textControlFrame)
if (textControlFrame) {
rv = textControlFrame->SetSelectionEnd(aSelectionEnd);
if (NS_SUCCEEDED(rv)) {
rv = textControlFrame->ScrollSelectionIntoView();
}
}
}
return rv;

View File

@ -879,8 +879,12 @@ nsHTMLTextAreaElement::SetSelectionStart(PRInt32 aSelectionStart)
if (formControlFrame){
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
if (textControlFrame)
if (textControlFrame) {
rv = textControlFrame->SetSelectionStart(aSelectionStart);
if (NS_SUCCEEDED(rv)) {
rv = textControlFrame->ScrollSelectionIntoView();
}
}
}
return rv;
@ -903,8 +907,12 @@ nsHTMLTextAreaElement::SetSelectionEnd(PRInt32 aSelectionEnd)
if (formControlFrame) {
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
if (textControlFrame)
if (textControlFrame) {
rv = textControlFrame->SetSelectionEnd(aSelectionEnd);
if (NS_SUCCEEDED(rv)) {
rv = textControlFrame->ScrollSelectionIntoView();
}
}
}
return rv;
@ -934,8 +942,12 @@ nsHTMLTextAreaElement::SetSelectionRange(PRInt32 aSelectionStart, PRInt32 aSelec
if (formControlFrame) {
nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
if (textControlFrame)
if (textControlFrame) {
rv = textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd);
if (NS_SUCCEEDED(rv)) {
rv = textControlFrame->ScrollSelectionIntoView();
}
}
}
return rv;

View File

@ -76,6 +76,8 @@ public:
* @throws various and sundry other things
*/
virtual nsresult EnsureEditorInitialized() = 0;
virtual nsresult ScrollSelectionIntoView() = 0;
};
#endif

View File

@ -855,18 +855,23 @@ nsTextControlFrame::SetSelectionInternal(nsIDOMNode *aStartNode,
NS_ENSURE_SUCCESS(rv, rv);
rv = selection->AddRange(range); // NOTE: can destroy the world
NS_ENSURE_SUCCESS(rv, rv);
// Fetch it again since it might have been destroyed (bug 626014).
selCon = txtCtrl->GetSelectionController();
if (!selCon) {
return NS_OK; // nothing to scroll, we're done
}
return rv;
}
nsresult
nsTextControlFrame::ScrollSelectionIntoView()
{
nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
NS_ASSERTION(txtCtrl, "Content not a text control element");
nsISelectionController* selCon = txtCtrl->GetSelectionController();
if (selCon) {
// Scroll the selection into view (see bug 231389).
return selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
nsISelectionController::SELECTION_FOCUS_REGION,
nsISelectionController::SCROLL_FIRST_ANCESTOR_ONLY);
}
return NS_ERROR_FAILURE;
}
nsresult
@ -914,8 +919,11 @@ nsTextControlFrame::SelectAllOrCollapseToEndOfText(PRBool aSelect)
}
}
return SetSelectionInternal(rootNode, aSelect ? 0 : numChildren,
rv = SetSelectionInternal(rootNode, aSelect ? 0 : numChildren,
rootNode, numChildren);
NS_ENSURE_SUCCESS(rv, rv);
return ScrollSelectionIntoView();
}
nsresult

View File

@ -370,6 +370,8 @@ protected:
nsresult CalcIntrinsicSize(nsIRenderingContext* aRenderingContext,
nsSize& aIntrinsicSize);
nsresult ScrollSelectionIntoView();
private:
//helper methods
nsresult SetSelectionInternal(nsIDOMNode *aStartNode, PRInt32 aStartOffset,