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 mBrightTitlebarForeground; 53 BOOL mUseMenuStyle; 54 BOOL mIsAnimationSuppressed; 55 56 nsTouchBar* mTouchBar; 57 } 58 59 - (void)importState:(NSDictionary*)aState; 60 - (NSMutableDictionary*)exportState; 61 - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState; 62 - (BOOL)drawsContentsIntoWindowFrame; 63 64 // These two methods are like contentRectForFrameRect and frameRectForContentRect, 65 // but they deal with the rect of the window's "main ChildView" instead of the 66 // rect of the window's content view. The two are sometimes sized differently: The 67 // window's content view always covers the entire window, whereas the ChildView 68 // only covers the full window when drawsContentsIntoWindowFrame is YES. When 69 // drawsContentsIntoWindowFrame is NO, there's a titlebar-sized gap above the 70 // ChildView within the content view. 71 - (NSRect)childViewRectForFrameRect:(NSRect)aFrameRect; 72 - (NSRect)frameRectForChildViewRect:(NSRect)aChildViewRect; 73 74 - (void)mouseEntered:(NSEvent*)aEvent; 75 - (void)mouseExited:(NSEvent*)aEvent; 76 - (void)mouseMoved:(NSEvent*)aEvent; 77 - (void)updateTrackingArea; 78 - (NSView*)trackingAreaView; 79 80 - (void)setBeingShown:(BOOL)aValue; 81 - (BOOL)isBeingShown; 82 - (BOOL)isVisibleOrBeingShown; 83 84 - (void)setIsAnimationSuppressed:(BOOL)aValue; 85 - (BOOL)isAnimationSuppressed; 86 87 // Returns an autoreleased NSArray containing the NSViews that we consider the 88 // "contents" of this window. All views in the returned array are subviews of 89 // this window's content view. However, the array may not include all of the 90 // content view's subviews; concretely, the ToolbarWindow implementation will 91 // exclude its TitlebarGradientView from the array that is returned here. 92 // In the vast majority of cases, the array will only have a single element: 93 // this window's mainChildView. 94 - (NSArray<NSView*>*)contentViewContents; 95 96 - (ChildView*)mainChildView; 97 98 - (void)setWantsTitleDrawn:(BOOL)aDrawTitle; 99 - (BOOL)wantsTitleDrawn; 100 101 - (void)setUseBrightTitlebarForeground:(BOOL)aBrightForeground; 102 - (BOOL)useBrightTitlebarForeground; 103 104 - (void)disableSetNeedsDisplay; 105 - (void)enableSetNeedsDisplay; 106 107 - (NSRect)getAndResetNativeDirtyRect; 108 109 - (void)setUseMenuStyle:(BOOL)aValue; 110 111 - (void)releaseJSObjects; 112 113 @end 114 115 @interface NSWindow (Undocumented) 116 117 // If a window has been explicitly removed from the "window cache" (to 118 // deactivate it), it's sometimes necessary to "reset" it to reactivate it 119 // (and put it back in the "window cache"). One way to do this, which Apple 120 // often uses, is to set the "window number" to '-1' and then back to its 121 // original value. 122 - (void)_setWindowNumber:(NSInteger)aNumber; 123 124 - (BOOL)bottomCornerRounded; 125 126 // Present in the same form on OS X since at least OS X 10.5. 127 - (NSRect)contentRectForFrameRect:(NSRect)windowFrame styleMask:(NSUInteger)windowStyle; 128 - (NSRect)frameRectForContentRect:(NSRect)windowContentRect styleMask:(NSUInteger)windowStyle; 129 130 // Present since at least OS X 10.5. The OS calls this method on NSWindow 131 // (and its subclasses) to find out which NSFrameView subclass to instantiate 132 // to create its "frame view". 133 + (Class)frameViewClassForStyleMask:(NSUInteger)styleMask; 134 135 @end 136 137 @interface PopupWindow : BaseWindow { 138 @private 139 BOOL mIsContextMenu; 140 } 141 142 - (id)initWithContentRect:(NSRect)contentRect 143 styleMask:(NSUInteger)styleMask 144 backing:(NSBackingStoreType)bufferingType 145 defer:(BOOL)deferCreation; 146 - (BOOL)isContextMenu; 147 - (void)setIsContextMenu:(BOOL)flag; 148 - (BOOL)canBecomeMainWindow; 149 150 @end 151 152 @interface BorderlessWindow : BaseWindow { 153 } 154 155 - (BOOL)canBecomeKeyWindow; 156 - (BOOL)canBecomeMainWindow; 157 158 @end 159 160 @interface WindowDelegate : NSObject <NSWindowDelegate> { 161 nsCocoaWindow* mGeckoWindow; // [WEAK] (we are owned by the window) 162 // Used to avoid duplication when we send NS_ACTIVATE and 163 // NS_DEACTIVATE to Gecko for toplevel widgets. Starts out 164 // false. 165 bool mToplevelActiveState; 166 BOOL mHasEverBeenZoomed; 167 } 168 + (void)paintMenubarForWindow:(NSWindow*)aWindow; 169 - (id)initWithGeckoWindow:(nsCocoaWindow*)geckoWind; 170 - (void)windowDidResize:(NSNotification*)aNotification; 171 - (nsCocoaWindow*)geckoWidget; 172 - (bool)toplevelActiveState; 173 - (void)sendToplevelActivateEvents; 174 - (void)sendToplevelDeactivateEvents; 175 @end 176 177 @interface TitlebarGradientView : NSView 178 @end 179 180 // NSWindow subclass for handling windows with toolbars. 181 @interface ToolbarWindow : BaseWindow { 182 // This window's titlebar gradient view, if present. 183 // Will be nil if drawsContentsIntoWindowFrame is YES. 184 // This view is a subview of the window's content view and gets created and 185 // destroyed by updateTitlebarGradientViewPresence. 186 TitlebarGradientView* mTitlebarGradientView; // [STRONG] 187 188 CGFloat mUnifiedToolbarHeight; 189 CGFloat mSheetAttachmentPosition; 190 NSRect mWindowButtonsRect; 191 NSRect mFullScreenButtonRect; 192 } 193 - (void)setUnifiedToolbarHeight:(CGFloat)aHeight; 194 - (CGFloat)unifiedToolbarHeight; 195 - (CGFloat)titlebarHeight; 196 - (NSRect)titlebarRect; 197 - (void)setTitlebarNeedsDisplay; 198 - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState; 199 - (void)setSheetAttachmentPosition:(CGFloat)aY; 200 - (CGFloat)sheetAttachmentPosition; 201 - (void)placeWindowButtons:(NSRect)aRect; 202 - (void)placeFullScreenButton:(NSRect)aRect; 203 - (NSPoint)windowButtonsPositionWithDefaultPosition:(NSPoint)aDefaultPosition; 204 - (NSPoint)fullScreenButtonPositionWithDefaultPosition:(NSPoint)aDefaultPosition; 205 - (void)windowMainStateChanged; 206 @end 207 208 class nsCocoaWindow final : public nsBaseWidget, public nsPIWidgetCocoa { 209 private: 210 typedef nsBaseWidget Inherited; 211 212 public: 213 nsCocoaWindow(); 214 215 NS_DECL_ISUPPORTS_INHERITED 216 NS_DECL_NSPIWIDGETCOCOA; // semicolon for clang-format bug 1629756 217 218 [[nodiscard]] virtual nsresult Create(nsIWidget* aParent, nsNativeWidget aNativeParent, 219 const DesktopIntRect& aRect, 220 nsWidgetInitData* aInitData = nullptr) override; 221 222 [[nodiscard]] virtual nsresult Create(nsIWidget* aParent, nsNativeWidget aNativeParent, 223 const LayoutDeviceIntRect& aRect, 224 nsWidgetInitData* aInitData = nullptr) override; 225 226 virtual void Destroy() override; 227 228 virtual void Show(bool aState) override; 229 virtual bool NeedsRecreateToReshow() override; 230 231 virtual nsIWidget* GetSheetWindowParent(void) override; 232 virtual void Enable(bool aState) override; 233 virtual bool IsEnabled() const override; 234 virtual void SetModal(bool aState) override; 235 virtual void SetFakeModal(bool aState) override; 236 virtual bool IsRunningAppModal() override; 237 virtual bool IsVisible() const override; 238 virtual void SetFocus(Raise, mozilla::dom::CallerType aCallerType) override; 239 virtual LayoutDeviceIntPoint WidgetToScreenOffset() override; 240 virtual LayoutDeviceIntPoint GetClientOffset() override; 241 virtual LayoutDeviceIntSize ClientToWindowSize(const LayoutDeviceIntSize& aClientSize) override; 242 243 virtual void* GetNativeData(uint32_t aDataType) override; 244 245 virtual void ConstrainPosition(bool aAllowSlop, int32_t* aX, int32_t* aY) override; 246 virtual void SetSizeConstraints(const SizeConstraints& aConstraints) override; 247 virtual void Move(double aX, double aY) override; 248 virtual void SetSizeMode(nsSizeMode aMode) override; 249 virtual void GetWorkspaceID(nsAString& workspaceID) override; 250 virtual void MoveToWorkspace(const nsAString& workspaceID) override; 251 virtual void SuppressAnimation(bool aSuppress) override; 252 virtual void HideWindowChrome(bool aShouldHide) override; 253 254 void WillEnterFullScreen(bool aFullScreen); 255 void EnteredFullScreen(bool aFullScreen, bool aNativeMode = true); 256 virtual bool PrepareForFullscreenTransition(nsISupports** aData) override; 257 virtual void PerformFullscreenTransition(FullscreenTransitionStage aStage, uint16_t aDuration, 258 nsISupports* aData, nsIRunnable* aCallback) override; 259 nsresult MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen = nullptr) final; 260 nsresult MakeFullScreenWithNativeTransition(bool aFullScreen, 261 nsIScreen* aTargetScreen = nullptr) final; FullscreenTransitionAnimation()262 NSAnimation* FullscreenTransitionAnimation() const { return mFullscreenTransitionAnimation; } ReleaseFullscreenTransitionAnimation()263 void ReleaseFullscreenTransitionAnimation() { 264 MOZ_ASSERT(mFullscreenTransitionAnimation, "Should only be called when there is animation"); 265 [mFullscreenTransitionAnimation release]; 266 mFullscreenTransitionAnimation = nil; 267 } 268 269 virtual void Resize(double aWidth, double aHeight, bool aRepaint) override; 270 virtual void Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint) override; 271 NSRect GetClientCocoaRect(); 272 virtual LayoutDeviceIntRect GetClientBounds() override; 273 virtual LayoutDeviceIntRect GetScreenBounds() override; 274 void ReportMoveEvent(); 275 void ReportSizeEvent(); 276 virtual void SetCursor(nsCursor aDefaultCursor, imgIContainer* aCursorImage, uint32_t aHotspotX, 277 uint32_t aHotspotY) override; 278 279 CGFloat BackingScaleFactor(); 280 void BackingScaleFactorChanged(); 281 virtual double GetDefaultScaleInternal() override; 282 virtual int32_t RoundsWidgetCoordinatesTo() override; 283 GetDesktopToDeviceScale()284 mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() final { 285 return mozilla::DesktopToLayoutDeviceScale(BackingScaleFactor()); 286 } 287 288 virtual nsresult SetTitle(const nsAString& aTitle) override; 289 290 virtual void Invalidate(const LayoutDeviceIntRect& aRect) override; 291 virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations) override; 292 virtual LayerManager* GetLayerManager( 293 PLayerTransactionChild* aShadowManager = nullptr, 294 LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE, 295 LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT) override; 296 virtual nsresult DispatchEvent(mozilla::WidgetGUIEvent* aEvent, nsEventStatus& aStatus) override; 297 virtual void CaptureRollupEvents(nsIRollupListener* aListener, bool aDoCapture) override; 298 [[nodiscard]] virtual nsresult GetAttention(int32_t aCycleCount) override; 299 virtual bool HasPendingInputEvent() override; 300 virtual nsTransparencyMode GetTransparencyMode() override; 301 virtual void SetTransparencyMode(nsTransparencyMode aMode) override; 302 virtual void SetWindowShadowStyle(mozilla::StyleWindowShadow aStyle) override; 303 virtual void SetWindowOpacity(float aOpacity) override; 304 virtual void SetWindowTransform(const mozilla::gfx::Matrix& aTransform) override; 305 virtual void SetWindowMouseTransparent(bool aIsTransparent) override; 306 virtual void SetShowsToolbarButton(bool aShow) override; 307 virtual void SetSupportsNativeFullscreen(bool aShow) override; 308 virtual void SetWindowAnimationType(WindowAnimationType aType) override; 309 virtual void SetDrawsTitle(bool aDrawTitle) override; 310 virtual void SetUseBrightTitlebarForeground(bool aBrightForeground) override; 311 virtual nsresult SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override; 312 virtual void SetDrawsInTitlebar(bool aState) override; 313 virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) override; 314 virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage, 315 uint32_t aModifierFlags, 316 nsIObserver* aObserver) override; 317 virtual void LockAspectRatio(bool aShouldLock) override; 318 319 void DispatchSizeModeEvent(); 320 void DispatchOcclusionEvent(); 321 322 // be notified that a some form of drag event needs to go into Gecko 323 virtual bool DragEvent(unsigned int aMessage, mozilla::gfx::Point aMouseGlobal, 324 UInt16 aKeyModifiers); 325 HasModalDescendents()326 bool HasModalDescendents() { return mNumModalDescendents > 0; } GetCocoaWindow()327 NSWindow* GetCocoaWindow() { return mWindow; } 328 329 void SetMenuBar(nsMenuBarX* aMenuBar); 330 nsMenuBarX* GetMenuBar(); 331 332 virtual void SetInputContext(const InputContext& aContext, 333 const InputContextAction& aAction) override; GetInputContext()334 virtual InputContext GetInputContext() override { return mInputContext; } 335 virtual bool GetEditCommands(NativeKeyBindingsType aType, 336 const mozilla::WidgetKeyboardEvent& aEvent, 337 nsTArray<mozilla::CommandInt>& aCommands) override; 338 339 void SetPopupWindowLevel(); 340 InFullScreenMode()341 bool InFullScreenMode() const { return mInFullScreenMode; } 342 343 protected: 344 virtual ~nsCocoaWindow(); 345 346 nsresult CreateNativeWindow(const NSRect& aRect, nsBorderStyle aBorderStyle, 347 bool aRectIsFrameRect); 348 nsresult CreatePopupContentView(const LayoutDeviceIntRect& aRect, nsWidgetInitData* aInitData); 349 void DestroyNativeWindow(); 350 void AdjustWindowShadow(); 351 void SetWindowBackgroundBlur(); 352 void UpdateBounds(); 353 int32_t GetWorkspaceID(); 354 355 void DoResize(double aX, double aY, double aWidth, double aHeight, bool aRepaint, 356 bool aConstrainToCurrentScreen); 357 358 inline bool ShouldToggleNativeFullscreen(bool aFullScreen, bool aUseSystemTransition); 359 void UpdateFullscreenState(bool aFullScreen, bool aNativeMode); 360 nsresult DoMakeFullScreen(bool aFullScreen, bool aUseSystemTransition); 361 AllocateChildPopupWidget()362 virtual already_AddRefed<nsIWidget> AllocateChildPopupWidget() override { 363 return nsIWidget::CreateTopLevelWindow(); 364 } 365 366 nsIWidget* mParent; // if we're a popup, this is our parent [WEAK] 367 nsIWidget* mAncestorLink; // link to traverse ancestors [WEAK] 368 BaseWindow* mWindow; // our cocoa window [STRONG] 369 WindowDelegate* mDelegate; // our delegate for processing window msgs [STRONG] 370 RefPtr<nsMenuBarX> mMenuBar; 371 NSWindow* mSheetWindowParent; // if this is a sheet, this is the NSWindow it's attached to 372 nsChildView* mPopupContentView; // if this is a popup, this is its content widget 373 // if this is a toplevel window, and there is any ongoing fullscreen 374 // transition, it is the animation object. 375 NSAnimation* mFullscreenTransitionAnimation; 376 mozilla::StyleWindowShadow mShadowStyle; 377 378 CGFloat mBackingScaleFactor; 379 CGFloat mAspectRatio; 380 381 WindowAnimationType mAnimationType; 382 383 bool mWindowMadeHere; // true if we created the window, false for embedding 384 bool mSheetNeedsShow; // if this is a sheet, are we waiting to be shown? 385 // this is used for sibling sheet contention only 386 bool mInFullScreenMode; 387 bool mInFullScreenTransition; // true from the request to enter/exit fullscreen 388 // (MakeFullScreen() call) to EnteredFullScreen() 389 bool mModal; 390 bool mFakeModal; 391 392 // Whether we are currently using native fullscreen. It could be false because 393 // we are in the DOM fullscreen where we do not use the native fullscreen. 394 bool mInNativeFullScreenMode; 395 396 bool mIsAnimationSuppressed; 397 398 bool mInReportMoveEvent; // true if in a call to ReportMoveEvent(). 399 bool mInResize; // true if in a call to DoResize(). 400 bool mWindowTransformIsIdentity; 401 bool mAlwaysOnTop; 402 bool mAspectRatioLocked; 403 404 int32_t mNumModalDescendents; 405 InputContext mInputContext; 406 NSWindowAnimationBehavior mWindowAnimationBehavior; 407 408 private: 409 // true if Show() has been called. 410 bool mWasShown; 411 }; 412 413 #endif // nsCocoaWindow_h_ 414