Bug 871590 - Make unified titlebar / toolbar handling more robust. r=roc
authorMarkus Stange <mstange@themasta.com>
Wed, 22 May 2013 11:50:57 +0200
changeset 144119 6bd49cfa6711d71e47a4fe0153ae501ee4b71e25
parent 144118 331851701133d09eaae7bfcccd6ddb4f390ea844
child 144120 ba68dd582bc1e874bc54d075bc021516bdf05071
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs871590
milestone24.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
Bug 871590 - Make unified titlebar / toolbar handling more robust. r=roc
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
widget/cocoa/nsChildView.mm
widget/cocoa/nsCocoaWindow.h
widget/cocoa/nsCocoaWindow.mm
widget/cocoa/nsNativeThemeCocoa.h
widget/cocoa/nsNativeThemeCocoa.mm
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -1562,17 +1562,18 @@ nsDisplayBackgroundImage::nsDisplayBackg
 {
   MOZ_COUNT_CTOR(nsDisplayBackgroundImage);
 
   if (mIsThemed) {
     const nsStyleDisplay* disp = mFrame->StyleDisplay();
     mFrame->IsThemed(disp, &mThemeTransparency);
     // Perform necessary RegisterThemeGeometry
     if (disp->mAppearance == NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR ||
-        disp->mAppearance == NS_THEME_TOOLBAR) {
+        disp->mAppearance == NS_THEME_TOOLBAR ||
+        disp->mAppearance == NS_THEME_WINDOW_TITLEBAR) {
       RegisterThemeGeometry(aBuilder, aFrame);
     } else if (disp->mAppearance == NS_THEME_WIN_BORDERLESS_GLASS ||
                disp->mAppearance == NS_THEME_WIN_GLASS) {
       aBuilder->SetGlassDisplayItem(this);
     }
   } else if (mBackgroundStyle) {
     // Set HasFixedItems if we construct a background-attachment:fixed item
     if (mLayer != mBackgroundStyle->mImageCount - 1) {
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -449,21 +449,21 @@ public:
       (aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) ||
       GetIncludeAllOutOfFlows();
   }
 
   /**
    * Notifies the builder that a particular themed widget exists
    * at the given rectangle within the currently built display list.
    * For certain appearance values (currently only
-   * NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR and NS_THEME_TOOLBAR) this gets
-   * called during every display list construction, for every themed widget of
-   * the right type within the display list, except for themed widgets which
-   * are transformed or have effects applied to them (e.g. CSS opacity or
-   * filters).
+   * NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR, NS_THEME_TOOLBAR and
+   * NS_THEME_WINDOW_TITLEBAR) this gets called during every display list
+   * construction, for every themed widget of the right type within the
+   * display list, except for themed widgets which are transformed or have
+   * effects applied to them (e.g. CSS opacity or filters).
    *
    * @param aWidgetType the -moz-appearance value for the themed widget
    * @param aRect the device-pixel rect relative to the widget's displayRoot
    * for the themed widget
    */
   void RegisterThemeGeometry(uint8_t aWidgetType,
                              const nsIntRect& aRect) {
     if (mIsPaintingToWindow && mPresShellStates.Length() == 1) {
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -2067,42 +2067,68 @@ nsChildView::MaybeDrawRoundedBottomCorne
                              gfx3DMatrix::Translation(aRect.width, aRect.height, 0));
   aManager->BindAndDrawQuad(program);
   
   // Reset blend mode.
   aManager->gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
                                      LOCAL_GL_ONE, LOCAL_GL_ONE);
 }
 
+static int32_t
+FindTitlebarBottom(const nsTArray<nsIWidget::ThemeGeometry>& aThemeGeometries,
+                   int32_t aWindowWidth)
+{
+  int32_t titlebarBottom = 0;
+  for (uint32_t i = 0; i < aThemeGeometries.Length(); ++i) {
+    const nsIWidget::ThemeGeometry& g = aThemeGeometries[i];
+    if ((g.mWidgetType == NS_THEME_WINDOW_TITLEBAR) &&
+        g.mRect.X() <= 0 &&
+        g.mRect.XMost() >= aWindowWidth &&
+        g.mRect.Y() <= 0) {
+      titlebarBottom = std::max(titlebarBottom, g.mRect.YMost());
+    }
+  }
+  return titlebarBottom;
+}
+
+static int32_t
+FindUnifiedToolbarBottom(const nsTArray<nsIWidget::ThemeGeometry>& aThemeGeometries,
+                         int32_t aWindowWidth, int32_t aTitlebarBottom)
+{
+  int32_t unifiedToolbarBottom = aTitlebarBottom;
+  for (uint32_t i = 0; i < aThemeGeometries.Length(); ++i) {
+    const nsIWidget::ThemeGeometry& g = aThemeGeometries[i];
+    if ((g.mWidgetType == NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR ||
+         g.mWidgetType == NS_THEME_TOOLBAR) &&
+        g.mRect.X() <= 0 &&
+        g.mRect.XMost() >= aWindowWidth &&
+        g.mRect.Y() <= aTitlebarBottom) {
+      unifiedToolbarBottom = std::max(unifiedToolbarBottom, g.mRect.YMost());
+    }
+  }
+  return unifiedToolbarBottom;
+}
+
 void
 nsChildView::UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries)
 {
   if (![mView window] || ![[mView window] isKindOfClass:[ToolbarWindow class]])
     return;
 
+  int32_t windowWidth = mBounds.width;
+  int32_t titlebarBottom = FindTitlebarBottom(aThemeGeometries, windowWidth);
+  int32_t unifiedToolbarBottom =
+    FindUnifiedToolbarBottom(aThemeGeometries, windowWidth, titlebarBottom);
+
   ToolbarWindow* win = (ToolbarWindow*)[mView window];
   bool drawsContentsIntoWindowFrame = [win drawsContentsIntoWindowFrame];
-  int32_t windowWidth = mBounds.width;
   int32_t titlebarHeight = CocoaPointsToDevPixels([win titlebarHeight]);
-  int32_t underTitlebarPos = drawsContentsIntoWindowFrame ? titlebarHeight : 0;
-  int32_t unifiedToolbarBottom = 0;
-
-  for (uint32_t i = 0; i < aThemeGeometries.Length(); ++i) {
-    const ThemeGeometry& g = aThemeGeometries[i];
-    if ((g.mWidgetType == NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR ||
-         g.mWidgetType == NS_THEME_TOOLBAR) &&
-        g.mRect.X() <= 0 &&
-        g.mRect.XMost() >= windowWidth &&
-        g.mRect.Y() <= underTitlebarPos) {
-      unifiedToolbarBottom = g.mRect.YMost();
-    }
-  }
-
-  CGFloat unifiedHeight = DevPixelsToCocoaPoints(titlebarHeight + unifiedToolbarBottom - underTitlebarPos);
-  [win setUnifiedToolbarHeight:unifiedHeight];
+  int32_t contentOffset = drawsContentsIntoWindowFrame ? titlebarHeight : 0;
+  int32_t devUnifiedHeight = titlebarHeight + unifiedToolbarBottom - contentOffset;
+  [win setUnifiedToolbarHeight:DevPixelsToCocoaPoints(devUnifiedHeight)];
 }
 
 NS_IMETHODIMP
 nsChildView::BeginSecureKeyboardInput()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   nsresult rv = nsBaseWidget::BeginSecureKeyboardInput();
