blob: 4db9bbbe481f9729e0524af6308816fee72e9b3a [file] [log] [blame]
/*
* 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 "ExceptionCodePlaceholder.h"
#import "GraphicsContextCG.h"
#import "HTMLMediaElement.h"
#import "LocalCurrentGraphicsContext.h"
#import "MediaControlElements.h"
#import "PaintInfo.h"
#import "RenderMedia.h"
#import "RenderMediaControlElements.h"
#import "RenderMediaControls.h"
#import "RenderView.h"
#import "TimeRanges.h"
#import "ThemeMac.h"
#import "WebCoreSystemInterface.h"
#import "UserAgentStyleSheets.h"
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
#import <wtf/RetainPtr.h>
namespace WebCore {
using namespace HTMLNames;
PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page*)
{
static RenderTheme* rt = RenderThemeMac::create().leakRef();
return rt;
}
PassRefPtr<RenderTheme> 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<int>(width * zoomLevel), Fixed));
style->setHeight(Length(static_cast<int>(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<HTMLMediaElement*>(mediaNode);
if (!mediaElement)
return false;
RefPtr<TimeRanges> timeRanges = mediaElement->buffered();
float timeLoaded = timeRanges->length() ? timeRanges->end(0, IGNORE_EXCEPTION) : 0;
float currentTime = mediaElement->currentTime();
float duration = mediaElement->duration();
if (std::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::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