Bug 1421088 - Simplify search field cell management and make the "is-within-toolbar" computation eager instead of lazy. r?spohl
MozReview-Commit-ID: GkMSvimeuaf
--- 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";