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"
|
|
|
|
|
2003-06-25 12:50:48 +04:00
|
|
|
#include <math.h>
|
|
|
|
|
2018-11-06 09:09:18 +03:00
|
|
|
#include "HTMLEditorEventListener.h"
|
2016-07-07 13:05:51 +03:00
|
|
|
#include "HTMLEditRules.h"
|
2016-07-07 08:01:12 +03:00
|
|
|
#include "HTMLEditUtils.h"
|
2016-07-07 07:44:32 +03:00
|
|
|
#include "TextEditUtils.h"
|
2018-01-12 13:01:04 +03:00
|
|
|
#include "mozilla/EditAction.h"
|
2012-07-13 10:33:42 +04:00
|
|
|
#include "mozilla/Preferences.h"
|
2019-03-15 08:01:10 +03:00
|
|
|
#include "mozilla/PresShell.h"
|
2017-12-21 08:52:32 +03:00
|
|
|
#include "mozilla/TextEditRules.h"
|
2014-04-10 20:09:40 +04:00
|
|
|
#include "mozilla/dom/Selection.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 "nsAlgorithm.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"
|
|
|
|
#include "nsGkAtoms.h"
|
2003-06-25 12:50:48 +04:00
|
|
|
#include "nsIContent.h"
|
2012-12-14 13:14:21 +04:00
|
|
|
#include "nsROCSSPrimitiveValue.h"
|
2012-07-13 10:33:42 +04:00
|
|
|
#include "nsIDOMEventListener.h"
|
|
|
|
#include "nsIDOMWindow.h"
|
|
|
|
#include "nsIHTMLObjectResizer.h"
|
|
|
|
#include "nsINode.h"
|
2019-06-10 13:27:07 +03:00
|
|
|
#include "nsIPrincipal.h"
|
2012-07-13 10:33:42 +04:00
|
|
|
#include "nsISupportsImpl.h"
|
|
|
|
#include "nsISupportsUtils.h"
|
|
|
|
#include "nsLiteralString.h"
|
|
|
|
#include "nsReadableUtils.h"
|
|
|
|
#include "nsString.h"
|
|
|
|
#include "nsStringFwd.h"
|
|
|
|
#include "nscore.h"
|
2013-01-15 16:22:03 +04:00
|
|
|
#include <algorithm>
|
2011-06-17 04:59:29 +04:00
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
namespace mozilla {
|
|
|
|
|
|
|
|
using namespace dom;
|
2011-06-17 04:59:29 +04:00
|
|
|
|
2019-06-10 13:27:07 +03:00
|
|
|
nsresult HTMLEditor::SetSelectionToAbsoluteOrStaticAsAction(
|
|
|
|
bool aEnabled, nsIPrincipal* aPrincipal) {
|
2018-10-30 13:02:58 +03:00
|
|
|
MOZ_ASSERT(IsEditActionDataAvailable());
|
|
|
|
|
2018-10-30 13:00:17 +03:00
|
|
|
AutoEditActionDataSetter editActionData(
|
2019-06-10 13:27:07 +03:00
|
|
|
*this, EditAction::eSetPositionToAbsoluteOrStatic, aPrincipal);
|
2018-10-30 13:00:17 +03:00
|
|
|
if (NS_WARN_IF(!editActionData.CanHandle())) {
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
}
|
|
|
|
|
2018-10-24 12:42:06 +03:00
|
|
|
AutoPlaceholderBatch treatAsOneTransaction(*this);
|
2019-08-20 04:52:50 +03:00
|
|
|
AutoEditSubActionNotifier startToHandleEditSubAction(
|
Bug 1463985 - part 1: Rename EditAction to EditSubAction and related stuff r=m_kato
When we implement InputEvent.inputType, we need to set a stack class to record
which edit action is currently handled. However, currently, we call smaller
jobs as edit action. For example, when user types a character at selecting
some characters, then, EditAction::deleteSelection is performed first, then,
EditAction::insertText is performed. However, for the InputEvent.inputType,
we need inserText information. So, for making new enum EditAction, we need
to rename current EditAction to EditSubAction.
And also this renames related stuff:
EditorBase::mIsInEditAction -> EditorBase::mIsInEditSubAction
EditorBase::IsInEditAction() -> EditorBase::IsInEditSubAction()
EditorBase::mAction -> EditorBase::mTopLevelEditSubAction
TextEditRules::mTheAction -> TextEditRules::mTopLevelEditSubAction
EditorBase::StartOperation() ->
EditorBase::OnStartToHandleTopLevelEditSubAction()
EditorBase::EndOperation() ->
EditorBase::OnEndHandlingTopLevelEditSubAction()
AutoRules -> AutoTopLevelEditSubActionNotifier
RulesInfo -> EditSubActionInfo
MozReview-Commit-ID: cvSkPUjFm1
--HG--
extra : rebase_source : baf527a3e353b7a8ebe9a46be2243b059c500234
2018-05-28 14:12:34 +03:00
|
|
|
*this,
|
2018-05-28 17:48:39 +03:00
|
|
|
aEnabled ? EditSubAction::eSetPositionToAbsolute
|
|
|
|
: EditSubAction::eSetPositionToStatic,
|
Bug 1463985 - part 1: Rename EditAction to EditSubAction and related stuff r=m_kato
When we implement InputEvent.inputType, we need to set a stack class to record
which edit action is currently handled. However, currently, we call smaller
jobs as edit action. For example, when user types a character at selecting
some characters, then, EditAction::deleteSelection is performed first, then,
EditAction::insertText is performed. However, for the InputEvent.inputType,
we need inserText information. So, for making new enum EditAction, we need
to rename current EditAction to EditSubAction.
And also this renames related stuff:
EditorBase::mIsInEditAction -> EditorBase::mIsInEditSubAction
EditorBase::IsInEditAction() -> EditorBase::IsInEditSubAction()
EditorBase::mAction -> EditorBase::mTopLevelEditSubAction
TextEditRules::mTheAction -> TextEditRules::mTopLevelEditSubAction
EditorBase::StartOperation() ->
EditorBase::OnStartToHandleTopLevelEditSubAction()
EditorBase::EndOperation() ->
EditorBase::OnEndHandlingTopLevelEditSubAction()
AutoRules -> AutoTopLevelEditSubActionNotifier
RulesInfo -> EditSubActionInfo
MozReview-Commit-ID: cvSkPUjFm1
--HG--
extra : rebase_source : baf527a3e353b7a8ebe9a46be2243b059c500234
2018-05-28 14:12:34 +03:00
|
|
|
nsIEditor::eNext);
|
2015-05-28 18:58:42 +03:00
|
|
|
|
2003-09-03 17:58:00 +04:00
|
|
|
// the line below does not match the code; should it be removed?
|
2003-06-25 12:50:48 +04:00
|
|
|
// Find out if the selection is collapsed:
|
|
|
|
|
Bug 1463985 - part 1: Rename EditAction to EditSubAction and related stuff r=m_kato
When we implement InputEvent.inputType, we need to set a stack class to record
which edit action is currently handled. However, currently, we call smaller
jobs as edit action. For example, when user types a character at selecting
some characters, then, EditAction::deleteSelection is performed first, then,
EditAction::insertText is performed. However, for the InputEvent.inputType,
we need inserText information. So, for making new enum EditAction, we need
to rename current EditAction to EditSubAction.
And also this renames related stuff:
EditorBase::mIsInEditAction -> EditorBase::mIsInEditSubAction
EditorBase::IsInEditAction() -> EditorBase::IsInEditSubAction()
EditorBase::mAction -> EditorBase::mTopLevelEditSubAction
TextEditRules::mTheAction -> TextEditRules::mTopLevelEditSubAction
EditorBase::StartOperation() ->
EditorBase::OnStartToHandleTopLevelEditSubAction()
EditorBase::EndOperation() ->
EditorBase::OnEndHandlingTopLevelEditSubAction()
AutoRules -> AutoTopLevelEditSubActionNotifier
RulesInfo -> EditSubActionInfo
MozReview-Commit-ID: cvSkPUjFm1
--HG--
extra : rebase_source : baf527a3e353b7a8ebe9a46be2243b059c500234
2018-05-28 14:12:34 +03:00
|
|
|
EditSubActionInfo subActionInfo(aEnabled
|
2018-05-28 17:48:39 +03:00
|
|
|
? EditSubAction::eSetPositionToAbsolute
|
|
|
|
: EditSubAction::eSetPositionToStatic);
|
2011-09-29 10:19:26 +04:00
|
|
|
bool cancel, handled;
|
2013-03-23 07:47:57 +04:00
|
|
|
// Protect the edit rules object from dying
|
2017-12-21 08:52:32 +03:00
|
|
|
RefPtr<TextEditRules> rules(mRules);
|
2018-10-30 13:02:58 +03:00
|
|
|
nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
|
2016-10-19 12:09:33 +03:00
|
|
|
if (NS_FAILED(rv) || cancel) {
|
2019-02-25 12:07:54 +03:00
|
|
|
return EditorBase::ToGenericNSResult(rv);
|
2016-10-19 12:09:33 +03:00
|
|
|
}
|
2015-05-28 18:58:42 +03:00
|
|
|
|
2018-10-30 13:02:58 +03:00
|
|
|
rv = rules->DidDoAction(subActionInfo, rv);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
2019-02-25 12:07:54 +03:00
|
|
|
return EditorBase::ToGenericNSResult(rv);
|
2018-10-30 13:02:58 +03:00
|
|
|
}
|
|
|
|
return NS_OK;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2018-01-30 07:42:52 +03:00
|
|
|
already_AddRefed<Element>
|
2019-08-13 10:34:11 +03:00
|
|
|
HTMLEditor::GetAbsolutelyPositionedSelectionContainer() const {
|
2018-10-30 13:00:17 +03:00
|
|
|
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
|
|
|
|
if (NS_WARN_IF(!editActionData.CanHandle())) {
|
2018-08-16 18:12:51 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-10-30 13:01:38 +03:00
|
|
|
RefPtr<Element> element = GetSelectionContainerElement();
|
2018-08-16 18:12:51 +03:00
|
|
|
if (NS_WARN_IF(!element)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString positionStr;
|
2018-01-30 07:42:52 +03:00
|
|
|
while (element && !element->IsHTMLElement(nsGkAtoms::html)) {
|
2018-02-02 12:42:25 +03:00
|
|
|
nsresult rv = CSSEditUtils::GetComputedProperty(
|
|
|
|
*element, *nsGkAtoms::position, positionStr);
|
2017-08-04 12:30:13 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
2018-01-30 07:42:52 +03:00
|
|
|
return nullptr;
|
2017-08-04 12:30:13 +03:00
|
|
|
}
|
2018-01-30 07:42:52 +03:00
|
|
|
if (positionStr.EqualsLiteral("absolute")) {
|
|
|
|
return element.forget();
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
2018-01-30 07:42:52 +03:00
|
|
|
element = element->GetParentElement();
|
2008-01-22 10:39:06 +03:00
|
|
|
}
|
2018-01-30 07:42:52 +03:00
|
|
|
return nullptr;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-07-09 05:42:33 +03:00
|
|
|
HTMLEditor::GetAbsolutePositioningEnabled(bool* aIsEnabled) {
|
2018-04-04 16:27:49 +03:00
|
|
|
*aIsEnabled = IsAbsolutePositionEditorEnabled();
|
2003-06-25 12:50:48 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-07-09 05:42:33 +03:00
|
|
|
HTMLEditor::SetAbsolutePositioningEnabled(bool aIsEnabled) {
|
2018-04-04 16:27:49 +03:00
|
|
|
EnableAbsolutePositionEditor(aIsEnabled);
|
2003-06-25 12:50:48 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2018-02-01 04:55:25 +03:00
|
|
|
nsresult HTMLEditor::RelativeChangeElementZIndex(Element& aElement,
|
|
|
|
int32_t aChange,
|
|
|
|
int32_t* aReturn) {
|
2003-06-25 12:50:48 +04:00
|
|
|
NS_ENSURE_ARG_POINTER(aReturn);
|
|
|
|
if (!aChange) // early way out, no change
|
|
|
|
return NS_OK;
|
|
|
|
|
2018-02-01 04:55:25 +03:00
|
|
|
int32_t zIndex = GetZIndex(aElement);
|
2013-01-15 16:22:03 +04:00
|
|
|
zIndex = std::max(zIndex + aChange, 0);
|
2018-02-01 04:55:25 +03:00
|
|
|
SetZIndex(aElement, zIndex);
|
2003-06-25 12:50:48 +04:00
|
|
|
*aReturn = zIndex;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2018-02-01 04:55:25 +03:00
|
|
|
void HTMLEditor::SetZIndex(Element& aElement, int32_t aZindex) {
|
2003-06-25 12:50:48 +04:00
|
|
|
nsAutoString zIndexStr;
|
|
|
|
zIndexStr.AppendInt(aZindex);
|
|
|
|
|
2018-02-01 04:55:25 +03:00
|
|
|
mCSSEditUtils->SetCSSProperty(aElement, *nsGkAtoms::z_index, zIndexStr);
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2019-06-10 13:27:07 +03:00
|
|
|
nsresult HTMLEditor::AddZIndexAsAction(int32_t aChange,
|
|
|
|
nsIPrincipal* aPrincipal) {
|
2018-10-30 13:02:58 +03:00
|
|
|
MOZ_ASSERT(IsEditActionDataAvailable());
|
|
|
|
|
2018-10-30 13:00:17 +03:00
|
|
|
AutoEditActionDataSetter editActionData(
|
2019-06-10 13:27:07 +03:00
|
|
|
*this, EditAction::eIncreaseOrDecreaseZIndex, aPrincipal);
|
2018-10-30 13:00:17 +03:00
|
|
|
if (NS_WARN_IF(!editActionData.CanHandle())) {
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
}
|
|
|
|
|
2018-10-24 12:42:06 +03:00
|
|
|
AutoPlaceholderBatch treatAsOneTransaction(*this);
|
2019-08-20 04:52:50 +03:00
|
|
|
AutoEditSubActionNotifier startToHandleEditSubAction(
|
Bug 1463985 - part 1: Rename EditAction to EditSubAction and related stuff r=m_kato
When we implement InputEvent.inputType, we need to set a stack class to record
which edit action is currently handled. However, currently, we call smaller
jobs as edit action. For example, when user types a character at selecting
some characters, then, EditAction::deleteSelection is performed first, then,
EditAction::insertText is performed. However, for the InputEvent.inputType,
we need inserText information. So, for making new enum EditAction, we need
to rename current EditAction to EditSubAction.
And also this renames related stuff:
EditorBase::mIsInEditAction -> EditorBase::mIsInEditSubAction
EditorBase::IsInEditAction() -> EditorBase::IsInEditSubAction()
EditorBase::mAction -> EditorBase::mTopLevelEditSubAction
TextEditRules::mTheAction -> TextEditRules::mTopLevelEditSubAction
EditorBase::StartOperation() ->
EditorBase::OnStartToHandleTopLevelEditSubAction()
EditorBase::EndOperation() ->
EditorBase::OnEndHandlingTopLevelEditSubAction()
AutoRules -> AutoTopLevelEditSubActionNotifier
RulesInfo -> EditSubActionInfo
MozReview-Commit-ID: cvSkPUjFm1
--HG--
extra : rebase_source : baf527a3e353b7a8ebe9a46be2243b059c500234
2018-05-28 14:12:34 +03:00
|
|
|
*this,
|
2018-05-28 17:52:16 +03:00
|
|
|
aChange < 0 ? EditSubAction::eDecreaseZIndex
|
|
|
|
: EditSubAction::eIncreaseZIndex,
|
Bug 1463985 - part 1: Rename EditAction to EditSubAction and related stuff r=m_kato
When we implement InputEvent.inputType, we need to set a stack class to record
which edit action is currently handled. However, currently, we call smaller
jobs as edit action. For example, when user types a character at selecting
some characters, then, EditAction::deleteSelection is performed first, then,
EditAction::insertText is performed. However, for the InputEvent.inputType,
we need inserText information. So, for making new enum EditAction, we need
to rename current EditAction to EditSubAction.
And also this renames related stuff:
EditorBase::mIsInEditAction -> EditorBase::mIsInEditSubAction
EditorBase::IsInEditAction() -> EditorBase::IsInEditSubAction()
EditorBase::mAction -> EditorBase::mTopLevelEditSubAction
TextEditRules::mTheAction -> TextEditRules::mTopLevelEditSubAction
EditorBase::StartOperation() ->
EditorBase::OnStartToHandleTopLevelEditSubAction()
EditorBase::EndOperation() ->
EditorBase::OnEndHandlingTopLevelEditSubAction()
AutoRules -> AutoTopLevelEditSubActionNotifier
RulesInfo -> EditSubActionInfo
MozReview-Commit-ID: cvSkPUjFm1
--HG--
extra : rebase_source : baf527a3e353b7a8ebe9a46be2243b059c500234
2018-05-28 14:12:34 +03:00
|
|
|
nsIEditor::eNext);
|
2015-05-28 18:58:42 +03:00
|
|
|
|
2003-09-03 17:58:00 +04:00
|
|
|
// brade: can we get rid of this comment?
|
2003-06-25 12:50:48 +04:00
|
|
|
// Find out if the selection is collapsed:
|
2018-05-28 17:52:16 +03:00
|
|
|
EditSubActionInfo subActionInfo(aChange < 0 ? EditSubAction::eDecreaseZIndex
|
|
|
|
: EditSubAction::eIncreaseZIndex);
|
2011-09-29 10:19:26 +04:00
|
|
|
bool cancel, handled;
|
2013-03-23 07:47:57 +04:00
|
|
|
// Protect the edit rules object from dying
|
2017-12-21 08:52:32 +03:00
|
|
|
RefPtr<TextEditRules> rules(mRules);
|
2018-10-30 13:02:58 +03:00
|
|
|
nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
|
2016-10-19 12:09:33 +03:00
|
|
|
if (cancel || NS_FAILED(rv)) {
|
2019-02-25 12:07:54 +03:00
|
|
|
return EditorBase::ToGenericNSResult(rv);
|
2016-10-19 12:09:33 +03:00
|
|
|
}
|
2015-05-28 18:58:42 +03:00
|
|
|
|
2018-10-30 13:02:58 +03:00
|
|
|
rv = rules->DidDoAction(subActionInfo, rv);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
2019-02-25 12:07:54 +03:00
|
|
|
return EditorBase::ToGenericNSResult(rv);
|
2018-10-30 13:02:58 +03:00
|
|
|
}
|
|
|
|
return NS_OK;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2018-02-01 04:55:25 +03:00
|
|
|
int32_t HTMLEditor::GetZIndex(Element& aElement) {
|
2018-10-30 13:00:17 +03:00
|
|
|
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
|
|
|
|
if (NS_WARN_IF(!editActionData.CanHandle())) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-06-25 12:50:48 +04:00
|
|
|
nsAutoString zIndexStr;
|
2003-09-03 17:58:00 +04:00
|
|
|
|
2018-02-02 12:42:25 +03:00
|
|
|
nsresult rv = CSSEditUtils::GetSpecifiedProperty(
|
|
|
|
aElement, *nsGkAtoms::z_index, zIndexStr);
|
2018-02-01 04:55:25 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return 0;
|
|
|
|
}
|
2004-05-23 02:15:22 +04:00
|
|
|
if (zIndexStr.EqualsLiteral("auto")) {
|
2003-06-25 12:50:48 +04:00
|
|
|
// we have to look at the positioned ancestors
|
|
|
|
// cf. CSS 2 spec section 9.9.1
|
2018-02-01 04:55:25 +03:00
|
|
|
nsCOMPtr<nsINode> node = aElement.GetParentNode();
|
2003-06-25 12:50:48 +04:00
|
|
|
nsAutoString positionStr;
|
2015-04-19 15:28:50 +03:00
|
|
|
while (node && zIndexStr.EqualsLiteral("auto") &&
|
|
|
|
!node->IsHTMLElement(nsGkAtoms::body)) {
|
2018-02-02 12:42:25 +03:00
|
|
|
rv = CSSEditUtils::GetComputedProperty(*node, *nsGkAtoms::position,
|
|
|
|
positionStr);
|
2018-02-01 04:55:25 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return 0;
|
|
|
|
}
|
2004-05-23 02:15:22 +04:00
|
|
|
if (positionStr.EqualsLiteral("absolute")) {
|
2003-06-25 12:50:48 +04:00
|
|
|
// ah, we found one, what's its z-index ? If its z-index is auto,
|
|
|
|
// we have to continue climbing the document's tree
|
2018-02-02 12:42:25 +03:00
|
|
|
rv = CSSEditUtils::GetComputedProperty(*node, *nsGkAtoms::z_index,
|
|
|
|
zIndexStr);
|
2018-02-01 04:55:25 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return 0;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
2015-04-19 15:28:50 +03:00
|
|
|
node = node->GetParentNode();
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-01 04:55:25 +03:00
|
|
|
if (zIndexStr.EqualsLiteral("auto")) {
|
|
|
|
return 0;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2018-02-01 04:55:25 +03:00
|
|
|
nsresult errorCode;
|
|
|
|
return zIndexStr.ToInteger(&errorCode);
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2018-09-11 08:30:33 +03:00
|
|
|
bool HTMLEditor::CreateGrabberInternal(nsIContent& aParentContent) {
|
|
|
|
if (NS_WARN_IF(mGrabber)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
mGrabber = CreateAnonymousElement(nsGkAtoms::span, aParentContent,
|
|
|
|
NS_LITERAL_STRING("mozGrabber"), false);
|
|
|
|
|
|
|
|
// mGrabber may be destroyed during creation due to there may be
|
|
|
|
// mutation event listener.
|
|
|
|
if (NS_WARN_IF(!mGrabber)) {
|
|
|
|
return false;
|
2016-11-24 12:07:47 +03:00
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-04-04 18:32:32 +03:00
|
|
|
EventListenerManager* eventListenerManager =
|
2018-09-11 08:30:33 +03:00
|
|
|
mGrabber->GetOrCreateListenerManager();
|
2018-04-04 18:32:32 +03:00
|
|
|
eventListenerManager->AddEventListenerByType(
|
|
|
|
mEventListener, NS_LITERAL_STRING("mousedown"),
|
|
|
|
TrustedEventsAtSystemGroupBubble());
|
2018-09-11 08:30:33 +03:00
|
|
|
MOZ_ASSERT(mGrabber);
|
|
|
|
return true;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-07-09 05:42:33 +03:00
|
|
|
HTMLEditor::RefreshGrabber() {
|
2018-09-11 08:30:33 +03:00
|
|
|
if (NS_WARN_IF(!mAbsolutelyPositionedObject)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-10-30 13:00:17 +03:00
|
|
|
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
|
|
|
|
if (NS_WARN_IF(!editActionData.CanHandle())) {
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
}
|
|
|
|
|
2018-09-11 08:30:33 +03:00
|
|
|
nsresult rv = RefreshGrabberInternal();
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
2019-02-25 12:07:54 +03:00
|
|
|
return EditorBase::ToGenericNSResult(rv);
|
2018-09-11 08:30:33 +03:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-09-11 08:30:33 +03:00
|
|
|
nsresult HTMLEditor::RefreshGrabberInternal() {
|
|
|
|
if (!mAbsolutelyPositionedObject) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
nsresult rv = GetPositionAndDimensions(
|
|
|
|
*mAbsolutelyPositionedObject, mPositionedObjectX, mPositionedObjectY,
|
|
|
|
mPositionedObjectWidth, mPositionedObjectHeight,
|
|
|
|
mPositionedObjectBorderLeft, mPositionedObjectBorderTop,
|
|
|
|
mPositionedObjectMarginLeft, mPositionedObjectMarginTop);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2019-05-09 10:37:51 +03:00
|
|
|
RefPtr<Element> grabber = mGrabber.get();
|
2018-09-11 08:30:33 +03:00
|
|
|
SetAnonymousElementPosition(mPositionedObjectX + 12, mPositionedObjectY - 14,
|
2019-05-09 10:37:51 +03:00
|
|
|
grabber);
|
2003-06-25 12:50:48 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2018-09-11 08:30:33 +03:00
|
|
|
void HTMLEditor::HideGrabberInternal() {
|
|
|
|
if (NS_WARN_IF(!mAbsolutelyPositionedObject)) {
|
2018-02-01 04:55:25 +03:00
|
|
|
return;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-09-11 08:30:33 +03:00
|
|
|
// Move all members to the local variables first since mutation event
|
|
|
|
// listener may try to show grabber while we're hiding them.
|
|
|
|
RefPtr<Element> absolutePositioningObject =
|
|
|
|
std::move(mAbsolutelyPositionedObject);
|
|
|
|
ManualNACPtr grabber = std::move(mGrabber);
|
|
|
|
ManualNACPtr positioningShadow = std::move(mPositioningShadow);
|
|
|
|
|
|
|
|
DebugOnly<nsresult> rv = absolutePositioningObject->UnsetAttr(
|
|
|
|
kNameSpaceID_None, nsGkAtoms::_moz_abspos, true);
|
|
|
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to unset the attribute");
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2010-05-06 05:20:43 +04:00
|
|
|
// We allow the pres shell to be null; when it is, we presume there
|
|
|
|
// are no document observers to notify, but we still want to
|
|
|
|
// UnbindFromTree.
|
2019-03-15 08:01:10 +03:00
|
|
|
RefPtr<PresShell> presShell = GetPresShell();
|
2018-09-11 08:30:33 +03:00
|
|
|
if (grabber) {
|
|
|
|
DeleteRefToAnonymousNode(std::move(grabber), presShell);
|
|
|
|
}
|
|
|
|
if (positioningShadow) {
|
|
|
|
DeleteRefToAnonymousNode(std::move(positioningShadow), presShell);
|
|
|
|
}
|
2018-01-30 07:42:52 +03:00
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-09-11 08:30:33 +03:00
|
|
|
nsresult HTMLEditor::ShowGrabberInternal(Element& aElement) {
|
2018-01-30 07:42:52 +03:00
|
|
|
if (NS_WARN_IF(!IsDescendantOfEditorRoot(&aElement))) {
|
2017-09-09 17:49:02 +03:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2018-09-11 08:30:33 +03:00
|
|
|
if (NS_WARN_IF(mGrabber)) {
|
2008-04-14 00:22:31 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2003-06-25 12:50:48 +04:00
|
|
|
nsAutoString classValue;
|
2018-01-30 07:42:52 +03:00
|
|
|
nsresult rv =
|
|
|
|
GetTemporaryStyleForFocusedPositionedElement(aElement, classValue);
|
2016-10-19 12:09:33 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-01-30 07:42:52 +03:00
|
|
|
rv = aElement.SetAttr(kNameSpaceID_None, nsGkAtoms::_moz_abspos, classValue,
|
2016-10-19 12:09:33 +03:00
|
|
|
true);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-01-30 07:42:52 +03:00
|
|
|
mAbsolutelyPositionedObject = &aElement;
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-01-30 07:42:52 +03:00
|
|
|
nsIContent* parentContent = aElement.GetParent();
|
2017-08-07 08:09:51 +03:00
|
|
|
if (NS_WARN_IF(!parentContent)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2018-09-11 08:30:33 +03:00
|
|
|
if (NS_WARN_IF(!CreateGrabberInternal(*parentContent))) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we succeeded to create the grabber, HideGrabberInternal() hasn't been
|
|
|
|
// called yet. So, mAbsolutelyPositionedObject should be non-nullptr.
|
|
|
|
MOZ_ASSERT(mAbsolutelyPositionedObject);
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-09-11 08:30:33 +03:00
|
|
|
// Finally, move the grabber to proper position.
|
|
|
|
rv = RefreshGrabberInternal();
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2018-03-19 08:14:45 +03:00
|
|
|
nsresult HTMLEditor::StartMoving() {
|
2017-08-07 08:09:51 +03:00
|
|
|
nsCOMPtr<nsIContent> parentContent = mGrabber->GetParent();
|
|
|
|
if (NS_WARN_IF(!parentContent) || NS_WARN_IF(!mAbsolutelyPositionedObject)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
|
|
|
// now, let's create the resizing shadow
|
2017-08-07 08:09:51 +03:00
|
|
|
mPositioningShadow =
|
|
|
|
CreateShadow(*parentContent, *mAbsolutelyPositionedObject);
|
2018-09-11 11:15:52 +03:00
|
|
|
if (NS_WARN_IF(!mPositioningShadow) ||
|
|
|
|
NS_WARN_IF(!mAbsolutelyPositionedObject)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2019-05-09 10:37:51 +03:00
|
|
|
RefPtr<Element> positioningShadow = mPositioningShadow.get();
|
|
|
|
RefPtr<Element> absolutelyPositionedObject = mAbsolutelyPositionedObject;
|
2018-09-11 11:15:52 +03:00
|
|
|
nsresult rv =
|
2019-05-09 10:37:51 +03:00
|
|
|
SetShadowPosition(*positioningShadow, *absolutelyPositionedObject,
|
2016-10-19 12:09:33 +03:00
|
|
|
mPositionedObjectX, mPositionedObjectY);
|
2019-05-09 10:37:51 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
|
|
|
// make the shadow appear
|
2015-04-19 15:28:50 +03:00
|
|
|
mPositioningShadow->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_class, true);
|
2003-06-25 12:50:48 +04:00
|
|
|
|
|
|
|
// position it
|
2019-05-09 10:37:51 +03:00
|
|
|
positioningShadow = mPositioningShadow.get();
|
|
|
|
mCSSEditUtils->SetCSSPropertyPixels(*positioningShadow, *nsGkAtoms::width,
|
2003-09-03 17:58:00 +04:00
|
|
|
mPositionedObjectWidth);
|
2019-05-09 10:37:51 +03:00
|
|
|
mCSSEditUtils->SetCSSPropertyPixels(*positioningShadow, *nsGkAtoms::height,
|
2003-09-03 17:58:00 +04:00
|
|
|
mPositionedObjectHeight);
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
mIsMoving = true;
|
2016-10-19 12:09:33 +03:00
|
|
|
return NS_OK; // XXX Looks like nobody refers this result
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
void HTMLEditor::SnapToGrid(int32_t& newX, int32_t& newY) {
|
2003-06-25 12:50:48 +04:00
|
|
|
if (mSnapToGridEnabled && mGridSize) {
|
2012-08-22 19:56:38 +04:00
|
|
|
newX = (int32_t)floor(((float)newX / (float)mGridSize) + 0.5f) * mGridSize;
|
|
|
|
newY = (int32_t)floor(((float)newY / (float)mGridSize) + 0.5f) * mGridSize;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
nsresult HTMLEditor::GrabberClicked() {
|
2018-11-06 09:09:18 +03:00
|
|
|
if (NS_WARN_IF(!mEventListener)) {
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
}
|
|
|
|
nsresult rv = static_cast<HTMLEditorEventListener*>(mEventListener.get())
|
|
|
|
->ListenToMouseMoveEventForGrabber(true);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return NS_OK;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
mGrabberClicked = true;
|
2016-10-19 12:09:33 +03:00
|
|
|
return rv;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
nsresult HTMLEditor::EndMoving() {
|
2003-06-25 12:50:48 +04:00
|
|
|
if (mPositioningShadow) {
|
2019-03-15 08:01:10 +03:00
|
|
|
RefPtr<PresShell> presShell = GetPresShell();
|
|
|
|
if (NS_WARN_IF(!presShell)) {
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2019-03-15 08:01:10 +03:00
|
|
|
DeleteRefToAnonymousNode(std::move(mPositioningShadow), presShell);
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
mPositioningShadow = nullptr;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2018-11-06 09:09:18 +03:00
|
|
|
if (mEventListener) {
|
|
|
|
DebugOnly<nsresult> rvIgnored =
|
|
|
|
static_cast<HTMLEditorEventListener*>(mEventListener.get())
|
|
|
|
->ListenToMouseMoveEventForGrabber(false);
|
|
|
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
|
|
|
"Failed to remove mousemove event listener");
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
mGrabberClicked = false;
|
|
|
|
mIsMoving = false;
|
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))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
2016-07-09 05:42:33 +03:00
|
|
|
nsresult HTMLEditor::SetFinalPosition(int32_t aX, int32_t aY) {
|
2016-10-19 12:09:33 +03:00
|
|
|
nsresult rv = EndMoving();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2003-06-25 12:50:48 +04:00
|
|
|
|
|
|
|
// we have now to set the new width and height of the resized object
|
|
|
|
// we don't set the x and y position because we don't control that in
|
|
|
|
// a normal HTML layout
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t newX = mPositionedObjectX + aX - mOriginalX -
|
|
|
|
(mPositionedObjectBorderLeft + mPositionedObjectMarginLeft);
|
|
|
|
int32_t newY = mPositionedObjectY + aY - mOriginalY -
|
|
|
|
(mPositionedObjectBorderTop + mPositionedObjectMarginTop);
|
2003-06-25 12:50:48 +04:00
|
|
|
|
|
|
|
SnapToGrid(newX, newY);
|
|
|
|
|
|
|
|
nsAutoString x, y;
|
|
|
|
x.AppendInt(newX);
|
|
|
|
y.AppendInt(newY);
|
|
|
|
|
|
|
|
// we want one transaction only from a user's point of view
|
2018-10-24 12:42:06 +03:00
|
|
|
AutoPlaceholderBatch treatAsOneTransaction(*this);
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-09-11 08:30:33 +03:00
|
|
|
if (NS_WARN_IF(!mAbsolutelyPositionedObject)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
OwningNonNull<Element> absolutelyPositionedObject =
|
|
|
|
*mAbsolutelyPositionedObject;
|
2016-07-07 12:35:13 +03:00
|
|
|
mCSSEditUtils->SetCSSPropertyPixels(*absolutelyPositionedObject,
|
2014-08-29 15:43:24 +04:00
|
|
|
*nsGkAtoms::top, newY);
|
2016-07-07 12:35:13 +03:00
|
|
|
mCSSEditUtils->SetCSSPropertyPixels(*absolutelyPositionedObject,
|
2014-08-29 15:43:24 +04:00
|
|
|
*nsGkAtoms::left, newX);
|
2003-06-25 12:50:48 +04:00
|
|
|
// keep track of that size
|
|
|
|
mPositionedObjectX = newX;
|
|
|
|
mPositionedObjectY = newY;
|
|
|
|
|
2018-09-11 11:15:52 +03:00
|
|
|
rv = RefreshResizers();
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
void HTMLEditor::AddPositioningOffset(int32_t& aX, int32_t& aY) {
|
2003-06-25 12:50:48 +04:00
|
|
|
// Get the positioning offset
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t positioningOffset =
|
2011-06-17 04:59:29 +04:00
|
|
|
Preferences::GetInt("editor.positioning.offset", 0);
|
2003-06-25 12:50:48 +04:00
|
|
|
|
|
|
|
aX += positioningOffset;
|
|
|
|
aY += positioningOffset;
|
|
|
|
}
|
|
|
|
|
2018-02-01 04:55:25 +03:00
|
|
|
nsresult HTMLEditor::SetPositionToAbsoluteOrStatic(Element& aElement,
|
|
|
|
bool aEnabled) {
|
2003-06-25 12:50:48 +04:00
|
|
|
nsAutoString positionStr;
|
2018-02-02 12:42:25 +03:00
|
|
|
CSSEditUtils::GetComputedProperty(aElement, *nsGkAtoms::position,
|
|
|
|
positionStr);
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isPositioned = (positionStr.EqualsLiteral("absolute"));
|
2003-06-25 12:50:48 +04:00
|
|
|
|
|
|
|
// nothing to do if the element is already in the state we want
|
2018-02-01 04:55:25 +03:00
|
|
|
if (isPositioned == aEnabled) {
|
2003-06-25 12:50:48 +04:00
|
|
|
return NS_OK;
|
2018-02-01 04:55:25 +03:00
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-02-01 04:55:25 +03:00
|
|
|
if (aEnabled) {
|
|
|
|
return SetPositionToAbsolute(aElement);
|
|
|
|
}
|
|
|
|
|
|
|
|
return SetPositionToStatic(aElement);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult HTMLEditor::SetPositionToAbsolute(Element& aElement) {
|
2018-10-30 13:04:08 +03:00
|
|
|
MOZ_ASSERT(IsEditActionDataAvailable());
|
|
|
|
|
2018-10-24 12:42:06 +03:00
|
|
|
AutoPlaceholderBatch treatAsOneTransaction(*this);
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-02-01 04:55:25 +03:00
|
|
|
int32_t x, y;
|
|
|
|
GetElementOrigin(aElement, x, y);
|
|
|
|
|
|
|
|
mCSSEditUtils->SetCSSProperty(aElement, *nsGkAtoms::position,
|
|
|
|
NS_LITERAL_STRING("absolute"));
|
|
|
|
|
|
|
|
AddPositioningOffset(x, y);
|
|
|
|
SnapToGrid(x, y);
|
|
|
|
SetTopAndLeft(aElement, x, y);
|
|
|
|
|
|
|
|
// we may need to create a br if the positioned element is alone in its
|
|
|
|
// container
|
|
|
|
nsINode* parentNode = aElement.GetParentNode();
|
|
|
|
if (parentNode->GetChildCount() == 1) {
|
2018-04-16 13:21:29 +03:00
|
|
|
RefPtr<Element> newBrElement =
|
Bug 1569902 - part 4: Make `TextEditor` inserts padding `<br>` element for empty last line after setting flags to `NS_PADDING_FOR_EMPTY_LAST_LINE` r=m_kato
Stopping using attribute for "moz-br", `IMEContentObserver` cannot know when
new `<br>` element is changed to padding element for empty last line.
Therefore, editor needs to insert padding `<br>` element after setting the
flag properly. Then, `IMEContentObserver` does not need to recompute the
length of `<br>` element (if it's for padding, it computes the length as 0).
Unfortunately, `TextEditor::InsertBrElementWithTransaction()` is used in too
many places and it already has optional argument. Therefore, it's difficult
to change it. However, we should share the preparation before creating `<br>`
element in it with new method. Therefore, this patch creates
`EditorBase::PrepareToInsertBRElement()` to share the preparation point (almost
just moved from the method). Then, new method is created as
`EditorBase::InsertPaddingBRElementForEmptyLastLineWithTransaction()` because
it's used both in `TextEditor` and `HTMLEditor`. Finally, `TextEditor` won't
insert `<br>` element with `InsertBrElementWithTransaction()`. Therefore, it's
moved to `HTMLEditor` with renaming to `InsertBRElementWithTransaction()`.
Differential Revision: https://phabricator.services.mozilla.com/D39860
--HG--
extra : moz-landing-system : lando
2019-08-02 08:46:41 +03:00
|
|
|
InsertBRElementWithTransaction(EditorDOMPoint(parentNode, 0));
|
2018-04-16 13:21:29 +03:00
|
|
|
if (NS_WARN_IF(!newBrElement)) {
|
2018-02-01 04:55:25 +03:00
|
|
|
return NS_ERROR_FAILURE;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
}
|
2018-02-01 04:55:25 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult HTMLEditor::SetPositionToStatic(Element& aElement) {
|
2018-10-24 12:42:06 +03:00
|
|
|
AutoPlaceholderBatch treatAsOneTransaction(*this);
|
2018-02-01 04:55:25 +03:00
|
|
|
|
|
|
|
mCSSEditUtils->RemoveCSSProperty(aElement, *nsGkAtoms::position,
|
|
|
|
EmptyString());
|
|
|
|
mCSSEditUtils->RemoveCSSProperty(aElement, *nsGkAtoms::top, EmptyString());
|
|
|
|
mCSSEditUtils->RemoveCSSProperty(aElement, *nsGkAtoms::left, EmptyString());
|
|
|
|
mCSSEditUtils->RemoveCSSProperty(aElement, *nsGkAtoms::z_index,
|
|
|
|
EmptyString());
|
|
|
|
|
|
|
|
if (!HTMLEditUtils::IsImage(&aElement)) {
|
|
|
|
mCSSEditUtils->RemoveCSSProperty(aElement, *nsGkAtoms::width,
|
2014-08-29 15:43:24 +04:00
|
|
|
EmptyString());
|
2018-02-01 04:55:25 +03:00
|
|
|
mCSSEditUtils->RemoveCSSProperty(aElement, *nsGkAtoms::height,
|
2014-08-29 15:43:24 +04:00
|
|
|
EmptyString());
|
2018-02-01 04:55:25 +03:00
|
|
|
}
|
2003-06-25 12:50:48 +04:00
|
|
|
|
2018-02-01 04:55:25 +03:00
|
|
|
if (aElement.IsHTMLElement(nsGkAtoms::div) &&
|
|
|
|
!HasStyleOrIdOrClass(&aElement)) {
|
|
|
|
RefPtr<HTMLEditRules> htmlRules = static_cast<HTMLEditRules*>(mRules.get());
|
|
|
|
NS_ENSURE_TRUE(htmlRules, NS_ERROR_FAILURE);
|
2018-04-26 16:41:34 +03:00
|
|
|
nsresult rv = htmlRules->MakeSureElemStartsAndEndsOnCR(aElement);
|
2018-02-01 04:55:25 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2018-04-12 16:23:04 +03:00
|
|
|
rv = RemoveContainerWithTransaction(aElement);
|
2018-02-01 04:55:25 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
2012-06-11 03:44:50 +04:00
|
|
|
return NS_OK;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-07-09 05:42:33 +03:00
|
|
|
HTMLEditor::SetSnapToGridEnabled(bool aEnabled) {
|
2003-06-25 12:50:48 +04:00
|
|
|
mSnapToGridEnabled = aEnabled;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-07-09 05:42:33 +03:00
|
|
|
HTMLEditor::GetSnapToGridEnabled(bool* aIsEnabled) {
|
2003-06-25 12:50:48 +04:00
|
|
|
*aIsEnabled = mSnapToGridEnabled;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-07-09 05:42:33 +03:00
|
|
|
HTMLEditor::SetGridSize(uint32_t aSize) {
|
2003-06-25 12:50:48 +04:00
|
|
|
mGridSize = aSize;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-07-09 05:42:33 +03:00
|
|
|
HTMLEditor::GetGridSize(uint32_t* aSize) {
|
2003-06-25 12:50:48 +04:00
|
|
|
*aSize = mGridSize;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// self-explanatory
|
2018-02-01 04:55:25 +03:00
|
|
|
void HTMLEditor::SetTopAndLeft(Element& aElement, int32_t aX, int32_t aY) {
|
2018-10-24 12:42:06 +03:00
|
|
|
AutoPlaceholderBatch treatAsOneTransaction(*this);
|
2016-07-07 12:35:13 +03:00
|
|
|
mCSSEditUtils->SetCSSPropertyPixels(aElement, *nsGkAtoms::left, aX);
|
|
|
|
mCSSEditUtils->SetCSSPropertyPixels(aElement, *nsGkAtoms::top, aY);
|
2015-05-13 18:58:25 +03:00
|
|
|
}
|
|
|
|
|
2018-01-30 07:42:52 +03:00
|
|
|
nsresult HTMLEditor::GetTemporaryStyleForFocusedPositionedElement(
|
|
|
|
Element& aElement, nsAString& aReturn) {
|
2003-06-25 12:50:48 +04:00
|
|
|
// we are going to outline the positioned element and bring it to the
|
|
|
|
// front to overlap any other element intersecting with it. But
|
|
|
|
// first, let's see what's the background and foreground colors of the
|
|
|
|
// positioned element.
|
|
|
|
// if background-image computed value is 'none,
|
|
|
|
// If the background color is 'auto' and R G B values of the foreground are
|
|
|
|
// each above #d0, use a black background
|
|
|
|
// If the background color is 'auto' and at least one of R G B values of
|
|
|
|
// the foreground is below #d0, use a white background
|
|
|
|
// Otherwise don't change background/foreground
|
|
|
|
aReturn.Truncate();
|
2015-05-28 18:58:42 +03:00
|
|
|
|
2003-06-25 12:50:48 +04:00
|
|
|
nsAutoString bgImageStr;
|
2018-02-02 12:42:25 +03:00
|
|
|
nsresult rv = CSSEditUtils::GetComputedProperty(
|
|
|
|
aElement, *nsGkAtoms::background_image, bgImageStr);
|
2016-10-19 12:09:33 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2018-01-30 07:42:52 +03:00
|
|
|
if (!bgImageStr.EqualsLiteral("none")) {
|
|
|
|
return NS_OK;
|
2003-06-25 12:50:48 +04:00
|
|
|
}
|
|
|
|
|
2018-01-30 07:42:52 +03:00
|
|
|
nsAutoString bgColorStr;
|
2018-02-02 12:42:25 +03:00
|
|
|
rv = CSSEditUtils::GetComputedProperty(aElement, *nsGkAtoms::backgroundColor,
|
|
|
|
bgColorStr);
|
2018-01-30 07:42:52 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2018-03-15 14:57:38 +03:00
|
|
|
if (!bgColorStr.EqualsLiteral("rgba(0, 0, 0, 0)")) {
|
2018-01-30 07:42:52 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2018-03-22 21:20:41 +03:00
|
|
|
RefPtr<ComputedStyle> style =
|
|
|
|
nsComputedDOMStyle::GetComputedStyle(&aElement, nullptr);
|
2018-03-15 14:57:38 +03:00
|
|
|
NS_ENSURE_STATE(style);
|
2018-01-30 07:42:52 +03:00
|
|
|
|
2018-03-15 14:57:38 +03:00
|
|
|
const uint8_t kBlackBgTrigger = 0xd0;
|
2018-01-30 07:42:52 +03:00
|
|
|
|
2019-05-31 17:48:22 +03:00
|
|
|
const auto& color = style->StyleText()->mColor;
|
2019-04-06 20:47:58 +03:00
|
|
|
if (color.red >= kBlackBgTrigger && color.green >= kBlackBgTrigger &&
|
|
|
|
color.blue >= kBlackBgTrigger) {
|
2018-01-30 07:42:52 +03:00
|
|
|
aReturn.AssignLiteral("black");
|
|
|
|
} else {
|
|
|
|
aReturn.AssignLiteral("white");
|
|
|
|
}
|
2018-03-15 14:57:38 +03:00
|
|
|
|
2003-06-25 12:50:48 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
} // namespace mozilla
|