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) => { component && (state.current = component) // keep the last component state.components.forEach(c => c.toggle(false)) state.current?.toggle(force) 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 locked ? footerEl.classList.remove('hover') : footerEl.classList.add('hover') trackPointer(locked) await keyboard.lock(locked) input.retropad.toggle(!locked) } rootEl.addEventListener('fullscreenchange', async () => { const fs = document.fullscreenElement !== null cursor.autoHide(!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, }