/* * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. * * 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. */ #import "config.h" #import "RenderThemeMac.h" #import "Element.h" #import "GraphicsContextCG.h" #import "HTMLMediaElement.h" #import "LocalCurrentGraphicsContext.h" #import "MediaControlElements.h" #import "PaintInfo.h" #import "RenderMedia.h" #import "RenderMediaControls.h" #import "RenderView.h" #import "TimeRanges.h" #import "ThemeMac.h" #import "WebCoreSystemInterface.h" #import "UserAgentStyleSheets.h" #import #import #import namespace WebCore { using namespace HTMLNames; PassRefPtr RenderTheme::themeForPage(Page*) { static RenderTheme* rt = RenderThemeMac::create().leakRef(); return rt; } PassRefPtr RenderThemeMac::create() { return adoptRef(new RenderThemeMac); } RenderThemeMac::RenderThemeMac() { } RenderThemeMac::~RenderThemeMac() { } NSView* RenderThemeMac::documentViewFor(RenderObject* o) const { return ThemeMac::ensuredView(o->view()->frameView()); } #if ENABLE(VIDEO) typedef enum { MediaControllerThemeClassic = 1, MediaControllerThemeQuickTime = 2 } MediaControllerThemeStyle; static int mediaControllerTheme() { static int controllerTheme = -1; if (controllerTheme != -1) return controllerTheme; controllerTheme = MediaControllerThemeClassic; Boolean validKey; Boolean useQTMediaUIPref = CFPreferencesGetAppBooleanValue(CFSTR("UseQuickTimeMediaUI"), CFSTR("com.apple.WebCore"), &validKey); if (validKey && !useQTMediaUIPref) return controllerTheme; controllerTheme = MediaControllerThemeQuickTime; return controllerTheme; } const int mediaSliderThumbWidth = 13; const int mediaSliderThumbHeight = 14; void RenderThemeMac::adjustMediaSliderThumbSize(RenderStyle* style) const { int wkPart; switch (style->appearance()) { case MediaSliderThumbPart: wkPart = MediaSliderThumb; break; case MediaVolumeSliderThumbPart: wkPart = MediaVolumeSliderThumb; break; case MediaFullScreenVolumeSliderThumbPart: wkPart = MediaFullScreenVolumeSliderThumb; break; default: return; } int width = mediaSliderThumbWidth; int height = mediaSliderThumbHeight; if (mediaControllerTheme() == MediaControllerThemeQuickTime) { CGSize size; wkMeasureMediaUIPart(wkPart, MediaControllerThemeQuickTime, NULL, &size); width = size.width; height = size.height; } float zoomLevel = style->effectiveZoom(); style->setWidth(Length(static_cast(width * zoomLevel), Fixed)); style->setHeight(Length(static_cast(height * zoomLevel), Fixed)); } enum WKMediaControllerThemeState { MediaUIPartDisabledFlag = 1 << 0, MediaUIPartPressedFlag = 1 << 1, MediaUIPartDrawEndCapsFlag = 1 << 3, }; static unsigned getMediaUIPartStateFlags(Node* node) { unsigned flags = 0; if (node->disabled()) flags |= MediaUIPartDisabledFlag; else if (node->active()) flags |= MediaUIPartPressedFlag; return flags; } // Utility to scale when the UI part are not scaled by wkDrawMediaUIPart static FloatRect getUnzoomedRectAndAdjustCurrentContext(RenderObject* o, const PaintInfo& paintInfo, const IntRect &originalRect) { float zoomLevel = o->style()->effectiveZoom(); FloatRect unzoomedRect(originalRect); if (zoomLevel != 1.0f && mediaControllerTheme() == MediaControllerThemeQuickTime) { unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y()); paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel)); paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); } return unzoomedRect; } bool RenderThemeMac::paintMediaFullscreenButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); if (!node) return false; if (node->isMediaControlElement()) { LocalCurrentGraphicsContext localContext(paintInfo.context); wkDrawMediaUIPart(mediaControlElementType(node), mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node)); } return false; } bool RenderThemeMac::paintMediaMuteButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); Node* mediaNode = node ? node->shadowHost() : 0; if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag))) return false; if (node->isMediaControlElement()) { LocalCurrentGraphicsContext localContext(paintInfo.context); wkDrawMediaUIPart(mediaControlElementType(node), mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node)); } return false; } bool RenderThemeMac::paintMediaPlayButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); Node* mediaNode = node ? node->shadowHost() : 0; if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag))) return false; if (node->isMediaControlElement()) { LocalCurrentGraphicsContext localContext(paintInfo.context); wkDrawMediaUIPart(mediaControlElementType(node), mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node)); } return false; } bool RenderThemeMac::paintMediaSeekBackButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); if (!node) return false; LocalCurrentGraphicsContext localContext(paintInfo.context); wkDrawMediaUIPart(MediaSeekBackButton, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node)); return false; } bool RenderThemeMac::paintMediaSeekForwardButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); if (!node) return false; LocalCurrentGraphicsContext localContext(paintInfo.context); wkDrawMediaUIPart(MediaSeekForwardButton, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node)); return false; } bool RenderThemeMac::paintMediaSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); Element* mediaNode = node ? node->shadowHost() : 0; if (!mediaNode || !mediaNode->isMediaElement()) return false; HTMLMediaElement* mediaElement = static_cast(mediaNode); if (!mediaElement) return false; RefPtr timeRanges = mediaElement->buffered(); ExceptionCode ignoredException; float timeLoaded = timeRanges->length() ? timeRanges->end(0, ignoredException) : 0; float currentTime = mediaElement->currentTime(); float duration = mediaElement->duration(); if (isnan(duration)) duration = 0; ContextContainer cgContextContainer(paintInfo.context); CGContextRef context = cgContextContainer.context(); GraphicsContextStateSaver stateSaver(*paintInfo.context); FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r); wkDrawMediaSliderTrack(mediaControllerTheme(), context, unzoomedRect, timeLoaded, currentTime, duration, getMediaUIPartStateFlags(node)); return false; } bool RenderThemeMac::paintMediaSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); if (!node) return false; LocalCurrentGraphicsContext localContext(paintInfo.context); wkDrawMediaUIPart(MediaSliderThumb, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node)); return false; } bool RenderThemeMac::paintMediaRewindButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); if (!node) return false; LocalCurrentGraphicsContext localContext(paintInfo.context); wkDrawMediaUIPart(MediaRewindButton, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node)); return false; } bool RenderThemeMac::paintMediaReturnToRealtimeButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); if (!node) return false; LocalCurrentGraphicsContext localContext(paintInfo.context); wkDrawMediaUIPart(MediaReturnToRealtimeButton, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node)); return false; } bool RenderThemeMac::paintMediaToggleClosedCaptionsButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); if (!node) return false; if (!node->isMediaControlElement()) return false; LocalCurrentGraphicsContext localContext(paintInfo.context); wkDrawMediaUIPart(mediaControlElementType(node), mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node)); return false; } bool RenderThemeMac::paintMediaControlsBackground(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); if (!node) return false; LocalCurrentGraphicsContext localContext(paintInfo.context); wkDrawMediaUIPart(MediaTimelineContainer, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node)); return false; } bool RenderThemeMac::paintMediaCurrentTime(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); if (!node) return false; ContextContainer cgContextContainer(paintInfo.context); GraphicsContextStateSaver stateSaver(*paintInfo.context); FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r); wkDrawMediaUIPart(MediaCurrentTimeDisplay, mediaControllerTheme(), cgContextContainer.context(), unzoomedRect, getMediaUIPartStateFlags(node)); return false; } bool RenderThemeMac::paintMediaTimeRemaining(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); if (!node) return false; ContextContainer cgContextContainer(paintInfo.context); GraphicsContextStateSaver stateSaver(*paintInfo.context); FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r); wkDrawMediaUIPart(MediaTimeRemainingDisplay, mediaControllerTheme(), cgContextContainer.context(), unzoomedRect, getMediaUIPartStateFlags(node)); return false; } bool RenderThemeMac::paintMediaVolumeSliderContainer(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); if (!node) return false; LocalCurrentGraphicsContext localContext(paintInfo.context); wkDrawMediaUIPart(MediaVolumeSliderContainer, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node)); return false; } bool RenderThemeMac::paintMediaVolumeSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); if (!node) return false; LocalCurrentGraphicsContext localContext(paintInfo.context); wkDrawMediaUIPart(MediaVolumeSlider, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node)); return false; } bool RenderThemeMac::paintMediaVolumeSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); if (!node) return false; LocalCurrentGraphicsContext localContext(paintInfo.context); wkDrawMediaUIPart(MediaVolumeSliderThumb, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node)); return false; } bool RenderThemeMac::paintMediaFullScreenVolumeSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); if (!node) return false; LocalCurrentGraphicsContext localContext(paintInfo.context); wkDrawMediaUIPart(MediaFullScreenVolumeSlider, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node)); return false; } bool RenderThemeMac::paintMediaFullScreenVolumeSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); if (!node) return false; LocalCurrentGraphicsContext localContext(paintInfo.context); wkDrawMediaUIPart(MediaFullScreenVolumeSliderThumb, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node)); return false; } String RenderThemeMac::extraMediaControlsStyleSheet() { if (mediaControllerTheme() == MediaControllerThemeQuickTime) return String(mediaControlsQuickTimeUserAgentStyleSheet, sizeof(mediaControlsQuickTimeUserAgentStyleSheet)); return String(); } #if ENABLE(FULLSCREEN_API) String RenderThemeMac::extraFullScreenStyleSheet() { if (mediaControllerTheme() == MediaControllerThemeQuickTime) return String(fullscreenQuickTimeUserAgentStyleSheet, sizeof(fullscreenQuickTimeUserAgentStyleSheet)); return String(); } #endif bool RenderThemeMac::hasOwnDisabledStateHandlingFor(ControlPart part) const { if (part == MediaMuteButtonPart) return false; return mediaControllerTheme() == MediaControllerThemeClassic; } bool RenderThemeMac::usesMediaControlStatusDisplay() { return mediaControllerTheme() == MediaControllerThemeQuickTime; } bool RenderThemeMac::usesMediaControlVolumeSlider() const { return mediaControllerTheme() == MediaControllerThemeQuickTime; } IntPoint RenderThemeMac::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const IntSize& size) const { return RenderMediaControls::volumeSliderOffsetFromMuteButton(muteButtonBox, size); } #endif // ENABLE(VIDEO) } // namespace WebCore