Bug 1421088 - Simplify search field cell management and make the "is-within-toolbar" computation eager instead of lazy. r?spohl draft
authorMarkus Stange <mstange@themasta.com>
Fri, 13 Apr 2018 18:19:32 -0400
changeset 782218 85dc8a3e1f3a92755039b31a68019ad6e1b3a077
parent 781042 ee1d1bf1dc8a83eec16967ddb61dd5024c8d6058
child 782219 e6d041191beeda2788b0e26ad4b6aab6a5c31999
push id106503
push userbmo:mstange@themasta.com
push dateSun, 15 Apr 2018 02:35:01 +0000
reviewersspohl
bugs1421088
milestone61.0a1
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";