[PATCH 7/9] Support for specifying PC/SDL key modifiers in the mapping file

[ Thread Index | Date Index | More lists.tuxfamily.org/hatari-devel Archives ]


Loosely based on Vincent Barilliot's patch.

TODO: get rid of the redundant "KMOD_" prefixes (needed in key mapping
file for compatibility with Vincent's keymap files) before merging
this.

Similarly to Vincent's patch:

* This removes support for using SDL key names.  Names are now
  supported only for modifier keys, and SDL scancodes need to be used
  for the rest

Unlike Vincent's patch:

* This always ignores NumLock in PC modifiers as that has special
  functionality / key handling in Hatari

* There's no support for specifying mask for SDL modifiers in keymap

* User can specify multiple modifiers for the SDL key.  It's not very
  useful, but code for parsing modifiers has same logic as one used
  for ST modifiers
---
 src/keymap.c | 112 ++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 94 insertions(+), 18 deletions(-)

diff --git a/src/keymap.c b/src/keymap.c
index 0f67cbd2..1e177653 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -46,9 +46,13 @@ static const uint8_t DebounceExtendedKeys[] =
 	0  /* End of list */
 };
 
+/* ignore capslock & numlock on SDL modifier matching */
+#define PC_MOD_MASK (~KMOD_NUM)
+
 typedef struct
 {
 	SDL_Scancode scancode;
+	SDL_Keymod mods;
 } SDLKey;
 
 static const struct
@@ -481,6 +485,7 @@ static ST_Key* Keymap_RemapKeyToSTKey(const SDL_Keysym* pKeySym)
 	if (ConfigureParams.Keyboard.nKeymapType == KEYMAP_LOADED)
 	{
 		int i;
+		SDL_Keymod mods = pKeySym->mod;
 		for (i = 0; i < ARRAY_SIZE(LoadedKeymap); i++)
 		{
 			KeyMapping *mapping = &LoadedKeymap[i];
@@ -491,6 +496,9 @@ static ST_Key* Keymap_RemapKeyToSTKey(const SDL_Keysym* pKeySym)
 			if (mapping->pc.scancode != scancode)
 				continue;
 
+			if (mapping->pc.mods != (mods & PC_MOD_MASK))
+				continue;
+
 			KeysDown[scancode].mods = mapping->st.mods;
 			return UpdateMapping("keymap", scancode,
 					     mapping->st.scancode);
@@ -503,6 +511,52 @@ static ST_Key* Keymap_RemapKeyToSTKey(const SDL_Keysym* pKeySym)
 }
 
 
+/*-----------------------------------------------------------------------*/
+/**
+ * Parse SDL modifier name from 'name' and return 'mods' value with
+ * corresponding bit added to it, or return KMOD_NONE for error.
+ *
+ * NOTE: KMOD_CTRL / KMOD_SHIFT / KMOD_ALT / KMOD_GUI are composed of
+ * corresponding left & right variant bits, so they are left out
+ */
+static SDL_Keymod AddSdlModifier(SDL_Keymod mods, const char *name) {
+	struct {
+		SDL_Keymod mod;
+		const char *name;
+	} const keymodNames[] = {
+		{ KMOD_LSHIFT, "KMOD_LSHIFT" },
+		{ KMOD_RSHIFT, "KMOD_RSHIFT" },
+		{ KMOD_LCTRL, "KMOD_LCTRL" },
+		{ KMOD_RCTRL, "KMOD_RCTRL" },
+		{ KMOD_LALT, "KMOD_LALT" },
+		{ KMOD_RALT, "KMOD_RALT" },
+		{ KMOD_LGUI, "KMOD_LGUI" },
+		{ KMOD_RGUI, "KMOD_RGUI" },
+		{ KMOD_CAPS, "KMOD_CAPS" },
+		{ KMOD_MODE, "KMOD_MODE" },
+		{ KMOD_CTRL, "KMOD_CTRL" },
+	};
+	SDL_Keymod mod;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(keymodNames); i++)
+	{
+		if (strcmp(name, keymodNames[i].name) != 0)
+			continue;
+
+		mod = keymodNames[i].mod;
+		if (mod & mods)
+		{
+			Log_Printf(LOG_WARN, "PC/SDL modifier '%s' specified twice\n", name);
+			return KMOD_NONE;
+		}
+		return (mods | mod);
+	};
+	Log_Printf(LOG_ERROR, "unknown/unsupported PC/SDL modifier '%s'\n", name);
+	return KMOD_NONE;
+}
+
+
 /*-----------------------------------------------------------------------*/
 /**
  * Fill "mapping" KeyMapping host part based on host "spec" string.
@@ -510,30 +564,52 @@ static ST_Key* Keymap_RemapKeyToSTKey(const SDL_Keysym* pKeySym)
  */
 static bool HostSpecToKeymap(const char *spec, KeyMapping* mapping)
 {
-	int key;
+	char buf[64], *token, *saveptr, *endptr;
+	SDL_Scancode scancode = 0;
+	SDL_Keymod mods = 0;
+
 	if (!spec)
 		return false;
-
-	key = atoi(spec);    /* Direct key code? */
-	if (key < 10)
+	if (strlcpy(buf, spec, sizeof(buf)) >= sizeof(buf))
 	{
-		/* If it's not a valid number >= 10, then
-		 * assume we've got a symbolic key name
-		 */
-		int offset = 0;
-		/* quoted character (e.g. comment line char)? */
-		if (*spec == '\\' && strlen(spec) == 2)
-			offset = 1;
-		key = Keymap_GetKeyFromName(spec+offset);
+		Log_Printf(LOG_ERROR, "PC/SDL scancode spec '%s' too long\n", spec);
+		return false;
 	}
-	if (key < 8)
+
+	scancode = mods = 0;
+	for (token = strtok_r(buf, "|", &saveptr);
+	     token;
+	     token = strtok_r(NULL, "|", &saveptr))
 	{
-		Log_Printf(LOG_WARN, "Invalid PC key: '%s' (%d >= 8)\n",
-			   spec, key);
-		return false;
+		token = Str_Trim(token);
+		if (isalpha(token[0]))
+		{
+			mods = AddSdlModifier(mods, token);
+			if (!mods)
+				return false;
+			continue;
+		}
+		if (scancode)
+		{
+			Log_Printf(LOG_WARN, "extra '%s', PC/SDL scancode already set\n", token);
+			return false;
+		}
+		scancode = strtol(token, &endptr, 10);
+		if (!scancode)
+		{
+			Log_Printf(LOG_ERROR, "invalid PC/SDL scancode '%s'\n", token);
+			return false;
+		}
+		if (*endptr)
+		{
+			Log_Printf(LOG_WARN, "'%s' garbage at end of '%s' PC/SDL scancode\n",
+				   endptr, token);
+			return false;
+		}
 	}
-	mapping->pc.scancode = key;
-	return true;
+	mapping->pc.scancode = scancode;
+	mapping->pc.mods = mods;
+	return (scancode > 0);
 }
 
 
-- 
2.30.2


--------------7873925CF10FCA11A2667F70
Content-Type: text/x-patch; charset=UTF-8;
 name="0006-Add-trace-output-for-ST-key-modifiers.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="0006-Add-trace-output-for-ST-key-modifiers.patch"



Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/