Bug 1433345 - part 4: Make EditorBase derived from nsISelectionListener and notify its owning classes of selection change r=m_kato

This patch makes EditorBase derived from nsISelectionListener.  Then, we can
make IMEContentObserver, TextInputListener, ComposerCommandsUpdater,
TypeInState not derived from nsISelectionListener since EditorBase or
HTMLEditor can notify them of selection change directly.  Additionally,
ResizerSelectionListener is not necessary anymore since it just implements
nsISelectionListener and calls only a method of HTMLEditor.  So, HTMLEditor
can call it directly.

Note that the order of selection listeners may be different.  However,
according to what each selection listener does, changing the order isn't
problem.

MozReview-Commit-ID: 1JXZxQcS0tP

--HG--
extra : rebase_source : c2ebe622a74001ad4e421da492dcdab8e6fe1649
This commit is contained in:
Masayuki Nakano 2018-01-26 17:25:45 +09:00
parent 1ef303c32e
commit 4b7e512db0
15 changed files with 201 additions and 222 deletions

View File

@ -186,12 +186,11 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IMEContentObserver)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IMEContentObserver)
NS_INTERFACE_MAP_ENTRY(nsISelectionListener)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_ENTRY(nsIReflowObserver)
NS_INTERFACE_MAP_ENTRY(nsIScrollObserver)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISelectionListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIReflowObserver)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(IMEContentObserver)
@ -476,11 +475,6 @@ IMEContentObserver::ObserveEditableNode()
}
if (!WasInitializedWithPlugin()) {
// Add selection change listener only when this starts to observe
// non-plugin content since we cannot detect selection changes in
// plugins.
nsresult rv = mSelection->AddSelectionListener(this);
NS_ENSURE_SUCCESS_VOID(rv);
// Add text change observer only when this starts to observe
// non-plugin content since we cannot detect text changes in
// plugins.
@ -553,7 +547,6 @@ IMEContentObserver::UnregisterObservers()
}
if (mSelection) {
mSelection->RemoveSelectionListener(this);
mSelectionData.Clear();
mFocusedWidget = nullptr;
}
@ -716,15 +709,14 @@ IMEContentObserver::GetSelectionAndRoot(nsISelection** aSelection,
return NS_OK;
}
nsresult
IMEContentObserver::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
nsISelection* aSelection,
int16_t aReason)
void
IMEContentObserver::OnSelectionChange(Selection& aSelection)
{
int32_t count = 0;
nsresult rv = aSelection->GetRangeCount(&count);
NS_ENSURE_SUCCESS(rv, rv);
if (count > 0 && mWidget) {
if (!mIsObserving) {
return;
}
if (aSelection.RangeCount() && mWidget) {
bool causedByComposition = IsEditorHandlingEventForComposition();
bool causedBySelectionEvent = TextComposition::IsHandlingSelectionEvent();
bool duringComposition = IsEditorComposing();
@ -732,7 +724,6 @@ IMEContentObserver::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
causedBySelectionEvent,
duringComposition);
}
return NS_OK;
}
void

View File

