Refactoring: Replace Element::disabled and isEnabledFormControl with isDisabledFormCo...
[WebKit-https.git] / Source / WebCore / rendering / RenderThemeMac.mm
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #import "config.h"
21 #import "RenderThemeMac.h"
22
23 #import "Element.h"
24 #import "ExceptionCodePlaceholder.h"
25 #import "GraphicsContextCG.h"
26 #import "HTMLMediaElement.h"
27 #import "LocalCurrentGraphicsContext.h"
28 #import "MediaControlElements.h"
29 #import "PaintInfo.h"
30 #import "RenderMedia.h"
31 #import "RenderMediaControlElements.h"
32 #import "RenderMediaControls.h"
33 #import "RenderView.h"
34 #import "TimeRanges.h"
35 #import "ThemeMac.h"
36 #import "WebCoreSystemInterface.h"
37 #import "UserAgentStyleSheets.h"
38 #import <Carbon/Carbon.h>
39 #import <Cocoa/Cocoa.h>
40 #import <wtf/RetainPtr.h>
41
42 namespace WebCore {
43
44 using namespace HTMLNames;
45
46 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page*)
47 {
48     static RenderTheme* rt = RenderThemeMac::create().leakRef();
49     return rt;
50 }
51
52 PassRefPtr<RenderTheme> RenderThemeMac::create()
53 {
54     return adoptRef(new RenderThemeMac);
55 }
56
57 RenderThemeMac::RenderThemeMac()
58 {
59 }
60
61 RenderThemeMac::~RenderThemeMac()
62 {
63 }
64
65 NSView* RenderThemeMac::documentViewFor(RenderObject* o) const
66 {
67     return ThemeMac::ensuredView(o->view()->frameView());
68 }
69
70 #if ENABLE(VIDEO)
71
72 typedef enum {
73     MediaControllerThemeClassic   = 1,
74     MediaControllerThemeQuickTime = 2
75 } MediaControllerThemeStyle;
76
77 static int mediaControllerTheme()
78 {
79     static int controllerTheme = -1;
80
81     if (controllerTheme != -1)
82         return controllerTheme;
83
84     controllerTheme = MediaControllerThemeClassic;
85
86     Boolean validKey;
87     Boolean useQTMediaUIPref = CFPreferencesGetAppBooleanValue(CFSTR("UseQuickTimeMediaUI"), CFSTR("com.apple.WebCore"), &validKey);
88
89     if (validKey && !useQTMediaUIPref)
90         return controllerTheme;
91
92     controllerTheme = MediaControllerThemeQuickTime;
93     return controllerTheme;
94 }
95
96 const int mediaSliderThumbWidth = 13;
97 const int mediaSliderThumbHeight = 14;
98
99 void RenderThemeMac::adjustMediaSliderThumbSize(RenderStyle* style) const
100 {
101     int wkPart;
102     switch (style->appearance()) {
103     case MediaSliderThumbPart:
104         wkPart = MediaSliderThumb;
105         break;
106     case MediaVolumeSliderThumbPart:
107         wkPart = MediaVolumeSliderThumb;
108         break;
109     case MediaFullScreenVolumeSliderThumbPart:
110         wkPart = MediaFullScreenVolumeSliderThumb;
111         break;
112     default:
113         return;
114     }
115
116     int width = mediaSliderThumbWidth;
117     int height = mediaSliderThumbHeight;
118
119     if (mediaControllerTheme() == MediaControllerThemeQuickTime) {
120         CGSize size;
121         wkMeasureMediaUIPart(wkPart, MediaControllerThemeQuickTime, NULL, &size);
122         width = size.width;
123         height = size.height;
124     }
125
126     float zoomLevel = style->effectiveZoom();
127     style->setWidth(Length(static_cast<int>(width * zoomLevel), Fixed));
128     style->setHeight(Length(static_cast<int>(height * zoomLevel), Fixed));
129 }
130
131 enum WKMediaControllerThemeState {
132     MediaUIPartDisabledFlag = 1 << 0,
133     MediaUIPartPressedFlag = 1 << 1,
134     MediaUIPartDrawEndCapsFlag = 1 << 3,
135 };
136
137 static unsigned getMediaUIPartStateFlags(Node* node)
138 {
139     unsigned flags = 0;
140
141     if (isDisabledFormControl(node))
142         flags |= MediaUIPartDisabledFlag;
143     else if (node->active())
144         flags |= MediaUIPartPressedFlag;
145     return flags;
146 }
147
148 // Utility to scale when the UI part are not scaled by wkDrawMediaUIPart
149 static FloatRect getUnzoomedRectAndAdjustCurrentContext(RenderObject* o, const PaintInfo& paintInfo, const IntRect &originalRect)
150 {
151     float zoomLevel = o->style()->effectiveZoom();
152     FloatRect unzoomedRect(originalRect);
153     if (zoomLevel != 1.0f && mediaControllerTheme() == MediaControllerThemeQuickTime) {
154         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
155         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
156         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
157         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
158         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
159     }
160     return unzoomedRect;
161 }
162
163 bool RenderThemeMac::paintMediaFullscreenButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
164 {
165     Node* node = o->node();
166     if (!node)
167         return false;
168
169     if (node->isMediaControlElement()) {
170         LocalCurrentGraphicsContext localContext(paintInfo.context);
171         wkDrawMediaUIPart(mediaControlElementType(node), mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
172     }
173     return false;
174 }
175
176 bool RenderThemeMac::paintMediaMuteButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
177 {
178     Node* node = o->node();
179     Node* mediaNode = node ? node->shadowHost() : 0;
180     if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
181         return false;
182
183     if (node->isMediaControlElement()) {
184         LocalCurrentGraphicsContext localContext(paintInfo.context);
185         wkDrawMediaUIPart(mediaControlElementType(node), mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
186     }
187     return false;
188 }
189
190 bool RenderThemeMac::paintMediaPlayButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
191 {
192     Node* node = o->node();
193     Node* mediaNode = node ? node->shadowHost() : 0;
194     if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
195         return false;
196
197     if (node->isMediaControlElement()) {
198         LocalCurrentGraphicsContext localContext(paintInfo.context);
199         wkDrawMediaUIPart(mediaControlElementType(node), mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
200     }
201     return false;
202 }
203
204 bool RenderThemeMac::paintMediaSeekBackButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
205 {
206     Node* node = o->node();
207     if (!node)
208         return false;
209
210     LocalCurrentGraphicsContext localContext(paintInfo.context);
211     wkDrawMediaUIPart(MediaSeekBackButton, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
212     return false;
213 }
214
215 bool RenderThemeMac::paintMediaSeekForwardButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
216 {
217     Node* node = o->node();
218     if (!node)
219         return false;
220
221     LocalCurrentGraphicsContext localContext(paintInfo.context);
222     wkDrawMediaUIPart(MediaSeekForwardButton, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
223     return false;
224 }
225
226 bool RenderThemeMac::paintMediaSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
227 {
228     Node* node = o->node();
229     Element* mediaNode = node ? node->shadowHost() : 0;
230     if (!mediaNode || !mediaNode->isMediaElement())
231         return false;
232
233     HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
234     if (!mediaElement)
235         return false;
236
237     RefPtr<TimeRanges> timeRanges = mediaElement->buffered();
238     float timeLoaded = timeRanges->length() ? timeRanges->end(0, IGNORE_EXCEPTION) : 0;
239     float currentTime = mediaElement->currentTime();
240     float duration = mediaElement->duration();
241     if (std::isnan(duration))
242         duration = 0;
243
244     ContextContainer cgContextContainer(paintInfo.context);
245     CGContextRef context = cgContextContainer.context();
246     GraphicsContextStateSaver stateSaver(*paintInfo.context);
247     FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
248     wkDrawMediaSliderTrack(mediaControllerTheme(), context, unzoomedRect,
249         timeLoaded, currentTime, duration, getMediaUIPartStateFlags(node));
250     return false;
251 }
252
253 bool RenderThemeMac::paintMediaSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
254 {
255     Node* node = o->node();
256     if (!node)
257         return false;
258
259     LocalCurrentGraphicsContext localContext(paintInfo.context);
260     wkDrawMediaUIPart(MediaSliderThumb, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
261     return false;
262 }
263
264 bool RenderThemeMac::paintMediaRewindButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
265 {
266     Node* node = o->node();
267     if (!node)
268         return false;
269
270     LocalCurrentGraphicsContext localContext(paintInfo.context);
271     wkDrawMediaUIPart(MediaRewindButton, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
272     return false;
273 }
274
275 bool RenderThemeMac::paintMediaReturnToRealtimeButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
276 {
277     Node* node = o->node();
278     if (!node)
279         return false;
280
281     LocalCurrentGraphicsContext localContext(paintInfo.context);
282     wkDrawMediaUIPart(MediaReturnToRealtimeButton, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
283     return false;
284 }
285
286 bool RenderThemeMac::paintMediaControlsBackground(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
287 {
288     Node* node = o->node();
289     if (!node)
290         return false;
291
292     LocalCurrentGraphicsContext localContext(paintInfo.context);
293     wkDrawMediaUIPart(MediaTimelineContainer, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
294     return false;
295 }
296
297 bool RenderThemeMac::paintMediaCurrentTime(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
298 {
299     Node* node = o->node();
300     if (!node)
301         return false;
302
303     ContextContainer cgContextContainer(paintInfo.context);
304     GraphicsContextStateSaver stateSaver(*paintInfo.context);
305     FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
306     wkDrawMediaUIPart(MediaCurrentTimeDisplay, mediaControllerTheme(), cgContextContainer.context(), unzoomedRect, getMediaUIPartStateFlags(node));
307     return false;
308 }
309
310 bool RenderThemeMac::paintMediaTimeRemaining(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
311 {
312     Node* node = o->node();
313     if (!node)
314         return false;
315
316     ContextContainer cgContextContainer(paintInfo.context);
317     GraphicsContextStateSaver stateSaver(*paintInfo.context);
318     FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
319     wkDrawMediaUIPart(MediaTimeRemainingDisplay, mediaControllerTheme(), cgContextContainer.context(), unzoomedRect, getMediaUIPartStateFlags(node));
320     return false;
321 }
322
323 bool RenderThemeMac::paintMediaVolumeSliderContainer(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
324 {
325     Node* node = o->node();
326     if (!node)
327         return false;
328
329     LocalCurrentGraphicsContext localContext(paintInfo.context);
330     wkDrawMediaUIPart(MediaVolumeSliderContainer, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
331     return false;
332 }
333
334 bool RenderThemeMac::paintMediaVolumeSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
335 {
336     Node* node = o->node();
337     if (!node)
338         return false;
339
340     LocalCurrentGraphicsContext localContext(paintInfo.context);
341     wkDrawMediaUIPart(MediaVolumeSlider, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
342     return false;
343 }
344
345 bool RenderThemeMac::paintMediaVolumeSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
346 {
347     Node* node = o->node();
348     if (!node)
349         return false;
350
351     LocalCurrentGraphicsContext localContext(paintInfo.context);
352     wkDrawMediaUIPart(MediaVolumeSliderThumb, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
353     return false;
354 }
355
356 bool RenderThemeMac::paintMediaFullScreenVolumeSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
357 {
358     Node* node = o->node();
359     if (!node)
360         return false;
361
362     LocalCurrentGraphicsContext localContext(paintInfo.context);
363     wkDrawMediaUIPart(MediaFullScreenVolumeSlider, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
364     return false;
365 }
366
367 bool RenderThemeMac::paintMediaFullScreenVolumeSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
368 {
369     Node* node = o->node();
370     if (!node)
371         return false;
372
373     LocalCurrentGraphicsContext localContext(paintInfo.context);
374     wkDrawMediaUIPart(MediaFullScreenVolumeSliderThumb, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
375     return false;
376 }
377
378 String RenderThemeMac::extraMediaControlsStyleSheet()
379 {
380     if (mediaControllerTheme() == MediaControllerThemeQuickTime)
381         return String(mediaControlsQuickTimeUserAgentStyleSheet, sizeof(mediaControlsQuickTimeUserAgentStyleSheet));
382
383     return String();
384 }
385
386 #if ENABLE(FULLSCREEN_API)
387 String RenderThemeMac::extraFullScreenStyleSheet()
388 {
389     if (mediaControllerTheme() == MediaControllerThemeQuickTime)
390         return String(fullscreenQuickTimeUserAgentStyleSheet, sizeof(fullscreenQuickTimeUserAgentStyleSheet));
391
392     return String();
393 }
394 #endif
395
396 bool RenderThemeMac::hasOwnDisabledStateHandlingFor(ControlPart part) const
397 {
398     if (part == MediaMuteButtonPart)
399         return false;
400
401     return mediaControllerTheme() == MediaControllerThemeClassic;
402 }
403
404 bool RenderThemeMac::usesMediaControlStatusDisplay()
405 {
406     return mediaControllerTheme() == MediaControllerThemeQuickTime;
407 }
408
409 bool RenderThemeMac::usesMediaControlVolumeSlider() const
410 {
411     return mediaControllerTheme() == MediaControllerThemeQuickTime;
412 }
413
414 IntPoint RenderThemeMac::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const IntSize& size) const
415 {
416     return RenderMediaControls::volumeSliderOffsetFromMuteButton(muteButtonBox, size);
417 }
418
419 #endif // ENABLE(VIDEO)
420
421 } // namespace WebCore