summaryrefslogtreecommitdiffstats
path: root/toolkit/themes/shared/pictureinpicture
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /toolkit/themes/shared/pictureinpicture
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/themes/shared/pictureinpicture')
-rw-r--r--toolkit/themes/shared/pictureinpicture/player.css648
-rw-r--r--toolkit/themes/shared/pictureinpicture/texttracks.css74
2 files changed, 722 insertions, 0 deletions
diff --git a/toolkit/themes/shared/pictureinpicture/player.css b/toolkit/themes/shared/pictureinpicture/player.css
new file mode 100644
index 0000000000..a2687f3771
--- /dev/null
+++ b/toolkit/themes/shared/pictureinpicture/player.css
@@ -0,0 +1,648 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+:root {
+ --player-bg-color: #000;
+ --player-control-icon-fill: #fff;
+ --player-control-item-half-width: clamp(calc(16px / 2), calc(10vmax / 2), calc(32px / 2));
+ --player-control-item-height: clamp(16px, 10vmax, 32px);
+ --close-btn-fill-color: #000;
+ --controls-bottom-distance: 15px;
+ --controls-bottom-upper-height: 30px;
+ --scrubber-vertical-margin: 7px;
+ --resize-margin: 5px;
+
+ background-color: var(--player-bg-color);
+ overflow: hidden;
+}
+
+button::-moz-focus-inner {
+ border: 0;
+}
+
+body {
+ margin: 0;
+}
+
+body:fullscreen {
+ -moz-window-dragging: no-drag;
+}
+
+.player-holder {
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ overflow: hidden;
+}
+
+browser {
+ flex: 1;
+}
+
+#controls {
+ height: calc(100% - 2 * var(--resize-margin));
+ left: 0;
+ position: absolute;
+ top: 0;
+ width: calc(100% - 2 * var(--resize-margin));
+ margin: var(--resize-margin);
+ -moz-window-dragging: drag;
+}
+
+#controls button {
+ appearance: none;
+ border: 0;
+ z-index: 1;
+}
+
+#controls button:focus-visible,
+#controls input:focus-visible,
+.switch > input:focus-visible + .slider {
+ outline: 3px solid #0060DF;
+ box-shadow: 1px 2px 5px #000;
+}
+
+/* Styling for background gradient.
+ * Opacity changes are handled separately under .control-item.
+ */
+#controls-bottom-gradient {
+ background: linear-gradient(0deg, #000000 -13.24%, rgba(0, 0, 0, 0) 90.44%);
+ position: absolute;
+ height: calc(var(--controls-bottom-distance) + 2 * var(--resize-margin) + var(--player-control-item-height) + var(--controls-bottom-upper-height) + var(--scrubber-vertical-margin));
+ bottom: 0;
+ width: 100vw;
+ margin: 0 calc(-1 * var(--resize-margin)) calc(-1 * var(--resize-margin)) calc(-1 * var(--resize-margin));
+ pointer-events: none;
+ -moz-window-dragging: drag;
+}
+
+#controls-bottom {
+ position: absolute;
+ bottom: var(--controls-bottom-distance);
+ width: 100%;
+}
+
+.controls-bottom-lower {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ margin: 0 24px;
+}
+
+.start-controls {
+ display: grid;
+ justify-self: start;
+}
+
+.center-controls {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ grid-template-areas: "seekbackward playpause seekforward";
+ justify-self: center;
+ gap: 8px;
+}
+
+.end-controls {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ grid-template-areas: "audio closedcaption fullscreen";
+ justify-self: end;
+ gap: 8px;
+}
+
+.control-item {
+ -moz-window-dragging: no-drag;
+ transition: opacity 160ms linear, fill-opacity 160ms linear;
+ opacity: 0;
+ cursor: pointer;
+}
+
+.control-button {
+ background-color: transparent;
+ border-radius: 4px;
+ /**
+ * Make the button dimensions a square proportional to one
+ * dimension of the window - in this case, the width dimension,
+ * since we suspect most videos are wider than they are tall.
+ */
+ height: var(--player-control-item-height);
+ width: 10vmax;
+ max-width: 32px;
+ min-width: 16px;
+ -moz-context-properties: fill, fill-opacity;
+ fill: var(--player-control-icon-fill);
+ background-position: center;
+ background-size: 60%;
+ background-repeat: no-repeat;
+}
+
+.control-button:hover:enabled {
+ background-color: rgba(255, 255, 255, .25);
+}
+
+#controls:is([keying], [showing]) .control-button:disabled,
+/* Only change opacity on hover events for non-fullscreen mode.
+ * Fullscreen mode uses the `showing` attribute instead. */
+body:not(:fullscreen) #controls:hover .control-button:disabled {
+ /* Set `fill-opacity` to the desired opacity in addition to full `opacity`
+ * to allow having the button's tooltip in full opacity even if the button is disabled. */
+ fill-opacity: 0.4;
+ opacity: 1 !important;
+}
+
+.control-item:focus-visible::after,
+.control-item:hover::after {
+ content: attr(tooltip);
+ display: inline-block;
+ width: max-content;
+ position: relative;
+ padding: .4em .5em;
+ background: #000000;
+ color: #ffffff;
+ border-radius: 4px;
+ pointer-events: none;
+}
+
+/* Since #controls is set to LTR, button tooltips would normally appear
+ * as LTR also for RTL locales. To fix this, set the .control-item's ::after
+ * to RTL based on the root directionality.
+ * Because of that, don't set logical properties for the next set of rules. */
+:root:dir(rtl) .control-item::after {
+ direction: rtl;
+}
+
+/* Set the tooltip position for different playback controls */
+
+.tooltip-under-controls:focus-visible::after,
+.tooltip-under-controls:hover::after {
+ bottom: -3em;
+}
+
+#close:focus-visible::after,
+#close:hover::after,
+#unpip[mac="true"]:focus-visible::after,
+#unpip[mac="true"]:hover::after {
+ float: right;
+ transform: translateX(1em);
+}
+
+#unpip:focus-visible::after,
+#unpip:hover::after,
+#close[mac="true"]:focus-visible::after,
+#close[mac="true"]:hover::after {
+ float: left;
+ transform: translateX(-1em);
+}
+
+.tooltip-over-controls:focus-visible::after,
+.tooltip-over-controls:hover::after {
+ bottom: 3em;
+}
+
+.inline-end-tooltip:focus-visible::after,
+.inline-end-tooltip:hover::after {
+ float: right;
+ right: -1em;
+}
+
+.inline-start-tooltip:focus-visible::after,
+.inline-start-tooltip:hover::after {
+ float: left;
+ left: -1em;
+}
+
+.center-tooltip:focus-visible::after,
+.center-tooltip:hover::after {
+ right: 0.8em;
+ translate: calc(-50% + var(--player-control-item-half-width));
+}
+
+/* Since the unpip button icon is reversed for RTL locales,
+ * re-position the tooltip so that the tooltip remains in the original placement */
+:root:dir(rtl) #unpip:focus-visible::after,
+:root:dir(rtl) #unpip:hover::after {
+ float: right;
+}
+
+:root:dir(rtl) #unpip[mac="true"]:focus-visible::after,
+:root:dir(rtl) #unpip[mac="true"]:hover::after {
+ float: left;
+}
+
+/* Since the unpip icon is reversed for RTL locales,
+ * flip its tooltip back */
+:root:dir(rtl) #unpip:focus-visible::after,
+:root:dir(rtl) #unpip:hover::after {
+ scale: -1 1;
+}
+
+/* Set opacity for buttons and scrubber when controls are visible on the pip window and are not hovered over.
+ * For fullscreen mode, only apply opacity if there is a showing attribute. */
+body:not(:fullscreen) #controls:hover .control-item:not(:hover),
+body:fullscreen #controls[showing]:hover .control-item:not(:hover),
+#controls[donthide] .control-item {
+ opacity: 0.8;
+}
+
+#controls[keying] .control-item,
+#controls[showing] .control-item,
+#controls:hover .control-item:hover {
+ opacity: 1;
+}
+
+/* Background gradient is the only control item with a fixed opacity value. */
+#controls[keying] .control-item#controls-bottom-gradient,
+#controls[showing] .control-item#controls-bottom-gradient,
+#controls:hover .control-item#controls-bottom-gradient:hover
+#controls[donthide] .control-item#controls-bottom-gradient {
+ opacity: 0.8;
+}
+
+/* For readability, timestamp should maintain full opacity when visible */
+body:not(:fullscreen) #controls:hover #timestamp,
+body:fullscreen #controls[showing]:hover {
+ opacity: 1;
+}
+
+#close,
+#unpip {
+ background-color: rgba(255, 255, 255, .8);
+ position: absolute;
+ fill: var(--close-btn-fill-color);
+}
+
+#close:is(:hover, :focus-visible),
+#unpip:is(:hover, :focus-visible) {
+ background-color: rgba(255, 255, 255, .9);
+}
+
+#close {
+ background-image: url("chrome://global/skin/icons/close.svg");
+ right: 10px;
+ top: 10px;
+}
+
+#close[mac="true"] {
+ right: auto;
+ left: 10px;
+}
+
+#unpip {
+ background-image: url("chrome://global/skin/media/picture-in-picture-closed.svg");
+ left: 10px;
+ top: 10px;
+}
+
+#unpip[mac="true"] {
+ right: 10px;
+ left: auto;
+}
+
+#playpause {
+ grid-area: playpause;
+}
+
+#audio {
+ grid-area: audio;
+}
+
+#fullscreen {
+ grid-area: fullscreen;
+}
+
+#controls.playing #playpause {
+ background-image: url("chrome://global/skin/media/pause-fill.svg");
+}
+
+#controls:not(.playing) #playpause {
+ background-image: url("chrome://global/skin/media/play-fill.svg");
+}
+
+#controls.muted #audio {
+ background-image: url("chrome://global/skin/media/audio-muted.svg");
+}
+
+#controls:not(.muted) #audio {
+ background-image: url("chrome://global/skin/media/audio.svg");
+}
+
+body:fullscreen #fullscreen {
+ background-image: url("chrome://global/skin/media/picture-in-picture-exit-fullscreen-button.svg");
+ background-size: auto;
+}
+
+body:not(:fullscreen) #fullscreen {
+ background-image: url("chrome://global/skin/media/picture-in-picture-enter-fullscreen-button.svg");
+ background-size: auto;
+}
+
+#seekBackward {
+ background-image: url("chrome://global/skin/media/picture-in-picture-seekBackward-button.svg");
+ background-size: auto;
+ grid-area: seekbackward;
+}
+
+#seekForward {
+ background-image: url("chrome://global/skin/media/picture-in-picture-seekForward-button.svg");
+ background-size: auto;
+ grid-area: seekforward;
+}
+
+:root:dir(rtl) #unpip {
+ transform: scaleX(-1);
+}
+
+#closed-caption {
+ background-image: url("chrome://global/skin/media/closed-caption-settings-button.svg");
+ color: white;
+ grid-area: closedcaption;
+}
+
+.box {
+ -moz-window-dragging: no-drag;
+ background-color: #2B2A33;
+ text-align: start;
+ font-size: 1em;
+ width: 186px;
+ padding: 0 8px;
+ margin: 0;
+ border-radius: 8px;
+}
+
+:root:dir(rtl) .box {
+ direction: rtl;
+}
+
+.a11y-only {
+ visibility: hidden;
+ position: absolute;
+}
+
+.hide {
+ display: none;
+}
+
+.bold {
+ font-weight: 590;
+}
+
+.box > input[type="radio"]{
+ background-color: red;
+ fill: currentColor;
+}
+
+.box label:not(.switch) {
+ color: white;
+ font-family: sans-serif;
+}
+
+#subtitles-toggle-label {
+ width: fit-content;
+ padding: 8px;
+}
+
+.panel {
+ position: absolute;
+ bottom: 40px;
+ user-select: none;
+ right: 24px;
+}
+
+.panel-fieldset {
+ border: none;
+ margin-top: 8px;
+ padding-inline-start: 0;
+}
+
+.panel-legend {
+ font-family: sans-serif;
+ color: white;
+ margin-top: 8px;
+ padding-inline-start: 0;
+}
+
+.arrow {
+ border: 10px solid transparent;
+ border-top-color: #2B2A33;
+ width: 0;
+ height: 0;
+ inset-inline-start: 136px;
+ position: relative;
+}
+
+.grey-line {
+ width: 100%;
+ height: 1px;
+ background: #8F8F9D;
+}
+
+.font-size-selection {
+ margin-inline-start: 8px;
+ padding-inline-start: 8px;
+}
+
+.font-size-selection-radio {
+ display: flex;
+ width: fit-content;
+ cursor: pointer;
+ padding-block: 8px;
+}
+
+.font-size-selection-radio label {
+ cursor: pointer;
+}
+
+.font-size-selection-radio > input[type="radio"] {
+ appearance: none;
+ width: 16px;
+ height: 16px;
+ border: 1px solid #8f8f9d;
+ border-radius: 50%;
+ margin: 0;
+ margin-inline-end: 6px;
+}
+
+.font-size-selection-radio > input[type="radio"]:checked {
+ border: 4px solid #00ddff;
+}
+
+.subtitle-grid {
+ display: grid;
+ grid-template-rows: auto;
+ grid-template-columns: auto 46px;
+ padding: 8px;
+}
+
+.switch {
+ position: relative;
+ display: inline-block;
+ width: 32px;
+ height: 16px;
+ grid-column: 2;
+ margin: 8px;
+ cursor: pointer;
+}
+
+.switch input {
+ opacity: 0;
+ width: 0;
+ height: 0;
+}
+
+.slider {
+ position: absolute;
+ inset: 0;
+ transition: transform 250ms;
+ border-radius: 13px;
+ background-color: #55545f;
+}
+
+.slider::before {
+ position: absolute;
+ content: '';
+ height: 12px;
+ width: 12px;
+ inset-inline-start: 2px;
+ bottom: 2px;
+ background-color: #2B2A33;
+ transition: transform 250ms;
+ border-radius: 50%;
+}
+
+input:checked + .slider {
+ background-color: #00ddff;
+}
+
+input:checked + .slider::before {
+ transform: translateX(16px);
+}
+
+:root:dir(rtl) input:checked + .slider::before {
+ transform: translateX(-16px);
+}
+
+.font-size-overlay {
+ opacity: 0.4;
+ pointer-events: none;
+}
+
+.controls-bottom-upper {
+ width: calc(100% - 38px);
+ height: var(--controls-bottom-upper-height);
+ margin: 0 19px;
+ display: grid;
+}
+
+.scrubber-no-drag {
+ -moz-window-dragging: no-drag;
+ height: 16px;
+ margin: var(--scrubber-vertical-margin) 0;
+ display: grid;
+ justify-items: center;
+ align-items: center;
+ width: 100%;
+}
+
+#scrubber {
+ width: 100%;
+ background-color: transparent;
+ padding: 6px;
+}
+
+#scrubber::-moz-range-thumb {
+ border-radius: 14px;
+ background-color: #BFBFC9;
+ position: relative;
+ width: 8px;
+ height: 8px;
+ border: 3px solid #FFFFFF;
+ bottom: 24px;
+ padding: 0;
+}
+
+#scrubber::-moz-range-track {
+ background-color: #969696;
+}
+
+#scrubber::-moz-range-progress {
+ background-color: #FFFFFF;
+}
+
+#scrubber,
+#scrubber::-moz-range-track,
+#scrubber::-moz-range-progress {
+ height: 4px;
+ border-radius: 10px;
+}
+
+#timestamp {
+ align-self: center;
+ color: #FFFFFF;
+ cursor: default;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Ubuntu", "Helvetica Neue", sans-serif;
+ font-size: 0.9em;
+ user-select: none;
+ width: 16ch;
+ grid-area: timestamp;
+}
+
+#timestamp::after {
+ background: unset;
+ content: unset;
+}
+
+@media (height <= 325px), (width <= 475px) {
+ #closed-caption {
+ display: none;
+ }
+
+ .end-controls {
+ grid-template-columns: repeat(2, 1fr);
+ grid-template-areas: "audio fullscreen";
+ }
+}
+
+@media (width <= 440px) {
+ #timestamp {
+ display: none;
+ }
+}
+
+@media (width <= 350px) {
+ #fullscreen {
+ display: none;
+ }
+
+ .end-controls {
+ grid-template-columns: repeat(1, 1fr);
+ grid-template-areas: "audio";
+ }
+}
+
+@media (height <= 200px) {
+ .scrubber-no-drag {
+ display: none;
+ }
+}
+
+@media (width <= 300px) {
+ .scrubber-no-drag,
+ #seekForward,
+ #seekBackward,
+ .start-controls {
+ display: none;
+ }
+
+ .controls-bottom-lower {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ .center-controls {
+ grid-template-columns: repeat(1, 1fr);
+ grid-template-areas: "playpause";
+ }
+
+ .end-controls {
+ justify-self: center;
+ }
+}
diff --git a/toolkit/themes/shared/pictureinpicture/texttracks.css b/toolkit/themes/shared/pictureinpicture/texttracks.css
new file mode 100644
index 0000000000..ec7af4a7b4
--- /dev/null
+++ b/toolkit/themes/shared/pictureinpicture/texttracks.css
@@ -0,0 +1,74 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+:root {
+ --min-font-size: 14px;
+ --max-font-size: 40px;
+ --font-scale: 0.06;
+ --texttracks-bottom: calc(var(--font-scale) * 100vh);
+
+ /*
+ * Move text tracks if they visually overlap with pip player controls
+ * New text tracks position is determined by adding together:
+ * 1) bottom distance of #controls
+ * 2) height of #controls-bottom,
+ * 3) border size of player controls buttons
+ * 4) hardcoded px value (to ensure consistent distance, regardless of pip window size)
+ * NOTE: if changing player.css values, change values here too.
+ */
+ --resize-margin: 5px;
+ --player-controls-height: calc(100vh - 2 * var(--resize-margin));
+ --player-controls-bottom-distance: calc(100vh - var(--player-controls-height));
+ --player-controls-button-height: 10vmax;
+ --player-controls-button-max-height: 32px;
+ --player-controls-button-min-height: 16px;
+ --player-controls-button-outline-width: 2px;
+ --player-controls-scrubber-height: 0px;
+ --player-bottom-controls-height: calc(var(--player-controls-scrubber-height) + clamp(var(--player-controls-button-min-height), var(--player-controls-button-height), var(--player-controls-button-max-height)));
+ --distance-from-player-controls: 20px;
+ --texttracks-bottom-overlapped: calc(var(--player-controls-button-outline-width) + var(--player-controls-bottom-distance) + var(--player-bottom-controls-height) + var(--distance-from-player-controls));
+}
+
+#texttracks {
+ background-color: black;
+ opacity: 80%;
+ position: absolute;
+ text-align: center;
+ box-sizing: border-box;
+ color: white;
+ margin: 0;
+ display: block;
+ left: 50%;
+ transform: translateX(-50%);
+ padding: 8px;
+ max-width: calc(0.88 * 100vw);
+ bottom: var(--texttracks-bottom);
+ font-size: clamp(var(--min-font-size), calc(var(--font-scale) * 100vh), var(--max-font-size));
+ line-height: clamp(14.4px, calc(var(--font-scale) * 1.2 * 100vh), 48px);
+ white-space: pre-line;
+ width: max-content;
+ font-family: sans-serif;
+ transition: bottom 0.3s;
+ transition-delay: 0.1s;
+}
+
+#texttracks[overlap-video-controls] {
+ bottom: var(--texttracks-bottom-overlapped)
+}
+
+#texttracks:empty {
+ visibility: hidden;
+}
+
+@media (prefers-reduced-motion) {
+ #texttracks {
+ transition: none;
+ }
+}
+
+@media screen and (max-width: 319px) {
+ #texttracks {
+ display: none;
+ }
+}