diff --git a/dom/events/EventStateManager.cpp b/dom/events/EventStateManager.cpp index df09389cc2d..1735255b7d9 100644 --- a/dom/events/EventStateManager.cpp +++ b/dom/events/EventStateManager.cpp @@ -20,6 +20,7 @@ #include "mozilla/dom/UIEvent.h" #include "ContentEventHandler.h" +#include "IMEContentObserver.h" #include "WheelHandlingHelper.h" #include "nsCOMPtr.h" @@ -337,6 +338,8 @@ EventStateManager::Init() EventStateManager::~EventStateManager() { + ReleaseCurrentIMEContentObserver(); + if (sActiveESM == this) { sActiveESM = nullptr; } @@ -410,7 +413,7 @@ NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTING_ADDREF(EventStateManager) NS_IMPL_CYCLE_COLLECTING_RELEASE(EventStateManager) -NS_IMPL_CYCLE_COLLECTION_16(EventStateManager, +NS_IMPL_CYCLE_COLLECTION_17(EventStateManager, mCurrentTargetContent, mGestureDownContent, mGestureDownFrameOwner, @@ -426,8 +429,35 @@ NS_IMPL_CYCLE_COLLECTION_16(EventStateManager, mMouseEnterLeaveHelper, mPointersEnterLeaveHelper, mDocument, + mIMEContentObserver, mAccessKeys) +void +EventStateManager::ReleaseCurrentIMEContentObserver() +{ + if (mIMEContentObserver) { + mIMEContentObserver->DisconnectFromEventStateManager(); + } + mIMEContentObserver = nullptr; +} + +void +EventStateManager::OnStartToObserveContent( + IMEContentObserver* aIMEContentObserver) +{ + ReleaseCurrentIMEContentObserver(); + mIMEContentObserver = aIMEContentObserver; +} + +void +EventStateManager::OnStopObservingContent( + IMEContentObserver* aIMEContentObserver) +{ + aIMEContentObserver->DisconnectFromEventStateManager(); + NS_ENSURE_TRUE_VOID(mIMEContentObserver == aIMEContentObserver); + mIMEContentObserver = nullptr; +} + nsresult EventStateManager::PreHandleEvent(nsPresContext* aPresContext, WidgetEvent* aEvent, diff --git a/dom/events/EventStateManager.h b/dom/events/EventStateManager.h index f8409c11b59..c27403fb856 100644 --- a/dom/events/EventStateManager.h +++ b/dom/events/EventStateManager.h @@ -34,6 +34,7 @@ namespace mozilla { class EnterLeaveDispatcher; class EventStates; +class IMEContentObserver; class ScrollbarsForWheel; class WheelTransaction; @@ -133,6 +134,14 @@ public: void ContentRemoved(nsIDocument* aDocument, nsIContent* aContent); bool EventStatusOK(WidgetGUIEvent* aEvent); + /** + * EventStateManager stores IMEContentObserver while it's observing contents. + * Following mehtods are called by IMEContentObserver when it starts to + * observe or stops observing the content. + */ + void OnStartToObserveContent(IMEContentObserver* aIMEContentObserver); + void OnStopObservingContent(IMEContentObserver* aIMEContentObserver); + /** * Register accesskey on the given element. When accesskey is activated then * the element will be notified via nsIContent::PerformAccesskey() method. @@ -777,6 +786,8 @@ protected: nsIFrame* aTargetFrame, nsEventStatus* aStatus); + void ReleaseCurrentIMEContentObserver(); + private: static inline void DoStateChange(dom::Element* aElement, EventStates aState, bool aAddState); @@ -839,6 +850,8 @@ private: nsPresContext* mPresContext; // Not refcnted nsCOMPtr mDocument; // Doesn't necessarily need to be owner + nsRefPtr mIMEContentObserver; + uint32_t mLClickCount; uint32_t mMClickCount; uint32_t mRClickCount; diff --git a/dom/events/IMEContentObserver.cpp b/dom/events/IMEContentObserver.cpp index 65274f1188d..60eb54211e4 100644 --- a/dom/events/IMEContentObserver.cpp +++ b/dom/events/IMEContentObserver.cpp @@ -7,6 +7,7 @@ #include "ContentEventHandler.h" #include "IMEContentObserver.h" #include "mozilla/AsyncEventDispatcher.h" +#include "mozilla/EventStateManager.h" #include "mozilla/IMEStateManager.h" #include "mozilla/TextComposition.h" #include "mozilla/dom/Element.h" @@ -50,6 +51,7 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(IMEContentObserver) NS_IMPL_CYCLE_COLLECTING_RELEASE(IMEContentObserver) IMEContentObserver::IMEContentObserver() + : mESM(nullptr) { } @@ -58,6 +60,9 @@ IMEContentObserver::Init(nsIWidget* aWidget, nsPresContext* aPresContext, nsIContent* aContent) { + mESM = aPresContext->EventStateManager(); + mESM->OnStartToObserveContent(this); + mWidget = aWidget; mEditableNode = IMEStateManager::GetRootEditableNode(aPresContext, aContent); if (!mEditableNode) { @@ -183,6 +188,17 @@ IMEContentObserver::Destroy() mEditableNode = nullptr; mDocShell = nullptr; mUpdatePreference.mWantUpdates = nsIMEUpdatePreference::NOTIFY_NOTHING; + + if (mESM) { + mESM->OnStopObservingContent(this); + mESM = nullptr; + } +} + +void +IMEContentObserver::DisconnectFromEventStateManager() +{ + mESM = nullptr; } bool diff --git a/dom/events/IMEContentObserver.h b/dom/events/IMEContentObserver.h index 0d833671f2b..cf358c6d989 100644 --- a/dom/events/IMEContentObserver.h +++ b/dom/events/IMEContentObserver.h @@ -25,6 +25,8 @@ class nsPresContext; namespace mozilla { +class EventStateManager; + // IMEContentObserver notifies widget of any text and selection changes // in the currently focused editor class IMEContentObserver MOZ_FINAL : public nsISelectionListener, @@ -54,6 +56,12 @@ public: void Init(nsIWidget* aWidget, nsPresContext* aPresContext, nsIContent* aContent); void Destroy(); + /** + * IMEContentObserver is stored by EventStateManager during observing. + * DisconnectFromEventStateManager() is called when EventStateManager stops + * storing the instance. + */ + void DisconnectFromEventStateManager(); bool IsManaging(nsPresContext* aPresContext, nsIContent* aContent); bool IsEditorHandlingEventForComposition() const; bool KeepAliveDuringDeactive() const @@ -73,6 +81,9 @@ private: nsCOMPtr mRootContent; nsCOMPtr mEditableNode; nsCOMPtr mDocShell; + + EventStateManager* mESM; + nsIMEUpdatePreference mUpdatePreference; uint32_t mPreAttrChangeLength; };