summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-06 11:45:16 +0100
committerSteve Block <steveblock@google.com>2011-05-12 13:44:10 +0100
commitcad810f21b803229eb11403f9209855525a25d57 (patch)
tree29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/platform/gtk/RenderThemeGtk3.cpp
parent121b0cf4517156d0ac5111caf9830c51b69bae8f (diff)
downloadexternal_webkit-cad810f21b803229eb11403f9209855525a25d57.zip
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/platform/gtk/RenderThemeGtk3.cpp')
-rw-r--r--Source/WebCore/platform/gtk/RenderThemeGtk3.cpp643
1 files changed, 643 insertions, 0 deletions
diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp b/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp
new file mode 100644
index 0000000..663404d
--- /dev/null
+++ b/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp
@@ -0,0 +1,643 @@
+/*
+ * Copyright (C) 2007 Apple Inc.
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008 Collabora Ltd.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
+ * Copyright (C) 2010 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderThemeGtk.h"
+
+#ifndef GTK_API_VERSION_2
+
+#include "CSSValueKeywords.h"
+#include "GraphicsContext.h"
+#include "GtkVersioning.h"
+#include "HTMLNames.h"
+#include "MediaControlElements.h"
+#include "Page.h"
+#include "RenderObject.h"
+#include "TextDirection.h"
+#include "UserAgentStyleSheets.h"
+#include "WidgetRenderingContext.h"
+#include "gtkdrawing.h"
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+#if ENABLE(PROGRESS_TAG)
+#include "RenderProgress.h"
+#endif
+
+namespace WebCore {
+
+typedef HashMap<GType, GRefPtr<GtkStyleContext> > StyleContextMap;
+static StyleContextMap& styleContextMap();
+
+static void gtkStyleChangedCallback(GObject*, GParamSpec*)
+{
+ StyleContextMap::const_iterator end = styleContextMap().end();
+ for (StyleContextMap::const_iterator iter = styleContextMap().begin(); iter != end; ++iter)
+ gtk_style_context_invalidate(iter->second.get());
+
+ Page::scheduleForcedStyleRecalcForAllPages();
+}
+
+static StyleContextMap& styleContextMap()
+{
+ DEFINE_STATIC_LOCAL(StyleContextMap, map, ());
+
+ static bool initialized = false;
+ if (!initialized) {
+ GtkSettings* settings = gtk_settings_get_default();
+ g_signal_connect(settings, "notify::gtk-theme-name", G_CALLBACK(gtkStyleChangedCallback), 0);
+ g_signal_connect(settings, "notify::gtk-color-scheme", G_CALLBACK(gtkStyleChangedCallback), 0);
+ initialized = true;
+ }
+ return map;
+}
+
+static GtkStyleContext* getStyleContext(GType widgetType)
+{
+ std::pair<StyleContextMap::iterator, bool> result = styleContextMap().add(widgetType, 0);
+ if (!result.second)
+ return result.first->second.get();
+
+ GtkWidgetPath* path = gtk_widget_path_new();
+ gtk_widget_path_append_type(path, widgetType);
+
+ GRefPtr<GtkStyleContext> context = adoptGRef(gtk_style_context_new());
+ gtk_style_context_set_path(context.get(), path);
+ gtk_widget_path_free(path);
+
+ result.first->second = context;
+ return context.get();
+}
+
+// This is not a static method, because we want to avoid having GTK+ headers in RenderThemeGtk.h.
+extern GtkTextDirection gtkTextDirection(TextDirection);
+
+void RenderThemeGtk::initMediaColors()
+{
+ GtkStyle* style = gtk_widget_get_style(GTK_WIDGET(gtkContainer()));
+ m_panelColor = style->bg[GTK_STATE_NORMAL];
+ m_sliderColor = style->bg[GTK_STATE_ACTIVE];
+ m_sliderThumbColor = style->bg[GTK_STATE_SELECTED];
+}
+
+static void adjustRectForFocus(GtkStyleContext* context, IntRect& rect)
+{
+ gint focusWidth, focusPad;
+ gtk_style_context_get_style(context,
+ "focus-line-width", &focusWidth,
+ "focus-padding", &focusPad, NULL);
+ rect.inflate(focusWidth + focusPad);
+}
+
+void RenderThemeGtk::adjustRepaintRect(const RenderObject* renderObject, IntRect& rect)
+{
+ GtkStyleContext* context = 0;
+ ControlPart part = renderObject->style()->appearance();
+ switch (part) {
+ case SliderVerticalPart:
+ case SliderHorizontalPart:
+ context = getStyleContext(part == SliderThumbHorizontalPart ? GTK_TYPE_HSCALE : GTK_TYPE_VSCALE);
+ break;
+ case ButtonPart:
+ context = getStyleContext(GTK_TYPE_BUTTON);
+
+ gboolean interiorFocus;
+ gtk_style_context_get_style(context, "interior-focus", &interiorFocus, NULL);
+ if (interiorFocus)
+ return;
+
+ break;
+ default:
+ return;
+ }
+
+ ASSERT(context);
+ adjustRectForFocus(context, rect);
+}
+
+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 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()));
+}
+
+static void setToggleSize(const RenderThemeGtk* theme, RenderStyle* style, ControlPart appearance)
+{
+ // The width and height are both specified, so we shouldn't change them.
+ if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+ return;
+
+ // FIXME: This is probably not correct use of indicatorSize and indicatorSpacing.
+ gint indicatorSize, indicatorSpacing;
+ theme->getIndicatorMetrics(appearance, indicatorSize, indicatorSpacing);
+
+ // Other ports hard-code this to 13, but GTK+ users tend to demand the native look.
+ // It could be made a configuration option values other than 13 actually break site compatibility.
+ int length = indicatorSize + indicatorSpacing;
+ if (style->width().isIntrinsicOrAuto())
+ style->setWidth(Length(length, Fixed));
+
+ if (style->height().isAuto())
+ style->setHeight(Length(length, Fixed));
+}
+
+void RenderThemeGtk::setCheckboxSize(RenderStyle* style) const
+{
+ setToggleSize(this, style, RadioPart);
+}
+
+bool RenderThemeGtk::paintCheckbox(RenderObject* object, const PaintInfo& info, const IntRect& rect)
+{
+ return paintRenderObject(MOZ_GTK_CHECKBUTTON, object, info.context, rect, isChecked(object));
+}
+
+void RenderThemeGtk::setRadioSize(RenderStyle* style) const
+{
+ setToggleSize(this, style, RadioPart);
+}
+
+bool RenderThemeGtk::paintRadio(RenderObject* object, const PaintInfo& info, const IntRect& rect)
+{
+ return paintRenderObject(MOZ_GTK_RADIOBUTTON, object, info.context, rect, isChecked(object));
+}
+
+bool RenderThemeGtk::paintButton(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ GtkStyleContext* context = getStyleContext(GTK_TYPE_BUTTON);
+ gtk_style_context_save(context);
+
+ gtk_style_context_set_direction(context, static_cast<GtkTextDirection>(gtkTextDirection(renderObject->style()->direction())));
+ gtk_style_context_add_class(context, GTK_STYLE_CLASS_BUTTON);
+
+ IntRect buttonRect(rect);
+
+ if (isDefault(renderObject)) {
+ GtkBorder* borderPtr = 0;
+ GtkBorder border = { 1, 1, 1, 1 };
+
+ gtk_style_context_get_style(context, "default-border", &borderPtr, NULL);
+ if (borderPtr) {
+ border = *borderPtr;
+ gtk_border_free(borderPtr);
+ }
+
+ buttonRect.move(border.left, border.top);
+ buttonRect.setWidth(buttonRect.width() - (border.left + border.right));
+ buttonRect.setHeight(buttonRect.height() - (border.top + border.bottom));
+
+ gtk_style_context_add_class(context, GTK_STYLE_CLASS_DEFAULT);
+ }
+
+ guint flags = 0;
+ if (!isEnabled(renderObject) || isReadOnlyControl(renderObject))
+ flags |= GTK_STATE_FLAG_INSENSITIVE;
+ else if (isHovered(renderObject))
+ flags |= GTK_STATE_FLAG_PRELIGHT;
+ if (isPressed(renderObject))
+ flags |= GTK_STATE_FLAG_ACTIVE;
+ gtk_style_context_set_state(context, static_cast<GtkStateFlags>(flags));
+
+ gtk_render_background(context, paintInfo.context->platformContext(), buttonRect.x(), buttonRect.y(), buttonRect.width(), buttonRect.height());
+ gtk_render_frame(context, paintInfo.context->platformContext(), buttonRect.x(), buttonRect.y(), buttonRect.width(), buttonRect.height());
+
+ if (isFocused(renderObject)) {
+ gint focusWidth, focusPad;
+ gboolean displaceFocus, interiorFocus;
+ gtk_style_context_get_style(context,
+ "focus-line-width", &focusWidth,
+ "focus-padding", &focusPad,
+ "interior-focus", &interiorFocus,
+ "displace-focus", &displaceFocus,
+ NULL);
+
+ if (interiorFocus) {
+ GtkBorder borderWidth;
+ gtk_style_context_get_border(context, static_cast<GtkStateFlags>(flags), &borderWidth);
+
+ buttonRect = IntRect(buttonRect.x() + borderWidth.left + focusPad, buttonRect.y() + borderWidth.top + focusPad,
+ buttonRect.width() - (2 * focusPad + borderWidth.left + borderWidth.right),
+ buttonRect.height() - (2 * focusPad + borderWidth.top + borderWidth.bottom));
+ } else
+ buttonRect.inflate(focusWidth + focusPad);
+
+ if (displaceFocus && isPressed(renderObject)) {
+ gint childDisplacementX;
+ gint childDisplacementY;
+ gtk_style_context_get_style(context,
+ "child-displacement-x", &childDisplacementX,
+ "child-displacement-y", &childDisplacementY,
+ NULL);
+ buttonRect.move(childDisplacementX, childDisplacementY);
+ }
+
+ gtk_render_focus(context, paintInfo.context->platformContext(), buttonRect.x(), buttonRect.y(), buttonRect.width(), buttonRect.height());
+ }
+
+ gtk_style_context_restore(context);
+
+ return false;
+}
+
+static void getComboBoxPadding(RenderStyle* style, int& left, int& top, int& right, int& bottom)
+{
+ // If this menu list button isn't drawn using the native theme, we
+ // don't add any extra padding beyond what WebCore already uses.
+ if (style->appearance() == NoControlPart)
+ return;
+ moz_gtk_get_widget_border(MOZ_GTK_DROPDOWN, &left, &top, &right, &bottom,
+ gtkTextDirection(style->direction()), TRUE);
+}
+
+int RenderThemeGtk::popupInternalPaddingLeft(RenderStyle* style) const
+{
+ int left = 0, top = 0, right = 0, bottom = 0;
+ getComboBoxPadding(style, left, top, right, bottom);
+ return left;
+}
+
+int RenderThemeGtk::popupInternalPaddingRight(RenderStyle* style) const
+{
+ int left = 0, top = 0, right = 0, bottom = 0;
+ getComboBoxPadding(style, left, top, right, bottom);
+ return right;
+}
+
+int RenderThemeGtk::popupInternalPaddingTop(RenderStyle* style) const
+{
+ int left = 0, top = 0, right = 0, bottom = 0;
+ getComboBoxPadding(style, left, top, right, bottom);
+ return top;
+}
+
+int RenderThemeGtk::popupInternalPaddingBottom(RenderStyle* style) const
+{
+ int left = 0, top = 0, right = 0, bottom = 0;
+ getComboBoxPadding(style, left, top, right, bottom);
+ return bottom;
+}
+
+bool RenderThemeGtk::paintMenuList(RenderObject* object, const PaintInfo& info, const IntRect& rect)
+{
+ return paintRenderObject(MOZ_GTK_DROPDOWN, object, info.context, rect);
+}
+
+bool RenderThemeGtk::paintTextField(RenderObject* object, const PaintInfo& info, const IntRect& rect)
+{
+ return paintRenderObject(MOZ_GTK_ENTRY, object, info.context, rect);
+}
+
+bool RenderThemeGtk::paintSliderTrack(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ ControlPart part = renderObject->style()->appearance();
+ ASSERT(part == SliderHorizontalPart || part == SliderVerticalPart);
+
+ GtkStyleContext* context = getStyleContext(part == SliderThumbHorizontalPart ? GTK_TYPE_HSCALE : GTK_TYPE_VSCALE);
+ gtk_style_context_save(context);
+
+ gtk_style_context_set_direction(context, gtkTextDirection(renderObject->style()->direction()));
+ gtk_style_context_add_class(context, GTK_STYLE_CLASS_SCALE);
+ gtk_style_context_add_class(context, GTK_STYLE_CLASS_TROUGH);
+
+ if (!isEnabled(renderObject) || isReadOnlyControl(renderObject))
+ gtk_style_context_set_state(context, GTK_STATE_FLAG_INSENSITIVE);
+
+ gtk_render_background(context, paintInfo.context->platformContext(),
+ rect.x(), rect.y(), rect.width(), rect.height());
+ gtk_render_frame(context, paintInfo.context->platformContext(),
+ rect.x(), rect.y(), rect.width(), rect.height());
+
+ if (isFocused(renderObject)) {
+ gint focusWidth, focusPad;
+ gtk_style_context_get_style(context,
+ "focus-line-width", &focusWidth,
+ "focus-padding", &focusPad, NULL);
+ IntRect focusRect(rect);
+ focusRect.inflate(focusWidth + focusPad);
+ gtk_render_focus(context, paintInfo.context->platformContext(),
+ focusRect.x(), focusRect.y(), focusRect.width(), focusRect.height());
+ }
+
+ gtk_style_context_restore(context);
+ return false;
+}
+
+bool RenderThemeGtk::paintSliderThumb(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ ControlPart part = renderObject->style()->appearance();
+ ASSERT(part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart);
+
+ GtkStyleContext* context = getStyleContext(part == SliderThumbHorizontalPart ? GTK_TYPE_HSCALE : GTK_TYPE_VSCALE);
+ gtk_style_context_save(context);
+
+ gtk_style_context_set_direction(context, gtkTextDirection(renderObject->style()->direction()));
+ gtk_style_context_add_class(context, GTK_STYLE_CLASS_SCALE);
+ gtk_style_context_add_class(context, GTK_STYLE_CLASS_SLIDER);
+
+ gint troughBorder;
+ gtk_style_context_get_style(context, "trough-border", &troughBorder, NULL);
+
+ IntRect sliderRect(rect);
+ sliderRect.inflate(-troughBorder);
+
+ guint flags = 0;
+ if (!isEnabled(renderObject) || isReadOnlyControl(renderObject))
+ flags |= GTK_STATE_FLAG_INSENSITIVE;
+ else if (isHovered(renderObject))
+ flags |= GTK_STATE_FLAG_PRELIGHT;
+ if (isPressed(renderObject))
+ flags |= GTK_STATE_FLAG_ACTIVE;
+ gtk_style_context_set_state(context, static_cast<GtkStateFlags>(flags));
+
+ gtk_render_slider(context, paintInfo.context->platformContext(), sliderRect.x(), sliderRect.y(), sliderRect.width(), sliderRect.height(),
+ part == SliderThumbHorizontalPart ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL);
+
+ gtk_style_context_restore(context);
+
+ return false;
+}
+
+void RenderThemeGtk::adjustSliderThumbSize(RenderObject* renderObject) const
+{
+ ControlPart part = renderObject->style()->appearance();
+#if ENABLE(VIDEO)
+ if (part == MediaSliderThumbPart || part == MediaVolumeSliderThumbPart) {
+ adjustMediaSliderThumbSize(renderObject);
+ return;
+ }
+#endif
+
+ gint sliderWidth, sliderLength;
+ gtk_style_context_get_style(getStyleContext(part == SliderThumbHorizontalPart ? GTK_TYPE_HSCALE : GTK_TYPE_VSCALE),
+ "slider-width", &sliderWidth,
+ "slider-length", &sliderLength,
+ NULL);
+ if (part == SliderThumbHorizontalPart) {
+ renderObject->style()->setWidth(Length(sliderLength, Fixed));
+ renderObject->style()->setHeight(Length(sliderWidth, Fixed));
+ return;
+ }
+ ASSERT(part == SliderThumbVerticalPart);
+ renderObject->style()->setWidth(Length(sliderWidth, Fixed));
+ renderObject->style()->setHeight(Length(sliderLength, Fixed));
+}
+
+#if ENABLE(PROGRESS_TAG)
+bool RenderThemeGtk::paintProgressBar(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ if (!renderObject->isProgress())
+ return true;
+
+ GtkWidget* progressBarWidget = moz_gtk_get_progress_widget();
+ if (!progressBarWidget)
+ return true;
+
+ if (paintRenderObject(MOZ_GTK_PROGRESSBAR, renderObject, paintInfo.context, rect))
+ return true;
+
+ IntRect chunkRect(rect);
+ RenderProgress* renderProgress = toRenderProgress(renderObject);
+
+ GtkStyle* style = gtk_widget_get_style(progressBarWidget);
+ chunkRect.setHeight(chunkRect.height() - (2 * style->ythickness));
+ chunkRect.setY(chunkRect.y() + style->ythickness);
+ chunkRect.setWidth((chunkRect.width() - (2 * style->xthickness)) * renderProgress->position());
+ if (renderObject->style()->direction() == RTL)
+ chunkRect.setX(rect.x() + rect.width() - chunkRect.width() - style->xthickness);
+ else
+ chunkRect.setX(chunkRect.x() + style->xthickness);
+
+ return paintRenderObject(MOZ_GTK_PROGRESS_CHUNK, renderObject, paintInfo.context, chunkRect);
+}
+#endif
+
+GRefPtr<GdkPixbuf> RenderThemeGtk::getStockIcon(GType widgetType, const char* iconName, gint direction, gint state, gint iconSize)
+{
+ GtkStyleContext* context = getStyleContext(widgetType);
+ GtkIconSet* iconSet = gtk_style_context_lookup_icon_set(context, iconName);
+
+ gtk_style_context_save(context);
+
+ guint flags = 0;
+ if (state == GTK_STATE_PRELIGHT)
+ flags |= GTK_STATE_FLAG_PRELIGHT;
+ else if (state == GTK_STATE_INSENSITIVE)
+ flags |= GTK_STATE_FLAG_INSENSITIVE;
+
+ gtk_style_context_set_state(context, static_cast<GtkStateFlags>(flags));
+ gtk_style_context_set_direction(context, static_cast<GtkTextDirection>(direction));
+ GdkPixbuf* icon = gtk_icon_set_render_icon_pixbuf(iconSet, context, static_cast<GtkIconSize>(iconSize));
+
+ gtk_style_context_restore(context);
+
+ return adoptGRef(icon);
+}
+
+Color RenderThemeGtk::platformActiveSelectionBackgroundColor() const
+{
+ GdkRGBA gdkRGBAColor;
+ gtk_style_context_get_background_color(getStyleContext(GTK_TYPE_ENTRY), GTK_STATE_FLAG_SELECTED, &gdkRGBAColor);
+ return gdkRGBAColor;
+}
+
+Color RenderThemeGtk::platformInactiveSelectionBackgroundColor() const
+{
+ GdkRGBA gdkRGBAColor;
+ gtk_style_context_get_background_color(getStyleContext(GTK_TYPE_ENTRY), GTK_STATE_FLAG_ACTIVE, &gdkRGBAColor);
+ return gdkRGBAColor;
+}
+
+Color RenderThemeGtk::platformActiveSelectionForegroundColor() const
+{
+ GdkRGBA gdkRGBAColor;
+ gtk_style_context_get_color(getStyleContext(GTK_TYPE_ENTRY), GTK_STATE_FLAG_SELECTED, &gdkRGBAColor);
+ return gdkRGBAColor;
+}
+
+Color RenderThemeGtk::platformInactiveSelectionForegroundColor() const
+{
+ GdkRGBA gdkRGBAColor;
+ gtk_style_context_get_color(getStyleContext(GTK_TYPE_ENTRY), GTK_STATE_FLAG_ACTIVE, &gdkRGBAColor);
+ return gdkRGBAColor;
+}
+
+Color RenderThemeGtk::activeListBoxSelectionBackgroundColor() const
+{
+ GdkRGBA gdkRGBAColor;
+ gtk_style_context_get_background_color(getStyleContext(GTK_TYPE_TREE_VIEW), GTK_STATE_FLAG_SELECTED, &gdkRGBAColor);
+ return gdkRGBAColor;
+}
+
+Color RenderThemeGtk::inactiveListBoxSelectionBackgroundColor() const
+{
+ GdkRGBA gdkRGBAColor;
+ gtk_style_context_get_background_color(getStyleContext(GTK_TYPE_TREE_VIEW), GTK_STATE_FLAG_ACTIVE, &gdkRGBAColor);
+ return gdkRGBAColor;
+}
+
+Color RenderThemeGtk::activeListBoxSelectionForegroundColor() const
+{
+ GdkRGBA gdkRGBAColor;
+ gtk_style_context_get_color(getStyleContext(GTK_TYPE_TREE_VIEW), GTK_STATE_FLAG_SELECTED, &gdkRGBAColor);
+ return gdkRGBAColor;
+}
+
+Color RenderThemeGtk::inactiveListBoxSelectionForegroundColor() const
+{
+ GdkRGBA gdkRGBAColor;
+ gtk_style_context_get_color(getStyleContext(GTK_TYPE_TREE_VIEW), GTK_STATE_FLAG_ACTIVE, &gdkRGBAColor);
+ return gdkRGBAColor;
+}
+
+Color RenderThemeGtk::systemColor(int cssValueId) const
+{
+ GdkRGBA gdkRGBAColor;
+
+ switch (cssValueId) {
+ case CSSValueButtontext:
+ gtk_style_context_get_color(getStyleContext(GTK_TYPE_BUTTON), static_cast<GtkStateFlags>(0), &gdkRGBAColor);
+ return gdkRGBAColor;
+ case CSSValueCaptiontext:
+ gtk_style_context_get_color(getStyleContext(GTK_TYPE_ENTRY), static_cast<GtkStateFlags>(0), &gdkRGBAColor);
+ return gdkRGBAColor;
+ default:
+ return RenderTheme::systemColor(cssValueId);
+ }
+}
+
+static void gtkStyleSetCallback(GtkWidget* widget, GtkStyle* previous, RenderTheme* renderTheme)
+{
+ // FIXME: Make sure this function doesn't get called many times for a single GTK+ style change signal.
+ renderTheme->platformColorsDidChange();
+}
+
+void RenderThemeGtk::setupWidgetAndAddToContainer(GtkWidget* widget, GtkWidget* window) const
+{
+ gtk_container_add(GTK_CONTAINER(window), widget);
+ gtk_widget_realize(widget);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
+
+ // FIXME: Perhaps this should only be called for the containing window or parent container.
+ g_signal_connect(widget, "style-set", G_CALLBACK(gtkStyleSetCallback), const_cast<RenderThemeGtk*>(this));
+}
+
+GtkWidget* RenderThemeGtk::gtkContainer() const
+{
+ if (m_gtkContainer)
+ return m_gtkContainer;
+
+ m_gtkWindow = gtk_window_new(GTK_WINDOW_POPUP);
+ gtk_widget_realize(m_gtkWindow);
+ gtk_widget_set_name(m_gtkWindow, "MozillaGtkWidget");
+
+ m_gtkContainer = gtk_fixed_new();
+ setupWidgetAndAddToContainer(m_gtkContainer, m_gtkWindow);
+ return m_gtkContainer;
+}
+
+GtkWidget* RenderThemeGtk::gtkButton() const
+{
+ if (m_gtkButton)
+ return m_gtkButton;
+ m_gtkButton = gtk_button_new();
+ setupWidgetAndAddToContainer(m_gtkButton, gtkContainer());
+ return m_gtkButton;
+}
+
+GtkWidget* RenderThemeGtk::gtkEntry() const
+{
+ if (m_gtkEntry)
+ return m_gtkEntry;
+ m_gtkEntry = gtk_entry_new();
+ setupWidgetAndAddToContainer(m_gtkEntry, gtkContainer());
+ return m_gtkEntry;
+}
+
+GtkWidget* RenderThemeGtk::gtkTreeView() const
+{
+ if (m_gtkTreeView)
+ return m_gtkTreeView;
+ m_gtkTreeView = gtk_tree_view_new();
+ setupWidgetAndAddToContainer(m_gtkTreeView, gtkContainer());
+ return m_gtkTreeView;
+}
+
+GtkWidget* RenderThemeGtk::gtkVScale() const
+{
+ if (m_gtkVScale)
+ return m_gtkVScale;
+ m_gtkVScale = gtk_vscale_new(0);
+ setupWidgetAndAddToContainer(m_gtkVScale, gtkContainer());
+ return m_gtkVScale;
+}
+
+GtkWidget* RenderThemeGtk::gtkHScale() const
+{
+ if (m_gtkHScale)
+ return m_gtkHScale;
+ m_gtkHScale = gtk_hscale_new(0);
+ setupWidgetAndAddToContainer(m_gtkHScale, gtkContainer());
+ return m_gtkHScale;
+}
+
+GtkStyleContext* RenderThemeGtk::gtkScrollbarStyle()
+{
+ return getStyleContext(GTK_TYPE_SCROLLBAR);
+}
+
+} // namespace WebCore
+
+#endif // !GTK_API_VERSION_2