diff --git a/editor/libeditor/HTMLAbsPositionEditor.cpp b/editor/libeditor/HTMLAbsPositionEditor.cpp index 30a27801cf66..c8e092dbfea9 100644 --- a/editor/libeditor/HTMLAbsPositionEditor.cpp +++ b/editor/libeditor/HTMLAbsPositionEditor.cpp @@ -6,6 +6,7 @@ #include +#include "HTMLEditorEventListener.h" #include "HTMLEditorObjectResizerUtils.h" #include "HTMLEditRules.h" #include "HTMLEditUtils.h" @@ -436,20 +437,14 @@ HTMLEditor::SnapToGrid(int32_t& newX, int32_t& newY) nsresult HTMLEditor::GrabberClicked() { - // add a mouse move listener to the editor - nsresult rv = NS_OK; - if (!mMouseMotionListenerP) { - EventTarget* eventTarget = GetDOMEventTarget(); - if (NS_WARN_IF(!eventTarget)) { - return NS_ERROR_FAILURE; - } - mMouseMotionListenerP = new ResizerMouseMotionListener(*this); - EventListenerManager* eventListenerManager = - eventTarget->GetOrCreateListenerManager(); - eventListenerManager->AddEventListenerByType( - mMouseMotionListenerP, - NS_LITERAL_STRING("mousemove"), - TrustedEventsAtSystemGroupBubble()); + if (NS_WARN_IF(!mEventListener)) { + return NS_ERROR_NOT_INITIALIZED; + } + nsresult rv = + static_cast(mEventListener.get())-> + ListenToMouseMoveEventForGrabber(true); + if (NS_WARN_IF(NS_FAILED(rv))) { + return NS_OK; } mGrabberClicked = true; return rv; @@ -467,16 +462,13 @@ HTMLEditor::EndMoving() mPositioningShadow = nullptr; } - EventTarget* eventTarget = GetDOMEventTarget(); - if (eventTarget && mMouseMotionListenerP) { - EventListenerManager* eventListenerManager = - eventTarget->GetOrCreateListenerManager(); - eventListenerManager->RemoveEventListenerByType( - mMouseMotionListenerP, - NS_LITERAL_STRING("mousemove"), - TrustedEventsAtSystemGroupBubble()); + if (mEventListener) { + DebugOnly rvIgnored = + static_cast(mEventListener.get())-> + ListenToMouseMoveEventForGrabber(false); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored), + "Failed to remove mousemove event listener"); } - mMouseMotionListenerP = nullptr; mGrabberClicked = false; mIsMoving = false; diff --git a/editor/libeditor/HTMLEditor.cpp b/editor/libeditor/HTMLEditor.cpp index ba2902a922ea..fb8f98cd5262 100644 --- a/editor/libeditor/HTMLEditor.cpp +++ b/editor/libeditor/HTMLEditor.cpp @@ -286,7 +286,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLEditor, TextEditor) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResizingShadow) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResizingInfo) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResizedObject) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMouseMotionListenerP) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAbsolutelyPositionedObject) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGrabber) @@ -543,27 +542,6 @@ HTMLEditor::RemoveEventListeners() return; } - RefPtr target = GetDOMEventTarget(); - - if (target) { - // mMouseMotionListenerP can be registerd with other targets than the DOM - // event receiver that we can reach from here. But nonetheless, unregister - // the event listener with the DOM event receiver (if it's registerd with - // other targets, it'll get unregisterd once the target goes - // away). - - if (mMouseMotionListenerP) { - // mMouseMotionListenerP might be registerd either as bubbling or - // capturing, unregister by both. - target->RemoveEventListener(NS_LITERAL_STRING("mousemove"), - mMouseMotionListenerP, false); - target->RemoveEventListener(NS_LITERAL_STRING("mousemove"), - mMouseMotionListenerP, true); - } - } - - mMouseMotionListenerP = nullptr; - TextEditor::RemoveEventListeners(); } diff --git a/editor/libeditor/HTMLEditor.h b/editor/libeditor/HTMLEditor.h index bf6a5ea2eb16..16383d04eeea 100644 --- a/editor/libeditor/HTMLEditor.h +++ b/editor/libeditor/HTMLEditor.h @@ -227,7 +227,7 @@ public: * event callback when the mouse pointer is moved * @param aMouseEvent [IN] the event */ - nsresult OnMouseMove(dom::MouseEvent* aMouseEvent); + MOZ_CAN_RUN_SCRIPT nsresult OnMouseMove(dom::MouseEvent* aMouseEvent); /** * IsCSSEnabled() returns true if this editor treats styles with style @@ -2559,8 +2559,6 @@ protected: RefPtr mResizedObject; - nsCOMPtr mMouseMotionListenerP; - int32_t mOriginalX; int32_t mOriginalY; diff --git a/editor/libeditor/HTMLEditorEventListener.cpp b/editor/libeditor/HTMLEditorEventListener.cpp index 0bfec7eaac1e..5203d54e6130 100644 --- a/editor/libeditor/HTMLEditorEventListener.cpp +++ b/editor/libeditor/HTMLEditorEventListener.cpp @@ -45,6 +45,16 @@ HTMLEditorEventListener::Disconnect() EditorEventListener::Disconnect(); } + if (mListeningToMouseMoveEventForResizers) { + DebugOnly rvIgnored = ListenToMouseMoveEventForResizers(false); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored), + "Failed to remove resize event listener of resizers"); + } + if (mListeningToMouseMoveEventForGrabber) { + DebugOnly rvIgnored = ListenToMouseMoveEventForGrabber(false); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored), + "Failed to remove resize event listener of grabber"); + } if (mListeningToResizeEvent) { DebugOnly rvIgnored = ListenToWindowResizeEvent(false); NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored), @@ -59,6 +69,23 @@ HTMLEditorEventListener::HandleEvent(Event* aEvent) { WidgetEvent* internalEvent = aEvent->WidgetEventPtr(); switch (internalEvent->mMessage) { + case eMouseMove: { + if (DetachedFromEditor()) { + return NS_OK; + } + + RefPtr mouseEvent = aEvent->AsMouseEvent(); + if (NS_WARN_IF(!mouseEvent)) { + return NS_ERROR_FAILURE; + } + + RefPtr htmlEditor = mEditorBase->AsHTMLEditor(); + MOZ_ASSERT(htmlEditor); + DebugOnly rvIgnored = htmlEditor->OnMouseMove(mouseEvent); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored), + "Resizers failed to handle mousemove events"); + return NS_OK; + } case eResize: { if (DetachedFromEditor()) { return NS_OK; @@ -80,6 +107,82 @@ HTMLEditorEventListener::HandleEvent(Event* aEvent) return NS_OK; } } + +nsresult +HTMLEditorEventListener::ListenToMouseMoveEventForResizersOrGrabber( + bool aListen, + bool aForGrabber) +{ + MOZ_ASSERT(aForGrabber ? + mListeningToMouseMoveEventForGrabber != aListen : + mListeningToMouseMoveEventForResizers != aListen); + + if (NS_WARN_IF(DetachedFromEditor())) { + return aListen ? NS_ERROR_FAILURE : NS_OK; + } + + if (aListen) { + if (aForGrabber && mListeningToMouseMoveEventForResizers) { + // We've already added mousemove event listener for resizers. + mListeningToMouseMoveEventForGrabber = true; + return NS_OK; + } + if (!aForGrabber && mListeningToMouseMoveEventForGrabber) { + // We've already added mousemove event listener for grabber. + mListeningToMouseMoveEventForResizers = true; + return NS_OK; + } + } else { + if (aForGrabber && mListeningToMouseMoveEventForResizers) { + // We need to keep listening to mousemove event listener for resizers. + mListeningToMouseMoveEventForGrabber = false; + return NS_OK; + } + if (!aForGrabber && mListeningToMouseMoveEventForGrabber) { + // We need to keep listening to mousemove event listener for grabber. + mListeningToMouseMoveEventForResizers = false; + return NS_OK; + } + } + + EventTarget* target = mEditorBase->AsHTMLEditor()->GetDOMEventTarget(); + if (NS_WARN_IF(!target)) { + return NS_ERROR_FAILURE; + } + + // Listen to mousemove events in the system group since web apps may stop + // propagation before we receive the events. + EventListenerManager* eventListenerManager = + target->GetOrCreateListenerManager(); + if (NS_WARN_IF(!eventListenerManager)) { + return NS_ERROR_FAILURE; + } + + if (aListen) { + eventListenerManager->AddEventListenerByType( + this, + NS_LITERAL_STRING("mousemove"), + TrustedEventsAtSystemGroupBubble()); + if (aForGrabber) { + mListeningToMouseMoveEventForGrabber = true; + } else { + mListeningToMouseMoveEventForResizers = true; + } + return NS_OK; + } + + eventListenerManager->RemoveEventListenerByType( + this, + NS_LITERAL_STRING("mousemove"), + TrustedEventsAtSystemGroupBubble()); + if (aForGrabber) { + mListeningToMouseMoveEventForGrabber = false; + } else { + mListeningToMouseMoveEventForResizers = false; + } + return NS_OK; +} + nsresult HTMLEditorEventListener::ListenToWindowResizeEvent(bool aListen) { diff --git a/editor/libeditor/HTMLEditorEventListener.h b/editor/libeditor/HTMLEditorEventListener.h index 5f5e7171d2c8..d6081f3fe150 100644 --- a/editor/libeditor/HTMLEditorEventListener.h +++ b/editor/libeditor/HTMLEditorEventListener.h @@ -18,6 +18,8 @@ class HTMLEditorEventListener final : public EditorEventListener public: HTMLEditorEventListener() : EditorEventListener() + , mListeningToMouseMoveEventForResizers(false) + , mListeningToMouseMoveEventForGrabber(false) , mListeningToResizeEvent(false) { } @@ -37,6 +39,41 @@ public: virtual void Disconnect() override; + /** + * ListenToMouseMoveEventForResizers() starts to listen to or stop + * listening to "mousemove" events for resizers. + */ + nsresult ListenToMouseMoveEventForResizers(bool aListen) + { + if (aListen == mListeningToMouseMoveEventForResizers) { + return NS_OK; + } + nsresult rv = + ListenToMouseMoveEventForResizersOrGrabber(aListen, false); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + return NS_OK; + } + + /** + * ListenToMouseMoveEventForResizers() starts to listen to or stop + * listening to "mousemove" events for grabber to move absolutely + * positioned element. + */ + nsresult ListenToMouseMoveEventForGrabber(bool aListen) + { + if (aListen == mListeningToMouseMoveEventForGrabber) { + return NS_OK; + } + nsresult rv = + ListenToMouseMoveEventForResizersOrGrabber(aListen, true); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + return NS_OK; + } + /** * ListenToWindowResizeEvent() starts to listen to or stop listening to * "resize" events of the document. @@ -50,6 +87,11 @@ protected: MOZ_CAN_RUN_SCRIPT virtual nsresult MouseClick(WidgetMouseEvent* aMouseClickEvent) override; + nsresult + ListenToMouseMoveEventForResizersOrGrabber(bool aListen, bool aForGrabber); + + bool mListeningToMouseMoveEventForResizers; + bool mListeningToMouseMoveEventForGrabber; bool mListeningToResizeEvent; }; diff --git a/editor/libeditor/HTMLEditorObjectResizer.cpp b/editor/libeditor/HTMLEditorObjectResizer.cpp index 167cca8e52d2..58758fb6b7c6 100644 --- a/editor/libeditor/HTMLEditorObjectResizer.cpp +++ b/editor/libeditor/HTMLEditorObjectResizer.cpp @@ -39,36 +39,6 @@ namespace mozilla { using namespace dom; -/****************************************************************************** - * mozilla::ResizerMouseMotionListener - ******************************************************************************/ - -NS_IMPL_ISUPPORTS(ResizerMouseMotionListener, nsIDOMEventListener) - -ResizerMouseMotionListener::ResizerMouseMotionListener(HTMLEditor& aHTMLEditor) - : mHTMLEditorWeak(&aHTMLEditor) -{ -} - -NS_IMETHODIMP -ResizerMouseMotionListener::HandleEvent(Event* aMouseEvent) -{ - MouseEvent* mouseEvent = aMouseEvent->AsMouseEvent(); - if (!mouseEvent) { - //non-ui event passed in. bad things. - return NS_OK; - } - - // Don't do anything special if not an HTML object resizer editor - RefPtr htmlEditor = mHTMLEditorWeak.get(); - if (htmlEditor) { - // check if we have to redisplay a resizing shadow - htmlEditor->OnMouseMove(mouseEvent); - } - - return NS_OK; -} - /****************************************************************************** * mozilla::HTMLEditor ******************************************************************************/ @@ -529,8 +499,6 @@ HTMLEditor::HideResizersInternal() ManualNACPtr resizingShadow(std::move(mResizingShadow)); ManualNACPtr resizingInfo(std::move(mResizingInfo)); RefPtr activatedHandle(std::move(mActivatedHandle)); - nsCOMPtr mouseMotionListener( - std::move(mMouseMotionListenerP)); RefPtr resizedObject(std::move(mResizedObject)); // Remvoe all handles. @@ -573,13 +541,15 @@ HTMLEditor::HideResizersInternal() // Remove resizing state of the target element. resizedObject->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_moz_resizing, true); - // Remove mousemove event listener from the event target. - nsCOMPtr target = GetDOMEventTarget(); - NS_WARNING_ASSERTION(target, "GetDOMEventTarget() returned nullptr"); + if (!mEventListener) { + return NS_OK; + } - if (target && mouseMotionListener) { - target->RemoveEventListener(NS_LITERAL_STRING("mousemove"), - mouseMotionListener, true); + nsresult rv = + static_cast(mEventListener.get())-> + ListenToMouseMoveEventForResizers(false); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; } // Remove resize event listener from the window. @@ -587,9 +557,8 @@ HTMLEditor::HideResizersInternal() return NS_OK; } - nsresult rv = - static_cast(mEventListener.get())-> - ListenToWindowResizeEvent(false); + rv = static_cast(mEventListener.get())-> + ListenToWindowResizeEvent(false); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } @@ -654,22 +623,16 @@ HTMLEditor::StartResizing(Element* aHandle) mResizedObjectHeight); // add a mouse move listener to the editor - nsresult result = NS_OK; - if (!mMouseMotionListenerP) { - mMouseMotionListenerP = new ResizerMouseMotionListener(*this); - if (!mMouseMotionListenerP) { - return NS_ERROR_OUT_OF_MEMORY; - } - - EventTarget* target = GetDOMEventTarget(); - NS_ENSURE_TRUE(target, NS_ERROR_FAILURE); - - result = target->AddEventListener(NS_LITERAL_STRING("mousemove"), - mMouseMotionListenerP, true); - NS_ASSERTION(NS_SUCCEEDED(result), - "failed to register mouse motion listener"); + if (NS_WARN_IF(!mEventListener)) { + return NS_ERROR_NOT_INITIALIZED; } - return result; + nsresult rv = + static_cast(mEventListener.get())-> + ListenToMouseMoveEventForResizers(true); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + return NS_OK; } nsresult diff --git a/editor/libeditor/HTMLEditorObjectResizerUtils.h b/editor/libeditor/HTMLEditorObjectResizerUtils.h index b08094399a56..223e42fc5196 100644 --- a/editor/libeditor/HTMLEditorObjectResizerUtils.h +++ b/editor/libeditor/HTMLEditorObjectResizerUtils.h @@ -26,23 +26,6 @@ namespace mozilla { #define kBottom NS_LITERAL_STRING("s") #define kBottomRight NS_LITERAL_STRING("se") -/****************************************************************************** - * mozilla::ResizerMouseMotionListener - ******************************************************************************/ - -class ResizerMouseMotionListener final : public nsIDOMEventListener -{ -public: - explicit ResizerMouseMotionListener(HTMLEditor& aHTMLEditor); - - NS_DECL_ISUPPORTS - NS_DECL_NSIDOMEVENTLISTENER - -protected: - virtual ~ResizerMouseMotionListener() {} - CachedWeakPtr mHTMLEditorWeak; -}; - } // namespace mozilla #endif // #ifndef HTMLEditorObjectResizerUtils_h