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 24 matching lines...) Expand all Loading... | |
35 #include "core/html/track/TextTrackContainer.h" | 35 #include "core/html/track/TextTrackContainer.h" |
36 #include "core/layout/LayoutTheme.h" | 36 #include "core/layout/LayoutTheme.h" |
37 #include "platform/EventDispatchForbiddenScope.h" | 37 #include "platform/EventDispatchForbiddenScope.h" |
38 | 38 |
39 namespace blink { | 39 namespace blink { |
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 // We only want to show the overflow menu if it contains at least two buttons | |
46 static const int minOverflowMenuControlElementsNum = 2; | |
47 | |
45 static bool shouldShowFullscreenButton(const HTMLMediaElement& mediaElement) | 48 static bool shouldShowFullscreenButton(const HTMLMediaElement& mediaElement) |
46 { | 49 { |
47 // Unconditionally allow the user to exit fullscreen if we are in it | 50 // Unconditionally allow the user to exit fullscreen if we are in it |
48 // now. Especially on android, when we might not yet know if | 51 // now. Especially on android, when we might not yet know if |
49 // fullscreen is supported, we sometimes guess incorrectly and show | 52 // fullscreen is supported, we sometimes guess incorrectly and show |
50 // the button earlier, and we don't want to remove it here if the | 53 // the button earlier, and we don't want to remove it here if the |
51 // user chose to enter fullscreen. crbug.com/500732 . | 54 // user chose to enter fullscreen. crbug.com/500732 . |
52 if (mediaElement.isFullscreen()) | 55 if (mediaElement.isFullscreen()) |
53 return true; | 56 return true; |
54 | 57 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
110 , m_enclosure(nullptr) | 113 , m_enclosure(nullptr) |
111 , m_panel(nullptr) | 114 , m_panel(nullptr) |
112 , m_playButton(nullptr) | 115 , m_playButton(nullptr) |
113 , m_timeline(nullptr) | 116 , m_timeline(nullptr) |
114 , m_currentTimeDisplay(nullptr) | 117 , m_currentTimeDisplay(nullptr) |
115 , m_durationDisplay(nullptr) | 118 , m_durationDisplay(nullptr) |
116 , m_muteButton(nullptr) | 119 , m_muteButton(nullptr) |
117 , m_volumeSlider(nullptr) | 120 , m_volumeSlider(nullptr) |
118 , m_toggleClosedCaptionsButton(nullptr) | 121 , m_toggleClosedCaptionsButton(nullptr) |
119 , m_textTrackList(nullptr) | 122 , m_textTrackList(nullptr) |
123 , m_overflowList(nullptr) | |
120 , m_castButton(nullptr) | 124 , m_castButton(nullptr) |
121 , m_fullScreenButton(nullptr) | 125 , m_fullScreenButton(nullptr) |
122 , m_hideMediaControlsTimer(this, &MediaControls::hideMediaControlsTimerFired ) | 126 , m_hideMediaControlsTimer(this, &MediaControls::hideMediaControlsTimerFired ) |
123 , m_hideTimerBehaviorFlags(IgnoreNone) | 127 , m_hideTimerBehaviorFlags(IgnoreNone) |
124 , m_isMouseOverControls(false) | 128 , m_isMouseOverControls(false) |
125 , m_isPausedForScrubbing(false) | 129 , m_isPausedForScrubbing(false) |
126 , m_panelWidthChangedTimer(this, &MediaControls::panelWidthChangedTimerFired ) | 130 , m_panelWidthChangedTimer(this, &MediaControls::panelWidthChangedTimerFired ) |
127 , m_panelWidth(0) | 131 , m_panelWidth(0) |
128 , m_allowHiddenVolumeControls(RuntimeEnabledFeatures::newMediaPlaybackUiEnab led()) | 132 , m_allowHiddenVolumeControls(RuntimeEnabledFeatures::newMediaPlaybackUiEnab led()) |
129 { | 133 { |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
235 | 239 |
236 m_panel = panel; | 240 m_panel = panel; |
237 enclosure->appendChild(panel); | 241 enclosure->appendChild(panel); |
238 | 242 |
239 m_enclosure = enclosure; | 243 m_enclosure = enclosure; |
240 appendChild(enclosure); | 244 appendChild(enclosure); |
241 | 245 |
242 MediaControlTextTrackListElement* textTrackList = MediaControlTextTrackListE lement::create(*this); | 246 MediaControlTextTrackListElement* textTrackList = MediaControlTextTrackListE lement::create(*this); |
243 m_textTrackList = textTrackList; | 247 m_textTrackList = textTrackList; |
244 appendChild(textTrackList); | 248 appendChild(textTrackList); |
249 | |
250 MediaControlOverflowMenuButtonElement* overflowMenu = MediaControlOverflowMe nuButtonElement::create(*this); | |
251 m_overflowMenu = overflowMenu; | |
252 panel->appendChild(overflowMenu); | |
253 | |
254 MediaControlOverflowMenuListElement* overflowList = MediaControlOverflowMenu ListElement::create(*this); | |
255 m_overflowList = overflowList; | |
256 appendChild(overflowList); | |
257 | |
258 // The order in which we append elements to the overflow list does matter. | |
259 m_overflowList->appendChild(m_muteButton->createOverflowElement(*this, Media ControlMuteButtonElement::create(*this))); | |
260 m_overflowList->appendChild(m_castButton->createOverflowElement(*this, Media ControlCastButtonElement::create(*this, false))); | |
261 m_overflowList->appendChild(m_toggleClosedCaptionsButton->createOverflowElem ent(*this, MediaControlToggleClosedCaptionsButtonElement::create(*this))); | |
262 m_overflowList->appendChild(m_fullScreenButton->createOverflowElement(*this, MediaControlFullscreenButtonElement::create(*this))); | |
263 m_overflowList->appendChild(m_playButton->createOverflowElement(*this, Media ControlPlayButtonElement::create(*this))); | |
245 } | 264 } |
246 | 265 |
247 void MediaControls::reset() | 266 void MediaControls::reset() |
248 { | 267 { |
249 EventDispatchForbiddenScope::AllowUserAgentEvents allowEventsInShadow; | 268 EventDispatchForbiddenScope::AllowUserAgentEvents allowEventsInShadow; |
250 const bool useNewUi = RuntimeEnabledFeatures::newMediaPlaybackUiEnabled(); | 269 const bool useNewUi = RuntimeEnabledFeatures::newMediaPlaybackUiEnabled(); |
251 BatchedControlUpdate batch(this); | 270 BatchedControlUpdate batch(this); |
252 | 271 |
253 m_allowHiddenVolumeControls = useNewUi; | 272 m_allowHiddenVolumeControls = useNewUi; |
254 | 273 |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
681 { | 700 { |
682 // Hide all controls that don't fit, and show the ones that do. | 701 // Hide all controls that don't fit, and show the ones that do. |
683 // This might be better suited for a layout, but since JS media controls | 702 // This might be better suited for a layout, but since JS media controls |
684 // won't benefit from that anwyay, we just do it here like JS will. | 703 // won't benefit from that anwyay, we just do it here like JS will. |
685 | 704 |
686 if (!RuntimeEnabledFeatures::newMediaPlaybackUiEnabled()) | 705 if (!RuntimeEnabledFeatures::newMediaPlaybackUiEnabled()) |
687 return; | 706 return; |
688 | 707 |
689 // Controls that we'll hide / show, in order of decreasing priority. | 708 // Controls that we'll hide / show, in order of decreasing priority. |
690 MediaControlElement* elements[] = { | 709 MediaControlElement* elements[] = { |
691 // Exclude m_playButton; we handle it specially. | 710 // Exclude m_overflowMenu; we handle it specially. |
711 m_playButton.get(), | |
692 m_fullScreenButton.get(), | 712 m_fullScreenButton.get(), |
693 m_toggleClosedCaptionsButton.get(), | 713 m_toggleClosedCaptionsButton.get(), |
694 m_timeline.get(), | 714 m_timeline.get(), |
695 m_currentTimeDisplay.get(), | 715 m_currentTimeDisplay.get(), |
696 m_volumeSlider.get(), | 716 m_volumeSlider.get(), |
697 m_castButton.get(), | 717 m_castButton.get(), |
698 m_muteButton.get(), | 718 m_muteButton.get(), |
699 m_durationDisplay.get(), | 719 m_durationDisplay.get(), |
700 }; | 720 }; |
701 | 721 |
702 int usedWidth = 0; | 722 int usedWidth = 0; |
703 | 723 |
704 // Assume that all controls require 48px, unless we can get the computed | 724 // Assume that all controls require 48px, unless we can get the computed |
705 // style for the play button. Since the play button is always shown, it | 725 // style for the play button. Since the play button or overflow is always |
706 // should be available the first time we're called after layout. This will | 726 // shown, one of the two buttons should be available the first time we're |
727 // called after layout. This will | |
707 // also be the first time we have m_panelWidth!=0, so it won't matter if | 728 // also be the first time we have m_panelWidth!=0, so it won't matter if |
708 // we get this wrong before that. | 729 // we get this wrong before that. |
709 int minimumWidth = 48; | 730 int minimumWidth = 48; |
710 if (m_playButton->layoutObject() && m_playButton->layoutObject()->style()) { | 731 if (m_playButton->layoutObject() && m_playButton->layoutObject()->style()) { |
711 const ComputedStyle* style = m_playButton->layoutObject()->style(); | 732 const ComputedStyle* style = m_playButton->layoutObject()->style(); |
712 minimumWidth = ceil(style->width().pixels() / style->effectiveZoom()); | 733 minimumWidth = ceil(style->width().pixels() / style->effectiveZoom()); |
713 } | 734 } else if (m_overflowMenu->layoutObject() && m_overflowMenu->layoutObject()- >style()) { |
714 | 735 const ComputedStyle* style = m_overflowMenu->layoutObject()->style(); |
715 // Special-case the play button; it always fits. | 736 minimumWidth = ceil(style->width().pixels() / style->effectiveZoom()); |
716 if (m_playButton->isWanted()) { | |
717 m_playButton->setDoesFit(true); | |
718 usedWidth += minimumWidth; | |
719 } | 737 } |
mlamouri (slow - plz ping)
2016/09/06 10:25:45
Why is this needed?
kdsilva
2016/09/06 17:32:46
Acknowledged.
| |
720 | 738 |
721 if (!m_panelWidth) { | 739 if (!m_panelWidth) { |
722 // No layout yet -- hide everything, then make them show up later. | 740 // No layout yet -- hide everything, then make them show up later. |
723 // This prevents the wrong controls from being shown briefly | 741 // This prevents the wrong controls from being shown briefly |
724 // immediately after the first layout and paint, but before we have | 742 // immediately after the first layout and paint, but before we have |
725 // a chance to revise them. | 743 // a chance to revise them. |
726 for (MediaControlElement* element : elements) { | 744 for (MediaControlElement* element : elements) { |
727 if (element) | 745 if (element) |
728 element->setDoesFit(false); | 746 element->setDoesFit(false); |
729 } | 747 } |
730 return; | 748 return; |
731 } | 749 } |
732 | 750 |
751 int numOverflowElements = 0; | |
752 int widthWithOverflowMenu = minimumWidth; | |
753 // We take one pass assuming that we do have an overflow menu button | |
754 // displayed in the media controls. If it's presence results in at least | |
755 // two buttons in the overflow menu, we should show the overflow menu. | |
756 for (MediaControlElement* element : elements) { | |
757 if (element && element->isWanted()) { | |
758 if (widthWithOverflowMenu + minimumWidth <= m_panelWidth) { | |
759 widthWithOverflowMenu += minimumWidth; | |
760 } else { | |
761 if (element->hasOverflowButton()) | |
762 numOverflowElements++; | |
763 } | |
764 } | |
765 } | |
mlamouri (slow - plz ping)
2016/09/06 10:25:45
Do you have a test for this?
I would recommend so
kdsilva
2016/09/06 17:32:46
Done.
| |
766 | |
767 // We display an overflow menu only when we have at least two items | |
768 // within it. | |
769 if (numOverflowElements >= minOverflowMenuControlElementsNum) { | |
770 m_overflowMenu->setDoesFit(true); | |
771 m_overflowMenu->setIsWanted(true); | |
772 usedWidth = minimumWidth; | |
773 } else { | |
774 m_overflowMenu->setIsWanted(false); | |
775 m_overflowList->showOverflowMenu(false); | |
776 } | |
777 | |
733 // For each control that fits, enable it in order of decreasing priority. | 778 // For each control that fits, enable it in order of decreasing priority. |
734 bool droppedCastButton = false; | 779 bool droppedCastButton = false; |
735 for (MediaControlElement* element : elements) { | 780 for (MediaControlElement* element : elements) { |
736 if (!element) | 781 if (!element) |
737 continue; | 782 continue; |
738 | 783 element->shouldShowButtonInOverflowMenu(false); |
739 if (element->isWanted()) { | 784 if (element->isWanted()) { |
740 if (usedWidth + minimumWidth <= m_panelWidth) { | 785 if (usedWidth + minimumWidth <= m_panelWidth) { |
741 element->setDoesFit(true); | 786 element->setDoesFit(true); |
742 usedWidth += minimumWidth; | 787 usedWidth += minimumWidth; |
788 element->shouldShowButtonInOverflowMenu(false); | |
mlamouri (slow - plz ping)
2016/09/06 10:25:45
I don't think you need this.
kdsilva
2016/09/06 17:32:46
Done.
| |
743 } else { | 789 } else { |
744 element->setDoesFit(false); | 790 element->setDoesFit(false); |
745 if (element == m_castButton.get()) | 791 if (element == m_castButton.get()) |
746 droppedCastButton = true; | 792 droppedCastButton = true; |
793 element->shouldShowButtonInOverflowMenu(true); | |
747 } | 794 } |
748 } | 795 } |
749 } | 796 } |
750 | 797 |
751 // Special case for cast: if we want a cast button but dropped it, then | 798 // Special case for cast: if we want a cast button but dropped it, then |
752 // show the overlay cast button instead. | 799 // show the overlay cast button instead. |
753 if (m_castButton->isWanted()) { | 800 if (m_castButton->isWanted()) { |
754 if (droppedCastButton) | 801 if (droppedCastButton) |
755 m_overlayCastButton->tryShowOverlay(); | 802 m_overlayCastButton->tryShowOverlay(); |
756 else | 803 else |
(...skipping 20 matching lines...) Expand all Loading... | |
777 void MediaControls::networkStateChanged() | 824 void MediaControls::networkStateChanged() |
778 { | 825 { |
779 invalidate(m_playButton); | 826 invalidate(m_playButton); |
780 invalidate(m_overlayPlayButton); | 827 invalidate(m_overlayPlayButton); |
781 invalidate(m_muteButton); | 828 invalidate(m_muteButton); |
782 invalidate(m_fullScreenButton); | 829 invalidate(m_fullScreenButton); |
783 invalidate(m_timeline); | 830 invalidate(m_timeline); |
784 invalidate(m_volumeSlider); | 831 invalidate(m_volumeSlider); |
785 } | 832 } |
786 | 833 |
834 bool MediaControls::overflowMenuVisible() | |
835 { | |
836 return m_overflowList->isWanted(); | |
837 } | |
838 | |
839 void MediaControls::toggleOverflowMenu() | |
840 { | |
841 m_overflowList->showOverflowMenu(!m_overflowList->isWanted()); | |
842 } | |
843 | |
787 DEFINE_TRACE(MediaControls) | 844 DEFINE_TRACE(MediaControls) |
788 { | 845 { |
789 visitor->trace(m_mediaElement); | 846 visitor->trace(m_mediaElement); |
790 visitor->trace(m_panel); | 847 visitor->trace(m_panel); |
791 visitor->trace(m_overlayPlayButton); | 848 visitor->trace(m_overlayPlayButton); |
792 visitor->trace(m_overlayEnclosure); | 849 visitor->trace(m_overlayEnclosure); |
793 visitor->trace(m_playButton); | 850 visitor->trace(m_playButton); |
794 visitor->trace(m_currentTimeDisplay); | 851 visitor->trace(m_currentTimeDisplay); |
795 visitor->trace(m_timeline); | 852 visitor->trace(m_timeline); |
796 visitor->trace(m_muteButton); | 853 visitor->trace(m_muteButton); |
797 visitor->trace(m_volumeSlider); | 854 visitor->trace(m_volumeSlider); |
798 visitor->trace(m_toggleClosedCaptionsButton); | 855 visitor->trace(m_toggleClosedCaptionsButton); |
799 visitor->trace(m_fullScreenButton); | 856 visitor->trace(m_fullScreenButton); |
800 visitor->trace(m_durationDisplay); | 857 visitor->trace(m_durationDisplay); |
801 visitor->trace(m_enclosure); | 858 visitor->trace(m_enclosure); |
802 visitor->trace(m_textTrackList); | 859 visitor->trace(m_textTrackList); |
860 visitor->trace(m_overflowMenu); | |
861 visitor->trace(m_overflowList); | |
803 visitor->trace(m_castButton); | 862 visitor->trace(m_castButton); |
804 visitor->trace(m_overlayCastButton); | 863 visitor->trace(m_overlayCastButton); |
805 HTMLDivElement::trace(visitor); | 864 HTMLDivElement::trace(visitor); |
806 } | 865 } |
807 | 866 |
808 } // namespace blink | 867 } // namespace blink |
OLD | NEW |