[PATCH 4/9] Support for specifying ST key modifiers in the mapping file |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/hatari-devel Archives
]
- Subject: [PATCH 4/9] Support for specifying ST key modifiers in the mapping file
- From: Eero Tamminen <oak@xxxxxxxxxxxxxx>
- Date: Sun, 24 Oct 2021 12:45:26 +0300
Because modifier keys can now be specified being both individual ST
scancodes, and as modifiers to other scancodes, key presses & releases
need to be counted now, true & false values are not enough.
Inspired by Vincent Barilliot's patch.
---
src/keymap.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 128 insertions(+), 10 deletions(-)
diff --git a/src/keymap.c b/src/keymap.c
index 5c5fc8b1..fc5eb964 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -51,9 +51,23 @@ typedef struct
SDL_Scancode scancode;
} SDLKey;
+static const struct
+{
+ const char *name;
+ uint8_t scancode;
+ uint8_t mod;
+} ST_Modifiers[] = {
+ {"CONTROL", ST_CONTROL, 0x01},
+ {"LSHIFT", ST_LSHIFT, 0x02},
+ {"RSHIFT", ST_RSHIFT, 0x04},
+ {"ALT", ST_ALTERNATE, 0x08},
+};
+
typedef struct
{
uint8_t scancode;
+ /* key modifiers matching ST_Modifiers[].mod bit values */
+ uint8_t mods;
} ST_Key;
/* Key mappings: pair SDL key definition with ST key */
@@ -474,6 +488,7 @@ static ST_Key* Keymap_RemapKeyToSTKey(const SDL_Keysym* pKeySym)
if (mapping->pc.scancode != scancode)
continue;
+ KeysDown[scancode].mods = mapping->st.mods;
return UpdateMapping("keymap", scancode,
mapping->st.scancode);
}
@@ -519,6 +534,32 @@ static bool HostSpecToKeymap(const char *spec, KeyMapping* mapping)
}
+/*-----------------------------------------------------------------------*/
+/**
+ * Parse modifier name from 'name' and return 'mods' value with
+ * corresponding bit added to it, or return zero if there was no match
+ */
+static uint8_t AddSTModifier(uint8_t mods, const char *name)
+{
+ uint8_t mod, i;
+ for (i = 0; i < ARRAY_SIZE(ST_Modifiers); i++)
+ {
+ if (strcmp(ST_Modifiers[i].name, name) != 0)
+ continue;
+
+ mod = ST_Modifiers[i].mod;
+ if (mod & mods)
+ {
+ Log_Printf(LOG_WARN, "ST modifier '%s' specified twice\n", name);
+ return 0;
+ }
+ return (mods | mod);
+ }
+ Log_Printf(LOG_ERROR, "unknown/unsupported ST modifier '%s'\n", name);
+ return 0;
+}
+
+
/*-----------------------------------------------------------------------*/
/**
* Fill "mapping" KeyMapping guest (ST) part based on guest "spec" string.
@@ -526,19 +567,52 @@ static bool HostSpecToKeymap(const char *spec, KeyMapping* mapping)
*/
static bool GuestSpecToKeymap(const char *spec, KeyMapping* mapping)
{
- int key;
+ char buf[64], *token, *saveptr, *endptr;
+ uint8_t scancode, mods;
+
if (!spec)
return false;
-
- key = atoi(spec);
- if (key <= 0 || key > KBD_MAX_SCANCODE)
+ if (strlcpy(buf, spec, sizeof(buf)) >= sizeof(buf))
{
- Log_Printf(LOG_WARN, "Invalid ST scancode: '%s' (0 > %d < %d)\n",
- spec, key, KBD_MAX_SCANCODE);
+ Log_Printf(LOG_ERROR, "ST scancode spec '%s' too long\n", spec);
return false;
}
- mapping->st.scancode = key;
- return true;
+
+ scancode = mods = 0;
+ for (token = strtok_r(buf, "|", &saveptr);
+ token;
+ token = strtok_r(NULL, "|", &saveptr))
+ {
+ token = Str_Trim(token);
+ if (isalpha(token[0]))
+ {
+ mods = AddSTModifier(mods, token);
+ if (!mods)
+ return false;
+ continue;
+ }
+ if (scancode)
+ {
+ Log_Printf(LOG_WARN, "extra '%s', ST scancode already set\n", token);
+ return false;
+ }
+ scancode = strtol(token, &endptr, 10);
+ if (!scancode)
+ {
+ Log_Printf(LOG_ERROR, "invalid ST scancode '%s'\n", token);
+ return false;
+ }
+ if (*endptr)
+ {
+ Log_Printf(LOG_WARN, "'%s' garbage at end of '%s' ST scancode\n",
+ endptr, token);
+ return false;
+ }
+ }
+ mapping->st.scancode = scancode;
+ mapping->st.mods = mods;
+
+ return (scancode > 0);
}
@@ -715,6 +789,46 @@ static bool IsKeyTranslatable(SDL_Keycode symkey)
}
+/*-----------------------------------------------------------------------*/
+/**
+ * Set modifiers keys indicated by bits in 'mods' up or down
+ * based on 'down'.
+ */
+static void InsertModifiers(uint8_t mods, bool down)
+{
+ uint8_t i, scancode;
+ if (!mods)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(ST_Modifiers); i++)
+ {
+ if (!(mods & ST_Modifiers[i].mod))
+ continue;
+
+ scancode = ST_Modifiers[i].scancode;
+
+ if (down)
+ {
+ /* because modifiers may already be down
+ * due to normal key events (or mapped
+ * scancodes that happen to be modifiers),
+ * KeyStates need to be counted, bool
+ * for pressed state is not enough
+ */
+ if (Keyboard.KeyStates[scancode]++ > 0)
+ continue;
+ }
+ else
+ {
+ assert(Keyboard.KeyStates[scancode] >= 0);
+ if (--Keyboard.KeyStates[scancode] > 0)
+ continue;
+ }
+ IKBD_PressSTKey(scancode, down);
+ }
+}
+
+
/*-----------------------------------------------------------------------*/
/**
* User pressed a key down
@@ -747,10 +861,12 @@ void Keymap_KeyDown(const SDL_Keysym *sdlkey)
STScanCode = stkey->scancode;
LOG_TRACE(TRACE_KEYMAP, "key map: sym=0x%x to ST-scan=0x%02x\n", symkey, STScanCode);
+
+ InsertModifiers(stkey->mods, true);
if (!Keyboard.KeyStates[STScanCode])
{
/* Set down */
- Keyboard.KeyStates[STScanCode] = true;
+ Keyboard.KeyStates[STScanCode]++;
IKBD_PressSTKey(STScanCode, true);
}
}
@@ -792,11 +908,13 @@ void Keymap_KeyUp(const SDL_Keysym *sdlkey)
/* Release key (only if was pressed) */
STScanCode = stkey->scancode;
+ assert(Keyboard.KeyStates[STScanCode]);
if (Keyboard.KeyStates[STScanCode])
{
IKBD_PressSTKey(STScanCode, false);
- Keyboard.KeyStates[STScanCode] = false;
+ Keyboard.KeyStates[STScanCode]--;
}
+ InsertModifiers(stkey->mods, false);
}
/*-----------------------------------------------------------------------*/
--
2.30.2
--------------7873925CF10FCA11A2667F70
Content-Type: text/x-patch; charset=UTF-8;
name="0003-Add-defines-for-some-of-the-ST-scancode-values.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename*0="0003-Add-defines-for-some-of-the-ST-scancode-values.patch"