64 lines
2.2 KiB
TypeScript
64 lines
2.2 KiB
TypeScript
// Thin wrapper over the vendored guacamole-common-js client.
|
|
// The library attaches a global `Guacamole` object when loaded.
|
|
declare const Guacamole: any;
|
|
|
|
export function openConsole(
|
|
container: HTMLElement,
|
|
wsUrl: string,
|
|
connectData = ""
|
|
): { disconnect: () => void; setScale: (scale: number) => void } {
|
|
// Guacamole's WebSocketTunnel builds the socket URL as `wsUrl + "?" + data`,
|
|
// so wsUrl must NOT already contain a query string — pass params via connectData.
|
|
const tunnel = new Guacamole.WebSocketTunnel(wsUrl);
|
|
const client = new Guacamole.Client(tunnel);
|
|
|
|
container.innerHTML = "";
|
|
container.appendChild(client.getDisplay().getElement());
|
|
// Make the console focusable so keyboard capture is scoped to it (see below).
|
|
container.tabIndex = 0;
|
|
|
|
client.connect(connectData);
|
|
|
|
const display = client.getDisplay();
|
|
let scale = 1;
|
|
|
|
// Wire keyboard + mouse. The display element is rendered at `scale` of the
|
|
// remote's native resolution, but Guacamole.Mouse reports coordinates in
|
|
// element (on-screen) pixels. Divide by scale to map back to remote
|
|
// coordinates, otherwise the cursor is offset.
|
|
const mouse = new Guacamole.Mouse(display.getElement());
|
|
mouse.onmousedown = mouse.onmouseup = mouse.onmousemove = (state: any) => {
|
|
const s = new Guacamole.Mouse.State(
|
|
state.x / scale,
|
|
state.y / scale,
|
|
state.left,
|
|
state.middle,
|
|
state.right,
|
|
state.up,
|
|
state.down
|
|
);
|
|
client.sendMouseState(s);
|
|
};
|
|
// Scope keyboard capture to the container rather than `document`, so it only
|
|
// grabs keys while the console is focused and stops entirely once the element
|
|
// is removed (navigating away / disconnect). Attaching to `document` leaks the
|
|
// capture and swallows keystrokes in unrelated inputs.
|
|
const keyboard = new Guacamole.Keyboard(container);
|
|
keyboard.onkeydown = (k: number) => client.sendKeyEvent(1, k);
|
|
keyboard.onkeyup = (k: number) => client.sendKeyEvent(0, k);
|
|
container.focus();
|
|
|
|
return {
|
|
disconnect() {
|
|
keyboard.onkeydown = null;
|
|
keyboard.onkeyup = null;
|
|
if (typeof keyboard.reset === "function") keyboard.reset();
|
|
client.disconnect();
|
|
},
|
|
setScale(s: number) {
|
|
scale = s;
|
|
display.scale(s);
|
|
},
|
|
};
|
|
}
|