@ -14,7 +14,6 @@
#include "nsCycleCollectionParticipant.h"
#include "nsIDocShell.h" // XXX Why does only this need to be included here?
#include "nsIReflowObserver.h"
#include "nsISelectionListener.h"
#include "nsIScrollObserver.h"
#include "nsIWidget.h"
#include "nsStubDocumentObserver.h"
@ -32,10 +31,13 @@ namespace mozilla {
class EventStateManager;
class TextComposition;
namespace dom {
class Selection;
} // namespace dom
// IMEContentObserver notifies widget of any text and selection changes
// in the currently focused editor
class IMEContentObserver final : public nsISelectionListener
, public nsStubMutationObserver
class IMEContentObserver final : public nsStubMutationObserver
, public nsIReflowObserver
, public nsIScrollObserver
, public nsSupportsWeakReference
@ -51,8 +53,7 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(IMEContentObserver,
nsISelectionListener)
NS_DECL_NSISELECTIONLISTENER
nsIReflowObserver)
NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATAWILLCHANGE
NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
@ -65,6 +66,11 @@ public:
// nsIScrollObserver
virtual void ScrollPositionChanged() override;
/**
* OnSelectionChange() is called when selection is changed in the editor.
*/
void OnSelectionChange(dom::Selection& aSelection);
bool OnMouseButtonEvent(nsPresContext* aPresContext,
WidgetMouseEvent* aMouseEvent);
@ -336,14 +342,14 @@ private:
: Runnable(aName)
, mIMEContentObserver(
do_GetWeakReference(
static_cast<nsISelectionListener*>(aIMEContentObserver)))
static_cast<nsIReflowObserver*>(aIMEContentObserver)))
{
MOZ_ASSERT(aIMEContentObserver);
}
already_AddRefed<IMEContentObserver> GetObserver() const
{
nsCOMPtr<nsISelectionListener> observer =
nsCOMPtr<nsIReflowObserver> observer =
do_QueryReferent(mIMEContentObserver);
return observer.forget().downcast<IMEContentObserver>();
}

View File

@ -9,7 +9,6 @@
#include "nsCycleCollectionParticipant.h"
#include "nsIDOMEventListener.h"
#include "nsISelectionListener.h"
#include "nsStringFwd.h"
#include "nsWeakReference.h"
@ -20,8 +19,7 @@ class nsTextControlFrame;
namespace mozilla {
class TextInputListener final : public nsISelectionListener
, public nsIDOMEventListener
class TextInputListener final : public nsIDOMEventListener
, public nsSupportsWeakReference
{
public:
@ -51,10 +49,26 @@ public:
*/
void OnEditActionHandled();
/**
* OnSelectionChange() is called when selection is changed in the editor.
*/
void OnSelectionChange(Selection& aSelection, int16_t aReason);
/**
* Start to listen or end listening to selection change in the editor.
*/
void StartToListenToSelectionChange()
{
mListeningToSelectionChange = true;
}
void EndListeningToSelectionChange()
{
mListeningToSelectionChange = false;
}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(TextInputListener,
nsISelectionListener)
NS_DECL_NSISELECTIONLISTENER
nsIDOMEventListener)
NS_DECL_NSIDOMEVENTLISTENER
protected:
@ -90,6 +104,10 @@ protected:
* |SetValueChanged| to be called.
*/
bool mSetValueChanged;
/**
* Whether we're listening to selection change in the editor.
*/
bool mListeningToSelectionChange;
};
} // namespace mozilla

View File

