cloud-game/web/js/screen.js
2026-06-09 23:54:02 +03:00

88 lines
2.3 KiB
JavaScript

import { sub, SETTINGS_CHANGED, REFRESH_INPUT } from "event";
import { env } from "env";
import { input, pointer, keyboard } from "input";
import { opts, settings } from "settings";
import { gui } from "gui";
const rootEl = document.getElementById("screen");
const footerEl = document.getElementsByClassName("screen__footer")[0];
const state = {
components: [],
current: undefined,
forceFullscreen: false,
};
const toggle = async (component, force) => {
if (component) {
state.current = component;
} // keep the last component
state.components.forEach((c) => c.toggle(false));
state.current?.toggle(force);
if (state.forceFullscreen) {
fullscreen(true);
}
};
const init = () => {
state.forceFullscreen = settings.loadOr(opts.FORCE_FULLSCREEN, false);
sub(SETTINGS_CHANGED, () => {
state.forceFullscreen = settings.get()[opts.FORCE_FULLSCREEN];
});
};
const cursor = pointer.autoHide(rootEl, 2000);
const trackPointer = pointer.track(rootEl, () => {
const display = state.current;
return { ...display.video.size, s: !!display?.hasDisplay };
});
const fullscreen = () => {
if (state.current?.noFullscreen) return;
let h = parseFloat(getComputedStyle(rootEl, null).height.replace("px", ""));
env.display().toggleFullscreen(h !== window.innerHeight, rootEl);
};
const controls = async (locked = false) => {
if (!state.current?.hasDisplay) return;
if (env.isMobileDevice) return;
if (!input.kbm) return;
if (locked) {
await pointer.lock(rootEl);
}
// oof, remove hover:hover when the pointer is forcibly locked,
// leaving the element in the hovered state
footerEl.classList.toggle("hover", !locked);
trackPointer(locked);
await keyboard.lock(locked);
input.retropad.toggle(!locked);
};
rootEl.addEventListener("fullscreenchange", async () => {
const fs = document.fullscreenElement !== null;
cursor(!fs);
gui.toggle(footerEl, fs);
await controls(fs);
state.current?.onFullscreen?.(fs);
});
sub(REFRESH_INPUT, async () => {
await controls(document.fullscreenElement !== null);
});
export const screen = {
fullscreen,
toggle,
/**
* Adds a component. It should have toggle(bool) method and
* an optional noFullscreen (bool) property.
*/
add: (...o) => state.components.push(...o),
init,
};