summaryrefslogtreecommitdiffstats
path: root/xpfe/appshell/AppWindow.h
blob: 4acee5dbfee32965bf1dbb2a027b14b0ebe47703 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
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__ */