Chromium Code Reviews| Index: third_party/WebKit/Source/core/html/shadow/MediaControls.cpp |
| diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControls.cpp b/third_party/WebKit/Source/core/html/shadow/MediaControls.cpp |
| index 9652b7e9ef2c5f24ffaaa634bc31ec9b6efccb3d..03888b381a5f79c0c97ffb80287c42173679dd0d 100644 |
| --- a/third_party/WebKit/Source/core/html/shadow/MediaControls.cpp |
| +++ b/third_party/WebKit/Source/core/html/shadow/MediaControls.cpp |
| @@ -133,7 +133,8 @@ MediaControls::MediaControls(HTMLMediaElement& mediaElement) |
| &MediaControls::panelWidthChangedTimerFired), |
| m_panelWidth(0), |
| m_allowHiddenVolumeControls( |
| - RuntimeEnabledFeatures::newMediaPlaybackUiEnabled()) {} |
| + RuntimeEnabledFeatures::newMediaPlaybackUiEnabled()), |
| + m_keepShowingUntilTimerFires(false) {} |
| MediaControls* MediaControls::create(HTMLMediaElement& mediaElement) { |
| MediaControls* controls = new MediaControls(mediaElement); |
| @@ -391,6 +392,10 @@ void MediaControls::hide() { |
| m_overlayPlayButton->setIsWanted(false); |
| } |
| +bool MediaControls::isVisible() const { |
| + return m_panel->isOpaque(); |
| +} |
| + |
| void MediaControls::makeOpaque() { |
| m_panel->makeOpaque(); |
| } |
| @@ -402,26 +407,38 @@ void MediaControls::makeTransparent() { |
| bool MediaControls::shouldHideMediaControls(unsigned behaviorFlags) const { |
| // Never hide for a media element without visual representation. |
| if (!mediaElement().isHTMLVideoElement() || !mediaElement().hasVideo() || |
| - mediaElement().isPlayingRemotely()) |
| + mediaElement().isPlayingRemotely()) { |
| + return false; |
| + } |
| + |
| + // Keep the controls visible as long as the timer is running. |
| + const bool ignoreWaitForTimer = behaviorFlags & IgnoreWaitForTimer; |
| + if (!ignoreWaitForTimer && m_keepShowingUntilTimerFires) |
| return false; |
| + |
| // Don't hide if the mouse is over the controls. |
| const bool ignoreControlsHover = behaviorFlags & IgnoreControlsHover; |
| if (!ignoreControlsHover && m_panel->isHovered()) |
| return false; |
| + |
| // Don't hide if the mouse is over the video area. |
| const bool ignoreVideoHover = behaviorFlags & IgnoreVideoHover; |
| if (!ignoreVideoHover && m_isMouseOverControls) |
| return false; |
| + |
| // Don't hide if focus is on the HTMLMediaElement or within the |
| // controls/shadow tree. (Perform the checks separately to avoid going |
| // through all the potential ancestor hosts for the focused element.) |
| const bool ignoreFocus = behaviorFlags & IgnoreFocus; |
| if (!ignoreFocus && |
| - (mediaElement().isFocused() || contains(document().focusedElement()))) |
| + (mediaElement().isFocused() || contains(document().focusedElement()))) { |
| return false; |
| + } |
| + |
| // Don't hide the media controls when a panel is showing. |
| if (m_textTrackList->isWanted() || m_overflowList->isWanted()) |
| return false; |
| + |
| return true; |
| } |
| @@ -444,7 +461,7 @@ void MediaControls::playbackProgressed() { |
| m_timeline->setPosition(mediaElement().currentTime()); |
| updateCurrentTimeDisplay(); |
| - if (shouldHideMediaControls()) |
| + if (isVisible() && shouldHideMediaControls()) |
| makeTransparent(); |
| } |
| @@ -640,11 +657,35 @@ void MediaControls::defaultEventHandler(Event* event) { |
| // event, to allow the hide-timer to do the right thing when it fires. |
| // FIXME: Preferably we would only do this when we're actually handling the |
| // event here ourselves. |
| - bool wasLastEventTouch = |
| + bool isTouchEvent = |
| event->isTouchEvent() || event->isGestureEvent() || |
| (event->isMouseEvent() && toMouseEvent(event)->fromTouch()); |
| - m_hideTimerBehaviorFlags |= |
| - wasLastEventTouch ? IgnoreControlsHover : IgnoreNone; |
| + m_hideTimerBehaviorFlags |= isTouchEvent ? IgnoreControlsHover : IgnoreNone; |
| + |
| + // Touch events are treated differently to avoid fake mouse events to trigger |
| + // random behavior. The expect behaviour for touch is that a tap will show the |
| + // controls and they will hide when the timer to hide fires. |
| + if (isTouchEvent) { |
| + if (event->type() != EventTypeNames::gesturetap) |
| + return; |
| + |
| + if (!containsRelatedTarget(event)) { |
|
Zhiqiang Zhang (Slow)
2016/10/19 10:02:04
IIUC, the following logic is to handle the event b
mlamouri (slow - plz ping)
2016/10/20 10:32:06
Only the "setDefaultHandled" (to avoid the default
|
| + if (!mediaElement().paused()) { |
| + if (!isVisible()) { |
| + makeOpaque(); |
| + // When the panel switches from invisible to visible, we need to mark |
| + // the event handled to avoid buttons below the tap to be activated. |
| + event->setDefaultHandled(); |
| + } |
| + if (shouldHideMediaControls(IgnoreWaitForTimer)) { |
| + m_keepShowingUntilTimerFires = true; |
| + startHideMediaControlsTimer(); |
| + } |
| + } |
| + } |
| + |
| + return; |
| + } |
| if (event->type() == EventTypeNames::mouseover) { |
| if (!containsRelatedTarget(event)) { |
| @@ -681,6 +722,7 @@ void MediaControls::hideMediaControlsTimerFired(TimerBase*) { |
| unsigned behaviorFlags = |
| m_hideTimerBehaviorFlags | IgnoreFocus | IgnoreVideoHover; |
| m_hideTimerBehaviorFlags = IgnoreNone; |
| + m_keepShowingUntilTimerFires = false; |
| if (mediaElement().paused()) |
| return; |
| @@ -698,6 +740,7 @@ void MediaControls::startHideMediaControlsTimer() { |
| } |
| void MediaControls::stopHideMediaControlsTimer() { |
| + m_keepShowingUntilTimerFires = false; |
| m_hideMediaControlsTimer.stop(); |
| } |