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.
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.
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.
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.
26 #include "RenderThemeGtk.h"
28 #include "CSSValueKeywords.h"
29 #include "ExceptionCodePlaceholder.h"
31 #include "FileSystem.h"
32 #include "FontDescription.h"
34 #include "GraphicsContext.h"
35 #include "GtkVersioning.h"
36 #include "HTMLMediaElement.h"
37 #include "LocalizedStrings.h"
38 #include "MediaControlElements.h"
39 #include "NamedNodeMap.h"
40 #include "PaintInfo.h"
41 #include "PlatformContextCairo.h"
42 #include "RenderBox.h"
43 #include "RenderObject.h"
44 #include "RenderProgress.h"
45 #include "StringTruncator.h"
46 #include "TimeRanges.h"
47 #include "UserAgentScripts.h"
48 #include "UserAgentStyleSheets.h"
53 #include <wtf/gobject/GUniquePtr.h>
54 #include <wtf/text/CString.h>
55 #include <wtf/text/StringBuilder.h>
59 // This would be a static method, except that forward declaring GType is tricky, since its
60 // definition depends on including glib.h, negating the benefit of using a forward declaration.
61 extern GRefPtr<GdkPixbuf> getStockIconForWidgetType(GType, const char* iconName, gint direction, gint state, gint iconSize);
62 extern GRefPtr<GdkPixbuf> getStockSymbolicIconForWidgetType(GType widgetType, const char* symbolicIconName, const char* fallbackStockIconName, gint direction, gint state, gint iconSize);
65 static HTMLMediaElement* getMediaElementFromRenderObject(const RenderObject& o)
67 Node* node = o.node();
68 Node* mediaNode = node ? node->shadowHost() : 0;
71 if (!mediaNode || !mediaNode->isElementNode() || !toElement(mediaNode)->isMediaElement())
74 return toHTMLMediaElement(mediaNode);
77 void RenderThemeGtk::initMediaButtons()
79 static bool iconsInitialized = false;
84 GRefPtr<GtkIconFactory> iconFactory = adoptGRef(gtk_icon_factory_new());
85 GtkIconSource* iconSource = gtk_icon_source_new();
86 const char* icons[] = { "audio-volume-high", "audio-volume-muted" };
88 gtk_icon_factory_add_default(iconFactory.get());
90 for (size_t i = 0; i < G_N_ELEMENTS(icons); ++i) {
91 gtk_icon_source_set_icon_name(iconSource, icons[i]);
92 GtkIconSet* iconSet = gtk_icon_set_new();
93 gtk_icon_set_add_source(iconSet, iconSource);
94 gtk_icon_factory_add(iconFactory.get(), icons[i], iconSet);
95 gtk_icon_set_unref(iconSet);
98 gtk_icon_source_free(iconSource);
100 iconsInitialized = true;
104 static bool nodeHasPseudo(Node* node, const char* pseudo)
106 RefPtr<Node> attributeNode = node->attributes()->getNamedItem("pseudo");
108 return attributeNode ? attributeNode->nodeValue() == pseudo : false;
111 static bool nodeHasClass(Node* node, const char* className)
113 if (!node->isElementNode())
116 Element* element = toElement(node);
118 if (!element->hasClass())
121 return element->classNames().contains(className);
124 PassRefPtr<RenderTheme> RenderThemeGtk::create()
126 return adoptRef(new RenderThemeGtk());
129 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page*)
131 static RenderTheme* rt = RenderThemeGtk::create().leakRef();
135 RenderThemeGtk::RenderThemeGtk()
136 : m_panelColor(Color::white)
137 , m_sliderColor(Color::white)
138 , m_sliderThumbColor(Color::white)
139 , m_mediaIconSize(16)
140 , m_mediaSliderHeight(14)
149 static bool supportsFocus(ControlPart appearance)
151 switch (appearance) {
156 case SearchFieldPart:
160 case SliderHorizontalPart:
161 case SliderVerticalPart:
168 bool RenderThemeGtk::supportsFocusRing(const RenderStyle* style) const
170 return supportsFocus(style->appearance());
173 bool RenderThemeGtk::controlSupportsTints(const RenderObject& o) const
178 int RenderThemeGtk::baselinePosition(const RenderObject& o) const
183 // FIXME: This strategy is possibly incorrect for the GTK+ port.
184 if (o.style().appearance() == CheckboxPart
185 || o.style().appearance() == RadioPart) {
186 const RenderBox* box = toRenderBox(&o);
187 return box->marginTop() + box->height() - 2;
190 return RenderTheme::baselinePosition(o);
193 // This is used in RenderThemeGtk2 and RenderThemeGtk3. Normally, it would be in
194 // the RenderThemeGtk header (perhaps as a static method), but we want to avoid
195 // having to include GTK+ headers only for the GtkTextDirection enum.
196 GtkTextDirection gtkTextDirection(TextDirection direction)
200 return GTK_TEXT_DIR_RTL;
202 return GTK_TEXT_DIR_LTR;
204 return GTK_TEXT_DIR_NONE;
208 static GtkStateType gtkIconState(RenderTheme* theme, const RenderObject& renderObject)
210 if (!theme->isEnabled(renderObject))
211 return GTK_STATE_INSENSITIVE;
212 if (theme->isPressed(renderObject))
213 return GTK_STATE_ACTIVE;
214 if (theme->isHovered(renderObject))
215 return GTK_STATE_PRELIGHT;
217 return GTK_STATE_NORMAL;
220 void RenderThemeGtk::adjustButtonStyle(StyleResolver*, RenderStyle* style, WebCore::Element*) const
222 // Some layout tests check explicitly that buttons ignore line-height.
223 if (style->appearance() == PushButtonPart)
224 style->setLineHeight(RenderStyle::initialLineHeight());
227 void RenderThemeGtk::adjustMenuListStyle(StyleResolver*, RenderStyle* style, Element*) const
229 // The tests check explicitly that select menu buttons ignore line height.
230 style->setLineHeight(RenderStyle::initialLineHeight());
232 // We cannot give a proper rendering when border radius is active, unfortunately.
233 style->resetBorderRadius();
236 void RenderThemeGtk::adjustMenuListButtonStyle(StyleResolver& styleResolver, RenderStyle& style, Element& e) const
238 adjustMenuListStyle(&styleResolver, &style, &e);
241 bool RenderThemeGtk::paintMenuListButtonDecorations(const RenderObject& object, const PaintInfo& info, const FloatRect& rect)
243 return paintMenuList(object, info, rect);
246 bool RenderThemeGtk::paintTextArea(const RenderObject& o, const PaintInfo& i, const FloatRect& r)
248 return paintTextField(o, i, r);
251 static void paintGdkPixbuf(GraphicsContext* context, const GdkPixbuf* icon, const IntRect& iconRect)
253 IntSize iconSize(gdk_pixbuf_get_width(icon), gdk_pixbuf_get_height(icon));
254 GRefPtr<GdkPixbuf> scaledIcon;
255 if (iconRect.size() != iconSize) {
256 // We could use cairo_scale() here but cairo/pixman downscale quality is quite bad.
257 scaledIcon = adoptGRef(gdk_pixbuf_scale_simple(icon, iconRect.width(), iconRect.height(),
258 GDK_INTERP_BILINEAR));
259 icon = scaledIcon.get();
262 cairo_t* cr = context->platformContext()->cr();
264 gdk_cairo_set_source_pixbuf(cr, icon, iconRect.x(), iconRect.y());
269 // Defined in GTK+ (gtk/gtkiconfactory.c)
270 static const gint gtkIconSizeMenu = 16;
271 static const gint gtkIconSizeSmallToolbar = 18;
272 static const gint gtkIconSizeButton = 20;
273 static const gint gtkIconSizeLargeToolbar = 24;
274 static const gint gtkIconSizeDnd = 32;
275 static const gint gtkIconSizeDialog = 48;
277 static GtkIconSize getIconSizeForPixelSize(gint pixelSize)
279 if (pixelSize < gtkIconSizeSmallToolbar)
280 return GTK_ICON_SIZE_MENU;
281 if (pixelSize >= gtkIconSizeSmallToolbar && pixelSize < gtkIconSizeButton)
282 return GTK_ICON_SIZE_SMALL_TOOLBAR;
283 if (pixelSize >= gtkIconSizeButton && pixelSize < gtkIconSizeLargeToolbar)
284 return GTK_ICON_SIZE_BUTTON;
285 if (pixelSize >= gtkIconSizeLargeToolbar && pixelSize < gtkIconSizeDnd)
286 return GTK_ICON_SIZE_LARGE_TOOLBAR;
287 if (pixelSize >= gtkIconSizeDnd && pixelSize < gtkIconSizeDialog)
288 return GTK_ICON_SIZE_DND;
290 return GTK_ICON_SIZE_DIALOG;
293 void RenderThemeGtk::adjustSearchFieldResultsButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
295 adjustSearchFieldCancelButtonStyle(styleResolver, style, e);
298 bool RenderThemeGtk::paintSearchFieldResultsButton(const RenderObject& o, const PaintInfo& i, const IntRect& rect)
300 return paintSearchFieldResultsDecorationPart(o, i, rect);
303 static void adjustSearchFieldIconStyle(RenderStyle* style)
305 style->resetBorder();
306 style->resetPadding();
308 // Get the icon size based on the font size.
309 int fontSize = style->fontSize();
310 if (fontSize < gtkIconSizeMenu) {
311 style->setWidth(Length(fontSize, Fixed));
312 style->setHeight(Length(fontSize, Fixed));
315 gint width = 0, height = 0;
316 gtk_icon_size_lookup(getIconSizeForPixelSize(fontSize), &width, &height);
317 style->setWidth(Length(width, Fixed));
318 style->setHeight(Length(height, Fixed));
321 void RenderThemeGtk::adjustSearchFieldResultsDecorationPartStyle(StyleResolver*, RenderStyle* style, Element*) const
323 adjustSearchFieldIconStyle(style);
326 static IntRect centerRectVerticallyInParentInputElement(const RenderObject& renderObject, const IntRect& rect)
328 // Get the renderer of <input> element.
329 Node* input = renderObject.node()->shadowHost();
331 input = renderObject.node();
332 if (!input->renderer()->isBox())
335 // If possible center the y-coordinate of the rect vertically in the parent input element.
336 // We also add one pixel here to ensure that the y coordinate is rounded up for box heights
337 // that are even, which looks in relation to the box text.
338 IntRect inputContentBox = toRenderBox(input->renderer())->absoluteContentBox();
340 // Make sure the scaled decoration stays square and will fit in its parent's box.
341 int iconSize = std::min(inputContentBox.width(), std::min(inputContentBox.height(), rect.height()));
342 IntRect scaledRect(rect.x(), inputContentBox.y() + (inputContentBox.height() - iconSize + 1) / 2, iconSize, iconSize);
346 bool RenderThemeGtk::paintSearchFieldResultsDecorationPart(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
348 IntRect iconRect = centerRectVerticallyInParentInputElement(renderObject, rect);
349 if (iconRect.isEmpty())
352 GRefPtr<GdkPixbuf> icon = getStockIconForWidgetType(GTK_TYPE_ENTRY, GTK_STOCK_FIND,
353 gtkTextDirection(renderObject.style().direction()),
354 gtkIconState(this, renderObject),
355 getIconSizeForPixelSize(rect.height()));
356 paintGdkPixbuf(paintInfo.context, icon.get(), iconRect);
360 void RenderThemeGtk::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
362 adjustSearchFieldIconStyle(style);
365 bool RenderThemeGtk::paintSearchFieldCancelButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
367 IntRect iconRect = centerRectVerticallyInParentInputElement(renderObject, rect);
368 if (iconRect.isEmpty())
371 GRefPtr<GdkPixbuf> icon = getStockIconForWidgetType(GTK_TYPE_ENTRY, GTK_STOCK_CLEAR,
372 gtkTextDirection(renderObject.style().direction()),
373 gtkIconState(this, renderObject),
374 getIconSizeForPixelSize(rect.height()));
375 paintGdkPixbuf(paintInfo.context, icon.get(), iconRect);
379 void RenderThemeGtk::adjustSearchFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
381 // We cannot give a proper rendering when border radius is active, unfortunately.
382 style->resetBorderRadius();
383 style->setLineHeight(RenderStyle::initialLineHeight());
386 bool RenderThemeGtk::paintSearchField(const RenderObject& o, const PaintInfo& i, const IntRect& rect)
388 return paintTextField(o, i, rect);
391 bool RenderThemeGtk::paintCapsLockIndicator(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
393 // The other paint methods don't need to check whether painting is disabled because RenderTheme already checks it
394 // before calling them, but paintCapsLockIndicator() is called by RenderTextControlSingleLine which doesn't check it.
395 if (paintInfo.context->paintingDisabled())
398 int iconSize = std::min(rect.width(), rect.height());
399 GRefPtr<GdkPixbuf> icon = getStockIconForWidgetType(GTK_TYPE_ENTRY, GTK_STOCK_CAPS_LOCK_WARNING, gtkTextDirection(renderObject.style().direction()), 0, getIconSizeForPixelSize(iconSize));
401 // Only re-scale the icon when it's smaller than the minimum icon size.
402 if (iconSize >= gtkIconSizeMenu)
403 iconSize = gdk_pixbuf_get_height(icon.get());
405 // GTK+ locates the icon right aligned in the entry. The given rectangle is already
406 // centered vertically by RenderTextControlSingleLine.
407 IntRect iconRect(rect.x() + rect.width() - iconSize,
408 rect.y() + (rect.height() - iconSize) / 2,
410 paintGdkPixbuf(paintInfo.context, icon.get(), iconRect);
414 void RenderThemeGtk::adjustSliderTrackStyle(StyleResolver*, RenderStyle* style, Element*) const
416 style->setBoxShadow(nullptr);
419 void RenderThemeGtk::adjustSliderThumbStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
421 RenderTheme::adjustSliderThumbStyle(styleResolver, style, element);
422 style->setBoxShadow(nullptr);
425 double RenderThemeGtk::caretBlinkInterval() const
427 GtkSettings* settings = gtk_settings_get_default();
429 gboolean shouldBlink;
432 g_object_get(settings, "gtk-cursor-blink", &shouldBlink, "gtk-cursor-blink-time", &time, NULL);
440 double RenderThemeGtk::getScreenDPI()
442 // FIXME: Really this should be the widget's screen.
443 GdkScreen* screen = gdk_screen_get_default();
445 return 96; // Default to 96 DPI.
447 float dpi = gdk_screen_get_resolution(screen);
453 void RenderThemeGtk::systemFont(CSSValueID, FontDescription& fontDescription) const
455 GtkSettings* settings = gtk_settings_get_default();
459 // This will be a font selection string like "Sans 10" so we cannot use it as the family name.
460 GUniqueOutPtr<gchar> fontName;
461 g_object_get(settings, "gtk-font-name", &fontName.outPtr(), NULL);
463 PangoFontDescription* pangoDescription = pango_font_description_from_string(fontName.get());
464 if (!pangoDescription)
467 fontDescription.setOneFamily(pango_font_description_get_family(pangoDescription));
469 int size = pango_font_description_get_size(pangoDescription) / PANGO_SCALE;
470 // If the size of the font is in points, we need to convert it to pixels.
471 if (!pango_font_description_get_size_is_absolute(pangoDescription))
472 size = size * (getScreenDPI() / 72.0);
474 fontDescription.setSpecifiedSize(size);
475 fontDescription.setIsAbsoluteSize(true);
476 fontDescription.setGenericFamily(FontDescription::NoFamily);
477 fontDescription.setWeight(FontWeightNormal);
478 fontDescription.setItalic(false);
479 pango_font_description_free(pangoDescription);
482 void RenderThemeGtk::platformColorsDidChange()
487 RenderTheme::platformColorsDidChange();
491 String RenderThemeGtk::extraMediaControlsStyleSheet()
493 return String(mediaControlsGtkUserAgentStyleSheet, sizeof(mediaControlsGtkUserAgentStyleSheet));
496 #if ENABLE(FULLSCREEN_API)
497 String RenderThemeGtk::extraFullScreenStyleSheet()
503 bool RenderThemeGtk::paintMediaButton(const RenderObject& renderObject, GraphicsContext* context, const IntRect& rect, const char* symbolicIconName, const char* fallbackStockIconName)
505 IntRect iconRect(rect.x() + (rect.width() - m_mediaIconSize) / 2,
506 rect.y() + (rect.height() - m_mediaIconSize) / 2,
507 m_mediaIconSize, m_mediaIconSize);
508 GRefPtr<GdkPixbuf> icon = getStockSymbolicIconForWidgetType(GTK_TYPE_CONTAINER, symbolicIconName, fallbackStockIconName,
509 gtkTextDirection(renderObject.style().direction()), gtkIconState(this, renderObject), iconRect.width());
510 paintGdkPixbuf(context, icon.get(), iconRect);
514 bool RenderThemeGtk::hasOwnDisabledStateHandlingFor(ControlPart part) const
516 return (part != MediaMuteButtonPart);
519 bool RenderThemeGtk::paintMediaFullscreenButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
521 return paintMediaButton(renderObject, paintInfo.context, rect, "view-fullscreen-symbolic", GTK_STOCK_FULLSCREEN);
524 bool RenderThemeGtk::paintMediaMuteButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
526 HTMLMediaElement* mediaElement = getMediaElementFromRenderObject(renderObject);
530 bool muted = mediaElement->muted();
531 return paintMediaButton(renderObject, paintInfo.context, rect,
532 muted ? "audio-volume-muted-symbolic" : "audio-volume-high-symbolic",
533 muted ? "audio-volume-muted" : "audio-volume-high");
536 bool RenderThemeGtk::paintMediaPlayButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
538 Node* node = renderObject.node();
542 if (!nodeHasPseudo(node, "-webkit-media-controls-play-button"))
544 bool showPlayButton = nodeHasClass(node, "paused");
546 return paintMediaButton(renderObject, paintInfo.context, rect,
547 showPlayButton ? "media-playback-start-symbolic" : "media-playback-pause-symbolic",
548 showPlayButton ? GTK_STOCK_MEDIA_PLAY : GTK_STOCK_MEDIA_PAUSE);
551 bool RenderThemeGtk::paintMediaSeekBackButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
553 return paintMediaButton(renderObject, paintInfo.context, rect, "media-seek-backward-symbolic", GTK_STOCK_MEDIA_REWIND);
556 bool RenderThemeGtk::paintMediaSeekForwardButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
558 return paintMediaButton(renderObject, paintInfo.context, rect, "media-seek-forward-symbolic", GTK_STOCK_MEDIA_FORWARD);
561 #if ENABLE(VIDEO_TRACK)
562 bool RenderThemeGtk::paintMediaToggleClosedCaptionsButton(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
564 IntRect iconRect(rect.x() + (rect.width() - m_mediaIconSize) / 2, rect.y() + (rect.height() - m_mediaIconSize) / 2,
565 m_mediaIconSize, m_mediaIconSize);
566 GRefPtr<GdkPixbuf> icon = getStockSymbolicIconForWidgetType(GTK_TYPE_CONTAINER, "media-view-subtitles-symbolic", nullptr,
567 gtkTextDirection(renderObject.style().direction()), gtkIconState(this, renderObject), iconRect.width());
569 icon = getStockSymbolicIconForWidgetType(GTK_TYPE_CONTAINER, "user-invisible-symbolic", GTK_STOCK_JUSTIFY_FILL,
570 gtkTextDirection(renderObject.style().direction()), gtkIconState(this, renderObject), iconRect.width());
571 paintGdkPixbuf(paintInfo.context, icon.get(), iconRect);
576 static FloatRoundedRect::Radii borderRadiiFromStyle(RenderStyle* style)
578 return FloatRoundedRect::Radii(
579 IntSize(style->borderTopLeftRadius().width().intValue(), style->borderTopLeftRadius().height().intValue()),
580 IntSize(style->borderTopRightRadius().width().intValue(), style->borderTopRightRadius().height().intValue()),
581 IntSize(style->borderBottomLeftRadius().width().intValue(), style->borderBottomLeftRadius().height().intValue()),
582 IntSize(style->borderBottomRightRadius().width().intValue(), style->borderBottomRightRadius().height().intValue()));
585 bool RenderThemeGtk::paintMediaSliderTrack(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
587 HTMLMediaElement* mediaElement = parentMediaElement(o);
591 GraphicsContext* context = paintInfo.context;
593 context->setStrokeStyle(NoStroke);
595 float mediaDuration = mediaElement->duration();
596 float totalTrackWidth = r.width();
597 RenderStyle* style = &o.style();
598 RefPtr<TimeRanges> timeRanges = mediaElement->buffered();
599 for (unsigned index = 0; index < timeRanges->length(); ++index) {
600 float start = timeRanges->start(index, IGNORE_EXCEPTION);
601 float end = timeRanges->end(index, IGNORE_EXCEPTION);
602 float startRatio = start / mediaDuration;
603 float lengthRatio = (end - start) / mediaDuration;
607 IntRect rangeRect(r);
608 rangeRect.setWidth(lengthRatio * totalTrackWidth);
610 rangeRect.move(startRatio * totalTrackWidth, 0);
611 context->fillRoundedRect(FloatRoundedRect(rangeRect, borderRadiiFromStyle(style)), style->visitedDependentColor(CSSPropertyColor), style->colorSpace());
618 bool RenderThemeGtk::paintMediaSliderThumb(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
620 RenderStyle* style = &o.style();
621 paintInfo.context->fillRoundedRect(FloatRoundedRect(r, borderRadiiFromStyle(style)), style->visitedDependentColor(CSSPropertyColor), style->colorSpace());
625 bool RenderThemeGtk::paintMediaVolumeSliderContainer(const RenderObject&, const PaintInfo&, const IntRect&)
630 bool RenderThemeGtk::paintMediaVolumeSliderTrack(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
632 HTMLMediaElement* mediaElement = parentMediaElement(renderObject);
636 float volume = mediaElement->muted() ? 0.0f : mediaElement->volume();
640 GraphicsContext* context = paintInfo.context;
642 context->setStrokeStyle(NoStroke);
644 int rectHeight = rect.height();
645 float trackHeight = rectHeight * volume;
646 RenderStyle* style = &renderObject.style();
647 IntRect volumeRect(rect);
648 volumeRect.move(0, rectHeight - trackHeight);
649 volumeRect.setHeight(ceil(trackHeight));
651 context->fillRoundedRect(FloatRoundedRect(volumeRect, borderRadiiFromStyle(style)),
652 style->visitedDependentColor(CSSPropertyColor), style->colorSpace());
658 bool RenderThemeGtk::paintMediaVolumeSliderThumb(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
660 return paintMediaSliderThumb(renderObject, paintInfo, rect);
663 String RenderThemeGtk::formatMediaControlsCurrentTime(float currentTime, float duration) const
665 return formatMediaControlsTime(currentTime) + " / " + formatMediaControlsTime(duration);
668 bool RenderThemeGtk::paintMediaCurrentTime(const RenderObject&, const PaintInfo&, const IntRect&)
674 void RenderThemeGtk::adjustProgressBarStyle(StyleResolver*, RenderStyle* style, Element*) const
676 style->setBoxShadow(nullptr);
679 // These values have been copied from RenderThemeChromiumSkia.cpp
680 static const int progressActivityBlocks = 5;
681 static const int progressAnimationFrames = 10;
682 static const double progressAnimationInterval = 0.125;
683 double RenderThemeGtk::animationRepeatIntervalForProgressBar(RenderProgress*) const
685 return progressAnimationInterval;
688 double RenderThemeGtk::animationDurationForProgressBar(RenderProgress*) const
690 return progressAnimationInterval * progressAnimationFrames * 2; // "2" for back and forth;
693 IntRect RenderThemeGtk::calculateProgressRect(const RenderObject& renderObject, const IntRect& fullBarRect)
695 IntRect progressRect(fullBarRect);
696 const RenderProgress* renderProgress = toRenderProgress(&renderObject);
697 if (renderProgress->isDeterminate()) {
698 int progressWidth = progressRect.width() * renderProgress->position();
699 if (renderObject.style().direction() == RTL)
700 progressRect.setX(progressRect.x() + progressRect.width() - progressWidth);
701 progressRect.setWidth(progressWidth);
705 double animationProgress = renderProgress->animationProgress();
707 // Never let the progress rect shrink smaller than 2 pixels.
708 int newWidth = std::max(2, progressRect.width() / progressActivityBlocks);
709 int movableWidth = progressRect.width() - newWidth;
710 progressRect.setWidth(newWidth);
712 // We want the first 0.5 units of the animation progress to represent the
713 // forward motion and the second 0.5 units to represent the backward motion,
714 // thus we multiply by two here to get the full sweep of the progress bar with
716 if (animationProgress < 0.5)
717 progressRect.setX(progressRect.x() + (animationProgress * 2 * movableWidth));
719 progressRect.setX(progressRect.x() + ((1.0 - animationProgress) * 2 * movableWidth));
723 String RenderThemeGtk::fileListNameForWidth(const FileList* fileList, const Font& font, int width, bool multipleFilesAllowed) const
728 if (fileList->length() > 1)
729 return StringTruncator::rightTruncate(multipleFileUploadText(fileList->length()), width, font, StringTruncator::EnableRoundingHacks);
732 if (fileList->length())
733 string = pathGetFileName(fileList->item(0)->path());
734 else if (multipleFilesAllowed)
735 string = fileButtonNoFilesSelectedLabel();
737 string = fileButtonNoFileSelectedLabel();
739 return StringTruncator::centerTruncate(string, width, font, StringTruncator::EnableRoundingHacks);
742 #if ENABLE(DATALIST_ELEMENT)
743 IntSize RenderThemeGtk::sliderTickSize() const
745 // FIXME: We need to set this to the size of one tick mark.
746 return IntSize(0, 0);
749 int RenderThemeGtk::sliderTickOffsetFromTrackCenter() const
751 // FIXME: We need to set this to the position of the tick marks.
756 String RenderThemeGtk::mediaControlsScript()
758 StringBuilder scriptBuilder;
759 scriptBuilder.append(mediaControlsLocalizedStringsJavaScript, sizeof(mediaControlsLocalizedStringsJavaScript));
760 scriptBuilder.append(mediaControlsAppleJavaScript, sizeof(mediaControlsAppleJavaScript));
761 scriptBuilder.append(mediaControlsGtkJavaScript, sizeof(mediaControlsGtkJavaScript));
762 return scriptBuilder.toString();