Title: [282971] trunk/Source/WebCore
Revision
282971
Author
[email protected]
Date
2021-09-23 10:44:47 -0700 (Thu, 23 Sep 2021)

Log Message

[Media Controls] Allow for a single mute and volume button
https://bugs.webkit.org/show_bug.cgi?id=230692
<rdar://problem/79956248>

Reviewed by Dean Jackson.

Up to now, the mute button in the controls bar would act as a toggle for the "muted" property on the media element.
Hovering that button would make a slider appear that would allow the "volume" property of the media element to be
changed as well.

We now allow for a single button with a built-in range indicator to be used for mute and volume. Clicking on the
button without moving will toggle the mute status, while moving the mouse up or down will adjust the volume
and show a pill-link range indicator showing the current volume.

This new control is a Button subclass called RangeButton. The new VolumeButton class extends it to provide the
correct icon depending on the volume and muted state. The new MuteAndVolumeSupport class is used in conjunction
with VolumeButton.

To indicate that media controls want to use this new style, MediaControls subclasses can override the
usesSingleMuteAndVolumeButton getter to return true. Currently it's false everywhere until we decide
to use this style.

* DerivedSources-input.xcfilelist:
* DerivedSources.make:
* Modules/modern-media-controls/controls/media-controls.js:
(MediaControls.prototype.get usesSingleMuteAndVolumeButton):
* Modules/modern-media-controls/controls/range-button.css: Added.
(button.range > div.indicator):
(button.range > div.indicator > div.fill):
* Modules/modern-media-controls/controls/range-button.js: Added.
(RangeButton.prototype.get value):
(RangeButton.prototype.set value):
(RangeButton.prototype.commitProperty):
(RangeButton.prototype.handleEvent):
(RangeButton.prototype._handlePointerdown):
(RangeButton.prototype._handlePointermove):
(RangeButton.prototype._handlePointerup):
* Modules/modern-media-controls/controls/volume-button.js: Added.
(VolumeButton):
(VolumeButton.prototype.get volume):
(VolumeButton.prototype.set volume):
(VolumeButton.prototype.get muted):
(VolumeButton.prototype.set muted):
(VolumeButton.prototype.set usesLTRUserInterfaceLayoutDirection):
(VolumeButton.prototype.layout):
* Modules/modern-media-controls/js-files:
* Modules/modern-media-controls/media/media-controller.js:
(MediaController.prototype._supportingObjectClasses):
* Modules/modern-media-controls/media/mute-and-volume-support.js: Added.
(MuteAndVolumeSupport.prototype.get control):
(MuteAndVolumeSupport.prototype.get mediaEvents):
(MuteAndVolumeSupport.prototype.controlValueWillStartChanging):
(MuteAndVolumeSupport.prototype.controlValueDidChange):
(MuteAndVolumeSupport.prototype.controlValueDidStopChanging):
(MuteAndVolumeSupport.prototype.buttonWasPressed):
(MuteAndVolumeSupport.prototype.syncControl):
(MuteAndVolumeSupport):
* WebCore.xcodeproj/project.pbxproj:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (282970 => 282971)


