cli: fix joypad and keyboard config retrieval

because the GTK frontends use GDK keysyms, not SDL ones, - the former
are being stored in the config file and used by the GTK ui) -  a temporary
workaround was put into place 14 years ago: the loaded config values
were simply being overwritten with the hardcoded defaults.

this commit removes the overriding of the config, and introduces
a cli frontend specific section "SDLKEYS", which is written by the
GTK2 frontend upon a configuration change.
it tries to convert the GDK keycodes into SDL2 ones while doing so.

an alternative solution (involving less code changes) would have been
to do the conversion in the cli frontend, but that would require having
the gdk header available for compilation, which may not be the case
if the user only wants the cli frontend. such a user could now create
the config file on another machine with the GTK frontend, or simply
manually take the desired values from the SDL_keycode.h header.

this change is instigated by one of the changes in PR #822, which simply
removed the workaround and kept parsing on error, which mitigated the
problem for some keys, but not all.
This commit is contained in:
rofl0r 2024-10-27 16:19:13 +00:00
parent 0a36e96f66
commit 58bbe693e1
5 changed files with 312 additions and 15 deletions

View File

@ -526,10 +526,8 @@ int main(int argc, char ** argv) {
/* Initialize joysticks */
if(!init_joy()) return 1;
/* Load keyboard and joystick configuration */
keyfile = desmume_config_read_file(cli_kb_cfg);
keyfile = desmume_config_read_file(cli_kb_cfg, "SDLKEYS");
desmume_config_dispose(keyfile);
/* Since gtk has a different mapping the keys stop to work with the saved configuration :| */
load_default_config(cli_kb_cfg);
if(my_config.load_slot != -1){
loadstate_slot(my_config.load_slot);

View File

@ -2194,13 +2194,19 @@ static void Modify_Key(GtkWidget* widget, gpointer data)
}
#include "../shared/gdksdl.cpp"
static void Edit_Controls()
{
GtkWidget *ecDialog;
GtkWidget *ecKey;
gchar *Key_Label;
u32 keyboard_cfg_sdl[NB_KEYS];
int i;
g_assert(sizeof(Keypad_Temp) == sizeof(keyboard_cfg) &&
sizeof(keyboard_cfg) == sizeof(keyboard_cfg_sdl));
memcpy(&Keypad_Temp, &keyboard_cfg, sizeof(keyboard_cfg));
ecDialog = gtk_dialog_new_with_buttons("Edit controls",
@ -2222,8 +2228,17 @@ static void Edit_Controls()
switch (gtk_dialog_run(GTK_DIALOG(ecDialog))) {
case GTK_RESPONSE_OK:
memcpy(&keyboard_cfg, &Keypad_Temp, sizeof(keyboard_cfg));
desmume_config_update_keys(keyfile);
/* convert keycodes to SDL for the cli frontend, since it has no config menu */
for (i = 0; i < NB_KEYS; ++i) {
int sk = gdk_to_sdl_keycode(Keypad_Temp[i]);
/* if we don't know the keycode, chances are that SDL knows it anyways */
if (sk == -1) sk = (u32) Keypad_Temp[i];
keyboard_cfg_sdl[i] = sk;
}
memcpy(keyboard_cfg, keyboard_cfg_sdl, sizeof(keyboard_cfg));
desmume_config_update_keys(keyfile, "SDLKEYS");
memcpy(keyboard_cfg, Keypad_Temp, sizeof(keyboard_cfg));
desmume_config_update_keys(keyfile, "KEYS");
break;
case GTK_RESPONSE_CANCEL:
case GTK_RESPONSE_NONE:

View File

@ -25,7 +25,7 @@ static const gchar *desmume_old_config_file = ".desmume.ini";
static const gchar *desmume_config_dir = "desmume";
static const gchar *desmume_config_file = "config";
GKeyFile *desmume_config_read_file(const u32 *kb_cfg)
GKeyFile *desmume_config_read_file(const u32 *kb_cfg, const char* keysection)
{
gchar *config_file, *config_dir, *old_config_file;
GKeyFile *keyfile;
@ -56,7 +56,7 @@ GKeyFile *desmume_config_read_file(const u32 *kb_cfg)
g_free(old_config_file);
load_default_config(kb_cfg);
desmume_config_read_keys(keyfile);
desmume_config_read_keys(keyfile, keysection);
desmume_config_read_joykeys(keyfile);
return keyfile;
@ -92,10 +92,10 @@ static gboolean desmume_config_write_file(GKeyFile *keyfile)
return ret;
}
gboolean desmume_config_update_keys(GKeyFile *keyfile)
gboolean desmume_config_update_keys(GKeyFile *keyfile, const char *section)
{
for(int i = 0; i < NB_KEYS; i++) {
g_key_file_set_integer(keyfile, "KEYS", key_names[i], keyboard_cfg[i]);
g_key_file_set_integer(keyfile, section, key_names[i], keyboard_cfg[i]);
}
return desmume_config_write_file(keyfile);
@ -110,15 +110,15 @@ gboolean desmume_config_update_joykeys(GKeyFile *keyfile)
return desmume_config_write_file(keyfile);
}
gboolean desmume_config_read_keys(GKeyFile *keyfile)
gboolean desmume_config_read_keys(GKeyFile *keyfile, const char *section)
{
GError *error = NULL;
if (!g_key_file_has_group(keyfile, "KEYS"))
if (!g_key_file_has_group(keyfile, section))
return TRUE;
for (int i = 0; i < NB_KEYS; i++) {
keyboard_cfg[i] = g_key_file_get_integer(keyfile, "KEYS", key_names[i], &error);
keyboard_cfg[i] = g_key_file_get_integer(keyfile, section, key_names[i], &error);
if (error != NULL) {
g_error_free(error);
return FALSE;

View File

@ -18,12 +18,18 @@
#ifndef _DESMUME_GTK_CONFIG
#define _DESMUME_GTK_CONFIG
GKeyFile *desmume_config_read_file(const u32 *);
GKeyFile *desmume_config_read_file(const u32 *, const char *keysection = "KEYS");
void desmume_config_dispose(GKeyFile *);
gboolean desmume_config_update_keys(GKeyFile*);
/* since GTK uses GDK keysymbols, not SDL2 ones, we need
different sections for cli/gtk frontends.
KEYS = gtk keys,
SDLKEYS = sdl2 keys
*/
gboolean desmume_config_update_keys(GKeyFile*, const char *section = "KEYS");
gboolean desmume_config_read_keys(GKeyFile*, const char *section = "KEYS");
gboolean desmume_config_update_joykeys(GKeyFile*);
gboolean desmume_config_read_keys(GKeyFile*);
gboolean desmume_config_read_joykeys(GKeyFile*);
#endif

View File

@ -0,0 +1,278 @@
#include <gdk/gdkkeysyms.h>
#include <SDL.h>
int gdk_to_sdl_keycode(int gdk_key)
{
switch (gdk_key)
{
case GDK_BackSpace:
return SDLK_BACKSPACE;
case GDK_Tab:
return SDLK_TAB;
case GDK_Clear:
return SDLK_CLEAR;
case GDK_Return:
return SDLK_RETURN;
case GDK_Pause:
return SDLK_PAUSE;
case GDK_Escape:
return SDLK_ESCAPE;
case GDK_KP_Space:
return SDLK_SPACE;
case GDK_exclamdown:
return SDLK_EXCLAIM;
case GDK_quotedbl:
return SDLK_QUOTEDBL;
case GDK_numbersign:
return SDLK_HASH;
case GDK_dollar:
return SDLK_DOLLAR;
case GDK_ampersand:
return SDLK_AMPERSAND;
case GDK_quoteright:
return SDLK_QUOTE;
case GDK_parenleft:
return SDLK_LEFTPAREN;
case GDK_parenright:
return SDLK_RIGHTPAREN;
case GDK_asterisk:
return SDLK_ASTERISK;
case GDK_plus:
return SDLK_PLUS;
case GDK_comma:
return SDLK_COMMA;
case GDK_minus:
return SDLK_MINUS;
case GDK_period:
return SDLK_PERIOD;
case GDK_slash:
return SDLK_SLASH;
case GDK_0:
return SDLK_0;
case GDK_1:
return SDLK_1;
case GDK_2:
return SDLK_2;
case GDK_3:
return SDLK_3;
case GDK_4:
return SDLK_4;
case GDK_5:
return SDLK_5;
case GDK_6:
return SDLK_6;
case GDK_7:
return SDLK_7;
case GDK_8:
return SDLK_8;
case GDK_9:
return SDLK_9;
case GDK_colon:
return SDLK_COLON;
case GDK_semicolon:
return SDLK_SEMICOLON;
case GDK_less:
return SDLK_LESS;
case GDK_equal:
return SDLK_EQUALS;
case GDK_greater:
return SDLK_GREATER;
case GDK_question:
return SDLK_QUESTION;
case GDK_at:
return SDLK_AT;
case GDK_bracketleft:
return SDLK_LEFTBRACKET;
case GDK_backslash:
return SDLK_BACKSLASH;
case GDK_bracketright:
return SDLK_RIGHTBRACKET;
case GDK_asciicircum:
return SDLK_CARET;
case GDK_underscore:
return SDLK_UNDERSCORE;
case GDK_quoteleft:
return SDLK_BACKQUOTE;
case GDK_a:
return SDLK_a;
case GDK_b:
return SDLK_b;
case GDK_c:
return SDLK_c;
case GDK_d:
return SDLK_d;
case GDK_e:
return SDLK_e;
case GDK_f:
return SDLK_f;
case GDK_g:
return SDLK_g;
case GDK_h:
return SDLK_h;
case GDK_i:
return SDLK_i;
case GDK_j:
return SDLK_j;
case GDK_k:
return SDLK_k;
case GDK_l:
return SDLK_l;
case GDK_m:
return SDLK_m;
case GDK_n:
return SDLK_n;
case GDK_o:
return SDLK_o;
case GDK_p:
return SDLK_p;
case GDK_q:
return SDLK_q;
case GDK_r:
return SDLK_r;
case GDK_s:
return SDLK_s;
case GDK_t:
return SDLK_t;
case GDK_u:
return SDLK_u;
case GDK_v:
return SDLK_v;
case GDK_w:
return SDLK_w;
case GDK_x:
return SDLK_x;
case GDK_y:
return SDLK_y;
case GDK_z:
return SDLK_z;
case GDK_Delete:
return SDLK_DELETE;
case GDK_KP_0:
return SDLK_KP_0;
case GDK_KP_1:
return SDLK_KP_1;
case GDK_KP_2:
return SDLK_KP_2;
case GDK_KP_3:
return SDLK_KP_3;
case GDK_KP_4:
return SDLK_KP_4;
case GDK_KP_5:
return SDLK_KP_5;
case GDK_KP_6:
return SDLK_KP_6;
case GDK_KP_7:
return SDLK_KP_7;
case GDK_KP_8:
return SDLK_KP_8;
case GDK_KP_9:
return SDLK_KP_9;
case GDK_KP_Decimal:
return SDLK_KP_PERIOD;
case GDK_KP_Divide:
return SDLK_KP_DIVIDE;
case GDK_KP_Multiply:
return SDLK_KP_MULTIPLY;
case GDK_KP_Subtract:
return SDLK_KP_MINUS;
case GDK_KP_Add:
return SDLK_KP_PLUS;
case GDK_KP_Enter:
return SDLK_KP_ENTER;
case GDK_KP_Equal:
return SDLK_KP_EQUALS;
case GDK_Up:
return SDLK_UP;
case GDK_Down:
return SDLK_DOWN;
case GDK_Right:
return SDLK_RIGHT;
case GDK_Left:
return SDLK_LEFT;
case GDK_Insert:
return SDLK_INSERT;
case GDK_Home:
return SDLK_HOME;
case GDK_End:
return SDLK_END;
case GDK_Page_Up:
return SDLK_PAGEUP;
case GDK_Page_Down:
return SDLK_PAGEDOWN;
case GDK_F1:
return SDLK_F1;
case GDK_F2:
return SDLK_F2;
case GDK_F3:
return SDLK_F3;
case GDK_F4:
return SDLK_F4;
case GDK_F5:
return SDLK_F5;
case GDK_F6:
return SDLK_F6;
case GDK_F7:
return SDLK_F7;
case GDK_F8:
return SDLK_F8;
case GDK_F9:
return SDLK_F9;
case GDK_F10:
return SDLK_F10;
case GDK_F11:
return SDLK_F11;
case GDK_F12:
return SDLK_F12;
case GDK_F13:
return SDLK_F13;
case GDK_F14:
return SDLK_F14;
case GDK_F15:
return SDLK_F15;
case GDK_Num_Lock:
return SDLK_NUMLOCKCLEAR;
case GDK_Caps_Lock:
return SDLK_CAPSLOCK;
case GDK_Scroll_Lock:
return SDLK_SCROLLLOCK;
case GDK_Shift_R:
return SDLK_RSHIFT;
case GDK_Shift_L:
return SDLK_LSHIFT;
case GDK_Control_R:
return SDLK_RCTRL;
case GDK_Control_L:
return SDLK_LCTRL;
case GDK_Alt_R:
return SDLK_RALT;
case GDK_Alt_L:
return SDLK_LALT;
case GDK_Meta_R:
return SDLK_RGUI;
case GDK_Meta_L:
return SDLK_LGUI;
case GDK_Super_L:
return SDLK_LGUI;
case GDK_Super_R:
return SDLK_RGUI;
case GDK_Mode_switch:
return SDLK_MODE;
case GDK_Help:
return SDLK_HELP;
case GDK_Print:
return SDLK_PRINTSCREEN;
case GDK_Sys_Req:
return SDLK_SYSREQ;
case GDK_Break:
return SDLK_PAUSE;
case GDK_Menu:
return SDLK_MENU;
default:
return -1;
}
}