OLD | NEW |
---|---|
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 29 matching lines...) Expand all Loading... | |
40 | 40 |
41 // If you change this value, then also update the corresponding value in | 41 // If you change this value, then also update the corresponding value in |
42 // LayoutTests/media/media-controls.js. | 42 // LayoutTests/media/media-controls.js. |
43 static const double timeWithoutMouseMovementBeforeHidingMediaControls = 3; | 43 static const double timeWithoutMouseMovementBeforeHidingMediaControls = 3; |
44 | 44 |
45 static bool fullscreenIsSupported(const Document& document) | 45 static bool fullscreenIsSupported(const Document& document) |
46 { | 46 { |
47 return !document.settings() || document.settings()->fullscreenSupported(); | 47 return !document.settings() || document.settings()->fullscreenSupported(); |
48 } | 48 } |
49 | 49 |
50 static bool preferHiddenVolumeSlider(const Document& document) | |
51 { | |
52 return !document.settings() || document.settings()->preferHiddenVolumeSlider (); | |
53 } | |
54 | |
55 static bool preferHiddenMuteButton(const Document& document) | |
56 { | |
57 return !document.settings() || document.settings()->preferHiddenMuteButton() ; | |
58 } | |
59 | |
60 static bool allowHiddenAudioElements(const Document& document) | |
61 { | |
62 // The new UI always allows this. The old one doesn't, but it's | |
63 // convenient for tests if it can enable it. This isn't included in the | |
64 // prefer...() functions because we have three different outcomes, | |
65 // especially for the mute button. | |
66 return RuntimeEnabledFeatures::newMediaPlaybackUiEnabled() | |
67 || (document.settings() && document.settings()->forceAllowHiddenAudioEle ments()); | |
68 } | |
69 | |
50 MediaControls::MediaControls(HTMLMediaElement& mediaElement) | 70 MediaControls::MediaControls(HTMLMediaElement& mediaElement) |
51 : HTMLDivElement(mediaElement.document()) | 71 : HTMLDivElement(mediaElement.document()) |
52 , m_mediaElement(&mediaElement) | 72 , m_mediaElement(&mediaElement) |
53 , m_overlayEnclosure(nullptr) | 73 , m_overlayEnclosure(nullptr) |
54 , m_overlayPlayButton(nullptr) | 74 , m_overlayPlayButton(nullptr) |
55 , m_overlayCastButton(nullptr) | 75 , m_overlayCastButton(nullptr) |
56 , m_enclosure(nullptr) | 76 , m_enclosure(nullptr) |
57 , m_panel(nullptr) | 77 , m_panel(nullptr) |
58 , m_playButton(nullptr) | 78 , m_playButton(nullptr) |
59 , m_timeline(nullptr) | 79 , m_timeline(nullptr) |
60 , m_currentTimeDisplay(nullptr) | 80 , m_currentTimeDisplay(nullptr) |
61 , m_durationDisplay(nullptr) | 81 , m_durationDisplay(nullptr) |
62 , m_muteButton(nullptr) | 82 , m_muteButton(nullptr) |
63 , m_volumeSlider(nullptr) | 83 , m_volumeSlider(nullptr) |
64 , m_toggleClosedCaptionsButton(nullptr) | 84 , m_toggleClosedCaptionsButton(nullptr) |
65 , m_castButton(nullptr) | 85 , m_castButton(nullptr) |
66 , m_fullScreenButton(nullptr) | 86 , m_fullScreenButton(nullptr) |
67 , m_hideMediaControlsTimer(this, &MediaControls::hideMediaControlsTimerFired ) | 87 , m_hideMediaControlsTimer(this, &MediaControls::hideMediaControlsTimerFired ) |
68 , m_hideTimerBehaviorFlags(IgnoreNone) | 88 , m_hideTimerBehaviorFlags(IgnoreNone) |
69 , m_isMouseOverControls(false) | 89 , m_isMouseOverControls(false) |
70 , m_isPausedForScrubbing(false) | 90 , m_isPausedForScrubbing(false) |
91 , m_panelWidthChangedTimer(this, &MediaControls::panelWidthChangedTimerFired ) | |
92 , m_panelWidth(0) | |
71 { | 93 { |
72 } | 94 } |
73 | 95 |
74 PassRefPtrWillBeRawPtr<MediaControls> MediaControls::create(HTMLMediaElement& me diaElement) | 96 PassRefPtrWillBeRawPtr<MediaControls> MediaControls::create(HTMLMediaElement& me diaElement) |
75 { | 97 { |
76 RefPtrWillBeRawPtr<MediaControls> controls = adoptRefWillBeNoop(new MediaCon trols(mediaElement)); | 98 RefPtrWillBeRawPtr<MediaControls> controls = adoptRefWillBeNoop(new MediaCon trols(mediaElement)); |
77 controls->setShadowPseudoId(AtomicString("-webkit-media-controls", AtomicStr ing::ConstructFromLiteral)); | 99 controls->setShadowPseudoId(AtomicString("-webkit-media-controls", AtomicStr ing::ConstructFromLiteral)); |
78 controls->initializeControls(); | 100 controls->initializeControls(); |
79 return controls.release(); | 101 return controls.release(); |
80 } | 102 } |
81 | 103 |
82 // The media controls DOM structure looks like: | 104 // The media controls DOM structure looks like: |
83 // | 105 // |
84 // MediaControls (-webkit-media-controls) | 106 // MediaControls (-webkit-media-controls) |
85 // +-MediaControlOverlayEnclosureElement (-webkit-media-controls-o verlay-enclosure) | 107 // +-MediaControlOverlayEnclosureElement (-webkit-media-controls-o verlay-enclosure) |
86 // | +-MediaControlOverlayPlayButtonElement (-webkit-media-controls-o verlay-play-button) | 108 // | +-MediaControlOverlayPlayButtonElement (-webkit-media-controls-o verlay-play-button) |
87 // | | {if mediaControlsOverlayPlayButtonEnabled} | 109 // | | {if mediaControlsOverlayPlayButtonEnabled} |
88 // | \-MediaControlCastButtonElement (-internal-media-controls -overlay-cast-button) | 110 // | \-MediaControlCastButtonElement (-internal-media-controls -overlay-cast-button) |
89 // \-MediaControlPanelEnclosureElement (-webkit-media-controls-e nclosure) | 111 // \-MediaControlPanelEnclosureElement (-webkit-media-controls-e nclosure) |
90 // \-MediaControlPanelElement (-webkit-media-controls-p anel) | 112 // \-MediaControlPanelElement (-webkit-media-controls-p anel) |
91 // +-MediaControlPlayButtonElement (-webkit-media-controls-p lay-button) | 113 // +-MediaControlPlayButtonElement (-webkit-media-controls-p lay-button) |
114 // | {if !RTE::newMediaPlaybackUi()} | |
92 // +-MediaControlTimelineElement (-webkit-media-controls-t imeline) | 115 // +-MediaControlTimelineElement (-webkit-media-controls-t imeline) |
93 // +-MediaControlCurrentTimeDisplayElement (-webkit-media-controls-c urrent-time-display) | 116 // +-MediaControlCurrentTimeDisplayElement (-webkit-media-controls-c urrent-time-display) |
94 // +-MediaControlTimeRemainingDisplayElement (-webkit-media-controls-t ime-remaining-display) | 117 // +-MediaControlTimeRemainingDisplayElement (-webkit-media-controls-t ime-remaining-display) |
118 // | {if RTE::newMediaPlaybackUi()} | |
119 // +-MediaControlTimelineElement (-webkit-media-controls-t imeline) | |
95 // +-MediaControlMuteButtonElement (-webkit-media-controls-m ute-button) | 120 // +-MediaControlMuteButtonElement (-webkit-media-controls-m ute-button) |
96 // +-MediaControlVolumeSliderElement (-webkit-media-controls-v olume-slider) | 121 // +-MediaControlVolumeSliderElement (-webkit-media-controls-v olume-slider) |
97 // +-MediaControlToggleClosedCaptionsButtonElement (-webkit-media-controls-t oggle-closed-captions-button) | 122 // +-MediaControlToggleClosedCaptionsButtonElement (-webkit-media-controls-t oggle-closed-captions-button) |
98 // +-MediaControlCastButtonElement (-internal-media-controls -cast-button) | 123 // +-MediaControlCastButtonElement (-internal-media-controls -cast-button) |
99 // \-MediaControlFullscreenButtonElement (-webkit-media-controls-f ullscreen-button) | 124 // \-MediaControlFullscreenButtonElement (-webkit-media-controls-f ullscreen-button) |
100 void MediaControls::initializeControls() | 125 void MediaControls::initializeControls() |
101 { | 126 { |
127 const bool useNewUi = RuntimeEnabledFeatures::newMediaPlaybackUiEnabled(); | |
102 RefPtrWillBeRawPtr<MediaControlOverlayEnclosureElement> overlayEnclosure = M ediaControlOverlayEnclosureElement::create(*this); | 128 RefPtrWillBeRawPtr<MediaControlOverlayEnclosureElement> overlayEnclosure = M ediaControlOverlayEnclosureElement::create(*this); |
103 | 129 |
104 if (document().settings() && document().settings()->mediaControlsOverlayPlay ButtonEnabled()) { | 130 if (document().settings() && document().settings()->mediaControlsOverlayPlay ButtonEnabled()) { |
105 RefPtrWillBeRawPtr<MediaControlOverlayPlayButtonElement> overlayPlayButt on = MediaControlOverlayPlayButtonElement::create(*this); | 131 RefPtrWillBeRawPtr<MediaControlOverlayPlayButtonElement> overlayPlayButt on = MediaControlOverlayPlayButtonElement::create(*this); |
106 m_overlayPlayButton = overlayPlayButton.get(); | 132 m_overlayPlayButton = overlayPlayButton.get(); |
107 overlayEnclosure->appendChild(overlayPlayButton.release()); | 133 overlayEnclosure->appendChild(overlayPlayButton.release()); |
108 } | 134 } |
109 | 135 |
110 RefPtrWillBeRawPtr<MediaControlCastButtonElement> overlayCastButton = MediaC ontrolCastButtonElement::create(*this, true); | 136 RefPtrWillBeRawPtr<MediaControlCastButtonElement> overlayCastButton = MediaC ontrolCastButtonElement::create(*this, true); |
111 m_overlayCastButton = overlayCastButton.get(); | 137 m_overlayCastButton = overlayCastButton.get(); |
112 overlayEnclosure->appendChild(overlayCastButton.release()); | 138 overlayEnclosure->appendChild(overlayCastButton.release()); |
113 | 139 |
114 m_overlayEnclosure = overlayEnclosure.get(); | 140 m_overlayEnclosure = overlayEnclosure.get(); |
115 appendChild(overlayEnclosure.release()); | 141 appendChild(overlayEnclosure.release()); |
116 | 142 |
117 // Create an enclosing element for the panel so we can visually offset the c ontrols correctly. | 143 // Create an enclosing element for the panel so we can visually offset the c ontrols correctly. |
118 RefPtrWillBeRawPtr<MediaControlPanelEnclosureElement> enclosure = MediaContr olPanelEnclosureElement::create(*this); | 144 RefPtrWillBeRawPtr<MediaControlPanelEnclosureElement> enclosure = MediaContr olPanelEnclosureElement::create(*this); |
119 | 145 |
120 RefPtrWillBeRawPtr<MediaControlPanelElement> panel = MediaControlPanelElemen t::create(*this); | 146 RefPtrWillBeRawPtr<MediaControlPanelElement> panel = MediaControlPanelElemen t::create(*this); |
121 | 147 |
122 RefPtrWillBeRawPtr<MediaControlPlayButtonElement> playButton = MediaControlP layButtonElement::create(*this); | 148 RefPtrWillBeRawPtr<MediaControlPlayButtonElement> playButton = MediaControlP layButtonElement::create(*this); |
123 m_playButton = playButton.get(); | 149 m_playButton = playButton.get(); |
124 panel->appendChild(playButton.release()); | 150 panel->appendChild(playButton.release()); |
125 | 151 |
126 RefPtrWillBeRawPtr<MediaControlTimelineElement> timeline = MediaControlTimel ineElement::create(*this); | 152 RefPtrWillBeRawPtr<MediaControlTimelineElement> timeline = MediaControlTimel ineElement::create(*this); |
127 m_timeline = timeline.get(); | 153 m_timeline = timeline.get(); |
128 panel->appendChild(timeline.release()); | 154 // In old UX, timeline is before the time / duration text. |
155 if (!useNewUi) | |
156 panel->appendChild(timeline.release()); | |
157 // else we will attach it later. | |
129 | 158 |
130 RefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> currentTimeDisplay = MediaControlCurrentTimeDisplayElement::create(*this); | 159 RefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> currentTimeDisplay = MediaControlCurrentTimeDisplayElement::create(*this); |
131 m_currentTimeDisplay = currentTimeDisplay.get(); | 160 m_currentTimeDisplay = currentTimeDisplay.get(); |
132 m_currentTimeDisplay->hide(); | 161 m_currentTimeDisplay->setIsWanted(useNewUi); |
162 | |
133 panel->appendChild(currentTimeDisplay.release()); | 163 panel->appendChild(currentTimeDisplay.release()); |
134 | 164 |
135 RefPtrWillBeRawPtr<MediaControlTimeRemainingDisplayElement> durationDisplay = MediaControlTimeRemainingDisplayElement::create(*this); | 165 RefPtrWillBeRawPtr<MediaControlTimeRemainingDisplayElement> durationDisplay = MediaControlTimeRemainingDisplayElement::create(*this); |
136 m_durationDisplay = durationDisplay.get(); | 166 m_durationDisplay = durationDisplay.get(); |
137 panel->appendChild(durationDisplay.release()); | 167 panel->appendChild(durationDisplay.release()); |
138 | 168 |
169 // In new UX, timeline is after the time / duration text. | |
170 if (useNewUi) | |
171 panel->appendChild(timeline.release()); | |
172 | |
139 RefPtrWillBeRawPtr<MediaControlMuteButtonElement> muteButton = MediaControlM uteButtonElement::create(*this); | 173 RefPtrWillBeRawPtr<MediaControlMuteButtonElement> muteButton = MediaControlM uteButtonElement::create(*this); |
140 m_muteButton = muteButton.get(); | 174 m_muteButton = muteButton.get(); |
141 panel->appendChild(muteButton.release()); | 175 panel->appendChild(muteButton.release()); |
176 const bool allowHiddenAudio = allowHiddenAudioElements(document()); | |
177 if (allowHiddenAudio && preferHiddenMuteButton(document())) | |
178 m_muteButton->setIsWanted(false); | |
142 | 179 |
143 RefPtrWillBeRawPtr<MediaControlVolumeSliderElement> slider = MediaControlVol umeSliderElement::create(*this); | 180 RefPtrWillBeRawPtr<MediaControlVolumeSliderElement> slider = MediaControlVol umeSliderElement::create(*this); |
144 m_volumeSlider = slider.get(); | 181 m_volumeSlider = slider.get(); |
145 panel->appendChild(slider.release()); | 182 panel->appendChild(slider.release()); |
183 if (allowHiddenAudio && preferHiddenVolumeSlider(document())) | |
184 m_volumeSlider->setIsWanted(false); | |
146 | 185 |
147 RefPtrWillBeRawPtr<MediaControlToggleClosedCaptionsButtonElement> toggleClos edCaptionsButton = MediaControlToggleClosedCaptionsButtonElement::create(*this); | 186 RefPtrWillBeRawPtr<MediaControlToggleClosedCaptionsButtonElement> toggleClos edCaptionsButton = MediaControlToggleClosedCaptionsButtonElement::create(*this); |
148 m_toggleClosedCaptionsButton = toggleClosedCaptionsButton.get(); | 187 m_toggleClosedCaptionsButton = toggleClosedCaptionsButton.get(); |
149 panel->appendChild(toggleClosedCaptionsButton.release()); | 188 panel->appendChild(toggleClosedCaptionsButton.release()); |
150 | 189 |
151 RefPtrWillBeRawPtr<MediaControlCastButtonElement> castButton = MediaControlC astButtonElement::create(*this, false); | 190 RefPtrWillBeRawPtr<MediaControlCastButtonElement> castButton = MediaControlC astButtonElement::create(*this, false); |
152 m_castButton = castButton.get(); | 191 m_castButton = castButton.get(); |
153 panel->appendChild(castButton.release()); | 192 panel->appendChild(castButton.release()); |
154 | 193 |
155 RefPtrWillBeRawPtr<MediaControlFullscreenButtonElement> fullscreenButton = M ediaControlFullscreenButtonElement::create(*this); | 194 RefPtrWillBeRawPtr<MediaControlFullscreenButtonElement> fullscreenButton = M ediaControlFullscreenButtonElement::create(*this); |
156 m_fullScreenButton = fullscreenButton.get(); | 195 m_fullScreenButton = fullscreenButton.get(); |
157 panel->appendChild(fullscreenButton.release()); | 196 panel->appendChild(fullscreenButton.release()); |
158 | 197 |
159 m_panel = panel.get(); | 198 m_panel = panel.get(); |
160 enclosure->appendChild(panel.release()); | 199 enclosure->appendChild(panel.release()); |
161 | 200 |
162 m_enclosure = enclosure.get(); | 201 m_enclosure = enclosure.get(); |
163 appendChild(enclosure.release()); | 202 appendChild(enclosure.release()); |
164 } | 203 } |
165 | 204 |
166 void MediaControls::reset() | 205 void MediaControls::reset() |
167 { | 206 { |
168 double duration = mediaElement().duration(); | 207 const bool useNewUi = RuntimeEnabledFeatures::newMediaPlaybackUiEnabled(); |
208 const double duration = mediaElement().duration(); | |
169 m_durationDisplay->setInnerText(LayoutTheme::theme().formatMediaControlsTime (duration), ASSERT_NO_EXCEPTION); | 209 m_durationDisplay->setInnerText(LayoutTheme::theme().formatMediaControlsTime (duration), ASSERT_NO_EXCEPTION); |
170 m_durationDisplay->setCurrentValue(duration); | 210 m_durationDisplay->setCurrentValue(duration); |
171 | 211 |
212 if (useNewUi) { | |
213 // Show everything that we might hide. | |
214 // If we don't have a duration, then mark it to be hidden. For the | |
215 // old UI case, want / don't want is the same as show / hide since | |
216 // it is never marked as not fitting. | |
217 if (std::isfinite(duration)) | |
218 m_durationDisplay->setIsWanted(true); | |
219 else | |
220 m_durationDisplay->setIsWanted(false); | |
221 m_currentTimeDisplay->setIsWanted(true); | |
222 m_timeline->setIsWanted(true); | |
223 } | |
224 | |
172 updatePlayState(); | 225 updatePlayState(); |
173 | 226 |
174 updateCurrentTimeDisplay(); | 227 updateCurrentTimeDisplay(); |
175 | 228 |
176 m_timeline->setDuration(duration); | 229 m_timeline->setDuration(duration); |
177 m_timeline->setPosition(mediaElement().currentTime()); | 230 m_timeline->setPosition(mediaElement().currentTime()); |
178 | 231 |
179 if (!mediaElement().hasAudio()) | |
180 m_volumeSlider->hide(); | |
181 else | |
182 m_volumeSlider->show(); | |
183 updateVolume(); | 232 updateVolume(); |
184 | 233 |
185 refreshClosedCaptionsButtonVisibility(); | 234 refreshClosedCaptionsButtonVisibility(); |
186 | 235 |
187 // Unconditionally allow the user to exit fullscreen if we are in it | 236 // Unconditionally allow the user to exit fullscreen if we are in it |
188 // now. Especially on android, when we might not yet know if | 237 // now. Especially on android, when we might not yet know if |
189 // fullscreen is supported, we sometimes guess incorrectly and show | 238 // fullscreen is supported, we sometimes guess incorrectly and show |
190 // the button earlier, and we don't want to remove it here if the | 239 // the button earlier, and we don't want to remove it here if the |
191 // user chose to enter fullscreen. crbug.com/500732 . | 240 // user chose to enter fullscreen. crbug.com/500732 . |
192 if ((mediaElement().hasVideo() && fullscreenIsSupported(document())) | 241 m_fullScreenButton->setIsWanted((mediaElement().hasVideo() |
193 || mediaElement().isFullscreen()) | 242 && fullscreenIsSupported(document())) |
194 m_fullScreenButton->show(); | 243 || mediaElement().isFullscreen()); |
195 else | |
196 m_fullScreenButton->hide(); | |
197 | 244 |
198 refreshCastButtonVisibility(); | 245 refreshCastButtonVisibilityWithoutUpdate(); |
199 makeOpaque(); | 246 makeOpaque(); |
247 changedControlSelections(); | |
200 } | 248 } |
201 | 249 |
202 LayoutObject* MediaControls::layoutObjectForTextTrackLayout() | 250 LayoutObject* MediaControls::layoutObjectForTextTrackLayout() |
203 { | 251 { |
204 return m_panel->layoutObject(); | 252 return m_panel->layoutObject(); |
205 } | 253 } |
206 | 254 |
207 void MediaControls::show() | 255 void MediaControls::show() |
208 { | 256 { |
209 makeOpaque(); | 257 makeOpaque(); |
210 m_panel->show(); | 258 m_panel->setIsWanted(true); |
211 m_panel->setIsDisplayed(true); | 259 m_panel->setIsDisplayed(true); |
212 if (m_overlayPlayButton) | 260 if (m_overlayPlayButton) |
213 m_overlayPlayButton->updateDisplayType(); | 261 m_overlayPlayButton->updateDisplayType(); |
214 } | 262 } |
215 | 263 |
216 void MediaControls::mediaElementFocused() | 264 void MediaControls::mediaElementFocused() |
217 { | 265 { |
218 if (mediaElement().shouldShowControls()) { | 266 if (mediaElement().shouldShowControls()) { |
219 show(); | 267 show(); |
220 resetHideMediaControlsTimer(); | 268 resetHideMediaControlsTimer(); |
221 } | 269 } |
222 } | 270 } |
223 | 271 |
224 void MediaControls::hide() | 272 void MediaControls::hide() |
225 { | 273 { |
226 m_panel->hide(); | 274 m_panel->setIsWanted(false); |
227 m_panel->setIsDisplayed(false); | 275 m_panel->setIsDisplayed(false); |
228 if (m_overlayPlayButton) | 276 if (m_overlayPlayButton) |
229 m_overlayPlayButton->hide(); | 277 m_overlayPlayButton->setIsWanted(false); |
230 } | 278 } |
231 | 279 |
232 void MediaControls::makeOpaque() | 280 void MediaControls::makeOpaque() |
233 { | 281 { |
234 m_panel->makeOpaque(); | 282 m_panel->makeOpaque(); |
235 } | 283 } |
236 | 284 |
237 void MediaControls::makeTransparent() | 285 void MediaControls::makeTransparent() |
238 { | 286 { |
239 m_panel->makeTransparent(); | 287 m_panel->makeTransparent(); |
(...skipping 16 matching lines...) Expand all Loading... | |
256 // controls/shadow tree. (Perform the checks separately to avoid going | 304 // controls/shadow tree. (Perform the checks separately to avoid going |
257 // through all the potential ancestor hosts for the focused element.) | 305 // through all the potential ancestor hosts for the focused element.) |
258 const bool ignoreFocus = behaviorFlags & IgnoreFocus; | 306 const bool ignoreFocus = behaviorFlags & IgnoreFocus; |
259 if (!ignoreFocus && (mediaElement().focused() || contains(document().focused Element()))) | 307 if (!ignoreFocus && (mediaElement().focused() || contains(document().focused Element()))) |
260 return false; | 308 return false; |
261 return true; | 309 return true; |
262 } | 310 } |
263 | 311 |
264 void MediaControls::playbackStarted() | 312 void MediaControls::playbackStarted() |
265 { | 313 { |
266 m_currentTimeDisplay->show(); | 314 if (!RuntimeEnabledFeatures::newMediaPlaybackUiEnabled()) { |
267 m_durationDisplay->hide(); | 315 m_currentTimeDisplay->setIsWanted(true); |
316 m_durationDisplay->setIsWanted(false); | |
317 } | |
268 | 318 |
269 updatePlayState(); | 319 updatePlayState(); |
270 m_timeline->setPosition(mediaElement().currentTime()); | 320 m_timeline->setPosition(mediaElement().currentTime()); |
271 updateCurrentTimeDisplay(); | 321 updateCurrentTimeDisplay(); |
272 | 322 |
273 startHideMediaControlsTimer(); | 323 startHideMediaControlsTimer(); |
274 } | 324 } |
275 | 325 |
276 void MediaControls::playbackProgressed() | 326 void MediaControls::playbackProgressed() |
277 { | 327 { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
318 mediaElement().togglePlayState(); | 368 mediaElement().togglePlayState(); |
319 } | 369 } |
320 } | 370 } |
321 | 371 |
322 void MediaControls::updateCurrentTimeDisplay() | 372 void MediaControls::updateCurrentTimeDisplay() |
323 { | 373 { |
324 double now = mediaElement().currentTime(); | 374 double now = mediaElement().currentTime(); |
325 double duration = mediaElement().duration(); | 375 double duration = mediaElement().duration(); |
326 | 376 |
327 // After seek, hide duration display and show current time. | 377 // After seek, hide duration display and show current time. |
328 if (now > 0) { | 378 if (!RuntimeEnabledFeatures::newMediaPlaybackUiEnabled() && now > 0) { |
329 m_currentTimeDisplay->show(); | 379 m_currentTimeDisplay->setIsWanted(true); |
330 m_durationDisplay->hide(); | 380 m_durationDisplay->setIsWanted(false); |
331 } | 381 } |
332 | 382 |
333 // Allow the theme to format the time. | 383 // Allow the theme to format the time. |
334 m_currentTimeDisplay->setInnerText(LayoutTheme::theme().formatMediaControlsC urrentTime(now, duration), IGNORE_EXCEPTION); | 384 m_currentTimeDisplay->setInnerText(LayoutTheme::theme().formatMediaControlsC urrentTime(now, duration), IGNORE_EXCEPTION); |
335 m_currentTimeDisplay->setCurrentValue(now); | 385 m_currentTimeDisplay->setCurrentValue(now); |
336 } | 386 } |
337 | 387 |
338 void MediaControls::updateVolume() | 388 void MediaControls::updateVolume() |
339 { | 389 { |
340 m_muteButton->updateDisplayType(); | 390 m_muteButton->updateDisplayType(); |
341 // Invalidate the mute button because it paints differently according to vol ume. | 391 // Invalidate the mute button because it paints differently according to vol ume. |
342 if (LayoutObject* layoutObject = m_muteButton->layoutObject()) | 392 if (LayoutObject* layoutObject = m_muteButton->layoutObject()) |
343 layoutObject->setShouldDoFullPaintInvalidation(); | 393 layoutObject->setShouldDoFullPaintInvalidation(); |
344 | 394 |
345 if (mediaElement().muted()) | 395 if (mediaElement().muted()) { |
346 m_volumeSlider->setVolume(0); | 396 m_volumeSlider->setVolume(0); |
347 else | 397 } else { |
348 m_volumeSlider->setVolume(mediaElement().volume()); | 398 m_volumeSlider->setVolume(mediaElement().volume()); |
399 } | |
400 | |
401 // Update the visibility of our audio elements. | |
402 // Old and new UI never want the volume slider if there's no audio. | |
403 // If there is audio, then we want it unless hiding audio is enabled and | |
404 // we prefer to hide it. | |
405 const bool allowHiddenAudio = allowHiddenAudioElements(document()); | |
406 m_volumeSlider->setIsWanted(mediaElement().hasAudio() | |
407 && !(allowHiddenAudio && preferHiddenVolumeSlider(document()))); | |
408 | |
409 // The mute button is a little more complicated. The old UI never | |
410 // sets it; it lets CSS choose. The new UI does. If we're allowing | |
philipj_slow
2015/07/10 14:51:59
I would be nice if these descriptions were in term
liberato (no reviews please)
2015/07/10 15:32:19
i agree that 'old' and 'new' are awful names. i'v
| |
411 // hidden audio, then we may set it. Note that this is why | |
412 // allowHiddenAudio isn't rolled into prefer...(). | |
413 if (allowHiddenAudio) { | |
414 // If there is no audio track, then hide the mute button. If there | |
415 // is an audio track, then we always show the mute button unless | |
416 // we prefer to hide it and the media isn't muted. If it's muted, | |
417 // then we show it to let the user unmute it. | |
418 m_muteButton->setIsWanted(mediaElement().hasAudio() | |
419 && (!preferHiddenMuteButton(document()) || mediaElement().muted())); | |
420 } | |
421 | |
422 | |
349 // Invalidate the volume slider because it paints differently according to v olume. | 423 // Invalidate the volume slider because it paints differently according to v olume. |
350 if (LayoutObject* layoutObject = m_volumeSlider->layoutObject()) | 424 if (LayoutObject* layoutObject = m_volumeSlider->layoutObject()) |
351 layoutObject->setShouldDoFullPaintInvalidation(); | 425 layoutObject->setShouldDoFullPaintInvalidation(); |
352 } | 426 } |
353 | 427 |
354 void MediaControls::changedClosedCaptionsVisibility() | 428 void MediaControls::changedClosedCaptionsVisibility() |
355 { | 429 { |
356 m_toggleClosedCaptionsButton->updateDisplayType(); | 430 m_toggleClosedCaptionsButton->updateDisplayType(); |
357 } | 431 } |
358 | 432 |
359 void MediaControls::refreshClosedCaptionsButtonVisibility() | 433 void MediaControls::refreshClosedCaptionsButtonVisibility() |
360 { | 434 { |
361 if (mediaElement().hasClosedCaptions()) | 435 m_toggleClosedCaptionsButton->setIsWanted(mediaElement().hasClosedCaptions() ); |
362 m_toggleClosedCaptionsButton->show(); | |
363 else | |
364 m_toggleClosedCaptionsButton->hide(); | |
365 } | 436 } |
366 | 437 |
367 static Element* elementFromCenter(Element& element) | 438 static Element* elementFromCenter(Element& element) |
368 { | 439 { |
369 ClientRect* clientRect = element.getBoundingClientRect(); | 440 ClientRect* clientRect = element.getBoundingClientRect(); |
370 int centerX = static_cast<int>((clientRect->left() + clientRect->right()) / 2); | 441 int centerX = static_cast<int>((clientRect->left() + clientRect->right()) / 2); |
371 int centerY = static_cast<int>((clientRect->top() + clientRect->bottom()) / 2); | 442 int centerY = static_cast<int>((clientRect->top() + clientRect->bottom()) / 2); |
372 | 443 |
373 return element.document().elementFromPoint(centerX , centerY); | 444 return element.document().elementFromPoint(centerX , centerY); |
374 } | 445 } |
375 | 446 |
376 void MediaControls::tryShowOverlayCastButton() | 447 void MediaControls::tryShowOverlayCastButton() |
377 { | 448 { |
378 // The element needs to be shown to have its dimensions and position. | 449 // The element needs to be shown to have its dimensions and position. |
379 m_overlayCastButton->show(); | 450 m_overlayCastButton->setIsWanted(true); |
380 | |
381 if (elementFromCenter(*m_overlayCastButton) != &mediaElement()) | 451 if (elementFromCenter(*m_overlayCastButton) != &mediaElement()) |
382 m_overlayCastButton->hide(); | 452 m_overlayCastButton->setIsWanted(false); |
383 } | 453 } |
384 | 454 |
385 void MediaControls::refreshCastButtonVisibility() | 455 void MediaControls::refreshCastButtonVisibility() |
386 { | 456 { |
457 refreshCastButtonVisibilityWithoutUpdate(); | |
458 changedControlSelections(); | |
459 } | |
460 | |
461 void MediaControls::refreshCastButtonVisibilityWithoutUpdate() | |
462 { | |
387 if (mediaElement().hasRemoteRoutes()) { | 463 if (mediaElement().hasRemoteRoutes()) { |
388 // The reason for the autoplay test is that some pages (e.g. vimeo.com) have an autoplay background video, which | 464 // The reason for the autoplay test is that some pages (e.g. vimeo.com) have an autoplay background video, which |
389 // doesn't autoplay on Chrome for Android (we prevent it) so starts paus ed. In such cases we don't want to automatically | 465 // doesn't autoplay on Chrome for Android (we prevent it) so starts paus ed. In such cases we don't want to automatically |
390 // show the cast button, since it looks strange and is unlikely to corre spond with anything the user wants to do. | 466 // show the cast button, since it looks strange and is unlikely to corre spond with anything the user wants to do. |
391 // If a user does want to cast a paused autoplay video then they can sti ll do so by touching or clicking on the | 467 // If a user does want to cast a paused autoplay video then they can sti ll do so by touching or clicking on the |
392 // video, which will cause the cast button to appear. | 468 // video, which will cause the cast button to appear. |
393 if (!mediaElement().shouldShowControls() && !mediaElement().autoplay() & & mediaElement().paused()) { | 469 if (!mediaElement().shouldShowControls() && !mediaElement().autoplay() & & mediaElement().paused()) { |
394 showOverlayCastButton(); | 470 // Note that this is a case where we add the overlay cast button |
471 // without wanting the panel cast button. We depend on the fact | |
472 // that computeWhichControlsFit() won't change overlay cast button | |
473 // visibility in the case where the cast button isn't wanted. | |
474 // We don't call compute...() here, but it will be called as | |
475 // non-cast changes (e.g., resize) occur. If the panel button | |
476 // is shown, however, compute...() will take control of the | |
477 // overlay cast button if it needs to hide it from the panel. | |
478 tryShowOverlayCastButton(); | |
479 m_castButton->setIsWanted(false); | |
395 } else if (mediaElement().shouldShowControls()) { | 480 } else if (mediaElement().shouldShowControls()) { |
396 m_overlayCastButton->hide(); | 481 m_overlayCastButton->setIsWanted(false); |
397 m_castButton->show(); | 482 m_castButton->setIsWanted(true); |
398 // Check that the cast button actually fits on the bar. | 483 // Check that the cast button actually fits on the bar. For the |
399 if (m_fullScreenButton->getBoundingClientRect()->right() > m_panel-> getBoundingClientRect()->right()) { | 484 // new ui, we let changedControlSelections() handle this. |
400 m_castButton->hide(); | 485 if ( !RuntimeEnabledFeatures::newMediaPlaybackUiEnabled() |
486 && m_fullScreenButton->getBoundingClientRect()->right() > m_pane l->getBoundingClientRect()->right()) { | |
487 m_castButton->setIsWanted(false); | |
401 tryShowOverlayCastButton(); | 488 tryShowOverlayCastButton(); |
402 } | 489 } |
403 } | 490 } |
404 } else { | 491 } else { |
405 m_castButton->hide(); | 492 m_castButton->setIsWanted(false); |
406 m_overlayCastButton->hide(); | 493 m_overlayCastButton->setIsWanted(false); |
407 } | 494 } |
408 } | 495 } |
409 | 496 |
410 void MediaControls::showOverlayCastButton() | 497 void MediaControls::showOverlayCastButton() |
411 { | 498 { |
412 tryShowOverlayCastButton(); | 499 tryShowOverlayCastButton(); |
413 resetHideMediaControlsTimer(); | 500 resetHideMediaControlsTimer(); |
414 } | 501 } |
415 | 502 |
416 void MediaControls::enteredFullscreen() | 503 void MediaControls::enteredFullscreen() |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
487 unsigned behaviorFlags = m_hideTimerBehaviorFlags | IgnoreFocus | IgnoreVide oHover; | 574 unsigned behaviorFlags = m_hideTimerBehaviorFlags | IgnoreFocus | IgnoreVide oHover; |
488 m_hideTimerBehaviorFlags = IgnoreNone; | 575 m_hideTimerBehaviorFlags = IgnoreNone; |
489 | 576 |
490 if (mediaElement().togglePlayStateWillPlay()) | 577 if (mediaElement().togglePlayStateWillPlay()) |
491 return; | 578 return; |
492 | 579 |
493 if (!shouldHideMediaControls(behaviorFlags)) | 580 if (!shouldHideMediaControls(behaviorFlags)) |
494 return; | 581 return; |
495 | 582 |
496 makeTransparent(); | 583 makeTransparent(); |
497 m_overlayCastButton->hide(); | 584 m_overlayCastButton->setIsWanted(false); |
498 } | 585 } |
499 | 586 |
500 void MediaControls::startHideMediaControlsTimer() | 587 void MediaControls::startHideMediaControlsTimer() |
501 { | 588 { |
502 m_hideMediaControlsTimer.startOneShot(timeWithoutMouseMovementBeforeHidingMe diaControls, FROM_HERE); | 589 m_hideMediaControlsTimer.startOneShot(timeWithoutMouseMovementBeforeHidingMe diaControls, FROM_HERE); |
503 } | 590 } |
504 | 591 |
505 void MediaControls::stopHideMediaControlsTimer() | 592 void MediaControls::stopHideMediaControlsTimer() |
506 { | 593 { |
507 m_hideMediaControlsTimer.stop(); | 594 m_hideMediaControlsTimer.stop(); |
(...skipping 10 matching lines...) Expand all Loading... | |
518 bool MediaControls::containsRelatedTarget(Event* event) | 605 bool MediaControls::containsRelatedTarget(Event* event) |
519 { | 606 { |
520 if (!event->isMouseEvent()) | 607 if (!event->isMouseEvent()) |
521 return false; | 608 return false; |
522 EventTarget* relatedTarget = toMouseEvent(event)->relatedTarget(); | 609 EventTarget* relatedTarget = toMouseEvent(event)->relatedTarget(); |
523 if (!relatedTarget) | 610 if (!relatedTarget) |
524 return false; | 611 return false; |
525 return contains(relatedTarget->toNode()); | 612 return contains(relatedTarget->toNode()); |
526 } | 613 } |
527 | 614 |
615 void MediaControls::notifyPanelWidthChanged(int panelWidth) | |
616 { | |
617 // Don't bother to do any work if this matches the most recent panel | |
618 // width, since we're called after layout. | |
619 if (panelWidth == 0) | |
620 return; | |
621 | |
622 if (!RuntimeEnabledFeatures::newMediaPlaybackUiEnabled()) | |
623 return; | |
624 | |
625 m_panelWidth = panelWidth; | |
626 m_panelWidthChangedTimer.startOneShot(0, FROM_HERE); | |
627 } | |
628 | |
629 void MediaControls::changedControlSelections() | |
630 { | |
631 int panelWidth = m_panel->clientWidth(); | |
632 // Don't short-circuit update if the panel hasn't changed. The fit state | |
633 // is a function of the controls we want, so recompute if we can. | |
634 if (panelWidth == 0) | |
635 return; | |
636 | |
637 m_panelWidth = panelWidth; | |
638 computeWhichControlsFit(); | |
639 } | |
640 | |
641 void MediaControls::panelWidthChangedTimerFired(Timer<MediaControls>*) | |
642 { | |
643 computeWhichControlsFit(); | |
644 } | |
645 | |
646 void MediaControls::computeWhichControlsFit() | |
647 { | |
648 // Hide all controls that don't fit, and show the ones that do. | |
649 // This might be better suited for a layout, but since JS media controls | |
650 // won't benefit from that anwyay, we just do it here like JS will. | |
651 // The order, in order of decreasing droppiness: | |
652 // Volume, time, seek bar, cast. | |
653 | |
654 if (!RuntimeEnabledFeatures::newMediaPlaybackUiEnabled()) | |
655 return; | |
656 | |
657 if (!m_panelWidth) | |
658 return; | |
659 | |
660 // Controls that we'll hide / show, in order of decreasing priority. | |
661 MediaControlElement* elements[] = { | |
662 m_playButton.get(), | |
663 m_toggleClosedCaptionsButton.get(), | |
664 m_fullScreenButton.get(), | |
665 m_timeline.get(), | |
666 m_currentTimeDisplay.get(), | |
667 m_volumeSlider.get(), | |
668 m_castButton.get(), | |
669 m_muteButton.get(), | |
670 m_durationDisplay.get(), | |
671 }; | |
672 | |
673 int usedWidth = 0; | |
674 bool droppedCastButton = false; | |
675 for (MediaControlElement* element : elements) { | |
676 if (!element) | |
677 continue; | |
678 | |
679 if (element->isWanted()) { | |
680 if (usedWidth + element->minimumWidth() <= m_panelWidth) { | |
681 element->setDoesFit(true); | |
682 usedWidth += element->minimumWidth(); | |
683 } else { | |
684 element->setDoesFit(false); | |
685 if (element == m_castButton.get()) | |
686 droppedCastButton = true; | |
687 } | |
688 } | |
689 } | |
690 | |
691 // Special case for cast: if we want a cast button but dropped it, then | |
692 // show the overlay cast button instead. | |
693 if (m_castButton->isWanted()) | |
694 m_overlayCastButton->setIsWanted(!droppedCastButton); | |
695 } | |
696 | |
528 DEFINE_TRACE(MediaControls) | 697 DEFINE_TRACE(MediaControls) |
529 { | 698 { |
530 visitor->trace(m_mediaElement); | 699 visitor->trace(m_mediaElement); |
531 visitor->trace(m_panel); | 700 visitor->trace(m_panel); |
532 visitor->trace(m_overlayPlayButton); | 701 visitor->trace(m_overlayPlayButton); |
533 visitor->trace(m_overlayEnclosure); | 702 visitor->trace(m_overlayEnclosure); |
534 visitor->trace(m_playButton); | 703 visitor->trace(m_playButton); |
535 visitor->trace(m_currentTimeDisplay); | 704 visitor->trace(m_currentTimeDisplay); |
536 visitor->trace(m_timeline); | 705 visitor->trace(m_timeline); |
537 visitor->trace(m_muteButton); | 706 visitor->trace(m_muteButton); |
538 visitor->trace(m_volumeSlider); | 707 visitor->trace(m_volumeSlider); |
539 visitor->trace(m_toggleClosedCaptionsButton); | 708 visitor->trace(m_toggleClosedCaptionsButton); |
540 visitor->trace(m_fullScreenButton); | 709 visitor->trace(m_fullScreenButton); |
541 visitor->trace(m_durationDisplay); | 710 visitor->trace(m_durationDisplay); |
542 visitor->trace(m_enclosure); | 711 visitor->trace(m_enclosure); |
543 visitor->trace(m_castButton); | 712 visitor->trace(m_castButton); |
544 visitor->trace(m_overlayCastButton); | 713 visitor->trace(m_overlayCastButton); |
545 HTMLDivElement::trace(visitor); | 714 HTMLDivElement::trace(visitor); |
546 } | 715 } |
547 | 716 |
548 } | 717 } |
OLD | NEW |