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.

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

mercurial