81 lines
3.0 KiB
JavaScript
81 lines
3.0 KiB
JavaScript
/*
|
|
* RDP-Session-Client: guacamole-common-js <-> /ws/rdp/{host_id}.
|
|
*
|
|
* Vollbild: native Browser-Fullscreen-API (Konzept 4.3).
|
|
* Copy & Paste: bidirektionale Synchronisation ueber Guacamole.Client
|
|
* onclipboard-Event (Ziel -> Browser) und den `paste`-Browser-Event
|
|
* (Browser -> Ziel, sendet eine "clipboard"-Instruktion). Wird serverseitig
|
|
* zusaetzlich blockiert, wenn fuer den Host clipboard_enabled=false ist
|
|
* (siehe app/rdp_proxy/ws_tunnel.py) -- das UI blendet den Hinweis dann ein.
|
|
*/
|
|
(() => {
|
|
"use strict";
|
|
|
|
const shell = document.getElementById("session-shell");
|
|
const hostId = shell.dataset.hostId;
|
|
const statusEl = document.getElementById("status");
|
|
const displayDiv = document.getElementById("rdp-display");
|
|
|
|
const proto = window.location.protocol === "https:" ? "wss:" : "ws:";
|
|
const width = Math.round(window.innerWidth);
|
|
const height = Math.round(window.innerHeight - 40);
|
|
const dpi = Math.round(window.devicePixelRatio * 96) || 96;
|
|
|
|
const tunnelUrl = `${proto}//${window.location.host}/ws/rdp/${hostId}?width=${width}&height=${height}&dpi=${dpi}`;
|
|
const tunnel = new Guacamole.WebSocketTunnel(tunnelUrl);
|
|
const client = new Guacamole.Client(tunnel);
|
|
|
|
displayDiv.appendChild(client.getDisplay().getElement());
|
|
|
|
client.onstatechange = (state) => {
|
|
// 0=idle,1=connecting,2=waiting,3=connected,4=disconnecting,5=disconnected
|
|
const labels = ["Idle", "Verbinde ...", "Warte auf Server ...", "Verbunden", "Trenne ...", "Getrennt"];
|
|
statusEl.textContent = labels[state] || `Status ${state}`;
|
|
};
|
|
client.onerror = (err) => {
|
|
statusEl.textContent = "Fehler: " + (err.message || "unbekannt");
|
|
};
|
|
|
|
client.onclipboard = (stream, mimetype) => {
|
|
if (!mimetype.startsWith("text/")) return;
|
|
const reader = new Guacamole.StringReader(stream);
|
|
let data = "";
|
|
reader.ontext = (text) => { data += text; };
|
|
reader.onend = () => {
|
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
navigator.clipboard.writeText(data).catch(() => {});
|
|
}
|
|
};
|
|
};
|
|
|
|
client.connect();
|
|
|
|
window.addEventListener("beforeunload", () => client.disconnect());
|
|
|
|
const mouse = new Guacamole.Mouse(client.getDisplay().getElement());
|
|
mouse.onmousedown = mouse.onmouseup = mouse.onmousemove = (mouseState) => {
|
|
client.sendMouseState(mouseState);
|
|
};
|
|
|
|
const keyboard = new Guacamole.Keyboard(document);
|
|
keyboard.onkeydown = (keysym) => client.sendKeyEvent(1, keysym);
|
|
keyboard.onkeyup = (keysym) => client.sendKeyEvent(0, keysym);
|
|
|
|
document.addEventListener("paste", (ev) => {
|
|
const text = (ev.clipboardData || window.clipboardData).getData("text");
|
|
if (!text) return;
|
|
const stream = client.createClipboardStream("text/plain");
|
|
const writer = new Guacamole.StringWriter(stream);
|
|
writer.sendText(text);
|
|
writer.sendEnd();
|
|
});
|
|
|
|
document.getElementById("fullscreen-btn").addEventListener("click", () => {
|
|
if (!document.fullscreenElement) {
|
|
shell.requestFullscreen().catch(() => {});
|
|
} else {
|
|
document.exitFullscreen();
|
|
}
|
|
});
|
|
})();
|