diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index e9b13b72889..6f37bd14421 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -1934,6 +1934,19 @@ nsObjectFrame::HandleEvent(nsPresContext* aPresContext, return nsObjectFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus); } +#ifdef XP_MACOSX +// Needed to make the routing of mouse events while dragging conform to +// standard OS X practice, and to the Cocoa NPAPI spec. See bug 525078. +NS_IMETHODIMP +nsObjectFrame::HandlePress(nsPresContext* aPresContext, + nsGUIEvent* anEvent, + nsEventStatus* anEventStatus) +{ + nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED); + return nsObjectFrameSuper::HandlePress(aPresContext, anEvent, anEventStatus); +} +#endif + nsresult nsObjectFrame::GetPluginInstance(nsIPluginInstance*& aPluginInstance) { @@ -4264,6 +4277,16 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent) } break; case NS_MOUSE_MOVE: + { + // Ignore mouse-moved events that happen as part of a dragging + // operation that started over another frame. See bug 525078. + nsCOMPtr frameselection = mObjectFrame->GetFrameSelection(); + if (frameselection->GetMouseDownState() && + (nsIPresShell::GetCapturingContent() != mObjectFrame->GetContent())) { + pluginWidget->EndDrawPlugin(); + return nsEventStatus_eIgnore; + } + } #ifndef NP_NO_CARBON if (eventModel == NPEventModelCarbon) { synthCarbonEvent.what = osEvt; @@ -4288,15 +4311,34 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent) } break; case NS_MOUSE_BUTTON_UP: + // If we're in a dragging operation that started over another frame, + // either ignore the mouse-up event (in the Carbon Event Model) or + // convert it into a mouse-entered event (in the Cocoa Event Model). + // See bug 525078. + if ((static_cast(anEvent).button == nsMouseEvent::eLeftButton) && + (nsIPresShell::GetCapturingContent() != mObjectFrame->GetContent())) { #ifndef NP_NO_CARBON - if (eventModel == NPEventModelCarbon) { - synthCarbonEvent.what = mouseUp; - } else + if (eventModel == NPEventModelCarbon) { + pluginWidget->EndDrawPlugin(); + return nsEventStatus_eIgnore; + } else #endif - { - synthCocoaEvent.type = NPCocoaEventMouseUp; - synthCocoaEvent.data.mouse.pluginX = static_cast(ptPx.x); - synthCocoaEvent.data.mouse.pluginY = static_cast(ptPx.y); + { + synthCocoaEvent.type = NPCocoaEventMouseEntered; + synthCocoaEvent.data.mouse.pluginX = static_cast(ptPx.x); + synthCocoaEvent.data.mouse.pluginY = static_cast(ptPx.y); + } + } else { +#ifndef NP_NO_CARBON + if (eventModel == NPEventModelCarbon) { + synthCarbonEvent.what = mouseUp; + } else +#endif + { + synthCocoaEvent.type = NPCocoaEventMouseUp; + synthCocoaEvent.data.mouse.pluginX = static_cast(ptPx.x); + synthCocoaEvent.data.mouse.pluginY = static_cast(ptPx.y); + } } break; default: diff --git a/layout/generic/nsObjectFrame.h b/layout/generic/nsObjectFrame.h index 89032129584..f8849562613 100644 --- a/layout/generic/nsObjectFrame.h +++ b/layout/generic/nsObjectFrame.h @@ -90,6 +90,12 @@ public: nsGUIEvent* aEvent, nsEventStatus* aEventStatus); +#ifdef XP_MACOSX + NS_IMETHOD HandlePress(nsPresContext* aPresContext, + nsGUIEvent* aEvent, + nsEventStatus* aEventStatus); +#endif + virtual nsIAtom* GetType() const; virtual PRBool IsFrameOfType(PRUint32 aFlags) const diff --git a/widget/src/cocoa/nsChildView.h b/widget/src/cocoa/nsChildView.h index fce167c865e..d145ab1feea 100644 --- a/widget/src/cocoa/nsChildView.h +++ b/widget/src/cocoa/nsChildView.h @@ -284,13 +284,13 @@ public: static void OnDestroyView(ChildView* aView); static BOOL WindowAcceptsEvent(NSWindow* aWindow, NSEvent* aEvent); static void ReEvaluateMouseEnterState(NSEvent* aEvent = nil); + static ChildView* ViewForEvent(NSEvent* aEvent); static ChildView* sLastMouseEventView; private: static NSWindow* WindowForEvent(NSEvent* aEvent); - static ChildView* ViewForEvent(NSEvent* aEvent); }; //------------------------------------------------------------------------- diff --git a/widget/src/cocoa/nsChildView.mm b/widget/src/cocoa/nsChildView.mm index c6405351d18..51c2bc6dbc2 100644 --- a/widget/src/cocoa/nsChildView.mm +++ b/widget/src/cocoa/nsChildView.mm @@ -3135,10 +3135,11 @@ static BOOL DrawingAtWindowTop(CGContextRef aContext) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - if (!mGeckoChild) return; + nsAutoRetainCocoaObject kungFuDeathGrip(self); + nsMouseEvent geckoEvent(PR_TRUE, NS_MOUSE_BUTTON_UP, nsnull, nsMouseEvent::eReal); [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; if (nsCocoaUtils::GetCocoaEventModifierFlags(theEvent) & NSControlKeyMask) @@ -3149,35 +3150,67 @@ static BOOL DrawingAtWindowTop(CGContextRef aContext) // Create event for use by plugins. // This is going to our child view so we don't need to look up the destination // event type. + if (mIsPluginView) { #ifndef NP_NO_CARBON - EventRecord carbonEvent; - if (mPluginEventModel == NPEventModelCarbon) { - carbonEvent.what = mouseUp; - carbonEvent.message = 0; - carbonEvent.when = ::TickCount(); - ::GetGlobalMouse(&carbonEvent.where); - carbonEvent.modifiers = ::GetCurrentKeyModifiers(); - geckoEvent.pluginEvent = &carbonEvent; - } + EventRecord carbonEvent; + if (mPluginEventModel == NPEventModelCarbon) { + carbonEvent.what = mouseUp; + carbonEvent.message = 0; + carbonEvent.when = ::TickCount(); + ::GetGlobalMouse(&carbonEvent.where); + carbonEvent.modifiers = ::GetCurrentKeyModifiers(); + geckoEvent.pluginEvent = &carbonEvent; + } #endif - NPCocoaEvent cocoaEvent; - if (mPluginEventModel == NPEventModelCocoa) { - InitNPCocoaEvent(&cocoaEvent); - NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; - cocoaEvent.type = NPCocoaEventMouseUp; - cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags]; - cocoaEvent.data.mouse.pluginX = point.x; - cocoaEvent.data.mouse.pluginY = point.y; - cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber]; - cocoaEvent.data.mouse.clickCount = [theEvent clickCount]; - cocoaEvent.data.mouse.deltaX = [theEvent deltaX]; - cocoaEvent.data.mouse.deltaY = [theEvent deltaY]; - cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ]; - geckoEvent.pluginEvent = &cocoaEvent; + NPCocoaEvent cocoaEvent; + if (mPluginEventModel == NPEventModelCocoa) { + InitNPCocoaEvent(&cocoaEvent); + NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + cocoaEvent.type = NPCocoaEventMouseUp; + cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags]; + cocoaEvent.data.mouse.pluginX = point.x; + cocoaEvent.data.mouse.pluginY = point.y; + cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber]; + cocoaEvent.data.mouse.clickCount = [theEvent clickCount]; + cocoaEvent.data.mouse.deltaX = [theEvent deltaX]; + cocoaEvent.data.mouse.deltaY = [theEvent deltaY]; + cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ]; + geckoEvent.pluginEvent = &cocoaEvent; + } } mGeckoChild->DispatchWindowEvent(geckoEvent); + // If our mouse-up event's location is over some other object (as might + // happen if it came at the end of a dragging operation), also send our + // Gecko frame a mouse-exit event. + if (mIsPluginView) { +#ifndef NP_NO_CARBON + if (mPluginEventModel == NPEventModelCocoa) +#endif + { + if (ChildViewMouseTracker::ViewForEvent(theEvent) != self) { + nsMouseEvent geckoExitEvent(PR_TRUE, NS_MOUSE_EXIT, nsnull, nsMouseEvent::eReal); + [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoExitEvent]; + + NPCocoaEvent cocoaEvent; + InitNPCocoaEvent(&cocoaEvent); + NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + cocoaEvent.type = NPCocoaEventMouseExited; + cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags]; + cocoaEvent.data.mouse.pluginX = point.x; + cocoaEvent.data.mouse.pluginY = point.y; + cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber]; + cocoaEvent.data.mouse.deltaX = [theEvent deltaX]; + cocoaEvent.data.mouse.deltaY = [theEvent deltaY]; + cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ]; + geckoExitEvent.pluginEvent = &cocoaEvent; + + mGeckoChild->DispatchWindowEvent(geckoExitEvent); + } + } + } + NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -3296,31 +3329,33 @@ static BOOL DrawingAtWindowTop(CGContextRef aContext) [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; // create event for use by plugins + if (mIsPluginView) { #ifndef NP_NO_CARBON - EventRecord carbonEvent; - if (mPluginEventModel == NPEventModelCarbon) { - carbonEvent.what = NPEventType_AdjustCursorEvent; - carbonEvent.message = 0; - carbonEvent.when = ::TickCount(); - ::GetGlobalMouse(&carbonEvent.where); - carbonEvent.modifiers = btnState | ::GetCurrentKeyModifiers(); - geckoEvent.pluginEvent = &carbonEvent; - } + EventRecord carbonEvent; + if (mPluginEventModel == NPEventModelCarbon) { + carbonEvent.what = NPEventType_AdjustCursorEvent; + carbonEvent.message = 0; + carbonEvent.when = ::TickCount(); + ::GetGlobalMouse(&carbonEvent.where); + carbonEvent.modifiers = btnState | ::GetCurrentKeyModifiers(); + geckoEvent.pluginEvent = &carbonEvent; + } #endif - NPCocoaEvent cocoaEvent; - if (mPluginEventModel == NPEventModelCocoa) { - InitNPCocoaEvent(&cocoaEvent); - NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; - cocoaEvent.type = NPCocoaEventMouseDragged; - cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags]; - cocoaEvent.data.mouse.pluginX = point.x; - cocoaEvent.data.mouse.pluginY = point.y; - cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber]; - cocoaEvent.data.mouse.clickCount = [theEvent clickCount]; - cocoaEvent.data.mouse.deltaX = [theEvent deltaX]; - cocoaEvent.data.mouse.deltaY = [theEvent deltaY]; - cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ]; - geckoEvent.pluginEvent = &cocoaEvent; + NPCocoaEvent cocoaEvent; + if (mPluginEventModel == NPEventModelCocoa) { + InitNPCocoaEvent(&cocoaEvent); + NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + cocoaEvent.type = NPCocoaEventMouseDragged; + cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags]; + cocoaEvent.data.mouse.pluginX = point.x; + cocoaEvent.data.mouse.pluginY = point.y; + cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber]; + cocoaEvent.data.mouse.clickCount = [theEvent clickCount]; + cocoaEvent.data.mouse.deltaX = [theEvent deltaX]; + cocoaEvent.data.mouse.deltaY = [theEvent deltaY]; + cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ]; + geckoEvent.pluginEvent = &cocoaEvent; + } } mGeckoChild->DispatchWindowEvent(geckoEvent); @@ -3401,31 +3436,33 @@ static BOOL DrawingAtWindowTop(CGContextRef aContext) geckoEvent.clickCount = [theEvent clickCount]; // create event for use by plugins + if (mIsPluginView) { #ifndef NP_NO_CARBON - EventRecord carbonEvent; - if (mPluginEventModel == NPEventModelCarbon) { - carbonEvent.what = mouseUp; - carbonEvent.message = 0; - carbonEvent.when = ::TickCount(); - ::GetGlobalMouse(&carbonEvent.where); - carbonEvent.modifiers = controlKey; // fake a context menu click - geckoEvent.pluginEvent = &carbonEvent; - } + EventRecord carbonEvent; + if (mPluginEventModel == NPEventModelCarbon) { + carbonEvent.what = mouseUp; + carbonEvent.message = 0; + carbonEvent.when = ::TickCount(); + ::GetGlobalMouse(&carbonEvent.where); + carbonEvent.modifiers = controlKey; // fake a context menu click + geckoEvent.pluginEvent = &carbonEvent; + } #endif - NPCocoaEvent cocoaEvent; - if (mPluginEventModel == NPEventModelCocoa) { - InitNPCocoaEvent(&cocoaEvent); - NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; - cocoaEvent.type = NPCocoaEventMouseUp; - cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags]; - cocoaEvent.data.mouse.pluginX = point.x; - cocoaEvent.data.mouse.pluginY = point.y; - cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber]; - cocoaEvent.data.mouse.clickCount = [theEvent clickCount]; - cocoaEvent.data.mouse.deltaX = [theEvent deltaX]; - cocoaEvent.data.mouse.deltaY = [theEvent deltaY]; - cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ]; - geckoEvent.pluginEvent = &cocoaEvent; + NPCocoaEvent cocoaEvent; + if (mPluginEventModel == NPEventModelCocoa) { + InitNPCocoaEvent(&cocoaEvent); + NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + cocoaEvent.type = NPCocoaEventMouseUp; + cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags]; + cocoaEvent.data.mouse.pluginX = point.x; + cocoaEvent.data.mouse.pluginY = point.y; + cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber]; + cocoaEvent.data.mouse.clickCount = [theEvent clickCount]; + cocoaEvent.data.mouse.deltaX = [theEvent deltaX]; + cocoaEvent.data.mouse.deltaY = [theEvent deltaY]; + cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ]; + geckoEvent.pluginEvent = &cocoaEvent; + } } nsAutoRetainCocoaObject kungFuDeathGrip(self);