UNPKG

@kmamal/sdl

Version:
420 lines (338 loc) 9.82 kB
const Globals = require('../globals') const Bindings = require('../bindings') const { video: videoModule } = require('../video') const { reconcileDisplays } = require('./reconcile-displays') const { keyboard: keyboardModule } = require('../keyboard') const { mapping } = require('../keyboard/key-mapping') const { reconcileAudioDevices } = require('./reconcile-audio-devices') const { reconcileJoystickAndControllerDevices } = require('./reconcile-joystick-and-controller-devices') const { clipboard: clipboardModule } = require('../clipboard') const handleEvent = (event) => { const { family, type } = event if (family === undefined || type === undefined) { return } delete event.family switch (family) { case 'app': { if (type !== 'quit') { return } for (const window of Globals.windows.all.values()) { window.destroyGently() } } break // TODO: this also needs a reconcile function case 'display': { const { displayIndex } = event delete event.displayIndex switch (type) { case 'displayAdd': case 'displayRemove': { const { displays } = event delete event.displays reconcileDisplays(displays) return } case 'displayOrient': { const display = Globals.displays[displayIndex] display.orientation = event.orientation } break case 'displayMove': { const { geometryX, geometryY, usableX, usableY } = event delete event.geometryX delete event.geometryY delete event.usableX delete event.usableY const display = Globals.displays[displayIndex] display.geometry.x = geometryX display.geometry.y = geometryY display.usable.x = usableX display.usable.y = usableY } break // No default } videoModule.emit(type, event) } break case 'window': { const { windowId } = event delete event.windowId const window = Globals.windows.all.get(windowId) if (!window) { return } switch (type) { case 'move': { window._x = event.x window._y = event.y } break case 'resize': { window._width = event.width window._height = event.height window._pixelWidth = event.pixelWidth window._pixelHeight = event.pixelHeight } break case 'displayChange': { window._displayIndex = event.displayIndex delete event.displayIndex event.display = window.display } break case 'show': { window._visible = true } break case 'hide': { window._visible = false } break case 'expose': { // Nothing } break case 'minimize': { window._visible = false window._minimized = true window._maximized = false window._fullscreen = false } break case 'maximize': { window._visible = true window._minimized = false window._maximized = true window._fullscreen = false } break case 'restore': { window._visible = true window._minimized = false window._maximized = false window._fullscreen = false } break case 'focus': { Globals.windows.focused = window } break case 'blur': { Globals.windows.focused = null } break case 'hover': { Globals.windows.hovered = window } break case 'leave': { Globals.windows.hovered = null } break case 'close': { window.destroyGently() return } default: return } window.emit(type, event) } break case 'keymap': { keyboardModule.emit(type, event) } break case 'keyboard': { const { windowId } = event delete event.windowId const window = Globals.windows.all.get(windowId) if (!window) { return } const { key } = event event.key = mapping[key] ?? (key?.length === 1 ? key : null) window.emit(type, event) } break case 'mouse': case 'text': case 'drop': { const { windowId } = event delete event.windowId const window = Globals.windows.all.get(windowId) if (!window) { return } window.emit(type, event) } break case 'touch': { const { touchId } = event delete event.touchId let device = Globals.touchState.devices.find(({ id }) => id === touchId) if (device === undefined) { Globals.touchDevices = Bindings.touch_getDevices() device = Globals.touchState.devices.find(({ id }) => id === touchId) } const { windowId } = event delete event.windowId const window = Globals.windows.all.get(windowId) if (!window) { return } event.device = device window.emit(type, event) } break case 'joystickDevice': { if (type === 'deviceRemove') { const { joystickId } = event delete event.joystickId closeJoysticks: { const collection = Globals.joystickInstances.byId.get(joystickId) if (!collection) { break closeJoysticks } for (const joystickInstance of collection.values()) { joystickInstance.close() } } closeControllers: { const collection = Globals.controllerInstances.byId.get(joystickId) if (!collection) { break closeControllers } for (const controllerInstance of collection.values()) { controllerInstance.close() } } } const { devices } = event delete event.devices reconcileJoystickAndControllerDevices(devices) } break case 'joystick': { const { joystickId } = event delete event.joystickId const collection = Globals.joystickInstances.byId.get(joystickId) if (!collection) { return } switch (type) { case 'axisMotion': { for (const joystickInstance of collection) { joystickInstance._axes[event.axis] = event.value joystickInstance.emit(type, event) } } break case 'ballMotion': { for (const joystickInstance of collection) { const ball = joystickInstance._balls[event.ball] ball.x = event.x ball.y = event.y joystickInstance.emit(type, event) } } break case 'buttonDown': { for (const joystickInstance of collection) { joystickInstance._buttons[event.button] = true joystickInstance.emit(type, event) } } break case 'buttonUp': { for (const joystickInstance of collection) { joystickInstance._buttons[event.button] = false joystickInstance.emit(type, event) } } break case 'hatMotion': { for (const joystickInstance of collection) { joystickInstance._hats[event.hat] = event.value joystickInstance.emit(type, event) } } break case 'powerUpdate': { for (const joystickInstance of collection) { joystickInstance._power = event.power joystickInstance.emit(type, event) } const otherCollection = Globals.controllerInstances.byId.get(joystickId) if (!otherCollection) { break } for (const controllerInstance of otherCollection) { controllerInstance._power = event.power controllerInstance.emit(type, event) } } break // No default } } break case 'controller': { const { controllerId } = event delete event.controllerId const collection = Globals.controllerInstances.byId.get(controllerId) if (!collection) { return } switch (type) { case 'axisMotion': { for (const controllerInstance of collection.values()) { controllerInstance._axes[event.axis] = event.value controllerInstance.emit(type, event) } } break case 'buttonDown': { for (const controllerInstance of collection.values()) { controllerInstance._buttons[event.button] = true controllerInstance.emit(type, event) } } break case 'buttonUp': { for (const controllerInstance of collection.values()) { controllerInstance._buttons[event.button] = false controllerInstance.emit(type, event) } } break case 'steamHandleUpdate': { for (const controllerInstance of collection.values()) { controllerInstance._steamHandle = event.steamHandle controllerInstance.emit(type, event) } } break case 'remap': { const { axes, buttons } = event delete event.axes delete event.buttons for (const controllerInstance of collection.values()) { Object.assign(controllerInstance._axes, axes) Object.assign(controllerInstance._buttons, buttons) controllerInstance.emit(type, event) } } break // No default } } break case 'sensor': { const { sensorId } = event delete event.sensorId const collection = Globals.sensorInstances.byId.get(sensorId) if (!collection) { return } switch (type) { case 'update': { for (const sensorInstance of collection.values()) { sensorInstance.emit(type, event) } } break // No default } } break case 'audioDevice': { const { audioDeviceType } = event delete event.audioDeviceType if (type === 'deviceRemove') { const { audioId } = event delete event.audioId const audioInstance = Globals.audioInstances.get(audioId) if (audioInstance) { audioInstance.close() } } const { devices } = event delete event.devices reconcileAudioDevices(devices, audioDeviceType) } break case 'clipboard': { clipboardModule.emit(type, event) } break // No default } } let polling = false const poll = () => { if (polling) { return } polling = true Bindings.events_poll(handleEvent) polling = false } let pollInterval = null const switchToPollingFast = () => { clearInterval(pollInterval) pollInterval = setInterval(poll, 0) } const switchToPollingSlow = () => { clearInterval(pollInterval) pollInterval = setInterval(poll, 1e3) pollInterval.unref() } const stopPolling = () => { clearInterval(pollInterval) pollInterval = null } switchToPollingSlow() poll() Globals.events = { poll, switchToPollingFast, switchToPollingSlow, stopPolling, }