Changeset 275358 in webkit


Ignore:
Timestamp:
Apr 1, 2021 8:05:24 AM (3 years ago)
Author:
Devin Rousso
Message:

Limit the number of buttons shown in media controls
https://bugs.webkit.org/show_bug.cgi?id=223909

Reviewed by Eric Carlson.

Source/WebCore:

When in fullscreen, it's possible to have five different buttons to the right of "Play":

  • AirPlay
  • Enter Picture in Picture
  • Audio/Languages
  • Exit Full Screen
  • More...

This turns the UI into something of an "icon soup" and should really be avoided, especially
now that OverflowButton allows for a single button to have multiple actions (via a native
contextmenu). This matches AVKit behavior.

Tests: media/modern-media-controls/ios-inline-media-controls/ios-inline-media-dropping-controls.html:

media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-buttons-containers-styles.html:
media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-buttons-styles.html:
media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-constructor.html:
media/modern-media-controls/macos-inline-media-controls/macos-inline-media-dropping-controls.html:

  • Modules/modern-media-controls/controls/inline-media-controls.js:

(InlineMediaControls.prototype.layout):
(InlineMediaControls.prototype._droppableButtons):
(InlineMediaControls.prototype._collapsableButtons): Added.

  • Modules/modern-media-controls/controls/macos-fullscreen-media-controls.js:

(MacOSFullscreenMediaControls):
(MacOSFullscreenMediaControls.prototype.layout):
(MacOSFullscreenMediaControls.prototype._collapsableButtons): Added.
Limit the number of visible buttons in rightContainer.children by iteratively marking
dropped = true on buttons that are also in _collapsableButtons until either there are
no iterations left (i < 0) or the number of visible buttons is below the maximum (2 for
inline and 3 for fullscreen).

  • Modules/modern-media-controls/controls/pip-button.js:

(PiPButton.prototype.get contextMenuOptions): Added.

  • Modules/mediacontrols/MediaControlsHost.cpp:

(WebCore::MediaControlsHost::showMediaControlsContextMenu):
Add support for includePictureInPicture to the native contextmenu.

  • en.lproj/Localizable.strings:
  • testing/Internals.idl:
  • testing/Internals.h:
  • testing/Internals.cpp:

(WebCore::Internals::setMediaControlsMaximumRightContainerButtonCountOverride): Added.

  • html/HTMLMediaElement.h:
  • html/HTMLMediaElement.cpp:

(WebCore::HTMLMediaElement::setMediaControlsMaximumRightContainerButtonCountOverride): Added.

  • Modules/modern-media-controls/media/media-controller.js:

(MediaController.prototype.set maximumRightContainerButtonCountOverride): Added.
Add a way to override the default maximum right container button count for testing. This is
useful for testing the functionality of a specific button when not in the collapsed state,
allowing for tests to not have to worry about other state that may affect collapsing (e.g.
the AirPlay button is shown when there are AirPlay targets).

LayoutTests:

  • media/modern-media-controls/ios-inline-media-controls/ios-inline-media-dropping-controls.html:
  • media/modern-media-controls/ios-inline-media-controls/ios-inline-media-dropping-controls-expected.txt:
  • media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-buttons-containers-styles.html:
  • media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-buttons-containers-styles-expected.txt:
  • media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-buttons-styles.html:
  • media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-buttons-styles-expected.txt:
  • media/modern-media-controls/macos-inline-media-controls/macos-inline-media-dropping-controls.html:
  • media/modern-media-controls/macos-inline-media-controls/macos-inline-media-dropping-controls-expected.txt:
  • media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-constructor.html:
  • media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-constructor-expected.txt:
  • media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-right-container-margin.html: Removed.
  • media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-right-container-margin-expected.txt: Removed.

macOS fullscreen controls don't adjust the buttonMargin anymore as buttons are moved into
the overflow menu instead.

  • media/modern-media-controls/tracks-support/auto-text-track.html:
  • media/modern-media-controls/tracks-support/click-track-in-contextmenu.html:
  • media/modern-media-controls/tracks-support/hidden-tracks.html:
  • media/modern-media-controls/tracks-support/off-text-track.html:
  • media/modern-media-controls/tracks-support/show-contextmenu-then-double-click-on-tracks-button.html:
  • media/modern-media-controls/tracks-support/text-track-selected-via-media-api.html:

Override the default maximum right container button count so that the tracks button is shown.

