1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef nsCocoaWindow_h_
7 #define nsCocoaWindow_h_
11 #import <Cocoa/Cocoa.h>
13 #include "mozilla/RefPtr.h"
14 #include "nsBaseWidget.h"
15 #include "nsPIWidgetCocoa.h"
16 #include "nsCocoaUtils.h"
17 #include "nsTouchBar.h"
27 enum class NativeKeyBindingsType
: uint8_t;
28 } // namespace mozilla
30 typedef struct _nsCocoaWindowList
{
31 _nsCocoaWindowList() : prev(nullptr), window(nullptr) {}
32 struct _nsCocoaWindowList
* prev
;
33 nsCocoaWindow
* window
; // Weak
36 // NSWindow subclass that is the base class for all of our own window classes.
37 // Among other things, this class handles the storage of those settings that
38 // need to be persisted across window destruction and reconstruction, i.e. when
39 // switching to and from fullscreen mode.
40 // We don't save shadow, transparency mode or background color because it's not
41 // worth the hassle - Gecko will reset them anyway as soon as the window is
43 @interface BaseWindow
: NSWindow
{
45 NSMutableDictionary
* mState
;
46 BOOL mDrawsIntoWindowFrame
;
48 // Invalidation disabling
49 BOOL mDisabledNeedsDisplay
;
51 NSTrackingArea
* mTrackingArea
;
57 BOOL mIsAnimationSuppressed
;
59 nsTouchBar
* mTouchBar
;
62 - (void)importState
:(NSDictionary
*)aState
;
63 - (NSMutableDictionary
*)exportState
;
64 - (void)setDrawsContentsIntoWindowFrame
:(BOOL
)aState
;
65 - (BOOL
)drawsContentsIntoWindowFrame
;
67 // These two methods are like contentRectForFrameRect and
68 // frameRectForContentRect, but they deal with the rect of the window's "main
69 // ChildView" instead of the rect of the window's content view. The two are
70 // sometimes sized differently: The window's content view always covers the
71 // entire window, whereas the ChildView only covers the full window when
72 // drawsContentsIntoWindowFrame is YES. When drawsContentsIntoWindowFrame is NO,
73 // there's a titlebar-sized gap above the ChildView within the content view.
74 - (NSRect
)childViewRectForFrameRect
:(NSRect
)aFrameRect
;
75 - (NSRect
)frameRectForChildViewRect
:(NSRect
)aChildViewRect
;
77 - (void)mouseEntered
:(NSEvent
*)aEvent
;
78 - (void)mouseExited
:(NSEvent
*)aEvent
;
79 - (void)mouseMoved
:(NSEvent
*)aEvent
;
80 - (void)updateTrackingArea
;
81 - (NSView
*)trackingAreaView
;
83 - (void)setBeingShown
:(BOOL
)aValue
;
85 - (BOOL
)isVisibleOrBeingShown
;
87 - (void)setIsAnimationSuppressed
:(BOOL
)aValue
;
88 - (BOOL
)isAnimationSuppressed
;
90 // Returns an autoreleased NSArray containing the NSViews that we consider the
91 // "contents" of this window. All views in the returned array are subviews of
92 // this window's content view. However, the array may not include all of the
93 // content view's subviews; concretely, the ToolbarWindow implementation will
94 // exclude its MOZTitlebarView from the array that is returned here.
95 // In the vast majority of cases, the array will only have a single element:
96 // this window's mainChildView.
97 - (NSArray
<NSView
*>*)contentViewContents
;
99 - (ChildView
*)mainChildView
;
101 - (void)setWantsTitleDrawn
:(BOOL
)aDrawTitle
;
102 - (BOOL
)wantsTitleDrawn
;
104 - (void)disableSetNeedsDisplay
;
105 - (void)enableSetNeedsDisplay
;
107 - (NSRect
)getAndResetNativeDirtyRect
;
109 - (void)setEffectViewWrapperForStyle
:(mozilla::WindowShadow
)aStyle
;
110 @
property(nonatomic
) mozilla::WindowShadow shadowStyle
;
112 - (void)releaseJSObjects
;
116 @interface
NSWindow (Undocumented
)
117 - (NSDictionary
*)shadowParameters
;
119 // Present in the same form on OS X since at least OS X 10.5.
120 - (NSRect
)contentRectForFrameRect
:(NSRect
)windowFrame
121 styleMask
:(NSUInteger
)windowStyle
;
122 - (NSRect
)frameRectForContentRect
:(NSRect
)windowContentRect
123 styleMask
:(NSUInteger
)windowStyle
;
125 // Present since at least OS X 10.5. The OS calls this method on NSWindow
126 // (and its subclasses) to find out which NSFrameView subclass to instantiate
127 // to create its "frame view".
128 + (Class
)frameViewClassForStyleMask
:(NSUInteger
)styleMask
;
132 @interface PopupWindow
: BaseWindow
{
137 - (id
)initWithContentRect
:(NSRect
)contentRect
138 styleMask
:(NSUInteger
)styleMask
139 backing
:(NSBackingStoreType
)bufferingType
140 defer
:(BOOL
)deferCreation
;
141 - (BOOL
)isContextMenu
;
142 - (void)setIsContextMenu
:(BOOL
)flag
;
143 - (BOOL
)canBecomeMainWindow
;
147 @interface BorderlessWindow
: BaseWindow
{
150 - (BOOL
)canBecomeKeyWindow
;
151 - (BOOL
)canBecomeMainWindow
;
155 @interface WindowDelegate
: NSObject
<NSWindowDelegate
> {
156 nsCocoaWindow
* mGeckoWindow
; // [WEAK] (we are owned by the window)
157 // Used to avoid duplication when we send NS_ACTIVATE and
158 // NS_DEACTIVATE to Gecko for toplevel widgets. Starts out
160 bool mToplevelActiveState
;
161 BOOL mHasEverBeenZoomed
;
163 + (void)paintMenubarForWindow
:(NSWindow
*)aWindow
;
164 - (id
)initWithGeckoWindow
:(nsCocoaWindow
*)geckoWind
;
165 - (void)windowDidResize
:(NSNotification
*)aNotification
;
166 - (nsCocoaWindow
*)geckoWidget
;
167 - (bool)toplevelActiveState
;
168 - (void)sendToplevelActivateEvents
;
169 - (void)sendToplevelDeactivateEvents
;
172 @interface MOZTitlebarView
: NSVisualEffectView
175 @interface FullscreenTitlebarTracker
: NSTitlebarAccessoryViewController
176 - (FullscreenTitlebarTracker
*)init
;
179 // NSWindow subclass for handling windows with toolbars.
180 @interface ToolbarWindow
: BaseWindow
{
181 // This window's titlebar view, if present.
182 // Will be nil if the window has neither a titlebar nor a unified toolbar.
183 // This view is a subview of the window's content view and gets created and
184 // destroyed by updateTitlebarView.
185 MOZTitlebarView
* mTitlebarView
; // [STRONG]
186 // mFullscreenTitlebarTracker attaches an invisible rectangle to the system
187 // title bar. This allows us to detect when the title bar is showing in
189 FullscreenTitlebarTracker
* mFullscreenTitlebarTracker
;
191 CGFloat mUnifiedToolbarHeight
;
192 CGFloat mSheetAttachmentPosition
;
193 CGFloat mMenuBarHeight
;
194 /* Store the height of the titlebar when this window is initialized. The
195 titlebarHeight getter returns 0 when in fullscreen, which is not useful in
197 CGFloat mInitialTitlebarHeight
;
198 NSRect mWindowButtonsRect
;
200 - (void)setUnifiedToolbarHeight
:(CGFloat
)aHeight
;
201 - (CGFloat
)unifiedToolbarHeight
;
202 - (CGFloat
)titlebarHeight
;
203 - (NSRect
)titlebarRect
;
204 - (void)setTitlebarNeedsDisplay
;
205 - (void)setDrawsContentsIntoWindowFrame
:(BOOL
)aState
;
206 - (void)setSheetAttachmentPosition
:(CGFloat
)aY
;
207 - (CGFloat
)sheetAttachmentPosition
;
208 - (void)placeWindowButtons
:(NSRect
)aRect
;
209 - (NSRect
)windowButtonsRect
;
210 - (void)windowMainStateChanged
;
213 class nsCocoaWindow final
: public nsBaseWidget
, public nsPIWidgetCocoa
{
215 typedef nsBaseWidget Inherited
;
220 NS_DECL_ISUPPORTS_INHERITED
221 NS_DECL_NSPIWIDGETCOCOA
; // semicolon for clang-format bug 1629756
223 [[nodiscard
]] virtual nsresult
Create(nsIWidget
* aParent
,
224 nsNativeWidget aNativeParent
,
225 const DesktopIntRect
& aRect
,
226 InitData
* = nullptr) override
;
228 [[nodiscard
]] virtual nsresult
Create(nsIWidget
* aParent
,
229 nsNativeWidget aNativeParent
,
230 const LayoutDeviceIntRect
& aRect
,
231 InitData
* = nullptr) override
;
233 virtual void Destroy() override
;
235 virtual void Show(bool aState
) override
;
236 virtual bool NeedsRecreateToReshow() override
;
238 virtual nsIWidget
* GetSheetWindowParent(void) override
;
239 virtual void Enable(bool aState
) override
;
240 virtual bool IsEnabled() const override
;
241 virtual void SetModal(bool aState
) override
;
242 virtual void SetFakeModal(bool aState
) override
;
243 virtual bool IsRunningAppModal() override
;
244 virtual bool IsVisible() const override
;
245 virtual void SetFocus(Raise
, mozilla::dom::CallerType aCallerType
) override
;
246 virtual LayoutDeviceIntPoint
WidgetToScreenOffset() override
;
247 virtual LayoutDeviceIntPoint
GetClientOffset() override
;
248 virtual LayoutDeviceIntMargin
ClientToWindowMargin() override
;
250 virtual void* GetNativeData(uint32_t aDataType
) override
;
252 virtual void ConstrainPosition(DesktopIntPoint
&) override
;
253 virtual void SetSizeConstraints(const SizeConstraints
& aConstraints
) override
;
254 virtual void Move(double aX
, double aY
) override
;
255 virtual nsSizeMode
SizeMode() override
{ return mSizeMode
; }
256 virtual void SetSizeMode(nsSizeMode aMode
) override
;
257 virtual void GetWorkspaceID(nsAString
& workspaceID
) override
;
258 virtual void MoveToWorkspace(const nsAString
& workspaceID
) override
;
259 virtual void SuppressAnimation(bool aSuppress
) override
;
260 virtual void HideWindowChrome(bool aShouldHide
) override
;
262 virtual bool PrepareForFullscreenTransition(nsISupports
** aData
) override
;
263 virtual void PerformFullscreenTransition(FullscreenTransitionStage aStage
,
266 nsIRunnable
* aCallback
) override
;
267 virtual void CleanupFullscreenTransition() override
;
268 nsresult
MakeFullScreen(bool aFullScreen
) final
;
269 nsresult
MakeFullScreenWithNativeTransition(bool aFullScreen
) final
;
270 NSAnimation
* FullscreenTransitionAnimation() const {
271 return mFullscreenTransitionAnimation
;
273 void ReleaseFullscreenTransitionAnimation() {
274 MOZ_ASSERT(mFullscreenTransitionAnimation
,
275 "Should only be called when there is animation");
276 [mFullscreenTransitionAnimation release
];
277 mFullscreenTransitionAnimation
= nil
;
280 virtual void Resize(double aWidth
, double aHeight
, bool aRepaint
) override
;
281 virtual void Resize(double aX
, double aY
, double aWidth
, double aHeight
,
282 bool aRepaint
) override
;
283 NSRect
GetClientCocoaRect();
284 virtual LayoutDeviceIntRect
GetClientBounds() override
;
285 virtual LayoutDeviceIntRect
GetScreenBounds() override
;
286 void ReportMoveEvent();
287 void ReportSizeEvent();
288 virtual void SetCursor(const Cursor
&) override
;
290 CGFloat
BackingScaleFactor();
291 void BackingScaleFactorChanged();
292 virtual double GetDefaultScaleInternal() override
;
293 virtual int32_t RoundsWidgetCoordinatesTo() override
;
295 mozilla::DesktopToLayoutDeviceScale
GetDesktopToDeviceScale() final
{
296 return mozilla::DesktopToLayoutDeviceScale(BackingScaleFactor());
299 virtual nsresult
SetTitle(const nsAString
& aTitle
) override
;
301 virtual void Invalidate(const LayoutDeviceIntRect
& aRect
) override
;
302 virtual WindowRenderer
* GetWindowRenderer() override
;
303 virtual nsresult
DispatchEvent(mozilla::WidgetGUIEvent
* aEvent
,
304 nsEventStatus
& aStatus
) override
;
305 virtual void CaptureRollupEvents(bool aDoCapture
) override
;
306 [[nodiscard
]] virtual nsresult
GetAttention(int32_t aCycleCount
) override
;
307 virtual bool HasPendingInputEvent() override
;
308 virtual TransparencyMode
GetTransparencyMode() override
;
309 virtual void SetTransparencyMode(TransparencyMode aMode
) override
;
310 virtual void SetWindowShadowStyle(mozilla::WindowShadow aStyle
) override
;
311 virtual void SetWindowOpacity(float aOpacity
) override
;
312 virtual void SetWindowTransform(
313 const mozilla::gfx::Matrix
& aTransform
) override
;
314 virtual void SetInputRegion(const InputRegion
&) override
;
315 virtual void SetColorScheme(
316 const mozilla::Maybe
<mozilla::ColorScheme
>&) override
;
317 virtual void SetShowsToolbarButton(bool aShow
) override
;
318 virtual void SetSupportsNativeFullscreen(bool aShow
) override
;
319 virtual void SetWindowAnimationType(WindowAnimationType aType
) override
;
320 virtual void SetDrawsTitle(bool aDrawTitle
) override
;
321 virtual nsresult
SetNonClientMargins(const LayoutDeviceIntMargin
&) override
;
322 void SetDrawsInTitlebar(bool aState
);
323 virtual void UpdateThemeGeometries(
324 const nsTArray
<ThemeGeometry
>& aThemeGeometries
) override
;
325 virtual nsresult
SynthesizeNativeMouseEvent(
326 LayoutDeviceIntPoint aPoint
, NativeMouseMessage aNativeMessage
,
327 mozilla::MouseButton aButton
, nsIWidget::Modifiers aModifierFlags
,
328 nsIObserver
* aObserver
) override
;
329 virtual nsresult
SynthesizeNativeMouseScrollEvent(
330 LayoutDeviceIntPoint aPoint
, uint32_t aNativeMessage
, double aDeltaX
,
331 double aDeltaY
, double aDeltaZ
, uint32_t aModifierFlags
,
332 uint32_t aAdditionalFlags
, nsIObserver
* aObserver
) override
;
333 virtual void LockAspectRatio(bool aShouldLock
) override
;
335 void DispatchSizeModeEvent();
336 void DispatchOcclusionEvent();
338 // be notified that a some form of drag event needs to go into Gecko
339 virtual bool DragEvent(unsigned int aMessage
,
340 mozilla::gfx::Point aMouseGlobal
,
341 UInt16 aKeyModifiers
);
343 bool HasModalDescendents() { return mNumModalDescendents
> 0; }
344 NSWindow
* GetCocoaWindow() { return mWindow
; }
346 void SetMenuBar(RefPtr
<nsMenuBarX
>&& aMenuBar
);
347 nsMenuBarX
* GetMenuBar();
349 virtual void SetInputContext(const InputContext
& aContext
,
350 const InputContextAction
& aAction
) override
;
351 virtual InputContext
GetInputContext() override
{ return mInputContext
; }
352 MOZ_CAN_RUN_SCRIPT
virtual bool GetEditCommands(
353 mozilla::NativeKeyBindingsType aType
,
354 const mozilla::WidgetKeyboardEvent
& aEvent
,
355 nsTArray
<mozilla::CommandInt
>& aCommands
) override
;
357 void SetPopupWindowLevel();
359 bool InFullScreenMode() const { return mInFullScreenMode
; }
361 void PauseOrResumeCompositor(bool aPause
) override
;
363 bool AsyncPanZoomEnabled() const override
;
365 bool StartAsyncAutoscroll(const ScreenPoint
& aAnchorLocation
,
366 const ScrollableLayerGuid
& aGuid
) override
;
367 void StopAsyncAutoscroll(const ScrollableLayerGuid
& aGuid
) override
;
369 // Class method versions of NSWindow/Delegate callbacks which need to
370 // access object state.
371 void CocoaWindowWillEnterFullscreen(bool aFullscreen
);
372 void CocoaWindowDidEnterFullscreen(bool aFullscreen
);
373 void CocoaWindowDidResize();
374 void CocoaSendToplevelActivateEvents();
375 void CocoaSendToplevelDeactivateEvents();
377 enum class TransitionType
{
385 void FinishCurrentTransitionIfMatching(const TransitionType
& aTransition
);
387 // Called when something has happened that might cause us to update our
388 // fullscreen state. Returns true if we updated state. We'll call this
389 // on window resize, and we'll call it when we enter or exit fullscreen,
390 // since fullscreen to-and-from zoomed windows won't necessarily trigger
392 bool HandleUpdateFullscreenOnResize();
395 virtual ~nsCocoaWindow();
397 nsresult
CreateNativeWindow(const NSRect
& aRect
, BorderStyle aBorderStyle
,
398 bool aRectIsFrameRect
, bool aIsPrivateBrowsing
);
399 nsresult
CreatePopupContentView(const LayoutDeviceIntRect
& aRect
, InitData
*);
400 void DestroyNativeWindow();
402 int32_t GetWorkspaceID();
404 void DoResize(double aX
, double aY
, double aWidth
, double aHeight
,
405 bool aRepaint
, bool aConstrainToCurrentScreen
);
407 void UpdateFullscreenState(bool aFullScreen
, bool aNativeMode
);
408 nsresult
DoMakeFullScreen(bool aFullScreen
, bool aUseSystemTransition
);
410 virtual already_AddRefed
<nsIWidget
> AllocateChildPopupWidget() override
{
411 return nsIWidget::CreateTopLevelWindow();
414 nsIWidget
* mParent
; // if we're a popup, this is our parent [WEAK]
415 nsIWidget
* mAncestorLink
; // link to traverse ancestors [WEAK]
416 BaseWindow
* mWindow
; // our cocoa window [STRONG]
418 mDelegate
; // our delegate for processing window msgs [STRONG]
419 RefPtr
<nsMenuBarX
> mMenuBar
;
420 NSWindow
* mSheetWindowParent
; // if this is a sheet, this is the NSWindow
423 mPopupContentView
; // if this is a popup, this is its content widget
424 // if this is a toplevel window, and there is any ongoing fullscreen
425 // transition, it is the animation object.
426 NSAnimation
* mFullscreenTransitionAnimation
;
427 mozilla::WindowShadow mShadowStyle
;
429 CGFloat mBackingScaleFactor
;
430 CGFloat mAspectRatio
;
432 WindowAnimationType mAnimationType
;
434 bool mWindowMadeHere
; // true if we created the window, false for embedding
435 bool mSheetNeedsShow
; // if this is a sheet, are we waiting to be shown?
436 // this is used for sibling sheet contention only
437 nsSizeMode mSizeMode
;
438 bool mInFullScreenMode
;
439 // Whether we are currently using native fullscreen. It could be false because
440 // we are in the emulated fullscreen where we do not use the native
442 bool mInNativeFullScreenMode
;
444 mozilla::Maybe
<TransitionType
> mTransitionCurrent
;
445 std::queue
<TransitionType
> mTransitionsPending
;
447 // Sometimes we add a transition that wasn't requested by a caller. We do this
448 // to manage transitions between states that otherwise would be rejected by
449 // Cocoa. When we do this, it's useful to know when we are handling an added
450 // transition because we don't want to send size mode events when they
452 bool mIsTransitionCurrentAdded
= false;
454 // Whether we are treating the next resize as the start of a fullscreen
455 // transition. If we are, which direction are we going: Fullscreen or
457 mozilla::Maybe
<TransitionType
> mUpdateFullscreenOnResize
;
459 bool IsInTransition() { return mTransitionCurrent
.isSome(); }
460 void QueueTransition(const TransitionType
& aTransition
);
461 void ProcessTransitions();
463 bool mInProcessTransitions
= false;
465 // While running an emulated fullscreen transition, we want to suppress
466 // sending size mode events due to window resizing. We fix it up at the end
467 // when the transition is complete.
468 bool mSuppressSizeModeEvents
= false;
470 // Ignore occlusion events caused by displaying the temporary fullscreen
471 // window during the fullscreen transition animation because only focused
472 // contexts are permitted to enter DOM fullscreen.
473 int mIgnoreOcclusionCount
;
475 // Set to true when a native fullscreen transition is initiated -- either to
476 // or from fullscreen -- and set to false when it is complete. During this
477 // period, we presume the window is visible, which prevents us from sending
478 // unnecessary OcclusionStateChanged events.
479 bool mHasStartedNativeFullscreen
;
484 bool mIsAnimationSuppressed
;
486 bool mInReportMoveEvent
; // true if in a call to ReportMoveEvent().
487 bool mInResize
; // true if in a call to DoResize().
488 bool mWindowTransformIsIdentity
;
490 bool mAspectRatioLocked
;
492 int32_t mNumModalDescendents
;
493 InputContext mInputContext
;
494 NSWindowAnimationBehavior mWindowAnimationBehavior
;
497 // This is class state for tracking which nsCocoaWindow, if any, is in the
498 // middle of a native fullscreen transition.
499 static nsCocoaWindow
* sWindowInNativeTransition
;
501 // This function returns true if the caller has been able to claim the sole
502 // permission to start a native transition. It must be followed by a call
503 // to EndOurNativeTransition() when the native transition is complete.
504 bool CanStartNativeTransition();
505 void EndOurNativeTransition();
507 // true if Show() has been called.
511 #endif // nsCocoaWindow_h_