replace uglobalhotkey submodule with localized version (#117)
parent
7382bb5244
commit
f5cbc2c888
|
@ -1,3 +0,0 @@
|
|||
[submodule "tools/UGlobalHotkey"]
|
||||
path = tools/UGlobalHotkey
|
||||
url = https://github.com/JoelAtDeluxe/UGlobalHotkey.git
|
20
ashirt.pro
20
ashirt.pro
|
@ -1,4 +1,4 @@
|
|||
QT += core gui network sql widgets
|
||||
QT += core gui network sql widgets gui-private
|
||||
|
||||
CONFIG += c++11
|
||||
TEMPLATE = app
|
||||
|
@ -66,6 +66,8 @@ SOURCES += \
|
|||
src/forms/getinfo/getinfo.cpp \
|
||||
src/forms/porting/porting_dialog.cpp \
|
||||
src/helpers/clipboard/clipboardhelper.cpp \
|
||||
src/helpers/hotkeys/uglobalhotkeys.cpp \
|
||||
src/helpers/hotkeys/ukeysequence.cpp \
|
||||
src/models/codeblock.cpp \
|
||||
src/helpers/multipartparser.cpp \
|
||||
src/hotkeymanager.cpp \
|
||||
|
@ -111,6 +113,10 @@ HEADERS += \
|
|||
src/forms/porting/porting_dialog.h \
|
||||
src/helpers/clipboard/clipboardhelper.h \
|
||||
src/helpers/constants.h \
|
||||
src/helpers/hotkeys/hotkeymap.h \
|
||||
src/helpers/hotkeys/uglobal.h \
|
||||
src/helpers/hotkeys/uglobalhotkeys.h \
|
||||
src/helpers/hotkeys/ukeysequence.h \
|
||||
src/helpers/request_builder.h \
|
||||
src/helpers/system_helpers.h \
|
||||
src/helpers/ui_helpers.h \
|
||||
|
@ -137,7 +143,17 @@ HEADERS += \
|
|||
src/forms/evidence/evidencemanager.h \
|
||||
src/forms/settings/settings.h
|
||||
|
||||
include(tools/UGlobalHotkey/uglobalhotkey.pri)
|
||||
linux: LIBS += -lxcb -lxcb-keysyms
|
||||
mac: LIBS += -framework Carbon
|
||||
|
||||
windows {
|
||||
*-g++* {
|
||||
LIBS += -luser32
|
||||
}
|
||||
*-msvc* {
|
||||
LIBS += user32.lib
|
||||
}
|
||||
}
|
||||
|
||||
macx {
|
||||
ICON = icons/ashirt.icns
|
||||
|
|
|
@ -0,0 +1,296 @@
|
|||
#include <QtCore>
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
inline size_t QtKeyToWin(Qt::Key key)
|
||||
{
|
||||
switch ((Qt::Key)key) {
|
||||
case Qt::Key_Escape:
|
||||
return VK_ESCAPE;
|
||||
case Qt::Key_Tab:
|
||||
case Qt::Key_Backtab:
|
||||
return VK_TAB;
|
||||
case Qt::Key_Backspace:
|
||||
return VK_BACK;
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Enter:
|
||||
return VK_RETURN;
|
||||
case Qt::Key_Insert:
|
||||
return VK_INSERT;
|
||||
case Qt::Key_Delete:
|
||||
return VK_DELETE;
|
||||
case Qt::Key_Pause:
|
||||
return VK_PAUSE;
|
||||
case Qt::Key_Print:
|
||||
return VK_SNAPSHOT;
|
||||
case Qt::Key_Clear:
|
||||
return VK_CLEAR;
|
||||
case Qt::Key_Home:
|
||||
return VK_HOME;
|
||||
case Qt::Key_End:
|
||||
return VK_END;
|
||||
case Qt::Key_Left:
|
||||
return VK_LEFT;
|
||||
case Qt::Key_Up:
|
||||
return VK_UP;
|
||||
case Qt::Key_Right:
|
||||
return VK_RIGHT;
|
||||
case Qt::Key_Down:
|
||||
return VK_DOWN;
|
||||
case Qt::Key_PageUp:
|
||||
return VK_PRIOR;
|
||||
case Qt::Key_PageDown:
|
||||
return VK_NEXT;
|
||||
case Qt::Key_F1:
|
||||
return VK_F1;
|
||||
case Qt::Key_F2:
|
||||
return VK_F2;
|
||||
case Qt::Key_F3:
|
||||
return VK_F3;
|
||||
case Qt::Key_F4:
|
||||
return VK_F4;
|
||||
case Qt::Key_F5:
|
||||
return VK_F5;
|
||||
case Qt::Key_F6:
|
||||
return VK_F6;
|
||||
case Qt::Key_F7:
|
||||
return VK_F7;
|
||||
case Qt::Key_F8:
|
||||
return VK_F8;
|
||||
case Qt::Key_F9:
|
||||
return VK_F9;
|
||||
case Qt::Key_F10:
|
||||
return VK_F10;
|
||||
case Qt::Key_F11:
|
||||
return VK_F11;
|
||||
case Qt::Key_F12:
|
||||
return VK_F12;
|
||||
case Qt::Key_F13:
|
||||
return VK_F13;
|
||||
case Qt::Key_F14:
|
||||
return VK_F14;
|
||||
case Qt::Key_F15:
|
||||
return VK_F15;
|
||||
case Qt::Key_F16:
|
||||
return VK_F16;
|
||||
case Qt::Key_F17:
|
||||
return VK_F17;
|
||||
case Qt::Key_F18:
|
||||
return VK_F18;
|
||||
case Qt::Key_F19:
|
||||
return VK_F19;
|
||||
case Qt::Key_F20:
|
||||
return VK_F20;
|
||||
case Qt::Key_F21:
|
||||
return VK_F21;
|
||||
case Qt::Key_F22:
|
||||
return VK_F22;
|
||||
case Qt::Key_F23:
|
||||
return VK_F23;
|
||||
case Qt::Key_F24:
|
||||
return VK_F24;
|
||||
case Qt::Key_Space:
|
||||
return VK_SPACE;
|
||||
case Qt::Key_Asterisk:
|
||||
return VK_MULTIPLY;
|
||||
case Qt::Key_Plus:
|
||||
return VK_ADD;
|
||||
case Qt::Key_Comma:
|
||||
return VK_SEPARATOR;
|
||||
case Qt::Key_Minus:
|
||||
return VK_SUBTRACT;
|
||||
case Qt::Key_Slash:
|
||||
return VK_DIVIDE;
|
||||
case Qt::Key_MediaNext:
|
||||
return VK_MEDIA_NEXT_TRACK;
|
||||
case Qt::Key_MediaPrevious:
|
||||
return VK_MEDIA_PREV_TRACK;
|
||||
case Qt::Key_MediaPlay:
|
||||
return VK_MEDIA_PLAY_PAUSE;
|
||||
case Qt::Key_MediaStop:
|
||||
return VK_MEDIA_STOP;
|
||||
case Qt::Key_VolumeDown:
|
||||
return VK_VOLUME_DOWN;
|
||||
case Qt::Key_VolumeUp:
|
||||
return VK_VOLUME_UP;
|
||||
case Qt::Key_VolumeMute:
|
||||
return VK_VOLUME_MUTE;
|
||||
}
|
||||
|
||||
if (key >= 0x01000030 && key <= 0x01000047) {
|
||||
return VK_F1 + (key - Qt::Key_F1);
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
#elif defined(Q_OS_LINUX)
|
||||
|
||||
#include "ukeysequence.h"
|
||||
#include <unordered_map>
|
||||
#include "xcb/xcb.h"
|
||||
#include "xcb/xcb_keysyms.h"
|
||||
#include "X11/keysym.h"
|
||||
|
||||
struct UKeyData {
|
||||
int key;
|
||||
int mods;
|
||||
};
|
||||
|
||||
static std::unordered_map<uint32_t, uint32_t> KEY_MAP = {
|
||||
{Qt::Key_Escape, XK_Escape},
|
||||
{Qt::Key_Tab, XK_Tab},
|
||||
{Qt::Key_Backspace, XK_BackSpace},
|
||||
{Qt::Key_Return, XK_Return},
|
||||
{Qt::Key_Enter, XK_Return},
|
||||
{Qt::Key_Insert, XK_Insert},
|
||||
{Qt::Key_Delete, XK_Delete},
|
||||
{Qt::Key_Pause, XK_Pause},
|
||||
{Qt::Key_Print, XK_Print},
|
||||
{Qt::Key_SysReq, XK_Sys_Req},
|
||||
{Qt::Key_Clear, XK_Clear},
|
||||
{Qt::Key_Home, XK_Home},
|
||||
{Qt::Key_End, XK_End},
|
||||
{Qt::Key_Left, XK_Left},
|
||||
{Qt::Key_Up, XK_Up},
|
||||
{Qt::Key_Right, XK_Right},
|
||||
{Qt::Key_Down, XK_Down},
|
||||
{Qt::Key_PageUp, XK_Page_Up},
|
||||
{Qt::Key_PageDown, XK_Page_Down}
|
||||
};
|
||||
|
||||
inline UKeyData QtKeyToLinux(const UKeySequence &keySeq)
|
||||
{
|
||||
UKeyData data = {0, 0};
|
||||
|
||||
auto key = keySeq.getSimpleKeys();
|
||||
if (key.size() > 0) {
|
||||
data.key = key[0];
|
||||
} else {
|
||||
qWarning() << "Invalid hotkey";
|
||||
return data;
|
||||
}
|
||||
// Key conversion
|
||||
// Misc Keys
|
||||
if (KEY_MAP.find(key[0]) != KEY_MAP.end()) {
|
||||
data.key = KEY_MAP[key[0]];
|
||||
} else if (data.key >= Qt::Key_F1 && data.key <= Qt::Key_F35) { // Qt's F keys need conversion
|
||||
const size_t DIFF = Qt::Key_F1 - XK_F1;
|
||||
data.key -= DIFF;
|
||||
} else if (data.key >= Qt::Key_Space && data.key <= Qt::Key_QuoteLeft) {
|
||||
// conversion is not necessary, if the value in the range Qt::Key_Space - Qt::Key_QuoteLeft
|
||||
} else {
|
||||
qWarning() << "Invalid hotkey: key conversion is not defined";
|
||||
return data;
|
||||
}
|
||||
|
||||
// Modifiers conversion
|
||||
auto mods = keySeq.getModifiers();
|
||||
|
||||
for (auto i : mods) {
|
||||
if (i == Qt::Key_Shift)
|
||||
data.mods |= XCB_MOD_MASK_SHIFT;
|
||||
else if (i == Qt::Key_Control)
|
||||
data.mods |= XCB_MOD_MASK_CONTROL;
|
||||
else if (i == Qt::Key_Alt)
|
||||
data.mods |= XCB_MOD_MASK_1;
|
||||
else if (i == Qt::Key_Meta)
|
||||
data.mods |= XCB_MOD_MASK_4; // !
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
#elif defined(Q_OS_MAC)
|
||||
|
||||
#include "ukeysequence.h"
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <unordered_map>
|
||||
|
||||
struct UKeyData {
|
||||
uint32_t key;
|
||||
uint32_t mods;
|
||||
};
|
||||
|
||||
static std::unordered_map<uint32_t, uint32_t> KEY_MAP = {
|
||||
{Qt::Key_A, kVK_ANSI_A},
|
||||
{Qt::Key_B, kVK_ANSI_B},
|
||||
{Qt::Key_C, kVK_ANSI_C},
|
||||
{Qt::Key_D, kVK_ANSI_D},
|
||||
{Qt::Key_E, kVK_ANSI_E},
|
||||
{Qt::Key_F, kVK_ANSI_F},
|
||||
{Qt::Key_G, kVK_ANSI_G},
|
||||
{Qt::Key_H, kVK_ANSI_H},
|
||||
{Qt::Key_I, kVK_ANSI_I},
|
||||
{Qt::Key_J, kVK_ANSI_J},
|
||||
{Qt::Key_K, kVK_ANSI_K},
|
||||
{Qt::Key_L, kVK_ANSI_L},
|
||||
{Qt::Key_M, kVK_ANSI_M},
|
||||
{Qt::Key_N, kVK_ANSI_N},
|
||||
{Qt::Key_O, kVK_ANSI_O},
|
||||
{Qt::Key_P, kVK_ANSI_P},
|
||||
{Qt::Key_Q, kVK_ANSI_Q},
|
||||
{Qt::Key_R, kVK_ANSI_R},
|
||||
{Qt::Key_S, kVK_ANSI_S},
|
||||
{Qt::Key_T, kVK_ANSI_T},
|
||||
{Qt::Key_U, kVK_ANSI_U},
|
||||
{Qt::Key_V, kVK_ANSI_V},
|
||||
{Qt::Key_W, kVK_ANSI_W},
|
||||
{Qt::Key_X, kVK_ANSI_X},
|
||||
{Qt::Key_Y, kVK_ANSI_Y},
|
||||
{Qt::Key_Z, kVK_ANSI_Z},
|
||||
{Qt::Key_0, kVK_ANSI_0},
|
||||
{Qt::Key_1, kVK_ANSI_1},
|
||||
{Qt::Key_2, kVK_ANSI_2},
|
||||
{Qt::Key_3, kVK_ANSI_3},
|
||||
{Qt::Key_4, kVK_ANSI_4},
|
||||
{Qt::Key_5, kVK_ANSI_5},
|
||||
{Qt::Key_6, kVK_ANSI_6},
|
||||
{Qt::Key_7, kVK_ANSI_7},
|
||||
{Qt::Key_8, kVK_ANSI_8},
|
||||
{Qt::Key_9, kVK_ANSI_9},
|
||||
{Qt::Key_F1, kVK_F1},
|
||||
{Qt::Key_F2, kVK_F2},
|
||||
{Qt::Key_F3, kVK_F3},
|
||||
{Qt::Key_F4, kVK_F4},
|
||||
{Qt::Key_F5, kVK_F5},
|
||||
{Qt::Key_F6, kVK_F6},
|
||||
{Qt::Key_F7, kVK_F7},
|
||||
{Qt::Key_F8, kVK_F8},
|
||||
{Qt::Key_F9, kVK_F9},
|
||||
{Qt::Key_F10, kVK_F10},
|
||||
{Qt::Key_F11, kVK_F11},
|
||||
{Qt::Key_F12, kVK_F12},
|
||||
{Qt::Key_F13, kVK_F13},
|
||||
{Qt::Key_F14, kVK_F14},
|
||||
{Qt::Key_Print, kVK_F14},
|
||||
};
|
||||
|
||||
static std::unordered_map<uint32_t, uint32_t> MOD_MAP = {
|
||||
{Qt::Key_Shift, shiftKey},
|
||||
{Qt::Key_Alt, optionKey},
|
||||
{Qt::Key_Control, controlKey},
|
||||
{Qt::Key_Option, optionKey},
|
||||
{Qt::Key_Meta, cmdKey},
|
||||
};
|
||||
|
||||
inline UKeyData QtKeyToMac(const UKeySequence &keySeq)
|
||||
{
|
||||
UKeyData data = {0, 0};
|
||||
auto key = keySeq.getSimpleKeys();
|
||||
auto mods = keySeq.getModifiers();
|
||||
|
||||
if (key.size() == 1 && KEY_MAP.find(key[0]) != KEY_MAP.end()) {
|
||||
data.key = KEY_MAP[key[0]];
|
||||
} else {
|
||||
qWarning() << "Invalid hotkey";
|
||||
return data;
|
||||
}
|
||||
|
||||
for (auto && mod : mods) {
|
||||
if (MOD_MAP.find(mod) == MOD_MAP.end())
|
||||
return data;
|
||||
|
||||
data.mods += MOD_MAP[mod];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef UGLOBAL_H
|
||||
#define UGLOBAL_H
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
#if defined(UGLOBALHOTKEY_LIBRARY)
|
||||
# define UGLOBALHOTKEY_EXPORT Q_DECL_EXPORT
|
||||
#elif defined(UGLOBALHOTKEY_NOEXPORT)
|
||||
# define UGLOBALHOTKEY_EXPORT
|
||||
#else
|
||||
# define UGLOBALHOTKEY_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#endif // UGLOBAL_H
|
|
@ -0,0 +1,237 @@
|
|||
#include <QtCore>
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <windows.h>
|
||||
#elif defined(Q_OS_LINUX)
|
||||
#include <QWindow>
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
#include <QApplication>
|
||||
#endif
|
||||
|
||||
#include "hotkeymap.h"
|
||||
#include "uglobalhotkeys.h"
|
||||
|
||||
UGlobalHotkeys::UGlobalHotkeys(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
#if defined(Q_OS_LINUX)
|
||||
qApp->installNativeEventFilter(this);
|
||||
QWindow wndw;
|
||||
void *v = qApp->platformNativeInterface()->nativeResourceForWindow("connection", &wndw);
|
||||
X11Connection = (xcb_connection_t *)v;
|
||||
X11Wid = xcb_setup_roots_iterator(xcb_get_setup(X11Connection)).data->root;
|
||||
X11KeySymbs = xcb_key_symbols_alloc(X11Connection);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UGlobalHotkeys::registerHotkey(const QString &keySeq, size_t id)
|
||||
{
|
||||
return registerHotkey(UKeySequence(keySeq), id);
|
||||
}
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
OSStatus macHotkeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData)
|
||||
{
|
||||
Q_UNUSED(nextHandler);
|
||||
EventHotKeyID hkCom;
|
||||
GetEventParameter(theEvent, kEventParamDirectObject, typeEventHotKeyID, NULL,
|
||||
sizeof(hkCom), NULL, &hkCom);
|
||||
size_t id = hkCom.id;
|
||||
|
||||
UGlobalHotkeys *caller = (UGlobalHotkeys *)userData;
|
||||
caller->onHotkeyPressed(id);
|
||||
return noErr;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool UGlobalHotkeys::registerHotkey(const UKeySequence &keySeq, size_t id)
|
||||
{
|
||||
if (keySeq.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_LINUX)
|
||||
if (Registered.find(id) != Registered.end()) {
|
||||
unregisterHotkey(id);
|
||||
}
|
||||
#endif
|
||||
#if defined(Q_OS_WIN)
|
||||
size_t winMod = 0;
|
||||
size_t key = VK_F2;
|
||||
|
||||
for (size_t i = 0; i != keySeq.size(); i++) {
|
||||
if (keySeq[i] == Qt::Key_Control) {
|
||||
winMod |= MOD_CONTROL;
|
||||
} else if (keySeq[i] == Qt::Key_Alt) {
|
||||
winMod |= MOD_ALT;
|
||||
} else if (keySeq[i] == Qt::Key_Shift) {
|
||||
winMod |= MOD_SHIFT;
|
||||
} else if (keySeq[i] == Qt::Key_Meta) {
|
||||
winMod |= MOD_WIN;
|
||||
} else {
|
||||
key = QtKeyToWin(keySeq[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!RegisterHotKey((HWND)winId(), id, winMod, key)) {
|
||||
return false;
|
||||
} else {
|
||||
Registered.insert(id);
|
||||
}
|
||||
#elif defined(Q_OS_LINUX)
|
||||
regLinuxHotkey(keySeq, id);
|
||||
#endif
|
||||
#if defined(Q_OS_MAC)
|
||||
unregisterHotkey(id);
|
||||
|
||||
EventHotKeyRef gMyHotKeyRef;
|
||||
EventHotKeyID gMyHotKeyID;
|
||||
EventTypeSpec eventType;
|
||||
eventType.eventClass = kEventClassKeyboard;
|
||||
eventType.eventKind = kEventHotKeyPressed;
|
||||
|
||||
InstallApplicationEventHandler(&macHotkeyHandler, 1, &eventType, this, NULL);
|
||||
|
||||
gMyHotKeyID.signature = uint32_t(id);
|
||||
gMyHotKeyID.id = uint32_t(id);
|
||||
|
||||
UKeyData macKey = QtKeyToMac(keySeq);
|
||||
|
||||
RegisterEventHotKey(macKey.key, macKey.mods, gMyHotKeyID,
|
||||
GetApplicationEventTarget(), 0, &gMyHotKeyRef);
|
||||
|
||||
HotkeyRefs[id] = gMyHotKeyRef;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UGlobalHotkeys::unregisterHotkey(size_t id)
|
||||
{
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_LINUX)
|
||||
Q_ASSERT(Registered.find(id) != Registered.end() && "Unregistered hotkey");
|
||||
#endif
|
||||
#if defined(Q_OS_WIN)
|
||||
UnregisterHotKey((HWND)winId(), id);
|
||||
#elif defined(Q_OS_LINUX)
|
||||
unregLinuxHotkey(id);
|
||||
#endif
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_LINUX)
|
||||
Registered.remove(id);
|
||||
#endif
|
||||
#if defined(Q_OS_MAC)
|
||||
if (HotkeyRefs.find(id) != HotkeyRefs.end()) {
|
||||
UnregisterEventHotKey(HotkeyRefs[id]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void UGlobalHotkeys::unregisterAllHotkeys()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
foreach (const size_t id, Registered) {
|
||||
this->unregisterHotkey(id);
|
||||
}
|
||||
#elif defined(Q_OS_LINUX)
|
||||
foreach (const size_t id, Registered.keys()) {
|
||||
this->unregisterHotkey(id);
|
||||
}
|
||||
#elif defined(Q_OS_MAC)
|
||||
for (auto ref : HotkeyRefs) {
|
||||
UnregisterEventHotKey(ref);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
UGlobalHotkeys::~UGlobalHotkeys()
|
||||
{
|
||||
#if defined(Q_OS_WIN)
|
||||
for (QSet<size_t>::iterator i = Registered.begin(); i != Registered.end(); ++i) {
|
||||
UnregisterHotKey((HWND)winId(), *i);
|
||||
}
|
||||
#elif defined(Q_OS_LINUX)
|
||||
xcb_key_symbols_free(X11KeySymbs);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
void UGlobalHotkeys::onHotkeyPressed(size_t id)
|
||||
{
|
||||
emit activated(id);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
bool UGlobalHotkeys::winEvent(MSG *message, long *result)
|
||||
{
|
||||
Q_UNUSED(result);
|
||||
if (message->message == WM_HOTKEY) {
|
||||
size_t id = message->wParam;
|
||||
Q_ASSERT(Registered.find(id) != Registered.end() && "Unregistered hotkey");
|
||||
emit activated(id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UGlobalHotkeys::nativeEvent(const QByteArray &eventType,
|
||||
void *message, long *result)
|
||||
{
|
||||
Q_UNUSED(eventType);
|
||||
return winEvent((MSG *)message, result);
|
||||
}
|
||||
|
||||
#elif defined(Q_OS_LINUX)
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
bool UGlobalHotkeys::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result)
|
||||
#else
|
||||
bool UGlobalHotkeys::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
|
||||
#endif
|
||||
{
|
||||
Q_UNUSED(eventType);
|
||||
Q_UNUSED(result);
|
||||
return linuxEvent(static_cast<xcb_generic_event_t *>(message));
|
||||
}
|
||||
|
||||
bool UGlobalHotkeys::linuxEvent(xcb_generic_event_t *message)
|
||||
{
|
||||
if ((message->response_type & ~0x80) == XCB_KEY_PRESS) {
|
||||
xcb_key_press_event_t *ev = (xcb_key_press_event_t *)message;
|
||||
auto ind = Registered.key({ev->detail, (ev->state & ~XCB_MOD_MASK_2)});
|
||||
|
||||
if (ind == 0) // this is not hotkeys
|
||||
return false;
|
||||
|
||||
emit activated(ind);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UGlobalHotkeys::regLinuxHotkey(const UKeySequence &keySeq, size_t id)
|
||||
{
|
||||
UHotkeyData data;
|
||||
UKeyData keyData = QtKeyToLinux(keySeq);
|
||||
|
||||
xcb_keycode_t *keyC = xcb_key_symbols_get_keycode(X11KeySymbs, keyData.key);
|
||||
|
||||
if (keyC == XCB_NO_SYMBOL) { // 0x0
|
||||
qWarning() << "Cannot find symbol";
|
||||
return;
|
||||
}
|
||||
|
||||
data.keyCode = *keyC;
|
||||
data.mods = keyData.mods;
|
||||
|
||||
xcb_grab_key(X11Connection, 1, X11Wid, data.mods, data.keyCode, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
|
||||
// NumLk
|
||||
xcb_grab_key(X11Connection, 1, X11Wid, data.mods | XCB_MOD_MASK_2, data.keyCode, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
|
||||
|
||||
Registered.insert(id, data);
|
||||
}
|
||||
|
||||
void UGlobalHotkeys::unregLinuxHotkey(size_t id)
|
||||
{
|
||||
UHotkeyData data = Registered.take(id);
|
||||
xcb_ungrab_key(X11Connection, data.keyCode, X11Wid, data.mods);
|
||||
xcb_ungrab_key(X11Connection, data.keyCode, X11Wid, data.mods | XCB_MOD_MASK_2);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,77 @@
|
|||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QAbstractNativeEventFilter>
|
||||
#include <QSet>
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
#include "xcb/xcb.h"
|
||||
#include "xcb/xcb_keysyms.h"
|
||||
#elif defined(Q_OS_MAC)
|
||||
#include <Carbon/Carbon.h>
|
||||
#endif
|
||||
|
||||
#include "ukeysequence.h"
|
||||
#include "uglobal.h"
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
struct UHotkeyData {
|
||||
xcb_keycode_t keyCode;
|
||||
int mods;
|
||||
bool operator ==(const UHotkeyData &data) const
|
||||
{
|
||||
return data.keyCode == this->keyCode && data.mods == this->mods;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
class UGLOBALHOTKEY_EXPORT UGlobalHotkeys : public QWidget
|
||||
#if defined(Q_OS_LINUX)
|
||||
, public QAbstractNativeEventFilter
|
||||
#endif
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit UGlobalHotkeys(QWidget *parent = 0);
|
||||
bool registerHotkey(const QString &keySeq, size_t id = 1);
|
||||
bool registerHotkey(const UKeySequence &keySeq, size_t id = 1);
|
||||
void unregisterHotkey(size_t id = 1);
|
||||
void unregisterAllHotkeys();
|
||||
~UGlobalHotkeys();
|
||||
|
||||
protected:
|
||||
#if defined(Q_OS_WIN)
|
||||
bool winEvent(MSG *message, long *result);
|
||||
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
|
||||
#elif defined(Q_OS_LINUX)
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override;
|
||||
#else
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override;
|
||||
#endif
|
||||
bool linuxEvent(xcb_generic_event_t *message);
|
||||
void regLinuxHotkey(const UKeySequence &keySeq, size_t id);
|
||||
void unregLinuxHotkey(size_t id);
|
||||
#endif
|
||||
|
||||
public:
|
||||
#if defined (Q_OS_MAC)
|
||||
void onHotkeyPressed(size_t id);
|
||||
#endif
|
||||
signals:
|
||||
void activated(size_t id);
|
||||
|
||||
private:
|
||||
#if defined(Q_OS_WIN)
|
||||
QSet<size_t> Registered;
|
||||
#elif defined(Q_OS_LINUX)
|
||||
QHash<size_t, UHotkeyData> Registered;
|
||||
xcb_connection_t *X11Connection;
|
||||
xcb_window_t X11Wid;
|
||||
xcb_key_symbols_t *X11KeySymbs;
|
||||
#elif defined(Q_OS_MAC)
|
||||
QHash<size_t, EventHotKeyRef> HotkeyRefs;
|
||||
#endif
|
||||
};
|
|
@ -0,0 +1,135 @@
|
|||
#include "ukeysequence.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
UKeySequence::UKeySequence(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
UKeySequence::UKeySequence(const QString &str, QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
fromString(str);
|
||||
}
|
||||
|
||||
void UKeySequence::fromString(const QString &str)
|
||||
{
|
||||
QStringList keys = str.split('+');
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
addKey(keys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
QString UKeySequence::toString()
|
||||
{
|
||||
QVector<Qt::Key> simpleKeys = getSimpleKeys();
|
||||
QVector<Qt::Key> modifiers = getModifiers();
|
||||
QStringList result;
|
||||
for (int i = 0; i < modifiers.size(); i++) {
|
||||
result.push_back(keyToStr(modifiers[i]));
|
||||
}
|
||||
for (int i = 0; i < simpleKeys.size(); i++) {
|
||||
result.push_back(keyToStr(simpleKeys[i]));
|
||||
}
|
||||
return result.join('+');
|
||||
}
|
||||
|
||||
QVector<Qt::Key> UKeySequence::getSimpleKeys() const
|
||||
{
|
||||
QVector<Qt::Key> result;
|
||||
for (int i = 0; i < mKeys.size(); i++) {
|
||||
if (!isModifier(mKeys[i])) {
|
||||
result.push_back(mKeys[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QVector<Qt::Key> UKeySequence::getModifiers() const
|
||||
{
|
||||
QVector<Qt::Key> result;
|
||||
for (int i = 0; i < mKeys.size(); i++) {
|
||||
if (isModifier(mKeys[i])) {
|
||||
result.push_back(mKeys[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void UKeySequence::addModifiers(Qt::KeyboardModifiers mod)
|
||||
{
|
||||
if (mod == Qt::NoModifier) {
|
||||
return;
|
||||
}
|
||||
if (mod & Qt::ShiftModifier) {
|
||||
addKey(Qt::Key_Shift);
|
||||
}
|
||||
if (mod & Qt::ControlModifier) {
|
||||
addKey(Qt::Key_Control);
|
||||
}
|
||||
if (mod & Qt::AltModifier) {
|
||||
addKey(Qt::Key_Alt);
|
||||
}
|
||||
if (mod & Qt::MetaModifier) {
|
||||
addKey(Qt::Key_Meta);
|
||||
}
|
||||
}
|
||||
|
||||
void UKeySequence::addKey(const QString &key)
|
||||
{
|
||||
if (key.contains("+") || key.contains(",")) {
|
||||
qWarning() << "Wrong key";
|
||||
return;
|
||||
}
|
||||
|
||||
QString mod = key.toLower();
|
||||
// qDebug() << "mod: " << mod;
|
||||
if (mod == "alt") {
|
||||
addKey(Qt::Key_Alt);
|
||||
return;
|
||||
}
|
||||
if (mod == "shift" || mod == "shft") {
|
||||
addKey(Qt::Key_Shift);
|
||||
return;
|
||||
}
|
||||
if (mod == "control" || mod == "ctrl") {
|
||||
addKey(Qt::Key_Control);
|
||||
return;
|
||||
}
|
||||
if (mod == "win" || mod == "meta") {
|
||||
addKey(Qt::Key_Meta);
|
||||
return;
|
||||
}
|
||||
QKeySequence seq(key);
|
||||
if (seq.count() != 1) {
|
||||
qWarning() << "Wrong key";
|
||||
return;
|
||||
}
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
|
||||
addKey((Qt::Key) seq[0]);
|
||||
#else
|
||||
addKey(seq[0].key());
|
||||
#endif
|
||||
}
|
||||
|
||||
void UKeySequence::addKey(Qt::Key key)
|
||||
{
|
||||
if (key <= 0) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < mKeys.size(); i++) {
|
||||
if (mKeys[i] == key) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// qDebug() << "Key added: " << key;
|
||||
mKeys.push_back(key);
|
||||
}
|
||||
|
||||
void UKeySequence::addKey(const QKeyEvent *event)
|
||||
{
|
||||
addKey((Qt::Key) event->key());
|
||||
addModifiers(event->modifiers());
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QStringList>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "uglobal.h"
|
||||
|
||||
class UGLOBALHOTKEY_EXPORT UKeySequence : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit UKeySequence(QObject *parent = 0);
|
||||
explicit UKeySequence(const QString &str, QObject *parent = 0);
|
||||
|
||||
void fromString(const QString &str);
|
||||
QString toString();
|
||||
void addKey(Qt::Key key);
|
||||
void addKey(const QString &key);
|
||||
void addModifiers(Qt::KeyboardModifiers mod);
|
||||
void addKey(const QKeyEvent *event);
|
||||
|
||||
inline size_t size() const
|
||||
{
|
||||
return mKeys.size();
|
||||
}
|
||||
inline Qt::Key operator [](size_t n) const
|
||||
{
|
||||
if ((int)n > mKeys.size()) {
|
||||
return Qt::Key_unknown;
|
||||
}
|
||||
|
||||
return mKeys[n];
|
||||
}
|
||||
|
||||
QVector<Qt::Key> getSimpleKeys() const;
|
||||
QVector<Qt::Key> getModifiers() const;
|
||||
|
||||
private:
|
||||
QVector<Qt::Key> mKeys;
|
||||
|
||||
inline static bool isModifier(Qt::Key key)
|
||||
{
|
||||
return (key == Qt::Key_Shift ||
|
||||
key == Qt::Key_Control ||
|
||||
key == Qt::Key_Alt ||
|
||||
key == Qt::Key_Meta);
|
||||
}
|
||||
|
||||
inline static QString keyToStr(int key)
|
||||
{
|
||||
if (key == Qt::Key_Shift) {
|
||||
return "Shift";
|
||||
}
|
||||
if (key == Qt::Key_Control) {
|
||||
return "Ctrl";
|
||||
}
|
||||
if (key == Qt::Key_Alt) {
|
||||
return "Alt";
|
||||
}
|
||||
if (key == Qt::Key_Meta) {
|
||||
return "Meta";
|
||||
}
|
||||
|
||||
QKeySequence seq(key);
|
||||
return seq.toString();
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "appconfig.h"
|
||||
#include "appsettings.h"
|
||||
#include "helpers/hotkeys/uglobalhotkeys.h"
|
||||
|
||||
HotkeyManager::HotkeyManager() {
|
||||
hotkeyManager = new UGlobalHotkeys();
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <QObject>
|
||||
|
||||
#include "helpers/screenshot.h"
|
||||
#include "tools/UGlobalHotkey/uglobalhotkeys.h"
|
||||
#include "helpers/hotkeys/uglobalhotkeys.h"
|
||||
|
||||
/**
|
||||
* @brief The HotkeyManager class registers and unregisters hotkeys against the operating system.
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
#include "helpers/netman.h"
|
||||
#include "helpers/screenshot.h"
|
||||
#include "helpers/constants.h"
|
||||
#include "helpers/hotkeys/uglobalhotkeys.h"
|
||||
#include "hotkeymanager.h"
|
||||
#include "models/codeblock.h"
|
||||
#include "tools/UGlobalHotkey/uglobalhotkeys.h"
|
||||
#include "porting/system_manifest.h"
|
||||
|
||||
// Tray icons are handled differently between different OS and desktop
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "forms/settings/settings.h"
|
||||
#include "helpers/screenshot.h"
|
||||
#include "hotkeymanager.h"
|
||||
#include "tools/UGlobalHotkey/uglobalhotkeys.h"
|
||||
#include "helpers/hotkeys/uglobalhotkeys.h"
|
||||
#include "forms/add_operation/createoperation.h"
|
||||
|
||||
#ifndef QT_NO_SYSTEMTRAYICON
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Subproject commit e53db08a970694c4bb92e8ec4f2a4173a4125d37
|
Loading…
Reference in New Issue