--- trunk/Source/WebCore/ChangeLog	2021-09-23 17:41:22 UTC (rev 282970)
+++ trunk/Source/WebCore/ChangeLog	2021-09-23 17:44:47 UTC (rev 282971)
@@ -1,3 +1,64 @@
+2021-09-23  Antoine Quint  <[email protected]>
+
+        [Media Controls] Allow for a single mute and volume button
+        https://bugs.webkit.org/show_bug.cgi?id=230692
+        <rdar://problem/79956248>
+
+        Reviewed by Dean Jackson.
+
+        Up to now, the mute button in the controls bar would act as a toggle for the "muted" property on the media element.
+        Hovering that button would make a slider appear that would allow the "volume" property of the media element to be
+        changed as well.
+
+        We now allow for a single button with a built-in range indicator to be used for mute and volume. Clicking on the
+        button without moving will toggle the mute status, while moving the mouse up or down will adjust the volume
+        and show a pill-link range indicator showing the current volume.
+
+        This new control is a Button subclass called RangeButton. The new VolumeButton class extends it to provide the
+        correct icon depending on the volume and muted state. The new MuteAndVolumeSupport class is used in conjunction
+        with VolumeButton.
+
+        To indicate that media controls want to use this new style, MediaControls subclasses can override the
+        usesSingleMuteAndVolumeButton getter to return true. Currently it's false everywhere until we decide
+        to use this style.
+
+        * DerivedSources-input.xcfilelist:
+        * DerivedSources.make:
+        * Modules/modern-media-controls/controls/media-controls.js:
+        (MediaControls.prototype.get usesSingleMuteAndVolumeButton):
+        * Modules/modern-media-controls/controls/range-button.css: Added.
+        (button.range > div.indicator):
+        (button.range > div.indicator > div.fill):
+        * Modules/modern-media-controls/controls/range-button.js: Added.
+        (RangeButton.prototype.get value):
+        (RangeButton.prototype.set value):
+        (RangeButton.prototype.commitProperty):
+        (RangeButton.prototype.handleEvent):
+        (RangeButton.prototype._handlePointerdown):
+        (RangeButton.prototype._handlePointermove):
+        (RangeButton.prototype._handlePointerup):
+        * Modules/modern-media-controls/controls/volume-button.js: Added.
+        (VolumeButton):
+        (VolumeButton.prototype.get volume):
+        (VolumeButton.prototype.set volume):
+        (VolumeButton.prototype.get muted):
+        (VolumeButton.prototype.set muted):
+        (VolumeButton.prototype.set usesLTRUserInterfaceLayoutDirection):
+        (VolumeButton.prototype.layout):
+        * Modules/modern-media-controls/js-files:
+        * Modules/modern-media-controls/media/media-controller.js:
+        (MediaController.prototype._supportingObjectClasses):
+        * Modules/modern-media-controls/media/mute-and-volume-support.js: Added.
+        (MuteAndVolumeSupport.prototype.get control):
+        (MuteAndVolumeSupport.prototype.get mediaEvents):
+        (MuteAndVolumeSupport.prototype.controlValueWillStartChanging):
+        (MuteAndVolumeSupport.prototype.controlValueDidChange):
+        (MuteAndVolumeSupport.prototype.controlValueDidStopChanging):
+        (MuteAndVolumeSupport.prototype.buttonWasPressed):
+        (MuteAndVolumeSupport.prototype.syncControl):
+        (MuteAndVolumeSupport):
+        * WebCore.xcodeproj/project.pbxproj:
+
 2021-09-23  Tim Horton  <[email protected]>
 
         shouldAllowPictureInPictureMediaPlayback should use WebCore's linkedOnOrAfter()

Modified: trunk/Source/WebCore/DerivedSources-input.xcfilelist (282970 => 282971)


--- trunk/Source/WebCore/DerivedSources-input.xcfilelist	2021-09-23 17:41:22 UTC (rev 282970)
+++ trunk/Source/WebCore/DerivedSources-input.xcfilelist	2021-09-23 17:44:47 UTC (rev 282971)
@@ -327,6 +327,8 @@
 $(PROJECT_DIR)/Modules/modern-media-controls/controls/placard.css
 $(PROJECT_DIR)/Modules/modern-media-controls/controls/placard.js
 $(PROJECT_DIR)/Modules/modern-media-controls/controls/play-pause-button.js
+$(PROJECT_DIR)/Modules/modern-media-controls/controls/range-button.css
+$(PROJECT_DIR)/Modules/modern-media-controls/controls/range-button.js
 $(PROJECT_DIR)/Modules/modern-media-controls/controls/rewind-button.js
 $(PROJECT_DIR)/Modules/modern-media-controls/controls/scheduler.js
 $(PROJECT_DIR)/Modules/modern-media-controls/controls/seek-button.js
@@ -341,6 +343,7 @@
 $(PROJECT_DIR)/Modules/modern-media-controls/controls/time-label.css
 $(PROJECT_DIR)/Modules/modern-media-controls/controls/time-label.js
 $(PROJECT_DIR)/Modules/modern-media-controls/controls/tracks-button.js
