shithub: m8c

Download patch

ref: 9c06c3f1031aef6c4d256c52bb3d283aaeb3d19e
parent: 7ee19d3d5baa4da0fb7a06f82b5fb2a3f233fd4f
author: Jonne Kokkonen <jonne.kokkonen@gmail.com>
date: Fri Mar 28 08:02:56 EDT 2025

Add IOS event handlers

--- a/src/input.c
+++ b/src/input.c
@@ -117,19 +117,19 @@
     SDL_Scancode scancode;
     uint8_t value;
   } normal_key_map[] = {
-    {conf->key_up, key_up},
-    {conf->key_left, key_left},
-    {conf->key_down, key_down},
-    {conf->key_right, key_right},
-    {conf->key_select, key_select},
-    {conf->key_select_alt, key_select},
-    {conf->key_start, key_start},
-    {conf->key_start_alt, key_start},
-    {conf->key_opt, key_opt},
-    {conf->key_opt_alt, key_opt},
-    {conf->key_edit, key_edit},
-    {conf->key_edit_alt, key_edit},
-    {conf->key_delete, key_opt | key_edit},
+      {conf->key_up, key_up},
+      {conf->key_left, key_left},
+      {conf->key_down, key_down},
+      {conf->key_right, key_right},
+      {conf->key_select, key_select},
+      {conf->key_select_alt, key_select},
+      {conf->key_start, key_start},
+      {conf->key_start_alt, key_start},
+      {conf->key_opt, key_opt},
+      {conf->key_opt_alt, key_opt},
+      {conf->key_edit, key_edit},
+      {conf->key_edit_alt, key_edit},
+      {conf->key_delete, key_opt | key_edit},
   };
 
   // Handle special messages (different message type)
@@ -137,8 +137,8 @@
     SDL_Scancode scancode;
     special_messages_t message;
   } special_key_map[] = {
-    {conf->key_reset, msg_reset_display},
-    {conf->key_toggle_audio, msg_toggle_audio},
+      {conf->key_reset, msg_reset_display},
+      {conf->key_toggle_audio, msg_toggle_audio},
   };
 
   // Check normal key mappings
--- a/src/main.c
+++ b/src/main.c
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 
 enum app_state app_state = WAIT_FOR_DEVICE;
+unsigned char device_connected = 0;
 
 // Handle CTRL+C / SIGINT, SIGKILL etc.
 static void signal_handler(int unused) {
@@ -35,9 +36,8 @@
 #endif
 }
 
-
 static void do_wait_for_device(const char *preferred_device, unsigned char *m8_connected,
-                        config_params_s *conf) {
+                               config_params_s *conf) {
   static Uint64 ticks_poll_device = 0;
   static Uint64 ticks_update_screen = 0;
 
@@ -88,7 +88,8 @@
   }
 }
 
-static config_params_s initialize_config(int argc, char *argv[], char **preferred_device, char **config_filename) {
+static config_params_s initialize_config(int argc, char *argv[], char **preferred_device,
+                                         char **config_filename) {
   for (int i = 1; i < argc; i++) {
     if (SDL_strcmp(argv[i], "--list") == 0) {
       exit(m8_list_devices());
@@ -123,7 +124,8 @@
   SDL_Log("Shutting down.");
 }
 
-static unsigned char handle_device_initialization(unsigned char wait_for_device, const char *preferred_device) {
+static unsigned char handle_device_initialization(unsigned char wait_for_device,
+                                                  const char *preferred_device) {
   const unsigned char device_connected = m8_initialize(1, preferred_device);
   if (!wait_for_device && device_connected == 0) {
     SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "Device not detected!");
@@ -132,8 +134,55 @@
   return device_connected;
 }
 
+#if TARGET_OS_IOS
+// IOS events handler
+unsigned char handle_app_events(void *userdata, SDL_Event *event) {
+  const config_params_s *conf = (config_params_s *)userdata;
+  switch (event->type) {
+  case SDL_EVENT_TERMINATING:
+    /* Terminate the app.
+       Shut everything down before returning from this function.
+    */
+    cleanup_resources(device_connected, conf);
+    return 0;
+  case SDL_EVENT_DID_ENTER_BACKGROUND:
+    /* This will get called if the user accepted whatever sent your app to the background.
+       If the user got a phone call and canceled it, you'll instead get an
+       SDL_EVENT_DID_ENTER_FOREGROUND event and restart your loops. When you get this, you have 5
+       seconds to save all your state or the app will be terminated. Your app is NOT active at this
+       point.
+    */
+    m8_close(); // Disconnect so that buffers and queues don't fill up
+    device_connected = 0;
+    app_state = WAIT_FOR_DEVICE;
+    return 0;
+  case SDL_EVENT_LOW_MEMORY:
+    /* You will get this when your app is paused and iOS wants more memory.
+       Release as much memory as possible.
+    */
+    return 0;
+  case SDL_EVENT_WILL_ENTER_BACKGROUND:
+    /* Prepare your app to go into the background.  Stop loops, etc.
+       This gets called when the user hits the home button, or gets a call.
+    */
+    return 0;
+  case SDL_EVENT_WILL_ENTER_FOREGROUND:
+    /* This call happens when your app is coming back to the foreground.
+       Restore all your state here.
+    */
+  case SDL_EVENT_DID_ENTER_FOREGROUND:
+    /* Restart your loops here.
+       Your app is interactive and getting CPU again.
+    */
+    return 0;
+  default:
+    /* No special processing, add it to the event queue */
+    return 1;
+  }
+}
+#endif // TARGET_OS_IOS
+
 static void main_loop(config_params_s *conf, const char *preferred_device) {
-  unsigned char device_connected = 0;
 
   do {
     device_connected = m8_initialize(1, preferred_device);
@@ -140,7 +189,7 @@
     if (device_connected && m8_enable_and_reset_display()) {
       if (conf->audio_enabled) {
         audio_initialize(conf->audio_device_name, conf->audio_buffer_size);
-        m8_reset_display();  // Avoid display glitches.
+        m8_reset_display(); // Avoid display glitches.
       }
       app_state = RUN;
     } else {
@@ -174,7 +223,6 @@
   cleanup_resources(device_connected, conf);
 }
 
-
 int main(const int argc, char *argv[]) {
   char *preferred_device = NULL;
   char *config_filename = NULL;
@@ -182,12 +230,18 @@
   config_params_s conf = initialize_config(argc, argv, &preferred_device, &config_filename);
   initialize_signals();
 
-  const unsigned char initial_device_connected = handle_device_initialization(conf.wait_for_device, preferred_device);
+  const unsigned char initial_device_connected =
+      handle_device_initialization(conf.wait_for_device, preferred_device);
   if (!renderer_initialize(conf.init_fullscreen)) {
     SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "Failed to initialize renderer.");
     cleanup_resources(initial_device_connected, &conf);
     return EXIT_FAILURE;
   }
+
+#if TARGET_OS_IOS
+  // IOS events handler
+  SDL_SetEventFilter(handle_app_events, &conf);
+#endif
 
   gamecontrollers_initialize();
 
--