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 */,