mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
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:
parent
1ef303c32e
commit
4b7e512db0
@ -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
|
||||
|
@ -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>();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
******************************************************************************/
|
||||
|
@ -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
|
||||
******************************************************************************/
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user