Skip to content

Commit

Permalink
Bug 1077365 - Use NSTextFieldCell for drawing text fields. r=mac-revi…
Browse files Browse the repository at this point in the history
…ewers,bradwerth

Differential Revision: https://phabricator.services.mozilla.com/D107910
  • Loading branch information
mstange committed Mar 12, 2021
1 parent e22127a commit ef69315
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 83 deletions.
30 changes: 13 additions & 17 deletions widget/cocoa/nsNativeThemeCocoa.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,7 @@ class nsNativeThemeCocoa : private nsNativeTheme, public nsITheme {
bool isMain = false;
};

struct TextBoxParams {
bool disabled = false;
bool focused = false;
bool borderless = false;
};

struct SearchFieldParams {
struct TextFieldParams {
float verticalAlignFactor = 0.5f;
bool insideToolbar = false;
bool disabled = false;
Expand Down Expand Up @@ -201,8 +195,8 @@ class nsNativeThemeCocoa : private nsNativeTheme, public nsITheme {
eNativeTitlebar, // UnifiedToolbarParams
eStatusBar, // bool
eGroupBox,
eTextBox, // TextBoxParams
eSearchField, // SearchFieldParams
eTextField, // TextFieldParams
eSearchField, // TextFieldParams
eProgressBar, // ProgressParams
eMeter, // MeterParams
eTreeHeaderCell, // TreeHeaderCellParams
Expand Down Expand Up @@ -266,10 +260,10 @@ class nsNativeThemeCocoa : private nsNativeTheme, public nsITheme {
}
static WidgetInfo StatusBar(bool aParams) { return WidgetInfo(Widget::eStatusBar, aParams); }
static WidgetInfo GroupBox() { return WidgetInfo(Widget::eGroupBox, false); }
static WidgetInfo TextBox(const TextBoxParams& aParams) {
return WidgetInfo(Widget::eTextBox, aParams);
static WidgetInfo TextField(const TextFieldParams& aParams) {
return WidgetInfo(Widget::eTextField, aParams);
}
static WidgetInfo SearchField(const SearchFieldParams& aParams) {
static WidgetInfo SearchField(const TextFieldParams& aParams) {
return WidgetInfo(Widget::eSearchField, aParams);
}
static WidgetInfo ProgressBar(const ProgressParams& aParams) {
Expand Down Expand Up @@ -320,8 +314,8 @@ class nsNativeThemeCocoa : private nsNativeTheme, public nsITheme {

mozilla::Variant<mozilla::gfx::sRGBColor, MenuIconParams, MenuItemParams, CheckboxOrRadioParams,
ButtonParams, DropdownParams, SpinButtonParams, SegmentParams,
UnifiedToolbarParams, TextBoxParams, SearchFieldParams, ProgressParams,
MeterParams, TreeHeaderCellParams, ScaleParams, ScrollbarParams, bool>
UnifiedToolbarParams, TextFieldParams, ProgressParams, MeterParams,
TreeHeaderCellParams, ScaleParams, ScrollbarParams, bool>
mVariant;

enum Widget mWidget;
Expand Down Expand Up @@ -390,7 +384,7 @@ class nsNativeThemeCocoa : private nsNativeTheme, public nsITheme {
bool aIsChecked);
SegmentParams ComputeSegmentParams(nsIFrame* aFrame, mozilla::EventStates aEventState,
SegmentType aSegmentType);
SearchFieldParams ComputeSearchFieldParams(nsIFrame* aFrame, mozilla::EventStates aEventState);
TextFieldParams ComputeTextFieldParams(nsIFrame* aFrame, mozilla::EventStates aEventState);
ProgressParams ComputeProgressParams(nsIFrame* aFrame, mozilla::EventStates aEventState,
bool aIsHorizontal);
MeterParams ComputeMeterParams(nsIFrame* aFrame);
Expand All @@ -400,7 +394,6 @@ class nsNativeThemeCocoa : private nsNativeTheme, public nsITheme {
mozilla::EventStates aEventState);

// HITheme drawing routines
void DrawTextBox(CGContextRef context, const HIRect& inBoxRect, TextBoxParams aParams);
void DrawMeter(CGContextRef context, const HIRect& inBoxRect, const MeterParams& aParams);
void DrawSegment(CGContextRef cgContext, const HIRect& inBoxRect, const SegmentParams& aParams);
void DrawSegmentBackground(CGContextRef cgContext, const HIRect& inBoxRect,
Expand All @@ -410,7 +403,9 @@ class nsNativeThemeCocoa : private nsNativeTheme, public nsITheme {
void DrawCheckboxOrRadio(CGContextRef cgContext, bool inCheckbox, const HIRect& inBoxRect,
const CheckboxOrRadioParams& aParams);
void DrawSearchField(CGContextRef cgContext, const HIRect& inBoxRect,
const SearchFieldParams& aParams);
const TextFieldParams& aParams);
void DrawTextField(CGContextRef cgContext, const HIRect& inBoxRect,
const TextFieldParams& aParams);
void DrawRoundedBezelPushButton(CGContextRef cgContext, const HIRect& inBoxRect,
ControlParams aControlParams);
void DrawSquareBezelPushButton(CGContextRef cgContext, const HIRect& inBoxRect,
Expand Down Expand Up @@ -459,6 +454,7 @@ class nsNativeThemeCocoa : private nsNativeTheme, public nsITheme {
NSButtonCell* mPushButtonCell;
NSButtonCell* mRadioButtonCell;
NSButtonCell* mCheckboxCell;
NSTextFieldCell* mTextFieldCell;
NSSearchFieldCell* mSearchFieldCell;
NSSearchFieldCell* mToolbarSearchFieldCell;
NSPopUpButtonCell* mDropdownCell;
Expand Down
108 changes: 42 additions & 66 deletions widget/cocoa/nsNativeThemeCocoa.mm
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,11 @@ static bool IsInSourceList(nsIFrame* aFrame) {
[mCheckboxCell setButtonType:NSSwitchButton];
[mCheckboxCell setAllowsMixedState:YES];

mTextFieldCell = [[NSTextFieldCell alloc] initTextCell:@""];
[mTextFieldCell setBezeled:YES];
[mTextFieldCell setEditable:YES];
[mTextFieldCell setFocusRingType:NSFocusRingTypeExterior];

mSearchFieldCell = [[NSSearchFieldCell alloc] initTextCell:@""];
[mSearchFieldCell setBezelStyle:NSTextFieldRoundedBezel];
[mSearchFieldCell setBezeled:YES];
Expand Down Expand Up @@ -432,6 +437,7 @@ static bool IsInSourceList(nsIFrame* aFrame) {
[mPushButtonCell release];
[mRadioButtonCell release];
[mCheckboxCell release];
[mTextFieldCell release];
[mSearchFieldCell release];
[mToolbarSearchFieldCell release];
[mDropdownCell release];
Expand Down Expand Up @@ -932,19 +938,44 @@ static bool IsInsideToolbar(nsIFrame* aFrame) {
return false;
}

nsNativeThemeCocoa::SearchFieldParams nsNativeThemeCocoa::ComputeSearchFieldParams(
nsNativeThemeCocoa::TextFieldParams nsNativeThemeCocoa::ComputeTextFieldParams(
nsIFrame* aFrame, EventStates aEventState) {
SearchFieldParams params;
TextFieldParams params;
params.insideToolbar = IsInsideToolbar(aFrame);
params.disabled = IsDisabled(aFrame, aEventState);
params.focused = IsFocused(aFrame);

// See ShouldUnconditionallyDrawFocusRingIfFocused.
params.focused = aEventState.HasState(NS_EVENT_STATE_FOCUS);
// XUL textboxes set the native appearance on the containing box, while
// concrete focus is set on the html:input element within it. We can
// though, check the focused attribute of xul textboxes in this case.
// On Mac, focus rings are always shown for textboxes, so we do not need
// to check the window's focus ring state here
if (aFrame->GetContent()->IsXULElement() && IsFocused(aFrame)) {
params.focused = true;
}

params.rtl = IsFrameRTL(aFrame);
params.verticalAlignFactor = VerticalAlignFactor(aFrame);
return params;
}

void nsNativeThemeCocoa::DrawTextField(CGContextRef cgContext, const HIRect& inBoxRect,
const TextFieldParams& aParams) {
NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;

NSTextFieldCell* cell = mTextFieldCell;
[cell setEnabled:!aParams.disabled];
[cell setShowsFirstResponder:aParams.focused];

DrawCellWithSnapping(cell, cgContext, inBoxRect, searchFieldSettings, aParams.verticalAlignFactor,
mCellDrawView, aParams.rtl);

NS_OBJC_END_TRY_IGNORE_BLOCK;
}

void nsNativeThemeCocoa::DrawSearchField(CGContextRef cgContext, const HIRect& inBoxRect,
const SearchFieldParams& aParams) {
const TextFieldParams& aParams) {
NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;

NSSearchFieldCell* cell = aParams.insideToolbar ? mToolbarSearchFieldCell : mSearchFieldCell;
Expand Down Expand Up @@ -1637,47 +1668,6 @@ static ThemeDrawState ToThemeDrawState(const nsNativeThemeCocoa::ControlParams&
NS_OBJC_END_TRY_IGNORE_BLOCK;
}

void nsNativeThemeCocoa::DrawTextBox(CGContextRef cgContext, const HIRect& inBoxRect,
TextBoxParams aParams) {
NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;

SetCGContextFillColor(cgContext, sRGBColor(1.0, 1.0, 1.0, 1.0));
CGContextFillRect(cgContext, inBoxRect);

#if DRAW_IN_FRAME_DEBUG
CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
CGContextFillRect(cgContext, inBoxRect);
#endif

if (aParams.borderless) {
return;
}

HIThemeFrameDrawInfo fdi;
fdi.version = 0;
fdi.kind = kHIThemeFrameTextFieldSquare;

// We don't ever set an inactive state for this because it doesn't
// look right (see other apps).
fdi.state = aParams.disabled ? kThemeStateUnavailable : kThemeStateActive;
fdi.isFocused = aParams.focused;

// HIThemeDrawFrame takes the rect for the content area of the frame, not
// the bounding rect for the frame. Here we reduce the size of the rect we
// will pass to make it the size of the content.
HIRect drawRect = inBoxRect;
SInt32 frameOutset = 0;
::GetThemeMetric(kThemeMetricEditTextFrameOutset, &frameOutset);
drawRect.origin.x += frameOutset;
drawRect.origin.y += frameOutset;
drawRect.size.width -= frameOutset * 2;
drawRect.size.height -= frameOutset * 2;

HIThemeDrawFrame(&drawRect, &fdi, cgContext, HITHEME_ORIENTATION);

NS_OBJC_END_TRY_IGNORE_BLOCK;
}

static const CellRenderSettings progressSettings[2][2] = {
// Vertical progress bar.
{// Determined settings.
Expand Down Expand Up @@ -2570,25 +2560,11 @@ static bool IsHiDPIContext(nsDeviceContext* aContext) {
return Some(WidgetInfo::GroupBox());

case StyleAppearance::Textfield:
case StyleAppearance::NumberInput: {
// See ShouldUnconditionallyDrawFocusRingIfFocused.
bool isFocused = eventState.HasState(NS_EVENT_STATE_FOCUS);
// XUL textboxes set the native appearance on the containing box, while
// concrete focus is set on the html:input element within it. We can
// though, check the focused attribute of xul textboxes in this case.
// On Mac, focus rings are always shown for textboxes, so we do not need
// to check the window's focus ring state here
if (aFrame->GetContent()->IsXULElement() && IsFocused(aFrame)) {
isFocused = true;
}

bool isDisabled = IsDisabled(aFrame, eventState) || IsReadOnly(aFrame);
return Some(
WidgetInfo::TextBox(TextBoxParams{isDisabled, isFocused, /* borderless = */ false}));
}
case StyleAppearance::NumberInput:
return Some(WidgetInfo::TextField(ComputeTextFieldParams(aFrame, eventState)));

case StyleAppearance::Searchfield:
return Some(WidgetInfo::SearchField(ComputeSearchFieldParams(aFrame, eventState)));
return Some(WidgetInfo::SearchField(ComputeTextFieldParams(aFrame, eventState)));

case StyleAppearance::ProgressBar: {
if (IsIndeterminateProgress(aFrame, eventState)) {
Expand Down Expand Up @@ -2917,13 +2893,13 @@ static bool IsHiDPIContext(nsDeviceContext* aContext) {
HIThemeDrawGroupBox(&macRect, &gdi, cgContext, HITHEME_ORIENTATION);
break;
}
case Widget::eTextBox: {
TextBoxParams params = aWidgetInfo.Params<TextBoxParams>();
DrawTextBox(cgContext, macRect, params);
case Widget::eTextField: {
TextFieldParams params = aWidgetInfo.Params<TextFieldParams>();
DrawTextField(cgContext, macRect, params);
break;
}
case Widget::eSearchField: {
SearchFieldParams params = aWidgetInfo.Params<SearchFieldParams>();
TextFieldParams params = aWidgetInfo.Params<TextFieldParams>();
DrawSearchField(cgContext, macRect, params);
break;
}
Expand Down

0 comments on commit ef69315

Please sign in to comment.