@ -802,6 +802,7 @@ TextInputListener::TextInputListener(nsITextControlElement* aTxtCtrlElement)
, mHadRedoItems(false)
, mSettingValue(false)
, mSetValueChanged(true)
, mListeningToSelectionChange(false)
{
}
@ -809,30 +810,24 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(TextInputListener)
NS_IMPL_CYCLE_COLLECTING_RELEASE(TextInputListener)
NS_INTERFACE_MAP_BEGIN(TextInputListener)
NS_INTERFACE_MAP_ENTRY(nsISelectionListener)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISelectionListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(TextInputListener)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_0(TextInputListener)
// BEGIN nsIDOMSelectionListener
NS_IMETHODIMP
TextInputListener::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
nsISelection* aSelection,
int16_t aReason)
void
TextInputListener::OnSelectionChange(Selection& aSelection,
int16_t aReason)
{
bool collapsed;
AutoWeakFrame weakFrame = mFrame;
if (!aDOMDocument || !aSelection ||
NS_FAILED(aSelection->GetIsCollapsed(&collapsed))) {
return NS_OK;
if (!mListeningToSelectionChange) {
return;
}
AutoWeakFrame weakFrame = mFrame;
// Fire the select event
// The specs don't exactly say when we should fire the select event.
// IE: Whenever you add/remove a character to/from the selection. Also
@ -847,6 +842,7 @@ TextInputListener::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
// was previously selected, becase technically select all will first collapse
// and then extend. Mozilla will never create an event if the selection
// collapses to nothing.
bool collapsed = aSelection.IsCollapsed();
if (!collapsed && (aReason & (nsISelectionListener::MOUSEUP_REASON |
nsISelectionListener::KEYPRESS_REASON |
nsISelectionListener::SELECTALL_REASON))) {
@ -867,22 +863,20 @@ TextInputListener::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
// if the collapsed state did not change, don't fire notifications
if (collapsed == mSelectionWasCollapsed) {
return NS_OK;
return;
}
mSelectionWasCollapsed = collapsed;
if (!weakFrame.IsAlive() ||
!nsContentUtils::IsFocusedContent(mFrame->GetContent())) {
return NS_OK;
return;
}
return UpdateTextInputCommands(NS_LITERAL_STRING("select"),
aSelection, aReason);
UpdateTextInputCommands(NS_LITERAL_STRING("select"),
&aSelection, aReason);
}
// END nsIDOMSelectionListener
static void
DoCommandCallback(Command aCommand, void* aData)
{
@ -1263,7 +1257,7 @@ nsTextEditorState::BindToFrame(nsTextControlFrame* aFrame)
if (caret) {
selection->AddSelectionListener(caret);
}
selection->AddSelectionListener(mTextListener);
mTextListener->StartToListenToSelectionChange();
}
// If an editor exists from before, prepare it for usage
@ -2112,14 +2106,7 @@ nsTextEditorState::UnbindFromFrame(nsTextControlFrame* aFrame)
if (mSelCon) {
if (mTextListener) {
// FYI: It's safe to use raw pointer for calling
// Selection::RemoveSelectionListener() because it only removes the
// listener from its array.
Selection* selection =
mSelCon->GetSelection(SelectionType::eNormal);
if (selection) {
selection->RemoveSelectionListener(mTextListener);
}
mTextListener->EndListeningToSelectionChange();
}
mSelCon->SetScrollableFrame(nullptr);

View File

@ -23,7 +23,6 @@
#include "nsPICommandUpdater.h" // for nsPICommandUpdater
#include "nsPIDOMWindow.h" // for nsPIDOMWindow
class nsIDOMDocument;
class nsITransaction;
namespace mozilla {
@ -47,7 +46,6 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(ComposerCommandsUpdater)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ComposerCommandsUpdater)
NS_INTERFACE_MAP_BEGIN(ComposerCommandsUpdater)
NS_INTERFACE_MAP_ENTRY(nsISelectionListener)
NS_INTERFACE_MAP_ENTRY(nsIDocumentStateListener)
NS_INTERFACE_MAP_ENTRY(nsITransactionListener)
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
@ -99,14 +97,6 @@ ComposerCommandsUpdater::NotifyDocumentStateChanged(bool aNowDirty)
return UpdateDirtyState(aNowDirty);
}
NS_IMETHODIMP
ComposerCommandsUpdater::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
nsISelection* aSelection,
int16_t aReason)
{
return PrimeUpdateTimer();
}
#if 0
#pragma mark -
#endif

View File

@ -11,7 +11,6 @@
#include "nsCycleCollectionParticipant.h"
#include "nsIDocumentStateListener.h"
#include "nsINamed.h"
#include "nsISelectionListener.h"
#include "nsISupportsImpl.h" // for NS_DECL_ISUPPORTS
#include "nsITimer.h" // for NS_DECL_NSITIMERCALLBACK, etc
#include "nsITransactionListener.h" // for nsITransactionListener
@ -26,8 +25,7 @@ class nsPICommandUpdater;
namespace mozilla {
class ComposerCommandsUpdater final : public nsISelectionListener
, public nsIDocumentStateListener
class ComposerCommandsUpdater final : public nsIDocumentStateListener
, public nsITransactionListener
, public nsITimerCallback
, public nsINamed
@ -40,9 +38,6 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ComposerCommandsUpdater,
nsIDocumentStateListener)
// nsISelectionListener
NS_DECL_NSISELECTIONLISTENER
// nsIDocumentStateListener
NS_DECL_NSIDOCUMENTSTATELISTENER
@ -57,6 +52,14 @@ public:
nsresult Init(nsPIDOMWindowOuter* aDOMWindow);
/**
* OnSelectionChange() is called when selection is changed in the editor.
*/
void OnSelectionChange()
{
PrimeUpdateTimer();
}
protected:
virtual ~ComposerCommandsUpdater();

View File

@ -467,10 +467,6 @@ nsEditingSession::SetupEditorOnWindow(mozIDOMWindowProxy* aWindow)
return NS_ERROR_FAILURE;
}
rv = selection->AddSelectionListener(mComposerCommandsUpdater);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
htmlEditor->SetComposerCommandsUpdater(mComposerCommandsUpdater);
// and as a transaction listener
@ -501,10 +497,6 @@ nsEditingSession::RemoveListenersAndControllers(nsPIDOMWindowOuter* aWindow,
}
// Remove all the listeners
RefPtr<Selection> selection = aHTMLEditor->GetSelection();
if (selection) {
selection->RemoveSelectionListener(mComposerCommandsUpdater);
}
aHTMLEditor->SetComposerCommandsUpdater(nullptr);
aHTMLEditor->RemoveDocumentStateListener(mComposerCommandsUpdater);

