@@ -378,14 +378,11 @@ static const FieldParse TheMetaMapFieldParseTable[] =
378378
379379// -------------------------------------------------------------------------------------------------
380380MetaEventTranslator::MetaEventTranslator () :
381- m_lastKeyDown(MK_NONE),
382381 m_lastModState(0 )
383382{
384383 for (Int i = 0 ; i < NUM_MOUSE_BUTTONS; ++i) {
385384 m_nextUpShouldCreateDoubleClick[i] = FALSE ;
386385 }
387-
388-
389386}
390387
391388// -------------------------------------------------------------------------------------------------
@@ -441,8 +438,19 @@ GameMessageDisposition MetaEventTranslator::translateGameMessage(const GameMessa
441438
442439 if (t == GameMessage::MSG_RAW_KEY_DOWN || t == GameMessage::MSG_RAW_KEY_UP)
443440 {
444- MappableKeyType key = (MappableKeyType)msg->getArgument (0 )->integer ;
445- Int keyState = msg->getArgument (1 )->integer ;
441+ Int systemKey = msg->getArgument (0 )->integer ;
442+ switch (systemKey)
443+ {
444+ case KEY_LCTRL:
445+ case KEY_RCTRL:
446+ case KEY_LSHIFT:
447+ case KEY_RSHIFT:
448+ case KEY_LALT:
449+ case KEY_RALT:
450+ systemKey = KEY_NONE;
451+ }
452+ const MappableKeyType key = (MappableKeyType)systemKey;
453+ const Int keyState = msg->getArgument (1 )->integer ;
446454
447455 // for our purposes here, we don't care to distinguish between right and left keys,
448456 // so just fudge a little to simplify things.
@@ -463,6 +471,52 @@ GameMessageDisposition MetaEventTranslator::translateGameMessage(const GameMessa
463471 newModState |= ALT;
464472 }
465473
474+ const Bool modStateRemoved = newModState < m_lastModState;
475+
476+ if (modStateRemoved)
477+ {
478+ // TheSuperHackers @fix The key handler now ignores the order in which modifier keys are released.
479+ // This avoids frustrating experiences where a wrong button release order would skip an important key event.
480+
481+ for (Int keyDownIndex = 0 ; keyDownIndex < ARRAY_SIZE (m_keyDownInfos); ++keyDownIndex)
482+ {
483+ const MappableKeyType keyDown = (MappableKeyType)keyDownIndex;
484+ KeyDownInfo &keyDownInfo = m_keyDownInfos[keyDownIndex];
485+
486+ if (!keyDownInfo.isKeyDown ())
487+ continue ;
488+
489+ for (UnsignedInt modStateIndex = 0 ; modStateIndex < KeyDownInfo::getMaxKeyModStateCount (); ++modStateIndex)
490+ {
491+ const MappableKeyModState keyDownModState = keyDownInfo.getKeyModState (modStateIndex);
492+
493+ if (keyDownModState == NONE)
494+ continue ;
495+
496+ if (BitsAreSet (keyDownModState, newModState))
497+ continue ;
498+
499+ // Forget that this key and mod state are pressed.
500+ keyDownInfo.clearKeyModState (modStateIndex);
501+
502+ for (const MetaMapRec *map = TheMetaMap->getFirstMetaMapRec (); map; map = map->m_next )
503+ {
504+ if (!isMessageUsable (map->m_usableIn ))
505+ continue ;
506+
507+ if (!(map->m_key == keyDown && map->m_modState == keyDownModState && map->m_transition == UP))
508+ continue ;
509+
510+ TheMessageStream->appendMessage (map->m_meta );
511+ disp = DESTROY_MESSAGE;
512+ }
513+ }
514+ }
515+ }
516+ else
517+ {
518+ // TheSuperHackers @info The regular key handler only triggers events when the mapped key is pressed,
519+ // not when the modifier (CTRL, ALT, SHIFT) is pressed, unless the key is MK_NONE.
466520
467521 for (const MetaMapRec *map = TheMetaMap->getFirstMetaMapRec (); map; map = map->m_next )
468522 {
@@ -472,23 +526,6 @@ GameMessageDisposition MetaEventTranslator::translateGameMessage(const GameMessa
472526 if (!isMessageUsable (map->m_usableIn ))
473527 continue ;
474528
475- // check for the special case of mods-only-changed.
476- if (
477- map->m_key == MK_NONE &&
478- newModState != m_lastModState &&
479- (
480- (map->m_transition == UP && map->m_modState == m_lastModState) ||
481- (map->m_transition == DOWN && map->m_modState == newModState)
482- )
483- )
484- {
485- // DEBUG_LOG(("Frame %d: MetaEventTranslator::translateGameMessage() Mods-only change: %s", TheGameLogic->getFrame(), findGameMessageNameByType(map->m_meta)));
486- /* GameMessage *metaMsg =*/ TheMessageStream->appendMessage (map->m_meta );
487- disp = DESTROY_MESSAGE;
488- break ;
489- }
490-
491- // ok, now check for "normal" key transitions.
492529 if (
493530 map->m_key == key &&
494531 map->m_modState == newModState &&
@@ -499,7 +536,6 @@ GameMessageDisposition MetaEventTranslator::translateGameMessage(const GameMessa
499536 )
500537 )
501538 {
502-
503539 if ( keyState & KEY_STATE_AUTOREPEAT )
504540 {
505541 // if it's an autorepeat of a "known" key, don't generate the meta-event,
@@ -540,13 +576,10 @@ GameMessageDisposition MetaEventTranslator::translateGameMessage(const GameMessa
540576 }
541577 }
542578
543-
579+ }
544580
545581 if (t == GameMessage::MSG_RAW_KEY_DOWN)
546582 {
547- m_lastKeyDown = key;
548-
549-
550583#ifdef DUMP_ALL_KEYS_TO_LOG
551584
552585 WideChar Wkey = TheKeyboard->getPrintableKey (key, 0 );
@@ -556,11 +589,13 @@ GameMessageDisposition MetaEventTranslator::translateGameMessage(const GameMessa
556589 aKey.translate (uKey);
557590 DEBUG_LOG ((" ^%s " , aKey.str ()));
558591#endif
559-
592+ if (newModState != NONE)
593+ {
594+ // Remember that this key and mod state are pressed.
595+ m_keyDownInfos[key].setKeyModState ((MappableKeyModState)newModState);
596+ }
560597 }
561598
562-
563-
564599 m_lastModState = newModState;
565600 }
566601
0 commit comments