From 7e54e84631debb72a67871a19794eaf37fe29b36 Mon Sep 17 00:00:00 2001 From: Christopher Serr Date: Sat, 12 Apr 2025 23:38:59 +0200 Subject: [PATCH] Use Document Picture-in-Picture API if Available (#1047) Chrome supports the [Document Picture-in-Picture API](https://developer.chrome.com/blog/the-future-of-picture-in-picture/), which allows us to create a popup window that is always on top, has a "return to tab" button, remembers its position and size, and has a more compact title bar. Considering not every browser supports this API, we automatically fall back to `window.open` if the API is not available. --- src/ui/LiveSplit.tsx | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/ui/LiveSplit.tsx b/src/ui/LiveSplit.tsx index 8c9d72a..2ff9fcc 100644 --- a/src/ui/LiveSplit.tsx +++ b/src/ui/LiveSplit.tsx @@ -1092,6 +1092,33 @@ export class LiveSplit extends React.Component { } } +async function openPopupWindow( + width: number, + height: number, +): Promise { + try { + const pipPromise = ( + window as any + ).documentPictureInPicture?.requestWindow({ + width, + height, + }); + + if (pipPromise) { + return (await pipPromise) as Window; + } + } catch { + // It's fine if it fails, as not all browsers support this. + } + + const childWindow = window.open( + "", + "_blank", + `popup,width=${width},height=${height}`, + ); + return childWindow; +} + async function popOut( commandSink: LSOCommandSink, getLayout: () => LayoutRefMut, @@ -1099,11 +1126,7 @@ async function popOut( width: number, height: number, ) { - const childWindow = window.open( - "", - "_blank", - `popup,width=${width},height=${height}`, - ); + const childWindow = await openPopupWindow(width, height); if (!childWindow) { return; } @@ -1165,8 +1188,8 @@ async function popOut( }} layoutUrlCache={urlCache} allowResize={false} - width="100%" - height="100%" + width="100vw" + height="100vh" generalSettings={generalSettings} renderer={renderer} onResize={(width, height) =>