xpfe/appshell/src/nsXULWindow.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim:set ts=2 sw=2 sts=2 ci et: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "mozilla/MathAlgorithms.h"
     9 // Local includes
    10 #include "nsXULWindow.h"
    11 #include <algorithm>
    13 // Helper classes
    14 #include "nsPrintfCString.h"
    15 #include "nsString.h"
    16 #include "nsWidgetsCID.h"
    17 #include "prprf.h"
    18 #include "nsCRT.h"
    19 #include "nsThreadUtils.h"
    20 #include "nsNetCID.h"
    22 //Interfaces needed to be included
    23 #include "nsIAppShell.h"
    24 #include "nsIAppShellService.h"
    25 #include "nsIServiceManager.h"
    26 #include "nsIContentViewer.h"
    27 #include "nsIDocument.h"
    28 #include "nsIDOMDocument.h"
    29 #include "nsIDOMXULDocument.h"
    30 #include "nsIDOMElement.h"
    31 #include "nsIDOMXULElement.h"
    32 #include "nsPIDOMWindow.h"
    33 #include "nsIDOMScreen.h"
    34 #include "nsIEmbeddingSiteWindow.h"
    35 #include "nsIInterfaceRequestor.h"
    36 #include "nsIInterfaceRequestorUtils.h"
    37 #include "nsIIOService.h"
    38 #include "nsIMarkupDocumentViewer.h"
    39 #include "nsIObserverService.h"
    40 #include "nsIWindowMediator.h"
    41 #include "nsIScreenManager.h"
    42 #include "nsIScreen.h"
    43 #include "nsIScrollable.h"
    44 #include "nsIScriptSecurityManager.h"
    45 #include "nsIWindowWatcher.h"
    46 #include "nsIURI.h"
    47 #include "nsIDOMCSSStyleDeclaration.h"
    48 #include "nsAppShellCID.h"
    49 #include "nsReadableUtils.h"
    50 #include "nsStyleConsts.h"
    51 #include "nsPresContext.h"
    52 #include "nsContentUtils.h"
    53 #include "nsWebShellWindow.h" // get rid of this one, too...
    54 #include "nsGlobalWindow.h"
    56 #include "prenv.h"
    57 #include "mozilla/AutoRestore.h"
    58 #include "mozilla/Preferences.h"
    59 #include "mozilla/dom/BarProps.h"
    60 #include "mozilla/dom/Element.h"
    61 #include "mozilla/dom/Event.h"
    62 #include "mozilla/dom/ScriptSettings.h"
    64 using namespace mozilla;
    65 using dom::AutoNoJSAPI;
    67 #define SIZEMODE_NORMAL     NS_LITERAL_STRING("normal")
    68 #define SIZEMODE_MAXIMIZED  NS_LITERAL_STRING("maximized")
    69 #define SIZEMODE_MINIMIZED  NS_LITERAL_STRING("minimized")
    70 #define SIZEMODE_FULLSCREEN NS_LITERAL_STRING("fullscreen")
    72 #define WINDOWTYPE_ATTRIBUTE NS_LITERAL_STRING("windowtype")
    74 #define PERSIST_ATTRIBUTE  NS_LITERAL_STRING("persist")
    75 #define SCREENX_ATTRIBUTE  NS_LITERAL_STRING("screenX")
    76 #define SCREENY_ATTRIBUTE  NS_LITERAL_STRING("screenY")
    77 #define WIDTH_ATTRIBUTE    NS_LITERAL_STRING("width")
    78 #define HEIGHT_ATTRIBUTE   NS_LITERAL_STRING("height")
    79 #define MODE_ATTRIBUTE     NS_LITERAL_STRING("sizemode")
    80 #define ZLEVEL_ATTRIBUTE   NS_LITERAL_STRING("zlevel")
    83 //*****************************************************************************
    84 //***    nsXULWindow: Object Management
    85 //*****************************************************************************
    87 nsXULWindow::nsXULWindow(uint32_t aChromeFlags)
    88   : mChromeTreeOwner(nullptr), 
    89     mContentTreeOwner(nullptr),
    90     mPrimaryContentTreeOwner(nullptr),
    91     mModalStatus(NS_OK),
    92     mContinueModalLoop(false),
    93     mDebuting(false),
    94     mChromeLoaded(false), 
    95     mShowAfterLoad(false),
    96     mIntrinsicallySized(false),
    97     mCenterAfterLoad(false),
    98     mIsHiddenWindow(false),
    99     mLockedUntilChromeLoad(false),
   100     mIgnoreXULSize(false),
   101     mIgnoreXULPosition(false),
   102     mChromeFlagsFrozen(false),
   103     mIgnoreXULSizeMode(false),
   104     mDestroying(false),
   105     mContextFlags(0),
   106     mPersistentAttributesDirty(0),
   107     mPersistentAttributesMask(0),
   108     mChromeFlags(aChromeFlags)
   109 {
   110 }
   112 nsXULWindow::~nsXULWindow()
   113 {
   114   Destroy();
   115 }
   117 //*****************************************************************************
   118 // nsXULWindow::nsISupports
   119 //*****************************************************************************
   121 NS_IMPL_ADDREF(nsXULWindow)
   122 NS_IMPL_RELEASE(nsXULWindow)
   124 NS_INTERFACE_MAP_BEGIN(nsXULWindow)
   125   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULWindow)
   126   NS_INTERFACE_MAP_ENTRY(nsIXULWindow)
   127   NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
   128   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   129   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   130   if (aIID.Equals(NS_GET_IID(nsXULWindow)))
   131     foundInterface = reinterpret_cast<nsISupports*>(this);
   132   else
   133 NS_INTERFACE_MAP_END
   135 //*****************************************************************************
   136 // nsXULWindow::nsIIntefaceRequestor
   137 //*****************************************************************************   
   139 NS_IMETHODIMP nsXULWindow::GetInterface(const nsIID& aIID, void** aSink)
   140 {
   141   nsresult rv;
   143   NS_ENSURE_ARG_POINTER(aSink);
   145   if (aIID.Equals(NS_GET_IID(nsIPrompt))) {
   146     rv = EnsurePrompter();
   147     if (NS_FAILED(rv)) return rv;
   148     return mPrompter->QueryInterface(aIID, aSink);
   149   }   
   150   if (aIID.Equals(NS_GET_IID(nsIAuthPrompt))) {
   151     rv = EnsureAuthPrompter();
   152     if (NS_FAILED(rv)) return rv;
   153     return mAuthPrompter->QueryInterface(aIID, aSink);
   154   }
   155   if (aIID.Equals(NS_GET_IID(nsIDOMWindow))) {
   156     return GetWindowDOMWindow(reinterpret_cast<nsIDOMWindow**>(aSink));
   157   }
   158   if (aIID.Equals(NS_GET_IID(nsIDOMWindowInternal))) {
   159     nsIDOMWindow* domWindow = nullptr;
   160     rv = GetWindowDOMWindow(&domWindow);
   161     nsIDOMWindowInternal* domWindowInternal =
   162       static_cast<nsIDOMWindowInternal*>(domWindow);
   163     *aSink = domWindowInternal;
   164     return rv;
   165   }
   166   if (aIID.Equals(NS_GET_IID(nsIWebBrowserChrome)) && 
   167     NS_SUCCEEDED(EnsureContentTreeOwner()) &&
   168     NS_SUCCEEDED(mContentTreeOwner->QueryInterface(aIID, aSink)))
   169     return NS_OK;
   171   if (aIID.Equals(NS_GET_IID(nsIEmbeddingSiteWindow)) && 
   172     NS_SUCCEEDED(EnsureContentTreeOwner()) &&
   173     NS_SUCCEEDED(mContentTreeOwner->QueryInterface(aIID, aSink)))
   174     return NS_OK;
   176   return QueryInterface(aIID, aSink);
   177 }
   179 //*****************************************************************************
   180 // nsXULWindow::nsIXULWindow
   181 //*****************************************************************************   
   183 NS_IMETHODIMP nsXULWindow::GetDocShell(nsIDocShell** aDocShell)
   184 {
   185   NS_ENSURE_ARG_POINTER(aDocShell);
   187   *aDocShell = mDocShell;
   188   NS_IF_ADDREF(*aDocShell);
   189   return NS_OK;
   190 }
   192 NS_IMETHODIMP nsXULWindow::GetZLevel(uint32_t *outLevel)
   193 {
   194   nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
   195   if (mediator)
   196     mediator->GetZLevel(this, outLevel);
   197   else
   198     *outLevel = normalZ;
   199   return NS_OK;
   200 }
   202 NS_IMETHODIMP nsXULWindow::SetZLevel(uint32_t aLevel)
   203 {
   204   nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
   205   if (!mediator)
   206     return NS_ERROR_FAILURE;
   208   uint32_t zLevel;
   209   mediator->GetZLevel(this, &zLevel);
   210   if (zLevel == aLevel)
   211     return NS_OK;
   213   /* refuse to raise a maximized window above the normal browser level,
   214      for fear it could hide newly opened browser windows */
   215   if (aLevel > nsIXULWindow::normalZ && mWindow) {
   216     int32_t sizeMode = mWindow->SizeMode();
   217     if (sizeMode == nsSizeMode_Maximized || sizeMode == nsSizeMode_Fullscreen) {
   218       return NS_ERROR_FAILURE;
   219     }
   220   }
   222   // do it
   223   mediator->SetZLevel(this, aLevel);
   224   PersistentAttributesDirty(PAD_MISC);
   225   SavePersistentAttributes();
   227   nsCOMPtr<nsIContentViewer> cv;
   228   mDocShell->GetContentViewer(getter_AddRefs(cv));
   229   if (cv) {
   230     nsCOMPtr<nsIDocument> doc = cv->GetDocument();
   231     if (doc) {
   232       ErrorResult rv;
   233       nsRefPtr<dom::Event> event =
   234         doc->CreateEvent(NS_LITERAL_STRING("Events"),rv);
   235       if (event) {
   236         event->InitEvent(NS_LITERAL_STRING("windowZLevel"), true, false);
   238         event->SetTrusted(true);
   240         bool defaultActionEnabled;
   241         doc->DispatchEvent(event, &defaultActionEnabled);
   242       }
   243     }
   244   }
   245   return NS_OK;
   246 }
   248 NS_IMETHODIMP nsXULWindow::GetContextFlags(uint32_t *aContextFlags)
   249 {
   250   NS_ENSURE_ARG_POINTER(aContextFlags);
   251   *aContextFlags = mContextFlags;
   252   return NS_OK;
   253 }
   255 NS_IMETHODIMP nsXULWindow::SetContextFlags(uint32_t aContextFlags)
   256 {
   257   mContextFlags = aContextFlags;
   258   return NS_OK;
   259 }
   261 NS_IMETHODIMP nsXULWindow::GetChromeFlags(uint32_t *aChromeFlags)
   262 {
   263   NS_ENSURE_ARG_POINTER(aChromeFlags);
   264   *aChromeFlags = mChromeFlags;
   265   /* mChromeFlags is kept up to date, except for scrollbar visibility.
   266      That can be changed directly by the content DOM window, which
   267      doesn't know to update the chrome window. So that we must check
   268      separately. */
   270   // however, it's pointless to ask if the window isn't set up yet
   271   if (!mChromeLoaded)
   272     return NS_OK;
   274   if (GetContentScrollbarVisibility())
   275     *aChromeFlags |= nsIWebBrowserChrome::CHROME_SCROLLBARS;
   276   else
   277     *aChromeFlags &= ~nsIWebBrowserChrome::CHROME_SCROLLBARS;
   279   return NS_OK;
   280 }
   282 NS_IMETHODIMP nsXULWindow::SetChromeFlags(uint32_t aChromeFlags)
   283 {
   284   NS_ASSERTION(!mChromeFlagsFrozen,
   285                "SetChromeFlags() after AssumeChromeFlagsAreFrozen()!");
   287   mChromeFlags = aChromeFlags;
   288   if (mChromeLoaded)
   289     NS_ENSURE_SUCCESS(ApplyChromeFlags(), NS_ERROR_FAILURE);
   290   return NS_OK;
   291 }
   293 NS_IMETHODIMP nsXULWindow::AssumeChromeFlagsAreFrozen()
   294 {
   295   mChromeFlagsFrozen = true;
   296   return NS_OK;
   297 }
   299 NS_IMETHODIMP nsXULWindow::SetIntrinsicallySized(bool aIntrinsicallySized)
   300 {
   301   mIntrinsicallySized = aIntrinsicallySized;
   302   return NS_OK;
   303 }
   305 NS_IMETHODIMP nsXULWindow::GetIntrinsicallySized(bool* aIntrinsicallySized)
   306 {
   307   NS_ENSURE_ARG_POINTER(aIntrinsicallySized);
   309   *aIntrinsicallySized = mIntrinsicallySized;
   310   return NS_OK;
   311 }
   313 NS_IMETHODIMP nsXULWindow::GetPrimaryContentShell(nsIDocShellTreeItem** 
   314    aDocShellTreeItem)
   315 {
   316   NS_ENSURE_ARG_POINTER(aDocShellTreeItem);
   317   NS_IF_ADDREF(*aDocShellTreeItem = mPrimaryContentShell);
   318   return NS_OK;
   319 }
   321 NS_IMETHODIMP nsXULWindow::GetContentShellById(const char16_t* aID, 
   322    nsIDocShellTreeItem** aDocShellTreeItem)
   323 {
   324   NS_ENSURE_ARG_POINTER(aDocShellTreeItem);
   325   *aDocShellTreeItem = nullptr;
   327   uint32_t count = mContentShells.Length();
   328   for (uint32_t i = 0; i < count; i++) {
   329     nsContentShellInfo* shellInfo = mContentShells.ElementAt(i);
   330     if (shellInfo->id.Equals(aID)) {
   331       *aDocShellTreeItem = nullptr;
   332       if (shellInfo->child)
   333         CallQueryReferent(shellInfo->child.get(), aDocShellTreeItem);
   334       return NS_OK;
   335     }
   336   }
   337   return NS_ERROR_FAILURE;
   338 }
   340 NS_IMETHODIMP nsXULWindow::AddChildWindow(nsIXULWindow *aChild)
   341 {
   342   // we're not really keeping track of this right now
   343   return NS_OK;
   344 }
   346 NS_IMETHODIMP nsXULWindow::RemoveChildWindow(nsIXULWindow *aChild)
   347 {
   348   // we're not really keeping track of this right now
   349   return NS_OK;
   350 }
   352 NS_IMETHODIMP nsXULWindow::ShowModal()
   353 {
   354   // Store locally so it doesn't die on us
   355   nsCOMPtr<nsIWidget> window = mWindow;
   356   nsCOMPtr<nsIXULWindow> tempRef = this;  
   358   window->SetModal(true);
   359   mContinueModalLoop = true;
   360   EnableParent(false);
   362   {
   363     AutoNoJSAPI nojsapi;
   364     nsIThread *thread = NS_GetCurrentThread();
   365     while (mContinueModalLoop) {
   366       if (!NS_ProcessNextEvent(thread))
   367         break;
   368     }
   369   }
   371   mContinueModalLoop = false;
   372   window->SetModal(false);
   373   /*   Note there's no EnableParent(true) here to match the false one
   374      above. That's done in ExitModalLoop. It's important that the parent
   375      be re-enabled before this window is made invisible; to do otherwise
   376      causes bizarre z-ordering problems. At this point, the window is
   377      already invisible.
   378        No known current implementation of Enable would have a problem with
   379      re-enabling the parent twice, so we could do it again here without
   380      breaking any current implementation. But that's unnecessary if the
   381      modal loop is always exited using ExitModalLoop (the other way would be
   382      to change the protected member variable directly.)
   383   */
   385   return mModalStatus;
   386 }
   388 //*****************************************************************************
   389 // nsXULWindow::nsIBaseWindow
   390 //*****************************************************************************   
   392 NS_IMETHODIMP nsXULWindow::InitWindow(nativeWindow aParentNativeWindow,
   393    nsIWidget* parentWidget, int32_t x, int32_t y, int32_t cx, int32_t cy)   
   394 {
   395   //XXX First Check In
   396   NS_ASSERTION(false, "Not Yet Implemented");
   397   return NS_OK;
   398 }
   400 NS_IMETHODIMP nsXULWindow::Create()
   401 {
   402   //XXX First Check In
   403   NS_ASSERTION(false, "Not Yet Implemented");
   404   return NS_OK;
   405 }
   407 NS_IMETHODIMP nsXULWindow::Destroy()
   408 {
   409   if (!mWindow)
   410      return NS_OK;
   412   // Ensure we don't reenter this code
   413   if (mDestroying)
   414     return NS_OK;
   416   mozilla::AutoRestore<bool> guard(mDestroying);
   417   mDestroying = true;
   419   nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
   420   NS_ASSERTION(appShell, "Couldn't get appShell... xpcom shutdown?");
   421   if (appShell)
   422     appShell->UnregisterTopLevelWindow(static_cast<nsIXULWindow*>(this));
   424   nsCOMPtr<nsIXULWindow> parentWindow(do_QueryReferent(mParentWindow));
   425   if (parentWindow)
   426     parentWindow->RemoveChildWindow(this);
   428   // let's make sure the window doesn't get deleted out from under us
   429   // while we are trying to close....this can happen if the docshell
   430   // we close ends up being the last owning reference to this xulwindow
   432   // XXXTAB This shouldn't be an issue anymore because the ownership model
   433   // only goes in one direction.  When webshell container is fully removed
   434   // try removing this...
   436   nsCOMPtr<nsIXULWindow> placeHolder = this;
   438   // Remove modality (if any) and hide while destroying. More than
   439   // a convenience, the hide prevents user interaction with the partially
   440   // destroyed window. This is especially necessary when the eldest window
   441   // in a stack of modal windows is destroyed first. It happens.
   442   ExitModalLoop(NS_OK);
   443   if (mWindow)
   444     mWindow->Show(false);
   446 #if defined(XP_WIN)
   447   // We need to explicitly set the focus on Windows, but 
   448   // only if the parent is visible.
   449   nsCOMPtr<nsIBaseWindow> parent(do_QueryReferent(mParentWindow));
   450   if (parent) {
   451     nsCOMPtr<nsIWidget> parentWidget;
   452     parent->GetMainWidget(getter_AddRefs(parentWidget));
   453     if (!parentWidget || parentWidget->IsVisible()) {
   454       nsCOMPtr<nsIBaseWindow> baseHiddenWindow;
   455       if (appShell) {
   456         nsCOMPtr<nsIXULWindow> hiddenWindow;
   457         appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow));
   458         if (hiddenWindow)
   459           baseHiddenWindow = do_GetInterface(hiddenWindow);
   460       }
   461       // somebody screwed up somewhere. hiddenwindow shouldn't be anybody's
   462       // parent. still, when it happens, skip activating it.
   463       if (baseHiddenWindow != parent) {
   464         nsCOMPtr<nsIWidget> parentWidget;
   465         parent->GetMainWidget(getter_AddRefs(parentWidget));
   466         if (parentWidget)
   467           parentWidget->PlaceBehind(eZPlacementTop, 0, true);
   468       }
   469     }
   470   }
   471 #endif
   473   mDOMWindow = nullptr;
   474   if (mDocShell) {
   475     nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(mDocShell));
   476     shellAsWin->Destroy();
   477     mDocShell = nullptr; // this can cause reentrancy of this function
   478   }
   480   // Remove our ref on the content shells
   481   uint32_t count = mContentShells.Length();
   482   for (uint32_t i = 0; i < count; i++) {
   483     nsContentShellInfo* shellInfo = mContentShells.ElementAt(i);
   484     delete shellInfo;
   485   }
   486   mContentShells.Clear();
   487   mPrimaryContentShell = nullptr;
   489   if (mContentTreeOwner) {
   490     mContentTreeOwner->XULWindow(nullptr);
   491     NS_RELEASE(mContentTreeOwner);
   492   }
   493   if (mPrimaryContentTreeOwner) {
   494     mPrimaryContentTreeOwner->XULWindow(nullptr);
   495     NS_RELEASE(mPrimaryContentTreeOwner);
   496   }
   497   if (mChromeTreeOwner) {
   498     mChromeTreeOwner->XULWindow(nullptr);
   499     NS_RELEASE(mChromeTreeOwner);
   500   }
   501   if (mWindow) {
   502     mWindow->SetWidgetListener(nullptr); // nsWebShellWindow hackery
   503     mWindow->Destroy();
   504     mWindow = nullptr;
   505   }
   507   if (!mIsHiddenWindow) {
   508     /* Inform appstartup we've destroyed this window and it could
   509        quit now if it wanted. This must happen at least after mDocShell
   510        is destroyed, because onunload handlers fire then, and those being
   511        script, anything could happen. A new window could open, even.
   512        See bug 130719. */
   513     nsCOMPtr<nsIObserverService> obssvc =
   514         do_GetService("@mozilla.org/observer-service;1");
   515     NS_ASSERTION(obssvc, "Couldn't get observer service?");
   517     if (obssvc)
   518       obssvc->NotifyObservers(nullptr, "xul-window-destroyed", nullptr);
   519   }
   521   return NS_OK;
   522 }
   524 NS_IMETHODIMP nsXULWindow::GetUnscaledDevicePixelsPerCSSPixel(double *aScale)
   525 {
   526   *aScale = mWindow ? mWindow->GetDefaultScale().scale : 1.0;
   527   return NS_OK;
   528 }
   530 NS_IMETHODIMP nsXULWindow::SetPosition(int32_t aX, int32_t aY)
   531 {
   532   // Don't reset the window's size mode here - platforms that don't want to move
   533   // maximized windows should reset it in their respective Move implementation.
   534   CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale();
   535   double invScale = 1.0 / scale.scale;
   536   nsresult rv = mWindow->Move(aX * invScale, aY * invScale);
   537   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
   538   if (!mChromeLoaded) {
   539     // If we're called before the chrome is loaded someone obviously wants this
   540     // window at this position. We don't persist this one-time position.
   541     mIgnoreXULPosition = true;
   542     return NS_OK;
   543   }
   544   PersistentAttributesDirty(PAD_POSITION);
   545   SavePersistentAttributes();
   546   return NS_OK;
   547 }
   549 NS_IMETHODIMP nsXULWindow::GetPosition(int32_t* aX, int32_t* aY)
   550 {
   551   return GetPositionAndSize(aX, aY, nullptr, nullptr);
   552 }
   554 NS_IMETHODIMP nsXULWindow::SetSize(int32_t aCX, int32_t aCY, bool aRepaint)
   555 {
   556   /* any attempt to set the window's size or position overrides the window's
   557      zoom state. this is important when these two states are competing while
   558      the window is being opened. but it should probably just always be so. */
   559   mWindow->SetSizeMode(nsSizeMode_Normal);
   561   mIntrinsicallySized = false;
   563   CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale();
   564   double invScale = 1.0 / scale.scale;
   565   nsresult rv = mWindow->Resize(aCX * invScale, aCY * invScale, aRepaint);
   566   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
   567   if (!mChromeLoaded) {
   568     // If we're called before the chrome is loaded someone obviously wants this
   569     // window at this size & in the normal size mode (since it is the only mode
   570     // in which setting dimensions makes sense). We don't persist this one-time
   571     // size.
   572     mIgnoreXULSize = true;
   573     mIgnoreXULSizeMode = true;
   574     return NS_OK;
   575   }
   576   PersistentAttributesDirty(PAD_SIZE);
   577   SavePersistentAttributes();
   578   return NS_OK;
   579 }
   581 NS_IMETHODIMP nsXULWindow::GetSize(int32_t* aCX, int32_t* aCY)
   582 {
   583   return GetPositionAndSize(nullptr, nullptr, aCX, aCY);
   584 }
   586 NS_IMETHODIMP nsXULWindow::SetPositionAndSize(int32_t aX, int32_t aY, 
   587    int32_t aCX, int32_t aCY, bool aRepaint)
   588 {
   589   /* any attempt to set the window's size or position overrides the window's
   590      zoom state. this is important when these two states are competing while
   591      the window is being opened. but it should probably just always be so. */
   592   mWindow->SetSizeMode(nsSizeMode_Normal);
   594   mIntrinsicallySized = false;
   596   CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale();
   597   double invScale = 1.0 / scale.scale;
   598   nsresult rv = mWindow->Resize(aX * invScale, aY * invScale,
   599                                 aCX * invScale, aCY * invScale,
   600                                 aRepaint);
   601   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
   602   if (!mChromeLoaded) {
   603     // If we're called before the chrome is loaded someone obviously wants this
   604     // window at this size and position. We don't persist this one-time setting.
   605     mIgnoreXULPosition = true;
   606     mIgnoreXULSize = true;
   607     mIgnoreXULSizeMode = true;
   608     return NS_OK;
   609   }
   610   PersistentAttributesDirty(PAD_POSITION | PAD_SIZE);
   611   SavePersistentAttributes();
   612   return NS_OK;
   613 }
   615 NS_IMETHODIMP nsXULWindow::GetPositionAndSize(int32_t* x, int32_t* y, int32_t* cx,
   616    int32_t* cy)
   617 {
   618   nsIntRect rect;
   620   if (!mWindow)
   621     return NS_ERROR_FAILURE;
   623   mWindow->GetScreenBounds(rect);
   625   if (x)
   626     *x = rect.x;
   627   if (y)
   628     *y = rect.y;
   629   if (cx)
   630     *cx = rect.width;
   631   if (cy)
   632     *cy = rect.height;
   634   return NS_OK;
   635 }
   637 NS_IMETHODIMP nsXULWindow::Center(nsIXULWindow *aRelative, bool aScreen, bool aAlert)
   638 {
   639   int32_t  left, top, width, height,
   640            ourWidth, ourHeight;
   641   bool     screenCoordinates =  false,
   642            windowCoordinates =  false;
   643   nsresult result;
   645   if (!mChromeLoaded) {
   646     // note we lose the parameters. at time of writing, this isn't a problem.
   647     mCenterAfterLoad = true;
   648     return NS_OK;
   649   }
   651   if (!aScreen && !aRelative)
   652     return NS_ERROR_INVALID_ARG;
   654   nsCOMPtr<nsIScreenManager> screenmgr = do_GetService("@mozilla.org/gfx/screenmanager;1", &result);
   655   if (NS_FAILED(result))
   656     return result;
   658   nsCOMPtr<nsIScreen> screen;
   660   if (aRelative) {
   661     nsCOMPtr<nsIBaseWindow> base(do_QueryInterface(aRelative, &result));
   662     if (base) {
   663       // get window rect
   664       result = base->GetPositionAndSize(&left, &top, &width, &height);
   665       if (NS_SUCCEEDED(result)) {
   666         double scale;
   667         if (NS_SUCCEEDED(base->GetUnscaledDevicePixelsPerCSSPixel(&scale))) {
   668           // convert device-pixel coordinates to global display pixels
   669           left = NSToIntRound(left / scale);
   670           top = NSToIntRound(top / scale);
   671           width = NSToIntRound(width / scale);
   672           height = NSToIntRound(height / scale);
   673         }
   674         // if centering on screen, convert that to the corresponding screen
   675         if (aScreen)
   676           screenmgr->ScreenForRect(left, top, width, height, getter_AddRefs(screen));
   677         else
   678           windowCoordinates = true;
   679       } else {
   680         // something's wrong with the reference window.
   681         // fall back to the primary screen
   682         aRelative = 0;
   683         aScreen = true;
   684       }
   685     }
   686   }
   687   if (!aRelative) {
   688     if (!mOpenerScreenRect.IsEmpty()) {
   689       // FIXME - check if these are device or display pixels
   690       screenmgr->ScreenForRect(mOpenerScreenRect.x, mOpenerScreenRect.y,
   691                                mOpenerScreenRect.width, mOpenerScreenRect.height,
   692                                getter_AddRefs(screen));
   693     } else {
   694       screenmgr->GetPrimaryScreen(getter_AddRefs(screen));
   695     }
   696   }
   698   if (aScreen && screen) {
   699     screen->GetAvailRectDisplayPix(&left, &top, &width, &height);
   700     screenCoordinates = true;
   701   }
   703   if (screenCoordinates || windowCoordinates) {
   704     NS_ASSERTION(mWindow, "what, no window?");
   705     CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale();
   706     GetSize(&ourWidth, &ourHeight);
   707     ourWidth = NSToIntRound(ourWidth / scale.scale);
   708     ourHeight = NSToIntRound(ourHeight / scale.scale);
   709     left += (width - ourWidth) / 2;
   710     top += (height - ourHeight) / (aAlert ? 3 : 2);
   711     if (windowCoordinates) {
   712       mWindow->ConstrainPosition(false, &left, &top);
   713     }
   714     SetPosition(left * scale.scale, top * scale.scale);
   715     return NS_OK;
   716   }
   717   return NS_ERROR_FAILURE;
   718 }
   720 NS_IMETHODIMP nsXULWindow::Repaint(bool aForce)
   721 {
   722   //XXX First Check In
   723   NS_ASSERTION(false, "Not Yet Implemented");
   724   return NS_OK;
   725 }
   727 NS_IMETHODIMP nsXULWindow::GetParentWidget(nsIWidget** aParentWidget)
   728 {
   729   NS_ENSURE_ARG_POINTER(aParentWidget);
   730   NS_ENSURE_STATE(mWindow);
   732   NS_IF_ADDREF(*aParentWidget = mWindow->GetParent());
   733   return NS_OK;
   734 }
   736 NS_IMETHODIMP nsXULWindow::SetParentWidget(nsIWidget* aParentWidget)
   737 {
   738   //XXX First Check In
   739   NS_ASSERTION(false, "Not Yet Implemented");
   740   return NS_OK;
   741 }
   743 NS_IMETHODIMP nsXULWindow::GetParentNativeWindow(nativeWindow* aParentNativeWindow)
   744 {
   745   NS_ENSURE_ARG_POINTER(aParentNativeWindow);
   747   nsCOMPtr<nsIWidget> parentWidget;
   748   NS_ENSURE_SUCCESS(GetParentWidget(getter_AddRefs(parentWidget)), NS_ERROR_FAILURE);
   750   if (parentWidget) {
   751     *aParentNativeWindow = parentWidget->GetNativeData(NS_NATIVE_WIDGET);
   752   }
   754   return NS_OK;
   755 }
   757 NS_IMETHODIMP nsXULWindow::SetParentNativeWindow(nativeWindow aParentNativeWindow)
   758 {
   759   //XXX First Check In
   760   NS_ASSERTION(false, "Not Yet Implemented");
   761   return NS_OK;
   762 }
   764 NS_IMETHODIMP nsXULWindow::GetNativeHandle(nsAString& aNativeHandle)
   765 {
   766   nsCOMPtr<nsIWidget> mainWidget;
   767   NS_ENSURE_SUCCESS(GetMainWidget(getter_AddRefs(mainWidget)), NS_ERROR_FAILURE);
   769   if (mainWidget) {
   770     nativeWindow nativeWindowPtr = mainWidget->GetNativeData(NS_NATIVE_WINDOW);
   771     /* the nativeWindow pointer is converted to and exposed as a string. This
   772        is a more reliable way not to lose information (as opposed to JS
   773        |Number| for instance) */
   774     aNativeHandle = NS_ConvertASCIItoUTF16(nsPrintfCString("0x%p", nativeWindowPtr));
   775   }
   777   return NS_OK;
   778 }
   780 NS_IMETHODIMP nsXULWindow::GetVisibility(bool* aVisibility)
   781 {
   782   NS_ENSURE_ARG_POINTER(aVisibility);
   784   // Always claim to be visible for now. See bug
   785   // https://bugzilla.mozilla.org/show_bug.cgi?id=306245.
   787   *aVisibility = true;
   789   return NS_OK;
   790 }
   792 NS_IMETHODIMP nsXULWindow::SetVisibility(bool aVisibility)
   793 {
   794   if (!mChromeLoaded) {
   795     mShowAfterLoad = aVisibility;
   796     return NS_OK;
   797   }
   799   if (mDebuting) {
   800     return NS_OK;
   801   }
   802   mDebuting = true;  // (Show / Focus is recursive)
   804   //XXXTAB Do we really need to show docshell and the window?  Isn't 
   805   // the window good enough?
   806   nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(mDocShell));
   807   shellAsWin->SetVisibility(aVisibility);
   808   // Store locally so it doesn't die on us. 'Show' can result in the window
   809   // being closed with nsXULWindow::Destroy being called. That would set
   810   // mWindow to null and posibly destroy the nsIWidget while its Show method
   811   // is on the stack. We need to keep it alive until Show finishes.
   812   nsCOMPtr<nsIWidget> window = mWindow;
   813   window->Show(aVisibility);
   815   nsCOMPtr<nsIWindowMediator> windowMediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
   816   if (windowMediator)
   817      windowMediator->UpdateWindowTimeStamp(static_cast<nsIXULWindow*>(this));
   819   // notify observers so that we can hide the splash screen if possible
   820   nsCOMPtr<nsIObserverService> obssvc
   821     (do_GetService("@mozilla.org/observer-service;1"));
   822   NS_ASSERTION(obssvc, "Couldn't get observer service.");
   823   if (obssvc) {
   824     obssvc->NotifyObservers(nullptr, "xul-window-visible", nullptr); 
   825   }
   827   mDebuting = false;
   828   return NS_OK;
   829 }
   831 NS_IMETHODIMP nsXULWindow::GetEnabled(bool *aEnabled)
   832 {
   833   NS_ENSURE_ARG_POINTER(aEnabled);
   835   if (mWindow) {
   836     *aEnabled = mWindow->IsEnabled();
   837     return NS_OK;
   838   }
   840   *aEnabled = true; // better guess than most
   841   return NS_ERROR_FAILURE;
   842 }
   844 NS_IMETHODIMP nsXULWindow::SetEnabled(bool aEnable)
   845 {
   846   if (mWindow) {
   847     mWindow->Enable(aEnable);
   848     return NS_OK;
   849   }
   850   return NS_ERROR_FAILURE;
   851 }
   853 NS_IMETHODIMP nsXULWindow::GetMainWidget(nsIWidget** aMainWidget)
   854 {
   855   NS_ENSURE_ARG_POINTER(aMainWidget);
   857   *aMainWidget = mWindow;
   858   NS_IF_ADDREF(*aMainWidget);
   859   return NS_OK;
   860 }
   862 NS_IMETHODIMP nsXULWindow::SetFocus()
   863 {
   864   //XXX First Check In
   865   NS_ASSERTION(false, "Not Yet Implemented");
   866   return NS_OK;
   867 }
   869 NS_IMETHODIMP nsXULWindow::GetTitle(char16_t** aTitle)
   870 {
   871   NS_ENSURE_ARG_POINTER(aTitle);
   873   *aTitle = ToNewUnicode(mTitle);
   874   if (!*aTitle)
   875     return NS_ERROR_OUT_OF_MEMORY;
   876   return NS_OK;
   877 }
   879 NS_IMETHODIMP nsXULWindow::SetTitle(const char16_t* aTitle)
   880 {
   881   NS_ENSURE_STATE(mWindow);
   882   mTitle.Assign(aTitle);
   883   mTitle.StripChars("\n\r");
   884   NS_ENSURE_SUCCESS(mWindow->SetTitle(mTitle), NS_ERROR_FAILURE);
   886   // Tell the window mediator that a title has changed
   887   nsCOMPtr<nsIWindowMediator> windowMediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
   888   if (!windowMediator)
   889     return NS_OK;
   891   windowMediator->UpdateWindowTitle(static_cast<nsIXULWindow*>(this), aTitle);
   893   return NS_OK;
   894 }
   897 //*****************************************************************************
   898 // nsXULWindow: Helpers
   899 //*****************************************************************************   
   901 NS_IMETHODIMP nsXULWindow::EnsureChromeTreeOwner()
   902 {
   903   if (mChromeTreeOwner)
   904     return NS_OK;
   906   mChromeTreeOwner = new nsChromeTreeOwner();
   907   NS_ENSURE_TRUE(mChromeTreeOwner, NS_ERROR_OUT_OF_MEMORY);
   909   NS_ADDREF(mChromeTreeOwner);
   910   mChromeTreeOwner->XULWindow(this);
   912   return NS_OK;
   913 }
   915 NS_IMETHODIMP nsXULWindow::EnsureContentTreeOwner()
   916 {
   917   if (mContentTreeOwner)
   918     return NS_OK;
   920   mContentTreeOwner = new nsContentTreeOwner(false);
   921   NS_ENSURE_TRUE(mContentTreeOwner, NS_ERROR_FAILURE);
   923   NS_ADDREF(mContentTreeOwner);
   924   mContentTreeOwner->XULWindow(this);
   926   return NS_OK;
   927 }
   929 NS_IMETHODIMP nsXULWindow::EnsurePrimaryContentTreeOwner()
   930 {
   931   if (mPrimaryContentTreeOwner)
   932     return NS_OK;
   934   mPrimaryContentTreeOwner = new nsContentTreeOwner(true);
   935   NS_ENSURE_TRUE(mPrimaryContentTreeOwner, NS_ERROR_FAILURE);
   937   NS_ADDREF(mPrimaryContentTreeOwner);
   938   mPrimaryContentTreeOwner->XULWindow(this);
   940   return NS_OK;
   941 }
   943 NS_IMETHODIMP nsXULWindow::EnsurePrompter()
   944 {
   945   if (mPrompter)
   946     return NS_OK;
   948   nsCOMPtr<nsIDOMWindow> ourWindow;
   949   nsresult rv = GetWindowDOMWindow(getter_AddRefs(ourWindow));
   950   if (NS_SUCCEEDED(rv)) {
   951     nsCOMPtr<nsIWindowWatcher> wwatch = 
   952         do_GetService(NS_WINDOWWATCHER_CONTRACTID);
   953     if (wwatch)
   954       wwatch->GetNewPrompter(ourWindow, getter_AddRefs(mPrompter));
   955   }
   956   return mPrompter ? NS_OK : NS_ERROR_FAILURE;
   957 }
   959 NS_IMETHODIMP nsXULWindow::EnsureAuthPrompter()
   960 {
   961   if (mAuthPrompter)
   962     return NS_OK;
   964   nsCOMPtr<nsIDOMWindow> ourWindow;
   965   nsresult rv = GetWindowDOMWindow(getter_AddRefs(ourWindow));
   966   if (NS_SUCCEEDED(rv)) {
   967     nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
   968     if (wwatch)
   969       wwatch->GetNewAuthPrompter(ourWindow, getter_AddRefs(mAuthPrompter));
   970   }
   971   return mAuthPrompter ? NS_OK : NS_ERROR_FAILURE;
   972 }
   974 void nsXULWindow::OnChromeLoaded()
   975 {
   976   nsresult rv = EnsureContentTreeOwner();
   978   if (NS_SUCCEEDED(rv)) {
   979     mChromeLoaded = true;
   980     ApplyChromeFlags();
   981     SyncAttributesToWidget();
   982     if (!mIgnoreXULSize)
   983       LoadSizeFromXUL();
   984     if (mIntrinsicallySized) {
   985       // (if LoadSizeFromXUL set the size, mIntrinsicallySized will be false)
   986       nsCOMPtr<nsIContentViewer> cv;
   987       mDocShell->GetContentViewer(getter_AddRefs(cv));
   988       nsCOMPtr<nsIMarkupDocumentViewer> markupViewer = do_QueryInterface(cv);
   989       if (markupViewer) {
   990         nsCOMPtr<nsIDocShellTreeItem> docShellAsItem = do_QueryInterface(mDocShell);
   991         nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
   992         docShellAsItem->GetTreeOwner(getter_AddRefs(treeOwner));
   993         if (treeOwner) {
   994           int32_t width, height;
   995           markupViewer->GetContentSize(&width, &height);
   996           treeOwner->SizeShellTo(docShellAsItem, width, height);
   997         }
   998       }
   999     }
  1001     bool positionSet = !mIgnoreXULPosition;
  1002     nsCOMPtr<nsIXULWindow> parentWindow(do_QueryReferent(mParentWindow));
  1003 #if defined(XP_UNIX) && !defined(XP_MACOSX)
  1004     // don't override WM placement on unix for independent, top-level windows
  1005     // (however, we think the benefits of intelligent dependent window placement
  1006     // trump that override.)
  1007     if (!parentWindow)
  1008       positionSet = false;
  1009 #endif
  1010     if (positionSet)
  1011       positionSet = LoadPositionFromXUL();
  1012     LoadMiscPersistentAttributesFromXUL();
  1014     if (mCenterAfterLoad && !positionSet)
  1015       Center(parentWindow, parentWindow ? false : true, false);
  1017     if (mShowAfterLoad) {
  1018       SetVisibility(true);
  1019       // At this point the window may have been closed during Show(), so
  1020       // nsXULWindow::Destroy may already have been called. Take care!
  1023   mPersistentAttributesMask |= PAD_POSITION | PAD_SIZE | PAD_MISC;
  1026 bool nsXULWindow::LoadPositionFromXUL()
  1028   bool     gotPosition = false;
  1030   // if we're the hidden window, don't try to validate our size/position. We're
  1031   // special.
  1032   if (mIsHiddenWindow)
  1033     return false;
  1035   nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement();
  1036   NS_ENSURE_TRUE(windowElement, false);
  1038   int32_t currX = 0;
  1039   int32_t currY = 0;
  1040   int32_t currWidth = 0;
  1041   int32_t currHeight = 0;
  1042   nsresult errorCode;
  1043   int32_t temp;
  1045   GetPositionAndSize(&currX, &currY, &currWidth, &currHeight);
  1047   // Convert to global display pixels for consistent window management across
  1048   // screens with diverse resolutions
  1049   CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale();
  1050   currX = NSToIntRound(currX / scale.scale);
  1051   currY = NSToIntRound(currY / scale.scale);
  1052   currWidth = NSToIntRound(currWidth / scale.scale);
  1053   currHeight = NSToIntRound(currHeight / scale.scale);
  1055   // Obtain the position information from the <xul:window> element.
  1056   int32_t specX = currX;
  1057   int32_t specY = currY;
  1058   nsAutoString posString;
  1060   windowElement->GetAttribute(SCREENX_ATTRIBUTE, posString);
  1061   temp = posString.ToInteger(&errorCode);
  1062   if (NS_SUCCEEDED(errorCode)) {
  1063     specX = temp;
  1064     gotPosition = true;
  1066   windowElement->GetAttribute(SCREENY_ATTRIBUTE, posString);
  1067   temp = posString.ToInteger(&errorCode);
  1068   if (NS_SUCCEEDED(errorCode)) {
  1069     specY = temp;
  1070     gotPosition = true;
  1073   if (gotPosition) {
  1074     // our position will be relative to our parent, if any
  1075     nsCOMPtr<nsIBaseWindow> parent(do_QueryReferent(mParentWindow));
  1076     if (parent) {
  1077       int32_t parentX, parentY;
  1078       if (NS_SUCCEEDED(parent->GetPosition(&parentX, &parentY))) {
  1079         double scale;
  1080         if (NS_SUCCEEDED(parent->GetUnscaledDevicePixelsPerCSSPixel(&scale))) {
  1081           parentX = NSToIntRound(parentX / scale);
  1082           parentY = NSToIntRound(parentY / scale);
  1084         specX += parentX;
  1085         specY += parentY;
  1088     else {
  1089       StaggerPosition(specX, specY, currWidth, currHeight);
  1092   mWindow->ConstrainPosition(false, &specX, &specY);
  1093   if (specX != currX || specY != currY) {
  1094     CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale();
  1095     SetPosition(specX * scale.scale, specY * scale.scale);
  1098   return gotPosition;
  1101 bool nsXULWindow::LoadSizeFromXUL()
  1103   bool     gotSize = false;
  1105   // if we're the hidden window, don't try to validate our size/position. We're
  1106   // special.
  1107   if (mIsHiddenWindow)
  1108     return false;
  1110   nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement();
  1111   NS_ENSURE_TRUE(windowElement, false);
  1113   int32_t currWidth = 0;
  1114   int32_t currHeight = 0;
  1115   nsresult errorCode;
  1116   int32_t temp;
  1118   NS_ASSERTION(mWindow, "we expected to have a window already");
  1120   CSSToLayoutDeviceScale scale = mWindow ? mWindow->GetDefaultScale()
  1121                                          : CSSToLayoutDeviceScale(1.0);
  1122   GetSize(&currWidth, &currHeight);
  1123   currWidth = NSToIntRound(currWidth / scale.scale);
  1124   currHeight = NSToIntRound(currHeight / scale.scale);
  1126   // Obtain the position and sizing information from the <xul:window> element.
  1127   int32_t specWidth = currWidth;
  1128   int32_t specHeight = currHeight;
  1129   nsAutoString sizeString;
  1131   windowElement->GetAttribute(WIDTH_ATTRIBUTE, sizeString);
  1132   temp = sizeString.ToInteger(&errorCode);
  1133   if (NS_SUCCEEDED(errorCode) && temp > 0) {
  1134     specWidth = std::max(temp, 100);
  1135     gotSize = true;
  1137   windowElement->GetAttribute(HEIGHT_ATTRIBUTE, sizeString);
  1138   temp = sizeString.ToInteger(&errorCode);
  1139   if (NS_SUCCEEDED(errorCode) && temp > 0) {
  1140     specHeight = std::max(temp, 100);
  1141     gotSize = true;
  1144   if (gotSize) {
  1145     // constrain to screen size
  1146     nsCOMPtr<nsIDOMWindow> domWindow;
  1147     GetWindowDOMWindow(getter_AddRefs(domWindow));
  1148     if (domWindow) {
  1149       nsCOMPtr<nsIDOMScreen> screen;
  1150       domWindow->GetScreen(getter_AddRefs(screen));
  1151       if (screen) {
  1152         int32_t screenWidth;
  1153         int32_t screenHeight;
  1154         screen->GetAvailWidth(&screenWidth);
  1155         screen->GetAvailHeight(&screenHeight);
  1156         if (specWidth > screenWidth)
  1157           specWidth = screenWidth;
  1158         if (specHeight > screenHeight)
  1159           specHeight = screenHeight;
  1163     mIntrinsicallySized = false;
  1164     if (specWidth != currWidth || specHeight != currHeight) {
  1165       CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale();
  1166       SetSize(specWidth * scale.scale, specHeight * scale.scale, false);
  1170   return gotSize;
  1173 /* Miscellaneous persistent attributes are attributes named in the
  1174    |persist| attribute, other than size and position. Those are special
  1175    because it's important to load those before one of the misc
  1176    attributes (sizemode) and they require extra processing. */
  1177 bool nsXULWindow::LoadMiscPersistentAttributesFromXUL()
  1179   bool     gotState = false;
  1181   /* There are no misc attributes of interest to the hidden window.
  1182      It's especially important not to try to validate that window's
  1183      size or position, because some platforms (Mac OS X) need to
  1184      make it visible and offscreen. */
  1185   if (mIsHiddenWindow)
  1186     return false;
  1188   nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement();
  1189   NS_ENSURE_TRUE(windowElement, false);
  1191   nsAutoString stateString;
  1193   // sizemode
  1194   windowElement->GetAttribute(MODE_ATTRIBUTE, stateString);
  1195   int32_t sizeMode = nsSizeMode_Normal;
  1196   /* ignore request to minimize, to not confuse novices
  1197   if (stateString.Equals(SIZEMODE_MINIMIZED))
  1198     sizeMode = nsSizeMode_Minimized;
  1199   */
  1200   if (!mIgnoreXULSizeMode &&
  1201       (stateString.Equals(SIZEMODE_MAXIMIZED) || stateString.Equals(SIZEMODE_FULLSCREEN))) {
  1202     /* Honor request to maximize only if the window is sizable.
  1203        An unsizable, unmaximizable, yet maximized window confuses
  1204        Windows OS and is something of a travesty, anyway. */
  1205     if (mChromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE) {
  1206       mIntrinsicallySized = false;
  1208       if (stateString.Equals(SIZEMODE_MAXIMIZED))
  1209         sizeMode = nsSizeMode_Maximized;
  1210       else
  1211         sizeMode = nsSizeMode_Fullscreen;
  1215   // If we are told to ignore the size mode attribute update the
  1216   // document so the attribute and window are in sync.
  1217   if (mIgnoreXULSizeMode) {
  1218     nsAutoString sizeString;
  1219     if (sizeMode == nsSizeMode_Maximized)
  1220       sizeString.Assign(SIZEMODE_MAXIMIZED);
  1221     else if (sizeMode == nsSizeMode_Fullscreen)
  1222       sizeString.Assign(SIZEMODE_FULLSCREEN);
  1223     else if (sizeMode == nsSizeMode_Normal)
  1224       sizeString.Assign(SIZEMODE_NORMAL);
  1225     if (!sizeString.IsEmpty()) {
  1226       ErrorResult rv;
  1227       windowElement->SetAttribute(MODE_ATTRIBUTE, sizeString, rv);
  1231   if (sizeMode == nsSizeMode_Fullscreen) {
  1232     nsCOMPtr<nsIDOMWindow> ourWindow;
  1233     GetWindowDOMWindow(getter_AddRefs(ourWindow));
  1234     ourWindow->SetFullScreen(true);
  1235   } else {
  1236     mWindow->SetSizeMode(sizeMode);
  1238   gotState = true;
  1240   // zlevel
  1241   windowElement->GetAttribute(ZLEVEL_ATTRIBUTE, stateString);
  1242   if (!stateString.IsEmpty()) {
  1243     nsresult errorCode;
  1244     int32_t zLevel = stateString.ToInteger(&errorCode);
  1245     if (NS_SUCCEEDED(errorCode) && zLevel >= lowestZ && zLevel <= highestZ)
  1246       SetZLevel(zLevel);
  1249   return gotState;
  1252 /* Stagger windows of the same type so they don't appear on top of each other.
  1253    This code does have a scary double loop -- it'll keep passing through
  1254    the entire list of open windows until it finds a non-collision. Doesn't
  1255    seem to be a problem, but it deserves watching.
  1256 */
  1257 void nsXULWindow::StaggerPosition(int32_t &aRequestedX, int32_t &aRequestedY,
  1258                                   int32_t aSpecWidth, int32_t aSpecHeight)
  1260   const int32_t kOffset = 22;
  1261   const uint32_t kSlop  = 4;
  1263   bool     keepTrying;
  1264   int      bouncedX = 0, // bounced off vertical edge of screen
  1265            bouncedY = 0; // bounced off horizontal edge
  1267   // look for any other windows of this type
  1268   nsCOMPtr<nsIWindowMediator> wm(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
  1269   if (!wm)
  1270     return;
  1272   nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement();
  1273   if (!windowElement)
  1274     return;
  1276   nsCOMPtr<nsIXULWindow> ourXULWindow(this);
  1278   nsAutoString windowType;
  1279   windowElement->GetAttribute(WINDOWTYPE_ATTRIBUTE, windowType);
  1281   int32_t screenTop = 0,    // it's pointless to initialize these ...
  1282           screenRight = 0,  // ... but to prevent oversalubrious and ...
  1283           screenBottom = 0, // ... underbright compilers from ...
  1284           screenLeft = 0;   // ... issuing warnings.
  1285   bool    gotScreen = false;
  1287   { // fetch screen coordinates
  1288     nsCOMPtr<nsIScreenManager> screenMgr(do_GetService(
  1289                                          "@mozilla.org/gfx/screenmanager;1"));
  1290     if (screenMgr) {
  1291       nsCOMPtr<nsIScreen> ourScreen;
  1292       // the coordinates here are already display pixels
  1293       screenMgr->ScreenForRect(aRequestedX, aRequestedY,
  1294                                aSpecWidth, aSpecHeight,
  1295                                getter_AddRefs(ourScreen));
  1296       if (ourScreen) {
  1297         int32_t screenWidth, screenHeight;
  1298         ourScreen->GetAvailRectDisplayPix(&screenLeft, &screenTop,
  1299                                           &screenWidth, &screenHeight);
  1300         screenBottom = screenTop + screenHeight;
  1301         screenRight = screenLeft + screenWidth;
  1302         gotScreen = true;
  1307   // One full pass through all windows of this type, repeat until no collisions.
  1308   do {
  1309     keepTrying = false;
  1310     nsCOMPtr<nsISimpleEnumerator> windowList;
  1311     wm->GetXULWindowEnumerator(windowType.get(), getter_AddRefs(windowList));
  1313     if (!windowList)
  1314       break;
  1316     // One full pass through all windows of this type, offset and stop on collision.
  1317     do {
  1318       bool more;
  1319       windowList->HasMoreElements(&more);
  1320       if (!more)
  1321         break;
  1323       nsCOMPtr<nsISupports> supportsWindow;
  1324       windowList->GetNext(getter_AddRefs(supportsWindow));
  1326       nsCOMPtr<nsIXULWindow> listXULWindow(do_QueryInterface(supportsWindow));
  1327       if (listXULWindow != ourXULWindow) {
  1328         int32_t listX, listY;
  1329         nsCOMPtr<nsIBaseWindow> listBaseWindow(do_QueryInterface(supportsWindow));
  1330         listBaseWindow->GetPosition(&listX, &listY);
  1331         double scale;
  1332         if (NS_SUCCEEDED(listBaseWindow->GetUnscaledDevicePixelsPerCSSPixel(&scale))) {
  1333           listX = NSToIntRound(listX / scale);
  1334           listY = NSToIntRound(listY / scale);
  1337         if (Abs(listX - aRequestedX) <= kSlop && Abs(listY - aRequestedY) <= kSlop) {
  1338           // collision! offset and start over
  1339           if (bouncedX & 0x1)
  1340             aRequestedX -= kOffset;
  1341           else
  1342             aRequestedX += kOffset;
  1343           aRequestedY += kOffset;
  1345           if (gotScreen) {
  1346             // if we're moving to the right and we need to bounce...
  1347             if (!(bouncedX & 0x1) && ((aRequestedX + aSpecWidth) > screenRight)) {
  1348               aRequestedX = screenRight - aSpecWidth;
  1349               ++bouncedX;
  1352             // if we're moving to the left and we need to bounce...
  1353             if ((bouncedX & 0x1) && aRequestedX < screenLeft) {
  1354               aRequestedX = screenLeft;
  1355               ++bouncedX;
  1358             // if we hit the bottom then bounce to the top
  1359             if (aRequestedY + aSpecHeight > screenBottom) {
  1360               aRequestedY = screenTop;
  1361               ++bouncedY;
  1365           /* loop around again,
  1366              but it's time to give up once we've covered the screen.
  1367              there's a potential infinite loop with lots of windows. */
  1368           keepTrying = bouncedX < 2 || bouncedY == 0;
  1369           break;
  1372     } while(1);
  1373   } while (keepTrying);
  1376 void nsXULWindow::SyncAttributesToWidget()
  1378   nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement();
  1379   if (!windowElement)
  1380     return;
  1382   nsAutoString attr;
  1384   // "hidechrome" attribute
  1385   if (windowElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidechrome,
  1386                                  nsGkAtoms::_true, eCaseMatters)) {
  1387     mWindow->HideWindowChrome(true);
  1390   // "chromemargin" attribute
  1391   nsIntMargin margins;
  1392   windowElement->GetAttribute(NS_LITERAL_STRING("chromemargin"), attr);
  1393   if (nsContentUtils::ParseIntMarginValue(attr, margins)) {
  1394     mWindow->SetNonClientMargins(margins);
  1397   // "accelerated" attribute
  1398   bool isAccelerated = windowElement->HasAttribute(NS_LITERAL_STRING("accelerated"));
  1399   mWindow->SetLayersAcceleration(isAccelerated);
  1401   // "windowtype" attribute
  1402   windowElement->GetAttribute(WINDOWTYPE_ATTRIBUTE, attr);
  1403   if (!attr.IsEmpty()) {
  1404     mWindow->SetWindowClass(attr);
  1407   // "id" attribute for icon
  1408   windowElement->GetAttribute(NS_LITERAL_STRING("id"), attr);
  1409   if (attr.IsEmpty()) {
  1410     attr.AssignLiteral("default");
  1412   mWindow->SetIcon(attr);
  1414   // "drawtitle" attribute
  1415   windowElement->GetAttribute(NS_LITERAL_STRING("drawtitle"), attr);
  1416   mWindow->SetDrawsTitle(attr.LowerCaseEqualsLiteral("true"));
  1418   // "toggletoolbar" attribute
  1419   windowElement->GetAttribute(NS_LITERAL_STRING("toggletoolbar"), attr);
  1420   mWindow->SetShowsToolbarButton(attr.LowerCaseEqualsLiteral("true"));
  1422   // "fullscreenbutton" attribute
  1423   windowElement->GetAttribute(NS_LITERAL_STRING("fullscreenbutton"), attr);
  1424   mWindow->SetShowsFullScreenButton(attr.LowerCaseEqualsLiteral("true"));
  1426   // "macanimationtype" attribute
  1427   windowElement->GetAttribute(NS_LITERAL_STRING("macanimationtype"), attr);
  1428   if (attr.EqualsLiteral("document")) {
  1429     mWindow->SetWindowAnimationType(nsIWidget::eDocumentWindowAnimation);
  1433 NS_IMETHODIMP nsXULWindow::SavePersistentAttributes()
  1435   // can happen when the persistence timer fires at an inopportune time
  1436   // during window shutdown
  1437   if (!mDocShell)
  1438     return NS_ERROR_FAILURE;
  1440   nsCOMPtr<dom::Element> docShellElement = GetWindowDOMElement();
  1441   if (!docShellElement)
  1442     return NS_ERROR_FAILURE;
  1444   nsAutoString   persistString;
  1445   docShellElement->GetAttribute(PERSIST_ATTRIBUTE, persistString);
  1446   if (persistString.IsEmpty()) { // quick check which sometimes helps
  1447     mPersistentAttributesDirty = 0;
  1448     return NS_OK;
  1451   // get our size, position and mode to persist
  1452   int32_t x, y, cx, cy;
  1453   NS_ENSURE_SUCCESS(GetPositionAndSize(&x, &y, &cx, &cy), NS_ERROR_FAILURE);
  1455   int32_t sizeMode = mWindow->SizeMode();
  1456   CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale();
  1458   // make our position relative to our parent, if any
  1459   nsCOMPtr<nsIBaseWindow> parent(do_QueryReferent(mParentWindow));
  1460   if (parent) {
  1461     int32_t parentX, parentY;
  1462     if (NS_SUCCEEDED(parent->GetPosition(&parentX, &parentY))) {
  1463       x -= parentX;
  1464       y -= parentY;
  1468   char                        sizeBuf[10];
  1469   nsAutoString                sizeString;
  1470   nsAutoString                windowElementId;
  1471   nsCOMPtr<nsIDOMXULDocument> ownerXULDoc;
  1473   // fetch docShellElement's ID and XUL owner document
  1474   ownerXULDoc = do_QueryInterface(docShellElement->OwnerDoc());
  1475   if (docShellElement->IsXUL()) {
  1476     docShellElement->GetId(windowElementId);
  1479   ErrorResult rv;
  1480   // (only for size elements which are persisted)
  1481   if ((mPersistentAttributesDirty & PAD_POSITION) &&
  1482       sizeMode == nsSizeMode_Normal) {
  1483     if (persistString.Find("screenX") >= 0) {
  1484       PR_snprintf(sizeBuf, sizeof(sizeBuf), "%d", NSToIntRound(x / scale.scale));
  1485       sizeString.AssignWithConversion(sizeBuf);
  1486       docShellElement->SetAttribute(SCREENX_ATTRIBUTE, sizeString, rv);
  1487       if (ownerXULDoc) // force persistence in case the value didn't change
  1488         ownerXULDoc->Persist(windowElementId, SCREENX_ATTRIBUTE);
  1490     if (persistString.Find("screenY") >= 0) {
  1491       PR_snprintf(sizeBuf, sizeof(sizeBuf), "%d", NSToIntRound(y / scale.scale));
  1492       sizeString.AssignWithConversion(sizeBuf);
  1493       docShellElement->SetAttribute(SCREENY_ATTRIBUTE, sizeString, rv);
  1494       if (ownerXULDoc)
  1495         ownerXULDoc->Persist(windowElementId, SCREENY_ATTRIBUTE);
  1499   if ((mPersistentAttributesDirty & PAD_SIZE) &&
  1500       sizeMode == nsSizeMode_Normal) {
  1501     if (persistString.Find("width") >= 0) {
  1502       PR_snprintf(sizeBuf, sizeof(sizeBuf), "%d", NSToIntRound(cx / scale.scale));
  1503       sizeString.AssignWithConversion(sizeBuf);
  1504       docShellElement->SetAttribute(WIDTH_ATTRIBUTE, sizeString, rv);
  1505       if (ownerXULDoc)
  1506         ownerXULDoc->Persist(windowElementId, WIDTH_ATTRIBUTE);
  1508     if (persistString.Find("height") >= 0) {
  1509       PR_snprintf(sizeBuf, sizeof(sizeBuf), "%d", NSToIntRound(cy / scale.scale));
  1510       sizeString.AssignWithConversion(sizeBuf);
  1511       docShellElement->SetAttribute(HEIGHT_ATTRIBUTE, sizeString, rv);
  1512       if (ownerXULDoc)
  1513         ownerXULDoc->Persist(windowElementId, HEIGHT_ATTRIBUTE);
  1517   if (mPersistentAttributesDirty & PAD_MISC) {
  1518     if (sizeMode != nsSizeMode_Minimized) {
  1519       if (sizeMode == nsSizeMode_Maximized)
  1520         sizeString.Assign(SIZEMODE_MAXIMIZED);
  1521       else if (sizeMode == nsSizeMode_Fullscreen)
  1522         sizeString.Assign(SIZEMODE_FULLSCREEN);
  1523       else
  1524         sizeString.Assign(SIZEMODE_NORMAL);
  1525       docShellElement->SetAttribute(MODE_ATTRIBUTE, sizeString, rv);
  1526       if (ownerXULDoc && persistString.Find("sizemode") >= 0)
  1527         ownerXULDoc->Persist(windowElementId, MODE_ATTRIBUTE);
  1529     if (persistString.Find("zlevel") >= 0) {
  1530       uint32_t zLevel;
  1531       nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
  1532       if (mediator) {
  1533         mediator->GetZLevel(this, &zLevel);
  1534         PR_snprintf(sizeBuf, sizeof(sizeBuf), "%lu", (unsigned long)zLevel);
  1535         sizeString.AssignWithConversion(sizeBuf);
  1536         docShellElement->SetAttribute(ZLEVEL_ATTRIBUTE, sizeString, rv);
  1537         ownerXULDoc->Persist(windowElementId, ZLEVEL_ATTRIBUTE);
  1542   mPersistentAttributesDirty = 0;
  1543   return NS_OK;
  1546 NS_IMETHODIMP nsXULWindow::GetWindowDOMWindow(nsIDOMWindow** aDOMWindow)
  1548   NS_ENSURE_STATE(mDocShell);
  1550   if (!mDOMWindow)
  1551     mDOMWindow = do_GetInterface(mDocShell);
  1552   NS_ENSURE_TRUE(mDOMWindow, NS_ERROR_FAILURE);
  1554   *aDOMWindow = mDOMWindow;
  1555   NS_ADDREF(*aDOMWindow);
  1556   return NS_OK;
  1559 dom::Element*
  1560 nsXULWindow::GetWindowDOMElement() const
  1562   NS_ENSURE_TRUE(mDocShell, nullptr);
  1564   nsCOMPtr<nsIContentViewer> cv;
  1565   mDocShell->GetContentViewer(getter_AddRefs(cv));
  1566   NS_ENSURE_TRUE(cv, nullptr);
  1568   const nsIDocument* document = cv->GetDocument();
  1569   NS_ENSURE_TRUE(document, nullptr);
  1571   return document->GetRootElement();
  1574 nsresult nsXULWindow::ContentShellAdded(nsIDocShellTreeItem* aContentShell,
  1575    bool aPrimary, bool aTargetable, const nsAString& aID)
  1577   nsContentShellInfo* shellInfo = nullptr;
  1579   uint32_t i, count = mContentShells.Length();
  1580   nsWeakPtr contentShellWeak = do_GetWeakReference(aContentShell);
  1581   for (i = 0; i < count; i++) {
  1582     nsContentShellInfo* info = mContentShells.ElementAt(i);
  1583     if (info->id.Equals(aID)) {
  1584       // We already exist. Do a replace.
  1585       info->child = contentShellWeak;
  1586       shellInfo = info;
  1588     else if (info->child == contentShellWeak)
  1589       info->child = nullptr;
  1592   if (!shellInfo) {
  1593     shellInfo = new nsContentShellInfo(aID, contentShellWeak);
  1594     mContentShells.AppendElement(shellInfo);
  1597   // Set the default content tree owner
  1598   if (aPrimary) {
  1599     NS_ENSURE_SUCCESS(EnsurePrimaryContentTreeOwner(), NS_ERROR_FAILURE);
  1600     aContentShell->SetTreeOwner(mPrimaryContentTreeOwner);
  1601     mPrimaryContentShell = aContentShell;
  1603   else {
  1604     NS_ENSURE_SUCCESS(EnsureContentTreeOwner(), NS_ERROR_FAILURE);
  1605     aContentShell->SetTreeOwner(mContentTreeOwner);
  1606     if (mPrimaryContentShell == aContentShell)
  1607       mPrimaryContentShell = nullptr;
  1610   if (aTargetable) {
  1611 #ifdef DEBUG
  1612     int32_t debugCount = mTargetableShells.Count();
  1613     int32_t debugCounter;
  1614     for (debugCounter = debugCount - 1; debugCounter >= 0; --debugCounter) {
  1615       nsCOMPtr<nsIDocShellTreeItem> curItem =
  1616         do_QueryReferent(mTargetableShells[debugCounter]);
  1617       NS_ASSERTION(!SameCOMIdentity(curItem, aContentShell),
  1618                    "Adding already existing item to mTargetableShells");
  1620 #endif
  1622     // put the new shell at the start of the targetable shells list if either
  1623     // it's the new primary shell or there is no existing primary shell (which
  1624     // means that chances are this one just stopped being primary).  If we
  1625     // really cared, we could keep track of the "last no longer primary shell"
  1626     // explicitly, but it probably doesn't matter enough: the difference would
  1627     // only be felt in a situation where all shells were non-primary, which
  1628     // doesn't happen much.  In a situation where there is one and only one
  1629     // primary shell, and in which shells get unmarked as primary before some
  1630     // other shell gets marked as primary, this effectively stores the list of
  1631     // targetable shells in "most recently primary first" order.
  1632     bool inserted;
  1633     if (aPrimary || !mPrimaryContentShell) {
  1634       inserted = mTargetableShells.InsertObjectAt(contentShellWeak, 0);
  1635     } else {
  1636       inserted = mTargetableShells.AppendObject(contentShellWeak);
  1638     NS_ENSURE_TRUE(inserted, NS_ERROR_OUT_OF_MEMORY);
  1641   return NS_OK;
  1644 nsresult nsXULWindow::ContentShellRemoved(nsIDocShellTreeItem* aContentShell)
  1646   if (mPrimaryContentShell == aContentShell) {
  1647     mPrimaryContentShell = nullptr;
  1650   int32_t i, count = mContentShells.Length();
  1651   for (i = count - 1; i >= 0; --i) {
  1652     nsContentShellInfo* info = mContentShells.ElementAt(i);
  1653     nsCOMPtr<nsIDocShellTreeItem> curItem = do_QueryReferent(info->child);
  1654     if (!curItem || SameCOMIdentity(curItem, aContentShell)) {
  1655       mContentShells.RemoveElementAt(i);
  1656       delete info;
  1660   count = mTargetableShells.Count();
  1661   for (i = count - 1; i >= 0; --i) {
  1662     nsCOMPtr<nsIDocShellTreeItem> curItem =
  1663       do_QueryReferent(mTargetableShells[i]);
  1664     if (!curItem || SameCOMIdentity(curItem, aContentShell)) {
  1665       mTargetableShells.RemoveObjectAt(i);
  1669   return NS_OK;
  1672 NS_IMETHODIMP nsXULWindow::SizeShellTo(nsIDocShellTreeItem* aShellItem,
  1673    int32_t aCX, int32_t aCY)
  1675   // XXXTAB This is wrong, we should actually reflow based on the passed in
  1676   // shell.  For now we are hacking and doing delta sizing.  This is bad
  1677   // because it assumes all size we add will go to the shell which probably
  1678   // won't happen.
  1680   nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(aShellItem));
  1681   NS_ENSURE_TRUE(shellAsWin, NS_ERROR_FAILURE);
  1683   int32_t width = 0;
  1684   int32_t height = 0;
  1685   shellAsWin->GetSize(&width, &height);
  1687   int32_t widthDelta = aCX - width;
  1688   int32_t heightDelta = aCY - height;
  1690   if (widthDelta || heightDelta) {
  1691     int32_t winCX = 0;
  1692     int32_t winCY = 0;
  1694     GetSize(&winCX, &winCY);
  1695     // There's no point in trying to make the window smaller than the
  1696     // desired docshell size --- that's not likely to work. This whole
  1697     // function assumes that the outer docshell is adding some constant
  1698     // "border" chrome to aShellItem.
  1699     winCX = std::max(winCX + widthDelta, aCX);
  1700     winCY = std::max(winCY + heightDelta, aCY);
  1701     SetSize(winCX, winCY, true);
  1704   return NS_OK;
  1707 NS_IMETHODIMP nsXULWindow::ExitModalLoop(nsresult aStatus)
  1709   if (mContinueModalLoop)
  1710     EnableParent(true);
  1711   mContinueModalLoop = false;
  1712   mModalStatus = aStatus;
  1713   return NS_OK;
  1716 // top-level function to create a new window
  1717 NS_IMETHODIMP nsXULWindow::CreateNewWindow(int32_t aChromeFlags,
  1718                              nsIXULWindow **_retval)
  1720   NS_ENSURE_ARG_POINTER(_retval);
  1722   if (aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)
  1723     return CreateNewChromeWindow(aChromeFlags, _retval);
  1724   return CreateNewContentWindow(aChromeFlags, _retval);
  1727 NS_IMETHODIMP nsXULWindow::CreateNewChromeWindow(int32_t aChromeFlags,
  1728                                                  nsIXULWindow **_retval)
  1730   nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
  1731   NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
  1733   // Just do a normal create of a window and return.
  1735   nsCOMPtr<nsIXULWindow> newWindow;
  1736   appShell->CreateTopLevelWindow(this, nullptr, aChromeFlags,
  1737                                  nsIAppShellService::SIZE_TO_CONTENT,
  1738                                  nsIAppShellService::SIZE_TO_CONTENT,
  1739                                  getter_AddRefs(newWindow));
  1741   NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE);
  1743   *_retval = newWindow;
  1744   NS_ADDREF(*_retval);
  1746   return NS_OK;
  1749 NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(int32_t aChromeFlags,
  1750                                                   nsIXULWindow **_retval)
  1752   nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
  1753   NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
  1755   // We need to create a new top level window and then enter a nested
  1756   // loop. Eventually the new window will be told that it has loaded,
  1757   // at which time we know it is safe to spin out of the nested loop
  1758   // and allow the opening code to proceed.
  1760   nsCOMPtr<nsIURI> uri;
  1762   nsAdoptingCString urlStr = Preferences::GetCString("browser.chromeURL");
  1763   if (urlStr.IsEmpty()) {
  1764     urlStr.AssignLiteral("chrome://navigator/content/navigator.xul");
  1767   nsCOMPtr<nsIIOService> service(do_GetService(NS_IOSERVICE_CONTRACTID));
  1768   if (service) {
  1769     service->NewURI(urlStr, nullptr, nullptr, getter_AddRefs(uri));
  1771   NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
  1773   // We need to create a chrome window to contain the content window we're about
  1774   // to pass back. The subject principal needs to be system while we're creating
  1775   // it to make things work right, so force a system caller. See bug 799348
  1776   // comment 13 for a description of what happens when we don't.
  1777   nsCOMPtr<nsIXULWindow> newWindow;
  1779     AutoNoJSAPI nojsapi;
  1780     appShell->CreateTopLevelWindow(this, uri,
  1781                                    aChromeFlags, 615, 480,
  1782                                    getter_AddRefs(newWindow));
  1783     NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE);
  1786   // Specify that we want the window to remain locked until the chrome has loaded.
  1787   nsXULWindow *xulWin = static_cast<nsXULWindow*>
  1788                                    (static_cast<nsIXULWindow*>
  1789                                                (newWindow));
  1791   xulWin->LockUntilChromeLoad();
  1794     AutoNoJSAPI nojsapi;
  1795     nsIThread *thread = NS_GetCurrentThread();
  1796     while (xulWin->IsLocked()) {
  1797       if (!NS_ProcessNextEvent(thread))
  1798         break;
  1802   NS_ENSURE_STATE(xulWin->mPrimaryContentShell);
  1804   *_retval = newWindow;
  1805   NS_ADDREF(*_retval);
  1807   return NS_OK;
  1810 void nsXULWindow::EnableParent(bool aEnable)
  1812   nsCOMPtr<nsIBaseWindow> parentWindow;
  1813   nsCOMPtr<nsIWidget>     parentWidget;
  1815   parentWindow = do_QueryReferent(mParentWindow);
  1816   if (parentWindow)
  1817     parentWindow->GetMainWidget(getter_AddRefs(parentWidget));
  1818   if (parentWidget)
  1819     parentWidget->Enable(aEnable);
  1822 // Constrain the window to its proper z-level
  1823 bool nsXULWindow::ConstrainToZLevel(bool        aImmediate,
  1824                                       nsWindowZ  *aPlacement,
  1825                                       nsIWidget  *aReqBelow,
  1826                                       nsIWidget **aActualBelow)
  1828 #if 0
  1829   /* Do we have a parent window? This means our z-order is already constrained,
  1830      since we're a dependent window. Our window list isn't hierarchical,
  1831      so we can't properly calculate placement for such a window.
  1832      Should we just abort? */
  1833   nsCOMPtr<nsIBaseWindow> parentWindow = do_QueryReferent(mParentWindow);
  1834   if (parentWindow)
  1835     return false;
  1836 #endif
  1838   nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
  1839   if (!mediator)
  1840     return false;
  1842   bool           altered;
  1843   uint32_t       position,
  1844                  newPosition,
  1845                  zLevel;
  1846   nsIXULWindow  *us = this;
  1848   altered = false;
  1849   mediator->GetZLevel(this, &zLevel);
  1851   // translate from WidgetGUIEvent to nsIWindowMediator constants
  1852   position = nsIWindowMediator::zLevelTop;
  1853   if (*aPlacement == nsWindowZBottom || zLevel == nsIXULWindow::lowestZ)
  1854     position = nsIWindowMediator::zLevelBottom;
  1855   else if (*aPlacement == nsWindowZRelative)
  1856     position = nsIWindowMediator::zLevelBelow;
  1858   if (NS_SUCCEEDED(mediator->CalculateZPosition(us, position, aReqBelow,
  1859                                &newPosition, aActualBelow, &altered))) {
  1860     /* If we were asked to move to the top but constrained to remain
  1861        below one of our other windows, first move all windows in that
  1862        window's layer and above to the top. This allows the user to
  1863        click a window which can't be topmost and still bring mozilla
  1864        to the foreground. */
  1865     if (altered &&
  1866         (position == nsIWindowMediator::zLevelTop ||
  1867          (position == nsIWindowMediator::zLevelBelow && aReqBelow == 0)))
  1868       PlaceWindowLayersBehind(zLevel + 1, nsIXULWindow::highestZ, 0);
  1870     if (*aPlacement != nsWindowZBottom &&
  1871         position == nsIWindowMediator::zLevelBottom)
  1872       altered = true;
  1873     if (altered || aImmediate) {
  1874       if (newPosition == nsIWindowMediator::zLevelTop)
  1875         *aPlacement = nsWindowZTop;
  1876       else if (newPosition == nsIWindowMediator::zLevelBottom)
  1877         *aPlacement = nsWindowZBottom;
  1878       else
  1879         *aPlacement = nsWindowZRelative;
  1881       if (aImmediate) {
  1882         nsCOMPtr<nsIBaseWindow> ourBase = do_QueryObject(this);
  1883         if (ourBase) {
  1884           nsCOMPtr<nsIWidget> ourWidget;
  1885           ourBase->GetMainWidget(getter_AddRefs(ourWidget));
  1886           ourWidget->PlaceBehind(*aPlacement == nsWindowZBottom ?
  1887                                    eZPlacementBottom : eZPlacementBelow,
  1888                                  *aActualBelow, false);
  1893     /* CalculateZPosition can tell us to be below nothing, because it tries
  1894        not to change something it doesn't recognize. A request to verify
  1895        being below an unrecognized window, then, is treated as a request
  1896        to come to the top (below null) */
  1897     nsCOMPtr<nsIXULWindow> windowAbove;
  1898     if (newPosition == nsIWindowMediator::zLevelBelow && *aActualBelow) {
  1899       windowAbove = (*aActualBelow)->GetWidgetListener()->GetXULWindow();
  1902     mediator->SetZPosition(us, newPosition, windowAbove);
  1905   return altered;
  1908 /* Re-z-position all windows in the layers from aLowLevel to aHighLevel,
  1909    inclusive, to be behind aBehind. aBehind of null means on top.
  1910    Note this method actually does nothing to our relative window positions.
  1911    (And therefore there's no need to inform WindowMediator we're moving
  1912    things, because we aren't.) This method is useful for, say, moving
  1913    a range of layers of our own windows relative to windows belonging to
  1914    external applications.
  1915 */
  1916 void nsXULWindow::PlaceWindowLayersBehind(uint32_t aLowLevel,
  1917                                           uint32_t aHighLevel,
  1918                                           nsIXULWindow *aBehind)
  1920   // step through windows in z-order from top to bottommost window
  1922   nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
  1923   if (!mediator)
  1924     return;
  1926   nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
  1927   mediator->GetZOrderXULWindowEnumerator(0, true,
  1928               getter_AddRefs(windowEnumerator));
  1929   if (!windowEnumerator)
  1930     return;
  1932   // each window will be moved behind previousHighWidget, itself
  1933   // a moving target. initialize it.
  1934   nsCOMPtr<nsIWidget> previousHighWidget;
  1935   if (aBehind) {
  1936     nsCOMPtr<nsIBaseWindow> highBase(do_QueryInterface(aBehind));
  1937     if (highBase)
  1938       highBase->GetMainWidget(getter_AddRefs(previousHighWidget));
  1941   // get next lower window
  1942   bool more;
  1943   while (windowEnumerator->HasMoreElements(&more), more) {
  1944     uint32_t nextZ; // z-level of nextWindow
  1945     nsCOMPtr<nsISupports> nextWindow;
  1946     windowEnumerator->GetNext(getter_AddRefs(nextWindow));
  1947     nsCOMPtr<nsIXULWindow> nextXULWindow(do_QueryInterface(nextWindow));
  1948     nextXULWindow->GetZLevel(&nextZ);
  1949     if (nextZ < aLowLevel)
  1950       break; // we've processed all windows through aLowLevel
  1952     // move it just below its next higher window
  1953     nsCOMPtr<nsIBaseWindow> nextBase(do_QueryInterface(nextXULWindow));
  1954     if (nextBase) {
  1955       nsCOMPtr<nsIWidget> nextWidget;
  1956       nextBase->GetMainWidget(getter_AddRefs(nextWidget));
  1957       if (nextZ <= aHighLevel)
  1958         nextWidget->PlaceBehind(eZPlacementBelow, previousHighWidget, false);
  1959       previousHighWidget = nextWidget;
  1964 void nsXULWindow::SetContentScrollbarVisibility(bool aVisible)
  1966   nsCOMPtr<nsPIDOMWindow> contentWin(do_GetInterface(mPrimaryContentShell));
  1967   if (contentWin) {
  1968     mozilla::ErrorResult rv;
  1969     nsRefPtr<nsGlobalWindow> window = static_cast<nsGlobalWindow*>(contentWin.get());
  1970     nsRefPtr<mozilla::dom::BarProp> scrollbars = window->GetScrollbars(rv);
  1971     if (scrollbars) {
  1972       scrollbars->SetVisible(aVisible, rv);
  1977 bool nsXULWindow::GetContentScrollbarVisibility()
  1979   // This code already exists in dom/src/base/nsBarProp.cpp, but we
  1980   // can't safely get to that from here as this function is called
  1981   // while the DOM window is being set up, and we need the DOM window
  1982   // to get to that code.
  1983   nsCOMPtr<nsIScrollable> scroller(do_QueryInterface(mPrimaryContentShell));
  1985   if (scroller) {
  1986     int32_t prefValue;
  1987     scroller->GetDefaultScrollbarPreferences(
  1988                   nsIScrollable::ScrollOrientation_Y, &prefValue);
  1989     if (prefValue == nsIScrollable::Scrollbar_Never) // try the other way
  1990       scroller->GetDefaultScrollbarPreferences(
  1991                   nsIScrollable::ScrollOrientation_X, &prefValue);
  1993     if (prefValue == nsIScrollable::Scrollbar_Never)
  1994       return false;
  1997   return true;
  2000 // during spinup, attributes that haven't been loaded yet can't be dirty
  2001 void nsXULWindow::PersistentAttributesDirty(uint32_t aDirtyFlags)
  2003   mPersistentAttributesDirty |= aDirtyFlags & mPersistentAttributesMask;
  2006 NS_IMETHODIMP nsXULWindow::ApplyChromeFlags()
  2008   nsCOMPtr<dom::Element> window = GetWindowDOMElement();
  2009   NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
  2011   if (mChromeLoaded) {
  2012     // The two calls in this block don't need to happen early because they
  2013     // don't cause a global restyle on the document.  Not only that, but the
  2014     // scrollbar stuff needs a content area to toggle the scrollbars on anyway.
  2015     // So just don't do these until mChromeLoaded is true.
  2017     // Scrollbars have their own special treatment.
  2018     SetContentScrollbarVisibility(mChromeFlags &
  2019                                   nsIWebBrowserChrome::CHROME_SCROLLBARS ?
  2020                                     true : false);
  2023   /* the other flags are handled together. we have style rules
  2024      in navigator.css that trigger visibility based on
  2025      the 'chromehidden' attribute of the <window> tag. */
  2026   nsAutoString newvalue;
  2028   if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_MENUBAR))
  2029     newvalue.AppendLiteral("menubar ");
  2031   if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_TOOLBAR))
  2032     newvalue.AppendLiteral("toolbar ");
  2034   if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_LOCATIONBAR))
  2035     newvalue.AppendLiteral("location ");
  2037   if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR))
  2038     newvalue.AppendLiteral("directories ");
  2040   if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_STATUSBAR))
  2041     newvalue.AppendLiteral("status ");
  2043   if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_EXTRA))
  2044     newvalue.AppendLiteral("extrachrome ");
  2046   // Note that if we're not actually changing the value this will be a no-op,
  2047   // so no need to compare to the old value.
  2048   ErrorResult rv;
  2049   window->SetAttribute(NS_LITERAL_STRING("chromehidden"), newvalue, rv);
  2051   return NS_OK;
  2054 NS_IMETHODIMP nsXULWindow::GetXULBrowserWindow(nsIXULBrowserWindow * *aXULBrowserWindow)
  2056   NS_IF_ADDREF(*aXULBrowserWindow = mXULBrowserWindow);
  2057   return NS_OK;
  2060 NS_IMETHODIMP nsXULWindow::SetXULBrowserWindow(nsIXULBrowserWindow * aXULBrowserWindow)
  2062   mXULBrowserWindow = aXULBrowserWindow;
  2063   return NS_OK;
  2066 //*****************************************************************************
  2067 //*** nsContentShellInfo: Object Management
  2068 //*****************************************************************************   
  2070 nsContentShellInfo::nsContentShellInfo(const nsAString& aID,
  2071                                        nsIWeakReference* aContentShell)
  2072   : id(aID),
  2073     child(aContentShell)
  2075   MOZ_COUNT_CTOR(nsContentShellInfo);
  2078 nsContentShellInfo::~nsContentShellInfo()
  2080   MOZ_COUNT_DTOR(nsContentShellInfo);
  2081    //XXX Set Tree Owner to null if the tree owner is nsXULWindow->mContentTreeOwner

mercurial