From 2c38b0b6b707e18bd03ec4dd15ffe6d60597701a Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Tue, 9 Sep 2014 23:27:56 +0000 Subject: [PATCH] Bug 1061468 - Notify the editor when removing the focused element is its ancestor limiter. r=ehsan --- content/base/public/nsISelectionPrivate.idl | 5 ++--- dom/base/nsFocusManager.cpp | 25 +++++++++++++++++++-- editor/libeditor/nsEditor.cpp | 13 ++++++----- editor/libeditor/nsEditor.h | 3 --- editor/nsIEditor.idl | 7 +++++- layout/generic/nsSelection.cpp | 10 +++++++++ 6 files changed, 48 insertions(+), 15 deletions(-) diff --git a/content/base/public/nsISelectionPrivate.idl b/content/base/public/nsISelectionPrivate.idl index 46f1622d6ece..f329f66b1975 100644 --- a/content/base/public/nsISelectionPrivate.idl +++ b/content/base/public/nsISelectionPrivate.idl @@ -28,13 +28,14 @@ template class nsTArray; native nsDirection(nsDirection); native ScrollAxis(nsIPresShell::ScrollAxis); -[scriptable, builtinclass, uuid(52629837-7b3f-4434-940d-a14de7ef9b7a)] +[scriptable, builtinclass, uuid(5a82ee9a-35ce-11e4-8c3e-b7043d68ad70)] interface nsISelectionPrivate : nsISelection { const short ENDOFPRECEDINGLINE=0; const short STARTOFNEXTLINE=1; attribute boolean interlinePosition; + [noscript] attribute nsIContent ancestorLimiter; /* startBatchChanges match this up with endbatchChanges. will stop ui updates while multiple selection methods are called @@ -81,8 +82,6 @@ interface nsISelectionPrivate : nsISelection */ [noscript] void getCachedFrameOffset(in nsIFrame aFrame, in int32_t inOffset, in nsPointRef aPoint); - [noscript] void setAncestorLimiter(in nsIContent aContent); - /** * Set the painting style for the range. The range must be a range in * the selection. The textRangeStyle will be used by text frame diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp index 3e25711af145..ed8570662978 100644 --- a/dom/base/nsFocusManager.cpp +++ b/dom/base/nsFocusManager.cpp @@ -12,6 +12,7 @@ #include "nsContentUtils.h" #include "nsIDocument.h" #include "nsIDOMWindow.h" +#include "nsIEditor.h" #include "nsPIDOMWindow.h" #include "nsIDOMElement.h" #include "nsIDOMDocument.h" @@ -815,8 +816,7 @@ nsFocusManager::ContentRemoved(nsIDocument* aDocument, nsIContent* aContent) // element as well, but don't fire any events. if (window == mFocusedWindow) { mFocusedContent = nullptr; - } - else { + } else { // Check if the node that was focused is an iframe or similar by looking // if it has a subdocument. This would indicate that this focused iframe // and its descendants will be going away. We will need to move the @@ -834,6 +834,27 @@ nsFocusManager::ContentRemoved(nsIDocument* aDocument, nsIContent* aContent) } } + // Notify the editor in case we removed its ancestor limiter. + if (content->IsEditable()) { + nsCOMPtr docShell = aDocument->GetDocShell(); + if (docShell) { + nsCOMPtr editor; + docShell->GetEditor(getter_AddRefs(editor)); + if (editor) { + nsCOMPtr s; + editor->GetSelection(getter_AddRefs(s)); + nsCOMPtr selection = do_QueryInterface(s); + if (selection) { + nsCOMPtr limiter; + selection->GetAncestorLimiter(getter_AddRefs(limiter)); + if (limiter == content) { + editor->FinalizeSelection(); + } + } + } + } + } + NotifyFocusStateChange(content, shouldShowFocusRing, false); } diff --git a/editor/libeditor/nsEditor.cpp b/editor/libeditor/nsEditor.cpp index 25926466d564..37cd765346ac 100644 --- a/editor/libeditor/nsEditor.cpp +++ b/editor/libeditor/nsEditor.cpp @@ -4806,30 +4806,30 @@ nsEditor::InitializeSelection(nsIDOMEventTarget* aFocusEventTarget) return NS_OK; } -void +NS_IMETHODIMP nsEditor::FinalizeSelection() { nsCOMPtr selCon; nsresult rv = GetSelectionController(getter_AddRefs(selCon)); - NS_ENSURE_SUCCESS_VOID(rv); + NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr selection; rv = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection)); - NS_ENSURE_SUCCESS_VOID(rv); + NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr selectionPrivate = do_QueryInterface(selection); - NS_ENSURE_TRUE_VOID(selectionPrivate); + NS_ENSURE_TRUE(selectionPrivate, rv); selectionPrivate->SetAncestorLimiter(nullptr); nsCOMPtr presShell = GetPresShell(); - NS_ENSURE_TRUE_VOID(presShell); + NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_INITIALIZED); selCon->SetCaretEnabled(false); nsFocusManager* fm = nsFocusManager::GetFocusManager(); - NS_ENSURE_TRUE_VOID(fm); + NS_ENSURE_TRUE(fm, NS_ERROR_NOT_INITIALIZED); fm->UpdateCaretForCaretBrowsingMode(); if (!HasIndependentSelection()) { @@ -4860,6 +4860,7 @@ nsEditor::FinalizeSelection() } selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL); + return NS_OK; } dom::Element * diff --git a/editor/libeditor/nsEditor.h b/editor/libeditor/nsEditor.h index e3b0549f93bd..9d95d9c98a35 100644 --- a/editor/libeditor/nsEditor.h +++ b/editor/libeditor/nsEditor.h @@ -801,9 +801,6 @@ public: // nothing. nsresult InitializeSelection(nsIDOMEventTarget* aFocusEventTarget); - // Finalizes selection and caret for the editor. - void FinalizeSelection(); - // This method has to be called by nsEditorEventListener::Focus. // All actions that have to be done when the editor is focused needs to be // added here. diff --git a/editor/nsIEditor.idl b/editor/nsIEditor.idl index 161a59cba2fd..250a2b18584c 100644 --- a/editor/nsIEditor.idl +++ b/editor/nsIEditor.idl @@ -21,7 +21,7 @@ interface nsIEditActionListener; interface nsIInlineSpellChecker; interface nsITransferable; -[scriptable, uuid(04714a01-e02f-4ef5-a388-612451d0db16)] +[scriptable, uuid(a1ddae68-35d0-11e4-9329-cb55463f21c9)] interface nsIEditor : nsISupports { @@ -42,6 +42,11 @@ interface nsIEditor : nsISupports readonly attribute nsISelection selection; + /** + * Finalizes selection and caret for the editor. + */ + [noscript] void finalizeSelection(); + /** * Init is to tell the implementation of nsIEditor to begin its services * @param aDoc The dom document interface being observed diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index 0cf22065016c..bfe39dcc77d7 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -4265,6 +4265,16 @@ Selection::GetCachedFrameOffset(nsIFrame* aFrame, int32_t inOffset, return rv; } +NS_IMETHODIMP +Selection::GetAncestorLimiter(nsIContent** aContent) +{ + if (mFrameSelection) { + nsCOMPtr c = mFrameSelection->GetAncestorLimiter(); + c.forget(aContent); + } + return NS_OK; +} + NS_IMETHODIMP Selection::SetAncestorLimiter(nsIContent* aContent) {