mirror of
https://github.com/SoPat712/Speeder.git
synced 2026-08-19 11:52:31 -04:00
fix(controller): restore fullscreen overlay visibility
This commit is contained in:
@@ -4,7 +4,7 @@ Constraints: local commits only; no push; no browser testing; one commit per fea
|
||||
|
||||
## Controller and targeting
|
||||
|
||||
- [ ] Keep the controller visible for its own video in element and ancestor fullscreen.
|
||||
- [x] Keep the controller visible for its own video in element and ancestor fullscreen.
|
||||
- [ ] Target popup actions at the frame represented by the displayed speed; keep “all videos” intentional.
|
||||
- [ ] Ignore shortcuts originating from editable controls, including shadow-DOM inputs.
|
||||
|
||||
|
||||
@@ -3196,12 +3196,13 @@ function syncControllerFullscreenMount(videoController) {
|
||||
var doc = video.ownerDocument;
|
||||
var fullscreenElement = getFullscreenElement(doc);
|
||||
var targetMount = videoController.normalControllerMount;
|
||||
|
||||
if (
|
||||
var ownsFullscreen = Boolean(
|
||||
fullscreenElement &&
|
||||
(fullscreenElement === video ||
|
||||
isComposedDescendant(video, fullscreenElement))
|
||||
) {
|
||||
(fullscreenElement === video ||
|
||||
isComposedDescendant(video, fullscreenElement))
|
||||
);
|
||||
|
||||
if (ownsFullscreen) {
|
||||
targetMount = getControllerMount(video, fullscreenElement);
|
||||
} else if (!fullscreenElement && (!targetMount || !targetMount.isConnected)) {
|
||||
targetMount = getControllerMount(video);
|
||||
@@ -3210,7 +3211,7 @@ function syncControllerFullscreenMount(videoController) {
|
||||
|
||||
if (!targetMount) return false;
|
||||
|
||||
if (fullscreenElement) {
|
||||
if (ownsFullscreen) {
|
||||
// Fullscreen elements and popovers both participate in the browser's top
|
||||
// layer. Showing Speeder's host after the player enters fullscreen keeps it
|
||||
// above provider-owned surfaces even when the provider clips descendants or
|
||||
|
||||
@@ -10,6 +10,24 @@
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
/* Important declarations inside a shadow tree outrank important page styles.
|
||||
Repeat the top-layer positioning here so fullscreen cannot fall back to the
|
||||
base absolute host rule. */
|
||||
:host(.vsc-fullscreen-popover) {
|
||||
position: fixed !important;
|
||||
inset: auto !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
border: 0 !important;
|
||||
background: transparent !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
:host(.vsc-fullscreen-popover)::backdrop {
|
||||
pointer-events: none !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
:host(.vsc-nosource),
|
||||
:host(.vsc-hidden) {
|
||||
display: none !important;
|
||||
|
||||
@@ -612,6 +612,42 @@ describe("inject.js media/controller lifecycle regressions", () => {
|
||||
controller.controllerHostCleanup();
|
||||
});
|
||||
|
||||
it("only promotes the controller owned by the fullscreen player", async () => {
|
||||
bootInject();
|
||||
await settleLifecycle();
|
||||
|
||||
const fullscreenPlayer = document.createElement("div");
|
||||
const fullscreenVideo = document.createElement("video");
|
||||
const otherVideo = document.createElement("video");
|
||||
const rect = makeRect(0, 0, 640, 360);
|
||||
|
||||
fullscreenVideo.src = "https://example.org/fullscreen.mp4";
|
||||
otherVideo.src = "https://example.org/other.mp4";
|
||||
fullscreenPlayer.appendChild(fullscreenVideo);
|
||||
document.body.append(fullscreenPlayer, otherVideo);
|
||||
[fullscreenPlayer, fullscreenVideo, otherVideo].forEach((element) => {
|
||||
setRect(element, rect);
|
||||
setBoxMetrics(element, rect.width, rect.height);
|
||||
});
|
||||
window.ensureController(fullscreenVideo, fullscreenPlayer);
|
||||
window.ensureController(otherVideo, document.body);
|
||||
fullscreenVideo.vsc.div.showPopover = vi.fn();
|
||||
otherVideo.vsc.div.showPopover = vi.fn();
|
||||
|
||||
Object.defineProperty(document, "fullscreenElement", {
|
||||
configurable: true,
|
||||
value: fullscreenPlayer
|
||||
});
|
||||
window.syncControllerFullscreenMount(fullscreenVideo.vsc);
|
||||
window.syncControllerFullscreenMount(otherVideo.vsc);
|
||||
|
||||
expect(fullscreenVideo.vsc.div.showPopover).toHaveBeenCalledOnce();
|
||||
expect(otherVideo.vsc.div.showPopover).not.toHaveBeenCalled();
|
||||
expect(
|
||||
otherVideo.vsc.div.classList.contains("vsc-fullscreen-popover")
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("preserves direct-video requestFullscreen semantics and overlays with a popover", async () => {
|
||||
bootInject();
|
||||
await settleLifecycle();
|
||||
|
||||
Reference in New Issue
Block a user