author | harry <htwyford@mozilla.com> |
Thu, 18 Mar 2021 20:20:39 +0000 | |
changeset 571858 | f4dfcad8b8817e955a3c781820474768492557f4 |
parent 571857 | 1f963fd58e0ae8062a8233f46ca9ce41819c2937 |
child 571859 | 8ec37432c5b12fa65a4bf68272461ba9591e1126 |
push id | 38300 |
push user | btara@mozilla.com |
push date | Fri, 19 Mar 2021 09:53:39 +0000 |
treeherder | mozilla-central@092ee6b0c9f2 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mac-reviewers, mstange |
bugs | 1699506 |
milestone | 88.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/base/nsGlobalWindowOuter.cpp +++ b/dom/base/nsGlobalWindowOuter.cpp @@ -11,16 +11,17 @@ #include <algorithm> #include "mozilla/MemoryReporting.h" // Local Includes #include "Navigator.h" #include "mozilla/Encoding.h" #include "nsContentSecurityManager.h" +#include "nsGlobalWindowOuter.h" #include "nsScreen.h" #include "nsHistory.h" #include "nsDOMNavigationTiming.h" #include "nsIDOMStorageManager.h" #include "nsISecureBrowserUI.h" #include "nsIWebProgressListener.h" #include "mozilla/AntiTrackingUtils.h" #include "mozilla/ContentBlocking.h" @@ -4711,16 +4712,49 @@ void nsGlobalWindowOuter::FinishFullscre if (nsRefreshDriver* rd = presShell->GetRefreshDriver()) { rd->Thaw(); } mChromeFields.mFullscreenPresShell = nullptr; } } } +/* virtual */ +void nsGlobalWindowOuter::MacFullscreenMenubarOverlapChanged( + mozilla::DesktopCoord aOverlapAmount) { + ErrorResult res; + RefPtr<Event> domEvent = + mDoc->CreateEvent(u"CustomEvent"_ns, CallerType::System, res); + if (res.Failed()) { + return; + } + + AutoJSAPI jsapi; + jsapi.Init(); + JSContext* cx = jsapi.cx(); + JSAutoRealm ar(cx, GetWrapperPreserveColor()); + + JS::Rooted<JS::Value> detailValue(cx); + if (!ToJSValue(cx, aOverlapAmount, &detailValue)) { + return; + } + + CustomEvent* customEvent = static_cast<CustomEvent*>(domEvent.get()); + customEvent->InitCustomEvent(cx, u"MacFullscreenMenubarRevealUpdate"_ns, + /* aCanBubble = */ true, + /* aCancelable = */ true, detailValue); + domEvent->SetTrusted(true); + domEvent->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true; + + nsCOMPtr<EventTarget> target = this; + domEvent->SetTarget(target); + + target->DispatchEvent(*domEvent, CallerType::System, IgnoreErrors()); +} + bool nsGlobalWindowOuter::Fullscreen() const { NS_ENSURE_TRUE(mDocShell, mFullscreen); // Get the fullscreen value of the root window, to always have the value // accurate, even when called from content. nsCOMPtr<nsIDocShellTreeItem> rootItem; mDocShell->GetInProcessRootTreeItem(getter_AddRefs(rootItem)); if (rootItem == mDocShell) {
--- a/dom/base/nsGlobalWindowOuter.h +++ b/dom/base/nsGlobalWindowOuter.h @@ -344,16 +344,18 @@ class nsGlobalWindowOuter final : public friend class FullscreenTransitionTask; // Outer windows only. nsresult SetFullscreenInternal(FullscreenReason aReason, bool aIsFullscreen) final; void FullscreenWillChange(bool aIsFullscreen) final; void FinishFullscreenChange(bool aIsFullscreen) final; void ForceFullScreenInWidget() final; + void MacFullscreenMenubarOverlapChanged( + mozilla::DesktopCoord aOverlapAmount) final; bool SetWidgetFullscreen(FullscreenReason aReason, bool aIsFullscreen, nsIWidget* aWidget, nsIScreen* aScreen); bool Fullscreen() const; // nsIInterfaceRequestor NS_DECL_NSIINTERFACEREQUESTOR mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> IndexedGetterOuter(
--- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -7,16 +7,17 @@ #ifndef nsPIDOMWindow_h__ #define nsPIDOMWindow_h__ #include "nsIDOMWindow.h" #include "mozIDOMWindow.h" #include "nsCOMPtr.h" #include "nsTArray.h" +#include "Units.h" #include "mozilla/dom/EventTarget.h" #include "mozilla/EventForwards.h" #include "mozilla/Maybe.h" #include "mozilla/TaskCategory.h" #include "js/TypeDecls.h" #include "nsRefPtrHashtable.h" #include "nsILoadInfo.h" @@ -928,16 +929,19 @@ class nsPIDOMWindowOuter : public mozIDO * finishes its change to or from fullscreen. * * @param aIsFullscreen indicates whether the widget is in fullscreen. */ virtual void FinishFullscreenChange(bool aIsFullscreen) = 0; virtual void ForceFullScreenInWidget() = 0; + virtual void MacFullscreenMenubarOverlapChanged( + mozilla::DesktopCoord aOverlapAmount) = 0; + // XXX: These focus methods all forward to the inner, could we change // consumers to call these on the inner directly? /* * Get and set the currently focused element within the document. If * aNeedsFocus is true, then set mNeedsFocus to true to indicate that a * document focus event is needed. *
--- a/widget/cocoa/nsCocoaWindow.h +++ b/widget/cocoa/nsCocoaWindow.h @@ -169,26 +169,39 @@ typedef struct _nsCocoaWindowList { - (bool)toplevelActiveState; - (void)sendToplevelActivateEvents; - (void)sendToplevelDeactivateEvents; @end @interface MOZTitlebarView : NSVisualEffectView @end +@interface FullscreenTitlebarTracker : NSTitlebarAccessoryViewController +- (FullscreenTitlebarTracker*)init; +@end + // NSWindow subclass for handling windows with toolbars. @interface ToolbarWindow : BaseWindow { // This window's titlebar view, if present. // Will be nil if the window has neither a titlebar nor a unified toolbar. // This view is a subview of the window's content view and gets created and // destroyed by updateTitlebarView. MOZTitlebarView* mTitlebarView; // [STRONG] + // mFullscreenTitlebarTracker attaches an invisible rectangle to the system + // title bar. This allows us to detect when the title bar is showing in + // fullscreen. + FullscreenTitlebarTracker* mFullscreenTitlebarTracker; CGFloat mUnifiedToolbarHeight; CGFloat mSheetAttachmentPosition; + CGFloat mMenuBarHeight; + /* Store the height of the titlebar when this window is initialized. The + titlebarHeight getter returns 0 when in fullscreen, which is not useful in + some cases. */ + CGFloat mInitialTitlebarHeight; NSRect mWindowButtonsRect; } - (void)setUnifiedToolbarHeight:(CGFloat)aHeight; - (CGFloat)unifiedToolbarHeight; - (CGFloat)titlebarHeight; - (NSRect)titlebarRect; - (void)setTitlebarNeedsDisplay; - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState;
--- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -3361,16 +3361,25 @@ static const NSString* kStateWantsTitleD } else if (nsCocoaUtils::ShouldMinimizeOnTitlebarDoubleClick()) { [[self window] performMiniaturize:nil]; } } } @end +@implementation FullscreenTitlebarTracker +- (FullscreenTitlebarTracker*)init { + [super init]; + self.view = [[[NSView alloc] initWithFrame:NSZeroRect] autorelease]; + self.hidden = YES; + return self; +} +@end + // This class allows us to exercise control over the window's title bar. It is // used for all windows with titlebars. // // ToolbarWindow supports two modes: // - drawsContentsIntoWindowFrame mode: In this mode, the Gecko ChildView is // sized to cover the entire window frame and manages titlebar drawing. // - separate titlebar mode, with support for unified toolbars: In this mode, // the Gecko ChildView does not extend into the titlebar. However, this @@ -3431,27 +3440,93 @@ static const NSString* kStateWantsTitleD if ((self = [super initWithContentRect:contentRect styleMask:aStyle backing:aBufferingType defer:aFlag])) { mTitlebarView = nil; mUnifiedToolbarHeight = 22.0f; mSheetAttachmentPosition = aChildViewRect.size.height; mWindowButtonsRect = NSZeroRect; + mInitialTitlebarHeight = [self titlebarHeight]; [self setTitlebarAppearsTransparent:YES]; [self updateTitlebarView]; + + mFullscreenTitlebarTracker = [[FullscreenTitlebarTracker alloc] init]; + // revealAmount is an undocumented property of + // NSTitlebarAccessoryViewController that updates whenever the menubar + // slides down in fullscreen mode. + [mFullscreenTitlebarTracker addObserver:self + forKeyPath:@"revealAmount" + options:NSKeyValueObservingOptionNew + context:nil]; + [(NSWindow*)self addTitlebarAccessoryViewController:mFullscreenTitlebarTracker]; } return self; NS_OBJC_END_TRY_BLOCK_RETURN(nil); } +- (void)observeValueForKeyPath:(NSString*)keyPath + ofObject:(id)object + change:(NSDictionary<NSKeyValueChangeKey, id>*)change + context:(void*)context { + if ([keyPath isEqualToString:@"revealAmount"]) { + NSNumber* revealAmount = (change[NSKeyValueChangeNewKey]); + [self updateTitlebarShownAmount:[revealAmount doubleValue]]; + } +} + +- (void)updateTitlebarShownAmount:(CGFloat)aShownAmount { + NSInteger styleMask = [self styleMask]; + if (!(styleMask & NSWindowStyleMaskFullScreen)) { + // We are not interested in the size of the titlebar unless we are in + // fullscreen. + return; + } + + // [NSApp mainMenu] menuBarHeight] returns one of two values: the full height + // if the menubar is shown or is in the process of being shown, and 0 + // otherwise. Since we are multiplying the menubar height by aShownAmount, we + // always want the full height. + if ([[NSApp mainMenu] menuBarHeight] > 0) { + mMenuBarHeight = [[NSApp mainMenu] menuBarHeight]; + } + + if ([[self delegate] isKindOfClass:[WindowDelegate class]]) { + WindowDelegate* windowDelegate = (WindowDelegate*)[self delegate]; + nsCocoaWindow* geckoWindow = [windowDelegate geckoWidget]; + if (!geckoWindow) { + return; + } + + nsIWidgetListener* listener = geckoWindow->GetWidgetListener(); + if (listener) { + // Use the titlebar height cached in our frame rather than + // [ToolbarWindow titlebarHeight]. titlebarHeight returns 0 when we're in + // fullscreen. + CGFloat shiftByPixels = (mInitialTitlebarHeight + mMenuBarHeight) * aShownAmount; + // Use mozilla::DesktopToLayoutDeviceScale rather than the + // DesktopToLayoutDeviceScale in nsCocoaWindow. The latter accounts for + // screen DPI. We don't want that because the revealAmount property + // already accounts for it, so we'd be compounding DPI scales > 1. + mozilla::DesktopCoord coord = + LayoutDeviceCoord(shiftByPixels) / mozilla::DesktopToLayoutDeviceScale(); + + listener->MacFullscreenMenubarOverlapChanged(coord); + } + } +} + - (void)dealloc { [mTitlebarView release]; + [mFullscreenTitlebarTracker removeObserver:self forKeyPath:@"revealAmount"]; + [mFullscreenTitlebarTracker removeFromParentViewController]; + [mFullscreenTitlebarTracker release]; + [super dealloc]; } - (NSArray<NSView*>*)contentViewContents { NSMutableArray<NSView*>* contents = [[[self contentView] subviews] mutableCopy]; if (mTitlebarView) { // Do not include the titlebar gradient view in the returned array. [contents removeObject:mTitlebarView];
--- a/widget/nsIWidgetListener.cpp +++ b/widget/nsIWidgetListener.cpp @@ -43,16 +43,19 @@ void nsIWidgetListener::DynamicToolbarMa } void nsIWidgetListener::DynamicToolbarOffsetChanged(ScreenIntCoord aOffset) {} #endif void nsIWidgetListener::FullscreenWillChange(bool aInFullscreen) {} void nsIWidgetListener::FullscreenChanged(bool aInFullscreen) {} +void nsIWidgetListener::MacFullscreenMenubarOverlapChanged( + mozilla::DesktopCoord aOverlapAmount) {} + bool nsIWidgetListener::ZLevelChanged(bool aImmediate, nsWindowZ* aPlacement, nsIWidget* aRequestBelow, nsIWidget** aActualBelow) { return false; } void nsIWidgetListener::OcclusionStateChanged(bool aIsFullyOccluded) {}
--- a/widget/nsIWidgetListener.h +++ b/widget/nsIWidgetListener.h @@ -107,16 +107,22 @@ class nsIWidgetListener { virtual void FullscreenWillChange(bool aInFullscreen); /** * Called when the window entered or left the fullscreen state. */ virtual void FullscreenChanged(bool aInFullscreen); /** + * Called when the macOS titlebar is shown while in fullscreen. + */ + virtual void MacFullscreenMenubarOverlapChanged( + mozilla::DesktopCoord aOverlapAmount); + + /** * Called when the occlusion state is changed. */ virtual void OcclusionStateChanged(bool aIsFullyOccluded); /** * Called when the window is activated and focused. */ virtual void WindowActivated();
--- a/xpfe/appshell/AppWindow.cpp +++ b/xpfe/appshell/AppWindow.cpp @@ -2906,16 +2906,25 @@ void AppWindow::FinishFullscreenChange(b mFullscreenChangeState = FullscreenChangeState::NotChanging; if (mDocShell) { if (nsCOMPtr<nsPIDOMWindowOuter> ourWindow = mDocShell->GetWindow()) { ourWindow->FinishFullscreenChange(aInFullscreen); } } } +void AppWindow::MacFullscreenMenubarOverlapChanged( + mozilla::DesktopCoord aOverlapAmount) { + if (mDocShell) { + if (nsCOMPtr<nsPIDOMWindowOuter> ourWindow = mDocShell->GetWindow()) { + ourWindow->MacFullscreenMenubarOverlapChanged(aOverlapAmount); + } + } +} + void AppWindow::OcclusionStateChanged(bool aIsFullyOccluded) { nsCOMPtr<nsPIDOMWindowOuter> ourWindow = mDocShell ? mDocShell->GetWindow() : nullptr; if (ourWindow) { // And always fire a user-defined occlusionstatechange event on the window ourWindow->DispatchCustomEvent(u"occlusionstatechange"_ns, ChromeOnlyDispatch::eYes); } @@ -3292,16 +3301,22 @@ void AppWindow::WidgetListenerDelegate:: holder->FullscreenWillChange(aInFullscreen); } void AppWindow::WidgetListenerDelegate::FullscreenChanged(bool aInFullscreen) { RefPtr<AppWindow> holder = mAppWindow; holder->FullscreenChanged(aInFullscreen); } +void AppWindow::WidgetListenerDelegate::MacFullscreenMenubarOverlapChanged( + DesktopCoord aOverlapAmount) { + RefPtr<AppWindow> holder = mAppWindow; + return holder->MacFullscreenMenubarOverlapChanged(aOverlapAmount); +} + void AppWindow::WidgetListenerDelegate::OcclusionStateChanged( bool aIsFullyOccluded) { RefPtr<AppWindow> holder = mAppWindow; holder->OcclusionStateChanged(aIsFullyOccluded); } void AppWindow::WidgetListenerDelegate::OSToolbarButtonPressed() { RefPtr<AppWindow> holder = mAppWindow;
--- a/xpfe/appshell/AppWindow.h +++ b/xpfe/appshell/AppWindow.h @@ -101,16 +101,19 @@ class AppWindow final : public nsIBaseWi virtual void SizeModeChanged(nsSizeMode sizeMode) override; MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void UIResolutionChanged() override; MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void FullscreenWillChange(bool aInFullscreen) override; MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void FullscreenChanged(bool aInFullscreen) override; MOZ_CAN_RUN_SCRIPT_BOUNDARY + virtual void MacFullscreenMenubarOverlapChanged( + mozilla::DesktopCoord aOverlapAmount) override; + MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void OcclusionStateChanged(bool aIsFullyOccluded) override; MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void OSToolbarButtonPressed() override; MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual bool ZLevelChanged(bool aImmediate, nsWindowZ* aPlacement, nsIWidget* aRequestBelow, nsIWidget** aActualBelow) override; MOZ_CAN_RUN_SCRIPT_BOUNDARY @@ -156,16 +159,18 @@ class AppWindow final : public nsIBaseWi bool WindowMoved(nsIWidget* aWidget, int32_t aX, int32_t aY); MOZ_CAN_RUN_SCRIPT bool WindowResized(nsIWidget* aWidget, int32_t aWidth, int32_t aHeight); MOZ_CAN_RUN_SCRIPT bool RequestWindowClose(nsIWidget* aWidget); MOZ_CAN_RUN_SCRIPT void SizeModeChanged(nsSizeMode aSizeMode); MOZ_CAN_RUN_SCRIPT void UIResolutionChanged(); MOZ_CAN_RUN_SCRIPT void FullscreenWillChange(bool aInFullscreen); MOZ_CAN_RUN_SCRIPT void FullscreenChanged(bool aInFullscreen); + MOZ_CAN_RUN_SCRIPT void MacFullscreenMenubarOverlapChanged( + mozilla::DesktopCoord aOverlapAmount); MOZ_CAN_RUN_SCRIPT void OcclusionStateChanged(bool aIsFullyOccluded); MOZ_CAN_RUN_SCRIPT void OSToolbarButtonPressed(); MOZ_CAN_RUN_SCRIPT bool ZLevelChanged(bool aImmediate, nsWindowZ* aPlacement, nsIWidget* aRequestBelow, nsIWidget** aActualBelow); MOZ_CAN_RUN_SCRIPT void WindowActivated(); MOZ_CAN_RUN_SCRIPT void WindowDeactivated();