diff --git a/widget/cocoa/nsNativeThemeCocoa.h b/widget/cocoa/nsNativeThemeCocoa.h index 648be1cdfed9c..69ee55dc6e0f2 100644 --- a/widget/cocoa/nsNativeThemeCocoa.h +++ b/widget/cocoa/nsNativeThemeCocoa.h @@ -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; @@ -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 @@ -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) { @@ -320,8 +314,8 @@ class nsNativeThemeCocoa : private nsNativeTheme, public nsITheme { mozilla::Variant + UnifiedToolbarParams, TextFieldParams, ProgressParams, MeterParams, + TreeHeaderCellParams, ScaleParams, ScrollbarParams, bool> mVariant; enum Widget mWidget; @@ -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); @@ -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, @@ -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, @@ -459,6 +454,7 @@ class nsNativeThemeCocoa : private nsNativeTheme, public nsITheme { NSButtonCell* mPushButtonCell; NSButtonCell* mRadioButtonCell; NSButtonCell* mCheckboxCell; + NSTextFieldCell* mTextFieldCell; NSSearchFieldCell* mSearchFieldCell; NSSearchFieldCell* mToolbarSearchFieldCell; NSPopUpButtonCell* mDropdownCell; diff --git a/widget/cocoa/nsNativeThemeCocoa.mm b/widget/cocoa/nsNativeThemeCocoa.mm index bba243a820b91..a0998889c2d98 100644 --- a/widget/cocoa/nsNativeThemeCocoa.mm +++ b/widget/cocoa/nsNativeThemeCocoa.mm @@ -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]; @@ -432,6 +437,7 @@ static bool IsInSourceList(nsIFrame* aFrame) { [mPushButtonCell release]; [mRadioButtonCell release]; [mCheckboxCell release]; + [mTextFieldCell release]; [mSearchFieldCell release]; [mToolbarSearchFieldCell release]; [mDropdownCell release]; @@ -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; @@ -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. @@ -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)) { @@ -2917,13 +2893,13 @@ static bool IsHiDPIContext(nsDeviceContext* aContext) { HIThemeDrawGroupBox(&macRect, &gdi, cgContext, HITHEME_ORIENTATION); break; } - case Widget::eTextBox: { - TextBoxParams params = aWidgetInfo.Params(); - DrawTextBox(cgContext, macRect, params); + case Widget::eTextField: { + TextFieldParams params = aWidgetInfo.Params(); + DrawTextField(cgContext, macRect, params); break; } case Widget::eSearchField: { - SearchFieldParams params = aWidgetInfo.Params(); + TextFieldParams params = aWidgetInfo.Params(); DrawSearchField(cgContext, macRect, params); break; }