shithub: m8c

Download patch

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) {
--