--- a/widget/cocoa/nsCocoaWindow.h
+++ b/widget/cocoa/nsCocoaWindow.h
@@ -174,25 +174,25 @@ typedef struct _nsCocoaWindowList {
 - (id)initWithWindow:(ToolbarWindow*)aWindow;
 
 @end
 
 // NSWindow subclass for handling windows with toolbars.
 @interface ToolbarWindow : BaseWindow
 {
   TitlebarAndBackgroundColor *mColor;
-  float mUnifiedToolbarHeight;
+  CGFloat mUnifiedToolbarHeight;
   NSColor *mBackgroundColor;
   NSView *mTitlebarView; // strong
 }
 // Pass nil here to get the default appearance.
 - (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive;
-- (void)setUnifiedToolbarHeight:(float)aHeight;
-- (float)unifiedToolbarHeight;
-- (float)titlebarHeight;
+- (void)setUnifiedToolbarHeight:(CGFloat)aHeight;
+- (CGFloat)unifiedToolbarHeight;
+- (CGFloat)titlebarHeight;
 - (NSRect)titlebarRect;
 - (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect sync:(BOOL)aSync;
 - (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect;
 - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState;
 @end
 
 class nsCocoaWindow : public nsBaseWidget, public nsPIWidgetCocoa
 {
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -2942,29 +2942,29 @@ static const NSString* kStateShowsToolba
 
 - (NSRect)titlebarRect
 {
   return NSMakeRect(0, [[self contentView] bounds].size.height,
                     [self frame].size.width, [self titlebarHeight]);
 }
 
 // Returns the unified height of titlebar + toolbar.
-- (float)unifiedToolbarHeight
+- (CGFloat)unifiedToolbarHeight
 {
   return mUnifiedToolbarHeight;
 }
 
-- (float)titlebarHeight
+- (CGFloat)titlebarHeight
 {
   NSRect frameRect = [self frame];
   return frameRect.size.height - [self contentRectForFrameRect:frameRect].size.height;
 }
 
 // Stores the complete height of titlebar + toolbar.
-- (void)setUnifiedToolbarHeight:(float)aHeight
+- (void)setUnifiedToolbarHeight:(CGFloat)aHeight
 {
   if (aHeight == mUnifiedToolbarHeight)
     return;
 
   mUnifiedToolbarHeight = aHeight;
 
   // Update sheet positioning hint.
   [self setContentBorderThickness:mUnifiedToolbarHeight - [self titlebarHeight] forEdge:NSMaxYEdge];
@@ -3149,28 +3149,28 @@ static const NSString* kStateShowsToolba
   if ((self = [super init])) {
     mWindow = aWindow; // weak ref to avoid a cycle
   }
   return self;
 }
 
 static void
 DrawNativeTitlebar(CGContextRef aContext, CGRect aTitlebarRect,
-                   float aUnifiedToolbarHeight, BOOL aIsMain)
+                   CGFloat aUnifiedToolbarHeight, BOOL aIsMain)
 {
   if (aTitlebarRect.size.width * aTitlebarRect.size.height > CUIDRAW_MAX_AREA) {
     return;
   }
 
   CUIDraw([NSWindow coreUIRenderer], aTitlebarRect, aContext,
           (CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
             @"kCUIWidgetWindowFrame", @"widget",
             @"regularwin", @"windowtype",
             (aIsMain ? @"normal" : @"inactive"), @"state",
-            [NSNumber numberWithInt:aUnifiedToolbarHeight], @"kCUIWindowFrameUnifiedTitleBarHeightKey",
+            [NSNumber numberWithDouble:aUnifiedToolbarHeight], @"kCUIWindowFrameUnifiedTitleBarHeightKey",
             [NSNumber numberWithBool:YES], @"kCUIWindowFrameDrawTitleSeparatorKey",
             nil],
           nil);
 
   if (nsCocoaFeatures::OnLionOrLater()) {
     // On Lion the call to CUIDraw doesn't draw the top pixel strip at some
     // window widths. We don't want to have a flickering transparent line, so
     // we overdraw it.
--- a/widget/cocoa/nsNativeThemeCocoa.h
+++ b/widget/cocoa/nsNativeThemeCocoa.h
@@ -104,17 +104,17 @@ protected:
                        const HIRect& inBoxRect, ThemeDrawState inDrawState,
                        ThemeButtonAdornment inAdornment, nsEventStates inState,
                        nsIFrame* aFrame);
   void DrawUnifiedToolbar(CGContextRef cgContext, const HIRect& inBoxRect,
                           NSWindow* aWindow);
   void DrawStatusBar(CGContextRef cgContext, const HIRect& inBoxRect,
                      nsIFrame *aFrame);
   void DrawNativeTitlebar(CGContextRef aContext, CGRect aTitlebarRect,
-                          float aUnifiedHeight, BOOL aIsMain);
+                          CGFloat aUnifiedHeight, BOOL aIsMain);
   void DrawResizer(CGContextRef cgContext, const HIRect& aRect, nsIFrame *aFrame);
 
   // Scrollbars
   void DrawScrollbar(CGContextRef aCGContext, const HIRect& aBoxRect, nsIFrame *aFrame);
   void GetScrollbarPressStates (nsIFrame *aFrame, nsEventStates aButtonStates[]);
   void GetScrollbarDrawInfo (HIThemeTrackDrawInfo& aTdi, nsIFrame *aFrame, 
                              const CGSize& aSize, bool aShouldGetButtonStates);
   nsIFrame* GetParentScrollbarFrame(nsIFrame *aFrame);
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -1790,24 +1790,19 @@ nsNativeThemeCocoa::GetParentScrollbarFr
 static bool
 ToolbarCanBeUnified(CGContextRef cgContext, const HIRect& inBoxRect, NSWindow* aWindow)
 {
   if (![aWindow isKindOfClass:[ToolbarWindow class]])
     return false;
 
   ToolbarWindow* win = (ToolbarWindow*)aWindow;
   float unifiedToolbarHeight = [win unifiedToolbarHeight];
-  float titlebarHeight = [win titlebarHeight];
-  bool drawsContentsIntoWindowFrame = [win drawsContentsIntoWindowFrame];
-  float underTitlebarPos = drawsContentsIntoWindowFrame ? titlebarHeight : 0;
-
   return inBoxRect.origin.x == 0 &&
          inBoxRect.size.width >= [win frame].size.width &&
-         inBoxRect.origin.y <= underTitlebarPos &&
-         floor(inBoxRect.origin.y + inBoxRect.size.height) <= unifiedToolbarHeight;
+         CGRectGetMaxY(inBoxRect) <= unifiedToolbarHeight;
 }
 
 void
 nsNativeThemeCocoa::DrawUnifiedToolbar(CGContextRef cgContext, const HIRect& inBoxRect,
                                        NSWindow* aWindow)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
@@ -1871,17 +1866,17 @@ nsNativeThemeCocoa::DrawStatusBar(CGCont
 
   CGContextRestoreGState(cgContext);
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 void
 nsNativeThemeCocoa::DrawNativeTitlebar(CGContextRef aContext, CGRect aTitlebarRect,
-                                       float aUnifiedHeight, BOOL aIsMain)
+                                       CGFloat aUnifiedHeight, BOOL aIsMain)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   if (aTitlebarRect.size.width * aTitlebarRect.size.height > CUIDRAW_MAX_AREA) {
     return;
   }
 
   CGContextSaveGState(aContext);