This commit is contained in:
2026-02-23 19:45:49 -06:00
parent 6bdd375dbb
commit ba6a0c2e12
2 changed files with 328 additions and 502 deletions

1
gpu.c
View File

@@ -1,5 +1,4 @@
#include "sdl.h"
#include "quickjs.h"
#include <SDL3/SDL_gpu.h>
#include "cell.h"

829
input.c
View File

@@ -1,5 +1,4 @@
#include "cell.h"
#include "wota.h"
#include <SDL3/SDL.h>
#include "sdl.h"
@@ -77,7 +76,7 @@ JSC_CCALL(input_mousestate,
JS_RETURN(m);
)
// Event processing functions (moved from cell.c)
// Event processing functions
const char* event_type_to_string(Uint32 event_type) {
switch (event_type) {
@@ -233,524 +232,355 @@ const char* mouse_button_to_string(int mouse) {
}
}
static void wota_write_vec2(WotaBuffer *wb, double x, double y) {
// We'll store as WOTA_ARR of length 2, then two numbers
wota_write_array(wb, 2);
wota_write_number(wb, x);
wota_write_number(wb, y);
static JSValue js_vec2(JSContext *js, double x, double y) {
JS_FRAME(js);
JS_LOCAL(arr, JS_NewArray(js));
JS_SetPropertyNumber(js, arr, 0, number2js(js, x));
JS_SetPropertyNumber(js, arr, 1, number2js(js, y));
JS_RETURN(arr);
}
static int event2wota_count_props(const SDL_Event *event)
{
// We always store at least "type" and "timestamp".
int count = 2;
static JSValue event2js(JSContext *js, const SDL_Event *e) {
JS_FRAME(js);
JS_LOCAL(obj, JS_NewObject(js));
JSValue tmp;
tmp = JS_NewString(js, event_type_to_string(e->type));
JS_SetPropertyStr(js, obj, "type", tmp);
JS_SetPropertyStr(js, obj, "timestamp",
number2js(js, (double)e->common.timestamp));
switch (event->type) {
switch (e->type) {
case SDL_EVENT_AUDIO_DEVICE_ADDED:
case SDL_EVENT_AUDIO_DEVICE_REMOVED:
count += 2; // which, recording
break;
case SDL_EVENT_AUDIO_DEVICE_ADDED:
case SDL_EVENT_AUDIO_DEVICE_REMOVED:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->adevice.which));
JS_SetPropertyStr(js, obj, "recording",
JS_NewBool(js, e->adevice.recording));
break;
case SDL_EVENT_DISPLAY_ORIENTATION:
case SDL_EVENT_DISPLAY_ADDED:
case SDL_EVENT_DISPLAY_REMOVED:
case SDL_EVENT_DISPLAY_MOVED:
case SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED:
case SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED:
case SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED:
count += 3; // which, orientation/data1, data2
break;
case SDL_EVENT_DISPLAY_ORIENTATION:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->display.displayID));
JS_SetPropertyStr(js, obj, "orientation",
number2js(js, (double)e->display.data1));
JS_SetPropertyStr(js, obj, "data2",
number2js(js, (double)e->display.data2));
break;
case SDL_EVENT_MOUSE_MOTION:
count += 5;
break;
case SDL_EVENT_DISPLAY_ADDED:
case SDL_EVENT_DISPLAY_REMOVED:
case SDL_EVENT_DISPLAY_MOVED:
case SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED:
case SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED:
case SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->display.displayID));
JS_SetPropertyStr(js, obj, "data1",
number2js(js, (double)e->display.data1));
JS_SetPropertyStr(js, obj, "data2",
number2js(js, (double)e->display.data2));
break;
case SDL_EVENT_MOUSE_WHEEL:
// window, which, scroll, mouse => 4 extra
count += 4;
break;
case SDL_EVENT_MOUSE_MOTION:
JS_SetPropertyStr(js, obj, "window",
number2js(js, (double)e->motion.windowID));
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->motion.which));
JS_SetPropertyStr(js, obj, "state",
number2js(js, (double)e->motion.state));
tmp = js_vec2(js, (double)e->motion.x, (double)e->motion.y);
JS_SetPropertyStr(js, obj, "pos", tmp);
tmp = js_vec2(js, (double)e->motion.xrel, (double)e->motion.yrel);
JS_SetPropertyStr(js, obj, "d_pos", tmp);
break;
case SDL_EVENT_MOUSE_BUTTON_UP:
case SDL_EVENT_MOUSE_BUTTON_DOWN:
// window, which, down, button, clicks, mouse => 6 extra
count += 6;
break;
case SDL_EVENT_MOUSE_WHEEL:
JS_SetPropertyStr(js, obj, "window",
number2js(js, (double)e->wheel.windowID));
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->wheel.which));
tmp = js_vec2(js, (double)e->wheel.x, (double)e->wheel.y);
JS_SetPropertyStr(js, obj, "scroll", tmp);
tmp = js_vec2(js, (double)e->wheel.mouse_x, (double)e->wheel.mouse_y);
JS_SetPropertyStr(js, obj, "pos", tmp);
break;
case SDL_EVENT_SENSOR_UPDATE:
// which, sensor_timestamp => 2 extra
count += 2;
break;
case SDL_EVENT_MOUSE_BUTTON_UP:
case SDL_EVENT_MOUSE_BUTTON_DOWN:
JS_SetPropertyStr(js, obj, "window",
number2js(js, (double)e->button.windowID));
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->button.which));
JS_SetPropertyStr(js, obj, "down",
JS_NewBool(js, e->button.down));
tmp = JS_NewString(js, mouse_button_to_string(e->button.button));
JS_SetPropertyStr(js, obj, "button", tmp);
JS_SetPropertyStr(js, obj, "clicks",
number2js(js, (double)e->button.clicks));
tmp = js_vec2(js, (double)e->button.x, (double)e->button.y);
JS_SetPropertyStr(js, obj, "pos", tmp);
break;
case SDL_EVENT_KEY_DOWN:
case SDL_EVENT_KEY_UP:
// window, which, down, repeat, key, scancode, mod => 7 extra
count += 7;
break;
case SDL_EVENT_SENSOR_UPDATE:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->sensor.which));
JS_SetPropertyStr(js, obj, "sensor_timestamp",
number2js(js, (double)e->sensor.sensor_timestamp));
break;
case SDL_EVENT_FINGER_MOTION:
case SDL_EVENT_FINGER_DOWN:
case SDL_EVENT_FINGER_UP:
// touch, finger, pos, d_pos, pressure, window => 6 extra
count += 6;
break;
case SDL_EVENT_KEY_DOWN:
case SDL_EVENT_KEY_UP:
JS_SetPropertyStr(js, obj, "window",
number2js(js, (double)e->key.windowID));
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->key.which));
JS_SetPropertyStr(js, obj, "down",
JS_NewBool(js, e->key.down));
JS_SetPropertyStr(js, obj, "repeat",
JS_NewBool(js, e->key.repeat));
JS_SetPropertyStr(js, obj, "key",
number2js(js, (double)e->key.key));
JS_SetPropertyStr(js, obj, "scancode",
number2js(js, (double)e->key.scancode));
JS_SetPropertyStr(js, obj, "mod",
number2js(js, (double)e->key.mod));
break;
case SDL_EVENT_DROP_BEGIN:
case SDL_EVENT_DROP_FILE:
case SDL_EVENT_DROP_TEXT:
case SDL_EVENT_DROP_COMPLETE:
case SDL_EVENT_DROP_POSITION:
// window, pos, data, source => 4 extra
count += 4;
break;
case SDL_EVENT_FINGER_MOTION:
case SDL_EVENT_FINGER_DOWN:
case SDL_EVENT_FINGER_UP:
JS_SetPropertyStr(js, obj, "touch",
number2js(js, (double)e->tfinger.touchID));
JS_SetPropertyStr(js, obj, "finger",
number2js(js, (double)e->tfinger.fingerID));
tmp = js_vec2(js, (double)e->tfinger.x, (double)e->tfinger.y);
JS_SetPropertyStr(js, obj, "pos", tmp);
tmp = js_vec2(js, (double)e->tfinger.dx, (double)e->tfinger.dy);
JS_SetPropertyStr(js, obj, "d_pos", tmp);
JS_SetPropertyStr(js, obj, "pressure",
number2js(js, (double)e->tfinger.pressure));
JS_SetPropertyStr(js, obj, "window",
number2js(js, (double)e->key.windowID));
break;
case SDL_EVENT_TEXT_INPUT:
// window, text, mod => 3 extra
count += 3;
break;
case SDL_EVENT_DROP_BEGIN:
case SDL_EVENT_DROP_FILE:
case SDL_EVENT_DROP_TEXT:
case SDL_EVENT_DROP_COMPLETE:
case SDL_EVENT_DROP_POSITION:
JS_SetPropertyStr(js, obj, "window",
number2js(js, (double)e->drop.windowID));
tmp = js_vec2(js, (double)e->drop.x, (double)e->drop.y);
JS_SetPropertyStr(js, obj, "pos", tmp);
tmp = JS_NewString(js, e->drop.data ? e->drop.data : "");
JS_SetPropertyStr(js, obj, "data", tmp);
tmp = JS_NewString(js, e->drop.source ? e->drop.source : "");
JS_SetPropertyStr(js, obj, "source", tmp);
break;
case SDL_EVENT_CAMERA_DEVICE_APPROVED:
case SDL_EVENT_CAMERA_DEVICE_REMOVED:
case SDL_EVENT_CAMERA_DEVICE_ADDED:
case SDL_EVENT_CAMERA_DEVICE_DENIED:
// which => 1 extra
count += 1;
break;
case SDL_EVENT_TEXT_INPUT:
JS_SetPropertyStr(js, obj, "window",
number2js(js, (double)e->text.windowID));
tmp = JS_NewString(js, e->text.text);
JS_SetPropertyStr(js, obj, "text", tmp);
JS_SetPropertyStr(js, obj, "mod", number2js(js, 0));
break;
case SDL_EVENT_CLIPBOARD_UPDATE:
// owner => 1 extra
count += 1;
break;
case SDL_EVENT_CAMERA_DEVICE_APPROVED:
case SDL_EVENT_CAMERA_DEVICE_REMOVED:
case SDL_EVENT_CAMERA_DEVICE_ADDED:
case SDL_EVENT_CAMERA_DEVICE_DENIED:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->cdevice.which));
break;
/* Window events that only need 'which' */
case SDL_EVENT_WINDOW_EXPOSED:
case SDL_EVENT_WINDOW_FOCUS_GAINED:
case SDL_EVENT_WINDOW_FOCUS_LOST:
case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
// which => 1 extra
count += 1;
break;
case SDL_EVENT_CLIPBOARD_UPDATE:
JS_SetPropertyStr(js, obj, "owner",
JS_NewBool(js, e->clipboard.owner));
break;
/* Window events that need data1 and data2 */
case SDL_EVENT_WINDOW_SHOWN:
case SDL_EVENT_WINDOW_HIDDEN:
case SDL_EVENT_WINDOW_MOVED:
case SDL_EVENT_WINDOW_RESIZED:
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
case SDL_EVENT_WINDOW_METAL_VIEW_RESIZED:
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_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:
case SDL_EVENT_WINDOW_HDR_STATE_CHANGED:
// which, x/width/display_index, y/height => 3 extra
count += 3;
break;
case SDL_EVENT_WINDOW_EXPOSED:
case SDL_EVENT_WINDOW_FOCUS_GAINED:
case SDL_EVENT_WINDOW_FOCUS_LOST:
case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->window.windowID));
break;
case SDL_EVENT_WINDOW_SAFE_AREA_CHANGED:
// which, x, y, width, height => 5 extra
count += 5;
break;
case SDL_EVENT_WINDOW_SHOWN:
case SDL_EVENT_WINDOW_HIDDEN:
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_HIT_TEST:
case SDL_EVENT_WINDOW_ICCPROF_CHANGED:
case SDL_EVENT_WINDOW_OCCLUDED:
case SDL_EVENT_WINDOW_ENTER_FULLSCREEN:
case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN:
case SDL_EVENT_WINDOW_DESTROYED:
case SDL_EVENT_WINDOW_HDR_STATE_CHANGED:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->window.windowID));
JS_SetPropertyStr(js, obj, "data1",
number2js(js, (double)e->window.data1));
JS_SetPropertyStr(js, obj, "data2",
number2js(js, (double)e->window.data2));
break;
case SDL_EVENT_JOYSTICK_ADDED:
case SDL_EVENT_JOYSTICK_REMOVED:
case SDL_EVENT_JOYSTICK_UPDATE_COMPLETE:
// which => 1 extra
count += 1;
break;
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
// which, axis, value => 3 extra
count += 3;
break;
case SDL_EVENT_JOYSTICK_BALL_MOTION:
// which, ball, rel => 3 extra
count += 3;
break;
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
case SDL_EVENT_JOYSTICK_BUTTON_UP:
// which, button, down => 3 extra
count += 3;
break;
case SDL_EVENT_GAMEPAD_ADDED:
case SDL_EVENT_GAMEPAD_REMOVED:
case SDL_EVENT_GAMEPAD_REMAPPED:
case SDL_EVENT_GAMEPAD_UPDATE_COMPLETE:
case SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED:
// which => 1 extra
count += 1;
break;
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
// which, axis, value => 3 extra
count += 3;
break;
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
case SDL_EVENT_GAMEPAD_BUTTON_UP:
// which, button, down => 3 extra
count += 3;
break;
case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN:
case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION:
case SDL_EVENT_GAMEPAD_TOUCHPAD_UP:
// which, touchpad, finger, pos, pressure => 5 extra
count += 5;
break;
case SDL_EVENT_GAMEPAD_SENSOR_UPDATE:
// which, sensor, sensor_timestamp => 3 extra
count += 3;
break;
case SDL_EVENT_USER:
// cb => 1 extra
count += 1;
break;
case SDL_EVENT_WINDOW_SAFE_AREA_CHANGED: {
SDL_Window *window = SDL_GetWindowFromID(e->window.windowID);
SDL_Rect safe_area = {0, 0, 0, 0};
if (window && SDL_GetWindowSafeArea(window, &safe_area)) {
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->window.windowID));
JS_SetPropertyStr(js, obj, "x",
number2js(js, (double)safe_area.x));
JS_SetPropertyStr(js, obj, "y",
number2js(js, (double)safe_area.y));
JS_SetPropertyStr(js, obj, "width",
number2js(js, (double)safe_area.w));
JS_SetPropertyStr(js, obj, "height",
number2js(js, (double)safe_area.h));
} else {
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->window.windowID));
JS_SetPropertyStr(js, obj, "data1",
number2js(js, (double)e->window.data1));
JS_SetPropertyStr(js, obj, "data2",
number2js(js, (double)e->window.data2));
}
break;
}
return count;
}
case SDL_EVENT_WINDOW_MOVED:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->window.windowID));
JS_SetPropertyStr(js, obj, "x",
number2js(js, (double)e->window.data1));
JS_SetPropertyStr(js, obj, "y",
number2js(js, (double)e->window.data2));
break;
static void event2wota_write(WotaBuffer *wb, const SDL_Event *e, int c) {
wota_write_record(wb, (unsigned long long)c);
wota_write_text(wb, "type");
wota_write_text(wb, event_type_to_string(e->type));
wota_write_text(wb, "timestamp");
wota_write_number(wb, (double)e->common.timestamp);
switch(e->type) {
case SDL_EVENT_AUDIO_DEVICE_ADDED:
case SDL_EVENT_AUDIO_DEVICE_REMOVED:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->adevice.which);
wota_write_text(wb, "recording");
wota_write_sym(wb, e->adevice.recording ? WOTA_TRUE : WOTA_FALSE);
break;
case SDL_EVENT_DISPLAY_ORIENTATION:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->display.displayID);
wota_write_text(wb, "orientation");
wota_write_number(wb, (double)e->display.data1);
wota_write_text(wb, "data2");
wota_write_number(wb, (double)e->display.data2);
break;
case SDL_EVENT_DISPLAY_ADDED:
case SDL_EVENT_DISPLAY_REMOVED:
case SDL_EVENT_DISPLAY_MOVED:
case SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED:
case SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED:
case SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->display.displayID);
wota_write_text(wb, "data1");
wota_write_number(wb, (double)e->display.data1);
wota_write_text(wb, "data2");
wota_write_number(wb, (double)e->display.data2);
break;
case SDL_EVENT_MOUSE_MOTION:
wota_write_text(wb, "window");
wota_write_number(wb, (double)e->motion.windowID);
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->motion.which);
wota_write_text(wb, "state");
wota_write_number(wb, (double)e->motion.state);
wota_write_text(wb, "pos");
wota_write_vec2(wb, (double)e->motion.x, (double)e->motion.y);
wota_write_text(wb, "d_pos");
wota_write_vec2(wb, (double)e->motion.xrel, (double)e->motion.yrel);
break;
case SDL_EVENT_MOUSE_WHEEL:
wota_write_text(wb, "window");
wota_write_number(wb, (double)e->wheel.windowID);
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->wheel.which);
wota_write_text(wb, "scroll");
wota_write_vec2(wb, (double)e->wheel.x, (double)e->wheel.y);
wota_write_text(wb, "pos");
wota_write_vec2(wb, (double)e->wheel.mouse_x, (double)e->wheel.mouse_y);
break;
case SDL_EVENT_MOUSE_BUTTON_UP:
case SDL_EVENT_MOUSE_BUTTON_DOWN:
wota_write_text(wb, "window");
wota_write_number(wb, (double)e->button.windowID);
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->button.which);
wota_write_text(wb, "down");
wota_write_sym(wb, e->button.down ? WOTA_TRUE : WOTA_FALSE);
wota_write_text(wb, "button");
wota_write_text(wb, mouse_button_to_string(e->button.button));
wota_write_text(wb, "clicks");
wota_write_number(wb, (double)e->button.clicks);
wota_write_text(wb, "pos");
wota_write_vec2(wb, (double)e->button.x, (double)e->button.y);
break;
case SDL_EVENT_SENSOR_UPDATE:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->sensor.which);
wota_write_text(wb, "sensor_timestamp");
wota_write_number(wb, (double)e->sensor.sensor_timestamp);
break;
case SDL_EVENT_KEY_DOWN:
case SDL_EVENT_KEY_UP:
wota_write_text(wb, "window");
wota_write_number(wb, (double)e->key.windowID);
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->key.which);
wota_write_text(wb, "down");
wota_write_sym(wb, e->key.down ? WOTA_TRUE : WOTA_FALSE);
wota_write_text(wb, "repeat");
wota_write_sym(wb, e->key.repeat ? WOTA_TRUE : WOTA_FALSE);
wota_write_text(wb, "key");
wota_write_number(wb, (double)e->key.key);
wota_write_text(wb, "scancode");
wota_write_number(wb, (double)e->key.scancode);
wota_write_text(wb, "mod");
wota_write_number(wb, (double)e->key.mod);
break;
case SDL_EVENT_FINGER_MOTION:
case SDL_EVENT_FINGER_DOWN:
case SDL_EVENT_FINGER_UP:
wota_write_text(wb, "touch");
wota_write_number(wb, (double)e->tfinger.touchID);
wota_write_text(wb, "finger");
wota_write_number(wb, (double)e->tfinger.fingerID);
wota_write_text(wb, "pos");
wota_write_vec2(wb, (double)e->tfinger.x, (double)e->tfinger.y);
wota_write_text(wb, "d_pos");
wota_write_vec2(wb, (double)e->tfinger.dx, (double)e->tfinger.dy);
wota_write_text(wb, "pressure");
wota_write_number(wb, (double)e->tfinger.pressure);
wota_write_text(wb, "window");
wota_write_number(wb, (double)e->key.windowID);
break;
case SDL_EVENT_DROP_BEGIN:
case SDL_EVENT_DROP_FILE:
case SDL_EVENT_DROP_TEXT:
case SDL_EVENT_DROP_COMPLETE:
case SDL_EVENT_DROP_POSITION:
wota_write_text(wb, "window");
wota_write_number(wb, (double)e->drop.windowID);
wota_write_text(wb, "pos");
wota_write_vec2(wb, (double)e->drop.x, (double)e->drop.y);
wota_write_text(wb, "data");
wota_write_text(wb, e->drop.data ? e->drop.data : "");
wota_write_text(wb, "source");
wota_write_text(wb, e->drop.source ? e->drop.source : "");
break;
case SDL_EVENT_TEXT_INPUT:
wota_write_text(wb, "window");
wota_write_number(wb, (double)e->text.windowID);
wota_write_text(wb, "text");
wota_write_text(wb, e->text.text);
wota_write_text(wb, "mod");
wota_write_number(wb, 0);
break;
case SDL_EVENT_CAMERA_DEVICE_APPROVED:
case SDL_EVENT_CAMERA_DEVICE_REMOVED:
case SDL_EVENT_CAMERA_DEVICE_ADDED:
case SDL_EVENT_CAMERA_DEVICE_DENIED:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->cdevice.which);
break;
case SDL_EVENT_CLIPBOARD_UPDATE:
wota_write_text(wb, "owner");
wota_write_sym(wb, e->clipboard.owner ? WOTA_TRUE : WOTA_FALSE);
break;
case SDL_EVENT_WINDOW_EXPOSED:
case SDL_EVENT_WINDOW_FOCUS_GAINED:
case SDL_EVENT_WINDOW_FOCUS_LOST:
case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->window.windowID);
break;
case SDL_EVENT_WINDOW_SHOWN:
case SDL_EVENT_WINDOW_HIDDEN:
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_HIT_TEST:
case SDL_EVENT_WINDOW_ICCPROF_CHANGED:
case SDL_EVENT_WINDOW_OCCLUDED:
case SDL_EVENT_WINDOW_ENTER_FULLSCREEN:
case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN:
case SDL_EVENT_WINDOW_DESTROYED:
case SDL_EVENT_WINDOW_HDR_STATE_CHANGED:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->window.windowID);
wota_write_text(wb, "data1");
wota_write_number(wb, (double)e->window.data1);
wota_write_text(wb, "data2");
wota_write_number(wb, (double)e->window.data2);
break;
case SDL_EVENT_WINDOW_SAFE_AREA_CHANGED:
{
SDL_Window *window = SDL_GetWindowFromID(e->window.windowID);
SDL_Rect safe_area = {0, 0, 0, 0};
if (window && SDL_GetWindowSafeArea(window, &safe_area)) {
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->window.windowID);
wota_write_text(wb, "x");
wota_write_number(wb, (double)safe_area.x);
wota_write_text(wb, "y");
wota_write_number(wb, (double)safe_area.y);
wota_write_text(wb, "width");
wota_write_number(wb, (double)safe_area.w);
wota_write_text(wb, "height");
wota_write_number(wb, (double)safe_area.h);
} else {
// Fallback to original behavior if SDL_GetWindowSafeArea fails
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->window.windowID);
wota_write_text(wb, "data1");
wota_write_number(wb, (double)e->window.data1);
wota_write_text(wb, "data2");
wota_write_number(wb, (double)e->window.data2);
}
}
break;
case SDL_EVENT_WINDOW_MOVED:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->window.windowID);
wota_write_text(wb, "x");
wota_write_number(wb, (double)e->window.data1);
wota_write_text(wb, "y");
wota_write_number(wb, (double)e->window.data2);
break;
case SDL_EVENT_WINDOW_RESIZED:
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
case SDL_EVENT_WINDOW_METAL_VIEW_RESIZED:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->window.windowID);
wota_write_text(wb, "width");
wota_write_number(wb, (double)e->window.data1);
wota_write_text(wb, "height");
wota_write_number(wb, (double)e->window.data2);
break;
case SDL_EVENT_WINDOW_DISPLAY_CHANGED:
case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->window.windowID);
wota_write_text(wb, "display_index");
wota_write_number(wb, (double)e->window.data1);
wota_write_text(wb, "data2");
wota_write_number(wb, (double)e->window.data2);
break;
case SDL_EVENT_JOYSTICK_ADDED:
case SDL_EVENT_JOYSTICK_REMOVED:
case SDL_EVENT_JOYSTICK_UPDATE_COMPLETE:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->jdevice.which);
break;
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->jaxis.which);
wota_write_text(wb, "axis");
wota_write_number(wb, (double)e->jaxis.axis);
wota_write_text(wb, "value");
wota_write_number(wb, (double)e->jaxis.value);
break;
case SDL_EVENT_JOYSTICK_BALL_MOTION:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->jball.which);
wota_write_text(wb, "ball");
wota_write_number(wb, (double)e->jball.ball);
wota_write_text(wb, "rel");
wota_write_vec2(wb, (double)e->jball.xrel, (double)e->jball.yrel);
break;
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
case SDL_EVENT_JOYSTICK_BUTTON_UP:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->jbutton.which);
wota_write_text(wb, "button");
wota_write_number(wb, (double)e->jbutton.button);
wota_write_text(wb, "down");
wota_write_sym(wb, e->jbutton.down ? WOTA_TRUE : WOTA_FALSE);
break;
case SDL_EVENT_GAMEPAD_ADDED:
case SDL_EVENT_GAMEPAD_REMOVED:
case SDL_EVENT_GAMEPAD_REMAPPED:
case SDL_EVENT_GAMEPAD_UPDATE_COMPLETE:
case SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->gdevice.which);
break;
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->gaxis.which);
wota_write_text(wb, "axis");
wota_write_text(wb, SDL_GetGamepadStringForAxis(e->gaxis.axis));
wota_write_text(wb, "value");
// Normalize axis values
double normalized_value;
if (e->gaxis.axis == SDL_GAMEPAD_AXIS_LEFT_TRIGGER ||
e->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) {
// Triggers: 0 to 32767 -> 0 to 1
normalized_value = (double)e->gaxis.value / 32767.0;
} else {
// Thumbsticks: -32768 to 32767 -> -1 to 1
normalized_value = (double)e->gaxis.value / 32767.0;
}
wota_write_number(wb, normalized_value);
break;
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
case SDL_EVENT_GAMEPAD_BUTTON_UP:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->gbutton.which);
wota_write_text(wb, "button");
wota_write_text(wb, SDL_GetGamepadStringForButton(e->gbutton.button));
wota_write_text(wb, "down");
wota_write_sym(wb, e->gbutton.down ? WOTA_TRUE : WOTA_FALSE);
break;
case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN:
case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION:
case SDL_EVENT_GAMEPAD_TOUCHPAD_UP:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->gtouchpad.which);
wota_write_text(wb, "touchpad");
wota_write_number(wb, (double)e->gtouchpad.touchpad);
wota_write_text(wb, "finger");
wota_write_number(wb, (double)e->gtouchpad.finger);
wota_write_text(wb, "pos");
wota_write_vec2(wb, (double)e->gtouchpad.x, (double)e->gtouchpad.y);
wota_write_text(wb, "pressure");
wota_write_number(wb, (double)e->gtouchpad.pressure);
break;
case SDL_EVENT_GAMEPAD_SENSOR_UPDATE:
wota_write_text(wb, "which");
wota_write_number(wb, (double)e->gsensor.which);
wota_write_text(wb, "sensor");
wota_write_number(wb, (double)e->gsensor.sensor);
wota_write_text(wb, "sensor_timestamp");
wota_write_number(wb, (double)e->gsensor.sensor_timestamp);
break;
case SDL_EVENT_USER:
wota_write_text(wb, "cb");
wota_write_number(wb, (double)(uintptr_t)e->user.data1);
break;
}
}
case SDL_EVENT_WINDOW_RESIZED:
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
case SDL_EVENT_WINDOW_METAL_VIEW_RESIZED:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->window.windowID));
JS_SetPropertyStr(js, obj, "width",
number2js(js, (double)e->window.data1));
JS_SetPropertyStr(js, obj, "height",
number2js(js, (double)e->window.data2));
break;
static WotaBuffer event2wota(const SDL_Event *event) {
WotaBuffer wb;
wota_buffer_init(&wb, 8);
int n = event2wota_count_props(event);
event2wota_write(&wb, event, n);
return wb;
case SDL_EVENT_WINDOW_DISPLAY_CHANGED:
case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->window.windowID));
JS_SetPropertyStr(js, obj, "display_index",
number2js(js, (double)e->window.data1));
JS_SetPropertyStr(js, obj, "data2",
number2js(js, (double)e->window.data2));
break;
case SDL_EVENT_JOYSTICK_ADDED:
case SDL_EVENT_JOYSTICK_REMOVED:
case SDL_EVENT_JOYSTICK_UPDATE_COMPLETE:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->jdevice.which));
break;
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->jaxis.which));
JS_SetPropertyStr(js, obj, "axis",
number2js(js, (double)e->jaxis.axis));
JS_SetPropertyStr(js, obj, "value",
number2js(js, (double)e->jaxis.value));
break;
case SDL_EVENT_JOYSTICK_BALL_MOTION:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->jball.which));
JS_SetPropertyStr(js, obj, "ball",
number2js(js, (double)e->jball.ball));
tmp = js_vec2(js, (double)e->jball.xrel, (double)e->jball.yrel);
JS_SetPropertyStr(js, obj, "rel", tmp);
break;
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
case SDL_EVENT_JOYSTICK_BUTTON_UP:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->jbutton.which));
JS_SetPropertyStr(js, obj, "button",
number2js(js, (double)e->jbutton.button));
JS_SetPropertyStr(js, obj, "down",
JS_NewBool(js, e->jbutton.down));
break;
case SDL_EVENT_GAMEPAD_ADDED:
case SDL_EVENT_GAMEPAD_REMOVED:
case SDL_EVENT_GAMEPAD_REMAPPED:
case SDL_EVENT_GAMEPAD_UPDATE_COMPLETE:
case SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->gdevice.which));
break;
case SDL_EVENT_GAMEPAD_AXIS_MOTION: {
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->gaxis.which));
tmp = JS_NewString(js, SDL_GetGamepadStringForAxis(e->gaxis.axis));
JS_SetPropertyStr(js, obj, "axis", tmp);
double normalized_value = (double)e->gaxis.value / 32767.0;
JS_SetPropertyStr(js, obj, "value",
number2js(js, normalized_value));
break;
}
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
case SDL_EVENT_GAMEPAD_BUTTON_UP:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->gbutton.which));
tmp = JS_NewString(js, SDL_GetGamepadStringForButton(e->gbutton.button));
JS_SetPropertyStr(js, obj, "button", tmp);
JS_SetPropertyStr(js, obj, "down",
JS_NewBool(js, e->gbutton.down));
break;
case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN:
case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION:
case SDL_EVENT_GAMEPAD_TOUCHPAD_UP:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->gtouchpad.which));
JS_SetPropertyStr(js, obj, "touchpad",
number2js(js, (double)e->gtouchpad.touchpad));
JS_SetPropertyStr(js, obj, "finger",
number2js(js, (double)e->gtouchpad.finger));
tmp = js_vec2(js, (double)e->gtouchpad.x, (double)e->gtouchpad.y);
JS_SetPropertyStr(js, obj, "pos", tmp);
JS_SetPropertyStr(js, obj, "pressure",
number2js(js, (double)e->gtouchpad.pressure));
break;
case SDL_EVENT_GAMEPAD_SENSOR_UPDATE:
JS_SetPropertyStr(js, obj, "which",
number2js(js, (double)e->gsensor.which));
JS_SetPropertyStr(js, obj, "sensor",
number2js(js, (double)e->gsensor.sensor));
JS_SetPropertyStr(js, obj, "sensor_timestamp",
number2js(js, (double)e->gsensor.sensor_timestamp));
break;
case SDL_EVENT_USER:
JS_SetPropertyStr(js, obj, "cb",
number2js(js, (double)(uintptr_t)e->user.data1));
break;
}
JS_RETURN(obj);
}
// Get all events directly from SDL event queue
@@ -773,10 +603,7 @@ JSC_CCALL(input_get_events,
JSC_CCALL(input_objectify,
SDL_Event *e = js2SDL_Event(js, argv[0]);
if (!e) return JS_ThrowTypeError(js, "Expected SDL_Event object");
WotaBuffer wb = event2wota(e);
JSValue event_obj = wota2value(js, wb.data);
wota_buffer_free(&wb);
return event_obj;
return event2js(js, e);
)
JSC_CCALL(input_gamepad_id_to_type,