Skip to content

Commit a66bdf5

Browse files
committed
Revamped handling of modifier keys in IE driver
The IE driver is now able to distinguish between the left and right modifier keys (Shift, Control, Alt) on the keyboard.
1 parent e73ca05 commit a66bdf5

File tree

2 files changed

+101
-15
lines changed

2 files changed

+101
-15
lines changed

cpp/iedriver/InputManager.cpp

Lines changed: 100 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -641,68 +641,147 @@ void InputManager::AddKeyboardInput(HWND window_handle,
641641
return;
642642
}
643643

644+
if (character == WD_KEY_NULL) {
645+
std::vector<WORD> modifier_key_codes;
646+
if (input_state->is_shift_pressed) {
647+
if (this->IsKeyPressed(WD_KEY_SHIFT)) {
648+
modifier_key_codes.push_back(VK_SHIFT);
649+
this->UpdatePressedKeys(WD_KEY_SHIFT, false);
650+
}
651+
if (this->IsKeyPressed(WD_KEY_R_SHIFT)) {
652+
modifier_key_codes.push_back(VK_RSHIFT);
653+
this->UpdatePressedKeys(WD_KEY_R_SHIFT, false);
654+
}
655+
input_state->is_shift_pressed = false;
656+
}
657+
658+
if (input_state->is_control_pressed) {
659+
if (this->IsKeyPressed(WD_KEY_CONTROL)) {
660+
modifier_key_codes.push_back(VK_CONTROL);
661+
this->UpdatePressedKeys(WD_KEY_CONTROL, false);
662+
}
663+
if (this->IsKeyPressed(WD_KEY_R_CONTROL)) {
664+
modifier_key_codes.push_back(VK_RCONTROL);
665+
this->UpdatePressedKeys(WD_KEY_R_CONTROL, false);
666+
}
667+
input_state->is_control_pressed = false;
668+
}
669+
670+
if (input_state->is_alt_pressed) {
671+
if (this->IsKeyPressed(WD_KEY_ALT)) {
672+
modifier_key_codes.push_back(VK_MENU);
673+
this->UpdatePressedKeys(WD_KEY_ALT, false);
674+
}
675+
if (this->IsKeyPressed(WD_KEY_R_ALT)) {
676+
modifier_key_codes.push_back(VK_RMENU);
677+
this->UpdatePressedKeys(WD_KEY_R_ALT, false);
678+
}
679+
input_state->is_alt_pressed = false;
680+
}
681+
682+
if (input_state->is_meta_pressed) {
683+
if (this->IsKeyPressed(WD_KEY_META)) {
684+
modifier_key_codes.push_back(VK_LWIN);
685+
this->UpdatePressedKeys(WD_KEY_META, false);
686+
}
687+
if (this->IsKeyPressed(WD_KEY_R_META)) {
688+
modifier_key_codes.push_back(VK_RWIN);
689+
this->UpdatePressedKeys(WD_KEY_R_META, false);
690+
}
691+
input_state->is_meta_pressed = false;
692+
}
693+
694+
std::vector<WORD>::const_iterator it = modifier_key_codes.begin();
695+
for (; it != modifier_key_codes.end(); ++it) {
696+
KeyInfo modifier_key_info = { 0, 0, false, false, false, character };
697+
UINT scan_code = ::MapVirtualKey(*it, MAPVK_VK_TO_VSC);
698+
modifier_key_info.key_code = *it;
699+
modifier_key_info.scan_code = scan_code;
700+
this->CreateKeyboardInputItem(modifier_key_info,
701+
KEYEVENTF_SCANCODE,
702+
true);
703+
}
704+
return;
705+
}
706+
644707
if (this->IsModifierKey(character)) {
645708
KeyInfo modifier_key_info = { 0, 0, false, false, false, character };
646709
// If the character represents the Shift key, or represents the
647710
// "release all modifiers" key and the Shift key is down, send
648711
// the appropriate down or up keystroke for the Shift key.
649712
if (character == WD_KEY_SHIFT ||
650-
character == WD_KEY_R_SHIFT ||
651-
(character == WD_KEY_NULL && input_state->is_shift_pressed)) {
713+
character == WD_KEY_R_SHIFT) {
714+
WORD key_code = VK_SHIFT;
715+
if (character == WD_KEY_R_SHIFT) {
716+
key_code = VK_RSHIFT;
717+
}
718+
UINT scan_code = ::MapVirtualKey(key_code, MAPVK_VK_TO_VSC);
652719
modifier_key_info.key_code = VK_SHIFT;
720+
modifier_key_info.scan_code = scan_code;
653721
this->CreateKeyboardInputItem(modifier_key_info,
654-
0,
722+
KEYEVENTF_SCANCODE,
655723
input_state->is_shift_pressed);
656724
if (input_state->is_shift_pressed) {
657725
input_state->is_shift_pressed = false;
658726
} else {
659727
input_state->is_shift_pressed = true;
660728
}
661-
this->UpdatePressedKeys(WD_KEY_SHIFT, input_state->is_shift_pressed);
729+
this->UpdatePressedKeys(character, input_state->is_shift_pressed);
662730
}
663731

664732
// If the character represents the Control key, or represents the
665733
// "release all modifiers" key and the Control key is down, send
666734
// the appropriate down or up keystroke for the Control key.
667735
if (character == WD_KEY_CONTROL ||
668-
character == WD_KEY_R_CONTROL ||
669-
(character == WD_KEY_NULL && input_state->is_control_pressed)) {
736+
character == WD_KEY_R_CONTROL) {
737+
WORD key_code = VK_CONTROL;
738+
if (character == WD_KEY_R_CONTROL) {
739+
key_code = VK_RCONTROL;
740+
modifier_key_info.is_extended_key = true;
741+
}
742+
UINT scan_code = ::MapVirtualKey(key_code, MAPVK_VK_TO_VSC);
670743
modifier_key_info.key_code = VK_CONTROL;
744+
modifier_key_info.scan_code = scan_code;
671745
this->CreateKeyboardInputItem(modifier_key_info,
672-
0,
746+
KEYEVENTF_SCANCODE,
673747
input_state->is_control_pressed);
674748
if (input_state->is_control_pressed) {
675749
input_state->is_control_pressed = false;
676750
} else {
677751
input_state->is_control_pressed = true;
678752
}
679-
this->UpdatePressedKeys(WD_KEY_CONTROL, input_state->is_control_pressed);
753+
this->UpdatePressedKeys(character, input_state->is_control_pressed);
680754
}
681755

682756
// If the character represents the Alt key, or represents the
683757
// "release all modifiers" key and the Alt key is down, send
684758
// the appropriate down or up keystroke for the Alt key.
685759
if (character == WD_KEY_ALT ||
686-
character == WD_KEY_R_ALT ||
687-
(character == WD_KEY_NULL && input_state->is_alt_pressed)) {
760+
character == WD_KEY_R_ALT) {
761+
WORD key_code = VK_MENU;
762+
if (character == WD_KEY_R_ALT) {
763+
key_code = VK_RMENU;
764+
modifier_key_info.is_extended_key = true;
765+
}
766+
UINT scan_code = ::MapVirtualKey(key_code, MAPVK_VK_TO_VSC);
688767
modifier_key_info.key_code = VK_MENU;
768+
modifier_key_info.scan_code = scan_code;
689769
this->CreateKeyboardInputItem(modifier_key_info,
690-
0,
770+
KEYEVENTF_SCANCODE,
691771
input_state->is_alt_pressed);
692772
if (input_state->is_alt_pressed) {
693773
input_state->is_alt_pressed = false;
694774
} else {
695775
input_state->is_alt_pressed = true;
696776
}
697-
this->UpdatePressedKeys(WD_KEY_ALT, input_state->is_alt_pressed);
777+
this->UpdatePressedKeys(character, input_state->is_alt_pressed);
698778
}
699779

700780
// If the character represents the Meta (Windows) key, or represents
701781
// the "release all modifiers" key and the Meta key is down, send
702782
// the appropriate down or up keystroke for the Meta key.
703783
if (character == WD_KEY_META ||
704-
character == WD_KEY_R_META ||
705-
(character == WD_KEY_NULL && input_state->is_meta_pressed)) {
784+
character == WD_KEY_R_META) {
706785
//modifier_key_info.key_code = VK_LWIN;
707786
//this->CreateKeyboardInputItem(modifier_key_info,
708787
// 0,
@@ -738,7 +817,6 @@ void InputManager::AddKeyboardInput(HWND window_handle,
738817
}
739818
}
740819

741-
742820
unsigned short modifier_key_info = HIBYTE(key_info.key_code);
743821
if (modifier_key_info != 0) {
744822
// Requested key is a <modifier keys> + <key>. Thus, don't use the key code.
@@ -785,6 +863,12 @@ void InputManager::AddKeyboardInput(HWND window_handle,
785863
}
786864
}
787865

866+
bool InputManager::IsKeyPressed(wchar_t character) {
867+
return std::find(this->pressed_keys_.begin(),
868+
this->pressed_keys_.end(),
869+
character) != this->pressed_keys_.end();
870+
}
871+
788872
void InputManager::UpdatePressedKeys(wchar_t character, bool press_key) {
789873
std::wstring log_string = this->GetKeyDescription(character);
790874
if (press_key) {
@@ -1015,6 +1099,7 @@ KeyInfo InputManager::GetKeyInfo(HWND window_handle, wchar_t character) {
10151099
else if (character == WD_KEY_SEPARATOR) { // separator
10161100
key_info.key_code = VkKeyScanExW(L',', layout);
10171101
key_info.scan_code = MapVirtualKeyExW(LOBYTE(key_info.key_code), 0, layout);
1102+
key_info.is_extended_key = true;
10181103
}
10191104
else if (character == WD_KEY_SUBTRACT) { // subtract
10201105
key_info.key_code = VK_SUBTRACT;

cpp/iedriver/InputManager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ class InputManager {
116116
KeyInfo GetKeyInfo(HWND windows_handle, wchar_t character);
117117
InputState CloneCurrentInputState(void);
118118
void UpdatePressedKeys(wchar_t character, bool press_key);
119+
bool IsKeyPressed(wchar_t character);
119120

120121
void SetupKeyDescriptions(void);
121122
std::wstring GetKeyDescription(const wchar_t character);

0 commit comments

Comments
 (0)