diff --git a/content/html/content/src/HTMLInputElement.cpp b/content/html/content/src/HTMLInputElement.cpp
index 9753d69944cc..806363da52ff 100644
--- a/content/html/content/src/HTMLInputElement.cpp
+++ b/content/html/content/src/HTMLInputElement.cpp
@@ -3328,6 +3328,8 @@ HTMLInputElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
nsNumberControlFrame* numberControlFrame =
do_QueryFrame(GetPrimaryFrame());
if (numberControlFrame) {
+ bool oldNumberControlSpinTimerSpinsUpValue =
+ mNumberControlSpinnerSpinsUp;
switch (numberControlFrame->GetSpinButtonForPointerEvent(
aVisitor.mEvent->AsMouseEvent())) {
case nsNumberControlFrame::eSpinButtonUp:
@@ -3339,6 +3341,14 @@ HTMLInputElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
stopSpin = false;
break;
}
+ if (mNumberControlSpinnerSpinsUp !=
+ oldNumberControlSpinTimerSpinsUpValue) {
+ nsNumberControlFrame* numberControlFrame =
+ do_QueryFrame(GetPrimaryFrame());
+ if (numberControlFrame) {
+ numberControlFrame->SpinnerStateChanged();
+ }
+ }
}
if (stopSpin) {
StopNumberControlSpinnerSpin();
@@ -3360,6 +3370,15 @@ HTMLInputElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
numberControlFrame->HandleFocusEvent(aVisitor.mEvent);
}
}
+ if (frame->IsThemed()) {
+ // Our frame's nested will be invalidated when it
+ // loses focus, but since we are also native themed we need to make
+ // sure that our entire area is repainted since any focus highlight
+ // from the theme should be removed from us (the repainting of the
+ // sub-area occupied by the anon text control is not enough to do
+ // that).
+ frame->InvalidateFrame();
+ }
}
} else if (aVisitor.mEvent->message == NS_KEY_UP) {
WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent();
@@ -3511,6 +3530,12 @@ HTMLInputElement::StartNumberControlSpinnerSpin()
// Capture the mouse so that we can tell if the pointer moves from one
// spin button to the other, or to some other element:
nsIPresShell::SetCapturingContent(this, CAPTURE_IGNOREALLOWED);
+
+ nsNumberControlFrame* numberControlFrame =
+ do_QueryFrame(GetPrimaryFrame());
+ if (numberControlFrame) {
+ numberControlFrame->SpinnerStateChanged();
+ }
}
void
@@ -3526,6 +3551,12 @@ HTMLInputElement::StopNumberControlSpinnerSpin()
mNumberControlSpinnerIsSpinning = false;
FireChangeEventIfNeeded();
+
+ nsNumberControlFrame* numberControlFrame =
+ do_QueryFrame(GetPrimaryFrame());
+ if (numberControlFrame) {
+ numberControlFrame->SpinnerStateChanged();
+ }
}
}
diff --git a/content/html/content/src/HTMLInputElement.h b/content/html/content/src/HTMLInputElement.h
index 13abe71ca751..a6fd14a866cb 100644
--- a/content/html/content/src/HTMLInputElement.h
+++ b/content/html/content/src/HTMLInputElement.h
@@ -688,6 +688,16 @@ public:
*/
static void HandleNumberControlSpin(void* aData);
+ bool NumberSpinnerUpButtonIsDepressed() const
+ {
+ return mNumberControlSpinnerIsSpinning && mNumberControlSpinnerSpinsUp;
+ }
+
+ bool NumberSpinnerDownButtonIsDepressed() const
+ {
+ return mNumberControlSpinnerIsSpinning && !mNumberControlSpinnerSpinsUp;
+ }
+
bool MozIsTextField(bool aExcludePassword);
nsIEditor* GetEditor();
diff --git a/layout/forms/nsNumberControlFrame.cpp b/layout/forms/nsNumberControlFrame.cpp
index b64ff2477681..50b0d613e6a7 100644
--- a/layout/forms/nsNumberControlFrame.cpp
+++ b/layout/forms/nsNumberControlFrame.cpp
@@ -14,6 +14,7 @@
#include "nsGkAtoms.h"
#include "nsINodeInfo.h"
#include "nsINameSpaceManager.h"
+#include "nsThemeConstants.h"
#include "mozilla/BasicEvents.h"
#include "nsContentUtils.h"
#include "nsContentCreatorFunctions.h"
@@ -318,6 +319,49 @@ nsNumberControlFrame::GetAnonTextControl()
return mTextField ? HTMLInputElement::FromContent(mTextField) : nullptr;
}
+/* static */ nsNumberControlFrame*
+nsNumberControlFrame::GetNumberControlFrameForTextField(nsIFrame* aFrame)
+{
+ // If aFrame is the anon text field for an then we expect
+ // the frame of its mContent's grandparent to be that input's frame. We
+ // have to check for this via the content tree because we don't know whether
+ // extra frames will be wrapped around any of the elements between aFrame and
+ // the nsNumberControlFrame that we're looking for (e.g. flex wrappers).
+ nsIContent* content = aFrame->GetContent();
+ if (content->IsInNativeAnonymousSubtree() &&
+ content->GetParent() && content->GetParent()->GetParent()) {
+ nsIContent* grandparent = content->GetParent()->GetParent();
+ if (grandparent->IsHTML(nsGkAtoms::input) &&
+ grandparent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+ nsGkAtoms::number, eCaseMatters)) {
+ return do_QueryFrame(grandparent->GetPrimaryFrame());
+ }
+ }
+ return nullptr;
+}
+
+/* static */ nsNumberControlFrame*
+nsNumberControlFrame::GetNumberControlFrameForSpinButton(nsIFrame* aFrame)
+{
+ // If aFrame is a spin button for an then we expect the
+ // frame of its mContent's great-grandparent to be that input's frame. We
+ // have to check for this via the content tree because we don't know whether
+ // extra frames will be wrapped around any of the elements between aFrame and
+ // the nsNumberControlFrame that we're looking for (e.g. flex wrappers).
+ nsIContent* content = aFrame->GetContent();
+ if (content->IsInNativeAnonymousSubtree() &&
+ content->GetParent() && content->GetParent()->GetParent() &&
+ content->GetParent()->GetParent()->GetParent()) {
+ nsIContent* greatgrandparent = content->GetParent()->GetParent()->GetParent();
+ if (greatgrandparent->IsHTML(nsGkAtoms::input) &&
+ greatgrandparent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+ nsGkAtoms::number, eCaseMatters)) {
+ return do_QueryFrame(greatgrandparent->GetPrimaryFrame());
+ }
+ }
+ return nullptr;
+}
+
int32_t
nsNumberControlFrame::GetSpinButtonForPointerEvent(WidgetGUIEvent* aEvent) const
{
@@ -330,9 +374,64 @@ nsNumberControlFrame::GetSpinButtonForPointerEvent(WidgetGUIEvent* aEvent) const
if (aEvent->originalTarget == mSpinDown) {
return eSpinButtonDown;
}
+ if (aEvent->originalTarget == mSpinBox) {
+ // In the case that the up/down buttons are hidden (display:none) we use
+ // just the spin box element, spinning up if the pointer is over the top
+ // half of the element, or down if it's over the bottom half. This is
+ // important to handle since this is the state things are in for the
+ // default UA style sheet. See the comment in forms.css for why.
+ LayoutDeviceIntPoint absPoint = aEvent->refPoint;
+ nsPoint point =
+ nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent,
+ LayoutDeviceIntPoint::ToUntyped(absPoint),
+ mSpinBox->GetPrimaryFrame());
+ if (point != nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)) {
+ if (point.y < mSpinBox->GetPrimaryFrame()->GetSize().height / 2) {
+ return eSpinButtonUp;
+ }
+ return eSpinButtonDown;
+ }
+ }
return eSpinButtonNone;
}
+void
+nsNumberControlFrame::SpinnerStateChanged() const
+{
+ nsIFrame* spinUpFrame = mSpinUp->GetPrimaryFrame();
+ if (spinUpFrame && spinUpFrame->IsThemed()) {
+ spinUpFrame->InvalidateFrame();
+ }
+ nsIFrame* spinDownFrame = mSpinDown->GetPrimaryFrame();
+ if (spinDownFrame && spinDownFrame->IsThemed()) {
+ spinDownFrame->InvalidateFrame();
+ }
+}
+
+bool
+nsNumberControlFrame::SpinnerUpButtonIsDepressed() const
+{
+ return HTMLInputElement::FromContent(mContent)->
+ NumberSpinnerUpButtonIsDepressed();
+}
+
+bool
+nsNumberControlFrame::SpinnerDownButtonIsDepressed() const
+{
+ return HTMLInputElement::FromContent(mContent)->
+ NumberSpinnerDownButtonIsDepressed();
+}
+
+bool
+nsNumberControlFrame::IsFocused() const
+{
+ // Normally this depends on the state of our anonymous text control (which
+ // takes focus for us), but in the case that it does not have a frame we will
+ // have focus ourself.
+ return mTextField->AsElement()->State().HasState(NS_EVENT_STATE_FOCUS) ||
+ mContent->AsElement()->State().HasState(NS_EVENT_STATE_FOCUS);
+}
+
void
nsNumberControlFrame::HandleFocusEvent(WidgetEvent* aEvent)
{
@@ -342,6 +441,27 @@ nsNumberControlFrame::HandleFocusEvent(WidgetEvent* aEvent)
}
}
+#define STYLES_DISABLING_NATIVE_THEMING \
+ NS_AUTHOR_SPECIFIED_BACKGROUND | \
+ NS_AUTHOR_SPECIFIED_PADDING | \
+ NS_AUTHOR_SPECIFIED_BORDER
+
+bool
+nsNumberControlFrame::ShouldUseNativeStyleForSpinner() const
+{
+ nsIFrame* spinUpFrame = mSpinUp->GetPrimaryFrame();
+ nsIFrame* spinDownFrame = mSpinDown->GetPrimaryFrame();
+
+ return spinUpFrame &&
+ spinUpFrame->StyleDisplay()->mAppearance == NS_THEME_SPINNER_UP_BUTTON &&
+ !PresContext()->HasAuthorSpecifiedRules(spinUpFrame,
+ STYLES_DISABLING_NATIVE_THEMING) &&
+ spinDownFrame &&
+ spinDownFrame->StyleDisplay()->mAppearance == NS_THEME_SPINNER_DOWN_BUTTON &&
+ !PresContext()->HasAuthorSpecifiedRules(spinDownFrame,
+ STYLES_DISABLING_NATIVE_THEMING);
+}
+
void
nsNumberControlFrame::AppendAnonymousContentTo(nsBaseContentList& aElements,
uint32_t aFilter)
diff --git a/layout/forms/nsNumberControlFrame.h b/layout/forms/nsNumberControlFrame.h
index 7d85e8fc5bcf..a82c24043e38 100644
--- a/layout/forms/nsNumberControlFrame.h
+++ b/layout/forms/nsNumberControlFrame.h
@@ -44,7 +44,7 @@ public:
virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
- virtual bool IsLeaf() const MOZ_OVERRIDE { return true; }
+ virtual bool IsLeaf() const MOZ_OVERRIDE { return false; }
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
@@ -91,6 +91,18 @@ public:
HTMLInputElement* GetAnonTextControl();
+ /**
+ * If the frame is the frame for an nsNumberControlFrame's anonymous text
+ * field, returns the nsNumberControlFrame. Else returns nullptr.
+ */
+ static nsNumberControlFrame* GetNumberControlFrameForTextField(nsIFrame* aFrame);
+
+ /**
+ * If the frame is the frame for an nsNumberControlFrame's up or down spin
+ * button, returns the nsNumberControlFrame. Else returns nullptr.
+ */
+ static nsNumberControlFrame* GetNumberControlFrameForSpinButton(nsIFrame* aFrame);
+
enum SpinButtonEnum {
eSpinButtonNone,
eSpinButtonUp,
@@ -104,10 +116,19 @@ public:
*/
int32_t GetSpinButtonForPointerEvent(WidgetGUIEvent* aEvent) const;
+ void SpinnerStateChanged() const;
+
+ bool SpinnerUpButtonIsDepressed() const;
+ bool SpinnerDownButtonIsDepressed() const;
+
+ bool IsFocused() const;
+
void HandleFocusEvent(WidgetEvent* aEvent);
virtual Element* GetPseudoElement(nsCSSPseudoElements::Type aType) MOZ_OVERRIDE;
+ bool ShouldUseNativeStyleForSpinner() const;
+
private:
nsresult MakeAnonymousElement(Element** aResult,
diff --git a/layout/style/forms.css b/layout/style/forms.css
index 90ffc318fb06..7dcc8409e95e 100644
--- a/layout/style/forms.css
+++ b/layout/style/forms.css
@@ -897,9 +897,6 @@ input[type=number]::-moz-number-wrapper {
display: flex;
float: none !important;
position: static !important;
- -moz-box-sizing: border-box;
- width: 100%;
- height: 100%;
}
input[type=number]::-moz-number-text {
@@ -922,18 +919,23 @@ input[type=number]::-moz-number-text {
input[type=number]::-moz-number-spin-box {
display: flex;
flex-direction: column;
- flex: 0 8px;
- cursor: default;
- padding: 1px;
+%ifdef XP_WIN
+ /* The Window's Theme's spin buttons have a very narrow minimum width, so
+ * make it something reasonable:
+ */
+ width: 16px;
+%endif
+ height: 0;
+ align-self: center;
+ justify-content: center;
}
input[type=number]::-moz-number-spin-up {
- /* We should be "display:block" so that we don't get wrapped in an anonymous
- * flex item that will prevent the setting of the "flex" property below from
- * working.
- */
- display: block;
- flex: 1;
+ -moz-appearance: spinner-upbutton;
+ display: block; /* bug 926670 */
+ flex: none;
+ cursor: default;
+ /* Style for when native theming is off: */
background-image: url('data:image/svg+xml,');
background-repeat: no-repeat;
background-position: center bottom;
@@ -944,12 +946,11 @@ input[type=number]::-moz-number-spin-up {
}
input[type=number]::-moz-number-spin-down {
- /* We should be "display:block" so that we don't get wrapped in an anonymous
- * flex item that will prevent the setting of the "flex" property below from
- * working.
- */
- display: block;
- flex: 1;
+ -moz-appearance: spinner-downbutton;
+ display: block; /* bug 926670 */
+ flex: none;
+ cursor: default;
+ /* Style for when native theming is off: */
background-image: url('data:image/svg+xml,');
background-repeat: no-repeat;
background-position: center top;
diff --git a/widget/cocoa/nsNativeThemeCocoa.h b/widget/cocoa/nsNativeThemeCocoa.h
index bdd6cc2c2bc5..f17be8450577 100644
--- a/widget/cocoa/nsNativeThemeCocoa.h
+++ b/widget/cocoa/nsNativeThemeCocoa.h
@@ -104,6 +104,10 @@ protected:
const HIRect& inBoxRect, ThemeDrawState inDrawState,
ThemeButtonAdornment inAdornment, nsEventStates inState,
nsIFrame* aFrame);
+ void DrawSpinButton(CGContextRef context, ThemeButtonKind inKind,
+ const HIRect& inBoxRect, ThemeDrawState inDrawState,
+ ThemeButtonAdornment inAdornment, nsEventStates inState,
+ nsIFrame* aFrame, uint8_t aWidgetType);
void DrawUnifiedToolbar(CGContextRef cgContext, const HIRect& inBoxRect,
NSWindow* aWindow);
void DrawStatusBar(CGContextRef cgContext, const HIRect& inBoxRect,
diff --git a/widget/cocoa/nsNativeThemeCocoa.mm b/widget/cocoa/nsNativeThemeCocoa.mm
index 5ece8b31c180..e094bd561621 100644
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -5,6 +5,7 @@
#include "nsNativeThemeCocoa.h"
#include "nsObjCExceptions.h"
+#include "nsNumberControlFrame.h"
#include "nsRangeFrame.h"
#include "nsRenderingContext.h"
#include "nsRect.h"
@@ -1210,6 +1211,26 @@ nsNativeThemeCocoa::DrawDropdown(CGContextRef cgContext, const HIRect& inBoxRect
NS_OBJC_END_TRY_ABORT_BLOCK;
}
+static const CellRenderSettings spinnerSettings = {
+ {
+ NSMakeSize(11, 16), // mini (width trimmed by 2px to reduce blank border)
+ NSMakeSize(15, 22), // small
+ NSMakeSize(19, 27) // regular
+ },
+ {
+ NSMakeSize(11, 16), // mini (width trimmed by 2px to reduce blank border)
+ NSMakeSize(15, 22), // small
+ NSMakeSize(19, 27) // regular
+ },
+ {
+ { // Leopard
+ {0, 0, 0, 0}, // mini
+ {0, 0, 0, 0}, // small
+ {0, 0, 0, 0} // regular
+ }
+ }
+};
+
void
nsNativeThemeCocoa::DrawSpinButtons(CGContextRef cgContext, ThemeButtonKind inKind,
const HIRect& inBoxRect, ThemeDrawState inDrawState,
@@ -1234,6 +1255,56 @@ nsNativeThemeCocoa::DrawSpinButtons(CGContextRef cgContext, ThemeButtonKind inKi
NS_OBJC_END_TRY_ABORT_BLOCK;
}
+void
+nsNativeThemeCocoa::DrawSpinButton(CGContextRef cgContext,
+ ThemeButtonKind inKind,
+ const HIRect& inBoxRect,
+ ThemeDrawState inDrawState,
+ ThemeButtonAdornment inAdornment,
+ nsEventStates inState,
+ nsIFrame* aFrame,
+ uint8_t aWidgetType)
+{
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
+
+ MOZ_ASSERT(aWidgetType == NS_THEME_SPINNER_UP_BUTTON ||
+ aWidgetType == NS_THEME_SPINNER_DOWN_BUTTON);
+
+ HIThemeButtonDrawInfo bdi;
+ bdi.version = 0;
+ bdi.kind = inKind;
+ bdi.value = kThemeButtonOff;
+ bdi.adornment = inAdornment;
+
+ if (IsDisabled(aFrame, inState))
+ bdi.state = kThemeStateUnavailable;
+ else
+ bdi.state = FrameIsInActiveWindow(aFrame) ? inDrawState : kThemeStateActive;
+
+ // Cocoa only allows kThemeIncDecButton to paint the up and down spin buttons
+ // together as a single unit (presumably because when one button is active,
+ // the appearance of both changes (in different ways)). Here we have to paint
+ // both buttons, using clip to hide the one we don't want to paint.
+ HIRect drawRect = inBoxRect;
+ drawRect.size.height *= 2;
+ if (aWidgetType == NS_THEME_SPINNER_DOWN_BUTTON) {
+ drawRect.origin.y -= inBoxRect.size.height;
+ }
+
+ // Shift the drawing a little to the left, since cocoa paints with more
+ // blank space around the visual buttons than we'd like:
+ drawRect.origin.x -= 1;
+
+ CGContextSaveGState(cgContext);
+ CGContextClipToRect(cgContext, inBoxRect);
+
+ HIThemeDrawButton(&drawRect, &bdi, cgContext, HITHEME_ORIENTATION, NULL);
+
+ CGContextRestoreGState(cgContext);
+
+ NS_OBJC_END_TRY_ABORT_BLOCK;
+}
+
void
nsNativeThemeCocoa::DrawFrame(CGContextRef cgContext, HIThemeFrameKind inKind,
const HIRect& inBoxRect, bool inDisabled,
@@ -2135,8 +2206,14 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsRenderingContext* aContext,
break;
case NS_THEME_SPINNER: {
- ThemeDrawState state = kThemeStateActive;
nsIContent* content = aFrame->GetContent();
+ if (content->IsHTML()) {
+ // In HTML the theming for the spin buttons is drawn individually into
+ // their own backgrounds instead of being drawn into the background of
+ // their spinner parent as it is for XUL.
+ break;
+ }
+ ThemeDrawState state = kThemeStateActive;
if (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::state,
NS_LITERAL_STRING("up"), eCaseMatters)) {
state = kThemeStatePressedUp;
@@ -2151,6 +2228,23 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsRenderingContext* aContext,
}
break;
+ case NS_THEME_SPINNER_UP_BUTTON:
+ case NS_THEME_SPINNER_DOWN_BUTTON: {
+ nsNumberControlFrame* numberControlFrame =
+ nsNumberControlFrame::GetNumberControlFrameForSpinButton(aFrame);
+ if (numberControlFrame) {
+ ThemeDrawState state = kThemeStateActive;
+ if (numberControlFrame->SpinnerUpButtonIsDepressed()) {
+ state = kThemeStatePressedUp;
+ } else if (numberControlFrame->SpinnerDownButtonIsDepressed()) {
+ state = kThemeStatePressedDown;
+ }
+ DrawSpinButton(cgContext, kThemeIncDecButtonMini, macRect, state,
+ kThemeAdornmentNone, eventState, aFrame, aWidgetType);
+ }
+ }
+ break;
+
case NS_THEME_TOOLBAR_BUTTON:
DrawSegment(cgContext, macRect, eventState, aFrame, toolbarButtonRenderSettings);
break;
@@ -2747,12 +2841,25 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsRenderingContext* aContext,
}
case NS_THEME_SPINNER:
+ case NS_THEME_SPINNER_UP_BUTTON:
+ case NS_THEME_SPINNER_DOWN_BUTTON:
{
SInt32 buttonHeight = 0, buttonWidth = 0;
- ::GetThemeMetric(kThemeMetricLittleArrowsWidth, &buttonWidth);
- ::GetThemeMetric(kThemeMetricLittleArrowsHeight, &buttonHeight);
+ if (aFrame->GetContent()->IsXUL()) {
+ ::GetThemeMetric(kThemeMetricLittleArrowsWidth, &buttonWidth);
+ ::GetThemeMetric(kThemeMetricLittleArrowsHeight, &buttonHeight);
+ } else {
+ NSSize size =
+ spinnerSettings.minimumSizes[EnumSizeForCocoaSize(NSMiniControlSize)];
+ buttonWidth = size.width;
+ buttonHeight = size.height;
+ if (aWidgetType != NS_THEME_SPINNER) {
+ // the buttons are half the height of the spinner
+ buttonHeight /= 2;
+ }
+ }
aResult->SizeTo(buttonWidth, buttonHeight);
- *aIsOverridable = false;
+ *aIsOverridable = true;
break;
}
@@ -3100,6 +3207,8 @@ nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* a
case NS_THEME_BUTTON_BEVEL:
case NS_THEME_TOOLBAR_BUTTON:
case NS_THEME_SPINNER:
+ case NS_THEME_SPINNER_UP_BUTTON:
+ case NS_THEME_SPINNER_DOWN_BUTTON:
case NS_THEME_TOOLBAR:
case NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR:
case NS_THEME_STATUSBAR:
@@ -3224,6 +3333,8 @@ nsNativeThemeCocoa::WidgetAppearanceDependsOnWindowFocus(uint8_t aWidgetType)
case NS_THEME_MENUSEPARATOR:
case NS_THEME_TOOLTIP:
case NS_THEME_SPINNER:
+ case NS_THEME_SPINNER_UP_BUTTON:
+ case NS_THEME_SPINNER_DOWN_BUTTON:
case NS_THEME_TOOLBAR_SEPARATOR:
case NS_THEME_TOOLBOX:
case NS_THEME_TEXTFIELD:
diff --git a/widget/xpwidgets/nsNativeTheme.cpp b/widget/xpwidgets/nsNativeTheme.cpp
index b764fbc89d9a..b9b6cef9df09 100644
--- a/widget/xpwidgets/nsNativeTheme.cpp
+++ b/widget/xpwidgets/nsNativeTheme.cpp
@@ -9,6 +9,7 @@
#include "nsIContent.h"
#include "nsIFrame.h"
#include "nsIPresShell.h"
+#include "nsNumberControlFrame.h"
#include "nsPresContext.h"
#include "nsEventStateManager.h"
#include "nsString.h"
@@ -74,6 +75,16 @@ nsNativeTheme::GetContentState(nsIFrame* aFrame, uint8_t aWidgetType)
nsEventStates flags;
if (frameContent->IsElement()) {
flags = frameContent->AsElement()->State();
+
+ // needs special handling since its nested native
+ // anonymous takes focus for it.
+ if (aWidgetType == NS_THEME_TEXTFIELD &&
+ frameContent->IsHTML(nsGkAtoms::input)) {
+ nsNumberControlFrame *numberControlFrame = do_QueryFrame(aFrame);
+ if (numberControlFrame && numberControlFrame->IsFocused()) {
+ flags |= NS_EVENT_STATE_FOCUS;
+ }
+ }
}
if (isXULCheckboxRadio && aWidgetType == NS_THEME_RADIO) {
@@ -313,6 +324,15 @@ nsNativeTheme::IsWidgetStyled(nsPresContext* aPresContext, nsIFrame* aFrame,
}
}
+ if (aWidgetType == NS_THEME_SPINNER_UP_BUTTON ||
+ aWidgetType == NS_THEME_SPINNER_DOWN_BUTTON) {
+ nsNumberControlFrame* numberControlFrame =
+ nsNumberControlFrame::GetNumberControlFrameForSpinButton(aFrame);
+ if (numberControlFrame) {
+ return !numberControlFrame->ShouldUseNativeStyleForSpinner();
+ }
+ }
+
return (aWidgetType == NS_THEME_BUTTON ||
aWidgetType == NS_THEME_TEXTFIELD ||
aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||