Bug 1152300 - When focus shifts from a native plugin window to content, content needs to forward the request for focus change to chrome. r=enn
authorJim Mathies <jmathies@mozilla.com>
Thu, 09 Jul 2015 09:48:57 -0500
changeset 252224 4ba02f888904f05199d21e73f8b174f53bb5e119
parent 252223 1610d8749d37632fe561667044d1554e45cdda72
child 252225 ff0b2f8117cb19b661dc88e1b4b5958658a004d8
push id29028
push usercbook@mozilla.com
push dateFri, 10 Jul 2015 10:18:05 +0000
treeherdermozilla-central@f7e1f596d57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersenn
bugs1152300
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1152300 - When focus shifts from a native plugin window to content, content needs to forward the request for focus change to chrome. r=enn
dom/base/nsFocusManager.cpp
dom/ipc/PBrowser.ipdl
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -1624,24 +1624,34 @@ nsFocusManager::Blur(nsPIDOMWindow* aWin
     // if an object/plug-in/remote browser is being blurred, move the system focus
     // to the parent window, otherwise events will still get fired at the plugin.
     // But don't do this if we are blurring due to the window being lowered,
     // otherwise, the parent window can get raised again.
     if (mActiveWindow) {
       nsIFrame* contentFrame = content->GetPrimaryFrame();
       nsIObjectFrame* objectFrame = do_QueryFrame(contentFrame);
       if (aAdjustWidgets && objectFrame && !sTestMode) {
-        // note that the presshell's widget is being retrieved here, not the one
-        // for the object frame.
-        nsViewManager* vm = presShell->GetViewManager();
-        if (vm) {
-          nsCOMPtr<nsIWidget> widget;
-          vm->GetRootWidget(getter_AddRefs(widget));
-          if (widget)
-            widget->SetFocus(false);
+        if (XRE_IsContentProcess()) {
+          // set focus to the top level window via the chrome process.
+          nsCOMPtr<nsITabChild> tabChild = do_GetInterface(docShell);
+          if (tabChild) {
+            static_cast<TabChild*>(tabChild.get())->SendDispatchFocusToTopLevelWindow();
+          }
+        } else {
+          // note that the presshell's widget is being retrieved here, not the one
+          // for the object frame.
+          nsViewManager* vm = presShell->GetViewManager();
+          if (vm) {
+            nsCOMPtr<nsIWidget> widget;
+            vm->GetRootWidget(getter_AddRefs(widget));
+            if (widget) {
+              // set focus to the top level window but don't raise it.
+              widget->SetFocus(false);
+            }
+          }
         }
       }
     }
 
       // if the object being blurred is a remote browser, deactivate remote content
     if (TabParent* remote = TabParent::GetFrom(content)) {
       remote->Deactivate();
       LOGFOCUS(("Remote browser deactivated"));
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -135,16 +135,23 @@ parent:
      */
     sync PPluginWidget();
 
     /**
      * Return native data of root widget
      */
     sync GetWidgetNativeData() returns (WindowsHandle value);
 
+    /**
+     * When content moves focus from a native plugin window that's a child
+     * of the native browser window we need to move native focus to the
+     * browser. Otherwise the plugin window will never relinquish focus.
+     */
+    sync DispatchFocusToTopLevelWindow();
+
 parent:
     /**
      * When child sends this message, parent should move focus to
      * the next or previous focusable element.
      */
     MoveFocus(bool forward);
 
     Event(RemoteDOMEvent aEvent);
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -2468,33 +2468,51 @@ TabParent::RecvGetMaxTouchPoints(uint32_
   if (widget) {
     *aTouchPoints = widget->GetMaxTouchPoints();
   } else {
     *aTouchPoints = 0;
   }
   return true;
 }
 
-bool
-TabParent::RecvGetWidgetNativeData(WindowsHandle* aValue)
+already_AddRefed<nsIWidget>
+TabParent::GetTopLevelWidget()
 {
-  *aValue = 0;
   nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
   if (content) {
     nsIPresShell* shell = content->OwnerDoc()->GetShell();
     if (shell) {
       nsViewManager* vm = shell->GetViewManager();
       nsCOMPtr<nsIWidget> widget;
       vm->GetRootWidget(getter_AddRefs(widget));
-      if (widget) {
-        *aValue = reinterpret_cast<WindowsHandle>(
-          widget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW));
-      }
+      return widget.forget();
     }
   }
+  return nullptr;
+}
+
+bool
+TabParent::RecvGetWidgetNativeData(WindowsHandle* aValue)
+{
+  *aValue = 0;
+  nsCOMPtr<nsIWidget> widget = GetTopLevelWidget();
+  if (widget) {
+    *aValue = reinterpret_cast<WindowsHandle>(
+      widget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW));
+  }
+  return true;
+}
+
+bool
+TabParent::RecvDispatchFocusToTopLevelWindow()
+{
+  nsCOMPtr<nsIWidget> widget = GetTopLevelWidget();
+  if (widget) {
+    widget->SetFocus(false);
+  }
   return true;
 }
 
 bool
 TabParent::ReceiveMessage(const nsString& aMessage,
                           bool aSync,
                           const StructuredCloneData* aCloneData,
                           CpowHolder* aCpows,
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -111,17 +111,17 @@ public:
     bool IsVisible();
 
     nsIBrowserDOMWindow *GetBrowserDOMWindow() { return mBrowserDOMWindow; }
     void SetBrowserDOMWindow(nsIBrowserDOMWindow* aBrowserDOMWindow) {
         mBrowserDOMWindow = aBrowserDOMWindow;
     }
 
     already_AddRefed<nsILoadContext> GetLoadContext();
-
+    already_AddRefed<nsIWidget> GetTopLevelWidget();
     nsIXULBrowserWindow* GetXULBrowserWindow();
 
     void Destroy();
 
     void RemoveWindowListeners();
     void AddWindowListeners();
     void DidRefresh() override;
 
@@ -213,16 +213,17 @@ public:
     virtual bool RecvIsParentWindowMainWidgetVisible(bool* aIsVisible) override;
     virtual bool RecvShowTooltip(const uint32_t& aX, const uint32_t& aY, const nsString& aTooltip) override;
     virtual bool RecvHideTooltip() override;
     virtual bool RecvGetTabOffset(LayoutDeviceIntPoint* aPoint) override;
     virtual bool RecvGetDPI(float* aValue) override;
     virtual bool RecvGetDefaultScale(double* aValue) override;
     virtual bool RecvGetMaxTouchPoints(uint32_t* aTouchPoints) override;
     virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue) override;
+    virtual bool RecvDispatchFocusToTopLevelWindow() override;
     virtual bool RecvZoomToRect(const uint32_t& aPresShellId,
                                 const ViewID& aViewId,
                                 const CSSRect& aRect) override;
     virtual bool RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
                                            const ViewID& aViewId,
                                            const MaybeZoomConstraints& aConstraints) override;
     virtual bool RecvContentReceivedInputBlock(const ScrollableLayerGuid& aGuid,
                                                const uint64_t& aInputBlockId,