cloud-game/web/js/screen.js
Sergey Stepanov 7ee98c1b03 Add keyboard and mouse support
Keyboard and mouse controls will now work if you use the kbMouseSupport parameter in the config for Libretro cores. Be aware that capturing mouse and keyboard controls properly is only possible in fullscreen mode.

Note: In the case of DOSBox, a virtual filesystem handler is not yet implemented, thus each game state will be shared between all rooms (DOS game instances) of CloudRetro.
2024-08-02 11:04:44 +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) => {
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,
}