Bug 1487301 - Part 2. Set ancestor limitter if no set yet. r=masayuki

The ancestor limiter is set by focus event handler of editor. But window that
is run script has no focus, this event isn't fired by addRange etc.

Some execCommand's commands such as 'forwardDelete' uses WillDeleteSelection
then selection for deletion is set by selection controller (in
TextEditor::ExtendSelectionForDelete). So, due to no ancestor limiter, caret
(and any for delete commands such as CharacterExtendForDelete) can move to out
of editor's root.

So we should set ancestor limiter if nothing. If focus event is received by
user interaction etc, limiter will be set again.

Differential Revision: https://phabricator.services.mozilla.com/D6374

--HG--
extra : rebase_source : 240c3bc09b37d46d1ce3245bcca55cafc59454c5
This commit is contained in:
Makoto Kato 2018-09-20 19:03:24 +09:00
parent eed71e1db2
commit e851a155cb
2 changed files with 44 additions and 0 deletions

View File

@ -162,6 +162,41 @@ protected:
HTMLEditor* mHTMLEditor;
};
class MOZ_RAII AutoSetTemporaryAncestorLimiter final
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
public:
explicit AutoSetTemporaryAncestorLimiter(HTMLEditor& aHTMLEditor,
Selection& aSelection,
nsINode& aStartPointNode
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
if (aSelection.GetAncestorLimiter()) {
return;
}
Element* root = aHTMLEditor.FindSelectionRoot(&aStartPointNode);
if (root) {
aHTMLEditor.InitializeSelectionAncestorLimit(aSelection, *root);
mSelection = &aSelection;
}
}
~AutoSetTemporaryAncestorLimiter()
{
if (mSelection) {
mSelection->SetAncestorLimiter(nullptr);
}
}
private:
RefPtr<Selection> mSelection;
};
/********************************************************
* mozilla::HTMLEditRules
********************************************************/
@ -2405,6 +2440,13 @@ HTMLEditRules::WillDeleteSelection(nsIEditor::EDirection aAction,
return NS_OK;
}
// ExtendSelectionForDelete will use selection controller to set
// selection for delete. But if focus event doesn't receive yet,
// ancestor isn't set. So we must set root eleement of editor to
// ancestor.
AutoSetTemporaryAncestorLimiter autoSetter(HTMLEditorRef(), SelectionRef(),
*startPoint.GetContainer());
rv = HTMLEditorRef().ExtendSelectionForDelete(&SelectionRef(), &aAction);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;

View File

@ -42,6 +42,7 @@ class nsRange;
namespace mozilla {
class AutoSelectionSetterAfterTableEdit;
class AutoSetTemporaryAncestorLimiter;
class DocumentResizeEventListener;
class EmptyEditableFunctor;
class ResizerSelectionListener;
@ -2397,6 +2398,7 @@ protected:
ParagraphSeparator mDefaultParagraphSeparator;
friend class AutoSelectionSetterAfterTableEdit;
friend class AutoSetTemporaryAncestorLimiter;
friend class CSSEditUtils;
friend class DocumentResizeEventListener;
friend class EditorBase;