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

Side by Side 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: cl feedback, rebased. Created 5 years, 4 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. 2 * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
3 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. 3 * Copyright (C) 2011, 2012 Google Inc. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 55
56 if (!mediaElement.hasVideo()) 56 if (!mediaElement.hasVideo())
57 return false; 57 return false;
58 58
59 if (!Fullscreen::fullscreenEnabled(mediaElement.document())) 59 if (!Fullscreen::fullscreenEnabled(mediaElement.document()))
60 return false; 60 return false;
61 61
62 return true; 62 return true;
63 } 63 }
64 64
65 static bool preferHiddenVolumeControls(const Document& document)
66 {
67 return !document.settings() || document.settings()->preferHiddenVolumeContro ls();
68 }
69
70 class MediaControls::BatchedControlUpdate {
71 public:
72 BatchedControlUpdate(MediaControls* controls) : m_controls(controls)
73 {
74 m_controls->beginBatchUpdate();
75 }
76 ~BatchedControlUpdate()
77 {
78 m_controls->endBatchUpdate();
79 }
80
81 private:
82 MediaControls* m_controls;
83 WTF_MAKE_NONCOPYABLE(BatchedControlUpdate);
philipj_slow 2015/08/04 11:54:53 This is usually before the public: bit, for some r
liberato (no reviews please) 2015/08/05 06:11:35 Done.
84 };
85
65 MediaControls::MediaControls(HTMLMediaElement& mediaElement) 86 MediaControls::MediaControls(HTMLMediaElement& mediaElement)
66 : HTMLDivElement(mediaElement.document()) 87 : HTMLDivElement(mediaElement.document())
67 , m_mediaElement(&mediaElement) 88 , m_mediaElement(&mediaElement)
68 , m_overlayEnclosure(nullptr) 89 , m_overlayEnclosure(nullptr)
69 , m_overlayPlayButton(nullptr) 90 , m_overlayPlayButton(nullptr)
70 , m_overlayCastButton(nullptr) 91 , m_overlayCastButton(nullptr)
71 , m_enclosure(nullptr) 92 , m_enclosure(nullptr)
72 , m_panel(nullptr) 93 , m_panel(nullptr)
73 , m_playButton(nullptr) 94 , m_playButton(nullptr)
74 , m_timeline(nullptr) 95 , m_timeline(nullptr)
75 , m_currentTimeDisplay(nullptr) 96 , m_currentTimeDisplay(nullptr)
76 , m_durationDisplay(nullptr) 97 , m_durationDisplay(nullptr)
77 , m_muteButton(nullptr) 98 , m_muteButton(nullptr)
78 , m_volumeSlider(nullptr) 99 , m_volumeSlider(nullptr)
79 , m_toggleClosedCaptionsButton(nullptr) 100 , m_toggleClosedCaptionsButton(nullptr)
80 , m_castButton(nullptr) 101 , m_castButton(nullptr)
81 , m_fullScreenButton(nullptr) 102 , m_fullScreenButton(nullptr)
82 , m_hideMediaControlsTimer(this, &MediaControls::hideMediaControlsTimerFired ) 103 , m_hideMediaControlsTimer(this, &MediaControls::hideMediaControlsTimerFired )
83 , m_hideTimerBehaviorFlags(IgnoreNone) 104 , m_hideTimerBehaviorFlags(IgnoreNone)
84 , m_isMouseOverControls(false) 105 , m_isMouseOverControls(false)
85 , m_isPausedForScrubbing(false) 106 , m_isPausedForScrubbing(false)
107 , m_panelWidthChangedTimer(this, &MediaControls::panelWidthChangedTimerFired )
108 , m_panelWidth(0)
109 , m_allowHiddenVolumeControls(RuntimeEnabledFeatures::newMediaPlaybackUiEnab led())
110 , m_keepMuteButton(false)
111 , m_batchDepth(0)
86 { 112 {
87 } 113 }
88 114
89 PassRefPtrWillBeRawPtr<MediaControls> MediaControls::create(HTMLMediaElement& me diaElement) 115 PassRefPtrWillBeRawPtr<MediaControls> MediaControls::create(HTMLMediaElement& me diaElement)
90 { 116 {
91 RefPtrWillBeRawPtr<MediaControls> controls = adoptRefWillBeNoop(new MediaCon trols(mediaElement)); 117 RefPtrWillBeRawPtr<MediaControls> controls = adoptRefWillBeNoop(new MediaCon trols(mediaElement));
92 controls->setShadowPseudoId(AtomicString("-webkit-media-controls", AtomicStr ing::ConstructFromLiteral)); 118 controls->setShadowPseudoId(AtomicString("-webkit-media-controls", AtomicStr ing::ConstructFromLiteral));
93 controls->initializeControls(); 119 controls->initializeControls();
94 return controls.release(); 120 return controls.release();
95 } 121 }
96 122
97 // The media controls DOM structure looks like: 123 // The media controls DOM structure looks like:
98 // 124 //
99 // MediaControls (-webkit-media-controls) 125 // MediaControls (-webkit-media-controls)
100 // +-MediaControlOverlayEnclosureElement (-webkit-media-controls-o verlay-enclosure) 126 // +-MediaControlOverlayEnclosureElement (-webkit-media-controls-o verlay-enclosure)
101 // | +-MediaControlOverlayPlayButtonElement (-webkit-media-controls-o verlay-play-button) 127 // | +-MediaControlOverlayPlayButtonElement (-webkit-media-controls-o verlay-play-button)
102 // | | {if mediaControlsOverlayPlayButtonEnabled} 128 // | | {if mediaControlsOverlayPlayButtonEnabled}
103 // | \-MediaControlCastButtonElement (-internal-media-controls -overlay-cast-button) 129 // | \-MediaControlCastButtonElement (-internal-media-controls -overlay-cast-button)
104 // \-MediaControlPanelEnclosureElement (-webkit-media-controls-e nclosure) 130 // \-MediaControlPanelEnclosureElement (-webkit-media-controls-e nclosure)
105 // \-MediaControlPanelElement (-webkit-media-controls-p anel) 131 // \-MediaControlPanelElement (-webkit-media-controls-p anel)
106 // +-MediaControlPlayButtonElement (-webkit-media-controls-p lay-button) 132 // +-MediaControlPlayButtonElement (-webkit-media-controls-p lay-button)
133 // | {if !RTE::newMediaPlaybackUi()}
107 // +-MediaControlTimelineElement (-webkit-media-controls-t imeline) 134 // +-MediaControlTimelineElement (-webkit-media-controls-t imeline)
108 // +-MediaControlCurrentTimeDisplayElement (-webkit-media-controls-c urrent-time-display) 135 // +-MediaControlCurrentTimeDisplayElement (-webkit-media-controls-c urrent-time-display)
109 // +-MediaControlTimeRemainingDisplayElement (-webkit-media-controls-t ime-remaining-display) 136 // +-MediaControlTimeRemainingDisplayElement (-webkit-media-controls-t ime-remaining-display)
137 // | {if RTE::newMediaPlaybackUi()}
138 // +-MediaControlTimelineElement (-webkit-media-controls-t imeline)
110 // +-MediaControlMuteButtonElement (-webkit-media-controls-m ute-button) 139 // +-MediaControlMuteButtonElement (-webkit-media-controls-m ute-button)
111 // +-MediaControlVolumeSliderElement (-webkit-media-controls-v olume-slider) 140 // +-MediaControlVolumeSliderElement (-webkit-media-controls-v olume-slider)
112 // +-MediaControlToggleClosedCaptionsButtonElement (-webkit-media-controls-t oggle-closed-captions-button) 141 // +-MediaControlToggleClosedCaptionsButtonElement (-webkit-media-controls-t oggle-closed-captions-button)
113 // +-MediaControlCastButtonElement (-internal-media-controls -cast-button) 142 // +-MediaControlCastButtonElement (-internal-media-controls -cast-button)
114 // \-MediaControlFullscreenButtonElement (-webkit-media-controls-f ullscreen-button) 143 // \-MediaControlFullscreenButtonElement (-webkit-media-controls-f ullscreen-button)
115 void MediaControls::initializeControls() 144 void MediaControls::initializeControls()
116 { 145 {
146 const bool useNewUi = RuntimeEnabledFeatures::newMediaPlaybackUiEnabled();
117 RefPtrWillBeRawPtr<MediaControlOverlayEnclosureElement> overlayEnclosure = M ediaControlOverlayEnclosureElement::create(*this); 147 RefPtrWillBeRawPtr<MediaControlOverlayEnclosureElement> overlayEnclosure = M ediaControlOverlayEnclosureElement::create(*this);
118 148
119 if (document().settings() && document().settings()->mediaControlsOverlayPlay ButtonEnabled()) { 149 if (document().settings() && document().settings()->mediaControlsOverlayPlay ButtonEnabled()) {
120 RefPtrWillBeRawPtr<MediaControlOverlayPlayButtonElement> overlayPlayButt on = MediaControlOverlayPlayButtonElement::create(*this); 150 RefPtrWillBeRawPtr<MediaControlOverlayPlayButtonElement> overlayPlayButt on = MediaControlOverlayPlayButtonElement::create(*this);
121 m_overlayPlayButton = overlayPlayButton.get(); 151 m_overlayPlayButton = overlayPlayButton.get();
122 overlayEnclosure->appendChild(overlayPlayButton.release()); 152 overlayEnclosure->appendChild(overlayPlayButton.release());
123 } 153 }
124 154
125 RefPtrWillBeRawPtr<MediaControlCastButtonElement> overlayCastButton = MediaC ontrolCastButtonElement::create(*this, true); 155 RefPtrWillBeRawPtr<MediaControlCastButtonElement> overlayCastButton = MediaC ontrolCastButtonElement::create(*this, true);
126 m_overlayCastButton = overlayCastButton.get(); 156 m_overlayCastButton = overlayCastButton.get();
127 overlayEnclosure->appendChild(overlayCastButton.release()); 157 overlayEnclosure->appendChild(overlayCastButton.release());
128 158
129 m_overlayEnclosure = overlayEnclosure.get(); 159 m_overlayEnclosure = overlayEnclosure.get();
130 appendChild(overlayEnclosure.release()); 160 appendChild(overlayEnclosure.release());
131 161
132 // Create an enclosing element for the panel so we can visually offset the c ontrols correctly. 162 // Create an enclosing element for the panel so we can visually offset the c ontrols correctly.
133 RefPtrWillBeRawPtr<MediaControlPanelEnclosureElement> enclosure = MediaContr olPanelEnclosureElement::create(*this); 163 RefPtrWillBeRawPtr<MediaControlPanelEnclosureElement> enclosure = MediaContr olPanelEnclosureElement::create(*this);
134 164
135 RefPtrWillBeRawPtr<MediaControlPanelElement> panel = MediaControlPanelElemen t::create(*this); 165 RefPtrWillBeRawPtr<MediaControlPanelElement> panel = MediaControlPanelElemen t::create(*this);
136 166
137 RefPtrWillBeRawPtr<MediaControlPlayButtonElement> playButton = MediaControlP layButtonElement::create(*this); 167 RefPtrWillBeRawPtr<MediaControlPlayButtonElement> playButton = MediaControlP layButtonElement::create(*this);
138 m_playButton = playButton.get(); 168 m_playButton = playButton.get();
139 panel->appendChild(playButton.release()); 169 panel->appendChild(playButton.release());
140 170
141 RefPtrWillBeRawPtr<MediaControlTimelineElement> timeline = MediaControlTimel ineElement::create(*this); 171 RefPtrWillBeRawPtr<MediaControlTimelineElement> timeline = MediaControlTimel ineElement::create(*this);
142 m_timeline = timeline.get(); 172 m_timeline = timeline.get();
143 panel->appendChild(timeline.release()); 173 // In old UX, timeline is before the time / duration text.
174 if (!useNewUi)
175 panel->appendChild(timeline.release());
176 // else we will attach it later.
144 177
145 RefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> currentTimeDisplay = MediaControlCurrentTimeDisplayElement::create(*this); 178 RefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> currentTimeDisplay = MediaControlCurrentTimeDisplayElement::create(*this);
146 m_currentTimeDisplay = currentTimeDisplay.get(); 179 m_currentTimeDisplay = currentTimeDisplay.get();
147 m_currentTimeDisplay->hide(); 180 m_currentTimeDisplay->setIsWanted(useNewUi);
148 panel->appendChild(currentTimeDisplay.release()); 181 panel->appendChild(currentTimeDisplay.release());
149 182
150 RefPtrWillBeRawPtr<MediaControlTimeRemainingDisplayElement> durationDisplay = MediaControlTimeRemainingDisplayElement::create(*this); 183 RefPtrWillBeRawPtr<MediaControlTimeRemainingDisplayElement> durationDisplay = MediaControlTimeRemainingDisplayElement::create(*this);
151 m_durationDisplay = durationDisplay.get(); 184 m_durationDisplay = durationDisplay.get();
152 panel->appendChild(durationDisplay.release()); 185 panel->appendChild(durationDisplay.release());
153 186
187 // Timeline is after the time / duration text if newMediaPlaybackUiEnabled.
188 if (useNewUi)
189 panel->appendChild(timeline.release());
190
154 RefPtrWillBeRawPtr<MediaControlMuteButtonElement> muteButton = MediaControlM uteButtonElement::create(*this); 191 RefPtrWillBeRawPtr<MediaControlMuteButtonElement> muteButton = MediaControlM uteButtonElement::create(*this);
155 m_muteButton = muteButton.get(); 192 m_muteButton = muteButton.get();
156 panel->appendChild(muteButton.release()); 193 panel->appendChild(muteButton.release());
194 if (m_allowHiddenVolumeControls && preferHiddenVolumeControls(document()))
195 m_muteButton->setIsWanted(false);
157 196
158 RefPtrWillBeRawPtr<MediaControlVolumeSliderElement> slider = MediaControlVol umeSliderElement::create(*this); 197 RefPtrWillBeRawPtr<MediaControlVolumeSliderElement> slider = MediaControlVol umeSliderElement::create(*this);
159 m_volumeSlider = slider.get(); 198 m_volumeSlider = slider.get();
160 panel->appendChild(slider.release()); 199 panel->appendChild(slider.release());
200 if (m_allowHiddenVolumeControls && preferHiddenVolumeControls(document()))
201 m_volumeSlider->setIsWanted(false);
161 202
162 RefPtrWillBeRawPtr<MediaControlToggleClosedCaptionsButtonElement> toggleClos edCaptionsButton = MediaControlToggleClosedCaptionsButtonElement::create(*this); 203 RefPtrWillBeRawPtr<MediaControlToggleClosedCaptionsButtonElement> toggleClos edCaptionsButton = MediaControlToggleClosedCaptionsButtonElement::create(*this);
163 m_toggleClosedCaptionsButton = toggleClosedCaptionsButton.get(); 204 m_toggleClosedCaptionsButton = toggleClosedCaptionsButton.get();
164 panel->appendChild(toggleClosedCaptionsButton.release()); 205 panel->appendChild(toggleClosedCaptionsButton.release());
165 206
166 RefPtrWillBeRawPtr<MediaControlCastButtonElement> castButton = MediaControlC astButtonElement::create(*this, false); 207 RefPtrWillBeRawPtr<MediaControlCastButtonElement> castButton = MediaControlC astButtonElement::create(*this, false);
167 m_castButton = castButton.get(); 208 m_castButton = castButton.get();
168 panel->appendChild(castButton.release()); 209 panel->appendChild(castButton.release());
169 210
170 RefPtrWillBeRawPtr<MediaControlFullscreenButtonElement> fullscreenButton = M ediaControlFullscreenButtonElement::create(*this); 211 RefPtrWillBeRawPtr<MediaControlFullscreenButtonElement> fullscreenButton = M ediaControlFullscreenButtonElement::create(*this);
171 m_fullScreenButton = fullscreenButton.get(); 212 m_fullScreenButton = fullscreenButton.get();
172 panel->appendChild(fullscreenButton.release()); 213 panel->appendChild(fullscreenButton.release());
173 214
174 m_panel = panel.get(); 215 m_panel = panel.get();
175 enclosure->appendChild(panel.release()); 216 enclosure->appendChild(panel.release());
176 217
177 m_enclosure = enclosure.get(); 218 m_enclosure = enclosure.get();
178 appendChild(enclosure.release()); 219 appendChild(enclosure.release());
179 } 220 }
180 221
181 void MediaControls::reset() 222 void MediaControls::reset()
182 { 223 {
183 double duration = mediaElement().duration(); 224 const bool useNewUi = RuntimeEnabledFeatures::newMediaPlaybackUiEnabled();
225 BatchedControlUpdate batch(this);
226
227 m_allowHiddenVolumeControls = useNewUi;
228 m_keepMuteButton = false;
229
230 const double duration = mediaElement().duration();
184 m_durationDisplay->setInnerText(LayoutTheme::theme().formatMediaControlsTime (duration), ASSERT_NO_EXCEPTION); 231 m_durationDisplay->setInnerText(LayoutTheme::theme().formatMediaControlsTime (duration), ASSERT_NO_EXCEPTION);
185 m_durationDisplay->setCurrentValue(duration); 232 m_durationDisplay->setCurrentValue(duration);
186 233
234 if (useNewUi) {
235 // Show everything that we might hide.
236 // If we don't have a duration, then mark it to be hidden. For the
237 // old UI case, want / don't want is the same as show / hide since
238 // it is never marked as not fitting.
239 m_durationDisplay->setIsWanted(std::isfinite(duration));
240 m_currentTimeDisplay->setIsWanted(true);
241 m_timeline->setIsWanted(true);
242 }
243
187 updatePlayState(); 244 updatePlayState();
188 245
189 updateCurrentTimeDisplay(); 246 updateCurrentTimeDisplay();
190 247
191 m_timeline->setDuration(duration); 248 m_timeline->setDuration(duration);
192 m_timeline->setPosition(mediaElement().currentTime()); 249 m_timeline->setPosition(mediaElement().currentTime());
193 250
194 if (!mediaElement().hasAudio())
195 m_volumeSlider->hide();
196 else
197 m_volumeSlider->show();
198 updateVolume(); 251 updateVolume();
199 252
200 refreshClosedCaptionsButtonVisibility(); 253 refreshClosedCaptionsButtonVisibility();
201 254
202 if (shouldShowFullscreenButton(mediaElement())) 255 m_fullScreenButton->setIsWanted(shouldShowFullscreenButton(mediaElement()));
203 m_fullScreenButton->show();
204 else
205 m_fullScreenButton->hide();
206 256
207 refreshCastButtonVisibility(); 257 refreshCastButtonVisibilityWithoutUpdate();
208 makeOpaque(); 258 makeOpaque();
259
260 // Set the panel width here, and force a layout, before the controls update .
261 m_panelWidth = m_panel->clientWidth();
209 } 262 }
210 263
211 LayoutObject* MediaControls::layoutObjectForTextTrackLayout() 264 LayoutObject* MediaControls::layoutObjectForTextTrackLayout()
212 { 265 {
213 return m_panel->layoutObject(); 266 return m_panel->layoutObject();
214 } 267 }
215 268
216 void MediaControls::show() 269 void MediaControls::show()
217 { 270 {
218 makeOpaque(); 271 makeOpaque();
219 m_panel->show(); 272 m_panel->setIsWanted(true);
220 m_panel->setIsDisplayed(true); 273 m_panel->setIsDisplayed(true);
221 if (m_overlayPlayButton) 274 if (m_overlayPlayButton)
222 m_overlayPlayButton->updateDisplayType(); 275 m_overlayPlayButton->updateDisplayType();
223 } 276 }
224 277
225 void MediaControls::mediaElementFocused() 278 void MediaControls::mediaElementFocused()
226 { 279 {
227 if (mediaElement().shouldShowControls()) { 280 if (mediaElement().shouldShowControls()) {
228 show(); 281 show();
229 resetHideMediaControlsTimer(); 282 resetHideMediaControlsTimer();
230 } 283 }
231 } 284 }
232 285
233 void MediaControls::hide() 286 void MediaControls::hide()
234 { 287 {
235 m_panel->hide(); 288 m_panel->setIsWanted(false);
236 m_panel->setIsDisplayed(false); 289 m_panel->setIsDisplayed(false);
237 if (m_overlayPlayButton) 290 if (m_overlayPlayButton)
238 m_overlayPlayButton->hide(); 291 m_overlayPlayButton->setIsWanted(false);
239 } 292 }
240 293
241 void MediaControls::makeOpaque() 294 void MediaControls::makeOpaque()
242 { 295 {
243 m_panel->makeOpaque(); 296 m_panel->makeOpaque();
244 } 297 }
245 298
246 void MediaControls::makeTransparent() 299 void MediaControls::makeTransparent()
247 { 300 {
248 m_panel->makeTransparent(); 301 m_panel->makeTransparent();
302 m_overlayCastButton->setIsWanted(false);
249 } 303 }
250 304
251 bool MediaControls::shouldHideMediaControls(unsigned behaviorFlags) const 305 bool MediaControls::shouldHideMediaControls(unsigned behaviorFlags) const
252 { 306 {
253 // Never hide for a media element without visual representation. 307 // Never hide for a media element without visual representation.
254 if (!mediaElement().hasVideo() || mediaElement().isPlayingRemotely()) 308 if (!mediaElement().hasVideo() || mediaElement().isPlayingRemotely())
255 return false; 309 return false;
256 // Don't hide if the mouse is over the controls. 310 // Don't hide if the mouse is over the controls.
257 const bool ignoreControlsHover = behaviorFlags & IgnoreControlsHover; 311 const bool ignoreControlsHover = behaviorFlags & IgnoreControlsHover;
258 if (!ignoreControlsHover && m_panel->hovered()) 312 if (!ignoreControlsHover && m_panel->hovered())
259 return false; 313 return false;
260 // Don't hide if the mouse is over the video area. 314 // Don't hide if the mouse is over the video area.
261 const bool ignoreVideoHover = behaviorFlags & IgnoreVideoHover; 315 const bool ignoreVideoHover = behaviorFlags & IgnoreVideoHover;
262 if (!ignoreVideoHover && m_isMouseOverControls) 316 if (!ignoreVideoHover && m_isMouseOverControls)
263 return false; 317 return false;
264 // Don't hide if focus is on the HTMLMediaElement or within the 318 // Don't hide if focus is on the HTMLMediaElement or within the
265 // controls/shadow tree. (Perform the checks separately to avoid going 319 // controls/shadow tree. (Perform the checks separately to avoid going
266 // through all the potential ancestor hosts for the focused element.) 320 // through all the potential ancestor hosts for the focused element.)
267 const bool ignoreFocus = behaviorFlags & IgnoreFocus; 321 const bool ignoreFocus = behaviorFlags & IgnoreFocus;
268 if (!ignoreFocus && (mediaElement().focused() || contains(document().focused Element()))) 322 if (!ignoreFocus && (mediaElement().focused() || contains(document().focused Element())))
269 return false; 323 return false;
270 return true; 324 return true;
271 } 325 }
272 326
273 void MediaControls::playbackStarted() 327 void MediaControls::playbackStarted()
274 { 328 {
275 m_currentTimeDisplay->show(); 329 BatchedControlUpdate batch(this);
276 m_durationDisplay->hide(); 330
331 if (!RuntimeEnabledFeatures::newMediaPlaybackUiEnabled()) {
332 m_currentTimeDisplay->setIsWanted(true);
333 m_durationDisplay->setIsWanted(false);
334 }
277 335
278 updatePlayState(); 336 updatePlayState();
279 m_timeline->setPosition(mediaElement().currentTime()); 337 m_timeline->setPosition(mediaElement().currentTime());
280 updateCurrentTimeDisplay(); 338 updateCurrentTimeDisplay();
281 339
282 startHideMediaControlsTimer(); 340 startHideMediaControlsTimer();
283 } 341 }
284 342
285 void MediaControls::playbackProgressed() 343 void MediaControls::playbackProgressed()
286 { 344 {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 mediaElement().togglePlayState(); 385 mediaElement().togglePlayState();
328 } 386 }
329 } 387 }
330 388
331 void MediaControls::updateCurrentTimeDisplay() 389 void MediaControls::updateCurrentTimeDisplay()
332 { 390 {
333 double now = mediaElement().currentTime(); 391 double now = mediaElement().currentTime();
334 double duration = mediaElement().duration(); 392 double duration = mediaElement().duration();
335 393
336 // After seek, hide duration display and show current time. 394 // After seek, hide duration display and show current time.
337 if (now > 0) { 395 if (!RuntimeEnabledFeatures::newMediaPlaybackUiEnabled() && now > 0) {
338 m_currentTimeDisplay->show(); 396 BatchedControlUpdate batch(this);
339 m_durationDisplay->hide(); 397 m_currentTimeDisplay->setIsWanted(true);
398 m_durationDisplay->setIsWanted(false);
340 } 399 }
341 400
342 // Allow the theme to format the time. 401 // Allow the theme to format the time.
343 m_currentTimeDisplay->setInnerText(LayoutTheme::theme().formatMediaControlsC urrentTime(now, duration), IGNORE_EXCEPTION); 402 m_currentTimeDisplay->setInnerText(LayoutTheme::theme().formatMediaControlsC urrentTime(now, duration), IGNORE_EXCEPTION);
344 m_currentTimeDisplay->setCurrentValue(now); 403 m_currentTimeDisplay->setCurrentValue(now);
345 } 404 }
346 405
347 void MediaControls::updateVolume() 406 void MediaControls::updateVolume()
348 { 407 {
349 m_muteButton->updateDisplayType(); 408 m_muteButton->updateDisplayType();
350 // Invalidate the mute button because it paints differently according to vol ume. 409 // Invalidate the mute button because it paints differently according to vol ume.
351 if (LayoutObject* layoutObject = m_muteButton->layoutObject()) 410 if (LayoutObject* layoutObject = m_muteButton->layoutObject())
352 layoutObject->setShouldDoFullPaintInvalidation(); 411 layoutObject->setShouldDoFullPaintInvalidation();
353 412
354 if (mediaElement().muted()) 413 if (mediaElement().muted())
355 m_volumeSlider->setVolume(0); 414 m_volumeSlider->setVolume(0);
356 else 415 else
357 m_volumeSlider->setVolume(mediaElement().volume()); 416 m_volumeSlider->setVolume(mediaElement().volume());
417
418 // Update the visibility of our audio elements.
419 // We never want the volume slider if there's no audio.
420 // If there is audio, then we want it unless hiding audio is enabled and
421 // we prefer to hide it.
422 BatchedControlUpdate batch(this);
423 m_volumeSlider->setIsWanted(mediaElement().hasAudio()
424 && !(m_allowHiddenVolumeControls && preferHiddenVolumeControls(document( ))));
425
426 // The mute button is a little more complicated. If enableNewMediaPlaybackU i
427 // is true, then we choose to hide or show the mute button to save space.
428 // If enableNew* is not set, then we never touch the mute button, and
429 // instead leave it to the CSS.
430 // Note that this is why m_allowHiddenVolumeControls isn't rolled into prefe r...().
431 if (m_allowHiddenVolumeControls) {
432 // If there is no audio track, then hide the mute button. If there
433 // is an audio track, then we always show the mute button unless
434 // we prefer to hide it and the media isn't muted. If it's muted,
435 // then we show it to let the user unmute it. In this case, we don't
436 // want to re-hide the mute button later.
437 m_keepMuteButton |= mediaElement().muted();
438 m_muteButton->setIsWanted(mediaElement().hasAudio()
439 && (!preferHiddenVolumeControls(document()) || m_keepMuteButton));
440 }
441
358 // Invalidate the volume slider because it paints differently according to v olume. 442 // Invalidate the volume slider because it paints differently according to v olume.
359 if (LayoutObject* layoutObject = m_volumeSlider->layoutObject()) 443 if (LayoutObject* layoutObject = m_volumeSlider->layoutObject())
360 layoutObject->setShouldDoFullPaintInvalidation(); 444 layoutObject->setShouldDoFullPaintInvalidation();
361 } 445 }
362 446
363 void MediaControls::changedClosedCaptionsVisibility() 447 void MediaControls::changedClosedCaptionsVisibility()
364 { 448 {
365 m_toggleClosedCaptionsButton->updateDisplayType(); 449 m_toggleClosedCaptionsButton->updateDisplayType();
366 } 450 }
367 451
368 void MediaControls::refreshClosedCaptionsButtonVisibility() 452 void MediaControls::refreshClosedCaptionsButtonVisibility()
369 { 453 {
370 if (mediaElement().hasClosedCaptions()) 454 m_toggleClosedCaptionsButton->setIsWanted(mediaElement().hasClosedCaptions() );
371 m_toggleClosedCaptionsButton->show(); 455 BatchedControlUpdate batch(this);
372 else
373 m_toggleClosedCaptionsButton->hide();
374 } 456 }
375 457
376 static Element* elementFromCenter(Element& element) 458 static Element* elementFromCenter(Element& element)
377 { 459 {
378 ClientRect* clientRect = element.getBoundingClientRect(); 460 ClientRect* clientRect = element.getBoundingClientRect();
379 int centerX = static_cast<int>((clientRect->left() + clientRect->right()) / 2); 461 int centerX = static_cast<int>((clientRect->left() + clientRect->right()) / 2);
380 int centerY = static_cast<int>((clientRect->top() + clientRect->bottom()) / 2); 462 int centerY = static_cast<int>((clientRect->top() + clientRect->bottom()) / 2);
381 463
382 return element.document().elementFromPoint(centerX , centerY); 464 return element.document().elementFromPoint(centerX , centerY);
383 } 465 }
384 466
385 void MediaControls::tryShowOverlayCastButton() 467 void MediaControls::tryShowOverlayCastButton()
386 { 468 {
387 // The element needs to be shown to have its dimensions and position. 469 // The element needs to be shown to have its dimensions and position.
388 m_overlayCastButton->show(); 470 m_overlayCastButton->setIsWanted(true);
389
390 if (elementFromCenter(*m_overlayCastButton) != &mediaElement()) 471 if (elementFromCenter(*m_overlayCastButton) != &mediaElement())
391 m_overlayCastButton->hide(); 472 m_overlayCastButton->setIsWanted(false);
392 } 473 }
393 474
394 void MediaControls::refreshCastButtonVisibility() 475 void MediaControls::refreshCastButtonVisibility()
395 { 476 {
477 refreshCastButtonVisibilityWithoutUpdate();
478 BatchedControlUpdate batch(this);
479 }
480
481 void MediaControls::refreshCastButtonVisibilityWithoutUpdate()
482 {
396 if (mediaElement().hasRemoteRoutes()) { 483 if (mediaElement().hasRemoteRoutes()) {
397 // The reason for the autoplay test is that some pages (e.g. vimeo.com) have an autoplay background video, which 484 // The reason for the autoplay test is that some pages (e.g. vimeo.com) have an autoplay background video, which
398 // doesn't autoplay on Chrome for Android (we prevent it) so starts paus ed. In such cases we don't want to automatically 485 // doesn't autoplay on Chrome for Android (we prevent it) so starts paus ed. In such cases we don't want to automatically
399 // show the cast button, since it looks strange and is unlikely to corre spond with anything the user wants to do. 486 // show the cast button, since it looks strange and is unlikely to corre spond with anything the user wants to do.
400 // If a user does want to cast a paused autoplay video then they can sti ll do so by touching or clicking on the 487 // If a user does want to cast a paused autoplay video then they can sti ll do so by touching or clicking on the
401 // video, which will cause the cast button to appear. 488 // video, which will cause the cast button to appear.
402 if (!mediaElement().shouldShowControls() && !mediaElement().autoplay() & & mediaElement().paused()) { 489 if (!mediaElement().shouldShowControls() && !mediaElement().autoplay() & & mediaElement().paused()) {
403 showOverlayCastButton(); 490 // Note that this is a case where we add the overlay cast button
491 // without wanting the panel cast button. We depend on the fact
492 // that computeWhichControlsFit() won't change overlay cast button
493 // visibility in the case where the cast button isn't wanted.
494 // We don't call compute...() here, but it will be called as
495 // non-cast changes (e.g., resize) occur. If the panel button
496 // is shown, however, compute...() will take control of the
497 // overlay cast button if it needs to hide it from the panel.
498 tryShowOverlayCastButton();
499 m_castButton->setIsWanted(false);
404 } else if (mediaElement().shouldShowControls()) { 500 } else if (mediaElement().shouldShowControls()) {
405 m_overlayCastButton->hide(); 501 m_overlayCastButton->setIsWanted(false);
406 m_castButton->show(); 502 m_castButton->setIsWanted(true);
407 // Check that the cast button actually fits on the bar. 503 // Check that the cast button actually fits on the bar. For the
408 if (m_fullScreenButton->getBoundingClientRect()->right() > m_panel-> getBoundingClientRect()->right()) { 504 // newMediaPlaybackUiEnabled case, we let computeWhichControlsFit()
409 m_castButton->hide(); 505 // handle this.
506 if ( !RuntimeEnabledFeatures::newMediaPlaybackUiEnabled()
507 && m_fullScreenButton->getBoundingClientRect()->right() > m_pane l->getBoundingClientRect()->right()) {
508 m_castButton->setIsWanted(false);
410 tryShowOverlayCastButton(); 509 tryShowOverlayCastButton();
411 } 510 }
412 } 511 }
413 } else { 512 } else {
414 m_castButton->hide(); 513 m_castButton->setIsWanted(false);
415 m_overlayCastButton->hide(); 514 m_overlayCastButton->setIsWanted(false);
416 } 515 }
417 } 516 }
418 517
419 void MediaControls::showOverlayCastButton() 518 void MediaControls::showOverlayCastButton()
420 { 519 {
421 tryShowOverlayCastButton(); 520 tryShowOverlayCastButton();
422 resetHideMediaControlsTimer(); 521 resetHideMediaControlsTimer();
423 } 522 }
424 523
425 void MediaControls::enteredFullscreen() 524 void MediaControls::enteredFullscreen()
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 unsigned behaviorFlags = m_hideTimerBehaviorFlags | IgnoreFocus | IgnoreVide oHover; 595 unsigned behaviorFlags = m_hideTimerBehaviorFlags | IgnoreFocus | IgnoreVide oHover;
497 m_hideTimerBehaviorFlags = IgnoreNone; 596 m_hideTimerBehaviorFlags = IgnoreNone;
498 597
499 if (mediaElement().togglePlayStateWillPlay()) 598 if (mediaElement().togglePlayStateWillPlay())
500 return; 599 return;
501 600
502 if (!shouldHideMediaControls(behaviorFlags)) 601 if (!shouldHideMediaControls(behaviorFlags))
503 return; 602 return;
504 603
505 makeTransparent(); 604 makeTransparent();
506 m_overlayCastButton->hide();
507 } 605 }
508 606
509 void MediaControls::startHideMediaControlsTimer() 607 void MediaControls::startHideMediaControlsTimer()
510 { 608 {
511 m_hideMediaControlsTimer.startOneShot(timeWithoutMouseMovementBeforeHidingMe diaControls, FROM_HERE); 609 m_hideMediaControlsTimer.startOneShot(timeWithoutMouseMovementBeforeHidingMe diaControls, FROM_HERE);
512 } 610 }
513 611
514 void MediaControls::stopHideMediaControlsTimer() 612 void MediaControls::stopHideMediaControlsTimer()
515 { 613 {
516 m_hideMediaControlsTimer.stop(); 614 m_hideMediaControlsTimer.stop();
(...skipping 10 matching lines...) Expand all
527 bool MediaControls::containsRelatedTarget(Event* event) 625 bool MediaControls::containsRelatedTarget(Event* event)
528 { 626 {
529 if (!event->isMouseEvent()) 627 if (!event->isMouseEvent())
530 return false; 628 return false;
531 EventTarget* relatedTarget = toMouseEvent(event)->relatedTarget(); 629 EventTarget* relatedTarget = toMouseEvent(event)->relatedTarget();
532 if (!relatedTarget) 630 if (!relatedTarget)
533 return false; 631 return false;
534 return contains(relatedTarget->toNode()); 632 return contains(relatedTarget->toNode());
535 } 633 }
536 634
635 void MediaControls::notifyPanelWidthChanged(const LayoutUnit& newWidth)
636 {
637 // Don't bother to do any work if this matches the most recent panel
638 // width, since we're called after layout.
639 // Note that this code permits a bad frame on resize, since it is
640 // run after the relayout / paint happens. It would be great to improve
641 // this, but it would be even greater to move this code entirely to
642 // JS and fix it there.
643 const int panelWidth = newWidth.toInt();
644
645 if (!RuntimeEnabledFeatures::newMediaPlaybackUiEnabled())
646 return;
647
648 m_panelWidth = panelWidth;
649
650 // Adjust for effective zoom.
651 if (!m_panel->layoutObject() || !m_panel->layoutObject()->style())
652 return;
653 m_panelWidth = ceil(m_panelWidth / m_panel->layoutObject()->style()->effecti veZoom());
654
655 m_panelWidthChangedTimer.startOneShot(0, FROM_HERE);
656 }
657
658 void MediaControls::panelWidthChangedTimerFired(Timer<MediaControls>*)
659 {
660 computeWhichControlsFit();
661 }
662
663 void MediaControls::computeWhichControlsFit()
664 {
665 // Hide all controls that don't fit, and show the ones that do.
666 // This might be better suited for a layout, but since JS media controls
667 // won't benefit from that anwyay, we just do it here like JS will.
668 // The order, in order of decreasing droppiness:
669 // Volume, time, seek bar, cast.
670
671 if (!RuntimeEnabledFeatures::newMediaPlaybackUiEnabled())
672 return;
673
674 if (!m_panelWidth)
675 return;
676
677 // Controls that we'll hide / show, in order of decreasing priority.
678 MediaControlElement* elements[] = {
679 m_playButton.get(),
680 m_toggleClosedCaptionsButton.get(),
681 m_fullScreenButton.get(),
682 m_timeline.get(),
683 m_currentTimeDisplay.get(),
684 m_volumeSlider.get(),
685 m_castButton.get(),
686 m_muteButton.get(),
687 m_durationDisplay.get(),
688 };
689
690 int usedWidth = 0;
691 bool droppedCastButton = false;
692 for (MediaControlElement* element : elements) {
693 if (!element)
694 continue;
695
696 if (element->isWanted()) {
697 const int minimumWidth = element->minimumWidth();
698 if (usedWidth + minimumWidth <= m_panelWidth) {
699 element->setDoesFit(true);
700 usedWidth += minimumWidth;
701 } else {
702 element->setDoesFit(false);
703 if (element == m_castButton.get())
704 droppedCastButton = true;
705 }
706 }
707 }
708
709 // Special case for cast: if we want a cast button but dropped it, then
710 // show the overlay cast button instead.
711 if (m_castButton->isWanted())
712 m_overlayCastButton->setIsWanted(droppedCastButton);
713 }
714
715 void MediaControls::setAllowHiddenVolumeControls(bool allow)
716 {
717 m_allowHiddenVolumeControls = allow;
718 // Clear the 'keep muted flag', for tests.
719 m_keepMuteButton = false;
720 // Update the controls visibility.
721 updateVolume();
722 }
723
724 void MediaControls::beginBatchUpdate()
725 {
726 ASSERT(m_batchDepth >= 0);
727 m_batchDepth++;
728 }
729
730 void MediaControls::endBatchUpdate()
731 {
732 if (!(--m_batchDepth))
733 computeWhichControlsFit();
734 ASSERT(m_batchDepth >= 0);
735 }
736
537 DEFINE_TRACE(MediaControls) 737 DEFINE_TRACE(MediaControls)
538 { 738 {
539 visitor->trace(m_mediaElement); 739 visitor->trace(m_mediaElement);
540 visitor->trace(m_panel); 740 visitor->trace(m_panel);
541 visitor->trace(m_overlayPlayButton); 741 visitor->trace(m_overlayPlayButton);
542 visitor->trace(m_overlayEnclosure); 742 visitor->trace(m_overlayEnclosure);
543 visitor->trace(m_playButton); 743 visitor->trace(m_playButton);
544 visitor->trace(m_currentTimeDisplay); 744 visitor->trace(m_currentTimeDisplay);
545 visitor->trace(m_timeline); 745 visitor->trace(m_timeline);
546 visitor->trace(m_muteButton); 746 visitor->trace(m_muteButton);
547 visitor->trace(m_volumeSlider); 747 visitor->trace(m_volumeSlider);
548 visitor->trace(m_toggleClosedCaptionsButton); 748 visitor->trace(m_toggleClosedCaptionsButton);
549 visitor->trace(m_fullScreenButton); 749 visitor->trace(m_fullScreenButton);
550 visitor->trace(m_durationDisplay); 750 visitor->trace(m_durationDisplay);
551 visitor->trace(m_enclosure); 751 visitor->trace(m_enclosure);
552 visitor->trace(m_castButton); 752 visitor->trace(m_castButton);
553 visitor->trace(m_overlayCastButton); 753 visitor->trace(m_overlayCastButton);
554 HTMLDivElement::trace(visitor); 754 HTMLDivElement::trace(visitor);
555 } 755 }
556 756
557 } 757 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698