feat(sim): web viewer at /sim + touch injection at /api/sim/touch

- GET /sim: live viewer page, 2s screenshot refresh, click-to-touch
- POST /api/sim/touch?x,y,down: injects into sdl-pointer backend,
  auto-releases after 1.5s; simulator-only (404 on ESP32)
- sdl_input: file-scope touch override state with extern C setters
This commit is contained in:
Adolfo Reyna
2026-09-14 21:02:54 -04:00
parent 620d56e19a
commit 2060095028
4 changed files with 144 additions and 1 deletions
+40 -1
View File
@@ -14,6 +14,34 @@ constexpr size_t KEY_QUEUE_CAPACITY = 32;
SdlPointerState pointer_state = { 0, 0, false };
} // namespace
// Web touch-injection override (headless sim viewer). Guarded by tick count so
// a press auto-releases even if the viewer never sends the release event.
// File-scope (not anonymous namespace): the extern "C" setters below must be
// visible to the linker for WebServerService's touch endpoint.
bool touch_override_active = false;
SdlPointerState touch_override = { 0, 0, false };
uint32_t touch_override_until_tick = 0;
#define SIM_TOUCH_HOLD_MS 1500
extern "C" void sdl_input_set_touch_override(int32_t x, int32_t y, bool pressed) {
touch_override.x = x;
touch_override.y = y;
touch_override.pressed = pressed;
touch_override_active = pressed;
if (pressed) {
touch_override_until_tick = SDL_GetTicks() + SIM_TOUCH_HOLD_MS;
}
}
extern "C" void sdl_input_clear_touch_override(void) {
touch_override_active = false;
touch_override.pressed = false;
}
namespace {
uint32_t key_queue[KEY_QUEUE_CAPACITY];
size_t key_queue_head = 0;
size_t key_queue_count = 0;
@@ -70,7 +98,7 @@ uint32_t keycode_to_key(SDL_Keycode sdl_key, bool shift) {
}
}
}
} // namespace
void sdl_input_pump() {
if (!text_input_started) {
@@ -125,6 +153,17 @@ void sdl_input_pump() {
}
void sdl_input_get_pointer_state(SdlPointerState* out_state) {
if (touch_override_active) {
// Auto-release: viewer sends press only; LVGL needs press then release
// to register a click. Hold long enough for several indev polls.
if ((int32_t)(SDL_GetTicks() - touch_override_until_tick) >= 0) {
touch_override_active = false;
touch_override.pressed = false;
} else {
*out_state = touch_override;
return;
}
}
*out_state = pointer_state;
}
@@ -42,6 +42,16 @@ bool sdl_input_pop_key(uint32_t* out_key);
*/
bool sdl_input_has_queued_key(void);
/**
* @brief Web-injected touch override (for headless sim viewer without SDL window).
* When active, sdl_pointer_get_touched_points() reports this state instead of
* the SDL mouse state. Coordinates are in LVGL logical pixels (e.g. 640x480).
* Pass pressed=false to release. Auto-releases after SIM_TOUCH_HOLD_MS unless
* refreshed (tap = press, wait, release handled by the web viewer).
*/
void sdl_input_set_touch_override(int32_t x, int32_t y, bool pressed);
void sdl_input_clear_touch_override(void);
#ifdef __cplusplus
}
#endif