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

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

Powered by Google App Engine
This is Rietveld 408576698