2011-05-29 Brian Weinstein <bweinstein@apple.com>
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 30 May 2011 03:37:14 +0000 (03:37 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 30 May 2011 03:37:14 +0000 (03:37 +0000)
        Reviewed by Darin Adler.

        Controls never hide in full screen after user stops moving mouse
        https://bugs.webkit.org/show_bug.cgi?id=61715
        <rdar://problem/9522182>

        When we get a mouse move event in HTMLMediaElement::defaultEventHandler, and we are in full screen,
        show the media controls, and then start a timer.

        The timer fires 3 seconds after the user's last mouse movement (timer is restarted on every mouse
        move), and hides the controls.

        * html/HTMLMediaElement.cpp:
        (WebCore::HTMLMediaElement::HTMLMediaElement): Initialize our new timer.
        (WebCore::HTMLMediaElement::play): If we are in full screen mode, start our timer to hide the full screen
            controls. We don't want the user to have to move the mouse to hide them when they use the spacebar
            to play.
        (WebCore::HTMLMediaElement::startHideFullscreenControlsTimer): Starts a oneshot timer 3 seconds in the future
            if we are in full screen.
        (WebCore::HTMLMediaElement::hideFullscreenControlsTimerFired): Make sure that we are currently playing, and
            we are in full screen, and hide the controls. We don't want to hide the controls if we are paused.
        (WebCore::HTMLMediaElement::stopHideFullscreenControlsTimer): Stops the timer.
        (WebCore::HTMLMediaElement::defaultEventHandler): If we get a mouse move event and are in full screen, show the
            controls and start a timer to hide them.
        (WebCore::HTMLMediaElement::enterFullscreen): Start a timer to hide the full screen controls. The user shouldn't
            have the move the mouse once they enter full screen to hide the controls.
        (WebCore::HTMLMediaElement::exitFullscreen): Stop the timer to hide the full screen controls.
        * html/HTMLMediaElement.h:
        * html/shadow/MediaControls.h: Added pure virtual shouldHideControls() method.
        * html/shadow/MediaControlRootElement.cpp:
        (WebCore::MediaControlRootElement::playbackStopped): Stop the timer to hide the full screen controls.
        (WebCore::MediaControlRootElement::shouldHideControls): Added, only report that
            the caller should hide the controls if the panel is not hovered.
        * html/shadow/MediaControlRootElement.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@87661 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLMediaElement.h
Source/WebCore/html/shadow/MediaControlRootElement.cpp
Source/WebCore/html/shadow/MediaControlRootElement.h
Source/WebCore/html/shadow/MediaControls.h

index 678929e..50ff814 100644 (file)
@@ -1,3 +1,40 @@
+2011-05-29  Brian Weinstein  <bweinstein@apple.com>
+
+        Reviewed by Darin Adler.
+
+        Controls never hide in full screen after user stops moving mouse
+        https://bugs.webkit.org/show_bug.cgi?id=61715
+        <rdar://problem/9522182>
+        
+        When we get a mouse move event in HTMLMediaElement::defaultEventHandler, and we are in full screen,
+        show the media controls, and then start a timer.
+        
+        The timer fires 3 seconds after the user's last mouse movement (timer is restarted on every mouse
+        move), and hides the controls.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::HTMLMediaElement): Initialize our new timer.
+        (WebCore::HTMLMediaElement::play): If we are in full screen mode, start our timer to hide the full screen
+            controls. We don't want the user to have to move the mouse to hide them when they use the spacebar
+            to play.
+        (WebCore::HTMLMediaElement::startHideFullscreenControlsTimer): Starts a oneshot timer 3 seconds in the future
+            if we are in full screen.
+        (WebCore::HTMLMediaElement::hideFullscreenControlsTimerFired): Make sure that we are currently playing, and
+            we are in full screen, and hide the controls. We don't want to hide the controls if we are paused.
+        (WebCore::HTMLMediaElement::stopHideFullscreenControlsTimer): Stops the timer.
+        (WebCore::HTMLMediaElement::defaultEventHandler): If we get a mouse move event and are in full screen, show the
+            controls and start a timer to hide them.
+        (WebCore::HTMLMediaElement::enterFullscreen): Start a timer to hide the full screen controls. The user shouldn't
+            have the move the mouse once they enter full screen to hide the controls.
+        (WebCore::HTMLMediaElement::exitFullscreen): Stop the timer to hide the full screen controls.
+        * html/HTMLMediaElement.h:
+        * html/shadow/MediaControls.h: Added pure virtual shouldHideControls() method.
+        * html/shadow/MediaControlRootElement.cpp:
+        (WebCore::MediaControlRootElement::playbackStopped): Stop the timer to hide the full screen controls.
+        (WebCore::MediaControlRootElement::shouldHideControls): Added, only report that
+            the caller should hide the controls if the panel is not hovered.
+        * html/shadow/MediaControlRootElement.h:
+
 2011-05-29  Jer Noble  <jer.noble@apple.com>
 
         Reviewed by Simon Fraser.