+$(PROJECT_DIR)/Modules/modern-media-controls/controls/volume-button.js
 $(PROJECT_DIR)/Modules/modern-media-controls/controls/watchos-activity-indicator.css
 $(PROJECT_DIR)/Modules/modern-media-controls/controls/watchos-activity-indicator.js
 $(PROJECT_DIR)/Modules/modern-media-controls/controls/watchos-layout-traits.js
@@ -357,6 +360,7 @@
 $(PROJECT_DIR)/Modules/modern-media-controls/media/media-controller-support.js
 $(PROJECT_DIR)/Modules/modern-media-controls/media/media-controller.js
 $(PROJECT_DIR)/Modules/modern-media-controls/media/media-document-controller.js
+$(PROJECT_DIR)/Modules/modern-media-controls/media/mute-and-volume-support.js
 $(PROJECT_DIR)/Modules/modern-media-controls/media/mute-support.js
 $(PROJECT_DIR)/Modules/modern-media-controls/media/overflow-support.js
 $(PROJECT_DIR)/Modules/modern-media-controls/media/pip-support.js

Modified: trunk/Source/WebCore/DerivedSources.make (282970 => 282971)


--- trunk/Source/WebCore/DerivedSources.make	2021-09-23 17:41:22 UTC (rev 282970)
+++ trunk/Source/WebCore/DerivedSources.make	2021-09-23 17:44:47 UTC (rev 282971)
@@ -1549,6 +1549,7 @@
     $(WebCore)/Modules/modern-media-controls/controls/media-controls.css \
     $(WebCore)/Modules/modern-media-controls/controls/media-document.css \
     $(WebCore)/Modules/modern-media-controls/controls/placard.css \
+    $(WebCore)/Modules/modern-media-controls/controls/range-button.css \
     $(WebCore)/Modules/modern-media-controls/controls/slider.css \
     $(WebCore)/Modules/modern-media-controls/controls/status-label.css \
     $(WebCore)/Modules/modern-media-controls/controls/text-tracks.css \
@@ -1624,6 +1625,8 @@
     $(WebCore)/Modules/modern-media-controls/controls/rewind-button.js \
     $(WebCore)/Modules/modern-media-controls/controls/forward-button.js \
     $(WebCore)/Modules/modern-media-controls/controls/overflow-button.js \
+    $(WebCore)/Modules/modern-media-controls/controls/range-button.js \
+    $(WebCore)/Modules/modern-media-controls/controls/volume-button.js \
     $(WebCore)/Modules/modern-media-controls/controls/buttons-container.js \
     $(WebCore)/Modules/modern-media-controls/controls/status-label.js \
     $(WebCore)/Modules/modern-media-controls/controls/controls-bar.js \
@@ -1664,6 +1667,7 @@
     $(WebCore)/Modules/modern-media-controls/media/time-control-support.js \
     $(WebCore)/Modules/modern-media-controls/media/tracks-support.js \
     $(WebCore)/Modules/modern-media-controls/media/volume-support.js \
+    $(WebCore)/Modules/modern-media-controls/media/mute-and-volume-support.js \
     $(WebCore)/Modules/modern-media-controls/media/media-document-controller.js \
     $(WebCore)/Modules/modern-media-controls/media/watchos-media-controls-support.js \
     $(WebCore)/Modules/modern-media-controls/media/media-controller.js \

Modified: trunk/Source/WebCore/Modules/modern-media-controls/controls/media-controls.js (282970 => 282971)


--- trunk/Source/WebCore/Modules/modern-media-controls/controls/media-controls.js	2021-09-23 17:41:22 UTC (rev 282970)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/media-controls.js	2021-09-23 17:44:47 UTC (rev 282971)
@@ -44,6 +44,7 @@
         this.muteButton = new MuteButton(this);
         this.tracksButton = new TracksButton(this);
         this.overflowButton = new OverflowButton(this);
+        this.volumeButton = new VolumeButton(this);
 
         this.statusLabel = new StatusLabel(this);
         this.timeControl = new TimeControl(this);
@@ -235,4 +236,8 @@
             super.commitProperty(propertyName);
     }
 
