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