mirror of
https://github.com/giongto35/cloud-game.git
synced 2026-01-23 10:35:44 +00:00
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.
153 lines
3.4 KiB
JavaScript
153 lines
3.4 KiB
JavaScript
// Pointer (aka mouse) stuff
|
|
import {
|
|
MOUSE_PRESSED,
|
|
MOUSE_MOVED,
|
|
pub
|
|
} from 'event';
|
|
import {browser, env} from 'env';
|
|
|
|
const hasRawPointer = 'onpointerrawupdate' in window
|
|
|
|
const p = {dx: 0, dy: 0}
|
|
|
|
const move = (e, cb, single = false) => {
|
|
// !to fix ff https://github.com/w3c/pointerlock/issues/42
|
|
if (single) {
|
|
p.dx = e.movementX
|
|
p.dy = e.movementY
|
|
cb(p)
|
|
} else {
|
|
const _events = e.getCoalescedEvents?.()
|
|
if (_events && (hasRawPointer || _events.length > 1)) {
|
|
for (let i = 0; i < _events.length; i++) {
|
|
p.dx = _events[i].movementX
|
|
p.dy = _events[i].movementY
|
|
cb(p)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const _track = (el, cb, single) => {
|
|
const _move = (e) => {
|
|
move(e, cb, single)
|
|
}
|
|
el.addEventListener(hasRawPointer ? 'pointerrawupdate' : 'pointermove', _move)
|
|
return () => {
|
|
el.removeEventListener(hasRawPointer ? 'pointerrawupdate' : 'pointermove', _move)
|
|
}
|
|
}
|
|
|
|
const dpiScaler = () => {
|
|
let ex = 0
|
|
let ey = 0
|
|
let scaled = {dx: 0, dy: 0}
|
|
return {
|
|
scale(x, y, src_w, src_h, dst_w, dst_h) {
|
|
scaled.dx = x / (src_w / dst_w) + ex
|
|
scaled.dy = y / (src_h / dst_h) + ey
|
|
|
|
ex = scaled.dx % 1
|
|
ey = scaled.dy % 1
|
|
|
|
scaled.dx -= ex
|
|
scaled.dy -= ey
|
|
|
|
return scaled
|
|
}
|
|
}
|
|
}
|
|
|
|
const dpi = dpiScaler()
|
|
|
|
const handlePointerMove = (el, cb) => {
|
|
let w, h = 0
|
|
let s = false
|
|
const dw = 640, dh = 480
|
|
return (p) => {
|
|
({w, h, s} = cb())
|
|
pub(MOUSE_MOVED, s ? dpi.scale(p.dx, p.dy, w, h, dw, dh) : p)
|
|
}
|
|
}
|
|
|
|
const trackPointer = (el, cb) => {
|
|
let mpu, mpd
|
|
let noTrack
|
|
|
|
// disable coalesced mouse move events
|
|
const single = true
|
|
|
|
// coalesced event are broken since FF 120
|
|
const isFF = env.getBrowser === browser.firefox
|
|
|
|
const pm = handlePointerMove(el, cb)
|
|
|
|
return (enabled) => {
|
|
if (enabled) {
|
|
!noTrack && (noTrack = _track(el, pm, isFF || single))
|
|
mpu = pointer.handle.up(el)
|
|
mpd = pointer.handle.down(el)
|
|
return
|
|
}
|
|
|
|
mpu?.()
|
|
mpd?.()
|
|
noTrack?.()
|
|
noTrack = null
|
|
}
|
|
}
|
|
|
|
const handleDown = ((b = {b: null, p: true}) => (e) => {
|
|
b.b = e.button
|
|
pub(MOUSE_PRESSED, b)
|
|
})()
|
|
|
|
const handleUp = ((b = {b: null, p: false}) => (e) => {
|
|
b.b = e.button
|
|
pub(MOUSE_PRESSED, b)
|
|
})()
|
|
|
|
const autoHide = (el, time = 3000) => {
|
|
let tm
|
|
let move
|
|
const cl = el.classList
|
|
|
|
const hide = (force = false) => {
|
|
cl.add('no-pointer')
|
|
!force && el.addEventListener('pointermove', move)
|
|
}
|
|
|
|
move = () => {
|
|
cl.remove('no-pointer')
|
|
clearTimeout(tm)
|
|
tm = setTimeout(hide, time)
|
|
}
|
|
|
|
const show = () => {
|
|
clearTimeout(tm)
|
|
el.removeEventListener('pointermove', move)
|
|
cl.remove('no-pointer')
|
|
}
|
|
|
|
return {
|
|
autoHide: (on) => on ? show() : hide()
|
|
}
|
|
}
|
|
|
|
export const pointer = {
|
|
autoHide,
|
|
lock: async (el) => {
|
|
await el.requestPointerLock(/*{ unadjustedMovement: true}*/)
|
|
},
|
|
track: trackPointer,
|
|
handle: {
|
|
down: (el) => {
|
|
el.onpointerdown = handleDown
|
|
return () => (el.onpointerdown = null)
|
|
},
|
|
up: (el) => {
|
|
el.onpointerup = handleUp
|
|
return () => (el.onpointerup = null)
|
|
}
|
|
}
|
|
}
|