Location:
trunk
Files:
2 deleted
29 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r275356 r275358  
     12021-04-01  Devin Rousso  <drousso@apple.com>
     2
     3        Limit the number of buttons shown in media controls
     4        https://bugs.webkit.org/show_bug.cgi?id=223909
     5
     6        Reviewed by Eric Carlson.
     7
     8        * media/modern-media-controls/ios-inline-media-controls/ios-inline-media-dropping-controls.html:
     9        * media/modern-media-controls/ios-inline-media-controls/ios-inline-media-dropping-controls-expected.txt:
     10        * media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-buttons-containers-styles.html:
     11        * media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-buttons-containers-styles-expected.txt:
     12        * media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-buttons-styles.html:
     13        * media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-buttons-styles-expected.txt:
     14        * media/modern-media-controls/macos-inline-media-controls/macos-inline-media-dropping-controls.html:
     15        * media/modern-media-controls/macos-inline-media-controls/macos-inline-media-dropping-controls-expected.txt:
     16
     17        * media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-constructor.html:
     18        * media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-constructor-expected.txt:
     19        * media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-right-container-margin.html: Removed.
     20        * media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-right-container-margin-expected.txt: Removed.
     21        macOS fullscreen controls don't adjust the `buttonMargin` anymore as buttons are moved into
     22        the overflow menu instead.
     23
     24        * media/modern-media-controls/tracks-support/auto-text-track.html:
     25        * media/modern-media-controls/tracks-support/click-track-in-contextmenu.html:
     26        * media/modern-media-controls/tracks-support/hidden-tracks.html:
     27        * media/modern-media-controls/tracks-support/off-text-track.html:
     28        * media/modern-media-controls/tracks-support/show-contextmenu-then-double-click-on-tracks-button.html:
     29        * media/modern-media-controls/tracks-support/text-track-selected-via-media-api.html:
     30        Override the default maximum right container button count so that the tracks button is shown.
     31
    1322021-04-01  Commit Queue  <commit-queue@webkit.org>
    233
  • trunk/LayoutTests/media/modern-media-controls/ios-inline-media-controls/ios-inline-media-dropping-controls-expected.txt

    r227979 r275358  
    66PASS ready() became true
    77
    8 SkipForwardButton was dropped at 384.
    9 SkipBackButton was dropped at 355.
    10 AirplayButton was dropped at 326.
    11 TracksButton was dropped at 294.
     8TracksButton was dropped at 681.
     9PiPButton was dropped at 681.
     10SkipForwardButton was dropped at 453.
     11SkipBackButton was dropped at 424.
     12MuteButton was dropped at 395.
     13AirplayButton was dropped at 357.
     14FullscreenButton was dropped at 325.
     15OverflowButton was dropped at 294.
    1216
    1317PASS successfullyParsed is true
  • trunk/LayoutTests/media/modern-media-controls/ios-inline-media-controls/ios-inline-media-dropping-controls.html

    r227979 r275358  
    1010
    1111const mediaControls = new IOSInlineMediaControls({ width: 680, height: 300 });
     12mediaControls.shouldUseSingleBarLayout = true;
    1213
    1314const droppableControls = [
     15    mediaControls.overflowButton,
     16    mediaControls.fullscreenButton,
     17    mediaControls.airplayButton,
     18    mediaControls.muteButton,
     19    mediaControls.skipBackButton,
    1420    mediaControls.skipForwardButton,
    15     mediaControls.skipBackButton,
    16     mediaControls.airplayButton,
    17     mediaControls.tracksButton
     21    mediaControls.pipButton,
     22    mediaControls.tracksButton,
    1823];
    1924
     
    2530shouldBecomeEqual("ready()", "true", () => {
    2631    debug("");
    27     droppableControls.forEach(control => {
    28         while (control.visible)
    29             mediaControls.width--;
    30         debug(`${control.constructor.name} was dropped at ${mediaControls.width + 1}.`);
    31     });
     32    while (droppableControls.length) {
     33        for (let i = droppableControls.length - 1; i >= 0; --i) {
     34            if (!droppableControls[i].visible) {
     35                debug(`${droppableControls[i].constructor.name} was dropped at ${mediaControls.width + 1}.`);
     36                droppableControls.splice(i, 1);
     37            }
     38        }
     39
     40        mediaControls.width--;
     41    }
    3242    debug("");
    3343    finishJSTest();
  • trunk/LayoutTests/media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-buttons-containers-styles-expected.txt

    r274521 r275358  
    99PASS centerContainer.element.getBoundingClientRect().height is 44
    1010
    11 PASS Math.floor(rightContainer.element.getBoundingClientRect().width) became 131
    12 PASS rightContainer.element.getBoundingClientRect().left is within 0.5 of 503
     11PASS Math.floor(rightContainer.element.getBoundingClientRect().width) became 123
     12PASS rightContainer.element.getBoundingClientRect().left is within 0.5 of 511
    1313PASS rightContainer.element.getBoundingClientRect().top is 500
    1414PASS rightContainer.element.getBoundingClientRect().height is 44
  • trunk/LayoutTests/media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-buttons-containers-styles.html

    r274521 r275358  
    4242
    4343    debug("");
    44     shouldBecomeEqual("Math.floor(rightContainer.element.getBoundingClientRect().width)", "131", () => {
    45         shouldBeCloseTo("rightContainer.element.getBoundingClientRect().left", 503, 0.5);
     44    shouldBecomeEqual("Math.floor(rightContainer.element.getBoundingClientRect().width)", "123", () => {
     45        shouldBeCloseTo("rightContainer.element.getBoundingClientRect().left", 511, 0.5);
    4646        shouldBe("rightContainer.element.getBoundingClientRect().top", "500");
    4747        shouldBe("rightContainer.element.getBoundingClientRect().height", "44");
  • trunk/LayoutTests/media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-buttons-styles-expected.txt

    r274521 r275358  
    2727PiPButton
    2828PASS getComputedStyle(button.element).top became "18px"
    29 PASS getComputedStyle(button.element).left is "43px"
     29PASS getComputedStyle(button.element).left is "36px"
    3030PASS getComputedStyle(button.element).height is "16px"
    3131
    3232TracksButton
    3333PASS getComputedStyle(button.element).top became "18px"
    34 PASS getComputedStyle(button.element).left is "74px"
     34PASS getComputedStyle(button.element).left is "60px"
    3535PASS getComputedStyle(button.element).height is "16px"
    3636
    3737FullscreenButton
    3838PASS getComputedStyle(button.element).top became "18px"
    39 PASS getComputedStyle(button.element).left is "103px"
     39PASS getComputedStyle(button.element).left is "55px"
    4040PASS getComputedStyle(button.element).height is "16px"
    4141PASS successfullyParsed is true
  • trunk/LayoutTests/media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-buttons-styles.html

    r274521 r275358  
    1717    [mediaControls.forwardButton, 127, 14, 16],
    1818    [mediaControls.airplayButton, 12, 18, 16],
    19     [mediaControls.pipButton, 43, 18, 16],
    20     [mediaControls.tracksButton, 74, 18, 16],
    21     [mediaControls.fullscreenButton, 103, 18, 16],
     19    [mediaControls.pipButton, 36, 18, 16],
     20    [mediaControls.tracksButton, 60, 18, 16],
     21    [mediaControls.fullscreenButton, 55, 18, 16],
    2222];
    2323
  • trunk/LayoutTests/media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-constructor-expected.txt

    r274521 r275358  
    3333PASS mediaControls.bottomControlsBar.children[3].leftMargin is 12
    3434PASS mediaControls.bottomControlsBar.children[3].rightMargin is 12
    35 PASS mediaControls.bottomControlsBar.children[3].buttonMargin is 16
     35PASS mediaControls.bottomControlsBar.children[3].buttonMargin is 24
    3636
    3737PASS successfullyParsed is true
  • trunk/LayoutTests/media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-constructor.html

    r274521 r275358  
    4141shouldBe("mediaControls.bottomControlsBar.children[3].leftMargin", "12");
    4242shouldBe("mediaControls.bottomControlsBar.children[3].rightMargin", "12");
    43 shouldBe("mediaControls.bottomControlsBar.children[3].buttonMargin", "16");
     43shouldBe("mediaControls.bottomControlsBar.children[3].buttonMargin", "24");
    4444
    4545debug("");
  • trunk/LayoutTests/media/modern-media-controls/macos-inline-media-controls/macos-inline-media-dropping-controls-expected.txt

    r274521 r275358  
    66PASS ready() became true
    77
    8 SkipForwardButton was dropped at 482.
    9 SkipBackButton was dropped at 453.
    10 AirplayButton was dropped at 424.
    11 TracksButton was dropped at 392.
    12 PiPButton was dropped at 392.
     8TracksButton was dropped at 681.
     9PiPButton was dropped at 681.
     10SkipForwardButton was dropped at 447.
     11SkipBackButton was dropped at 418.
     12MuteButton was dropped at 389.
     13AirplayButton was dropped at 351.
    1314FullscreenButton was dropped at 319.
    14 MuteButton was dropped at 319.
     15OverflowButton was dropped at 288.
    1516
    1617PASS successfullyParsed is true
  • trunk/LayoutTests/media/modern-media-controls/macos-inline-media-controls/macos-inline-media-dropping-controls.html

    r227953 r275358  
    1313
    1414const droppableControls = [
     15    mediaControls.overflowButton,
     16    mediaControls.fullscreenButton,
     17    mediaControls.airplayButton,
     18    mediaControls.muteButton,
     19    mediaControls.skipBackButton,
    1520    mediaControls.skipForwardButton,
    16     mediaControls.skipBackButton,
    17     mediaControls.airplayButton,
     21    mediaControls.pipButton,
    1822    mediaControls.tracksButton,
    19     mediaControls.pipButton,
    20     mediaControls.fullscreenButton,
    21     mediaControls.muteButton
    2223];
    2324
     
    2930shouldBecomeEqual("ready()", "true", () => {
    3031    debug("");
    31     droppableControls.forEach(control => {
    32         while (control.visible)
    33             mediaControls.width--;
    34         debug(`${control.constructor.name} was dropped at ${mediaControls.width + 1}.`);
    35     });
     32    while (droppableControls.length) {
     33        for (let i = droppableControls.length - 1; i >= 0; --i) {
     34            if (!droppableControls[i].visible) {
     35                debug(`${droppableControls[i].constructor.name} was dropped at ${mediaControls.width + 1}.`);
     36                droppableControls.splice(i, 1);
     37            }
     38        }
     39
     40        mediaControls.width--;
     41    }
    3642    debug("");
    3743    finishJSTest();
  • trunk/LayoutTests/media/modern-media-controls/tracks-support/auto-text-track.html

    r275265 r275358  
    44<script src="../../../resources/js-test-pre.js"></script>
    55<body>
    6 <video src="../../content/counting-subtitled.m4v" style="position: absolute; left: 0; top: 0; width: 400px;" autoplay controls muted playsinline></video>
     6<video src="../../content/counting-subtitled.m4v" style="position: absolute; left: 0; top: 0; width: 600px;" autoplay controls muted playsinline></video>
    77<script type="text/javascript">
    88
     
    1313const media = document.querySelector("video");
    1414const shadowRoot = window.internals.shadowRoot(media);
     15
     16window.internals.setMediaControlsMaximumRightContainerButtonCountOverride(media, 100); // A finite value larger than anything likely.
    1517
    1618let checkedItems = null;
  • trunk/LayoutTests/media/modern-media-controls/tracks-support/click-track-in-contextmenu.html

    r275265 r275358  
    44<script src="../../../resources/js-test-pre.js"></script>
    55<body>
    6 <video src="../../content/audio-tracks.mp4" style="position: absolute; left: 0; top: 0; width: 400px;" controls autoplay muted playsinline></video>
     6<video src="../../content/audio-tracks.mp4" style="position: absolute; left: 0; top: 0; width: 600px;" controls autoplay muted playsinline></video>
    77<script type="text/javascript">
    88
     
    1313const media = document.querySelector("video");
    1414const shadowRoot = window.internals.shadowRoot(media);
     15
     16window.internals.setMediaControlsMaximumRightContainerButtonCountOverride(media, 100); // A finite value larger than anything likely.
    1517
    1618let selectedTrack = null;
  • trunk/LayoutTests/media/modern-media-controls/tracks-support/hidden-tracks.html

    r275265 r275358  
    44<script src="../../../resources/js-test-pre.js"></script>
    55<body>
    6 <video src="../../content/counting-subtitled.m4v" style="position: absolute; left: 0; top: 0; width: 400px;" controls autoplay muted playsinline></video>
     6<video src="../../content/counting-subtitled.m4v" style="position: absolute; left: 0; top: 0; width: 600px;" controls autoplay muted playsinline></video>
    77<script type="text/javascript">
    88
     
    1313const media = document.querySelector("video");
    1414const shadowRoot = window.internals.shadowRoot(media);
     15
     16window.internals.setMediaControlsMaximumRightContainerButtonCountOverride(media, 100); // A finite value larger than anything likely.
    1517
    1618let checkedItems = null;
  • trunk/LayoutTests/media/modern-media-controls/tracks-support/off-text-track.html

    r275265 r275358  
    44<script src="../../../resources/js-test-pre.js"></script>
    55<body>
    6 <video src="../../content/counting-subtitled.m4v" style="position: absolute; left: 0; top: 0; width: 400px;" autoplay controls muted playsinline></video>
     6<video src="../../content/counting-subtitled.m4v" style="position: absolute; left: 0; top: 0; width: 600px;" autoplay controls muted playsinline></video>
    77<script type="text/javascript">
    88
     
    1313const media = document.querySelector("video");
    1414const shadowRoot = window.internals.shadowRoot(media);
     15
     16window.internals.setMediaControlsMaximumRightContainerButtonCountOverride(media, 100); // A finite value larger than anything likely.
    1517
    1618let checkedItems = null;
  • trunk/LayoutTests/media/modern-media-controls/tracks-support/show-contextmenu-then-double-click-on-tracks-button.html

    r274521 r275358  
    44<script src="../../../resources/js-test-pre.js"></script>
    55<body>
    6 <video src="../../content/CC+Subtitles.mov" style="position: absolute; left: 0; top: 0; width: 400px;" autoplay controls muted playsinline></video>
     6<video src="../../content/CC+Subtitles.mov" style="position: absolute; left: 0; top: 0; width: 600px;" autoplay controls muted playsinline></video>
    77<script type="text/javascript">
    88
     
    1313const media = document.querySelector("video");
    1414const shadowRoot = window.internals.shadowRoot(media);
     15
     16window.internals.setMediaControlsMaximumRightContainerButtonCountOverride(media, 100); // A finite value larger than anything likely.
    1517
    1618media.addEventListener("play", () => {
  • trunk/LayoutTests/media/modern-media-controls/tracks-support/text-track-selected-via-media-api.html

    r275265 r275358  
    44<script src="../../../resources/js-test-pre.js"></script>
    55<body>
    6 <video src="../../content/counting-subtitled.m4v" style="position: absolute; left: 0; top: 0; width: 400px;" autoplay controls muted playsinline></video>
     6<video src="../../content/counting-subtitled.m4v" style="position: absolute; left: 0; top: 0; width: 600px;" autoplay controls muted playsinline></video>
    77<script type="text/javascript">
    88
     
    1414const media = document.querySelector("video");
    1515const shadowRoot = window.internals.shadowRoot(media);
     16
     17window.internals.setMediaControlsMaximumRightContainerButtonCountOverride(media, 100); // A finite value larger than anything likely.
    1618
    1719let contextmenu = null;
  • trunk/Source/WebCore/ChangeLog

    r275357 r275358  
     12021-04-01  Devin Rousso  <drousso@apple.com>
     2
     3        Limit the number of buttons shown in media controls
     4        https://bugs.webkit.org/show_bug.cgi?id=223909
     5
     6        Reviewed by Eric Carlson.
     7
     8        When in fullscreen, it's possible to have five different buttons to the right of "Play":
     9         - AirPlay
     10         - Enter Picture in Picture
     11         - Audio/Languages
     12         - Exit Full Screen
     13         - More...
     14        This turns the UI into something of an "icon soup" and should really be avoided, especially
     15        now that `OverflowButton` allows for a single button to have multiple actions (via a native
     16        contextmenu). This matches AVKit behavior.
     17
     18        Tests: media/modern-media-controls/ios-inline-media-controls/ios-inline-media-dropping-controls.html:
     19               media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-buttons-containers-styles.html:
     20               media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-buttons-styles.html:
     21               media/modern-media-controls/macos-fullscreen-media-controls/macos-fullscreen-media-controls-constructor.html:
     22               media/modern-media-controls/macos-inline-media-controls/macos-inline-media-dropping-controls.html:
     23
     24        * Modules/modern-media-controls/controls/inline-media-controls.js:
     25        (InlineMediaControls.prototype.layout):
     26        (InlineMediaControls.prototype._droppableButtons):
     27        (InlineMediaControls.prototype._collapsableButtons): Added.
     28        * Modules/modern-media-controls/controls/macos-fullscreen-media-controls.js:
     29        (MacOSFullscreenMediaControls):
     30        (MacOSFullscreenMediaControls.prototype.layout):
     31        (MacOSFullscreenMediaControls.prototype._collapsableButtons): Added.
     32        Limit the number of `visible` buttons in `rightContainer.children` by iteratively marking
     33        `dropped = true` on buttons that are also in `_collapsableButtons` until either there are
     34        no iterations left (`i < 0`) or the number of visible buttons is below the maximum (2 for
     35        inline and 3 for fullscreen).
     36
     37        * Modules/modern-media-controls/controls/pip-button.js:
     38        (PiPButton.prototype.get contextMenuOptions): Added.
     39        * Modules/mediacontrols/MediaControlsHost.cpp:
     40        (WebCore::MediaControlsHost::showMediaControlsContextMenu):
     41        Add support for `includePictureInPicture` to the native contextmenu.
     42
     43        * en.lproj/Localizable.strings:
     44
     45        * testing/Internals.idl:
     46        * testing/Internals.h:
     47        * testing/Internals.cpp:
     48        (WebCore::Internals::setMediaControlsMaximumRightContainerButtonCountOverride): Added.
     49        * html/HTMLMediaElement.h:
     50        * html/HTMLMediaElement.cpp:
     51        (WebCore::HTMLMediaElement::setMediaControlsMaximumRightContainerButtonCountOverride): Added.
     52        * Modules/modern-media-controls/media/media-controller.js:
     53        (MediaController.prototype.set maximumRightContainerButtonCountOverride): Added.
     54        Add a way to override the default maximum right container button count for testing. This is
     55        useful for testing the functionality of a specific button when not in the collapsed state,
     56        allowing for tests to not have to worry about other state that may affect collapsing (e.g.
     57        the AirPlay button is shown when there are AirPlay targets).
     58
    1592021-04-01  Zalan Bujtas  <zalan@apple.com>
    260
  • trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.cpp

    r275225 r275358  
    4646#include "HTMLElement.h"
    4747#include "HTMLMediaElement.h"
     48#include "HTMLVideoElement.h"
    4849#include "LocalizedStrings.h"
    4950#include "Logging.h"
     
    5657#include "TextTrack.h"
    5758#include "TextTrackList.h"
     59#include "UserGestureIndicator.h"
    5860#include "VoidCallback.h"
    5961#include <JavaScriptCore/JSCJSValueInlines.h>
     
    501503#endif
    502504
    503     using MenuData = Variant<RefPtr<AudioTrack>, RefPtr<TextTrack> MediaControlsHostAdditions_showMediaControlsContextMenu_MenuData>;
     505#if ENABLE(VIDEO_PRESENTATION_MODE)
     506    enum class PictureInPictureTag { IncludePictureInPicture };
     507#endif // ENABLE(VIDEO_PRESENTATION_MODE)
     508
     509    using MenuData = Variant<
     510#if ENABLE(VIDEO_PRESENTATION_MODE)
     511        PictureInPictureTag,
     512#endif // ENABLE(VIDEO_PRESENTATION_MODE)
     513        RefPtr<AudioTrack>,
     514        RefPtr<TextTrack>
     515        MediaControlsHostAdditions_showMediaControlsContextMenu_MenuData
     516    >;
    504517    HashMap<MenuItemIdentifier, MenuData> idMap;
    505518
     
    513526    };
    514527
    515     auto createMenuItem = [&] (MenuData data, const String& title, bool checked = false) -> MenuItem {
     528    auto createMenuItem = [&] (MenuData data, const String& title, bool checked = false, const String& icon = nullString()) -> MenuItem {
    516529        auto id = idMap.size() + 1;
    517530        idMap.add(id, data);
    518531
    519532#if USE(UICONTEXTMENU)
    520         return { id, title, /* icon */ nullString(), checked, /* children */ { } };
     533        return { id, title, icon, checked, /* children */ { } };
    521534#elif ENABLE(CONTEXT_MENUS) && USE(ACCESSIBILITY_CONTEXT_MENUS)
     535        UNUSED_PARAM(icon);
    522536        return { CheckableActionType, static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + id), title, /* enabled */ true, checked };
    523537#endif
     
    525539
    526540    Vector<MenuItem> items;
     541
     542#if ENABLE(VIDEO_PRESENTATION_MODE)
     543    if (optionsJSONObject->getBoolean("includePictureInPicture"_s).valueOr(false)) {
     544        ASSERT(is<HTMLVideoElement>(mediaElement));
     545        ASSERT(downcast<HTMLVideoElement>(mediaElement).webkitSupportsPresentationMode(HTMLVideoElement::VideoPresentationMode::PictureInPicture));
     546        items.append(createMenuItem(PictureInPictureTag::IncludePictureInPicture, WEB_UI_STRING_KEY("Picture in Picture", "Picture in Picture (Media Controls Menu)", "Picture in Picture media controls context menu title"), false, "pip.enter"_s));
     547    }
     548#endif // ENABLE(VIDEO_PRESENTATION_MODE)
    527549
    528550    if (optionsJSONObject->getBoolean("includeLanguages"_s).valueOr(false)) {
     
    602624        auto& mediaElement = *weakMediaElement;
    603625
     626        UserGestureIndicator gestureIndicator(ProcessingUserGesture, &mediaElement.document());
     627
    604628        auto selectedItem = idMap.get(selectedItemID);
    605629        WTF::switchOn(selectedItem,
     630#if ENABLE(VIDEO_PRESENTATION_MODE)
     631            [&] (PictureInPictureTag) {
     632                // Media controls are not shown when in PiP so we can assume that we're not in PiP.
     633                downcast<HTMLVideoElement>(mediaElement).webkitSetPresentationMode(HTMLVideoElement::VideoPresentationMode::PictureInPicture);
     634            },
     635#endif // ENABLE(VIDEO_PRESENTATION_MODE)
    606636            [&] (RefPtr<AudioTrack>& selectedAudioTrack) {
    607637                for (auto& track : idMap.values()) {
  • trunk/Source/WebCore/Modules/modern-media-controls/controls/inline-media-controls.js

    r274521 r275358  
    185185        }
    186186
     187        let collapsableButtons = this._collapsableButtons();
     188        let shownRightContainerButtons = this.rightContainer.children.filter(button => button.enabled && !button.dropped);
     189        let maximumRightContainerButtonCount = this.maximumRightContainerButtonCountOverride ?? 2; // Allow AirPlay and overflow if all buttons are shown.
     190        for (let i = shownRightContainerButtons.length - 1; i >= 0 && shownRightContainerButtons.length > maximumRightContainerButtonCount; --i) {
     191            let button = shownRightContainerButtons[i];
     192            if (!collapsableButtons.has(button))
     193                continue;
     194
     195            button.dropped = true;
     196            this.overflowButton.addContextMenuOptions(button.contextMenuOptions);
     197        }
     198
    187199        // Update layouts once more.
    188200        this.leftContainer.layout();
     
    270282    _droppableButtons()
    271283    {
     284        let buttons = this._collapsableButtons();
     285        buttons.add(this.skipForwardButton);
     286        buttons.add(this.skipBackButton);
     287        if (this._shouldUseSingleBarLayout || this.preferredMuteButtonStyle === Button.Styles.Bar)
     288            buttons.add(this.muteButton);
     289        buttons.add(this.airplayButton);
    272290        if (this._shouldUseSingleBarLayout)
    273             return [this.skipForwardButton, this.skipBackButton, this.airplayButton, this.tracksButton, this.pipButton, this.muteButton, this.fullscreenButton, this.overflowButton];
    274 
    275         const buttons = [this.skipForwardButton, this.skipBackButton, this.airplayButton, this.tracksButton];
    276         if (this.preferredMuteButtonStyle === Button.Styles.Bar)
    277             buttons.push(this.muteButton);
    278         buttons.push(this.overflowButton);
     291            buttons.add(this.fullscreenButton);
     292        buttons.add(this.overflowButton);
     293        return buttons;
     294    }
     295
     296    _collapsableButtons()
     297    {
     298        let buttons = new Set([
     299            this.tracksButton,
     300        ]);
     301        if (this._shouldUseSingleBarLayout)
     302            buttons.add(this.pipButton);
    279303        return buttons;
    280304    }
  • trunk/Source/WebCore/Modules/modern-media-controls/controls/macos-fullscreen-media-controls.js

    r274521 r275358  
    2424 */
    2525
    26 const ButtonMarginForThreeButtonsOrLess = 24;
    27 const ButtonMarginForFourButtons = 16;
    28 const ButtonMarginForFiveButtons = 12;
    2926const FullscreenTimeControlWidth = 448;
    3027
     
    6966            cssClassName: "right",
    7067            leftMargin: 12,
    71             rightMargin: 12
     68            rightMargin: 12,
     69            buttonMargin: 24
    7270        });
    7371
     
    112110            return;
    113111
    114         const numberOfEnabledButtons = this._rightContainer.children.filter(button => button.enabled).length;
    115 
    116         let buttonMargin = ButtonMarginForFiveButtons;
    117         if (numberOfEnabledButtons === 4)
    118             buttonMargin = ButtonMarginForFourButtons;
    119         else if (numberOfEnabledButtons <= 3)
    120             buttonMargin = ButtonMarginForThreeButtonsOrLess;
    121 
    122         this._rightContainer.buttonMargin = buttonMargin;
     112        this._rightContainer.children.forEach(button => delete button.dropped)
     113        this.overflowButton.clearContextMenuOptions();
    123114
    124115        this._leftContainer.visible = this.muteButton.enabled;
    125116        this._leftContainer.children = this._volumeControlsForCurrentDirection();
     117
     118        let collapsableButtons = this._collapsableButtons();
     119        let shownRightContainerButtons = this._rightContainer.children.filter(button => button.enabled && !button.dropped);
     120        let maximumRightContainerButtonCount = this.maximumRightContainerButtonCountOverride ?? 3; // Allow AirPlay, Exit Fullscreen, and overflow if all buttons are shown.
     121        for (let i = shownRightContainerButtons.length - 1; i >= 0 && shownRightContainerButtons.length > maximumRightContainerButtonCount; --i) {
     122            let button = shownRightContainerButtons[i];
     123            if (!collapsableButtons.has(button))
     124                continue;
     125
     126            button.dropped = true;
     127            this.overflowButton.addContextMenuOptions(button.contextMenuOptions);
     128        }
    126129
    127130        this._leftContainer.layout();
     
    148151    }
    149152
     153    _collapsableButtons()
     154    {
     155        return new Set([
     156            this.tracksButton,
     157            this.pipButton,
     158        ]);
     159    }
     160
    150161    _handleMousedown(event)
    151162    {
  • trunk/Source/WebCore/Modules/modern-media-controls/controls/pip-button.js

    r217823 r275358  
    3636    }
    3737
     38    // Public
     39
     40    get contextMenuOptions()
     41    {
     42        return {
     43            includePictureInPicture: true,
     44        };
     45    }
     46
    3847}
  • trunk/Source/WebCore/Modules/modern-media-controls/media/media-controller.js

    r274521 r275358  
    374374    }
    375375
     376    // Testing
     377
     378    set maximumRightContainerButtonCountOverride(count)
     379    {
     380        this.controls.maximumRightContainerButtonCountOverride = count;
     381    }
     382
    376383}
  • trunk/Source/WebCore/en.lproj/Localizable.strings

    r274698 r275358  
    662662"Photo Library (file upload action sheet)" = "Photo Library";
    663663
     664/* Picture in Picture media controls context menu title */
     665"Picture in Picture (Media Controls Menu)" = "Picture in Picture";
     666
    664667/* Media Play context menu item */
    665668"Play" = "Play";
  • trunk/Source/WebCore/html/HTMLMediaElement.cpp

    r275262 r275358  
    73897389}
    73907390
     7391void HTMLMediaElement::setMediaControlsMaximumRightContainerButtonCountOverride(size_t count)
     7392{
     7393    setControllerJSProperty("maximumRightContainerButtonCountOverride", JSC::jsNumber(count));
     7394}
     7395
    73917396unsigned long long HTMLMediaElement::fileSize() const
    73927397{
  • trunk/Source/WebCore/html/HTMLMediaElement.h

    r274264 r275358  
    495495    void userInterfaceLayoutDirectionChanged();
    496496    WEBCORE_EXPORT String getCurrentMediaControlsStatus();
     497    WEBCORE_EXPORT void setMediaControlsMaximumRightContainerButtonCountOverride(size_t);
    497498    MediaControlsHost* mediaControlsHost() { return m_mediaControlsHost.get(); }
    498499
  • trunk/Source/WebCore/testing/Internals.cpp

    r275187 r275358  
    47654765}
    47664766
     4767#if ENABLE(VIDEO)
     4768
    47674769String Internals::getCurrentMediaControlsStatusForElement(HTMLMediaElement& mediaElement)
    47684770{
    4769 #if ENABLE(VIDEO)
    47704771    return mediaElement.getCurrentMediaControlsStatus();
    4771 #else
    4772     UNUSED_PARAM(mediaElement);
    4773     return { };
    4774 #endif
    4775 }
     4772}
     4773
     4774void Internals::setMediaControlsMaximumRightContainerButtonCountOverride(HTMLMediaElement& mediaElement, size_t count)
     4775{
     4776    mediaElement.setMediaControlsMaximumRightContainerButtonCountOverride(count);
     4777}
     4778
     4779#endif // ENABLE(VIDEO)
    47764780
    47774781#if !PLATFORM(COCOA)
  • trunk/Source/WebCore/testing/Internals.h

    r275187 r275358  
    729729    ExceptionOr<String> pathStringWithShrinkWrappedRects(const Vector<double>& rectComponents, double radius);
    730730
     731#if ENABLE(VIDEO)
    731732    String getCurrentMediaControlsStatusForElement(HTMLMediaElement&);
     733    void setMediaControlsMaximumRightContainerButtonCountOverride(HTMLMediaElement&, size_t);
     734#endif // ENABLE(VIDEO)
    732735
    733736    String userVisibleString(const DOMURL&);
  • trunk/Source/WebCore/testing/Internals.idl

    r275187 r275358  
    764764
    765765    [Conditional=VIDEO] DOMString getCurrentMediaControlsStatusForElement(HTMLMediaElement element);
     766    [Conditional=VIDEO] undefined setMediaControlsMaximumRightContainerButtonCountOverride(HTMLMediaElement element, unsigned long count);
    766767
    767768    DOMString userVisibleString(DOMURL url);
Note: See TracChangeset for help on using the changeset viewer.