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 "nsCocoaUtils.h"
16 #include "nsTouchBar.h"
26 enum class NativeKeyBindingsType
: uint8_t;
27 } // namespace mozilla
29 // NSWindow subclass that is the base class for all of our own window classes.
30 // Among other things, this class handles the storage of those settings that
31 // need to be persisted across window destruction and reconstruction, i.e. when
32 // switching to and from fullscreen mode.
33 // We don't save shadow, transparency mode or background color because it's not
34 // worth the hassle - Gecko will reset them anyway as soon as the window is
36 @interface BaseWindow
: NSWindow
{
38 NSMutableDictionary
* mState
;
39 BOOL mDrawsIntoWindowFrame
;
41 // Invalidation disabling
42 BOOL mDisabledNeedsDisplay
;
44 NSTrackingArea
* mTrackingArea
;
50 BOOL mIsAnimationSuppressed
;
52 nsTouchBar
* mTouchBar
;
55 - (void)importState
:(NSDictionary
*)aState
;
56 - (NSMutableDictionary
*)exportState
;
57 - (void)setDrawsContentsIntoWindowFrame
:(BOOL
)aState
;
58 - (BOOL
)drawsContentsIntoWindowFrame
;
60 // These two methods are like contentRectForFrameRect and
61 // frameRectForContentRect, but they deal with the rect of the window's "main
62 // ChildView" instead of the rect of the window's content view. The two are
63 // sometimes sized differently: The window's content view always covers the
64 // entire window, whereas the ChildView only covers the full window when
65 // drawsContentsIntoWindowFrame is YES. When drawsContentsIntoWindowFrame is NO,
66 // there's a titlebar-sized gap above the ChildView within the content view.
67 - (NSRect
)childViewRectForFrameRect
:(NSRect
)aFrameRect
;
68 - (NSRect
)frameRectForChildViewRect
:(NSRect
)aChildViewRect
;
70 - (void)mouseEntered
:(NSEvent
*)aEvent
;
71 - (void)mouseExited
:(NSEvent
*)aEvent
;
72 - (void)mouseMoved
:(NSEvent
*)aEvent
;
73 - (void)updateTrackingArea
;
74 - (NSView
*)trackingAreaView
;
76 - (void)setBeingShown
:(BOOL
)aValue
;
78 - (BOOL
)isVisibleOrBeingShown
;
80 - (void)setIsAnimationSuppressed
:(BOOL
)aValue
;
81 - (BOOL
)isAnimationSuppressed
;
83 // Returns an autoreleased NSArray containing the NSViews that we consider the
84 // "contents" of this window. All views in the returned array are subviews of
85 // this window's content view. However, the array may not include all of the
86 // content view's subviews; concretely, the ToolbarWindow implementation will
87 // exclude its MOZTitlebarView from the array that is returned here.
88 // In the vast majority of cases, the array will only have a single element:
89 // this window's mainChildView.
90 - (NSArray
<NSView
*>*)contentViewContents
;
92 - (ChildView
*)mainChildView
;
94 - (void)setWantsTitleDrawn
:(BOOL
)aDrawTitle
;
95 - (BOOL
)wantsTitleDrawn
;
97 - (void)disableSetNeedsDisplay
;
98 - (void)enableSetNeedsDisplay
;
100 - (NSRect
)getAndResetNativeDirtyRect
;
102 - (void)setEffectViewWrapperForStyle
:(mozilla::WindowShadow
)aStyle
;
103 @
property(nonatomic
) mozilla::WindowShadow shadowStyle
;
105 - (void)releaseJSObjects
;
109 @interface
NSWindow (Undocumented
)
110 - (NSDictionary
*)shadowParameters
;
112 // Present in the same form on OS X since at least OS X 10.5.
113 - (NSRect
)contentRectForFrameRect
:(NSRect
)windowFrame
114 styleMask
:(NSUInteger
)windowStyle
;
115 - (NSRect
)frameRectForContentRect
:(NSRect
)windowContentRect
116 styleMask
:(NSUInteger
)windowStyle
;
118 // Present since at least OS X 10.5. The OS calls this method on NSWindow
119 // (and its subclasses) to find out which NSFrameView subclass to instantiate
120 // to create its "frame view".
121 + (Class
)frameViewClassForStyleMask
:(NSUInteger
)styleMask
;
125 @interface PopupWindow
: BaseWindow
{
130 - (id
)initWithContentRect
:(NSRect
)contentRect
131 styleMask
:(NSUInteger
)styleMask
132 backing
:(NSBackingStoreType
)bufferingType
133 defer
:(BOOL
)deferCreation
;
134 - (BOOL
)isContextMenu
;
135 - (void)setIsContextMenu
:(BOOL
)flag
;
136 - (BOOL
)canBecomeMainWindow
;
140 @interface BorderlessWindow
: BaseWindow
{
143 - (BOOL
)canBecomeKeyWindow
;
144 - (BOOL
)canBecomeMainWindow
;
148 @interface WindowDelegate
: NSObject
<NSWindowDelegate
> {
149 nsCocoaWindow
* mGeckoWindow
; // [WEAK] (we are owned by the window)
150 // Used to avoid duplication when we send NS_ACTIVATE and
151 // NS_DEACTIVATE to Gecko for toplevel widgets. Starts out
153 bool mToplevelActiveState
;
154 BOOL mHasEverBeenZoomed
;
156 + (void)paintMenubarForWindow
:(NSWindow
*)aWindow
;
157 - (id
)initWithGeckoWindow
:(nsCocoaWindow
*)geckoWind
;
158 - (void)windowDidResize
:(NSNotification
*)aNotification
;
159 - (nsCocoaWindow
*)geckoWidget
;
160 - (bool)toplevelActiveState
;
161 - (void)sendToplevelActivateEvents
;
162 - (void)sendToplevelDeactivateEvents
;
165 @interface FullscreenTitlebarTracker
: NSTitlebarAccessoryViewController
166 - (FullscreenTitlebarTracker
*)init
;
169 // NSWindow subclass for handling windows with toolbars.
170 @interface ToolbarWindow
: BaseWindow
{
171 // mFullscreenTitlebarTracker attaches an invisible rectangle to the system
172 // title bar. This allows us to detect when the title bar is showing in
174 FullscreenTitlebarTracker
* mFullscreenTitlebarTracker
;
176 CGFloat mMenuBarHeight
;
177 NSRect mWindowButtonsRect
;
179 - (void)setDrawsContentsIntoWindowFrame
:(BOOL
)aState
;
180 - (void)placeWindowButtons
:(NSRect
)aRect
;
181 - (NSRect
)windowButtonsRect
;
182 - (void)windowMainStateChanged
;
185 class nsCocoaWindow final
: public nsBaseWidget
{
187 typedef nsBaseWidget Inherited
;
192 [[nodiscard
]] nsresult
Create(nsIWidget
* aParent
,
193 nsNativeWidget aNativeParent
,
194 const DesktopIntRect
& aRect
,
195 InitData
* = nullptr) override
;
197 [[nodiscard
]] nsresult
Create(nsIWidget
* aParent
,
198 nsNativeWidget aNativeParent
,
199 const LayoutDeviceIntRect
& aRect
,
200 InitData
* = nullptr) override
;
202 void Destroy() override
;
204 void Show(bool aState
) override
;
205 bool NeedsRecreateToReshow() override
;
207 void Enable(bool aState
) override
;
208 bool IsEnabled() const override
;
209 void SetModal(bool aState
) override
;
210 bool IsRunningAppModal() override
;
211 bool IsVisible() const override
;
212 void SetFocus(Raise
, mozilla::dom::CallerType aCallerType
) override
;
213 LayoutDeviceIntPoint
WidgetToScreenOffset() override
;
214 LayoutDeviceIntPoint
GetClientOffset() override
;
215 LayoutDeviceIntMargin
ClientToWindowMargin() override
;
217 void* GetNativeData(uint32_t aDataType
) override
;
219 void ConstrainPosition(DesktopIntPoint
&) override
;
220 void SetSizeConstraints(const SizeConstraints
& aConstraints
) override
;
221 void Move(double aX
, double aY
) override
;
222 nsSizeMode
SizeMode() override
{ return mSizeMode
; }
223 void SetSizeMode(nsSizeMode aMode
) override
;
224 void GetWorkspaceID(nsAString
& workspaceID
) override
;
225 void MoveToWorkspace(const nsAString
& workspaceID
) override
;
226 void SuppressAnimation(bool aSuppress
) override
;
227 void HideWindowChrome(bool aShouldHide
) override
;
229 bool PrepareForFullscreenTransition(nsISupports
** aData
) override
;
230 void PerformFullscreenTransition(FullscreenTransitionStage aStage
,
231 uint16_t aDuration
, nsISupports
* aData
,
232 nsIRunnable
* aCallback
) override
;
233 void CleanupFullscreenTransition() override
;
234 nsresult
MakeFullScreen(bool aFullScreen
) final
;
235 nsresult
MakeFullScreenWithNativeTransition(bool aFullScreen
) final
;
236 NSAnimation
* FullscreenTransitionAnimation() const {
237 return mFullscreenTransitionAnimation
;
239 void ReleaseFullscreenTransitionAnimation() {
240 MOZ_ASSERT(mFullscreenTransitionAnimation
,
241 "Should only be called when there is animation");
242 [mFullscreenTransitionAnimation release
];
243 mFullscreenTransitionAnimation
= nil
;
246 void Resize(double aWidth
, double aHeight
, bool aRepaint
) override
;
247 void Resize(double aX
, double aY
, double aWidth
, double aHeight
,
248 bool aRepaint
) override
;
249 NSRect
GetClientCocoaRect();
250 LayoutDeviceIntRect
GetClientBounds() override
;
251 LayoutDeviceIntRect
GetScreenBounds() override
;
252 void ReportMoveEvent();
253 void ReportSizeEvent();
254 void SetCursor(const Cursor
&) override
;
256 CGFloat
BackingScaleFactor();
257 void BackingScaleFactorChanged();
258 double GetDefaultScaleInternal() override
;
259 int32_t RoundsWidgetCoordinatesTo() override
;
261 mozilla::DesktopToLayoutDeviceScale
GetDesktopToDeviceScale() final
{
262 return mozilla::DesktopToLayoutDeviceScale(BackingScaleFactor());
265 nsresult
SetTitle(const nsAString
& aTitle
) override
;
267 void Invalidate(const LayoutDeviceIntRect
& aRect
) override
;
268 WindowRenderer
* GetWindowRenderer() override
;
269 nsresult
DispatchEvent(mozilla::WidgetGUIEvent
* aEvent
,
270 nsEventStatus
& aStatus
) override
;
271 void CaptureRollupEvents(bool aDoCapture
) override
;
272 [[nodiscard
]] nsresult
GetAttention(int32_t aCycleCount
) override
;
273 bool HasPendingInputEvent() override
;
274 TransparencyMode
GetTransparencyMode() override
;
275 void SetTransparencyMode(TransparencyMode aMode
) override
;
276 void SetWindowShadowStyle(mozilla::WindowShadow aStyle
) override
;
277 void SetWindowOpacity(float aOpacity
) override
;
278 void SetWindowTransform(const mozilla::gfx::Matrix
& aTransform
) override
;
279 void SetInputRegion(const InputRegion
&) override
;
280 void SetColorScheme(const mozilla::Maybe
<mozilla::ColorScheme
>&) override
;
281 void SetShowsToolbarButton(bool aShow
) override
;
282 void SetSupportsNativeFullscreen(bool aShow
) override
;
283 void SetWindowAnimationType(WindowAnimationType aType
) override
;
284 void SetDrawsTitle(bool aDrawTitle
) override
;
285 nsresult
SetNonClientMargins(const LayoutDeviceIntMargin
&) override
;
286 void SetDrawsInTitlebar(bool aState
);
287 void UpdateThemeGeometries(
288 const nsTArray
<ThemeGeometry
>& aThemeGeometries
) override
;
289 nsresult
SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint
,
290 NativeMouseMessage aNativeMessage
,
291 mozilla::MouseButton aButton
,
292 nsIWidget::Modifiers aModifierFlags
,
293 nsIObserver
* aObserver
) override
;
294 nsresult
SynthesizeNativeMouseScrollEvent(
295 LayoutDeviceIntPoint aPoint
, uint32_t aNativeMessage
, double aDeltaX
,
296 double aDeltaY
, double aDeltaZ
, uint32_t aModifierFlags
,
297 uint32_t aAdditionalFlags
, nsIObserver
* aObserver
) override
;
298 void LockAspectRatio(bool aShouldLock
) override
;
300 void DispatchSizeModeEvent();
301 void DispatchOcclusionEvent();
303 // be notified that a some form of drag event needs to go into Gecko
304 bool DragEvent(unsigned int aMessage
, mozilla::gfx::Point aMouseGlobal
,
305 UInt16 aKeyModifiers
);
307 bool HasModalDescendants() const { return mNumModalDescendants
> 0; }
308 bool IsModal() const { return mModal
; }
310 NSWindow
* GetCocoaWindow() { return mWindow
; }
312 void SetMenuBar(RefPtr
<nsMenuBarX
>&& aMenuBar
);
313 nsMenuBarX
* GetMenuBar();
315 void SetInputContext(const InputContext
& aContext
,
316 const InputContextAction
& aAction
) override
;
317 InputContext
GetInputContext() override
{ return mInputContext
; }
318 MOZ_CAN_RUN_SCRIPT
bool GetEditCommands(
319 mozilla::NativeKeyBindingsType aType
,
320 const mozilla::WidgetKeyboardEvent
& aEvent
,
321 nsTArray
<mozilla::CommandInt
>& aCommands
) override
;
323 void SetPopupWindowLevel();
325 bool InFullScreenMode() const { return mInFullScreenMode
; }
327 void PauseOrResumeCompositor(bool aPause
) override
;
329 bool AsyncPanZoomEnabled() const override
;
331 bool StartAsyncAutoscroll(const ScreenPoint
& aAnchorLocation
,
332 const ScrollableLayerGuid
& aGuid
) override
;
333 void StopAsyncAutoscroll(const ScrollableLayerGuid
& aGuid
) override
;
335 // Class method versions of NSWindow/Delegate callbacks which need to
336 // access object state.
337 void CocoaWindowWillEnterFullscreen(bool aFullscreen
);
338 void CocoaWindowDidEnterFullscreen(bool aFullscreen
);
339 void CocoaWindowDidResize();
340 void CocoaSendToplevelActivateEvents();
341 void CocoaSendToplevelDeactivateEvents();
343 enum class TransitionType
{
351 void FinishCurrentTransitionIfMatching(const TransitionType
& aTransition
);
353 // Called when something has happened that might cause us to update our
354 // fullscreen state. Returns true if we updated state. We'll call this
355 // on window resize, and we'll call it when we enter or exit fullscreen,
356 // since fullscreen to-and-from zoomed windows won't necessarily trigger
358 bool HandleUpdateFullscreenOnResize();
361 virtual ~nsCocoaWindow();
363 nsresult
CreateNativeWindow(const NSRect
& aRect
, BorderStyle aBorderStyle
,
364 bool aRectIsFrameRect
, bool aIsPrivateBrowsing
);
365 nsresult
CreatePopupContentView(const LayoutDeviceIntRect
& aRect
, InitData
*);
366 void DestroyNativeWindow();
368 int32_t GetWorkspaceID();
369 void SendSetZLevelEvent();
371 void DoResize(double aX
, double aY
, double aWidth
, double aHeight
,
372 bool aRepaint
, bool aConstrainToCurrentScreen
);
374 void UpdateFullscreenState(bool aFullScreen
, bool aNativeMode
);
375 nsresult
DoMakeFullScreen(bool aFullScreen
, bool aUseSystemTransition
);
377 already_AddRefed
<nsIWidget
> AllocateChildPopupWidget() override
{
378 return nsIWidget::CreateTopLevelWindow();
381 nsIWidget
* mParent
; // if we're a popup, this is our parent [WEAK]
382 nsIWidget
* mAncestorLink
; // link to traverse ancestors [WEAK]
383 BaseWindow
* mWindow
; // our cocoa window [STRONG]
385 mDelegate
; // our delegate for processing window msgs [STRONG]
386 RefPtr
<nsMenuBarX
> mMenuBar
;
388 mPopupContentView
; // if this is a popup, this is its content widget
389 // if this is a toplevel window, and there is any ongoing fullscreen
390 // transition, it is the animation object.
391 NSAnimation
* mFullscreenTransitionAnimation
;
392 mozilla::WindowShadow mShadowStyle
;
394 CGFloat mBackingScaleFactor
;
395 CGFloat mAspectRatio
;
397 WindowAnimationType mAnimationType
;
399 bool mWindowMadeHere
; // true if we created the window, false for embedding
400 nsSizeMode mSizeMode
;
401 bool mInFullScreenMode
;
402 // Whether we are currently using native fullscreen. It could be false because
403 // we are in the emulated fullscreen where we do not use the native
405 bool mInNativeFullScreenMode
;
407 mozilla::Maybe
<TransitionType
> mTransitionCurrent
;
408 std::queue
<TransitionType
> mTransitionsPending
;
410 // Sometimes we add a transition that wasn't requested by a caller. We do this
411 // to manage transitions between states that otherwise would be rejected by
412 // Cocoa. When we do this, it's useful to know when we are handling an added
413 // transition because we don't want to send size mode events when they
415 bool mIsTransitionCurrentAdded
= false;
417 // Whether we are treating the next resize as the start of a fullscreen
418 // transition. If we are, which direction are we going: Fullscreen or
420 mozilla::Maybe
<TransitionType
> mUpdateFullscreenOnResize
;
422 bool IsInTransition() { return mTransitionCurrent
.isSome(); }
423 void QueueTransition(const TransitionType
& aTransition
);
424 void ProcessTransitions();
426 // Call this to stop all transition processing, which is useful during
427 // window closing and shutdown.
428 void CancelAllTransitions();
430 bool mInProcessTransitions
= false;
432 // While running an emulated fullscreen transition, we want to suppress
433 // sending size mode events due to window resizing. We fix it up at the end
434 // when the transition is complete.
435 bool mSuppressSizeModeEvents
= false;
437 // Ignore occlusion events caused by displaying the temporary fullscreen
438 // window during the fullscreen transition animation because only focused
439 // contexts are permitted to enter DOM fullscreen.
440 int mIgnoreOcclusionCount
;
442 // Set to true when a native fullscreen transition is initiated -- either to
443 // or from fullscreen -- and set to false when it is complete. During this
444 // period, we presume the window is visible, which prevents us from sending
445 // unnecessary OcclusionStateChanged events.
446 bool mHasStartedNativeFullscreen
;
449 bool mIsAnimationSuppressed
= false;
451 bool mInReportMoveEvent
= false; // true if in a call to ReportMoveEvent().
452 bool mInResize
= false; // true if in a call to DoResize().
453 bool mWindowTransformIsIdentity
= true;
454 bool mAlwaysOnTop
= false;
455 bool mAspectRatioLocked
= false;
456 bool mIsAlert
= false; // True if this is an non-native alert window.
457 bool mWasShown
= false;
459 int32_t mNumModalDescendants
= 0;
460 InputContext mInputContext
;
461 NSWindowAnimationBehavior mWindowAnimationBehavior
;
464 // This is class state for tracking which nsCocoaWindow, if any, is in the
465 // middle of a native fullscreen transition.
466 static nsCocoaWindow
* sWindowInNativeTransition
;
468 // This function returns true if the caller has been able to claim the sole
469 // permission to start a native transition. It must be followed by a call
470 // to EndOurNativeTransition() when the native transition is complete.
471 bool CanStartNativeTransition();
472 void EndOurNativeTransition();
475 #endif // nsCocoaWindow_h_