| Line |
Branch |
Decision |
Call |
Exec |
Source |
| 1 |
|
|
|
|
#include "BaseNativeShortcutHandler.h" |
| 2 |
|
|
|
|
|
| 3 |
|
|
|
|
#include <ranges> |
| 4 |
|
|
|
|
#include <unordered_map> |
| 5 |
|
|
|
|
|
| 6 |
|
|
|
|
#include "Logging.h" |
| 7 |
|
|
|
|
#define LOGGER_NAME "Shortcut Handler" |
| 8 |
|
|
|
|
|
| 9 |
|
|
|
|
using namespace CLO3D; |
| 10 |
|
|
|
|
|
| 11 |
|
|
|
|
// TODO: class for statics |
| 12 |
|
|
|
|
static int nextId = 1; |
| 13 |
|
|
|
|
static std::unordered_map<int, BaseNativeShortcutHandler*> registry; |
| 14 |
|
|
|
|
|
| 15 |
|
|
|
|
#ifdef _WIN32 |
| 16 |
|
|
|
|
#include <Windows.h> |
| 17 |
|
|
|
|
HHOOK listenerHook = nullptr; |
| 18 |
|
|
|
|
|
| 19 |
|
|
|
|
LRESULT nativeEventHandler(const int nCode, const WPARAM wParam, const LPARAM lParam) { |
| 20 |
|
|
|
|
if (nCode == HC_ACTION) { |
| 21 |
|
|
|
|
const MSG* msg = reinterpret_cast<MSG*>(lParam); |
| 22 |
|
|
|
|
if (msg->message == WM_HOTKEY) { |
| 23 |
|
|
|
|
BaseNativeShortcutHandler::getEventHandler(msg->wParam)->handle(); |
| 24 |
|
|
|
|
} |
| 25 |
|
|
|
|
} |
| 26 |
|
|
|
|
return CallNextHookEx(nullptr, nCode, wParam, lParam); |
| 27 |
|
|
|
|
} |
| 28 |
|
|
|
|
#endif |
| 29 |
|
|
|
|
|
| 30 |
|
|
0/13
✗ Call 0 not invoked.
✗ Call 1 not invoked.
✗ Call 2 not invoked.
✗ Call 3 not invoked.
✗ Call 4 not invoked.
✗ Call 5 not invoked.
✗ Call 6 not invoked.
✗ Call 7 not invoked.
✗ Call 8 not invoked.
✗ Call 9 not invoked.
✗ Call 10 not invoked.
✗ Call 11 not invoked.
✗ Call 12 not invoked.
|
✗ |
BaseNativeShortcutHandler::BaseNativeShortcutHandler(const QKeySequence &shortcut): id_(nextId++), shortcut_(shortcut) { |
| 31 |
|
|
0/5
✗ Call 0 not invoked.
✗ Call 1 not invoked.
✗ Call 2 not invoked.
✗ Call 3 not invoked.
✗ Call 6 not invoked.
|
✗ |
registry[id_] = this; |
| 32 |
|
|
0/2
✗ Call 0 not invoked.
✗ Call 1 not invoked.
|
✗ |
} |
| 33 |
|
|
|
|
|
| 34 |
|
|
0/4
✗ Call 0 not invoked.
✗ Call 1 not invoked.
✗ Call 2 not invoked.
✗ Call 3 not invoked.
|
✗ |
BaseNativeShortcutHandler::~BaseNativeShortcutHandler() { |
| 35 |
|
|
0/4
✗ Call 0 not invoked.
✗ Call 1 not invoked.
✗ Call 2 not invoked.
✗ Call 3 not invoked.
|
✗ |
registry.erase(id_); |
| 36 |
|
|
|
|
#ifdef _WIN32 |
| 37 |
|
|
|
|
UnregisterHotKey(nullptr, id_); |
| 38 |
|
|
|
|
#endif |
| 39 |
|
|
0/2
✗ Call 0 not invoked.
✗ Call 1 not invoked.
|
✗ |
} |
| 40 |
|
|
|
|
|
| 41 |
|
|
|
✗ |
BaseNativeShortcutHandler* BaseNativeShortcutHandler::getEventHandler(const int id) { |
| 42 |
|
|
0/2
✗ Call 0 not invoked.
✗ Call 1 not invoked.
|
✗ |
return registry[id]; |
| 43 |
|
|
|
|
} |
| 44 |
|
|
|
|
|
| 45 |
|
|
|
✗ |
void BaseNativeShortcutHandler::stopListening() { |
| 46 |
|
|
|
|
#ifdef _WIN32 |
| 47 |
|
|
|
|
UnhookWindowsHookEx(listenerHook); |
| 48 |
|
|
|
|
#endif |
| 49 |
|
|
|
✗ |
} |
| 50 |
|
|
|
|
|
| 51 |
|
|
|
✗ |
void BaseNativeShortcutHandler::startListening() { |
| 52 |
|
|
|
|
#ifdef _WIN32 |
| 53 |
|
|
|
|
listenerHook = SetWindowsHookEx(WH_GETMESSAGE, &nativeEventHandler, nullptr, GetCurrentThreadId()); |
| 54 |
|
|
|
|
#endif |
| 55 |
|
|
|
✗ |
} |
| 56 |
|
|
|
|
|
| 57 |
|
|
|
✗ |
void BaseNativeShortcutHandler::registerShortcuts() { |
| 58 |
|
0/1
? Decision couldn't be analyzed.
|
0/11
✗ Call 0 not invoked.
✗ Call 1 not invoked.
✗ Call 2 not invoked.
✗ Call 3 not invoked.
✗ Call 6 not invoked.
✗ Call 7 not invoked.
✗ Call 8 not invoked.
✗ Call 11 not invoked.
✗ Call 12 not invoked.
✗ Call 13 not invoked.
✗ Call 14 not invoked.
|
✗ |
for (const auto &handler: registry | std::views::values) { |
| 59 |
|
|
0/8
✗ Call 0 not invoked.
✗ Call 1 not invoked.
✗ Call 2 not invoked.
✗ Call 3 not invoked.
✗ Call 4 not invoked.
✗ Call 5 not invoked.
✗ Call 6 not invoked.
✗ Call 7 not invoked.
|
✗ |
handler->registerShortcut(); |
| 60 |
|
|
|
|
} |
| 61 |
|
|
|
✗ |
} |
| 62 |
|
|
|
|
|
| 63 |
|
|
|
✗ |
void BaseNativeShortcutHandler::setShortcut(const QKeySequence &shortcut) { |
| 64 |
|
|
0/4
✗ Call 0 not invoked.
✗ Call 1 not invoked.
✗ Call 2 not invoked.
✗ Call 3 not invoked.
|
✗ |
shortcut_ = shortcut; |
| 65 |
|
|
0/4
✗ Call 0 not invoked.
✗ Call 1 not invoked.
✗ Call 2 not invoked.
✗ Call 3 not invoked.
|
✗ |
registerShortcut(); |
| 66 |
|
|
|
✗ |
} |
| 67 |
|
|
|
|
|
| 68 |
|
|
|
✗ |
void BaseNativeShortcutHandler::registerShortcut() const { |
| 69 |
|
|
|
|
#ifdef _WIN32 |
| 70 |
|
|
|
|
const auto key = shortcut_[0] & ~Qt::KeyboardModifierMask & 0xFFFF;; |
| 71 |
|
|
|
|
const auto qtModifiers = shortcut_[0] & Qt::KeyboardModifierMask; |
| 72 |
|
|
|
|
|
| 73 |
|
|
|
|
UINT winModifiers = 0; |
| 74 |
|
|
|
|
if (qtModifiers & Qt::ControlModifier) winModifiers |= MOD_CONTROL; |
| 75 |
|
|
|
|
if (qtModifiers & Qt::ShiftModifier) winModifiers |= MOD_SHIFT; |
| 76 |
|
|
|
|
if (qtModifiers & Qt::AltModifier) winModifiers |= MOD_ALT; |
| 77 |
|
|
|
|
if (qtModifiers & Qt::MetaModifier) winModifiers |= MOD_WIN; |
| 78 |
|
|
|
|
|
| 79 |
|
|
|
|
UnregisterHotKey(nullptr, id_); |
| 80 |
|
|
|
|
if (!RegisterHotKey(nullptr, id_, winModifiers, key)) { |
| 81 |
|
|
|
|
LOG_ERROR("Shortcut registration failed: {}", GetLastError()); |
| 82 |
|
|
|
|
} |
| 83 |
|
|
|
|
#endif |
| 84 |
|
|
|
✗ |
} |
| 85 |
|
|
|
|
|