diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 0102891b93bc..d9b4b678905c 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -7835,7 +7835,8 @@ nsresult nsContentUtils::SendMouseEvent( exitFrom = Some(WidgetMouseEvent::eChild); } else if (aType.EqualsLiteral("mousecancel")) { msg = eMouseExitFromWidget; - exitFrom = Some(WidgetMouseEvent::eTopLevel); + exitFrom = Some(XRE_IsParentProcess() ? WidgetMouseEvent::eTopLevel + : WidgetMouseEvent::ePuppet); } else if (aType.EqualsLiteral("mouselongtap")) { msg = eMouseLongTap; } else if (aType.EqualsLiteral("contextmenu")) { diff --git a/dom/events/EventStateManager.cpp b/dom/events/EventStateManager.cpp index 07829ead0aaf..6797bd884654 100644 --- a/dom/events/EventStateManager.cpp +++ b/dom/events/EventStateManager.cpp @@ -646,10 +646,11 @@ nsresult EventStateManager::PreHandleEvent(nsPresContext* aPresContext, // above, at eMouseEnterIntoWidget case. aEvent->StopCrossProcessForwarding(); - // If the event is not a top-level window exit, then it's not - // really an exit --- we may have traversed widget boundaries but - // we're still in our toplevel window. - if (mouseEvent->mExitFrom.value() != WidgetMouseEvent::eTopLevel) { + // If the event is not a top-level window or puppet widget exit, then it's + // not really an exit --- we may have traversed widget boundaries but + // we're still in our toplevel window or puppet widget. + if (mouseEvent->mExitFrom.value() != WidgetMouseEvent::eTopLevel && + mouseEvent->mExitFrom.value() != WidgetMouseEvent::ePuppet) { // Treat it as a synthetic move so we don't generate spurious // "exit" or "move" events. Any necessary "out" or "over" events // will be generated by GenerateMouseEnterExit @@ -657,10 +658,14 @@ nsresult EventStateManager::PreHandleEvent(nsPresContext* aPresContext, mouseEvent->mReason = WidgetMouseEvent::eSynthesized; // then fall through... } else { + MOZ_ASSERT_IF(XRE_IsParentProcess(), mouseEvent->mExitFrom.value() == + WidgetMouseEvent::eTopLevel); + MOZ_ASSERT_IF(XRE_IsContentProcess(), mouseEvent->mExitFrom.value() == + WidgetMouseEvent::ePuppet); // We should synthetize corresponding pointer events GeneratePointerEnterExit(ePointerLeave, mouseEvent); GenerateMouseEnterExit(mouseEvent); - // This is a window level mouse exit event and should stop here + // This is really an exit and should stop here aEvent->mMessage = eVoidEvent; break; } @@ -4220,11 +4225,11 @@ nsIFrame* EventStateManager::DispatchMouseOrPointerEvent( // event to the remote frame. if (IsTopLevelRemoteTarget(targetContent)) { if (aMessage == eMouseOut) { - // For remote content, send a "top-level" widget mouse exit event. + // For remote content, send a puppet widget mouse exit event. UniquePtr remoteEvent = CreateMouseOrPointerWidgetEvent(aMouseEvent, eMouseExitFromWidget, relatedContent); - remoteEvent->mExitFrom = Some(WidgetMouseEvent::eTopLevel); + remoteEvent->mExitFrom = Some(WidgetMouseEvent::ePuppet); // mCurrentTarget is set to the new target, so we must reset it to the // old target and then dispatch a cross-process event. (mCurrentTarget diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp index 2eec5135e72f..cb898d5e09cc 100644 --- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp @@ -6984,9 +6984,11 @@ nsresult PresShell::EventHandler::HandleEventUsingCoordinates( } WidgetMouseEvent* mouseEvent = aGUIEvent->AsMouseEvent(); - bool isWindowLevelMouseExit = (aGUIEvent->mMessage == eMouseExitFromWidget) && - (mouseEvent && mouseEvent->mExitFrom.value() == - WidgetMouseEvent::eTopLevel); + bool isWindowLevelMouseExit = + (aGUIEvent->mMessage == eMouseExitFromWidget) && + (mouseEvent && + (mouseEvent->mExitFrom.value() == WidgetMouseEvent::eTopLevel || + mouseEvent->mExitFrom.value() == WidgetMouseEvent::ePuppet)); // Get the frame at the event point. However, don't do this if we're // capturing and retargeting the event because the captured frame will diff --git a/widget/MouseEvents.h b/widget/MouseEvents.h index 23ecb2b55760..57573ffd04ae 100644 --- a/widget/MouseEvents.h +++ b/widget/MouseEvents.h @@ -190,8 +190,8 @@ class WidgetMouseEvent : public WidgetMouseEventBase, eControlClick }; - typedef bool ExitFromType; - enum ExitFrom : ExitFromType { eChild, eTopLevel }; + typedef uint8_t ExitFromType; + enum ExitFrom : ExitFromType { eChild, eTopLevel, ePuppet }; protected: WidgetMouseEvent() @@ -267,8 +267,8 @@ class WidgetMouseEvent : public WidgetMouseEventBase, ContextMenuTrigger mContextMenuTrigger; // mExitFrom contains a value only when mMessage is eMouseExitFromWidget. - // This indicates if the mouse cursor exits from a top level widget or - // a child widget. + // This indicates if the mouse cursor exits from a top level platform widget, + // a child widget or a puppet widget. Maybe mExitFrom; // Whether the event should ignore scroll frame bounds during dispatch.