+    get usesSingleMuteAndVolumeButton()
+    {
+        return false;
+    }
 }

Added: trunk/Source/WebCore/Modules/modern-media-controls/controls/range-button.css (0 => 282971)


--- trunk/Source/WebCore/Modules/modern-media-controls/controls/range-button.css	                        (rev 0)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/range-button.css	2021-09-23 17:44:47 UTC (rev 282971)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+button.range > div.indicator {
+    --indicator-width: 45px;
+    --indicator-height: 134px;
+
+    position: absolute;
+    top: calc(100% - var(--indicator-height) - 5px);
+    width: var(--indicator-width);
+    height: var(--indicator-height);
+
+    clip-path: path('M0,22.5 a22.5,22.5 0 0 1 45,0 v89 a22.5,22.5 0 0 1 -45,0 z');
+}
+
+button.range > div.indicator > div.fill {
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    width: 100%;
+    height: 0;
+    background-color: rgba(255, 255, 255, 0.5);
+}

Added: trunk/Source/WebCore/Modules/modern-media-controls/controls/range-button.js (0 => 282971)


--- trunk/Source/WebCore/Modules/modern-media-controls/controls/range-button.js	                        (rev 0)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/range-button.js	2021-09-23 17:44:47 UTC (rev 282971)
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+class RangeButton extends Button
+{
+
+    constructor({ layoutDelegate = null, cssClassName = "", iconName = "" } = {})
+    {
+        super({ layoutDelegate, cssClassName, iconName });
+
+        this._value = 0;
+
+        this.element.classList.add("range");
+        this.element.addEventListener("pointerdown", this);
+
+        this._indicator = this.addChild(new LayoutNode(`<div class="indicator"></div>`), 0);
+        this._indicatorTint = this._indicator.addChild(new BackgroundTint);
+        this._indicatorFill = this._indicator.addChild(new LayoutNode(`<div class="fill"></div>`));
+
+        this._indicator.visible = false;
+
+        if (GestureRecognizer.SupportsTouches)
+            this._tapGestureRecognizer.enabled = false;
+        else
+            this.element.removeEventListener("click", this);
+    }
+
+    // Public
+
+    get value()
+    {
+        return this._value;
+    }
+
+    set value(value)
+    {
+        this._value = value;
+        this.markDirtyProperty("value");
+    }
+
+    // Protected
+
+    commitProperty(propertyName)
+    {
+        if (propertyName === "value")
+            this._indicatorFill.element.style.height = `${this._value * 100}%`;
+        else
+            super.commitProperty(propertyName);
+    }
+
+    handleEvent(event)
+    {
+        if (event.currentTarget === this.element && event.type == "pointerdown")
+            this._handlePointerdown(event);
+        else if (event.currentTarget === window && event.type === "pointermove")
+            this._handlePointermove(event);
+        else if (event.currentTarget === window && event.type === "pointerup")
+            this._handlePointerup(event);
+        else
+            super.handleEvent(event);
+    }
+
+    // Private
+
+    _handlePointerdown(event)
+    {
+        window.addEventListener("pointermove", this, true);
+        window.addEventListener("pointerup", this, true);
+
+        this._initialPointerY = event.clientY;
+        this._initialValue = this._value;
+    }
+
+    _handlePointermove(event)
+    {
+        if (!this._indicator.visible) {
+            this._indicator.visible = true;
+            if (this.uiDelegate && typeof this.uiDelegate.controlValueWillStartChanging === "function")
+                this.uiDelegate.controlValueWillStartChanging(this);
+            return;
+        }
+
+        if (!this._indicatorHeight)
+            this._indicatorHeight = this._indicator.computedValueForStylePropertyInPx("height");
+
+        if (!this._indicatorHeight)
+            return;
+
+        const traveledPointerDistance = this._initialPointerY - event.clientY;
+        const valueIncrement = traveledPointerDistance / this._indicatorHeight;
+
+        const newValue = Math.max(0, Math.min(1, this._initialValue + valueIncrement));
+        if (this._value === newValue)
+            return;
+
+        this.value = newValue;
+
+        if (this.uiDelegate && typeof this.uiDelegate.controlValueDidChange === "function")
+            this.uiDelegate.controlValueDidChange(this);
+    }
+
+    _handlePointerup(event)
+    {
+        window.removeEventListener("pointermove", this, true);
+        window.removeEventListener("pointerup", this, true);
+
+        delete this._initialPointerY;
+        delete this._initialValue;
+
+        if (this._indicator.visible) {
+            if (this.uiDelegate && typeof this.uiDelegate.controlValueDidStopChanging === "function")
+                this.uiDelegate.controlValueDidStopChanging(this);
+            this._indicator.visible = false;
+        } else {
+            if (this._enabled && this.uiDelegate && typeof this.uiDelegate.buttonWasPressed === "function")
+                this.uiDelegate.buttonWasPressed(this);
+        }
+    }
+
+}

