2012-05-21 15:12:37 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
#include "mozilla/HTMLEditor.h"
|
|
|
|
|
2012-07-13 10:33:42 +04:00
|
|
|
#include "mozilla/Attributes.h"
|
2019-03-15 08:01:10 +03:00
|
|
|
#include "mozilla/PresShell.h"
|
2019-04-30 04:52:53 +03:00
|
|
|
#include "mozilla/PresShellInlines.h"
|
Bug 1555216 - Change the signature of BindToTree to be (BindContext&, nsINode& aParentNode). r=bzbarsky
BindContext was going to have way more information at first, but then I realized
that most of the things I wanted to know were basically a flag away using the
parent node.
Still I think it's worth it, now experimenting with BindToTree will only mean
adding a field to a struct that's included from a couple cpp files, instead of a
massive pain.
I also think this is clearer, and doing this highlights quite a few
inconsistencies in our code which I've left untouched, but commented with
FIXMEs.
Steps are:
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsresult BindToTree(Document\* aDocument, nsIContent\* aParent,#nsresult BindToTree(BindContext\&, nsINode\& aParent)#g' $file; done
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's# nsIContent\* aBindingParent) override#override#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(Document\* aDocument, nsIContent\* aParent,#::BindToTree(BindContext\& aContext, nsINode\& aParent)#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsIContent\* aBindingParent)##g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(aDocument, aParent, aBindingParent)#::BindToTree(aContext, aParent)#g' $file; done
$ ./mach clang-format
Then manual fixups.
Depends on D32948
Differential Revision: https://phabricator.services.mozilla.com/D32949
2019-05-29 07:27:04 +03:00
|
|
|
#include "mozilla/dom/BindContext.h"
|
2012-07-13 10:33:42 +04:00
|
|
|
#include "mozilla/dom/Element.h"
|
2018-04-05 20:42:40 +03:00
|
|
|
#include "mozilla/dom/EventTarget.h"
|
2012-07-13 10:33:42 +04:00
|
|
|
#include "mozilla/mozalloc.h"
|
|
|
|
#include "nsAString.h"
|
|
|
|
#include "nsCOMPtr.h"
|
2012-07-08 13:50:31 +04:00
|
|
|
#include "nsComputedDOMStyle.h"
|
2012-07-13 10:33:42 +04:00
|
|
|
#include "nsDebug.h"
|
|
|
|
#include "nsError.h"
|
2018-01-30 07:40:11 +03:00
|
|
|
#include "nsGenericHTMLElement.h"
|
2014-08-29 15:43:24 +04:00
|
|
|
#include "nsGkAtoms.h"
|
2017-10-03 01:05:19 +03:00
|
|
|
#include "nsAtom.h"
|
2003-06-25 12:50:48 +04:00
|
|
|
#include "nsIContent.h"
|
2012-07-13 10:33:42 +04:00
|
|
|
#include "nsID.h"
|
|
|
|
#include "nsIDOMWindow.h"
|
2019-01-02 16:05:23 +03:00
|
|
|
#include "mozilla/dom/Document.h"
|
2012-07-13 10:33:42 +04:00
|
|
|
#include "nsIDocumentObserver.h"
|
|
|
|
#include "nsIHTMLAbsPosEditor.h"
|
|
|
|
#include "nsIHTMLInlineTableEditor.h"
|
|
|
|
#include "nsIHTMLObjectResizer.h"
|
2016-07-14 13:41:14 +03:00
|
|
|
#include "nsStubMutationObserver.h"
|
2012-07-13 10:33:42 +04:00
|
|
|
#include "nsINode.h"
|
|
|
|
#include "nsISupportsImpl.h"
|
|
|
|
#include "nsISupportsUtils.h"
|
|
|
|
#include "nsLiteralString.h"
|
|
|
|
#include "nsPresContext.h"
|
|
|
|
#include "nsReadableUtils.h"
|
|
|
|
#include "nsString.h"
|
|
|
|
#include "nsStringFwd.h"
|
2004-02-19 05:44:03 +03:00
|
|
|
#include "nsUnicharUtils.h"
|
2012-07-13 10:33:42 +04:00
|
|
|
#include "nscore.h"
|
2013-08-22 10:29:57 +04:00
|
|
|
#include "nsContentUtils.h" // for nsAutoScriptBlocker
|
2018-01-11 11:17:57 +03:00
|
|
|
#include "nsROCSSPrimitiveValue.h"
|
2012-07-13 10:33:42 +04:00
|
|
|
|
|
|
|
class nsIDOMEventListener;
|
2004-02-19 05:44:03 +03:00
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
namespace mozilla {
|
|
|
|
|
|
|
|
using namespace dom;
|
2012-06-06 11:35:47 +04:00
|
|
|
|
2018-03-14 14:57:15 +03:00
|
|
|
// Retrieve the rounded number of CSS pixels from a computed CSS property.
|
|
|
|
//
|
|
|
|
// Note that this should only be called for properties whose resolved value
|
|
|
|
// is CSS pixels (like width, height, left, top, right, bottom, margin, padding,
|
|
|
|
// border-*-width, ...).
|
|
|
|
//
|
|
|
|
// See: https://drafts.csswg.org/cssom/#resolved-values
|
|
|
|
static int32_t GetCSSFloatValue(nsComputedDOMStyle* aComputedStyle,
|
|
|
|
const nsAString& aProperty) {
|
2018-01-11 11:17:57 +03:00
|
|
|
MOZ_ASSERT(aComputedStyle);
|
2003-06-25 12:50:48 +04:00
|
|
|
|
|
|
|
// get the computed CSSValue of the property
|
2018-03-14 14:57:15 +03:00
|
|
|
nsAutoString value;
|
|
|
|
nsresult rv = aComputedStyle->GetPropertyValue(aProperty, value);
|
|
|
|
if (NS_FAILED(rv)) {
|
2016-10-19 12:09:33 +03:00
|
|
|
return 0;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-03-16 20:07:33 +03:00
|
|
|
// We only care about resolved values, not a big deal if the element is
|
|
|
|
// undisplayed, for example, and the value is "auto" or what not.
|
2018-03-14 14:57:15 +03:00
|
|
|
int32_t val = value.ToInteger(&rv);
|
2018-03-16 20:07:33 +03:00
|
|
|
return NS_SUCCEEDED(rv) ? val : 0;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2016-07-14 13:41:14 +03:00
|
|
|
class ElementDeletionObserver final : public nsStubMutationObserver {
|
2008-04-06 16:40:33 +04:00
|
|
|
public:
|
2016-07-14 13:41:14 +03:00
|
|
|
ElementDeletionObserver(nsIContent* aNativeAnonNode,
|
Bug 1555216 - Change the signature of BindToTree to be (BindContext&, nsINode& aParentNode). r=bzbarsky
BindContext was going to have way more information at first, but then I realized
that most of the things I wanted to know were basically a flag away using the
parent node.
Still I think it's worth it, now experimenting with BindToTree will only mean
adding a field to a struct that's included from a couple cpp files, instead of a
massive pain.
I also think this is clearer, and doing this highlights quite a few
inconsistencies in our code which I've left untouched, but commented with
FIXMEs.
Steps are:
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsresult BindToTree(Document\* aDocument, nsIContent\* aParent,#nsresult BindToTree(BindContext\&, nsINode\& aParent)#g' $file; done
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's# nsIContent\* aBindingParent) override#override#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(Document\* aDocument, nsIContent\* aParent,#::BindToTree(BindContext\& aContext, nsINode\& aParent)#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsIContent\* aBindingParent)##g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(aDocument, aParent, aBindingParent)#::BindToTree(aContext, aParent)#g' $file; done
$ ./mach clang-format
Then manual fixups.
Depends on D32948
Differential Revision: https://phabricator.services.mozilla.com/D32949
2019-05-29 07:27:04 +03:00
|
|
|
Element* aObservedElement)
|
|
|
|
: mNativeAnonNode(aNativeAnonNode), mObservedElement(aObservedElement) {}
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2008-04-06 16:40:33 +04:00
|
|
|
NS_DECL_ISUPPORTS
|
2016-07-14 13:41:14 +03:00
|
|
|
NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
|
|
|
|
NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2008-04-06 16:40:33 +04:00
|
|
|
protected:
|
2016-07-09 05:42:33 +03:00
|
|
|
~ElementDeletionObserver() {}
|
2016-07-14 13:41:14 +03:00
|
|
|
nsIContent* mNativeAnonNode;
|
Bug 1555216 - Change the signature of BindToTree to be (BindContext&, nsINode& aParentNode). r=bzbarsky
BindContext was going to have way more information at first, but then I realized
that most of the things I wanted to know were basically a flag away using the
parent node.
Still I think it's worth it, now experimenting with BindToTree will only mean
adding a field to a struct that's included from a couple cpp files, instead of a
massive pain.
I also think this is clearer, and doing this highlights quite a few
inconsistencies in our code which I've left untouched, but commented with
FIXMEs.
Steps are:
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsresult BindToTree(Document\* aDocument, nsIContent\* aParent,#nsresult BindToTree(BindContext\&, nsINode\& aParent)#g' $file; done
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's# nsIContent\* aBindingParent) override#override#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(Document\* aDocument, nsIContent\* aParent,#::BindToTree(BindContext\& aContext, nsINode\& aParent)#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsIContent\* aBindingParent)##g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(aDocument, aParent, aBindingParent)#::BindToTree(aContext, aParent)#g' $file; done
$ ./mach clang-format
Then manual fixups.
Depends on D32948
Differential Revision: https://phabricator.services.mozilla.com/D32949
2019-05-29 07:27:04 +03:00
|
|
|
Element* mObservedElement;
|
2008-04-06 16:40:33 +04:00
|
|
|
};
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
NS_IMPL_ISUPPORTS(ElementDeletionObserver, nsIMutationObserver)
|
2016-07-14 13:41:14 +03:00
|
|
|
|
|
|
|
void ElementDeletionObserver::ParentChainChanged(nsIContent* aContent) {
|
|
|
|
// If the native anonymous content has been unbound already in
|
|
|
|
// DeleteRefToAnonymousNode, mNativeAnonNode's parentNode is null.
|
2019-06-06 04:48:10 +03:00
|
|
|
if (aContent != mObservedElement || !mNativeAnonNode ||
|
|
|
|
mNativeAnonNode->GetParent() != aContent) {
|
|
|
|
return;
|
2016-07-14 13:41:14 +03:00
|
|
|
}
|
2019-06-06 04:48:10 +03:00
|
|
|
|
|
|
|
ManualNACPtr::RemoveContentFromNACArray(mNativeAnonNode);
|
|
|
|
|
|
|
|
mObservedElement->RemoveMutationObserver(this);
|
|
|
|
mObservedElement = nullptr;
|
|
|
|
mNativeAnonNode->RemoveMutationObserver(this);
|
|
|
|
mNativeAnonNode = nullptr;
|
|
|
|
NS_RELEASE_THIS();
|
2016-07-14 13:41:14 +03:00
|
|
|
}
|
2008-04-06 16:40:33 +04:00
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
void ElementDeletionObserver::NodeWillBeDestroyed(const nsINode* aNode) {
|
Bug 1555216 - Change the signature of BindToTree to be (BindContext&, nsINode& aParentNode). r=bzbarsky
BindContext was going to have way more information at first, but then I realized
that most of the things I wanted to know were basically a flag away using the
parent node.
Still I think it's worth it, now experimenting with BindToTree will only mean
adding a field to a struct that's included from a couple cpp files, instead of a
massive pain.
I also think this is clearer, and doing this highlights quite a few
inconsistencies in our code which I've left untouched, but commented with
FIXMEs.
Steps are:
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsresult BindToTree(Document\* aDocument, nsIContent\* aParent,#nsresult BindToTree(BindContext\&, nsINode\& aParent)#g' $file; done
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's# nsIContent\* aBindingParent) override#override#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(Document\* aDocument, nsIContent\* aParent,#::BindToTree(BindContext\& aContext, nsINode\& aParent)#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsIContent\* aBindingParent)##g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(aDocument, aParent, aBindingParent)#::BindToTree(aContext, aParent)#g' $file; done
$ ./mach clang-format
Then manual fixups.
Depends on D32948
Differential Revision: https://phabricator.services.mozilla.com/D32949
2019-05-29 07:27:04 +03:00
|
|
|
NS_ASSERTION(aNode == mNativeAnonNode || aNode == mObservedElement,
|
2008-04-06 16:40:33 +04:00
|
|
|
"Wrong aNode!");
|
|
|
|
if (aNode == mNativeAnonNode) {
|
Bug 1555216 - Change the signature of BindToTree to be (BindContext&, nsINode& aParentNode). r=bzbarsky
BindContext was going to have way more information at first, but then I realized
that most of the things I wanted to know were basically a flag away using the
parent node.
Still I think it's worth it, now experimenting with BindToTree will only mean
adding a field to a struct that's included from a couple cpp files, instead of a
massive pain.
I also think this is clearer, and doing this highlights quite a few
inconsistencies in our code which I've left untouched, but commented with
FIXMEs.
Steps are:
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsresult BindToTree(Document\* aDocument, nsIContent\* aParent,#nsresult BindToTree(BindContext\&, nsINode\& aParent)#g' $file; done
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's# nsIContent\* aBindingParent) override#override#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(Document\* aDocument, nsIContent\* aParent,#::BindToTree(BindContext\& aContext, nsINode\& aParent)#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsIContent\* aBindingParent)##g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(aDocument, aParent, aBindingParent)#::BindToTree(aContext, aParent)#g' $file; done
$ ./mach clang-format
Then manual fixups.
Depends on D32948
Differential Revision: https://phabricator.services.mozilla.com/D32949
2019-05-29 07:27:04 +03:00
|
|
|
mObservedElement->RemoveMutationObserver(this);
|
|
|
|
mObservedElement = nullptr;
|
2008-04-06 16:40:33 +04:00
|
|
|
} else {
|
|
|
|
mNativeAnonNode->RemoveMutationObserver(this);
|
2016-07-14 13:41:14 +03:00
|
|
|
mNativeAnonNode->UnbindFromTree();
|
|
|
|
mNativeAnonNode = nullptr;
|
2008-04-06 16:40:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_RELEASE_THIS();
|
|
|
|
}
|
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
ManualNACPtr HTMLEditor::CreateAnonymousElement(nsAtom* aTag,
|
2017-08-07 08:09:51 +03:00
|
|
|
nsIContent& aParentContent,
|
2016-11-24 10:12:04 +03:00
|
|
|
const nsAString& aAnonClass,
|
|
|
|
bool aIsCreatedHidden) {
|
2017-08-03 07:23:38 +03:00
|
|
|
// Don't put anonymous editor element into non-HTML element.
|
|
|
|
// It is mainly for avoiding other anonymous element being inserted
|
|
|
|
// into <svg:use>, but in general we probably don't want to insert
|
|
|
|
// some random HTML anonymous element into a non-HTML element.
|
2017-08-07 08:09:51 +03:00
|
|
|
if (!aParentContent.IsHTMLElement()) {
|
2017-08-03 07:23:38 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-01-02 16:05:23 +03:00
|
|
|
RefPtr<Document> doc = GetDocument();
|
2016-11-24 10:12:04 +03:00
|
|
|
if (NS_WARN_IF(!doc)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
|
|
|
// Get the pres shell
|
2019-03-15 08:01:10 +03:00
|
|
|
RefPtr<PresShell> presShell = GetPresShell();
|
|
|
|
if (NS_WARN_IF(!presShell)) {
|
2016-11-24 10:12:04 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
|
|
|
// Create a new node through the element factory
|
2017-08-02 22:37:44 +03:00
|
|
|
RefPtr<Element> newContentRaw = CreateHTMLContent(aTag);
|
|
|
|
if (NS_WARN_IF(!newContentRaw)) {
|
2016-11-24 10:12:04 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
|
|
|
// add the "hidden" class if needed
|
|
|
|
if (aIsCreatedHidden) {
|
2017-08-02 22:37:44 +03:00
|
|
|
nsresult rv = newContentRaw->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
|
|
|
|
NS_LITERAL_STRING("hidden"), true);
|
2016-11-24 10:12:04 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// add an _moz_anonclass attribute if needed
|
|
|
|
if (!aAnonClass.IsEmpty()) {
|
2017-08-02 22:37:44 +03:00
|
|
|
nsresult rv = newContentRaw->SetAttr(
|
|
|
|
kNameSpaceID_None, nsGkAtoms::_moz_anonclass, aAnonClass, true);
|
2016-11-24 10:12:04 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2008-04-09 06:06:27 +04:00
|
|
|
{
|
|
|
|
nsAutoScriptBlocker scriptBlocker;
|
|
|
|
|
|
|
|
// establish parenthood of the element
|
2017-08-02 22:37:44 +03:00
|
|
|
newContentRaw->SetIsNativeAnonymousRoot();
|
Bug 1555216 - Change the signature of BindToTree to be (BindContext&, nsINode& aParentNode). r=bzbarsky
BindContext was going to have way more information at first, but then I realized
that most of the things I wanted to know were basically a flag away using the
parent node.
Still I think it's worth it, now experimenting with BindToTree will only mean
adding a field to a struct that's included from a couple cpp files, instead of a
massive pain.
I also think this is clearer, and doing this highlights quite a few
inconsistencies in our code which I've left untouched, but commented with
FIXMEs.
Steps are:
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsresult BindToTree(Document\* aDocument, nsIContent\* aParent,#nsresult BindToTree(BindContext\&, nsINode\& aParent)#g' $file; done
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's# nsIContent\* aBindingParent) override#override#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(Document\* aDocument, nsIContent\* aParent,#::BindToTree(BindContext\& aContext, nsINode\& aParent)#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsIContent\* aBindingParent)##g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(aDocument, aParent, aBindingParent)#::BindToTree(aContext, aParent)#g' $file; done
$ ./mach clang-format
Then manual fixups.
Depends on D32948
Differential Revision: https://phabricator.services.mozilla.com/D32949
2019-05-29 07:27:04 +03:00
|
|
|
BindContext context(*aParentContent.AsElement(),
|
|
|
|
BindContext::ForNativeAnonymous);
|
|
|
|
nsresult rv = newContentRaw->BindToTree(context, aParentContent);
|
2016-10-19 12:09:33 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
2017-08-02 22:37:44 +03:00
|
|
|
newContentRaw->UnbindFromTree();
|
2016-11-24 10:12:04 +03:00
|
|
|
return nullptr;
|
2008-04-09 06:06:27 +04:00
|
|
|
}
|
2005-04-06 03:54:35 +04:00
|
|
|
}
|
2008-04-06 16:40:33 +04:00
|
|
|
|
2017-08-02 22:37:44 +03:00
|
|
|
ManualNACPtr newContent(newContentRaw.forget());
|
2017-06-28 03:34:48 +03:00
|
|
|
|
2017-07-25 09:08:19 +03:00
|
|
|
// Must style the new element, otherwise the PostRecreateFramesFor call
|
|
|
|
// below will do nothing.
|
2019-03-15 08:01:10 +03:00
|
|
|
ServoStyleSet* styleSet = presShell->StyleSet();
|
2018-03-29 14:15:46 +03:00
|
|
|
// Sometimes editor likes to append anonymous content to elements
|
|
|
|
// in display:none subtrees, so avoid styling in those cases.
|
|
|
|
if (ServoStyleSet::MayTraverseFrom(newContent)) {
|
|
|
|
styleSet->StyleNewSubtree(newContent);
|
2017-07-25 09:08:19 +03:00
|
|
|
}
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
ElementDeletionObserver* observer =
|
Bug 1555216 - Change the signature of BindToTree to be (BindContext&, nsINode& aParentNode). r=bzbarsky
BindContext was going to have way more information at first, but then I realized
that most of the things I wanted to know were basically a flag away using the
parent node.
Still I think it's worth it, now experimenting with BindToTree will only mean
adding a field to a struct that's included from a couple cpp files, instead of a
massive pain.
I also think this is clearer, and doing this highlights quite a few
inconsistencies in our code which I've left untouched, but commented with
FIXMEs.
Steps are:
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsresult BindToTree(Document\* aDocument, nsIContent\* aParent,#nsresult BindToTree(BindContext\&, nsINode\& aParent)#g' $file; done
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's# nsIContent\* aBindingParent) override#override#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(Document\* aDocument, nsIContent\* aParent,#::BindToTree(BindContext\& aContext, nsINode\& aParent)#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsIContent\* aBindingParent)##g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(aDocument, aParent, aBindingParent)#::BindToTree(aContext, aParent)#g' $file; done
$ ./mach clang-format
Then manual fixups.
Depends on D32948
Differential Revision: https://phabricator.services.mozilla.com/D32949
2019-05-29 07:27:04 +03:00
|
|
|
new ElementDeletionObserver(newContent, aParentContent.AsElement());
|
2008-04-06 16:40:33 +04:00
|
|
|
NS_ADDREF(observer); // NodeWillBeDestroyed releases.
|
2017-08-07 08:09:51 +03:00
|
|
|
aParentContent.AddMutationObserver(observer);
|
2008-04-06 16:40:33 +04:00
|
|
|
newContent->AddMutationObserver(observer);
|
|
|
|
|
2015-07-23 18:51:09 +03:00
|
|
|
#ifdef DEBUG
|
2017-04-17 19:01:37 +03:00
|
|
|
// Editor anonymous content gets passed to PostRecreateFramesFor... which
|
|
|
|
// can't _really_ deal with anonymous content (because it can't get the frame
|
|
|
|
// tree ordering right). But for us the ordering doesn't matter so this is
|
|
|
|
// sort of ok.
|
2015-07-23 18:51:09 +03:00
|
|
|
newContent->SetProperty(nsGkAtoms::restylableAnonymousNode,
|
|
|
|
reinterpret_cast<void*>(true));
|
|
|
|
#endif // DEBUG
|
|
|
|
|
2003-06-25 12:50:48 +04:00
|
|
|
// display the element
|
2019-03-15 08:01:10 +03:00
|
|
|
presShell->PostRecreateFramesFor(newContent);
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-06-01 18:59:07 +03:00
|
|
|
return newContent;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2006-06-15 11:31:01 +04:00
|
|
|
// Removes event listener and calls DeleteRefToAnonymousNode.
|
2016-07-09 05:42:33 +03:00
|
|
|
void HTMLEditor::RemoveListenerAndDeleteRef(const nsAString& aEvent,
|
|
|
|
nsIDOMEventListener* aListener,
|
|
|
|
bool aUseCapture,
|
2017-08-02 22:37:44 +03:00
|
|
|
ManualNACPtr aElement,
|
2019-03-15 08:01:10 +03:00
|
|
|
PresShell* aPresShell) {
|
2018-04-05 20:42:40 +03:00
|
|
|
if (aElement) {
|
|
|
|
aElement->RemoveEventListener(aEvent, aListener, aUseCapture);
|
2006-06-15 11:31:01 +04:00
|
|
|
}
|
2019-03-15 08:01:10 +03:00
|
|
|
DeleteRefToAnonymousNode(std::move(aElement), aPresShell);
|
2006-06-15 11:31:01 +04:00
|
|
|
}
|
|
|
|
|
2003-06-25 12:50:48 +04:00
|
|
|
// Deletes all references to an anonymous element
|
2017-08-02 22:37:44 +03:00
|
|
|
void HTMLEditor::DeleteRefToAnonymousNode(ManualNACPtr aContent,
|
2019-03-15 08:01:10 +03:00
|
|
|
PresShell* aPresShell) {
|
2003-06-25 12:50:48 +04:00
|
|
|
// call ContentRemoved() for the anonymous content
|
|
|
|
// node so its references get removed from the frame manager's
|
|
|
|
// undisplay map, and its layout frames get destroyed!
|
|
|
|
|
2016-11-24 09:58:01 +03:00
|
|
|
if (NS_WARN_IF(!aContent)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-07-04 12:01:32 +03:00
|
|
|
nsIContent* parentContent = aContent->GetParent();
|
|
|
|
if (NS_WARN_IF(!parentContent)) {
|
|
|
|
// aContent was already removed?
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-11-24 09:58:01 +03:00
|
|
|
nsAutoScriptBlocker scriptBlocker;
|
2019-03-15 08:01:10 +03:00
|
|
|
// Need to check whether aPresShell has been destroyed (but not yet deleted).
|
2016-11-24 09:58:01 +03:00
|
|
|
// See bug 338129.
|
2019-03-15 08:01:10 +03:00
|
|
|
if (aContent->IsInComposedDoc() && aPresShell &&
|
|
|
|
!aPresShell->IsDestroying()) {
|
2018-02-17 03:46:35 +03:00
|
|
|
MOZ_ASSERT(aContent->IsRootOfAnonymousSubtree());
|
|
|
|
MOZ_ASSERT(!aContent->GetPreviousSibling(), "NAC has no siblings");
|
|
|
|
|
|
|
|
// FIXME(emilio): This is the only caller to PresShell::ContentRemoved that
|
|
|
|
// passes NAC into it. This is not great!
|
2019-03-15 08:01:10 +03:00
|
|
|
aPresShell->ContentRemoved(aContent, nullptr);
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
2017-06-28 03:34:48 +03:00
|
|
|
|
2017-08-02 22:37:44 +03:00
|
|
|
// The ManualNACPtr destructor will invoke UnbindFromTree.
|
2013-03-19 04:26:08 +04:00
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-08-17 13:03:02 +03:00
|
|
|
void HTMLEditor::HideAnonymousEditingUIs() {
|
|
|
|
if (mAbsolutelyPositionedObject) {
|
2018-09-11 08:30:33 +03:00
|
|
|
HideGrabberInternal();
|
2018-08-17 13:03:02 +03:00
|
|
|
NS_ASSERTION(!mAbsolutelyPositionedObject, "HideGrabber failed");
|
|
|
|
}
|
|
|
|
if (mInlineEditedCell) {
|
2018-09-11 15:10:54 +03:00
|
|
|
HideInlineTableEditingUIInternal();
|
|
|
|
NS_ASSERTION(!mInlineEditedCell, "HideInlineTableEditingUIInternal failed");
|
2018-08-17 13:03:02 +03:00
|
|
|
}
|
|
|
|
if (mResizedObject) {
|
2018-09-06 08:02:46 +03:00
|
|
|
DebugOnly<nsresult> rv = HideResizersInternal();
|
|
|
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "HideResizersInternal() failed");
|
|
|
|
NS_ASSERTION(!mResizedObject, "HideResizersInternal() failed");
|
2018-08-17 13:03:02 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void HTMLEditor::HideAnonymousEditingUIsIfUnnecessary() {
|
|
|
|
// XXX Perhaps, this is wrong approach to hide multiple UIs because
|
|
|
|
// hiding one UI may causes overwriting existing UI with newly
|
|
|
|
// created one. In such case, we will leak ovewritten UI.
|
|
|
|
if (!IsAbsolutePositionEditorEnabled() && mAbsolutelyPositionedObject) {
|
|
|
|
// XXX If we're moving something, we need to cancel or commit the
|
|
|
|
// operation now.
|
2018-09-11 08:30:33 +03:00
|
|
|
HideGrabberInternal();
|
2018-08-17 13:03:02 +03:00
|
|
|
NS_ASSERTION(!mAbsolutelyPositionedObject, "HideGrabber failed");
|
|
|
|
}
|
|
|
|
if (!IsInlineTableEditorEnabled() && mInlineEditedCell) {
|
|
|
|
// XXX If we're resizing a table element, we need to cancel or commit the
|
|
|
|
// operation now.
|
2018-09-11 15:10:54 +03:00
|
|
|
HideInlineTableEditingUIInternal();
|
|
|
|
NS_ASSERTION(!mInlineEditedCell, "HideInlineTableEditingUIInternal failed");
|
2018-08-17 13:03:02 +03:00
|
|
|
}
|
|
|
|
if (!IsObjectResizerEnabled() && mResizedObject) {
|
|
|
|
// XXX If we're resizing something, we need to cancel or commit the
|
|
|
|
// operation now.
|
2018-09-06 08:02:46 +03:00
|
|
|
DebugOnly<nsresult> rv = HideResizersInternal();
|
|
|
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "HideResizersInternal() failed");
|
|
|
|
NS_ASSERTION(!mResizedObject, "HideResizersInternal() failed");
|
2018-08-17 13:03:02 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-06-25 12:50:48 +04:00
|
|
|
NS_IMETHODIMP
|
2018-10-30 13:01:38 +03:00
|
|
|
HTMLEditor::CheckSelectionStateForAnonymousButtons() {
|
2018-10-30 13:00:17 +03:00
|
|
|
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
|
|
|
|
if (NS_WARN_IF(!editActionData.CanHandle())) {
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
}
|
|
|
|
|
2019-05-09 10:37:51 +03:00
|
|
|
nsresult rv = RefreshEditingUI();
|
2018-08-17 11:56:28 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
2019-02-25 12:07:54 +03:00
|
|
|
return EditorBase::ToGenericNSResult(rv);
|
2018-08-17 11:56:28 +03:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2019-05-09 10:37:51 +03:00
|
|
|
nsresult HTMLEditor::RefreshEditingUI() {
|
2018-10-30 13:01:38 +03:00
|
|
|
MOZ_ASSERT(IsEditActionDataAvailable());
|
|
|
|
|
2018-08-17 13:03:02 +03:00
|
|
|
// First, we need to remove unnecessary editing UI now since some of them
|
|
|
|
// may be disabled while them are visible.
|
|
|
|
HideAnonymousEditingUIsIfUnnecessary();
|
|
|
|
|
2003-06-25 12:50:48 +04:00
|
|
|
// early way out if all contextual UI extensions are disabled
|
2018-08-17 11:56:28 +03:00
|
|
|
if (!IsObjectResizerEnabled() && !IsAbsolutePositionEditorEnabled() &&
|
|
|
|
!IsInlineTableEditorEnabled()) {
|
Bug 1449564 - part 1: Disable object resizer and inline table editor in default r=m_kato
Gecko supports resizers of <img> elements and <table>, <td>, <th> elements and
has UI to remove existing table row or column in default. However, the other
browsers don't have such UI and web apps need to disable this feature with
calling both:
document.execCommand("enableObjectResizing", false, false);
document.execCommand("enableInlineTableEditing", false, false);
for avoiding conflicting with their own features to edit such elements.
Therefore, it doesn't make sense to keep enabling them in default only on
Gecko. If web apps want to keep using these features, they should call:
document.execCommand("enableObjectResizing", false, true);
document.execCommand("enableInlineTableEditing", false, true);
at initializing the editor.
And also this patch fixes bugs of
document.queryCommandState("enableObjectResizing") and
document.queryCommandState("enableInlineTableEditing"). They always return
false even after calling document.execCommand(..., false, true) since
nsSetDocumentStateCommand::GetCommandStateParams() sets bool value as
STATE_ATTRIBUTE. However, nsHTMLDocument::QueryCommandValue() which is the
caller referring STATE_ATTRIBUTE doesn't treat it as bool value. And also
those commands are related to state of document. Therefore, they should be
return as bool value of STATE_ALL instead. Then,
nsHTMLDocument::QueryCommandState() returns the state as expected. Note that
those commands are supported only by Gecko. So, we don't need to worry about
the compatibility.
Finally, this patch rewrites 2 existing tests to check basic behavior of
resizers and appearance of resizers.
Note that this patch does not add new tests to test inline table editor
since it's difficult to test the behavior with current API. Perhaps, we
should add an API to nsIHTMLEditor to retrieve each anonymous elements in
another bug since it requires to add wrapping API of SpecialPowers.
MozReview-Commit-ID: 1FhYo5vcV60
--HG--
rename : editor/libeditor/tests/test_objectResizing.html => editor/libeditor/tests/test_resizers_appearance.html
rename : editor/libeditor/tests/test_bug640321.html => editor/libeditor/tests/test_resizers_resizing_elements.html
extra : rebase_source : a707de5a64ef1f8ce974cdf1be093d1b4f61c7bc
2018-04-02 11:26:46 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2007-06-14 12:22:47 +04:00
|
|
|
// Don't change selection state if we're moving.
|
|
|
|
if (mIsMoving) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2003-06-25 12:50:48 +04:00
|
|
|
// let's get the containing element of the selection
|
2018-10-30 13:01:38 +03:00
|
|
|
RefPtr<Element> focusElement = GetSelectionContainerElement();
|
2018-08-16 18:12:51 +03:00
|
|
|
if (NS_WARN_IF(!focusElement)) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2012-06-24 10:54:43 +04:00
|
|
|
// If we're not in a document, don't try to add resizers
|
2018-01-30 07:42:52 +03:00
|
|
|
if (!focusElement->IsInUncomposedDoc()) {
|
2012-06-24 10:54:43 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2003-06-25 12:50:48 +04:00
|
|
|
// what's its tag?
|
2018-01-30 07:42:52 +03:00
|
|
|
nsAtom* focusTagAtom = focusElement->NodeInfo()->NameAtom();
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-01-30 07:42:52 +03:00
|
|
|
RefPtr<Element> absPosElement;
|
2018-04-04 16:27:49 +03:00
|
|
|
if (IsAbsolutePositionEditorEnabled()) {
|
2003-06-25 12:50:48 +04:00
|
|
|
// Absolute Positioning support is enabled, is the selection contained
|
|
|
|
// in an absolutely positioned element ?
|
2018-01-30 07:42:52 +03:00
|
|
|
absPosElement = GetAbsolutelyPositionedSelectionContainer();
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2017-12-15 19:14:54 +03:00
|
|
|
RefPtr<Element> cellElement;
|
Bug 1449564 - part 1: Disable object resizer and inline table editor in default r=m_kato
Gecko supports resizers of <img> elements and <table>, <td>, <th> elements and
has UI to remove existing table row or column in default. However, the other
browsers don't have such UI and web apps need to disable this feature with
calling both:
document.execCommand("enableObjectResizing", false, false);
document.execCommand("enableInlineTableEditing", false, false);
for avoiding conflicting with their own features to edit such elements.
Therefore, it doesn't make sense to keep enabling them in default only on
Gecko. If web apps want to keep using these features, they should call:
document.execCommand("enableObjectResizing", false, true);
document.execCommand("enableInlineTableEditing", false, true);
at initializing the editor.
And also this patch fixes bugs of
document.queryCommandState("enableObjectResizing") and
document.queryCommandState("enableInlineTableEditing"). They always return
false even after calling document.execCommand(..., false, true) since
nsSetDocumentStateCommand::GetCommandStateParams() sets bool value as
STATE_ATTRIBUTE. However, nsHTMLDocument::QueryCommandValue() which is the
caller referring STATE_ATTRIBUTE doesn't treat it as bool value. And also
those commands are related to state of document. Therefore, they should be
return as bool value of STATE_ALL instead. Then,
nsHTMLDocument::QueryCommandState() returns the state as expected. Note that
those commands are supported only by Gecko. So, we don't need to worry about
the compatibility.
Finally, this patch rewrites 2 existing tests to check basic behavior of
resizers and appearance of resizers.
Note that this patch does not add new tests to test inline table editor
since it's difficult to test the behavior with current API. Perhaps, we
should add an API to nsIHTMLEditor to retrieve each anonymous elements in
another bug since it requires to add wrapping API of SpecialPowers.
MozReview-Commit-ID: 1FhYo5vcV60
--HG--
rename : editor/libeditor/tests/test_objectResizing.html => editor/libeditor/tests/test_resizers_appearance.html
rename : editor/libeditor/tests/test_bug640321.html => editor/libeditor/tests/test_resizers_resizing_elements.html
extra : rebase_source : a707de5a64ef1f8ce974cdf1be093d1b4f61c7bc
2018-04-02 11:26:46 +03:00
|
|
|
if (IsObjectResizerEnabled() || IsInlineTableEditorEnabled()) {
|
2003-06-25 12:50:48 +04:00
|
|
|
// Resizing or Inline Table Editing is enabled, we need to check if the
|
|
|
|
// selection is contained in a table cell
|
2018-10-30 13:01:38 +03:00
|
|
|
cellElement = GetElementOrParentByTagNameAtSelection(*nsGkAtoms::td);
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
Bug 1449564 - part 1: Disable object resizer and inline table editor in default r=m_kato
Gecko supports resizers of <img> elements and <table>, <td>, <th> elements and
has UI to remove existing table row or column in default. However, the other
browsers don't have such UI and web apps need to disable this feature with
calling both:
document.execCommand("enableObjectResizing", false, false);
document.execCommand("enableInlineTableEditing", false, false);
for avoiding conflicting with their own features to edit such elements.
Therefore, it doesn't make sense to keep enabling them in default only on
Gecko. If web apps want to keep using these features, they should call:
document.execCommand("enableObjectResizing", false, true);
document.execCommand("enableInlineTableEditing", false, true);
at initializing the editor.
And also this patch fixes bugs of
document.queryCommandState("enableObjectResizing") and
document.queryCommandState("enableInlineTableEditing"). They always return
false even after calling document.execCommand(..., false, true) since
nsSetDocumentStateCommand::GetCommandStateParams() sets bool value as
STATE_ATTRIBUTE. However, nsHTMLDocument::QueryCommandValue() which is the
caller referring STATE_ATTRIBUTE doesn't treat it as bool value. And also
those commands are related to state of document. Therefore, they should be
return as bool value of STATE_ALL instead. Then,
nsHTMLDocument::QueryCommandState() returns the state as expected. Note that
those commands are supported only by Gecko. So, we don't need to worry about
the compatibility.
Finally, this patch rewrites 2 existing tests to check basic behavior of
resizers and appearance of resizers.
Note that this patch does not add new tests to test inline table editor
since it's difficult to test the behavior with current API. Perhaps, we
should add an API to nsIHTMLEditor to retrieve each anonymous elements in
another bug since it requires to add wrapping API of SpecialPowers.
MozReview-Commit-ID: 1FhYo5vcV60
--HG--
rename : editor/libeditor/tests/test_objectResizing.html => editor/libeditor/tests/test_resizers_appearance.html
rename : editor/libeditor/tests/test_bug640321.html => editor/libeditor/tests/test_resizers_resizing_elements.html
extra : rebase_source : a707de5a64ef1f8ce974cdf1be093d1b4f61c7bc
2018-04-02 11:26:46 +03:00
|
|
|
if (IsObjectResizerEnabled() && cellElement) {
|
2003-06-25 12:50:48 +04:00
|
|
|
// we are here because Resizing is enabled AND selection is contained in
|
|
|
|
// a cell
|
2003-09-03 17:58:00 +04:00
|
|
|
|
2003-06-25 12:50:48 +04:00
|
|
|
// get the enclosing table
|
2014-08-29 15:43:24 +04:00
|
|
|
if (nsGkAtoms::img != focusTagAtom) {
|
2003-06-25 12:50:48 +04:00
|
|
|
// the element container of the selection is not an image, so we'll show
|
|
|
|
// the resizers around the table
|
2018-08-17 11:56:28 +03:00
|
|
|
// XXX There may be a bug. cellElement may be not in <table> in invalid
|
|
|
|
// tree. So, perhaps, GetEnclosingTable() returns nullptr, we should
|
|
|
|
// not set focusTagAtom to nsGkAtoms::table.
|
2018-01-30 07:42:52 +03:00
|
|
|
focusElement = GetEnclosingTable(cellElement);
|
2014-08-29 15:43:24 +04:00
|
|
|
focusTagAtom = nsGkAtoms::table;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// we allow resizers only around images, tables, and absolutely positioned
|
|
|
|
// elements. If we don't have image/table, let's look at the latter case.
|
2014-08-29 15:43:24 +04:00
|
|
|
if (nsGkAtoms::img != focusTagAtom && nsGkAtoms::table != focusTagAtom) {
|
2003-06-25 12:50:48 +04:00
|
|
|
focusElement = absPosElement;
|
2014-08-29 15:43:24 +04:00
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
|
|
|
// at this point, focusElement contains the element for Resizing,
|
|
|
|
// cellElement contains the element for InlineTableEditing
|
|
|
|
// absPosElement contains the element for Positioning
|
|
|
|
|
2008-04-14 00:22:31 +04:00
|
|
|
// Note: All the Hide/Show methods below may change attributes on real
|
|
|
|
// content which means a DOMAttrModified handler may cause arbitrary
|
|
|
|
// side effects while this code runs (bug 420439).
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-04-04 16:27:49 +03:00
|
|
|
if (IsAbsolutePositionEditorEnabled() && mAbsolutelyPositionedObject &&
|
2018-01-30 07:42:52 +03:00
|
|
|
absPosElement != mAbsolutelyPositionedObject) {
|
2018-09-11 08:30:33 +03:00
|
|
|
HideGrabberInternal();
|
2008-04-14 00:22:31 +04:00
|
|
|
NS_ASSERTION(!mAbsolutelyPositionedObject, "HideGrabber failed");
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
Bug 1449564 - part 1: Disable object resizer and inline table editor in default r=m_kato
Gecko supports resizers of <img> elements and <table>, <td>, <th> elements and
has UI to remove existing table row or column in default. However, the other
browsers don't have such UI and web apps need to disable this feature with
calling both:
document.execCommand("enableObjectResizing", false, false);
document.execCommand("enableInlineTableEditing", false, false);
for avoiding conflicting with their own features to edit such elements.
Therefore, it doesn't make sense to keep enabling them in default only on
Gecko. If web apps want to keep using these features, they should call:
document.execCommand("enableObjectResizing", false, true);
document.execCommand("enableInlineTableEditing", false, true);
at initializing the editor.
And also this patch fixes bugs of
document.queryCommandState("enableObjectResizing") and
document.queryCommandState("enableInlineTableEditing"). They always return
false even after calling document.execCommand(..., false, true) since
nsSetDocumentStateCommand::GetCommandStateParams() sets bool value as
STATE_ATTRIBUTE. However, nsHTMLDocument::QueryCommandValue() which is the
caller referring STATE_ATTRIBUTE doesn't treat it as bool value. And also
those commands are related to state of document. Therefore, they should be
return as bool value of STATE_ALL instead. Then,
nsHTMLDocument::QueryCommandState() returns the state as expected. Note that
those commands are supported only by Gecko. So, we don't need to worry about
the compatibility.
Finally, this patch rewrites 2 existing tests to check basic behavior of
resizers and appearance of resizers.
Note that this patch does not add new tests to test inline table editor
since it's difficult to test the behavior with current API. Perhaps, we
should add an API to nsIHTMLEditor to retrieve each anonymous elements in
another bug since it requires to add wrapping API of SpecialPowers.
MozReview-Commit-ID: 1FhYo5vcV60
--HG--
rename : editor/libeditor/tests/test_objectResizing.html => editor/libeditor/tests/test_resizers_appearance.html
rename : editor/libeditor/tests/test_bug640321.html => editor/libeditor/tests/test_resizers_resizing_elements.html
extra : rebase_source : a707de5a64ef1f8ce974cdf1be093d1b4f61c7bc
2018-04-02 11:26:46 +03:00
|
|
|
if (IsObjectResizerEnabled() && mResizedObject &&
|
2018-01-30 07:42:52 +03:00
|
|
|
mResizedObject != focusElement) {
|
2018-09-06 08:02:46 +03:00
|
|
|
// Perhaps, even if HideResizersInternal() failed, we should try to hide
|
|
|
|
// inline table editing UI. However, it returns error only when we cannot
|
|
|
|
// do anything. So, it's okay for now.
|
|
|
|
nsresult rv = HideResizersInternal();
|
2018-08-17 11:56:28 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2018-09-06 08:02:46 +03:00
|
|
|
NS_ASSERTION(!mResizedObject, "HideResizersInternal() failed");
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2018-08-17 13:03:02 +03:00
|
|
|
if (IsInlineTableEditorEnabled() && mInlineEditedCell &&
|
2003-06-25 12:50:48 +04:00
|
|
|
mInlineEditedCell != cellElement) {
|
2018-09-11 15:10:54 +03:00
|
|
|
HideInlineTableEditingUIInternal();
|
|
|
|
NS_ASSERTION(!mInlineEditedCell, "HideInlineTableEditingUIInternal failed");
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// now, let's display all contextual UI for good
|
2011-09-07 21:34:58 +04:00
|
|
|
nsIContent* hostContent = GetActiveEditingHost();
|
2003-06-25 12:50:48 +04:00
|
|
|
|
Bug 1449564 - part 1: Disable object resizer and inline table editor in default r=m_kato
Gecko supports resizers of <img> elements and <table>, <td>, <th> elements and
has UI to remove existing table row or column in default. However, the other
browsers don't have such UI and web apps need to disable this feature with
calling both:
document.execCommand("enableObjectResizing", false, false);
document.execCommand("enableInlineTableEditing", false, false);
for avoiding conflicting with their own features to edit such elements.
Therefore, it doesn't make sense to keep enabling them in default only on
Gecko. If web apps want to keep using these features, they should call:
document.execCommand("enableObjectResizing", false, true);
document.execCommand("enableInlineTableEditing", false, true);
at initializing the editor.
And also this patch fixes bugs of
document.queryCommandState("enableObjectResizing") and
document.queryCommandState("enableInlineTableEditing"). They always return
false even after calling document.execCommand(..., false, true) since
nsSetDocumentStateCommand::GetCommandStateParams() sets bool value as
STATE_ATTRIBUTE. However, nsHTMLDocument::QueryCommandValue() which is the
caller referring STATE_ATTRIBUTE doesn't treat it as bool value. And also
those commands are related to state of document. Therefore, they should be
return as bool value of STATE_ALL instead. Then,
nsHTMLDocument::QueryCommandState() returns the state as expected. Note that
those commands are supported only by Gecko. So, we don't need to worry about
the compatibility.
Finally, this patch rewrites 2 existing tests to check basic behavior of
resizers and appearance of resizers.
Note that this patch does not add new tests to test inline table editor
since it's difficult to test the behavior with current API. Perhaps, we
should add an API to nsIHTMLEditor to retrieve each anonymous elements in
another bug since it requires to add wrapping API of SpecialPowers.
MozReview-Commit-ID: 1FhYo5vcV60
--HG--
rename : editor/libeditor/tests/test_objectResizing.html => editor/libeditor/tests/test_resizers_appearance.html
rename : editor/libeditor/tests/test_bug640321.html => editor/libeditor/tests/test_resizers_resizing_elements.html
extra : rebase_source : a707de5a64ef1f8ce974cdf1be093d1b4f61c7bc
2018-04-02 11:26:46 +03:00
|
|
|
if (IsObjectResizerEnabled() && focusElement &&
|
2018-08-03 14:10:46 +03:00
|
|
|
IsModifiableNode(*focusElement) && focusElement != hostContent) {
|
2014-08-29 15:43:24 +04:00
|
|
|
if (nsGkAtoms::img == focusTagAtom) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mResizedObjectIsAnImage = true;
|
2014-08-29 15:43:24 +04:00
|
|
|
}
|
2016-10-19 12:09:33 +03:00
|
|
|
if (mResizedObject) {
|
2018-09-11 11:15:52 +03:00
|
|
|
nsresult rv = RefreshResizersInternal();
|
2016-10-19 12:09:33 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
} else {
|
Bug 1485923 - Remove nsIHTMLObjectResizer.showResizers(), rename HTMLEditor::ShowResizers() to HTMLEditor::ShowResizersInternal() and merge it with HTMLEditor::ShowResizersInner() r=m_kato
First, nobody uses nsIHTMLObjectResizer.showResizers(). So, we can remove it.
Then, we have two private methods, one is non-virtual
HTMLEditor::ShowResizers(), and the other is HTMLEditor::ShowResizersInner().
HTMLEditor::ShowResizers() calls HTMLEditor::ShowResizersInner() and if
it fails, calls HideResizers(). However, in some cases, e.g., when it already
has visible resizers, hiding resizers does not make sense.
So, this patch removes non-virtual HTMLEditor::ShowResizers() method too,
then, renames HTMLEditor::ShowResizersInner() to HTMLEditor::ShowResizers(),
finally, it hides resizers only when it fails to setup resizers for keeping
resizers hidden.
Differential Revision: https://phabricator.services.mozilla.com/D4921
--HG--
extra : moz-landing-system : lando
2018-09-06 07:38:00 +03:00
|
|
|
nsresult rv = ShowResizersInternal(*focusElement);
|
2016-10-19 12:09:33 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2018-04-04 16:27:49 +03:00
|
|
|
if (IsAbsolutePositionEditorEnabled() && absPosElement &&
|
2018-08-03 14:10:46 +03:00
|
|
|
IsModifiableNode(*absPosElement) && absPosElement != hostContent) {
|
2016-10-19 12:09:33 +03:00
|
|
|
if (mAbsolutelyPositionedObject) {
|
2018-09-11 08:30:33 +03:00
|
|
|
nsresult rv = RefreshGrabberInternal();
|
2016-10-19 12:09:33 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
} else {
|
2018-09-11 08:30:33 +03:00
|
|
|
nsresult rv = ShowGrabberInternal(*absPosElement);
|
2016-10-19 12:09:33 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2018-08-17 13:03:02 +03:00
|
|
|
if (IsInlineTableEditorEnabled() && cellElement &&
|
2018-08-03 14:10:46 +03:00
|
|
|
IsModifiableNode(*cellElement) && cellElement != hostContent) {
|
2016-10-19 12:09:33 +03:00
|
|
|
if (mInlineEditedCell) {
|
2018-09-11 15:10:54 +03:00
|
|
|
nsresult rv = RefreshInlineTableEditingUIInternal();
|
2016-10-19 12:09:33 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
} else {
|
2018-09-11 15:10:54 +03:00
|
|
|
nsresult rv = ShowInlineTableEditingUIInternal(*cellElement);
|
2016-10-19 12:09:33 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2016-10-19 12:09:33 +03:00
|
|
|
return NS_OK;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Resizing and Absolute Positioning need to know everything about the
|
|
|
|
// containing box of the element: position, size, margins, borders
|
2017-08-07 08:09:51 +03:00
|
|
|
nsresult HTMLEditor::GetPositionAndDimensions(Element& aElement, int32_t& aX,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t& aY, int32_t& aW,
|
|
|
|
int32_t& aH, int32_t& aBorderLeft,
|
|
|
|
int32_t& aBorderTop,
|
|
|
|
int32_t& aMarginLeft,
|
|
|
|
int32_t& aMarginTop) {
|
2003-06-25 12:50:48 +04:00
|
|
|
// Is the element positioned ? let's check the cheap way first...
|
2017-08-07 08:09:51 +03:00
|
|
|
bool isPositioned =
|
|
|
|
aElement.HasAttr(kNameSpaceID_None, nsGkAtoms::_moz_abspos);
|
2003-06-25 12:50:48 +04:00
|
|
|
if (!isPositioned) {
|
|
|
|
// hmmm... the expensive way now...
|
|
|
|
nsAutoString positionStr;
|
2018-02-02 12:42:25 +03:00
|
|
|
CSSEditUtils::GetComputedProperty(aElement, *nsGkAtoms::position,
|
2003-06-25 12:50:48 +04:00
|
|
|
positionStr);
|
2004-05-23 02:15:22 +04:00
|
|
|
isPositioned = positionStr.EqualsLiteral("absolute");
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (isPositioned) {
|
|
|
|
// Yes, it is absolutely positioned
|
2011-10-17 18:59:28 +04:00
|
|
|
mResizedObjectIsAbsolutelyPositioned = true;
|
2003-06-25 12:50:48 +04:00
|
|
|
|
|
|
|
// Get the all the computed css styles attached to the element node
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsComputedDOMStyle> cssDecl =
|
2018-02-02 12:42:25 +03:00
|
|
|
CSSEditUtils::GetComputedStyle(&aElement);
|
2012-07-08 13:50:31 +04:00
|
|
|
NS_ENSURE_STATE(cssDecl);
|
2003-06-25 12:50:48 +04:00
|
|
|
|
|
|
|
aBorderLeft =
|
|
|
|
GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("border-left-width"));
|
|
|
|
aBorderTop =
|
|
|
|
GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("border-top-width"));
|
|
|
|
aMarginLeft = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("margin-left"));
|
|
|
|
aMarginTop = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("margin-top"));
|
|
|
|
|
|
|
|
aX = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("left")) + aMarginLeft +
|
|
|
|
aBorderLeft;
|
|
|
|
aY = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("top")) + aMarginTop +
|
|
|
|
aBorderTop;
|
|
|
|
aW = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("width"));
|
|
|
|
aH = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("height"));
|
2016-10-24 05:27:45 +03:00
|
|
|
} else {
|
2011-10-17 18:59:28 +04:00
|
|
|
mResizedObjectIsAbsolutelyPositioned = false;
|
2018-01-30 07:40:11 +03:00
|
|
|
RefPtr<nsGenericHTMLElement> htmlElement =
|
2018-04-20 12:10:12 +03:00
|
|
|
nsGenericHTMLElement::FromNode(aElement);
|
2011-10-30 00:03:55 +04:00
|
|
|
if (!htmlElement) {
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
GetElementOrigin(aElement, aX, aY);
|
|
|
|
|
2018-01-30 07:40:11 +03:00
|
|
|
aW = htmlElement->OffsetWidth();
|
|
|
|
aH = htmlElement->OffsetHeight();
|
2003-06-25 12:50:48 +04:00
|
|
|
|
|
|
|
aBorderLeft = 0;
|
|
|
|
aBorderTop = 0;
|
|
|
|
aMarginLeft = 0;
|
|
|
|
aMarginTop = 0;
|
|
|
|
}
|
2016-10-19 12:09:33 +03:00
|
|
|
return NS_OK;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// self-explanatory
|
2016-07-09 05:42:33 +03:00
|
|
|
void HTMLEditor::SetAnonymousElementPosition(int32_t aX, int32_t aY,
|
2016-11-24 09:58:01 +03:00
|
|
|
Element* aElement) {
|
|
|
|
mCSSEditUtils->SetCSSPropertyPixels(*aElement, *nsGkAtoms::left, aX);
|
|
|
|
mCSSEditUtils->SetCSSPropertyPixels(*aElement, *nsGkAtoms::top, aY);
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
} // namespace mozilla
|