Bug 525078 - Make plugin mouse up/down/dragging behavior conform to OS X practice and Cocoa NPAPI spec clarifications. r=josh

This commit is contained in:
Steven Michaud 2010-01-22 14:57:04 -06:00
Родитель d17bf9a27b
Коммит 406b239c95
4 изменённых файлов: 163 добавлений и 78 удалений

Просмотреть файл

@ -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<nsFrameSelection> 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<const nsMouseEvent&>(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<double>(ptPx.x);
synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
{
synthCocoaEvent.type = NPCocoaEventMouseEntered;
synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
}
} else {
#ifndef NP_NO_CARBON
if (eventModel == NPEventModelCarbon) {
synthCarbonEvent.what = mouseUp;
} else
#endif
{
synthCocoaEvent.type = NPCocoaEventMouseUp;
synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
}
}
break;
default:

Просмотреть файл

@ -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

Просмотреть файл

@ -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);
};
//-------------------------------------------------------------------------

Просмотреть файл

@ -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);