commit af3ec6b99835c54f7de8fd5615386e15c583cd71 Author: Steven Michaud smichaud@pobox.com Date: Fri May 16 12:55:28 2014 -0500
Bug 995603 - Ensure mouse-enter/exit events are sent to plugins as appropriate. r=mstange,masayuki a=sledru --- content/events/src/nsContentEventHandler.cpp | 25 +++++++-- content/events/src/nsContentEventHandler.h | 2 +- widget/cocoa/nsChildView.mm | 78 +++++++++----------------- widget/cocoa/nsCocoaWindow.h | 3 - widget/cocoa/nsCocoaWindow.mm | 30 ---------- 5 files changed, 45 insertions(+), 93 deletions(-)
diff --git a/content/events/src/nsContentEventHandler.cpp b/content/events/src/nsContentEventHandler.cpp index 8b151cb..03c0721 100644 --- a/content/events/src/nsContentEventHandler.cpp +++ b/content/events/src/nsContentEventHandler.cpp @@ -44,11 +44,8 @@ nsContentEventHandler::nsContentEventHandler( }
nsresult -nsContentEventHandler::InitCommon() +nsContentEventHandler::InitBasic() { - if (mSelection) - return NS_OK; - NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
// If text frame which has overflowing selection underline is dirty, @@ -58,11 +55,24 @@ nsContentEventHandler::InitCommon() // Flushing notifications can cause mPresShell to be destroyed (bug 577963). NS_ENSURE_TRUE(!mPresShell->IsDestroying(), NS_ERROR_FAILURE);
+ return NS_OK; +} + +nsresult +ContentEventHandler::InitCommon() +{ + if (mSelection) { + return NS_OK; + } + + nsresult rv = InitBasic(); + NS_ENSURE_SUCCESS(rv, rv); + nsCopySupport::GetSelectionForCopy(mPresShell->GetDocument(), getter_AddRefs(mSelection));
nsCOMPtr<nsIDOMRange> firstRange; - nsresult rv = mSelection->GetRangeAt(0, getter_AddRefs(firstRange)); + rv = mSelection->GetRangeAt(0, getter_AddRefs(firstRange)); // This shell doesn't support selection. if (NS_FAILED(rv)) return NS_ERROR_NOT_AVAILABLE; @@ -860,10 +870,13 @@ nsContentEventHandler::OnQueryCharacterAtPoint(nsQueryContentEvent* aEvent) nsresult nsContentEventHandler::OnQueryDOMWidgetHittest(nsQueryContentEvent* aEvent) { - nsresult rv = Init(aEvent); + NS_ASSERTION(aEvent, "aEvent must not be null"); + + nsresult rv = InitBasic(); if (NS_FAILED(rv)) return rv;
+ aEvent->mSucceeded = false; aEvent->mReply.mWidgetIsHit = false;
NS_ENSURE_TRUE(aEvent->widget, NS_ERROR_FAILURE); diff --git a/content/events/src/nsContentEventHandler.h b/content/events/src/nsContentEventHandler.h index 4c4f492..1624d35 100644 --- a/content/events/src/nsContentEventHandler.h +++ b/content/events/src/nsContentEventHandler.h @@ -66,7 +66,7 @@ protected: nsresult Init(nsQueryContentEvent* aEvent); nsresult Init(nsSelectionEvent* aEvent);
- // InitCommon() is called from each Init(). + nsresult InitBasic(); nsresult InitCommon();
public: diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index aef01c7..fe619e0 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -2790,6 +2790,31 @@ NSEvent* gLastDragMouseDownEvent = nil; return mIsPluginView; }
+- (NSView *)hitTest:(NSPoint)aPoint +{ + NSView* target = [super hitTest:aPoint]; + if ((target == self) && [self isPluginView] && mGeckoChild) { + nsAutoRetainCocoaObject kungFuDeathGrip(self); + + NSPoint cocoaLoc = [[self superview] convertPoint:aPoint toView:self]; + LayoutDeviceIntPoint widgetLoc = LayoutDeviceIntPoint::FromUntyped( + mGeckoChild->CocoaPointsToDevPixels(cocoaLoc)); + + WidgetQueryContentEvent hitTest(true, NS_QUERY_DOM_WIDGET_HITTEST, + mGeckoChild); + hitTest.InitForQueryDOMWidgetHittest(widgetLoc); + // This might destroy our widget. + mGeckoChild->DispatchWindowEvent(hitTest); + if (!mGeckoChild) { + return nil; + } + if (hitTest.mSucceeded && !hitTest.mReply.mWidgetIsHit) { + return nil; + } + } + return target; +} + // Are we processing an NSLeftMouseDown event that will fail to click through? // If so, we shouldn't focus or unfocus a plugin. - (BOOL)isInFailingLeftClickThrough @@ -4913,65 +4938,12 @@ static int32_t RoundUp(double aDouble) return !mGeckoChild->DispatchWindowEvent(geckoEvent); }
-// Don't focus a plugin if the user has clicked on a DOM element above it. -// In this case the user has actually clicked on the plugin's ChildView -// (underneath the non-plugin DOM element). But we shouldn't allow the -// ChildView to be focused. See bug 627649. -- (BOOL)currentEventShouldFocusPlugin -{ - if (!mGeckoChild) - return NO; - - NSEvent* currentEvent = [NSApp currentEvent]; - if ([currentEvent type] != NSLeftMouseDown) - return YES; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - // hitTest needs coordinates in device pixels - NSPoint eventLoc = nsCocoaUtils::ScreenLocationForEvent(currentEvent); - eventLoc.y = nsCocoaUtils::FlippedScreenY(eventLoc.y); - nsIntPoint widgetLoc = mGeckoChild->CocoaPointsToDevPixels(eventLoc) - - mGeckoChild->WidgetToScreenOffset(); - - nsQueryContentEvent hitTest(true, NS_QUERY_DOM_WIDGET_HITTEST, mGeckoChild); - hitTest.InitForQueryDOMWidgetHittest(widgetLoc); - // This might destroy our widget (and null out mGeckoChild). - mGeckoChild->DispatchWindowEvent(hitTest); - if (!mGeckoChild) - return NO; - if (hitTest.mSucceeded && !hitTest.mReply.mWidgetIsHit) - return NO; - - return YES; -} - -// Don't focus a plugin if we're in a left click-through that will fail (see -// [ChildView isInFailingLeftClickThrough] above). -- (BOOL)shouldFocusPlugin:(BOOL)getFocus -{ - if (!mGeckoChild) - return NO; - - nsCocoaWindow* windowWidget = mGeckoChild->GetXULWindowWidget(); - if (windowWidget && !windowWidget->ShouldFocusPlugin()) - return NO; - - if (getFocus && ![self currentEventShouldFocusPlugin]) - return NO; - - return YES; -} - // Returns NO if the plugin shouldn't be focused/unfocused. - (BOOL)updatePluginFocusStatus:(BOOL)getFocus { if (!mGeckoChild) return NO;
- if (![self shouldFocusPlugin:getFocus]) - return NO; - if (mPluginEventModel == NPEventModelCocoa) { nsPluginEvent pluginEvent(true, NS_PLUGIN_FOCUS_EVENT, mGeckoChild); NPCocoaEvent cocoaEvent; diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h index ac434e0..dc5994671 100644 --- a/widget/cocoa/nsCocoaWindow.h +++ b/widget/cocoa/nsCocoaWindow.h @@ -316,9 +316,6 @@ public:
void SetPopupWindowLevel();
- bool IsChildInFailingLeftClickThrough(NSView *aChild); - bool ShouldFocusPlugin(); - NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent); protected:
diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm index b95c072..b435155 100644 --- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -2051,36 +2051,6 @@ void nsCocoaWindow::SetPopupWindowLevel() } }
-bool nsCocoaWindow::IsChildInFailingLeftClickThrough(NSView *aChild) -{ - if ([aChild isKindOfClass:[ChildView class]]) { - ChildView* childView = (ChildView*) aChild; - if ([childView isInFailingLeftClickThrough]) - return true; - } - NSArray* subviews = [aChild subviews]; - if (subviews) { - NSUInteger count = [subviews count]; - for (NSUInteger i = 0; i < count; ++i) { - NSView* aView = (NSView*) [subviews objectAtIndex:i]; - if (IsChildInFailingLeftClickThrough(aView)) - return true; - } - } - return false; -} - -// Don't focus a plugin if we're in a left click-through that will -// fail (see [ChildView isInFailingLeftClickThrough]). Called from -// [ChildView shouldFocusPlugin]. -bool nsCocoaWindow::ShouldFocusPlugin() -{ - if (!mWindow || IsChildInFailingLeftClickThrough([mWindow contentView])) - return false; - - return true; -} - NS_IMETHODIMP nsCocoaWindow::NotifyIME(NotificationToIME aNotification) {
tbb-commits@lists.torproject.org