Bug 583976. Part 1 - Add focus manager support for focus activation/deactivation in remote content. r=enn,smaug
authorFelipe Gomes <felipc@gmail.com>
Fri, 17 Jun 2011 17:08:32 -0700
changeset 72542 238b9a9479ed090b134d80ee8984855ec4746129
parent 72541 258bc8fe5713d89729ba052526876eb0c169710a
child 72543 6759afeead2bef9224fa7774fb7532a41c6bc386
push id20730
push userfelipc@gmail.com
push dateFri, 08 Jul 2011 15:21:37 +0000
treeherdermozilla-central@0e1c0a79effc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersenn, smaug
bugs583976
milestone8.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 583976. Part 1 - Add focus manager support for focus activation/deactivation in remote content. r=enn,smaug
content/base/public/nsIFrameLoader.idl
content/base/src/nsFrameLoader.cpp
dom/base/nsFocusManager.cpp
dom/base/nsFocusManager.h
dom/ipc/PBrowser.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
--- a/content/base/public/nsIFrameLoader.idl
+++ b/content/base/public/nsIFrameLoader.idl
@@ -136,17 +136,17 @@ interface nsIContentViewManager : nsISup
                          [retval, array, size_is(aLength)] out nsIContentView aResult);
 
   /**
    * The root content view.
    */
   readonly attribute nsIContentView rootContentView;
 };
 
