Files
totk-pc-recomp/runtime/ui/menu_sdl.cpp
T
Wellington Dias 1d51343ac1 Build and run the runtime natively on Linux.
Shared runtime code now goes through runtime/platform/platform.h, implemented by platform/win32.c and a new
platform/linux.c: futex locks, a userfaultfd and PAGEMAP_SCAN write watch, signal-based async preemption, our own
fiber switch, and a SIGSEGV handler for the thaw and crash hooks. The window, input, menu and software keyboard get
SDL3 back ends beside the Win32 ones, with the swapchain (gfx_present.c) and input merging (input.c) shared. SHA-256
replaces BCrypt, ELF builds get their own override sections, and the build tools gain Linux branches.

On Linux the selftest and the gfx-abi, astc, nvn and window probes pass. probe-vkmem still fails: imported guest
memory cannot be write-watched on Linux, which the shadow buffers in vk_memory.c will address.
2026-10-29 16:56:56 -03:00

83 lines
3.6 KiB
C++

// SDL3 adapter of the in-game menu: the window's events to menu events (menu.h), as ui/menu_win.cpp does for Win32.
// Window thread (gfx_window_sdl.c's event loop, after input_sdl_event).
//
// F1 opens and closes the menu, Esc opens it (with the menu open, Esc goes to the menu, which closes). Esc also releases
// the cursor (input_sdl.c sees the event first; closing the menu gives the capture back). While the menu is open, its
// keys, the mouse and focus changes go to it; the game reads the keyboard through input_sdl.c and gets nothing while
// the menu is open (input_menu). Mouse positions come in window units and go to the menu in pixels.
#include <SDL3/SDL.h>
#include "imgui.h"
extern "C" {
#include "input.h"
#include "input_sdl.h"
#include "ui/menu.h"
}
static ImGuiKey key_of(SDL_Scancode sc) {
switch (sc) {
case SDL_SCANCODE_UP: return ImGuiKey_UpArrow;
case SDL_SCANCODE_DOWN: return ImGuiKey_DownArrow;
case SDL_SCANCODE_LEFT: return ImGuiKey_LeftArrow;
case SDL_SCANCODE_RIGHT: return ImGuiKey_RightArrow;
case SDL_SCANCODE_RETURN: case SDL_SCANCODE_KP_ENTER: return ImGuiKey_Enter;
case SDL_SCANCODE_SPACE: return ImGuiKey_Space;
case SDL_SCANCODE_ESCAPE: return ImGuiKey_Escape;
case SDL_SCANCODE_TAB: return ImGuiKey_Tab;
case SDL_SCANCODE_BACKSPACE: return ImGuiKey_Backspace;
case SDL_SCANCODE_DELETE: return ImGuiKey_Delete; // clears a cell of the remapping rows
case SDL_SCANCODE_HOME: return ImGuiKey_Home;
case SDL_SCANCODE_END: return ImGuiKey_End;
case SDL_SCANCODE_PAGEUP: return ImGuiKey_PageUp;
case SDL_SCANCODE_PAGEDOWN: return ImGuiKey_PageDown;
case SDL_SCANCODE_LSHIFT: case SDL_SCANCODE_RSHIFT: return ImGuiKey_LeftShift;
case SDL_SCANCODE_LCTRL: case SDL_SCANCODE_RCTRL: return ImGuiKey_LeftCtrl;
case SDL_SCANCODE_Q: return ImGuiKey_Q; // previous tab
case SDL_SCANCODE_E: return ImGuiKey_E; // next tab
default: return ImGuiKey_None;
}
}
extern "C" void menu_sdl_event(const SDL_Event *e) {
float d = (float)gfx_window_sdl_density();
switch (e->type) {
case SDL_EVENT_KEY_DOWN:
// Esc with the menu open (opened by F1 too) is not a toggle here: it goes to the menu, which closes itself
if (!e->key.repeat && (e->key.scancode == SDL_SCANCODE_F1 ||
(e->key.scancode == SDL_SCANCODE_ESCAPE && !menu_is_open()))) {
menu_toggle();
return;
}
if (e->key.scancode == SDL_SCANCODE_F10) {
if (!e->key.repeat) menu_perf_cycle();
return;
}
[[fallthrough]];
case SDL_EVENT_KEY_UP:
if (!menu_is_open()) return;
if (ImGuiKey k = key_of(e->key.scancode)) menu_event_key(k, e->type == SDL_EVENT_KEY_DOWN);
return;
case SDL_EVENT_MOUSE_MOTION:
if (menu_is_open()) menu_event_mouse_pos(e->motion.x * d, e->motion.y * d);
return;
case SDL_EVENT_MOUSE_BUTTON_DOWN:
case SDL_EVENT_MOUSE_BUTTON_UP: {
if (!menu_is_open()) return;
int b = e->button.button == SDL_BUTTON_LEFT ? 0 : e->button.button == SDL_BUTTON_RIGHT ? 1
: e->button.button == SDL_BUTTON_MIDDLE ? 2 : -1;
if (b < 0) return;
menu_event_mouse_pos(e->button.x * d, e->button.y * d);
menu_event_mouse_button(b, e->type == SDL_EVENT_MOUSE_BUTTON_DOWN);
return;
}
case SDL_EVENT_MOUSE_WHEEL:
if (menu_is_open()) menu_event_wheel(e->wheel.x, e->wheel.y);
return;
case SDL_EVENT_WINDOW_FOCUS_GAINED:
case SDL_EVENT_WINDOW_FOCUS_LOST:
menu_event_focus(e->type == SDL_EVENT_WINDOW_FOCUS_GAINED);
return;
}
}