-
Notifications
You must be signed in to change notification settings - Fork 189
fix(metaevent): Ignore order in which modifier keys are released to trigger meta events #2577
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -377,15 +377,11 @@ static const FieldParse TheMetaMapFieldParseTable[] = | |
| // PUBLIC FUNCTIONS /////////////////////////////////////////////////////////////////////////////// | ||
|
|
||
| //------------------------------------------------------------------------------------------------- | ||
| MetaEventTranslator::MetaEventTranslator() : | ||
| m_lastKeyDown(MK_NONE), | ||
| m_lastModState(0) | ||
| MetaEventTranslator::MetaEventTranslator() | ||
| { | ||
| for (Int i = 0; i < NUM_MOUSE_BUTTONS; ++i) { | ||
| m_nextUpShouldCreateDoubleClick[i] = FALSE; | ||
| } | ||
|
|
||
|
|
||
| } | ||
|
|
||
| //------------------------------------------------------------------------------------------------- | ||
|
|
@@ -441,8 +437,20 @@ GameMessageDisposition MetaEventTranslator::translateGameMessage(const GameMessa | |
|
|
||
| if (t == GameMessage::MSG_RAW_KEY_DOWN || t == GameMessage::MSG_RAW_KEY_UP) | ||
| { | ||
| MappableKeyType key = (MappableKeyType)msg->getArgument(0)->integer; | ||
| Int keyState = msg->getArgument(1)->integer; | ||
| const Int systemKey = msg->getArgument(0)->integer; | ||
| const Int keyState = msg->getArgument(1)->integer; | ||
|
|
||
| MappableKeyType key = (MappableKeyType)systemKey; | ||
| switch (systemKey) | ||
| { | ||
| case KEY_LCTRL: | ||
| case KEY_RCTRL: | ||
| case KEY_LSHIFT: | ||
| case KEY_RSHIFT: | ||
| case KEY_LALT: | ||
| case KEY_RALT: | ||
| key = MK_NONE; | ||
| } | ||
|
|
||
| // for our purposes here, we don't care to distinguish between right and left keys, | ||
| // so just fudge a little to simplify things. | ||
|
|
@@ -463,6 +471,52 @@ GameMessageDisposition MetaEventTranslator::translateGameMessage(const GameMessa | |
| newModState |= ALT; | ||
| } | ||
|
|
||
| const Bool modStateRemoved = (key == MK_NONE) && (t == GameMessage::MSG_RAW_KEY_UP); | ||
|
|
||
| if (modStateRemoved) | ||
| { | ||
| // TheSuperHackers @fix The key handler now ignores the order in which modifier keys are released. | ||
| // This avoids frustrating experiences where a wrong button release order would skip an important key event. | ||
|
|
||
| for (Int keyDownIndex = 0; keyDownIndex < ARRAY_SIZE(m_keyDownInfos); ++keyDownIndex) | ||
| { | ||
| const MappableKeyType keyDown = (MappableKeyType)keyDownIndex; | ||
| KeyDownInfo &keyDownInfo = m_keyDownInfos[keyDownIndex]; | ||
|
|
||
| if (!keyDownInfo.isKeyDown()) | ||
| continue; | ||
|
|
||
| for (UnsignedInt modStateIndex = 0; modStateIndex < KeyDownInfo::getMaxKeyModStateCount(); ++modStateIndex) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you think we can extract some of the inner loop handling?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes I wanted to make a follow up change that refactors this function because it is quite a bit long. |
||
| { | ||
| const MappableKeyModState keyDownModState = keyDownInfo.getKeyModState(modStateIndex); | ||
|
|
||
| if (keyDownModState == NONE) | ||
| continue; | ||
|
|
||
| if (BitsAreSet(newModState, keyDownModState)) | ||
| continue; | ||
|
|
||
| // Forget that this key and mod state are pressed. | ||
| keyDownInfo.clearKeyModState(modStateIndex); | ||
|
|
||
| for (const MetaMapRec *map = TheMetaMap->getFirstMetaMapRec(); map; map = map->m_next) | ||
| { | ||
| if (!isMessageUsable(map->m_usableIn)) | ||
| continue; | ||
|
|
||
| if (!(map->m_key == keyDown && map->m_modState == keyDownModState && map->m_transition == UP)) | ||
| continue; | ||
|
|
||
| TheMessageStream->appendMessage(map->m_meta); | ||
| disp = DESTROY_MESSAGE; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| else | ||
| { | ||
| // TheSuperHackers @info The regular key handler only triggers events when the mapped key is pressed, | ||
| // not when the modifier (CTRL, ALT, SHIFT) is pressed, unless the key is MK_NONE. | ||
|
|
||
| for (const MetaMapRec *map = TheMetaMap->getFirstMetaMapRec(); map; map = map->m_next) | ||
| { | ||
|
|
@@ -472,23 +526,6 @@ GameMessageDisposition MetaEventTranslator::translateGameMessage(const GameMessa | |
| if (!isMessageUsable(map->m_usableIn)) | ||
| continue; | ||
|
|
||
| // check for the special case of mods-only-changed. | ||
| if ( | ||
| map->m_key == MK_NONE && | ||
| newModState != m_lastModState && | ||
| ( | ||
| (map->m_transition == UP && map->m_modState == m_lastModState) || | ||
| (map->m_transition == DOWN && map->m_modState == newModState) | ||
| ) | ||
| ) | ||
| { | ||
| //DEBUG_LOG(("Frame %d: MetaEventTranslator::translateGameMessage() Mods-only change: %s", TheGameLogic->getFrame(), findGameMessageNameByType(map->m_meta))); | ||
| /*GameMessage *metaMsg =*/ TheMessageStream->appendMessage(map->m_meta); | ||
| disp = DESTROY_MESSAGE; | ||
| break; | ||
| } | ||
|
|
||
| // ok, now check for "normal" key transitions. | ||
| if ( | ||
| map->m_key == key && | ||
| map->m_modState == newModState && | ||
|
|
@@ -499,7 +536,6 @@ GameMessageDisposition MetaEventTranslator::translateGameMessage(const GameMessa | |
| ) | ||
| ) | ||
| { | ||
|
|
||
| if( keyState & KEY_STATE_AUTOREPEAT ) | ||
| { | ||
| // if it's an autorepeat of a "known" key, don't generate the meta-event, | ||
|
|
@@ -540,13 +576,8 @@ GameMessageDisposition MetaEventTranslator::translateGameMessage(const GameMessa | |
| } | ||
|
greptile-apps[bot] marked this conversation as resolved.
|
||
| } | ||
|
|
||
|
|
||
|
|
||
| if (t == GameMessage::MSG_RAW_KEY_DOWN) | ||
| { | ||
| m_lastKeyDown = key; | ||
|
|
||
|
|
||
| #ifdef DUMP_ALL_KEYS_TO_LOG | ||
|
|
||
| WideChar Wkey = TheKeyboard->getPrintableKey(key, 0); | ||
|
|
@@ -556,12 +587,24 @@ GameMessageDisposition MetaEventTranslator::translateGameMessage(const GameMessa | |
| aKey.translate(uKey); | ||
| DEBUG_LOG(("^%s ", aKey.str())); | ||
| #endif | ||
|
|
||
| if (newModState != NONE) | ||
| { | ||
| // Remember that this key and mod state are pressed. | ||
| m_keyDownInfos[key].setKeyModState((MappableKeyModState)newModState); | ||
| } | ||
| } | ||
| else | ||
| { | ||
| if (newModState != NONE) | ||
| { | ||
| DEBUG_ASSERTCRASH(key != MK_NONE, ("Key is expected to be not MK_NONE")); | ||
|
|
||
| // Forget that this key and mod state are pressed. | ||
| m_keyDownInfos[key].clearKeyModState((MappableKeyModState)newModState); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| m_lastModState = newModState; | ||
| } | ||
|
Mauller marked this conversation as resolved.
|
||
| } | ||
|
|
||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.