Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(749)

Unified Diff: Source/core/html/shadow/MediaControls.cpp

Issue 1156993013: New media playback UI. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: manual rebaseline. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/html/shadow/MediaControls.cpp
diff --git a/Source/core/html/shadow/MediaControls.cpp b/Source/core/html/shadow/MediaControls.cpp
index 17d1096113fffeb9acbde1c6aaa10e83a405b48e..1325e20a7756d0398be662acb070f08f1a182a9a 100644
--- a/Source/core/html/shadow/MediaControls.cpp
+++ b/Source/core/html/shadow/MediaControls.cpp
@@ -35,6 +35,7 @@
#include "core/html/MediaController.h"
#include "core/html/track/TextTrackContainer.h"
#include "core/layout/LayoutTheme.h"
+#include "public/platform/Platform.h"
philipj_slow 2015/07/08 15:06:38 It doesn't look like this include is needed.
liberato (no reviews please) 2015/07/09 12:10:56 Done.
namespace blink {
@@ -89,9 +90,9 @@ PassRefPtrWillBeRawPtr<MediaControls> MediaControls::create(HTMLMediaElement& me
// \-MediaControlPanelEnclosureElement (-webkit-media-controls-enclosure)
// \-MediaControlPanelElement (-webkit-media-controls-panel)
// +-MediaControlPlayButtonElement (-webkit-media-controls-play-button)
-// +-MediaControlTimelineElement (-webkit-media-controls-timeline)
// +-MediaControlCurrentTimeDisplayElement (-webkit-media-controls-current-time-display)
// +-MediaControlTimeRemainingDisplayElement (-webkit-media-controls-time-remaining-display)
+// +-MediaControlTimelineElement (-webkit-media-controls-timeline)
philipj_slow 2015/07/08 15:06:38 Can you keep it in both places and annotated with
liberato (no reviews please) 2015/07/09 12:10:56 Done.
// +-MediaControlMuteButtonElement (-webkit-media-controls-mute-button)
// +-MediaControlVolumeSliderElement (-webkit-media-controls-volume-slider)
// +-MediaControlToggleClosedCaptionsButtonElement (-webkit-media-controls-toggle-closed-captions-button)
@@ -125,24 +126,43 @@ void MediaControls::initializeControls()
RefPtrWillBeRawPtr<MediaControlTimelineElement> timeline = MediaControlTimelineElement::create(*this);
m_timeline = timeline.get();
- panel->appendChild(timeline.release());
+ // In old UX, timeline is before the time / duration text.
+ if (!RuntimeEnabledFeatures::newMediaPlaybackUiEnabled())
+ panel->appendChild(timeline.release());
+ // else we will attach it later.
RefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> currentTimeDisplay = MediaControlCurrentTimeDisplayElement::create(*this);
m_currentTimeDisplay = currentTimeDisplay.get();
- m_currentTimeDisplay->hide();
+ if (!RuntimeEnabledFeatures::newMediaPlaybackUiEnabled())
+ m_currentTimeDisplay->dontWant();
+ else
+ m_currentTimeDisplay->want();
+
panel->appendChild(currentTimeDisplay.release());
RefPtrWillBeRawPtr<MediaControlTimeRemainingDisplayElement> durationDisplay = MediaControlTimeRemainingDisplayElement::create(*this);
m_durationDisplay = durationDisplay.get();
panel->appendChild(durationDisplay.release());
+ // In new UX, timeline is after the time / duration text.
+ if (RuntimeEnabledFeatures::newMediaPlaybackUiEnabled())
+ panel->appendChild(timeline.release());
+
RefPtrWillBeRawPtr<MediaControlMuteButtonElement> muteButton = MediaControlMuteButtonElement::create(*this);
m_muteButton = muteButton.get();
panel->appendChild(muteButton.release());
+#if OS(ANDROID)
+ if (RuntimeEnabledFeatures::newMediaPlaybackUiEnabled())
+ m_muteButton->dontWant();
+#endif
RefPtrWillBeRawPtr<MediaControlVolumeSliderElement> slider = MediaControlVolumeSliderElement::create(*this);
m_volumeSlider = slider.get();
panel->appendChild(slider.release());
+#if OS(ANDROID)
+ if (RuntimeEnabledFeatures::newMediaPlaybackUiEnabled())
+ m_volumeSlider->dontWant();
+#endif
RefPtrWillBeRawPtr<MediaControlToggleClosedCaptionsButtonElement> toggleClosedCaptionsButton = MediaControlToggleClosedCaptionsButtonElement::create(*this);
m_toggleClosedCaptionsButton = toggleClosedCaptionsButton.get();
@@ -165,10 +185,24 @@ void MediaControls::initializeControls()
void MediaControls::reset()
{
+ const bool useNewUi = RuntimeEnabledFeatures::newMediaPlaybackUiEnabled();
double duration = mediaElement().duration();
m_durationDisplay->setInnerText(LayoutTheme::theme().formatMediaControlsTime(duration), ASSERT_NO_EXCEPTION);
m_durationDisplay->setCurrentValue(duration);
+ if (useNewUi) {
+ // Show everything that we might hide.
+ // If we don't have a duration, then mark it to be hidden by
+ // scheduleUpdateControlsVisibilityForSpace(). For the old UI case, we still
+ // hide / show it here, too, since update*() won't.
+ if (std::isfinite(duration))
+ m_durationDisplay->want();
+ else
+ m_durationDisplay->dontWant();
+ m_currentTimeDisplay->want();
+ m_timeline->want();
+ }
+
updatePlayState();
updateCurrentTimeDisplay();
@@ -176,10 +210,20 @@ void MediaControls::reset()
m_timeline->setDuration(duration);
m_timeline->setPosition(mediaElement().currentTime());
- if (!mediaElement().hasAudio())
- m_volumeSlider->hide();
- else
- m_volumeSlider->show();
+ if (!mediaElement().hasAudio()) {
+ m_volumeSlider->dontWant();
+ } else {
+#if OS(ANDROID)
+ // New UI always hides the volume slider on Android.
+ if (useNewUi)
+ m_volumeSlider->dontWant();
+ else
+ m_volumeSlider->want();
+#else
+ m_volumeSlider->want();
+#endif
+ }
+
updateVolume();
refreshClosedCaptionsButtonVisibility();
@@ -190,13 +234,22 @@ void MediaControls::reset()
// the button earlier, and we don't want to remove it here if the
// user chose to enter fullscreen. crbug.com/500732 .
if ((mediaElement().hasVideo() && fullscreenIsSupported(document()))
- || mediaElement().isFullscreen())
- m_fullScreenButton->show();
- else
- m_fullScreenButton->hide();
+ || mediaElement().isFullscreen()) {
+ m_fullScreenButton->want();
+ } else {
+ m_fullScreenButton->dontWant();
+ }
refreshCastButtonVisibility();
+ scheduleUpdateControlsVisibilityForSpace();
fs 2015/07/08 09:31:00 First refreshCastButtonVisibility will call update
liberato (no reviews please) 2015/07/09 12:10:56 updated to ...WithoutLayout(), which is now called
makeOpaque();
+
+ // Request resize events from our layout object. Our show / hide logic
+ // would be better suited to a layout, but JS doesn't have that option.
+ // So, we opt for an event-based solution to keep the logic JS-friendly,
+ // though the particular event may change.
+ if (layoutObject() && useNewUi)
+ layoutObject()->setSendResizeEvent(true);
}
LayoutObject* MediaControls::layoutObjectForTextTrackLayout()
@@ -263,8 +316,10 @@ bool MediaControls::shouldHideMediaControls(unsigned behaviorFlags) const
void MediaControls::playbackStarted()
{
- m_currentTimeDisplay->show();
- m_durationDisplay->hide();
+ if (!RuntimeEnabledFeatures::newMediaPlaybackUiEnabled()) {
+ m_currentTimeDisplay->want();
+ m_durationDisplay->dontWant();
+ }
updatePlayState();
m_timeline->setPosition(mediaElement().currentTime());
@@ -325,9 +380,9 @@ void MediaControls::updateCurrentTimeDisplay()
double duration = mediaElement().duration();
// After seek, hide duration display and show current time.
- if (now > 0) {
- m_currentTimeDisplay->show();
- m_durationDisplay->hide();
+ if (!RuntimeEnabledFeatures::newMediaPlaybackUiEnabled() && now > 0) {
+ m_currentTimeDisplay->want();
+ m_durationDisplay->dontWant();
}
// Allow the theme to format the time.
@@ -359,9 +414,9 @@ void MediaControls::changedClosedCaptionsVisibility()
void MediaControls::refreshClosedCaptionsButtonVisibility()
{
if (mediaElement().hasClosedCaptions())
- m_toggleClosedCaptionsButton->show();
+ m_toggleClosedCaptionsButton->want();
else
- m_toggleClosedCaptionsButton->hide();
+ m_toggleClosedCaptionsButton->dontWant();
}
static Element* elementFromCenter(Element& element)
@@ -384,6 +439,12 @@ void MediaControls::tryShowOverlayCastButton()
void MediaControls::refreshCastButtonVisibility()
{
+ refreshCastButtonVisibilityWithoutLayout();
+ updateControlsVisibilityForSpace();
+}
+
+void MediaControls::refreshCastButtonVisibilityWithoutLayout()
philipj_slow 2015/07/08 15:06:38 This name doesn't seem right, getBoundingClientRec
liberato (no reviews please) 2015/07/09 12:10:56 "causes no more layouts than before". i've rename
+{
if (mediaElement().hasRemoteRoutes()) {
// The reason for the autoplay test is that some pages (e.g. vimeo.com) have an autoplay background video, which
// doesn't autoplay on Chrome for Android (we prevent it) so starts paused. In such cases we don't want to automatically
@@ -391,20 +452,31 @@ void MediaControls::refreshCastButtonVisibility()
// If a user does want to cast a paused autoplay video then they can still do so by touching or clicking on the
// video, which will cause the cast button to appear.
if (!mediaElement().shouldShowControls() && !mediaElement().autoplay() && mediaElement().paused()) {
+ // Note that this is a case where we add the overlay cast button
+ // without wanting the bar cast button. We depend on the fact
+ // that scheduleUpdate...() won't change overlay cast button
+ // visibility in this case.
showOverlayCastButton();
+ m_castButton->dontWant();
} else if (mediaElement().shouldShowControls()) {
m_overlayCastButton->hide();
- m_castButton->show();
- // Check that the cast button actually fits on the bar.
- if (m_fullScreenButton->getBoundingClientRect()->right() > m_panel->getBoundingClientRect()->right()) {
- m_castButton->hide();
+ m_castButton->want();
+ // Check that the cast button actually fits on the bar. For the
+ // new ui, we let updateControlsVisibilityForSpace() handle this.
+ if ( !RuntimeEnabledFeatures::newMediaPlaybackUiEnabled()
+ && m_fullScreenButton->getBoundingClientRect()->right() > m_panel->getBoundingClientRect()->right()) {
+ m_castButton->dontWant();
tryShowOverlayCastButton();
}
}
} else {
- m_castButton->hide();
+ m_castButton->dontWant();
m_overlayCastButton->hide();
}
+
+ // do NOT updateControls...() here - that triggers a layout.
+ // we could schedule, I suppose, though be careful that it
+ // doesn't also trigger one immediately.
}
void MediaControls::showOverlayCastButton()
@@ -451,6 +523,13 @@ void MediaControls::defaultEventHandler(Event* event)
|| (event->isMouseEvent() && toMouseEvent(event)->fromTouch());
m_hideTimerBehaviorFlags |= wasLastEventTouch ? IgnoreControlsHover : IgnoreNone;
+ // If we get a resize event, then update our controls. Note that if
+ // we get a resize in the old UI case, update*() will do nothing anyway.
+ if (event->type() == EventTypeNames::resize) {
+ updateControlsVisibilityForSpace();
+ return;
+ }
+
if (event->type() == EventTypeNames::mouseover) {
if (!containsRelatedTarget(event)) {
m_isMouseOverControls = true;
@@ -525,6 +604,72 @@ bool MediaControls::containsRelatedTarget(Event* event)
return contains(relatedTarget->toNode());
}
+void MediaControls::scheduleUpdateControlsVisibilityForSpace()
+{
+ // Schedule an update event for us, of the same type that our LayoutObject
+ // will send on resize. We post these rather than directly modify
+ // controls visibility because repaints are missed otherwise.
+ RefPtrWillBeRawPtr<Event> event = Event::create(EventTypeNames::resize);
+ event->setTarget(this);
+ LocalDOMWindow* win = document().executingWindow();
+ if (win)
+ win->eventQueue()->enqueueEvent(event);
+
+ // This causes a relayout when controls are queried, but it also sometimes
+ // misses paints. As in, mouse over will cause a control to show / hide.
+ updateControlsVisibilityForSpace(); // So that queries work
fs 2015/07/08 09:31:00 Having a schedule<operation> that also performs <o
liberato (no reviews please) 2015/07/09 12:10:56 true. it no longer does this.
+}
+
+void MediaControls::updateControlsVisibilityForSpace()
+{
+ // Hide all controls that don't fit, and show the ones that do.
+ // This might be better suited for a layout, but since JS media controls
+ // won't benefit from that anwyay, we just do it here like JS will.
+ // The order, in order of decreasing droppiness:
+ // Volume, time, seek bar, cast.
+
+ int panelWidth = m_panel->clientWidth();
+ if (panelWidth == 0)
+ return;
+
+ // Controls that we'll hide / show, in order of decreasing priority.
+ MediaControlElement* elements[] = {
+ m_playButton.get(),
+ m_toggleClosedCaptionsButton.get(),
+ m_fullScreenButton.get(),
+ m_timeline.get(),
+ m_currentTimeDisplay.get(),
+ m_volumeSlider.get(),
+ m_castButton.get(),
+ m_muteButton.get(),
+ m_durationDisplay.get(),
+ 0
+ };
+
+ int usedWidth = 0;
+ for (int i = 0; elements[i]; i++) {
+ if (elements[i]->isWanted()) {
+ if (usedWidth + elements[i]->minimumWidth() <= panelWidth) {
+ elements[i]->show();
+ usedWidth += elements[i]->minimumWidth();
+ } else {
+ elements[i]->hide();
+ }
+ } else {
+ elements[i]->hide(); // paranoia.
+ }
+ }
+
+ // Special case for cast: if we want a cast button but dropped it, then
+ // show the overlay cast button instead.
+ if (m_castButton->isWanted()) {
+ if (!m_castButton->isShown())
+ m_overlayCastButton->show();
+ else
+ m_overlayCastButton->hide();
+ } // else do not change overlay cast button state.
+}
+
DEFINE_TRACE(MediaControls)
{
visitor->trace(m_mediaElement);

Powered by Google App Engine
This is Rietveld 408576698