ref: ff835dd2004173c5b994e7793d004f39fd7ccba0
parent: 9a669c32d7bb6e5edee452dd3bfbcd1426b38ed5
author: laamaa <jonne.kokkonen@gmail.com>
date: Wed Sep 10 18:46:00 EDT 2025
add gamepad event handling for settings navigation and guide button functionality
--- a/src/events.c
+++ b/src/events.c
@@ -8,6 +8,8 @@
#include <SDL3/SDL.h>
#include <SDL3/SDL_events.h>
+static Uint64 g_guide_pressed_at = 0;
+
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {struct app_context *ctx = appstate;
SDL_AppResult ret_val = SDL_APP_CONTINUE;
@@ -80,6 +82,12 @@
break;
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
+ // Start measuring hold time for GUIDE; trigger handled on button up after 1s hold
+ if (event->gbutton.button == SDL_GAMEPAD_BUTTON_GUIDE) {+ g_guide_pressed_at = SDL_GetTicks();
+ return ret_val;
+ }
+
if (settings_is_open()) {settings_handle_event(ctx, event);
return ret_val;
@@ -88,6 +96,16 @@
break;
case SDL_EVENT_GAMEPAD_BUTTON_UP:
+ // Handle GUIDE release: toggle settings if held for at least 1 second
+ if (event->gbutton.button == SDL_GAMEPAD_BUTTON_GUIDE) {+ Uint64 now = SDL_GetTicks();
+ if (g_guide_pressed_at != 0 && (now - g_guide_pressed_at) >= 1000) {+ settings_toggle_open();
+ }
+ g_guide_pressed_at = 0;
+ return ret_val;
+ }
+
if (settings_is_open()) {settings_handle_event(ctx, event);
return ret_val;
--- a/src/settings.c
+++ b/src/settings.c
@@ -345,6 +345,105 @@
}
}
+ // Gamepad navigation and cancel/back handling
+ if (e->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) {+ SDL_GamepadButton btn = e->gbutton.button;
+
+ // Cancel capture or go back/close with B/Back
+ if (btn == SDL_GAMEPAD_BUTTON_EAST || btn == SDL_GAMEPAD_BUTTON_BACK) {+ if (g_capture_mode != CAPTURE_NONE) {+ g_capture_mode = CAPTURE_NONE;
+ g_capture_target = NULL;
+ g_needs_redraw = 1;
+ return;
+ }
+ if (g_view != VIEW_ROOT) {+ g_view = VIEW_ROOT;
+ g_selected_index = 1;
+ g_needs_redraw = 1;
+ return;
+ }
+ settings_toggle_open();
+ return;
+ }
+
+ // If capturing a button, let the capture handler below process it
+ if (g_capture_mode == CAPTURE_NONE) {+ // D-pad navigation
+ if (btn == SDL_GAMEPAD_BUTTON_DPAD_UP) {+ settings_move(&ctx->conf, -1);
+ return;
+ }
+ if (btn == SDL_GAMEPAD_BUTTON_DPAD_DOWN) {+ settings_move(&ctx->conf, 1);
+ return;
+ }
+ if (btn == SDL_GAMEPAD_BUTTON_DPAD_LEFT || btn == SDL_GAMEPAD_BUTTON_DPAD_RIGHT) {+ setting_item_s items[64];
+ int count = 0;
+ build_menu(&ctx->conf, items, &count);
+ if (g_selected_index > 0 && g_selected_index < count) {+ setting_item_s *it = &items[g_selected_index];
+ if (it->type == ITEM_INT_ADJ && it->target != NULL) {+ int *val = (int *)it->target;
+ int delta = (btn == SDL_GAMEPAD_BUTTON_DPAD_LEFT ? -it->step : it->step);
+ int newv = *val + delta;
+ if (newv < it->min_val)
+ newv = it->min_val;
+ if (newv > it->max_val)
+ newv = it->max_val;
+ *val = newv;
+ g_needs_redraw = 1;
+ return;
+ }
+ }
+ }
+ // Activate/select with A
+ if (btn == SDL_GAMEPAD_BUTTON_SOUTH) {+ setting_item_s items[64];
+ int count = 0;
+ build_menu(&ctx->conf, items, &count);
+ // Handle entering submenus from root based on item type
+ if (g_view == VIEW_ROOT) {+ const setting_item_s *it = &items[g_selected_index];
+ if (it->type == ITEM_SUBMENU && it->label &&
+ SDL_strstr(it->label, "Keyboard bindings") == it->label) {+ g_view = VIEW_KEYS;
+ g_selected_index = 1;
+ g_needs_redraw = 1;
+ return;
+ }
+ if (it->type == ITEM_SUBMENU && it->label &&
+ SDL_strstr(it->label, "Gamepad bindings") == it->label) {+ g_view = VIEW_GAMEPAD;
+ g_selected_index = 1;
+ g_needs_redraw = 1;
+ return;
+ }
+ if (it->type == ITEM_SUBMENU && it->label &&
+ SDL_strstr(it->label, "Gamepad analog axis") == it->label) {+ g_view = VIEW_ANALOG;
+ g_selected_index = 1;
+ g_needs_redraw = 1;
+ return;
+ }
+ }
+ // Back item in submenus
+ if (g_view != VIEW_ROOT) {+ const setting_item_s *it = &items[g_selected_index];
+ if (it->type == ITEM_CLOSE && it->label && SDL_strcmp(it->label, "Back") == 0) {+ g_view = VIEW_ROOT;
+ g_selected_index = 1;
+ g_needs_redraw = 1;
+ return;
+ }
+ }
+ settings_activate(ctx, items, count);
+ return;
+ }
+ }
+ }
+
// Capture gamepad button
if (g_capture_mode == CAPTURE_BUTTON && e->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) { if (g_capture_target != NULL) {--
⑨