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();
--
⑨