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/. */ 5 6 #ifndef nsCocoaWindow_h_ 7 #define nsCocoaWindow_h_ 8 9 #undef DARWIN 10 11 #import <Cocoa/Cocoa.h> 12 13 #include "mozilla/RefPtr.h" 14 #include "nsBaseWidget.h" 15 #include "nsPIWidgetCocoa.h" 16 #include "nsCocoaUtils.h" 17 #include "nsTouchBar.h" 18 #include <dlfcn.h> 19 20 class nsCocoaWindow; 21 class nsChildView; 22 class nsMenuBarX; 23 @class ChildView; 24 25 typedef struct _nsCocoaWindowList { _nsCocoaWindowList_nsCocoaWindowList26 _nsCocoaWindowList() : prev(nullptr), window(nullptr) {} 27 struct _nsCocoaWindowList* prev; 28 nsCocoaWindow* window; // Weak 29 } nsCocoaWindowList; 30 31 // NSWindow subclass that is the base class for all of our own window classes. 32 // Among other things, this class handles the storage of those settings that 33 // need to be persisted across window destruction and reconstruction, i.e. when 34 // switching to and from fullscreen mode. 35 // We don't save shadow, transparency mode or background color because it's not 36 // worth the hassle - Gecko will reset them anyway as soon as the window is 37 // resized. 38 @interface BaseWindow : NSWindow { 39 // Data Storage 40 NSMutableDictionary* mState; 41 BOOL mDrawsIntoWindowFrame; 42 43 // Invalidation disabling 44 BOOL mDisabledNeedsDisplay; 45 46 NSTrackingArea* mTrackingArea; 47 48 NSRect mDirtyRect; 49 50 BOOL mBeingShown; 51 BOOL mDrawTitle; 52 BOOL mUseMenuStyle; 53 BOOL mIsAnimationSuppressed; 54 55 nsTouchBar* mTouchBar; 56 } 57 58 - (void)importState:(NSDictionary*)aState; 59 - (NSMutableDictionary*)exportState; 60 - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState; 61 - (BOOL)drawsContentsIntoWindowFrame; 62 63 // These two methods are like contentRectForFrameRect and frameRectForContentRect, 64 // but they deal with the rect of the window's "main ChildView" instead of the 65 // rect of the window's content view. The two are sometimes sized differently: The 66 // window's content view always covers the entire window, whereas the ChildView 67 // only covers the full window when drawsContentsIntoWindowFrame is YES. When 68 // drawsContentsIntoWindowFrame is NO, there's a titlebar-sized gap above the 69 // ChildView within the content view. 70 - (NSRect)childViewRectForFrameRect:(NSRect)aFrameRect; 71 - (NSRect)frameRectForChildViewRect:(NSRect)aChildViewRect; 72 73 - (void)mouseEntered:(NSEvent*)aEvent; 74 - (void)mouseExited:(NSEvent*)aEvent; 75 - (void)mouseMoved:(NSEvent*)aEvent; 76 - (void)updateTrackingArea; 77 - (NSView*)trackingAreaView; 78 79 - (void)setBeingShown:(BOOL)aValue; 80 - (BOOL)isBeingShown; 81 - (BOOL)isVisibleOrBeingShown; 82 83 - (void)setIsAnimationSuppressed:(BOOL)aValue; 84 - (BOOL)isAnimationSuppressed; 85 86 // Returns an autoreleased NSArray containing the NSViews that we consider the 87 // "contents" of this window. All views in the returned array are subviews of 88 // this window's content view. However, the array may not include all of the 89 // content view's subviews; concretely, the ToolbarWindow implementation will 90 // exclude its MOZTitlebarView from the array that is returned here. 91 // In the vast majority of cases, the array will only have a single element: 92 // this window's mainChildView. 93 - (NSArray<NSView*>*)contentViewContents; 94 95 - (ChildView*)mainChildView; 96 97 - (void)setWantsTitleDrawn:(BOOL)aDrawTitle; 98 - (BOOL)wantsTitleDrawn; 99 100 - (void)disableSetNeedsDisplay; 101 - (void)enableSetNeedsDisplay; 102 103 - (NSRect)getAndResetNativeDirtyRect; 104 105 - (void)setUseMenuStyle:(BOOL)aValue; 106 @property(nonatomic) mozilla::StyleWindowShadow shadowStyle; 107 108 - (void)releaseJSObjects; 109 110 @end 111 112 @interface NSWindow (Undocumented) 113 114 // If a window has been explicitly removed from the "window cache" (to 115 // deactivate it), it's sometimes necessary to "reset" it to reactivate it 116 // (and put it back in the "window cache"). One way to do this, which Apple 117 // often uses, is to set the "window number" to '-1' and then back to its 118 // original value. 119 - (void)_setWindowNumber:(NSInteger)aNumber; 120 121 - (BOOL)bottomCornerRounded; 122 123 // Present in the same form on OS X since at least OS X 10.5. 124 - (NSRect)contentRectForFrameRect:(NSRect)windowFrame styleMask:(NSUInteger)windowStyle; 125 - (NSRect)frameRectForContentRect:(NSRect)windowContentRect styleMask:(NSUInteger)windowStyle; 126 127 // Present since at least OS X 10.5. The OS calls this method on NSWindow 128 // (and its subclasses) to find out which NSFrameView subclass to instantiate 129 // to create its "frame view". 130 + (Class)frameViewClassForStyleMask:(NSUInteger)styleMask; 131 132 @end 133 134 @interface PopupWindow : BaseWindow { 135 @private 136 BOOL mIsContextMenu; 137 } 138 139 - (id)initWithContentRect:(NSRect)contentRect 140 styleMask:(NSUInteger)styleMask 141 backing:(NSBackingStoreType)bufferingType 142 defer:(BOOL)deferCreation; 143 - (BOOL)isContextMenu; 144 - (void)setIsContextMenu:(BOOL)flag; 145 - (BOOL)canBecomeMainWindow; 146 147 @end 148 149 @interface BorderlessWindow : BaseWindow { 150 } 151 152 - (BOOL)canBecomeKeyWindow; 153 - (BOOL)canBecomeMainWindow; 154 155 @end 156 157 @interface WindowDelegate : NSObject <NSWindowDelegate> { 158 nsCocoaWindow* mGeckoWindow; // [WEAK] (we are owned by the window) 159 // Used to avoid duplication when we send NS_ACTIVATE and 160 // NS_DEACTIVATE to Gecko for toplevel widgets. Starts out 161 // false. 162 bool mToplevelActiveState; 163 BOOL mHasEverBeenZoomed; 164 } 165 + (void)paintMenubarForWindow:(NSWindow*)aWindow; 166 - (id)initWithGeckoWindow:(nsCocoaWindow*)geckoWind; 167 - (void)windowDidResize:(NSNotification*)aNotification; 168 - (nsCocoaWindow*)geckoWidget; 169 - (bool)toplevelActiveState; 170 - (void)sendToplevelActivateEvents; 171 - (void)sendToplevelDeactivateEvents; 172 @end 173 174 @interface MOZTitlebarView : NSVisualEffectView 175 @end 176 177 @interface FullscreenTitlebarTracker : NSTitlebarAccessoryViewController 178 - (FullscreenTitlebarTracker*)init; 179 @end 180 181 // NSWindow subclass for handling windows with toolbars. 182 @interface ToolbarWindow : BaseWindow { 183 // This window's titlebar view, if present. 184 // Will be nil if the window has neither a titlebar nor a unified toolbar. 185 // This view is a subview of the window's content view and gets created and 186 // destroyed by updateTitlebarView. 187 MOZTitlebarView* mTitlebarView; // [STRONG] 188 // mFullscreenTitlebarTracker attaches an invisible rectangle to the system 189 // title bar. This allows us to detect when the title bar is showing in 190 // fullscreen. 191 FullscreenTitlebarTracker* mFullscreenTitlebarTracker; 192 193 CGFloat mUnifiedToolbarHeight; 194 CGFloat mSheetAttachmentPosition; 195 CGFloat mMenuBarHeight; 196 /* Store the height of the titlebar when this window is initialized. The 197 titlebarHeight getter returns 0 when in fullscreen, which is not useful in 198 some cases. */ 199 CGFloat mInitialTitlebarHeight; 200 NSRect mWindowButtonsRect; 201 } 202 - (void)setUnifiedToolbarHeight:(CGFloat)aHeight; 203 - (CGFloat)unifiedToolbarHeight; 204 - (CGFloat)titlebarHeight; 205 - (NSRect)titlebarRect; 206 - (void)setTitlebarNeedsDisplay; 207 - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState; 208 - (void)setSheetAttachmentPosition:(CGFloat)aY; 209 - (CGFloat)sheetAttachmentPosition; 210 - (void)placeWindowButtons:(NSRect)aRect; 211 - (NSPoint)windowButtonsPositionWithDefaultPosition:(NSPoint)aDefaultPosition; 212 - (void)windowMainStateChanged; 213 @end 214 215 class nsCocoaWindow final : public nsBaseWidget, public nsPIWidgetCocoa { 216 private: 217 typedef nsBaseWidget Inherited; 218 219 public: 220 nsCocoaWindow(); 221 222 NS_DECL_ISUPPORTS_INHERITED 223 NS_DECL_NSPIWIDGETCOCOA; // semicolon for clang-format bug 1629756 224 225 [[nodiscard]] virtual nsresult Create(nsIWidget* aParent, nsNativeWidget aNativeParent, 226 const DesktopIntRect& aRect, 227 nsWidgetInitData* aInitData = nullptr) override; 228 229 [[nodiscard]] virtual nsresult Create(nsIWidget* aParent, nsNativeWidget aNativeParent, 230 const LayoutDeviceIntRect& aRect, 231 nsWidgetInitData* aInitData = nullptr) override; 232 233 virtual void Destroy() override; 234 235 virtual void Show(bool aState) override; 236 virtual bool NeedsRecreateToReshow() override; 237 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 LayoutDeviceIntSize ClientToWindowSize(const LayoutDeviceIntSize& aClientSize) override; 249 250 virtual void* GetNativeData(uint32_t aDataType) override; 251 252 virtual void ConstrainPosition(bool aAllowSlop, int32_t* aX, int32_t* aY) override; 253 virtual void SetSizeConstraints(const SizeConstraints& aConstraints) override; 254 virtual void Move(double aX, double aY) override; 255 virtual void SetSizeMode(nsSizeMode aMode) override; 256 virtual void GetWorkspaceID(nsAString& workspaceID) override; 257 virtual void MoveToWorkspace(const nsAString& workspaceID) override; 258 virtual void SuppressAnimation(bool aSuppress) override; 259 virtual void HideWindowChrome(bool aShouldHide) override; 260 261 void WillEnterFullScreen(bool aFullScreen); 262 void EnteredFullScreen(bool aFullScreen, bool aNativeMode = true); 263 virtual bool PrepareForFullscreenTransition(nsISupports** aData) override; 264 virtual void PerformFullscreenTransition(FullscreenTransitionStage aStage, uint16_t aDuration, 265 nsISupports* aData, nsIRunnable* aCallback) override; 266 virtual void CleanupFullscreenTransition() override; 267 nsresult MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen = nullptr) final; 268 nsresult MakeFullScreenWithNativeTransition(bool aFullScreen, 269 nsIScreen* aTargetScreen = nullptr) final; FullscreenTransitionAnimation()270 NSAnimation* FullscreenTransitionAnimation() const { return mFullscreenTransitionAnimation; } ReleaseFullscreenTransitionAnimation()271 void ReleaseFullscreenTransitionAnimation() { 272 MOZ_ASSERT(mFullscreenTransitionAnimation, "Should only be called when there is animation"); 273 [mFullscreenTransitionAnimation release]; 274 mFullscreenTransitionAnimation = nil; 275 } 276 277 virtual void Resize(double aWidth, double aHeight, bool aRepaint) override; 278 virtual void Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint) override; 279 NSRect GetClientCocoaRect(); 280 virtual LayoutDeviceIntRect GetClientBounds() override; 281 virtual LayoutDeviceIntRect GetScreenBounds() override; 282 void ReportMoveEvent(); 283 void ReportSizeEvent(); 284 virtual void SetCursor(const Cursor&) override; 285 286 CGFloat BackingScaleFactor(); 287 void BackingScaleFactorChanged(); 288 virtual double GetDefaultScaleInternal() override; 289 virtual int32_t RoundsWidgetCoordinatesTo() override; 290 GetDesktopToDeviceScale()291 mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() final { 292 return mozilla::DesktopToLayoutDeviceScale(BackingScaleFactor()); 293 } 294 295 virtual nsresult SetTitle(const nsAString& aTitle) override; 296 297 virtual void Invalidate(const LayoutDeviceIntRect& aRect) override; 298 virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations) override; 299 virtual LayerManager* GetLayerManager( 300 PLayerTransactionChild* aShadowManager = nullptr, 301 LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE, 302 LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT) override; 303 virtual nsresult DispatchEvent(mozilla::WidgetGUIEvent* aEvent, nsEventStatus& aStatus) override; 304 virtual void CaptureRollupEvents(nsIRollupListener* aListener, bool aDoCapture) override; 305 [[nodiscard]] virtual nsresult GetAttention(int32_t aCycleCount) override; 306 virtual bool HasPendingInputEvent() override; 307 virtual nsTransparencyMode GetTransparencyMode() override; 308 virtual void SetTransparencyMode(nsTransparencyMode aMode) override; 309 virtual void SetWindowShadowStyle(mozilla::StyleWindowShadow aStyle) override; 310 virtual void SetWindowOpacity(float aOpacity) override; 311 virtual void SetWindowTransform(const mozilla::gfx::Matrix& aTransform) override; 312 virtual void SetWindowMouseTransparent(bool aIsTransparent) override; 313 virtual void SetShowsToolbarButton(bool aShow) override; 314 virtual void SetSupportsNativeFullscreen(bool aShow) override; 315 virtual void SetWindowAnimationType(WindowAnimationType aType) override; 316 virtual void SetDrawsTitle(bool aDrawTitle) override; 317 virtual nsresult SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override; 318 virtual void SetDrawsInTitlebar(bool aState) override; 319 virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) override; 320 virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, 321 NativeMouseMessage aNativeMessage, 322 mozilla::MouseButton aButton, 323 nsIWidget::Modifiers aModifierFlags, 324 nsIObserver* aObserver) override; 325 virtual nsresult SynthesizeNativeMouseScrollEvent(LayoutDeviceIntPoint aPoint, 326 uint32_t aNativeMessage, double aDeltaX, 327 double aDeltaY, double aDeltaZ, 328 uint32_t aModifierFlags, 329 uint32_t aAdditionalFlags, 330 nsIObserver* aObserver) override; 331 virtual void LockAspectRatio(bool aShouldLock) override; 332 333 void DispatchSizeModeEvent(); 334 void DispatchOcclusionEvent(); 335 336 // be notified that a some form of drag event needs to go into Gecko 337 virtual bool DragEvent(unsigned int aMessage, mozilla::gfx::Point aMouseGlobal, 338 UInt16 aKeyModifiers); 339 HasModalDescendents()340 bool HasModalDescendents() { return mNumModalDescendents > 0; } GetCocoaWindow()341 NSWindow* GetCocoaWindow() { return mWindow; } 342 343 void SetMenuBar(RefPtr<nsMenuBarX>&& aMenuBar); 344 nsMenuBarX* GetMenuBar(); 345 346 virtual void SetInputContext(const InputContext& aContext, 347 const InputContextAction& aAction) override; GetInputContext()348 virtual InputContext GetInputContext() override { return mInputContext; } 349 MOZ_CAN_RUN_SCRIPT virtual bool GetEditCommands( 350 NativeKeyBindingsType aType, const mozilla::WidgetKeyboardEvent& aEvent, 351 nsTArray<mozilla::CommandInt>& aCommands) override; 352 353 void SetPopupWindowLevel(); 354 InFullScreenMode()355 bool InFullScreenMode() const { return mInFullScreenMode; } 356 357 void PauseCompositor(); 358 void ResumeCompositor(); 359 360 bool AsyncPanZoomEnabled() const override; 361 362 bool StartAsyncAutoscroll(const ScreenPoint& aAnchorLocation, 363 const ScrollableLayerGuid& aGuid) override; 364 void StopAsyncAutoscroll(const ScrollableLayerGuid& aGuid) override; 365 366 protected: 367 virtual ~nsCocoaWindow(); 368 369 nsresult CreateNativeWindow(const NSRect& aRect, nsBorderStyle aBorderStyle, 370 bool aRectIsFrameRect); 371 nsresult CreatePopupContentView(const LayoutDeviceIntRect& aRect, nsWidgetInitData* aInitData); 372 void DestroyNativeWindow(); 373 void UpdateBounds(); 374 int32_t GetWorkspaceID(); 375 376 void DoResize(double aX, double aY, double aWidth, double aHeight, bool aRepaint, 377 bool aConstrainToCurrentScreen); 378 379 inline bool ShouldToggleNativeFullscreen(bool aFullScreen, bool aUseSystemTransition); 380 void UpdateFullscreenState(bool aFullScreen, bool aNativeMode); 381 nsresult DoMakeFullScreen(bool aFullScreen, bool aUseSystemTransition); 382 AllocateChildPopupWidget()383 virtual already_AddRefed<nsIWidget> AllocateChildPopupWidget() override { 384 return nsIWidget::CreateTopLevelWindow(); 385 } 386 387 nsIWidget* mParent; // if we're a popup, this is our parent [WEAK] 388 nsIWidget* mAncestorLink; // link to traverse ancestors [WEAK] 389 BaseWindow* mWindow; // our cocoa window [STRONG] 390 WindowDelegate* mDelegate; // our delegate for processing window msgs [STRONG] 391 RefPtr<nsMenuBarX> mMenuBar; 392 NSWindow* mSheetWindowParent; // if this is a sheet, this is the NSWindow it's attached to 393 nsChildView* mPopupContentView; // if this is a popup, this is its content widget 394 // if this is a toplevel window, and there is any ongoing fullscreen 395 // transition, it is the animation object. 396 NSAnimation* mFullscreenTransitionAnimation; 397 mozilla::StyleWindowShadow mShadowStyle; 398 399 CGFloat mBackingScaleFactor; 400 CGFloat mAspectRatio; 401 402 WindowAnimationType mAnimationType; 403 404 bool mWindowMadeHere; // true if we created the window, false for embedding 405 bool mSheetNeedsShow; // if this is a sheet, are we waiting to be shown? 406 // this is used for sibling sheet contention only 407 bool mInFullScreenMode; 408 bool mInFullScreenTransition; // true from the request to enter/exit fullscreen 409 // (MakeFullScreen() call) to EnteredFullScreen() 410 411 // Ignore occlusion events caused by displaying the temporary fullscreen 412 // window during the fullscreen transition animation because only focused 413 // contexts are permitted to enter DOM fullscreen. 414 int mIgnoreOcclusionCount; 415 416 bool mModal; 417 bool mFakeModal; 418 419 // Whether we are currently using native fullscreen. It could be false because 420 // we are in the DOM fullscreen where we do not use the native fullscreen. 421 bool mInNativeFullScreenMode; 422 423 bool mIsAnimationSuppressed; 424 425 bool mInReportMoveEvent; // true if in a call to ReportMoveEvent(). 426 bool mInResize; // true if in a call to DoResize(). 427 bool mWindowTransformIsIdentity; 428 bool mAlwaysOnTop; 429 bool mAspectRatioLocked; 430 431 int32_t mNumModalDescendents; 432 InputContext mInputContext; 433 NSWindowAnimationBehavior mWindowAnimationBehavior; 434 435 private: 436 // true if Show() has been called. 437 bool mWasShown; 438 }; 439 440 #endif // nsCocoaWindow_h_ 441