diff options
Diffstat (limited to '')
-rw-r--r-- | xpfe/appshell/AppWindow.h | 398 |
1 files changed, 398 insertions, 0 deletions
diff --git a/xpfe/appshell/AppWindow.h b/xpfe/appshell/AppWindow.h new file mode 100644 index 0000000000..4acee5dbfe --- /dev/null +++ b/xpfe/appshell/AppWindow.h @@ -0,0 +1,398 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_AppWindow_h__ +#define mozilla_AppWindow_h__ + +// Local Includes +#include "nsChromeTreeOwner.h" +#include "nsContentTreeOwner.h" + +// Helper classes +#include "nsCOMPtr.h" +#include "nsTArray.h" +#include "nsString.h" +#include "nsWeakReference.h" +#include "nsCOMArray.h" +#include "nsDocShell.h" +#include "nsRect.h" +#include "Units.h" +#include "mozilla/Maybe.h" +#include "mozilla/Mutex.h" + +// Interfaces needed +#include "nsIBaseWindow.h" +#include "nsIDocShellTreeItem.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIAppWindow.h" +#include "nsIPrompt.h" +#include "nsIAuthPrompt.h" +#include "nsIXULBrowserWindow.h" +#include "nsIWidgetListener.h" +#include "nsIRemoteTab.h" +#include "nsIWebProgressListener.h" +#include "nsITimer.h" +#include "nsIXULStore.h" + +class nsAtom; +class nsXULTooltipListener; + +namespace mozilla { +class PresShell; +class AppWindowTimerCallback; +class L10nReadyPromiseHandler; +namespace dom { +class Element; +} // namespace dom +namespace widget { +struct InitData; +} // namespace widget +} // namespace mozilla + +// AppWindow + +#define NS_APPWINDOW_IMPL_CID \ + { /* 8eaec2f3-ed02-4be2-8e0f-342798477298 */ \ + 0x8eaec2f3, 0xed02, 0x4be2, { \ + 0x8e, 0x0f, 0x34, 0x27, 0x98, 0x47, 0x72, 0x98 \ + } \ + } + +class nsContentShellInfo; + +namespace mozilla { + +class AppWindow final : public nsIBaseWindow, + public nsIInterfaceRequestor, + public nsIAppWindow, + public nsSupportsWeakReference, + public nsIWebProgressListener { + friend class ::nsChromeTreeOwner; + friend class ::nsContentTreeOwner; + + public: + // The implementation of non-refcounted nsIWidgetListener, which would hold a + // strong reference on stack before calling AppWindow's + // MOZ_CAN_RUN_SCRIPT methods. + class WidgetListenerDelegate : public nsIWidgetListener { + public: + explicit WidgetListenerDelegate(AppWindow* aAppWindow) + : mAppWindow(aAppWindow) {} + + MOZ_CAN_RUN_SCRIPT_BOUNDARY + virtual nsIAppWindow* GetAppWindow() override; + MOZ_CAN_RUN_SCRIPT_BOUNDARY + virtual mozilla::PresShell* GetPresShell() override; + MOZ_CAN_RUN_SCRIPT_BOUNDARY + virtual bool WindowMoved(nsIWidget* aWidget, int32_t x, int32_t y, + ByMoveToRect) override; + MOZ_CAN_RUN_SCRIPT_BOUNDARY + virtual bool WindowResized(nsIWidget* aWidget, int32_t aWidth, + int32_t aHeight) override; + MOZ_CAN_RUN_SCRIPT_BOUNDARY + virtual bool RequestWindowClose(nsIWidget* aWidget) override; + MOZ_CAN_RUN_SCRIPT_BOUNDARY + virtual void SizeModeChanged(nsSizeMode sizeMode) override; + MOZ_CAN_RUN_SCRIPT_BOUNDARY + virtual void UIResolutionChanged() override; + MOZ_CAN_RUN_SCRIPT_BOUNDARY + virtual void MacFullscreenMenubarOverlapChanged( + mozilla::DesktopCoord aOverlapAmount) override; + MOZ_CAN_RUN_SCRIPT_BOUNDARY + virtual void OcclusionStateChanged(bool aIsFullyOccluded) override; + MOZ_CAN_RUN_SCRIPT_BOUNDARY + virtual void OSToolbarButtonPressed() override; + MOZ_CAN_RUN_SCRIPT_BOUNDARY + virtual bool ZLevelChanged(bool aImmediate, nsWindowZ* aPlacement, + nsIWidget* aRequestBelow, + nsIWidget** aActualBelow) override; + MOZ_CAN_RUN_SCRIPT_BOUNDARY + virtual void WindowActivated() override; + MOZ_CAN_RUN_SCRIPT_BOUNDARY + virtual void WindowDeactivated() override; + + private: + // The lifetime of WidgetListenerDelegate is bound to AppWindow so + // we just use a raw pointer here. + AppWindow* mAppWindow; + }; + + NS_DECL_THREADSAFE_ISUPPORTS + + NS_DECL_NSIINTERFACEREQUESTOR + NS_DECL_NSIAPPWINDOW + NS_DECL_NSIBASEWINDOW + + NS_DECLARE_STATIC_IID_ACCESSOR(NS_APPWINDOW_IMPL_CID) + + void LockUntilChromeLoad() { mLockedUntilChromeLoad = true; } + bool IsLocked() const { return mLockedUntilChromeLoad; } + void IgnoreXULSizeMode(bool aEnable) { mIgnoreXULSizeMode = aEnable; } + void WasRegistered() { mRegistered = true; } + + using nsIBaseWindow::GetPositionAndSize; + using nsIBaseWindow::GetSize; + + // AppWindow methods... + nsresult Initialize(nsIAppWindow* aParent, nsIAppWindow* aOpener, + int32_t aInitialWidth, int32_t aInitialHeight, + bool aIsHiddenWindow, widget::InitData& widgetInitData); + + nsDocShell* GetDocShell() { return mDocShell; } + + nsresult Toolbar(); + + // nsIWebProgressListener + NS_DECL_NSIWEBPROGRESSLISTENER + + // nsIWidgetListener methods for WidgetListenerDelegate. + nsIAppWindow* GetAppWindow() { return this; } + mozilla::PresShell* GetPresShell(); + MOZ_CAN_RUN_SCRIPT + bool WindowMoved(nsIWidget* aWidget, int32_t aX, int32_t aY); + MOZ_CAN_RUN_SCRIPT + bool WindowResized(nsIWidget* aWidget, int32_t aWidth, int32_t aHeight); + MOZ_CAN_RUN_SCRIPT bool RequestWindowClose(nsIWidget* aWidget); + MOZ_CAN_RUN_SCRIPT void SizeModeChanged(nsSizeMode aSizeMode); + MOZ_CAN_RUN_SCRIPT void UIResolutionChanged(); + MOZ_CAN_RUN_SCRIPT void FullscreenWillChange(bool aInFullscreen); + MOZ_CAN_RUN_SCRIPT void FullscreenChanged(bool aInFullscreen); + MOZ_CAN_RUN_SCRIPT void MacFullscreenMenubarOverlapChanged( + mozilla::DesktopCoord aOverlapAmount); + MOZ_CAN_RUN_SCRIPT void OcclusionStateChanged(bool aIsFullyOccluded); + void RecomputeBrowsingContextVisibility(); + MOZ_CAN_RUN_SCRIPT void OSToolbarButtonPressed(); + MOZ_CAN_RUN_SCRIPT + bool ZLevelChanged(bool aImmediate, nsWindowZ* aPlacement, + nsIWidget* aRequestBelow, nsIWidget** aActualBelow); + MOZ_CAN_RUN_SCRIPT void WindowActivated(); + MOZ_CAN_RUN_SCRIPT void WindowDeactivated(); + + explicit AppWindow(uint32_t aChromeFlags); + + protected: + enum class PersistentAttribute : uint8_t { + Position, + Size, + Misc, + }; + using PersistentAttributes = EnumSet<PersistentAttribute>; + + static PersistentAttributes AllPersistentAttributes() { + return {PersistentAttribute::Position, PersistentAttribute::Size, + PersistentAttribute::Misc}; + } + + virtual ~AppWindow(); + + friend class mozilla::AppWindowTimerCallback; + + MOZ_CAN_RUN_SCRIPT bool ExecuteCloseHandler(); + void ConstrainToOpenerScreen(int32_t* aX, int32_t* aY); + + void SetPersistenceTimer(uint32_t aDirtyFlags); + void FirePersistenceTimer(); + + NS_IMETHOD EnsureChromeTreeOwner(); + NS_IMETHOD EnsureContentTreeOwner(); + NS_IMETHOD EnsurePrimaryContentTreeOwner(); + NS_IMETHOD EnsurePrompter(); + NS_IMETHOD EnsureAuthPrompter(); + NS_IMETHOD ForceRoundedDimensions(); + NS_IMETHOD GetAvailScreenSize(int32_t* aAvailWidth, int32_t* aAvailHeight); + + void FinishFullscreenChange(bool aInFullscreen); + + void ApplyChromeFlags(); + MOZ_CAN_RUN_SCRIPT_BOUNDARY void SizeShell(); + void OnChromeLoaded(); + void StaggerPosition(int32_t& aRequestedX, int32_t& aRequestedY, + int32_t aSpecWidth, int32_t aSpecHeight); + bool LoadPositionFromXUL(int32_t aSpecWidth, int32_t aSpecHeight); + bool LoadSizeFromXUL(int32_t& aSpecWidth, int32_t& aSpecHeight); + void SetSpecifiedSize(int32_t aSpecWidth, int32_t aSpecHeight); + bool UpdateWindowStateFromMiscXULAttributes(); + void SyncAttributesToWidget(); + void SavePersistentAttributes(PersistentAttributes); + void MaybeSavePersistentPositionAndSize(PersistentAttributes, + dom::Element& aRootElement, + const nsAString& aPersistString, + bool aShouldPersist); + void MaybeSavePersistentMiscAttributes(PersistentAttributes, + dom::Element& aRootElement, + const nsAString& aPersistString, + bool aShouldPersist); + void SavePersistentAttributes() { + SavePersistentAttributes(mPersistentAttributesDirty); + } + + bool NeedsTooltipListener(); + void AddTooltipSupport(); + void RemoveTooltipSupport(); + + NS_IMETHOD GetWindowDOMWindow(mozIDOMWindowProxy** aDOMWindow); + dom::Element* GetWindowDOMElement() const; + + // See nsIDocShellTreeOwner for docs on next two methods + nsresult ContentShellAdded(nsIDocShellTreeItem* aContentShell, bool aPrimary); + nsresult ContentShellRemoved(nsIDocShellTreeItem* aContentShell); + NS_IMETHOD GetPrimaryContentSize(int32_t* aWidth, int32_t* aHeight); + NS_IMETHOD SetPrimaryContentSize(int32_t aWidth, int32_t aHeight); + nsresult GetRootShellSize(int32_t* aWidth, int32_t* aHeight); + nsresult SetRootShellSize(int32_t aWidth, int32_t aHeight); + + NS_IMETHOD SizeShellTo(nsIDocShellTreeItem* aShellItem, int32_t aCX, + int32_t aCY); + NS_IMETHOD ExitModalLoop(nsresult aStatus); + NS_IMETHOD CreateNewChromeWindow(int32_t aChromeFlags, + nsIAppWindow** _retval); + NS_IMETHOD CreateNewContentWindow(int32_t aChromeFlags, + nsIOpenWindowInfo* aOpenWindowInfo, + nsIAppWindow** _retval); + NS_IMETHOD GetHasPrimaryContent(bool* aResult); + + void EnableParent(bool aEnable); + bool ConstrainToZLevel(bool aImmediate, nsWindowZ* aPlacement, + nsIWidget* aReqBelow, nsIWidget** aActualBelow); + void PlaceWindowLayersBehind(uint32_t aLowLevel, uint32_t aHighLevel, + nsIAppWindow* aBehind); + void SetContentScrollbarVisibility(bool aVisible); + + enum PersistentAttributeUpdate { Sync, Async }; + void PersistentAttributesDirty(PersistentAttributes, + PersistentAttributeUpdate); + nsresult GetTabCount(uint32_t* aResult); + + void LoadPersistentWindowState(); + nsresult GetPersistentValue(const nsAtom* aAttr, nsAString& aValue); + nsresult SetPersistentValue(const nsAtom* aAttr, const nsAString& aValue); + + // Saves window size and positioning values in order to display a very early + // skeleton UI. This has to happen before we can reasonably initialize the + // xulstore (i.e., before even loading libxul), so they have to use a special + // purpose store to do so. + nsresult MaybeSaveEarlyWindowPersistentValues( + const LayoutDeviceIntRect& aRect); + + // Gets the uri spec and the window element ID for this window. + nsresult GetDocXulStoreKeys(nsString& aUriSpec, nsString& aWindowElementId); + + // Enum for the current state of a fullscreen change. + // + // It is used to ensure that fullscreen change is issued after both + // the window state change and the window size change at best effort. + // This is needed because some platforms can't guarantee the order + // between such two events. + // + // It's changed in the following way: + // +---------------------------+--------------------------------------+ + // | | | + // | v | + // | NotChanging | + // | + | + // | | FullscreenWillChange | + // | v | + // | +-----------+ WillChange +------------------+ | + // | | WindowResized FullscreenChanged | | + // | v v | + // | WidgetResized WidgetEnteredFullscreen | + // | + or WidgetExitedFullscreen | + // | | FullscreenChanged + | + // | v WindowResized or | | + // +--------+ delayed dispatch | | + // v | + // +-------------+ + // + // The delayed dispatch serves as timeout, which is necessary because it's + // not even guaranteed that the widget will be resized at all. + enum class FullscreenChangeState : uint8_t { + // No current fullscreen change. Any previous change has finished. + NotChanging, + // Indicate there is going to be a fullscreen change. + WillChange, + // The widget has been resized since WillChange. + WidgetResized, + // The widget has entered fullscreen state since WillChange. + WidgetEnteredFullscreen, + // The widget has exited fullscreen state since WillChange. + WidgetExitedFullscreen, + }; + + nsChromeTreeOwner* mChromeTreeOwner; + nsContentTreeOwner* mContentTreeOwner; + nsContentTreeOwner* mPrimaryContentTreeOwner; + nsCOMPtr<nsIWidget> mWindow; + RefPtr<nsDocShell> mDocShell; + nsCOMPtr<nsPIDOMWindowOuter> mDOMWindow; + nsWeakPtr mParentWindow; + nsCOMPtr<nsIPrompt> mPrompter; + nsCOMPtr<nsIAuthPrompt> mAuthPrompter; + nsCOMPtr<nsIXULBrowserWindow> mXULBrowserWindow; + nsCOMPtr<nsIDocShellTreeItem> mPrimaryContentShell; + nsresult mModalStatus; + FullscreenChangeState mFullscreenChangeState; + bool mContinueModalLoop; + bool mDebuting; // being made visible right now + bool mChromeLoaded; // True when chrome has loaded + bool mSizingShellFromXUL; // true when in SizeShell() + bool mShowAfterLoad; + bool mIntrinsicallySized; + bool mCenterAfterLoad; + bool mIsHiddenWindow; + bool mLockedUntilChromeLoad; + bool mIgnoreXULSize; + bool mIgnoreXULPosition; + bool mChromeFlagsFrozen; + bool mIgnoreXULSizeMode; + // mDestroying is used to prevent reentry into into Destroy(), which can + // otherwise happen due to script running as we tear down various things. + bool mDestroying; + bool mRegistered; + // Indicator for whether the client size, instead of the window size, should + // be maintained in case of a change in their relation. + bool mDominantClientSize; + PersistentAttributes mPersistentAttributesDirty; + PersistentAttributes mPersistentAttributesMask; + uint32_t mChromeFlags; + nsCOMPtr<nsIOpenWindowInfo> mInitialOpenWindowInfo; + nsString mTitle; + + // The screen rect of the opener. + mozilla::DesktopIntRect mOpenerScreenRect; + + nsCOMPtr<nsIRemoteTab> mPrimaryBrowserParent; + + nsCOMPtr<nsITimer> mSPTimer; + WidgetListenerDelegate mWidgetListenerDelegate; + + private: + MOZ_CAN_RUN_SCRIPT void IntrinsicallySizeShell(const CSSIntSize& aWindowDiff, + int32_t& aSpecWidth, + int32_t& aSpecHeight); + + // GetPrimaryBrowserParentSize is called from xpidl methods and we don't have + // a good way to annotate those with MOZ_CAN_RUN_SCRIPT yet. It takes no + // refcounted args other than "this", and the "this" uses seem ok. + MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult + GetPrimaryRemoteTabSize(int32_t* aWidth, int32_t* aHeight); + nsresult GetPrimaryContentShellSize(int32_t* aWidth, int32_t* aHeight); + nsresult SetPrimaryRemoteTabSize(int32_t aWidth, int32_t aHeight); + void SizeShellToWithLimit(int32_t aDesiredWidth, int32_t aDesiredHeight, + int32_t shellItemWidth, int32_t shellItemHeight); + nsresult MoveResize(const Maybe<LayoutDeviceIntPoint>& aPosition, + const Maybe<LayoutDeviceIntSize>& aSize, bool aRepaint); + nsresult MoveResize(const Maybe<DesktopPoint>& aPosition, + const Maybe<DesktopSize>& aSize, bool aRepaint); + nsCOMPtr<nsIXULStore> mLocalStore; + bool mIsWidgetInFullscreen = false; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(AppWindow, NS_APPWINDOW_IMPL_CID) + +} // namespace mozilla + +#endif /* mozilla_AppWindow_h__ */ |