From 44ae690779919ef01bde7869ae948564e0662165 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Wed, 4 Apr 2018 22:27:49 +0900 Subject: [PATCH] Bug 1449564 - part 2: Make absolute positioned element editor disabled in default and make it possible to enable it with new command r=m_kato We have another built-in UI of editor which is not implemented by any other browsers. That is a draggable handler to move absolute positioned elements. So, we should disable it in default for compatibility with the other browsers. However, different from resizers and inline table editor, we don't have command to enable/disable this feature but for backward compatibility, we should have it. Therefore, this patch adds new command "enableAbsolutePositionEditor". Note that whether resizing UI is available only with enableObjectResizing state is different from enableInlineTableEditing command. Resizers for absolute positioned elements are NOT available both enableObjectResizing and enableAbsolutePositionEditor are enabled. Additionally, this adds automated tests to check basic functions of absolute positioned editor. MozReview-Commit-ID: 9ZSGB8tLpFw --HG-- rename : editor/libeditor/tests/test_resizers_appearance.html => editor/libeditor/tests/test_abs_positioner_appearance.html rename : editor/libeditor/tests/test_resizers_resizing_elements.html => editor/libeditor/tests/test_abs_positioner_positioning_elements.html extra : rebase_source : d516f3f3ef36d4ad13938f214cb6e3868d7ff407 --- dom/html/nsHTMLDocument.cpp | 1 + editor/libeditor/HTMLAbsPositionEditor.cpp | 4 +- editor/libeditor/HTMLAnonymousNodeEditor.cpp | 8 +- editor/libeditor/HTMLEditor.cpp | 2 +- editor/libeditor/HTMLEditor.h | 14 +- editor/libeditor/HTMLEditorCommands.cpp | 38 ++-- editor/libeditor/HTMLEditorController.cpp | 3 +- .../libeditor/HTMLEditorDocumentCommands.cpp | 27 +++ editor/libeditor/tests/mochitest.ini | 4 + .../tests/test_abs_positioner_appearance.html | 167 ++++++++++++++++++ ...t_abs_positioner_positioning_elements.html | 120 +++++++++++++ .../tests/test_resizers_appearance.html | 53 +++--- .../test_resizers_resizing_elements.html | 11 ++ 13 files changed, 399 insertions(+), 53 deletions(-) create mode 100644 editor/libeditor/tests/test_abs_positioner_appearance.html create mode 100644 editor/libeditor/tests/test_abs_positioner_positioning_elements.html diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp index 9f8e664f720c..aea06f9aba2b 100644 --- a/dom/html/nsHTMLDocument.cpp +++ b/dom/html/nsHTMLDocument.cpp @@ -2728,6 +2728,7 @@ static const struct MidasCommand gMidasCommandTable[] = { { "defaultParagraphSeparator", "cmd_defaultParagraphSeparator", "", false, false }, { "enableObjectResizing", "cmd_enableObjectResizing", "", false, true }, { "enableInlineTableEditing", "cmd_enableInlineTableEditing", "", false, true }, + { "enableAbsolutePositionEditing", "cmd_enableAbsolutePositionEditing", "", false, true }, #if 0 // no editor support to remove alignments right now { "justifynone", "cmd_align", "", true, false }, diff --git a/editor/libeditor/HTMLAbsPositionEditor.cpp b/editor/libeditor/HTMLAbsPositionEditor.cpp index 96d8534d577b..2569e7ce1c8f 100644 --- a/editor/libeditor/HTMLAbsPositionEditor.cpp +++ b/editor/libeditor/HTMLAbsPositionEditor.cpp @@ -109,14 +109,14 @@ HTMLEditor::GetAbsolutelyPositionedSelectionContainer() NS_IMETHODIMP HTMLEditor::GetAbsolutePositioningEnabled(bool* aIsEnabled) { - *aIsEnabled = AbsolutePositioningEnabled(); + *aIsEnabled = IsAbsolutePositionEditorEnabled(); return NS_OK; } NS_IMETHODIMP HTMLEditor::SetAbsolutePositioningEnabled(bool aIsEnabled) { - mIsAbsolutelyPositioningEnabled = aIsEnabled; + EnableAbsolutePositionEditor(aIsEnabled); return NS_OK; } diff --git a/editor/libeditor/HTMLAnonymousNodeEditor.cpp b/editor/libeditor/HTMLAnonymousNodeEditor.cpp index 87d9f18b60b6..55553479568a 100644 --- a/editor/libeditor/HTMLAnonymousNodeEditor.cpp +++ b/editor/libeditor/HTMLAnonymousNodeEditor.cpp @@ -295,7 +295,7 @@ HTMLEditor::CheckSelectionStateForAnonymousButtons(Selection* aSelection) // early way out if all contextual UI extensions are disabled if (NS_WARN_IF(!IsObjectResizerEnabled() && - !mIsAbsolutelyPositioningEnabled && + !IsAbsolutePositionEditorEnabled() && !IsInlineTableEditorEnabled())) { return NS_OK; } @@ -320,7 +320,7 @@ HTMLEditor::CheckSelectionStateForAnonymousButtons(Selection* aSelection) nsAtom* focusTagAtom = focusElement->NodeInfo()->NameAtom(); RefPtr absPosElement; - if (mIsAbsolutelyPositioningEnabled) { + if (IsAbsolutePositionEditorEnabled()) { // Absolute Positioning support is enabled, is the selection contained // in an absolutely positioned element ? absPosElement = GetAbsolutelyPositionedSelectionContainer(); @@ -361,7 +361,7 @@ HTMLEditor::CheckSelectionStateForAnonymousButtons(Selection* aSelection) // content which means a DOMAttrModified handler may cause arbitrary // side effects while this code runs (bug 420439). - if (mIsAbsolutelyPositioningEnabled && mAbsolutelyPositionedObject && + if (IsAbsolutePositionEditorEnabled() && mAbsolutelyPositionedObject && absPosElement != mAbsolutelyPositionedObject) { HideGrabber(); NS_ASSERTION(!mAbsolutelyPositionedObject, "HideGrabber failed"); @@ -402,7 +402,7 @@ HTMLEditor::CheckSelectionStateForAnonymousButtons(Selection* aSelection) } } - if (mIsAbsolutelyPositioningEnabled && absPosElement && + if (IsAbsolutePositionEditorEnabled() && absPosElement && IsModifiableNode(*absPosElement) && absPosElement != hostContent) { if (mAbsolutelyPositionedObject) { nsresult rv = RefreshGrabber(); diff --git a/editor/libeditor/HTMLEditor.cpp b/editor/libeditor/HTMLEditor.cpp index 30f2e563bcfb..d1a4e6556289 100644 --- a/editor/libeditor/HTMLEditor.cpp +++ b/editor/libeditor/HTMLEditor.cpp @@ -120,7 +120,7 @@ HTMLEditor::HTMLEditor() , mIsResizing(false) , mPreserveRatio(false) , mResizedObjectIsAnImage(false) - , mIsAbsolutelyPositioningEnabled(true) + , mIsAbsolutelyPositioningEnabled(false) , mResizedObjectIsAbsolutelyPositioned(false) , mHasShownGrabber(false) , mGrabberClicked(false) diff --git a/editor/libeditor/HTMLEditor.h b/editor/libeditor/HTMLEditor.h index 9050d96a4fb2..22bae73e013e 100644 --- a/editor/libeditor/HTMLEditor.h +++ b/editor/libeditor/HTMLEditor.h @@ -247,12 +247,22 @@ public: return mIsInlineTableEditingEnabled; } - // non-virtual methods of interface methods - bool AbsolutePositioningEnabled() const + /** + * Enable/disable absolute position editor, resizing absolute positioned + * elements (required object resizers enabled) or positioning them with + * dragging grabber. + */ + void EnableAbsolutePositionEditor(bool aEnable) + { + mIsAbsolutelyPositioningEnabled = aEnable; + } + bool IsAbsolutePositionEditorEnabled() const { return mIsAbsolutelyPositioningEnabled; } + // non-virtual methods of interface methods + /** * returns the deepest absolutely positioned container of the selection * if it exists or null. diff --git a/editor/libeditor/HTMLEditorCommands.cpp b/editor/libeditor/HTMLEditorCommands.cpp index 513c5aaeabb9..fb73127137be 100644 --- a/editor/libeditor/HTMLEditorCommands.cpp +++ b/editor/libeditor/HTMLEditorCommands.cpp @@ -1084,9 +1084,9 @@ AbsolutePositioningCommand::AbsolutePositioningCommand() NS_IMETHODIMP AbsolutePositioningCommand::IsCommandEnabled(const char* aCommandName, nsISupports* aCommandRefCon, - bool* outCmdEnabled) + bool* aOutCmdEnabled) { - *outCmdEnabled = false; + *aOutCmdEnabled = false; nsCOMPtr editor = do_QueryInterface(aCommandRefCon); if (!editor) { @@ -1099,7 +1099,7 @@ AbsolutePositioningCommand::IsCommandEnabled(const char* aCommandName, if (!htmlEditor->IsSelectionEditable()) { return NS_OK; } - *outCmdEnabled = htmlEditor->AbsolutePositioningEnabled(); + *aOutCmdEnabled = htmlEditor->IsAbsolutePositionEditorEnabled(); return NS_OK; } @@ -1112,8 +1112,7 @@ AbsolutePositioningCommand::GetCurrentState(HTMLEditor* aHTMLEditor, } nsCommandParams* params = aParams->AsCommandParams(); - bool isEnabled = aHTMLEditor->AbsolutePositioningEnabled(); - if (!isEnabled) { + if (!aHTMLEditor->IsAbsolutePositionEditorEnabled()) { params->SetBool(STATE_MIXED, false); params->SetCString(STATE_ATTRIBUTE, EmptyCString()); return NS_OK; @@ -1143,10 +1142,10 @@ AbsolutePositioningCommand::ToggleState(HTMLEditor* aHTMLEditor) NS_IMETHODIMP DecreaseZIndexCommand::IsCommandEnabled(const char* aCommandName, - nsISupports* refCon, - bool* outCmdEnabled) + nsISupports* aRefCon, + bool* aOutCmdEnabled) { - nsCOMPtr editor = do_QueryInterface(refCon); + nsCOMPtr editor = do_QueryInterface(aRefCon); if (NS_WARN_IF(!editor)) { return NS_ERROR_FAILURE; } @@ -1155,18 +1154,19 @@ DecreaseZIndexCommand::IsCommandEnabled(const char* aCommandName, return NS_ERROR_FAILURE; } - *outCmdEnabled = htmlEditor->AbsolutePositioningEnabled(); - if (!(*outCmdEnabled)) + if (!htmlEditor->IsAbsolutePositionEditorEnabled()) { + *aOutCmdEnabled = false; return NS_OK; + } RefPtr positionedElement = htmlEditor->GetPositionedElement(); - *outCmdEnabled = false; if (!positionedElement) { + *aOutCmdEnabled = false; return NS_OK; } int32_t z = htmlEditor->GetZIndex(*positionedElement); - *outCmdEnabled = (z > 0); + *aOutCmdEnabled = (z > 0); return NS_OK; } @@ -1209,10 +1209,10 @@ DecreaseZIndexCommand::GetCommandStateParams(const char* aCommandName, NS_IMETHODIMP IncreaseZIndexCommand::IsCommandEnabled(const char* aCommandName, - nsISupports* refCon, - bool* outCmdEnabled) + nsISupports* aRefCon, + bool* aOutCmdEnabled) { - nsCOMPtr editor = do_QueryInterface(refCon); + nsCOMPtr editor = do_QueryInterface(aRefCon); if (NS_WARN_IF(!editor)) { return NS_ERROR_FAILURE; } @@ -1221,12 +1221,12 @@ IncreaseZIndexCommand::IsCommandEnabled(const char* aCommandName, return NS_ERROR_FAILURE; } - *outCmdEnabled = htmlEditor->AbsolutePositioningEnabled(); - if (!(*outCmdEnabled)) + if (!htmlEditor->IsAbsolutePositionEditorEnabled()) { + *aOutCmdEnabled = false; return NS_OK; + } - Element* positionedElement = htmlEditor->GetPositionedElement(); - *outCmdEnabled = (nullptr != positionedElement); + *aOutCmdEnabled = !!htmlEditor->GetPositionedElement(); return NS_OK; } diff --git a/editor/libeditor/HTMLEditorController.cpp b/editor/libeditor/HTMLEditorController.cpp index 7aec368c56d8..2897a2e39359 100644 --- a/editor/libeditor/HTMLEditorController.cpp +++ b/editor/libeditor/HTMLEditorController.cpp @@ -69,7 +69,8 @@ HTMLEditorController::RegisterEditorDocStateCommands( NS_REGISTER_NEXT_COMMAND(SetDocumentStateCommand, "cmd_insertBrOnReturn") NS_REGISTER_NEXT_COMMAND(SetDocumentStateCommand, "cmd_defaultParagraphSeparator") NS_REGISTER_NEXT_COMMAND(SetDocumentStateCommand, "cmd_enableObjectResizing") - NS_REGISTER_LAST_COMMAND(SetDocumentStateCommand, "cmd_enableInlineTableEditing") + NS_REGISTER_NEXT_COMMAND(SetDocumentStateCommand, "cmd_enableInlineTableEditing") + NS_REGISTER_LAST_COMMAND(SetDocumentStateCommand, "cmd_enableAbsolutePositionEditing") NS_REGISTER_ONE_COMMAND(SetDocumentOptionsCommand, "cmd_setDocumentOptions") diff --git a/editor/libeditor/HTMLEditorDocumentCommands.cpp b/editor/libeditor/HTMLEditorDocumentCommands.cpp index 81026a785e5e..4a58b1cedfb0 100644 --- a/editor/libeditor/HTMLEditorDocumentCommands.cpp +++ b/editor/libeditor/HTMLEditorDocumentCommands.cpp @@ -362,6 +362,21 @@ SetDocumentStateCommand::DoCommandParams(const char* aCommandName, return NS_OK; } + if (!nsCRT::strcmp(aCommandName, "cmd_enableAbsolutePositionEditing")) { + NS_ENSURE_ARG_POINTER(aParams); + HTMLEditor* htmlEditor = textEditor->AsHTMLEditor(); + if (NS_WARN_IF(!htmlEditor)) { + return NS_ERROR_INVALID_ARG; + } + ErrorResult error; + bool enabled = params->GetBool(STATE_ATTRIBUTE, error); + if (NS_WARN_IF(error.Failed())) { + return error.StealNSResult(); + } + htmlEditor->EnableAbsolutePositionEditor(enabled); + return NS_OK; + } + return NS_ERROR_NOT_IMPLEMENTED; } @@ -524,6 +539,18 @@ SetDocumentStateCommand::GetCommandStateParams(const char* aCommandName, return NS_OK; } + // cmd_enableAbsolutePositionEditing is a Gecko specific command, + // "cenableAbsolutePositionEditing". + if (!nsCRT::strcmp(aCommandName, "cmd_enableAbsolutePositionEditing")) { + NS_ENSURE_ARG_POINTER(aParams); + HTMLEditor* htmlEditor = textEditor->AsHTMLEditor(); + if (NS_WARN_IF(!htmlEditor)) { + return NS_ERROR_INVALID_ARG; + } + return params->SetBool(STATE_ALL, + htmlEditor->IsAbsolutePositionEditorEnabled()); + } + return NS_ERROR_NOT_IMPLEMENTED; } diff --git a/editor/libeditor/tests/mochitest.ini b/editor/libeditor/tests/mochitest.ini index 021aaa8e9b8d..377694231c59 100644 --- a/editor/libeditor/tests/mochitest.ini +++ b/editor/libeditor/tests/mochitest.ini @@ -259,6 +259,10 @@ skip-if = toolkit == 'android' # bug 1315898 [test_bug1409520.html] [test_bug1425997.html] +[test_abs_positioner_appearance.html] +skip-if = toolkit == 'android' && debug # bug 1480702, causes permanent failure of non-related test +[test_abs_positioner_positioning_elements.html] +skip-if = android_version == '18' # bug 1147989 [test_CF_HTML_clipboard.html] subsuite = clipboard [test_composition_event_created_in_chrome.html] diff --git a/editor/libeditor/tests/test_abs_positioner_appearance.html b/editor/libeditor/tests/test_abs_positioner_appearance.html new file mode 100644 index 000000000000..b7fd8e840b02 --- /dev/null +++ b/editor/libeditor/tests/test_abs_positioner_appearance.html @@ -0,0 +1,167 @@ + + + + Test for absolute positioner appearance + + + + + +