index d9efc39..faace8d 100644 (file)
@@ -123,6 +123,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* docum
     , m_asyncEventTimer(this, &HTMLMediaElement::asyncEventTimerFired)
     , m_progressEventTimer(this, &HTMLMediaElement::progressEventTimerFired)
     , m_playbackProgressTimer(this, &HTMLMediaElement::playbackProgressTimerFired)
+    , m_hideFullscreenControlsTimer(this, &HTMLMediaElement::hideFullscreenControlsTimerFired)
     , m_playedTimeRanges()
     , m_playbackRate(1.0f)
     , m_defaultPlaybackRate(1.0f)
@@ -1425,6 +1426,9 @@ void HTMLMediaElement::play(bool isUserGesture)
             return;
     }
     
+    if (isFullscreen())
+        startHideFullscreenControlsTimer();
+    
     playInternal();
 }
 
@@ -1610,6 +1614,8 @@ void HTMLMediaElement::endScrubbing()
 // "15 to 250ms", we choose the slowest frequency
 static const double maxTimeupdateEventFrequency = 0.25;
 
+static const double timeWithoutMouseMovementBeforeHidingControls = 3;
+
 void HTMLMediaElement::startPlaybackProgressTimer()
 {
     if (m_playbackProgressTimer.isActive())
@@ -1635,6 +1641,36 @@ void HTMLMediaElement::playbackProgressTimerFired(Timer<HTMLMediaElement>*)
     // FIXME: deal with cue ranges here
 }
 
+void HTMLMediaElement::startHideFullscreenControlsTimer()
+{
+    if (!isFullscreen())
+        return;
+    
+    m_hideFullscreenControlsTimer.startOneShot(timeWithoutMouseMovementBeforeHidingControls);
+}
+
+void HTMLMediaElement::hideFullscreenControlsTimerFired(Timer<HTMLMediaElement>*)
+{
+    if (!m_playing)
+        return;
+    
+    if (!isFullscreen())
+        return;
+    
+    if (!controls() || !hasMediaControls())
+        return;
+    
+    if (!mediaControls()->shouldHideControls())
+        return;
+        
+    mediaControls()->makeTransparent();
+}
+
+void HTMLMediaElement::stopHideFullscreenControlsTimer()
+{
+    m_hideFullscreenControlsTimer.stop();
+}
+
 void HTMLMediaElement::scheduleTimeupdateEvent(bool periodicEvent)
 {
     double now = WTF::currentTime();
@@ -2378,10 +2414,24 @@ void HTMLMediaElement::defaultEventHandler(Event* event)
         if (mouseEvent->relatedTarget() != this) {
             if (event->type() == eventNames().mouseoverEvent) {
                 m_mouseOver = true;
-                if (hasMediaControls() && controls() && !canPlay())
+                if (hasMediaControls() && controls() && !canPlay()) {
                     mediaControls()->makeOpaque();
-            } else if (event->type() == eventNames().mouseoutEvent)
+                    if (mediaControls()->shouldHideControls())
+                        startHideFullscreenControlsTimer();
+                }
+            } else if (event->type() == eventNames().mouseoutEvent) {
                 m_mouseOver = false;
+                stopHideFullscreenControlsTimer();
+            } else if (event->type() == eventNames().mousemoveEvent) {
+                if (isFullscreen() && hasMediaControls() && controls()) {
+                    // When we get a mouse move in fullscreen mode, show the media controls, and start a timer
+                    // that will hide the media controls after a 3 seconds without a mouse move.
+                    mediaControls()->makeOpaque();
+                    if (mediaControls()->shouldHideControls())
+                        startHideFullscreenControlsTimer();
+                }
+            }
+    
         }
     }
 
