155 lines
5.7 KiB
HTML
155 lines
5.7 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<title>LazyBoy desktop</title>
|
|
<style>
|
|
html, body, #screen {
|
|
margin: 0;
|
|
height: 100%;
|
|
width: 100%;
|
|
background: #0f172a;
|
|
overflow: hidden;
|
|
}
|
|
#status {
|
|
display: none;
|
|
}
|
|
#screen canvas { cursor: default; }
|
|
</style>
|
|
<script type="module">
|
|
import RFB from "./core/rfb.js";
|
|
|
|
function query(name) {
|
|
const match = `${document.location.href}${window.location.hash}`.match(
|
|
new RegExp(`[?&#]${name}=([^&#]*)`)
|
|
);
|
|
return match ? decodeURIComponent(match[1]) : null;
|
|
}
|
|
|
|
function flag(name, fallback = false) {
|
|
const raw = query(name);
|
|
if (raw == null) return fallback;
|
|
const value = String(raw).toLowerCase();
|
|
return value === "1" || value === "true" || value === "yes";
|
|
}
|
|
|
|
const statusEl = document.getElementById("status");
|
|
const setStatus = (text) => {
|
|
statusEl.textContent = text;
|
|
};
|
|
|
|
const prefix = window.location.pathname.replace(/[^/]+$/, "");
|
|
const protocol = window.location.protocol === "https:" ? "wss" : "ws";
|
|
const path = (query("path") || "websockify").replace(/^\//, "");
|
|
const url = path.includes("/")
|
|
? `${protocol}://${window.location.host}/${path}`
|
|
: `${protocol}://${window.location.host}${prefix}${path}`;
|
|
|
|
let rfb = null;
|
|
let reconnectTimer = null;
|
|
const parentOrigin = window.location.origin;
|
|
|
|
function pasteIntoDesktop(text) {
|
|
if (!rfb || rfb.viewOnly || !text) return;
|
|
window.parent.postMessage({type:"lazyboy-paste-text", text}, parentOrigin);
|
|
}
|
|
|
|
function pinTaskbar() {
|
|
// noVNC centers the scaled canvas (margin:auto), leaving a dead
|
|
// strip under the panel. Stick the canvas to the bottom.
|
|
const inner = document.querySelector("#screen > div");
|
|
const canvas = document.querySelector("#screen canvas");
|
|
if (inner) {
|
|
inner.style.alignItems = "flex-end";
|
|
inner.style.justifyContent = "center";
|
|
}
|
|
if (canvas) {
|
|
canvas.style.margin = "0 auto";
|
|
}
|
|
}
|
|
|
|
function applyViewOnly(value) {
|
|
if (!rfb) return;
|
|
rfb.viewOnly = Boolean(value);
|
|
}
|
|
|
|
function connect() {
|
|
setStatus("Connecting to desktop…");
|
|
window.parent.postMessage({ type: "lazyboy-desktop-lost" }, parentOrigin);
|
|
rfb = new RFB(document.getElementById("screen"), url);
|
|
rfb.viewOnly = flag("view_only", true);
|
|
rfb.scaleViewport = true;
|
|
rfb.clipViewport = false;
|
|
rfb.background = "#0f172a";
|
|
pinTaskbar();
|
|
rfb.addEventListener("connect", () => {
|
|
pinTaskbar();
|
|
try { rfb.focus(); } catch (_) {}
|
|
window.parent.postMessage({ type: "lazyboy-desktop-ready" }, parentOrigin);
|
|
});
|
|
rfb.addEventListener("disconnect", (event) => {
|
|
window.parent.postMessage({ type: "lazyboy-desktop-lost" }, parentOrigin);
|
|
const clean = event && event.detail && event.detail.clean;
|
|
setStatus(clean ? "Disconnected — retrying" : "Desktop connection lost — retrying");
|
|
if (reconnectTimer) clearTimeout(reconnectTimer);
|
|
reconnectTimer = setTimeout(connect, 1500);
|
|
});
|
|
rfb.addEventListener("clipboard", (event) => {
|
|
const text = event && event.detail ? event.detail.text : "";
|
|
if (typeof text === "string") {
|
|
window.parent.postMessage({ type: "lazyboy-desktop-clipboard", text }, parentOrigin);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Capture before noVNC forwards the shortcut; otherwise stale remote
|
|
// clipboard contents can be pasted once before the local text arrives.
|
|
window.addEventListener("keydown", async (event) => {
|
|
if (rfb && !rfb.viewOnly && event.metaKey && event.code === "KeyC") {
|
|
event.preventDefault(); event.stopImmediatePropagation();
|
|
window.parent.postMessage({type:"lazyboy-copy-request"},parentOrigin); return;
|
|
}
|
|
if (!rfb || rfb.viewOnly || !(event.ctrlKey || event.metaKey) || event.altKey || event.code !== "KeyV") return;
|
|
event.preventDefault();
|
|
event.stopImmediatePropagation();
|
|
const target = rfb;
|
|
try {
|
|
const text = await navigator.clipboard.readText();
|
|
if (rfb === target && !target.viewOnly) pasteIntoDesktop(text);
|
|
} catch (_) {
|
|
window.parent.postMessage({ type: "lazyboy-paste-request" }, parentOrigin);
|
|
}
|
|
}, true);
|
|
connect();
|
|
window.addEventListener("resize", pinTaskbar);
|
|
window.addEventListener("pointerdown", () => {
|
|
try { if (rfb) rfb.focus(); } catch (_) {}
|
|
if (rfb && rfb.viewOnly) {
|
|
window.parent.postMessage({ type: "lazyboy-request-control" }, parentOrigin);
|
|
}
|
|
});
|
|
window.addEventListener("paste", (event) => {
|
|
if (!rfb || rfb.viewOnly) return;
|
|
const text = event.clipboardData ? event.clipboardData.getData("text") : "";
|
|
if (!text) return;
|
|
event.preventDefault();
|
|
pasteIntoDesktop(text);
|
|
});
|
|
window.addEventListener("message", (event) => {
|
|
if (event.origin !== parentOrigin || event.source !== window.parent) return;
|
|
if (!event.data) return;
|
|
if (event.data.type === "lazyboy-view-only") {
|
|
applyViewOnly(event.data.viewOnly);
|
|
return;
|
|
}
|
|
if (event.data.type !== "lazyboy-host-clipboard") return;
|
|
pasteIntoDesktop(String(event.data.text || ""));
|
|
});
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<div id="status" hidden>Loading desktop…</div>
|
|
<div id="screen"></div>
|
|
</body>
|
|
</html>
|