Bug 1421088 - Simplify search field cell management and make the "is-within-toolbar" computation eager instead of lazy. r=spohl
authorMarkus Stange <mstange@themasta.com>
Fri, 13 Apr 2018 18:19:32 -0400
changeset 466930 3718eabad30ea80c67a183ae379b94ee8710764a
parent 466929 ed07fb947b5e6c14b93c00a6596b756b37d306c0
child 466931 03a6d5b78824286d1af0f847a1dbab4152cab892
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersspohl
bugs1421088
milestone61.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 1421088 - Simplify search field cell management and make the "is-within-toolbar" computation eager instead of lazy. r=spohl MozReview-Commit-ID: GkMSvimeuaf
widget/cocoa/nsNativeThemeCocoa.h
widget/cocoa/nsNativeThemeCocoa.mm
--- a/widget/cocoa/nsNativeThemeCocoa.h
+++ b/widget/cocoa/nsNativeThemeCocoa.h
@@ -11,17 +11,16 @@
 
 #include "nsITheme.h"
 #include "nsCOMPtr.h"
 #include "nsAtom.h"
 #include "nsNativeTheme.h"
 
 @class CellDrawView;
 @class NSProgressBarCell;
-@class ContextAwareSearchFieldCell;
 class nsDeviceContext;
 struct SegmentedControlRenderSettings;
 
 namespace mozilla {
 class EventStates;
 } // namespace mozilla
 
 class nsNativeThemeCocoa : private nsNativeTheme,
@@ -167,17 +166,18 @@ protected:
   bool IsParentScrollbarRolledOver(nsIFrame* aFrame);
 
 private:
   NSButtonCell* mDisclosureButtonCell;
   NSButtonCell* mHelpButtonCell;
   NSButtonCell* mPushButtonCell;
   NSButtonCell* mRadioButtonCell;
   NSButtonCell* mCheckboxCell;
-  ContextAwareSearchFieldCell* mSearchFieldCell;
+  NSSearchFieldCell* mSearchFieldCell;
+  NSSearchFieldCell* mToolbarSearchFieldCell;
   NSPopUpButtonCell* mDropdownCell;
   NSComboBoxCell* mComboBoxCell;
   NSProgressBarCell* mProgressBarCell;
   NSLevelIndicatorCell* mMeterBarCell;
   CellDrawView* mCellDrawView;
 };
 
 #endif // nsNativeThemeCocoa_h_
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -270,83 +270,22 @@ DrawCellIncludingFocusRing(NSCell* aCell
   tdi.trackInfo.progress.phase = uint8_t(PR_IntervalToMilliseconds(PR_IntervalNow()) /
                                          milliSecondsPerStep);
 
   HIThemeDrawTrack(&tdi, NULL, cgContext, kHIThemeOrientationNormal);
 }
 
 @end
 
-@interface ContextAwareSearchFieldCell : NSSearchFieldCell
-{
-  nsIFrame* mContext;
-}
-
-// setContext: stores the searchfield nsIFrame so that it can be consulted
-// during painting. Please reset this by calling setContext:nullptr as soon as
-// you're done with painting because we don't want to keep a dangling pointer.
-- (void)setContext:(nsIFrame*)aContext;
-@end
-
-@implementation ContextAwareSearchFieldCell
-
-- (id)initTextCell:(NSString*)aString
-{
-  if ((self = [super initTextCell:aString])) {
-    mContext = nullptr;
-  }
-  return self;
-}
-
-- (void)setContext:(nsIFrame*)aContext
-{
-  mContext = aContext;
-}
-
-static BOOL IsToolbarStyleContainer(nsIFrame* aFrame)
-{
-  nsIContent* content = aFrame->GetContent();
-  if (!content)
-    return NO;
-
-  if (content->IsAnyOfXULElements(nsGkAtoms::toolbar,
-                                  nsGkAtoms::toolbox,
-                                  nsGkAtoms::statusbar))
-    return YES;
-
-  switch (aFrame->StyleDisplay()->mAppearance) {
-    case NS_THEME_TOOLBAR:
-    case NS_THEME_STATUSBAR:
-      return YES;
-    default:
-      return NO;
-  }
-}
-
-- (BOOL)_isToolbarMode
-{
-  // On 10.7, searchfields have two different styles, depending on whether
-  // the searchfield is on top of of window chrome. This function is called on
-  // 10.7 during drawing in order to determine which style to use.
-  for (nsIFrame* frame = mContext; frame; frame = frame->GetParent()) {
-    if (IsToolbarStyleContainer(frame)) {
-      return YES;
-    }
-  }
-  return NO;
-}
-
-@end
+@interface SearchFieldCellWithFocusRing : NSSearchFieldCell {} @end
 
 // Workaround for Bug 542048
 // On 64-bit, NSSearchFieldCells don't draw focus rings.
 #if defined(__x86_64__)
 