-[scriptable, uuid(13c512d6-fba0-402a-9244-fe7941c43965)]
+[scriptable, uuid(12905a29-4246-475a-81d4-fc389197df02)]
 interface nsIFrameLoader : nsISupports
 {
   /**
    * Get the docshell from the frame loader.
    */
   readonly attribute nsIDocShell docShell;
 
   /**
@@ -183,16 +183,22 @@ interface nsIFrameLoader : nsISupports
 
   /**
    * Activate remote frame.
    * Throws an exception with non-remote frames.
    */
   void activateRemoteFrame();
 
   /**
+   * Deactivate remote frame.
+   * Throws an exception with non-remote frames.
+   */
+  void deactivateRemoteFrame();
+
+  /**
    * @see nsIDOMWindowUtils sendMouseEvent.
    */
   void sendCrossProcessMouseEvent(in AString aType,
                                   in float aX,
                                   in float aY,
                                   in long aButton,
                                   in long aClickCount,
                                   in long aModifiers,
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -1767,16 +1767,25 @@ nsFrameLoader::ActivateRemoteFrame() {
   if (mRemoteBrowser) {
     mRemoteBrowser->Activate();
     return NS_OK;
   }
   return NS_ERROR_UNEXPECTED;
 }
 
 NS_IMETHODIMP
+nsFrameLoader::DeactivateRemoteFrame() {
+  if (mRemoteBrowser) {
+    mRemoteBrowser->Deactivate();
+    return NS_OK;
+  }
+  return NS_ERROR_UNEXPECTED;
+}
+
+NS_IMETHODIMP
 nsFrameLoader::SendCrossProcessMouseEvent(const nsAString& aType,
                                           float aX,
                                           float aY,
                                           PRInt32 aButton,
                                           PRInt32 aClickCount,
                                           PRInt32 aModifiers,
                                           PRBool aIgnoreRootScrollFrame)
 {
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -29,16 +29,18 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "mozilla/dom/TabParent.h"
+
 #include "nsFocusManager.h"
 
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIServiceManager.h"
 #include "nsIEnumerator.h"
 #include "nsTPtrArray.h"
 #include "nsGkAtoms.h"
@@ -1526,34 +1528,43 @@ nsFocusManager::Blur(nsPIDOMWindow* aWin
   // Don't fire blur event on the root content which isn't editable.
   PRBool sendBlurEvent =
     content && content->IsInDoc() && !IsNonFocusableRoot(content);
   if (content) {
     if (sendBlurEvent) {
       NotifyFocusStateChange(content, shouldShowFocusRing, PR_FALSE);
     }
 
-    // if an object/plug-in is being blurred, move the system focus to the
-    // parent window, otherwise events will still get fired at the plugin.
+    // 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 && aAdjustWidgets) {
+    if (mActiveWindow) {
       nsIFrame* contentFrame = content->GetPrimaryFrame();
       nsIObjectFrame* objectFrame = do_QueryFrame(contentFrame);
-      if (objectFrame) {
+      if (aAdjustWidgets && objectFrame) {
         // note that the presshell's widget is being retrieved here, not the one
         // for the object frame.
         nsIViewManager* vm = presShell->GetViewManager();
         if (vm) {
           nsCOMPtr<nsIWidget> widget;
           vm->GetRootWidget(getter_AddRefs(widget));
           if (widget)
             widget->SetFocus(PR_FALSE);
         }
       }
+
+      // if the object being blurred is a remote browser, deactivate remote content
+      TabParent* remote = GetRemoteForContent(content);
+      if (remote) {
+        remote->Deactivate();
+  #ifdef DEBUG_FOCUS
+      printf("*Remote browser deactivated\n");
+  #endif
+      }
     }
   }
 
   PRBool result = PR_TRUE;
   if (sendBlurEvent) {
     // if there is an active window, update commands. If there isn't an active
     // window, then this was a blur caused by the active window being lowered,
     // so there is no need to update the commands
@@ -1741,22 +1752,31 @@ nsFocusManager::Focus(nsPIDOMWindow* aWi
     nsPresContext* presContext = presShell->GetPresContext();
     if (sendFocusEvent) {
       // if the focused element changed, scroll it into view
       if (aFocusChanged)
         ScrollIntoView(presShell, aContent, aFlags);
 
       NotifyFocusStateChange(aContent, aWindow->ShouldShowFocusRing(), PR_TRUE);
 
-      // if this is an object/plug-in, focus the plugin's widget.  Note that we might
+      // if this is an object/plug-in/remote browser, focus its widget.  Note that we might
       // no longer be in the same document, due to the events we fired above when
       // aIsNewDocument.
-      if (aAdjustWidgets && presShell->GetDocument() == aContent->GetDocument()) {
-        if (objectFrameWidget)
+      if (presShell->GetDocument() == aContent->GetDocument()) {
+        if (aAdjustWidgets && objectFrameWidget)
           objectFrameWidget->SetFocus(PR_FALSE);
+
+        // if the object being focused is a remote browser, activate remote content
+        TabParent* remote = GetRemoteForContent(aContent);
+        if (remote) {
+          remote->Activate();
+#ifdef DEBUG_FOCUS
+          printf("*Remote browser activated\n");
+#endif
+        }
       }
 
       PRUint32 reason = GetFocusMoveReason(aFlags);
       nsIMEStateManager::OnChangeFocus(presContext, aContent, reason);
 
       // as long as this focus wasn't because a window was raised, update the
       // commands
       // XXXndeakin P2 someone could adjust the focus during the update
@@ -2943,16 +2963,38 @@ nsFocusManager::GetRootForFocus(nsPIDOMW
           return nsnull;
       }
     }
   }
 
   return rootElement;
 }
 
+TabParent*
+nsFocusManager::GetRemoteForContent(nsIContent* aContent) {
+  if (!aContent ||
+      aContent->Tag() != nsGkAtoms::browser ||
+      !aContent->IsXUL() ||
+      !aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote,
+                             nsGkAtoms::_true, eIgnoreCase))
+    return nsnull;
+
+  nsCOMPtr<nsIFrameLoaderOwner> loaderOwner = do_QueryInterface(aContent);
+  if (!loaderOwner)
+    return nsnull;
+
+  nsRefPtr<nsFrameLoader> frameLoader = loaderOwner->GetFrameLoader();
+  if (!frameLoader)
+    return nsnull;
+
+  PBrowserParent* remoteBrowser = frameLoader->GetRemoteBrowser();
+  TabParent* remote = static_cast<TabParent*>(remoteBrowser);
+  return remote;
+}
+
 void
 nsFocusManager::GetLastDocShell(nsIDocShellTreeItem* aItem,
                                 nsIDocShellTreeItem** aResult)
 {
   *aResult = nsnull;
 
   nsCOMPtr<nsIDocShellTreeItem> curItem = aItem;
   while (curItem) {
--- a/dom/base/nsFocusManager.h
+++ b/dom/base/nsFocusManager.h
@@ -44,16 +44,23 @@
 
 #define FOCUSMETHOD_MASK 0xF000
 #define FOCUSMETHODANDRING_MASK 0xF0F000
 
 #define FOCUSMANAGER_CONTRACTID "@mozilla.org/focus-manager;1"
 
 class nsIDocShellTreeItem;
 class nsPIDOMWindow;
+
+namespace mozilla {
+namespace dom {
+  class TabParent;
+}
+}
+
 struct nsDelayedBlurOrFocusEvent;
 
 /**
  * The focus manager keeps track of where the focus is, that is, the node
  * which receives key events.
  */
 
 class nsFocusManager : public nsIFocusManager,
@@ -420,16 +427,22 @@ protected:
    * - if aDocument is a frameset document.
    */
   nsIContent* GetRootForFocus(nsPIDOMWindow* aWindow,
                               nsIDocument* aDocument,
                               PRBool aIsForDocNavigation,
                               PRBool aCheckVisibility);
 
   /**
+   * Get the TabParent associated with aContent if it is a remote browser,
+   * or null in all other cases.
+   */
+  mozilla::dom::TabParent* GetRemoteForContent(nsIContent* aContent);
+
+  /**
    * Get the last docshell child of aItem and return it in aResult.
    */
   void GetLastDocShell(nsIDocShellTreeItem* aItem,
                        nsIDocShellTreeItem** aResult);
 
   /**
    * Get the next docshell child of aItem and return it in aResult.
    */
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -236,16 +236,18 @@ child:
 
     Move(nsIntSize size);
 
     /**
      * Sending an activate message moves focus to the child.
      */
     Activate();
 
+    Deactivate();
+
     /**
      * @see nsIDOMWindowUtils sendMouseEvent.
      */
     MouseEvent(nsString aType,
                float aX,
                float aY,
                PRInt32 aButton,
                PRInt32 aClickCount,
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -551,16 +551,23 @@ TabChild::RecvMove(const nsIntSize& size
 bool
 TabChild::RecvActivate()
 {
   nsCOMPtr<nsIWebBrowserFocus> browser = do_QueryInterface(mWebNav);
   browser->Activate();
   return true;
 }
 
+bool TabChild::RecvDeactivate()
+{
+  nsCOMPtr<nsIWebBrowserFocus> browser = do_QueryInterface(mWebNav);
+  browser->Deactivate();
+  return true;
+}
+
 bool
 TabChild::RecvMouseEvent(const nsString& aType,
                          const float&    aX,
                          const float&    aY,
                          const PRInt32&  aButton,
                          const PRInt32&  aClickCount,
                          const PRInt32&  aModifiers,
                          const bool&     aIgnoreRootScrollFrame)
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -175,16 +175,17 @@ public:
     NS_DECL_NSIINTERFACEREQUESTOR
     NS_DECL_NSIWINDOWPROVIDER
     NS_DECL_NSIDIALOGCREATOR
 
     virtual bool RecvLoadURL(const nsCString& uri);
     virtual bool RecvShow(const nsIntSize& size);
     virtual bool RecvMove(const nsIntSize& size);
     virtual bool RecvActivate();
+    virtual bool RecvDeactivate();
     virtual bool RecvMouseEvent(const nsString& aType,
                                 const float&    aX,
                                 const float&    aY,
                                 const PRInt32&  aButton,
                                 const PRInt32&  aClickCount,
                                 const PRInt32&  aModifiers,
                                 const bool&     aIgnoreRootScrollFrame);
     virtual bool RecvKeyEvent(const nsString& aType,
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -214,16 +214,22 @@ TabParent::Move(const nsIntSize& size)
 }
 
 void
 TabParent::Activate()
 {
     unused << SendActivate();
 }
 
+void
+TabParent::Deactivate()
+{
+  unused << SendDeactivate();
+}
+
 NS_IMETHODIMP
 TabParent::Init(nsIDOMWindow *window)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TabParent::GetState(PRUint32 *aState)
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -122,16 +122,17 @@ public:
 
     void LoadURL(nsIURI* aURI);
     // XXX/cjones: it's not clear what we gain by hiding these
     // message-sending functions under a layer of indirection and
     // eating the return values
     void Show(const nsIntSize& size);
     void Move(const nsIntSize& size);
     void Activate();
+    void Deactivate();
     void SendMouseEvent(const nsAString& aType, float aX, float aY,
                         PRInt32 aButton, PRInt32 aClickCount,
                         PRInt32 aModifiers, PRBool aIgnoreRootScrollFrame);
     void SendKeyEvent(const nsAString& aType, PRInt32 aKeyCode,
                       PRInt32 aCharCode, PRInt32 aModifiers,
                       PRBool aPreventDefault);
 
     virtual PDocumentRendererParent*