#include "cell.h" #include // Event type to string conversion static const char *event_type_to_string(Uint32 type) { switch (type) { // Application events case SDL_EVENT_QUIT: return "quit"; case SDL_EVENT_TERMINATING: return "terminating"; case SDL_EVENT_LOW_MEMORY: return "low_memory"; case SDL_EVENT_WILL_ENTER_BACKGROUND: return "will_enter_background"; case SDL_EVENT_DID_ENTER_BACKGROUND: return "did_enter_background"; case SDL_EVENT_WILL_ENTER_FOREGROUND: return "will_enter_foreground"; case SDL_EVENT_DID_ENTER_FOREGROUND: return "did_enter_foreground"; case SDL_EVENT_LOCALE_CHANGED: return "locale_changed"; case SDL_EVENT_SYSTEM_THEME_CHANGED: return "system_theme_changed"; // Display events case SDL_EVENT_DISPLAY_ORIENTATION: return "display_orientation"; case SDL_EVENT_DISPLAY_ADDED: return "display_added"; case SDL_EVENT_DISPLAY_REMOVED: return "display_removed"; case SDL_EVENT_DISPLAY_MOVED: return "display_moved"; case SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED: return "display_content_scale_changed"; // Window events case SDL_EVENT_WINDOW_SHOWN: return "window_shown"; case SDL_EVENT_WINDOW_HIDDEN: return "window_hidden"; case SDL_EVENT_WINDOW_EXPOSED: return "window_exposed"; case SDL_EVENT_WINDOW_MOVED: return "window_moved"; case SDL_EVENT_WINDOW_RESIZED: return "window_resized"; case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: return "window_pixel_size_changed"; case SDL_EVENT_WINDOW_MINIMIZED: return "window_minimized"; case SDL_EVENT_WINDOW_MAXIMIZED: return "window_maximized"; case SDL_EVENT_WINDOW_RESTORED: return "window_restored"; case SDL_EVENT_WINDOW_MOUSE_ENTER: return "window_mouse_enter"; case SDL_EVENT_WINDOW_MOUSE_LEAVE: return "window_mouse_leave"; case SDL_EVENT_WINDOW_FOCUS_GAINED: return "window_focus_gained"; case SDL_EVENT_WINDOW_FOCUS_LOST: return "window_focus_lost"; case SDL_EVENT_WINDOW_CLOSE_REQUESTED: return "window_close_requested"; case SDL_EVENT_WINDOW_HIT_TEST: return "window_hit_test"; case SDL_EVENT_WINDOW_ICCPROF_CHANGED: return "window_iccprof_changed"; case SDL_EVENT_WINDOW_DISPLAY_CHANGED: return "window_display_changed"; case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED: return "window_display_scale_changed"; case SDL_EVENT_WINDOW_OCCLUDED: return "window_occluded"; case SDL_EVENT_WINDOW_ENTER_FULLSCREEN: return "window_enter_fullscreen"; case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN: return "window_leave_fullscreen"; case SDL_EVENT_WINDOW_DESTROYED: return "window_destroyed"; // Keyboard events case SDL_EVENT_KEY_DOWN: return "key_down"; case SDL_EVENT_KEY_UP: return "key_up"; case SDL_EVENT_TEXT_EDITING: return "text_editing"; case SDL_EVENT_TEXT_INPUT: return "text_input"; case SDL_EVENT_KEYMAP_CHANGED: return "keymap_changed"; case SDL_EVENT_KEYBOARD_ADDED: return "keyboard_added"; case SDL_EVENT_KEYBOARD_REMOVED: return "keyboard_removed"; // Mouse events case SDL_EVENT_MOUSE_MOTION: return "mouse_motion"; case SDL_EVENT_MOUSE_BUTTON_DOWN: return "mouse_button_down"; case SDL_EVENT_MOUSE_BUTTON_UP: return "mouse_button_up"; case SDL_EVENT_MOUSE_WHEEL: return "mouse_wheel"; case SDL_EVENT_MOUSE_ADDED: return "mouse_added"; case SDL_EVENT_MOUSE_REMOVED: return "mouse_removed"; // Joystick events case SDL_EVENT_JOYSTICK_AXIS_MOTION: return "joystick_axis_motion"; case SDL_EVENT_JOYSTICK_BALL_MOTION: return "joystick_ball_motion"; case SDL_EVENT_JOYSTICK_HAT_MOTION: return "joystick_hat_motion"; case SDL_EVENT_JOYSTICK_BUTTON_DOWN: return "joystick_button_down"; case SDL_EVENT_JOYSTICK_BUTTON_UP: return "joystick_button_up"; case SDL_EVENT_JOYSTICK_ADDED: return "joystick_added"; case SDL_EVENT_JOYSTICK_REMOVED: return "joystick_removed"; case SDL_EVENT_JOYSTICK_BATTERY_UPDATED: return "joystick_battery_updated"; case SDL_EVENT_JOYSTICK_UPDATE_COMPLETE: return "joystick_update_complete"; // Gamepad events case SDL_EVENT_GAMEPAD_AXIS_MOTION: return "gamepad_axis_motion"; case SDL_EVENT_GAMEPAD_BUTTON_DOWN: return "gamepad_button_down"; case SDL_EVENT_GAMEPAD_BUTTON_UP: return "gamepad_button_up"; case SDL_EVENT_GAMEPAD_ADDED: return "gamepad_added"; case SDL_EVENT_GAMEPAD_REMOVED: return "gamepad_removed"; case SDL_EVENT_GAMEPAD_REMAPPED: return "gamepad_remapped"; case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN: return "gamepad_touchpad_down"; case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION: return "gamepad_touchpad_motion"; case SDL_EVENT_GAMEPAD_TOUCHPAD_UP: return "gamepad_touchpad_up"; case SDL_EVENT_GAMEPAD_SENSOR_UPDATE: return "gamepad_sensor_update"; case SDL_EVENT_GAMEPAD_UPDATE_COMPLETE: return "gamepad_update_complete"; case SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED: return "gamepad_steam_handle_updated"; // Touch events case SDL_EVENT_FINGER_DOWN: return "finger_down"; case SDL_EVENT_FINGER_UP: return "finger_up"; case SDL_EVENT_FINGER_MOTION: return "finger_motion"; // Clipboard events case SDL_EVENT_CLIPBOARD_UPDATE: return "clipboard_update"; // Drag and drop events case SDL_EVENT_DROP_FILE: return "drop_file"; case SDL_EVENT_DROP_TEXT: return "drop_text"; case SDL_EVENT_DROP_BEGIN: return "drop_begin"; case SDL_EVENT_DROP_COMPLETE: return "drop_complete"; case SDL_EVENT_DROP_POSITION: return "drop_position"; // Audio events case SDL_EVENT_AUDIO_DEVICE_ADDED: return "audio_device_added"; case SDL_EVENT_AUDIO_DEVICE_REMOVED: return "audio_device_removed"; case SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED: return "audio_device_format_changed"; // Sensor events case SDL_EVENT_SENSOR_UPDATE: return "sensor_update"; // Pen events case SDL_EVENT_PEN_PROXIMITY_IN: return "pen_proximity_in"; case SDL_EVENT_PEN_PROXIMITY_OUT: return "pen_proximity_out"; case SDL_EVENT_PEN_DOWN: return "pen_down"; case SDL_EVENT_PEN_UP: return "pen_up"; case SDL_EVENT_PEN_BUTTON_DOWN: return "pen_button_down"; case SDL_EVENT_PEN_BUTTON_UP: return "pen_button_up"; case SDL_EVENT_PEN_MOTION: return "pen_motion"; case SDL_EVENT_PEN_AXIS: return "pen_axis"; // Camera events case SDL_EVENT_CAMERA_DEVICE_ADDED: return "camera_device_added"; case SDL_EVENT_CAMERA_DEVICE_REMOVED: return "camera_device_removed"; case SDL_EVENT_CAMERA_DEVICE_APPROVED: return "camera_device_approved"; case SDL_EVENT_CAMERA_DEVICE_DENIED: return "camera_device_denied"; // Render events case SDL_EVENT_RENDER_TARGETS_RESET: return "render_targets_reset"; case SDL_EVENT_RENDER_DEVICE_RESET: return "render_device_reset"; case SDL_EVENT_RENDER_DEVICE_LOST: return "render_device_lost"; default: return "unknown"; } } // Mouse button to string static const char *mouse_button_to_string(Uint8 button) { switch (button) { case SDL_BUTTON_LEFT: return "left"; case SDL_BUTTON_MIDDLE: return "middle"; case SDL_BUTTON_RIGHT: return "right"; case SDL_BUTTON_X1: return "x1"; case SDL_BUTTON_X2: return "x2"; default: return "unknown"; } } // Convert SDL_Event to JS object static JSValue event_to_js(JSContext *js, SDL_Event *event) { JS_FRAME(js); JS_LOCAL(obj, JS_NewObject(js)); JS_SetPropertyStr(js, obj, "type", JS_NewString(js, event_type_to_string(event->type))); JS_SetPropertyStr(js, obj, "timestamp", JS_NewInt64(js, event->common.timestamp)); switch (event->type) { // Window events case SDL_EVENT_WINDOW_SHOWN: case SDL_EVENT_WINDOW_HIDDEN: case SDL_EVENT_WINDOW_EXPOSED: case SDL_EVENT_WINDOW_MOVED: case SDL_EVENT_WINDOW_RESIZED: case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: case SDL_EVENT_WINDOW_MINIMIZED: case SDL_EVENT_WINDOW_MAXIMIZED: case SDL_EVENT_WINDOW_RESTORED: case SDL_EVENT_WINDOW_MOUSE_ENTER: case SDL_EVENT_WINDOW_MOUSE_LEAVE: case SDL_EVENT_WINDOW_FOCUS_GAINED: case SDL_EVENT_WINDOW_FOCUS_LOST: case SDL_EVENT_WINDOW_CLOSE_REQUESTED: case SDL_EVENT_WINDOW_HIT_TEST: case SDL_EVENT_WINDOW_ICCPROF_CHANGED: case SDL_EVENT_WINDOW_DISPLAY_CHANGED: case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED: case SDL_EVENT_WINDOW_OCCLUDED: case SDL_EVENT_WINDOW_ENTER_FULLSCREEN: case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN: case SDL_EVENT_WINDOW_DESTROYED: JS_SetPropertyStr(js, obj, "window_id", JS_NewUint32(js, event->window.windowID)); JS_SetPropertyStr(js, obj, "data1", JS_NewInt32(js, event->window.data1)); JS_SetPropertyStr(js, obj, "data2", JS_NewInt32(js, event->window.data2)); break; // Keyboard events case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_UP: JS_SetPropertyStr(js, obj, "window_id", JS_NewUint32(js, event->key.windowID)); JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->key.which)); JS_SetPropertyStr(js, obj, "scancode", JS_NewInt32(js, event->key.scancode)); JS_SetPropertyStr(js, obj, "key", JS_NewUint32(js, event->key.key)); JS_SetPropertyStr(js, obj, "mod", JS_NewUint32(js, event->key.mod)); JS_SetPropertyStr(js, obj, "repeat", JS_NewBool(js, event->key.repeat)); JS_SetPropertyStr(js, obj, "down", JS_NewBool(js, event->key.down)); break; // Text input case SDL_EVENT_TEXT_INPUT: JS_SetPropertyStr(js, obj, "window_id", JS_NewUint32(js, event->text.windowID)); JS_SetPropertyStr(js, obj, "text", JS_NewString(js, event->text.text)); break; // Text editing case SDL_EVENT_TEXT_EDITING: JS_SetPropertyStr(js, obj, "window_id", JS_NewUint32(js, event->edit.windowID)); JS_SetPropertyStr(js, obj, "text", JS_NewString(js, event->edit.text)); JS_SetPropertyStr(js, obj, "start", JS_NewInt32(js, event->edit.start)); JS_SetPropertyStr(js, obj, "length", JS_NewInt32(js, event->edit.length)); break; // Mouse motion case SDL_EVENT_MOUSE_MOTION: JS_SetPropertyStr(js, obj, "window_id", JS_NewUint32(js, event->motion.windowID)); JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->motion.which)); JS_SetPropertyStr(js, obj, "state", JS_NewUint32(js, event->motion.state)); JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, event->motion.x)); JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, event->motion.y)); JS_SetPropertyStr(js, obj, "xrel", JS_NewFloat64(js, event->motion.xrel)); JS_SetPropertyStr(js, obj, "yrel", JS_NewFloat64(js, event->motion.yrel)); break; // Mouse button case SDL_EVENT_MOUSE_BUTTON_DOWN: case SDL_EVENT_MOUSE_BUTTON_UP: JS_SetPropertyStr(js, obj, "window_id", JS_NewUint32(js, event->button.windowID)); JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->button.which)); JS_SetPropertyStr(js, obj, "button", JS_NewString(js, mouse_button_to_string(event->button.button))); JS_SetPropertyStr(js, obj, "button_num", JS_NewUint32(js, event->button.button)); JS_SetPropertyStr(js, obj, "down", JS_NewBool(js, event->button.down)); JS_SetPropertyStr(js, obj, "clicks", JS_NewUint32(js, event->button.clicks)); JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, event->button.x)); JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, event->button.y)); break; // Mouse wheel case SDL_EVENT_MOUSE_WHEEL: JS_SetPropertyStr(js, obj, "window_id", JS_NewUint32(js, event->wheel.windowID)); JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->wheel.which)); JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, event->wheel.x)); JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, event->wheel.y)); JS_SetPropertyStr(js, obj, "direction", JS_NewString(js, event->wheel.direction == SDL_MOUSEWHEEL_FLIPPED ? "flipped" : "normal")); JS_SetPropertyStr(js, obj, "mouse_x", JS_NewFloat64(js, event->wheel.mouse_x)); JS_SetPropertyStr(js, obj, "mouse_y", JS_NewFloat64(js, event->wheel.mouse_y)); break; // Joystick axis case SDL_EVENT_JOYSTICK_AXIS_MOTION: JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->jaxis.which)); JS_SetPropertyStr(js, obj, "axis", JS_NewUint32(js, event->jaxis.axis)); JS_SetPropertyStr(js, obj, "value", JS_NewInt32(js, event->jaxis.value)); break; // Joystick ball case SDL_EVENT_JOYSTICK_BALL_MOTION: JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->jball.which)); JS_SetPropertyStr(js, obj, "ball", JS_NewUint32(js, event->jball.ball)); JS_SetPropertyStr(js, obj, "xrel", JS_NewInt32(js, event->jball.xrel)); JS_SetPropertyStr(js, obj, "yrel", JS_NewInt32(js, event->jball.yrel)); break; // Joystick hat case SDL_EVENT_JOYSTICK_HAT_MOTION: JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->jhat.which)); JS_SetPropertyStr(js, obj, "hat", JS_NewUint32(js, event->jhat.hat)); JS_SetPropertyStr(js, obj, "value", JS_NewUint32(js, event->jhat.value)); break; // Joystick button case SDL_EVENT_JOYSTICK_BUTTON_DOWN: case SDL_EVENT_JOYSTICK_BUTTON_UP: JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->jbutton.which)); JS_SetPropertyStr(js, obj, "button", JS_NewUint32(js, event->jbutton.button)); JS_SetPropertyStr(js, obj, "down", JS_NewBool(js, event->jbutton.down)); break; // Joystick device case SDL_EVENT_JOYSTICK_ADDED: case SDL_EVENT_JOYSTICK_REMOVED: JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->jdevice.which)); break; // Gamepad axis case SDL_EVENT_GAMEPAD_AXIS_MOTION: JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->gaxis.which)); JS_SetPropertyStr(js, obj, "axis", JS_NewUint32(js, event->gaxis.axis)); JS_SetPropertyStr(js, obj, "value", JS_NewInt32(js, event->gaxis.value)); break; // Gamepad button case SDL_EVENT_GAMEPAD_BUTTON_DOWN: case SDL_EVENT_GAMEPAD_BUTTON_UP: JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->gbutton.which)); JS_SetPropertyStr(js, obj, "button", JS_NewUint32(js, event->gbutton.button)); JS_SetPropertyStr(js, obj, "down", JS_NewBool(js, event->gbutton.down)); break; // Gamepad device case SDL_EVENT_GAMEPAD_ADDED: case SDL_EVENT_GAMEPAD_REMOVED: case SDL_EVENT_GAMEPAD_REMAPPED: JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->gdevice.which)); break; // Gamepad touchpad case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN: case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION: case SDL_EVENT_GAMEPAD_TOUCHPAD_UP: JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->gtouchpad.which)); JS_SetPropertyStr(js, obj, "touchpad", JS_NewInt32(js, event->gtouchpad.touchpad)); JS_SetPropertyStr(js, obj, "finger", JS_NewInt32(js, event->gtouchpad.finger)); JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, event->gtouchpad.x)); JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, event->gtouchpad.y)); JS_SetPropertyStr(js, obj, "pressure", JS_NewFloat64(js, event->gtouchpad.pressure)); break; // Gamepad sensor case SDL_EVENT_GAMEPAD_SENSOR_UPDATE: JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->gsensor.which)); JS_SetPropertyStr(js, obj, "sensor", JS_NewInt32(js, event->gsensor.sensor)); { JSValue data = JS_NewArray(js); JSLocalRef data__lr = {.ptr = &data}; JS_PushLocalRef(_js_ctx, &data__lr); for (int i = 0; i < 3; i++) { JS_SetPropertyNumber(js, data, i, JS_NewFloat64(js, event->gsensor.data[i])); } JS_SetPropertyStr(js, obj, "data", data); } JS_SetPropertyStr(js, obj, "sensor_timestamp", JS_NewInt64(js, event->gsensor.sensor_timestamp)); break; // Touch finger case SDL_EVENT_FINGER_DOWN: case SDL_EVENT_FINGER_UP: case SDL_EVENT_FINGER_MOTION: JS_SetPropertyStr(js, obj, "touch_id", JS_NewInt64(js, event->tfinger.touchID)); JS_SetPropertyStr(js, obj, "finger_id", JS_NewInt64(js, event->tfinger.fingerID)); JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, event->tfinger.x)); JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, event->tfinger.y)); JS_SetPropertyStr(js, obj, "dx", JS_NewFloat64(js, event->tfinger.dx)); JS_SetPropertyStr(js, obj, "dy", JS_NewFloat64(js, event->tfinger.dy)); JS_SetPropertyStr(js, obj, "pressure", JS_NewFloat64(js, event->tfinger.pressure)); JS_SetPropertyStr(js, obj, "window_id", JS_NewUint32(js, event->tfinger.windowID)); break; // Drop events case SDL_EVENT_DROP_FILE: case SDL_EVENT_DROP_TEXT: JS_SetPropertyStr(js, obj, "window_id", JS_NewUint32(js, event->drop.windowID)); JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, event->drop.x)); JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, event->drop.y)); if (event->drop.data) JS_SetPropertyStr(js, obj, "data", JS_NewString(js, event->drop.data)); break; case SDL_EVENT_DROP_BEGIN: case SDL_EVENT_DROP_COMPLETE: case SDL_EVENT_DROP_POSITION: JS_SetPropertyStr(js, obj, "window_id", JS_NewUint32(js, event->drop.windowID)); JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, event->drop.x)); JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, event->drop.y)); break; // Audio device case SDL_EVENT_AUDIO_DEVICE_ADDED: case SDL_EVENT_AUDIO_DEVICE_REMOVED: case SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED: JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->adevice.which)); JS_SetPropertyStr(js, obj, "recording", JS_NewBool(js, event->adevice.recording)); break; // Sensor update case SDL_EVENT_SENSOR_UPDATE: JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->sensor.which)); { JSValue data = JS_NewArray(js); JSLocalRef data__lr = {.ptr = &data}; JS_PushLocalRef(_js_ctx, &data__lr); for (int i = 0; i < 6; i++) { JS_SetPropertyNumber(js, data, i, JS_NewFloat64(js, event->sensor.data[i])); } JS_SetPropertyStr(js, obj, "data", data); } JS_SetPropertyStr(js, obj, "sensor_timestamp", JS_NewInt64(js, event->sensor.sensor_timestamp)); break; // Pen events case SDL_EVENT_PEN_PROXIMITY_IN: case SDL_EVENT_PEN_PROXIMITY_OUT: case SDL_EVENT_PEN_DOWN: case SDL_EVENT_PEN_UP: case SDL_EVENT_PEN_MOTION: JS_SetPropertyStr(js, obj, "window_id", JS_NewUint32(js, event->pmotion.windowID)); JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->pmotion.which)); JS_SetPropertyStr(js, obj, "pen_state", JS_NewUint32(js, event->pmotion.pen_state)); JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, event->pmotion.x)); JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, event->pmotion.y)); break; case SDL_EVENT_PEN_BUTTON_DOWN: case SDL_EVENT_PEN_BUTTON_UP: JS_SetPropertyStr(js, obj, "window_id", JS_NewUint32(js, event->pbutton.windowID)); JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->pbutton.which)); JS_SetPropertyStr(js, obj, "pen_state", JS_NewUint32(js, event->pbutton.pen_state)); JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, event->pbutton.x)); JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, event->pbutton.y)); JS_SetPropertyStr(js, obj, "button", JS_NewUint32(js, event->pbutton.button)); JS_SetPropertyStr(js, obj, "down", JS_NewBool(js, event->pbutton.down)); break; case SDL_EVENT_PEN_AXIS: JS_SetPropertyStr(js, obj, "window_id", JS_NewUint32(js, event->paxis.windowID)); JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->paxis.which)); JS_SetPropertyStr(js, obj, "pen_state", JS_NewUint32(js, event->paxis.pen_state)); JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, event->paxis.x)); JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, event->paxis.y)); JS_SetPropertyStr(js, obj, "axis", JS_NewUint32(js, event->paxis.axis)); JS_SetPropertyStr(js, obj, "value", JS_NewFloat64(js, event->paxis.value)); break; // Camera device case SDL_EVENT_CAMERA_DEVICE_ADDED: case SDL_EVENT_CAMERA_DEVICE_REMOVED: case SDL_EVENT_CAMERA_DEVICE_APPROVED: case SDL_EVENT_CAMERA_DEVICE_DENIED: JS_SetPropertyStr(js, obj, "which", JS_NewUint32(js, event->cdevice.which)); break; // Display events case SDL_EVENT_DISPLAY_ORIENTATION: case SDL_EVENT_DISPLAY_ADDED: case SDL_EVENT_DISPLAY_REMOVED: case SDL_EVENT_DISPLAY_MOVED: case SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED: JS_SetPropertyStr(js, obj, "display_id", JS_NewUint32(js, event->display.displayID)); JS_SetPropertyStr(js, obj, "data1", JS_NewInt32(js, event->display.data1)); break; default: break; } JS_RETURN(obj); } // SDL_PumpEvents() JSC_CCALL(events_pump, SDL_PumpEvents(); return JS_NULL; ) // SDL_PollEvent() -> event object or null JSC_CCALL(events_poll, SDL_Event event; if (SDL_PollEvent(&event)) { return event_to_js(js, &event); } return JS_NULL; ) // SDL_WaitEvent(timeout_ms) -> event object or null JSC_CCALL(events_wait, SDL_Event event; int timeout = -1; if (argc > 0) JS_ToInt32(js, &timeout, argv[0]); bool result; if (timeout < 0) { result = SDL_WaitEvent(&event); } else { result = SDL_WaitEventTimeout(&event, timeout); } if (result) { return event_to_js(js, &event); } return JS_NULL; ) // SDL_PeepEvents(count, action, min_type, max_type) -> array of events JSC_CCALL(events_peep, int count = 10; if (argc > 0) JS_ToInt32(js, &count, argv[0]); SDL_Event *events = malloc(count * sizeof(SDL_Event)); if (!events) return JS_ThrowOutOfMemory(js); int num = SDL_PeepEvents(events, count, SDL_PEEKEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST); if (num < 0) { free(events); return JS_NewArray(js); } JS_FRAME(js); JS_LOCAL(arr, JS_NewArray(js)); for (int i = 0; i < num; i++) { JS_SetPropertyNumber(js, arr, i, event_to_js(js, &events[i])); } free(events); JS_RestoreFrame(_js_ctx, _js_gc_frame, _js_local_frame); ret = arr; ) // SDL_HasEvent(type) -> bool JSC_CCALL(events_has, uint32_t type; JS_ToUint32(js, &type, argv[0]); return JS_NewBool(js, SDL_HasEvent(type)); ) // SDL_FlushEvent(type) JSC_CCALL(events_flush, uint32_t type; JS_ToUint32(js, &type, argv[0]); SDL_FlushEvent(type); return JS_NULL; ) // SDL_FlushEvents(min_type, max_type) JSC_CCALL(events_flush_range, uint32_t min_type, max_type; JS_ToUint32(js, &min_type, argv[0]); JS_ToUint32(js, &max_type, argv[1]); SDL_FlushEvents(min_type, max_type); return JS_NULL; ) // Get all pending events as array JSC_CCALL(events_get_all, JS_FRAME(js); JS_LOCAL(arr, JS_NewArray(js)); SDL_Event event; int i = 0; while (SDL_PollEvent(&event)) { JS_SetPropertyNumber(js, arr, i++, event_to_js(js, &event)); } JS_RestoreFrame(_js_ctx, _js_gc_frame, _js_local_frame); ret = arr; ) static const JSCFunctionListEntry js_events_funcs[] = { MIST_FUNC_DEF(events, pump, 0), MIST_FUNC_DEF(events, poll, 0), MIST_FUNC_DEF(events, wait, 1), MIST_FUNC_DEF(events, peep, 1), MIST_FUNC_DEF(events, has, 1), MIST_FUNC_DEF(events, flush, 1), MIST_FUNC_DEF(events, flush_range, 2), MIST_FUNC_DEF(events, get_all, 0), }; CELL_USE_INIT( JS_FRAME(js); JS_LOCAL(mod, JS_NewObject(js)); JS_SetPropertyFunctionList(js, mod, js_events_funcs, countof(js_events_funcs)); JS_RETURN(mod); )