[Qt] Test fonts are not used with Qt5
[WebKit-https.git] / Source / WebCore / html / shadow / MediaControlRootElement.cpp
1 /*
2  * Copyright (C) 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
3  * Copyright (C) 2011 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28
29 #if ENABLE(VIDEO)
30 #include "MediaControlRootElement.h"
31
32 #include "Chrome.h"
33 #include "HTMLMediaElement.h"
34 #include "MediaControlElements.h"
35 #include "MouseEvent.h"
36 #include "Page.h"
37 #include "RenderTheme.h"
38
39 using namespace std;
40
41 namespace WebCore {
42
43 static const double timeWithoutMouseMovementBeforeHidingControls = 3;
44
45 MediaControlRootElement::MediaControlRootElement(Document* document)
46     : MediaControls(document)
47     , m_mediaController(0)
48     , m_rewindButton(0)
49     , m_playButton(0)
50     , m_returnToRealTimeButton(0)
51     , m_statusDisplay(0)
52     , m_currentTimeDisplay(0)
53     , m_timeline(0)
54     , m_timeRemainingDisplay(0)
55     , m_timelineContainer(0)
56     , m_seekBackButton(0)
57     , m_seekForwardButton(0)
58     , m_toggleClosedCaptionsButton(0)
59     , m_panelMuteButton(0)
60     , m_volumeSlider(0)
61     , m_volumeSliderMuteButton(0)
62     , m_volumeSliderContainer(0)
63     , m_fullScreenButton(0)
64     , m_fullScreenMinVolumeButton(0)
65     , m_fullScreenVolumeSlider(0)
66     , m_fullScreenMaxVolumeButton(0)
67     , m_panel(0)
68     , m_isMouseOverControls(false)
69     , m_hideFullscreenControlsTimer(this, &MediaControlRootElement::hideFullscreenControlsTimerFired)
70 {
71 }
72
73 PassRefPtr<MediaControls> MediaControls::create(Document* document)
74 {
75     return MediaControlRootElement::create(document);
76 }
77
78 PassRefPtr<MediaControlRootElement> MediaControlRootElement::create(Document* document)
79 {
80     if (!document->page())
81         return 0;
82
83     RefPtr<MediaControlRootElement> controls = adoptRef(new MediaControlRootElement(document));
84
85     RefPtr<MediaControlPanelElement> panel = MediaControlPanelElement::create(document);
86
87     ExceptionCode ec;
88
89     RefPtr<MediaControlRewindButtonElement> rewindButton = MediaControlRewindButtonElement::create(document);
90     controls->m_rewindButton = rewindButton.get();
91     panel->appendChild(rewindButton.release(), ec, true);
92     if (ec)
93         return 0;
94
95     RefPtr<MediaControlPlayButtonElement> playButton = MediaControlPlayButtonElement::create(document);
96     controls->m_playButton = playButton.get();
97     panel->appendChild(playButton.release(), ec, true);
98     if (ec)
99         return 0;
100
101     RefPtr<MediaControlReturnToRealtimeButtonElement> returnToRealtimeButton = MediaControlReturnToRealtimeButtonElement::create(document);
102     controls->m_returnToRealTimeButton = returnToRealtimeButton.get();
103     panel->appendChild(returnToRealtimeButton.release(), ec, true);
104     if (ec)
105         return 0;
106
107     if (document->page()->theme()->usesMediaControlStatusDisplay()) {
108         RefPtr<MediaControlStatusDisplayElement> statusDisplay = MediaControlStatusDisplayElement::create(document);
109         controls->m_statusDisplay = statusDisplay.get();
110         panel->appendChild(statusDisplay.release(), ec, true);
111         if (ec)
112             return 0;
113     }
114
115     RefPtr<MediaControlTimelineContainerElement> timelineContainer = MediaControlTimelineContainerElement::create(document);
116
117     RefPtr<MediaControlCurrentTimeDisplayElement> currentTimeDisplay = MediaControlCurrentTimeDisplayElement::create(document);
118     controls->m_currentTimeDisplay = currentTimeDisplay.get();
119     timelineContainer->appendChild(currentTimeDisplay.release(), ec, true);
120     if (ec)
121         return 0;
122
123     RefPtr<MediaControlTimelineElement> timeline = MediaControlTimelineElement::create(document, controls.get());
124     controls->m_timeline = timeline.get();
125     timelineContainer->appendChild(timeline.release(), ec, true);
126     if (ec)
127         return 0;
128
129     RefPtr<MediaControlTimeRemainingDisplayElement> timeRemainingDisplay = MediaControlTimeRemainingDisplayElement::create(document);
130     controls->m_timeRemainingDisplay = timeRemainingDisplay.get();
131     timelineContainer->appendChild(timeRemainingDisplay.release(), ec, true);
132     if (ec)
133         return 0;
134
135     controls->m_timelineContainer = timelineContainer.get();
136     panel->appendChild(timelineContainer.release(), ec, true);
137     if (ec)
138         return 0;
139
140     // FIXME: Only create when needed <http://webkit.org/b/57163>
141     RefPtr<MediaControlSeekBackButtonElement> seekBackButton = MediaControlSeekBackButtonElement::create(document);
142     controls->m_seekBackButton = seekBackButton.get();
143     panel->appendChild(seekBackButton.release(), ec, true);
144     if (ec)
145         return 0;
146
147     // FIXME: Only create when needed <http://webkit.org/b/57163>
148     RefPtr<MediaControlSeekForwardButtonElement> seekForwardButton = MediaControlSeekForwardButtonElement::create(document);
149     controls->m_seekForwardButton = seekForwardButton.get();
150     panel->appendChild(seekForwardButton.release(), ec, true);
151     if (ec)
152         return 0;
153
154     if (document->page()->theme()->supportsClosedCaptioning()) {
155         RefPtr<MediaControlToggleClosedCaptionsButtonElement> toggleClosedCaptionsButton = MediaControlToggleClosedCaptionsButtonElement::create(document);
156         controls->m_toggleClosedCaptionsButton = toggleClosedCaptionsButton.get();
157         panel->appendChild(toggleClosedCaptionsButton.release(), ec, true);
158         if (ec)
159             return 0;
160     }
161
162     // FIXME: Only create when needed <http://webkit.org/b/57163>
163     RefPtr<MediaControlFullscreenButtonElement> fullScreenButton = MediaControlFullscreenButtonElement::create(document, controls.get());
164     controls->m_fullScreenButton = fullScreenButton.get();
165     panel->appendChild(fullScreenButton.release(), ec, true);
166
167     RefPtr<MediaControlPanelMuteButtonElement> panelMuteButton = MediaControlPanelMuteButtonElement::create(document, controls.get());
168     controls->m_panelMuteButton = panelMuteButton.get();
169     panel->appendChild(panelMuteButton.release(), ec, true);
170     if (ec)
171         return 0;
172
173     if (document->page()->theme()->usesMediaControlVolumeSlider()) {
174         RefPtr<MediaControlVolumeSliderContainerElement> volumeSliderContainer = MediaControlVolumeSliderContainerElement::create(document);
175
176         RefPtr<MediaControlVolumeSliderElement> slider = MediaControlVolumeSliderElement::create(document);
177         controls->m_volumeSlider = slider.get();
178         volumeSliderContainer->appendChild(slider.release(), ec, true);
179         if (ec)
180             return 0;
181
182         RefPtr<MediaControlVolumeSliderMuteButtonElement> volumeSliderMuteButton = MediaControlVolumeSliderMuteButtonElement::create(document);
183         controls->m_volumeSliderMuteButton = volumeSliderMuteButton.get();
184         volumeSliderContainer->appendChild(volumeSliderMuteButton.release(), ec, true);
185         if (ec)
186             return 0;
187
188         controls->m_volumeSliderContainer = volumeSliderContainer.get();
189         panel->appendChild(volumeSliderContainer.release(), ec, true);
190         if (ec)
191             return 0;
192     }
193
194     // FIXME: Only create when needed <http://webkit.org/b/57163>
195     RefPtr<MediaControlFullscreenVolumeMinButtonElement> fullScreenMinVolumeButton = MediaControlFullscreenVolumeMinButtonElement::create(document);
196     controls->m_fullScreenMinVolumeButton = fullScreenMinVolumeButton.get();
197     panel->appendChild(fullScreenMinVolumeButton.release(), ec, true);
198     if (ec)
199         return 0;
200
201     RefPtr<MediaControlFullscreenVolumeSliderElement> fullScreenVolumeSlider = MediaControlFullscreenVolumeSliderElement::create(document);
202     controls->m_fullScreenVolumeSlider = fullScreenVolumeSlider.get();
203     panel->appendChild(fullScreenVolumeSlider.release(), ec, true);
204     if (ec)
205         return 0;
206
207     RefPtr<MediaControlFullscreenVolumeMaxButtonElement> fullScreenMaxVolumeButton = MediaControlFullscreenVolumeMaxButtonElement::create(document);
208     controls->m_fullScreenMaxVolumeButton = fullScreenMaxVolumeButton.get();
209     panel->appendChild(fullScreenMaxVolumeButton.release(), ec, true);
210     if (ec)
211         return 0;
212
213     controls->m_panel = panel.get();
214     controls->appendChild(panel.release(), ec, true);
215     if (ec)
216         return 0;
217
218     return controls.release();
219 }
220
221 void MediaControlRootElement::setMediaController(MediaControllerInterface* controller)
222 {
223     if (m_mediaController == controller)
224         return;
225     m_mediaController = controller;
226
227     if (m_rewindButton)
228         m_rewindButton->setMediaController(controller);
229     if (m_playButton)
230         m_playButton->setMediaController(controller);
231     if (m_returnToRealTimeButton)
232         m_returnToRealTimeButton->setMediaController(controller);
233     if (m_statusDisplay)
234         m_statusDisplay->setMediaController(controller);
235     if (m_currentTimeDisplay)
236         m_currentTimeDisplay->setMediaController(controller);
237     if (m_timeline)
238         m_timeline->setMediaController(controller);
239     if (m_timeRemainingDisplay)
240         m_timeRemainingDisplay->setMediaController(controller);
241     if (m_timelineContainer)
242         m_timelineContainer->setMediaController(controller);
243     if (m_seekBackButton)
244         m_seekBackButton->setMediaController(controller);
245     if (m_seekForwardButton)
246         m_seekForwardButton->setMediaController(controller);
247     if (m_toggleClosedCaptionsButton)
248         m_toggleClosedCaptionsButton->setMediaController(controller);
249     if (m_panelMuteButton)
250         m_panelMuteButton->setMediaController(controller);
251     if (m_volumeSlider)
252         m_volumeSlider->setMediaController(controller);
253     if (m_volumeSliderMuteButton)
254         m_volumeSliderMuteButton->setMediaController(controller);
255     if (m_volumeSliderContainer)
256         m_volumeSliderContainer->setMediaController(controller);
257     if (m_fullScreenButton)
258         m_fullScreenButton->setMediaController(controller);
259     if (m_fullScreenMinVolumeButton)
260         m_fullScreenMinVolumeButton->setMediaController(controller);
261     if (m_fullScreenVolumeSlider)
262         m_fullScreenVolumeSlider->setMediaController(controller);
263     if (m_fullScreenMaxVolumeButton)
264         m_fullScreenMaxVolumeButton->setMediaController(controller);
265     if (m_panel)
266         m_panel->setMediaController(controller);
267     reset();
268 }
269
270 void MediaControlRootElement::show()
271 {
272     m_panel->show();
273 }
274
275 void MediaControlRootElement::hide()
276 {
277     m_panel->hide();
278 }
279
280 void MediaControlRootElement::makeOpaque()
281 {
282     m_panel->makeOpaque();
283 }
284
285 void MediaControlRootElement::makeTransparent()
286 {
287     m_panel->makeTransparent();
288 }
289
290 void MediaControlRootElement::reset()
291 {
292     Page* page = document()->page();
293     if (!page)
294         return;
295
296     updateStatusDisplay();
297
298     if (m_mediaController->supportsFullscreen())
299         m_fullScreenButton->show();
300     else
301         m_fullScreenButton->hide();
302
303     float duration = m_mediaController->duration();
304     if (isfinite(duration) || page->theme()->hasOwnDisabledStateHandlingFor(MediaSliderPart)) {
305         m_timeline->setDuration(duration);
306         m_timelineContainer->show();
307         m_timeline->setPosition(m_mediaController->currentTime());
308         updateTimeDisplay();
309     } else
310         m_timelineContainer->hide();
311
312     if (m_mediaController->hasAudio() || page->theme()->hasOwnDisabledStateHandlingFor(MediaMuteButtonPart))
313         m_panelMuteButton->show();
314     else
315         m_panelMuteButton->hide();
316
317     if (m_volumeSlider)
318         m_volumeSlider->setVolume(m_mediaController->volume());
319
320     if (m_toggleClosedCaptionsButton) {
321         if (m_mediaController->hasClosedCaptions())
322             m_toggleClosedCaptionsButton->show();
323         else
324             m_toggleClosedCaptionsButton->hide();
325     }
326
327     m_playButton->updateDisplayType();
328
329 #if ENABLE(FULLSCREEN_API)
330     if (document()->webkitIsFullScreen() && document()->webkitCurrentFullScreenElement() == toParentMediaElement(this)) {
331         if (m_mediaController->isLiveStream()) {
332             m_seekBackButton->hide();
333             m_seekForwardButton->hide();
334             m_rewindButton->show();
335             m_returnToRealTimeButton->show();
336         } else {
337             m_seekBackButton->show();
338             m_seekForwardButton->show();
339             m_rewindButton->hide();
340             m_returnToRealTimeButton->hide();
341         }
342     } else
343 #endif
344     if (!m_mediaController->isLiveStream()) {
345         m_returnToRealTimeButton->hide();
346         m_rewindButton->show();
347     } else {
348         m_returnToRealTimeButton->show();
349         m_rewindButton->hide();
350     }
351
352     makeOpaque();
353 }
354
355 void MediaControlRootElement::playbackStarted()
356 {
357     m_playButton->updateDisplayType();
358     m_timeline->setPosition(m_mediaController->currentTime());
359     updateTimeDisplay();
360
361     if (m_mediaController->isFullscreen())
362         startHideFullscreenControlsTimer();
363 }
364
365 void MediaControlRootElement::playbackProgressed()
366 {
367     m_timeline->setPosition(m_mediaController->currentTime());
368     updateTimeDisplay();
369     
370     if (!m_isMouseOverControls && m_mediaController->hasVideo())
371         makeTransparent();
372 }
373
374 void MediaControlRootElement::playbackStopped()
375 {
376     m_playButton->updateDisplayType();
377     m_timeline->setPosition(m_mediaController->currentTime());
378     updateTimeDisplay();
379     makeOpaque();
380     
381     stopHideFullscreenControlsTimer();
382 }
383
384 void MediaControlRootElement::updateTimeDisplay()
385 {
386     float now = m_mediaController->currentTime();
387     float duration = m_mediaController->duration();
388
389     Page* page = document()->page();
390     if (!page)
391         return;
392
393     // Allow the theme to format the time.
394     ExceptionCode ec;
395     m_currentTimeDisplay->setInnerText(page->theme()->formatMediaControlsCurrentTime(now, duration), ec);
396     m_currentTimeDisplay->setCurrentValue(now);
397     m_timeRemainingDisplay->setInnerText(page->theme()->formatMediaControlsRemainingTime(now, duration), ec);
398     m_timeRemainingDisplay->setCurrentValue(now - duration);
399 }
400
401 void MediaControlRootElement::reportedError()
402 {
403     Page* page = document()->page();
404     if (!page)
405         return;
406
407     if (!page->theme()->hasOwnDisabledStateHandlingFor(MediaSliderPart))
408         m_timelineContainer->hide();
409
410     if (!page->theme()->hasOwnDisabledStateHandlingFor(MediaMuteButtonPart))
411         m_panelMuteButton->hide();
412
413      m_fullScreenButton->hide();
414
415     if (m_volumeSliderContainer)
416         m_volumeSliderContainer->hide();
417     if (m_toggleClosedCaptionsButton && !page->theme()->hasOwnDisabledStateHandlingFor(MediaToggleClosedCaptionsButtonPart))
418         m_toggleClosedCaptionsButton->hide();
419 }
420
421 void MediaControlRootElement::updateStatusDisplay()
422 {
423     if (m_statusDisplay)
424         m_statusDisplay->update();
425 }
426
427 void MediaControlRootElement::loadedMetadata()
428 {
429     if (m_statusDisplay && m_mediaController->isLiveStream())
430         m_statusDisplay->hide();
431
432     reset();
433 }
434
435 void MediaControlRootElement::changedClosedCaptionsVisibility()
436 {
437     if (m_toggleClosedCaptionsButton)
438         m_toggleClosedCaptionsButton->updateDisplayType();
439 }
440
441 void MediaControlRootElement::changedMute()
442 {
443     m_panelMuteButton->changedMute();
444     if (m_volumeSliderMuteButton)
445         m_volumeSliderMuteButton->changedMute();
446 }
447
448 void MediaControlRootElement::changedVolume()
449 {
450     if (m_volumeSlider)
451         m_volumeSlider->setVolume(m_mediaController->volume());
452 }
453
454 void MediaControlRootElement::enteredFullscreen()
455 {
456     if (m_mediaController->isLiveStream()) {
457         m_seekBackButton->hide();
458         m_seekForwardButton->hide();
459         m_rewindButton->show();
460         m_returnToRealTimeButton->show();
461     } else {
462         m_seekBackButton->show();
463         m_seekForwardButton->show();
464         m_rewindButton->hide();
465         m_returnToRealTimeButton->hide();
466     }
467
468     m_panel->setCanBeDragged(true);
469
470     if (Page* page = document()->page())
471         page->chrome()->setCursorHiddenUntilMouseMoves(true);
472
473     startHideFullscreenControlsTimer();
474 }
475
476 void MediaControlRootElement::exitedFullscreen()
477 {
478     // "show" actually means removal of display:none style, so we are just clearing styles
479     // when exiting fullscreen.
480     // FIXME: Clarify naming of show/hide <http://webkit.org/b/58157>
481     m_rewindButton->show();
482     m_seekBackButton->show();
483     m_seekForwardButton->show();
484     m_returnToRealTimeButton->show();
485
486     m_panel->setCanBeDragged(false);
487
488     // We will keep using the panel, but we want it to go back to the standard position.
489     // This will matter right away because we use the panel even when not fullscreen.
490     // And if we reenter fullscreen we also want the panel in the standard position.
491     m_panel->resetPosition();
492
493     stopHideFullscreenControlsTimer();    
494 }
495
496 void MediaControlRootElement::showVolumeSlider()
497 {
498     if (!m_mediaController->hasAudio())
499         return;
500
501     if (m_volumeSliderContainer)
502         m_volumeSliderContainer->show();
503 }
504
505 bool MediaControlRootElement::shouldHideControls()
506 {
507     return !m_panel->hovered();
508 }
509
510 bool MediaControlRootElement::containsRelatedTarget(Event* event)
511 {
512     if (!event->isMouseEvent())
513         return false;
514     EventTarget* relatedTarget = static_cast<MouseEvent*>(event)->relatedTarget();
515     if (!relatedTarget)
516         return false;
517     return contains(relatedTarget->toNode());
518 }
519
520 void MediaControlRootElement::defaultEventHandler(Event* event)
521 {
522     MediaControls::defaultEventHandler(event);
523
524     if (event->type() == eventNames().mouseoverEvent) {
525         if (!containsRelatedTarget(event)) {
526             m_isMouseOverControls = true;
527             if (!m_mediaController->canPlay()) {
528                 makeOpaque();
529                 if (shouldHideControls())
530                     startHideFullscreenControlsTimer();
531             }
532         }
533     } else if (event->type() == eventNames().mouseoutEvent) {
534         if (!containsRelatedTarget(event)) {
535             m_isMouseOverControls = false;
536             stopHideFullscreenControlsTimer();
537         }
538     } else if (event->type() == eventNames().mousemoveEvent) {
539         if (m_mediaController->isFullscreen()) {
540             // When we get a mouse move in fullscreen mode, show the media controls, and start a timer
541             // that will hide the media controls after a 3 seconds without a mouse move.
542             makeOpaque();
543             if (shouldHideControls())
544                 startHideFullscreenControlsTimer();
545         }
546     }
547 }
548
549 void MediaControlRootElement::startHideFullscreenControlsTimer()
550 {
551     if (!m_mediaController->isFullscreen())
552         return;
553     
554     m_hideFullscreenControlsTimer.startOneShot(timeWithoutMouseMovementBeforeHidingControls);
555 }
556
557 void MediaControlRootElement::hideFullscreenControlsTimerFired(Timer<MediaControlRootElement>*)
558 {
559     if (m_mediaController->paused())
560         return;
561     
562     if (!m_mediaController->isFullscreen())
563         return;
564     
565     if (!shouldHideControls())
566         return;
567
568     if (Page* page = document()->page())
569         page->chrome()->setCursorHiddenUntilMouseMoves(true);
570
571     makeTransparent();
572 }
573
574 void MediaControlRootElement::stopHideFullscreenControlsTimer()
575 {
576     m_hideFullscreenControlsTimer.stop();
577 }
578
579 const AtomicString& MediaControlRootElement::shadowPseudoId() const
580 {
581     DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls"));
582     return id;
583 }
584
585 }
586
587 #endif