+ + +
+
+ +
+
+
+
+ + diff --git a/editor/libeditor/tests/test_abs_positioner_positioning_elements.html b/editor/libeditor/tests/test_abs_positioner_positioning_elements.html new file mode 100644 index 000000000000..660182836706 --- /dev/null +++ b/editor/libeditor/tests/test_abs_positioner_positioning_elements.html @@ -0,0 +1,120 @@ + + + + Test for positioners of absolute positioned elements + + + + + + +

+
+
+ +
+
+
+ + diff --git a/editor/libeditor/tests/test_resizers_appearance.html b/editor/libeditor/tests/test_resizers_appearance.html index 9536db9474c6..19e25fc72f0b 100644 --- a/editor/libeditor/tests/test_resizers_appearance.html +++ b/editor/libeditor/tests/test_resizers_appearance.html @@ -44,7 +44,7 @@ SimpleTest.waitForFocus(async function() { }, { description: "absolute positioned
", innerHTML: "
positioned
", - resizable: true, + resizable: function () { return document.queryCommandState("enableAbsolutePositionEditing"); }, }, { description: "fixed positioned
", innerHTML: "
positioned
", @@ -56,35 +56,40 @@ SimpleTest.waitForFocus(async function() { }, ]; - for (const kTest of kTests) { - const kDescription = kTest.description + ": "; - editor.innerHTML = kTest.innerHTML; - let target = document.getElementById("target"); + for (let kEnableAbsolutePositionEditor of [true, false]) { + document.execCommand("enableAbsolutePositionEditing", false, kEnableAbsolutePositionEditor); + for (const kTest of kTests) { + const kDescription = kTest.description + + (kEnableAbsolutePositionEditor ? " (enabled absolute position editor)" : "") + ": "; + editor.innerHTML = kTest.innerHTML; + let target = document.getElementById("target"); - document.execCommand("enableObjectResizing", false, false); - ok(!document.queryCommandState("enableObjectResizing"), - kDescription + "Object resizer should be disabled by the call of execCommand"); + document.execCommand("enableObjectResizing", false, false); + ok(!document.queryCommandState("enableObjectResizing"), + kDescription + "Object resizer should be disabled by the call of execCommand"); - synthesizeMouseAtCenter(outOfEditor, {}); - let promiseSelectionChangeEvent1 = waitForSelectionChange(); - synthesizeMouseAtCenter(target, {}); - await promiseSelectionChangeEvent1; + synthesizeMouseAtCenter(outOfEditor, {}); + let promiseSelectionChangeEvent1 = waitForSelectionChange(); + synthesizeMouseAtCenter(target, {}); + await promiseSelectionChangeEvent1; - ok(!target.hasAttribute("_moz_resizing"), - kDescription + ": While enableObjectResizing is disabled, resizers shouldn't appear"); + ok(!target.hasAttribute("_moz_resizing"), + kDescription + ": While enableObjectResizing is disabled, resizers shouldn't appear"); - document.execCommand("enableObjectResizing", false, true); - ok(document.queryCommandState("enableObjectResizing"), - kDescription + "Object resizer should be enabled by the call of execCommand"); + document.execCommand("enableObjectResizing", false, true); + ok(document.queryCommandState("enableObjectResizing"), + kDescription + "Object resizer should be enabled by the call of execCommand"); - synthesizeMouseAtCenter(outOfEditor, {}); - let promiseSelectionChangeEvent2 = waitForSelectionChange(); - synthesizeMouseAtCenter(target, {}); - await promiseSelectionChangeEvent2; + synthesizeMouseAtCenter(outOfEditor, {}); + let promiseSelectionChangeEvent2 = waitForSelectionChange(); + synthesizeMouseAtCenter(target, {}); + await promiseSelectionChangeEvent2; - is(target.hasAttribute("_moz_resizing"), kTest.resizable, - kDescription + (kTest.resizable ? "While enableObjectResizing is enabled, resizers should appear" : - "Even while enableObjectResizing is enabled, resizers shouldn't appear")); + const kResizable = typeof kTest.resizable === "function" ? kTest.resizable() : kTest.resizable; + is(target.hasAttribute("_moz_resizing"), kResizable, + kDescription + (kResizable ? "While enableObjectResizing is enabled, resizers should appear" : + "Even while enableObjectResizing is enabled, resizers shouldn't appear")); + } } SimpleTest.finish(); diff --git a/editor/libeditor/tests/test_resizers_resizing_elements.html b/editor/libeditor/tests/test_resizers_resizing_elements.html index b0d66249b10b..959d21bace28 100644 --- a/editor/libeditor/tests/test_resizers_resizing_elements.html +++ b/editor/libeditor/tests/test_resizers_resizing_elements.html @@ -47,6 +47,9 @@ SimpleTest.waitForFocus(async function() { if (SpecialPowers.getBoolPref("editor.resizing.preserve_ratio")) { description += " (preserve ratio pref is true)"; } + if (document.queryCommandState("enableAbsolutePositionEditing")) { + description += " (absolute position editor is enabled)"; + } description += ": "; content.innerHTML = aInnerHTML; let target = document.getElementById("target"); @@ -202,23 +205,31 @@ SimpleTest.waitForFocus(async function() { { description: "Resiziers for ", innerHTML: "", mayPreserveRatio: true, + isAbsolutePosition: false, }, { description: "Resiziers for ", innerHTML: "
cellcell
", mayPreserveRatio: false, + isAbsolutePosition: false, }, { description: "Resiziers for absolute positioned
", innerHTML: "
positioned
", mayPreserveRatio: false, + isAbsolutePosition: true, }, ]; + // Resizers for absolute positioned element are available only when + // enableAbsolutePositionEditing is enabled. So, let's enable it + // during testing resizers for absolute positioned elements. await SpecialPowers.pushPrefEnv({"set": [["editor.resizing.preserve_ratio", false]]}); for (const kTest of kTests) { + document.execCommand("enableAbsolutePositionEditing", false, kTests.isAbsolutePosition); await doTest(kTest.description, false, kTest.innerHTML); } await SpecialPowers.pushPrefEnv({"set": [["editor.resizing.preserve_ratio", true]]}); for (const kTest of kTests) { + document.execCommand("enableAbsolutePositionEditing", false, kTests.isAbsolutePosition); await doTest(kTest.description, kTest.mayPreserveRatio, kTest.innerHTML); } content.innerHTML = "";