Bug 1387317 - part2: EditorEventListener should stop using interface methods as far as possible r?m_kato
MozReview-Commit-ID: EPQeBez2tJh
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -2567,17 +2567,17 @@ nsTextEditorState::SetValue(const nsAStr
if (nsContentUtils::IsSafeToRunScript()) {
WeakPtr<nsTextEditorState> self(this);
// WARNING: During this call, compositionupdate, compositionend, input
// events will be fired. Therefore, everything can occur. E.g., the
// document may be unloaded.
mValueBeingSet = aValue;
mIsCommittingComposition = true;
RefPtr<TextEditor> textEditor = mTextEditor;
- nsresult rv = textEditor->ForceCompositionEnd();
+ nsresult rv = textEditor->CommitComposition();
if (!self.get()) {
return true;
}
mIsCommittingComposition = false;
// If this is called recursively during committing composition and
// some of them may be skipped above. Therefore, we need to set
// value to the editor with the aValue of the latest call.
newValue = mValueBeingSet;
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -2188,21 +2188,23 @@ EditorBase::EndIMEComposition()
// notify editor observers of action
NotifyEditorObservers(eNotifyEditorObserversOfEnd);
}
NS_IMETHODIMP
EditorBase::ForceCompositionEnd()
{
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- if (!ps) {
- return NS_ERROR_NOT_AVAILABLE;
- }
- nsPresContext* pc = ps->GetPresContext();
+ return CommitComposition();
+}
+
+nsresult
+EditorBase::CommitComposition()
+{
+ nsPresContext* pc = GetPresContext();
if (!pc) {
return NS_ERROR_NOT_AVAILABLE;
}
return mComposition ?
IMEStateManager::NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, pc) : NS_OK;
}
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -246,16 +246,21 @@ protected:
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EditorBase, nsIEditor)
bool IsInitialized() const { return !!mDocument; }
already_AddRefed<nsIDOMDocument> GetDOMDocument();
already_AddRefed<nsIDocument> GetDocument();
already_AddRefed<nsIPresShell> GetPresShell();
+ nsPresContext* GetPresContext()
+ {
+ RefPtr<nsIPresShell> presShell = GetPresShell();
+ return presShell ? presShell->GetPresContext() : nullptr;
+ }
already_AddRefed<nsIWidget> GetWidget();
nsISelectionController* GetSelectionController() const
{
if (mSelectionController) {
return mSelectionController;
}
if (!mDocument) {
return nullptr;
@@ -346,16 +351,25 @@ public:
/**
* IME event handlers.
*/
virtual nsresult BeginIMEComposition(WidgetCompositionEvent* aEvent);
virtual nsresult UpdateIMEComposition(
WidgetCompositionEvent* aCompositionChangeEvet) = 0;
void EndIMEComposition();
+ /**
+ * Commit composition if there is.
+ * Note that when there is a composition, this requests to commit composition
+ * to native IME. Therefore, when there is composition, this can do anything.
+ * For example, the editor instance, the widget or the process itself may
+ * be destroyed.
+ */
+ nsresult CommitComposition();
+
void SwitchTextDirectionTo(uint32_t aDirection);
protected:
nsresult DetermineCurrentDirection();
void FireInputEvent();
/**
* Create a transaction for setting aAttribute to aValue on aElement. Never
@@ -942,16 +956,46 @@ public:
*/
Element* GetExposedRoot();
/**
* Accessor methods to flags.
*/
uint32_t Flags() const { return mFlags; }
+ nsresult AddFlags(uint32_t aFlags)
+ {
+ const uint32_t kOldFlags = Flags();
+ const uint32_t kNewFlags = (kOldFlags | aFlags);
+ if (kNewFlags == kOldFlags) {
+ return NS_OK;
+ }
+ return SetFlags(kNewFlags); // virtual call and may be expensive.
+ }
+ nsresult RemoveFlags(uint32_t aFlags)
+ {
+ const uint32_t kOldFlags = Flags();
+ const uint32_t kNewFlags = (kOldFlags & ~aFlags);
+ if (kNewFlags == kOldFlags) {
+ return NS_OK;
+ }
+ return SetFlags(kNewFlags); // virtual call and may be expensive.
+ }
+ nsresult AddAndRemoveFlags(uint32_t aAddingFlags, uint32_t aRemovingFlags)
+ {
+ MOZ_ASSERT(!(aAddingFlags & aRemovingFlags),
+ "Same flags are specified both adding and removing");
+ const uint32_t kOldFlags = Flags();
+ const uint32_t kNewFlags = ((kOldFlags | aAddingFlags) & ~aRemovingFlags);
+ if (kNewFlags == kOldFlags) {
+ return NS_OK;
+ }
+ return SetFlags(kNewFlags); // virtual call and may be expensive.
+ }
+
bool IsPlaintextEditor() const
{
return (mFlags & nsIPlaintextEditor::eEditorPlaintextMask) != 0;
}
bool IsSingleLineEditor() const
{
return (mFlags & nsIPlaintextEditor::eEditorSingleLineMask) != 0;
--- a/editor/libeditor/EditorEventListener.cpp
+++ b/editor/libeditor/EditorEventListener.cpp
@@ -7,16 +7,17 @@
#include "EditorEventListener.h"
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc.
#include "mozilla/ContentEvents.h" // for InternalFocusEvent
#include "mozilla/EditorBase.h" // for EditorBase, etc.
#include "mozilla/EventListenerManager.h" // for EventListenerManager
#include "mozilla/IMEStateManager.h" // for IMEStateManager
#include "mozilla/Preferences.h" // for Preferences
+#include "mozilla/TextEditor.h" // for TextEditor
#include "mozilla/TextEvents.h" // for WidgetCompositionEvent
#include "mozilla/dom/Element.h" // for Element
#include "mozilla/dom/Event.h" // for Event
#include "mozilla/dom/EventTarget.h" // for EventTarget
#include "mozilla/dom/Selection.h"
#include "nsAString.h"
#include "nsCaret.h" // for nsCaret
#include "nsDebug.h" // for NS_ENSURE_TRUE, etc.
@@ -31,21 +32,18 @@
#include "nsIDOMDocument.h" // for nsIDOMDocument
#include "nsIDOMDragEvent.h" // for nsIDOMDragEvent
#include "nsIDOMElement.h" // for nsIDOMElement
#include "nsIDOMEvent.h" // for nsIDOMEvent
#include "nsIDOMEventTarget.h" // for nsIDOMEventTarget
#include "nsIDOMMouseEvent.h" // for nsIDOMMouseEvent
#include "nsIDOMNode.h" // for nsIDOMNode
#include "nsIDocument.h" // for nsIDocument
-#include "nsIEditor.h" // for EditorBase::GetSelection, etc.
-#include "nsIEditorMailSupport.h" // for nsIEditorMailSupport
#include "nsIFocusManager.h" // for nsIFocusManager
#include "nsIFormControl.h" // for nsIFormControl, etc.
-#include "nsIHTMLEditor.h" // for nsIHTMLEditor
#include "nsINode.h" // for nsINode, ::NODE_IS_EDITABLE, etc.
#include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc.
#include "nsIPresShell.h" // for nsIPresShell
#include "nsISelectionController.h" // for nsISelectionController, etc.
#include "nsITransferable.h" // for kFileMime, kHTMLMime, etc.
#include "nsIWidget.h" // for nsIWidget
#include "nsLiteralString.h" // for NS_LITERAL_STRING
#include "nsPIWindowRoot.h" // for nsPIWindowRoot
@@ -361,17 +359,17 @@ EditorEventListener::DetachedFromEditorO
aWidgetEvent->DefaultPrevented();
}
bool
EditorEventListener::EnsureCommitCompoisition()
{
MOZ_ASSERT(!DetachedFromEditor());
RefPtr<EditorBase> editorBase(mEditorBase);
- editorBase->ForceCompositionEnd();
+ editorBase->CommitComposition();
return !DetachedFromEditor();
}
NS_IMETHODIMP
EditorEventListener::HandleEvent(nsIDOMEvent* aEvent)
{
// Let's handle each event with the message of the internal event of the
// coming event. If the DOM event was created with improper interface,
@@ -706,45 +704,42 @@ EditorEventListener::HandleMiddleClickPa
if (NS_FAILED(aMouseEvent->GetRangeParent(getter_AddRefs(parent)))) {
return NS_ERROR_NULL_POINTER;
}
int32_t offset = 0;
if (NS_FAILED(aMouseEvent->GetRangeOffset(&offset))) {
return NS_ERROR_NULL_POINTER;
}
- RefPtr<EditorBase> editorBase(mEditorBase);
- RefPtr<Selection> selection = editorBase->GetSelection();
+ RefPtr<TextEditor> textEditor = mEditorBase->AsTextEditor();
+ MOZ_ASSERT(textEditor);
+
+ RefPtr<Selection> selection = textEditor->GetSelection();
if (selection) {
selection->Collapse(parent, offset);
}
- // If the ctrl key is pressed, we'll do paste as quotation.
- // Would've used the alt key, but the kde wmgr treats alt-middle specially.
- nsCOMPtr<nsIEditorMailSupport> mailEditor;
- if (clickEvent->IsControl()) {
- mailEditor = do_QueryObject(editorBase);
- }
-
nsresult rv;
int32_t clipboard = nsIClipboard::kGlobalClipboard;
nsCOMPtr<nsIClipboard> clipboardService =
do_GetService("@mozilla.org/widget/clipboard;1", &rv);
if (NS_SUCCEEDED(rv)) {
bool selectionSupported;
rv = clipboardService->SupportsSelectionClipboard(&selectionSupported);
if (NS_SUCCEEDED(rv) && selectionSupported) {
clipboard = nsIClipboard::kSelectionClipboard;
}
}
- if (mailEditor) {
- mailEditor->PasteAsQuotation(clipboard);
+ // If the ctrl key is pressed, we'll do paste as quotation.
+ // Would've used the alt key, but the kde wmgr treats alt-middle specially.
+ if (clickEvent->IsControl()) {
+ textEditor->PasteAsQuotation(clipboard);
} else {
- editorBase->Paste(clipboard);
+ textEditor->Paste(clipboard);
}
// Prevent the event from propagating up to be possibly handled
// again by the containing window:
clickEvent->StopPropagation();
clickEvent->PreventDefault();
// We processed the event, whether drop/paste succeeded or not
@@ -1186,21 +1181,18 @@ EditorEventListener::Blur(InternalFocusE
void
EditorEventListener::SpellCheckIfNeeded()
{
MOZ_ASSERT(!DetachedFromEditor());
// If the spell check skip flag is still enabled from creation time,
// disable it because focused editors are allowed to spell check.
RefPtr<EditorBase> editorBase(mEditorBase);
- uint32_t currentFlags = 0;
- editorBase->GetFlags(¤tFlags);
- if(currentFlags & nsIPlaintextEditor::eEditorSkipSpellCheck) {
- currentFlags ^= nsIPlaintextEditor::eEditorSkipSpellCheck;
- editorBase->SetFlags(currentFlags);
+ if(editorBase->ShouldSkipSpellCheck()) {
+ editorBase->RemoveFlags(nsIPlaintextEditor::eEditorSkipSpellCheck);
}
}
bool
EditorEventListener::IsFileControlTextBox()
{
MOZ_ASSERT(!DetachedFromEditor());
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -1198,17 +1198,17 @@ HTMLEditor::CollapseSelectionToDeepestNo
NS_IMETHODIMP
HTMLEditor::ReplaceHeadContentsWithHTML(const nsAString& aSourceToInsert)
{
// don't do any post processing, rules get confused
AutoRules beginRulesSniffing(this, EditAction::ignore, nsIEditor::eNone);
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- ForceCompositionEnd();
+ CommitComposition();
// Do not use AutoRules -- rules code won't let us insert in <head>. Use
// the head node as a parent and delete/insert directly.
nsCOMPtr<nsIDocument> document = GetDocument();
if (NS_WARN_IF(!document)) {
return NS_ERROR_NOT_INITIALIZED;
}
@@ -1268,17 +1268,17 @@ HTMLEditor::ReplaceHeadContentsWithHTML(
}
return NS_OK;
}
NS_IMETHODIMP
HTMLEditor::RebuildDocumentFromSource(const nsAString& aSourceString)
{
- ForceCompositionEnd();
+ CommitComposition();
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
nsCOMPtr<Element> bodyElement = GetRoot();
NS_ENSURE_TRUE(bodyElement, NS_ERROR_NULL_POINTER);
// Find where the <body> tag starts.
@@ -1532,17 +1532,17 @@ HTMLEditor::InsertElementAtSelection(nsI
// Protect the edit rules object from dying
nsCOMPtr<nsIEditRules> rules(mRules);
nsCOMPtr<Element> element = do_QueryInterface(aElement);
NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
- ForceCompositionEnd();
+ CommitComposition();
AutoEditBatch beginBatching(this);
AutoRules beginRulesSniffing(this, EditAction::insertElement,
nsIEditor::eNext);
RefPtr<Selection> selection = GetSelection();
if (!selection) {
return NS_ERROR_FAILURE;
}
@@ -3575,17 +3575,17 @@ HTMLEditor::SelectEntireDocument(Selecti
}
return EditorBase::SelectEntireDocument(aSelection);
}
NS_IMETHODIMP
HTMLEditor::SelectAll()
{
- ForceCompositionEnd();
+ CommitComposition();
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
nsCOMPtr<nsIDOMNode> anchorNode;
nsresult rv = selection->GetAnchorNode(getter_AddRefs(anchorNode));
NS_ENSURE_SUCCESS(rv, rv);
@@ -4514,17 +4514,17 @@ HTMLEditor::SetIsCSSEnabled(bool aIsCSSP
return SetFlags(flags);
}
// Set the block background color
nsresult
HTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
{
NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
- ForceCompositionEnd();
+ CommitComposition();
// Protect the edit rules object from dying
nsCOMPtr<nsIEditRules> rules(mRules);
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
bool isCollapsed = selection->Collapsed();
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -97,17 +97,17 @@ static nsresult FindTargetNode(nsIDOMNod
nsCOMPtr<nsIDOMNode>& aResult);
nsresult
HTMLEditor::LoadHTML(const nsAString& aInputString)
{
NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
// force IME commit; set up rules sniffing and batching
- ForceCompositionEnd();
+ CommitComposition();
AutoEditBatch beginBatching(this);
AutoRules beginRulesSniffing(this, EditAction::loadHTML, nsIEditor::eNext);
// Get selection
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
TextRulesInfo ruleInfo(EditAction::loadHTML);
@@ -192,17 +192,17 @@ HTMLEditor::DoInsertHTMLWithContext(cons
bool aClearStyle)
{
NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
// Prevent the edit rules object from dying
nsCOMPtr<nsIEditRules> rules(mRules);
// force IME commit; set up rules sniffing and batching
- ForceCompositionEnd();
+ CommitComposition();
AutoEditBatch beginBatching(this);
AutoRules beginRulesSniffing(this, EditAction::htmlPaste, nsIEditor::eNext);
// Get selection
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
// create a dom document fragment that represents the structure to paste
@@ -1489,17 +1489,17 @@ HTMLEditor::PasteTransferable(nsITransfe
*/
NS_IMETHODIMP
HTMLEditor::PasteNoFormatting(int32_t aSelectionType)
{
if (!FireClipboardEvent(ePasteNoFormatting, aSelectionType)) {
return NS_OK;
}
- ForceCompositionEnd();
+ CommitComposition();
// Get Clipboard Service
nsresult rv;
nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
NS_ENSURE_SUCCESS(rv, rv);
// Get the nsITransferable interface for getting the data from the clipboard.
// use TextEditor::PrepareTransferable() to force unicode plaintext data.
--- a/editor/libeditor/HTMLEditorEventListener.cpp
+++ b/editor/libeditor/HTMLEditorEventListener.cpp
@@ -13,18 +13,16 @@
#include "nsCOMPtr.h"
#include "nsDebug.h"
#include "nsError.h"
#include "nsIDOMElement.h"
#include "nsIDOMEvent.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMMouseEvent.h"
#include "nsIDOMNode.h"
-#include "nsIHTMLInlineTableEditor.h"
-#include "nsIHTMLObjectResizer.h"
#include "nsISupportsImpl.h"
#include "nsLiteralString.h"
#include "nsQueryObject.h"
#include "nsRange.h"
namespace mozilla {
using namespace dom;
--- a/editor/libeditor/HTMLEditorEventListener.h
+++ b/editor/libeditor/HTMLEditorEventListener.h
@@ -7,17 +7,16 @@
#define HTMLEditorEventListener_h
#include "EditorEventListener.h"
#include "nscore.h"
namespace mozilla {
class EditorBase;
-class HTMLEditor;
class HTMLEditorEventListener final : public EditorEventListener
{
public:
HTMLEditorEventListener()
{
}
--- a/editor/libeditor/HTMLStyleEditor.cpp
+++ b/editor/libeditor/HTMLStyleEditor.cpp
@@ -105,17 +105,17 @@ HTMLEditor::RemoveAllDefaultProperties()
NS_IMETHODIMP
HTMLEditor::SetInlineProperty(nsIAtom* aProperty,
const nsAString& aAttribute,
const nsAString& aValue)
{
NS_ENSURE_TRUE(aProperty, NS_ERROR_NULL_POINTER);
NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
nsCOMPtr<nsIEditRules> rules(mRules);
- ForceCompositionEnd();
+ CommitComposition();
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
if (selection->Collapsed()) {
// Manipulating text attributes on a collapsed selection only sets state
// for the next text insertion
mTypeInState->SetProp(aProperty, aAttribute, aValue);
@@ -1197,17 +1197,17 @@ HTMLEditor::RemoveInlineProperty(nsIAtom
}
nsresult
HTMLEditor::RemoveInlinePropertyImpl(nsIAtom* aProperty,
const nsAString* aAttribute)
{
MOZ_ASSERT_IF(aProperty, aAttribute);
NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
- ForceCompositionEnd();
+ CommitComposition();
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
if (selection->Collapsed()) {
// Manipulating text attributes on a collapsed selection only sets state
// for the next text insertion
@@ -1346,17 +1346,17 @@ NS_IMETHODIMP
HTMLEditor::DecreaseFontSize()
{
return RelativeFontChange(FontSize::decr);
}
nsresult
HTMLEditor::RelativeFontChange(FontSize aDir)
{
- ForceCompositionEnd();
+ CommitComposition();
// Get the selection
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
// If selection is collapsed, set typing state
if (selection->Collapsed()) {
nsIAtom& atom = aDir == FontSize::incr ? *nsGkAtoms::big :
*nsGkAtoms::small;
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -1075,17 +1075,17 @@ TextEditor::SetNewlineHandling(int32_t a
NS_IMETHODIMP
TextEditor::Undo(uint32_t aCount)
{
// Protect the edit rules object from dying
nsCOMPtr<nsIEditRules> rules(mRules);
AutoUpdateViewBatch beginViewBatching(this);
- ForceCompositionEnd();
+ CommitComposition();
NotifyEditorObservers(eNotifyEditorObserversOfBefore);
AutoRules beginRulesSniffing(this, EditAction::undo, nsIEditor::eNone);
TextRulesInfo ruleInfo(EditAction::undo);
RefPtr<Selection> selection = GetSelection();
bool cancel, handled;
@@ -1103,17 +1103,17 @@ TextEditor::Undo(uint32_t aCount)
NS_IMETHODIMP
TextEditor::Redo(uint32_t aCount)
{
// Protect the edit rules object from dying
nsCOMPtr<nsIEditRules> rules(mRules);
AutoUpdateViewBatch beginViewBatching(this);
- ForceCompositionEnd();
+ CommitComposition();
NotifyEditorObservers(eNotifyEditorObserversOfBefore);
AutoRules beginRulesSniffing(this, EditAction::redo, nsIEditor::eNone);
TextRulesInfo ruleInfo(EditAction::redo);
RefPtr<Selection> selection = GetSelection();
bool cancel, handled;
@@ -1145,17 +1145,17 @@ TextEditor::CanCutOrCopy(PasswordFieldAl
}
bool
TextEditor::FireClipboardEvent(EventMessage aEventMessage,
int32_t aSelectionType,
bool* aActionTaken)
{
if (aEventMessage == ePaste) {
- ForceCompositionEnd();
+ CommitComposition();
}
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
NS_ENSURE_TRUE(presShell, false);
RefPtr<Selection> selection = GetSelection();
if (!selection) {
return false;
--- a/editor/libeditor/TextEditorDataTransfer.cpp
+++ b/editor/libeditor/TextEditorDataTransfer.cpp
@@ -158,17 +158,17 @@ TextEditor::InsertFromDataTransfer(DataT
}
return NS_OK;
}
nsresult
TextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
{
- ForceCompositionEnd();
+ CommitComposition();
nsCOMPtr<nsIDOMDragEvent> dragEvent(do_QueryInterface(aDropEvent));
NS_ENSURE_TRUE(dragEvent, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMDataTransfer> domDataTransfer;
dragEvent->GetDataTransfer(getter_AddRefs(domDataTransfer));
nsCOMPtr<DataTransfer> dataTransfer = do_QueryInterface(domDataTransfer);
NS_ENSURE_TRUE(dataTransfer, NS_ERROR_FAILURE);