Never mind - sorry about that. I figured it out. Thanks for all your help!
I wasn’t accounting for the case where mappedKey was H, J, K, L but the key was not just toggled on.
So the working code is:
static Key specialHook(Key mappedKey, byte row, byte col, uint8_t keyState) {
// If this key is not the one we want to treat specially, return early.
if (mappedKey != Key_Enter && mappedKey != Key_Escape && mappedKey != Key_H &&
mappedKey != Key_J && mappedKey != Key_K && mappedKey != Key_L)
{
return mappedKey;
}
if (appSwitchActive) {
if (mappedKey == Key_Enter && keyToggledOn(keyState)) {
appSwitchActive = false;
return mappedKey;
}
else if (mappedKey == Key_Escape && keyToggledOn(keyState)) {
appSwitchActive = false;
return mappedKey;
}
else if (mappedKey == Key_H) {
if (keyToggledOn(keyState)) {
Macros.play(MACRO(D(LeftAlt), T(LeftArrow)));
} else {
Macros.play(MACRO(D(LeftAlt)));
return Key_NoKey;
}
}
else if (mappedKey == Key_J) {
if (keyToggledOn(keyState)) {
Macros.play(MACRO(D(LeftAlt), T(DownArrow)));
} else {
Macros.play(MACRO(D(LeftAlt)));
return Key_NoKey;
}
}
else if (mappedKey == Key_K) {
if (keyToggledOn(keyState)) {
Macros.play(MACRO(D(LeftAlt), T(UpArrow)));
} else {
Macros.play(MACRO(D(LeftAlt)));
return Key_NoKey;
}
}
else if (mappedKey == Key_L) {
if (keyToggledOn(keyState)) {
Macros.play(MACRO(D(LeftAlt), T(RightArrow)));
} else {
Macros.play(MACRO(D(LeftAlt)));
return Key_NoKey;
}
}
}
else return mappedKey;
}
const macro_t *macroAppSwitch(uint8_t keyState) {
// Key was just pressed and we are in app switch mode
if (keyToggledOn(keyState) && appSwitchActive == true) {
appSwitchActive = false;
return MACRO(U(LAlt));
}
// Key was just pressed and we are not in app switch mode
if (keyToggledOn(keyState) && appSwitchActive == false) {
appSwitchActive = true;
return MACRO(D(LAlt), T(Tab));
}
// Key was not just released.
// if appSwitchActive is true, we continue holding Alt.
if (appSwitchActive) {
return MACRO(D(LAlt));
}
// otherwise we do nothing
return MACRO_NONE;
}