ported from UXP: Issue #3011 - Part 1: Add As{Text|Html}Editor() and AsEditorBase() (2f201000)

This commit is contained in:
2026-03-25 07:36:20 +08:00
parent 1b04d4b0bf
commit 76bf4dc35d
11 changed files with 123 additions and 25 deletions
+1
View File
@@ -17,6 +17,7 @@
#include "mozilla/CORSMode.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/HTMLEditor.h"
#include "mozilla/InternalMutationEvent.h"
#include "mozilla/Likely.h"
#include "mozilla/MemoryReporting.h"
+1
View File
@@ -142,6 +142,7 @@ EditorBase::EditorBase()
, mDispatchInputEvent(true)
, mIsInEditAction(false)
, mHidingCaret(false)
, mIsHTMLEditorClass(false)
{
}
+20
View File
@@ -115,6 +115,7 @@ class DeleteNodeTransaction;
class DeleteTextTransaction;
class EditAggregateTransaction;
class ErrorResult;
class HTMLEditor;
class InsertNodeTransaction;
class InsertTextTransaction;
class JoinNodeTransaction;
@@ -122,6 +123,7 @@ class PlaceholderTransaction;
class RemoveStyleSheetTransaction;
class SplitNodeTransaction;
class TextComposition;
class TextEditor;
struct EditorDOMPoint;
namespace dom {
@@ -1118,14 +1120,32 @@ protected:
bool mIsInEditAction;
// Whether caret is hidden forcibly.
bool mHidingCaret;
// Whether we are an HTML editor class.
bool mIsHTMLEditorClass;
friend bool NSCanUnload(nsISupports* serviceMgr);
friend class AutoRules;
friend class AutoSelectionRestorer;
friend class AutoTransactionsConserveSelection;
friend class RangeUpdater;
friend class nsIEditor;
};
} // namespace mozilla
// nsIEditor helper functions.
// Here because of code context.
mozilla::EditorBase*
nsIEditor::AsEditorBase()
{
return static_cast<mozilla::EditorBase*>(this);
}
const mozilla::EditorBase*
nsIEditor::AsEditorBase() const
{
return static_cast<const mozilla::EditorBase*>(this);
}
#endif // #ifndef mozilla_EditorBase_h
+8 -1
View File
@@ -241,9 +241,16 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLEditRules, TextEditRules,
NS_IMETHODIMP
HTMLEditRules::Init(TextEditor* aTextEditor)
{
if (NS_WARN_IF(!aTextEditor)) {
return NS_ERROR_INVALID_ARG;
}
InitFields();
mHTMLEditor = static_cast<HTMLEditor*>(aTextEditor);
mHTMLEditor = aTextEditor->AsHTMLEditor();
if (NS_WARN_IF(!mHTMLEditor)) {
return NS_ERROR_INVALID_ARG;
}
// call through to base class Init
nsresult rv = TextEditRules::Init(aTextEditor);
+2 -1
View File
@@ -132,6 +132,7 @@ HTMLEditor::HTMLEditor()
, mPositionedObjectBorderTop(0)
, mGridSize(0)
{
mIsHTMLEditorClass = true;
}
HTMLEditor::~HTMLEditor()
@@ -501,7 +502,7 @@ HTMLEditor::InitRules()
// instantiate the rules for the html editor
mRules = new HTMLEditRules();
}
return mRules->Init(static_cast<TextEditor*>(this));
return mRules->Init(this);
}
NS_IMETHODIMP
+16
View File
@@ -1121,4 +1121,20 @@ private:
} // namespace mozilla
// nsIEditor helper functions.
// Here because of code context.
mozilla::HTMLEditor*
nsIEditor::AsHTMLEditor()
{
return static_cast<mozilla::EditorBase*>(this)->mIsHTMLEditorClass ?
static_cast<mozilla::HTMLEditor*>(this) : nullptr;
}
const mozilla::HTMLEditor*
nsIEditor::AsHTMLEditor() const
{
return static_cast<const mozilla::EditorBase*>(this)->mIsHTMLEditorClass ?
static_cast<const mozilla::HTMLEditor*>(this) : nullptr;
}
#endif // #ifndef mozilla_HTMLEditor_h
+21 -18
View File
@@ -30,24 +30,18 @@ namespace mozilla {
using namespace dom;
#ifdef DEBUG
nsresult
HTMLEditorEventListener::Connect(EditorBase* aEditorBase)
{
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryObject(aEditorBase);
nsCOMPtr<nsIHTMLInlineTableEditor> htmlInlineTableEditor =
do_QueryObject(aEditorBase);
NS_PRECONDITION(htmlEditor && htmlInlineTableEditor,
"Set HTMLEditor or its sub class");
return EditorEventListener::Connect(aEditorBase);
}
#endif
HTMLEditor*
HTMLEditorEventListener::GetHTMLEditor()
{
// mEditor must be HTMLEditor or its subclass.
return static_cast<HTMLEditor*>(mEditorBase);
if (NS_WARN_IF(!aEditorBase)) {
return NS_ERROR_INVALID_ARG;
}
// Guarantee that mEditorBase is always HTMLEditor.
HTMLEditor* htmlEditor = aEditorBase->AsHTMLEditor();
if (NS_WARN_IF(!htmlEditor)) {
return NS_ERROR_INVALID_ARG;
}
return EditorEventListener::Connect(htmlEditor);
}
nsresult
@@ -59,7 +53,8 @@ HTMLEditorEventListener::MouseUp(nsIDOMMouseEvent* aMouseEvent)
// FYI: We need to notify HTML editor of mouseup even if it's consumed
// because HTML editor always needs to release grabbing resizer.
HTMLEditor* htmlEditor = GetHTMLEditor();
HTMLEditor* htmlEditor = mEditorBase->AsHTMLEditor();
MOZ_ASSERT(htmlEditor);
nsCOMPtr<nsIDOMEventTarget> target;
nsresult rv = aMouseEvent->AsEvent()->GetTarget(getter_AddRefs(target));
@@ -85,7 +80,9 @@ HTMLEditorEventListener::MouseDown(nsIDOMMouseEvent* aMouseEvent)
WidgetMouseEvent* mousedownEvent =
aMouseEvent->AsEvent()->WidgetEventPtr()->AsMouseEvent();
HTMLEditor* htmlEditor = GetHTMLEditor();
HTMLEditor* htmlEditor = mEditorBase->AsHTMLEditor();
MOZ_ASSERT(htmlEditor);
// Contenteditable should disregard mousedowns outside it.
// IsAcceptableInputEvent() checks it for a mouse event.
if (!htmlEditor->IsAcceptableInputEvent(mousedownEvent)) {
@@ -221,13 +218,19 @@ HTMLEditorEventListener::MouseDown(nsIDOMMouseEvent* aMouseEvent)
nsresult
HTMLEditorEventListener::MouseClick(nsIDOMMouseEvent* aMouseEvent)
{
if (NS_WARN_IF(DetachedFromEditor())) {
return NS_OK;
}
nsCOMPtr<nsIDOMEventTarget> target;
nsresult rv = aMouseEvent->AsEvent()->GetTarget(getter_AddRefs(target));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(target, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
GetHTMLEditor()->DoInlineTableEditingAction(element);
HTMLEditor* htmlEditor = mEditorBase->AsHTMLEditor();
MOZ_ASSERT(htmlEditor);
htmlEditor->DoInlineTableEditingAction(element);
return EditorEventListener::MouseClick(aMouseEvent);
}
+1 -5
View File
@@ -25,17 +25,13 @@ public:
{
}
#ifdef DEBUG
// WARNING: You must be use HTMLEditor or its sub class for this class.
// Connect() fails if aEditorBase isn't an HTMLEditor instance.
virtual nsresult Connect(EditorBase* aEditorBase) override;
#endif
protected:
virtual nsresult MouseDown(nsIDOMMouseEvent* aMouseEvent) override;
virtual nsresult MouseUp(nsIDOMMouseEvent* aMouseEvent) override;
virtual nsresult MouseClick(nsIDOMMouseEvent* aMouseEvent) override;
inline HTMLEditor* GetHTMLEditor();
};
} // namespace mozilla
+1
View File
@@ -10,6 +10,7 @@
#include "gfxFontUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/EditorUtils.h" // AutoEditBatch, AutoRules
#include "mozilla/HTMLEditor.h"
#include "mozilla/mozalloc.h"
#include "mozilla/Preferences.h"
#include "mozilla/TextEditRules.h"
+14
View File
@@ -241,4 +241,18 @@ protected:
} // namespace mozilla
// nsIEditor helper functions.
// Here because of code context.
mozilla::TextEditor*
nsIEditor::AsTextEditor()
{
return static_cast<mozilla::TextEditor*>(this);
}
const mozilla::TextEditor*
nsIEditor::AsTextEditor() const
{
return static_cast<const mozilla::TextEditor*>(this);
}
#endif // #ifndef mozilla_TextEditor_h
+38
View File
@@ -31,6 +31,14 @@ struct IMEState;
native IMEState(mozilla::widget::IMEState);
%{C++
namespace mozilla {
class EditorBase;
class HTMLEditor;
class TextEditor;
} // namespace mozilla
%}
[scriptable, uuid(094be624-f0bf-400f-89e2-6a84baab9474)]
interface nsIEditor : nsISupports
{
@@ -589,4 +597,34 @@ interface nsIEditor : nsISupports
* whether this editor has active IME transaction
*/
readonly attribute boolean composing;
%{C++
/**
* AsEditorBase() returns a pointer to EditorBase class.
*
* In order to avoid circular dependency issues, this method is defined
* in mozilla/EditorBase.h. Consumers need to #include that header.
*/
inline mozilla::EditorBase* AsEditorBase();
inline const mozilla::EditorBase* AsEditorBase() const;
/**
* AsTextEditor() returns a pointer to TextEditor class.
*
* In order to avoid circular dependency issues, this method is defined
* in mozilla/TextEditor.h. Consumers need to #include that header.
*/
inline mozilla::TextEditor* AsTextEditor();
inline const mozilla::TextEditor* AsTextEditor() const;
/**
* AsHTMLEditor() returns a pointer to HTMLEditor class.
*
* In order to avoid circular dependency issues, this method is defined
* in mozilla/HTMLEditor.h. Consumers need to #include that header.
*/
inline mozilla::HTMLEditor* AsHTMLEditor();
inline const mozilla::HTMLEditor* AsHTMLEditor() const;
%}
};