commit 94b845556474e198effe7a2d6fe7e1bc0bd1f729
Author: Steven Michaud <smichaud(a)pobox.com>
Date: Wed Jun 18 11:13:35 2014 -0500
Bug 995603 - Ensure mouse-enter/exit events are sent to plugins as appropriate. r=mstange a=abillings
---
content/events/src/nsContentEventHandler.cpp | 25 ++++++--
content/events/src/nsContentEventHandler.h | 2 +-
widget/cocoa/nsChildView.mm | 81 +++++++++-----------------
widget/cocoa/nsCocoaWindow.h | 3 -
widget/cocoa/nsCocoaWindow.mm | 30 ----------
5 files changed, 48 insertions(+), 93 deletions(-)
diff --git a/content/events/src/nsContentEventHandler.cpp b/content/events/src/nsContentEventHandler.cpp
index 8b151cb..e989535 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
+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;
- 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..9d99be9 100644
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -2790,6 +2790,34 @@ NSEvent* gLastDragMouseDownEvent = nil;
return mIsPluginView;
}
+- (NSView *)hitTest:(NSPoint)aPoint
+{
+ NSView* target = [super hitTest:aPoint];
+ NSWindow *window = [self window];
+ if (window && (target == self) && [self isPluginView] && mGeckoChild) {
+ nsAutoRetainCocoaObject kungFuDeathGrip(self);
+
+ NSPoint windowLoc = [[self superview] convertPoint:aPoint toView:nil];
+ NSPoint screenLoc = [window convertBaseToScreen:windowLoc];
+ screenLoc.y = nsCocoaUtils::FlippedScreenY(screenLoc.y);
+ nsIntPoint widgetLoc = mGeckoChild->CocoaPointsToDevPixels(screenLoc) -
+ 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
@@ -4913,65 +4941,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)
{