-@interface SearchFieldCellWithFocusRing : ContextAwareSearchFieldCell {} @end
-
 @implementation SearchFieldCellWithFocusRing
 
 - (void)drawWithFrame:(NSRect)rect inView:(NSView*)controlView
 {
   [super drawWithFrame:rect inView:controlView];
 
   if (FocusIsDrawnByDrawWithFrame(self)) {
     // For some reason, -[NSSearchFieldCell drawWithFrame:inView] doesn't draw a
@@ -364,16 +303,31 @@ static BOOL IsToolbarStyleContainer(nsIF
   // focus ring.
   [super drawWithFrame:rect inView:controlView];
 }
 
 @end
 
 #endif
 
+@interface ToolbarSearchFieldCellWithFocusRing : SearchFieldCellWithFocusRing
+@end
+
+@implementation ToolbarSearchFieldCellWithFocusRing
+
+- (BOOL)_isToolbarMode
+{
+  // This function is called during -[NSSearchFieldCell drawWithFrame:inView:].
+  // Returning YES from it selects the style that's appropriate for search
+  // fields inside toolbars.
+  return YES;
+}
+
+@end
+
 #define HITHEME_ORIENTATION kHIThemeOrientationNormal
 
 static CGFloat kMaxFocusRingWidth = 0; // initialized by the nsNativeThemeCocoa constructor
 
 // These enums are for indexing into the margin array.
 enum {
   leopardOSorlater = 0, // 10.6 - 10.9
   yosemiteOSorlater = 1 // 10.10+
@@ -552,26 +506,28 @@ nsNativeThemeCocoa::nsNativeThemeCocoa()
 
   mRadioButtonCell = [[RadioButtonCell alloc] initTextCell:@""];
   [mRadioButtonCell setButtonType:NSRadioButton];
 
   mCheckboxCell = [[CheckboxCell alloc] initTextCell:@""];
   [mCheckboxCell setButtonType:NSSwitchButton];
   [mCheckboxCell setAllowsMixedState:YES];
 
-#if defined(__x86_64__)
   mSearchFieldCell = [[SearchFieldCellWithFocusRing alloc] initTextCell:@""];
-#else
-  mSearchFieldCell = [[ContextAwareSearchFieldCell alloc] initTextCell:@""];
-#endif
   [mSearchFieldCell setBezelStyle:NSTextFieldRoundedBezel];
   [mSearchFieldCell setBezeled:YES];
   [mSearchFieldCell setEditable:YES];
   [mSearchFieldCell setFocusRingType:NSFocusRingTypeExterior];
 
+  mToolbarSearchFieldCell = [[ToolbarSearchFieldCellWithFocusRing alloc] initTextCell:@""];
+  [mToolbarSearchFieldCell setBezelStyle:NSTextFieldRoundedBezel];
+  [mToolbarSearchFieldCell setBezeled:YES];
+  [mToolbarSearchFieldCell setEditable:YES];
+  [mToolbarSearchFieldCell setFocusRingType:NSFocusRingTypeExterior];
+
   mDropdownCell = [[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO];
 
   mComboBoxCell = [[NSComboBoxCell alloc] initTextCell:@""];
   [mComboBoxCell setBezeled:YES];
   [mComboBoxCell setEditable:YES];
   [mComboBoxCell setFocusRingType:NSFocusRingTypeExterior];
 
   mProgressBarCell = [[NSProgressBarCell alloc] init];
@@ -591,16 +547,17 @@ nsNativeThemeCocoa::~nsNativeThemeCocoa(
   [mMeterBarCell release];
   [mProgressBarCell release];
   [mDisclosureButtonCell release];
   [mHelpButtonCell release];
   [mPushButtonCell release];
   [mRadioButtonCell release];
   [mCheckboxCell release];
   [mSearchFieldCell release];
+  [mToolbarSearchFieldCell release];
   [mDropdownCell release];
   [mComboBoxCell release];
   [mCellDrawView release];
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 // Limit on the area of the target rect (in pixels^2) in
@@ -1084,38 +1041,69 @@ static const CellRenderSettings searchFi
     { // Yosemite
       {0, 0, 0, 0},     // mini
       {0, 0, 0, 0},     // small
       {0, 0, 0, 0}      // regular
     }
   }
 };
 
+static bool
+IsToolbarStyleContainer(nsIFrame* aFrame)
+{
+  nsIContent* content = aFrame->GetContent();
+  if (!content) {
+    return false;
+  }
+
+  if (content->IsAnyOfXULElements(nsGkAtoms::toolbar,
+                                  nsGkAtoms::toolbox,
+                                  nsGkAtoms::statusbar)) {
+    return true;
+  }
+
+  switch (aFrame->StyleDisplay()->mAppearance) {
+    case NS_THEME_TOOLBAR:
+    case NS_THEME_STATUSBAR:
+      return true;
+    default:
+      return false;
+  }
+}
+
+static bool
+IsInsideToolbar(nsIFrame* aFrame)
+{
+  for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent()) {
+    if (IsToolbarStyleContainer(frame)) {
+      return true;
+    }
+  }
+  return false;
+}
+
 void
 nsNativeThemeCocoa::DrawSearchField(CGContextRef cgContext, const HIRect& inBoxRect,
                                     nsIFrame* aFrame, EventStates inState)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
-  ContextAwareSearchFieldCell* cell = mSearchFieldCell;
-  [cell setContext:aFrame];
+  NSSearchFieldCell* cell =
+    IsInsideToolbar(aFrame) ? mToolbarSearchFieldCell : mSearchFieldCell;
   [cell setEnabled:!IsDisabled(aFrame, inState)];
-  // NOTE: this could probably use inState
   [cell setShowsFirstResponder:IsFocused(aFrame)];
 
   // When using the 10.11 SDK, the default string will be shown if we don't
   // set the placeholder string.
   [cell setPlaceholderString:@""];
 
   DrawCellWithSnapping(cell, cgContext, inBoxRect, searchFieldSettings,
                        VerticalAlignFactor(aFrame), mCellDrawView,
                        IsFrameRTL(aFrame));
 
-  [cell setContext:nullptr];
-
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 static const NSSize kCheckmarkSize = NSMakeSize(11, 11);
 static const NSSize kMenuarrowSize = NSMakeSize(9, 10);
 static const NSSize kMenuScrollArrowSize = NSMakeSize(10, 8);
 static NSString* kCheckmarkImage = @"MenuOnState";
 static NSString* kMenuarrowRightImage = @"MenuSubmenu";