@@ -2518,6 +2568,9 @@ bool HTMLMediaElement::isFullscreen() const
 void HTMLMediaElement::enterFullscreen()
 {
     LOG(Media, "HTMLMediaElement::enterFullscreen");
+    
+    startHideFullscreenControlsTimer();
+    
 #if ENABLE(FULLSCREEN_API)
     if (document() && document()->settings() && document()->settings()->fullScreenEnabled()) {
         document()->requestFullScreenForElement(this, 0, Document::ExemptIFrameAllowFulScreenRequirement);
@@ -2537,6 +2590,9 @@ void HTMLMediaElement::enterFullscreen()
 void HTMLMediaElement::exitFullscreen()
 {
     LOG(Media, "HTMLMediaElement::exitFullscreen");
+    
+    stopHideFullscreenControlsTimer();
+    
 #if ENABLE(FULLSCREEN_API)
     if (document() && document()->settings() && document()->settings()->fullScreenEnabled()) {
         if (document()->webkitIsFullScreen() && document()->webkitCurrentFullScreenElement() == this)
index d352e44..c824e18 100644 (file)
@@ -146,6 +146,8 @@ public:
     void togglePlayState();
     void beginScrubbing();
     void endScrubbing();
+    
+    void stopHideFullscreenControlsTimer();
 
     bool canPlay() const;
 
@@ -270,8 +272,10 @@ private:
     void asyncEventTimerFired(Timer<HTMLMediaElement>*);
     void progressEventTimerFired(Timer<HTMLMediaElement>*);
     void playbackProgressTimerFired(Timer<HTMLMediaElement>*);
+    void hideFullscreenControlsTimerFired(Timer<HTMLMediaElement>*);
     void startPlaybackProgressTimer();
     void startProgressEventTimer();
+    void startHideFullscreenControlsTimer();
     void stopPeriodicTimers();
 
     void seek(float time, ExceptionCode&);
@@ -341,6 +345,7 @@ private:
     Timer<HTMLMediaElement> m_asyncEventTimer;
     Timer<HTMLMediaElement> m_progressEventTimer;
     Timer<HTMLMediaElement> m_playbackProgressTimer;
+    Timer<HTMLMediaElement> m_hideFullscreenControlsTimer;
     Vector<RefPtr<Event> > m_pendingEvents;
     RefPtr<TimeRanges> m_playedTimeRanges;
 
index a1e620b..e31f290 100644 (file)
@@ -350,6 +350,8 @@ void MediaControlRootElement::playbackStopped()
     m_timeline->setPosition(m_mediaElement->currentTime());
     updateTimeDisplay();
     makeOpaque();
+    
+    m_mediaElement->stopHideFullscreenControlsTimer();
 }
 
 void MediaControlRootElement::updateTimeDisplay()
@@ -457,6 +459,11 @@ void MediaControlRootElement::showVolumeSlider()
         m_volumeSliderContainer->show();
 }
 
+bool MediaControlRootElement::shouldHideControls()
+{
+    return !m_panel->hovered();
+}
+
 const AtomicString& MediaControlRootElement::shadowPseudoId() const
 {
     DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls"));
index 1fdcc01..7e0722f 100644 (file)
@@ -96,6 +96,7 @@ public:
     void updateTimeDisplay();
     void updateStatusDisplay();
 
+    virtual bool shouldHideControls();
 private:
     MediaControlRootElement(HTMLMediaElement*);
 
index 9acdb65..433b17b 100644 (file)
@@ -68,6 +68,8 @@ class MediaControls : public HTMLDivElement {
     virtual void updateTimeDisplay() = 0;
     virtual void updateStatusDisplay() = 0;
 
+    virtual bool shouldHideControls() = 0;
+
 protected:
     MediaControls(HTMLMediaElement*);