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