View File

@ -210,6 +210,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(EditorBase)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EditorBase)
NS_INTERFACE_MAP_ENTRY(nsISelectionListener)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIEditor)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEditor)
@ -283,6 +284,11 @@ EditorBase::Init(nsIDOMDocument* aDOMDocument,
MOZ_ASSERT(IsInitialized());
Selection* selection = GetSelection();
if (selection) {
selection->AddSelectionListener(this);
}
// Make sure that the editor will be destroyed properly
mDidPreDestroy = false;
// Make sure that the ediotr will be created properly
@ -470,6 +476,11 @@ EditorBase::PreDestroy(bool aDestroyingFrames)
if (mDidPreDestroy)
return NS_OK;
Selection* selection = GetSelection();
if (selection) {
selection->RemoveSelectionListener(this);
}
IMEStateManager::OnEditorDestroying(*this);
// Let spellchecker clean up its observers etc. It is important not to
@ -2115,6 +2126,33 @@ EditorBase::RemoveEditorObserver(nsIEditorObserver* aObserver)
return NS_OK;
}
NS_IMETHODIMP
EditorBase::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
nsISelection* aSelection,
int16_t aReason)
{
if (NS_WARN_IF(!aDOMDocument) || NS_WARN_IF(!aSelection)) {
return NS_ERROR_INVALID_ARG;
}
RefPtr<Selection> selection = aSelection->AsSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_UNEXPECTED;
}
if (mTextInputListener) {
RefPtr<TextInputListener> textInputListener = mTextInputListener;
textInputListener->OnSelectionChange(*selection, aReason);
}
if (mIMEContentObserver) {
RefPtr<IMEContentObserver> observer = mIMEContentObserver;
observer->OnSelectionChange(*selection);
}
return NS_OK;
}
class EditorInputEventDispatcher final : public Runnable
{
public:

View File

@ -26,6 +26,7 @@
#include "nsIObserver.h" // for NS_DECL_NSIOBSERVER, etc.
#include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc.
#include "nsISelectionController.h" // for nsISelectionController constants
#include "nsISelectionListener.h" // for nsISelectionListener
#include "nsISupportsImpl.h" // for EditorBase::Release, etc.
#include "nsIWeakReferenceUtils.h" // for nsWeakPtr
#include "nsLiteralString.h" // for NS_LITERAL_STRING
@ -188,6 +189,7 @@ enum class SplitAtEdges
* implementation.
*/
class EditorBase : public nsIEditor
, public nsISelectionListener
, public nsSupportsWeakReference
{
public:
@ -254,6 +256,9 @@ public:
// nsIEditor methods
NS_DECL_NSIEDITOR
// nsISelectionListener method
NS_DECL_NSISELECTIONLISTENER
/**
* Set or unset TextInputListener. If setting non-nullptr when the editor
* already has a TextInputListener, this will crash in debug build.

View File

@ -141,21 +141,7 @@ HTMLEditor::~HTMLEditor()
mRules->AsHTMLEditRules()->EndListeningToEditActions();
}
//the autopointers will clear themselves up.
//but we need to also remove the listeners or we have a leak
RefPtr<Selection> selection = GetSelection();
// if we don't get the selection, just skip this
if (selection) {
if (mTypeInState) {
selection->RemoveSelectionListener(mTypeInState);
}
if (mResizerSelectionListener) {
selection->RemoveSelectionListener(mResizerSelectionListener);
}
}
mTypeInState = nullptr;
mResizerSelectionListener = nullptr;
if (mLinkHandler && IsInitialized()) {
nsCOMPtr<nsIPresShell> ps = GetPresShell();
@ -199,7 +185,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLEditor, TextEditor)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTypeInState)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mComposerCommandsUpdater)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResizerSelectionListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheets)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTopLeftHandle)
@ -299,23 +284,10 @@ HTMLEditor::Init(nsIDOMDocument* aDoc,
// init the type-in state
mTypeInState = new TypeInState();
// init the selection listener for image resizing
mResizerSelectionListener = new ResizerSelectionListener(*this);
if (!IsInteractionAllowed()) {
// ignore any errors from this in case the file is missing
AddOverrideStyleSheet(NS_LITERAL_STRING("resource://gre/res/EditorOverride.css"));
}
RefPtr<Selection> selection = GetSelection();
if (selection) {
if (mTypeInState) {
selection->AddSelectionListener(mTypeInState);
}
if (mResizerSelectionListener) {
selection->AddSelectionListener(mResizerSelectionListener);
}
}
}
NS_ENSURE_SUCCESS(rulesRv, rulesRv);
@ -345,6 +317,48 @@ HTMLEditor::PreDestroy(bool aDestroyingFrames)
return TextEditor::PreDestroy(aDestroyingFrames);
}
NS_IMETHODIMP
HTMLEditor::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
nsISelection* aSelection,
int16_t aReason)
{
if (NS_WARN_IF(!aDOMDocument) || NS_WARN_IF(!aSelection)) {
return NS_ERROR_INVALID_ARG;
}
RefPtr<Selection> selection = aSelection->AsSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_UNEXPECTED;
}
if (mTypeInState) {
RefPtr<TypeInState> typeInState = mTypeInState;
typeInState->OnSelectionChange(*selection);
// We used a class which derived from nsISelectionListener to call
// HTMLEditor::CheckSelectionStateForAnonymousButtons(). The lifetime of
// the class was exactly same as mTypeInState. So, call it only when
// mTypeInState is not nullptr.
if ((aReason & (nsISelectionListener::MOUSEDOWN_REASON |
nsISelectionListener::KEYPRESS_REASON |
nsISelectionListener::SELECTALL_REASON)) && aSelection) {
// the selection changed and we need to check if we have to
// hide and/or redisplay resizing handles
// FYI: This is an XPCOM method. So, the caller, Selection, guarantees
// the lifetime of this instance. So, don't need to grab this with
// local variable.
CheckSelectionStateForAnonymousButtons(selection);
}
}
if (mComposerCommandsUpdater) {
RefPtr<ComposerCommandsUpdater> updater = mComposerCommandsUpdater;
updater->OnSelectionChange();
}
return EditorBase::NotifySelectionChanged(aDOMDocument, aSelection, aReason);
}
void
HTMLEditor::UpdateRootElement()
{

View File

@ -30,7 +30,6 @@
#include "nsIHTMLEditor.h"
#include "nsIHTMLInlineTableEditor.h"
#include "nsIHTMLObjectResizer.h"
#include "nsISelectionListener.h"
#include "nsITableEditor.h"
#include "nsPoint.h"
#include "nsStubMutationObserver.h"
@ -39,11 +38,13 @@
class nsDocumentFragment;
class nsITransferable;
class nsIClipboard;
class nsIDOMDocument;
class nsIDOMMouseEvent;
class nsILinkHandler;
class nsTableWrapperFrame;
class nsIDOMRange;
class nsRange;
class nsISelection;
namespace mozilla {
class AutoSelectionSetterAfterTableEdit;
@ -108,6 +109,11 @@ public:
// nsIEditor overrides
NS_IMETHOD GetPreferredIMEState(widget::IMEState* aState) override;
// nsISelectionListener overrides
NS_IMETHOD NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
nsISelection* aSelection,
int16_t aReason) override;
// TextEditor overrides
NS_IMETHOD BeginningOfDocument() override;
virtual nsresult HandleKeyPressEvent(
@ -990,7 +996,6 @@ protected:
protected:
RefPtr<TypeInState> mTypeInState;
RefPtr<ComposerCommandsUpdater> mComposerCommandsUpdater;
RefPtr<ResizerSelectionListener> mResizerSelectionListener;
bool mCRInParagraphCreatesParagraph;

View File

@ -67,49 +67,6 @@ DocumentResizeEventListener::HandleEvent(nsIDOMEvent* aMouseEvent)
return NS_OK;
}
/******************************************************************************
* mozilla::ResizerSelectionListener
******************************************************************************/
NS_IMPL_CYCLE_COLLECTING_ADDREF(ResizerSelectionListener)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ResizerSelectionListener)
NS_INTERFACE_MAP_BEGIN(ResizerSelectionListener)
NS_INTERFACE_MAP_ENTRY(nsISelectionListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISelectionListener)
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(ResizerSelectionListener)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION(ResizerSelectionListener,
mHTMLEditor)
ResizerSelectionListener::ResizerSelectionListener(HTMLEditor& aHTMLEditor)
: mHTMLEditor(&aHTMLEditor)
{
}
NS_IMETHODIMP
ResizerSelectionListener::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
nsISelection* aSelection,
int16_t aReason)
{
if (!mHTMLEditor) {
return NS_OK;
}
if ((aReason & (nsISelectionListener::MOUSEDOWN_REASON |
nsISelectionListener::KEYPRESS_REASON |
nsISelectionListener::SELECTALL_REASON)) && aSelection) {
// the selection changed and we need to check if we have to
// hide and/or redisplay resizing handles
RefPtr<HTMLEditor> htmlEditor = mHTMLEditor;
if (htmlEditor) {
htmlEditor->CheckSelectionStateForAnonymousButtons(aSelection);
}
}
return NS_OK;
}
/******************************************************************************
* mozilla::ResizerMouseMotionListener
******************************************************************************/