Added: trunk/Source/WebCore/Modules/modern-media-controls/controls/volume-button.js (0 => 282971)


--- trunk/Source/WebCore/Modules/modern-media-controls/controls/volume-button.js	                        (rev 0)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/volume-button.js	2021-09-23 17:44:47 UTC (rev 282971)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+class VolumeButton extends RangeButton
+{
+
+    constructor(layoutDelegate)
+    {
+        super({
+            cssClassName: "mute",
+            iconName: Icons.VolumeMutedRTL,
+            layoutDelegate
+        });
+
+        this._muted = true;
+
+        this._usesLTRUserInterfaceLayoutDirection = undefined;
+    }
+
+    // Public
+
+    get volume()
+    {
+        return this.value;
+    }
+
+    set volume(volume)
+    {
+        this.value = volume;
+        this.needsLayout = true;
+    }
+
+    get muted()
+    {
+        return this._muted;
+    }
+
+    set muted(flag)
+    {
+        if (this._muted === flag)
+            return;
+
+        this._muted = flag;
+        this.needsLayout = true;
+    }
+
+    set usesLTRUserInterfaceLayoutDirection(usesLTRUserInterfaceLayoutDirection)
+    {
+        if (usesLTRUserInterfaceLayoutDirection === this._usesLTRUserInterfaceLayoutDirection)
+            return;
+
+        this._usesLTRUserInterfaceLayoutDirection = usesLTRUserInterfaceLayoutDirection;
+
+        this.needsLayout = true;
+    }
+
+    // Protected
+
+    layout()
+    {
+        if (this._muted || this.volume < 0)
+            this.iconName = this._usesLTRUserInterfaceLayoutDirection ? Icons.VolumeMuted : Icons.VolumeMutedRTL;
+        else if (this.volume < 0.25)
+            this.iconName = this._usesLTRUserInterfaceLayoutDirection ? Icons.Volume0 : Icons.Volume0RTL;
+        else if (this.volume < 0.5)
+            this.iconName = this._usesLTRUserInterfaceLayoutDirection ? Icons.Volume1 : Icons.Volume1RTL;
+        else if (this.volume < 0.75)
+            this.iconName = this._usesLTRUserInterfaceLayoutDirection ? Icons.Volume2 : Icons.Volume2RTL;
+        else
+            this.iconName = this._usesLTRUserInterfaceLayoutDirection ? Icons.Volume3 : Icons.Volume3RTL;
+    }
+}

Modified: trunk/Source/WebCore/Modules/modern-media-controls/js-files (282970 => 282971)


--- trunk/Source/WebCore/Modules/modern-media-controls/js-files	2021-09-23 17:41:22 UTC (rev 282970)
+++ trunk/Source/WebCore/Modules/modern-media-controls/js-files	2021-09-23 17:44:47 UTC (rev 282971)
@@ -24,6 +24,8 @@
 controls/rewind-button.js
 controls/forward-button.js
 controls/overflow-button.js
+controls/range-button.js
+controls/volume-button.js
 controls/buttons-container.js
 controls/status-label.js
 controls/controls-bar.js
@@ -48,6 +50,7 @@
 media/audio-support.js
 media/controls-visibility-support.js
 media/fullscreen-support.js
