Bug 410337. Pass the parent window further down the window creation path so that its screen rect can be saved in nsXULWindow and used to determine what screen to open on in some cases. r=enndeakin
authorTimothy Nikkel <tnikkel@gmail.com>
Mon, 28 Sep 2009 21:20:46 -0500
changeset 33261 1deff8db43525a0d0caefaa9e23bec7922e349ae
parent 33260 790211c5a8ddbc5c34e4728e1745520a93946d7b
child 33262 2c6aeb49c93cf5aec2f0fd77a71fc0168861dd71
push idunknown
push userunknown
push dateunknown
reviewersenndeakin
bugs410337
milestone1.9.3a1pre
Bug 410337. Pass the parent window further down the window creation path so that its screen rect can be saved in nsXULWindow and used to determine what screen to open on in some cases. r=enndeakin
layout/base/tests/test_bug518777.html
xpfe/appshell/public/nsIXULWindow.idl
xpfe/appshell/src/nsAppShellService.cpp
xpfe/appshell/src/nsWebShellWindow.cpp
xpfe/appshell/src/nsWebShellWindow.h
xpfe/appshell/src/nsXULWindow.cpp
xpfe/appshell/src/nsXULWindow.h
--- a/xpfe/appshell/public/nsIXULWindow.idl
+++ b/xpfe/appshell/public/nsIXULWindow.idl
@@ -93,22 +93,25 @@ interface nsIXULWindow : nsISupports
   /**
    * Tell this window that it has lost a child XUL window
    * @param aChild the child window being removed
    */
   void removeChildWindow(in nsIXULWindow aChild);
 
   /**
    * Move the window to a centered position.
-   * @param aRelative the window relative to which the window is moved.
-   *                  See screen parameter for details. if null, the
-   *                  window is centered relative to the main screen.
+   * @param aRelative If not null, the window relative to which the window is
+   *                  moved. See aScreen parameter for details.
    * @param aScreen   PR_TRUE to center the window relative to the screen
-   *                  containing aRelative. PR_FALSE to center it relative
-   *                  to aRelative itself.
+   *                  containing aRelative if aRelative is not null. If
+   *                  aRelative is null then relative to the screen of the
+   *                  opener window if it was initialized by passing it to
+   *                  nsWebShellWindow::Initialize. Failing that relative to
+   *                  the main screen.
+   *                  PR_FALSE to center it relative to aRelative itself.
    * @param aAlert    PR_TRUE to move the window to an alert position,
    *                  generally centered horizontally and 1/3 down from the top.
    */
   void center(in nsIXULWindow aRelative, in boolean aScreen, in boolean aAlert);
 
   /**
    * Shows the window as a modal window. That is, ensures that it is visible
    * and runs a local event loop, exiting only once the window has been closed.
--- a/xpfe/appshell/src/nsAppShellService.cpp
+++ b/xpfe/appshell/src/nsAppShellService.cpp
@@ -233,17 +233,20 @@ nsAppShellService::CreateTopLevelWindow(
                            aChromeMask, aInitialWidth, aInitialHeight,
                            PR_FALSE, aAppShell, &newWindow);  // addrefs
 
   *aResult = newWindow; // transfer ref
 
   if (NS_SUCCEEDED(rv)) {
     // the addref resulting from this is the owning addref for this window
     RegisterTopLevelWindow(*aResult);
-    (*aResult)->SetZLevel(CalculateWindowZLevel(aParent, aChromeMask));
+    nsCOMPtr<nsIXULWindow> parent;
+    if (aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT)
+      parent = aParent;
+    (*aResult)->SetZLevel(CalculateWindowZLevel(parent, aChromeMask));
   }
 
   return rv;
 }
 
 PRUint32
 nsAppShellService::CalculateWindowZLevel(nsIXULWindow *aParent,
                                          PRUint32      aChromeMask)
@@ -290,16 +293,20 @@ nsAppShellService::JustCreateTopWindow(n
                                        PRInt32 aInitialWidth,
                                        PRInt32 aInitialHeight,
                                        PRBool aIsHiddenWindow,
                                        nsIAppShell* aAppShell,
                                        nsWebShellWindow **aResult)
 {
   *aResult = nsnull;
 
+  nsCOMPtr<nsIXULWindow> parent;
+  if (aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT)
+    parent = aParent;
+
   nsRefPtr<nsWebShellWindow> window = new nsWebShellWindow(aChromeMask);
   NS_ENSURE_TRUE(window, NS_ERROR_OUT_OF_MEMORY);
 
   nsWidgetInitData widgetInitData;
 
   if (aIsHiddenWindow)
     widgetInitData.mWindowType = eWindowType_invisible;
   else
@@ -314,17 +321,17 @@ nsAppShellService::JustCreateTopWindow(n
   // Adding CHROME_OPENAS_CHROME to sheetMask makes modal windows opened from
   // nsGlobalWindow::ShowModalDialog() be dialogs (not sheets), while modal
   // windows opened from nsPromptService::DoDialog() still are sheets.  This
   // fixes bmo bug 395465 (see nsCocoaWindow::StandardCreate() and
   // nsCocoaWindow::SetModal()).
   PRUint32 sheetMask = nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
                        nsIWebBrowserChrome::CHROME_MODAL |
                        nsIWebBrowserChrome::CHROME_OPENAS_CHROME;
-  if (aParent && ((aChromeMask & sheetMask) == sheetMask))
+  if (parent && ((aChromeMask & sheetMask) == sheetMask))
     widgetInitData.mWindowType = eWindowType_sheet;
 #endif
 
   widgetInitData.mContentType = eContentTypeUI;                
 
   // note default chrome overrides other OS chrome settings, but
   // not internal chrome
   if (aChromeMask & nsIWebBrowserChrome::CHROME_DEFAULT)
@@ -356,28 +363,31 @@ nsAppShellService::JustCreateTopWindow(n
 
   if (aInitialWidth == nsIAppShellService::SIZE_TO_CONTENT ||
       aInitialHeight == nsIAppShellService::SIZE_TO_CONTENT) {
     aInitialWidth = 1;
     aInitialHeight = 1;
     window->SetIntrinsicallySized(PR_TRUE);
   }
 
-  nsresult rv = window->Initialize(aParent, aAppShell, aUrl,
+  PRBool center = aChromeMask & nsIWebBrowserChrome::CHROME_CENTER_SCREEN;
+
+  nsresult rv = window->Initialize(parent, center ? aParent : nsnull,
+                                   aAppShell, aUrl,
                                    aInitialWidth, aInitialHeight,
                                    aIsHiddenWindow, widgetInitData);
       
   NS_ENSURE_SUCCESS(rv, rv);
 
   window.swap(*aResult); // transfer reference
-  if (aParent)
-    aParent->AddChildWindow(*aResult);
+  if (parent)
+    parent->AddChildWindow(*aResult);
 
-  if (aChromeMask & nsIWebBrowserChrome::CHROME_CENTER_SCREEN)
-    rv = (*aResult)->Center(aParent, aParent ? PR_FALSE : PR_TRUE, PR_FALSE);
+  if (center)
+    rv = (*aResult)->Center(parent, parent ? PR_FALSE : PR_TRUE, PR_FALSE);
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsAppShellService::GetHiddenWindow(nsIXULWindow **aWindow)
 {
   NS_ENSURE_ARG_POINTER(aWindow);
--- a/xpfe/appshell/src/nsWebShellWindow.cpp
+++ b/xpfe/appshell/src/nsWebShellWindow.cpp
@@ -145,27 +145,39 @@ nsWebShellWindow::~nsWebShellWindow()
 NS_IMPL_ADDREF_INHERITED(nsWebShellWindow, nsXULWindow)
 NS_IMPL_RELEASE_INHERITED(nsWebShellWindow, nsXULWindow)
 
 NS_INTERFACE_MAP_BEGIN(nsWebShellWindow)
   NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
 NS_INTERFACE_MAP_END_INHERITING(nsXULWindow)
 
 nsresult nsWebShellWindow::Initialize(nsIXULWindow* aParent,
-                                      nsIAppShell* aShell, nsIURI* aUrl, 
+                                      nsIXULWindow* aOpener,
+                                      nsIAppShell* aShell, nsIURI* aUrl,
                                       PRInt32 aInitialWidth,
                                       PRInt32 aInitialHeight,
                                       PRBool aIsHiddenWindow,
                                       nsWidgetInitData& widgetInitData)
 {
   nsresult rv;
   nsCOMPtr<nsIWidget> parentWidget;
 
   mIsHiddenWindow = aIsHiddenWindow;
-  
+
+  nsCOMPtr<nsIBaseWindow> base(do_QueryInterface(aOpener));
+  if (base) {
+    rv = base->GetPositionAndSize(&mOpenerScreenRect.x,
+                                  &mOpenerScreenRect.y,
+                                  &mOpenerScreenRect.width,
+                                  &mOpenerScreenRect.height);
+    if (NS_FAILED(rv)) {
+      mOpenerScreenRect.Empty();
+    }
+  }
+
   // XXX: need to get the default window size from prefs...
   // Doesn't come from prefs... will come from CSS/XUL/RDF
   nsIntRect r(0, 0, aInitialWidth, aInitialHeight);
   
   // Create top level window
   mWindow = do_CreateInstance(kWindowCID, &rv);
   if (NS_OK != rv) {
     return rv;
--- a/xpfe/appshell/src/nsWebShellWindow.h
+++ b/xpfe/appshell/src/nsWebShellWindow.h
@@ -57,18 +57,18 @@ class nsWebShellWindow : public nsXULWin
 {
 public:
   nsWebShellWindow(PRUint32 aChromeFlags);
 
   // nsISupports interface...
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsWebShellWindow methods...
-  nsresult Initialize(nsIXULWindow * aParent, nsIAppShell* aShell,
-                      nsIURI* aUrl,
+  nsresult Initialize(nsIXULWindow * aParent, nsIXULWindow * aOpener,
+                      nsIAppShell* aShell, nsIURI* aUrl,
                       PRInt32 aInitialWidth, PRInt32 aInitialHeight,
                       PRBool aIsHiddenWindow,
                       nsWidgetInitData& widgetInitData);
 
   nsresult Toolbar();
 
   // nsIWebProgressListener
   NS_DECL_NSIWEBPROGRESSLISTENER
--- a/xpfe/appshell/src/nsXULWindow.cpp
+++ b/xpfe/appshell/src/nsXULWindow.cpp
@@ -680,18 +680,25 @@ NS_IMETHODIMP nsXULWindow::Center(nsIXUL
       } else {
         // something's wrong with the reference window.
         // fall back to the primary screen
         aRelative = 0;
         aScreen = PR_TRUE;
       }
     }
   }
-  if (!aRelative)
-    screenmgr->GetPrimaryScreen(getter_AddRefs(screen));
+  if (!aRelative) {
+    if (!mOpenerScreenRect.IsEmpty()) {
+      screenmgr->ScreenForRect(mOpenerScreenRect.x, mOpenerScreenRect.y,
+                               mOpenerScreenRect.width, mOpenerScreenRect.height,
+                               getter_AddRefs(screen));
+    } else {
+      screenmgr->GetPrimaryScreen(getter_AddRefs(screen));
+    }
+  }
 
   if (aScreen && screen) {
     screen->GetAvailRect(&left, &top, &width, &height);
     screenCoordinates = PR_TRUE;
   }
 
   if (screenCoordinates || windowCoordinates) {
     GetSize(&ourWidth, &ourHeight);
@@ -1686,23 +1693,19 @@ NS_IMETHODIMP nsXULWindow::CreateNewWind
 NS_IMETHODIMP nsXULWindow::CreateNewChromeWindow(PRInt32 aChromeFlags,
    nsIAppShell* aAppShell, nsIXULWindow **_retval)
 {
   NS_TIMELINE_ENTER("nsXULWindow::CreateNewChromeWindow");
   nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
   NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
 
   // Just do a normal create of a window and return.
-  //XXXTAB remove this when appshell talks in terms of nsIXULWindow
-  nsCOMPtr<nsIXULWindow> parent;
-  if (aChromeFlags & nsIWebBrowserChrome::CHROME_DEPENDENT)
-    parent = this;
 
   nsCOMPtr<nsIXULWindow> newWindow;
-  appShell->CreateTopLevelWindow(parent, nsnull, aChromeFlags,
+  appShell->CreateTopLevelWindow(this, nsnull, aChromeFlags,
                                  nsIAppShellService::SIZE_TO_CONTENT,
                                  nsIAppShellService::SIZE_TO_CONTENT,
                                  aAppShell, getter_AddRefs(newWindow));
 
   NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE);
 
   *_retval = newWindow;
   NS_ADDREF(*_retval);
@@ -1714,20 +1717,16 @@ NS_IMETHODIMP nsXULWindow::CreateNewChro
 NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(PRInt32 aChromeFlags,
    nsIAppShell* aAppShell, nsIXULWindow **_retval)
 {
   NS_TIMELINE_ENTER("nsXULWindow::CreateNewContentWindow");
 
   nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
   NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
 
-  nsCOMPtr<nsIXULWindow> parent;
-  if (aChromeFlags & nsIWebBrowserChrome::CHROME_DEPENDENT)
-    parent = this;
-
   // We need to create a new top level window and then enter a nested
   // loop. Eventually the new window will be told that it has loaded,
   // at which time we know it is safe to spin out of the nested loop
   // and allow the opening code to proceed.
 
   nsCOMPtr<nsIURI> uri;
 
   nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
@@ -1742,19 +1741,19 @@ NS_IMETHODIMP nsXULWindow::CreateNewCont
 
     nsCOMPtr<nsIIOService> service(do_GetService(NS_IOSERVICE_CONTRACTID));
     if (service)
       service->NewURI(urlStr, nsnull, nsnull, getter_AddRefs(uri));
   }
   NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIXULWindow> newWindow;
-  appShell->CreateTopLevelWindow(parent, uri,
-                                aChromeFlags, 615, 480, aAppShell,
-                                getter_AddRefs(newWindow));
+  appShell->CreateTopLevelWindow(this, uri,
+                                 aChromeFlags, 615, 480, aAppShell,
+                                 getter_AddRefs(newWindow));
 
   NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE);
 
   // Specify that we want the window to remain locked until the chrome has loaded.
   nsXULWindow *xulWin = static_cast<nsXULWindow*>
                                    (static_cast<nsIXULWindow*>
                                                (newWindow));
 
--- a/xpfe/appshell/src/nsXULWindow.h
+++ b/xpfe/appshell/src/nsXULWindow.h
@@ -63,21 +63,21 @@
 #include "nsIAuthPrompt.h"
 #include "nsGUIEvent.h"
 #include "nsIXULBrowserWindow.h"
 #include "nsIWeakReference.h"
 
 // nsXULWindow
 
 #define NS_XULWINDOW_IMPL_CID                         \
-{ /* 2a38ef7e-3174-44ad-a785-b5a863cf5588 */          \
-     0x2a38ef7e,                                      \
-     0x3174,                                          \
-     0x44ad,                                          \
-   { 0xa7, 0x85, 0xb5, 0xa8, 0x63, 0xcf, 0x55, 0x88 } \
+{ /* 8eaec2f3-ed02-4be2-8e0f-342798477298 */          \
+     0x8eaec2f3,                                      \
+     0xed02,                                          \
+     0x4be2,                                          \
+   { 0x8e, 0x0f, 0x34, 0x27, 0x98, 0x47, 0x72, 0x98 } \
 }
 
 class nsContentShellInfo;
 
 class nsXULWindow : public nsIBaseWindow,
                     public nsIInterfaceRequestor,
                     public nsIXULWindow,
                     public nsSupportsWeakReference
@@ -172,16 +172,17 @@ protected:
    PRUint32                mContextFlags;
    PRUint32                mBlurSuppressionLevel;
    PRUint32                mPersistentAttributesDirty; // persistentAttributes
    PRUint32                mPersistentAttributesMask;
    PRUint32                mChromeFlags;
    PRUint32                mAppPerDev; // sometimes needed when we can't get
                                        // it from the widget
    nsString                mTitle;
+   nsIntRect               mOpenerScreenRect; // the screen rect of the opener
 
    nsCOMArray<nsIWeakReference> mTargetableShells; // targetable shells only
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsXULWindow, NS_XULWINDOW_IMPL_CID)
 
 // nsContentShellInfo
 // Used to map shell IDs to nsIDocShellTreeItems.