unsigned RenderThemeChromiumWin::determineState(RenderObject* o, ControlSubPart subPart) { unsigned result = TS_NORMAL; ControlPart appearance = o->style()->appearance(); if (!isEnabled(o)) result = TS_DISABLED; else if (isReadOnlyControl(o)) result = (appearance == TextFieldPart || appearance == TextAreaPart || appearance == SearchFieldPart) ? ETS_READONLY : TS_DISABLED; // Active overrides hover and focused. else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o)) result = TS_PRESSED; else if (supportsFocus(appearance) && isFocused(o)) result = ETS_FOCUSED; else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o)) result = TS_HOT; // CBS_UNCHECKED*: 1-4 // CBS_CHECKED*: 5-8 // CBS_MIXED*: 9-12 if (isIndeterminate(o)) result += 8; else if (isChecked(o)) result += 4; return result; }
bool RenderThemeGtk::paintRenderObject(GtkThemeWidgetType type, RenderObject* renderObject, GraphicsContext* context, const IntRect& rect, int flags) { // Painting is disabled so just claim to have succeeded if (context->paintingDisabled()) return false; GtkWidgetState widgetState; widgetState.active = isPressed(renderObject); widgetState.focused = isFocused(renderObject); // https://bugs.webkit.org/show_bug.cgi?id=18364 // The Mozilla theme drawing code, only paints a button as pressed when it's pressed // while hovered. Until we move away from the Mozila code, work-around the issue by // forcing a pressed button into the hovered state. This ensures that buttons activated // via the keyboard have the proper rendering. widgetState.inHover = isHovered(renderObject) || (type == MOZ_GTK_BUTTON && isPressed(renderObject)); // FIXME: Disabled does not always give the correct appearance for ReadOnly widgetState.disabled = !isEnabled(renderObject) || isReadOnlyControl(renderObject); widgetState.isDefault = false; widgetState.canDefault = false; widgetState.depressed = false; WidgetRenderingContext widgetContext(context, rect); return !widgetContext.paintMozillaWidget(type, &widgetState, flags, gtkTextDirection(renderObject->style()->direction())); }
ControlStates::States RenderTheme::extractControlStatesForRenderer(const RenderObject& o) const { ControlStates::States states = 0; if (isHovered(o)) { states |= ControlStates::HoverState; if (isSpinUpButtonPartHovered(o)) states |= ControlStates::SpinUpState; } if (isPressed(o)) { states |= ControlStates::PressedState; if (isSpinUpButtonPartPressed(o)) states |= ControlStates::SpinUpState; } if (isFocused(o) && o.style().outlineStyleIsAuto()) states |= ControlStates::FocusState; if (isEnabled(o)) states |= ControlStates::EnabledState; if (isChecked(o)) states |= ControlStates::CheckedState; if (isReadOnlyControl(o)) states |= ControlStates::ReadOnlyState; if (isDefault(o)) states |= ControlStates::DefaultState; if (!isActive(o)) states |= ControlStates::WindowInactiveState; if (isIndeterminate(o)) states |= ControlStates::IndeterminateState; return states; }
ControlStates LayoutTheme::controlStatesForLayoutObject(const LayoutObject& o) { ControlStates result = 0; if (isHovered(o)) { result |= HoverControlState; if (isSpinUpButtonPartHovered(o)) result |= SpinUpControlState; } if (isPressed(o)) { result |= PressedControlState; if (isSpinUpButtonPartPressed(o)) result |= SpinUpControlState; } if (isFocused(o) && o.style()->outlineStyleIsAuto()) result |= FocusControlState; if (isEnabled(o)) result |= EnabledControlState; if (isChecked(o)) result |= CheckedControlState; if (isReadOnlyControl(o)) result |= ReadOnlyControlState; if (!isActive(o)) result |= WindowInactiveControlState; if (isIndeterminate(o)) result |= IndeterminateControlState; return result; }
ControlStates RenderTheme::controlStatesForRenderer(const RenderObject* o) const { ControlStates result = 0; if (isHovered(o)) { result |= HoverState; if (isSpinUpButtonPartHovered(o)) result |= SpinUpState; } if (isPressed(o)) { result |= PressedState; if (isSpinUpButtonPartPressed(o)) result |= SpinUpState; } if (isFocused(o) && o->style()->outlineStyleIsAuto()) result |= FocusState; if (isEnabled(o)) result |= EnabledState; if (isChecked(o)) result |= CheckedState; if (isReadOnlyControl(o)) result |= ReadOnlyState; if (isDefault(o)) result |= DefaultState; if (!isActive(o)) result |= WindowInactiveState; if (isIndeterminate(o)) result |= IndeterminateState; return result; }
bool RenderThemeChromiumLinux::paintInnerSpinButton(RenderObject* o, const PaintInfo& i, const IntRect& rect) { PlatformSupport::ThemePaintExtraParams extraParams; extraParams.innerSpin.spinUp = (controlStatesForRenderer(o) & SpinUpState); extraParams.innerSpin.readOnly = isReadOnlyControl(o); PlatformSupport::paintThemePart(i.context, PlatformSupport::PartInnerSpinButton, getWebThemeState(this, o), rect, &extraParams); return false; }
bool RenderThemeNix::paintInnerSpinButton(RenderObject* o, const PaintInfo& i, const IntRect& rect) { WebKit::WebThemeEngine::InnerSpinButtonExtraParams extraParams; extraParams.spinUp = isSpinUpButtonPartPressed(o); extraParams.readOnly = isReadOnlyControl(o); themeEngine()->paintInnerSpinButton(webCanvas(i), getWebThemeState(this, o), WebKit::WebRect(rect), extraParams); return false; }
EAppearance RenderThemeQt::applyTheme(QStyleOption& option, RenderObject* o) const { // Default bits: no focus, no mouse over option.state &= ~(QStyle::State_HasFocus | QStyle::State_MouseOver); if (!isEnabled(o)) option.state &= ~QStyle::State_Enabled; if (isReadOnlyControl(o)) // Readonly is supported on textfields. option.state |= QStyle::State_ReadOnly; if (supportsFocus(o->style()->appearance()) && isFocused(o)) option.state |= QStyle::State_HasFocus; if (isHovered(o)) option.state |= QStyle::State_MouseOver; EAppearance result = o->style()->appearance(); switch (result) { case PushButtonAppearance: case SquareButtonAppearance: case ButtonAppearance: case ButtonBevelAppearance: case ListItemAppearance: case MenulistButtonAppearance: case ScrollbarButtonLeftAppearance: case ScrollbarButtonRightAppearance: case ScrollbarTrackHorizontalAppearance: case ScrollbarTrackVerticalAppearance: case ScrollbarThumbHorizontalAppearance: case ScrollbarThumbVerticalAppearance: case SearchFieldResultsButtonAppearance: case SearchFieldCancelButtonAppearance: { if (isPressed(o)) option.state |= QStyle::State_Sunken; else if (result == PushButtonAppearance) option.state |= QStyle::State_Raised; break; } } if(result == RadioAppearance || result == CheckboxAppearance) option.state |= (isChecked(o) ? QStyle::State_On : QStyle::State_Off); // If the webview has a custom palette, use it Page *page = o->document()->page(); if (page) { QWidget *view = static_cast<ChromeClientQt*>(page->chrome()->client())->m_webPage->view(); if (view) option.palette = view->palette(); } return result; }
GtkStateType RenderThemeGtk::getGtkStateType(RenderObject* object) { if (!isEnabled(object) || isReadOnlyControl(object)) return GTK_STATE_INSENSITIVE; if (isPressed(object)) return GTK_STATE_ACTIVE; if (isHovered(object)) return GTK_STATE_PRELIGHT; return GTK_STATE_NORMAL; }
bool RenderThemeChromiumDefault::paintInnerSpinButton(RenderObject* o, const PaintInfo& i, const IntRect& rect) { WebKit::WebThemeEngine::ExtraParams extraParams; WebKit::WebCanvas* canvas = i.context->canvas(); extraParams.innerSpin.spinUp = (controlStatesForRenderer(o) & SpinUpState); extraParams.innerSpin.readOnly = isReadOnlyControl(o); WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartInnerSpinButton, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams); return false; }
unsigned RenderThemeWinCE::determineClassicState(RenderObject* o) { unsigned result = 0; if (!isEnabled(o) || isReadOnlyControl(o)) result = DFCS_INACTIVE; else if (isPressed(o)) // Active supersedes hover result = DFCS_PUSHED; if (isChecked(o)) result |= DFCS_CHECKED; return result; }
unsigned RenderThemeChromiumWin::determineClassicState(RenderObject* o, ControlSubPart subPart) { unsigned result = 0; ControlPart part = o->style()->appearance(); // Sliders are always in the normal state. if (part == SliderHorizontalPart || part == SliderVerticalPart) return result; // So are readonly text fields. if (isReadOnlyControl(o) && (part == TextFieldPart || part == TextAreaPart || part == SearchFieldPart)) return result; if (part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) { if (!isEnabled(o->parent())) result = DFCS_INACTIVE; else if (toRenderSlider(o->parent())->inDragMode()) // Active supersedes hover result = DFCS_PUSHED; else if (isHovered(o)) result = DFCS_HOT; } else { if (!isEnabled(o) || isReadOnlyControl(o)) result = DFCS_INACTIVE; // Active supersedes hover else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o)) result = DFCS_PUSHED; else if (supportsFocus(part) && isFocused(o)) // So does focused result = 0; else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o)) result = DFCS_HOT; // Classic theme can't represent indeterminate states. Use unchecked appearance. if (isChecked(o) && !isIndeterminate(o)) result |= DFCS_CHECKED; } return result; }
EAppearance RenderThemeQt::applyTheme(QStyleOption& option, RenderObject* o) const { // Default bits: no focus, no mouse over option.state &= ~(QStyle::State_HasFocus | QStyle::State_MouseOver); if (!isEnabled(o)) option.state &= ~QStyle::State_Enabled; if (isReadOnlyControl(o)) // Readonly is supported on textfields. option.state |= QStyle::State_ReadOnly; if (supportsFocus(o->style()->appearance()) && isFocused(o)) option.state |= QStyle::State_HasFocus; if (isHovered(o)) option.state |= QStyle::State_MouseOver; EAppearance result = o->style()->appearance(); switch (result) { case PushButtonAppearance: case SquareButtonAppearance: case ButtonAppearance: case ButtonBevelAppearance: case ListItemAppearance: case MenulistButtonAppearance: case ScrollbarButtonLeftAppearance: case ScrollbarButtonRightAppearance: case ScrollbarTrackHorizontalAppearance: case ScrollbarTrackVerticalAppearance: case ScrollbarThumbHorizontalAppearance: case ScrollbarThumbVerticalAppearance: case SearchFieldResultsButtonAppearance: case SearchFieldCancelButtonAppearance: { if (isPressed(o)) option.state |= QStyle::State_Sunken; else if (result == PushButtonAppearance) option.state |= QStyle::State_Raised; break; } } if(result == RadioAppearance || result == CheckboxAppearance) option.state |= (isChecked(o) ? QStyle::State_On : QStyle::State_Off); return result; }
unsigned RenderThemeGdk::determineState(RenderObject* o) { unsigned result = TS_NORMAL; if (!isEnabled(o)) result = TS_DISABLED; else if (isReadOnlyControl(o)) result = TFS_READONLY; // Readonly is supported on textfields. else if (supportsFocus(o->style()->appearance()) && isFocused(o)) result = TS_FOCUSED; else if (isPressed(o)) result = TS_ACTIVE; else if (isHovered(o)) result = TS_HOVER; if (isChecked(o)) result += 4; // 4 unchecked states, 4 checked states. return result; }
unsigned RenderThemeChromiumWin::determineState(RenderObject* o) { unsigned result = TS_NORMAL; ControlPart appearance = o->style()->appearance(); if (!isEnabled(o)) result = TS_DISABLED; else if (isReadOnlyControl(o) && (TextFieldPart == appearance || TextAreaPart == appearance || SearchFieldPart == appearance)) result = ETS_READONLY; // Readonly is supported on textfields. else if (isPressed(o)) // Active overrides hover and focused. result = TS_PRESSED; else if (supportsFocus(appearance) && isFocused(o)) result = ETS_FOCUSED; else if (isHovered(o)) result = TS_HOT; if (isChecked(o)) result += 4; // 4 unchecked states, 4 checked states. return result; }
bool RenderThemeGtk::paintTextField(RenderObject* renderObject, const PaintInfo& info, const IntRect& rect) { GtkWidget* widget = gtkEntry(); bool enabled = isEnabled(renderObject) && !isReadOnlyControl(renderObject); GtkStateType backgroundState = enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE; gtk_widget_set_sensitive(widget, enabled); gtk_widget_set_direction(widget, gtkTextDirection(renderObject->style().direction())); setWidgetHasFocus(widget, isFocused(renderObject)); WidgetRenderingContext widgetContext(info.context, rect); IntRect textFieldRect(IntPoint(), rect.size()); // The entry background is only painted over the interior part of the GTK+ entry, not // the entire frame. This happens in the Mozilla theme drawing code as well. IntRect interiorRect(textFieldRect); GtkStyle* style = gtk_widget_get_style(widget); interiorRect.inflateX(-style->xthickness); interiorRect.inflateY(-style->ythickness); widgetContext.gtkPaintFlatBox(interiorRect, widget, backgroundState, GTK_SHADOW_NONE, "entry_bg"); // This is responsible for drawing the actual frame. widgetContext.gtkPaintShadow(textFieldRect, widget, GTK_STATE_NORMAL, GTK_SHADOW_IN, "entry"); gboolean interiorFocus; gint focusWidth; gtk_widget_style_get(widget, "interior-focus", &interiorFocus, "focus-line-width", &focusWidth, NULL); if (isFocused(renderObject) && !interiorFocus) { // When GTK+ paints a text entry with focus, it shrinks the size of the frame area by the // focus width and paints over the previously unfocused text entry. We need to emulate that // by drawing both the unfocused frame above and the focused frame here. IntRect shadowRect(textFieldRect); shadowRect.inflate(-focusWidth); widgetContext.gtkPaintShadow(shadowRect, widget, GTK_STATE_NORMAL, GTK_SHADOW_IN, "entry"); widgetContext.gtkPaintFocus(textFieldRect, widget, GTK_STATE_NORMAL, "entry"); } return false; }
bool RenderThemeGtk::paintInnerSpinButton(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect) { // We expand the painted area by 2 pixels on the top and bottom and 2 pixels on the right. This // is because GTK+ themes want to draw over the text box borders, but WebCore renders the inner // spin button inside the text box. IntRect expandedRect(rect); expandedRect.inflateY(2); expandedRect.setWidth(rect.width() + 2); WidgetRenderingContext widgetContext(paintInfo.context, expandedRect); GtkWidget* widget = gtkSpinButton(); gtk_widget_set_direction(widget, gtkTextDirection(renderObject->style().direction())); IntRect fullSpinButtonRect(IntPoint(), expandedRect.size()); widgetContext.gtkPaintBox(fullSpinButtonRect, widget, GTK_STATE_NORMAL, GTK_SHADOW_IN, "spinbutton"); bool upPressed = isSpinUpButtonPartPressed(renderObject); bool upHovered = isSpinUpButtonPartHovered(renderObject); bool controlActive = isEnabled(renderObject) && !isReadOnlyControl(renderObject); GtkShadowType shadowType = upPressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT; GtkStateType stateType = GTK_STATE_INSENSITIVE; if (controlActive) { if (isPressed(renderObject) && upPressed) stateType = GTK_STATE_ACTIVE; else if (isHovered(renderObject) && upHovered) stateType = GTK_STATE_PRELIGHT; else stateType = GTK_STATE_NORMAL; } IntRect topRect(IntPoint(), expandedRect.size()); topRect.setHeight(expandedRect.height() / 2); widgetContext.gtkPaintBox(topRect, widget, stateType, shadowType, "spinbutton_up"); // The arrow size/position calculation here is based on the arbitrary gymnastics that happen // in gtkspinbutton.c. It isn't pretty there and it isn't pretty here. This manages to make // the button look native for many themes though. IntRect arrowRect; int arrowSize = (expandedRect.width() - 3) / 2; arrowSize -= (arrowSize % 2) - 1; // Force odd. arrowRect.setWidth(arrowSize); arrowRect.setHeight(arrowSize); arrowRect.move((expandedRect.width() - arrowRect.width()) / 2, (topRect.height() - arrowRect.height()) / 2 + 1); widgetContext.gtkPaintArrow(arrowRect, widget, stateType, shadowType, GTK_ARROW_UP, "spinbutton"); shadowType = isPressed(renderObject) && !upPressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT; if (controlActive) { if (isPressed(renderObject) && !upPressed) stateType = GTK_STATE_ACTIVE; else if (isHovered(renderObject) && !upHovered) stateType = GTK_STATE_PRELIGHT; else stateType = GTK_STATE_NORMAL; } IntRect bottomRect(IntPoint(0, expandedRect.height() / 2), expandedRect.size()); bottomRect.setHeight(expandedRect.height() - bottomRect.y()); widgetContext.gtkPaintBox(bottomRect, widget, stateType, shadowType, "spinbutton_down"); arrowRect.setY(arrowRect.y() + bottomRect.y() - 1); widgetContext.gtkPaintArrow(arrowRect, widget, stateType, shadowType, GTK_ARROW_DOWN, "spinbutton"); return false; }