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/. */
8 #include "mozilla/MathAlgorithms.h"
11 #include "AppWindow.h"
15 #include "nsPrintfCString.h"
17 #include "nsWidgetsCID.h"
18 #include "nsThreadUtils.h"
20 #include "nsQueryObject.h"
21 #include "mozilla/ProfilerLabels.h"
22 #include "mozilla/Sprintf.h"
23 #include "mozilla/Try.h"
25 // Interfaces needed to be included
26 #include "nsGlobalWindowOuter.h"
27 #include "nsIAppShell.h"
28 #include "nsIAppShellService.h"
29 #include "nsIDocumentViewer.h"
30 #include "mozilla/dom/Document.h"
31 #include "mozilla/dom/CanonicalBrowsingContext.h"
32 #include "nsPIDOMWindow.h"
34 #include "nsIInterfaceRequestor.h"
35 #include "nsIInterfaceRequestorUtils.h"
36 #include "nsIIOService.h"
37 #include "nsIObserverService.h"
38 #include "nsIOpenWindowInfo.h"
39 #include "nsIWindowMediator.h"
40 #include "nsIScreenManager.h"
41 #include "nsIScreen.h"
42 #include "nsIWindowWatcher.h"
44 #include "nsAppShellCID.h"
45 #include "nsReadableUtils.h"
46 #include "nsStyleConsts.h"
47 #include "nsPresContext.h"
48 #include "nsContentUtils.h"
49 #include "nsXULTooltipListener.h"
50 #include "nsXULPopupManager.h"
51 #include "nsFocusManager.h"
52 #include "nsContentList.h"
53 #include "nsIDOMWindowUtils.h"
54 #include "nsServiceManagerUtils.h"
57 #include "mozilla/AppShutdown.h"
58 #include "mozilla/AutoRestore.h"
59 #include "mozilla/Preferences.h"
60 #include "mozilla/PresShell.h"
61 #include "mozilla/Services.h"
62 #include "mozilla/SpinEventLoopUntil.h"
63 #include "mozilla/dom/BarProps.h"
64 #include "mozilla/dom/DOMRect.h"
65 #include "mozilla/dom/Element.h"
66 #include "mozilla/dom/Event.h"
67 #include "mozilla/dom/ScriptSettings.h"
68 #include "mozilla/dom/BrowserHost.h"
69 #include "mozilla/dom/BrowserParent.h"
70 #include "mozilla/dom/LoadURIOptionsBinding.h"
71 #include "mozilla/intl/LocaleService.h"
72 #include "mozilla/EventDispatcher.h"
75 # include "mozilla/PreXULSkeletonUI.h"
76 # include "nsIWindowsUIUtils.h"
79 #include "mozilla/dom/DocumentL10n.h"
81 #if defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK)
82 # include "mozilla/widget/NativeMenuSupport.h"
83 # define USE_NATIVE_MENUS
86 #define SIZEMODE_NORMAL u"normal"_ns
87 #define SIZEMODE_MAXIMIZED u"maximized"_ns
88 #define SIZEMODE_MINIMIZED u"minimized"_ns
89 #define SIZEMODE_FULLSCREEN u"fullscreen"_ns
91 #define SIZE_PERSISTENCE_TIMEOUT 500 // msec
93 //*****************************************************************************
94 //*** AppWindow: Object Management
95 //*****************************************************************************
99 using dom::AutoNoJSAPI
;
100 using dom::BrowserHost
;
101 using dom::BrowsingContext
;
103 using dom::DocumentL10n
;
105 using dom::EventTarget
;
106 using dom::LoadURIOptions
;
109 AppWindow::AppWindow(uint32_t aChromeFlags
)
110 : mChromeTreeOwner(nullptr),
111 mContentTreeOwner(nullptr),
112 mPrimaryContentTreeOwner(nullptr),
114 mFullscreenChangeState(FullscreenChangeState::NotChanging
),
115 mContinueModalLoop(false),
117 mChromeLoaded(false),
118 mSizingShellFromXUL(false),
119 mShowAfterLoad(false),
120 mIntrinsicallySized(false),
121 mCenterAfterLoad(false),
122 mIsHiddenWindow(false),
123 mLockedUntilChromeLoad(false),
124 mIgnoreXULSize(false),
125 mIgnoreXULPosition(false),
126 mChromeFlagsFrozen(false),
127 mIgnoreXULSizeMode(false),
130 mDominantClientSize(false),
131 mChromeFlags(aChromeFlags
),
132 mWidgetListenerDelegate(this) {}
134 AppWindow::~AppWindow() {
142 //*****************************************************************************
143 // AppWindow::nsISupports
144 //*****************************************************************************
146 NS_IMPL_ADDREF(AppWindow
)
147 NS_IMPL_RELEASE(AppWindow
)
149 NS_INTERFACE_MAP_BEGIN(AppWindow
)
150 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIAppWindow
)
151 NS_INTERFACE_MAP_ENTRY(nsIAppWindow
)
152 NS_INTERFACE_MAP_ENTRY(nsIBaseWindow
)
153 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor
)
154 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
155 NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener
)
156 NS_INTERFACE_MAP_ENTRY_CONCRETE(AppWindow
)
159 nsresult
AppWindow::Initialize(nsIAppWindow
* aParent
, nsIAppWindow
* aOpener
,
160 int32_t aInitialWidth
, int32_t aInitialHeight
,
161 bool aIsHiddenWindow
,
162 widget::InitData
& widgetInitData
) {
164 nsCOMPtr
<nsIWidget
> parentWidget
;
166 mIsHiddenWindow
= aIsHiddenWindow
;
168 DesktopIntPoint initialPos
;
169 nsCOMPtr
<nsIBaseWindow
> base(do_QueryInterface(aOpener
));
171 LayoutDeviceIntRect rect
= base
->GetPositionAndSize();
173 DesktopIntRect::Round(rect
/ base
->DevicePixelsPerDesktopPixel());
174 if (!mOpenerScreenRect
.IsEmpty()) {
175 initialPos
= mOpenerScreenRect
.TopLeft();
176 ConstrainToOpenerScreen(&initialPos
.x
.value
, &initialPos
.y
.value
);
180 // XXX: need to get the default window size from prefs...
181 // Doesn't come from prefs... will come from CSS/XUL/RDF
182 DesktopIntRect
deskRect(initialPos
,
183 DesktopIntSize(aInitialWidth
, aInitialHeight
));
185 // Create top level window
186 if (gfxPlatform::IsHeadless()) {
187 mWindow
= nsIWidget::CreateHeadlessWidget();
189 mWindow
= nsIWidget::CreateTopLevelWindow();
192 return NS_ERROR_FAILURE
;
195 /* This next bit is troublesome. We carry two different versions of a pointer
196 to our parent window. One is the parent window's widget, which is passed
197 to our own widget. The other is a weak reference we keep here to our
198 parent AppWindow. The former is useful to the widget, and we can't
199 trust its treatment of the parent reference because they're platform-
200 specific. The latter is useful to this class.
201 A better implementation would be one in which the parent keeps strong
202 references to its children and closes them before it allows itself
203 to be closed. This would mimic the behaviour of OSes that support
204 top-level child windows in OSes that do not. Later.
206 nsCOMPtr
<nsIBaseWindow
> parentAsWin(do_QueryInterface(aParent
));
208 parentAsWin
->GetMainWidget(getter_AddRefs(parentWidget
));
209 mParentWindow
= do_GetWeakReference(aParent
);
212 mWindow
->SetWidgetListener(&mWidgetListenerDelegate
);
213 rv
= mWindow
->Create((nsIWidget
*)parentWidget
, // Parent nsIWidget
214 nullptr, // Native parent widget
215 deskRect
, // Widget dimensions
216 &widgetInitData
); // Widget initialization data
217 NS_ENSURE_SUCCESS(rv
, rv
);
219 LayoutDeviceIntRect r
= mWindow
->GetClientBounds();
220 // Match the default background color of content. Previously important on
221 // Windows, but no longer has any effect there.
222 mWindow
->SetBackgroundColor(NS_RGB(255, 255, 255));
224 // All Chrome BCs exist within the same BrowsingContextGroup, so we don't need
225 // to pass in the opener window here. The opener is set later, if needed, by
227 RefPtr
<BrowsingContext
> browsingContext
=
228 BrowsingContext::CreateIndependent(BrowsingContext::Type::Chrome
);
231 mDocShell
= nsDocShell::Create(browsingContext
);
232 NS_ENSURE_TRUE(mDocShell
, NS_ERROR_FAILURE
);
234 // Make sure to set the item type on the docshell _before_ calling
235 // InitWindow() so it knows what type it is.
236 NS_ENSURE_SUCCESS(EnsureChromeTreeOwner(), NS_ERROR_FAILURE
);
238 mDocShell
->SetTreeOwner(mChromeTreeOwner
);
241 NS_ENSURE_SUCCESS(mDocShell
->InitWindow(nullptr, mWindow
, r
.X(), r
.Y(),
242 r
.Width(), r
.Height()),
245 // Attach a WebProgress listener.during initialization...
246 mDocShell
->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_NETWORK
);
248 mWindow
->MaybeDispatchInitialFocusEvent();
253 //*****************************************************************************
254 // AppWindow::nsIIntefaceRequestor
255 //*****************************************************************************
257 NS_IMETHODIMP
AppWindow::GetInterface(const nsIID
& aIID
, void** aSink
) {
260 NS_ENSURE_ARG_POINTER(aSink
);
262 if (aIID
.Equals(NS_GET_IID(nsIPrompt
))) {
263 rv
= EnsurePrompter();
264 if (NS_FAILED(rv
)) return rv
;
265 return mPrompter
->QueryInterface(aIID
, aSink
);
267 if (aIID
.Equals(NS_GET_IID(nsIAuthPrompt
))) {
268 rv
= EnsureAuthPrompter();
269 if (NS_FAILED(rv
)) return rv
;
270 return mAuthPrompter
->QueryInterface(aIID
, aSink
);
272 if (aIID
.Equals(NS_GET_IID(mozIDOMWindowProxy
))) {
273 return GetWindowDOMWindow(reinterpret_cast<mozIDOMWindowProxy
**>(aSink
));
275 if (aIID
.Equals(NS_GET_IID(nsIDOMWindow
))) {
276 nsCOMPtr
<mozIDOMWindowProxy
> window
= nullptr;
277 rv
= GetWindowDOMWindow(getter_AddRefs(window
));
278 nsCOMPtr
<nsIDOMWindow
> domWindow
= do_QueryInterface(window
);
279 domWindow
.forget(aSink
);
282 if (aIID
.Equals(NS_GET_IID(nsIWebBrowserChrome
)) &&
283 NS_SUCCEEDED(EnsureContentTreeOwner()) &&
284 NS_SUCCEEDED(mContentTreeOwner
->QueryInterface(aIID
, aSink
))) {
288 return QueryInterface(aIID
, aSink
);
291 //*****************************************************************************
292 // AppWindow::nsIAppWindow
293 //*****************************************************************************
295 NS_IMETHODIMP
AppWindow::GetDocShell(nsIDocShell
** aDocShell
) {
296 NS_ENSURE_ARG_POINTER(aDocShell
);
298 *aDocShell
= mDocShell
;
299 NS_IF_ADDREF(*aDocShell
);
303 NS_IMETHODIMP
AppWindow::GetChromeFlags(uint32_t* aChromeFlags
) {
304 NS_ENSURE_ARG_POINTER(aChromeFlags
);
305 *aChromeFlags
= mChromeFlags
;
309 NS_IMETHODIMP
AppWindow::SetChromeFlags(uint32_t aChromeFlags
) {
310 NS_ASSERTION(!mChromeFlagsFrozen
,
311 "SetChromeFlags() after AssumeChromeFlagsAreFrozen()!");
313 mChromeFlags
= aChromeFlags
;
320 NS_IMETHODIMP
AppWindow::AssumeChromeFlagsAreFrozen() {
321 mChromeFlagsFrozen
= true;
325 NS_IMETHODIMP
AppWindow::SetIntrinsicallySized(bool aIntrinsicallySized
) {
326 mIntrinsicallySized
= aIntrinsicallySized
;
330 NS_IMETHODIMP
AppWindow::GetIntrinsicallySized(bool* aIntrinsicallySized
) {
331 NS_ENSURE_ARG_POINTER(aIntrinsicallySized
);
333 *aIntrinsicallySized
= mIntrinsicallySized
;
337 NS_IMETHODIMP
AppWindow::GetPrimaryContentShell(
338 nsIDocShellTreeItem
** aDocShellTreeItem
) {
339 NS_ENSURE_ARG_POINTER(aDocShellTreeItem
);
340 NS_IF_ADDREF(*aDocShellTreeItem
= mPrimaryContentShell
);
345 AppWindow::RemoteTabAdded(nsIRemoteTab
* aTab
, bool aPrimary
) {
347 mPrimaryBrowserParent
= aTab
;
348 mPrimaryContentShell
= nullptr;
349 } else if (mPrimaryBrowserParent
== aTab
) {
350 mPrimaryBrowserParent
= nullptr;
357 AppWindow::RemoteTabRemoved(nsIRemoteTab
* aTab
) {
358 if (aTab
== mPrimaryBrowserParent
) {
359 mPrimaryBrowserParent
= nullptr;
366 AppWindow::GetPrimaryRemoteTab(nsIRemoteTab
** aTab
) {
367 nsCOMPtr
<nsIRemoteTab
> tab
= mPrimaryBrowserParent
;
373 AppWindow::GetPrimaryContentBrowsingContext(
374 mozilla::dom::BrowsingContext
** aBc
) {
375 if (mPrimaryBrowserParent
) {
376 return mPrimaryBrowserParent
->GetBrowsingContext(aBc
);
378 if (mPrimaryContentShell
) {
379 return mPrimaryContentShell
->GetBrowsingContextXPCOM(aBc
);
385 static LayoutDeviceIntSize
GetOuterToInnerSizeDifference(nsIWidget
* aWindow
) {
387 return LayoutDeviceIntSize();
389 return aWindow
->ClientToWindowSizeDifference();
392 static CSSIntSize
GetOuterToInnerSizeDifferenceInCSSPixels(
393 nsIWidget
* aWindow
, CSSToLayoutDeviceScale aScale
) {
394 LayoutDeviceIntSize devPixelSize
= GetOuterToInnerSizeDifference(aWindow
);
395 return RoundedToInt(devPixelSize
/ aScale
);
399 AppWindow::GetOuterToInnerHeightDifferenceInCSSPixels(uint32_t* aResult
) {
400 *aResult
= GetOuterToInnerSizeDifferenceInCSSPixels(
401 mWindow
, UnscaledDevicePixelsPerCSSPixel())
407 AppWindow::GetOuterToInnerWidthDifferenceInCSSPixels(uint32_t* aResult
) {
408 *aResult
= GetOuterToInnerSizeDifferenceInCSSPixels(
409 mWindow
, UnscaledDevicePixelsPerCSSPixel())
414 nsTArray
<RefPtr
<mozilla::LiveResizeListener
>>
415 AppWindow::GetLiveResizeListeners() {
416 nsTArray
<RefPtr
<mozilla::LiveResizeListener
>> listeners
;
417 if (mPrimaryBrowserParent
) {
418 BrowserHost
* host
= BrowserHost::GetFrom(mPrimaryBrowserParent
.get());
419 RefPtr
<mozilla::LiveResizeListener
> actor
= host
->GetActor();
421 listeners
.AppendElement(actor
);
427 NS_IMETHODIMP
AppWindow::ShowModal() {
428 AUTO_PROFILER_LABEL("AppWindow::ShowModal", OTHER
);
430 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed
)) {
431 MOZ_ASSERT_UNREACHABLE(
432 "Trying to show modal window after shutdown started.");
433 return NS_ERROR_ILLEGAL_DURING_SHUTDOWN
;
436 // Store locally so it doesn't die on us
437 nsCOMPtr
<nsIWidget
> window
= mWindow
;
438 nsCOMPtr
<nsIAppWindow
> tempRef
= this;
440 #ifdef USE_NATIVE_MENUS
441 if (!gfxPlatform::IsHeadless()) {
442 // On macOS, for modals created early in startup. (e.g.
443 // ProfileManager/ProfileDowngrade) this creates a fallback menu for the
444 // menu bar which only contains a "Quit" menu item. This allows the user to
445 // quit the application in a regular way with cmd+Q.
446 widget::NativeMenuSupport::CreateNativeMenuBar(mWindow
, nullptr);
450 window
->SetModal(true);
451 mContinueModalLoop
= true;
456 SpinEventLoopUntil("AppWindow::ShowModal"_ns
, [&]() {
458 AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed
))) {
459 // TODO: Bug 1699041 would apply also here: Should we return an error
460 // if we are bailing out from a pre-existing modal dialog for shutdown?
461 ExitModalLoop(NS_OK
);
463 return !mContinueModalLoop
;
467 mContinueModalLoop
= false;
468 window
->SetModal(false);
469 /* Note there's no EnableParent(true) here to match the false one
470 above. That's done in ExitModalLoop. It's important that the parent
471 be re-enabled before this window is made invisible; to do otherwise
472 causes bizarre z-ordering problems. At this point, the window is
474 No known current implementation of Enable would have a problem with
475 re-enabling the parent twice, so we could do it again here without
476 breaking any current implementation. But that's unnecessary if the
477 modal loop is always exited using ExitModalLoop (the other way would be
478 to change the protected member variable directly.)
484 NS_IMETHODIMP
AppWindow::RollupAllPopups() {
485 if (nsXULPopupManager
* pm
= nsXULPopupManager::GetInstance()) {
491 //*****************************************************************************
492 // AppWindow::nsIBaseWindow
493 //*****************************************************************************
495 NS_IMETHODIMP
AppWindow::InitWindow(nativeWindow aParentNativeWindow
,
496 nsIWidget
* parentWidget
, int32_t x
,
497 int32_t y
, int32_t cx
, int32_t cy
) {
498 // XXX First Check In
499 NS_ASSERTION(false, "Not Yet Implemented");
503 NS_IMETHODIMP
AppWindow::Destroy() {
504 nsCOMPtr
<nsIAppWindow
> kungFuDeathGrip(this);
507 mDocShell
->RemoveProgressListener(this);
512 SavePersistentAttributes();
516 if (!mWindow
) return NS_OK
;
518 // Ensure we don't reenter this code
519 if (mDestroying
) return NS_OK
;
521 mozilla::AutoRestore
<bool> guard(mDestroying
);
524 nsCOMPtr
<nsIAppShellService
> appShell(
525 do_GetService(NS_APPSHELLSERVICE_CONTRACTID
));
526 NS_ASSERTION(appShell
, "Couldn't get appShell... xpcom shutdown?");
528 appShell
->UnregisterTopLevelWindow(static_cast<nsIAppWindow
*>(this));
531 // Remove modality (if any) and hide while destroying. More than
532 // a convenience, the hide prevents user interaction with the partially
533 // destroyed window. This is especially necessary when the eldest window
534 // in a stack of modal windows is destroyed first. It happens.
535 ExitModalLoop(NS_OK
);
536 // XXX: Skip unmapping the window on Linux due to GLX hangs on the compositor
537 // thread with NVIDIA driver 310.32. We don't need to worry about user
538 // interactions with destroyed windows on X11 either.
539 #ifndef MOZ_WIDGET_GTK
540 if (mWindow
) mWindow
->Show(false);
543 RemoveTooltipSupport();
545 mDOMWindow
= nullptr;
547 RefPtr
<BrowsingContext
> bc(mDocShell
->GetBrowsingContext());
548 mDocShell
->Destroy();
550 mDocShell
= nullptr; // this can cause reentrancy of this function
553 mPrimaryContentShell
= nullptr;
555 if (mContentTreeOwner
) {
556 mContentTreeOwner
->AppWindow(nullptr);
557 NS_RELEASE(mContentTreeOwner
);
559 if (mPrimaryContentTreeOwner
) {
560 mPrimaryContentTreeOwner
->AppWindow(nullptr);
561 NS_RELEASE(mPrimaryContentTreeOwner
);
563 if (mChromeTreeOwner
) {
564 mChromeTreeOwner
->AppWindow(nullptr);
565 NS_RELEASE(mChromeTreeOwner
);
568 mWindow
->SetWidgetListener(nullptr); // nsWebShellWindow hackery
573 if (!mIsHiddenWindow
&& mRegistered
) {
574 /* Inform appstartup we've destroyed this window and it could
575 quit now if it wanted. This must happen at least after mDocShell
576 is destroyed, because onunload handlers fire then, and those being
577 script, anything could happen. A new window could open, even.
579 nsCOMPtr
<nsIObserverService
> obssvc
= services::GetObserverService();
580 NS_ASSERTION(obssvc
, "Couldn't get observer service?");
583 obssvc
->NotifyObservers(nullptr, "xul-window-destroyed", nullptr);
589 NS_IMETHODIMP
AppWindow::GetDevicePixelsPerDesktopPixel(double* aScale
) {
590 *aScale
= mWindow
? mWindow
->GetDesktopToDeviceScale().scale
: 1.0;
594 double AppWindow::GetWidgetCSSToDeviceScale() {
595 return mWindow
? mWindow
->GetDefaultScale().scale
: 1.0;
598 NS_IMETHODIMP
AppWindow::SetPositionDesktopPix(int32_t aX
, int32_t aY
) {
599 return MoveResize(Some(DesktopIntPoint(aX
, aY
)), Nothing(), false);
602 // The parameters here are device pixels; do the best we can to convert to
603 // desktop px, using the window's current scale factor (if available).
604 NS_IMETHODIMP
AppWindow::SetPosition(int32_t aX
, int32_t aY
) {
605 // Don't reset the window's size mode here - platforms that don't want to move
606 // maximized windows should reset it in their respective Move implementation.
607 return MoveResize(Some(LayoutDeviceIntPoint(aX
, aY
)), Nothing(), false);
610 NS_IMETHODIMP
AppWindow::GetPosition(int32_t* aX
, int32_t* aY
) {
611 return GetPositionAndSize(aX
, aY
, nullptr, nullptr);
614 NS_IMETHODIMP
AppWindow::SetSize(int32_t aCX
, int32_t aCY
, bool aRepaint
) {
615 /* any attempt to set the window's size or position overrides the window's
616 zoom state. this is important when these two states are competing while
617 the window is being opened. but it should probably just always be so. */
618 return MoveResize(Nothing(), Some(LayoutDeviceIntSize(aCX
, aCY
)), aRepaint
);
621 NS_IMETHODIMP
AppWindow::GetSize(int32_t* aCX
, int32_t* aCY
) {
622 return GetPositionAndSize(nullptr, nullptr, aCX
, aCY
);
625 NS_IMETHODIMP
AppWindow::SetPositionAndSize(int32_t aX
, int32_t aY
, int32_t aCX
,
626 int32_t aCY
, uint32_t aFlags
) {
627 /* any attempt to set the window's size or position overrides the window's
628 zoom state. this is important when these two states are competing while
629 the window is being opened. but it should probably just always be so. */
630 return MoveResize(Some(LayoutDeviceIntPoint(aX
, aY
)),
631 Some(LayoutDeviceIntSize(aCX
, aCY
)),
632 !!(aFlags
& nsIBaseWindow::eRepaint
));
635 NS_IMETHODIMP
AppWindow::GetPositionAndSize(int32_t* x
, int32_t* y
, int32_t* cx
,
637 if (!mWindow
) return NS_ERROR_FAILURE
;
639 LayoutDeviceIntRect rect
= mWindow
->GetScreenBounds();
641 if (x
) *x
= rect
.X();
642 if (y
) *y
= rect
.Y();
643 if (cx
) *cx
= rect
.Width();
644 if (cy
) *cy
= rect
.Height();
650 AppWindow::SetDimensions(DimensionRequest
&& aRequest
) {
651 if (aRequest
.mDimensionKind
== DimensionKind::Inner
) {
652 // For the chrome the inner size is the root shell size, and for the
653 // content it's the primary content size. We lack an indicator here that
654 // would allow us to distinguish between the two.
655 return NS_ERROR_NOT_IMPLEMENTED
;
658 MOZ_TRY(aRequest
.SupplementFrom(this));
659 return aRequest
.ApplyOuterTo(this);
663 AppWindow::GetDimensions(DimensionKind aDimensionKind
, int32_t* aX
, int32_t* aY
,
664 int32_t* aCX
, int32_t* aCY
) {
665 if (aDimensionKind
== DimensionKind::Inner
) {
666 // For the chrome the inner size is the root shell size, and for the
667 // content it's the primary content size. We lack an indicator here that
668 // would allow us to distinguish between the two.
669 return NS_ERROR_NOT_IMPLEMENTED
;
671 return GetPositionAndSize(aX
, aY
, aCX
, aCY
);
674 nsresult
AppWindow::MoveResize(const Maybe
<LayoutDeviceIntPoint
>& aPosition
,
675 const Maybe
<LayoutDeviceIntSize
>& aSize
,
677 NS_ENSURE_STATE(mWindow
);
678 DesktopToLayoutDeviceScale scale
= mWindow
->GetDesktopToDeviceScale();
679 return MoveResize(aPosition
? Some(*aPosition
/ scale
) : Nothing(),
680 aSize
? Some(*aSize
/ scale
) : Nothing(), aRepaint
);
683 nsresult
AppWindow::MoveResize(const Maybe
<DesktopPoint
>& aPosition
,
684 const Maybe
<DesktopSize
>& aSize
, bool aRepaint
) {
685 NS_ENSURE_STATE(mWindow
);
686 PersistentAttributes dirtyAttributes
;
688 if (!aPosition
&& !aSize
) {
689 MOZ_ASSERT_UNREACHABLE("Doing nothing?");
690 return NS_ERROR_UNEXPECTED
;
694 mWindow
->SetSizeMode(nsSizeMode_Normal
);
695 mIntrinsicallySized
= false;
696 mDominantClientSize
= false;
699 if (aPosition
&& aSize
) {
700 mWindow
->Resize(aPosition
->x
, aPosition
->y
, aSize
->width
, aSize
->height
,
702 dirtyAttributes
= {PersistentAttribute::Size
,
703 PersistentAttribute::Position
};
705 mWindow
->Resize(aSize
->width
, aSize
->height
, aRepaint
);
706 dirtyAttributes
= {PersistentAttribute::Size
};
707 } else if (aPosition
) {
708 mWindow
->Move(aPosition
->x
, aPosition
->y
);
709 dirtyAttributes
= {PersistentAttribute::Position
};
712 if (mSizingShellFromXUL
) {
713 // If we're invoked for sizing from XUL, we want to neither ignore anything
714 // nor persist anything, since it's already the value in XUL.
717 if (!mChromeLoaded
) {
718 // If we're called before the chrome is loaded someone obviously wants this
719 // window at this size & in the normal size mode (since it is the only mode
720 // in which setting dimensions makes sense). We don't persist this one-time
723 mIgnoreXULPosition
= true;
726 mIgnoreXULSize
= true;
727 mIgnoreXULSizeMode
= true;
732 PersistentAttributesDirty(dirtyAttributes
, Sync
);
736 NS_IMETHODIMP
AppWindow::Center(nsIAppWindow
* aRelative
, bool aScreen
,
739 bool screenCoordinates
= false, windowCoordinates
= false;
742 if (!mChromeLoaded
) {
743 // note we lose the parameters. at time of writing, this isn't a problem.
744 mCenterAfterLoad
= true;
748 if (!aScreen
&& !aRelative
) return NS_ERROR_INVALID_ARG
;
750 nsCOMPtr
<nsIScreenManager
> screenmgr
=
751 do_GetService("@mozilla.org/gfx/screenmanager;1", &result
);
752 if (NS_FAILED(result
)) {
756 nsCOMPtr
<nsIScreen
> screen
;
759 nsCOMPtr
<nsIBaseWindow
> base(do_QueryInterface(aRelative
));
761 rect
= RoundedToInt(base
->GetPositionAndSize() /
762 base
->DevicePixelsPerDesktopPixel());
763 // if centering on screen, convert that to the corresponding screen
765 screen
= screenmgr
->ScreenForRect(rect
);
767 windowCoordinates
= true;
772 if (!mOpenerScreenRect
.IsEmpty()) {
773 screen
= screenmgr
->ScreenForRect(mOpenerScreenRect
);
775 screenmgr
->GetPrimaryScreen(getter_AddRefs(screen
));
779 if (aScreen
&& screen
) {
780 rect
= screen
->GetAvailRectDisplayPix();
781 screenCoordinates
= true;
784 if (!screenCoordinates
&& !windowCoordinates
) {
785 return NS_ERROR_FAILURE
;
788 NS_ASSERTION(mWindow
, "what, no window?");
789 const LayoutDeviceIntSize ourDevSize
= GetSize();
790 const DesktopIntSize ourSize
=
791 RoundedToInt(ourDevSize
/ DevicePixelsPerDesktopPixel());
794 DesktopIntPoint((rect
.width
- ourSize
.width
) / 2,
795 (rect
.height
- ourSize
.height
) / (aAlert
? 3 : 2));
796 if (windowCoordinates
) {
797 mWindow
->ConstrainPosition(newPos
);
800 SetPositionDesktopPix(newPos
.x
, newPos
.y
);
802 // If moving the window caused it to change size, re-do the centering.
803 if (GetSize() != ourDevSize
) {
804 return Center(aRelative
, aScreen
, aAlert
);
809 NS_IMETHODIMP
AppWindow::Repaint(bool aForce
) {
810 // XXX First Check In
811 NS_ASSERTION(false, "Not Yet Implemented");
815 NS_IMETHODIMP
AppWindow::GetParentWidget(nsIWidget
** aParentWidget
) {
816 NS_ENSURE_ARG_POINTER(aParentWidget
);
817 NS_ENSURE_STATE(mWindow
);
819 NS_IF_ADDREF(*aParentWidget
= mWindow
->GetParent());
823 NS_IMETHODIMP
AppWindow::SetParentWidget(nsIWidget
* aParentWidget
) {
824 // XXX First Check In
825 NS_ASSERTION(false, "Not Yet Implemented");
829 NS_IMETHODIMP
AppWindow::GetParentNativeWindow(
830 nativeWindow
* aParentNativeWindow
) {
831 NS_ENSURE_ARG_POINTER(aParentNativeWindow
);
833 nsCOMPtr
<nsIWidget
> parentWidget
;
834 NS_ENSURE_SUCCESS(GetParentWidget(getter_AddRefs(parentWidget
)),
838 *aParentNativeWindow
= parentWidget
->GetNativeData(NS_NATIVE_WIDGET
);
844 NS_IMETHODIMP
AppWindow::SetParentNativeWindow(
845 nativeWindow aParentNativeWindow
) {
846 // XXX First Check In
847 NS_ASSERTION(false, "Not Yet Implemented");
851 NS_IMETHODIMP
AppWindow::GetNativeHandle(nsAString
& aNativeHandle
) {
852 nsCOMPtr
<nsIWidget
> mainWidget
;
853 NS_ENSURE_SUCCESS(GetMainWidget(getter_AddRefs(mainWidget
)),
857 nativeWindow nativeWindowPtr
= mainWidget
->GetNativeData(NS_NATIVE_WINDOW
);
858 /* the nativeWindow pointer is converted to and exposed as a string. This
859 is a more reliable way not to lose information (as opposed to JS
860 |Number| for instance) */
862 NS_ConvertASCIItoUTF16(nsPrintfCString("0x%p", nativeWindowPtr
));
868 NS_IMETHODIMP
AppWindow::GetVisibility(bool* aVisibility
) {
869 NS_ENSURE_ARG_POINTER(aVisibility
);
871 // Always claim to be visible for now. See bug
872 // https://bugzilla.mozilla.org/show_bug.cgi?id=306245.
879 NS_IMETHODIMP
AppWindow::SetVisibility(bool aVisibility
) {
880 if (!mChromeLoaded
) {
881 mShowAfterLoad
= aVisibility
;
889 NS_ENSURE_STATE(mDocShell
);
891 mDebuting
= true; // (Show / Focus is recursive)
893 // XXXTAB Do we really need to show docshell and the window? Isn't
894 // the window good enough?
895 mDocShell
->SetVisibility(aVisibility
);
896 // Store locally so it doesn't die on us. 'Show' can result in the window
897 // being closed with AppWindow::Destroy being called. That would set
898 // mWindow to null and posibly destroy the nsIWidget while its Show method
899 // is on the stack. We need to keep it alive until Show finishes.
900 nsCOMPtr
<nsIWidget
> window
= mWindow
;
901 window
->Show(aVisibility
);
903 nsCOMPtr
<nsIWindowMediator
> windowMediator(
904 do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
));
906 windowMediator
->UpdateWindowTimeStamp(static_cast<nsIAppWindow
*>(this));
908 // notify observers so that we can hide the splash screen if possible
909 nsCOMPtr
<nsIObserverService
> obssvc
= services::GetObserverService();
910 NS_ASSERTION(obssvc
, "Couldn't get observer service.");
912 obssvc
->NotifyObservers(static_cast<nsIAppWindow
*>(this),
913 "xul-window-visible", nullptr);
920 NS_IMETHODIMP
AppWindow::GetEnabled(bool* aEnabled
) {
921 NS_ENSURE_ARG_POINTER(aEnabled
);
924 *aEnabled
= mWindow
->IsEnabled();
928 *aEnabled
= true; // better guess than most
929 return NS_ERROR_FAILURE
;
932 NS_IMETHODIMP
AppWindow::SetEnabled(bool aEnable
) {
934 mWindow
->Enable(aEnable
);
937 return NS_ERROR_FAILURE
;
940 NS_IMETHODIMP
AppWindow::GetMainWidget(nsIWidget
** aMainWidget
) {
941 NS_ENSURE_ARG_POINTER(aMainWidget
);
942 NS_IF_ADDREF(*aMainWidget
= mWindow
);
946 NS_IMETHODIMP
AppWindow::GetTitle(nsAString
& aTitle
) {
951 NS_IMETHODIMP
AppWindow::SetTitle(const nsAString
& aTitle
) {
952 NS_ENSURE_STATE(mWindow
);
953 mTitle
.Assign(aTitle
);
955 NS_ENSURE_SUCCESS(mWindow
->SetTitle(mTitle
), NS_ERROR_FAILURE
);
959 //*****************************************************************************
960 // AppWindow: Helpers
961 //*****************************************************************************
963 NS_IMETHODIMP
AppWindow::EnsureChromeTreeOwner() {
964 if (mChromeTreeOwner
) return NS_OK
;
966 mChromeTreeOwner
= new nsChromeTreeOwner();
967 NS_ADDREF(mChromeTreeOwner
);
968 mChromeTreeOwner
->AppWindow(this);
973 NS_IMETHODIMP
AppWindow::EnsureContentTreeOwner() {
974 if (mContentTreeOwner
) return NS_OK
;
976 mContentTreeOwner
= new nsContentTreeOwner(false);
977 NS_ADDREF(mContentTreeOwner
);
978 mContentTreeOwner
->AppWindow(this);
983 NS_IMETHODIMP
AppWindow::EnsurePrimaryContentTreeOwner() {
984 if (mPrimaryContentTreeOwner
) return NS_OK
;
986 mPrimaryContentTreeOwner
= new nsContentTreeOwner(true);
987 NS_ADDREF(mPrimaryContentTreeOwner
);
988 mPrimaryContentTreeOwner
->AppWindow(this);
993 NS_IMETHODIMP
AppWindow::EnsurePrompter() {
994 if (mPrompter
) return NS_OK
;
996 nsCOMPtr
<mozIDOMWindowProxy
> ourWindow
;
997 nsresult rv
= GetWindowDOMWindow(getter_AddRefs(ourWindow
));
998 if (NS_SUCCEEDED(rv
)) {
999 nsCOMPtr
<nsIWindowWatcher
> wwatch
=
1000 do_GetService(NS_WINDOWWATCHER_CONTRACTID
);
1001 if (wwatch
) wwatch
->GetNewPrompter(ourWindow
, getter_AddRefs(mPrompter
));
1003 return mPrompter
? NS_OK
: NS_ERROR_FAILURE
;
1006 NS_IMETHODIMP
AppWindow::EnsureAuthPrompter() {
1007 if (mAuthPrompter
) return NS_OK
;
1009 nsCOMPtr
<mozIDOMWindowProxy
> ourWindow
;
1010 nsresult rv
= GetWindowDOMWindow(getter_AddRefs(ourWindow
));
1011 if (NS_SUCCEEDED(rv
)) {
1012 nsCOMPtr
<nsIWindowWatcher
> wwatch(
1013 do_GetService(NS_WINDOWWATCHER_CONTRACTID
));
1015 wwatch
->GetNewAuthPrompter(ourWindow
, getter_AddRefs(mAuthPrompter
));
1017 return mAuthPrompter
? NS_OK
: NS_ERROR_FAILURE
;
1020 NS_IMETHODIMP
AppWindow::GetAvailScreenSize(int32_t* aAvailWidth
,
1021 int32_t* aAvailHeight
) {
1022 nsCOMPtr
<mozIDOMWindowProxy
> domWindow
;
1023 GetWindowDOMWindow(getter_AddRefs(domWindow
));
1024 NS_ENSURE_STATE(domWindow
);
1026 auto* window
= nsGlobalWindowOuter::Cast(domWindow
);
1028 RefPtr
<nsScreen
> screen
= window
->GetScreen();
1029 NS_ENSURE_STATE(screen
);
1031 *aAvailWidth
= screen
->AvailWidth();
1032 *aAvailHeight
= screen
->AvailHeight();
1036 // Rounds window size to 1000x1000, or, if there isn't enough available
1037 // screen space, to a multiple of 200x100.
1038 NS_IMETHODIMP
AppWindow::ForceRoundedDimensions() {
1039 if (mIsHiddenWindow
) {
1043 CSSToLayoutDeviceScale scale
= UnscaledDevicePixelsPerCSSPixel();
1045 CSSIntSize availSizeCSS
;
1046 GetAvailScreenSize(&availSizeCSS
.width
, &availSizeCSS
.height
);
1048 // To get correct chrome size, we have to resize the window to a proper
1049 // size first. So, here, we size it to its available size.
1050 SetSpecifiedSize(availSizeCSS
.width
, availSizeCSS
.height
);
1052 // Get the current window size for calculating chrome UI size.
1053 CSSIntSize windowSizeCSS
= RoundedToInt(GetSize() / scale
);
1055 // Get the content size for calculating chrome UI size.
1056 LayoutDeviceIntSize contentSizeDev
;
1057 GetPrimaryContentSize(&contentSizeDev
.width
, &contentSizeDev
.height
);
1058 CSSIntSize contentSizeCSS
= RoundedToInt(contentSizeDev
/ scale
);
1060 // Calculate the chrome UI size.
1061 CSSIntSize chromeSizeCSS
= windowSizeCSS
- contentSizeCSS
;
1063 CSSIntSize targetSizeCSS
;
1064 // Here, we use the available screen dimensions as the input dimensions to
1065 // force the window to be rounded as the maximum available content size.
1066 nsContentUtils::CalcRoundedWindowSizeForResistingFingerprinting(
1067 chromeSizeCSS
.width
, chromeSizeCSS
.height
, availSizeCSS
.width
,
1068 availSizeCSS
.height
, availSizeCSS
.width
, availSizeCSS
.height
,
1069 false, // aSetOuterWidth
1070 false, // aSetOuterHeight
1071 &targetSizeCSS
.width
, &targetSizeCSS
.height
);
1073 LayoutDeviceIntSize targetSizeDev
= RoundedToInt(targetSizeCSS
* scale
);
1075 SetPrimaryContentSize(targetSizeDev
.width
, targetSizeDev
.height
);
1080 void AppWindow::OnChromeLoaded() {
1081 nsresult rv
= EnsureContentTreeOwner();
1083 if (NS_SUCCEEDED(rv
)) {
1084 mChromeLoaded
= true;
1086 SyncAttributesToWidget();
1089 if (mShowAfterLoad
) {
1090 SetVisibility(true);
1092 AddTooltipSupport();
1094 // At this point the window may have been closed already during Show() or
1095 // SyncAttributesToWidget(), so AppWindow::Destroy may already have been
1096 // called. Take care!
1098 mPersistentAttributesMask
+= AllPersistentAttributes();
1101 bool AppWindow::NeedsTooltipListener() {
1102 nsCOMPtr
<dom::Element
> docShellElement
= GetWindowDOMElement();
1103 if (!docShellElement
|| docShellElement
->IsXULElement()) {
1104 // Tooltips in XUL are handled by each element.
1107 // All other non-XUL document types need a tooltip listener.
1111 void AppWindow::AddTooltipSupport() {
1112 if (!NeedsTooltipListener()) {
1115 nsXULTooltipListener
* listener
= nsXULTooltipListener::GetInstance();
1120 nsCOMPtr
<dom::Element
> docShellElement
= GetWindowDOMElement();
1121 MOZ_ASSERT(docShellElement
);
1122 listener
->AddTooltipSupport(docShellElement
);
1125 void AppWindow::RemoveTooltipSupport() {
1126 if (!NeedsTooltipListener()) {
1129 nsXULTooltipListener
* listener
= nsXULTooltipListener::GetInstance();
1134 nsCOMPtr
<dom::Element
> docShellElement
= GetWindowDOMElement();
1135 MOZ_ASSERT(docShellElement
);
1136 listener
->RemoveTooltipSupport(docShellElement
);
1139 static Maybe
<int32_t> ReadIntAttribute(const Element
& aElement
,
1141 nsAtom
* aSecondary
= nullptr) {
1142 nsAutoString attrString
;
1143 if (!aElement
.GetAttr(aPrimary
, attrString
)) {
1145 return ReadIntAttribute(aElement
, aSecondary
);
1150 nsresult res
= NS_OK
;
1151 int32_t ret
= attrString
.ToInteger(&res
);
1152 return NS_SUCCEEDED(res
) ? Some(ret
) : Nothing();
1155 // If aSpecWidth and/or aSpecHeight are > 0, we will use these CSS px sizes
1156 // to fit to the screen when staggering windows; if they're negative,
1157 // we use the window's current size instead.
1158 bool AppWindow::LoadPositionFromXUL(int32_t aSpecWidth
, int32_t aSpecHeight
) {
1159 bool gotPosition
= false;
1161 // if we're the hidden window, don't try to validate our size/position. We're
1163 if (mIsHiddenWindow
) {
1167 RefPtr
<dom::Element
> root
= GetWindowDOMElement();
1168 NS_ENSURE_TRUE(root
, false);
1170 const LayoutDeviceIntRect devRect
= GetPositionAndSize();
1172 // Convert to global display pixels for consistent window management across
1173 // screens with diverse resolutions
1174 const DesktopIntPoint curPoint
=
1175 RoundedToInt(devRect
.TopLeft() / DevicePixelsPerDesktopPixel());
1177 // For size, use specified value if > 0, else current value
1178 CSSIntSize
cssSize(aSpecWidth
, aSpecHeight
);
1180 CSSIntSize currentSize
=
1181 RoundedToInt(devRect
.Size() / UnscaledDevicePixelsPerCSSPixel());
1182 if (aSpecHeight
<= 0) {
1183 cssSize
.height
= currentSize
.height
;
1185 if (aSpecWidth
<= 0) {
1186 cssSize
.width
= currentSize
.width
;
1190 // Obtain the position information from the <xul:window> element.
1191 DesktopIntPoint specPoint
= curPoint
;
1193 // Also read lowercase screenx/y because the front-end sometimes sets these
1194 // via setAttribute on HTML documents like about:blank, and stuff gets
1197 // TODO(emilio): We should probably rename screenX/Y to screen-x/y to
1198 // prevent this impedance mismatch.
1200 ReadIntAttribute(*root
, nsGkAtoms::screenX
, nsGkAtoms::screenx
)) {
1201 specPoint
.x
= *attr
;
1206 ReadIntAttribute(*root
, nsGkAtoms::screenY
, nsGkAtoms::screeny
)) {
1207 specPoint
.y
= *attr
;
1212 // Our position will be relative to our parent, if any
1213 nsCOMPtr
<nsIBaseWindow
> parent(do_QueryReferent(mParentWindow
));
1215 const DesktopIntPoint parentPos
= RoundedToInt(
1216 parent
->GetPosition() / parent
->DevicePixelsPerDesktopPixel());
1217 specPoint
+= parentPos
;
1219 StaggerPosition(specPoint
.x
.value
, specPoint
.y
.value
, cssSize
.width
,
1223 mWindow
->ConstrainPosition(specPoint
);
1224 if (specPoint
!= curPoint
) {
1225 SetPositionDesktopPix(specPoint
.x
, specPoint
.y
);
1231 static Maybe
<int32_t> ReadSize(const Element
& aElement
, nsAtom
* aAttr
,
1232 nsAtom
* aMinAttr
, nsAtom
* aMaxAttr
) {
1233 Maybe
<int32_t> attr
= ReadIntAttribute(aElement
, aAttr
);
1239 std::max(100, ReadIntAttribute(aElement
, aMinAttr
).valueOr(100));
1240 int32_t max
= ReadIntAttribute(aElement
, aMaxAttr
)
1241 .valueOr(std::numeric_limits
<int32_t>::max());
1243 return Some(std::min(max
, std::max(*attr
, min
)));
1246 bool AppWindow::LoadSizeFromXUL(int32_t& aSpecWidth
, int32_t& aSpecHeight
) {
1247 bool gotSize
= false;
1249 // if we're the hidden window, don't try to validate our size/position. We're
1251 if (mIsHiddenWindow
) {
1255 nsCOMPtr
<dom::Element
> windowElement
= GetWindowDOMElement();
1256 NS_ENSURE_TRUE(windowElement
, false);
1258 // Obtain the sizing information from the <xul:window> element.
1262 if (auto width
= ReadSize(*windowElement
, nsGkAtoms::width
,
1263 nsGkAtoms::minwidth
, nsGkAtoms::maxwidth
)) {
1264 aSpecWidth
= *width
;
1268 if (auto height
= ReadSize(*windowElement
, nsGkAtoms::height
,
1269 nsGkAtoms::minheight
, nsGkAtoms::maxheight
)) {
1270 aSpecHeight
= *height
;
1277 void AppWindow::SetSpecifiedSize(int32_t aSpecWidth
, int32_t aSpecHeight
) {
1278 // These are in CSS pixels of the main window.
1279 // TODO(emilio): In my testing we usually have a pres context around, can we
1280 // just use it? That'd simplify the coordinate calculations.
1282 int32_t screenWidth
;
1283 int32_t screenHeight
;
1285 if (NS_SUCCEEDED(GetAvailScreenSize(&screenWidth
, &screenHeight
))) {
1286 if (aSpecWidth
> screenWidth
) {
1287 aSpecWidth
= screenWidth
;
1289 if (aSpecHeight
> screenHeight
) {
1290 aSpecHeight
= screenHeight
;
1295 NS_ASSERTION(mWindow
, "we expected to have a window already");
1297 mIntrinsicallySized
= false;
1299 // Convert specified values to device pixels, and resize
1300 auto newSize
= RoundedToInt(CSSIntSize(aSpecWidth
, aSpecHeight
) *
1301 UnscaledDevicePixelsPerCSSPixel());
1303 // Note: Because of the asynchronous resizing on Linux we have to call
1304 // SetSize even when the size doesn't appear to change. A previous call that
1305 // has yet to complete can still change the size. We want the latest call to
1306 // define the final size.
1307 SetSize(newSize
.width
, newSize
.height
, false);
1310 /* Miscellaneous persistent attributes are attributes named in the
1311 |persist| attribute, other than size and position. Those are special
1312 because it's important to load those before one of the misc
1313 attributes (sizemode) and they require extra processing. */
1314 bool AppWindow::UpdateWindowStateFromMiscXULAttributes() {
1315 /* There are no misc attributes of interest to the hidden window.
1316 It's especially important not to try to validate that window's
1317 size or position, because some platforms (Mac OS X) need to
1318 make it visible and offscreen. */
1319 if (mIsHiddenWindow
) {
1323 nsCOMPtr
<dom::Element
> windowElement
= GetWindowDOMElement();
1324 NS_ENSURE_TRUE(windowElement
, false);
1326 nsAutoString stateString
;
1327 nsSizeMode sizeMode
= nsSizeMode_Normal
;
1329 // If we are told to ignore the size mode attribute, force
1331 if (mIgnoreXULSizeMode
) {
1332 windowElement
->SetAttr(nsGkAtoms::sizemode
, SIZEMODE_NORMAL
,
1335 // Otherwise, read sizemode from DOM and, if the window is resizable,
1337 windowElement
->GetAttr(nsGkAtoms::sizemode
, stateString
);
1338 if ((stateString
.Equals(SIZEMODE_MAXIMIZED
) ||
1339 stateString
.Equals(SIZEMODE_FULLSCREEN
))) {
1340 /* Honor request to maximize only if the window is sizable.
1341 An unsizable, unmaximizable, yet maximized window confuses
1342 Windows OS and is something of a travesty, anyway. */
1343 if (mChromeFlags
& nsIWebBrowserChrome::CHROME_WINDOW_RESIZE
) {
1344 mIntrinsicallySized
= false;
1346 sizeMode
= stateString
.Equals(SIZEMODE_MAXIMIZED
)
1347 ? nsSizeMode_Maximized
1348 : nsSizeMode_Fullscreen
;
1353 if (sizeMode
== nsSizeMode_Fullscreen
) {
1354 nsCOMPtr
<mozIDOMWindowProxy
> ourWindow
;
1355 GetWindowDOMWindow(getter_AddRefs(ourWindow
));
1356 auto* piWindow
= nsPIDOMWindowOuter::From(ourWindow
);
1357 piWindow
->SetFullScreen(true);
1359 // For maximized windows, ignore the XUL size and position attributes,
1360 // as setting them would set the window back to normal sizemode.
1361 if (sizeMode
== nsSizeMode_Maximized
) {
1362 mIgnoreXULSize
= true;
1363 mIgnoreXULPosition
= true;
1365 mWindow
->SetSizeMode(sizeMode
);
1370 /* Stagger windows of the same type so they don't appear on top of each other.
1371 This code does have a scary double loop -- it'll keep passing through
1372 the entire list of open windows until it finds a non-collision. Doesn't
1373 seem to be a problem, but it deserves watching.
1374 The aRequested{X,Y} parameters here are in desktop pixels;
1375 the aSpec{Width,Height} parameters are CSS pixel dimensions.
1377 void AppWindow::StaggerPosition(int32_t& aRequestedX
, int32_t& aRequestedY
,
1378 int32_t aSpecWidth
, int32_t aSpecHeight
) {
1379 // These "constants" will be converted from CSS to desktop pixels
1380 // for the appropriate screen, assuming we find a screen to use...
1381 // hence they're not actually declared const here.
1382 int32_t kOffset
= 22;
1386 int bouncedX
= 0, // bounced off vertical edge of screen
1387 bouncedY
= 0; // bounced off horizontal edge
1389 // look for any other windows of this type
1390 nsCOMPtr
<nsIWindowMediator
> wm(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
));
1393 nsCOMPtr
<dom::Element
> windowElement
= GetWindowDOMElement();
1394 if (!windowElement
) return;
1396 nsCOMPtr
<nsIAppWindow
> ourAppWindow(this);
1398 nsAutoString windowType
;
1399 windowElement
->GetAttr(nsGkAtoms::windowtype
, windowType
);
1401 DesktopIntRect screenRect
;
1402 bool gotScreen
= false;
1404 { // fetch screen coordinates
1405 nsCOMPtr
<nsIScreenManager
> screenMgr(
1406 do_GetService("@mozilla.org/gfx/screenmanager;1"));
1408 nsCOMPtr
<nsIScreen
> ourScreen
;
1409 // The coordinates here are already display pixels
1410 // XXX aSpecWidth and aSpecHeight are CSS pixels!
1411 screenMgr
->ScreenForRect(aRequestedX
, aRequestedY
, aSpecWidth
,
1412 aSpecHeight
, getter_AddRefs(ourScreen
));
1414 screenRect
= ourScreen
->GetAvailRectDisplayPix();
1416 // Get the screen's scaling factors and convert staggering constants
1417 // from CSS px to desktop pixel units
1418 auto scale
= ourScreen
->GetCSSToDesktopScale();
1419 kOffset
= (CSSCoord(kOffset
) * scale
).Rounded();
1420 kSlop
= (CSSCoord(kSlop
) * scale
).Rounded();
1421 // Convert dimensions from CSS to desktop pixels
1422 aSpecWidth
= (CSSCoord(aSpecWidth
) * scale
).Rounded();
1423 aSpecHeight
= (CSSCoord(aSpecHeight
) * scale
).Rounded();
1429 // One full pass through all windows of this type, repeat until no collisions.
1432 nsCOMPtr
<nsISimpleEnumerator
> windowList
;
1433 wm
->GetAppWindowEnumerator(windowType
.get(), getter_AddRefs(windowList
));
1435 if (!windowList
) break;
1437 // One full pass through all windows of this type, offset and stop on
1441 windowList
->HasMoreElements(&more
);
1444 nsCOMPtr
<nsISupports
> supportsWindow
;
1445 windowList
->GetNext(getter_AddRefs(supportsWindow
));
1447 nsCOMPtr
<nsIAppWindow
> listAppWindow(do_QueryInterface(supportsWindow
));
1448 if (listAppWindow
!= ourAppWindow
) {
1449 int32_t listX
, listY
;
1450 nsCOMPtr
<nsIBaseWindow
> listBaseWindow(
1451 do_QueryInterface(supportsWindow
));
1452 listBaseWindow
->GetPosition(&listX
, &listY
);
1455 listBaseWindow
->GetDevicePixelsPerDesktopPixel(&scale
))) {
1456 listX
= NSToIntRound(listX
/ scale
);
1457 listY
= NSToIntRound(listY
/ scale
);
1460 if (Abs(listX
- aRequestedX
) <= kSlop
&&
1461 Abs(listY
- aRequestedY
) <= kSlop
) {
1462 // collision! offset and start over
1464 aRequestedX
-= kOffset
;
1466 aRequestedX
+= kOffset
;
1467 aRequestedY
+= kOffset
;
1470 // if we're moving to the right and we need to bounce...
1471 if (!(bouncedX
& 0x1) &&
1472 ((aRequestedX
+ aSpecWidth
) > screenRect
.XMost())) {
1473 aRequestedX
= screenRect
.XMost() - aSpecWidth
;
1477 // if we're moving to the left and we need to bounce...
1478 if ((bouncedX
& 0x1) && aRequestedX
< screenRect
.X()) {
1479 aRequestedX
= screenRect
.X();
1483 // if we hit the bottom then bounce to the top
1484 if (aRequestedY
+ aSpecHeight
> screenRect
.YMost()) {
1485 aRequestedY
= screenRect
.Y();
1490 /* loop around again,
1491 but it's time to give up once we've covered the screen.
1492 there's a potential infinite loop with lots of windows. */
1493 keepTrying
= bouncedX
< 2 || bouncedY
== 0;
1498 } while (keepTrying
);
1501 void AppWindow::SyncAttributesToWidget() {
1502 nsCOMPtr
<dom::Element
> windowElement
= GetWindowDOMElement();
1503 if (!windowElement
) return;
1505 MOZ_DIAGNOSTIC_ASSERT(mWindow
, "No widget on SyncAttributesToWidget?");
1509 // Some attributes can change the client size (e.g. chromemargin on Windows
1510 // and MacOS). But we might want to keep it.
1511 const LayoutDeviceIntSize oldClientSize
= mWindow
->GetClientSize();
1512 // We have to check now whether we want to restore the client size, as any
1513 // change in size will reset its state.
1514 bool maintainClientSize
= mDominantClientSize
;
1516 // "hidechrome" attribute
1517 if (windowElement
->AttrValueIs(kNameSpaceID_None
, nsGkAtoms::hidechrome
,
1518 nsGkAtoms::_true
, eCaseMatters
)) {
1519 mWindow
->HideWindowChrome(true);
1522 NS_ENSURE_TRUE_VOID(mWindow
);
1524 // "chromemargin" attribute
1525 nsIntMargin margins
;
1526 windowElement
->GetAttribute(u
"chromemargin"_ns
, attr
);
1527 if (nsContentUtils::ParseIntMarginValue(attr
, margins
)) {
1528 mWindow
->SetNonClientMargins(
1529 LayoutDeviceIntMargin::FromUnknownMargin(margins
));
1532 NS_ENSURE_TRUE_VOID(mWindow
);
1534 // "windowtype", "windowclass", "windowname" attributes
1535 nsAutoString windowClassAttr
, windowNameAttr
;
1536 windowElement
->GetAttr(nsGkAtoms::windowtype
, attr
);
1537 windowElement
->GetAttribute(u
"windowclass"_ns
, windowClassAttr
);
1538 windowElement
->GetAttribute(u
"windowname"_ns
, windowNameAttr
);
1539 mWindow
->SetWindowClass(attr
, windowClassAttr
, windowNameAttr
);
1541 NS_ENSURE_TRUE_VOID(mWindow
);
1543 // Only change blank window status once we're loaded, so that a
1544 // partially-loaded browser window doesn't start painting early.
1545 if (mChromeLoaded
) {
1546 mWindow
->SetIsEarlyBlankWindow(attr
.EqualsLiteral("navigator:blank"));
1547 NS_ENSURE_TRUE_VOID(mWindow
);
1551 windowElement
->GetAttribute(u
"icon"_ns
, attr
);
1552 if (!attr
.IsEmpty()) {
1553 mWindow
->SetIcon(attr
);
1554 NS_ENSURE_TRUE_VOID(mWindow
);
1557 // "drawtitle" attribute
1558 windowElement
->GetAttribute(u
"drawtitle"_ns
, attr
);
1559 mWindow
->SetDrawsTitle(attr
.LowerCaseEqualsLiteral("true"));
1560 NS_ENSURE_TRUE_VOID(mWindow
);
1562 // "toggletoolbar" attribute
1563 windowElement
->GetAttribute(u
"toggletoolbar"_ns
, attr
);
1564 mWindow
->SetShowsToolbarButton(attr
.LowerCaseEqualsLiteral("true"));
1565 NS_ENSURE_TRUE_VOID(mWindow
);
1567 // "macnativefullscreen" attribute
1568 windowElement
->GetAttribute(u
"macnativefullscreen"_ns
, attr
);
1569 mWindow
->SetSupportsNativeFullscreen(attr
.LowerCaseEqualsLiteral("true"));
1570 NS_ENSURE_TRUE_VOID(mWindow
);
1572 // "macanimationtype" attribute
1573 windowElement
->GetAttribute(u
"macanimationtype"_ns
, attr
);
1574 if (attr
.EqualsLiteral("document")) {
1575 mWindow
->SetWindowAnimationType(nsIWidget::eDocumentWindowAnimation
);
1578 // Check if the client size did change and if we want to restore it.
1579 if (maintainClientSize
&& mWindow
->SizeMode() == nsSizeMode_Normal
&&
1580 oldClientSize
!= mWindow
->GetClientSize()) {
1581 mWindow
->ResizeClient(oldClientSize
/ mWindow
->GetDesktopToDeviceScale(),
1583 mDominantClientSize
= true;
1587 enum class ConversionDirection
{
1592 static void ConvertWindowSize(nsIAppWindow
* aWin
, const nsAtom
* aAttr
,
1593 ConversionDirection aDirection
,
1594 nsAString
& aInOutString
) {
1596 MOZ_ASSERT(aAttr
== nsGkAtoms::width
|| aAttr
== nsGkAtoms::height
);
1599 int32_t size
= aInOutString
.ToInteger(&rv
);
1600 if (NS_FAILED(rv
)) {
1604 int32_t sizeDiff
= aAttr
== nsGkAtoms::width
1605 ? aWin
->GetOuterToInnerWidthDifferenceInCSSPixels()
1606 : aWin
->GetOuterToInnerHeightDifferenceInCSSPixels();
1612 int32_t multiplier
= aDirection
== ConversionDirection::InnerToOuter
? 1 : -1;
1614 CopyASCIItoUTF16(nsPrintfCString("%d", size
+ multiplier
* sizeDiff
),
1618 nsresult
AppWindow::GetPersistentValue(const nsAtom
* aAttr
, nsAString
& aValue
) {
1619 if (!XRE_IsParentProcess()) {
1620 // The XULStore is only available in the parent process.
1621 return NS_ERROR_UNEXPECTED
;
1624 nsCOMPtr
<dom::Element
> docShellElement
= GetWindowDOMElement();
1625 if (!docShellElement
) {
1626 return NS_ERROR_FAILURE
;
1629 nsAutoString windowElementId
;
1630 docShellElement
->GetId(windowElementId
);
1631 // Elements must have an ID to be persisted.
1632 if (windowElementId
.IsEmpty()) {
1636 RefPtr
<dom::Document
> ownerDoc
= docShellElement
->OwnerDoc();
1637 nsIURI
* docURI
= ownerDoc
->GetDocumentURI();
1639 return NS_ERROR_FAILURE
;
1641 nsAutoCString utf8uri
;
1642 nsresult rv
= docURI
->GetSpec(utf8uri
);
1643 NS_ENSURE_SUCCESS(rv
, rv
);
1644 NS_ConvertUTF8toUTF16
uri(utf8uri
);
1647 mLocalStore
= do_GetService("@mozilla.org/xul/xulstore;1");
1648 if (NS_WARN_IF(!mLocalStore
)) {
1649 return NS_ERROR_NOT_INITIALIZED
;
1653 rv
= mLocalStore
->GetValue(uri
, windowElementId
, nsDependentAtomString(aAttr
),
1655 if (NS_WARN_IF(NS_FAILED(rv
))) {
1659 if (aAttr
== nsGkAtoms::width
|| aAttr
== nsGkAtoms::height
) {
1660 // Convert attributes from outer size to inner size for top-level
1661 // windows, see bug 1444525 & co.
1662 ConvertWindowSize(this, aAttr
, ConversionDirection::OuterToInner
, aValue
);
1668 nsresult
AppWindow::GetDocXulStoreKeys(nsString
& aUriSpec
,
1669 nsString
& aWindowElementId
) {
1670 nsCOMPtr
<dom::Element
> docShellElement
= GetWindowDOMElement();
1671 if (!docShellElement
) {
1672 return NS_ERROR_FAILURE
;
1675 docShellElement
->GetId(aWindowElementId
);
1676 // Match the behavior of XULPersist and only persist values if the element
1678 if (aWindowElementId
.IsEmpty()) {
1682 RefPtr
<dom::Document
> ownerDoc
= docShellElement
->OwnerDoc();
1683 nsIURI
* docURI
= ownerDoc
->GetDocumentURI();
1685 return NS_ERROR_FAILURE
;
1688 nsAutoCString utf8uri
;
1689 nsresult rv
= docURI
->GetSpec(utf8uri
);
1690 if (NS_WARN_IF(NS_FAILED(rv
))) {
1694 aUriSpec
= NS_ConvertUTF8toUTF16(utf8uri
);
1699 nsresult
AppWindow::MaybeSaveEarlyWindowPersistentValues(
1700 const LayoutDeviceIntRect
& aRect
) {
1703 nsAutoString windowElementId
;
1704 nsresult rv
= GetDocXulStoreKeys(uri
, windowElementId
);
1706 if (NS_WARN_IF(NS_FAILED(rv
))) {
1710 if (!windowElementId
.EqualsLiteral("main-window") ||
1711 !uri
.EqualsLiteral("chrome://browser/content/browser.xhtml")) {
1715 SkeletonUISettings settings
;
1717 settings
.screenX
= aRect
.X();
1718 settings
.screenY
= aRect
.Y();
1719 settings
.width
= aRect
.Width();
1720 settings
.height
= aRect
.Height();
1722 settings
.maximized
= mWindow
->SizeMode() == nsSizeMode_Maximized
;
1723 settings
.cssToDevPixelScaling
= UnscaledDevicePixelsPerCSSPixel().scale
;
1725 nsCOMPtr
<dom::Element
> windowElement
= GetWindowDOMElement();
1726 Document
* doc
= windowElement
->GetComposedDoc();
1727 Element
* urlbarEl
= doc
->GetElementById(u
"urlbar"_ns
);
1729 nsCOMPtr
<nsPIDOMWindowOuter
> window
= mDocShell
->GetWindow();
1730 nsCOMPtr
<nsIDOMWindowUtils
> utils
=
1731 nsGlobalWindowOuter::Cast(window
)->WindowUtils();
1732 RefPtr
<dom::DOMRect
> urlbarRect
;
1733 rv
= utils
->GetBoundsWithoutFlushing(urlbarEl
, getter_AddRefs(urlbarRect
));
1734 if (NS_WARN_IF(NS_FAILED(rv
))) {
1738 double urlbarX
= urlbarRect
->X();
1739 double urlbarWidth
= urlbarRect
->Width();
1741 // Hard-coding the following values and this behavior in general is rather
1742 // fragile, and can easily get out of sync with the actual front-end values.
1743 // This is not intended as a long-term solution, but only as the relatively
1744 // straightforward implementation of an experimental feature. If we want to
1745 // ship the skeleton UI to all users, we should strongly consider a more
1746 // robust solution than this. The vertical position of the urlbar will be
1748 nsAutoString attributeValue
;
1749 urlbarEl
->GetAttribute(u
"breakout-extend"_ns
, attributeValue
);
1750 // Scale down the urlbar if it is focused
1751 if (attributeValue
.EqualsLiteral("true")) {
1752 // defined in browser.inc.css as 2px
1753 int urlbarBreakoutExtend
= 2;
1754 // defined in urlbar-searchbar.inc.css as 5px
1755 int urlbarMarginInline
= 5;
1757 // breakout-extend measurements are defined in urlbar-searchbar.inc.css
1758 urlbarX
+= (double)(urlbarBreakoutExtend
+ urlbarMarginInline
);
1759 urlbarWidth
-= (double)(2 * (urlbarBreakoutExtend
+ urlbarMarginInline
));
1761 CSSPixelSpan urlbar
;
1762 urlbar
.start
= urlbarX
;
1763 urlbar
.end
= urlbar
.start
+ urlbarWidth
;
1764 settings
.urlbarSpan
= urlbar
;
1766 Element
* navbar
= doc
->GetElementById(u
"nav-bar"_ns
);
1768 Element
* searchbarEl
= doc
->GetElementById(u
"searchbar"_ns
);
1769 CSSPixelSpan searchbar
;
1770 if (navbar
->Contains(searchbarEl
)) {
1771 RefPtr
<dom::DOMRect
> searchbarRect
;
1772 rv
= utils
->GetBoundsWithoutFlushing(searchbarEl
,
1773 getter_AddRefs(searchbarRect
));
1774 if (NS_WARN_IF(NS_FAILED(rv
))) {
1777 searchbar
.start
= searchbarRect
->X();
1778 searchbar
.end
= searchbar
.start
+ searchbarRect
->Width();
1780 // There is no searchbar in the UI
1781 searchbar
.start
= 0;
1784 settings
.searchbarSpan
= searchbar
;
1786 nsAutoString bookmarksVisibility
;
1787 Preferences::GetString("browser.toolbars.bookmarks.visibility",
1788 bookmarksVisibility
);
1789 settings
.bookmarksToolbarShown
=
1790 bookmarksVisibility
.EqualsLiteral("always") ||
1791 bookmarksVisibility
.EqualsLiteral("newtab");
1793 Element
* menubar
= doc
->GetElementById(u
"toolbar-menubar"_ns
);
1794 menubar
->GetAttribute(u
"autohide"_ns
, attributeValue
);
1795 settings
.menubarShown
= attributeValue
.EqualsLiteral("false");
1798 nsCOMPtr
<nsIHTMLCollection
> toolbarSprings
= navbar
->GetElementsByTagNameNS(
1799 u
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"_ns
,
1800 u
"toolbarspring"_ns
, err
);
1802 return NS_ERROR_FAILURE
;
1804 mozilla::Vector
<CSSPixelSpan
> springs
;
1805 for (size_t i
= 0; i
< toolbarSprings
->Length(); i
++) {
1806 RefPtr
<Element
> springEl
= toolbarSprings
->Item(i
);
1807 RefPtr
<dom::DOMRect
> springRect
;
1808 rv
= utils
->GetBoundsWithoutFlushing(springEl
, getter_AddRefs(springRect
));
1809 if (NS_WARN_IF(NS_FAILED(rv
))) {
1812 CSSPixelSpan spring
;
1813 spring
.start
= springRect
->X();
1814 spring
.end
= spring
.start
+ springRect
->Width();
1815 if (!settings
.springs
.append(spring
)) {
1816 return NS_ERROR_FAILURE
;
1820 settings
.rtlEnabled
= intl::LocaleService::GetInstance()->IsAppLocaleRTL();
1822 bool isInTabletMode
= false;
1823 bool autoTouchModePref
=
1824 Preferences::GetBool("browser.touchmode.auto", false);
1825 if (autoTouchModePref
) {
1826 nsCOMPtr
<nsIWindowsUIUtils
> uiUtils(
1827 do_GetService("@mozilla.org/windows-ui-utils;1"));
1828 if (!NS_WARN_IF(!uiUtils
)) {
1829 uiUtils
->GetInTabletMode(&isInTabletMode
);
1833 if (isInTabletMode
) {
1834 settings
.uiDensity
= SkeletonUIDensity::Touch
;
1836 int uiDensityPref
= Preferences::GetInt("browser.uidensity", 0);
1837 switch (uiDensityPref
) {
1839 settings
.uiDensity
= SkeletonUIDensity::Default
;
1843 settings
.uiDensity
= SkeletonUIDensity::Compact
;
1847 settings
.uiDensity
= SkeletonUIDensity::Touch
;
1853 Unused
<< PersistPreXULSkeletonUIValues(settings
);
1859 nsresult
AppWindow::SetPersistentValue(const nsAtom
* aAttr
,
1860 const nsAString
& aValue
) {
1861 if (!XRE_IsParentProcess()) {
1862 // The XULStore is only available in the parent process.
1863 return NS_ERROR_UNEXPECTED
;
1867 nsAutoString windowElementId
;
1868 nsresult rv
= GetDocXulStoreKeys(uri
, windowElementId
);
1870 if (NS_FAILED(rv
) || windowElementId
.IsEmpty()) {
1874 nsAutoString
maybeConvertedValue(aValue
);
1875 if (aAttr
== nsGkAtoms::width
|| aAttr
== nsGkAtoms::height
) {
1876 // Make sure we store the <window> attributes as outer window size, see
1877 // bug 1444525 & co.
1878 ConvertWindowSize(this, aAttr
, ConversionDirection::InnerToOuter
,
1879 maybeConvertedValue
);
1883 mLocalStore
= do_GetService("@mozilla.org/xul/xulstore;1");
1884 if (NS_WARN_IF(!mLocalStore
)) {
1885 return NS_ERROR_NOT_INITIALIZED
;
1889 return mLocalStore
->SetValue(
1890 uri
, windowElementId
, nsDependentAtomString(aAttr
), maybeConvertedValue
);
1893 void AppWindow::MaybeSavePersistentPositionAndSize(
1894 PersistentAttributes aAttributes
, Element
& aRootElement
,
1895 const nsAString
& aPersistString
, bool aShouldPersist
) {
1896 if ((aAttributes
& PersistentAttributes
{PersistentAttribute::Position
,
1897 PersistentAttribute::Size
})
1902 // get our size, position and mode to persist
1903 LayoutDeviceIntRect rect
;
1904 if (NS_FAILED(mWindow
->GetRestoredBounds(rect
))) {
1908 // we use CSS pixels for size, but desktop pixels for position
1909 CSSToLayoutDeviceScale sizeScale
= UnscaledDevicePixelsPerCSSPixel();
1910 DesktopToLayoutDeviceScale posScale
= DevicePixelsPerDesktopPixel();
1912 // make our position relative to our parent, if any
1913 nsCOMPtr
<nsIBaseWindow
> parent(do_QueryReferent(mParentWindow
));
1915 int32_t parentX
, parentY
;
1916 if (NS_SUCCEEDED(parent
->GetPosition(&parentX
, &parentY
))) {
1917 rect
.MoveBy(-parentX
, -parentY
);
1921 nsAutoString sizeString
;
1922 // (only for size elements which are persisted)
1923 if (aAttributes
.contains(PersistentAttribute::Position
)) {
1924 if (aPersistString
.Find(u
"screenX") >= 0) {
1925 sizeString
.Truncate();
1926 sizeString
.AppendInt(NSToIntRound(rect
.X() / posScale
.scale
));
1927 aRootElement
.SetAttr(nsGkAtoms::screenX
, sizeString
, IgnoreErrors());
1928 if (aShouldPersist
) {
1929 Unused
<< SetPersistentValue(nsGkAtoms::screenX
, sizeString
);
1932 if (aPersistString
.Find(u
"screenY") >= 0) {
1933 sizeString
.Truncate();
1934 sizeString
.AppendInt(NSToIntRound(rect
.Y() / posScale
.scale
));
1935 aRootElement
.SetAttr(nsGkAtoms::screenY
, sizeString
, IgnoreErrors());
1936 if (aShouldPersist
) {
1937 Unused
<< SetPersistentValue(nsGkAtoms::screenY
, sizeString
);
1942 if (aAttributes
.contains(PersistentAttribute::Size
)) {
1943 LayoutDeviceIntRect innerRect
=
1944 rect
- GetOuterToInnerSizeDifference(mWindow
);
1945 if (aPersistString
.Find(u
"width") >= 0) {
1946 sizeString
.Truncate();
1947 sizeString
.AppendInt(NSToIntRound(innerRect
.Width() / sizeScale
.scale
));
1948 aRootElement
.SetAttr(nsGkAtoms::width
, sizeString
, IgnoreErrors());
1949 if (aShouldPersist
) {
1950 Unused
<< SetPersistentValue(nsGkAtoms::width
, sizeString
);
1953 if (aPersistString
.Find(u
"height") >= 0) {
1954 sizeString
.Truncate();
1955 sizeString
.AppendInt(NSToIntRound(innerRect
.Height() / sizeScale
.scale
));
1956 aRootElement
.SetAttr(nsGkAtoms::height
, sizeString
, IgnoreErrors());
1957 if (aShouldPersist
) {
1958 Unused
<< SetPersistentValue(nsGkAtoms::height
, sizeString
);
1963 Unused
<< MaybeSaveEarlyWindowPersistentValues(rect
);
1966 void AppWindow::MaybeSavePersistentMiscAttributes(
1967 PersistentAttributes aAttributes
, Element
& aRootElement
,
1968 const nsAString
& aPersistString
, bool aShouldPersist
) {
1969 if (!aAttributes
.contains(PersistentAttribute::Misc
)) {
1973 nsSizeMode sizeMode
= mWindow
->SizeMode();
1974 nsAutoString sizeString
;
1975 if (sizeMode
!= nsSizeMode_Minimized
) {
1976 if (sizeMode
== nsSizeMode_Maximized
) {
1977 sizeString
.Assign(SIZEMODE_MAXIMIZED
);
1978 } else if (sizeMode
== nsSizeMode_Fullscreen
) {
1979 sizeString
.Assign(SIZEMODE_FULLSCREEN
);
1981 sizeString
.Assign(SIZEMODE_NORMAL
);
1983 aRootElement
.SetAttr(nsGkAtoms::sizemode
, sizeString
, IgnoreErrors());
1984 if (aShouldPersist
&& aPersistString
.Find(u
"sizemode") >= 0) {
1985 Unused
<< SetPersistentValue(nsGkAtoms::sizemode
, sizeString
);
1988 aRootElement
.SetAttribute(u
"gtktiledwindow"_ns
,
1989 mWindow
->IsTiled() ? u
"true"_ns
: u
"false"_ns
,
1993 void AppWindow::SavePersistentAttributes(
1994 const PersistentAttributes aAttributes
) {
1995 // can happen when the persistence timer fires at an inopportune time
1996 // during window shutdown
2001 nsCOMPtr
<dom::Element
> docShellElement
= GetWindowDOMElement();
2002 if (!docShellElement
) {
2006 nsAutoString persistString
;
2007 docShellElement
->GetAttr(nsGkAtoms::persist
, persistString
);
2008 if (persistString
.IsEmpty()) { // quick check which sometimes helps
2009 mPersistentAttributesDirty
.clear();
2013 bool shouldPersist
= mWindow
->SizeMode() != nsSizeMode_Fullscreen
;
2014 MaybeSavePersistentPositionAndSize(aAttributes
, *docShellElement
,
2015 persistString
, shouldPersist
);
2016 MaybeSavePersistentMiscAttributes(aAttributes
, *docShellElement
,
2017 persistString
, shouldPersist
);
2018 mPersistentAttributesDirty
-= aAttributes
;
2021 NS_IMETHODIMP
AppWindow::GetWindowDOMWindow(mozIDOMWindowProxy
** aDOMWindow
) {
2022 NS_ENSURE_STATE(mDocShell
);
2024 if (!mDOMWindow
) mDOMWindow
= mDocShell
->GetWindow();
2025 NS_ENSURE_TRUE(mDOMWindow
, NS_ERROR_FAILURE
);
2027 *aDOMWindow
= mDOMWindow
;
2028 NS_ADDREF(*aDOMWindow
);
2032 dom::Element
* AppWindow::GetWindowDOMElement() const {
2033 NS_ENSURE_TRUE(mDocShell
, nullptr);
2035 nsCOMPtr
<nsIDocumentViewer
> viewer
;
2036 mDocShell
->GetDocViewer(getter_AddRefs(viewer
));
2037 NS_ENSURE_TRUE(viewer
, nullptr);
2039 const dom::Document
* document
= viewer
->GetDocument();
2040 NS_ENSURE_TRUE(document
, nullptr);
2042 return document
->GetRootElement();
2045 nsresult
AppWindow::ContentShellAdded(nsIDocShellTreeItem
* aContentShell
,
2047 // Set the default content tree owner
2049 NS_ENSURE_SUCCESS(EnsurePrimaryContentTreeOwner(), NS_ERROR_FAILURE
);
2050 aContentShell
->SetTreeOwner(mPrimaryContentTreeOwner
);
2051 mPrimaryContentShell
= aContentShell
;
2052 mPrimaryBrowserParent
= nullptr;
2054 NS_ENSURE_SUCCESS(EnsureContentTreeOwner(), NS_ERROR_FAILURE
);
2055 aContentShell
->SetTreeOwner(mContentTreeOwner
);
2056 if (mPrimaryContentShell
== aContentShell
) mPrimaryContentShell
= nullptr;
2062 nsresult
AppWindow::ContentShellRemoved(nsIDocShellTreeItem
* aContentShell
) {
2063 if (mPrimaryContentShell
== aContentShell
) {
2064 mPrimaryContentShell
= nullptr;
2070 AppWindow::GetPrimaryContentSize(int32_t* aWidth
, int32_t* aHeight
) {
2071 if (mPrimaryBrowserParent
) {
2072 return GetPrimaryRemoteTabSize(aWidth
, aHeight
);
2074 if (mPrimaryContentShell
) {
2075 return GetPrimaryContentShellSize(aWidth
, aHeight
);
2077 return NS_ERROR_UNEXPECTED
;
2080 nsresult
AppWindow::GetPrimaryRemoteTabSize(int32_t* aWidth
, int32_t* aHeight
) {
2081 BrowserHost
* host
= BrowserHost::GetFrom(mPrimaryBrowserParent
.get());
2082 // Need strong ref, since Client* can run script.
2083 RefPtr
<dom::Element
> element
= host
->GetOwnerElement();
2084 NS_ENSURE_STATE(element
);
2086 CSSIntSize
size(element
->ClientWidth(), element
->ClientHeight());
2087 LayoutDeviceIntSize sizeDev
=
2088 RoundedToInt(size
* UnscaledDevicePixelsPerCSSPixel());
2090 *aWidth
= sizeDev
.width
;
2093 *aHeight
= sizeDev
.height
;
2098 nsresult
AppWindow::GetPrimaryContentShellSize(int32_t* aWidth
,
2100 NS_ENSURE_STATE(mPrimaryContentShell
);
2102 nsCOMPtr
<nsIBaseWindow
> shellWindow(do_QueryInterface(mPrimaryContentShell
));
2103 NS_ENSURE_STATE(shellWindow
);
2105 LayoutDeviceIntSize sizeDev
= shellWindow
->GetSize();
2107 *aWidth
= sizeDev
.width
;
2110 *aHeight
= sizeDev
.height
;
2116 AppWindow::SetPrimaryContentSize(int32_t aWidth
, int32_t aHeight
) {
2117 if (mPrimaryBrowserParent
) {
2118 return SetPrimaryRemoteTabSize(aWidth
, aHeight
);
2120 if (mPrimaryContentShell
) {
2121 return SizeShellTo(mPrimaryContentShell
, aWidth
, aHeight
);
2123 return NS_ERROR_UNEXPECTED
;
2126 nsresult
AppWindow::SetPrimaryRemoteTabSize(int32_t aWidth
, int32_t aHeight
) {
2127 int32_t shellWidth
, shellHeight
;
2128 GetPrimaryRemoteTabSize(&shellWidth
, &shellHeight
);
2129 SizeShellToWithLimit(aWidth
, aHeight
, shellWidth
, shellHeight
);
2133 nsresult
AppWindow::GetRootShellSize(int32_t* aWidth
, int32_t* aHeight
) {
2134 NS_ENSURE_TRUE(mDocShell
, NS_ERROR_FAILURE
);
2135 return mDocShell
->GetSize(aWidth
, aHeight
);
2138 nsresult
AppWindow::SetRootShellSize(int32_t aWidth
, int32_t aHeight
) {
2139 return SizeShellTo(mDocShell
, aWidth
, aHeight
);
2142 NS_IMETHODIMP
AppWindow::SizeShellTo(nsIDocShellTreeItem
* aShellItem
,
2143 int32_t aCX
, int32_t aCY
) {
2144 MOZ_ASSERT(aShellItem
== mDocShell
|| aShellItem
== mPrimaryContentShell
);
2145 if (aShellItem
== mDocShell
) {
2147 LayoutDeviceIntSize(aCX
, aCY
) + GetOuterToInnerSizeDifference(mWindow
);
2148 SetSize(newSize
.width
, newSize
.height
, /* aRepaint = */ true);
2149 mDominantClientSize
= true;
2153 // XXXTAB This is wrong, we should actually reflow based on the passed in
2154 // shell. For now we are hacking and doing delta sizing. This is bad
2155 // because it assumes all size we add will go to the shell which probably
2157 nsCOMPtr
<nsIBaseWindow
> shellAsWin(do_QueryInterface(aShellItem
));
2158 NS_ENSURE_TRUE(shellAsWin
, NS_ERROR_FAILURE
);
2162 shellAsWin
->GetSize(&width
, &height
);
2164 SizeShellToWithLimit(aCX
, aCY
, width
, height
);
2169 NS_IMETHODIMP
AppWindow::ExitModalLoop(nsresult aStatus
) {
2170 if (mContinueModalLoop
) EnableParent(true);
2171 mContinueModalLoop
= false;
2172 mModalStatus
= aStatus
;
2176 // top-level function to create a new window
2177 NS_IMETHODIMP
AppWindow::CreateNewWindow(int32_t aChromeFlags
,
2178 nsIOpenWindowInfo
* aOpenWindowInfo
,
2179 nsIAppWindow
** _retval
) {
2180 NS_ENSURE_ARG_POINTER(_retval
);
2182 if (aChromeFlags
& nsIWebBrowserChrome::CHROME_OPENAS_CHROME
) {
2185 "Unexpected nsOpenWindowInfo when creating a new chrome window");
2186 return CreateNewChromeWindow(aChromeFlags
, _retval
);
2189 return CreateNewContentWindow(aChromeFlags
, aOpenWindowInfo
, _retval
);
2192 NS_IMETHODIMP
AppWindow::CreateNewChromeWindow(int32_t aChromeFlags
,
2193 nsIAppWindow
** _retval
) {
2194 nsCOMPtr
<nsIAppShellService
> appShell(
2195 do_GetService(NS_APPSHELLSERVICE_CONTRACTID
));
2196 NS_ENSURE_TRUE(appShell
, NS_ERROR_FAILURE
);
2198 // Just do a normal create of a window and return.
2199 nsCOMPtr
<nsIAppWindow
> newWindow
;
2200 appShell
->CreateTopLevelWindow(
2201 this, nullptr, aChromeFlags
, nsIAppShellService::SIZE_TO_CONTENT
,
2202 nsIAppShellService::SIZE_TO_CONTENT
, getter_AddRefs(newWindow
));
2204 NS_ENSURE_TRUE(newWindow
, NS_ERROR_FAILURE
);
2206 newWindow
.forget(_retval
);
2211 NS_IMETHODIMP
AppWindow::CreateNewContentWindow(
2212 int32_t aChromeFlags
, nsIOpenWindowInfo
* aOpenWindowInfo
,
2213 nsIAppWindow
** _retval
) {
2214 nsCOMPtr
<nsIAppShellService
> appShell(
2215 do_GetService(NS_APPSHELLSERVICE_CONTRACTID
));
2216 NS_ENSURE_TRUE(appShell
, NS_ERROR_FAILURE
);
2218 // We need to create a new top level window and then enter a nested
2219 // loop. Eventually the new window will be told that it has loaded,
2220 // at which time we know it is safe to spin out of the nested loop
2221 // and allow the opening code to proceed.
2223 nsCOMPtr
<nsIURI
> uri
;
2224 nsAutoCString urlStr
;
2225 urlStr
.AssignLiteral(BROWSER_CHROME_URL_QUOTED
);
2227 nsCOMPtr
<nsIIOService
> service(do_GetService(NS_IOSERVICE_CONTRACTID
));
2229 service
->NewURI(urlStr
, nullptr, nullptr, getter_AddRefs(uri
));
2231 NS_ENSURE_TRUE(uri
, NS_ERROR_FAILURE
);
2233 // We need to create a chrome window to contain the content window we're about
2234 // to pass back. The subject principal needs to be system while we're creating
2235 // it to make things work right, so force a system caller. See bug 799348
2236 // comment 13 for a description of what happens when we don't.
2237 nsCOMPtr
<nsIAppWindow
> newWindow
;
2239 AutoNoJSAPI nojsapi
;
2240 appShell
->CreateTopLevelWindow(this, uri
, aChromeFlags
, 615, 480,
2241 getter_AddRefs(newWindow
));
2242 NS_ENSURE_TRUE(newWindow
, NS_ERROR_FAILURE
);
2246 static_cast<AppWindow
*>(static_cast<nsIAppWindow
*>(newWindow
));
2248 // Specify which flags should be used by browser.xhtml to create the initial
2249 // content browser window.
2250 appWin
->mInitialOpenWindowInfo
= aOpenWindowInfo
;
2252 // Specify that we want the window to remain locked until the chrome has
2254 appWin
->LockUntilChromeLoad();
2257 AutoNoJSAPI nojsapi
;
2258 SpinEventLoopUntil("AppWindow::CreateNewContentWindow"_ns
,
2259 [&]() { return !appWin
->IsLocked(); });
2262 NS_ENSURE_STATE(appWin
->mPrimaryContentShell
||
2263 appWin
->mPrimaryBrowserParent
);
2264 MOZ_ASSERT_IF(appWin
->mPrimaryContentShell
,
2265 !aOpenWindowInfo
->GetNextRemoteBrowser());
2267 newWindow
.forget(_retval
);
2272 NS_IMETHODIMP
AppWindow::GetHasPrimaryContent(bool* aResult
) {
2273 *aResult
= mPrimaryBrowserParent
|| mPrimaryContentShell
;
2277 void AppWindow::EnableParent(bool aEnable
) {
2278 nsCOMPtr
<nsIBaseWindow
> parentWindow
;
2279 nsCOMPtr
<nsIWidget
> parentWidget
;
2281 parentWindow
= do_QueryReferent(mParentWindow
);
2282 if (parentWindow
) parentWindow
->GetMainWidget(getter_AddRefs(parentWidget
));
2283 if (parentWidget
) parentWidget
->Enable(aEnable
);
2286 void AppWindow::SetContentScrollbarVisibility(bool aVisible
) {
2287 nsCOMPtr
<nsPIDOMWindowOuter
> contentWin(
2288 do_GetInterface(mPrimaryContentShell
));
2293 nsContentUtils::SetScrollbarsVisibility(contentWin
->GetDocShell(), aVisible
);
2296 void AppWindow::ApplyChromeFlags() {
2297 nsCOMPtr
<dom::Element
> window
= GetWindowDOMElement();
2302 if (mChromeLoaded
) {
2303 // The two calls in this block don't need to happen early because they
2304 // don't cause a global restyle on the document. Not only that, but the
2305 // scrollbar stuff needs a content area to toggle the scrollbars on anyway.
2306 // So just don't do these until mChromeLoaded is true.
2308 // Scrollbars have their own special treatment.
2309 SetContentScrollbarVisibility(mChromeFlags
&
2310 nsIWebBrowserChrome::CHROME_SCROLLBARS
);
2313 /* the other flags are handled together. we have style rules
2314 in navigator.css that trigger visibility based on
2315 the 'chromehidden' attribute of the <window> tag. */
2316 nsAutoString newvalue
;
2318 if (!(mChromeFlags
& nsIWebBrowserChrome::CHROME_MENUBAR
))
2319 newvalue
.AppendLiteral("menubar ");
2321 if (!(mChromeFlags
& nsIWebBrowserChrome::CHROME_TOOLBAR
))
2322 newvalue
.AppendLiteral("toolbar ");
2324 if (!(mChromeFlags
& nsIWebBrowserChrome::CHROME_LOCATIONBAR
))
2325 newvalue
.AppendLiteral("location ");
2327 if (!(mChromeFlags
& nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR
))
2328 newvalue
.AppendLiteral("directories ");
2330 if (!(mChromeFlags
& nsIWebBrowserChrome::CHROME_STATUSBAR
))
2331 newvalue
.AppendLiteral("status ");
2333 if (!(mChromeFlags
& nsIWebBrowserChrome::CHROME_EXTRA
))
2334 newvalue
.AppendLiteral("extrachrome ");
2336 // Note that if we're not actually changing the value this will be a no-op,
2337 // so no need to compare to the old value.
2338 IgnoredErrorResult rv
;
2339 window
->SetAttribute(u
"chromehidden"_ns
, newvalue
, rv
);
2343 AppWindow::BeforeStartLayout() {
2345 // Ordering here is important, loading width/height values in
2346 // LoadPersistentWindowState() depends on the chromemargin attribute (since
2347 // we need to translate outer to inner sizes).
2348 SyncAttributesToWidget();
2349 LoadPersistentWindowState();
2357 AppWindow::LockAspectRatio(bool aShouldLock
) {
2358 mWindow
->LockAspectRatio(aShouldLock
);
2363 AppWindow::NeedFastSnaphot() {
2364 MOZ_ASSERT(mWindow
);
2366 return NS_ERROR_FAILURE
;
2368 mWindow
->SetNeedFastSnaphot();
2372 void AppWindow::LoadPersistentWindowState() {
2373 nsCOMPtr
<dom::Element
> docShellElement
= GetWindowDOMElement();
2374 if (!docShellElement
) {
2378 // Check if the window wants to persist anything.
2379 nsAutoString persist
;
2380 docShellElement
->GetAttr(nsGkAtoms::persist
, persist
);
2381 if (persist
.IsEmpty()) {
2385 auto loadValue
= [&](nsAtom
* aAttr
) {
2386 nsDependentAtomString
attrString(aAttr
);
2387 if (persist
.Find(attrString
) >= 0) {
2389 nsresult rv
= GetPersistentValue(aAttr
, value
);
2390 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
), "Failed to get persistent state.");
2391 if (NS_SUCCEEDED(rv
) && !value
.IsEmpty()) {
2392 docShellElement
->SetAttr(aAttr
, value
, IgnoreErrors());
2397 loadValue(nsGkAtoms::screenX
);
2398 loadValue(nsGkAtoms::screenY
);
2399 loadValue(nsGkAtoms::width
);
2400 loadValue(nsGkAtoms::height
);
2401 loadValue(nsGkAtoms::sizemode
);
2404 void AppWindow::IntrinsicallySizeShell(const CSSIntSize
& aWindowDiff
,
2405 int32_t& aSpecWidth
,
2406 int32_t& aSpecHeight
) {
2407 nsCOMPtr
<nsIDocumentViewer
> viewer
;
2408 mDocShell
->GetDocViewer(getter_AddRefs(viewer
));
2412 RefPtr
<nsDocShell
> docShell
= mDocShell
;
2414 CSSIntCoord maxWidth
= 0;
2415 CSSIntCoord maxHeight
= 0;
2416 CSSIntCoord prefWidth
= 0;
2417 if (RefPtr element
= GetWindowDOMElement()) {
2418 nsAutoString prefWidthAttr
;
2419 if (element
->GetAttr(nsGkAtoms::prefwidth
, prefWidthAttr
)) {
2420 // TODO: Make this more generic perhaps?
2421 if (prefWidthAttr
.EqualsLiteral("min-width")) {
2422 if (auto* f
= element
->GetPrimaryFrame(FlushType::Frames
)) {
2423 const auto& coord
= f
->StylePosition()->mMinWidth
;
2424 if (coord
.ConvertsToLength()) {
2425 prefWidth
= CSSPixel::FromAppUnitsRounded(coord
.ToLength());
2432 Maybe
<CSSIntSize
> size
=
2433 viewer
->GetContentSize(maxWidth
, maxHeight
, prefWidth
);
2437 nsPresContext
* pc
= viewer
->GetPresContext();
2438 MOZ_ASSERT(pc
, "Should have pres context");
2440 int32_t width
= pc
->CSSPixelsToDevPixels(size
->width
);
2441 int32_t height
= pc
->CSSPixelsToDevPixels(size
->height
);
2442 SizeShellTo(docShell
, width
, height
);
2444 // Update specified size for the final LoadPositionFromXUL call.
2445 aSpecWidth
= size
->width
+ aWindowDiff
.width
;
2446 aSpecHeight
= size
->height
+ aWindowDiff
.height
;
2449 void AppWindow::SizeShell() {
2450 AutoRestore
<bool> sizingShellFromXUL(mSizingShellFromXUL
);
2451 mSizingShellFromXUL
= true;
2453 int32_t specWidth
= -1, specHeight
= -1;
2454 bool gotSize
= false;
2456 nsAutoString windowType
;
2457 if (nsCOMPtr
<dom::Element
> windowElement
= GetWindowDOMElement()) {
2458 windowElement
->GetAttr(nsGkAtoms::windowtype
, windowType
);
2461 const CSSIntSize windowDiff
= GetOuterToInnerSizeDifferenceInCSSPixels(
2462 mWindow
, UnscaledDevicePixelsPerCSSPixel());
2464 // If we're using fingerprint resistance, we're going to resize the window
2465 // once we have primary content.
2466 if (nsContentUtils::ShouldResistFingerprinting(
2467 "if RFP is enabled we want to round the dimensions of the new"
2468 "new pop up window regardless of their origin",
2469 RFPTarget::RoundWindowSize
) &&
2470 windowType
.EqualsLiteral("navigator:browser")) {
2471 // Once we've got primary content, force dimensions.
2472 if (mPrimaryContentShell
|| mPrimaryBrowserParent
) {
2473 ForceRoundedDimensions();
2475 // Always avoid setting size/sizemode on this window.
2476 mIgnoreXULSize
= true;
2477 mIgnoreXULSizeMode
= true;
2478 } else if (!mIgnoreXULSize
) {
2479 gotSize
= LoadSizeFromXUL(specWidth
, specHeight
);
2480 specWidth
+= windowDiff
.width
;
2481 specHeight
+= windowDiff
.height
;
2484 bool positionSet
= !mIgnoreXULPosition
;
2485 nsCOMPtr
<nsIAppWindow
> parentWindow(do_QueryReferent(mParentWindow
));
2486 #if defined(XP_UNIX) && !defined(XP_MACOSX)
2487 // don't override WM placement on unix for independent, top-level windows
2488 // (however, we think the benefits of intelligent dependent window placement
2489 // trump that override.)
2490 if (!parentWindow
) positionSet
= false;
2493 // We have to do this before sizing the window, because sizing depends
2494 // on the resolution of the screen we're on. But positioning needs to
2495 // know the size so that it can constrain to screen bounds.... as an
2496 // initial guess here, we'll use the specified size (if any).
2497 positionSet
= LoadPositionFromXUL(specWidth
, specHeight
);
2501 SetSpecifiedSize(specWidth
, specHeight
);
2504 // If LoadSizeFromXUL set the size, mIntrinsicallySized will be false.
2505 if (mIntrinsicallySized
) {
2506 IntrinsicallySizeShell(windowDiff
, specWidth
, specHeight
);
2509 // Now that we have set the window's final size, we can re-do its
2510 // positioning so that it is properly constrained to the screen.
2512 LoadPositionFromXUL(specWidth
, specHeight
);
2515 UpdateWindowStateFromMiscXULAttributes();
2517 if (mChromeLoaded
&& mCenterAfterLoad
&& !positionSet
&&
2518 mWindow
->SizeMode() == nsSizeMode_Normal
) {
2519 Center(parentWindow
, parentWindow
? false : true, false);
2523 NS_IMETHODIMP
AppWindow::GetXULBrowserWindow(
2524 nsIXULBrowserWindow
** aXULBrowserWindow
) {
2525 NS_IF_ADDREF(*aXULBrowserWindow
= mXULBrowserWindow
);
2529 NS_IMETHODIMP
AppWindow::SetXULBrowserWindow(
2530 nsIXULBrowserWindow
* aXULBrowserWindow
) {
2531 mXULBrowserWindow
= aXULBrowserWindow
;
2535 // Given the dimensions of some content area held within this XUL window, and
2536 // assuming that that content area will change its dimensions in linear
2537 // proportion to the dimensions of this XUL window, changes the size of the XUL
2538 // window so that the content area reaches a particular size.
2539 void AppWindow::SizeShellToWithLimit(int32_t aDesiredWidth
,
2540 int32_t aDesiredHeight
,
2541 int32_t shellItemWidth
,
2542 int32_t shellItemHeight
) {
2543 int32_t widthDelta
= aDesiredWidth
- shellItemWidth
;
2544 int32_t heightDelta
= aDesiredHeight
- shellItemHeight
;
2546 int32_t winWidth
= 0;
2547 int32_t winHeight
= 0;
2549 GetSize(&winWidth
, &winHeight
);
2550 // There's no point in trying to make the window smaller than the
2551 // desired content area size --- that's not likely to work. This whole
2552 // function assumes that the outer docshell is adding some constant
2553 // "border" chrome to the content area.
2554 winWidth
= std::max(winWidth
+ widthDelta
, aDesiredWidth
);
2555 winHeight
= std::max(winHeight
+ heightDelta
, aDesiredHeight
);
2557 // Note: Because of the asynchronous resizing on Linux we have to call
2558 // SetSize even when the size doesn't appear to change. A previous call that
2559 // has yet to complete can still change the size. We want the latest call to
2560 // define the final size.
2561 SetSize(winWidth
, winHeight
, true);
2562 mDominantClientSize
= true;
2565 nsresult
AppWindow::GetTabCount(uint32_t* aResult
) {
2566 if (mXULBrowserWindow
) {
2567 return mXULBrowserWindow
->GetTabCount(aResult
);
2574 nsresult
AppWindow::GetInitialOpenWindowInfo(
2575 nsIOpenWindowInfo
** aOpenWindowInfo
) {
2576 NS_ENSURE_ARG_POINTER(aOpenWindowInfo
);
2577 *aOpenWindowInfo
= do_AddRef(mInitialOpenWindowInfo
).take();
2581 PresShell
* AppWindow::GetPresShell() {
2585 return mDocShell
->GetPresShell();
2588 bool AppWindow::WindowMoved(nsIWidget
* aWidget
, int32_t x
, int32_t y
) {
2589 nsXULPopupManager
* pm
= nsXULPopupManager::GetInstance();
2591 nsCOMPtr
<nsPIDOMWindowOuter
> window
=
2592 mDocShell
? mDocShell
->GetWindow() : nullptr;
2593 pm
->AdjustPopupsOnWindowChange(window
);
2596 // Notify all tabs that the widget moved.
2597 if (mDocShell
&& mDocShell
->GetWindow()) {
2598 nsCOMPtr
<EventTarget
> eventTarget
=
2599 mDocShell
->GetWindow()->GetTopWindowRoot();
2600 nsContentUtils::DispatchChromeEvent(
2601 mDocShell
->GetDocument(), eventTarget
, u
"MozUpdateWindowPos"_ns
,
2602 CanBubble::eNo
, Cancelable::eNo
, nullptr);
2605 // Persist position, but not immediately, in case this OS is firing
2606 // repeated move events as the user drags the window
2607 PersistentAttributesDirty(PersistentAttribute::Position
, Async
);
2611 bool AppWindow::WindowResized(nsIWidget
* aWidget
, int32_t aWidth
,
2613 mDominantClientSize
= false;
2615 mDocShell
->SetPositionAndSize(0, 0, aWidth
, aHeight
, 0);
2617 // Persist size, but not immediately, in case this OS is firing
2618 // repeated size events as the user drags the sizing handle
2620 PersistentAttributesDirty(AllPersistentAttributes(), Async
);
2622 // Check if we need to continue a fullscreen change.
2623 switch (mFullscreenChangeState
) {
2624 case FullscreenChangeState::WillChange
:
2625 mFullscreenChangeState
= FullscreenChangeState::WidgetResized
;
2627 case FullscreenChangeState::WidgetEnteredFullscreen
:
2628 FinishFullscreenChange(true);
2630 case FullscreenChangeState::WidgetExitedFullscreen
:
2631 FinishFullscreenChange(false);
2633 case FullscreenChangeState::WidgetResized
:
2634 case FullscreenChangeState::NotChanging
:
2640 bool AppWindow::RequestWindowClose(nsIWidget
* aWidget
) {
2641 // Maintain a reference to this as it is about to get destroyed.
2642 nsCOMPtr
<nsIAppWindow
> appWindow(this);
2644 nsCOMPtr
<nsPIDOMWindowOuter
> window(mDocShell
? mDocShell
->GetWindow()
2646 nsCOMPtr
<EventTarget
> eventTarget
= do_QueryInterface(window
);
2648 RefPtr
<PresShell
> presShell
= mDocShell
->GetPresShell();
2650 mozilla::DebugOnly
<bool> dying
;
2651 MOZ_ASSERT(NS_SUCCEEDED(mDocShell
->IsBeingDestroyed(&dying
)) && dying
,
2652 "No presShell, but window is not being destroyed");
2653 } else if (eventTarget
) {
2654 RefPtr
<nsPresContext
> presContext
= presShell
->GetPresContext();
2656 nsEventStatus status
= nsEventStatus_eIgnore
;
2657 WidgetMouseEvent
event(true, eClose
, nullptr, WidgetMouseEvent::eReal
);
2658 if (NS_SUCCEEDED(EventDispatcher::Dispatch(eventTarget
, presContext
, &event
,
2659 nullptr, &status
)) &&
2660 status
== nsEventStatus_eConsumeNoDefault
)
2668 void AppWindow::SizeModeChanged(nsSizeMode aSizeMode
) {
2669 const bool wasWidgetInFullscreen
= mIsWidgetInFullscreen
;
2670 // Fullscreen and minimized states are usually compatible, and the widget
2671 // typically returns to fullscreen after restoration. By not updating the
2672 // widget's fullscreen state while it is minimized, we can avoid unnecessary
2673 // fullscreen exits, such as those encountered in bug 1823284.
2674 if (aSizeMode
!= nsSizeMode_Minimized
) {
2675 mIsWidgetInFullscreen
= aSizeMode
== nsSizeMode_Fullscreen
;
2678 const bool fullscreenChanged
= wasWidgetInFullscreen
!= mIsWidgetInFullscreen
;
2679 if (fullscreenChanged
) {
2680 FullscreenWillChange(mIsWidgetInFullscreen
);
2683 RecomputeBrowsingContextVisibility();
2685 PersistentAttributesDirty(PersistentAttribute::Misc
, Sync
);
2686 nsCOMPtr
<nsPIDOMWindowOuter
> ourWindow
=
2687 mDocShell
? mDocShell
->GetWindow() : nullptr;
2689 // Always fire a user-defined sizemodechange event on the window
2690 ourWindow
->DispatchCustomEvent(u
"sizemodechange"_ns
);
2693 if (PresShell
* presShell
= GetPresShell()) {
2694 presShell
->GetPresContext()->SizeModeChanged(aSizeMode
);
2697 if (fullscreenChanged
) {
2698 FullscreenChanged(mIsWidgetInFullscreen
);
2701 // Note the current implementation of SetSizeMode just stores
2702 // the new state; it doesn't actually resize. So here we store
2703 // the state and pass the event on to the OS. The day is coming
2704 // when we'll handle the event here, and the return result will
2705 // then need to be different.
2708 void AppWindow::FullscreenWillChange(bool aInFullscreen
) {
2710 if (nsCOMPtr
<nsPIDOMWindowOuter
> ourWindow
= mDocShell
->GetWindow()) {
2711 ourWindow
->FullscreenWillChange(aInFullscreen
);
2714 MOZ_ASSERT(mFullscreenChangeState
== FullscreenChangeState::NotChanging
);
2716 CSSToLayoutDeviceScale scale
= UnscaledDevicePixelsPerCSSPixel();
2717 CSSIntSize windowSizeCSS
= RoundedToInt(GetSize() / scale
);
2719 CSSIntSize screenSizeCSS
;
2720 GetAvailScreenSize(&screenSizeCSS
.width
, &screenSizeCSS
.height
);
2722 // Check if the window is already at the expected dimensions. If it is, set
2723 // the fullscreen change state to WidgetResized to avoid waiting for a resize
2724 // event. On macOS, a fullscreen window could be slightly higher than
2725 // available screen size because of the OS menu bar isn't yet hidden.
2726 mFullscreenChangeState
=
2727 (aInFullscreen
== (windowSizeCSS
.width
== screenSizeCSS
.width
&&
2728 windowSizeCSS
.height
>= screenSizeCSS
.height
))
2729 ? FullscreenChangeState::WidgetResized
2730 : FullscreenChangeState::WillChange
;
2733 void AppWindow::FullscreenChanged(bool aInFullscreen
) {
2734 if (mFullscreenChangeState
== FullscreenChangeState::WidgetResized
) {
2735 FinishFullscreenChange(aInFullscreen
);
2737 NS_WARNING_ASSERTION(
2738 mFullscreenChangeState
== FullscreenChangeState::WillChange
,
2739 "Unexpected fullscreen change state");
2740 FullscreenChangeState newState
=
2741 aInFullscreen
? FullscreenChangeState::WidgetEnteredFullscreen
2742 : FullscreenChangeState::WidgetExitedFullscreen
;
2743 mFullscreenChangeState
= newState
;
2744 nsCOMPtr
<nsIAppWindow
> kungFuDeathGrip(this);
2745 // Wait for resize for a small amount of time.
2746 // 80ms is actually picked arbitrarily. But it shouldn't be too large
2747 // in case the widget resize is not going to happen at all, which can
2748 // be the case for some Linux window managers and possibly Android.
2749 NS_DelayedDispatchToCurrentThread(
2750 NS_NewRunnableFunction(
2751 "AppWindow::FullscreenChanged",
2752 [this, kungFuDeathGrip
, newState
, aInFullscreen
]() {
2753 if (mFullscreenChangeState
== newState
) {
2754 FinishFullscreenChange(aInFullscreen
);
2761 void AppWindow::FinishFullscreenChange(bool aInFullscreen
) {
2762 mFullscreenChangeState
= FullscreenChangeState::NotChanging
;
2763 if (nsXULPopupManager
* pm
= nsXULPopupManager::GetInstance()) {
2767 if (nsCOMPtr
<nsPIDOMWindowOuter
> ourWindow
= mDocShell
->GetWindow()) {
2768 ourWindow
->FinishFullscreenChange(aInFullscreen
);
2773 void AppWindow::MacFullscreenMenubarOverlapChanged(
2774 mozilla::DesktopCoord aOverlapAmount
) {
2776 if (nsCOMPtr
<nsPIDOMWindowOuter
> ourWindow
= mDocShell
->GetWindow()) {
2777 ourWindow
->MacFullscreenMenubarOverlapChanged(aOverlapAmount
);
2782 void AppWindow::RecomputeBrowsingContextVisibility() {
2786 RefPtr bc
= mDocShell
->GetBrowsingContext();
2790 bc
->Canonical()->RecomputeAppWindowVisibility();
2793 void AppWindow::OcclusionStateChanged(bool aIsFullyOccluded
) {
2797 RecomputeBrowsingContextVisibility();
2798 if (RefPtr win
= mDocShell
->GetWindow()) {
2799 // And always fire a user-defined occlusionstatechange event on the window
2800 win
->DispatchCustomEvent(u
"occlusionstatechange"_ns
,
2801 ChromeOnlyDispatch::eYes
);
2805 void AppWindow::OSToolbarButtonPressed() {
2806 // Keep a reference as setting the chrome flags can fire events.
2807 nsCOMPtr
<nsIAppWindow
> appWindow(this);
2809 // rjc: don't use "nsIWebBrowserChrome::CHROME_EXTRA"
2810 // due to components with multiple sidebar components
2811 // (such as Mail/News, Addressbook, etc)... and frankly,
2812 // Mac IE, OmniWeb, and other Mac OS X apps all work this way
2813 uint32_t chromeMask
= (nsIWebBrowserChrome::CHROME_TOOLBAR
|
2814 nsIWebBrowserChrome::CHROME_LOCATIONBAR
|
2815 nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR
);
2817 nsCOMPtr
<nsIWebBrowserChrome
> wbc(do_GetInterface(appWindow
));
2820 uint32_t chromeFlags
, newChromeFlags
= 0;
2821 wbc
->GetChromeFlags(&chromeFlags
);
2822 newChromeFlags
= chromeFlags
& chromeMask
;
2823 if (!newChromeFlags
)
2824 chromeFlags
|= chromeMask
;
2826 chromeFlags
&= (~newChromeFlags
);
2827 wbc
->SetChromeFlags(chromeFlags
);
2830 void AppWindow::WindowActivated() {
2831 nsCOMPtr
<nsIAppWindow
> appWindow(this);
2833 // focusing the window could cause it to close, so keep a reference to it
2835 if (nsCOMPtr
<nsPIDOMWindowOuter
> window
= mDocShell
->GetWindow()) {
2836 if (RefPtr
<nsFocusManager
> fm
= nsFocusManager::GetFocusManager()) {
2837 fm
->WindowRaised(window
, nsFocusManager::GenerateFocusActionId());
2842 if (mChromeLoaded
) {
2843 PersistentAttributesDirty(AllPersistentAttributes(), Sync
);
2847 void AppWindow::WindowDeactivated() {
2849 if (nsCOMPtr
<nsPIDOMWindowOuter
> window
= mDocShell
->GetWindow()) {
2850 if (RefPtr
<nsFocusManager
> fm
= nsFocusManager::GetFocusManager()) {
2851 if (!fm
->IsTestMode()) {
2852 fm
->WindowLowered(window
, nsFocusManager::GenerateFocusActionId());
2859 #ifdef USE_NATIVE_MENUS
2861 struct LoadNativeMenusListener
{
2862 LoadNativeMenusListener(Document
* aDoc
, nsIWidget
* aParentWindow
)
2863 : mDocument(aDoc
), mParentWindow(aParentWindow
) {}
2865 RefPtr
<Document
> mDocument
;
2866 nsCOMPtr
<nsIWidget
> mParentWindow
;
2869 // On macOS the hidden window is created eagerly, and we want to wait for it to
2870 // load the native menus.
2871 static bool sWaitingForHiddenWindowToLoadNativeMenus
=
2879 static nsTArray
<LoadNativeMenusListener
> sLoadNativeMenusListeners
;
2881 static void BeginLoadNativeMenus(Document
* aDoc
, nsIWidget
* aParentWindow
);
2883 static void LoadNativeMenus(Document
* aDoc
, nsIWidget
* aParentWindow
) {
2884 MOZ_ASSERT(!gfxPlatform::IsHeadless());
2886 // Find the menubar tag (if there is more than one, we ignore all but
2888 nsCOMPtr
<nsINodeList
> menubarElements
= aDoc
->GetElementsByTagNameNS(
2889 u
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"_ns
,
2892 RefPtr
<Element
> menubar
;
2893 if (menubarElements
) {
2894 menubar
= Element::FromNodeOrNull(menubarElements
->Item(0));
2897 widget::NativeMenuSupport::CreateNativeMenuBar(aParentWindow
, menubar
);
2899 if (sWaitingForHiddenWindowToLoadNativeMenus
) {
2900 sWaitingForHiddenWindowToLoadNativeMenus
= false;
2901 for (auto& listener
: sLoadNativeMenusListeners
) {
2902 BeginLoadNativeMenus(listener
.mDocument
, listener
.mParentWindow
);
2904 sLoadNativeMenusListeners
.Clear();
2908 class L10nReadyPromiseHandler final
: public dom::PromiseNativeHandler
{
2912 L10nReadyPromiseHandler(Document
* aDoc
, nsIWidget
* aParentWindow
)
2913 : mDocument(aDoc
), mWindow(aParentWindow
) {}
2915 void ResolvedCallback(JSContext
* aCx
, JS::Handle
<JS::Value
> aValue
,
2916 ErrorResult
& aRv
) override
{
2917 LoadNativeMenus(mDocument
, mWindow
);
2920 void RejectedCallback(JSContext
* aCx
, JS::Handle
<JS::Value
> aValue
,
2921 ErrorResult
& aRv
) override
{
2922 // Again, this shouldn't happen, but fallback to loading the menus as is.
2924 "L10nReadyPromiseHandler rejected - loading fallback native "
2926 LoadNativeMenus(mDocument
, mWindow
);
2930 ~L10nReadyPromiseHandler() = default;
2932 RefPtr
<Document
> mDocument
;
2933 nsCOMPtr
<nsIWidget
> mWindow
;
2936 NS_IMPL_ISUPPORTS0(L10nReadyPromiseHandler
)
2938 static void BeginLoadNativeMenus(Document
* aDoc
, nsIWidget
* aParentWindow
) {
2939 if (RefPtr
<DocumentL10n
> l10n
= aDoc
->GetL10n()) {
2940 // Wait for l10n to be ready so the menus are localized.
2941 RefPtr
<Promise
> promise
= l10n
->Ready();
2942 MOZ_ASSERT(promise
);
2943 RefPtr handler
= new L10nReadyPromiseHandler(aDoc
, aParentWindow
);
2944 promise
->AppendNativeHandler(handler
);
2946 // Something went wrong loading the doc and l10n wasn't created. This
2947 // shouldn't really happen, but if it does fallback to trying to load
2949 LoadNativeMenus(aDoc
, aParentWindow
);
2955 class AppWindowTimerCallback final
: public nsITimerCallback
, public nsINamed
{
2957 explicit AppWindowTimerCallback(AppWindow
* aWindow
) : mWindow(aWindow
) {}
2959 NS_DECL_THREADSAFE_ISUPPORTS
2961 NS_IMETHOD
Notify(nsITimer
* aTimer
) override
{
2962 // Although this object participates in a refcount cycle (this -> mWindow
2963 // -> mSPTimer -> this), mSPTimer is a one-shot timer and releases this
2964 // after it fires. So we don't need to release mWindow here.
2966 mWindow
->FirePersistenceTimer();
2970 NS_IMETHOD
GetName(nsACString
& aName
) override
{
2971 aName
.AssignLiteral("AppWindowTimerCallback");
2976 ~AppWindowTimerCallback() {}
2978 RefPtr
<AppWindow
> mWindow
;
2981 NS_IMPL_ISUPPORTS(AppWindowTimerCallback
, nsITimerCallback
, nsINamed
)
2983 void AppWindow::PersistentAttributesDirty(PersistentAttributes aAttributes
,
2984 PersistentAttributeUpdate aUpdate
) {
2985 aAttributes
= aAttributes
& mPersistentAttributesMask
;
2986 if (aAttributes
.isEmpty()) {
2990 mPersistentAttributesDirty
+= aAttributes
;
2991 if (aUpdate
== Sync
) {
2992 // Only apply the attributes we've been requested to apply sync, not other
2993 // potentially dirty attributes that have been requested asynchronously.
2994 SavePersistentAttributes(aAttributes
);
2998 mSPTimer
= NS_NewTimer();
3000 NS_WARNING("Couldn't create timer instance?");
3005 RefPtr
<AppWindowTimerCallback
> callback
= new AppWindowTimerCallback(this);
3006 mSPTimer
->InitWithCallback(callback
, SIZE_PERSISTENCE_TIMEOUT
,
3007 nsITimer::TYPE_ONE_SHOT
);
3010 void AppWindow::FirePersistenceTimer() { SavePersistentAttributes(); }
3012 //----------------------------------------
3013 // nsIWebProgessListener implementation
3014 //----------------------------------------
3016 AppWindow::OnProgressChange(nsIWebProgress
* aProgress
, nsIRequest
* aRequest
,
3017 int32_t aCurSelfProgress
, int32_t aMaxSelfProgress
,
3018 int32_t aCurTotalProgress
,
3019 int32_t aMaxTotalProgress
) {
3020 MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)");
3025 AppWindow::OnStateChange(nsIWebProgress
* aProgress
, nsIRequest
* aRequest
,
3026 uint32_t aStateFlags
, nsresult aStatus
) {
3027 // If the notification is not about a document finishing, then just
3029 if (!(aStateFlags
& nsIWebProgressListener::STATE_STOP
) ||
3030 !(aStateFlags
& nsIWebProgressListener::STATE_IS_NETWORK
)) {
3034 if (mChromeLoaded
) return NS_OK
;
3036 // If this document notification is for a frame then ignore it...
3037 nsCOMPtr
<mozIDOMWindowProxy
> eventWin
;
3038 aProgress
->GetDOMWindow(getter_AddRefs(eventWin
));
3039 auto* eventPWin
= nsPIDOMWindowOuter::From(eventWin
);
3041 nsPIDOMWindowOuter
* rootPWin
= eventPWin
->GetPrivateRoot();
3042 if (eventPWin
!= rootPWin
) return NS_OK
;
3045 mChromeLoaded
= true;
3046 mLockedUntilChromeLoad
= false;
3048 #ifdef USE_NATIVE_MENUS
3049 ///////////////////////////////
3050 // Find the Menubar DOM and Load the menus, hooking them up to the loaded
3052 ///////////////////////////////
3053 if (!gfxPlatform::IsHeadless()) {
3054 if (RefPtr
<Document
> menubarDoc
= mDocShell
->GetExtantDocument()) {
3055 if (mIsHiddenWindow
|| !sWaitingForHiddenWindowToLoadNativeMenus
) {
3056 BeginLoadNativeMenus(menubarDoc
, mWindow
);
3058 sLoadNativeMenusListeners
.EmplaceBack(menubarDoc
, mWindow
);
3062 #endif // USE_NATIVE_MENUS
3070 AppWindow::OnLocationChange(nsIWebProgress
* aProgress
, nsIRequest
* aRequest
,
3071 nsIURI
* aURI
, uint32_t aFlags
) {
3072 MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)");
3077 AppWindow::OnStatusChange(nsIWebProgress
* aWebProgress
, nsIRequest
* aRequest
,
3078 nsresult aStatus
, const char16_t
* aMessage
) {
3079 MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)");
3084 AppWindow::OnSecurityChange(nsIWebProgress
* aWebProgress
, nsIRequest
* aRequest
,
3086 MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)");
3091 AppWindow::OnContentBlockingEvent(nsIWebProgress
* aWebProgress
,
3092 nsIRequest
* aRequest
, uint32_t aEvent
) {
3093 MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)");
3098 * ExecuteCloseHandler - Run the close handler, if any.
3099 * @return true iff we found a close handler to run.
3101 bool AppWindow::ExecuteCloseHandler() {
3102 /* If the event handler closes this window -- a likely scenario --
3103 things get deleted out of order without this death grip.
3104 (The problem may be the death grip in nsWindow::windowProc,
3105 which forces this window's widget to remain alive longer
3106 than it otherwise would.) */
3107 nsCOMPtr
<nsIAppWindow
> kungFuDeathGrip(this);
3109 nsCOMPtr
<EventTarget
> eventTarget
;
3111 eventTarget
= do_QueryInterface(mDocShell
->GetWindow());
3115 nsCOMPtr
<nsIDocumentViewer
> viewer
;
3116 mDocShell
->GetDocViewer(getter_AddRefs(viewer
));
3118 RefPtr
<nsPresContext
> presContext
= viewer
->GetPresContext();
3120 nsEventStatus status
= nsEventStatus_eIgnore
;
3121 WidgetMouseEvent
event(true, eClose
, nullptr, WidgetMouseEvent::eReal
);
3123 nsresult rv
= EventDispatcher::Dispatch(eventTarget
, presContext
, &event
,
3125 if (NS_SUCCEEDED(rv
) && status
== nsEventStatus_eConsumeNoDefault
)
3127 // else fall through and return false
3132 } // ExecuteCloseHandler
3134 void AppWindow::ConstrainToOpenerScreen(int32_t* aX
, int32_t* aY
) {
3135 if (mOpenerScreenRect
.IsEmpty()) {
3140 int32_t left
, top
, width
, height
;
3141 // Constrain initial positions to the same screen as opener
3142 nsCOMPtr
<nsIScreenManager
> screenmgr
=
3143 do_GetService("@mozilla.org/gfx/screenmanager;1");
3145 nsCOMPtr
<nsIScreen
> screen
= screenmgr
->ScreenForRect(mOpenerScreenRect
);
3147 screen
->GetAvailRectDisplayPix(&left
, &top
, &width
, &height
);
3148 if (*aX
< left
|| *aX
> left
+ width
) {
3151 if (*aY
< top
|| *aY
> top
+ height
) {
3158 nsIAppWindow
* AppWindow::WidgetListenerDelegate::GetAppWindow() {
3159 return mAppWindow
->GetAppWindow();
3162 PresShell
* AppWindow::WidgetListenerDelegate::GetPresShell() {
3163 return mAppWindow
->GetPresShell();
3166 bool AppWindow::WidgetListenerDelegate::WindowMoved(nsIWidget
* aWidget
,
3167 int32_t aX
, int32_t aY
,
3169 RefPtr
<AppWindow
> holder
= mAppWindow
;
3170 return holder
->WindowMoved(aWidget
, aX
, aY
);
3173 bool AppWindow::WidgetListenerDelegate::WindowResized(nsIWidget
* aWidget
,
3176 RefPtr
<AppWindow
> holder
= mAppWindow
;
3177 return holder
->WindowResized(aWidget
, aWidth
, aHeight
);
3180 bool AppWindow::WidgetListenerDelegate::RequestWindowClose(nsIWidget
* aWidget
) {
3181 RefPtr
<AppWindow
> holder
= mAppWindow
;
3182 return holder
->RequestWindowClose(aWidget
);
3185 void AppWindow::WidgetListenerDelegate::SizeModeChanged(nsSizeMode aSizeMode
) {
3186 RefPtr
<AppWindow
> holder
= mAppWindow
;
3187 holder
->SizeModeChanged(aSizeMode
);
3190 void AppWindow::WidgetListenerDelegate::MacFullscreenMenubarOverlapChanged(
3191 DesktopCoord aOverlapAmount
) {
3192 RefPtr
<AppWindow
> holder
= mAppWindow
;
3193 return holder
->MacFullscreenMenubarOverlapChanged(aOverlapAmount
);
3196 void AppWindow::WidgetListenerDelegate::OcclusionStateChanged(
3197 bool aIsFullyOccluded
) {
3198 RefPtr
<AppWindow
> holder
= mAppWindow
;
3199 holder
->OcclusionStateChanged(aIsFullyOccluded
);
3202 void AppWindow::WidgetListenerDelegate::OSToolbarButtonPressed() {
3203 RefPtr
<AppWindow
> holder
= mAppWindow
;
3204 holder
->OSToolbarButtonPressed();
3207 void AppWindow::WidgetListenerDelegate::WindowActivated() {
3208 RefPtr
<AppWindow
> holder
= mAppWindow
;
3209 holder
->WindowActivated();
3212 void AppWindow::WidgetListenerDelegate::WindowDeactivated() {
3213 RefPtr
<AppWindow
> holder
= mAppWindow
;
3214 holder
->WindowDeactivated();
3217 } // namespace mozilla