DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (b9a9e0b6f0df)

VCS Links

Line Code
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
/* -*- Mode: C++; tab-width: 4; 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 nsCocoaWindow_h_
#define nsCocoaWindow_h_

#undef DARWIN

#import <Cocoa/Cocoa.h>

#include "mozilla/RefPtr.h"
#include "nsBaseWidget.h"
#include "nsPIWidgetCocoa.h"
#include "nsCocoaUtils.h"
#include "nsTouchBar.h"

class nsCocoaWindow;
class nsChildView;
class nsMenuBarX;
@class ChildView;

typedef struct _nsCocoaWindowList {
  _nsCocoaWindowList() : prev(nullptr), window(nullptr) {}
  struct _nsCocoaWindowList* prev;
  nsCocoaWindow* window;  // Weak
} nsCocoaWindowList;

// NSWindow subclass that is the base class for all of our own window classes.
// Among other things, this class handles the storage of those settings that
// need to be persisted across window destruction and reconstruction, i.e. when
// switching to and from fullscreen mode.
// We don't save shadow, transparency mode or background color because it's not
// worth the hassle - Gecko will reset them anyway as soon as the window is
// resized.
@interface BaseWindow : NSWindow {
  // Data Storage
  NSMutableDictionary* mState;
  BOOL mDrawsIntoWindowFrame;

  // Invalidation disabling
  BOOL mDisabledNeedsDisplay;

  NSTrackingArea* mTrackingArea;

  NSRect mDirtyRect;

  BOOL mBeingShown;
  BOOL mDrawTitle;
  BOOL mBrightTitlebarForeground;
  BOOL mUseMenuStyle;

  nsTouchBar* mTouchBar;
}

- (void)importState:(NSDictionary*)aState;
- (NSMutableDictionary*)exportState;
- (void)setDrawsContentsIntoWindowFrame:(BOOL)aState;
- (BOOL)drawsContentsIntoWindowFrame;

// These two methods are like contentRectForFrameRect and frameRectForContentRect,
// but they deal with the rect of the window's "main ChildView" instead of the
// rect of the window's content view. The two are sometimes sized differently: The
// window's content view always covers the entire window, whereas the ChildView
// only covers the full window when drawsContentsIntoWindowFrame is YES. When
// drawsContentsIntoWindowFrame is NO, there's a titlebar-sized gap above the
// ChildView within the content view.
- (NSRect)childViewRectForFrameRect:(NSRect)aFrameRect;
- (NSRect)frameRectForChildViewRect:(NSRect)aChildViewRect;

- (void)mouseEntered:(NSEvent*)aEvent;
- (void)mouseExited:(NSEvent*)aEvent;
- (void)mouseMoved:(NSEvent*)aEvent;
- (void)updateTrackingArea;
- (NSView*)trackingAreaView;

- (void)setBeingShown:(BOOL)aValue;
- (BOOL)isBeingShown;
- (BOOL)isVisibleOrBeingShown;

// Returns an autoreleased NSArray containing the NSViews that we consider the
// "contents" of this window. All views in the returned array are subviews of
// this window's content view. However, the array may not include all of the
// content view's subviews; concretely, the ToolbarWindow implementation will
// exclude its TitlebarGradientView from the array that is returned here.
// In the vast majority of cases, the array will only have a single element:
// this window's mainChildView.
- (NSArray<NSView*>*)contentViewContents;

- (ChildView*)mainChildView;

- (NSArray*)titlebarControls;

- (void)setWantsTitleDrawn:(BOOL)aDrawTitle;
- (BOOL)wantsTitleDrawn;

- (void)setUseBrightTitlebarForeground:(BOOL)aBrightForeground;
- (BOOL)useBrightTitlebarForeground;

- (void)disableSetNeedsDisplay;
- (void)enableSetNeedsDisplay;

- (NSRect)getAndResetNativeDirtyRect;

- (void)setUseMenuStyle:(BOOL)aValue;

- (void)releaseJSObjects;

@end

@interface NSWindow (Undocumented)

// If a window has been explicitly removed from the "window cache" (to
// deactivate it), it's sometimes necessary to "reset" it to reactivate it
// (and put it back in the "window cache").  One way to do this, which Apple
// often uses, is to set the "window number" to '-1' and then back to its
// original value.
- (void)_setWindowNumber:(NSInteger)aNumber;

- (BOOL)bottomCornerRounded;

// Present in the same form on OS X since at least OS X 10.5.
- (NSRect)contentRectForFrameRect:(NSRect)windowFrame styleMask:(NSUInteger)windowStyle;
- (NSRect)frameRectForContentRect:(NSRect)windowContentRect styleMask:(NSUInteger)windowStyle;

// Present since at least OS X 10.5.  The OS calls this method on NSWindow
// (and its subclasses) to find out which NSFrameView subclass to instantiate
// to create its "frame view".
+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask;

@end

@interface PopupWindow : BaseWindow {
 @private
  BOOL mIsContextMenu;
}

- (id)initWithContentRect:(NSRect)contentRect
                styleMask:(NSUInteger)styleMask
                  backing:(NSBackingStoreType)bufferingType
                    defer:(BOOL)deferCreation;
- (BOOL)isContextMenu;
- (void)setIsContextMenu:(BOOL)flag;
- (BOOL)canBecomeMainWindow;

@end

@interface BorderlessWindow : BaseWindow {
}

- (BOOL)canBecomeKeyWindow;
- (BOOL)canBecomeMainWindow;

@end

@interface WindowDelegate : NSObject <NSWindowDelegate> {
  nsCocoaWindow* mGeckoWindow;  // [WEAK] (we are owned by the window)
  // Used to avoid duplication when we send NS_ACTIVATE and
  // NS_DEACTIVATE to Gecko for toplevel widgets.  Starts out
  // false.
  bool mToplevelActiveState;
  BOOL mHasEverBeenZoomed;
}
+ (void)paintMenubarForWindow:(NSWindow*)aWindow;
- (id)initWithGeckoWindow:(nsCocoaWindow*)geckoWind;
- (void)windowDidResize:(NSNotification*)aNotification;
- (nsCocoaWindow*)geckoWidget;
- (bool)toplevelActiveState;
- (void)sendToplevelActivateEvents;
- (void)sendToplevelDeactivateEvents;
@end

@interface TitlebarGradientView : NSView
@end

// NSWindow subclass for handling windows with toolbars.
@interface ToolbarWindow : BaseWindow {
  // This window's titlebar gradient view, if present.
  // Will be nil if drawsContentsIntoWindowFrame is YES.
  // This view is a subview of the window's content view and gets created and
  // destroyed by updateTitlebarGradientViewPresence.
  TitlebarGradientView* mTitlebarGradientView;  // [STRONG]

  CGFloat mUnifiedToolbarHeight;
  CGFloat mSheetAttachmentPosition;
  NSRect mWindowButtonsRect;
  NSRect mFullScreenButtonRect;
}
- (void)setUnifiedToolbarHeight:(CGFloat)aHeight;
- (CGFloat)unifiedToolbarHeight;
- (CGFloat)titlebarHeight;
- (NSRect)titlebarRect;
- (void)setTitlebarNeedsDisplay;
- (void)setDrawsContentsIntoWindowFrame:(BOOL)aState;
- (void)setSheetAttachmentPosition:(CGFloat)aY;
- (CGFloat)sheetAttachmentPosition;
- (void)placeWindowButtons:(NSRect)aRect;
- (void)placeFullScreenButton:(NSRect)aRect;
- (NSPoint)windowButtonsPositionWithDefaultPosition:(NSPoint)aDefaultPosition;
- (NSPoint)fullScreenButtonPositionWithDefaultPosition:(NSPoint)aDefaultPosition;
- (void)windowMainStateChanged;
@end

class nsCocoaWindow final : public nsBaseWidget, public nsPIWidgetCocoa {
 private:
  typedef nsBaseWidget Inherited;

 public:
  nsCocoaWindow();

  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_NSPIWIDGETCOCOA

  virtual MOZ_MUST_USE nsresult Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
                                       const DesktopIntRect& aRect,
                                       nsWidgetInitData* aInitData = nullptr) override;

  virtual MOZ_MUST_USE nsresult Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
                                       const LayoutDeviceIntRect& aRect,
                                       nsWidgetInitData* aInitData = nullptr) override;

  virtual void Destroy() override;

  virtual void Show(bool aState) override;
  virtual nsIWidget* GetSheetWindowParent(void) override;
  virtual void Enable(bool aState) override;
  virtual bool IsEnabled() const override;
  virtual void SetModal(bool aState) override;
  virtual void SetFakeModal(bool aState) override;
  virtual bool IsRunningAppModal() override;
  virtual bool IsVisible() const override;
  virtual nsresult SetFocus(bool aState = false) override;
  virtual LayoutDeviceIntPoint WidgetToScreenOffset() override;
  virtual LayoutDeviceIntPoint GetClientOffset() override;
  virtual LayoutDeviceIntSize ClientToWindowSize(const LayoutDeviceIntSize& aClientSize) override;

  virtual void* GetNativeData(uint32_t aDataType) override;

  virtual void ConstrainPosition(bool aAllowSlop, int32_t* aX, int32_t* aY) override;
  virtual void SetSizeConstraints(const SizeConstraints& aConstraints) override;
  virtual void Move(double aX, double aY) override;
  virtual void SetSizeMode(nsSizeMode aMode) override;
  virtual void SuppressAnimation(bool aSuppress) override;
  virtual void HideWindowChrome(bool aShouldHide) override;

  void WillEnterFullScreen(bool aFullScreen);
  void EnteredFullScreen(bool aFullScreen, bool aNativeMode = true);
  virtual bool PrepareForFullscreenTransition(nsISupports** aData) override;
  virtual void PerformFullscreenTransition(FullscreenTransitionStage aStage, uint16_t aDuration,
                                           nsISupports* aData, nsIRunnable* aCallback) override;
  nsresult MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen = nullptr) final;
  nsresult MakeFullScreenWithNativeTransition(bool aFullScreen,
                                              nsIScreen* aTargetScreen = nullptr) final;
  NSAnimation* FullscreenTransitionAnimation() const { return mFullscreenTransitionAnimation; }
  void ReleaseFullscreenTransitionAnimation() {
    MOZ_ASSERT(mFullscreenTransitionAnimation, "Should only be called when there is animation");
    [mFullscreenTransitionAnimation release];
    mFullscreenTransitionAnimation = nil;
  }

  virtual void Resize(double aWidth, double aHeight, bool aRepaint) override;
  virtual void Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint) override;
  NSRect GetClientCocoaRect();
  virtual LayoutDeviceIntRect GetClientBounds() override;
  virtual LayoutDeviceIntRect GetScreenBounds() override;
  void ReportMoveEvent();
  void ReportSizeEvent();
  virtual void SetCursor(nsCursor aDefaultCursor, imgIContainer* aCursorImage, uint32_t aHotspotX,
                         uint32_t aHotspotY) override;

  CGFloat BackingScaleFactor();
  void BackingScaleFactorChanged();
  virtual double GetDefaultScaleInternal() override;
  virtual int32_t RoundsWidgetCoordinatesTo() override;

  mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() final {
    return mozilla::DesktopToLayoutDeviceScale(BackingScaleFactor());
  }

  virtual nsresult SetTitle(const nsAString& aTitle) override;

  virtual void Invalidate(const LayoutDeviceIntRect& aRect) override;
  virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations) override;
  virtual LayerManager* GetLayerManager(
      PLayerTransactionChild* aShadowManager = nullptr,
      LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE,
      LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT) override;
  virtual nsresult DispatchEvent(mozilla::WidgetGUIEvent* aEvent, nsEventStatus& aStatus) override;
  virtual void CaptureRollupEvents(nsIRollupListener* aListener, bool aDoCapture) override;
  virtual MOZ_MUST_USE nsresult GetAttention(int32_t aCycleCount) override;
  virtual bool HasPendingInputEvent() override;
  virtual nsTransparencyMode GetTransparencyMode() override;
  virtual void SetTransparencyMode(nsTransparencyMode aMode) override;
  virtual void SetWindowShadowStyle(int32_t aStyle) override;
  virtual void SetWindowOpacity(float aOpacity) override;
  virtual void SetWindowTransform(const mozilla::gfx::Matrix& aTransform) override;
  virtual void SetShowsToolbarButton(bool aShow) override;
  virtual void SetShowsFullScreenButton(bool aShow) override;
  virtual void SetWindowAnimationType(WindowAnimationType aType) override;
  virtual void SetDrawsTitle(bool aDrawTitle) override;
  virtual void SetUseBrightTitlebarForeground(bool aBrightForeground) override;
  virtual nsresult SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override;
  virtual void SetDrawsInTitlebar(bool aState) override;
  virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) override;
  virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage,
                                              uint32_t aModifierFlags,
                                              nsIObserver* aObserver) override;

  void DispatchSizeModeEvent();
  void DispatchOcclusionEvent();

  // be notified that a some form of drag event needs to go into Gecko
  virtual bool DragEvent(unsigned int aMessage, mozilla::gfx::Point aMouseGlobal,
                         UInt16 aKeyModifiers);

  bool HasModalDescendents() { return mNumModalDescendents > 0; }
  NSWindow* GetCocoaWindow() { return mWindow; }

  void SetMenuBar(nsMenuBarX* aMenuBar);
  nsMenuBarX* GetMenuBar();

  virtual void SetInputContext(const InputContext& aContext,
                               const InputContextAction& aAction) override;
  virtual InputContext GetInputContext() override { return mInputContext; }
  virtual void GetEditCommands(NativeKeyBindingsType aType,
                               const mozilla::WidgetKeyboardEvent& aEvent,
                               nsTArray<mozilla::CommandInt>& aCommands) override;

  void SetPopupWindowLevel();

  bool InFullScreenMode() const { return mInFullScreenMode; }

 protected:
  virtual ~nsCocoaWindow();

  nsresult CreateNativeWindow(const NSRect& aRect, nsBorderStyle aBorderStyle,
                              bool aRectIsFrameRect);
  nsresult CreatePopupContentView(const LayoutDeviceIntRect& aRect, nsWidgetInitData* aInitData);
  void DestroyNativeWindow();
  void AdjustWindowShadow();
  void SetWindowBackgroundBlur();
  void UpdateBounds();

  void DoResize(double aX, double aY, double aWidth, double aHeight, bool aRepaint,
                bool aConstrainToCurrentScreen);

  inline bool ShouldToggleNativeFullscreen(bool aFullScreen, bool aUseSystemTransition);
  nsresult DoMakeFullScreen(bool aFullScreen, bool aUseSystemTransition);

  virtual already_AddRefed<nsIWidget> AllocateChildPopupWidget() override {
    return nsIWidget::CreateTopLevelWindow();
  }

  nsIWidget* mParent;         // if we're a popup, this is our parent [WEAK]
  nsIWidget* mAncestorLink;   // link to traverse ancestors [WEAK]
  BaseWindow* mWindow;        // our cocoa window [STRONG]
  WindowDelegate* mDelegate;  // our delegate for processing window msgs [STRONG]
  RefPtr<nsMenuBarX> mMenuBar;
  NSWindow* mSheetWindowParent;    // if this is a sheet, this is the NSWindow it's attached to
  nsChildView* mPopupContentView;  // if this is a popup, this is its content widget
  // if this is a toplevel window, and there is any ongoing fullscreen
  // transition, it is the animation object.
  NSAnimation* mFullscreenTransitionAnimation;
  int32_t mShadowStyle;

  CGFloat mBackingScaleFactor;

  WindowAnimationType mAnimationType;

  bool mWindowMadeHere;  // true if we created the window, false for embedding
  bool mSheetNeedsShow;  // if this is a sheet, are we waiting to be shown?
                         // this is used for sibling sheet contention only
  bool mInFullScreenMode;
  bool mInFullScreenTransition;  // true from the request to enter/exit fullscreen
                                 // (MakeFullScreen() call) to EnteredFullScreen()
  bool mModal;
  bool mFakeModal;

  // Only true on 10.7+ if SetShowsFullScreenButton(true) is called.
  bool mSupportsNativeFullScreen;
  // Whether we are currently using native fullscreen. It could be false because
  // we are in the DOM fullscreen where we do not use the native fullscreen.
  bool mInNativeFullScreenMode;

  bool mIsAnimationSuppressed;

  bool mInReportMoveEvent;  // true if in a call to ReportMoveEvent().
  bool mInResize;           // true if in a call to DoResize().
  bool mWindowTransformIsIdentity;

  int32_t mNumModalDescendents;
  InputContext mInputContext;
  NSWindowAnimationBehavior mWindowAnimationBehavior;
};

#endif  // nsCocoaWindow_h_