View File

@ -9,7 +9,6 @@
#include "mozilla/HTMLEditor.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIDOMEventListener.h"
#include "nsISelectionListener.h"
#include "nsISupportsImpl.h"
#include "nsIWeakReferenceUtils.h"
#include "nsLiteralString.h"
@ -27,27 +26,6 @@ namespace mozilla {
#define kBottom NS_LITERAL_STRING("s")
#define kBottomRight NS_LITERAL_STRING("se")
/******************************************************************************
* mozilla::ResizerSelectionListener
******************************************************************************/
class ResizerSelectionListener final : public nsISelectionListener
{
public:
explicit ResizerSelectionListener(HTMLEditor& aHTMLEditor);
void Reset();
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ResizerSelectionListener,
nsISelectionListener)
NS_DECL_NSISELECTIONLISTENER
protected:
virtual ~ResizerSelectionListener() = default;
RefPtr<HTMLEditor> mHTMLEditor;
};
/******************************************************************************
* mozilla::ResizerMouseMotionListener
******************************************************************************/

View File

@ -36,13 +36,18 @@ using namespace dom;
* mozilla::TypeInState
*******************************************************************/
NS_IMPL_CYCLE_COLLECTION(TypeInState, mLastSelectionContainer)
NS_IMPL_CYCLE_COLLECTING_ADDREF(TypeInState)
NS_IMPL_CYCLE_COLLECTING_RELEASE(TypeInState)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TypeInState)
NS_INTERFACE_MAP_ENTRY(nsISelectionListener)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_CLASS(TypeInState)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(TypeInState)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLastSelectionContainer)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(TypeInState)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLastSelectionContainer)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(TypeInState, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(TypeInState, Release)
TypeInState::TypeInState()
: mRelativeFontSize(0)
@ -73,11 +78,8 @@ TypeInState::UpdateSelState(Selection* aSelection)
&mLastSelectionOffset);
}
NS_IMETHODIMP
TypeInState::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
nsISelection* aSelection,
int16_t aReason)
void
TypeInState::OnSelectionChange(Selection& aSelection)
{
// XXX: Selection currently generates bogus selection changed notifications
// XXX: (bug 140303). It can notify us when the selection hasn't actually
@ -88,39 +90,34 @@ TypeInState::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
// XXX:
// XXX: This code temporarily fixes the problem where clicking the mouse in
// XXX: the same location clears the type-in-state.
RefPtr<Selection> selection =
aSelection ? aSelection->AsSelection() : nullptr;
if (aSelection) {
int32_t rangeCount = selection->RangeCount();
// TODO: We can make this use nsINode instead of nsIDOMNode.
if (aSelection.IsCollapsed() && aSelection.RangeCount()) {
nsCOMPtr<nsIDOMNode> selNode;
int32_t selOffset = 0;
if (selection->Collapsed() && rangeCount) {
nsCOMPtr<nsIDOMNode> selNode;
int32_t selOffset = 0;
nsresult rv =
EditorBase::GetStartNodeAndOffset(selection, getter_AddRefs(selNode),
&selOffset);
NS_ENSURE_SUCCESS(rv, rv);
if (selNode &&
selNode == mLastSelectionContainer &&
selOffset == mLastSelectionOffset) {
// We got a bogus selection changed notification!
return NS_OK;
}
mLastSelectionContainer = selNode;
mLastSelectionOffset = selOffset;
} else {
mLastSelectionContainer = nullptr;
mLastSelectionOffset = 0;
nsresult rv =
EditorBase::GetStartNodeAndOffset(&aSelection, getter_AddRefs(selNode),
&selOffset);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
if (selNode &&
selNode == mLastSelectionContainer &&
selOffset == mLastSelectionOffset) {
// We got a bogus selection changed notification!
return;
}
mLastSelectionContainer = selNode;
mLastSelectionOffset = selOffset;
} else {
mLastSelectionContainer = nullptr;
mLastSelectionOffset = 0;
}
Reset();
return NS_OK;
}
void

View File

@ -9,7 +9,6 @@
#include "mozilla/UniquePtr.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsISelectionListener.h"
#include "nsISupportsImpl.h"
#include "nsString.h"
#include "nsTArray.h"
@ -41,19 +40,18 @@ struct PropItem
~PropItem();
};
class TypeInState final : public nsISelectionListener
class TypeInState final
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(TypeInState)
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(TypeInState)
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(TypeInState)
TypeInState();
void Reset();
nsresult UpdateSelState(dom::Selection* aSelection);
// nsISelectionListener
NS_DECL_NSISELECTIONLISTENER
void OnSelectionChange(dom::Selection& aSelection);
void SetProp(nsAtom* aProp, nsAtom* aAttr, const nsAString& aValue);