commit 1b9259cf6ad5f15be9f3ae54e54205743bab6bc1 Author: Ryan VanderMeulen ryanvm@gmail.com Date: Mon Jun 9 14:42:40 2014 -0400
Backed out changeset 6402fb9a21cb (bug 995603) for causing bug 1021815. a=abillings --- content/events/src/nsContentEventHandler.cpp | 25 ++------ content/events/src/nsContentEventHandler.h | 2 +- widget/cocoa/nsChildView.mm | 79 +++++++++++++++++--------- widget/cocoa/nsCocoaWindow.h | 3 + widget/cocoa/nsCocoaWindow.mm | 30 ++++++++++ 5 files changed, 93 insertions(+), 46 deletions(-)
diff --git a/content/events/src/nsContentEventHandler.cpp b/content/events/src/nsContentEventHandler.cpp index e989535..8b151cb 100644 --- a/content/events/src/nsContentEventHandler.cpp +++ b/content/events/src/nsContentEventHandler.cpp @@ -44,8 +44,11 @@ nsContentEventHandler::nsContentEventHandler( }
nsresult -nsContentEventHandler::InitBasic() +nsContentEventHandler::InitCommon() { + if (mSelection) + return NS_OK; + NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
// If text frame which has overflowing selection underline is dirty, @@ -55,24 +58,11 @@ nsContentEventHandler::InitBasic() // Flushing notifications can cause mPresShell to be destroyed (bug 577963). NS_ENSURE_TRUE(!mPresShell->IsDestroying(), NS_ERROR_FAILURE);
- return NS_OK; -} - -nsresult -nsContentEventHandler::InitCommon() -{ - if (mSelection) { - return NS_OK; - } - - nsresult rv = InitBasic(); - NS_ENSURE_SUCCESS(rv, rv); - nsCopySupport::GetSelectionForCopy(mPresShell->GetDocument(), getter_AddRefs(mSelection));
nsCOMPtr<nsIDOMRange> firstRange; - rv = mSelection->GetRangeAt(0, getter_AddRefs(firstRange)); + nsresult rv = mSelection->GetRangeAt(0, getter_AddRefs(firstRange)); // This shell doesn't support selection. if (NS_FAILED(rv)) return NS_ERROR_NOT_AVAILABLE; @@ -870,13 +860,10 @@ nsContentEventHandler::OnQueryCharacterAtPoint(nsQueryContentEvent* aEvent) nsresult nsContentEventHandler::OnQueryDOMWidgetHittest(nsQueryContentEvent* aEvent) { - NS_ASSERTION(aEvent, "aEvent must not be null"); - - nsresult rv = InitBasic(); + nsresult rv = Init(aEvent); 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 1624d35..4c4f492 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);
- nsresult InitBasic(); + // InitCommon() is called from each Init(). nsresult InitCommon();
public: diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index 6ced313..aef01c7 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -2790,32 +2790,6 @@ 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]; - cocoaLoc.y = nsCocoaUtils::FlippedScreenY(cocoaLoc.y); - nsIntPoint widgetLoc = mGeckoChild->CocoaPointsToDevPixels(cocoaLoc) - - mGeckoChild->WidgetToScreenOffset(); - - nsQueryContentEvent 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 @@ -4939,12 +4913,65 @@ 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 dc5994671..ac434e0 100644 --- a/widget/cocoa/nsCocoaWindow.h +++ b/widget/cocoa/nsCocoaWindow.h @@ -316,6 +316,9 @@ 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 b435155..b95c072 100644 --- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -2051,6 +2051,36 @@ 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) {