From 46d8de1fe5038012073056c32b32964e630c1cc0 Mon Sep 17 00:00:00 2001 From: thesource Date: Sat, 19 Apr 2025 18:53:43 +0300 Subject: [PATCH] Linux/GTK: add support for gamepad touchpad -> touch screen input translation --- desmume/src/frontend/posix/cli/main.cpp | 2 +- desmume/src/frontend/posix/gtk/main.cpp | 59 +-- desmume/src/frontend/posix/gtk2/main.cpp | 59 +-- .../src/frontend/posix/shared/ctrlssdl.cpp | 455 +++++++++++++----- desmume/src/frontend/posix/shared/ctrlssdl.h | 12 +- 5 files changed, 381 insertions(+), 206 deletions(-) diff --git a/desmume/src/frontend/posix/cli/main.cpp b/desmume/src/frontend/posix/cli/main.cpp index 45f12e1e4..d3e0643be 100644 --- a/desmume/src/frontend/posix/cli/main.cpp +++ b/desmume/src/frontend/posix/cli/main.cpp @@ -493,7 +493,7 @@ int main(int argc, char ** argv) { fprintf(stderr, "Warning: X11 not thread-safe\n"); } - if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) == -1) + if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK| SDL_INIT_GAMECONTROLLER) == -1) { fprintf(stderr, "Error trying to initialize SDL: %s\n", SDL_GetError()); diff --git a/desmume/src/frontend/posix/gtk/main.cpp b/desmume/src/frontend/posix/gtk/main.cpp index 7003838d8..4a89f573a 100644 --- a/desmume/src/frontend/posix/gtk/main.cpp +++ b/desmume/src/frontend/posix/gtk/main.cpp @@ -2086,48 +2086,11 @@ static gboolean JoyKeyAcceptTimerFunc(gpointer data) { if(!in_joy_config_mode) return FALSE; - SDL_Event event; - u16 key; - bool done = FALSE; - while(SDL_PollEvent(&event) && !done) - { - switch(event.type) - { - case SDL_JOYBUTTONDOWN: - key = ((get_joystick_number_by_id(event.jbutton.which) & 15) << 12) | JOY_BUTTON << 8 | (event.jbutton.button & 255); - done = TRUE; - break; - case SDL_JOYAXISMOTION: - if( ((u32)abs(event.jaxis.value) >> 14) != 0 ) - { - key = ((get_joystick_number_by_id(event.jaxis.which) & 15) << 12) | JOY_AXIS << 8 | ((event.jaxis.axis & 127) << 1); - if (event.jaxis.value > 0) - key |= 1; - done = TRUE; - } - break; - case SDL_JOYHATMOTION: - if (event.jhat.value != SDL_HAT_CENTERED) { - key = ((get_joystick_number_by_id(event.jhat.which) & 15) << 12) | JOY_HAT << 8 | ((event.jhat.hat & 63) << 2); - if ((event.jhat.value & SDL_HAT_UP) != 0) - key |= JOY_HAT_UP; - else if ((event.jhat.value & SDL_HAT_RIGHT) != 0) - key |= JOY_HAT_RIGHT; - else if ((event.jhat.value & SDL_HAT_DOWN) != 0) - key |= JOY_HAT_DOWN; - else if ((event.jhat.value & SDL_HAT_LEFT) != 0) - key |= JOY_HAT_LEFT; - done = TRUE; - } - break; - default: - do_process_joystick_device_events(&event); - break; - } - } - - if(done) { - struct modify_key_ctx *ctx = (struct modify_key_ctx*)data; + struct modify_key_ctx *ctx = (struct modify_key_ctx*)data; + bool modified = FALSE; + u16 key=get_joy_key(ctx->key_id, &modified); + if(modified) { + ctx->mk_key_chosen = key; gchar* YouPressed = g_strdup_printf("You pressed : %d\nClick OK to keep this key.", ctx->mk_key_chosen); gtk_label_set_text(GTK_LABEL(ctx->label), YouPressed); @@ -2926,6 +2889,16 @@ gboolean EmuLoop(gpointer data) process_joystick_events(&keys_latch); /* Update! */ update_keypad(keys_latch); + /* Update mouse position and click (source - game controller touchpad)*/ + if(touchpad.down) { + NDS_setTouchPos(touchpad.x * 256, touchpad.y * 192); + touchpad.down = 2; + } + if(touchpad.click) + { + NDS_releaseTouch(); + touchpad.click = 0; + } desmume_cycle(); /* Emule ! */ @@ -3415,7 +3388,7 @@ common_gtk_main(GApplication *app, gpointer user_data) /* FIXME: SDL_INIT_VIDEO is needed for joystick support to work!? * Perhaps it needs a "window" to catch events...? */ SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,"1"); - if(SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO) == -1) { + if(SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO|SDL_INIT_JOYSTICK|SDL_INIT_GAMECONTROLLER) == -1) { g_printerr("Error trying to initialize SDL: %s\n", SDL_GetError()); // TODO: return a non-zero exit status. diff --git a/desmume/src/frontend/posix/gtk2/main.cpp b/desmume/src/frontend/posix/gtk2/main.cpp index 9ca1eda62..a6d9163cf 100644 --- a/desmume/src/frontend/posix/gtk2/main.cpp +++ b/desmume/src/frontend/posix/gtk2/main.cpp @@ -2269,48 +2269,11 @@ static gboolean JoyKeyAcceptTimerFunc(gpointer data) { if(!in_joy_config_mode) return FALSE; - SDL_Event event; - u16 key; - bool done = FALSE; - while(SDL_PollEvent(&event) && !done) - { - switch(event.type) - { - case SDL_JOYBUTTONDOWN: - key = ((get_joystick_number_by_id(event.jbutton.which) & 15) << 12) | JOY_BUTTON << 8 | (event.jbutton.button & 255); - done = TRUE; - break; - case SDL_JOYAXISMOTION: - if( ((u32)abs(event.jaxis.value) >> 14) != 0 ) - { - key = ((get_joystick_number_by_id(event.jaxis.which) & 15) << 12) | JOY_AXIS << 8 | ((event.jaxis.axis & 127) << 1); - if (event.jaxis.value > 0) - key |= 1; - done = TRUE; - } - break; - case SDL_JOYHATMOTION: - if (event.jhat.value != SDL_HAT_CENTERED) { - key = ((get_joystick_number_by_id(event.jhat.which) & 15) << 12) | JOY_HAT << 8 | ((event.jhat.hat & 63) << 2); - if ((event.jhat.value & SDL_HAT_UP) != 0) - key |= JOY_HAT_UP; - else if ((event.jhat.value & SDL_HAT_RIGHT) != 0) - key |= JOY_HAT_RIGHT; - else if ((event.jhat.value & SDL_HAT_DOWN) != 0) - key |= JOY_HAT_DOWN; - else if ((event.jhat.value & SDL_HAT_LEFT) != 0) - key |= JOY_HAT_LEFT; - done = TRUE; - } - break; - default: - do_process_joystick_device_events(&event); - break; - } - } - - if(done) { - struct modify_key_ctx *ctx = (struct modify_key_ctx*)data; + struct modify_key_ctx *ctx = (struct modify_key_ctx*)data; + bool modified = FALSE; + u16 key=get_joy_key(ctx->key_id, &modified); + if(modified) { + ctx->mk_key_chosen = key; gchar* YouPressed = g_strdup_printf("You pressed : %d\nClick OK to keep this key.", ctx->mk_key_chosen); gtk_label_set_text(GTK_LABEL(ctx->label), YouPressed); @@ -3107,6 +3070,16 @@ gboolean EmuLoop(gpointer data) process_joystick_events(&keys_latch); /* Update! */ update_keypad(keys_latch); + /* Update mouse position and click (source - game controller touchpad)*/ + if(touchpad.down) { + NDS_setTouchPos(touchpad.x * 256, touchpad.y * 192); + touchpad.down = 2; + } + if(touchpad.click) + { + NDS_releaseTouch(); + touchpad.click = 0; + } desmume_cycle(); /* Emule ! */ @@ -3538,7 +3511,7 @@ common_gtk_main( class configured_features *my_config) /* FIXME: SDL_INIT_VIDEO is needed for joystick support to work!? * Perhaps it needs a "window" to catch events...? */ SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,"1"); - if(SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO) == -1) { + if(SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO|SDL_INIT_JOYSTICK|SDL_INIT_GAMECONTROLLER) == -1) { g_printerr("Error trying to initialize SDL: %s\n", SDL_GetError()); return 1; diff --git a/desmume/src/frontend/posix/shared/ctrlssdl.cpp b/desmume/src/frontend/posix/shared/ctrlssdl.cpp index e06d81a63..0b25e8c10 100644 --- a/desmume/src/frontend/posix/shared/ctrlssdl.cpp +++ b/desmume/src/frontend/posix/shared/ctrlssdl.cpp @@ -36,10 +36,20 @@ u32 joypad_cfg[NB_KEYS]; static_assert(sizeof(keyboard_cfg) == sizeof(joypad_cfg), ""); mouse_status mouse; +touchpad_status touchpad = {0.0, 0.0, 0, 0}; static int fullscreen; -//List of currently connected joysticks (key - instance id, value - SDL_Joystick structure, joystick number) -static std::pair open_joysticks[MAX_JOYSTICKS]; +struct JoystickInfo +{ + bool isController; + union { + SDL_Joystick* joy; + SDL_GameController* gcont; + } handle; + SDL_JoystickID id; +}; + +static JoystickInfo open_joysticks[MAX_JOYSTICKS]; /* Keypad key names */ const char *key_names[NB_KEYS] = @@ -117,26 +127,44 @@ BOOL init_joy( void) { } for(i=0; i 0) { printf("Found %d joysticks\n", nbr_joy); for (i = 0; i < nbr_joy; i++) { - SDL_Joystick * joy = SDL_JoystickOpen(i); - if(joy) { - printf("Joystick %d %s\n", i, SDL_JoystickNameForIndex(i)); - printf("Axes: %d\n", SDL_JoystickNumAxes(joy)); - printf("Buttons: %d\n", SDL_JoystickNumButtons(joy)); - printf("Trackballs: %d\n", SDL_JoystickNumBalls(joy)); - printf("Hats: %d\n\n", SDL_JoystickNumHats(joy)); - open_joysticks[i]=std::make_pair(joy, SDL_JoystickInstanceID(joy)); + if(SDL_IsGameController(i)) { + SDL_GameController * gcont = SDL_GameControllerOpen(i); + if(gcont) { + printf("Game controller %d %s\n", i, SDL_GameControllerNameForIndex(i)); + printf("Axes: %d\n", SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(gcont))); + printf("Buttons: %d\n", SDL_JoystickNumButtons(SDL_GameControllerGetJoystick(gcont))); + printf("Touchpads: %d\n", SDL_GameControllerGetNumTouchpads(gcont)); + printf("%s\n", SDL_GameControllerHasSensor(gcont, SDL_SENSOR_ACCEL) ? "Accelerometer present" : "Accelerometer not present"); + printf("%s\n", SDL_GameControllerHasSensor(gcont, SDL_SENSOR_GYRO) ? "Gyroscope present" : "Gyroscope not present"); + open_joysticks[i]={TRUE, {.gcont=gcont}, SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gcont))}; + } + else { + fprintf(stderr, "Failed to open game controller %d: %s\n", i, SDL_GetError()); + joy_init_good = FALSE; + } } else { - fprintf(stderr, "Failed to open joystick %d: %s\n", i, SDL_GetError()); - joy_init_good = FALSE; + SDL_Joystick * joy = SDL_JoystickOpen(i); + if(joy) { + printf("Joystick %d %s\n", i, SDL_JoystickNameForIndex(i)); + printf("Axes: %d\n", SDL_JoystickNumAxes(joy)); + printf("Buttons: %d\n", SDL_JoystickNumButtons(joy)); + printf("Trackballs: %d\n", SDL_JoystickNumBalls(joy)); + printf("Hats: %d\n\n", SDL_JoystickNumHats(joy)); + open_joysticks[i]={FALSE, {joy}, SDL_JoystickInstanceID(joy)}; + } + else { + fprintf(stderr, "Failed to open joystick %d: %s\n", i, SDL_GetError()); + joy_init_good = FALSE; + } } } } @@ -149,10 +177,15 @@ void uninit_joy( void) { int i; for (i=0; i> 14) != 0 ) + jn=get_joystick_number_by_id(event.jbutton.which); + if(!open_joysticks[jn].isController) { - key = ((get_joystick_number_by_id(event.jaxis.which) & 15) << 12) | JOY_AXIS << 8 | ((event.jaxis.axis & 127) << 1); - if (event.jaxis.value > 0) { - printf( "Device: %d; Axis: %d (+)\n", event.jaxis.which, event.jaxis.axis ); - key |= 1; - } - else - printf( "Device: %d; Axis: %d (-)\n", event.jaxis.which, event.jaxis.axis ); - done = TRUE; + etype=0; + bnum=event.jbutton.button; } - break; + break; + case SDL_CONTROLLERBUTTONDOWN: + jn=get_joystick_number_by_id(event.cbutton.which); + if(open_joysticks[jn].isController) + { + etype=0; + bnum=event.cbutton.button; + } + break; + case SDL_JOYAXISMOTION: + jn=get_joystick_number_by_id(event.jaxis.which); + if(!open_joysticks[jn].isController) + { + etype=1; + bnum=event.jaxis.axis; + aval=event.jaxis.value; + } + break; + case SDL_CONTROLLERAXISMOTION: + jn=get_joystick_number_by_id(event.caxis.which); + if(open_joysticks[jn].isController) + { + etype=1; + bnum=event.caxis.axis; + aval=event.caxis.value; + } + break; case SDL_JOYHATMOTION: - /* Diagonal positions will be treated as two separate keys being activated, rather than a single diagonal key. */ - /* JOY_HAT_* are sequential integers, rather than a bitmask */ - if (event.jhat.value != SDL_HAT_CENTERED) { - key = ((get_joystick_number_by_id(event.jhat.which) & 15) << 12) | JOY_HAT << 8 | ((event.jhat.hat & 63) << 2); - /* Can't just use a switch here because SDL_HAT_* make up a bitmask. We only want one of these when assigning keys. */ - if ((event.jhat.value & SDL_HAT_UP) != 0) { - key |= JOY_HAT_UP; - printf( "Device: %d; Hat: %d (Up)\n", event.jhat.which, event.jhat.hat ); + jn=get_joystick_number_by_id(event.jhat.which); + if(!open_joysticks[jn].isController) + { + etype=2; + bnum=event.jhat.hat; + bval=event.jhat.value; } - else if ((event.jhat.value & SDL_HAT_RIGHT) != 0) { - key |= JOY_HAT_RIGHT; - printf( "Device: %d; Hat: %d (Right)\n", event.jhat.which, event.jhat.hat ); - } - else if ((event.jhat.value & SDL_HAT_DOWN) != 0) { - key |= JOY_HAT_DOWN; - printf( "Device: %d; Hat: %d (Down)\n", event.jhat.which, event.jhat.hat ); - } - else if ((event.jhat.value & SDL_HAT_LEFT) != 0) { - key |= JOY_HAT_LEFT; - printf( "Device: %d; Hat: %d (Left)\n", event.jhat.which, event.jhat.hat ); - } - done = TRUE; - } - break; + break; + default: + do_process_joystick_device_events(&event); + break; + } + + switch(etype) + { + case 0: + key = ((jn & 15) << 12) | JOY_BUTTON << 8 | (bnum & 255); + done = TRUE; + break; + case 1: + if( ((u32)abs(aval) >> 14) != 0 ) + { + key = ((jn & 15) << 12) | JOY_AXIS << 8 | ((bnum & 127) << 1); + if (aval > 0) + key |= 1; + done = TRUE; + } + break; + case 2: + if (bval != SDL_HAT_CENTERED) { + key = ((jn & 15) << 12) | JOY_HAT << 8 | ((bnum & 63) << 2); + if ((bval & SDL_HAT_UP) != 0) + key |= JOY_HAT_UP; + else if ((bval & SDL_HAT_RIGHT) != 0) + key |= JOY_HAT_RIGHT; + else if ((bval & SDL_HAT_DOWN) != 0) + key |= JOY_HAT_DOWN; + else if ((bval & SDL_HAT_LEFT) != 0) + key |= JOY_HAT_LEFT; + done = TRUE; + } + break; } } - - if( SDL_JoystickEventState(SDL_QUERY) == SDL_ENABLE ) - SDL_JoystickEventState(SDL_IGNORE); - - return key; + if(modified) + (*modified)=done; + return key; } /* Get and set a new joystick key */ @@ -372,16 +440,126 @@ do_process_joystick_events( u16 *keypad, SDL_Event *event) { u16 key_r; u16 key_d; u16 key_l; + + int jn, etype=-1; + Sint16 aval; + Uint8 bnum, bval; switch ( event->type) { - /* Joystick axis motion - Note: button constants have a 1bit offset. */ case SDL_JOYAXISMOTION: - key_code = ((get_joystick_number_by_id(event->jaxis.which) & 15) << 12) | JOY_AXIS << 8 | ((event->jaxis.axis & 127) << 1); - if( ((u32)abs(event->jaxis.value) >> 14) != 0 ) + jn=get_joystick_number_by_id(event->jaxis.which); + if(!open_joysticks[jn].isController) + { + etype=0; + bnum=event->jaxis.axis; + aval=event->jaxis.value; + } + break; + + case SDL_JOYHATMOTION: + jn=get_joystick_number_by_id(event->jhat.which); + if(!open_joysticks[jn].isController) + { + etype=1; + bnum=event->jhat.hat; + bval=event->jhat.value; + } + break; + + case SDL_JOYBUTTONDOWN: + jn=get_joystick_number_by_id(event->jbutton.which); + if(!open_joysticks[jn].isController) + { + etype=2; + bnum=event->jbutton.button; + } + break; + + case SDL_JOYBUTTONUP: + jn=get_joystick_number_by_id(event->jbutton.which); + if(!open_joysticks[jn].isController) + { + etype=3; + bnum=event->jbutton.button; + } + break; + + case SDL_CONTROLLERAXISMOTION: + jn=get_joystick_number_by_id(event->caxis.which); + if(open_joysticks[jn].isController) + { + etype=0; + bnum=event->caxis.axis; + aval=event->caxis.value; + } + break; + + case SDL_CONTROLLERBUTTONDOWN: + jn=get_joystick_number_by_id(event->cbutton.which); + if(open_joysticks[jn].isController) + { + etype=2; + bnum=event->cbutton.button; + } + break; + + case SDL_CONTROLLERBUTTONUP: + jn=get_joystick_number_by_id(event->cbutton.which); + if(open_joysticks[jn].isController) + { + etype=3; + bnum=event->cbutton.button; + } + break; + + case SDL_CONTROLLERTOUCHPADDOWN: + jn=get_joystick_number_by_id(event->ctouchpad.which); + if(open_joysticks[jn].isController) + { + if(event->ctouchpad.finger==0) + if(!touchpad.down) + touchpad.down=1; + } + break; + + case SDL_CONTROLLERTOUCHPADMOTION: + jn=get_joystick_number_by_id(event->ctouchpad.which); + if(open_joysticks[jn].isController) + if(event->ctouchpad.finger==0) { - if (event->jaxis.value > 0) + touchpad.x=event->ctouchpad.x; + touchpad.y=event->ctouchpad.y; + } + break; + + case SDL_CONTROLLERTOUCHPADUP: + jn=get_joystick_number_by_id(event->ctouchpad.which); + if(open_joysticks[jn].isController) + { + if(event->ctouchpad.finger==0) + if(touchpad.down) + { + touchpad.click = 1; + if(touchpad.down > 1) touchpad.down = 0; + } + } + break; + + default: + processed = 0; + break; + } + + switch(etype) + { + /* Joystick axis motion + Note: button constants have a 1bit offset. */ + case 0: + key_code = ((jn & 15) << 12) | JOY_AXIS << 8 | ((bnum & 127) << 1); + if( ((u32)abs(aval) >> 14) != 0 ) + { + if (aval > 0) key_code |= 1; key = lookup_joy_key( key_code ); key_o = lookup_joy_key( key_code ^ 1 ); @@ -401,53 +579,49 @@ do_process_joystick_events( u16 *keypad, SDL_Event *event) { RM_KEY( *keypad, key_o ); } break; - - case SDL_JOYHATMOTION: - /* Diagonal positions will be treated as two separate keys being activated, rather than a single diagonal key. */ - /* JOY_HAT_* are sequential integers, rather than a bitmask */ - key_code = ((get_joystick_number_by_id(event->jhat.which) & 15) << 12) | JOY_HAT << 8 | ((event->jhat.hat & 63) << 2); + + /* Diagonal positions will be treated as two separate keys being activated, rather than a single diagonal key. */ + /* JOY_HAT_* are sequential integers, rather than a bitmask */ + case 1: + key_code = ((jn & 15) << 12) | JOY_HAT << 8 | ((bnum & 63) << 2); key_u = lookup_joy_key( key_code | JOY_HAT_UP ); key_r = lookup_joy_key( key_code | JOY_HAT_RIGHT ); key_d = lookup_joy_key( key_code | JOY_HAT_DOWN ); key_l = lookup_joy_key( key_code | JOY_HAT_LEFT ); - if ((key_u != 0) && ((event->jhat.value & SDL_HAT_UP) != 0)) + if ((key_u != 0) && ((bval & SDL_HAT_UP) != 0)) ADD_KEY( *keypad, key_u ); else if (key_u != 0) RM_KEY( *keypad, key_u ); - if ((key_r != 0) && ((event->jhat.value & SDL_HAT_RIGHT) != 0)) + if ((key_r != 0) && ((bval & SDL_HAT_RIGHT) != 0)) ADD_KEY( *keypad, key_r ); else if (key_r != 0) RM_KEY( *keypad, key_r ); - if ((key_d != 0) && ((event->jhat.value & SDL_HAT_DOWN) != 0)) + if ((key_d != 0) && ((bval & SDL_HAT_DOWN) != 0)) ADD_KEY( *keypad, key_d ); else if (key_d != 0) RM_KEY( *keypad, key_d ); - if ((key_l != 0) && ((event->jhat.value & SDL_HAT_LEFT) != 0)) + if ((key_l != 0) && ((bval & SDL_HAT_LEFT) != 0)) ADD_KEY( *keypad, key_l ); else if (key_l != 0) RM_KEY( *keypad, key_l ); break; - - /* Joystick button pressed */ - case SDL_JOYBUTTONDOWN: - key_code = ((get_joystick_number_by_id(event->jbutton.which) & 15) << 12) | JOY_BUTTON << 8 | (event->jbutton.button & 255); + + /* Joystick button pressed */ + case 2: + key_code = ((jn & 15) << 12) | JOY_BUTTON << 8 | (bnum & 255); key = lookup_joy_key( key_code ); if (key != 0) ADD_KEY( *keypad, key ); break; - - /* Joystick button released */ - case SDL_JOYBUTTONUP: - key_code = ((get_joystick_number_by_id(event->jbutton.which) & 15) << 12) | JOY_BUTTON << 8 | (event->jbutton.button & 255); + + /* Joystick button released */ + case 3: + key_code = ((jn & 15) << 12) | JOY_BUTTON << 8 | (bnum & 255); key = lookup_joy_key( key_code ); if (key != 0) RM_KEY( *keypad, key ); break; - - default: - processed = 0; - break; - } + } return processed; } @@ -464,28 +638,32 @@ do_process_joystick_device_events(SDL_Event* event) { case SDL_JOYDEVICEREMOVED: n=get_joystick_number_by_id(event->jdevice.which); if(n != -1) { - printf("Joystick %d disconnected\n", n); - SDL_JoystickClose(open_joysticks[n].first); - open_joysticks[n]=std::make_pair((SDL_Joystick*)NULL, 0); + if(!open_joysticks[n].isController) { + printf("Joystick %d disconnected\n", n); + SDL_JoystickClose(open_joysticks[n].handle.joy); + open_joysticks[n]={FALSE, {NULL}, -1}; + } } break; /* Joystick connected */ case SDL_JOYDEVICEADDED: if(event->jdevice.whichjdevice.which].first) { - SDL_Joystick* joy = SDL_JoystickOpen(event->jdevice.which); - if(joy) { - printf("Joystick %d %s\n", event->jdevice.which, SDL_JoystickNameForIndex(event->jdevice.which)); - printf("Axes: %d\n", SDL_JoystickNumAxes(joy)); - printf("Buttons: %d\n", SDL_JoystickNumButtons(joy)); - printf("Trackballs: %d\n", SDL_JoystickNumBalls(joy)); - printf("Hats: %d\n\n", SDL_JoystickNumHats(joy)); - open_joysticks[event->jdevice.which]=std::make_pair(joy, SDL_JoystickInstanceID(joy)); + if(!SDL_IsGameController(event->jdevice.which)) { + //Filter connect events for joysticks already initialized in init_joy + if(!open_joysticks[event->jdevice.which].handle.joy) { + SDL_Joystick* joy = SDL_JoystickOpen(event->jdevice.which); + if(joy) { + printf("Joystick %d %s\n", event->jdevice.which, SDL_JoystickNameForIndex(event->jdevice.which)); + printf("Axes: %d\n", SDL_JoystickNumAxes(joy)); + printf("Buttons: %d\n", SDL_JoystickNumButtons(joy)); + printf("Trackballs: %d\n", SDL_JoystickNumBalls(joy)); + printf("Hats: %d\n\n", SDL_JoystickNumHats(joy)); + open_joysticks[event->jdevice.which]={FALSE, {joy}, SDL_JoystickInstanceID(joy)}; + } + else + fprintf(stderr, "Failed to open joystick %d: %s\n", event->jdevice.which, SDL_GetError()); } - else - fprintf(stderr, "Failed to open joystick %d: %s\n", event->jdevice.which, SDL_GetError()); } } else @@ -493,6 +671,44 @@ do_process_joystick_device_events(SDL_Event* event) { event->jdevice.which, MAX_JOYSTICKS-1); break; + /* Game controller disconnected */ + case SDL_CONTROLLERDEVICEREMOVED: + n=get_joystick_number_by_id(event->cdevice.which); + if(n != -1) { + if(open_joysticks[n].isController) { + printf("Game controller %d disconnected\n", n); + SDL_GameControllerClose(open_joysticks[n].handle.gcont); + open_joysticks[n]={FALSE, {NULL}, -1}; + } + } + break; + + /* Game controller connected */ + case SDL_CONTROLLERDEVICEADDED: + if(event->cdevice.whichcdevice.which)) { + //Filter connect events for joysticks already initialized in init_joy + if(!open_joysticks[event->cdevice.which].handle.gcont) { + SDL_GameController* gcont = SDL_GameControllerOpen(event->cdevice.which); + if(gcont) { + printf("Game controller %d %s\n", event->cdevice.which, SDL_GameControllerNameForIndex(event->cdevice.which)); + printf("Axes: %d\n", SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(gcont))); + printf("Buttons: %d\n", SDL_JoystickNumButtons(SDL_GameControllerGetJoystick(gcont))); + printf("Touchpads: %d\n", SDL_GameControllerGetNumTouchpads(gcont)); + printf("%s\n", SDL_GameControllerHasSensor(gcont, SDL_SENSOR_ACCEL) ? "Accelerometer present" : "Accelerometer not present"); + printf("%s\n", SDL_GameControllerHasSensor(gcont, SDL_SENSOR_GYRO) ? "Gyroscope present" : "Gyroscope not present"); + open_joysticks[event->cdevice.which]={TRUE, {.gcont=gcont}, SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gcont))}; + } + else + fprintf(stderr, "Failed to open game controller %d: %s\n", event->cdevice.which, SDL_GetError()); + } + } + } + else + printf("Game controller %d connected to the system, but maximum supported joystick index is %d, ignoring\n", + event->cdevice.which, MAX_JOYSTICKS-1); + break; + default: processed = 0; break; @@ -510,7 +726,9 @@ process_joystick_events( u16 *keypad) { /* IMPORTANT: Reenable joystick events if needed. */ if(SDL_JoystickEventState(SDL_QUERY) == SDL_IGNORE) SDL_JoystickEventState(SDL_ENABLE); - + if(SDL_GameControllerEventState(SDL_QUERY) == SDL_IGNORE) + SDL_GameControllerEventState(SDL_ENABLE); + /* There's an event waiting to be processed? */ while (SDL_PollEvent(&event)) { @@ -528,6 +746,8 @@ void process_joystick_device_events() { /* IMPORTANT: Reenable joystick events if needed. */ if(SDL_JoystickEventState(SDL_QUERY) == SDL_IGNORE) SDL_JoystickEventState(SDL_ENABLE); + if(SDL_GameControllerEventState(SDL_QUERY) == SDL_IGNORE) + SDL_GameControllerEventState(SDL_ENABLE); /* There's an event waiting to be processed? */ while (SDL_PollEvent(&event)) @@ -538,8 +758,7 @@ int get_joystick_number_by_id(SDL_JoystickID id) { int i; for(i=0; i=0) ++n; return n; } diff --git a/desmume/src/frontend/posix/shared/ctrlssdl.h b/desmume/src/frontend/posix/shared/ctrlssdl.h index 19d379394..ff81a4043 100644 --- a/desmume/src/frontend/posix/shared/ctrlssdl.h +++ b/desmume/src/frontend/posix/shared/ctrlssdl.h @@ -82,6 +82,16 @@ struct mouse_status extern mouse_status mouse; #endif // !GTK_UI +struct touchpad_status +{ + float x; + float y; + int down; + int click; +}; + +extern touchpad_status touchpad; + struct ctrls_event_config { unsigned short keypad; float nds_screen_size_ratio; @@ -98,7 +108,7 @@ struct ctrls_event_config { void load_default_config(const u32 kbCfg[]); BOOL init_joy( void); void uninit_joy( void); -u16 get_joy_key(int index); +u16 get_joy_key(int index, bool* modified=NULL); u16 get_set_joy_key(int index); void update_keypad(u16 keys); u16 get_keypad( void);