+media/mute-and-volume-support.js
 media/mute-support.js
 media/overflow-support.js
 media/pip-support.js

Modified: trunk/Source/WebCore/Modules/modern-media-controls/media/media-controller.js (282970 => 282971)


--- trunk/Source/WebCore/Modules/modern-media-controls/media/media-controller.js	2021-09-23 17:41:22 UTC (rev 282970)
+++ trunk/Source/WebCore/Modules/modern-media-controls/media/media-controller.js	2021-09-23 17:44:47 UTC (rev 282971)
@@ -213,7 +213,14 @@
         if (overridenSupportingObjectClasses)
             return overridenSupportingObjectClasses;
 
-        return [AirplaySupport, AudioSupport, ControlsVisibilitySupport, FullscreenSupport, MuteSupport, OverflowSupport, PiPSupport, PlacardSupport, PlaybackSupport, ScrubbingSupport, SeekBackwardSupport, SeekForwardSupport, SkipBackSupport, SkipForwardSupport, StartSupport, StatusSupport, TimeControlSupport, TracksSupport, VolumeSupport];
+        let classes = [AirplaySupport, AudioSupport, ControlsVisibilitySupport, FullscreenSupport, OverflowSupport, PiPSupport, PlacardSupport, PlaybackSupport, ScrubbingSupport, SeekBackwardSupport, SeekForwardSupport, SkipBackSupport, SkipForwardSupport, StartSupport, StatusSupport, TimeControlSupport, TracksSupport]
+
+        if (this.controls.usesSingleMuteAndVolumeButton)
+            classes.push(MuteAndVolumeSupport);
+        else
+            classes.push(MuteSupport, VolumeSupport);
+
+        return classes;
     }
 
     _updateControlsIfNeeded()

Added: trunk/Source/WebCore/Modules/modern-media-controls/media/mute-and-volume-support.js (0 => 282971)


--- trunk/Source/WebCore/Modules/modern-media-controls/media/mute-and-volume-support.js	                        (rev 0)
+++ trunk/Source/WebCore/Modules/modern-media-controls/media/mute-and-volume-support.js	2021-09-23 17:44:47 UTC (rev 282971)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+class MuteAndVolumeSupport extends MediaControllerSupport
+{
+
+    // Protected
+
+    get control()
+    {
+        return this.mediaController.controls.volumeButton;
+    }
+
+    get mediaEvents()
+    {
+        return ["volumechange"];
+    }
+
+    controlValueWillStartChanging(control)
+    {
+        this._volumeBeforeChange = this.mediaController.media.volume;
+        this.mediaController.controls.autoHideController.hasSecondaryUIAttached = true;
+    }
+
+    controlValueDidChange(control)
+    {
+        this.mediaController.media.volume = (control.value === 0 && this._volumeBeforeChange > 0) ? this._volumeBeforeChange : control.value;
+        this.mediaController.media.muted = control.value === 0;
+    }
+
+    controlValueDidStopChanging(control)
+    {
+        delete this._volumeBeforeChange;
+        this.mediaController.controls.autoHideController.hasSecondaryUIAttached = false;
+    }
+
+    buttonWasPressed(control)
+    {
+        const media = this.mediaController.media;
+        media.muted = !media.muted;
+    }
+
+    syncControl()
+    {
+        const media = this.mediaController.media;
+        this.control.volume = this.mediaController.media.volume;
+        this.control.muted = this.mediaController.media.muted;
+    }
+
+}

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (282970 => 282971)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-09-23 17:41:22 UTC (rev 282970)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-09-23 17:44:47 UTC (rev 282971)
@@ -10353,6 +10353,9 @@
 		715AD71D2050512400D592DC /* DeclarativeAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeclarativeAnimation.h; sourceTree = "<group>"; };
 		715AD71F2050512400D592DC /* DeclarativeAnimation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeclarativeAnimation.cpp; sourceTree = "<group>"; };
 		715DA5D3201BB902002EF2B0 /* JSWebAnimationCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebAnimationCustom.cpp; sourceTree = "<group>"; };
+		716A55AB26FA349B00C96D69 /* range-button.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = "range-button.css"; sourceTree = "<group>"; };
+		716A55AD26FA349C00C96D69 /* volume-button.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode._javascript_; path = "volume-button.js"; sourceTree = "<group>"; };
+		716A55AE26FA349C00C96D69 /* range-button.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode._javascript_; path = "range-button.js"; sourceTree = "<group>"; };
 		716FA0D81DB26591007323CC /* airplay-button.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = "airplay-button.css"; sourceTree = "<group>"; };
 		716FA0D91DB26591007323CC /* airplay-button.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = "airplay-button.js"; sourceTree = "<group>"; };
 		716FA0DA1DB26591007323CC /* airplay-placard.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = "airplay-placard.js"; sourceTree = "<group>"; };
@@ -10446,6 +10449,8 @@
 		71D6AA931DA4EAF700B23969 /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; };
 		71D6AAAA1DA4EAF700B23969 /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; };
 		71D6AAAB1DA4EAF700B23969 /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; };
+		71D8323126FCD8F600F348A4 /* mute-and-volume-support.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode._javascript_; path = "mute-and-volume-support.js"; sourceTree = "<group>"; };
+		71D8323326FCD8F600F348A4 /* skip-forward-support.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode._javascript_; path = "skip-forward-support.js"; sourceTree = "<group>"; };
 		71DCB6FF1568197600862271 /* JSSVGZoomAndPan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSVGZoomAndPan.cpp; sourceTree = "<group>"; };
 		71DCB7001568197600862271 /* JSSVGZoomAndPan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSVGZoomAndPan.h; sourceTree = "<group>"; };
 		71DE2794203A9C1C0058CB51 /* watchos-media-controls.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = "watchos-media-controls.js"; sourceTree = "<group>"; };
@@ -22834,6 +22839,8 @@
 				716FA0EF1DB26591007323CC /* placard.css */,
 				716FA0F01DB26591007323CC /* placard.js */,
 				716FA0F11DB26591007323CC /* play-pause-button.js */,
