Skip to content

Commit b87cda3

Browse files
Better hotkey simulation
1 parent 8f68d0b commit b87cda3

File tree

3 files changed

+68
-21
lines changed

3 files changed

+68
-21
lines changed

fixlayouts.c

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ void ConvertSelectedTextInActiveWindow(HKL hklSource, HKL hklTarget)
2525
}
2626

2727
// copy the selected text by simulating Ctrl-C
28-
SendKeyCombo(VK_CONTROL, 'C', FALSE);
28+
SendKeyCombo('C', TRUE, FALSE, FALSE);
2929

3030
// wait until copy operation completes and get the copied data from the clipboard
3131
// this loop has the nice side effect of setting copyOK to FALSE if there's no
@@ -67,7 +67,7 @@ void ConvertSelectedTextInActiveWindow(HKL hklSource, HKL hklTarget)
6767
if(SetClipboardText(targetText))
6868
{
6969
// simulate Ctrl-V to paste the text, replacing the previous text
70-
SendKeyCombo(VK_CONTROL, 'V', FALSE);
70+
SendKeyCombo('V', TRUE, FALSE, FALSE);
7171

7272
// let the application complete pasting before putting the old data back on the clipboard
7373
Sleep(REMOTE_APP_WAIT);
@@ -334,22 +334,69 @@ BOOL SetClipboardText(const WCHAR* text)
334334
}
335335

336336
///////////////////////////////////////////////////////////////////////////////
337-
// Simulates a key press in the active window
338-
void SendKey(BYTE vk, BOOL extended)
337+
// Simulates a key combination (such as Ctrl+X) in the active window
338+
void SendKeyCombo(BYTE vk, BOOL ctrl, BOOL alt, BOOL shift)
339339
{
340-
keybd_event(vk, 0, extended ? KEYEVENTF_EXTENDEDKEY : 0, 0);
341-
keybd_event(vk, 0, KEYEVENTF_KEYUP | (extended ? KEYEVENTF_EXTENDEDKEY : 0), 0);
340+
BYTE vkModifiers[3] = { VK_CONTROL, VK_MENU, VK_SHIFT };
341+
BOOL bModRequested[3] = { ctrl != 0, alt != 0, shift != 0 };
342+
BOOL bModPressed[3];
343+
BOOL bKeyPressed;
344+
345+
for(int i = 0; i < 3; i++)
346+
bModPressed[i] = GetKeyState(vkModifiers[i]) < 0;
347+
348+
bKeyPressed = GetKeyState(vk) < 0;
349+
350+
for(int i = 0; i < 3; i++)
351+
{
352+
if(bModRequested[i] != bModPressed[i])
353+
keybd_event(vkModifiers[i], 0, bModPressed[i] ? KEYEVENTF_KEYUP : 0, 0);
354+
}
355+
356+
if(!bKeyPressed)
357+
{
358+
keybd_event(vk, 0, 0, 0);
359+
keybd_event(vk, 0, KEYEVENTF_KEYUP, 0);
360+
}
361+
else
362+
{
363+
keybd_event(vk, 0, KEYEVENTF_KEYUP, 0);
364+
keybd_event(vk, 0, 0, 0);
365+
}
366+
367+
for(int i = 3; i >= 0; i--)
368+
{
369+
if(bModRequested[i] != bModPressed[i])
370+
keybd_event(vkModifiers[i], 0, bModPressed[i] ? 0 : KEYEVENTF_KEYUP, 0);
371+
}
342372
}
343373

344374
///////////////////////////////////////////////////////////////////////////////
345-
// Simulates a key combination (such as Ctrl+X) in the active window
346-
void SendKeyCombo(BYTE vkModifier, BYTE vk, BOOL extended)
375+
// Simulates Alt+Shift to change languages
376+
void SendAltShift()
347377
{
348-
BOOL modPressed = GetKeyState(vkModifier) < 0;
349-
if(!modPressed)
350-
keybd_event(vkModifier, 0, 0, 0);
351-
keybd_event(vk, 0, extended ? KEYEVENTF_EXTENDEDKEY : 0, 0);
352-
keybd_event(vk, 0, KEYEVENTF_KEYUP | (extended ? KEYEVENTF_EXTENDEDKEY : 0), 0);
353-
if(!modPressed)
354-
keybd_event(vkModifier, 0, KEYEVENTF_KEYUP, 0);
378+
BYTE vkModifiers[3] = { VK_CONTROL, VK_MENU, VK_SHIFT };
379+
BOOL bModRequested[3] = { FALSE, TRUE, TRUE };
380+
BOOL bModPressed[3];
381+
382+
for(int i = 0; i < 3; i++)
383+
bModPressed[i] = GetKeyState(vkModifiers[i]) < 0;
384+
385+
for(int i = 0; i < 3; i++)
386+
{
387+
if(bModRequested[i] != bModPressed[i])
388+
keybd_event(vkModifiers[i], 0, bModPressed[i] ? KEYEVENTF_KEYUP : 0, 0);
389+
}
390+
391+
if(bModRequested[2] && bModPressed[2])
392+
{
393+
keybd_event(vkModifiers[2], 0, KEYEVENTF_KEYUP, 0);
394+
keybd_event(vkModifiers[2], 0, 0, 0);
395+
}
396+
397+
for(int i = 3; i >= 0; i--)
398+
{
399+
if(bModRequested[i] != bModPressed[i])
400+
keybd_event(vkModifiers[i], 0, bModPressed[i] ? 0 : KEYEVENTF_KEYUP, 0);
401+
}
355402
}

fixlayouts.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,5 @@ WCHAR* GetClipboardText();
3535
BOOL SetClipboardText(const WCHAR* text);
3636

3737
// Functions that simulate key presses in the current window
38-
void SendKey(BYTE vk, BOOL extended);
39-
void SendKeyCombo(BYTE vkModifier, BYTE vk, BOOL extended);
38+
void SendKeyCombo(BYTE vk, BOOL ctrl, BOOL alt, BOOL shift);
39+
void SendAltShift();

recaps.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -451,10 +451,10 @@ HKL SwitchLayout(HWND hWnd, HKL hkl)
451451
{
452452
BOOL bBuggy = FALSE;
453453

454-
HWND hRootWnd = GetAncestor(hWnd, GA_ROOT);
454+
HWND hRootOwnerWnd = GetAncestor(hWnd, GA_ROOTOWNER);
455455

456456
WCHAR szClassName[256];
457-
if(hRootWnd && GetClassName(hRootWnd, szClassName, _countof(szClassName)))
457+
if(hRootOwnerWnd && GetClassName(hRootOwnerWnd, szClassName, _countof(szClassName)))
458458
{
459459
// Skype and Word hang when posting WM_INPUTLANGCHANGEREQUEST.
460460
if(wcscmp(szClassName, L"tSkMainForm") == 0 ||
@@ -475,7 +475,7 @@ HKL SwitchLayout(HWND hWnd, HKL hkl)
475475
break;
476476

477477
// Change layout by simulating Alt+Shift.
478-
SendKeyCombo(VK_MENU, VK_SHIFT, FALSE);
478+
SendAltShift();
479479

480480
// Wait for the change to apply.
481481
for(UINT j = 0; j < 10; j++)
@@ -566,7 +566,7 @@ void SwitchAndConvert(void *pParam)
566566
{
567567
if(bSelectAll)
568568
{
569-
SendKeyCombo(VK_CONTROL, 'A', FALSE);
569+
SendKeyCombo('A', TRUE, FALSE, FALSE);
570570
}
571571

572572
HKL sourceLayout = GetCurrentLayout();

0 commit comments

Comments
 (0)