1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpfe/appshell/src/nsXULWindow.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2082 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sw=2 sts=2 ci et: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "mozilla/MathAlgorithms.h" 1.11 + 1.12 +// Local includes 1.13 +#include "nsXULWindow.h" 1.14 +#include <algorithm> 1.15 + 1.16 +// Helper classes 1.17 +#include "nsPrintfCString.h" 1.18 +#include "nsString.h" 1.19 +#include "nsWidgetsCID.h" 1.20 +#include "prprf.h" 1.21 +#include "nsCRT.h" 1.22 +#include "nsThreadUtils.h" 1.23 +#include "nsNetCID.h" 1.24 + 1.25 +//Interfaces needed to be included 1.26 +#include "nsIAppShell.h" 1.27 +#include "nsIAppShellService.h" 1.28 +#include "nsIServiceManager.h" 1.29 +#include "nsIContentViewer.h" 1.30 +#include "nsIDocument.h" 1.31 +#include "nsIDOMDocument.h" 1.32 +#include "nsIDOMXULDocument.h" 1.33 +#include "nsIDOMElement.h" 1.34 +#include "nsIDOMXULElement.h" 1.35 +#include "nsPIDOMWindow.h" 1.36 +#include "nsIDOMScreen.h" 1.37 +#include "nsIEmbeddingSiteWindow.h" 1.38 +#include "nsIInterfaceRequestor.h" 1.39 +#include "nsIInterfaceRequestorUtils.h" 1.40 +#include "nsIIOService.h" 1.41 +#include "nsIMarkupDocumentViewer.h" 1.42 +#include "nsIObserverService.h" 1.43 +#include "nsIWindowMediator.h" 1.44 +#include "nsIScreenManager.h" 1.45 +#include "nsIScreen.h" 1.46 +#include "nsIScrollable.h" 1.47 +#include "nsIScriptSecurityManager.h" 1.48 +#include "nsIWindowWatcher.h" 1.49 +#include "nsIURI.h" 1.50 +#include "nsIDOMCSSStyleDeclaration.h" 1.51 +#include "nsAppShellCID.h" 1.52 +#include "nsReadableUtils.h" 1.53 +#include "nsStyleConsts.h" 1.54 +#include "nsPresContext.h" 1.55 +#include "nsContentUtils.h" 1.56 +#include "nsWebShellWindow.h" // get rid of this one, too... 1.57 +#include "nsGlobalWindow.h" 1.58 + 1.59 +#include "prenv.h" 1.60 +#include "mozilla/AutoRestore.h" 1.61 +#include "mozilla/Preferences.h" 1.62 +#include "mozilla/dom/BarProps.h" 1.63 +#include "mozilla/dom/Element.h" 1.64 +#include "mozilla/dom/Event.h" 1.65 +#include "mozilla/dom/ScriptSettings.h" 1.66 + 1.67 +using namespace mozilla; 1.68 +using dom::AutoNoJSAPI; 1.69 + 1.70 +#define SIZEMODE_NORMAL NS_LITERAL_STRING("normal") 1.71 +#define SIZEMODE_MAXIMIZED NS_LITERAL_STRING("maximized") 1.72 +#define SIZEMODE_MINIMIZED NS_LITERAL_STRING("minimized") 1.73 +#define SIZEMODE_FULLSCREEN NS_LITERAL_STRING("fullscreen") 1.74 + 1.75 +#define WINDOWTYPE_ATTRIBUTE NS_LITERAL_STRING("windowtype") 1.76 + 1.77 +#define PERSIST_ATTRIBUTE NS_LITERAL_STRING("persist") 1.78 +#define SCREENX_ATTRIBUTE NS_LITERAL_STRING("screenX") 1.79 +#define SCREENY_ATTRIBUTE NS_LITERAL_STRING("screenY") 1.80 +#define WIDTH_ATTRIBUTE NS_LITERAL_STRING("width") 1.81 +#define HEIGHT_ATTRIBUTE NS_LITERAL_STRING("height") 1.82 +#define MODE_ATTRIBUTE NS_LITERAL_STRING("sizemode") 1.83 +#define ZLEVEL_ATTRIBUTE NS_LITERAL_STRING("zlevel") 1.84 + 1.85 + 1.86 +//***************************************************************************** 1.87 +//*** nsXULWindow: Object Management 1.88 +//***************************************************************************** 1.89 + 1.90 +nsXULWindow::nsXULWindow(uint32_t aChromeFlags) 1.91 + : mChromeTreeOwner(nullptr), 1.92 + mContentTreeOwner(nullptr), 1.93 + mPrimaryContentTreeOwner(nullptr), 1.94 + mModalStatus(NS_OK), 1.95 + mContinueModalLoop(false), 1.96 + mDebuting(false), 1.97 + mChromeLoaded(false), 1.98 + mShowAfterLoad(false), 1.99 + mIntrinsicallySized(false), 1.100 + mCenterAfterLoad(false), 1.101 + mIsHiddenWindow(false), 1.102 + mLockedUntilChromeLoad(false), 1.103 + mIgnoreXULSize(false), 1.104 + mIgnoreXULPosition(false), 1.105 + mChromeFlagsFrozen(false), 1.106 + mIgnoreXULSizeMode(false), 1.107 + mDestroying(false), 1.108 + mContextFlags(0), 1.109 + mPersistentAttributesDirty(0), 1.110 + mPersistentAttributesMask(0), 1.111 + mChromeFlags(aChromeFlags) 1.112 +{ 1.113 +} 1.114 + 1.115 +nsXULWindow::~nsXULWindow() 1.116 +{ 1.117 + Destroy(); 1.118 +} 1.119 + 1.120 +//***************************************************************************** 1.121 +// nsXULWindow::nsISupports 1.122 +//***************************************************************************** 1.123 + 1.124 +NS_IMPL_ADDREF(nsXULWindow) 1.125 +NS_IMPL_RELEASE(nsXULWindow) 1.126 + 1.127 +NS_INTERFACE_MAP_BEGIN(nsXULWindow) 1.128 + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULWindow) 1.129 + NS_INTERFACE_MAP_ENTRY(nsIXULWindow) 1.130 + NS_INTERFACE_MAP_ENTRY(nsIBaseWindow) 1.131 + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) 1.132 + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) 1.133 + if (aIID.Equals(NS_GET_IID(nsXULWindow))) 1.134 + foundInterface = reinterpret_cast<nsISupports*>(this); 1.135 + else 1.136 +NS_INTERFACE_MAP_END 1.137 + 1.138 +//***************************************************************************** 1.139 +// nsXULWindow::nsIIntefaceRequestor 1.140 +//***************************************************************************** 1.141 + 1.142 +NS_IMETHODIMP nsXULWindow::GetInterface(const nsIID& aIID, void** aSink) 1.143 +{ 1.144 + nsresult rv; 1.145 + 1.146 + NS_ENSURE_ARG_POINTER(aSink); 1.147 + 1.148 + if (aIID.Equals(NS_GET_IID(nsIPrompt))) { 1.149 + rv = EnsurePrompter(); 1.150 + if (NS_FAILED(rv)) return rv; 1.151 + return mPrompter->QueryInterface(aIID, aSink); 1.152 + } 1.153 + if (aIID.Equals(NS_GET_IID(nsIAuthPrompt))) { 1.154 + rv = EnsureAuthPrompter(); 1.155 + if (NS_FAILED(rv)) return rv; 1.156 + return mAuthPrompter->QueryInterface(aIID, aSink); 1.157 + } 1.158 + if (aIID.Equals(NS_GET_IID(nsIDOMWindow))) { 1.159 + return GetWindowDOMWindow(reinterpret_cast<nsIDOMWindow**>(aSink)); 1.160 + } 1.161 + if (aIID.Equals(NS_GET_IID(nsIDOMWindowInternal))) { 1.162 + nsIDOMWindow* domWindow = nullptr; 1.163 + rv = GetWindowDOMWindow(&domWindow); 1.164 + nsIDOMWindowInternal* domWindowInternal = 1.165 + static_cast<nsIDOMWindowInternal*>(domWindow); 1.166 + *aSink = domWindowInternal; 1.167 + return rv; 1.168 + } 1.169 + if (aIID.Equals(NS_GET_IID(nsIWebBrowserChrome)) && 1.170 + NS_SUCCEEDED(EnsureContentTreeOwner()) && 1.171 + NS_SUCCEEDED(mContentTreeOwner->QueryInterface(aIID, aSink))) 1.172 + return NS_OK; 1.173 + 1.174 + if (aIID.Equals(NS_GET_IID(nsIEmbeddingSiteWindow)) && 1.175 + NS_SUCCEEDED(EnsureContentTreeOwner()) && 1.176 + NS_SUCCEEDED(mContentTreeOwner->QueryInterface(aIID, aSink))) 1.177 + return NS_OK; 1.178 + 1.179 + return QueryInterface(aIID, aSink); 1.180 +} 1.181 + 1.182 +//***************************************************************************** 1.183 +// nsXULWindow::nsIXULWindow 1.184 +//***************************************************************************** 1.185 + 1.186 +NS_IMETHODIMP nsXULWindow::GetDocShell(nsIDocShell** aDocShell) 1.187 +{ 1.188 + NS_ENSURE_ARG_POINTER(aDocShell); 1.189 + 1.190 + *aDocShell = mDocShell; 1.191 + NS_IF_ADDREF(*aDocShell); 1.192 + return NS_OK; 1.193 +} 1.194 + 1.195 +NS_IMETHODIMP nsXULWindow::GetZLevel(uint32_t *outLevel) 1.196 +{ 1.197 + nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); 1.198 + if (mediator) 1.199 + mediator->GetZLevel(this, outLevel); 1.200 + else 1.201 + *outLevel = normalZ; 1.202 + return NS_OK; 1.203 +} 1.204 + 1.205 +NS_IMETHODIMP nsXULWindow::SetZLevel(uint32_t aLevel) 1.206 +{ 1.207 + nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); 1.208 + if (!mediator) 1.209 + return NS_ERROR_FAILURE; 1.210 + 1.211 + uint32_t zLevel; 1.212 + mediator->GetZLevel(this, &zLevel); 1.213 + if (zLevel == aLevel) 1.214 + return NS_OK; 1.215 + 1.216 + /* refuse to raise a maximized window above the normal browser level, 1.217 + for fear it could hide newly opened browser windows */ 1.218 + if (aLevel > nsIXULWindow::normalZ && mWindow) { 1.219 + int32_t sizeMode = mWindow->SizeMode(); 1.220 + if (sizeMode == nsSizeMode_Maximized || sizeMode == nsSizeMode_Fullscreen) { 1.221 + return NS_ERROR_FAILURE; 1.222 + } 1.223 + } 1.224 + 1.225 + // do it 1.226 + mediator->SetZLevel(this, aLevel); 1.227 + PersistentAttributesDirty(PAD_MISC); 1.228 + SavePersistentAttributes(); 1.229 + 1.230 + nsCOMPtr<nsIContentViewer> cv; 1.231 + mDocShell->GetContentViewer(getter_AddRefs(cv)); 1.232 + if (cv) { 1.233 + nsCOMPtr<nsIDocument> doc = cv->GetDocument(); 1.234 + if (doc) { 1.235 + ErrorResult rv; 1.236 + nsRefPtr<dom::Event> event = 1.237 + doc->CreateEvent(NS_LITERAL_STRING("Events"),rv); 1.238 + if (event) { 1.239 + event->InitEvent(NS_LITERAL_STRING("windowZLevel"), true, false); 1.240 + 1.241 + event->SetTrusted(true); 1.242 + 1.243 + bool defaultActionEnabled; 1.244 + doc->DispatchEvent(event, &defaultActionEnabled); 1.245 + } 1.246 + } 1.247 + } 1.248 + return NS_OK; 1.249 +} 1.250 + 1.251 +NS_IMETHODIMP nsXULWindow::GetContextFlags(uint32_t *aContextFlags) 1.252 +{ 1.253 + NS_ENSURE_ARG_POINTER(aContextFlags); 1.254 + *aContextFlags = mContextFlags; 1.255 + return NS_OK; 1.256 +} 1.257 + 1.258 +NS_IMETHODIMP nsXULWindow::SetContextFlags(uint32_t aContextFlags) 1.259 +{ 1.260 + mContextFlags = aContextFlags; 1.261 + return NS_OK; 1.262 +} 1.263 + 1.264 +NS_IMETHODIMP nsXULWindow::GetChromeFlags(uint32_t *aChromeFlags) 1.265 +{ 1.266 + NS_ENSURE_ARG_POINTER(aChromeFlags); 1.267 + *aChromeFlags = mChromeFlags; 1.268 + /* mChromeFlags is kept up to date, except for scrollbar visibility. 1.269 + That can be changed directly by the content DOM window, which 1.270 + doesn't know to update the chrome window. So that we must check 1.271 + separately. */ 1.272 + 1.273 + // however, it's pointless to ask if the window isn't set up yet 1.274 + if (!mChromeLoaded) 1.275 + return NS_OK; 1.276 + 1.277 + if (GetContentScrollbarVisibility()) 1.278 + *aChromeFlags |= nsIWebBrowserChrome::CHROME_SCROLLBARS; 1.279 + else 1.280 + *aChromeFlags &= ~nsIWebBrowserChrome::CHROME_SCROLLBARS; 1.281 + 1.282 + return NS_OK; 1.283 +} 1.284 + 1.285 +NS_IMETHODIMP nsXULWindow::SetChromeFlags(uint32_t aChromeFlags) 1.286 +{ 1.287 + NS_ASSERTION(!mChromeFlagsFrozen, 1.288 + "SetChromeFlags() after AssumeChromeFlagsAreFrozen()!"); 1.289 + 1.290 + mChromeFlags = aChromeFlags; 1.291 + if (mChromeLoaded) 1.292 + NS_ENSURE_SUCCESS(ApplyChromeFlags(), NS_ERROR_FAILURE); 1.293 + return NS_OK; 1.294 +} 1.295 + 1.296 +NS_IMETHODIMP nsXULWindow::AssumeChromeFlagsAreFrozen() 1.297 +{ 1.298 + mChromeFlagsFrozen = true; 1.299 + return NS_OK; 1.300 +} 1.301 + 1.302 +NS_IMETHODIMP nsXULWindow::SetIntrinsicallySized(bool aIntrinsicallySized) 1.303 +{ 1.304 + mIntrinsicallySized = aIntrinsicallySized; 1.305 + return NS_OK; 1.306 +} 1.307 + 1.308 +NS_IMETHODIMP nsXULWindow::GetIntrinsicallySized(bool* aIntrinsicallySized) 1.309 +{ 1.310 + NS_ENSURE_ARG_POINTER(aIntrinsicallySized); 1.311 + 1.312 + *aIntrinsicallySized = mIntrinsicallySized; 1.313 + return NS_OK; 1.314 +} 1.315 + 1.316 +NS_IMETHODIMP nsXULWindow::GetPrimaryContentShell(nsIDocShellTreeItem** 1.317 + aDocShellTreeItem) 1.318 +{ 1.319 + NS_ENSURE_ARG_POINTER(aDocShellTreeItem); 1.320 + NS_IF_ADDREF(*aDocShellTreeItem = mPrimaryContentShell); 1.321 + return NS_OK; 1.322 +} 1.323 + 1.324 +NS_IMETHODIMP nsXULWindow::GetContentShellById(const char16_t* aID, 1.325 + nsIDocShellTreeItem** aDocShellTreeItem) 1.326 +{ 1.327 + NS_ENSURE_ARG_POINTER(aDocShellTreeItem); 1.328 + *aDocShellTreeItem = nullptr; 1.329 + 1.330 + uint32_t count = mContentShells.Length(); 1.331 + for (uint32_t i = 0; i < count; i++) { 1.332 + nsContentShellInfo* shellInfo = mContentShells.ElementAt(i); 1.333 + if (shellInfo->id.Equals(aID)) { 1.334 + *aDocShellTreeItem = nullptr; 1.335 + if (shellInfo->child) 1.336 + CallQueryReferent(shellInfo->child.get(), aDocShellTreeItem); 1.337 + return NS_OK; 1.338 + } 1.339 + } 1.340 + return NS_ERROR_FAILURE; 1.341 +} 1.342 + 1.343 +NS_IMETHODIMP nsXULWindow::AddChildWindow(nsIXULWindow *aChild) 1.344 +{ 1.345 + // we're not really keeping track of this right now 1.346 + return NS_OK; 1.347 +} 1.348 + 1.349 +NS_IMETHODIMP nsXULWindow::RemoveChildWindow(nsIXULWindow *aChild) 1.350 +{ 1.351 + // we're not really keeping track of this right now 1.352 + return NS_OK; 1.353 +} 1.354 + 1.355 +NS_IMETHODIMP nsXULWindow::ShowModal() 1.356 +{ 1.357 + // Store locally so it doesn't die on us 1.358 + nsCOMPtr<nsIWidget> window = mWindow; 1.359 + nsCOMPtr<nsIXULWindow> tempRef = this; 1.360 + 1.361 + window->SetModal(true); 1.362 + mContinueModalLoop = true; 1.363 + EnableParent(false); 1.364 + 1.365 + { 1.366 + AutoNoJSAPI nojsapi; 1.367 + nsIThread *thread = NS_GetCurrentThread(); 1.368 + while (mContinueModalLoop) { 1.369 + if (!NS_ProcessNextEvent(thread)) 1.370 + break; 1.371 + } 1.372 + } 1.373 + 1.374 + mContinueModalLoop = false; 1.375 + window->SetModal(false); 1.376 + /* Note there's no EnableParent(true) here to match the false one 1.377 + above. That's done in ExitModalLoop. It's important that the parent 1.378 + be re-enabled before this window is made invisible; to do otherwise 1.379 + causes bizarre z-ordering problems. At this point, the window is 1.380 + already invisible. 1.381 + No known current implementation of Enable would have a problem with 1.382 + re-enabling the parent twice, so we could do it again here without 1.383 + breaking any current implementation. But that's unnecessary if the 1.384 + modal loop is always exited using ExitModalLoop (the other way would be 1.385 + to change the protected member variable directly.) 1.386 + */ 1.387 + 1.388 + return mModalStatus; 1.389 +} 1.390 + 1.391 +//***************************************************************************** 1.392 +// nsXULWindow::nsIBaseWindow 1.393 +//***************************************************************************** 1.394 + 1.395 +NS_IMETHODIMP nsXULWindow::InitWindow(nativeWindow aParentNativeWindow, 1.396 + nsIWidget* parentWidget, int32_t x, int32_t y, int32_t cx, int32_t cy) 1.397 +{ 1.398 + //XXX First Check In 1.399 + NS_ASSERTION(false, "Not Yet Implemented"); 1.400 + return NS_OK; 1.401 +} 1.402 + 1.403 +NS_IMETHODIMP nsXULWindow::Create() 1.404 +{ 1.405 + //XXX First Check In 1.406 + NS_ASSERTION(false, "Not Yet Implemented"); 1.407 + return NS_OK; 1.408 +} 1.409 + 1.410 +NS_IMETHODIMP nsXULWindow::Destroy() 1.411 +{ 1.412 + if (!mWindow) 1.413 + return NS_OK; 1.414 + 1.415 + // Ensure we don't reenter this code 1.416 + if (mDestroying) 1.417 + return NS_OK; 1.418 + 1.419 + mozilla::AutoRestore<bool> guard(mDestroying); 1.420 + mDestroying = true; 1.421 + 1.422 + nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); 1.423 + NS_ASSERTION(appShell, "Couldn't get appShell... xpcom shutdown?"); 1.424 + if (appShell) 1.425 + appShell->UnregisterTopLevelWindow(static_cast<nsIXULWindow*>(this)); 1.426 + 1.427 + nsCOMPtr<nsIXULWindow> parentWindow(do_QueryReferent(mParentWindow)); 1.428 + if (parentWindow) 1.429 + parentWindow->RemoveChildWindow(this); 1.430 + 1.431 + // let's make sure the window doesn't get deleted out from under us 1.432 + // while we are trying to close....this can happen if the docshell 1.433 + // we close ends up being the last owning reference to this xulwindow 1.434 + 1.435 + // XXXTAB This shouldn't be an issue anymore because the ownership model 1.436 + // only goes in one direction. When webshell container is fully removed 1.437 + // try removing this... 1.438 + 1.439 + nsCOMPtr<nsIXULWindow> placeHolder = this; 1.440 + 1.441 + // Remove modality (if any) and hide while destroying. More than 1.442 + // a convenience, the hide prevents user interaction with the partially 1.443 + // destroyed window. This is especially necessary when the eldest window 1.444 + // in a stack of modal windows is destroyed first. It happens. 1.445 + ExitModalLoop(NS_OK); 1.446 + if (mWindow) 1.447 + mWindow->Show(false); 1.448 + 1.449 +#if defined(XP_WIN) 1.450 + // We need to explicitly set the focus on Windows, but 1.451 + // only if the parent is visible. 1.452 + nsCOMPtr<nsIBaseWindow> parent(do_QueryReferent(mParentWindow)); 1.453 + if (parent) { 1.454 + nsCOMPtr<nsIWidget> parentWidget; 1.455 + parent->GetMainWidget(getter_AddRefs(parentWidget)); 1.456 + if (!parentWidget || parentWidget->IsVisible()) { 1.457 + nsCOMPtr<nsIBaseWindow> baseHiddenWindow; 1.458 + if (appShell) { 1.459 + nsCOMPtr<nsIXULWindow> hiddenWindow; 1.460 + appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow)); 1.461 + if (hiddenWindow) 1.462 + baseHiddenWindow = do_GetInterface(hiddenWindow); 1.463 + } 1.464 + // somebody screwed up somewhere. hiddenwindow shouldn't be anybody's 1.465 + // parent. still, when it happens, skip activating it. 1.466 + if (baseHiddenWindow != parent) { 1.467 + nsCOMPtr<nsIWidget> parentWidget; 1.468 + parent->GetMainWidget(getter_AddRefs(parentWidget)); 1.469 + if (parentWidget) 1.470 + parentWidget->PlaceBehind(eZPlacementTop, 0, true); 1.471 + } 1.472 + } 1.473 + } 1.474 +#endif 1.475 + 1.476 + mDOMWindow = nullptr; 1.477 + if (mDocShell) { 1.478 + nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(mDocShell)); 1.479 + shellAsWin->Destroy(); 1.480 + mDocShell = nullptr; // this can cause reentrancy of this function 1.481 + } 1.482 + 1.483 + // Remove our ref on the content shells 1.484 + uint32_t count = mContentShells.Length(); 1.485 + for (uint32_t i = 0; i < count; i++) { 1.486 + nsContentShellInfo* shellInfo = mContentShells.ElementAt(i); 1.487 + delete shellInfo; 1.488 + } 1.489 + mContentShells.Clear(); 1.490 + mPrimaryContentShell = nullptr; 1.491 + 1.492 + if (mContentTreeOwner) { 1.493 + mContentTreeOwner->XULWindow(nullptr); 1.494 + NS_RELEASE(mContentTreeOwner); 1.495 + } 1.496 + if (mPrimaryContentTreeOwner) { 1.497 + mPrimaryContentTreeOwner->XULWindow(nullptr); 1.498 + NS_RELEASE(mPrimaryContentTreeOwner); 1.499 + } 1.500 + if (mChromeTreeOwner) { 1.501 + mChromeTreeOwner->XULWindow(nullptr); 1.502 + NS_RELEASE(mChromeTreeOwner); 1.503 + } 1.504 + if (mWindow) { 1.505 + mWindow->SetWidgetListener(nullptr); // nsWebShellWindow hackery 1.506 + mWindow->Destroy(); 1.507 + mWindow = nullptr; 1.508 + } 1.509 + 1.510 + if (!mIsHiddenWindow) { 1.511 + /* Inform appstartup we've destroyed this window and it could 1.512 + quit now if it wanted. This must happen at least after mDocShell 1.513 + is destroyed, because onunload handlers fire then, and those being 1.514 + script, anything could happen. A new window could open, even. 1.515 + See bug 130719. */ 1.516 + nsCOMPtr<nsIObserverService> obssvc = 1.517 + do_GetService("@mozilla.org/observer-service;1"); 1.518 + NS_ASSERTION(obssvc, "Couldn't get observer service?"); 1.519 + 1.520 + if (obssvc) 1.521 + obssvc->NotifyObservers(nullptr, "xul-window-destroyed", nullptr); 1.522 + } 1.523 + 1.524 + return NS_OK; 1.525 +} 1.526 + 1.527 +NS_IMETHODIMP nsXULWindow::GetUnscaledDevicePixelsPerCSSPixel(double *aScale) 1.528 +{ 1.529 + *aScale = mWindow ? mWindow->GetDefaultScale().scale : 1.0; 1.530 + return NS_OK; 1.531 +} 1.532 + 1.533 +NS_IMETHODIMP nsXULWindow::SetPosition(int32_t aX, int32_t aY) 1.534 +{ 1.535 + // Don't reset the window's size mode here - platforms that don't want to move 1.536 + // maximized windows should reset it in their respective Move implementation. 1.537 + CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale(); 1.538 + double invScale = 1.0 / scale.scale; 1.539 + nsresult rv = mWindow->Move(aX * invScale, aY * invScale); 1.540 + NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); 1.541 + if (!mChromeLoaded) { 1.542 + // If we're called before the chrome is loaded someone obviously wants this 1.543 + // window at this position. We don't persist this one-time position. 1.544 + mIgnoreXULPosition = true; 1.545 + return NS_OK; 1.546 + } 1.547 + PersistentAttributesDirty(PAD_POSITION); 1.548 + SavePersistentAttributes(); 1.549 + return NS_OK; 1.550 +} 1.551 + 1.552 +NS_IMETHODIMP nsXULWindow::GetPosition(int32_t* aX, int32_t* aY) 1.553 +{ 1.554 + return GetPositionAndSize(aX, aY, nullptr, nullptr); 1.555 +} 1.556 + 1.557 +NS_IMETHODIMP nsXULWindow::SetSize(int32_t aCX, int32_t aCY, bool aRepaint) 1.558 +{ 1.559 + /* any attempt to set the window's size or position overrides the window's 1.560 + zoom state. this is important when these two states are competing while 1.561 + the window is being opened. but it should probably just always be so. */ 1.562 + mWindow->SetSizeMode(nsSizeMode_Normal); 1.563 + 1.564 + mIntrinsicallySized = false; 1.565 + 1.566 + CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale(); 1.567 + double invScale = 1.0 / scale.scale; 1.568 + nsresult rv = mWindow->Resize(aCX * invScale, aCY * invScale, aRepaint); 1.569 + NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); 1.570 + if (!mChromeLoaded) { 1.571 + // If we're called before the chrome is loaded someone obviously wants this 1.572 + // window at this size & in the normal size mode (since it is the only mode 1.573 + // in which setting dimensions makes sense). We don't persist this one-time 1.574 + // size. 1.575 + mIgnoreXULSize = true; 1.576 + mIgnoreXULSizeMode = true; 1.577 + return NS_OK; 1.578 + } 1.579 + PersistentAttributesDirty(PAD_SIZE); 1.580 + SavePersistentAttributes(); 1.581 + return NS_OK; 1.582 +} 1.583 + 1.584 +NS_IMETHODIMP nsXULWindow::GetSize(int32_t* aCX, int32_t* aCY) 1.585 +{ 1.586 + return GetPositionAndSize(nullptr, nullptr, aCX, aCY); 1.587 +} 1.588 + 1.589 +NS_IMETHODIMP nsXULWindow::SetPositionAndSize(int32_t aX, int32_t aY, 1.590 + int32_t aCX, int32_t aCY, bool aRepaint) 1.591 +{ 1.592 + /* any attempt to set the window's size or position overrides the window's 1.593 + zoom state. this is important when these two states are competing while 1.594 + the window is being opened. but it should probably just always be so. */ 1.595 + mWindow->SetSizeMode(nsSizeMode_Normal); 1.596 + 1.597 + mIntrinsicallySized = false; 1.598 + 1.599 + CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale(); 1.600 + double invScale = 1.0 / scale.scale; 1.601 + nsresult rv = mWindow->Resize(aX * invScale, aY * invScale, 1.602 + aCX * invScale, aCY * invScale, 1.603 + aRepaint); 1.604 + NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); 1.605 + if (!mChromeLoaded) { 1.606 + // If we're called before the chrome is loaded someone obviously wants this 1.607 + // window at this size and position. We don't persist this one-time setting. 1.608 + mIgnoreXULPosition = true; 1.609 + mIgnoreXULSize = true; 1.610 + mIgnoreXULSizeMode = true; 1.611 + return NS_OK; 1.612 + } 1.613 + PersistentAttributesDirty(PAD_POSITION | PAD_SIZE); 1.614 + SavePersistentAttributes(); 1.615 + return NS_OK; 1.616 +} 1.617 + 1.618 +NS_IMETHODIMP nsXULWindow::GetPositionAndSize(int32_t* x, int32_t* y, int32_t* cx, 1.619 + int32_t* cy) 1.620 +{ 1.621 + nsIntRect rect; 1.622 + 1.623 + if (!mWindow) 1.624 + return NS_ERROR_FAILURE; 1.625 + 1.626 + mWindow->GetScreenBounds(rect); 1.627 + 1.628 + if (x) 1.629 + *x = rect.x; 1.630 + if (y) 1.631 + *y = rect.y; 1.632 + if (cx) 1.633 + *cx = rect.width; 1.634 + if (cy) 1.635 + *cy = rect.height; 1.636 + 1.637 + return NS_OK; 1.638 +} 1.639 + 1.640 +NS_IMETHODIMP nsXULWindow::Center(nsIXULWindow *aRelative, bool aScreen, bool aAlert) 1.641 +{ 1.642 + int32_t left, top, width, height, 1.643 + ourWidth, ourHeight; 1.644 + bool screenCoordinates = false, 1.645 + windowCoordinates = false; 1.646 + nsresult result; 1.647 + 1.648 + if (!mChromeLoaded) { 1.649 + // note we lose the parameters. at time of writing, this isn't a problem. 1.650 + mCenterAfterLoad = true; 1.651 + return NS_OK; 1.652 + } 1.653 + 1.654 + if (!aScreen && !aRelative) 1.655 + return NS_ERROR_INVALID_ARG; 1.656 + 1.657 + nsCOMPtr<nsIScreenManager> screenmgr = do_GetService("@mozilla.org/gfx/screenmanager;1", &result); 1.658 + if (NS_FAILED(result)) 1.659 + return result; 1.660 + 1.661 + nsCOMPtr<nsIScreen> screen; 1.662 + 1.663 + if (aRelative) { 1.664 + nsCOMPtr<nsIBaseWindow> base(do_QueryInterface(aRelative, &result)); 1.665 + if (base) { 1.666 + // get window rect 1.667 + result = base->GetPositionAndSize(&left, &top, &width, &height); 1.668 + if (NS_SUCCEEDED(result)) { 1.669 + double scale; 1.670 + if (NS_SUCCEEDED(base->GetUnscaledDevicePixelsPerCSSPixel(&scale))) { 1.671 + // convert device-pixel coordinates to global display pixels 1.672 + left = NSToIntRound(left / scale); 1.673 + top = NSToIntRound(top / scale); 1.674 + width = NSToIntRound(width / scale); 1.675 + height = NSToIntRound(height / scale); 1.676 + } 1.677 + // if centering on screen, convert that to the corresponding screen 1.678 + if (aScreen) 1.679 + screenmgr->ScreenForRect(left, top, width, height, getter_AddRefs(screen)); 1.680 + else 1.681 + windowCoordinates = true; 1.682 + } else { 1.683 + // something's wrong with the reference window. 1.684 + // fall back to the primary screen 1.685 + aRelative = 0; 1.686 + aScreen = true; 1.687 + } 1.688 + } 1.689 + } 1.690 + if (!aRelative) { 1.691 + if (!mOpenerScreenRect.IsEmpty()) { 1.692 + // FIXME - check if these are device or display pixels 1.693 + screenmgr->ScreenForRect(mOpenerScreenRect.x, mOpenerScreenRect.y, 1.694 + mOpenerScreenRect.width, mOpenerScreenRect.height, 1.695 + getter_AddRefs(screen)); 1.696 + } else { 1.697 + screenmgr->GetPrimaryScreen(getter_AddRefs(screen)); 1.698 + } 1.699 + } 1.700 + 1.701 + if (aScreen && screen) { 1.702 + screen->GetAvailRectDisplayPix(&left, &top, &width, &height); 1.703 + screenCoordinates = true; 1.704 + } 1.705 + 1.706 + if (screenCoordinates || windowCoordinates) { 1.707 + NS_ASSERTION(mWindow, "what, no window?"); 1.708 + CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale(); 1.709 + GetSize(&ourWidth, &ourHeight); 1.710 + ourWidth = NSToIntRound(ourWidth / scale.scale); 1.711 + ourHeight = NSToIntRound(ourHeight / scale.scale); 1.712 + left += (width - ourWidth) / 2; 1.713 + top += (height - ourHeight) / (aAlert ? 3 : 2); 1.714 + if (windowCoordinates) { 1.715 + mWindow->ConstrainPosition(false, &left, &top); 1.716 + } 1.717 + SetPosition(left * scale.scale, top * scale.scale); 1.718 + return NS_OK; 1.719 + } 1.720 + return NS_ERROR_FAILURE; 1.721 +} 1.722 + 1.723 +NS_IMETHODIMP nsXULWindow::Repaint(bool aForce) 1.724 +{ 1.725 + //XXX First Check In 1.726 + NS_ASSERTION(false, "Not Yet Implemented"); 1.727 + return NS_OK; 1.728 +} 1.729 + 1.730 +NS_IMETHODIMP nsXULWindow::GetParentWidget(nsIWidget** aParentWidget) 1.731 +{ 1.732 + NS_ENSURE_ARG_POINTER(aParentWidget); 1.733 + NS_ENSURE_STATE(mWindow); 1.734 + 1.735 + NS_IF_ADDREF(*aParentWidget = mWindow->GetParent()); 1.736 + return NS_OK; 1.737 +} 1.738 + 1.739 +NS_IMETHODIMP nsXULWindow::SetParentWidget(nsIWidget* aParentWidget) 1.740 +{ 1.741 + //XXX First Check In 1.742 + NS_ASSERTION(false, "Not Yet Implemented"); 1.743 + return NS_OK; 1.744 +} 1.745 + 1.746 +NS_IMETHODIMP nsXULWindow::GetParentNativeWindow(nativeWindow* aParentNativeWindow) 1.747 +{ 1.748 + NS_ENSURE_ARG_POINTER(aParentNativeWindow); 1.749 + 1.750 + nsCOMPtr<nsIWidget> parentWidget; 1.751 + NS_ENSURE_SUCCESS(GetParentWidget(getter_AddRefs(parentWidget)), NS_ERROR_FAILURE); 1.752 + 1.753 + if (parentWidget) { 1.754 + *aParentNativeWindow = parentWidget->GetNativeData(NS_NATIVE_WIDGET); 1.755 + } 1.756 + 1.757 + return NS_OK; 1.758 +} 1.759 + 1.760 +NS_IMETHODIMP nsXULWindow::SetParentNativeWindow(nativeWindow aParentNativeWindow) 1.761 +{ 1.762 + //XXX First Check In 1.763 + NS_ASSERTION(false, "Not Yet Implemented"); 1.764 + return NS_OK; 1.765 +} 1.766 + 1.767 +NS_IMETHODIMP nsXULWindow::GetNativeHandle(nsAString& aNativeHandle) 1.768 +{ 1.769 + nsCOMPtr<nsIWidget> mainWidget; 1.770 + NS_ENSURE_SUCCESS(GetMainWidget(getter_AddRefs(mainWidget)), NS_ERROR_FAILURE); 1.771 + 1.772 + if (mainWidget) { 1.773 + nativeWindow nativeWindowPtr = mainWidget->GetNativeData(NS_NATIVE_WINDOW); 1.774 + /* the nativeWindow pointer is converted to and exposed as a string. This 1.775 + is a more reliable way not to lose information (as opposed to JS 1.776 + |Number| for instance) */ 1.777 + aNativeHandle = NS_ConvertASCIItoUTF16(nsPrintfCString("0x%p", nativeWindowPtr)); 1.778 + } 1.779 + 1.780 + return NS_OK; 1.781 +} 1.782 + 1.783 +NS_IMETHODIMP nsXULWindow::GetVisibility(bool* aVisibility) 1.784 +{ 1.785 + NS_ENSURE_ARG_POINTER(aVisibility); 1.786 + 1.787 + // Always claim to be visible for now. See bug 1.788 + // https://bugzilla.mozilla.org/show_bug.cgi?id=306245. 1.789 + 1.790 + *aVisibility = true; 1.791 + 1.792 + return NS_OK; 1.793 +} 1.794 + 1.795 +NS_IMETHODIMP nsXULWindow::SetVisibility(bool aVisibility) 1.796 +{ 1.797 + if (!mChromeLoaded) { 1.798 + mShowAfterLoad = aVisibility; 1.799 + return NS_OK; 1.800 + } 1.801 + 1.802 + if (mDebuting) { 1.803 + return NS_OK; 1.804 + } 1.805 + mDebuting = true; // (Show / Focus is recursive) 1.806 + 1.807 + //XXXTAB Do we really need to show docshell and the window? Isn't 1.808 + // the window good enough? 1.809 + nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(mDocShell)); 1.810 + shellAsWin->SetVisibility(aVisibility); 1.811 + // Store locally so it doesn't die on us. 'Show' can result in the window 1.812 + // being closed with nsXULWindow::Destroy being called. That would set 1.813 + // mWindow to null and posibly destroy the nsIWidget while its Show method 1.814 + // is on the stack. We need to keep it alive until Show finishes. 1.815 + nsCOMPtr<nsIWidget> window = mWindow; 1.816 + window->Show(aVisibility); 1.817 + 1.818 + nsCOMPtr<nsIWindowMediator> windowMediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); 1.819 + if (windowMediator) 1.820 + windowMediator->UpdateWindowTimeStamp(static_cast<nsIXULWindow*>(this)); 1.821 + 1.822 + // notify observers so that we can hide the splash screen if possible 1.823 + nsCOMPtr<nsIObserverService> obssvc 1.824 + (do_GetService("@mozilla.org/observer-service;1")); 1.825 + NS_ASSERTION(obssvc, "Couldn't get observer service."); 1.826 + if (obssvc) { 1.827 + obssvc->NotifyObservers(nullptr, "xul-window-visible", nullptr); 1.828 + } 1.829 + 1.830 + mDebuting = false; 1.831 + return NS_OK; 1.832 +} 1.833 + 1.834 +NS_IMETHODIMP nsXULWindow::GetEnabled(bool *aEnabled) 1.835 +{ 1.836 + NS_ENSURE_ARG_POINTER(aEnabled); 1.837 + 1.838 + if (mWindow) { 1.839 + *aEnabled = mWindow->IsEnabled(); 1.840 + return NS_OK; 1.841 + } 1.842 + 1.843 + *aEnabled = true; // better guess than most 1.844 + return NS_ERROR_FAILURE; 1.845 +} 1.846 + 1.847 +NS_IMETHODIMP nsXULWindow::SetEnabled(bool aEnable) 1.848 +{ 1.849 + if (mWindow) { 1.850 + mWindow->Enable(aEnable); 1.851 + return NS_OK; 1.852 + } 1.853 + return NS_ERROR_FAILURE; 1.854 +} 1.855 + 1.856 +NS_IMETHODIMP nsXULWindow::GetMainWidget(nsIWidget** aMainWidget) 1.857 +{ 1.858 + NS_ENSURE_ARG_POINTER(aMainWidget); 1.859 + 1.860 + *aMainWidget = mWindow; 1.861 + NS_IF_ADDREF(*aMainWidget); 1.862 + return NS_OK; 1.863 +} 1.864 + 1.865 +NS_IMETHODIMP nsXULWindow::SetFocus() 1.866 +{ 1.867 + //XXX First Check In 1.868 + NS_ASSERTION(false, "Not Yet Implemented"); 1.869 + return NS_OK; 1.870 +} 1.871 + 1.872 +NS_IMETHODIMP nsXULWindow::GetTitle(char16_t** aTitle) 1.873 +{ 1.874 + NS_ENSURE_ARG_POINTER(aTitle); 1.875 + 1.876 + *aTitle = ToNewUnicode(mTitle); 1.877 + if (!*aTitle) 1.878 + return NS_ERROR_OUT_OF_MEMORY; 1.879 + return NS_OK; 1.880 +} 1.881 + 1.882 +NS_IMETHODIMP nsXULWindow::SetTitle(const char16_t* aTitle) 1.883 +{ 1.884 + NS_ENSURE_STATE(mWindow); 1.885 + mTitle.Assign(aTitle); 1.886 + mTitle.StripChars("\n\r"); 1.887 + NS_ENSURE_SUCCESS(mWindow->SetTitle(mTitle), NS_ERROR_FAILURE); 1.888 + 1.889 + // Tell the window mediator that a title has changed 1.890 + nsCOMPtr<nsIWindowMediator> windowMediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); 1.891 + if (!windowMediator) 1.892 + return NS_OK; 1.893 + 1.894 + windowMediator->UpdateWindowTitle(static_cast<nsIXULWindow*>(this), aTitle); 1.895 + 1.896 + return NS_OK; 1.897 +} 1.898 + 1.899 + 1.900 +//***************************************************************************** 1.901 +// nsXULWindow: Helpers 1.902 +//***************************************************************************** 1.903 + 1.904 +NS_IMETHODIMP nsXULWindow::EnsureChromeTreeOwner() 1.905 +{ 1.906 + if (mChromeTreeOwner) 1.907 + return NS_OK; 1.908 + 1.909 + mChromeTreeOwner = new nsChromeTreeOwner(); 1.910 + NS_ENSURE_TRUE(mChromeTreeOwner, NS_ERROR_OUT_OF_MEMORY); 1.911 + 1.912 + NS_ADDREF(mChromeTreeOwner); 1.913 + mChromeTreeOwner->XULWindow(this); 1.914 + 1.915 + return NS_OK; 1.916 +} 1.917 + 1.918 +NS_IMETHODIMP nsXULWindow::EnsureContentTreeOwner() 1.919 +{ 1.920 + if (mContentTreeOwner) 1.921 + return NS_OK; 1.922 + 1.923 + mContentTreeOwner = new nsContentTreeOwner(false); 1.924 + NS_ENSURE_TRUE(mContentTreeOwner, NS_ERROR_FAILURE); 1.925 + 1.926 + NS_ADDREF(mContentTreeOwner); 1.927 + mContentTreeOwner->XULWindow(this); 1.928 + 1.929 + return NS_OK; 1.930 +} 1.931 + 1.932 +NS_IMETHODIMP nsXULWindow::EnsurePrimaryContentTreeOwner() 1.933 +{ 1.934 + if (mPrimaryContentTreeOwner) 1.935 + return NS_OK; 1.936 + 1.937 + mPrimaryContentTreeOwner = new nsContentTreeOwner(true); 1.938 + NS_ENSURE_TRUE(mPrimaryContentTreeOwner, NS_ERROR_FAILURE); 1.939 + 1.940 + NS_ADDREF(mPrimaryContentTreeOwner); 1.941 + mPrimaryContentTreeOwner->XULWindow(this); 1.942 + 1.943 + return NS_OK; 1.944 +} 1.945 + 1.946 +NS_IMETHODIMP nsXULWindow::EnsurePrompter() 1.947 +{ 1.948 + if (mPrompter) 1.949 + return NS_OK; 1.950 + 1.951 + nsCOMPtr<nsIDOMWindow> ourWindow; 1.952 + nsresult rv = GetWindowDOMWindow(getter_AddRefs(ourWindow)); 1.953 + if (NS_SUCCEEDED(rv)) { 1.954 + nsCOMPtr<nsIWindowWatcher> wwatch = 1.955 + do_GetService(NS_WINDOWWATCHER_CONTRACTID); 1.956 + if (wwatch) 1.957 + wwatch->GetNewPrompter(ourWindow, getter_AddRefs(mPrompter)); 1.958 + } 1.959 + return mPrompter ? NS_OK : NS_ERROR_FAILURE; 1.960 +} 1.961 + 1.962 +NS_IMETHODIMP nsXULWindow::EnsureAuthPrompter() 1.963 +{ 1.964 + if (mAuthPrompter) 1.965 + return NS_OK; 1.966 + 1.967 + nsCOMPtr<nsIDOMWindow> ourWindow; 1.968 + nsresult rv = GetWindowDOMWindow(getter_AddRefs(ourWindow)); 1.969 + if (NS_SUCCEEDED(rv)) { 1.970 + nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); 1.971 + if (wwatch) 1.972 + wwatch->GetNewAuthPrompter(ourWindow, getter_AddRefs(mAuthPrompter)); 1.973 + } 1.974 + return mAuthPrompter ? NS_OK : NS_ERROR_FAILURE; 1.975 +} 1.976 + 1.977 +void nsXULWindow::OnChromeLoaded() 1.978 +{ 1.979 + nsresult rv = EnsureContentTreeOwner(); 1.980 + 1.981 + if (NS_SUCCEEDED(rv)) { 1.982 + mChromeLoaded = true; 1.983 + ApplyChromeFlags(); 1.984 + SyncAttributesToWidget(); 1.985 + if (!mIgnoreXULSize) 1.986 + LoadSizeFromXUL(); 1.987 + if (mIntrinsicallySized) { 1.988 + // (if LoadSizeFromXUL set the size, mIntrinsicallySized will be false) 1.989 + nsCOMPtr<nsIContentViewer> cv; 1.990 + mDocShell->GetContentViewer(getter_AddRefs(cv)); 1.991 + nsCOMPtr<nsIMarkupDocumentViewer> markupViewer = do_QueryInterface(cv); 1.992 + if (markupViewer) { 1.993 + nsCOMPtr<nsIDocShellTreeItem> docShellAsItem = do_QueryInterface(mDocShell); 1.994 + nsCOMPtr<nsIDocShellTreeOwner> treeOwner; 1.995 + docShellAsItem->GetTreeOwner(getter_AddRefs(treeOwner)); 1.996 + if (treeOwner) { 1.997 + int32_t width, height; 1.998 + markupViewer->GetContentSize(&width, &height); 1.999 + treeOwner->SizeShellTo(docShellAsItem, width, height); 1.1000 + } 1.1001 + } 1.1002 + } 1.1003 + 1.1004 + bool positionSet = !mIgnoreXULPosition; 1.1005 + nsCOMPtr<nsIXULWindow> parentWindow(do_QueryReferent(mParentWindow)); 1.1006 +#if defined(XP_UNIX) && !defined(XP_MACOSX) 1.1007 + // don't override WM placement on unix for independent, top-level windows 1.1008 + // (however, we think the benefits of intelligent dependent window placement 1.1009 + // trump that override.) 1.1010 + if (!parentWindow) 1.1011 + positionSet = false; 1.1012 +#endif 1.1013 + if (positionSet) 1.1014 + positionSet = LoadPositionFromXUL(); 1.1015 + LoadMiscPersistentAttributesFromXUL(); 1.1016 + 1.1017 + if (mCenterAfterLoad && !positionSet) 1.1018 + Center(parentWindow, parentWindow ? false : true, false); 1.1019 + 1.1020 + if (mShowAfterLoad) { 1.1021 + SetVisibility(true); 1.1022 + // At this point the window may have been closed during Show(), so 1.1023 + // nsXULWindow::Destroy may already have been called. Take care! 1.1024 + } 1.1025 + } 1.1026 + mPersistentAttributesMask |= PAD_POSITION | PAD_SIZE | PAD_MISC; 1.1027 +} 1.1028 + 1.1029 +bool nsXULWindow::LoadPositionFromXUL() 1.1030 +{ 1.1031 + bool gotPosition = false; 1.1032 + 1.1033 + // if we're the hidden window, don't try to validate our size/position. We're 1.1034 + // special. 1.1035 + if (mIsHiddenWindow) 1.1036 + return false; 1.1037 + 1.1038 + nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement(); 1.1039 + NS_ENSURE_TRUE(windowElement, false); 1.1040 + 1.1041 + int32_t currX = 0; 1.1042 + int32_t currY = 0; 1.1043 + int32_t currWidth = 0; 1.1044 + int32_t currHeight = 0; 1.1045 + nsresult errorCode; 1.1046 + int32_t temp; 1.1047 + 1.1048 + GetPositionAndSize(&currX, &currY, &currWidth, &currHeight); 1.1049 + 1.1050 + // Convert to global display pixels for consistent window management across 1.1051 + // screens with diverse resolutions 1.1052 + CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale(); 1.1053 + currX = NSToIntRound(currX / scale.scale); 1.1054 + currY = NSToIntRound(currY / scale.scale); 1.1055 + currWidth = NSToIntRound(currWidth / scale.scale); 1.1056 + currHeight = NSToIntRound(currHeight / scale.scale); 1.1057 + 1.1058 + // Obtain the position information from the <xul:window> element. 1.1059 + int32_t specX = currX; 1.1060 + int32_t specY = currY; 1.1061 + nsAutoString posString; 1.1062 + 1.1063 + windowElement->GetAttribute(SCREENX_ATTRIBUTE, posString); 1.1064 + temp = posString.ToInteger(&errorCode); 1.1065 + if (NS_SUCCEEDED(errorCode)) { 1.1066 + specX = temp; 1.1067 + gotPosition = true; 1.1068 + } 1.1069 + windowElement->GetAttribute(SCREENY_ATTRIBUTE, posString); 1.1070 + temp = posString.ToInteger(&errorCode); 1.1071 + if (NS_SUCCEEDED(errorCode)) { 1.1072 + specY = temp; 1.1073 + gotPosition = true; 1.1074 + } 1.1075 + 1.1076 + if (gotPosition) { 1.1077 + // our position will be relative to our parent, if any 1.1078 + nsCOMPtr<nsIBaseWindow> parent(do_QueryReferent(mParentWindow)); 1.1079 + if (parent) { 1.1080 + int32_t parentX, parentY; 1.1081 + if (NS_SUCCEEDED(parent->GetPosition(&parentX, &parentY))) { 1.1082 + double scale; 1.1083 + if (NS_SUCCEEDED(parent->GetUnscaledDevicePixelsPerCSSPixel(&scale))) { 1.1084 + parentX = NSToIntRound(parentX / scale); 1.1085 + parentY = NSToIntRound(parentY / scale); 1.1086 + } 1.1087 + specX += parentX; 1.1088 + specY += parentY; 1.1089 + } 1.1090 + } 1.1091 + else { 1.1092 + StaggerPosition(specX, specY, currWidth, currHeight); 1.1093 + } 1.1094 + } 1.1095 + mWindow->ConstrainPosition(false, &specX, &specY); 1.1096 + if (specX != currX || specY != currY) { 1.1097 + CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale(); 1.1098 + SetPosition(specX * scale.scale, specY * scale.scale); 1.1099 + } 1.1100 + 1.1101 + return gotPosition; 1.1102 +} 1.1103 + 1.1104 +bool nsXULWindow::LoadSizeFromXUL() 1.1105 +{ 1.1106 + bool gotSize = false; 1.1107 + 1.1108 + // if we're the hidden window, don't try to validate our size/position. We're 1.1109 + // special. 1.1110 + if (mIsHiddenWindow) 1.1111 + return false; 1.1112 + 1.1113 + nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement(); 1.1114 + NS_ENSURE_TRUE(windowElement, false); 1.1115 + 1.1116 + int32_t currWidth = 0; 1.1117 + int32_t currHeight = 0; 1.1118 + nsresult errorCode; 1.1119 + int32_t temp; 1.1120 + 1.1121 + NS_ASSERTION(mWindow, "we expected to have a window already"); 1.1122 + 1.1123 + CSSToLayoutDeviceScale scale = mWindow ? mWindow->GetDefaultScale() 1.1124 + : CSSToLayoutDeviceScale(1.0); 1.1125 + GetSize(&currWidth, &currHeight); 1.1126 + currWidth = NSToIntRound(currWidth / scale.scale); 1.1127 + currHeight = NSToIntRound(currHeight / scale.scale); 1.1128 + 1.1129 + // Obtain the position and sizing information from the <xul:window> element. 1.1130 + int32_t specWidth = currWidth; 1.1131 + int32_t specHeight = currHeight; 1.1132 + nsAutoString sizeString; 1.1133 + 1.1134 + windowElement->GetAttribute(WIDTH_ATTRIBUTE, sizeString); 1.1135 + temp = sizeString.ToInteger(&errorCode); 1.1136 + if (NS_SUCCEEDED(errorCode) && temp > 0) { 1.1137 + specWidth = std::max(temp, 100); 1.1138 + gotSize = true; 1.1139 + } 1.1140 + windowElement->GetAttribute(HEIGHT_ATTRIBUTE, sizeString); 1.1141 + temp = sizeString.ToInteger(&errorCode); 1.1142 + if (NS_SUCCEEDED(errorCode) && temp > 0) { 1.1143 + specHeight = std::max(temp, 100); 1.1144 + gotSize = true; 1.1145 + } 1.1146 + 1.1147 + if (gotSize) { 1.1148 + // constrain to screen size 1.1149 + nsCOMPtr<nsIDOMWindow> domWindow; 1.1150 + GetWindowDOMWindow(getter_AddRefs(domWindow)); 1.1151 + if (domWindow) { 1.1152 + nsCOMPtr<nsIDOMScreen> screen; 1.1153 + domWindow->GetScreen(getter_AddRefs(screen)); 1.1154 + if (screen) { 1.1155 + int32_t screenWidth; 1.1156 + int32_t screenHeight; 1.1157 + screen->GetAvailWidth(&screenWidth); 1.1158 + screen->GetAvailHeight(&screenHeight); 1.1159 + if (specWidth > screenWidth) 1.1160 + specWidth = screenWidth; 1.1161 + if (specHeight > screenHeight) 1.1162 + specHeight = screenHeight; 1.1163 + } 1.1164 + } 1.1165 + 1.1166 + mIntrinsicallySized = false; 1.1167 + if (specWidth != currWidth || specHeight != currHeight) { 1.1168 + CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale(); 1.1169 + SetSize(specWidth * scale.scale, specHeight * scale.scale, false); 1.1170 + } 1.1171 + } 1.1172 + 1.1173 + return gotSize; 1.1174 +} 1.1175 + 1.1176 +/* Miscellaneous persistent attributes are attributes named in the 1.1177 + |persist| attribute, other than size and position. Those are special 1.1178 + because it's important to load those before one of the misc 1.1179 + attributes (sizemode) and they require extra processing. */ 1.1180 +bool nsXULWindow::LoadMiscPersistentAttributesFromXUL() 1.1181 +{ 1.1182 + bool gotState = false; 1.1183 + 1.1184 + /* There are no misc attributes of interest to the hidden window. 1.1185 + It's especially important not to try to validate that window's 1.1186 + size or position, because some platforms (Mac OS X) need to 1.1187 + make it visible and offscreen. */ 1.1188 + if (mIsHiddenWindow) 1.1189 + return false; 1.1190 + 1.1191 + nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement(); 1.1192 + NS_ENSURE_TRUE(windowElement, false); 1.1193 + 1.1194 + nsAutoString stateString; 1.1195 + 1.1196 + // sizemode 1.1197 + windowElement->GetAttribute(MODE_ATTRIBUTE, stateString); 1.1198 + int32_t sizeMode = nsSizeMode_Normal; 1.1199 + /* ignore request to minimize, to not confuse novices 1.1200 + if (stateString.Equals(SIZEMODE_MINIMIZED)) 1.1201 + sizeMode = nsSizeMode_Minimized; 1.1202 + */ 1.1203 + if (!mIgnoreXULSizeMode && 1.1204 + (stateString.Equals(SIZEMODE_MAXIMIZED) || stateString.Equals(SIZEMODE_FULLSCREEN))) { 1.1205 + /* Honor request to maximize only if the window is sizable. 1.1206 + An unsizable, unmaximizable, yet maximized window confuses 1.1207 + Windows OS and is something of a travesty, anyway. */ 1.1208 + if (mChromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE) { 1.1209 + mIntrinsicallySized = false; 1.1210 + 1.1211 + if (stateString.Equals(SIZEMODE_MAXIMIZED)) 1.1212 + sizeMode = nsSizeMode_Maximized; 1.1213 + else 1.1214 + sizeMode = nsSizeMode_Fullscreen; 1.1215 + } 1.1216 + } 1.1217 + 1.1218 + // If we are told to ignore the size mode attribute update the 1.1219 + // document so the attribute and window are in sync. 1.1220 + if (mIgnoreXULSizeMode) { 1.1221 + nsAutoString sizeString; 1.1222 + if (sizeMode == nsSizeMode_Maximized) 1.1223 + sizeString.Assign(SIZEMODE_MAXIMIZED); 1.1224 + else if (sizeMode == nsSizeMode_Fullscreen) 1.1225 + sizeString.Assign(SIZEMODE_FULLSCREEN); 1.1226 + else if (sizeMode == nsSizeMode_Normal) 1.1227 + sizeString.Assign(SIZEMODE_NORMAL); 1.1228 + if (!sizeString.IsEmpty()) { 1.1229 + ErrorResult rv; 1.1230 + windowElement->SetAttribute(MODE_ATTRIBUTE, sizeString, rv); 1.1231 + } 1.1232 + } 1.1233 + 1.1234 + if (sizeMode == nsSizeMode_Fullscreen) { 1.1235 + nsCOMPtr<nsIDOMWindow> ourWindow; 1.1236 + GetWindowDOMWindow(getter_AddRefs(ourWindow)); 1.1237 + ourWindow->SetFullScreen(true); 1.1238 + } else { 1.1239 + mWindow->SetSizeMode(sizeMode); 1.1240 + } 1.1241 + gotState = true; 1.1242 + 1.1243 + // zlevel 1.1244 + windowElement->GetAttribute(ZLEVEL_ATTRIBUTE, stateString); 1.1245 + if (!stateString.IsEmpty()) { 1.1246 + nsresult errorCode; 1.1247 + int32_t zLevel = stateString.ToInteger(&errorCode); 1.1248 + if (NS_SUCCEEDED(errorCode) && zLevel >= lowestZ && zLevel <= highestZ) 1.1249 + SetZLevel(zLevel); 1.1250 + } 1.1251 + 1.1252 + return gotState; 1.1253 +} 1.1254 + 1.1255 +/* Stagger windows of the same type so they don't appear on top of each other. 1.1256 + This code does have a scary double loop -- it'll keep passing through 1.1257 + the entire list of open windows until it finds a non-collision. Doesn't 1.1258 + seem to be a problem, but it deserves watching. 1.1259 +*/ 1.1260 +void nsXULWindow::StaggerPosition(int32_t &aRequestedX, int32_t &aRequestedY, 1.1261 + int32_t aSpecWidth, int32_t aSpecHeight) 1.1262 +{ 1.1263 + const int32_t kOffset = 22; 1.1264 + const uint32_t kSlop = 4; 1.1265 + 1.1266 + bool keepTrying; 1.1267 + int bouncedX = 0, // bounced off vertical edge of screen 1.1268 + bouncedY = 0; // bounced off horizontal edge 1.1269 + 1.1270 + // look for any other windows of this type 1.1271 + nsCOMPtr<nsIWindowMediator> wm(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); 1.1272 + if (!wm) 1.1273 + return; 1.1274 + 1.1275 + nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement(); 1.1276 + if (!windowElement) 1.1277 + return; 1.1278 + 1.1279 + nsCOMPtr<nsIXULWindow> ourXULWindow(this); 1.1280 + 1.1281 + nsAutoString windowType; 1.1282 + windowElement->GetAttribute(WINDOWTYPE_ATTRIBUTE, windowType); 1.1283 + 1.1284 + int32_t screenTop = 0, // it's pointless to initialize these ... 1.1285 + screenRight = 0, // ... but to prevent oversalubrious and ... 1.1286 + screenBottom = 0, // ... underbright compilers from ... 1.1287 + screenLeft = 0; // ... issuing warnings. 1.1288 + bool gotScreen = false; 1.1289 + 1.1290 + { // fetch screen coordinates 1.1291 + nsCOMPtr<nsIScreenManager> screenMgr(do_GetService( 1.1292 + "@mozilla.org/gfx/screenmanager;1")); 1.1293 + if (screenMgr) { 1.1294 + nsCOMPtr<nsIScreen> ourScreen; 1.1295 + // the coordinates here are already display pixels 1.1296 + screenMgr->ScreenForRect(aRequestedX, aRequestedY, 1.1297 + aSpecWidth, aSpecHeight, 1.1298 + getter_AddRefs(ourScreen)); 1.1299 + if (ourScreen) { 1.1300 + int32_t screenWidth, screenHeight; 1.1301 + ourScreen->GetAvailRectDisplayPix(&screenLeft, &screenTop, 1.1302 + &screenWidth, &screenHeight); 1.1303 + screenBottom = screenTop + screenHeight; 1.1304 + screenRight = screenLeft + screenWidth; 1.1305 + gotScreen = true; 1.1306 + } 1.1307 + } 1.1308 + } 1.1309 + 1.1310 + // One full pass through all windows of this type, repeat until no collisions. 1.1311 + do { 1.1312 + keepTrying = false; 1.1313 + nsCOMPtr<nsISimpleEnumerator> windowList; 1.1314 + wm->GetXULWindowEnumerator(windowType.get(), getter_AddRefs(windowList)); 1.1315 + 1.1316 + if (!windowList) 1.1317 + break; 1.1318 + 1.1319 + // One full pass through all windows of this type, offset and stop on collision. 1.1320 + do { 1.1321 + bool more; 1.1322 + windowList->HasMoreElements(&more); 1.1323 + if (!more) 1.1324 + break; 1.1325 + 1.1326 + nsCOMPtr<nsISupports> supportsWindow; 1.1327 + windowList->GetNext(getter_AddRefs(supportsWindow)); 1.1328 + 1.1329 + nsCOMPtr<nsIXULWindow> listXULWindow(do_QueryInterface(supportsWindow)); 1.1330 + if (listXULWindow != ourXULWindow) { 1.1331 + int32_t listX, listY; 1.1332 + nsCOMPtr<nsIBaseWindow> listBaseWindow(do_QueryInterface(supportsWindow)); 1.1333 + listBaseWindow->GetPosition(&listX, &listY); 1.1334 + double scale; 1.1335 + if (NS_SUCCEEDED(listBaseWindow->GetUnscaledDevicePixelsPerCSSPixel(&scale))) { 1.1336 + listX = NSToIntRound(listX / scale); 1.1337 + listY = NSToIntRound(listY / scale); 1.1338 + } 1.1339 + 1.1340 + if (Abs(listX - aRequestedX) <= kSlop && Abs(listY - aRequestedY) <= kSlop) { 1.1341 + // collision! offset and start over 1.1342 + if (bouncedX & 0x1) 1.1343 + aRequestedX -= kOffset; 1.1344 + else 1.1345 + aRequestedX += kOffset; 1.1346 + aRequestedY += kOffset; 1.1347 + 1.1348 + if (gotScreen) { 1.1349 + // if we're moving to the right and we need to bounce... 1.1350 + if (!(bouncedX & 0x1) && ((aRequestedX + aSpecWidth) > screenRight)) { 1.1351 + aRequestedX = screenRight - aSpecWidth; 1.1352 + ++bouncedX; 1.1353 + } 1.1354 + 1.1355 + // if we're moving to the left and we need to bounce... 1.1356 + if ((bouncedX & 0x1) && aRequestedX < screenLeft) { 1.1357 + aRequestedX = screenLeft; 1.1358 + ++bouncedX; 1.1359 + } 1.1360 + 1.1361 + // if we hit the bottom then bounce to the top 1.1362 + if (aRequestedY + aSpecHeight > screenBottom) { 1.1363 + aRequestedY = screenTop; 1.1364 + ++bouncedY; 1.1365 + } 1.1366 + } 1.1367 + 1.1368 + /* loop around again, 1.1369 + but it's time to give up once we've covered the screen. 1.1370 + there's a potential infinite loop with lots of windows. */ 1.1371 + keepTrying = bouncedX < 2 || bouncedY == 0; 1.1372 + break; 1.1373 + } 1.1374 + } 1.1375 + } while(1); 1.1376 + } while (keepTrying); 1.1377 +} 1.1378 + 1.1379 +void nsXULWindow::SyncAttributesToWidget() 1.1380 +{ 1.1381 + nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement(); 1.1382 + if (!windowElement) 1.1383 + return; 1.1384 + 1.1385 + nsAutoString attr; 1.1386 + 1.1387 + // "hidechrome" attribute 1.1388 + if (windowElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidechrome, 1.1389 + nsGkAtoms::_true, eCaseMatters)) { 1.1390 + mWindow->HideWindowChrome(true); 1.1391 + } 1.1392 + 1.1393 + // "chromemargin" attribute 1.1394 + nsIntMargin margins; 1.1395 + windowElement->GetAttribute(NS_LITERAL_STRING("chromemargin"), attr); 1.1396 + if (nsContentUtils::ParseIntMarginValue(attr, margins)) { 1.1397 + mWindow->SetNonClientMargins(margins); 1.1398 + } 1.1399 + 1.1400 + // "accelerated" attribute 1.1401 + bool isAccelerated = windowElement->HasAttribute(NS_LITERAL_STRING("accelerated")); 1.1402 + mWindow->SetLayersAcceleration(isAccelerated); 1.1403 + 1.1404 + // "windowtype" attribute 1.1405 + windowElement->GetAttribute(WINDOWTYPE_ATTRIBUTE, attr); 1.1406 + if (!attr.IsEmpty()) { 1.1407 + mWindow->SetWindowClass(attr); 1.1408 + } 1.1409 + 1.1410 + // "id" attribute for icon 1.1411 + windowElement->GetAttribute(NS_LITERAL_STRING("id"), attr); 1.1412 + if (attr.IsEmpty()) { 1.1413 + attr.AssignLiteral("default"); 1.1414 + } 1.1415 + mWindow->SetIcon(attr); 1.1416 + 1.1417 + // "drawtitle" attribute 1.1418 + windowElement->GetAttribute(NS_LITERAL_STRING("drawtitle"), attr); 1.1419 + mWindow->SetDrawsTitle(attr.LowerCaseEqualsLiteral("true")); 1.1420 + 1.1421 + // "toggletoolbar" attribute 1.1422 + windowElement->GetAttribute(NS_LITERAL_STRING("toggletoolbar"), attr); 1.1423 + mWindow->SetShowsToolbarButton(attr.LowerCaseEqualsLiteral("true")); 1.1424 + 1.1425 + // "fullscreenbutton" attribute 1.1426 + windowElement->GetAttribute(NS_LITERAL_STRING("fullscreenbutton"), attr); 1.1427 + mWindow->SetShowsFullScreenButton(attr.LowerCaseEqualsLiteral("true")); 1.1428 + 1.1429 + // "macanimationtype" attribute 1.1430 + windowElement->GetAttribute(NS_LITERAL_STRING("macanimationtype"), attr); 1.1431 + if (attr.EqualsLiteral("document")) { 1.1432 + mWindow->SetWindowAnimationType(nsIWidget::eDocumentWindowAnimation); 1.1433 + } 1.1434 +} 1.1435 + 1.1436 +NS_IMETHODIMP nsXULWindow::SavePersistentAttributes() 1.1437 +{ 1.1438 + // can happen when the persistence timer fires at an inopportune time 1.1439 + // during window shutdown 1.1440 + if (!mDocShell) 1.1441 + return NS_ERROR_FAILURE; 1.1442 + 1.1443 + nsCOMPtr<dom::Element> docShellElement = GetWindowDOMElement(); 1.1444 + if (!docShellElement) 1.1445 + return NS_ERROR_FAILURE; 1.1446 + 1.1447 + nsAutoString persistString; 1.1448 + docShellElement->GetAttribute(PERSIST_ATTRIBUTE, persistString); 1.1449 + if (persistString.IsEmpty()) { // quick check which sometimes helps 1.1450 + mPersistentAttributesDirty = 0; 1.1451 + return NS_OK; 1.1452 + } 1.1453 + 1.1454 + // get our size, position and mode to persist 1.1455 + int32_t x, y, cx, cy; 1.1456 + NS_ENSURE_SUCCESS(GetPositionAndSize(&x, &y, &cx, &cy), NS_ERROR_FAILURE); 1.1457 + 1.1458 + int32_t sizeMode = mWindow->SizeMode(); 1.1459 + CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale(); 1.1460 + 1.1461 + // make our position relative to our parent, if any 1.1462 + nsCOMPtr<nsIBaseWindow> parent(do_QueryReferent(mParentWindow)); 1.1463 + if (parent) { 1.1464 + int32_t parentX, parentY; 1.1465 + if (NS_SUCCEEDED(parent->GetPosition(&parentX, &parentY))) { 1.1466 + x -= parentX; 1.1467 + y -= parentY; 1.1468 + } 1.1469 + } 1.1470 + 1.1471 + char sizeBuf[10]; 1.1472 + nsAutoString sizeString; 1.1473 + nsAutoString windowElementId; 1.1474 + nsCOMPtr<nsIDOMXULDocument> ownerXULDoc; 1.1475 + 1.1476 + // fetch docShellElement's ID and XUL owner document 1.1477 + ownerXULDoc = do_QueryInterface(docShellElement->OwnerDoc()); 1.1478 + if (docShellElement->IsXUL()) { 1.1479 + docShellElement->GetId(windowElementId); 1.1480 + } 1.1481 + 1.1482 + ErrorResult rv; 1.1483 + // (only for size elements which are persisted) 1.1484 + if ((mPersistentAttributesDirty & PAD_POSITION) && 1.1485 + sizeMode == nsSizeMode_Normal) { 1.1486 + if (persistString.Find("screenX") >= 0) { 1.1487 + PR_snprintf(sizeBuf, sizeof(sizeBuf), "%d", NSToIntRound(x / scale.scale)); 1.1488 + sizeString.AssignWithConversion(sizeBuf); 1.1489 + docShellElement->SetAttribute(SCREENX_ATTRIBUTE, sizeString, rv); 1.1490 + if (ownerXULDoc) // force persistence in case the value didn't change 1.1491 + ownerXULDoc->Persist(windowElementId, SCREENX_ATTRIBUTE); 1.1492 + } 1.1493 + if (persistString.Find("screenY") >= 0) { 1.1494 + PR_snprintf(sizeBuf, sizeof(sizeBuf), "%d", NSToIntRound(y / scale.scale)); 1.1495 + sizeString.AssignWithConversion(sizeBuf); 1.1496 + docShellElement->SetAttribute(SCREENY_ATTRIBUTE, sizeString, rv); 1.1497 + if (ownerXULDoc) 1.1498 + ownerXULDoc->Persist(windowElementId, SCREENY_ATTRIBUTE); 1.1499 + } 1.1500 + } 1.1501 + 1.1502 + if ((mPersistentAttributesDirty & PAD_SIZE) && 1.1503 + sizeMode == nsSizeMode_Normal) { 1.1504 + if (persistString.Find("width") >= 0) { 1.1505 + PR_snprintf(sizeBuf, sizeof(sizeBuf), "%d", NSToIntRound(cx / scale.scale)); 1.1506 + sizeString.AssignWithConversion(sizeBuf); 1.1507 + docShellElement->SetAttribute(WIDTH_ATTRIBUTE, sizeString, rv); 1.1508 + if (ownerXULDoc) 1.1509 + ownerXULDoc->Persist(windowElementId, WIDTH_ATTRIBUTE); 1.1510 + } 1.1511 + if (persistString.Find("height") >= 0) { 1.1512 + PR_snprintf(sizeBuf, sizeof(sizeBuf), "%d", NSToIntRound(cy / scale.scale)); 1.1513 + sizeString.AssignWithConversion(sizeBuf); 1.1514 + docShellElement->SetAttribute(HEIGHT_ATTRIBUTE, sizeString, rv); 1.1515 + if (ownerXULDoc) 1.1516 + ownerXULDoc->Persist(windowElementId, HEIGHT_ATTRIBUTE); 1.1517 + } 1.1518 + } 1.1519 + 1.1520 + if (mPersistentAttributesDirty & PAD_MISC) { 1.1521 + if (sizeMode != nsSizeMode_Minimized) { 1.1522 + if (sizeMode == nsSizeMode_Maximized) 1.1523 + sizeString.Assign(SIZEMODE_MAXIMIZED); 1.1524 + else if (sizeMode == nsSizeMode_Fullscreen) 1.1525 + sizeString.Assign(SIZEMODE_FULLSCREEN); 1.1526 + else 1.1527 + sizeString.Assign(SIZEMODE_NORMAL); 1.1528 + docShellElement->SetAttribute(MODE_ATTRIBUTE, sizeString, rv); 1.1529 + if (ownerXULDoc && persistString.Find("sizemode") >= 0) 1.1530 + ownerXULDoc->Persist(windowElementId, MODE_ATTRIBUTE); 1.1531 + } 1.1532 + if (persistString.Find("zlevel") >= 0) { 1.1533 + uint32_t zLevel; 1.1534 + nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); 1.1535 + if (mediator) { 1.1536 + mediator->GetZLevel(this, &zLevel); 1.1537 + PR_snprintf(sizeBuf, sizeof(sizeBuf), "%lu", (unsigned long)zLevel); 1.1538 + sizeString.AssignWithConversion(sizeBuf); 1.1539 + docShellElement->SetAttribute(ZLEVEL_ATTRIBUTE, sizeString, rv); 1.1540 + ownerXULDoc->Persist(windowElementId, ZLEVEL_ATTRIBUTE); 1.1541 + } 1.1542 + } 1.1543 + } 1.1544 + 1.1545 + mPersistentAttributesDirty = 0; 1.1546 + return NS_OK; 1.1547 +} 1.1548 + 1.1549 +NS_IMETHODIMP nsXULWindow::GetWindowDOMWindow(nsIDOMWindow** aDOMWindow) 1.1550 +{ 1.1551 + NS_ENSURE_STATE(mDocShell); 1.1552 + 1.1553 + if (!mDOMWindow) 1.1554 + mDOMWindow = do_GetInterface(mDocShell); 1.1555 + NS_ENSURE_TRUE(mDOMWindow, NS_ERROR_FAILURE); 1.1556 + 1.1557 + *aDOMWindow = mDOMWindow; 1.1558 + NS_ADDREF(*aDOMWindow); 1.1559 + return NS_OK; 1.1560 +} 1.1561 + 1.1562 +dom::Element* 1.1563 +nsXULWindow::GetWindowDOMElement() const 1.1564 +{ 1.1565 + NS_ENSURE_TRUE(mDocShell, nullptr); 1.1566 + 1.1567 + nsCOMPtr<nsIContentViewer> cv; 1.1568 + mDocShell->GetContentViewer(getter_AddRefs(cv)); 1.1569 + NS_ENSURE_TRUE(cv, nullptr); 1.1570 + 1.1571 + const nsIDocument* document = cv->GetDocument(); 1.1572 + NS_ENSURE_TRUE(document, nullptr); 1.1573 + 1.1574 + return document->GetRootElement(); 1.1575 +} 1.1576 + 1.1577 +nsresult nsXULWindow::ContentShellAdded(nsIDocShellTreeItem* aContentShell, 1.1578 + bool aPrimary, bool aTargetable, const nsAString& aID) 1.1579 +{ 1.1580 + nsContentShellInfo* shellInfo = nullptr; 1.1581 + 1.1582 + uint32_t i, count = mContentShells.Length(); 1.1583 + nsWeakPtr contentShellWeak = do_GetWeakReference(aContentShell); 1.1584 + for (i = 0; i < count; i++) { 1.1585 + nsContentShellInfo* info = mContentShells.ElementAt(i); 1.1586 + if (info->id.Equals(aID)) { 1.1587 + // We already exist. Do a replace. 1.1588 + info->child = contentShellWeak; 1.1589 + shellInfo = info; 1.1590 + } 1.1591 + else if (info->child == contentShellWeak) 1.1592 + info->child = nullptr; 1.1593 + } 1.1594 + 1.1595 + if (!shellInfo) { 1.1596 + shellInfo = new nsContentShellInfo(aID, contentShellWeak); 1.1597 + mContentShells.AppendElement(shellInfo); 1.1598 + } 1.1599 + 1.1600 + // Set the default content tree owner 1.1601 + if (aPrimary) { 1.1602 + NS_ENSURE_SUCCESS(EnsurePrimaryContentTreeOwner(), NS_ERROR_FAILURE); 1.1603 + aContentShell->SetTreeOwner(mPrimaryContentTreeOwner); 1.1604 + mPrimaryContentShell = aContentShell; 1.1605 + } 1.1606 + else { 1.1607 + NS_ENSURE_SUCCESS(EnsureContentTreeOwner(), NS_ERROR_FAILURE); 1.1608 + aContentShell->SetTreeOwner(mContentTreeOwner); 1.1609 + if (mPrimaryContentShell == aContentShell) 1.1610 + mPrimaryContentShell = nullptr; 1.1611 + } 1.1612 + 1.1613 + if (aTargetable) { 1.1614 +#ifdef DEBUG 1.1615 + int32_t debugCount = mTargetableShells.Count(); 1.1616 + int32_t debugCounter; 1.1617 + for (debugCounter = debugCount - 1; debugCounter >= 0; --debugCounter) { 1.1618 + nsCOMPtr<nsIDocShellTreeItem> curItem = 1.1619 + do_QueryReferent(mTargetableShells[debugCounter]); 1.1620 + NS_ASSERTION(!SameCOMIdentity(curItem, aContentShell), 1.1621 + "Adding already existing item to mTargetableShells"); 1.1622 + } 1.1623 +#endif 1.1624 + 1.1625 + // put the new shell at the start of the targetable shells list if either 1.1626 + // it's the new primary shell or there is no existing primary shell (which 1.1627 + // means that chances are this one just stopped being primary). If we 1.1628 + // really cared, we could keep track of the "last no longer primary shell" 1.1629 + // explicitly, but it probably doesn't matter enough: the difference would 1.1630 + // only be felt in a situation where all shells were non-primary, which 1.1631 + // doesn't happen much. In a situation where there is one and only one 1.1632 + // primary shell, and in which shells get unmarked as primary before some 1.1633 + // other shell gets marked as primary, this effectively stores the list of 1.1634 + // targetable shells in "most recently primary first" order. 1.1635 + bool inserted; 1.1636 + if (aPrimary || !mPrimaryContentShell) { 1.1637 + inserted = mTargetableShells.InsertObjectAt(contentShellWeak, 0); 1.1638 + } else { 1.1639 + inserted = mTargetableShells.AppendObject(contentShellWeak); 1.1640 + } 1.1641 + NS_ENSURE_TRUE(inserted, NS_ERROR_OUT_OF_MEMORY); 1.1642 + } 1.1643 + 1.1644 + return NS_OK; 1.1645 +} 1.1646 + 1.1647 +nsresult nsXULWindow::ContentShellRemoved(nsIDocShellTreeItem* aContentShell) 1.1648 +{ 1.1649 + if (mPrimaryContentShell == aContentShell) { 1.1650 + mPrimaryContentShell = nullptr; 1.1651 + } 1.1652 + 1.1653 + int32_t i, count = mContentShells.Length(); 1.1654 + for (i = count - 1; i >= 0; --i) { 1.1655 + nsContentShellInfo* info = mContentShells.ElementAt(i); 1.1656 + nsCOMPtr<nsIDocShellTreeItem> curItem = do_QueryReferent(info->child); 1.1657 + if (!curItem || SameCOMIdentity(curItem, aContentShell)) { 1.1658 + mContentShells.RemoveElementAt(i); 1.1659 + delete info; 1.1660 + } 1.1661 + } 1.1662 + 1.1663 + count = mTargetableShells.Count(); 1.1664 + for (i = count - 1; i >= 0; --i) { 1.1665 + nsCOMPtr<nsIDocShellTreeItem> curItem = 1.1666 + do_QueryReferent(mTargetableShells[i]); 1.1667 + if (!curItem || SameCOMIdentity(curItem, aContentShell)) { 1.1668 + mTargetableShells.RemoveObjectAt(i); 1.1669 + } 1.1670 + } 1.1671 + 1.1672 + return NS_OK; 1.1673 +} 1.1674 + 1.1675 +NS_IMETHODIMP nsXULWindow::SizeShellTo(nsIDocShellTreeItem* aShellItem, 1.1676 + int32_t aCX, int32_t aCY) 1.1677 +{ 1.1678 + // XXXTAB This is wrong, we should actually reflow based on the passed in 1.1679 + // shell. For now we are hacking and doing delta sizing. This is bad 1.1680 + // because it assumes all size we add will go to the shell which probably 1.1681 + // won't happen. 1.1682 + 1.1683 + nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(aShellItem)); 1.1684 + NS_ENSURE_TRUE(shellAsWin, NS_ERROR_FAILURE); 1.1685 + 1.1686 + int32_t width = 0; 1.1687 + int32_t height = 0; 1.1688 + shellAsWin->GetSize(&width, &height); 1.1689 + 1.1690 + int32_t widthDelta = aCX - width; 1.1691 + int32_t heightDelta = aCY - height; 1.1692 + 1.1693 + if (widthDelta || heightDelta) { 1.1694 + int32_t winCX = 0; 1.1695 + int32_t winCY = 0; 1.1696 + 1.1697 + GetSize(&winCX, &winCY); 1.1698 + // There's no point in trying to make the window smaller than the 1.1699 + // desired docshell size --- that's not likely to work. This whole 1.1700 + // function assumes that the outer docshell is adding some constant 1.1701 + // "border" chrome to aShellItem. 1.1702 + winCX = std::max(winCX + widthDelta, aCX); 1.1703 + winCY = std::max(winCY + heightDelta, aCY); 1.1704 + SetSize(winCX, winCY, true); 1.1705 + } 1.1706 + 1.1707 + return NS_OK; 1.1708 +} 1.1709 + 1.1710 +NS_IMETHODIMP nsXULWindow::ExitModalLoop(nsresult aStatus) 1.1711 +{ 1.1712 + if (mContinueModalLoop) 1.1713 + EnableParent(true); 1.1714 + mContinueModalLoop = false; 1.1715 + mModalStatus = aStatus; 1.1716 + return NS_OK; 1.1717 +} 1.1718 + 1.1719 +// top-level function to create a new window 1.1720 +NS_IMETHODIMP nsXULWindow::CreateNewWindow(int32_t aChromeFlags, 1.1721 + nsIXULWindow **_retval) 1.1722 +{ 1.1723 + NS_ENSURE_ARG_POINTER(_retval); 1.1724 + 1.1725 + if (aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME) 1.1726 + return CreateNewChromeWindow(aChromeFlags, _retval); 1.1727 + return CreateNewContentWindow(aChromeFlags, _retval); 1.1728 +} 1.1729 + 1.1730 +NS_IMETHODIMP nsXULWindow::CreateNewChromeWindow(int32_t aChromeFlags, 1.1731 + nsIXULWindow **_retval) 1.1732 +{ 1.1733 + nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); 1.1734 + NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE); 1.1735 + 1.1736 + // Just do a normal create of a window and return. 1.1737 + 1.1738 + nsCOMPtr<nsIXULWindow> newWindow; 1.1739 + appShell->CreateTopLevelWindow(this, nullptr, aChromeFlags, 1.1740 + nsIAppShellService::SIZE_TO_CONTENT, 1.1741 + nsIAppShellService::SIZE_TO_CONTENT, 1.1742 + getter_AddRefs(newWindow)); 1.1743 + 1.1744 + NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE); 1.1745 + 1.1746 + *_retval = newWindow; 1.1747 + NS_ADDREF(*_retval); 1.1748 + 1.1749 + return NS_OK; 1.1750 +} 1.1751 + 1.1752 +NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(int32_t aChromeFlags, 1.1753 + nsIXULWindow **_retval) 1.1754 +{ 1.1755 + nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); 1.1756 + NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE); 1.1757 + 1.1758 + // We need to create a new top level window and then enter a nested 1.1759 + // loop. Eventually the new window will be told that it has loaded, 1.1760 + // at which time we know it is safe to spin out of the nested loop 1.1761 + // and allow the opening code to proceed. 1.1762 + 1.1763 + nsCOMPtr<nsIURI> uri; 1.1764 + 1.1765 + nsAdoptingCString urlStr = Preferences::GetCString("browser.chromeURL"); 1.1766 + if (urlStr.IsEmpty()) { 1.1767 + urlStr.AssignLiteral("chrome://navigator/content/navigator.xul"); 1.1768 + } 1.1769 + 1.1770 + nsCOMPtr<nsIIOService> service(do_GetService(NS_IOSERVICE_CONTRACTID)); 1.1771 + if (service) { 1.1772 + service->NewURI(urlStr, nullptr, nullptr, getter_AddRefs(uri)); 1.1773 + } 1.1774 + NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE); 1.1775 + 1.1776 + // We need to create a chrome window to contain the content window we're about 1.1777 + // to pass back. The subject principal needs to be system while we're creating 1.1778 + // it to make things work right, so force a system caller. See bug 799348 1.1779 + // comment 13 for a description of what happens when we don't. 1.1780 + nsCOMPtr<nsIXULWindow> newWindow; 1.1781 + { 1.1782 + AutoNoJSAPI nojsapi; 1.1783 + appShell->CreateTopLevelWindow(this, uri, 1.1784 + aChromeFlags, 615, 480, 1.1785 + getter_AddRefs(newWindow)); 1.1786 + NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE); 1.1787 + } 1.1788 + 1.1789 + // Specify that we want the window to remain locked until the chrome has loaded. 1.1790 + nsXULWindow *xulWin = static_cast<nsXULWindow*> 1.1791 + (static_cast<nsIXULWindow*> 1.1792 + (newWindow)); 1.1793 + 1.1794 + xulWin->LockUntilChromeLoad(); 1.1795 + 1.1796 + { 1.1797 + AutoNoJSAPI nojsapi; 1.1798 + nsIThread *thread = NS_GetCurrentThread(); 1.1799 + while (xulWin->IsLocked()) { 1.1800 + if (!NS_ProcessNextEvent(thread)) 1.1801 + break; 1.1802 + } 1.1803 + } 1.1804 + 1.1805 + NS_ENSURE_STATE(xulWin->mPrimaryContentShell); 1.1806 + 1.1807 + *_retval = newWindow; 1.1808 + NS_ADDREF(*_retval); 1.1809 + 1.1810 + return NS_OK; 1.1811 +} 1.1812 + 1.1813 +void nsXULWindow::EnableParent(bool aEnable) 1.1814 +{ 1.1815 + nsCOMPtr<nsIBaseWindow> parentWindow; 1.1816 + nsCOMPtr<nsIWidget> parentWidget; 1.1817 + 1.1818 + parentWindow = do_QueryReferent(mParentWindow); 1.1819 + if (parentWindow) 1.1820 + parentWindow->GetMainWidget(getter_AddRefs(parentWidget)); 1.1821 + if (parentWidget) 1.1822 + parentWidget->Enable(aEnable); 1.1823 +} 1.1824 + 1.1825 +// Constrain the window to its proper z-level 1.1826 +bool nsXULWindow::ConstrainToZLevel(bool aImmediate, 1.1827 + nsWindowZ *aPlacement, 1.1828 + nsIWidget *aReqBelow, 1.1829 + nsIWidget **aActualBelow) 1.1830 +{ 1.1831 +#if 0 1.1832 + /* Do we have a parent window? This means our z-order is already constrained, 1.1833 + since we're a dependent window. Our window list isn't hierarchical, 1.1834 + so we can't properly calculate placement for such a window. 1.1835 + Should we just abort? */ 1.1836 + nsCOMPtr<nsIBaseWindow> parentWindow = do_QueryReferent(mParentWindow); 1.1837 + if (parentWindow) 1.1838 + return false; 1.1839 +#endif 1.1840 + 1.1841 + nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); 1.1842 + if (!mediator) 1.1843 + return false; 1.1844 + 1.1845 + bool altered; 1.1846 + uint32_t position, 1.1847 + newPosition, 1.1848 + zLevel; 1.1849 + nsIXULWindow *us = this; 1.1850 + 1.1851 + altered = false; 1.1852 + mediator->GetZLevel(this, &zLevel); 1.1853 + 1.1854 + // translate from WidgetGUIEvent to nsIWindowMediator constants 1.1855 + position = nsIWindowMediator::zLevelTop; 1.1856 + if (*aPlacement == nsWindowZBottom || zLevel == nsIXULWindow::lowestZ) 1.1857 + position = nsIWindowMediator::zLevelBottom; 1.1858 + else if (*aPlacement == nsWindowZRelative) 1.1859 + position = nsIWindowMediator::zLevelBelow; 1.1860 + 1.1861 + if (NS_SUCCEEDED(mediator->CalculateZPosition(us, position, aReqBelow, 1.1862 + &newPosition, aActualBelow, &altered))) { 1.1863 + /* If we were asked to move to the top but constrained to remain 1.1864 + below one of our other windows, first move all windows in that 1.1865 + window's layer and above to the top. This allows the user to 1.1866 + click a window which can't be topmost and still bring mozilla 1.1867 + to the foreground. */ 1.1868 + if (altered && 1.1869 + (position == nsIWindowMediator::zLevelTop || 1.1870 + (position == nsIWindowMediator::zLevelBelow && aReqBelow == 0))) 1.1871 + PlaceWindowLayersBehind(zLevel + 1, nsIXULWindow::highestZ, 0); 1.1872 + 1.1873 + if (*aPlacement != nsWindowZBottom && 1.1874 + position == nsIWindowMediator::zLevelBottom) 1.1875 + altered = true; 1.1876 + if (altered || aImmediate) { 1.1877 + if (newPosition == nsIWindowMediator::zLevelTop) 1.1878 + *aPlacement = nsWindowZTop; 1.1879 + else if (newPosition == nsIWindowMediator::zLevelBottom) 1.1880 + *aPlacement = nsWindowZBottom; 1.1881 + else 1.1882 + *aPlacement = nsWindowZRelative; 1.1883 + 1.1884 + if (aImmediate) { 1.1885 + nsCOMPtr<nsIBaseWindow> ourBase = do_QueryObject(this); 1.1886 + if (ourBase) { 1.1887 + nsCOMPtr<nsIWidget> ourWidget; 1.1888 + ourBase->GetMainWidget(getter_AddRefs(ourWidget)); 1.1889 + ourWidget->PlaceBehind(*aPlacement == nsWindowZBottom ? 1.1890 + eZPlacementBottom : eZPlacementBelow, 1.1891 + *aActualBelow, false); 1.1892 + } 1.1893 + } 1.1894 + } 1.1895 + 1.1896 + /* CalculateZPosition can tell us to be below nothing, because it tries 1.1897 + not to change something it doesn't recognize. A request to verify 1.1898 + being below an unrecognized window, then, is treated as a request 1.1899 + to come to the top (below null) */ 1.1900 + nsCOMPtr<nsIXULWindow> windowAbove; 1.1901 + if (newPosition == nsIWindowMediator::zLevelBelow && *aActualBelow) { 1.1902 + windowAbove = (*aActualBelow)->GetWidgetListener()->GetXULWindow(); 1.1903 + } 1.1904 + 1.1905 + mediator->SetZPosition(us, newPosition, windowAbove); 1.1906 + } 1.1907 + 1.1908 + return altered; 1.1909 +} 1.1910 + 1.1911 +/* Re-z-position all windows in the layers from aLowLevel to aHighLevel, 1.1912 + inclusive, to be behind aBehind. aBehind of null means on top. 1.1913 + Note this method actually does nothing to our relative window positions. 1.1914 + (And therefore there's no need to inform WindowMediator we're moving 1.1915 + things, because we aren't.) This method is useful for, say, moving 1.1916 + a range of layers of our own windows relative to windows belonging to 1.1917 + external applications. 1.1918 +*/ 1.1919 +void nsXULWindow::PlaceWindowLayersBehind(uint32_t aLowLevel, 1.1920 + uint32_t aHighLevel, 1.1921 + nsIXULWindow *aBehind) 1.1922 +{ 1.1923 + // step through windows in z-order from top to bottommost window 1.1924 + 1.1925 + nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); 1.1926 + if (!mediator) 1.1927 + return; 1.1928 + 1.1929 + nsCOMPtr<nsISimpleEnumerator> windowEnumerator; 1.1930 + mediator->GetZOrderXULWindowEnumerator(0, true, 1.1931 + getter_AddRefs(windowEnumerator)); 1.1932 + if (!windowEnumerator) 1.1933 + return; 1.1934 + 1.1935 + // each window will be moved behind previousHighWidget, itself 1.1936 + // a moving target. initialize it. 1.1937 + nsCOMPtr<nsIWidget> previousHighWidget; 1.1938 + if (aBehind) { 1.1939 + nsCOMPtr<nsIBaseWindow> highBase(do_QueryInterface(aBehind)); 1.1940 + if (highBase) 1.1941 + highBase->GetMainWidget(getter_AddRefs(previousHighWidget)); 1.1942 + } 1.1943 + 1.1944 + // get next lower window 1.1945 + bool more; 1.1946 + while (windowEnumerator->HasMoreElements(&more), more) { 1.1947 + uint32_t nextZ; // z-level of nextWindow 1.1948 + nsCOMPtr<nsISupports> nextWindow; 1.1949 + windowEnumerator->GetNext(getter_AddRefs(nextWindow)); 1.1950 + nsCOMPtr<nsIXULWindow> nextXULWindow(do_QueryInterface(nextWindow)); 1.1951 + nextXULWindow->GetZLevel(&nextZ); 1.1952 + if (nextZ < aLowLevel) 1.1953 + break; // we've processed all windows through aLowLevel 1.1954 + 1.1955 + // move it just below its next higher window 1.1956 + nsCOMPtr<nsIBaseWindow> nextBase(do_QueryInterface(nextXULWindow)); 1.1957 + if (nextBase) { 1.1958 + nsCOMPtr<nsIWidget> nextWidget; 1.1959 + nextBase->GetMainWidget(getter_AddRefs(nextWidget)); 1.1960 + if (nextZ <= aHighLevel) 1.1961 + nextWidget->PlaceBehind(eZPlacementBelow, previousHighWidget, false); 1.1962 + previousHighWidget = nextWidget; 1.1963 + } 1.1964 + } 1.1965 +} 1.1966 + 1.1967 +void nsXULWindow::SetContentScrollbarVisibility(bool aVisible) 1.1968 +{ 1.1969 + nsCOMPtr<nsPIDOMWindow> contentWin(do_GetInterface(mPrimaryContentShell)); 1.1970 + if (contentWin) { 1.1971 + mozilla::ErrorResult rv; 1.1972 + nsRefPtr<nsGlobalWindow> window = static_cast<nsGlobalWindow*>(contentWin.get()); 1.1973 + nsRefPtr<mozilla::dom::BarProp> scrollbars = window->GetScrollbars(rv); 1.1974 + if (scrollbars) { 1.1975 + scrollbars->SetVisible(aVisible, rv); 1.1976 + } 1.1977 + } 1.1978 +} 1.1979 + 1.1980 +bool nsXULWindow::GetContentScrollbarVisibility() 1.1981 +{ 1.1982 + // This code already exists in dom/src/base/nsBarProp.cpp, but we 1.1983 + // can't safely get to that from here as this function is called 1.1984 + // while the DOM window is being set up, and we need the DOM window 1.1985 + // to get to that code. 1.1986 + nsCOMPtr<nsIScrollable> scroller(do_QueryInterface(mPrimaryContentShell)); 1.1987 + 1.1988 + if (scroller) { 1.1989 + int32_t prefValue; 1.1990 + scroller->GetDefaultScrollbarPreferences( 1.1991 + nsIScrollable::ScrollOrientation_Y, &prefValue); 1.1992 + if (prefValue == nsIScrollable::Scrollbar_Never) // try the other way 1.1993 + scroller->GetDefaultScrollbarPreferences( 1.1994 + nsIScrollable::ScrollOrientation_X, &prefValue); 1.1995 + 1.1996 + if (prefValue == nsIScrollable::Scrollbar_Never) 1.1997 + return false; 1.1998 + } 1.1999 + 1.2000 + return true; 1.2001 +} 1.2002 + 1.2003 +// during spinup, attributes that haven't been loaded yet can't be dirty 1.2004 +void nsXULWindow::PersistentAttributesDirty(uint32_t aDirtyFlags) 1.2005 +{ 1.2006 + mPersistentAttributesDirty |= aDirtyFlags & mPersistentAttributesMask; 1.2007 +} 1.2008 + 1.2009 +NS_IMETHODIMP nsXULWindow::ApplyChromeFlags() 1.2010 +{ 1.2011 + nsCOMPtr<dom::Element> window = GetWindowDOMElement(); 1.2012 + NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); 1.2013 + 1.2014 + if (mChromeLoaded) { 1.2015 + // The two calls in this block don't need to happen early because they 1.2016 + // don't cause a global restyle on the document. Not only that, but the 1.2017 + // scrollbar stuff needs a content area to toggle the scrollbars on anyway. 1.2018 + // So just don't do these until mChromeLoaded is true. 1.2019 + 1.2020 + // Scrollbars have their own special treatment. 1.2021 + SetContentScrollbarVisibility(mChromeFlags & 1.2022 + nsIWebBrowserChrome::CHROME_SCROLLBARS ? 1.2023 + true : false); 1.2024 + } 1.2025 + 1.2026 + /* the other flags are handled together. we have style rules 1.2027 + in navigator.css that trigger visibility based on 1.2028 + the 'chromehidden' attribute of the <window> tag. */ 1.2029 + nsAutoString newvalue; 1.2030 + 1.2031 + if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_MENUBAR)) 1.2032 + newvalue.AppendLiteral("menubar "); 1.2033 + 1.2034 + if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_TOOLBAR)) 1.2035 + newvalue.AppendLiteral("toolbar "); 1.2036 + 1.2037 + if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_LOCATIONBAR)) 1.2038 + newvalue.AppendLiteral("location "); 1.2039 + 1.2040 + if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR)) 1.2041 + newvalue.AppendLiteral("directories "); 1.2042 + 1.2043 + if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_STATUSBAR)) 1.2044 + newvalue.AppendLiteral("status "); 1.2045 + 1.2046 + if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_EXTRA)) 1.2047 + newvalue.AppendLiteral("extrachrome "); 1.2048 + 1.2049 + // Note that if we're not actually changing the value this will be a no-op, 1.2050 + // so no need to compare to the old value. 1.2051 + ErrorResult rv; 1.2052 + window->SetAttribute(NS_LITERAL_STRING("chromehidden"), newvalue, rv); 1.2053 + 1.2054 + return NS_OK; 1.2055 +} 1.2056 + 1.2057 +NS_IMETHODIMP nsXULWindow::GetXULBrowserWindow(nsIXULBrowserWindow * *aXULBrowserWindow) 1.2058 +{ 1.2059 + NS_IF_ADDREF(*aXULBrowserWindow = mXULBrowserWindow); 1.2060 + return NS_OK; 1.2061 +} 1.2062 + 1.2063 +NS_IMETHODIMP nsXULWindow::SetXULBrowserWindow(nsIXULBrowserWindow * aXULBrowserWindow) 1.2064 +{ 1.2065 + mXULBrowserWindow = aXULBrowserWindow; 1.2066 + return NS_OK; 1.2067 +} 1.2068 + 1.2069 +//***************************************************************************** 1.2070 +//*** nsContentShellInfo: Object Management 1.2071 +//***************************************************************************** 1.2072 + 1.2073 +nsContentShellInfo::nsContentShellInfo(const nsAString& aID, 1.2074 + nsIWeakReference* aContentShell) 1.2075 + : id(aID), 1.2076 + child(aContentShell) 1.2077 +{ 1.2078 + MOZ_COUNT_CTOR(nsContentShellInfo); 1.2079 +} 1.2080 + 1.2081 +nsContentShellInfo::~nsContentShellInfo() 1.2082 +{ 1.2083 + MOZ_COUNT_DTOR(nsContentShellInfo); 1.2084 + //XXX Set Tree Owner to null if the tree owner is nsXULWindow->mContentTreeOwner 1.2085 +}