e9178163cc470a4fdd599ba8b35da943ab147a5c
[WebKit-https.git] / Source / WebCore / platform / gtk / RenderThemeGtk2.cpp
1 /*
2  * Copyright (C) 2007 Apple Inc.
3  * Copyright (C) 2007 Alp Toker <alp@atoker.com>
4  * Copyright (C) 2008 Collabora Ltd.
5  * Copyright (C) 2009 Kenneth Rohde Christiansen
6  * Copyright (C) 2010 Igalia S.L.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  */
24
25 #include "config.h"
26 #include "RenderThemeGtk.h"
27
28 #ifdef GTK_API_VERSION_2
29
30 #include "CSSValueKeywords.h"
31 #include "GraphicsContext.h"
32 #include "GtkVersioning.h"
33 #include "HTMLNames.h"
34 #include "MediaControlElements.h"
35 #include "PaintInfo.h"
36 #include "RenderObject.h"
37 #include "TextDirection.h"
38 #include "UserAgentStyleSheets.h"
39 #include "WidgetRenderingContext.h"
40 #include "gtkdrawing.h"
41 #include <gdk/gdk.h>
42 #include <gtk/gtk.h>
43
44 #if ENABLE(PROGRESS_TAG)
45 #include "RenderProgress.h"
46 #endif
47
48 namespace WebCore {
49
50 // This is not a static method, because we want to avoid having GTK+ headers in RenderThemeGtk.h.
51 extern GtkTextDirection gtkTextDirection(TextDirection);
52
53 static int mozGtkRefCount = 0;
54 void RenderThemeGtk::platformInit()
55 {
56     m_themePartsHaveRGBAColormap = true;
57     m_gtkWindow = 0;
58     m_gtkContainer = 0;
59     m_gtkButton = 0;
60     m_gtkEntry = 0;
61     m_gtkTreeView = 0;
62     m_gtkVScale = 0;
63     m_gtkHScale = 0;
64     m_gtkRadioButton = 0;
65     m_gtkCheckButton = 0;
66
67     memset(&m_themeParts, 0, sizeof(GtkThemeParts));
68     GdkColormap* colormap = gdk_screen_get_rgba_colormap(gdk_screen_get_default());
69     if (!colormap) {
70         m_themePartsHaveRGBAColormap = false;
71         colormap = gdk_screen_get_default_colormap(gdk_screen_get_default());
72     }
73     m_themeParts.colormap = colormap;
74
75     // Initialize the Mozilla theme drawing code.
76     if (!mozGtkRefCount) {
77         moz_gtk_init();
78         moz_gtk_use_theme_parts(&m_themeParts);
79     }
80     ++mozGtkRefCount;
81 }
82
83 RenderThemeGtk::~RenderThemeGtk()
84 {
85     --mozGtkRefCount;
86
87     if (!mozGtkRefCount)
88         moz_gtk_shutdown();
89
90     if (m_gtkWindow)
91         gtk_widget_destroy(m_gtkWindow);
92 }
93
94 #if ENABLE(VIDEO)
95 void RenderThemeGtk::initMediaColors()
96 {
97     GtkStyle* style = gtk_widget_get_style(GTK_WIDGET(gtkContainer()));
98     m_panelColor = style->bg[GTK_STATE_NORMAL];
99     m_sliderColor = style->bg[GTK_STATE_ACTIVE];
100     m_sliderThumbColor = style->bg[GTK_STATE_SELECTED];
101 }
102 #endif
103
104 static void adjustRectForFocus(GtkWidget* widget, IntRect& rect, bool ignoreInteriorFocusProperty = false)
105 {
106     gint focusWidth, focusPad;
107     gboolean interiorFocus = 0;
108     gtk_widget_style_get(widget,
109                          "interior-focus", &interiorFocus,
110                          "focus-line-width", &focusWidth,
111                          "focus-padding", &focusPad, NULL);
112     if (!ignoreInteriorFocusProperty && interiorFocus)
113         return;
114     rect.inflate(focusWidth + focusPad);
115 }
116
117 void RenderThemeGtk::adjustRepaintRect(const RenderObject* renderObject, IntRect& rect)
118 {
119     ControlPart part = renderObject->style()->appearance();
120     switch (part) {
121     case CheckboxPart:
122     case RadioPart: {
123         // We ignore the interior focus property and always expand the focus rect. In GTK+, the
124         // focus indicator is usually on the text next to a checkbox or radio button, but that doesn't
125         // happen in WebCore. By expanding the focus rectangle unconditionally we increase its prominence.
126         adjustRectForFocus(part == CheckboxPart ? gtkCheckButton() : gtkRadioButton(), rect, true);
127         return;
128     }
129     default:
130         return;
131     }
132 }
133
134 static GtkStateType getGtkStateType(RenderThemeGtk* theme, RenderObject* object)
135 {
136     if (!theme->isEnabled(object) || theme->isReadOnlyControl(object))
137         return GTK_STATE_INSENSITIVE;
138     if (theme->isPressed(object))
139         return GTK_STATE_ACTIVE;
140     if (theme->isHovered(object))
141         return GTK_STATE_PRELIGHT;
142     return GTK_STATE_NORMAL;
143 }
144
145 bool RenderThemeGtk::paintRenderObject(GtkThemeWidgetType type, RenderObject* renderObject, GraphicsContext* context, const IntRect& rect, int flags)
146 {
147     // Painting is disabled so just claim to have succeeded
148     if (context->paintingDisabled())
149         return false;
150
151     GtkWidgetState widgetState;
152     widgetState.active = isPressed(renderObject);
153     widgetState.focused = isFocused(renderObject);
154
155     // https://bugs.webkit.org/show_bug.cgi?id=18364
156     // The Mozilla theme drawing code, only paints a button as pressed when it's pressed 
157     // while hovered. Until we move away from the Mozila code, work-around the issue by
158     // forcing a pressed button into the hovered state. This ensures that buttons activated
159     // via the keyboard have the proper rendering.
160     widgetState.inHover = isHovered(renderObject) || (type == MOZ_GTK_BUTTON && isPressed(renderObject));
161
162     // FIXME: Disabled does not always give the correct appearance for ReadOnly
163     widgetState.disabled = !isEnabled(renderObject) || isReadOnlyControl(renderObject);
164     widgetState.isDefault = false;
165     widgetState.canDefault = false;
166     widgetState.depressed = false;
167
168     WidgetRenderingContext widgetContext(context, rect);
169     return !widgetContext.paintMozillaWidget(type, &widgetState, flags,
170                                              gtkTextDirection(renderObject->style()->direction()));
171 }
172
173 static void setToggleSize(const RenderThemeGtk* theme, RenderStyle* style, GtkWidget* widget)
174 {
175     // The width and height are both specified, so we shouldn't change them.
176     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
177         return;
178
179     gint indicatorSize;
180     gtk_widget_style_get(widget, "indicator-size", &indicatorSize, NULL);
181     if (style->width().isIntrinsicOrAuto())
182         style->setWidth(Length(indicatorSize, Fixed));
183     if (style->height().isAuto())
184         style->setHeight(Length(indicatorSize, Fixed));
185 }
186
187 static void paintToggle(RenderThemeGtk* theme, RenderObject* renderObject, const PaintInfo& info, const IntRect& rect, GtkWidget* widget)
188 {
189     // We do not call gtk_toggle_button_set_active here, because some themes begin a series of
190     // animation frames in a "toggled" signal handler. This puts some checkboxes in a half-way
191     // checked state. Every GTK+ theme I tested merely looks at the shadow type (and not the
192     // 'active' property) to determine whether or not to draw the check.
193     gtk_widget_set_sensitive(widget, theme->isEnabled(renderObject) && !theme->isReadOnlyControl(renderObject));
194     gtk_widget_set_direction(widget, gtkTextDirection(renderObject->style()->direction()));
195
196     bool indeterminate = theme->isIndeterminate(renderObject);
197     gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(widget), indeterminate);
198
199     GtkShadowType shadowType = GTK_SHADOW_OUT;
200     if (indeterminate) // This originates from the Mozilla code.
201         shadowType = GTK_SHADOW_ETCHED_IN;
202     else if (theme->isChecked(renderObject))
203         shadowType = GTK_SHADOW_IN;
204
205     WidgetRenderingContext widgetContext(info.context, rect);
206     IntRect buttonRect(IntPoint(), rect.size());
207     GtkStateType toggleState = getGtkStateType(theme, renderObject);
208     const char* detail = 0;
209     if (GTK_IS_RADIO_BUTTON(widget)) {
210         detail = "radiobutton";
211         widgetContext.gtkPaintOption(buttonRect, widget, toggleState, shadowType, detail);
212     } else {
213         detail = "checkbutton";
214         widgetContext.gtkPaintCheck(buttonRect, widget, toggleState, shadowType, detail);
215     }
216
217     if (theme->isFocused(renderObject)) {
218         IntRect focusRect(buttonRect);
219         adjustRectForFocus(widget, focusRect, true);
220         widgetContext.gtkPaintFocus(focusRect, widget, toggleState, detail);
221     }
222 }
223
224 void RenderThemeGtk::setCheckboxSize(RenderStyle* style) const
225 {
226     setToggleSize(this, style, gtkCheckButton());
227 }
228
229 bool RenderThemeGtk::paintCheckbox(RenderObject* renderObject, const PaintInfo& info, const IntRect& rect)
230 {
231     paintToggle(this, renderObject, info, rect, gtkCheckButton());
232     return false;
233 }
234
235 void RenderThemeGtk::setRadioSize(RenderStyle* style) const
236 {
237     setToggleSize(this, style, gtkRadioButton());
238 }
239
240 bool RenderThemeGtk::paintRadio(RenderObject* renderObject, const PaintInfo& info, const IntRect& rect)
241 {
242     paintToggle(this, renderObject, info, rect, gtkRadioButton());
243     return false;
244 }
245
246 bool RenderThemeGtk::paintButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
247 {
248     if (info.context->paintingDisabled())
249         return false;
250
251     GtkWidget* widget = gtkButton();
252     IntRect buttonRect(IntPoint(), rect.size());
253     IntRect focusRect(buttonRect);
254
255     GtkStateType state = getGtkStateType(this, object);
256     gtk_widget_set_state(widget, state);
257     gtk_widget_set_direction(widget, gtkTextDirection(object->style()->direction()));
258
259     if (isFocused(object)) {
260         if (isEnabled(object)) {
261 #if !GTK_CHECK_VERSION(2, 22, 0)
262             GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
263 #endif
264             g_object_set(widget, "has-focus", TRUE, NULL);
265         }
266
267         gboolean interiorFocus = 0, focusWidth = 0, focusPadding = 0;
268         gtk_widget_style_get(widget,
269                              "interior-focus", &interiorFocus,
270                              "focus-line-width", &focusWidth,
271                              "focus-padding", &focusPadding, NULL);
272         // If we are using exterior focus, we shrink the button rect down before
273         // drawing. If we are using interior focus we shrink the focus rect. This
274         // approach originates from the Mozilla theme drawing code (gtk2drawing.c).
275         if (interiorFocus) {
276             GtkStyle* style = gtk_widget_get_style(widget);
277             focusRect.inflateX(-style->xthickness - focusPadding);
278             focusRect.inflateY(-style->ythickness - focusPadding);
279         } else {
280             buttonRect.inflateX(-focusWidth - focusPadding);
281             buttonRect.inflateY(-focusPadding - focusPadding);
282         }
283     }
284
285     WidgetRenderingContext widgetContext(info.context, rect);
286     GtkShadowType shadowType = state == GTK_STATE_ACTIVE ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
287     widgetContext.gtkPaintBox(buttonRect, widget, state, shadowType, "button");
288     if (isFocused(object))
289         widgetContext.gtkPaintFocus(focusRect, widget, state, "button");
290
291 #if !GTK_CHECK_VERSION(2, 22, 0)
292     GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
293 #endif
294     g_object_set(widget, "has-focus", FALSE, NULL);
295     return false;
296 }
297
298 static void getComboBoxPadding(RenderStyle* style, int& left, int& top, int& right, int& bottom)
299 {
300     // If this menu list button isn't drawn using the native theme, we
301     // don't add any extra padding beyond what WebCore already uses.
302     if (style->appearance() == NoControlPart)
303         return;
304     moz_gtk_get_widget_border(MOZ_GTK_DROPDOWN, &left, &top, &right, &bottom,
305                               gtkTextDirection(style->direction()), TRUE);
306 }
307
308 int RenderThemeGtk::popupInternalPaddingLeft(RenderStyle* style) const
309 {
310     int left = 0, top = 0, right = 0, bottom = 0;
311     getComboBoxPadding(style, left, top, right, bottom);
312     return left;
313 }
314
315 int RenderThemeGtk::popupInternalPaddingRight(RenderStyle* style) const
316 {
317     int left = 0, top = 0, right = 0, bottom = 0;
318     getComboBoxPadding(style, left, top, right, bottom);
319     return right;
320 }
321
322 int RenderThemeGtk::popupInternalPaddingTop(RenderStyle* style) const
323 {
324     int left = 0, top = 0, right = 0, bottom = 0;
325     getComboBoxPadding(style, left, top, right, bottom);
326     return top;
327 }
328
329 int RenderThemeGtk::popupInternalPaddingBottom(RenderStyle* style) const
330 {
331     int left = 0, top = 0, right = 0, bottom = 0;
332     getComboBoxPadding(style, left, top, right, bottom);
333     return bottom;
334 }
335
336 bool RenderThemeGtk::paintMenuList(RenderObject* object, const PaintInfo& info, const IntRect& rect)
337 {
338     return paintRenderObject(MOZ_GTK_DROPDOWN, object, info.context, rect);
339 }
340
341 bool RenderThemeGtk::paintTextField(RenderObject* object, const PaintInfo& info, const IntRect& rect)
342 {
343     return paintRenderObject(MOZ_GTK_ENTRY, object, info.context, rect);
344 }
345
346 bool RenderThemeGtk::paintSliderTrack(RenderObject* object, const PaintInfo& info, const IntRect& rect)
347 {
348     if (info.context->paintingDisabled())
349         return false;
350
351     ControlPart part = object->style()->appearance();
352     ASSERT(part == SliderHorizontalPart || part == SliderVerticalPart || part == MediaVolumeSliderPart);
353
354     // We shrink the trough rect slightly to make room for the focus indicator.
355     IntRect troughRect(IntPoint(), rect.size()); // This is relative to rect.
356     GtkWidget* widget = 0;
357     if (part == SliderHorizontalPart) {
358         widget = gtkHScale();
359         troughRect.inflateX(-gtk_widget_get_style(widget)->xthickness);
360     } else {
361         widget = gtkVScale();
362         troughRect.inflateY(-gtk_widget_get_style(widget)->ythickness);
363     }
364     gtk_widget_set_direction(widget, gtkTextDirection(object->style()->direction()));
365
366     WidgetRenderingContext widgetContext(info.context, rect);
367     widgetContext.gtkPaintBox(troughRect, widget, GTK_STATE_ACTIVE, GTK_SHADOW_OUT, "trough");
368     if (isFocused(object))
369         widgetContext.gtkPaintFocus(IntRect(IntPoint(), rect.size()), widget, getGtkStateType(this, object), "trough");
370
371     return false;
372 }
373
374 bool RenderThemeGtk::paintSliderThumb(RenderObject* object, const PaintInfo& info, const IntRect& rect)
375 {
376     if (info.context->paintingDisabled())
377         return false;
378
379     ControlPart part = object->style()->appearance();
380     ASSERT(part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart || part == MediaVolumeSliderThumbPart);
381
382     GtkWidget* widget = 0;
383     const char* detail = 0;
384     GtkOrientation orientation;
385     if (part == SliderThumbHorizontalPart) {
386         widget = gtkHScale();
387         detail = "hscale";
388         orientation = GTK_ORIENTATION_HORIZONTAL;
389     } else {
390         widget = gtkVScale();
391         detail = "vscale";
392         orientation = GTK_ORIENTATION_VERTICAL;
393     }
394     gtk_widget_set_direction(widget, gtkTextDirection(object->style()->direction()));
395
396     // Only some themes have slider thumbs respond to clicks and some don't. This information is
397     // gathered via the 'activate-slider' property, but it's deprecated in GTK+ 2.22 and removed in
398     // GTK+ 3.x. The drawback of not honoring it is that slider thumbs change color when you click
399     // on them. 
400     IntRect thumbRect(IntPoint(), rect.size());
401     WidgetRenderingContext widgetContext(info.context, rect);
402     widgetContext.gtkPaintSlider(thumbRect, widget, getGtkStateType(this, object), GTK_SHADOW_OUT, detail, orientation);
403     return false;
404 }
405
406 void RenderThemeGtk::adjustSliderThumbSize(RenderObject* o) const
407 {
408     ControlPart part = o->style()->appearance();
409 #if ENABLE(VIDEO)
410     if (part == MediaSliderThumbPart) {
411         adjustMediaSliderThumbSize(o);
412         return;
413     }
414 #endif
415
416     GtkWidget* widget = part == SliderThumbHorizontalPart ? gtkHScale() : gtkVScale();
417     int length = 0, width = 0;
418     gtk_widget_style_get(widget,
419                          "slider_length", &length,
420                          "slider_width", &width,
421                          NULL);
422
423     if (part == SliderThumbHorizontalPart) {
424         o->style()->setWidth(Length(length, Fixed));
425         o->style()->setHeight(Length(width, Fixed));
426         return;
427     }
428     ASSERT(part == SliderThumbVerticalPart || part == MediaVolumeSliderThumbPart);
429     o->style()->setWidth(Length(width, Fixed));
430     o->style()->setHeight(Length(length, Fixed));
431 }
432
433 #if ENABLE(PROGRESS_TAG)
434 double RenderThemeGtk::animationRepeatIntervalForProgressBar(RenderProgress*) const
435 {
436     // FIXME: It doesn't look like there is a good way yet to support animated
437     // progress bars with the Mozilla theme drawing code.
438     return 0;
439 }
440
441 double RenderThemeGtk::animationDurationForProgressBar(RenderProgress*) const
442 {
443     // FIXME: It doesn't look like there is a good way yet to support animated
444     // progress bars with the Mozilla theme drawing code.
445     return 0;
446 }
447
448 bool RenderThemeGtk::paintProgressBar(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
449 {
450     if (!renderObject->isProgress())
451         return true;
452
453     GtkWidget* progressBarWidget = moz_gtk_get_progress_widget();
454     if (!progressBarWidget)
455         return true;
456
457     if (paintRenderObject(MOZ_GTK_PROGRESSBAR, renderObject, paintInfo.context, rect))
458         return true;
459
460     IntRect chunkRect(rect);
461     RenderProgress* renderProgress = toRenderProgress(renderObject);
462
463     GtkStyle* style = gtk_widget_get_style(progressBarWidget);
464     chunkRect.setHeight(chunkRect.height() - (2 * style->ythickness));
465     chunkRect.setY(chunkRect.y() + style->ythickness);
466     chunkRect.setWidth((chunkRect.width() - (2 * style->xthickness)) * renderProgress->position());
467     if (renderObject->style()->direction() == RTL)
468         chunkRect.setX(rect.x() + rect.width() - chunkRect.width() - style->xthickness);
469     else
470         chunkRect.setX(chunkRect.x() + style->xthickness);
471
472     return paintRenderObject(MOZ_GTK_PROGRESS_CHUNK, renderObject, paintInfo.context, chunkRect);
473 }
474 #endif
475
476 GRefPtr<GdkPixbuf> RenderThemeGtk::getStockIcon(GType widgetType, const char* iconName, gint direction, gint state, gint iconSize)
477 {
478     ASSERT(widgetType == GTK_TYPE_CONTAINER || widgetType == GTK_TYPE_ENTRY);
479     GtkWidget* widget = widgetType == GTK_TYPE_CONTAINER ? GTK_WIDGET(gtkContainer()) : gtkEntry();
480     GtkStyle* style = gtk_widget_get_style(widget);
481     GtkIconSet* iconSet = gtk_style_lookup_icon_set(style, iconName);
482     return adoptGRef(gtk_icon_set_render_icon(iconSet, style,
483                                               static_cast<GtkTextDirection>(direction),
484                                               static_cast<GtkStateType>(state),
485                                               static_cast<GtkIconSize>(iconSize), 0, 0));
486 }
487
488
489 Color RenderThemeGtk::platformActiveSelectionBackgroundColor() const
490 {
491     GtkWidget* widget = gtkEntry();
492     return gtk_widget_get_style(widget)->base[GTK_STATE_SELECTED];
493 }
494
495 Color RenderThemeGtk::platformInactiveSelectionBackgroundColor() const
496 {
497     GtkWidget* widget = gtkEntry();
498     return gtk_widget_get_style(widget)->base[GTK_STATE_ACTIVE];
499 }
500
501 Color RenderThemeGtk::platformActiveSelectionForegroundColor() const
502 {
503     GtkWidget* widget = gtkEntry();
504     return gtk_widget_get_style(widget)->text[GTK_STATE_SELECTED];
505 }
506
507 Color RenderThemeGtk::platformInactiveSelectionForegroundColor() const
508 {
509     GtkWidget* widget = gtkEntry();
510     return gtk_widget_get_style(widget)->text[GTK_STATE_ACTIVE];
511 }
512
513 Color RenderThemeGtk::activeListBoxSelectionBackgroundColor() const
514 {
515     GtkWidget* widget = gtkTreeView();
516     return gtk_widget_get_style(widget)->base[GTK_STATE_SELECTED];
517 }
518
519 Color RenderThemeGtk::inactiveListBoxSelectionBackgroundColor() const
520 {
521     GtkWidget* widget = gtkTreeView();
522     return gtk_widget_get_style(widget)->base[GTK_STATE_ACTIVE];
523 }
524
525 Color RenderThemeGtk::activeListBoxSelectionForegroundColor() const
526 {
527     GtkWidget* widget = gtkTreeView();
528     return gtk_widget_get_style(widget)->text[GTK_STATE_SELECTED];
529 }
530
531 Color RenderThemeGtk::inactiveListBoxSelectionForegroundColor() const
532 {
533     GtkWidget* widget = gtkTreeView();
534     return gtk_widget_get_style(widget)->text[GTK_STATE_ACTIVE];
535 }
536
537 Color RenderThemeGtk::systemColor(int cssValueId) const
538 {
539     switch (cssValueId) {
540     case CSSValueButtontext:
541         return Color(gtk_widget_get_style(gtkButton())->fg[GTK_STATE_NORMAL]);
542     case CSSValueCaptiontext:
543         return Color(gtk_widget_get_style(gtkEntry())->fg[GTK_STATE_NORMAL]);
544     default:
545         return RenderTheme::systemColor(cssValueId);
546     }
547 }
548
549 static void gtkStyleSetCallback(GtkWidget* widget, GtkStyle* previous, RenderTheme* renderTheme)
550 {
551     // FIXME: Make sure this function doesn't get called many times for a single GTK+ style change signal.
552     renderTheme->platformColorsDidChange();
553 }
554
555 void RenderThemeGtk::setupWidgetAndAddToContainer(GtkWidget* widget, GtkWidget* window) const
556 {
557     gtk_container_add(GTK_CONTAINER(window), widget);
558     gtk_widget_realize(widget);
559     g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
560
561     // FIXME: Perhaps this should only be called for the containing window or parent container.
562     g_signal_connect(widget, "style-set", G_CALLBACK(gtkStyleSetCallback), const_cast<RenderThemeGtk*>(this));
563 }
564
565 GtkWidget* RenderThemeGtk::gtkContainer() const
566 {
567     if (m_gtkContainer)
568         return m_gtkContainer;
569
570     m_gtkWindow = gtk_window_new(GTK_WINDOW_POPUP);
571     gtk_widget_set_colormap(m_gtkWindow, m_themeParts.colormap);
572     gtk_widget_realize(m_gtkWindow);
573     gtk_widget_set_name(m_gtkWindow, "MozillaGtkWidget");
574
575     m_gtkContainer = gtk_fixed_new();
576     setupWidgetAndAddToContainer(m_gtkContainer, m_gtkWindow);
577     return m_gtkContainer;
578 }
579
580 GtkWidget* RenderThemeGtk::gtkButton() const
581 {
582     if (m_gtkButton)
583         return m_gtkButton;
584     m_gtkButton = gtk_button_new();
585     setupWidgetAndAddToContainer(m_gtkButton, gtkContainer());
586     return m_gtkButton;
587 }
588
589 GtkWidget* RenderThemeGtk::gtkEntry() const
590 {
591     if (m_gtkEntry)
592         return m_gtkEntry;
593     m_gtkEntry = gtk_entry_new();
594     setupWidgetAndAddToContainer(m_gtkEntry, gtkContainer());
595     return m_gtkEntry;
596 }
597
598 GtkWidget* RenderThemeGtk::gtkTreeView() const
599 {
600     if (m_gtkTreeView)
601         return m_gtkTreeView;
602     m_gtkTreeView = gtk_tree_view_new();
603     setupWidgetAndAddToContainer(m_gtkTreeView, gtkContainer());
604     return m_gtkTreeView;
605 }
606
607 GtkWidget* RenderThemeGtk::gtkVScale() const
608 {
609     if (m_gtkVScale)
610         return m_gtkVScale;
611     m_gtkVScale = gtk_vscale_new(0);
612     setupWidgetAndAddToContainer(m_gtkVScale, gtkContainer());
613     return m_gtkVScale;
614 }
615
616 GtkWidget* RenderThemeGtk::gtkHScale() const
617 {
618     if (m_gtkHScale)
619         return m_gtkHScale;
620     m_gtkHScale = gtk_hscale_new(0);
621     setupWidgetAndAddToContainer(m_gtkHScale, gtkContainer());
622     return m_gtkHScale;
623 }
624
625 GtkWidget* RenderThemeGtk::gtkRadioButton() const
626 {
627     if (m_gtkRadioButton)
628         return m_gtkRadioButton;
629     m_gtkRadioButton = gtk_radio_button_new(0);
630     setupWidgetAndAddToContainer(m_gtkRadioButton, gtkContainer());
631     return m_gtkRadioButton;
632 }
633
634 GtkWidget* RenderThemeGtk::gtkCheckButton() const
635 {
636     if (m_gtkCheckButton)
637         return m_gtkCheckButton;
638     m_gtkCheckButton = gtk_check_button_new();
639     setupWidgetAndAddToContainer(m_gtkCheckButton, gtkContainer());
640     return m_gtkCheckButton;
641 }
642
643 GtkWidget* RenderThemeGtk::gtkScrollbar()
644 {
645     return moz_gtk_get_scrollbar_widget();
646 }
647
648 } // namespace WebCore
649
650 #endif // GTK_API_VERSION_2