+				716A55AB26FA349B00C96D69 /* range-button.css */,
+				716A55AE26FA349C00C96D69 /* range-button.js */,
 				716FA0F21DB26591007323CC /* rewind-button.js */,
 				716FA0F31DB26591007323CC /* scheduler.js */,
 				718675431DF101AD0033D7F3 /* seek-button.js */,
@@ -22848,6 +22855,7 @@
 				716FA0FC1DB26591007323CC /* time-label.css */,
 				716FA0FD1DB26591007323CC /* time-label.js */,
 				716FA0FE1DB26591007323CC /* tracks-button.js */,
+				716A55AD26FA349C00C96D69 /* volume-button.js */,
 				9551958E25FA9E3000F58CF0 /* watchos-activity-indicator.css */,
 				9551958F25FA9E3100F58CF0 /* watchos-activity-indicator.js */,
 				BCD3736F26864203003644E4 /* watchos-layout-traits.js */,
@@ -22868,6 +22876,7 @@
 				7177E2461DB80D2F00919A0B /* media-controller-support.js */,
 				71D02D921DB55C4E00DD5CF5 /* media-controller.js */,
 				9551959225FA9E4C00F58CF0 /* media-document-controller.js */,
+				71D8323126FCD8F600F348A4 /* mute-and-volume-support.js */,
 				7177E2471DB80D2F00919A0B /* mute-support.js */,
 				950C484925D6774200AB3D9C /* overflow-support.js */,
 				7130141D1DC9C08600CA3A88 /* pip-support.js */,
@@ -22878,6 +22887,7 @@
 				718675451DF101C60033D7F3 /* seek-forward-support.js */,
 				718675461DF101C60033D7F3 /* seek-support.js */,
 				71D2554F1DB900020004D76B /* skip-back-support.js */,
+				71D8323326FCD8F600F348A4 /* skip-forward-support.js */,
 				7177E2481DB80D2F00919A0B /* start-support.js */,
 				71B0460A1DD3C2EE00EE19CF /* status-support.js */,
 				9551959525FA9E7E00F58CF0 /* time-control-support.js */,
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to