1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Fixed hotkeys not working in some cases

See e.g. Swen Zwo.
This commit is contained in:
narzoul 2023-11-12 14:37:35 +01:00
parent 2f52e1028b
commit f96a0376bf
4 changed files with 61 additions and 9 deletions

View File

@ -29,6 +29,9 @@ public:
}
}
int getMax() const { return max; }
int getMin() const { return min; }
void reset()
{
m_bits.fill(0);

View File

@ -2,6 +2,7 @@
#include <Config/Parser.h>
#include <Input/HotKey.h>
#include <Input/Input.h>
namespace
{
@ -162,7 +163,7 @@ namespace
return modifiers.find(either) == modifiers.end() &&
modifiers.find(left) == modifiers.end() &&
modifiers.find(right) == modifiers.end() &&
(GetAsyncKeyState(either) & 0x8000);
Input::isKeyDown(either);
}
UINT getKeyCode(const std::string& name, const std::map<std::string, UINT>& keyNames)
@ -223,7 +224,7 @@ namespace Input
{
for (auto modifier : modifiers)
{
if (0 == (GetAsyncKeyState(modifier) & 0x8000))
if (!isKeyDown(modifier))
{
return false;
}

View File

@ -5,6 +5,7 @@
#include <Windows.h>
#include <winternl.h>
#include <Common/BitSet.h>
#include <Common/Hook.h>
#include <Common/Log.h>
#include <Common/Path.h>
@ -46,6 +47,7 @@ namespace
RECT g_monitorRect = {};
HHOOK g_keyboardHook = nullptr;
HHOOK g_mouseHook = nullptr;
BitSet<VK_LBUTTON, VK_OEM_CLEAR> g_keyState;
DInputMouseHookData g_dinputMouseHookData = {};
decltype(&PhysicalToLogicalPointForPerMonitorDPI) g_physicalToLogicalPointForPerMonitorDPI = nullptr;
@ -126,11 +128,24 @@ namespace
if (HC_ACTION == nCode &&
(WM_KEYDOWN == wParam || WM_KEYUP == wParam || WM_SYSKEYDOWN == wParam || WM_SYSKEYUP == wParam))
{
auto llHook = reinterpret_cast<const KBDLLHOOKSTRUCT*>(lParam);
if (static_cast<int>(llHook->vkCode) >= g_keyState.getMin() &&
static_cast<int>(llHook->vkCode) <= g_keyState.getMax())
{
if (WM_KEYDOWN == wParam || WM_SYSKEYDOWN == wParam)
{
g_keyState.set(llHook->vkCode);
}
else
{
g_keyState.reset(llHook->vkCode);
}
}
DWORD pid = 0;
GetWindowThreadProcessId(GetForegroundWindow(), &pid);
if (GetCurrentProcessId() == pid)
{
auto llHook = reinterpret_cast<const KBDLLHOOKSTRUCT*>(lParam);
for (auto& hotkey : g_hotKeys)
{
if (hotkey.first.vk == llHook->vkCode && Input::areModifierKeysDown(hotkey.first.modifiers))
@ -235,7 +250,13 @@ namespace
{
UnhookWindowsHookEx(g_keyboardHook);
}
g_keyState.reset();
g_keyboardHook = CALL_ORIG_FUNC(SetWindowsHookExA)(WH_KEYBOARD_LL, &lowLevelKeyboardProc, nullptr, 0);
if (!g_keyboardHook)
{
LOG_ONCE("ERROR: Failed to install low level keyboard hook, error code: " << GetLastError());
}
});
}
@ -251,12 +272,19 @@ namespace
g_origCursorPos = { MAXLONG, MAXLONG };
g_mouseHook = CALL_ORIG_FUNC(SetWindowsHookExA)(WH_MOUSE_LL, &lowLevelMouseProc, nullptr, 0);
INPUT inputs[2] = {};
inputs[0].mi.dy = 1;
inputs[0].mi.dwFlags = MOUSEEVENTF_MOVE;
inputs[1].mi.dx = 1;
inputs[1].mi.dwFlags = MOUSEEVENTF_MOVE;
SendInput(2, inputs, sizeof(INPUT));
if (g_mouseHook)
{
INPUT inputs[2] = {};
inputs[0].mi.dy = 1;
inputs[0].mi.dwFlags = MOUSEEVENTF_MOVE;
inputs[1].mi.dx = 1;
inputs[1].mi.dwFlags = MOUSEEVENTF_MOVE;
SendInput(2, inputs, sizeof(INPUT));
}
else
{
LOG_ONCE("ERROR: Failed to install low level mouse hook, error code: " << GetLastError());
}
});
}
@ -391,6 +419,25 @@ namespace Input
registerHotKey(Config::terminateHotKey.get(), onTerminate, nullptr, false);
}
bool isKeyDown(int vk)
{
switch (vk)
{
case VK_SHIFT:
return g_keyState.test(VK_LSHIFT) || g_keyState.test(VK_RSHIFT);
case VK_CONTROL:
return g_keyState.test(VK_LCONTROL) || g_keyState.test(VK_RCONTROL);
case VK_MENU:
return g_keyState.test(VK_LMENU) || g_keyState.test(VK_RMENU);
}
if (vk >= g_keyState.getMin() && vk <= g_keyState.getMax())
{
return g_keyState.test(vk);
}
return false;
}
void registerHotKey(const HotKey& hotKey, std::function<void(void*)> action, void* context, bool onKeyDown)
{
if (0 != hotKey.vk)

View File

@ -21,6 +21,7 @@ namespace Input
HWND getCursorWindow();
POINT getRelativeCursorPos();
void installHooks();
bool isKeyDown(int vk);
void registerHotKey(const HotKey& hotKey, std::function<void(void*)> action, void* context, bool onKeydown = true);
void setCapture(Overlay::Control* control);
void updateCursor();