diff --git a/src/InputStream.c b/src/InputStream.c index 54c021e..3fed7bd 100644 --- a/src/InputStream.c +++ b/src/InputStream.c @@ -561,14 +561,46 @@ int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers) { return -1; } - // Any keyboard event with the META modifier flag is dropped by all known GFE versions. - // This prevents us from sending shortcuts involving the meta key (Win+X, Win+Tab, etc). - // The catch is that the meta key event itself would actually work if it didn't set its - // own modifier flag, so we'll clear that here. This should be safe even if a new GFE - // release comes out that stops dropping events with MODIFIER_META flag. - if ((keyCode & 0x00FF) == 0x5B || // VK_LWIN - (keyCode & 0x00FF) == 0x5C) { // VK_RWIN + // For proper behavior, the MODIFIER flag must not be set on the modifier key down event itself + // for the extended modifiers on the right side of the keyboard. If the MODIFIER flag is set, + // GFE will synthesize an errant key down event for the non-extended key, causing that key to be + // stuck down after the extended modifier key is raised. For non-extended keys, we must set the + // MODIFIER flag for correct behavior. + switch (keyCode & 0xFF) { + case 0x5B: // VK_LWIN + case 0x5C: // VK_RWIN + // Any keyboard event with the META modifier flag is dropped by all known GFE versions. + // This prevents us from sending shortcuts involving the meta key (Win+X, Win+Tab, etc). + // The catch is that the meta key event itself would actually work if it didn't set its + // own modifier flag, so we'll clear that here. This should be safe even if a new GFE + // release comes out that stops dropping events with MODIFIER_META flag. modifiers &= ~MODIFIER_META; + break; + + case 0xA0: // VK_LSHIFT + modifiers |= MODIFIER_SHIFT; + break; + case 0xA1: // VK_RSHIFT + modifiers &= ~MODIFIER_SHIFT; + break; + + case 0xA2: // VK_LCONTROL + modifiers |= MODIFIER_CTRL; + break; + case 0xA3: // VK_RCONTROL + modifiers &= ~MODIFIER_CTRL; + break; + + case 0xA4: // VK_LMENU + modifiers |= MODIFIER_ALT; + break; + case 0xA5: // VK_RMENU + modifiers &= ~MODIFIER_ALT; + break; + + default: + // No fixups + break; } holder->packetLength = sizeof(NV_KEYBOARD_PACKET);