From 53bd8cdd148243d4482d3eca52f6398c61c75786 Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Tue, 18 Apr 2017 16:31:05 +0200 Subject: [PATCH 01/71] code cleanup --- QHotkey/qhotkey.cpp | 149 +++++++++++++++--------------- QHotkey/qhotkey.h | 12 +-- QHotkey/qhotkey_mac.cpp | 14 +-- QHotkey/qhotkey_p.h | 13 +-- QHotkey/qhotkey_x11.cpp | 196 ++++++++++++++++++++-------------------- qhotkey.pri | 3 - 6 files changed, 192 insertions(+), 195 deletions(-) diff --git a/QHotkey/qhotkey.cpp b/QHotkey/qhotkey.cpp index d5aedea..756c637 100644 --- a/QHotkey/qhotkey.cpp +++ b/QHotkey/qhotkey.cpp @@ -10,81 +10,81 @@ Q_LOGGING_CATEGORY(logQHotkey, "QHotkey") QHotkey::QHotkey(QObject *parent) : QObject(parent), - key(Qt::Key_unknown), - mods(Qt::NoModifier), - nativeShortcut(), - registered(false) + _keyCode(Qt::Key_unknown), + _modifiers(Qt::NoModifier), + _nativeShortcut(), + _registered(false) {} QHotkey::QHotkey(const QKeySequence &sequence, bool autoRegister, QObject *parent) : QHotkey(parent) { - this->setShortcut(sequence, autoRegister); + setShortcut(sequence, autoRegister); } -QHotkey::QHotkey(Qt::Key key, Qt::KeyboardModifiers modifiers, bool autoRegister, QObject *parent) : +QHotkey::QHotkey(Qt::Key keyCode, Qt::KeyboardModifiers modifiers, bool autoRegister, QObject *parent) : QHotkey(parent) { - this->setShortcut(key, modifiers, autoRegister); + setShortcut(keyCode, modifiers, autoRegister); } QHotkey::QHotkey(const QHotkey::NativeShortcut &shortcut, bool autoRegister, QObject *parent) : QHotkey(parent) { - this->setNativeShortcut(shortcut, autoRegister); + setNativeShortcut(shortcut, autoRegister); } QHotkey::~QHotkey() { - if(this->registered) + if(_registered) QHotkeyPrivate::instance()->removeShortcut(this); } QKeySequence QHotkey::shortcut() const { - if(this->key == Qt::Key_unknown) + if(_keyCode == Qt::Key_unknown) return QKeySequence(); else - return QKeySequence(this->key | this->mods); + return QKeySequence(_keyCode | _modifiers); } Qt::Key QHotkey::keyCode() const { - return this->key; + return _keyCode; } Qt::KeyboardModifiers QHotkey::modifiers() const { - return this->mods; + return _modifiers; } QHotkey::NativeShortcut QHotkey::currentNativeShortcut() const { - return this->nativeShortcut; + return _nativeShortcut; } bool QHotkey::isRegistered() const { - return this->registered; + return _registered; } bool QHotkey::setShortcut(const QKeySequence &shortcut, bool autoRegister) { if(shortcut.isEmpty()) { - return this->resetShortcut(); + return resetShortcut(); } else if(shortcut.count() > 1) { qCWarning(logQHotkey, "Keysequences with multiple shortcuts are not allowed! " "Only the first shortcut will be used!"); } - return this->setShortcut(Qt::Key(shortcut[0] & ~Qt::KeyboardModifierMask), - Qt::KeyboardModifiers(shortcut[0] & Qt::KeyboardModifierMask), - autoRegister); + return setShortcut(Qt::Key(shortcut[0] & ~Qt::KeyboardModifierMask), + Qt::KeyboardModifiers(shortcut[0] & Qt::KeyboardModifierMask), + autoRegister); } -bool QHotkey::setShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers, bool autoRegister) +bool QHotkey::setShortcut(Qt::Key keyCode, Qt::KeyboardModifiers modifiers, bool autoRegister) { - if(this->registered) { + if(_registered) { if(autoRegister) { if(!QHotkeyPrivate::instance()->removeShortcut(this)) return false; @@ -92,46 +92,46 @@ bool QHotkey::setShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers, bool aut return false; } - if(key == Qt::Key_unknown) { - this->key = Qt::Key_unknown; - this->mods = Qt::NoModifier; - this->nativeShortcut = NativeShortcut(); + if(keyCode == Qt::Key_unknown) { + _keyCode = Qt::Key_unknown; + _modifiers = Qt::NoModifier; + _nativeShortcut = NativeShortcut(); return true; } - this->key = key; - this->mods = modifiers; - this->nativeShortcut = QHotkeyPrivate::instance()->nativeShortcut(key, modifiers); - if(this->nativeShortcut.isValid()) { + _keyCode = keyCode; + _modifiers = modifiers; + _nativeShortcut = QHotkeyPrivate::instance()->nativeShortcut(keyCode, modifiers); + if(_nativeShortcut.isValid()) { if(autoRegister) return QHotkeyPrivate::instance()->addShortcut(this); else return true; } else { - qCWarning(logQHotkey) << "Unable to map shortcut to native keys. Key:" << key << "Modifiers:" << modifiers; - this->key = Qt::Key_unknown; - this->mods = Qt::NoModifier; - this->nativeShortcut = NativeShortcut(); + qCWarning(logQHotkey) << "Unable to map shortcut to native keys. Key:" << keyCode << "Modifiers:" << modifiers; + _keyCode = Qt::Key_unknown; + _modifiers = Qt::NoModifier; + _nativeShortcut = NativeShortcut(); return false; } } bool QHotkey::resetShortcut() { - if(this->registered && + if(_registered && !QHotkeyPrivate::instance()->removeShortcut(this)) { return false; } - this->key = Qt::Key_unknown; - this->mods = Qt::NoModifier; - this->nativeShortcut = NativeShortcut(); + _keyCode = Qt::Key_unknown; + _modifiers = Qt::NoModifier; + _nativeShortcut = NativeShortcut(); return true; } bool QHotkey::setNativeShortcut(QHotkey::NativeShortcut nativeShortcut, bool autoRegister) { - if(this->registered) { + if(_registered) { if(autoRegister) { if(!QHotkeyPrivate::instance()->removeShortcut(this)) return false; @@ -140,27 +140,27 @@ bool QHotkey::setNativeShortcut(QHotkey::NativeShortcut nativeShortcut, bool aut } if(nativeShortcut.isValid()) { - this->key = Qt::Key_unknown; - this->mods = Qt::NoModifier; - this->nativeShortcut = nativeShortcut; + _keyCode = Qt::Key_unknown; + _modifiers = Qt::NoModifier; + _nativeShortcut = nativeShortcut; if(autoRegister) return QHotkeyPrivate::instance()->addShortcut(this); else return true; } else { - this->key = Qt::Key_unknown; - this->mods = Qt::NoModifier; - this->nativeShortcut = NativeShortcut(); + _keyCode = Qt::Key_unknown; + _modifiers = Qt::NoModifier; + _nativeShortcut = NativeShortcut(); return true; } } bool QHotkey::setRegistered(bool registered) { - if(this->registered && !registered) + if(_registered && !registered) return QHotkeyPrivate::instance()->removeShortcut(this); - else if(!this->registered && registered) { - if(!this->nativeShortcut.isValid()) + else if(!_registered && registered) { + if(!_nativeShortcut.isValid()) return false; else return QHotkeyPrivate::instance()->addShortcut(this); @@ -181,15 +181,15 @@ QHotkeyPrivate::QHotkeyPrivate() : QHotkeyPrivate::~QHotkeyPrivate() { - if(!this->shortcuts.isEmpty()) - qCWarning(logQHotkey, "QHotkeyPrivate destroyed with registered shortcuts!"); + if(!shortcuts.isEmpty()) + qCWarning(logQHotkey) << "QHotkeyPrivate destroyed with registered shortcuts!"; if(qApp && qApp->eventDispatcher()) qApp->eventDispatcher()->removeNativeEventFilter(this); } QHotkey::NativeShortcut QHotkeyPrivate::nativeShortcut(Qt::Key keycode, Qt::KeyboardModifiers modifiers) { - Qt::ConnectionType conType = (QThread::currentThread() == this->thread() ? + Qt::ConnectionType conType = (QThread::currentThread() == thread() ? Qt::DirectConnection : Qt::BlockingQueuedConnection); QHotkey::NativeShortcut res; @@ -204,10 +204,10 @@ QHotkey::NativeShortcut QHotkeyPrivate::nativeShortcut(Qt::Key keycode, Qt::Keyb bool QHotkeyPrivate::addShortcut(QHotkey *hotkey) { - if(hotkey->registered) + if(hotkey->_registered) return false; - Qt::ConnectionType conType = (QThread::currentThread() == this->thread() ? + Qt::ConnectionType conType = (QThread::currentThread() == thread() ? Qt::DirectConnection : Qt::BlockingQueuedConnection); bool res = false; @@ -224,10 +224,10 @@ bool QHotkeyPrivate::addShortcut(QHotkey *hotkey) bool QHotkeyPrivate::removeShortcut(QHotkey *hotkey) { - if(!hotkey->registered) + if(!hotkey->_registered) return false; - Qt::ConnectionType conType = (QThread::currentThread() == this->thread() ? + Qt::ConnectionType conType = (QThread::currentThread() == thread() ? Qt::DirectConnection : Qt::BlockingQueuedConnection); bool res = false; @@ -245,38 +245,43 @@ bool QHotkeyPrivate::removeShortcut(QHotkey *hotkey) void QHotkeyPrivate::activateShortcut(QHotkey::NativeShortcut shortcut) { QMetaMethod signal = QMetaMethod::fromSignal(&QHotkey::activated); - for(QHotkey *hkey : this->shortcuts.values(shortcut)) + for(QHotkey *hkey : shortcuts.values(shortcut)) signal.invoke(hkey, Qt::QueuedConnection); } bool QHotkeyPrivate::addShortcutInvoked(QHotkey *hotkey) { - QHotkey::NativeShortcut shortcut = hotkey->nativeShortcut; + QHotkey::NativeShortcut shortcut = hotkey->_nativeShortcut; - if(!this->shortcuts.contains(shortcut)) { - if(!this->registerShortcut(shortcut)) + if(!shortcuts.contains(shortcut)) { + if(!registerShortcut(shortcut)) return false; } - this->shortcuts.insert(shortcut, hotkey); - hotkey->registered = true; + shortcuts.insert(shortcut, hotkey); + hotkey->_registered = true; return true; } bool QHotkeyPrivate::removeShortcutInvoked(QHotkey *hotkey) { - QHotkey::NativeShortcut shortcut = hotkey->nativeShortcut; + QHotkey::NativeShortcut shortcut = hotkey->_nativeShortcut; - if(this->shortcuts.remove(shortcut, hotkey) == 0) + if(shortcuts.remove(shortcut, hotkey) == 0) return false; - hotkey->registered = false; + hotkey->_registered = false; emit hotkey->registeredChanged(true); - if(this->shortcuts.count(shortcut) == 0) - return this->unregisterShortcut(shortcut); + if(shortcuts.count(shortcut) == 0) + return unregisterShortcut(shortcut); else return true; } +QHotkey::NativeShortcut QHotkeyPrivate::nativeShortcutInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers) +{ + return {this->nativeKeycode(keycode), this->nativeModifiers(modifiers)}; +} + QHotkey::NativeShortcut::NativeShortcut() : @@ -293,21 +298,21 @@ QHotkey::NativeShortcut::NativeShortcut(quint32 key, quint32 modifier) : bool QHotkey::NativeShortcut::isValid() const { - return this->valid; + return valid; } bool QHotkey::NativeShortcut::operator ==(const QHotkey::NativeShortcut &other) const { - return (this->key == other.key) && - (this->modifier == other.modifier) && - this->valid == other.valid; + return (key == other.key) && + (modifier == other.modifier) && + valid == other.valid; } bool QHotkey::NativeShortcut::operator !=(const QHotkey::NativeShortcut &other) const { - return (this->key != other.key) || - (this->modifier != other.modifier) || - this->valid != other.valid; + return (key != other.key) || + (modifier != other.modifier) || + valid != other.valid; } uint qHash(const QHotkey::NativeShortcut &key) diff --git a/QHotkey/qhotkey.h b/QHotkey/qhotkey.h index ee59830..cbf41d8 100644 --- a/QHotkey/qhotkey.h +++ b/QHotkey/qhotkey.h @@ -48,7 +48,7 @@ class QHotkey : public QObject //! Constructs a hotkey with a shortcut and optionally registers it explicit QHotkey(const QKeySequence &shortcut, bool autoRegister = false, QObject *parent = Q_NULLPTR); //! Constructs a hotkey with a key and modifiers and optionally registers it - explicit QHotkey(Qt::Key key, Qt::KeyboardModifiers modifiers, bool autoRegister = false, QObject *parent = Q_NULLPTR); + explicit QHotkey(Qt::Key keyCode, Qt::KeyboardModifiers modifiers, bool autoRegister = false, QObject *parent = Q_NULLPTR); //! Constructs a hotkey from a native shortcut and optionally registers it explicit QHotkey(const NativeShortcut &shortcut, bool autoRegister = false, QObject *parent = Q_NULLPTR); //! Destructor @@ -73,7 +73,7 @@ public slots: //! WRITE-Accessor for QHotkey::shortcut bool setShortcut(const QKeySequence &shortcut, bool autoRegister = false); //! WRITE-Accessor for QHotkey::shortcut - bool setShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers, bool autoRegister = false); + bool setShortcut(Qt::Key keyCode, Qt::KeyboardModifiers modifiers, bool autoRegister = false); //! RESET-Accessor for QHotkey::shortcut bool resetShortcut(); @@ -88,11 +88,11 @@ public slots: void registeredChanged(bool registered); private: - Qt::Key key; - Qt::KeyboardModifiers mods; + Qt::Key _keyCode; + Qt::KeyboardModifiers _modifiers; - NativeShortcut nativeShortcut; - bool registered; + NativeShortcut _nativeShortcut; + bool _registered; }; uint qHash(const QHotkey::NativeShortcut &key); diff --git a/QHotkey/qhotkey_mac.cpp b/QHotkey/qhotkey_mac.cpp index 7dee680..9e2f961 100644 --- a/QHotkey/qhotkey_mac.cpp +++ b/QHotkey/qhotkey_mac.cpp @@ -163,9 +163,9 @@ quint32 QHotkeyPrivateMac::nativeKeycode(Qt::Key keycode) else if (!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE) { if (keyToChar[k] == ch) return k; } - } // for k - } // for j - } // for i + } + } + } return 0; } @@ -196,12 +196,12 @@ bool QHotkeyPrivateMac::registerShortcut(QHotkey::NativeShortcut shortcut) } EventHotKeyID hkeyID; - hkeyID.signature = shortcut.key; - hkeyID.id = shortcut.modifier; + hkeyID.signature = shortcut.key; + hkeyID.id = shortcut.modifier; EventHotKeyRef eventRef = 0; - OSStatus status = RegisterEventHotKey(shortcut.key, - shortcut.modifier, + OSStatus status = RegisterEventHotKey(shortcut.key, + shortcut.modifier, hkeyID, GetApplicationEventTarget(), 0, diff --git a/QHotkey/qhotkey_p.h b/QHotkey/qhotkey_p.h index 2a98fdd..c21bc7a 100644 --- a/QHotkey/qhotkey_p.h +++ b/QHotkey/qhotkey_p.h @@ -31,13 +31,12 @@ class QHotkeyPrivate : public QObject, public QAbstractNativeEventFilter virtual bool registerShortcut(QHotkey::NativeShortcut shortcut) = 0;//platform implement virtual bool unregisterShortcut(QHotkey::NativeShortcut shortcut) = 0;//platform implement -private:/*functions*/ +private: + QMultiHash shortcuts; + Q_INVOKABLE bool addShortcutInvoked(QHotkey *hotkey); Q_INVOKABLE bool removeShortcutInvoked(QHotkey *hotkey); - Q_INVOKABLE inline QHotkey::NativeShortcut nativeShortcutInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers); - -private: - QMultiHash shortcuts; + Q_INVOKABLE QHotkey::NativeShortcut nativeShortcutInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers); }; #define NATIVE_INSTANCE(ClassName) \ @@ -48,8 +47,4 @@ class QHotkeyPrivate : public QObject, public QAbstractNativeEventFilter return hotkeyPrivate;\ } -inline QHotkey::NativeShortcut QHotkeyPrivate::nativeShortcutInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers) { - return {this->nativeKeycode(keycode), this->nativeModifiers(modifiers)}; -} - #endif // QHOTKEY_P_H diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index 4c2bee0..95062d2 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -9,35 +9,35 @@ class QHotkeyPrivateX11 : public QHotkeyPrivate { public: - // QAbstractNativeEventFilter interface - bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE; + // QAbstractNativeEventFilter interface + bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE; protected: - // QHotkeyPrivate interface - quint32 nativeKeycode(Qt::Key keycode) Q_DECL_OVERRIDE; - quint32 nativeModifiers(Qt::KeyboardModifiers modifiers) Q_DECL_OVERRIDE; - bool registerShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE; - bool unregisterShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE; + // QHotkeyPrivate interface + quint32 nativeKeycode(Qt::Key keycode) Q_DECL_OVERRIDE; + quint32 nativeModifiers(Qt::KeyboardModifiers modifiers) Q_DECL_OVERRIDE; + bool registerShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE; + bool unregisterShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE; private: - static const QVector specialModifiers; - static const quint32 validModsMask; + static const QVector specialModifiers; + static const quint32 validModsMask; - static QString formatX11Error(Display *display, int errorCode); + static QString formatX11Error(Display *display, int errorCode); - class HotkeyErrorHandler { - public: - HotkeyErrorHandler(); - ~HotkeyErrorHandler(); + class HotkeyErrorHandler { + public: + HotkeyErrorHandler(); + ~HotkeyErrorHandler(); static bool hasError; static QString errorString; - private: - XErrorHandler prevHandler; + private: + XErrorHandler prevHandler; - static int handleError(Display *display, XErrorEvent *error); - }; + static int handleError(Display *display, XErrorEvent *error); + }; }; NATIVE_INSTANCE(QHotkeyPrivateX11) @@ -46,104 +46,104 @@ const quint32 QHotkeyPrivateX11::validModsMask = ShiftMask | ControlMask | Mod1M bool QHotkeyPrivateX11::nativeEventFilter(const QByteArray &eventType, void *message, long *result) { - Q_UNUSED(eventType); - Q_UNUSED(result); + Q_UNUSED(eventType); + Q_UNUSED(result); - xcb_generic_event_t *genericEvent = static_cast(message); - if (genericEvent->response_type == XCB_KEY_PRESS) { - xcb_key_press_event_t *keyEvent = static_cast(message); - this->activateShortcut({keyEvent->detail, keyEvent->state & QHotkeyPrivateX11::validModsMask}); - } + xcb_generic_event_t *genericEvent = static_cast(message); + if (genericEvent->response_type == XCB_KEY_PRESS) { + xcb_key_press_event_t *keyEvent = static_cast(message); + this->activateShortcut({keyEvent->detail, keyEvent->state & QHotkeyPrivateX11::validModsMask}); + } - return false; + return false; } quint32 QHotkeyPrivateX11::nativeKeycode(Qt::Key keycode) { - KeySym keysym = XStringToKeysym(QKeySequence(keycode).toString(QKeySequence::NativeText).toLatin1().constData()); - if (keysym == NoSymbol) { - //not found -> just use the key - if(keycode <= 0xFFFF) - keysym = keycode; - else - return 0; - } - - Display *display = QX11Info::display(); - if(display) - return XKeysymToKeycode(QX11Info::display(), keysym); - else - return 0; + KeySym keysym = XStringToKeysym(QKeySequence(keycode).toString(QKeySequence::NativeText).toLatin1().constData()); + if (keysym == NoSymbol) { + //not found -> just use the key + if(keycode <= 0xFFFF) + keysym = keycode; + else + return 0; + } + + Display *display = QX11Info::display(); + if(display) + return XKeysymToKeycode(QX11Info::display(), keysym); + else + return 0; } quint32 QHotkeyPrivateX11::nativeModifiers(Qt::KeyboardModifiers modifiers) { - quint32 nMods = 0; - if (modifiers & Qt::ShiftModifier) - nMods |= ShiftMask; - if (modifiers & Qt::ControlModifier) - nMods |= ControlMask; - if (modifiers & Qt::AltModifier) - nMods |= Mod1Mask; - if (modifiers & Qt::MetaModifier) - nMods |= Mod4Mask; - return nMods; + quint32 nMods = 0; + if (modifiers & Qt::ShiftModifier) + nMods |= ShiftMask; + if (modifiers & Qt::ControlModifier) + nMods |= ControlMask; + if (modifiers & Qt::AltModifier) + nMods |= Mod1Mask; + if (modifiers & Qt::MetaModifier) + nMods |= Mod4Mask; + return nMods; } bool QHotkeyPrivateX11::registerShortcut(QHotkey::NativeShortcut shortcut) { - Display *display = QX11Info::display(); - if(!display) - return false; + Display *display = QX11Info::display(); + if(!display) + return false; - HotkeyErrorHandler errorHandler; - for(quint32 specialMod : QHotkeyPrivateX11::specialModifiers) { - XGrabKey(display, + HotkeyErrorHandler errorHandler; + for(quint32 specialMod : QHotkeyPrivateX11::specialModifiers) { + XGrabKey(display, shortcut.key, shortcut.modifier | specialMod, - DefaultRootWindow(display), - True, - GrabModeAsync, - GrabModeAsync); - } - - if(errorHandler.hasError) { - qCWarning(logQHotkey) << "[QHotkey] Failed to register hotkey. Error:" + DefaultRootWindow(display), + True, + GrabModeAsync, + GrabModeAsync); + } + + if(errorHandler.hasError) { + qCWarning(logQHotkey) << "Failed to register hotkey. Error:" << qPrintable(errorHandler.errorString); - this->unregisterShortcut(shortcut); - return false; - } else - return true; + this->unregisterShortcut(shortcut); + return false; + } else + return true; } bool QHotkeyPrivateX11::unregisterShortcut(QHotkey::NativeShortcut shortcut) { - Display *display = QX11Info::display(); - if(!display) - return false; + Display *display = QX11Info::display(); + if(!display) + return false; - HotkeyErrorHandler errorHandler; - for(quint32 specialMod : QHotkeyPrivateX11::specialModifiers) { - XUngrabKey(display, + HotkeyErrorHandler errorHandler; + for(quint32 specialMod : QHotkeyPrivateX11::specialModifiers) { + XUngrabKey(display, shortcut.key, shortcut.modifier | specialMod, - DefaultRootWindow(display)); - } + DefaultRootWindow(display)); + } if(errorHandler.hasError) { qCWarning(logQHotkey) << "Failed to unregister hotkey. Error:" << qPrintable(errorHandler.errorString); - this->unregisterShortcut(shortcut); - return false; - } else - return true; + this->unregisterShortcut(shortcut); + return false; + } else + return true; } QString QHotkeyPrivateX11::formatX11Error(Display *display, int errorCode) { - char errStr[256]; - XGetErrorText(display, errorCode, errStr, 256); - return QString::fromLatin1(errStr); + char errStr[256]; + XGetErrorText(display, errorCode, errStr, 256); + return QString::fromLatin1(errStr); } @@ -155,27 +155,27 @@ QString QHotkeyPrivateX11::HotkeyErrorHandler::errorString; QHotkeyPrivateX11::HotkeyErrorHandler::HotkeyErrorHandler() { - this->prevHandler = XSetErrorHandler(&HotkeyErrorHandler::handleError); + this->prevHandler = XSetErrorHandler(&HotkeyErrorHandler::handleError); } QHotkeyPrivateX11::HotkeyErrorHandler::~HotkeyErrorHandler() { - XSetErrorHandler(this->prevHandler); + XSetErrorHandler(this->prevHandler); } int QHotkeyPrivateX11::HotkeyErrorHandler::handleError(Display *display, XErrorEvent *error) { - switch (error->error_code) { - case BadAccess: - case BadValue: - case BadWindow: - if (error->request_code == 33 || //grab key - error->request_code == 34) {// ungrab key - HotkeyErrorHandler::hasError = true; - HotkeyErrorHandler::errorString = QHotkeyPrivateX11::formatX11Error(display, error->error_code); - return 1; - } - default: - return 0; - } + switch (error->error_code) { + case BadAccess: + case BadValue: + case BadWindow: + if (error->request_code == 33 || //grab key + error->request_code == 34) {// ungrab key + HotkeyErrorHandler::hasError = true; + HotkeyErrorHandler::errorString = QHotkeyPrivateX11::formatX11Error(display, error->error_code); + return 1; + } + default: + return 0; + } } diff --git a/qhotkey.pri b/qhotkey.pri index a76fcce..bb1e22d 100644 --- a/qhotkey.pri +++ b/qhotkey.pri @@ -18,6 +18,3 @@ mac { } INCLUDEPATH += $$PWD/QHotkey - -DISTFILES += \ - $$PWD/QHotkey/qhotkey.pri From 4446fe0a42a92acd94523148f6213d1383dfaf39 Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Tue, 18 Apr 2017 16:36:11 +0200 Subject: [PATCH 02/71] readme update --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dfa00f4..6a0e57a 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,17 @@ The QHotkey is a class that can be used to create hotkeys/global shortcuts, aka - Thread-Safe - Can be used on all threads (See section Thread safety) - Allows usage of native keycodes and modifiers, if needed +## Installation +The package is providet as qpm package, [`de.skycoder42.qhotkey`](https://www.qpm.io/packages/de.skycoder42.qhotkey/index.html). To install: + +1. Install qpm (See [GitHub - Installing](https://github.com/Cutehacks/qpm/blob/master/README.md#installing)) +2. In your projects root directory, run `qpm install de.skycoder42.qhotkey` +3. Include qpm to your project by adding `include(vendor/vendor.pri)` to your `.pro` file + +Check their [GitHub - Usage for App Developers](https://github.com/Cutehacks/qpm/blob/master/README.md#usage-for-app-developers) to learn more about qpm. + ## Usage -Just copy the repository into you application (preferebly by adding it as a git submodule) and add the line `include(./QHotkey/qhotkey.pri)` to your .pro-file. This way all files and required libraries will automatically be added. Use `#include ` to access the class. +The general usage is to create QHotkey instances for specific hotkeys, register them and then simply connect to the signal emitted once the hotkey is pressed. ### Example The following example shows a simple application that will run without a window in the background until you press the key-combination Ctrl+Alt+Q (++Q on Mac). This will quit the application. The debug output will tell if the hotkey was successfully registered and that it was pressed. @@ -69,7 +78,7 @@ The documentation was created using [doxygen](http://www.doxygen.org). It includ ## Technical ### Requirements - I built it with Qt 5.7, but may work with earlier versions, too - - At least the QtGui-Module (a QGuiApplication). Hotkeys on console based applications are not supported. (By the operating systems) + - At least the QtGui-Module (a QGuiApplication). Hotkeys on console based applications are not supported (By the operating systems). You can however create a gui application without any visible window. - C++11 ### Known Limitations From 040cf5ec0cf2ed605c39d7bc4d0164ab7c54d6bf Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Tue, 18 Apr 2017 16:38:02 +0200 Subject: [PATCH 03/71] added qpm --- qpm.json | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 qpm.json diff --git a/qpm.json b/qpm.json new file mode 100644 index 0000000..efd3447 --- /dev/null +++ b/qpm.json @@ -0,0 +1,22 @@ +{ + "name": "de.skycoder42.qhotkey", + "description": "A global shortcut/hotkey for Desktop Qt-Applications", + "author": { + "name": "Skycoder", + "email": "skycoder42.de@gmx.de" + }, + "repository": { + "type": "GITHUB", + "url": "https://github.com/Skycoder42/QHotkey.git" + }, + "version": { + "label": "1.1.1", + "revision": "", + "fingerprint": "" + }, + "dependencies": [ + ], + "license": "BSD_3_CLAUSE", + "pri_filename": "qhotkey.pri", + "webpage": "https://github.com/Skycoder42/QHotkey" +} \ No newline at end of file From 10d1e44b21adbbea571d35d1beb24648427e2c70 Mon Sep 17 00:00:00 2001 From: ArsenArsen Date: Mon, 1 May 2017 11:48:53 +0200 Subject: [PATCH 04/71] Fix a compile error on MXE --- qhotkey.pri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qhotkey.pri b/qhotkey.pri index bb1e22d..70e4cdf 100644 --- a/qhotkey.pri +++ b/qhotkey.pri @@ -10,7 +10,7 @@ mac { LIBS += -framework Carbon } else:win32 { SOURCES += $$PWD/QHotkey/qhotkey_win.cpp - LIBS += -lUser32 + LIBS += -luser32 } else:unix { SOURCES += $$PWD/QHotkey/qhotkey_x11.cpp QT += x11extras From 15e34a7dbf70fddd1cb6e11ba24e25b4a8f952a4 Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Mon, 1 May 2017 12:15:01 +0200 Subject: [PATCH 05/71] fixed initial tab --- HotkeyTest/hottestwidget.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HotkeyTest/hottestwidget.ui b/HotkeyTest/hottestwidget.ui index 30dbcdb..c1db840 100644 --- a/HotkeyTest/hottestwidget.ui +++ b/HotkeyTest/hottestwidget.ui @@ -17,7 +17,7 @@ - 3 + 0 From 7c4ef6a03a219c99932975bab270ea812589e1ad Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Mon, 1 May 2017 12:17:18 +0200 Subject: [PATCH 06/71] qpm update --- qpm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qpm.json b/qpm.json index efd3447..186f695 100644 --- a/qpm.json +++ b/qpm.json @@ -10,7 +10,7 @@ "url": "https://github.com/Skycoder42/QHotkey.git" }, "version": { - "label": "1.1.1", + "label": "1.1.2", "revision": "", "fingerprint": "" }, From 3fa176a3809080dd565b5276d01fcdd64d1e4c4a Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Sun, 14 May 2017 13:32:06 +0200 Subject: [PATCH 07/71] Added XSync call for hotkey without window For #3 --- HotkeyTest/main.cpp | 9 +++++++++ QHotkey/qhotkey_x11.cpp | 2 ++ 2 files changed, 11 insertions(+) diff --git a/HotkeyTest/main.cpp b/HotkeyTest/main.cpp index 3640393..f95d6fd 100644 --- a/HotkeyTest/main.cpp +++ b/HotkeyTest/main.cpp @@ -1,11 +1,20 @@ #include "hottestwidget.h" #include +//#define START_BACKGROUND + int main(int argc, char *argv[]) { QApplication a(argc, argv); HotTestWidget w; + +#ifdef START_BACKGROUND + auto startKey = new QHotkey(QKeySequence(Qt::MetaModifier | Qt::ControlModifier | Qt::Key_S), true, &w); + QObject::connect(startKey, &QHotkey::activated, + &w, &QWidget::show); +#else w.show(); +#endif return a.exec(); } diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index 95062d2..f10e350 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -106,6 +106,7 @@ bool QHotkeyPrivateX11::registerShortcut(QHotkey::NativeShortcut shortcut) GrabModeAsync, GrabModeAsync); } + XSync(display, QueuedAlready); if(errorHandler.hasError) { qCWarning(logQHotkey) << "Failed to register hotkey. Error:" @@ -129,6 +130,7 @@ bool QHotkeyPrivateX11::unregisterShortcut(QHotkey::NativeShortcut shortcut) shortcut.modifier | specialMod, DefaultRootWindow(display)); } + XSync(display, QueuedAlready); if(errorHandler.hasError) { qCWarning(logQHotkey) << "Failed to unregister hotkey. Error:" From 6baf644b40972da0a2a3db7cba0962202e75c5b6 Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Sun, 14 May 2017 13:34:55 +0200 Subject: [PATCH 08/71] fixed misread parameter #3 --- QHotkey/qhotkey_x11.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index f10e350..185aca3 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -106,7 +106,7 @@ bool QHotkeyPrivateX11::registerShortcut(QHotkey::NativeShortcut shortcut) GrabModeAsync, GrabModeAsync); } - XSync(display, QueuedAlready); + XSync(display, true); if(errorHandler.hasError) { qCWarning(logQHotkey) << "Failed to register hotkey. Error:" @@ -130,7 +130,7 @@ bool QHotkeyPrivateX11::unregisterShortcut(QHotkey::NativeShortcut shortcut) shortcut.modifier | specialMod, DefaultRootWindow(display)); } - XSync(display, QueuedAlready); + XSync(display, true); if(errorHandler.hasError) { qCWarning(logQHotkey) << "Failed to unregister hotkey. Error:" From 9eace8fbbd8dede95db623eea5e25403fd59b490 Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Sun, 14 May 2017 13:39:54 +0200 Subject: [PATCH 09/71] do not discard events on XSync --- QHotkey/qhotkey_x11.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index 185aca3..10ddf4e 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -106,7 +106,7 @@ bool QHotkeyPrivateX11::registerShortcut(QHotkey::NativeShortcut shortcut) GrabModeAsync, GrabModeAsync); } - XSync(display, true); + XSync(display, False); if(errorHandler.hasError) { qCWarning(logQHotkey) << "Failed to register hotkey. Error:" @@ -130,7 +130,7 @@ bool QHotkeyPrivateX11::unregisterShortcut(QHotkey::NativeShortcut shortcut) shortcut.modifier | specialMod, DefaultRootWindow(display)); } - XSync(display, true); + XSync(display, False); if(errorHandler.hasError) { qCWarning(logQHotkey) << "Failed to unregister hotkey. Error:" From cdb4d37453d59763998fcb5a73ead8bf83a6a3bd Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Sun, 14 May 2017 22:27:26 +0200 Subject: [PATCH 10/71] replaced XSync by XFlush --- QHotkey/qhotkey_x11.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index 10ddf4e..9c1c209 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -106,7 +106,7 @@ bool QHotkeyPrivateX11::registerShortcut(QHotkey::NativeShortcut shortcut) GrabModeAsync, GrabModeAsync); } - XSync(display, False); + XFlush(display); if(errorHandler.hasError) { qCWarning(logQHotkey) << "Failed to register hotkey. Error:" @@ -130,7 +130,7 @@ bool QHotkeyPrivateX11::unregisterShortcut(QHotkey::NativeShortcut shortcut) shortcut.modifier | specialMod, DefaultRootWindow(display)); } - XSync(display, False); + XFlush(display); if(errorHandler.hasError) { qCWarning(logQHotkey) << "Failed to unregister hotkey. Error:" From a0678c4cfc3d3261f1bf5fdb2c45f9f5f2dca975 Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Sun, 14 May 2017 22:28:10 +0200 Subject: [PATCH 11/71] qpm update --- qpm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qpm.json b/qpm.json index 186f695..6a58c11 100644 --- a/qpm.json +++ b/qpm.json @@ -10,7 +10,7 @@ "url": "https://github.com/Skycoder42/QHotkey.git" }, "version": { - "label": "1.1.2", + "label": "1.1.3", "revision": "", "fingerprint": "" }, From 2578b69dc51e3786402777e650181c5735015e1a Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Fri, 2 Jun 2017 21:24:14 +0200 Subject: [PATCH 12/71] remove recursive call detected by #4 --- QHotkey/qhotkey_x11.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index 9c1c209..95ccfe3 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -135,7 +135,6 @@ bool QHotkeyPrivateX11::unregisterShortcut(QHotkey::NativeShortcut shortcut) if(errorHandler.hasError) { qCWarning(logQHotkey) << "Failed to unregister hotkey. Error:" << qPrintable(errorHandler.errorString); - this->unregisterShortcut(shortcut); return false; } else return true; From f288e85ef106b5392bbe2663ee61d1d55e1b8c9e Mon Sep 17 00:00:00 2001 From: Felix Barz Date: Thu, 15 Jun 2017 11:41:09 +0200 Subject: [PATCH 13/71] Create README.md --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6a0e57a..ba49d66 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,16 @@ The QHotkey is a class that can be used to create hotkeys/global shortcuts, aka ## Installation The package is providet as qpm package, [`de.skycoder42.qhotkey`](https://www.qpm.io/packages/de.skycoder42.qhotkey/index.html). To install: -1. Install qpm (See [GitHub - Installing](https://github.com/Cutehacks/qpm/blob/master/README.md#installing)) +1. Install qpm (See [GitHub - Installing](https://github.com/Cutehacks/qpm/blob/master/README.md#installing), for **windows** see below) 2. In your projects root directory, run `qpm install de.skycoder42.qhotkey` 3. Include qpm to your project by adding `include(vendor/vendor.pri)` to your `.pro` file Check their [GitHub - Usage for App Developers](https://github.com/Cutehacks/qpm/blob/master/README.md#usage-for-app-developers) to learn more about qpm. +**Important for Windows users:** QPM Version *0.10.0* (the one you can download on the website) is currently broken on windows! It's already fixed in master, but not released yet. Until a newer versions gets released, you can download the latest dev build from here: +- https://storage.googleapis.com/www.qpm.io/download/latest/windows_amd64/qpm.exe +- https://storage.googleapis.com/www.qpm.io/download/latest/windows_386/qpm.exe + ## Usage The general usage is to create QHotkey instances for specific hotkeys, register them and then simply connect to the signal emitted once the hotkey is pressed. From 1833a053f6cdcabc84fe21960851399ae1e9abec Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Sun, 25 Jun 2017 14:40:03 +0200 Subject: [PATCH 14/71] fixed xerrorhandler fixes #4 --- QHotkey/qhotkey_x11.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index 95ccfe3..14e9342 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -106,7 +106,7 @@ bool QHotkeyPrivateX11::registerShortcut(QHotkey::NativeShortcut shortcut) GrabModeAsync, GrabModeAsync); } - XFlush(display); + XSync(display, False); if(errorHandler.hasError) { qCWarning(logQHotkey) << "Failed to register hotkey. Error:" @@ -130,7 +130,7 @@ bool QHotkeyPrivateX11::unregisterShortcut(QHotkey::NativeShortcut shortcut) shortcut.modifier | specialMod, DefaultRootWindow(display)); } - XFlush(display); + XSync(display, False); if(errorHandler.hasError) { qCWarning(logQHotkey) << "Failed to unregister hotkey. Error:" @@ -156,27 +156,32 @@ QString QHotkeyPrivateX11::HotkeyErrorHandler::errorString; QHotkeyPrivateX11::HotkeyErrorHandler::HotkeyErrorHandler() { - this->prevHandler = XSetErrorHandler(&HotkeyErrorHandler::handleError); + prevHandler = XSetErrorHandler(&HotkeyErrorHandler::handleError); } QHotkeyPrivateX11::HotkeyErrorHandler::~HotkeyErrorHandler() { - XSetErrorHandler(this->prevHandler); + XSetErrorHandler(prevHandler); + hasError = false; + errorString.clear(); } int QHotkeyPrivateX11::HotkeyErrorHandler::handleError(Display *display, XErrorEvent *error) { +QT_WARNING_PUSH +QT_WARNING_DISABLE_GCC("-Wimplicit-fallthrough") switch (error->error_code) { case BadAccess: case BadValue: case BadWindow: if (error->request_code == 33 || //grab key error->request_code == 34) {// ungrab key - HotkeyErrorHandler::hasError = true; - HotkeyErrorHandler::errorString = QHotkeyPrivateX11::formatX11Error(display, error->error_code); + hasError = true; + errorString = QHotkeyPrivateX11::formatX11Error(display, error->error_code); return 1; } default: return 0; } +QT_WARNING_POP } From 91f3542b5d11a6df8e5735ef03f336c399ceab93 Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Sun, 25 Jun 2017 14:41:23 +0200 Subject: [PATCH 15/71] qm update --- qpm.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qpm.json b/qpm.json index 6a58c11..0af4fa8 100644 --- a/qpm.json +++ b/qpm.json @@ -10,7 +10,7 @@ "url": "https://github.com/Skycoder42/QHotkey.git" }, "version": { - "label": "1.1.3", + "label": "1.1.4", "revision": "", "fingerprint": "" }, @@ -19,4 +19,4 @@ "license": "BSD_3_CLAUSE", "pri_filename": "qhotkey.pri", "webpage": "https://github.com/Skycoder42/QHotkey" -} \ No newline at end of file +} From 83910c8ecab7b5569591fbbc968747f7638e83a5 Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Sat, 30 Sep 2017 19:21:26 +0200 Subject: [PATCH 16/71] fixed invalid key detection --- QHotkey/qhotkey.cpp | 8 +++++++- QHotkey/qhotkey_mac.cpp | 23 ++++++++++++++++------- QHotkey/qhotkey_p.h | 4 ++-- QHotkey/qhotkey_win.cpp | 11 +++++++---- QHotkey/qhotkey_x11.cpp | 18 +++++++++++------- 5 files changed, 43 insertions(+), 21 deletions(-) diff --git a/QHotkey/qhotkey.cpp b/QHotkey/qhotkey.cpp index 756c637..e8e3adb 100644 --- a/QHotkey/qhotkey.cpp +++ b/QHotkey/qhotkey.cpp @@ -279,7 +279,13 @@ bool QHotkeyPrivate::removeShortcutInvoked(QHotkey *hotkey) QHotkey::NativeShortcut QHotkeyPrivate::nativeShortcutInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers) { - return {this->nativeKeycode(keycode), this->nativeModifiers(modifiers)}; + bool ok1, ok2 = false; + auto k = nativeKeycode(keycode, ok1); + auto m = nativeModifiers(modifiers, ok2); + if(ok1 && ok2) + return {k, m}; + else + return {}; } diff --git a/QHotkey/qhotkey_mac.cpp b/QHotkey/qhotkey_mac.cpp index 9e2f961..ac123bf 100644 --- a/QHotkey/qhotkey_mac.cpp +++ b/QHotkey/qhotkey_mac.cpp @@ -13,8 +13,8 @@ class QHotkeyPrivateMac : public QHotkeyPrivate protected: // QHotkeyPrivate interface - quint32 nativeKeycode(Qt::Key keycode) Q_DECL_OVERRIDE; - quint32 nativeModifiers(Qt::KeyboardModifiers modifiers) Q_DECL_OVERRIDE; + quint32 nativeKeycode(Qt::Key keycode, bool &ok) Q_DECL_OVERRIDE; + quint32 nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) Q_DECL_OVERRIDE; bool registerShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE; bool unregisterShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE; @@ -35,9 +35,10 @@ bool QHotkeyPrivateMac::nativeEventFilter(const QByteArray &eventType, void *mes return false; } -quint32 QHotkeyPrivateMac::nativeKeycode(Qt::Key keycode) +quint32 QHotkeyPrivateMac::nativeKeycode(Qt::Key keycode, bool &ok) { // Constants found in NSEvent.h from AppKit.framework + ok = true; switch (keycode) { case Qt::Key_Return: return kVK_Return; @@ -120,7 +121,8 @@ quint32 QHotkeyPrivateMac::nativeKeycode(Qt::Key keycode) case Qt::Key_Up: return kVK_UpArrow; default: - ; + ok = false; + break; } UTF16Char ch = keycode; @@ -157,11 +159,17 @@ quint32 QHotkeyPrivateMac::nativeKeycode(Qt::Key keycode) long idx = keyToChar[k] & kUCKeyOutputGetIndexMask; if (stateRec && idx < stateRec->keyStateRecordCount) { UCKeyStateRecord* rec = reinterpret_cast(data + stateRec->keyStateRecordOffsets[idx]); - if (rec->stateZeroCharData == ch) return k; + if (rec->stateZeroCharData == ch) { + ok = true; + return k; + } } } else if (!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE) { - if (keyToChar[k] == ch) return k; + if (keyToChar[k] == ch) { + ok = true; + return k; + } } } } @@ -169,7 +177,7 @@ quint32 QHotkeyPrivateMac::nativeKeycode(Qt::Key keycode) return 0; } -quint32 QHotkeyPrivateMac::nativeModifiers(Qt::KeyboardModifiers modifiers) +quint32 QHotkeyPrivateMac::nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) { quint32 nMods = 0; if (modifiers & Qt::ShiftModifier) @@ -182,6 +190,7 @@ quint32 QHotkeyPrivateMac::nativeModifiers(Qt::KeyboardModifiers modifiers) nMods |= controlKey; if (modifiers & Qt::KeypadModifier) nMods |= kEventKeyModifierNumLockMask; + ok = true; return nMods; } diff --git a/QHotkey/qhotkey_p.h b/QHotkey/qhotkey_p.h index c21bc7a..448b95e 100644 --- a/QHotkey/qhotkey_p.h +++ b/QHotkey/qhotkey_p.h @@ -25,8 +25,8 @@ class QHotkeyPrivate : public QObject, public QAbstractNativeEventFilter protected: void activateShortcut(QHotkey::NativeShortcut shortcut); - virtual quint32 nativeKeycode(Qt::Key keycode) = 0;//platform implement - virtual quint32 nativeModifiers(Qt::KeyboardModifiers modifiers) = 0;//platform implement + virtual quint32 nativeKeycode(Qt::Key keycode, bool &ok) = 0;//platform implement + virtual quint32 nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) = 0;//platform implement virtual bool registerShortcut(QHotkey::NativeShortcut shortcut) = 0;//platform implement virtual bool unregisterShortcut(QHotkey::NativeShortcut shortcut) = 0;//platform implement diff --git a/QHotkey/qhotkey_win.cpp b/QHotkey/qhotkey_win.cpp index 698428c..c7d25b4 100644 --- a/QHotkey/qhotkey_win.cpp +++ b/QHotkey/qhotkey_win.cpp @@ -13,8 +13,8 @@ class QHotkeyPrivateWin : public QHotkeyPrivate protected: // QHotkeyPrivate interface - quint32 nativeKeycode(Qt::Key keycode) Q_DECL_OVERRIDE; - quint32 nativeModifiers(Qt::KeyboardModifiers modifiers) Q_DECL_OVERRIDE; + quint32 nativeKeycode(Qt::Key keycode, bool &ok) Q_DECL_OVERRIDE; + quint32 nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) Q_DECL_OVERRIDE; bool registerShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE; bool unregisterShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE; @@ -35,8 +35,9 @@ bool QHotkeyPrivateWin::nativeEventFilter(const QByteArray &eventType, void *mes return false; } -quint32 QHotkeyPrivateWin::nativeKeycode(Qt::Key keycode) +quint32 QHotkeyPrivateWin::nativeKeycode(Qt::Key keycode, bool &ok) { + ok = true; if(keycode <= 0xFFFF) {//Try to obtain the key from it's "character" const SHORT vKey = VkKeyScanW(keycode); if(vKey > -1) @@ -201,11 +202,12 @@ quint32 QHotkeyPrivateWin::nativeKeycode(Qt::Key keycode) return VK_OEM_FJ_TOUROKU; default: + ok = false; return 0; } } -quint32 QHotkeyPrivateWin::nativeModifiers(Qt::KeyboardModifiers modifiers) +quint32 QHotkeyPrivateWin::nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) { quint32 nMods = 0; if (modifiers & Qt::ShiftModifier) @@ -216,6 +218,7 @@ quint32 QHotkeyPrivateWin::nativeModifiers(Qt::KeyboardModifiers modifiers) nMods |= MOD_ALT; if (modifiers & Qt::MetaModifier) nMods |= MOD_WIN; + ok = true; return nMods; } diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index 14e9342..ca323c2 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -14,8 +14,8 @@ class QHotkeyPrivateX11 : public QHotkeyPrivate protected: // QHotkeyPrivate interface - quint32 nativeKeycode(Qt::Key keycode) Q_DECL_OVERRIDE; - quint32 nativeModifiers(Qt::KeyboardModifiers modifiers) Q_DECL_OVERRIDE; + quint32 nativeKeycode(Qt::Key keycode, bool &ok) Q_DECL_OVERRIDE; + quint32 nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) Q_DECL_OVERRIDE; bool registerShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE; bool unregisterShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE; @@ -58,7 +58,7 @@ bool QHotkeyPrivateX11::nativeEventFilter(const QByteArray &eventType, void *mes return false; } -quint32 QHotkeyPrivateX11::nativeKeycode(Qt::Key keycode) +quint32 QHotkeyPrivateX11::nativeKeycode(Qt::Key keycode, bool &ok) { KeySym keysym = XStringToKeysym(QKeySequence(keycode).toString(QKeySequence::NativeText).toLatin1().constData()); if (keysym == NoSymbol) { @@ -70,13 +70,16 @@ quint32 QHotkeyPrivateX11::nativeKeycode(Qt::Key keycode) } Display *display = QX11Info::display(); - if(display) - return XKeysymToKeycode(QX11Info::display(), keysym); - else + if(display) { + auto res = XKeysymToKeycode(QX11Info::display(), keysym); + if(res != 0) + ok = true; + return res; + } else return 0; } -quint32 QHotkeyPrivateX11::nativeModifiers(Qt::KeyboardModifiers modifiers) +quint32 QHotkeyPrivateX11::nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) { quint32 nMods = 0; if (modifiers & Qt::ShiftModifier) @@ -87,6 +90,7 @@ quint32 QHotkeyPrivateX11::nativeModifiers(Qt::KeyboardModifiers modifiers) nMods |= Mod1Mask; if (modifiers & Qt::MetaModifier) nMods |= Mod4Mask; + ok = true; return nMods; } From 7d214ac41e38f80dee719180f1a0e362bb50c54c Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Sat, 30 Sep 2017 19:22:06 +0200 Subject: [PATCH 17/71] qpmx --- qpm.json | 40 ++++++++++++++++++++-------------------- qpmx.json | 28 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 20 deletions(-) create mode 100644 qpmx.json diff --git a/qpm.json b/qpm.json index 0af4fa8..4fd1161 100644 --- a/qpm.json +++ b/qpm.json @@ -1,22 +1,22 @@ { - "name": "de.skycoder42.qhotkey", - "description": "A global shortcut/hotkey for Desktop Qt-Applications", - "author": { - "name": "Skycoder", - "email": "skycoder42.de@gmx.de" - }, - "repository": { - "type": "GITHUB", - "url": "https://github.com/Skycoder42/QHotkey.git" - }, - "version": { - "label": "1.1.4", - "revision": "", - "fingerprint": "" - }, - "dependencies": [ - ], - "license": "BSD_3_CLAUSE", - "pri_filename": "qhotkey.pri", - "webpage": "https://github.com/Skycoder42/QHotkey" + "author": { + "email": "skycoder42.de@gmx.de", + "name": "Skycoder" + }, + "dependencies": [ + ], + "description": "A global shortcut/hotkey for Desktop Qt-Applications", + "license": "BSD_3_CLAUSE", + "name": "de.skycoder42.qhotkey", + "pri_filename": "qhotkey.pri", + "repository": { + "type": "GITHUB", + "url": "https://github.com/Skycoder42/QHotkey.git" + }, + "version": { + "fingerprint": "", + "label": "1.2.0", + "revision": "" + }, + "webpage": "https://github.com/Skycoder42/QHotkey" } diff --git a/qpmx.json b/qpmx.json new file mode 100644 index 0000000..9c03280 --- /dev/null +++ b/qpmx.json @@ -0,0 +1,28 @@ +{ + "dependencies": [ + ], + "license": { + "file": "LICENSE", + "name": "BSD_3_CLAUSE" + }, + "prcFile": "", + "priFile": "qhotkey.pri", + "priIncludes": [ + ], + "publishers": { + "qpm": { + "author": { + "email": "skycoder42.de@gmx.de", + "name": "Skycoder" + }, + "description": "A global shortcut/hotkey for Desktop Qt-Applications", + "name": "de.skycoder42.qhotkey", + "repository": { + "type": "GITHUB", + "url": "https://github.com/Skycoder42/QHotkey.git" + }, + "webpage": "https://github.com/Skycoder42/QHotkey" + } + }, + "source": false +} From c9cfd8fb6f0bf1f848f226306558e6ea1bfb1a89 Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Sat, 30 Sep 2017 22:22:21 +0200 Subject: [PATCH 18/71] fixed library parts --- qhotkey.prc | 6 ++++++ qhotkey.pri | 20 ++++++++------------ qpm.json | 2 +- qpmx.json | 2 +- 4 files changed, 16 insertions(+), 14 deletions(-) create mode 100644 qhotkey.prc diff --git a/qhotkey.prc b/qhotkey.prc new file mode 100644 index 0000000..30e2b04 --- /dev/null +++ b/qhotkey.prc @@ -0,0 +1,6 @@ +mac: LIBS += -framework Carbon +else:win32: LIBS += -luser32 +else:unix { + QT += x11extras + LIBS += -lX11 +} diff --git a/qhotkey.pri b/qhotkey.pri index 70e4cdf..d1a7d91 100644 --- a/qhotkey.pri +++ b/qhotkey.pri @@ -1,20 +1,16 @@ CONFIG += C++11 -HEADERS += $$PWD/QHotkey/qhotkey.h \ +PUBLIC_HEADERS += $$PWD/QHotkey/qhotkey.h + +HEADERS += $$PUBLIC_HEADERS \ $$PWD/QHotkey/qhotkey_p.h SOURCES += $$PWD/QHotkey/qhotkey.cpp -mac { - SOURCES += $$PWD/QHotkey/qhotkey_mac.cpp - LIBS += -framework Carbon -} else:win32 { - SOURCES += $$PWD/QHotkey/qhotkey_win.cpp - LIBS += -luser32 -} else:unix { - SOURCES += $$PWD/QHotkey/qhotkey_x11.cpp - QT += x11extras - LIBS += -lX11 -} +mac: SOURCES += $$PWD/QHotkey/qhotkey_mac.cpp +else:win32: SOURCES += $$PWD/QHotkey/qhotkey_win.cpp +else:unix: SOURCES += $$PWD/QHotkey/qhotkey_x11.cpp INCLUDEPATH += $$PWD/QHotkey + +include($$PWD/qhotkey.prc) diff --git a/qpm.json b/qpm.json index 4fd1161..093bb63 100644 --- a/qpm.json +++ b/qpm.json @@ -15,7 +15,7 @@ }, "version": { "fingerprint": "", - "label": "1.2.0", + "label": "1.2.1", "revision": "" }, "webpage": "https://github.com/Skycoder42/QHotkey" diff --git a/qpmx.json b/qpmx.json index 9c03280..bea438f 100644 --- a/qpmx.json +++ b/qpmx.json @@ -5,7 +5,7 @@ "file": "LICENSE", "name": "BSD_3_CLAUSE" }, - "prcFile": "", + "prcFile": "qhotkey.prc", "priFile": "qhotkey.pri", "priIncludes": [ ], From b910580fce27881fa539611448005addad713a1b Mon Sep 17 00:00:00 2001 From: "Martin T. H. Sandsmark" Date: Sun, 22 Oct 2017 13:27:38 +0200 Subject: [PATCH 19/71] add target to build as normal library --- QHotkey.pro | 3 ++- QHotkey/QHotkey.pro | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 QHotkey/QHotkey.pro diff --git a/QHotkey.pro b/QHotkey.pro index 4cb37f4..5fa7cbe 100644 --- a/QHotkey.pro +++ b/QHotkey.pro @@ -1,7 +1,8 @@ TEMPLATE = subdirs SUBDIRS += \ - HotkeyTest + HotkeyTest \ + QHotkey DISTFILES += README.md \ LICENSE \ diff --git a/QHotkey/QHotkey.pro b/QHotkey/QHotkey.pro new file mode 100644 index 0000000..14eeb1f --- /dev/null +++ b/QHotkey/QHotkey.pro @@ -0,0 +1,10 @@ +TARGET = QHotkey +CONFIG += dll +VERSION = 1.0 +TEMPLATE = lib +include(../qhotkey.pri) +headers.files = $$HEADERS QHotkey +headers.path = /$(DESTDIR)$$[QT_INSTALL_HEADERS] +target.path = /$(DESTDIR)$$[QT_INSTALL_LIBS] +INSTALLS += target headers + From 0943bb04941d14349a7a3f280119325cd63cf3b8 Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Mon, 23 Oct 2017 15:36:25 +0200 Subject: [PATCH 20/71] lib fixup --- QHotkey/QHotkey.pro | 18 ++++++++++++------ QHotkey/qhotkey.h | 20 +++++++++++++++----- QHotkey/qhotkey_p.h | 2 +- qhotkey.pri | 3 ++- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/QHotkey/QHotkey.pro b/QHotkey/QHotkey.pro index 14eeb1f..44e937b 100644 --- a/QHotkey/QHotkey.pro +++ b/QHotkey/QHotkey.pro @@ -1,10 +1,16 @@ -TARGET = QHotkey -CONFIG += dll -VERSION = 1.0 TEMPLATE = lib +win32: CONFIG += dll + +TARGET = QHotkey +VERSION = 1.2.1 + include(../qhotkey.pri) -headers.files = $$HEADERS QHotkey -headers.path = /$(DESTDIR)$$[QT_INSTALL_HEADERS] -target.path = /$(DESTDIR)$$[QT_INSTALL_LIBS] + +DEFINES += QHOTKEY_LIB QHOTKEY_LIB_BUILD + +# use INSTALL_ROOT to modify the install location +headers.files = $$PUBLIC_HEADERS +headers.path = $$[QT_INSTALL_HEADERS] +target.path = $$[QT_INSTALL_LIBS] INSTALLS += target headers diff --git a/QHotkey/qhotkey.h b/QHotkey/qhotkey.h index cbf41d8..92d13c8 100644 --- a/QHotkey/qhotkey.h +++ b/QHotkey/qhotkey.h @@ -6,8 +6,18 @@ #include #include +#ifdef QHOTKEY_LIB + #ifdef QHOTKEY_LIB_BUILD + #define QHOTKEY_SHARED_EXPORT Q_DECL_EXPORT + #else + #define QHOTKEY_SHARED_EXPORT Q_DECL_IMPORT + #endif +#else + #define QHOTKEY_SHARED_EXPORT +#endif + //! A class to define global, systemwide Hotkeys -class QHotkey : public QObject +class QHOTKEY_SHARED_EXPORT QHotkey : public QObject { Q_OBJECT friend class QHotkeyPrivate; @@ -19,7 +29,7 @@ class QHotkey : public QObject public: //! Defines shortcut with native keycodes - class NativeShortcut { + class QHOTKEY_SHARED_EXPORT NativeShortcut { public: //! The native keycode quint32 key; @@ -95,9 +105,9 @@ public slots: bool _registered; }; -uint qHash(const QHotkey::NativeShortcut &key); -uint qHash(const QHotkey::NativeShortcut &key, uint seed); +uint QHOTKEY_SHARED_EXPORT qHash(const QHotkey::NativeShortcut &key); +uint QHOTKEY_SHARED_EXPORT qHash(const QHotkey::NativeShortcut &key, uint seed); -Q_DECLARE_LOGGING_CATEGORY(logQHotkey) +QHOTKEY_SHARED_EXPORT Q_DECLARE_LOGGING_CATEGORY(logQHotkey) #endif // QHOTKEY_H diff --git a/QHotkey/qhotkey_p.h b/QHotkey/qhotkey_p.h index 448b95e..7ba4123 100644 --- a/QHotkey/qhotkey_p.h +++ b/QHotkey/qhotkey_p.h @@ -7,7 +7,7 @@ #include #include -class QHotkeyPrivate : public QObject, public QAbstractNativeEventFilter +class QHOTKEY_SHARED_EXPORT QHotkeyPrivate : public QObject, public QAbstractNativeEventFilter { Q_OBJECT diff --git a/qhotkey.pri b/qhotkey.pri index d1a7d91..1dc2ae9 100644 --- a/qhotkey.pri +++ b/qhotkey.pri @@ -1,6 +1,7 @@ CONFIG += C++11 -PUBLIC_HEADERS += $$PWD/QHotkey/qhotkey.h +PUBLIC_HEADERS += $$PWD/QHotkey/qhotkey.h \ + $$PWD/QHotkey/QHotkey HEADERS += $$PUBLIC_HEADERS \ $$PWD/QHotkey/qhotkey_p.h From 974af9253cb43b2b5f9919cbe23feacaa4a5ad3d Mon Sep 17 00:00:00 2001 From: Kolcha Date: Wed, 8 Nov 2017 12:55:42 +0300 Subject: [PATCH 21/71] removed warning for wide range of GCC versions (5,6,7) --- QHotkey/qhotkey_x11.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index ca323c2..7c26313 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -172,8 +172,6 @@ QHotkeyPrivateX11::HotkeyErrorHandler::~HotkeyErrorHandler() int QHotkeyPrivateX11::HotkeyErrorHandler::handleError(Display *display, XErrorEvent *error) { -QT_WARNING_PUSH -QT_WARNING_DISABLE_GCC("-Wimplicit-fallthrough") switch (error->error_code) { case BadAccess: case BadValue: @@ -184,8 +182,8 @@ QT_WARNING_DISABLE_GCC("-Wimplicit-fallthrough") errorString = QHotkeyPrivateX11::formatX11Error(display, error->error_code); return 1; } + // fall through default: return 0; } -QT_WARNING_POP } From 9a04e8f539be7be7f15bbb020ca1694cef6ce5f5 Mon Sep 17 00:00:00 2001 From: Kolcha Date: Wed, 8 Nov 2017 14:16:07 +0300 Subject: [PATCH 22/71] added Q_FALLTHROUGH macro --- QHotkey/qhotkey_x11.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index 7c26313..73e0c3b 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -182,6 +182,7 @@ int QHotkeyPrivateX11::HotkeyErrorHandler::handleError(Display *display, XErrorE errorString = QHotkeyPrivateX11::formatX11Error(display, error->error_code); return 1; } + Q_FALLTHROUGH(); // fall through default: return 0; From d46af319024a2d2aa858c3772d418d8f5a269eae Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Wed, 8 Nov 2017 14:07:59 +0100 Subject: [PATCH 23/71] Add define to stay compatible to pre Qt5.8 --- QHotkey/qhotkey_x11.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index 73e0c3b..6f6f1b6 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -6,6 +6,11 @@ #include #include +//compability to pre Qt 5.8 +#ifndef Q_FALLTHROUGH +#define Q_FALLTHROUGH() (void)0 +#endif + class QHotkeyPrivateX11 : public QHotkeyPrivate { public: From f549a7763fa3c8c0638861ce75217b60beccf43b Mon Sep 17 00:00:00 2001 From: aknobloch Date: Wed, 20 Dec 2017 20:15:02 -0500 Subject: [PATCH 24/71] X11 Media Key Support --- QHotkey/qhotkey_x11.cpp | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index 6f6f1b6..6d7cfc7 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -21,6 +21,7 @@ class QHotkeyPrivateX11 : public QHotkeyPrivate // QHotkeyPrivate interface quint32 nativeKeycode(Qt::Key keycode, bool &ok) Q_DECL_OVERRIDE; quint32 nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) Q_DECL_OVERRIDE; + QString getX11String(Qt::Key keycode); bool registerShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE; bool unregisterShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE; @@ -63,9 +64,33 @@ bool QHotkeyPrivateX11::nativeEventFilter(const QByteArray &eventType, void *mes return false; } +QString QHotkeyPrivateX11::getX11String(Qt::Key keycode) +{ + switch(keycode){ + + case Qt::Key_MediaLast : + case Qt::Key_MediaPrevious : + return "XF86AudioPrev"; + case Qt::Key_MediaNext : + return "XF86AudioNext"; + case Qt::Key_MediaPause : + case Qt::Key_MediaPlay : + case Qt::Key_MediaTogglePlayPause : + return "XF86AudioPlay"; + case Qt::Key_MediaRecord : + return "XF86AudioRecord"; + case Qt::Key_MediaStop : + return "XF86AudioStop"; + default : + return QKeySequence(keycode).toString(QKeySequence::NativeText); + } +} + quint32 QHotkeyPrivateX11::nativeKeycode(Qt::Key keycode, bool &ok) { - KeySym keysym = XStringToKeysym(QKeySequence(keycode).toString(QKeySequence::NativeText).toLatin1().constData()); + QString keyString = getX11String(keycode); + + KeySym keysym = XStringToKeysym(keyString.toLatin1().constData()); if (keysym == NoSymbol) { //not found -> just use the key if(keycode <= 0xFFFF) From fc259100b2f7eb9907a76c29485c5390214a27dd Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Thu, 21 Dec 2017 18:12:48 +0100 Subject: [PATCH 25/71] added addGlobalMapping method Enables overrides for specific key sequences, fixes #11 --- HotkeyTest/hottestwidget.cpp | 7 +++++++ QHotkey/qhotkey.cpp | 16 ++++++++++++++++ QHotkey/qhotkey.h | 4 ++++ QHotkey/qhotkey_p.h | 5 +++++ 4 files changed, 32 insertions(+) diff --git a/HotkeyTest/hottestwidget.cpp b/HotkeyTest/hottestwidget.cpp index 382378b..63faa24 100644 --- a/HotkeyTest/hottestwidget.cpp +++ b/HotkeyTest/hottestwidget.cpp @@ -1,6 +1,8 @@ #include "hottestwidget.h" #include "ui_hottestwidget.h" +//#define TEST_MAPPING + HotTestWidget::HotTestWidget(QWidget *parent) : QWidget(parent), ui(new Ui::HotTestWidget), @@ -18,6 +20,11 @@ HotTestWidget::HotTestWidget(QWidget *parent) : this->thread4->start(); this->thread5->start(); +#ifdef TEST_MAPPING + //shortcut mapping override + QHotkey::addGlobalMapping(QKeySequence("X"), QHotkey::NativeShortcut());// add invalid mapping to test if the overwrite works for all platforms +#endif + //1 connect(this->ui->hotkeyCheckbox_1, &QCheckBox::toggled, this->hotkey_1, &QHotkey::setRegistered); diff --git a/QHotkey/qhotkey.cpp b/QHotkey/qhotkey.cpp index e8e3adb..8b11bdd 100644 --- a/QHotkey/qhotkey.cpp +++ b/QHotkey/qhotkey.cpp @@ -8,6 +8,14 @@ Q_LOGGING_CATEGORY(logQHotkey, "QHotkey") +void QHotkey::addGlobalMapping(const QKeySequence &shortcut, const QHotkey::NativeShortcut &nativeShortcut) +{ + QMetaObject::invokeMethod(QHotkeyPrivate::instance(), "addMappingInvoked", Qt::QueuedConnection, + Q_ARG(Qt::Key, Qt::Key(shortcut[0] & ~Qt::KeyboardModifierMask)), + Q_ARG(Qt::KeyboardModifiers, Qt::KeyboardModifiers(shortcut[0] & Qt::KeyboardModifierMask)), + Q_ARG(QHotkey::NativeShortcut, nativeShortcut)); +} + QHotkey::QHotkey(QObject *parent) : QObject(parent), _keyCode(Qt::Key_unknown), @@ -249,6 +257,11 @@ void QHotkeyPrivate::activateShortcut(QHotkey::NativeShortcut shortcut) signal.invoke(hkey, Qt::QueuedConnection); } +void QHotkeyPrivate::addMappingInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers, const QHotkey::NativeShortcut &nativeShortcut) +{ + mapping.insert({keycode, modifiers}, nativeShortcut); +} + bool QHotkeyPrivate::addShortcutInvoked(QHotkey *hotkey) { QHotkey::NativeShortcut shortcut = hotkey->_nativeShortcut; @@ -279,6 +292,9 @@ bool QHotkeyPrivate::removeShortcutInvoked(QHotkey *hotkey) QHotkey::NativeShortcut QHotkeyPrivate::nativeShortcutInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers) { + if(mapping.contains({keycode, modifiers})) + return mapping.value({keycode, modifiers}); + bool ok1, ok2 = false; auto k = nativeKeycode(keycode, ok1); auto m = nativeModifiers(modifiers, ok2); diff --git a/QHotkey/qhotkey.h b/QHotkey/qhotkey.h index 92d13c8..411b00d 100644 --- a/QHotkey/qhotkey.h +++ b/QHotkey/qhotkey.h @@ -53,6 +53,8 @@ class QHOTKEY_SHARED_EXPORT QHotkey : public QObject bool valid; }; + static void addGlobalMapping(const QKeySequence &shortcut, const NativeShortcut &nativeShortcut); + //! Constructor explicit QHotkey(QObject *parent = Q_NULLPTR); //! Constructs a hotkey with a shortcut and optionally registers it @@ -110,4 +112,6 @@ uint QHOTKEY_SHARED_EXPORT qHash(const QHotkey::NativeShortcut &key, uint seed); QHOTKEY_SHARED_EXPORT Q_DECLARE_LOGGING_CATEGORY(logQHotkey) +Q_DECLARE_METATYPE(QHotkey::NativeShortcut) + #endif // QHOTKEY_H diff --git a/QHotkey/qhotkey_p.h b/QHotkey/qhotkey_p.h index 7ba4123..9e9e0ae 100644 --- a/QHotkey/qhotkey_p.h +++ b/QHotkey/qhotkey_p.h @@ -32,8 +32,10 @@ class QHOTKEY_SHARED_EXPORT QHotkeyPrivate : public QObject, public QAbstractNat virtual bool unregisterShortcut(QHotkey::NativeShortcut shortcut) = 0;//platform implement private: + QHash, QHotkey::NativeShortcut> mapping; QMultiHash shortcuts; + Q_INVOKABLE void addMappingInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers, const QHotkey::NativeShortcut &nativeShortcut); Q_INVOKABLE bool addShortcutInvoked(QHotkey *hotkey); Q_INVOKABLE bool removeShortcutInvoked(QHotkey *hotkey); Q_INVOKABLE QHotkey::NativeShortcut nativeShortcutInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers); @@ -47,4 +49,7 @@ class QHOTKEY_SHARED_EXPORT QHotkeyPrivate : public QObject, public QAbstractNat return hotkeyPrivate;\ } +Q_DECLARE_METATYPE(Qt::Key) +Q_DECLARE_METATYPE(Qt::KeyboardModifiers) + #endif // QHOTKEY_P_H From 2d218337429474b7be7a5d3c073a6839bda7a6e3 Mon Sep 17 00:00:00 2001 From: Felix Barz Date: Thu, 8 Feb 2018 15:28:56 +0100 Subject: [PATCH 26/71] Update README add help text --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ba49d66..de83bae 100644 --- a/README.md +++ b/README.md @@ -90,3 +90,4 @@ The documentation was created using [doxygen](http://www.doxygen.org). It includ - Qt::Key makes no difference between normal numbers and the Numpad numbers. Most keyboards however require this. Thus, you can't register shortcuts for the numpad, unless you use a native shortcut. - Supports not all keys, but most of the common ones. There are differences between platforms and it depends on the Keyboard-Layout. "Delete", for example, works on windows and mac, but not on X11 (At least on my test machines). I tried to use OS-Functions where possible, but since the Qt::Key values need to be converted into native keys, there are some limitations. I can use need such a key, try using the native shortcut. - The registered keys will be "taken" by QHotkey. This means after a hotkey was cosumend by your application, it will not be sent to the active application. This is done this way by the operating systems and cannot be changed. +- If you get a `QHotkey: Failed to register hotkey. Error: BadAccess (attempt to access private resource denied)` error on X11, this means you are trying to register a hotkey that is private to X11. Those keys simply cannot be registered using the normal API From 080ddd479abdaa559900d4480beaffb41ea3c9db Mon Sep 17 00:00:00 2001 From: Felix Barz Date: Thu, 22 Feb 2018 20:53:04 +0100 Subject: [PATCH 27/71] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index de83bae..3574799 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ The QHotkey is a class that can be used to create hotkeys/global shortcuts, aka - Thread-Safe - Can be used on all threads (See section Thread safety) - Allows usage of native keycodes and modifiers, if needed +**Note:** For now Wayland is not supported, as it is simply not possible to register a global shortcut with wayland. For more details, or possible Ideas on how to get Hotkeys working on wayland, see [Issue #14](https://github.com/Skycoder42/QHotkey/issues/14). + ## Installation The package is providet as qpm package, [`de.skycoder42.qhotkey`](https://www.qpm.io/packages/de.skycoder42.qhotkey/index.html). To install: From 9a90aff27329ea94482f85489d9806c2302a02a3 Mon Sep 17 00:00:00 2001 From: Andriy Semenets Date: Sat, 10 Mar 2018 16:42:45 +0200 Subject: [PATCH 28/71] Fix issue with non-English keyboard on Windows Full issue described in #17. --- QHotkey/qhotkey_win.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/QHotkey/qhotkey_win.cpp b/QHotkey/qhotkey_win.cpp index c7d25b4..6b458a5 100644 --- a/QHotkey/qhotkey_win.cpp +++ b/QHotkey/qhotkey_win.cpp @@ -202,8 +202,12 @@ quint32 QHotkeyPrivateWin::nativeKeycode(Qt::Key keycode, bool &ok) return VK_OEM_FJ_TOUROKU; default: - ok = false; - return 0; + if(keycode <= 0xFFFF) + return (byte)keycode; + else { + ok = false; + return 0; + } } } From 547cf7a7cc64a0f313887f42595088a470e36d33 Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Sat, 10 Mar 2018 23:22:50 +0100 Subject: [PATCH 29/71] updated qpm version fixes #19 --- qpm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qpm.json b/qpm.json index 093bb63..61cbd48 100644 --- a/qpm.json +++ b/qpm.json @@ -15,7 +15,7 @@ }, "version": { "fingerprint": "", - "label": "1.2.1", + "label": "1.2.2", "revision": "" }, "webpage": "https://github.com/Skycoder42/QHotkey" From 700367d132caaaf7f4697ddb84e61ce06d7252b1 Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Sun, 11 Mar 2018 00:06:42 +0100 Subject: [PATCH 30/71] updated readme and documentation --- QHotkey/qhotkey.h | 31 ++--- README.md | 31 +++-- doc/{qhotkey.doxy => Doxyfile} | 202 ++++++++++++++++++--------------- doc/qhotkey.dox | 74 +++++------- 4 files changed, 176 insertions(+), 162 deletions(-) rename doc/{qhotkey.doxy => Doxyfile} (92%) diff --git a/QHotkey/qhotkey.h b/QHotkey/qhotkey.h index 411b00d..133ef25 100644 --- a/QHotkey/qhotkey.h +++ b/QHotkey/qhotkey.h @@ -20,6 +20,7 @@ class QHOTKEY_SHARED_EXPORT QHotkey : public QObject { Q_OBJECT + //! @private friend class QHotkeyPrivate; //! Specifies whether this hotkey is currently registered or not @@ -53,40 +54,40 @@ class QHOTKEY_SHARED_EXPORT QHotkey : public QObject bool valid; }; + //! Adds a global mapping of a key sequence to a replacement native shortcut static void addGlobalMapping(const QKeySequence &shortcut, const NativeShortcut &nativeShortcut); - //! Constructor - explicit QHotkey(QObject *parent = Q_NULLPTR); + //! Default Constructor + explicit QHotkey(QObject *parent = nullptr); //! Constructs a hotkey with a shortcut and optionally registers it - explicit QHotkey(const QKeySequence &shortcut, bool autoRegister = false, QObject *parent = Q_NULLPTR); + explicit QHotkey(const QKeySequence &shortcut, bool autoRegister = false, QObject *parent = nullptr); //! Constructs a hotkey with a key and modifiers and optionally registers it - explicit QHotkey(Qt::Key keyCode, Qt::KeyboardModifiers modifiers, bool autoRegister = false, QObject *parent = Q_NULLPTR); + explicit QHotkey(Qt::Key keyCode, Qt::KeyboardModifiers modifiers, bool autoRegister = false, QObject *parent = nullptr); //! Constructs a hotkey from a native shortcut and optionally registers it - explicit QHotkey(const NativeShortcut &shortcut, bool autoRegister = false, QObject *parent = Q_NULLPTR); - //! Destructor + explicit QHotkey(const NativeShortcut &shortcut, bool autoRegister = false, QObject *parent = nullptr); ~QHotkey(); - //! READ-Accessor for QHotkey::registered + //! @readAcFn{QHotkey::registered} bool isRegistered() const; - //! READ-Accessor for QHotkey::shortcut - the key and modifiers as a QKeySequence + //! @readAcFn{QHotkey::shortcut} QKeySequence shortcut() const; - //! READ-Accessor for QHotkey::shortcut - the key only + //! @readAcFn{QHotkey::shortcut} - the key only Qt::Key keyCode() const; - //! READ-Accessor for QHotkey::shortcut - the modifiers only + //! @readAcFn{QHotkey::shortcut} - the modifiers only Qt::KeyboardModifiers modifiers() const; //! Get the current native shortcut NativeShortcut currentNativeShortcut() const; public slots: - //! WRITE-Accessor for QHotkey::registered + //! @writeAcFn{QHotkey::registered} bool setRegistered(bool registered); - //! WRITE-Accessor for QHotkey::shortcut + //! @writeAcFn{QHotkey::shortcut} bool setShortcut(const QKeySequence &shortcut, bool autoRegister = false); - //! WRITE-Accessor for QHotkey::shortcut + //! @writeAcFn{QHotkey::shortcut} bool setShortcut(Qt::Key keyCode, Qt::KeyboardModifiers modifiers, bool autoRegister = false); - //! RESET-Accessor for QHotkey::shortcut + //! @resetAcFn{QHotkey::shortcut} bool resetShortcut(); //! Set this hotkey to a native shortcut @@ -96,7 +97,7 @@ public slots: //! Will be emitted if the shortcut is pressed void activated(QPrivateSignal); - //! NOTIFY-Accessor for QHotkey::registered + //! @notifyAcFn{QHotkey::registered} void registeredChanged(bool registered); private: diff --git a/README.md b/README.md index 3574799..e4f3f78 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,16 @@ The QHotkey is a class that can be used to create hotkeys/global shortcuts, aka **Note:** For now Wayland is not supported, as it is simply not possible to register a global shortcut with wayland. For more details, or possible Ideas on how to get Hotkeys working on wayland, see [Issue #14](https://github.com/Skycoder42/QHotkey/issues/14). ## Installation -The package is providet as qpm package, [`de.skycoder42.qhotkey`](https://www.qpm.io/packages/de.skycoder42.qhotkey/index.html). To install: +The package is providet as qpm package, [`de.skycoder42.qhotkey`](https://www.qpm.io/packages/de.skycoder42.qhotkey/index.html). You can install it either via qpmx (preferred) or directly via qpm. + +### Via qpmx +[qpmx](https://github.com/Skycoder42/qpmx) is a frontend for qpm (and other tools) with additional features, and is the preferred way to install packages. To use it: + +1. Install qpmx (See [GitHub - Installation](https://github.com/Skycoder42/qpmx#installation)) +2. Install qpm (See [GitHub - Installing](https://github.com/Cutehacks/qpm/blob/master/README.md#installing), for **windows** see below) +3. In your projects root directory, run `qpmx install de.skycoder42.qhotkey` + +### Via qpm 1. Install qpm (See [GitHub - Installing](https://github.com/Cutehacks/qpm/blob/master/README.md#installing), for **windows** see below) 2. In your projects root directory, run `qpm install de.skycoder42.qhotkey` @@ -39,17 +48,17 @@ The following example shows a simple application that will run without a window int main(int argc, char *argv[]) { - QApplication a(argc, argv); + QApplication a(argc, argv); - QHotkey hotkey(QKeySequence("ctrl+alt+Q"), true);//The hotkey will be automatically registered - qDebug() << "Is Registered: " << hotkey.isRegistered(); + auto hotkey = new QHotkey(QKeySequence("ctrl+alt+Q"), true, &a);//The hotkey will be automatically registered + qDebug() << "Is Registered: " << hotkey->isRegistered(); - QObject::connect(&hotkey, &QHotkey::activated, qApp, [&](){ - qDebug() << "Hotkey Activated - the application will quit now"; - qApp->quit(); - }); + QObject::connect(hotkey, &QHotkey::activated, qApp, [&](){ + qDebug() << "Hotkey Activated - the application will quit now"; + qApp->quit(); + }); - return a.exec(); + return a.exec(); } ``` @@ -60,7 +69,7 @@ By running the example in `./HotkeyTest` you can test out the QHotkey class. The - **Playground:** You can enter some sequences here and try it out with different key combinations. - **Testings:** A list of selected hotkeys. Activate it and try out which ones work for you (*Hint:* Depending on OS and keyboard layout, it's very possible that a few don't work). - **Threading:** Activate the checkbox to move 2 Hotkeys of the playground to seperate threads. It should work without a difference. -- **Native Shortcut**: Allows you to try out the direct usage of native shortcuts +- **Native Shortcut**: Allows you to try out the direct usage of native shortcuts ### Logging By default, QHotkey prints some warning messages if something goes wrong (For example, a key that cannot be translated). All messages of QHotkey are grouped into the [QLoggingCategory](https://doc.qt.io/qt-5/qloggingcategory.html) `"QHotkey"`. If you want to simply disable the logging, call the folling function somewhere in your code: @@ -83,7 +92,7 @@ The documentation was created using [doxygen](http://www.doxygen.org). It includ ## Technical ### Requirements - - I built it with Qt 5.7, but may work with earlier versions, too + - Explicit support is only given down to the latest Qt LTS, but may work with earlier versions, too - At least the QtGui-Module (a QGuiApplication). Hotkeys on console based applications are not supported (By the operating systems). You can however create a gui application without any visible window. - C++11 diff --git a/doc/qhotkey.doxy b/doc/Doxyfile similarity index 92% rename from doc/qhotkey.doxy rename to doc/Doxyfile index da809e6..e65e660 100644 --- a/doc/qhotkey.doxy +++ b/doc/Doxyfile @@ -1,4 +1,4 @@ -# Doxyfile 1.8.12 +# Doxyfile 1.8.14 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -20,8 +20,8 @@ # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv -# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv -# for the list of possible encodings. +# built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 @@ -38,7 +38,7 @@ PROJECT_NAME = QHotkey # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.1.0 +PROJECT_NUMBER = 1.2.2 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -58,7 +58,7 @@ PROJECT_LOGO = # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = ../../QHotkey_doc_generated +OUTPUT_DIRECTORY = /tmp/qthotkeydoc # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and @@ -236,7 +236,8 @@ TAB_SIZE = 4 # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines. +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. ALIASES = "accessors{1}=\1
Accessors
" \ readAc{1}=READ\1 \ @@ -252,10 +253,13 @@ ALIASES = "accessors{1}=< "constantAc=" \ "finalAc=" \ "default{1}=Default: \1
" \ - overloads{1}=Overloads:
    \1
\ - ovElem{1}=
  • \1
  • \ - "overload=This is an overloaded function." \ - "povElem{1}=
  • \1 (primary, check for more details)
  • " + "readAcFn{1}=READ accessor for \1" \ + "writeAcFn{1}=WRITE accessor for \1" \ + "notifyAcFn{1}=NOTIFY accessor for \1" \ + "resetAcFn{1}=RESET accessor for \1" \ + "memberAcFn{1}=MEMBER accessor for \1" \ + "inherit{1}=Inherits \1" \ + "privsig=This is a private signal. It can be connect to as usual, but can only be emitted by the class it belongs to" # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" @@ -354,7 +358,7 @@ BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. @@ -725,7 +729,7 @@ LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool -# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. @@ -773,7 +777,7 @@ WARN_IF_DOC_ERROR = YES # parameter documentation, but not about the absence of documentation. # The default value is: NO. -WARN_NO_PARAMDOC = YES +WARN_NO_PARAMDOC = NO # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. @@ -814,7 +818,7 @@ INPUT = ../QHotkey/qhotkey.h \ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of # possible encodings. # The default value is: UTF-8. @@ -921,12 +925,21 @@ EXCLUDE_PATTERNS = moc_* \ # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* -EXCLUDE_SYMBOLS = QBasicAtomicInteger \ +EXCLUDE_SYMBOLS = QAbstractAspect \ + QBasicAtomicInteger \ QBasicAtomicPointer \ + QBasicMutex \ + QComponent \ + QEntity \ QFutureWatcherBase \ - QListSpecialMethods \ + QGeometry \ + QGeometryRenderer \ + QMaterial \ + QNode \ + QNodeCreatedChangeBase \ QPaintEngineEx \ - QQmlExtensionInterface + QQmlExtensionInterface \ + QTechniqueFilter # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include @@ -1069,7 +1082,7 @@ SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system -# (see http://www.gnu.org/software/global/global.html). You will need version +# (see https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: @@ -1096,25 +1109,6 @@ USE_HTAGS = NO VERBATIM_HEADERS = YES -# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the -# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the -# cost of reduced performance. This can be particularly helpful with template -# rich C++ code for which doxygen's built-in parser lacks the necessary type -# information. -# Note: The availability of this option depends on whether or not doxygen was -# generated with the -Duse-libclang=ON option for CMake. -# The default value is: NO. - -CLANG_ASSISTED_PARSING = NO - -# If clang assisted parsing is enabled you can provide the compiler with command -# line options that you would normally use when invoking the compiler. Note that -# the include paths will already be set by doxygen for the files and directories -# specified with INPUT and INCLUDE_PATH. -# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. - -CLANG_OPTIONS = - #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- @@ -1233,7 +1227,7 @@ HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see -# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. @@ -1269,6 +1263,17 @@ HTML_COLORSTYLE_GAMMA = 89 HTML_TIMESTAMP = YES +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via Javascript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have Javascript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. @@ -1292,12 +1297,12 @@ HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# environment (see: https://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# startup. See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1413,40 +1418,37 @@ QCH_FILE = QHotkeyHelp.qch # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace -# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# (see: http://doc.qt.io/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. -QHP_NAMESPACE = com.Skycoder42.QHotkey.110 +QHP_NAMESPACE = de.skycoder42.QHotkey.122 # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- -# folders). +# Folders (see: http://doc.qt.io/qt-4.8/qthelpproject.html#virtual-folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. -QHP_VIRTUAL_FOLDER = doc_QHotkey +QHP_VIRTUAL_FOLDER = doc_qhotkey # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). +# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. -QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_NAME = "QHotkey 1.2.2" # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). +# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. -QHP_CUST_FILTER_ATTRS = +QHP_CUST_FILTER_ATTRS = "qhotkey 1.2.2" # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# http://doc.qt.io/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = @@ -1456,7 +1458,7 @@ QHP_SECT_FILTER_ATTRS = # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. -QHG_LOCATION = C:/Qt/5.7/msvc2015_64/bin/qhelpgenerator.exe +QHG_LOCATION = /usr/bin/qhelpgenerator # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To @@ -1539,7 +1541,7 @@ EXT_LINKS_IN_WINDOW = YES FORMULA_FONTSIZE = 10 -# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # @@ -1551,7 +1553,7 @@ FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# http://www.mathjax.org) which uses client side Javascript for the rendering +# https://www.mathjax.org) which uses client side Javascript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path @@ -1578,8 +1580,8 @@ MATHJAX_FORMAT = HTML-CSS # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of -# MathJax from http://www.mathjax.org before deployment. -# The default value is: http://cdn.mathjax.org/mathjax/latest. +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest @@ -1640,7 +1642,7 @@ SERVER_BASED_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: http://xapian.org/). +# Xapian (see: https://xapian.org/). # # See the section "External Indexing and Searching" for details. # The default value is: NO. @@ -1653,7 +1655,7 @@ EXTERNAL_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: http://xapian.org/). See the section "External Indexing and +# Xapian (see: https://xapian.org/). See the section "External Indexing and # Searching" for details. # This tag requires that the tag SEARCHENGINE is set to YES. @@ -1840,7 +1842,7 @@ LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. See -# http://en.wikipedia.org/wiki/BibTeX and \cite for more info. +# https://en.wikipedia.org/wiki/BibTeX and \cite for more info. # The default value is: plain. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -2023,9 +2025,9 @@ DOCBOOK_PROGRAMLISTING = NO #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an -# AutoGen Definitions (see http://autogen.sf.net) file that captures the -# structure of the code including all documentation. Note that this feature is -# still experimental and incomplete at the moment. +# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures +# the structure of the code including all documentation. Note that this feature +# is still experimental and incomplete at the moment. # The default value is: NO. GENERATE_AUTOGEN_DEF = NO @@ -2107,7 +2109,7 @@ SEARCH_INCLUDES = YES # preprocessor. # This tag requires that the tag SEARCH_INCLUDES is set to YES. -INCLUDE_PATH = C:/Qt/5.7/msvc2015_64/include +INCLUDE_PATH = /usr/include/qt # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the @@ -2127,7 +2129,7 @@ INCLUDE_FILE_PATTERNS = *.h \ # recursively expanded use the := operator instead of the = operator. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = +PREDEFINED = __cplusplus=201402L # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The @@ -2165,37 +2167,50 @@ SKIP_FUNCTION_MACROS = YES # the path). If a tag file is not located in the directory in which doxygen is # run, you must also specify the path to the tagfile here. -TAGFILES = C:/Qt/Docs/Qt-5.7/qtwebengine/qtwebengine.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtgraphicaleffects/qtgraphicaleffects.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtwebchannel/qtwebchannel.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtwebsockets/qtwebsockets.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtbluetooth/qtbluetooth.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtnfc/qtnfc.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtsensors/qtsensors.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtlocation/qtlocation.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtpositioning/qtpositioning.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/activeqt/activeqt.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtquickcontrols/qtquickcontrols.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtqml/qtqml.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtquick/qtquick.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtxmlpatterns/qtxmlpatterns.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtsvg/qtsvg.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qdoc/qdoc.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtprintsupport/qtprintsupport.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtconcurrent/qtconcurrent.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtgui/qtgui.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qttestlib/qttestlib.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtwidgets/qtwidgets.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtcore/qtcore.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtnetwork/qtnetwork.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtsql/qtsql.tags=http://doc.qt.io/qt-5 \ - C:/Qt/Docs/Qt-5.7/qtxml/qtxml.tags=http://doc.qt.io/qt-5 +TAGFILES = "/home/sky/Qt/Docs/Qt-5.10.1/qdoc/qdoc.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtlabsplatform/qtlabsplatform.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtqml/qtqml.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtprintsupport/qtprintsupport.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qttestlib/qttestlib.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtautoupdater/qtautoupdater.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtlabscalendar/qtlabscalendar.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtdatasync/qtdatasync.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtwebchannel/qtwebchannel.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtpositioning/qtpositioning.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtrestclient/qtrestclient.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtcore/qtcore.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtnfc/qtnfc.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtquickcontrols/qtquickcontrols.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtwidgets/qtwidgets.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtgraphicaleffects/qtgraphicaleffects.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtlocation/qtlocation.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtgui/qtgui.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtwebengine/qtwebengine.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtnetwork/qtnetwork.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtxml/qtxml.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtscxml/qtscxml.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/activeqt/activeqt.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtjsonserializer/qtjsonserializer.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtsensors/qtsensors.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtnetworkauth/qtnetworkauth.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtxmlpatterns/qtxmlpatterns.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtspeech/qtspeech.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtsvg/qtsvg.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtserialbus/qtserialbus.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtbluetooth/qtbluetooth.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtsql/qtsql.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtwebsockets/qtwebsockets.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtquick/qtquick.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qt3d/qt3d.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtquickcontrols2/qtquickcontrols2.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtremoteobjects/qtremoteobjects.tags=https://doc.qt.io/qt-5" \ + "/home/sky/Qt/Docs/Qt-5.10.1/qtconcurrent/qtconcurrent.tags=https://doc.qt.io/qt-5" # When a file name is specified after GENERATE_TAGFILE, doxygen will create a # tag file that is based on the input files it reads. See section "Linking to # external documentation" for more information about the usage of tag files. -GENERATE_TAGFILE = ../../QHotkey_doc_generated/QHotkey.tag +GENERATE_TAGFILE = /tmp/qthotkeydoc/QHotkey.tag # If the ALLEXTERNALS tag is set to YES, all external class will be listed in # the class index. If set to NO, only the inherited external classes will be @@ -2473,6 +2488,11 @@ DIAFILE_DIRS = PLANTUML_JAR_PATH = +# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a +# configuration file for plantuml. + +PLANTUML_CFG_FILE = + # When using plantuml, the specified paths are searched for files specified by # the !include statement in a plantuml block. diff --git a/doc/qhotkey.dox b/doc/qhotkey.dox index f6624c1..fe184f3 100644 --- a/doc/qhotkey.dox +++ b/doc/qhotkey.dox @@ -22,9 +22,9 @@ thread until the applications eventloop has the time to handle it. If the loop i it does. This does not happen if used from the main thread. @accessors{ - @readAc{isRegistered()} - @writeAc{setRegistered()} - @notifyAc{registeredChanged()} + @readAc{isRegistered()} + @writeAc{setRegistered()} + @notifyAc{registeredChanged()} } In addition to the normal accessors, a modification of the QHotkey::shortcut property can change this property, too. @@ -49,15 +49,15 @@ thread until the applications eventloop has the time to handle it. If the loop i it does. This does not happen if used from the main thread. @accessors{ - @readAc{ - shortcut()
    - keyCode()
    - modifiers() - } - @writeAc{ - setShortcut(const QKeySequence &, bool)
    - setShortcut(Qt::Key, Qt::KeyboardModifiers, bool) - } + @readAc{ + shortcut()
    + keyCode()
    + modifiers() + } + @writeAc{ + setShortcut(const QKeySequence &, bool)
    + setShortcut(Qt::Key, Qt::KeyboardModifiers, bool) + } } @sa QHotkey::registered, QHotkey::isKeyCaptured, QHotkey::currentNativeShortcut, QHotkey::setNativeShortcut @@ -66,71 +66,39 @@ it does. This does not happen if used from the main thread. /*! @fn QHotkey::QHotkey(QObject *) -@overload @param parent The parent object - -@overloads{ - @povElem{QHotkey::QHotkey(QObject *)} - @ovElem{QHotkey::QHotkey(const QKeySequence &, bool, QObject *)} - @ovElem{QHotkey::QHotkey(Qt::Key, Qt::KeyboardModifiers, bool, QObject *)} - @ovElem{QHotkey::QHotkey(const NativeShortcut &, bool, QObject *)} -} */ /*! @fn QHotkey::QHotkey(const QKeySequence &, bool, QObject *) -@overload @param parent The parent object @param shortcut The shortcut this hotkey should be registered for @param autoRegister Specifies, whether the hotkey should be automatically registered or not -@overloads{ - @povElem{QHotkey::QHotkey(QObject *)} - @ovElem{QHotkey::QHotkey(const QKeySequence &, bool, QObject *)} - @ovElem{QHotkey::QHotkey(Qt::Key, Qt::KeyboardModifiers, bool, QObject *)} - @ovElem{QHotkey::QHotkey(const NativeShortcut &, bool, QObject *)} -} - @sa QHotkey::shortcut, QHotkey::registered */ /*! @fn QHotkey::QHotkey(Qt::Key, Qt::KeyboardModifiers, bool, QObject *) -@overload @param parent The parent object -@param key The key this hotkey should be registered for +@param keyCode The key this hotkey should be registered for @param modifiers The modifiers that have to be pressed together with the `key` @param autoRegister Specifies, whether the hotkey should be automatically registered or not -@overloads{ - @povElem{QHotkey::QHotkey(QObject *)} - @ovElem{QHotkey::QHotkey(const QKeySequence &, bool, QObject *)} - @ovElem{QHotkey::QHotkey(Qt::Key, Qt::KeyboardModifiers, bool, QObject *)} - @ovElem{QHotkey::QHotkey(const NativeShortcut &, bool, QObject *)} -} - @sa QHotkey::shortcut, QHotkey::registered */ /*! @fn QHotkey::QHotkey(const NativeShortcut &, bool, QObject *) -@overload @param parent The parent object @param shortcut The native shortcut this hotkey should be registered for @param autoRegister Specifies, whether the hotkey should be automatically registered or not @note Please check QHotkey::setNativeShortcut for important hints! -@overloads{ - @povElem{QHotkey::QHotkey(QObject *)} - @ovElem{QHotkey::QHotkey(const QKeySequence &, bool, QObject *)} - @ovElem{QHotkey::QHotkey(Qt::Key, Qt::KeyboardModifiers, bool, QObject *)} - @ovElem{QHotkey::QHotkey(const NativeShortcut &, bool, QObject *)} -} - @sa QHotkey::setNativeShortcut, QHotkey::registered */ @@ -168,6 +136,22 @@ from the thread this instance lives on. @note This is a private signal. It can be used in signal connections but cannot be emitted by the user. */ +/*! +@fn QHotkey::addGlobalMapping + +@param shortcut The keysequence to add the mapping for +@param nativeShortcut The native shortcut to overwrite the sequence with + +This method can be used to remap specific hotkey to a different native representation than the +one that would be used by default. This can be useful if specific key combinations work fine +on allmost all platforms, but on one you need a different keycode for the same effect. See +[Issue #15](https://github.com/Skycoder42/QHotkey/issues/15) for an example where this is the +case. + +The advantage of using this approach via simply registering it as native key directly, is that +these mappings work for cases where users input their own hotkeys. +*/ + /*! @class QHotkey::NativeShortcut From 9a44a0313be65b684613bb58758788f0ae1098dc Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris Date: Mon, 29 Oct 2018 17:21:05 +0200 Subject: [PATCH 31/71] Add CMake support --- CMakeLists.txt | 70 +++++++++++++++++++++++++++++++++++++++ HotkeyTest/CMakeLists.txt | 12 +++++++ 2 files changed, 82 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 HotkeyTest/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..41f2037 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,70 @@ +cmake_minimum_required(VERSION 3.1) + +project(qhotkey VERSION 1.2.2 LANGUAGES CXX) + +option(QHOTKEY_EXAMPLES "Build examples" ON) + +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +find_package(Qt5 COMPONENTS Core Widgets REQUIRED) + +qt5_wrap_cpp(MOC_HEADERS + QHotkey/qhotkey.h + QHotkey/qhotkey_p.h) + +set(LIBS + Qt5::Core + Qt5::Widgets) + +set(SRC_FILES + QHotkey/qhotkey.cpp) + +if(APPLE) + find_library(CARBON_LIBRARY Carbon) + mark_as_advanced(CARBON_LIBRARY) + + set(SRC_FILES ${SRC_FILES} QHotkey/qhotkey_mac.cpp) + set(LIBS ${LIBS} ${CARBON_LIBRARY}) +elseif(WIN32) + set(SRC_FILES ${SRC_FILES} QHotkey/qhotkey_win.cpp) +else() + find_package(X11 REQUIRED) + find_package(Qt5X11Extras REQUIRED) + + include_directories(${X11_INCLUDE_DIR}) + set(LIBS ${LIBS} ${X11_LIBRARIES} Qt5::X11Extras) + set(SRC_FILES ${SRC_FILES} QHotkey/qhotkey_x11.cpp) +endif() + +add_library(qhotkey ${SRC_FILES} ${MOC_HEADERS}) +add_library(QHotkey::QHotkey ALIAS qhotkey) +target_link_libraries(qhotkey ${LIBS}) + +target_include_directories(qhotkey + PUBLIC + $ + $) + +set_target_properties(qhotkey PROPERTIES + SOVERSION ${PROJECT_VERSION_MAJOR} + VERSION ${PROJECT_VERSION}) + +if(QHOTKEY_EXAMPLES) + add_subdirectory(HotkeyTest) +endif() + +include(GNUInstallDirs) +set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/QHotkey) + +install( + TARGETS qhotkey EXPORT QHotkeyConfig + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +install(FILES + ${CMAKE_SOURCE_DIR}/QHotkey/qhotkey.h + ${CMAKE_SOURCE_DIR}/QHotkey/QHotkey + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/) +install(EXPORT QHotkeyConfig DESTINATION ${INSTALL_CONFIGDIR}) + +export(TARGETS qhotkey FILE QHotkeyConfig.cmake) diff --git a/HotkeyTest/CMakeLists.txt b/HotkeyTest/CMakeLists.txt new file mode 100644 index 0000000..67dfc8e --- /dev/null +++ b/HotkeyTest/CMakeLists.txt @@ -0,0 +1,12 @@ +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +qt5_wrap_ui(test_UI_HEADERS hottestwidget.ui) +qt5_wrap_cpp(test_MOC_HEADERS hottestwidget.h) + +add_executable(HotkeyTest + main.cpp + hottestwidget.cpp + ${test_UI_HEADERS} + ${test_MOC_HEADERS}) +target_link_libraries(HotkeyTest Qt5::Widgets qhotkey) +target_include_directories(HotkeyTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) From a7110cabb39d2aef6a54a2ed837a52bf615b3638 Mon Sep 17 00:00:00 2001 From: Shatur95 Date: Wed, 6 Nov 2019 01:34:42 +0200 Subject: [PATCH 32/71] Fix crash on Wayland --- QHotkey/qhotkey_x11.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index 6d7cfc7..a3e48ee 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -99,8 +99,7 @@ quint32 QHotkeyPrivateX11::nativeKeycode(Qt::Key keycode, bool &ok) return 0; } - Display *display = QX11Info::display(); - if(display) { + if(QX11Info::isPlatformX11()) { auto res = XKeysymToKeycode(QX11Info::display(), keysym); if(res != 0) ok = true; From 9583eafe76186128ae77f4f02505ca777c1855d3 Mon Sep 17 00:00:00 2001 From: Hennadii Chernyshchyk Date: Tue, 7 Jan 2020 10:31:37 +0200 Subject: [PATCH 33/71] Add isPlatformSupported() (#28) * Add isPlatformSupported() * Remove extra semicolons * Add newlines before new methods --- QHotkey/qhotkey.cpp | 5 +++++ QHotkey/qhotkey.h | 3 +++ QHotkey/qhotkey_mac.cpp | 11 ++++++++--- QHotkey/qhotkey_p.h | 1 + QHotkey/qhotkey_win.cpp | 9 +++++++-- QHotkey/qhotkey_x11.cpp | 9 +++++++-- 6 files changed, 31 insertions(+), 7 deletions(-) diff --git a/QHotkey/qhotkey.cpp b/QHotkey/qhotkey.cpp index 8b11bdd..8dadc08 100644 --- a/QHotkey/qhotkey.cpp +++ b/QHotkey/qhotkey.cpp @@ -16,6 +16,11 @@ void QHotkey::addGlobalMapping(const QKeySequence &shortcut, const QHotkey::Nati Q_ARG(QHotkey::NativeShortcut, nativeShortcut)); } +bool QHotkey::isPlatformSupported() +{ + return QHotkeyPrivate::isPlatformSupported(); +} + QHotkey::QHotkey(QObject *parent) : QObject(parent), _keyCode(Qt::Key_unknown), diff --git a/QHotkey/qhotkey.h b/QHotkey/qhotkey.h index 133ef25..479dff5 100644 --- a/QHotkey/qhotkey.h +++ b/QHotkey/qhotkey.h @@ -57,6 +57,9 @@ class QHOTKEY_SHARED_EXPORT QHotkey : public QObject //! Adds a global mapping of a key sequence to a replacement native shortcut static void addGlobalMapping(const QKeySequence &shortcut, const NativeShortcut &nativeShortcut); + //! Checks if global shortcuts are supported by the current platform + static bool isPlatformSupported(); + //! Default Constructor explicit QHotkey(QObject *parent = nullptr); //! Constructs a hotkey with a shortcut and optionally registers it diff --git a/QHotkey/qhotkey_mac.cpp b/QHotkey/qhotkey_mac.cpp index ac123bf..a410373 100644 --- a/QHotkey/qhotkey_mac.cpp +++ b/QHotkey/qhotkey_mac.cpp @@ -24,14 +24,19 @@ class QHotkeyPrivateMac : public QHotkeyPrivate }; NATIVE_INSTANCE(QHotkeyPrivateMac) +bool QHotkeyPrivate::isPlatformSupported() +{ + return true; +} + bool QHotkeyPrivateMac::isHotkeyHandlerRegistered = false; QHash QHotkeyPrivateMac::hotkeyRefs; bool QHotkeyPrivateMac::nativeEventFilter(const QByteArray &eventType, void *message, long *result) { - Q_UNUSED(eventType); - Q_UNUSED(message); - Q_UNUSED(result); + Q_UNUSED(eventType) + Q_UNUSED(message) + Q_UNUSED(result) return false; } diff --git a/QHotkey/qhotkey_p.h b/QHotkey/qhotkey_p.h index 9e9e0ae..847f7db 100644 --- a/QHotkey/qhotkey_p.h +++ b/QHotkey/qhotkey_p.h @@ -16,6 +16,7 @@ class QHOTKEY_SHARED_EXPORT QHotkeyPrivate : public QObject, public QAbstractNat ~QHotkeyPrivate(); static QHotkeyPrivate *instance(); + static bool isPlatformSupported(); QHotkey::NativeShortcut nativeShortcut(Qt::Key keycode, Qt::KeyboardModifiers modifiers); diff --git a/QHotkey/qhotkey_win.cpp b/QHotkey/qhotkey_win.cpp index 6b458a5..ead6763 100644 --- a/QHotkey/qhotkey_win.cpp +++ b/QHotkey/qhotkey_win.cpp @@ -23,10 +23,15 @@ class QHotkeyPrivateWin : public QHotkeyPrivate }; NATIVE_INSTANCE(QHotkeyPrivateWin) +bool QHotkeyPrivate::isPlatformSupported() +{ + return true; +} + bool QHotkeyPrivateWin::nativeEventFilter(const QByteArray &eventType, void *message, long *result) { - Q_UNUSED(eventType); - Q_UNUSED(result); + Q_UNUSED(eventType) + Q_UNUSED(result) MSG* msg = static_cast(message); if(msg->message == WM_HOTKEY) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index a3e48ee..43f8956 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -47,13 +47,18 @@ class QHotkeyPrivateX11 : public QHotkeyPrivate }; NATIVE_INSTANCE(QHotkeyPrivateX11) +bool QHotkeyPrivate::isPlatformSupported() +{ + return QX11Info::isPlatformX11(); +} + const QVector QHotkeyPrivateX11::specialModifiers = {0, Mod2Mask, LockMask, (Mod2Mask | LockMask)}; const quint32 QHotkeyPrivateX11::validModsMask = ShiftMask | ControlMask | Mod1Mask | Mod4Mask; bool QHotkeyPrivateX11::nativeEventFilter(const QByteArray &eventType, void *message, long *result) { - Q_UNUSED(eventType); - Q_UNUSED(result); + Q_UNUSED(eventType) + Q_UNUSED(result) xcb_generic_event_t *genericEvent = static_cast(message); if (genericEvent->response_type == XCB_KEY_PRESS) { From 5b507a84df9f784513ee6abb71d415e557e56e09 Mon Sep 17 00:00:00 2001 From: Alexandre Vicente Date: Tue, 21 Apr 2020 12:45:10 -0300 Subject: [PATCH 34/71] Hotkey release signal --- QHotkey/qhotkey.cpp | 7 +++++++ QHotkey/qhotkey.h | 3 +++ QHotkey/qhotkey_mac.cpp | 39 +++++++++++++++++++++++++++++++++------ QHotkey/qhotkey_p.h | 1 + QHotkey/qhotkey_win.cpp | 24 +++++++++++++++++++++--- QHotkey/qhotkey_x11.cpp | 27 +++++++++++++++++++++++++-- 6 files changed, 90 insertions(+), 11 deletions(-) diff --git a/QHotkey/qhotkey.cpp b/QHotkey/qhotkey.cpp index 8dadc08..853b68d 100644 --- a/QHotkey/qhotkey.cpp +++ b/QHotkey/qhotkey.cpp @@ -262,6 +262,13 @@ void QHotkeyPrivate::activateShortcut(QHotkey::NativeShortcut shortcut) signal.invoke(hkey, Qt::QueuedConnection); } +void QHotkeyPrivate::releaseShortcut(QHotkey::NativeShortcut shortcut) +{ + QMetaMethod signal = QMetaMethod::fromSignal(&QHotkey::released); + for(QHotkey *hkey : shortcuts.values(shortcut)) + signal.invoke(hkey, Qt::QueuedConnection); +} + void QHotkeyPrivate::addMappingInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers, const QHotkey::NativeShortcut &nativeShortcut) { mapping.insert({keycode, modifiers}, nativeShortcut); diff --git a/QHotkey/qhotkey.h b/QHotkey/qhotkey.h index 479dff5..a1b5ce9 100644 --- a/QHotkey/qhotkey.h +++ b/QHotkey/qhotkey.h @@ -100,6 +100,9 @@ public slots: //! Will be emitted if the shortcut is pressed void activated(QPrivateSignal); + //! Will be emitted if the shortcut press is released + void released(QPrivateSignal); + //! @notifyAcFn{QHotkey::registered} void registeredChanged(bool registered); diff --git a/QHotkey/qhotkey_mac.cpp b/QHotkey/qhotkey_mac.cpp index a410373..11e765e 100644 --- a/QHotkey/qhotkey_mac.cpp +++ b/QHotkey/qhotkey_mac.cpp @@ -9,7 +9,8 @@ class QHotkeyPrivateMac : public QHotkeyPrivate // QAbstractNativeEventFilter interface bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE; - static OSStatus hotkeyEventHandler(EventHandlerCallRef nextHandler, EventRef event, void* data); + static OSStatus hotkeyPressEventHandler(EventHandlerCallRef nextHandler, EventRef event, void* data); + static OSStatus hotkeyReleaseEventHandler(EventHandlerCallRef nextHandler, EventRef event, void* data); protected: // QHotkeyPrivate interface @@ -203,10 +204,15 @@ bool QHotkeyPrivateMac::registerShortcut(QHotkey::NativeShortcut shortcut) { if (!this->isHotkeyHandlerRegistered) { - EventTypeSpec eventSpec; - eventSpec.eventClass = kEventClassKeyboard; - eventSpec.eventKind = kEventHotKeyPressed; - InstallApplicationEventHandler(&QHotkeyPrivateMac::hotkeyEventHandler, 1, &eventSpec, NULL, NULL); + EventTypeSpec pressEventSpec; + pressEventSpec.eventClass = kEventClassKeyboard; + pressEventSpec.eventKind = kEventHotKeyPressed; + InstallApplicationEventHandler(&QHotkeyPrivateMac::hotkeyPressEventHandler, 1, &pressEventSpec, NULL, NULL); + + EventTypeSpec releaseEventSpec; + releaseEventSpec.eventClass = kEventClassKeyboard; + releaseEventSpec.eventKind = kEventHotKeyReleased; + InstallApplicationEventHandler(&QHotkeyPrivateMac::hotkeyReleaseEventHandler, 1, &releaseEventSpec, NULL, NULL); } EventHotKeyID hkeyID; @@ -244,7 +250,7 @@ bool QHotkeyPrivateMac::unregisterShortcut(QHotkey::NativeShortcut shortcut) } } -OSStatus QHotkeyPrivateMac::hotkeyEventHandler(EventHandlerCallRef nextHandler, EventRef event, void* data) +OSStatus QHotkeyPrivateMac::hotkeyPressEventHandler(EventHandlerCallRef nextHandler, EventRef event, void* data) { Q_UNUSED(nextHandler); Q_UNUSED(data); @@ -264,3 +270,24 @@ OSStatus QHotkeyPrivateMac::hotkeyEventHandler(EventHandlerCallRef nextHandler, return noErr; } + +OSStatus QHotkeyPrivateMac::hotkeyReleaseEventHandler(EventHandlerCallRef nextHandler, EventRef event, void* data) +{ + Q_UNUSED(nextHandler); + Q_UNUSED(data); + + if (GetEventClass(event) == kEventClassKeyboard && + GetEventKind(event) == kEventHotKeyReleased) { + EventHotKeyID hkeyID; + GetEventParameter(event, + kEventParamDirectObject, + typeEventHotKeyID, + NULL, + sizeof(EventHotKeyID), + NULL, + &hkeyID); + hotkeyPrivate->releaseShortcut({hkeyID.signature, hkeyID.id}); + } + + return noErr; +} \ No newline at end of file diff --git a/QHotkey/qhotkey_p.h b/QHotkey/qhotkey_p.h index 847f7db..8fce3ae 100644 --- a/QHotkey/qhotkey_p.h +++ b/QHotkey/qhotkey_p.h @@ -25,6 +25,7 @@ class QHOTKEY_SHARED_EXPORT QHotkeyPrivate : public QObject, public QAbstractNat protected: void activateShortcut(QHotkey::NativeShortcut shortcut); + void releaseShortcut(QHotkey::NativeShortcut shortcut); virtual quint32 nativeKeycode(Qt::Key keycode, bool &ok) = 0;//platform implement virtual quint32 nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) = 0;//platform implement diff --git a/QHotkey/qhotkey_win.cpp b/QHotkey/qhotkey_win.cpp index ead6763..4b7c2f1 100644 --- a/QHotkey/qhotkey_win.cpp +++ b/QHotkey/qhotkey_win.cpp @@ -2,16 +2,19 @@ #include "qhotkey_p.h" #include #include +#include #define HKEY_ID(nativeShortcut) (((nativeShortcut.key ^ (nativeShortcut.modifier << 8)) & 0x0FFF) | 0x7000) class QHotkeyPrivateWin : public QHotkeyPrivate { public: + QHotkeyPrivateWin(); // QAbstractNativeEventFilter interface bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE; protected: + void pollForHotkeyRelease(); // QHotkeyPrivate interface quint32 nativeKeycode(Qt::Key keycode, bool &ok) Q_DECL_OVERRIDE; quint32 nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) Q_DECL_OVERRIDE; @@ -20,6 +23,8 @@ class QHotkeyPrivateWin : public QHotkeyPrivate private: static QString formatWinError(DWORD winError); + QTimer pollTimer; + QHotkey::NativeShortcut polledShortcut; }; NATIVE_INSTANCE(QHotkeyPrivateWin) @@ -34,12 +39,25 @@ bool QHotkeyPrivateWin::nativeEventFilter(const QByteArray &eventType, void *mes Q_UNUSED(result) MSG* msg = static_cast(message); - if(msg->message == WM_HOTKEY) - this->activateShortcut({HIWORD(msg->lParam), LOWORD(msg->lParam)}); + if(msg->message == WM_HOTKEY) { + QHotkey::NativeShortcut shortcut = {HIWORD(msg->lParam), LOWORD(msg->lParam)}; + this->activateShortcut(shortcut); + this->polledShortcut = shortcut; + this->pollTimer.start(); + } return false; } +void QHotkeyPrivateWin::pollForHotkeyRelease() +{ + bool pressed = (GetAsyncKeyState(this->polledShortcut.key) & (1 << 15)) != 0; + if(!pressed) { + this->pollTimer.stop(); + this->releaseShortcut(this->polledShortcut); + } +} + quint32 QHotkeyPrivateWin::nativeKeycode(Qt::Key keycode, bool &ok) { ok = true; @@ -235,7 +253,7 @@ bool QHotkeyPrivateWin::registerShortcut(QHotkey::NativeShortcut shortcut) { BOOL ok = RegisterHotKey(NULL, HKEY_ID(shortcut), - shortcut.modifier, + shortcut.modifier + MOD_NOREPEAT, shortcut.key); if(ok) return true; diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index 43f8956..ab3d306 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -41,6 +42,9 @@ class QHotkeyPrivateX11 : public QHotkeyPrivate private: XErrorHandler prevHandler; + xcb_key_press_event_t prevHandledEvent; + xcb_key_press_event_t prevEvent; + QTimer *releaseTimer = nullptr; static int handleError(Display *display, XErrorEvent *error); }; @@ -62,8 +66,27 @@ bool QHotkeyPrivateX11::nativeEventFilter(const QByteArray &eventType, void *mes xcb_generic_event_t *genericEvent = static_cast(message); if (genericEvent->response_type == XCB_KEY_PRESS) { - xcb_key_press_event_t *keyEvent = static_cast(message); - this->activateShortcut({keyEvent->detail, keyEvent->state & QHotkeyPrivateX11::validModsMask}); + xcb_key_press_event_t keyEvent = *static_cast(message); + this->prevEvent = keyEvent; + if (this->prevHandledEvent.response_type == XCB_KEY_RELEASE) { + if(this->prevHandledEvent.time == keyEvent.time) return false; + } + this->activateShortcut({keyEvent.detail, keyEvent.state & QHotkeyPrivateX11::validModsMask}); + } else if (genericEvent->response_type == XCB_KEY_RELEASE) { + xcb_key_release_event_t keyEvent = *static_cast(message); + this->prevEvent = keyEvent; + QTimer *timer = new QTimer(this); + timer->setSingleShot(true); + timer->setInterval(50); + connect(timer, &QTimer::timeout, this, [this, keyEvent, timer] { + if(this->prevEvent.time == keyEvent.time && this->prevEvent.response_type == keyEvent.response_type && this->prevEvent.detail == keyEvent.detail){ + this->releaseShortcut({keyEvent.detail, keyEvent.state & QHotkeyPrivateX11::validModsMask}); + } + delete timer; + }); + timer->start(); + this->releaseTimer = timer; + this->prevHandledEvent = keyEvent; } return false; From d32957e52cf9b597675ee21207cb7a456b8ee879 Mon Sep 17 00:00:00 2001 From: Alexandre Vicente Date: Tue, 21 Apr 2020 15:48:50 -0300 Subject: [PATCH 35/71] X11 header fix --- QHotkey/qhotkey_x11.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index ab3d306..9cb01eb 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -29,7 +29,10 @@ class QHotkeyPrivateX11 : public QHotkeyPrivate private: static const QVector specialModifiers; static const quint32 validModsMask; - + XErrorHandler prevHandler; + xcb_key_press_event_t prevHandledEvent; + xcb_key_press_event_t prevEvent; + static QString formatX11Error(Display *display, int errorCode); class HotkeyErrorHandler { @@ -41,9 +44,6 @@ class QHotkeyPrivateX11 : public QHotkeyPrivate static QString errorString; private: - XErrorHandler prevHandler; - xcb_key_press_event_t prevHandledEvent; - xcb_key_press_event_t prevEvent; QTimer *releaseTimer = nullptr; static int handleError(Display *display, XErrorEvent *error); From 12e05bfd4e09556a900953a66c4e4196d20b23ff Mon Sep 17 00:00:00 2001 From: Alexandre Vicente Date: Tue, 21 Apr 2020 22:02:52 -0300 Subject: [PATCH 36/71] Fix missing poll connect on Windows --- QHotkey/qhotkey_win.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/QHotkey/qhotkey_win.cpp b/QHotkey/qhotkey_win.cpp index 4b7c2f1..19712db 100644 --- a/QHotkey/qhotkey_win.cpp +++ b/QHotkey/qhotkey_win.cpp @@ -28,6 +28,11 @@ class QHotkeyPrivateWin : public QHotkeyPrivate }; NATIVE_INSTANCE(QHotkeyPrivateWin) +QHotkeyPrivateWin::QHotkeyPrivateWin(){ + pollTimer.setInterval(50); + connect(&pollTimer, &QTimer::timeout, this, &QHotkeyPrivateWin::pollForHotkeyRelease); +} + bool QHotkeyPrivate::isPlatformSupported() { return true; From e113ace9a16bd9f6b189db91b52234ba6ae8402f Mon Sep 17 00:00:00 2001 From: Alexandre Vicente Date: Tue, 21 Apr 2020 22:10:49 -0300 Subject: [PATCH 37/71] Indentation fix --- QHotkey/qhotkey.cpp | 6 +++--- QHotkey/qhotkey.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/QHotkey/qhotkey.cpp b/QHotkey/qhotkey.cpp index 853b68d..ccff07f 100644 --- a/QHotkey/qhotkey.cpp +++ b/QHotkey/qhotkey.cpp @@ -264,9 +264,9 @@ void QHotkeyPrivate::activateShortcut(QHotkey::NativeShortcut shortcut) void QHotkeyPrivate::releaseShortcut(QHotkey::NativeShortcut shortcut) { - QMetaMethod signal = QMetaMethod::fromSignal(&QHotkey::released); - for(QHotkey *hkey : shortcuts.values(shortcut)) - signal.invoke(hkey, Qt::QueuedConnection); + QMetaMethod signal = QMetaMethod::fromSignal(&QHotkey::released); + for(QHotkey *hkey : shortcuts.values(shortcut)) + signal.invoke(hkey, Qt::QueuedConnection); } void QHotkeyPrivate::addMappingInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers, const QHotkey::NativeShortcut &nativeShortcut) diff --git a/QHotkey/qhotkey.h b/QHotkey/qhotkey.h index a1b5ce9..c8270d4 100644 --- a/QHotkey/qhotkey.h +++ b/QHotkey/qhotkey.h @@ -100,8 +100,8 @@ public slots: //! Will be emitted if the shortcut is pressed void activated(QPrivateSignal); - //! Will be emitted if the shortcut press is released - void released(QPrivateSignal); + //! Will be emitted if the shortcut press is released + void released(QPrivateSignal); //! @notifyAcFn{QHotkey::registered} void registeredChanged(bool registered); From 7028920db574e078b9cd4f278b47b1c3ae8c0c4d Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Sat, 2 May 2020 21:05:04 +0200 Subject: [PATCH 38/71] fix #33 --- QHotkey/qhotkey_x11.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index 9cb01eb..5606177 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -29,10 +29,10 @@ class QHotkeyPrivateX11 : public QHotkeyPrivate private: static const QVector specialModifiers; static const quint32 validModsMask; - XErrorHandler prevHandler; + QTimer *releaseTimer = nullptr; xcb_key_press_event_t prevHandledEvent; xcb_key_press_event_t prevEvent; - + static QString formatX11Error(Display *display, int errorCode); class HotkeyErrorHandler { @@ -44,7 +44,7 @@ class QHotkeyPrivateX11 : public QHotkeyPrivate static QString errorString; private: - QTimer *releaseTimer = nullptr; + XErrorHandler prevHandler; static int handleError(Display *display, XErrorEvent *error); }; @@ -96,18 +96,18 @@ QString QHotkeyPrivateX11::getX11String(Qt::Key keycode) { switch(keycode){ - case Qt::Key_MediaLast : - case Qt::Key_MediaPrevious : + case Qt::Key_MediaLast : + case Qt::Key_MediaPrevious : return "XF86AudioPrev"; - case Qt::Key_MediaNext : + case Qt::Key_MediaNext : return "XF86AudioNext"; - case Qt::Key_MediaPause : - case Qt::Key_MediaPlay : + case Qt::Key_MediaPause : + case Qt::Key_MediaPlay : case Qt::Key_MediaTogglePlayPause : return "XF86AudioPlay"; case Qt::Key_MediaRecord : - return "XF86AudioRecord"; - case Qt::Key_MediaStop : + return "XF86AudioRecord"; + case Qt::Key_MediaStop : return "XF86AudioStop"; default : return QKeySequence(keycode).toString(QKeySequence::NativeText); From 83a0066760140e676fc12278be6f1aedde3a5987 Mon Sep 17 00:00:00 2001 From: Sven Kipry Date: Tue, 5 May 2020 07:53:57 +0200 Subject: [PATCH 39/71] fix include path in CMakeLists.txt The include path is not set correctly when QHotkey is build as a subproject. To fix that CMAKE_CURRENT_SOURCE_DIR should be used instead of CMAKE_SOURCE_DIR in target_include_directories. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 41f2037..30c40ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,7 +42,7 @@ target_link_libraries(qhotkey ${LIBS}) target_include_directories(qhotkey PUBLIC - $ + $ $) set_target_properties(qhotkey PROPERTIES From 0352904ec175216e7fdc4138f6aa3bcd7f0250b1 Mon Sep 17 00:00:00 2001 From: Patrizio Bekerle Date: Sat, 23 May 2020 07:46:08 +0200 Subject: [PATCH 40/71] Fix not declared MOD_NOREPEAT (Skycoder42/QHotkey/#36) (#37) Fix not declared MOD_NOREPEAT (#36) --- QHotkey/qhotkey_win.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/QHotkey/qhotkey_win.cpp b/QHotkey/qhotkey_win.cpp index 19712db..244ed51 100644 --- a/QHotkey/qhotkey_win.cpp +++ b/QHotkey/qhotkey_win.cpp @@ -6,6 +6,10 @@ #define HKEY_ID(nativeShortcut) (((nativeShortcut.key ^ (nativeShortcut.modifier << 8)) & 0x0FFF) | 0x7000) +#if !defined(MOD_NOREPEAT) +#define MOD_NOREPEAT 0x4000 +#endif + class QHotkeyPrivateWin : public QHotkeyPrivate { public: From 055d242ded352f5f67ff11bdbd995d5eaa845424 Mon Sep 17 00:00:00 2001 From: Shatur95 Date: Sat, 6 Jun 2020 22:42:09 +0300 Subject: [PATCH 41/71] Improve CMake rules * Disable building examples by default. * Use CMAKE_CURRENT_SOURCE_DIR instead of CMAKE_SOURCE_DIR. * Add an option to disable install rules. --- CMakeLists.txt | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 30c40ee..8b3d190 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.1) project(qhotkey VERSION 1.2.2 LANGUAGES CXX) -option(QHOTKEY_EXAMPLES "Build examples" ON) +option(QHOTKEY_EXAMPLES "Build examples" OFF) +option(QHOTKEY_INSTALL "Enable install rule" ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -53,18 +54,20 @@ if(QHOTKEY_EXAMPLES) add_subdirectory(HotkeyTest) endif() -include(GNUInstallDirs) -set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/QHotkey) - -install( - TARGETS qhotkey EXPORT QHotkeyConfig - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) -install(FILES - ${CMAKE_SOURCE_DIR}/QHotkey/qhotkey.h - ${CMAKE_SOURCE_DIR}/QHotkey/QHotkey - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/) -install(EXPORT QHotkeyConfig DESTINATION ${INSTALL_CONFIGDIR}) - -export(TARGETS qhotkey FILE QHotkeyConfig.cmake) +if(QHOTKEY_INSTALL) + include(GNUInstallDirs) + set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/QHotkey) + + install( + TARGETS qhotkey EXPORT QHotkeyConfig + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/QHotkey/qhotkey.h + ${CMAKE_CURRENT_SOURCE_DIR}/QHotkey/QHotkey + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/) + install(EXPORT QHotkeyConfig DESTINATION ${INSTALL_CONFIGDIR}) + + export(TARGETS qhotkey FILE QHotkeyConfig.cmake) +endif() From 483e07365ee943b19f8078a4951090b6a9b87a65 Mon Sep 17 00:00:00 2001 From: Shatur95 Date: Wed, 1 Jul 2020 23:16:13 +0300 Subject: [PATCH 42/71] Improve error messages * Show information about shortcut. * Make errors translatable. --- QHotkey/qhotkey.cpp | 14 ++++++++++---- QHotkey/qhotkey_mac.cpp | 6 ++---- QHotkey/qhotkey_p.h | 2 ++ QHotkey/qhotkey_win.cpp | 6 ++---- QHotkey/qhotkey_x11.cpp | 6 ++---- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/QHotkey/qhotkey.cpp b/QHotkey/qhotkey.cpp index ccff07f..7b6a399 100644 --- a/QHotkey/qhotkey.cpp +++ b/QHotkey/qhotkey.cpp @@ -279,8 +279,10 @@ bool QHotkeyPrivate::addShortcutInvoked(QHotkey *hotkey) QHotkey::NativeShortcut shortcut = hotkey->_nativeShortcut; if(!shortcuts.contains(shortcut)) { - if(!registerShortcut(shortcut)) + if(!registerShortcut(shortcut)) { + qCWarning(logQHotkey) << QHotkey::tr("Failed to register %1. Error: %2").arg(hotkey->shortcut().toString(), error); return false; + } } shortcuts.insert(shortcut, hotkey); @@ -296,9 +298,13 @@ bool QHotkeyPrivate::removeShortcutInvoked(QHotkey *hotkey) return false; hotkey->_registered = false; emit hotkey->registeredChanged(true); - if(shortcuts.count(shortcut) == 0) - return unregisterShortcut(shortcut); - else + if(shortcuts.count(shortcut) == 0) { + if (!unregisterShortcut(shortcut)) { + qCWarning(logQHotkey) << QHotkey::tr("Failed to unregister %1. Error: %2").arg(hotkey->shortcut().toString(), error); + return false; + } else + return true; + } else return true; } diff --git a/QHotkey/qhotkey_mac.cpp b/QHotkey/qhotkey_mac.cpp index 11e765e..0e06299 100644 --- a/QHotkey/qhotkey_mac.cpp +++ b/QHotkey/qhotkey_mac.cpp @@ -227,8 +227,7 @@ bool QHotkeyPrivateMac::registerShortcut(QHotkey::NativeShortcut shortcut) 0, &eventRef); if (status != noErr) { - qCWarning(logQHotkey) << "Failed to register hotkey. Error:" - << status; + error = QString::number(status); return false; } else { this->hotkeyRefs.insert(shortcut, eventRef); @@ -241,8 +240,7 @@ bool QHotkeyPrivateMac::unregisterShortcut(QHotkey::NativeShortcut shortcut) EventHotKeyRef eventRef = QHotkeyPrivateMac::hotkeyRefs.value(shortcut); OSStatus status = UnregisterEventHotKey(eventRef); if (status != noErr) { - qCWarning(logQHotkey) << "Failed to unregister hotkey. Error:" - << status; + error = QString::number(status); return false; } else { this->hotkeyRefs.remove(shortcut); diff --git a/QHotkey/qhotkey_p.h b/QHotkey/qhotkey_p.h index 8fce3ae..eec3bd6 100644 --- a/QHotkey/qhotkey_p.h +++ b/QHotkey/qhotkey_p.h @@ -33,6 +33,8 @@ class QHOTKEY_SHARED_EXPORT QHotkeyPrivate : public QObject, public QAbstractNat virtual bool registerShortcut(QHotkey::NativeShortcut shortcut) = 0;//platform implement virtual bool unregisterShortcut(QHotkey::NativeShortcut shortcut) = 0;//platform implement + QString error; + private: QHash, QHotkey::NativeShortcut> mapping; QMultiHash shortcuts; diff --git a/QHotkey/qhotkey_win.cpp b/QHotkey/qhotkey_win.cpp index 244ed51..22c64a8 100644 --- a/QHotkey/qhotkey_win.cpp +++ b/QHotkey/qhotkey_win.cpp @@ -267,8 +267,7 @@ bool QHotkeyPrivateWin::registerShortcut(QHotkey::NativeShortcut shortcut) if(ok) return true; else { - qCWarning(logQHotkey) << "Failed to register hotkey. Error:" - << qPrintable(QHotkeyPrivateWin::formatWinError(::GetLastError())); + error = QHotkeyPrivateWin::formatWinError(::GetLastError()); return false; } } @@ -279,8 +278,7 @@ bool QHotkeyPrivateWin::unregisterShortcut(QHotkey::NativeShortcut shortcut) if(ok) return true; else { - qCWarning(logQHotkey) << "Failed to unregister hotkey. Error:" - << qPrintable(QHotkeyPrivateWin::formatWinError(::GetLastError())); + error = QHotkeyPrivateWin::formatWinError(::GetLastError()); return false; } } diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index 5606177..1c99939 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -170,8 +170,7 @@ bool QHotkeyPrivateX11::registerShortcut(QHotkey::NativeShortcut shortcut) XSync(display, False); if(errorHandler.hasError) { - qCWarning(logQHotkey) << "Failed to register hotkey. Error:" - << qPrintable(errorHandler.errorString); + error = errorHandler.errorString; this->unregisterShortcut(shortcut); return false; } else @@ -194,8 +193,7 @@ bool QHotkeyPrivateX11::unregisterShortcut(QHotkey::NativeShortcut shortcut) XSync(display, False); if(errorHandler.hasError) { - qCWarning(logQHotkey) << "Failed to unregister hotkey. Error:" - << qPrintable(errorHandler.errorString); + error = errorHandler.errorString; return false; } else return true; From 941cb2f15fb68e613dcf65d8977c487f7d332f56 Mon Sep 17 00:00:00 2001 From: Oleg Antonyan Date: Tue, 18 Aug 2020 20:43:44 +0200 Subject: [PATCH 43/71] fix SIGSEGV on wayland --- QHotkey/qhotkey_x11.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index 1c99939..fdd3ab2 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -154,7 +154,7 @@ quint32 QHotkeyPrivateX11::nativeModifiers(Qt::KeyboardModifiers modifiers, bool bool QHotkeyPrivateX11::registerShortcut(QHotkey::NativeShortcut shortcut) { Display *display = QX11Info::display(); - if(!display) + if(!display || !QX11Info::isPlatformX11()) return false; HotkeyErrorHandler errorHandler; From b73b4955ae22d7ebb7acd2e4b70ab31a708c23fa Mon Sep 17 00:00:00 2001 From: Shatur95 Date: Thu, 15 Oct 2020 01:31:52 +0300 Subject: [PATCH 44/71] Fix implicit conversion warning --- QHotkey/qhotkey_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QHotkey/qhotkey_win.cpp b/QHotkey/qhotkey_win.cpp index 22c64a8..a03b8c0 100644 --- a/QHotkey/qhotkey_win.cpp +++ b/QHotkey/qhotkey_win.cpp @@ -71,7 +71,7 @@ quint32 QHotkeyPrivateWin::nativeKeycode(Qt::Key keycode, bool &ok) { ok = true; if(keycode <= 0xFFFF) {//Try to obtain the key from it's "character" - const SHORT vKey = VkKeyScanW(keycode); + const SHORT vKey = VkKeyScanW(static_cast(keycode)); if(vKey > -1) return LOBYTE(vKey); } From f0799fd4a47d86112b2b81b874d5f4b79dd8ef8b Mon Sep 17 00:00:00 2001 From: Shatur95 Date: Thu, 15 Oct 2020 21:50:58 +0300 Subject: [PATCH 45/71] Fix Clang Tidy warnings readability-convert-member-functions-to-static modernize-use-auto readability-else-after-return readability-static-accessed-through-instance readability-inconsistent-declaration-parameter-name --- QHotkey/qhotkey.cpp | 84 +++++++++++++++++++---------------------- QHotkey/qhotkey_x11.cpp | 24 ++++++------ 2 files changed, 51 insertions(+), 57 deletions(-) diff --git a/QHotkey/qhotkey.cpp b/QHotkey/qhotkey.cpp index 7b6a399..ea3957e 100644 --- a/QHotkey/qhotkey.cpp +++ b/QHotkey/qhotkey.cpp @@ -25,14 +25,13 @@ QHotkey::QHotkey(QObject *parent) : QObject(parent), _keyCode(Qt::Key_unknown), _modifiers(Qt::NoModifier), - _nativeShortcut(), _registered(false) {} -QHotkey::QHotkey(const QKeySequence &sequence, bool autoRegister, QObject *parent) : +QHotkey::QHotkey(const QKeySequence &shortcut, bool autoRegister, QObject *parent) : QHotkey(parent) { - setShortcut(sequence, autoRegister); + setShortcut(shortcut, autoRegister); } QHotkey::QHotkey(Qt::Key keyCode, Qt::KeyboardModifiers modifiers, bool autoRegister, QObject *parent) : @@ -57,8 +56,7 @@ QKeySequence QHotkey::shortcut() const { if(_keyCode == Qt::Key_unknown) return QKeySequence(); - else - return QKeySequence(_keyCode | _modifiers); + return QKeySequence(static_cast(_keyCode | _modifiers)); } Qt::Key QHotkey::keyCode() const @@ -83,9 +81,9 @@ bool QHotkey::isRegistered() const bool QHotkey::setShortcut(const QKeySequence &shortcut, bool autoRegister) { - if(shortcut.isEmpty()) { + if(shortcut.isEmpty()) return resetShortcut(); - } else if(shortcut.count() > 1) { + if(shortcut.count() > 1) { qCWarning(logQHotkey, "Keysequences with multiple shortcuts are not allowed! " "Only the first shortcut will be used!"); } @@ -118,15 +116,14 @@ bool QHotkey::setShortcut(Qt::Key keyCode, Qt::KeyboardModifiers modifiers, bool if(_nativeShortcut.isValid()) { if(autoRegister) return QHotkeyPrivate::instance()->addShortcut(this); - else - return true; - } else { - qCWarning(logQHotkey) << "Unable to map shortcut to native keys. Key:" << keyCode << "Modifiers:" << modifiers; - _keyCode = Qt::Key_unknown; - _modifiers = Qt::NoModifier; - _nativeShortcut = NativeShortcut(); - return false; + return true; } + + qCWarning(logQHotkey) << "Unable to map shortcut to native keys. Key:" << keyCode << "Modifiers:" << modifiers; + _keyCode = Qt::Key_unknown; + _modifiers = Qt::NoModifier; + _nativeShortcut = NativeShortcut(); + return false; } bool QHotkey::resetShortcut() @@ -158,35 +155,32 @@ bool QHotkey::setNativeShortcut(QHotkey::NativeShortcut nativeShortcut, bool aut _nativeShortcut = nativeShortcut; if(autoRegister) return QHotkeyPrivate::instance()->addShortcut(this); - else - return true; - } else { - _keyCode = Qt::Key_unknown; - _modifiers = Qt::NoModifier; - _nativeShortcut = NativeShortcut(); return true; - } + } + + _keyCode = Qt::Key_unknown; + _modifiers = Qt::NoModifier; + _nativeShortcut = NativeShortcut(); + return true; } bool QHotkey::setRegistered(bool registered) { if(_registered && !registered) return QHotkeyPrivate::instance()->removeShortcut(this); - else if(!_registered && registered) { + if(!_registered && registered) { if(!_nativeShortcut.isValid()) return false; - else - return QHotkeyPrivate::instance()->addShortcut(this); - } else - return true; + return QHotkeyPrivate::instance()->addShortcut(this); + } + return true; } // ---------- QHotkeyPrivate implementation ---------- -QHotkeyPrivate::QHotkeyPrivate() : - shortcuts() +QHotkeyPrivate::QHotkeyPrivate() { Q_ASSERT_X(qApp, Q_FUNC_INFO, "QHotkey requires QCoreApplication to be instantiated"); qApp->eventDispatcher()->installNativeEventFilter(this); @@ -211,8 +205,8 @@ QHotkey::NativeShortcut QHotkeyPrivate::nativeShortcut(Qt::Key keycode, Qt::Keyb Q_ARG(Qt::Key, keycode), Q_ARG(Qt::KeyboardModifiers, modifiers))) { return QHotkey::NativeShortcut(); - } else - return res; + } + return res; } bool QHotkeyPrivate::addShortcut(QHotkey *hotkey) @@ -228,11 +222,11 @@ bool QHotkeyPrivate::addShortcut(QHotkey *hotkey) Q_RETURN_ARG(bool, res), Q_ARG(QHotkey*, hotkey))) { return false; - } else { - if(res) - emit hotkey->registeredChanged(true); - return res; } + + if(res) + emit hotkey->registeredChanged(true); + return res; } bool QHotkeyPrivate::removeShortcut(QHotkey *hotkey) @@ -248,11 +242,11 @@ bool QHotkeyPrivate::removeShortcut(QHotkey *hotkey) Q_RETURN_ARG(bool, res), Q_ARG(QHotkey*, hotkey))) { return false; - } else { - if(res) - emit hotkey->registeredChanged(false); - return res; } + + if(res) + emit hotkey->registeredChanged(false); + return res; } void QHotkeyPrivate::activateShortcut(QHotkey::NativeShortcut shortcut) @@ -302,10 +296,10 @@ bool QHotkeyPrivate::removeShortcutInvoked(QHotkey *hotkey) if (!unregisterShortcut(shortcut)) { qCWarning(logQHotkey) << QHotkey::tr("Failed to unregister %1. Error: %2").arg(hotkey->shortcut().toString(), error); return false; - } else - return true; - } else + } return true; + } + return true; } QHotkey::NativeShortcut QHotkeyPrivate::nativeShortcutInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers) @@ -313,13 +307,13 @@ QHotkey::NativeShortcut QHotkeyPrivate::nativeShortcutInvoked(Qt::Key keycode, Q if(mapping.contains({keycode, modifiers})) return mapping.value({keycode, modifiers}); - bool ok1, ok2 = false; + bool ok1 = false; auto k = nativeKeycode(keycode, ok1); + bool ok2 = false; auto m = nativeModifiers(modifiers, ok2); if(ok1 && ok2) return {k, m}; - else - return {}; + return {}; } diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index fdd3ab2..b08bde2 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -22,7 +22,7 @@ class QHotkeyPrivateX11 : public QHotkeyPrivate // QHotkeyPrivate interface quint32 nativeKeycode(Qt::Key keycode, bool &ok) Q_DECL_OVERRIDE; quint32 nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) Q_DECL_OVERRIDE; - QString getX11String(Qt::Key keycode); + static QString getX11String(Qt::Key keycode); bool registerShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE; bool unregisterShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE; @@ -64,7 +64,7 @@ bool QHotkeyPrivateX11::nativeEventFilter(const QByteArray &eventType, void *mes Q_UNUSED(eventType) Q_UNUSED(result) - xcb_generic_event_t *genericEvent = static_cast(message); + auto *genericEvent = static_cast(message); if (genericEvent->response_type == XCB_KEY_PRESS) { xcb_key_press_event_t keyEvent = *static_cast(message); this->prevEvent = keyEvent; @@ -75,7 +75,7 @@ bool QHotkeyPrivateX11::nativeEventFilter(const QByteArray &eventType, void *mes } else if (genericEvent->response_type == XCB_KEY_RELEASE) { xcb_key_release_event_t keyEvent = *static_cast(message); this->prevEvent = keyEvent; - QTimer *timer = new QTimer(this); + auto *timer = new QTimer(this); timer->setSingleShot(true); timer->setInterval(50); connect(timer, &QTimer::timeout, this, [this, keyEvent, timer] { @@ -132,8 +132,8 @@ quint32 QHotkeyPrivateX11::nativeKeycode(Qt::Key keycode, bool &ok) if(res != 0) ok = true; return res; - } else - return 0; + } + return 0; } quint32 QHotkeyPrivateX11::nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) @@ -173,8 +173,8 @@ bool QHotkeyPrivateX11::registerShortcut(QHotkey::NativeShortcut shortcut) error = errorHandler.errorString; this->unregisterShortcut(shortcut); return false; - } else - return true; + } + return true; } bool QHotkeyPrivateX11::unregisterShortcut(QHotkey::NativeShortcut shortcut) @@ -188,15 +188,15 @@ bool QHotkeyPrivateX11::unregisterShortcut(QHotkey::NativeShortcut shortcut) XUngrabKey(display, shortcut.key, shortcut.modifier | specialMod, - DefaultRootWindow(display)); + XDefaultRootWindow(display)); } XSync(display, False); - if(errorHandler.hasError) { - error = errorHandler.errorString; + if(HotkeyErrorHandler::hasError) { + error = HotkeyErrorHandler::errorString; return false; - } else - return true; + } + return true; } QString QHotkeyPrivateX11::formatX11Error(Display *display, int errorCode) From 2a87965ed645f2657b3380a482d8e786747048ad Mon Sep 17 00:00:00 2001 From: Shatur95 Date: Thu, 15 Oct 2020 22:12:11 +0300 Subject: [PATCH 46/71] Add mising override --- QHotkey/qhotkey.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QHotkey/qhotkey.h b/QHotkey/qhotkey.h index c8270d4..3fc988e 100644 --- a/QHotkey/qhotkey.h +++ b/QHotkey/qhotkey.h @@ -68,7 +68,7 @@ class QHOTKEY_SHARED_EXPORT QHotkey : public QObject explicit QHotkey(Qt::Key keyCode, Qt::KeyboardModifiers modifiers, bool autoRegister = false, QObject *parent = nullptr); //! Constructs a hotkey from a native shortcut and optionally registers it explicit QHotkey(const NativeShortcut &shortcut, bool autoRegister = false, QObject *parent = nullptr); - ~QHotkey(); + ~QHotkey() override; //! @readAcFn{QHotkey::registered} bool isRegistered() const; From 4bb901a41e4044eb97fc0f982c8abf4f9422a406 Mon Sep 17 00:00:00 2001 From: Shatur95 Date: Sat, 17 Oct 2020 01:07:57 +0300 Subject: [PATCH 47/71] Pass NativeShortcut by value (trivially copyable) --- QHotkey/qhotkey.cpp | 14 +++++++------- QHotkey/qhotkey.h | 14 +++++++------- QHotkey/qhotkey_p.h | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/QHotkey/qhotkey.cpp b/QHotkey/qhotkey.cpp index ea3957e..ae6da22 100644 --- a/QHotkey/qhotkey.cpp +++ b/QHotkey/qhotkey.cpp @@ -8,7 +8,7 @@ Q_LOGGING_CATEGORY(logQHotkey, "QHotkey") -void QHotkey::addGlobalMapping(const QKeySequence &shortcut, const QHotkey::NativeShortcut &nativeShortcut) +void QHotkey::addGlobalMapping(const QKeySequence &shortcut, QHotkey::NativeShortcut nativeShortcut) { QMetaObject::invokeMethod(QHotkeyPrivate::instance(), "addMappingInvoked", Qt::QueuedConnection, Q_ARG(Qt::Key, Qt::Key(shortcut[0] & ~Qt::KeyboardModifierMask)), @@ -40,7 +40,7 @@ QHotkey::QHotkey(Qt::Key keyCode, Qt::KeyboardModifiers modifiers, bool autoRegi setShortcut(keyCode, modifiers, autoRegister); } -QHotkey::QHotkey(const QHotkey::NativeShortcut &shortcut, bool autoRegister, QObject *parent) : +QHotkey::QHotkey(QHotkey::NativeShortcut shortcut, bool autoRegister, QObject *parent) : QHotkey(parent) { setNativeShortcut(shortcut, autoRegister); @@ -263,7 +263,7 @@ void QHotkeyPrivate::releaseShortcut(QHotkey::NativeShortcut shortcut) signal.invoke(hkey, Qt::QueuedConnection); } -void QHotkeyPrivate::addMappingInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers, const QHotkey::NativeShortcut &nativeShortcut) +void QHotkeyPrivate::addMappingInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers, QHotkey::NativeShortcut nativeShortcut) { mapping.insert({keycode, modifiers}, nativeShortcut); } @@ -335,26 +335,26 @@ bool QHotkey::NativeShortcut::isValid() const return valid; } -bool QHotkey::NativeShortcut::operator ==(const QHotkey::NativeShortcut &other) const +bool QHotkey::NativeShortcut::operator ==(QHotkey::NativeShortcut other) const { return (key == other.key) && (modifier == other.modifier) && valid == other.valid; } -bool QHotkey::NativeShortcut::operator !=(const QHotkey::NativeShortcut &other) const +bool QHotkey::NativeShortcut::operator !=(QHotkey::NativeShortcut other) const { return (key != other.key) || (modifier != other.modifier) || valid != other.valid; } -uint qHash(const QHotkey::NativeShortcut &key) +uint qHash(QHotkey::NativeShortcut key) { return qHash(key.key) ^ qHash(key.modifier); } -uint qHash(const QHotkey::NativeShortcut &key, uint seed) +uint qHash(QHotkey::NativeShortcut key, uint seed) { return qHash(key.key, seed) ^ qHash(key.modifier, seed); } diff --git a/QHotkey/qhotkey.h b/QHotkey/qhotkey.h index 3fc988e..f669640 100644 --- a/QHotkey/qhotkey.h +++ b/QHotkey/qhotkey.h @@ -46,16 +46,16 @@ class QHOTKEY_SHARED_EXPORT QHotkey : public QObject bool isValid() const; //! Equality operator - bool operator ==(const NativeShortcut &other) const; + bool operator ==(NativeShortcut other) const; //! Inequality operator - bool operator !=(const NativeShortcut &other) const; + bool operator !=(NativeShortcut other) const; private: bool valid; }; //! Adds a global mapping of a key sequence to a replacement native shortcut - static void addGlobalMapping(const QKeySequence &shortcut, const NativeShortcut &nativeShortcut); + static void addGlobalMapping(const QKeySequence &shortcut, NativeShortcut nativeShortcut); //! Checks if global shortcuts are supported by the current platform static bool isPlatformSupported(); @@ -67,7 +67,7 @@ class QHOTKEY_SHARED_EXPORT QHotkey : public QObject //! Constructs a hotkey with a key and modifiers and optionally registers it explicit QHotkey(Qt::Key keyCode, Qt::KeyboardModifiers modifiers, bool autoRegister = false, QObject *parent = nullptr); //! Constructs a hotkey from a native shortcut and optionally registers it - explicit QHotkey(const NativeShortcut &shortcut, bool autoRegister = false, QObject *parent = nullptr); + explicit QHotkey(NativeShortcut shortcut, bool autoRegister = false, QObject *parent = nullptr); ~QHotkey() override; //! @readAcFn{QHotkey::registered} @@ -94,7 +94,7 @@ public slots: bool resetShortcut(); //! Set this hotkey to a native shortcut - bool setNativeShortcut(NativeShortcut nativeShortcut, bool autoRegister = false); + bool setNativeShortcut(QHotkey::NativeShortcut nativeShortcut, bool autoRegister = false); signals: //! Will be emitted if the shortcut is pressed @@ -114,8 +114,8 @@ public slots: bool _registered; }; -uint QHOTKEY_SHARED_EXPORT qHash(const QHotkey::NativeShortcut &key); -uint QHOTKEY_SHARED_EXPORT qHash(const QHotkey::NativeShortcut &key, uint seed); +uint QHOTKEY_SHARED_EXPORT qHash(QHotkey::NativeShortcut key); +uint QHOTKEY_SHARED_EXPORT qHash(QHotkey::NativeShortcut key, uint seed); QHOTKEY_SHARED_EXPORT Q_DECLARE_LOGGING_CATEGORY(logQHotkey) diff --git a/QHotkey/qhotkey_p.h b/QHotkey/qhotkey_p.h index eec3bd6..b7c1721 100644 --- a/QHotkey/qhotkey_p.h +++ b/QHotkey/qhotkey_p.h @@ -39,7 +39,7 @@ class QHOTKEY_SHARED_EXPORT QHotkeyPrivate : public QObject, public QAbstractNat QHash, QHotkey::NativeShortcut> mapping; QMultiHash shortcuts; - Q_INVOKABLE void addMappingInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers, const QHotkey::NativeShortcut &nativeShortcut); + Q_INVOKABLE void addMappingInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers, QHotkey::NativeShortcut nativeShortcut); Q_INVOKABLE bool addShortcutInvoked(QHotkey *hotkey); Q_INVOKABLE bool removeShortcutInvoked(QHotkey *hotkey); Q_INVOKABLE QHotkey::NativeShortcut nativeShortcutInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers); From 384f780b28a083f7abf045906cfffc5d58935121 Mon Sep 17 00:00:00 2001 From: Shatur95 Date: Sat, 17 Oct 2020 01:08:08 +0300 Subject: [PATCH 48/71] Use QStringLiteral --- QHotkey/qhotkey_x11.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index b08bde2..5310a07 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -98,17 +98,17 @@ QString QHotkeyPrivateX11::getX11String(Qt::Key keycode) case Qt::Key_MediaLast : case Qt::Key_MediaPrevious : - return "XF86AudioPrev"; + return QStringLiteral("XF86AudioPrev"); case Qt::Key_MediaNext : - return "XF86AudioNext"; + return QStringLiteral("XF86AudioNext"); case Qt::Key_MediaPause : case Qt::Key_MediaPlay : case Qt::Key_MediaTogglePlayPause : - return "XF86AudioPlay"; + return QStringLiteral("XF86AudioPlay"); case Qt::Key_MediaRecord : - return "XF86AudioRecord"; + return QStringLiteral("XF86AudioRecord"); case Qt::Key_MediaStop : - return "XF86AudioStop"; + return QStringLiteral("XF86AudioStop"); default : return QKeySequence(keycode).toString(QKeySequence::NativeText); } From 8584ff1b1589ffd2c567486e2f3f6219d5e8e4e8 Mon Sep 17 00:00:00 2001 From: Shatur95 Date: Tue, 20 Oct 2020 13:33:22 +0300 Subject: [PATCH 49/71] Use QTimer::singleShort https://doc.qt.io/qt-5/qtimer.html#singleShot-4 --- QHotkey/qhotkey_x11.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index 5310a07..e3f8519 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -29,7 +29,6 @@ class QHotkeyPrivateX11 : public QHotkeyPrivate private: static const QVector specialModifiers; static const quint32 validModsMask; - QTimer *releaseTimer = nullptr; xcb_key_press_event_t prevHandledEvent; xcb_key_press_event_t prevEvent; @@ -75,17 +74,11 @@ bool QHotkeyPrivateX11::nativeEventFilter(const QByteArray &eventType, void *mes } else if (genericEvent->response_type == XCB_KEY_RELEASE) { xcb_key_release_event_t keyEvent = *static_cast(message); this->prevEvent = keyEvent; - auto *timer = new QTimer(this); - timer->setSingleShot(true); - timer->setInterval(50); - connect(timer, &QTimer::timeout, this, [this, keyEvent, timer] { + QTimer::singleShot(50, [this, keyEvent] { if(this->prevEvent.time == keyEvent.time && this->prevEvent.response_type == keyEvent.response_type && this->prevEvent.detail == keyEvent.detail){ this->releaseShortcut({keyEvent.detail, keyEvent.state & QHotkeyPrivateX11::validModsMask}); } - delete timer; }); - timer->start(); - this->releaseTimer = timer; this->prevHandledEvent = keyEvent; } From 25f21849b3335f437ec6ee2cc74f043d174aaebb Mon Sep 17 00:00:00 2001 From: Daniel Bermond Date: Thu, 30 Sep 2021 14:46:35 -0300 Subject: [PATCH 50/71] Add support for Qt6 (#51) CMake: The 'QT_MAJOR' CMake variable controls which major version of Qt is used for building. Defaults to '5', so nothing changes when using the default 'cmake' invocation, as it will default to search/build for Qt5. qmake: Just build in the usual way with 'qmake6 && make' or 'qmake-qt5 && make'. When building with Qt6 on GNU/Linux and similar UNIXes, the minimium required Qt version is 6.2.0, as Qt 6.1 and 6.0 lacks support for getting the X11 display. --- CMakeLists.txt | 32 +++++++++++++++++++------- HotkeyTest/CMakeLists.txt | 11 ++++++--- QHotkey/qhotkey.cpp | 27 ++++++++++++++++++---- QHotkey/qhotkey.h | 8 ++++++- QHotkey/qhotkey_x11.cpp | 48 +++++++++++++++++++++++++++++++++------ qhotkey.prc | 11 ++++++++- 6 files changed, 112 insertions(+), 25 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b3d190..f85f8be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,15 +7,27 @@ option(QHOTKEY_INSTALL "Enable install rule" ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) -find_package(Qt5 COMPONENTS Core Widgets REQUIRED) +set(QT_MAJOR 5 CACHE STRING "Qt major version to use") -qt5_wrap_cpp(MOC_HEADERS - QHotkey/qhotkey.h - QHotkey/qhotkey_p.h) +if(QT_MAJOR EQUAL 6) + find_package(Qt${QT_MAJOR} 6.2.0 COMPONENTS Core Widgets REQUIRED) +else() + find_package(Qt${QT_MAJOR} COMPONENTS Core Widgets REQUIRED) +endif() + +if(QT_MAJOR GREATER_EQUAL 6) + qt_wrap_cpp(MOC_HEADERS + QHotkey/qhotkey.h + QHotkey/qhotkey_p.h) +else() + qt5_wrap_cpp(MOC_HEADERS + QHotkey/qhotkey.h + QHotkey/qhotkey_p.h) +endif() set(LIBS - Qt5::Core - Qt5::Widgets) + Qt${QT_MAJOR}::Core + Qt${QT_MAJOR}::Widgets) set(SRC_FILES QHotkey/qhotkey.cpp) @@ -30,10 +42,14 @@ elseif(WIN32) set(SRC_FILES ${SRC_FILES} QHotkey/qhotkey_win.cpp) else() find_package(X11 REQUIRED) - find_package(Qt5X11Extras REQUIRED) + if(QT_MAJOR GREATER_EQUAL 6) + set(LIBS ${LIBS} ${X11_LIBRARIES}) + else() + find_package(Qt${QT_MAJOR}X11Extras REQUIRED) + set(LIBS ${LIBS} ${X11_LIBRARIES} Qt${QT_MAJOR}::X11Extras) + endif() include_directories(${X11_INCLUDE_DIR}) - set(LIBS ${LIBS} ${X11_LIBRARIES} Qt5::X11Extras) set(SRC_FILES ${SRC_FILES} QHotkey/qhotkey_x11.cpp) endif() diff --git a/HotkeyTest/CMakeLists.txt b/HotkeyTest/CMakeLists.txt index 67dfc8e..6915fb3 100644 --- a/HotkeyTest/CMakeLists.txt +++ b/HotkeyTest/CMakeLists.txt @@ -1,12 +1,17 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) -qt5_wrap_ui(test_UI_HEADERS hottestwidget.ui) -qt5_wrap_cpp(test_MOC_HEADERS hottestwidget.h) +if(QT_MAJOR GREATER_EQUAL 6) + qt_wrap_ui(test_UI_HEADERS hottestwidget.ui) + qt_wrap_cpp(test_MOC_HEADERS hottestwidget.h) +else() + qt5_wrap_ui(test_UI_HEADERS hottestwidget.ui) + qt5_wrap_cpp(test_MOC_HEADERS hottestwidget.h) +endif() add_executable(HotkeyTest main.cpp hottestwidget.cpp ${test_UI_HEADERS} ${test_MOC_HEADERS}) -target_link_libraries(HotkeyTest Qt5::Widgets qhotkey) +target_link_libraries(HotkeyTest Qt${QT_MAJOR}::Widgets qhotkey) target_include_directories(HotkeyTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/QHotkey/qhotkey.cpp b/QHotkey/qhotkey.cpp index ae6da22..e1ce190 100644 --- a/QHotkey/qhotkey.cpp +++ b/QHotkey/qhotkey.cpp @@ -10,9 +10,15 @@ Q_LOGGING_CATEGORY(logQHotkey, "QHotkey") void QHotkey::addGlobalMapping(const QKeySequence &shortcut, QHotkey::NativeShortcut nativeShortcut) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + const int key = shortcut[0].toCombined(); +#else + const int key = shortcut[0]; +#endif + QMetaObject::invokeMethod(QHotkeyPrivate::instance(), "addMappingInvoked", Qt::QueuedConnection, - Q_ARG(Qt::Key, Qt::Key(shortcut[0] & ~Qt::KeyboardModifierMask)), - Q_ARG(Qt::KeyboardModifiers, Qt::KeyboardModifiers(shortcut[0] & Qt::KeyboardModifierMask)), + Q_ARG(Qt::Key, Qt::Key(key & ~Qt::KeyboardModifierMask)), + Q_ARG(Qt::KeyboardModifiers, Qt::KeyboardModifiers(key & Qt::KeyboardModifierMask)), Q_ARG(QHotkey::NativeShortcut, nativeShortcut)); } @@ -56,7 +62,12 @@ QKeySequence QHotkey::shortcut() const { if(_keyCode == Qt::Key_unknown) return QKeySequence(); + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + return QKeySequence((_keyCode | _modifiers).toCombined()); +#else return QKeySequence(static_cast(_keyCode | _modifiers)); +#endif } Qt::Key QHotkey::keyCode() const @@ -88,8 +99,14 @@ bool QHotkey::setShortcut(const QKeySequence &shortcut, bool autoRegister) "Only the first shortcut will be used!"); } - return setShortcut(Qt::Key(shortcut[0] & ~Qt::KeyboardModifierMask), - Qt::KeyboardModifiers(shortcut[0] & Qt::KeyboardModifierMask), +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + const int key = shortcut[0].toCombined(); +#else + const int key = shortcut[0]; +#endif + + return setShortcut(Qt::Key(key & ~Qt::KeyboardModifierMask), + Qt::KeyboardModifiers(key & Qt::KeyboardModifierMask), autoRegister); } @@ -354,7 +371,7 @@ uint qHash(QHotkey::NativeShortcut key) return qHash(key.key) ^ qHash(key.modifier); } -uint qHash(QHotkey::NativeShortcut key, uint seed) +QHOTKEY_HASH_SEED qHash(QHotkey::NativeShortcut key, QHOTKEY_HASH_SEED seed) { return qHash(key.key, seed) ^ qHash(key.modifier, seed); } diff --git a/QHotkey/qhotkey.h b/QHotkey/qhotkey.h index f669640..f21a2c8 100644 --- a/QHotkey/qhotkey.h +++ b/QHotkey/qhotkey.h @@ -16,6 +16,12 @@ #define QHOTKEY_SHARED_EXPORT #endif +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + #define QHOTKEY_HASH_SEED size_t +#else + #define QHOTKEY_HASH_SEED uint +#endif + //! A class to define global, systemwide Hotkeys class QHOTKEY_SHARED_EXPORT QHotkey : public QObject { @@ -115,7 +121,7 @@ public slots: }; uint QHOTKEY_SHARED_EXPORT qHash(QHotkey::NativeShortcut key); -uint QHOTKEY_SHARED_EXPORT qHash(QHotkey::NativeShortcut key, uint seed); +QHOTKEY_HASH_SEED QHOTKEY_SHARED_EXPORT qHash(QHotkey::NativeShortcut key, QHOTKEY_HASH_SEED seed); QHOTKEY_SHARED_EXPORT Q_DECLARE_LOGGING_CATEGORY(logQHotkey) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index e3f8519..fc06c7a 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -1,7 +1,17 @@ #include "qhotkey.h" #include "qhotkey_p.h" -#include -#include + +#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) + #include + + #define _NATIVE_EVENT_RESULT qintptr +#else + #include + #include + + #define _NATIVE_EVENT_RESULT long +#endif + #include #include #include @@ -16,7 +26,7 @@ class QHotkeyPrivateX11 : public QHotkeyPrivate { public: // QAbstractNativeEventFilter interface - bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE; + bool nativeEventFilter(const QByteArray &eventType, void *message, _NATIVE_EVENT_RESULT *result) override; protected: // QHotkeyPrivate interface @@ -52,13 +62,17 @@ NATIVE_INSTANCE(QHotkeyPrivateX11) bool QHotkeyPrivate::isPlatformSupported() { +#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) + return qGuiApp->nativeInterface(); +#else return QX11Info::isPlatformX11(); +#endif } const QVector QHotkeyPrivateX11::specialModifiers = {0, Mod2Mask, LockMask, (Mod2Mask | LockMask)}; const quint32 QHotkeyPrivateX11::validModsMask = ShiftMask | ControlMask | Mod1Mask | Mod4Mask; -bool QHotkeyPrivateX11::nativeEventFilter(const QByteArray &eventType, void *message, long *result) +bool QHotkeyPrivateX11::nativeEventFilter(const QByteArray &eventType, void *message, _NATIVE_EVENT_RESULT *result) { Q_UNUSED(eventType) Q_UNUSED(result) @@ -120,8 +134,16 @@ quint32 QHotkeyPrivateX11::nativeKeycode(Qt::Key keycode, bool &ok) return 0; } - if(QX11Info::isPlatformX11()) { - auto res = XKeysymToKeycode(QX11Info::display(), keysym); +#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) + const QNativeInterface::QX11Application *x11Interface = qGuiApp->nativeInterface(); + Display *display = x11Interface->display(); +#else + const bool x11Interface = QX11Info::isPlatformX11(); + Display *display = QX11Info::display(); +#endif + + if(x11Interface) { + auto res = XKeysymToKeycode(display, keysym); if(res != 0) ok = true; return res; @@ -146,8 +168,15 @@ quint32 QHotkeyPrivateX11::nativeModifiers(Qt::KeyboardModifiers modifiers, bool bool QHotkeyPrivateX11::registerShortcut(QHotkey::NativeShortcut shortcut) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) + const QNativeInterface::QX11Application *x11Interface = qGuiApp->nativeInterface(); + Display *display = x11Interface->display(); +#else + const bool x11Interface = QX11Info::isPlatformX11(); Display *display = QX11Info::display(); - if(!display || !QX11Info::isPlatformX11()) +#endif + + if(!display || !x11Interface) return false; HotkeyErrorHandler errorHandler; @@ -172,7 +201,12 @@ bool QHotkeyPrivateX11::registerShortcut(QHotkey::NativeShortcut shortcut) bool QHotkeyPrivateX11::unregisterShortcut(QHotkey::NativeShortcut shortcut) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) + Display *display = qGuiApp->nativeInterface()->display(); +#else Display *display = QX11Info::display(); +#endif + if(!display) return false; diff --git a/qhotkey.prc b/qhotkey.prc index 30e2b04..d8e8ac0 100644 --- a/qhotkey.prc +++ b/qhotkey.prc @@ -1,6 +1,15 @@ mac: LIBS += -framework Carbon else:win32: LIBS += -luser32 else:unix { - QT += x11extras + equals(QT_MAJOR_VERSION, 6) { + lessThan(QT_VERSION, 6.2.0) { + error("Qt 6.2.0 or greater is required when using Qt6") + } + } + else { + lessThan(QT_MAJOR_VERSION, 6) { + QT += x11extras + } + } LIBS += -lX11 } From 6b3cc35bbd91562ee5192b6b9e9e510a00769c97 Mon Sep 17 00:00:00 2001 From: Daniel Bermond Date: Fri, 1 Oct 2021 15:04:20 -0300 Subject: [PATCH 51/71] CMake: honor CMAKE_INSTALL_INCLUDEDIR in exported target Remove the hardcode to the 'include' directory in the CMake exported target. This will let the user correctly access the headers when building a client application with a QHotkey package that is installed with a CMAKE_INSTALL_INCLUDEDIR different than 'include'. --- CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f85f8be..2eb65cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,10 +57,12 @@ add_library(qhotkey ${SRC_FILES} ${MOC_HEADERS}) add_library(QHotkey::QHotkey ALIAS qhotkey) target_link_libraries(qhotkey ${LIBS}) +include(GNUInstallDirs) + target_include_directories(qhotkey PUBLIC $ - $) + $) set_target_properties(qhotkey PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR} @@ -71,7 +73,6 @@ if(QHOTKEY_EXAMPLES) endif() if(QHOTKEY_INSTALL) - include(GNUInstallDirs) set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/QHotkey) install( @@ -82,7 +83,7 @@ if(QHOTKEY_INSTALL) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/QHotkey/qhotkey.h ${CMAKE_CURRENT_SOURCE_DIR}/QHotkey/QHotkey - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/) + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install(EXPORT QHotkeyConfig DESTINATION ${INSTALL_CONFIGDIR}) export(TARGETS qhotkey FILE QHotkeyConfig.cmake) From dbec7d3a2da333de746ef693477a377af29ef4ce Mon Sep 17 00:00:00 2001 From: Daniel Bermond Date: Sun, 3 Oct 2021 05:01:00 -0300 Subject: [PATCH 52/71] Readme: add build instructions This will also provide information about the supported Qt versions. --- README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/README.md b/README.md index e4f3f78..8256f1f 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,32 @@ The QHotkey is a class that can be used to create hotkeys/global shortcuts, aka **Note:** For now Wayland is not supported, as it is simply not possible to register a global shortcut with wayland. For more details, or possible Ideas on how to get Hotkeys working on wayland, see [Issue #14](https://github.com/Skycoder42/QHotkey/issues/14). +## Building + +QHotkey supports both Qt6 and Qt5. When using Qt6, version 6.2.0 or later required. It can be built by either the CMake or qmake building systems. + +### CMake + +The CMake `QT_MAJOR` variable controls which major version of Qt is used for building, and defaults to `5`. For example, use the CMake command line option `-DQT_MAJOR=6` for building with Qt6. To build the testing application `QHotkeyTest`, specify `-DQHOTKEY_EXAMPLES=ON`. CMake example usage: + +``` +$ cd QHotkey +$ cmake -B build -S . -DQT_MAJOR=6 +$ cmake --build build +# cmake --install build +``` + +### qmake + +The major version of Qt is chosen by the qmake invokation itself, as the qmake executable is tied to a specific Qt version. The executable name can vary between operating systems. qmake example usage: + +``` +$ cd QHotkey +$ qmake +$ make +# make install +``` + ## Installation The package is providet as qpm package, [`de.skycoder42.qhotkey`](https://www.qpm.io/packages/de.skycoder42.qhotkey/index.html). You can install it either via qpmx (preferred) or directly via qpm. From 79e5dd65be78ccd43db69a40a40624a6203b1f51 Mon Sep 17 00:00:00 2001 From: Daniel Bermond Date: Sun, 3 Oct 2021 08:07:20 -0300 Subject: [PATCH 53/71] CMake: change link type and remove Qt Widgets (#53) Link type can be changed to PRIVATE. Only Qt Core will remain as PUBLIC linking. It looks like that Qt Widgets is not needed and can be removed. On Qt6, Qt6::Gui is strictly needed. --- CMakeLists.txt | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2eb65cf..df165bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,9 +10,9 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(QT_MAJOR 5 CACHE STRING "Qt major version to use") if(QT_MAJOR EQUAL 6) - find_package(Qt${QT_MAJOR} 6.2.0 COMPONENTS Core Widgets REQUIRED) + find_package(Qt${QT_MAJOR} 6.2.0 COMPONENTS Core Gui REQUIRED) else() - find_package(Qt${QT_MAJOR} COMPONENTS Core Widgets REQUIRED) + find_package(Qt${QT_MAJOR} COMPONENTS Core Gui REQUIRED) endif() if(QT_MAJOR GREATER_EQUAL 6) @@ -25,38 +25,35 @@ else() QHotkey/qhotkey_p.h) endif() -set(LIBS - Qt${QT_MAJOR}::Core - Qt${QT_MAJOR}::Widgets) - -set(SRC_FILES - QHotkey/qhotkey.cpp) +add_library(qhotkey QHotkey/qhotkey.cpp ${MOC_HEADERS}) +add_library(QHotkey::QHotkey ALIAS qhotkey) +target_link_libraries(qhotkey PUBLIC Qt${QT_MAJOR}::Core) +target_link_libraries(qhotkey PRIVATE Qt${QT_MAJOR}::Gui) if(APPLE) find_library(CARBON_LIBRARY Carbon) mark_as_advanced(CARBON_LIBRARY) - set(SRC_FILES ${SRC_FILES} QHotkey/qhotkey_mac.cpp) - set(LIBS ${LIBS} ${CARBON_LIBRARY}) + target_sources(qhotkey PRIVATE QHotkey/qhotkey_mac.cpp) + target_link_libraries(qhotkey PRIVATE ${CARBON_LIBRARY}) elseif(WIN32) - set(SRC_FILES ${SRC_FILES} QHotkey/qhotkey_win.cpp) + target_sources(qhotkey PRIVATE QHotkey/qhotkey_win.cpp) else() find_package(X11 REQUIRED) if(QT_MAJOR GREATER_EQUAL 6) - set(LIBS ${LIBS} ${X11_LIBRARIES}) + target_link_libraries(qhotkey PRIVATE ${X11_LIBRARIES}) else() find_package(Qt${QT_MAJOR}X11Extras REQUIRED) - set(LIBS ${LIBS} ${X11_LIBRARIES} Qt${QT_MAJOR}::X11Extras) + target_link_libraries(qhotkey + PRIVATE + ${X11_LIBRARIES} + Qt${QT_MAJOR}::X11Extras) endif() include_directories(${X11_INCLUDE_DIR}) - set(SRC_FILES ${SRC_FILES} QHotkey/qhotkey_x11.cpp) + target_sources(qhotkey PRIVATE QHotkey/qhotkey_x11.cpp) endif() -add_library(qhotkey ${SRC_FILES} ${MOC_HEADERS}) -add_library(QHotkey::QHotkey ALIAS qhotkey) -target_link_libraries(qhotkey ${LIBS}) - include(GNUInstallDirs) target_include_directories(qhotkey From 7b10ea6d64acb9d9f8ccd86b7bcd503435fcc844 Mon Sep 17 00:00:00 2001 From: Daniel Bermond Date: Sun, 3 Oct 2021 08:18:23 -0300 Subject: [PATCH 54/71] Qt6 support for Windows and Mac (#54) This follows commit 25f2184. On Windows, changing the return value of the qHash() variant that takes one argument fixes the following warning on MSVC 2019: qhotkey.cpp:(371,45): warning C4267: 'return': conversion from 'size_t' to 'uint', possible loss of data --- QHotkey/qhotkey.cpp | 2 +- QHotkey/qhotkey.h | 2 +- QHotkey/qhotkey_mac.cpp | 6 +++--- QHotkey/qhotkey_p.h | 6 ++++++ QHotkey/qhotkey_win.cpp | 4 ++-- QHotkey/qhotkey_x11.cpp | 4 ---- 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/QHotkey/qhotkey.cpp b/QHotkey/qhotkey.cpp index e1ce190..3b76d9c 100644 --- a/QHotkey/qhotkey.cpp +++ b/QHotkey/qhotkey.cpp @@ -366,7 +366,7 @@ bool QHotkey::NativeShortcut::operator !=(QHotkey::NativeShortcut other) const valid != other.valid; } -uint qHash(QHotkey::NativeShortcut key) +QHOTKEY_HASH_SEED qHash(QHotkey::NativeShortcut key) { return qHash(key.key) ^ qHash(key.modifier); } diff --git a/QHotkey/qhotkey.h b/QHotkey/qhotkey.h index f21a2c8..c520ba3 100644 --- a/QHotkey/qhotkey.h +++ b/QHotkey/qhotkey.h @@ -120,7 +120,7 @@ public slots: bool _registered; }; -uint QHOTKEY_SHARED_EXPORT qHash(QHotkey::NativeShortcut key); +QHOTKEY_HASH_SEED QHOTKEY_SHARED_EXPORT qHash(QHotkey::NativeShortcut key); QHOTKEY_HASH_SEED QHOTKEY_SHARED_EXPORT qHash(QHotkey::NativeShortcut key, QHOTKEY_HASH_SEED seed); QHOTKEY_SHARED_EXPORT Q_DECLARE_LOGGING_CATEGORY(logQHotkey) diff --git a/QHotkey/qhotkey_mac.cpp b/QHotkey/qhotkey_mac.cpp index 0e06299..2cf0db4 100644 --- a/QHotkey/qhotkey_mac.cpp +++ b/QHotkey/qhotkey_mac.cpp @@ -7,7 +7,7 @@ class QHotkeyPrivateMac : public QHotkeyPrivate { public: // QAbstractNativeEventFilter interface - bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE; + bool nativeEventFilter(const QByteArray &eventType, void *message, _NATIVE_EVENT_RESULT *result) override; static OSStatus hotkeyPressEventHandler(EventHandlerCallRef nextHandler, EventRef event, void* data); static OSStatus hotkeyReleaseEventHandler(EventHandlerCallRef nextHandler, EventRef event, void* data); @@ -33,7 +33,7 @@ bool QHotkeyPrivate::isPlatformSupported() bool QHotkeyPrivateMac::isHotkeyHandlerRegistered = false; QHash QHotkeyPrivateMac::hotkeyRefs; -bool QHotkeyPrivateMac::nativeEventFilter(const QByteArray &eventType, void *message, long *result) +bool QHotkeyPrivateMac::nativeEventFilter(const QByteArray &eventType, void *message, _NATIVE_EVENT_RESULT *result) { Q_UNUSED(eventType) Q_UNUSED(message) @@ -288,4 +288,4 @@ OSStatus QHotkeyPrivateMac::hotkeyReleaseEventHandler(EventHandlerCallRef nextHa } return noErr; -} \ No newline at end of file +} diff --git a/QHotkey/qhotkey_p.h b/QHotkey/qhotkey_p.h index b7c1721..d1bd1d2 100644 --- a/QHotkey/qhotkey_p.h +++ b/QHotkey/qhotkey_p.h @@ -7,6 +7,12 @@ #include #include +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + #define _NATIVE_EVENT_RESULT qintptr +#else + #define _NATIVE_EVENT_RESULT long +#endif + class QHOTKEY_SHARED_EXPORT QHotkeyPrivate : public QObject, public QAbstractNativeEventFilter { Q_OBJECT diff --git a/QHotkey/qhotkey_win.cpp b/QHotkey/qhotkey_win.cpp index a03b8c0..715b92e 100644 --- a/QHotkey/qhotkey_win.cpp +++ b/QHotkey/qhotkey_win.cpp @@ -15,7 +15,7 @@ class QHotkeyPrivateWin : public QHotkeyPrivate public: QHotkeyPrivateWin(); // QAbstractNativeEventFilter interface - bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE; + bool nativeEventFilter(const QByteArray &eventType, void *message, _NATIVE_EVENT_RESULT *result) override; protected: void pollForHotkeyRelease(); @@ -42,7 +42,7 @@ bool QHotkeyPrivate::isPlatformSupported() return true; } -bool QHotkeyPrivateWin::nativeEventFilter(const QByteArray &eventType, void *message, long *result) +bool QHotkeyPrivateWin::nativeEventFilter(const QByteArray &eventType, void *message, _NATIVE_EVENT_RESULT *result) { Q_UNUSED(eventType) Q_UNUSED(result) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index fc06c7a..ce408e6 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -3,13 +3,9 @@ #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) #include - - #define _NATIVE_EVENT_RESULT qintptr #else #include #include - - #define _NATIVE_EVENT_RESULT long #endif #include From 7f5840fd34644a6970f8ac544eee3d2ba28618b5 Mon Sep 17 00:00:00 2001 From: Hennadii Chernyshchyk Date: Sun, 3 Oct 2021 11:21:34 +0300 Subject: [PATCH 55/71] Add CI --- .github/workflows/build.yml | 57 +++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 15 ++-------- HotkeyTest/CMakeLists.txt | 16 ++++------- QHotkey/qhotkey_p.h | 3 -- 4 files changed, 65 insertions(+), 26 deletions(-) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..0467049 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,57 @@ +name: Build + +on: + push: + branches-ignore: + - "releases/**" + paths-ignore: + - "**.md" + +jobs: + build: + strategy: + matrix: + qt_version: [5.12.11, 5.15.2, 6.2.0] + platform: [ubuntu-20.04, windows-latest, macos-latest] + include: + - qt_version: 6.2.0 + additional_arguments: -D QT_MAJOR=6 + - platform: ubuntu-20.04 + make: make + CXXFLAGS: -Wall -Wextra -pedantic -Werror + MAKEFLAGS: -j2 + - platform: macos-latest + make: make + CXXFLAGS: -Wall -Wextra -pedantic -Werror -Wno-gnu-zero-variadic-macro-arguments # Ignore false-positive warning for qCWarning + MAKEFLAGS: -j3 + - platform: windows-latest + make: nmake + CXXFLAGS: /W4 /WX /MP + + runs-on: ${{ matrix.platform }} + env: + CXXFLAGS: ${{ matrix.CXXFLAGS }} + MAKEFLAGS: ${{ matrix.MAKEFLAGS }} + + steps: + - name: Clone repo + uses: actions/checkout@v2.3.4 + + - name: Install Qt + uses: jurplel/install-qt-action@v2.14.0 + with: + version: ${{ matrix.qt_version }} + + - name: Build with CMake + run: | + cmake . -D QHOTKEY_EXAMPLES=ON ${{ matrix.additional_arguments }} + cmake --build . + + - name: Setup MSVC environment for QMake + uses: ilammy/msvc-dev-cmd@v1 + + - name: Build with QMake + working-directory: HotkeyTest + run: | + qmake + ${{ matrix.make }} diff --git a/CMakeLists.txt b/CMakeLists.txt index df165bc..fe49287 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ option(QHOTKEY_EXAMPLES "Build examples" OFF) option(QHOTKEY_INSTALL "Enable install rule" ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(CMAKE_AUTOMOC ON) set(QT_MAJOR 5 CACHE STRING "Qt major version to use") @@ -15,17 +16,7 @@ else() find_package(Qt${QT_MAJOR} COMPONENTS Core Gui REQUIRED) endif() -if(QT_MAJOR GREATER_EQUAL 6) - qt_wrap_cpp(MOC_HEADERS - QHotkey/qhotkey.h - QHotkey/qhotkey_p.h) -else() - qt5_wrap_cpp(MOC_HEADERS - QHotkey/qhotkey.h - QHotkey/qhotkey_p.h) -endif() - -add_library(qhotkey QHotkey/qhotkey.cpp ${MOC_HEADERS}) +add_library(qhotkey QHotkey/qhotkey.cpp) add_library(QHotkey::QHotkey ALIAS qhotkey) target_link_libraries(qhotkey PUBLIC Qt${QT_MAJOR}::Core) target_link_libraries(qhotkey PRIVATE Qt${QT_MAJOR}::Gui) @@ -43,7 +34,7 @@ else() if(QT_MAJOR GREATER_EQUAL 6) target_link_libraries(qhotkey PRIVATE ${X11_LIBRARIES}) else() - find_package(Qt${QT_MAJOR}X11Extras REQUIRED) + find_package(Qt${QT_MAJOR} COMPONENTS X11Extras REQUIRED) target_link_libraries(qhotkey PRIVATE ${X11_LIBRARIES} diff --git a/HotkeyTest/CMakeLists.txt b/HotkeyTest/CMakeLists.txt index 6915fb3..17d3f2e 100644 --- a/HotkeyTest/CMakeLists.txt +++ b/HotkeyTest/CMakeLists.txt @@ -1,17 +1,11 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) -if(QT_MAJOR GREATER_EQUAL 6) - qt_wrap_ui(test_UI_HEADERS hottestwidget.ui) - qt_wrap_cpp(test_MOC_HEADERS hottestwidget.h) -else() - qt5_wrap_ui(test_UI_HEADERS hottestwidget.ui) - qt5_wrap_cpp(test_MOC_HEADERS hottestwidget.h) -endif() +set(CMAKE_AUTOUIC ON) add_executable(HotkeyTest main.cpp hottestwidget.cpp - ${test_UI_HEADERS} - ${test_MOC_HEADERS}) -target_link_libraries(HotkeyTest Qt${QT_MAJOR}::Widgets qhotkey) -target_include_directories(HotkeyTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + hottestwidget.ui) + +find_package(Qt${QT_MAJOR} COMPONENTS Widgets REQUIRED) +target_link_libraries(HotkeyTest Qt${QT_MAJOR}::Widgets QHotkey::QHotkey) diff --git a/QHotkey/qhotkey_p.h b/QHotkey/qhotkey_p.h index d1bd1d2..d588270 100644 --- a/QHotkey/qhotkey_p.h +++ b/QHotkey/qhotkey_p.h @@ -59,7 +59,4 @@ class QHOTKEY_SHARED_EXPORT QHotkeyPrivate : public QObject, public QAbstractNat return hotkeyPrivate;\ } -Q_DECLARE_METATYPE(Qt::Key) -Q_DECLARE_METATYPE(Qt::KeyboardModifiers) - #endif // QHOTKEY_P_H From 1d49a63827ae9d9180d8c6d95cb2e2b548d39880 Mon Sep 17 00:00:00 2001 From: Daniel Bermond Date: Sun, 3 Oct 2021 13:52:50 -0300 Subject: [PATCH 56/71] CMake: add package version config file (#57) By adding this file, client applications can have proper version checking support when calling 'find_package()'. --- .github/workflows/build.yml | 3 +++ CMakeLists.txt | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0467049..6dc6312 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,6 +6,9 @@ on: - "releases/**" paths-ignore: - "**.md" + pull_request: + paths-ignore: + - "**.md" jobs: build: diff --git a/CMakeLists.txt b/CMakeLists.txt index fe49287..b5c1131 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.1) -project(qhotkey VERSION 1.2.2 LANGUAGES CXX) +project(qhotkey VERSION 1.4.2 LANGUAGES CXX) option(QHOTKEY_EXAMPLES "Build examples" OFF) option(QHOTKEY_INSTALL "Enable install rule" ON) @@ -52,9 +52,18 @@ target_include_directories(qhotkey $ $) +include(CMakePackageConfigHelpers) + set_target_properties(qhotkey PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR} - VERSION ${PROJECT_VERSION}) + VERSION ${PROJECT_VERSION} + INTERFACE_QHotkey_MAJOR_VERSION ${PROJECT_VERSION_MAJOR} + COMPATIBLE_INTERFACE_STRING QHotkey_MAJOR_VERSION) + +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/QHotkeyConfigVersion.cmake + VERSION "${PROJECT_VERSION}" + COMPATIBILITY AnyNewerVersion) if(QHOTKEY_EXAMPLES) add_subdirectory(HotkeyTest) @@ -72,6 +81,9 @@ if(QHOTKEY_INSTALL) ${CMAKE_CURRENT_SOURCE_DIR}/QHotkey/qhotkey.h ${CMAKE_CURRENT_SOURCE_DIR}/QHotkey/QHotkey DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/QHotkeyConfigVersion.cmake + DESTINATION ${INSTALL_CONFIGDIR}) install(EXPORT QHotkeyConfig DESTINATION ${INSTALL_CONFIGDIR}) export(TARGETS qhotkey FILE QHotkeyConfig.cmake) From e0bc2a9b9fa71e325956d0a2d37be2d4a7441f58 Mon Sep 17 00:00:00 2001 From: Hennadii Chernyshchyk Date: Tue, 5 Oct 2021 01:25:26 +0300 Subject: [PATCH 57/71] Fix shared library build --- .github/workflows/build.yml | 15 +++++++++++++-- CMakeLists.txt | 5 +++++ QHotkey/QHotkey.pro | 2 +- QHotkey/qhotkey.h | 24 ++++++++++++------------ QHotkey/qhotkey_p.h | 2 +- 5 files changed, 32 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6dc6312..91171e8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -45,16 +45,27 @@ jobs: with: version: ${{ matrix.qt_version }} - - name: Build with CMake + - name: Build with CMake as static run: | cmake . -D QHOTKEY_EXAMPLES=ON ${{ matrix.additional_arguments }} cmake --build . + - name: Build with CMake as shared + run: | + cmake . -D BUILD_SHARED_LIBS=ON -D QHOTKEY_EXAMPLES=ON ${{ matrix.additional_arguments }} + cmake --build . + - name: Setup MSVC environment for QMake uses: ilammy/msvc-dev-cmd@v1 - - name: Build with QMake + - name: Build with QMake as static working-directory: HotkeyTest run: | qmake ${{ matrix.make }} + + - name: Build with QMake as shared + working-directory: HotkeyTest + run: | + qmake "DEFINES+=QHOTKEY_SHARED QHOTKEY_LIBRARY" + ${{ matrix.make }} diff --git a/CMakeLists.txt b/CMakeLists.txt index b5c1131..57880a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,11 @@ add_library(QHotkey::QHotkey ALIAS qhotkey) target_link_libraries(qhotkey PUBLIC Qt${QT_MAJOR}::Core) target_link_libraries(qhotkey PRIVATE Qt${QT_MAJOR}::Gui) +if(BUILD_SHARED_LIBS) + target_compile_definitions(qhotkey PRIVATE QHOTKEY_LIBRARY) + target_compile_definitions(qhotkey PUBLIC QHOTKEY_SHARED) +endif() + if(APPLE) find_library(CARBON_LIBRARY Carbon) mark_as_advanced(CARBON_LIBRARY) diff --git a/QHotkey/QHotkey.pro b/QHotkey/QHotkey.pro index 44e937b..5a261e0 100644 --- a/QHotkey/QHotkey.pro +++ b/QHotkey/QHotkey.pro @@ -6,7 +6,7 @@ VERSION = 1.2.1 include(../qhotkey.pri) -DEFINES += QHOTKEY_LIB QHOTKEY_LIB_BUILD +DEFINES += QHOTKEY_SHARED QHOTKEY_LIBRARY # use INSTALL_ROOT to modify the install location headers.files = $$PUBLIC_HEADERS diff --git a/QHotkey/qhotkey.h b/QHotkey/qhotkey.h index c520ba3..3697c8e 100644 --- a/QHotkey/qhotkey.h +++ b/QHotkey/qhotkey.h @@ -6,14 +6,14 @@ #include #include -#ifdef QHOTKEY_LIB - #ifdef QHOTKEY_LIB_BUILD - #define QHOTKEY_SHARED_EXPORT Q_DECL_EXPORT - #else - #define QHOTKEY_SHARED_EXPORT Q_DECL_IMPORT - #endif +#ifdef QHOTKEY_SHARED +# ifdef QHOTKEY_LIBRARY +# define QHOTKEY_EXPORT Q_DECL_EXPORT +# else +# define QHOTKEY_EXPORT Q_DECL_IMPORT +# endif #else - #define QHOTKEY_SHARED_EXPORT +# define QHOTKEY_EXPORT #endif #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) @@ -23,7 +23,7 @@ #endif //! A class to define global, systemwide Hotkeys -class QHOTKEY_SHARED_EXPORT QHotkey : public QObject +class QHOTKEY_EXPORT QHotkey : public QObject { Q_OBJECT //! @private @@ -36,7 +36,7 @@ class QHOTKEY_SHARED_EXPORT QHotkey : public QObject public: //! Defines shortcut with native keycodes - class QHOTKEY_SHARED_EXPORT NativeShortcut { + class QHOTKEY_EXPORT NativeShortcut { public: //! The native keycode quint32 key; @@ -120,10 +120,10 @@ public slots: bool _registered; }; -QHOTKEY_HASH_SEED QHOTKEY_SHARED_EXPORT qHash(QHotkey::NativeShortcut key); -QHOTKEY_HASH_SEED QHOTKEY_SHARED_EXPORT qHash(QHotkey::NativeShortcut key, QHOTKEY_HASH_SEED seed); +QHOTKEY_HASH_SEED QHOTKEY_EXPORT qHash(QHotkey::NativeShortcut key); +QHOTKEY_HASH_SEED QHOTKEY_EXPORT qHash(QHotkey::NativeShortcut key, QHOTKEY_HASH_SEED seed); -QHOTKEY_SHARED_EXPORT Q_DECLARE_LOGGING_CATEGORY(logQHotkey) +QHOTKEY_EXPORT Q_DECLARE_LOGGING_CATEGORY(logQHotkey) Q_DECLARE_METATYPE(QHotkey::NativeShortcut) diff --git a/QHotkey/qhotkey_p.h b/QHotkey/qhotkey_p.h index d588270..8bc5ab6 100644 --- a/QHotkey/qhotkey_p.h +++ b/QHotkey/qhotkey_p.h @@ -13,7 +13,7 @@ #define _NATIVE_EVENT_RESULT long #endif -class QHOTKEY_SHARED_EXPORT QHotkeyPrivate : public QObject, public QAbstractNativeEventFilter +class QHOTKEY_EXPORT QHotkeyPrivate : public QObject, public QAbstractNativeEventFilter { Q_OBJECT From 1114df5081f2cda334531ac664c7434c13dccfe6 Mon Sep 17 00:00:00 2001 From: Hennadii Chernyshchyk Date: Tue, 5 Oct 2021 19:08:48 +0300 Subject: [PATCH 58/71] Bump version to 1.4.2 in QMake --- QHotkey/QHotkey.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QHotkey/QHotkey.pro b/QHotkey/QHotkey.pro index 5a261e0..edc1110 100644 --- a/QHotkey/QHotkey.pro +++ b/QHotkey/QHotkey.pro @@ -2,7 +2,7 @@ TEMPLATE = lib win32: CONFIG += dll TARGET = QHotkey -VERSION = 1.2.1 +VERSION = 1.4.2 include(../qhotkey.pri) From 64fec66d358ead43784e085b424375f65b145307 Mon Sep 17 00:00:00 2001 From: Hennadii Chernyshchyk Date: Thu, 28 Oct 2021 22:33:17 +0300 Subject: [PATCH 59/71] Fix memory leak in README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 8256f1f..95ab938 100644 --- a/README.md +++ b/README.md @@ -74,17 +74,17 @@ The following example shows a simple application that will run without a window int main(int argc, char *argv[]) { - QApplication a(argc, argv); + QApplication app(argc, argv); - auto hotkey = new QHotkey(QKeySequence("ctrl+alt+Q"), true, &a);//The hotkey will be automatically registered - qDebug() << "Is Registered: " << hotkey->isRegistered(); + QHotkey hotkey(QKeySequence("Ctrl+Alt+Q"), true, &app); //The hotkey will be automatically registered + qDebug() << "Is segistered:" << hotkey.isRegistered(); - QObject::connect(hotkey, &QHotkey::activated, qApp, [&](){ + QObject::connect(&hotkey, &QHotkey::activated, qApp, [&](){ qDebug() << "Hotkey Activated - the application will quit now"; qApp->quit(); }); - return a.exec(); + return app.exec(); } ``` From fcf83f3e36d98c0f896704424622809bddf3d53c Mon Sep 17 00:00:00 2001 From: Hennadii Chernyshchyk Date: Thu, 28 Oct 2021 23:38:08 +0300 Subject: [PATCH 60/71] Use QT_DEFAULT_MAJOR_VERSION --- .github/workflows/build.yml | 2 +- CMakeLists.txt | 20 +++++++++++--------- HotkeyTest/CMakeLists.txt | 4 ++-- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 91171e8..7affb86 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: platform: [ubuntu-20.04, windows-latest, macos-latest] include: - qt_version: 6.2.0 - additional_arguments: -D QT_MAJOR=6 + additional_arguments: -D QT_DEFAULT_MAJOR_VERSION=6 - platform: ubuntu-20.04 make: make CXXFLAGS: -Wall -Wextra -pedantic -Werror diff --git a/CMakeLists.txt b/CMakeLists.txt index 57880a7..641aafc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,18 +8,20 @@ option(QHOTKEY_INSTALL "Enable install rule" ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_AUTOMOC ON) -set(QT_MAJOR 5 CACHE STRING "Qt major version to use") +if(NOT QT_DEFAULT_MAJOR_VERSION) + set(QT_DEFAULT_MAJOR_VERSION 5 CACHE STRING "Qt version to use (5 or 6), defaults to 5") +endif() -if(QT_MAJOR EQUAL 6) - find_package(Qt${QT_MAJOR} 6.2.0 COMPONENTS Core Gui REQUIRED) +if(QT_DEFAULT_MAJOR_VERSION EQUAL 6) + find_package(Qt${QT_DEFAULT_MAJOR_VERSION} 6.2.0 COMPONENTS Core Gui REQUIRED) else() - find_package(Qt${QT_MAJOR} COMPONENTS Core Gui REQUIRED) + find_package(Qt${QT_DEFAULT_MAJOR_VERSION} COMPONENTS Core Gui REQUIRED) endif() add_library(qhotkey QHotkey/qhotkey.cpp) add_library(QHotkey::QHotkey ALIAS qhotkey) -target_link_libraries(qhotkey PUBLIC Qt${QT_MAJOR}::Core) -target_link_libraries(qhotkey PRIVATE Qt${QT_MAJOR}::Gui) +target_link_libraries(qhotkey PUBLIC Qt${QT_DEFAULT_MAJOR_VERSION}::Core) +target_link_libraries(qhotkey PRIVATE Qt${QT_DEFAULT_MAJOR_VERSION}::Gui) if(BUILD_SHARED_LIBS) target_compile_definitions(qhotkey PRIVATE QHOTKEY_LIBRARY) @@ -36,14 +38,14 @@ elseif(WIN32) target_sources(qhotkey PRIVATE QHotkey/qhotkey_win.cpp) else() find_package(X11 REQUIRED) - if(QT_MAJOR GREATER_EQUAL 6) + if(QT_DEFAULT_MAJOR_VERSION GREATER_EQUAL 6) target_link_libraries(qhotkey PRIVATE ${X11_LIBRARIES}) else() - find_package(Qt${QT_MAJOR} COMPONENTS X11Extras REQUIRED) + find_package(Qt${QT_DEFAULT_MAJOR_VERSION} COMPONENTS X11Extras REQUIRED) target_link_libraries(qhotkey PRIVATE ${X11_LIBRARIES} - Qt${QT_MAJOR}::X11Extras) + Qt${QT_DEFAULT_MAJOR_VERSION}::X11Extras) endif() include_directories(${X11_INCLUDE_DIR}) diff --git a/HotkeyTest/CMakeLists.txt b/HotkeyTest/CMakeLists.txt index 17d3f2e..714585d 100644 --- a/HotkeyTest/CMakeLists.txt +++ b/HotkeyTest/CMakeLists.txt @@ -7,5 +7,5 @@ add_executable(HotkeyTest hottestwidget.cpp hottestwidget.ui) -find_package(Qt${QT_MAJOR} COMPONENTS Widgets REQUIRED) -target_link_libraries(HotkeyTest Qt${QT_MAJOR}::Widgets QHotkey::QHotkey) +find_package(Qt${QT_DEFAULT_MAJOR_VERSION} COMPONENTS Widgets REQUIRED) +target_link_libraries(HotkeyTest Qt${QT_DEFAULT_MAJOR_VERSION}::Widgets QHotkey::QHotkey) From 6a0cc377e6d950ac0407bd3a80809934062e4f4e Mon Sep 17 00:00:00 2001 From: Daniel Bermond Date: Thu, 28 Oct 2021 18:08:58 -0300 Subject: [PATCH 61/71] Bump version to 1.5.0 --- CMakeLists.txt | 2 +- QHotkey/QHotkey.pro | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 641aafc..d0904e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.1) -project(qhotkey VERSION 1.4.2 LANGUAGES CXX) +project(qhotkey VERSION 1.5.0 LANGUAGES CXX) option(QHOTKEY_EXAMPLES "Build examples" OFF) option(QHOTKEY_INSTALL "Enable install rule" ON) diff --git a/QHotkey/QHotkey.pro b/QHotkey/QHotkey.pro index edc1110..3a79376 100644 --- a/QHotkey/QHotkey.pro +++ b/QHotkey/QHotkey.pro @@ -2,7 +2,7 @@ TEMPLATE = lib win32: CONFIG += dll TARGET = QHotkey -VERSION = 1.4.2 +VERSION = 1.5.0 include(../qhotkey.pri) From 34330d6ff5d2ca111c376f6d7da66be9d1817430 Mon Sep 17 00:00:00 2001 From: Shatur95 Date: Fri, 29 Oct 2021 00:24:53 +0300 Subject: [PATCH 62/71] Link Gui as PUBLIC --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d0904e9..a3d1097 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,8 +20,7 @@ endif() add_library(qhotkey QHotkey/qhotkey.cpp) add_library(QHotkey::QHotkey ALIAS qhotkey) -target_link_libraries(qhotkey PUBLIC Qt${QT_DEFAULT_MAJOR_VERSION}::Core) -target_link_libraries(qhotkey PRIVATE Qt${QT_DEFAULT_MAJOR_VERSION}::Gui) +target_link_libraries(qhotkey PUBLIC Qt${QT_DEFAULT_MAJOR_VERSION}::Core Qt${QT_DEFAULT_MAJOR_VERSION}::Gui) if(BUILD_SHARED_LIBS) target_compile_definitions(qhotkey PRIVATE QHOTKEY_LIBRARY) From 308c96c28f9be4dc9139371200cd50c68f823a73 Mon Sep 17 00:00:00 2001 From: waneon Date: Sun, 6 Feb 2022 06:52:21 +0900 Subject: [PATCH 63/71] Fix invalid variable name in README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 95ab938..5e40930 100644 --- a/README.md +++ b/README.md @@ -20,11 +20,11 @@ QHotkey supports both Qt6 and Qt5. When using Qt6, version 6.2.0 or later requir ### CMake -The CMake `QT_MAJOR` variable controls which major version of Qt is used for building, and defaults to `5`. For example, use the CMake command line option `-DQT_MAJOR=6` for building with Qt6. To build the testing application `QHotkeyTest`, specify `-DQHOTKEY_EXAMPLES=ON`. CMake example usage: +The CMake `QT_DEFAULT_MAJOR_VERSION` variable controls which major version of Qt is used for building, and defaults to `5`. For example, use the CMake command line option `-DQT_DEFAULT_MAJOR_VERSION=6` for building with Qt6. To build the testing application `QHotkeyTest`, specify `-DQHOTKEY_EXAMPLES=ON`. CMake example usage: ``` $ cd QHotkey -$ cmake -B build -S . -DQT_MAJOR=6 +$ cmake -B build -S . -DQT_DEFAULT_MAJOR_VERSION=6 $ cmake --build build # cmake --install build ``` From 52e25acf221e5ac86ce648f6922620fb2d6a7121 Mon Sep 17 00:00:00 2001 From: YueLiang <38413990+Yue-Liang@users.noreply.github.com> Date: Mon, 21 Feb 2022 16:01:45 +0800 Subject: [PATCH 64/71] Fix bug for get natice keycode failed in mac (#66) TISCopyCurrentKeyboardInputSource will return null when using Chinese input method. Use TISCopyCurrentASCIICapableKeyboardLayoutInputSource instead. --- QHotkey/qhotkey_mac.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QHotkey/qhotkey_mac.cpp b/QHotkey/qhotkey_mac.cpp index 2cf0db4..799f515 100644 --- a/QHotkey/qhotkey_mac.cpp +++ b/QHotkey/qhotkey_mac.cpp @@ -134,7 +134,7 @@ quint32 QHotkeyPrivateMac::nativeKeycode(Qt::Key keycode, bool &ok) UTF16Char ch = keycode; CFDataRef currentLayoutData; - TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); + TISInputSourceRef currentKeyboard = TISCopyCurrentASCIICapableKeyboardLayoutInputSource(); if (currentKeyboard == NULL) return 0; From c501fbbadaf9f561ad5a5c35964f924783a69647 Mon Sep 17 00:00:00 2001 From: luz paz Date: Wed, 22 Jun 2022 19:20:55 -0400 Subject: [PATCH 65/71] Fix typos Found via `codespell -q 3` --- HotkeyTest/hottestwidget.ui | 6 +++--- QHotkey/qhotkey_x11.cpp | 2 +- README.md | 12 ++++++------ doc/qhotkey.dox | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/HotkeyTest/hottestwidget.ui b/HotkeyTest/hottestwidget.ui index c1db840..8da0d92 100644 --- a/HotkeyTest/hottestwidget.ui +++ b/HotkeyTest/hottestwidget.ui @@ -769,7 +769,7 @@ - <b>Testing:</b> Please press the combinations listed below to check whether they work properly or not. Everytime a shortcut is triggered, the checkbox will toggle it's value. Set the test active to begin. + <b>Testing:</b> Please press the combinations listed below to check whether they work properly or not. Every time a shortcut is triggered, the checkbox will toggle it's value. Set the test active to begin. true @@ -927,7 +927,7 @@ - <html><head/><body><p>This test was designed to try out multi-threaded shortcuts. The QHotkey class is completly <span style=" font-weight:600;">threadsafe</span>, but this test can help to see if it acutally works (It does).</p><p>If activated, <span style=" font-style:italic;">Hotkey 4 and Hotkey 5 </span>of the Playground will each run on their own thread. This means:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">Mainthread:</span> Hotkey 1, 2, 3</li><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">Second thread:</span> Hotkey 4</li><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">Third thread:</span> Hotkey 5</li></ul><p><span style=" font-weight:600;">Note:</span> The two hotkeys will be moved to the threads. For simplicity-reasons, you can't move them back in this test (But its possible, just not done here). Restart the test to get them back.</p></body></html> + <html><head/><body><p>This test was designed to try out multi-threaded shortcuts. The QHotkey class is completely <span style=" font-weight:600;">threadsafe</span>, but this test can help to see if it actually works (It does).</p><p>If activated, <span style=" font-style:italic;">Hotkey 4 and Hotkey 5 </span>of the Playground will each run on their own thread. This means:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">Mainthread:</span> Hotkey 1, 2, 3</li><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">Second thread:</span> Hotkey 4</li><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">Third thread:</span> Hotkey 5</li></ul><p><span style=" font-weight:600;">Note:</span> The two hotkeys will be moved to the threads. For simplicity-reasons, you can't move them back in this test (But its possible, just not done here). Restart the test to get them back.</p></body></html> Qt::RichText @@ -973,7 +973,7 @@ - <html><head/><body><p>QHotkey allows you to set native shortcuts explicitly. These, of course, only work on the platform they were choosen for. All platform use special constants for their key codes and modifiers, which makes it pretty simple to use them from code. If you want to test them out here, google for the tables.</p><p>In most cases, you will not need to specify native shortcuts directly. However, as explaind on previos tabs, some shotcuts may not be creatable from Qt's key (e.g. Numblock numbers). In that case, you can set the directly.</p><p><span style=" text-decoration: underline;">Example: Ctrl+A</span></p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Windows:</span> Key: <span style=" font-style:italic;">0x0041</span>, Modifier: <span style=" font-style:italic;">0x0002</span></li><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">X11:</span> Key: <span style=" font-style:italic;">0x0026</span>, Modifier: <span style=" font-style:italic;">0x0004</span></li><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">OsX:</span> Key: <span style=" font-style:italic;">0x0000</span>, Modifier: <span style=" font-style:italic;">0x0100</span><span style=" text-decoration: underline;"><br/></span></li></ul></body></html> + <html><head/><body><p>QHotkey allows you to set native shortcuts explicitly. These, of course, only work on the platform they were chosen for. All platform use special constants for their key codes and modifiers, which makes it pretty simple to use them from code. If you want to test them out here, google for the tables.</p><p>In most cases, you will not need to specify native shortcuts directly. However, as explained on previous tabs, some shortcuts may not be creatable from Qt's key (e.g. Numblock numbers). In that case, you can set the directly.</p><p><span style=" text-decoration: underline;">Example: Ctrl+A</span></p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Windows:</span> Key: <span style=" font-style:italic;">0x0041</span>, Modifier: <span style=" font-style:italic;">0x0002</span></li><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">X11:</span> Key: <span style=" font-style:italic;">0x0026</span>, Modifier: <span style=" font-style:italic;">0x0004</span></li><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">OsX:</span> Key: <span style=" font-style:italic;">0x0000</span>, Modifier: <span style=" font-style:italic;">0x0100</span><span style=" text-decoration: underline;"><br/></span></li></ul></body></html> true diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index ce408e6..d3ac1d1 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -13,7 +13,7 @@ #include #include -//compability to pre Qt 5.8 +//compatibility to pre Qt 5.8 #ifndef Q_FALLTHROUGH #define Q_FALLTHROUGH() (void)0 #endif diff --git a/README.md b/README.md index 5e40930..47595e0 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ $ cmake --build build ### qmake -The major version of Qt is chosen by the qmake invokation itself, as the qmake executable is tied to a specific Qt version. The executable name can vary between operating systems. qmake example usage: +The major version of Qt is chosen by the qmake invocation itself, as the qmake executable is tied to a specific Qt version. The executable name can vary between operating systems. qmake example usage: ``` $ cd QHotkey @@ -94,18 +94,18 @@ int main(int argc, char *argv[]) By running the example in `./HotkeyTest` you can test out the QHotkey class. There are 4 sections: - **Playground:** You can enter some sequences here and try it out with different key combinations. - **Testings:** A list of selected hotkeys. Activate it and try out which ones work for you (*Hint:* Depending on OS and keyboard layout, it's very possible that a few don't work). -- **Threading:** Activate the checkbox to move 2 Hotkeys of the playground to seperate threads. It should work without a difference. +- **Threading:** Activate the checkbox to move 2 Hotkeys of the playground to separate threads. It should work without a difference. - **Native Shortcut**: Allows you to try out the direct usage of native shortcuts ### Logging -By default, QHotkey prints some warning messages if something goes wrong (For example, a key that cannot be translated). All messages of QHotkey are grouped into the [QLoggingCategory](https://doc.qt.io/qt-5/qloggingcategory.html) `"QHotkey"`. If you want to simply disable the logging, call the folling function somewhere in your code: +By default, QHotkey prints some warning messages if something goes wrong (For example, a key that cannot be translated). All messages of QHotkey are grouped into the [QLoggingCategory](https://doc.qt.io/qt-5/qloggingcategory.html) `"QHotkey"`. If you want to simply disable the logging, call the following function somewhere in your code: ```cpp QLoggingCategory::setFilterRules(QStringLiteral("QHotkey.warning=false")); ``` -This will turn all warnings of QHotkey of (It only uses warnings for now, thats why this is enough). For more information about all the things you can do with the logging categories, check the Qt-Documentation +This will turn all warnings of QHotkey of (It only uses warnings for now, that's why this is enough). For more information about all the things you can do with the logging categories, check the Qt-Documentation -## Thread saftey -The QHotkey class itself is reentrant - wich means you can create as many instances as required on any thread. This allows you to use the QHotkey on all threads. **But** you should never use the QHotkey instance on a thread that is different from the one the instance belongs to! Internally the system uses a singleton instance that handles the hotkey events and distributes them to the QHotkey instances. This internal class is completley threadsafe. +## Thread safety +The QHotkey class itself is reentrant - which means you can create as many instances as required on any thread. This allows you to use the QHotkey on all threads. **But** you should never use the QHotkey instance on a thread that is different from the one the instance belongs to! Internally the system uses a singleton instance that handles the hotkey events and distributes them to the QHotkey instances. This internal class is completely threadsafe. However, this singleton instance only runs on the main thread. (One reason is that some of the OS-Functions are not thread safe). To make threaded hotkeys possible, the critical functions (registering/unregistering hotkeys and keytranslation) are all run on the mainthread too. The QHotkey instances on other threads use `QMetaObject::invokeMethod` with a `Qt::BlockingQueuedConnection`. diff --git a/doc/qhotkey.dox b/doc/qhotkey.dox index fe184f3..dabde3c 100644 --- a/doc/qhotkey.dox +++ b/doc/qhotkey.dox @@ -38,7 +38,7 @@ In addition to the normal accessors, a modification of the QHotkey::shortcut pro @default{`QKeySequence()` (`Qt::Key_unknown` + `Qt::NoModifier`)} Holds the shortcut this hotkey will be registered on. It can be used as QKeySequence or as a combination of -a Qt::Key and Qt::KeyboardModifiers. All write-accessors specifiy an additional parameter to immediatly register +a Qt::Key and Qt::KeyboardModifiers. All write-accessors specify an additional parameter to immediately register the hotkey. @note Since the operating systems do not support hotkeys that consist of multiple key-combinations in a sequence, @@ -107,7 +107,7 @@ it does. This does not happen if used from the main thread. If the hotkey is still registered on destruction, it will automatically unregister itself. -@warning If using a hotkey on a thread other than the main thread, make shure the QApplication is still running it's eventloop. +@warning If using a hotkey on a thread other than the main thread, make sure the QApplication is still running it's eventloop. Otherwise your application will hang up. @sa QHotkey::registered @@ -144,7 +144,7 @@ from the thread this instance lives on. This method can be used to remap specific hotkey to a different native representation than the one that would be used by default. This can be useful if specific key combinations work fine -on allmost all platforms, but on one you need a different keycode for the same effect. See +on almost all platforms, but on one you need a different keycode for the same effect. See [Issue #15](https://github.com/Skycoder42/QHotkey/issues/15) for an example where this is the case. From 6b1c6f1f4e2a26e346e6a813adba6427f3d2c054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20O=2E=20Cordero=20P=C3=A9rez?= Date: Tue, 21 Jun 2022 15:35:35 -0400 Subject: [PATCH 66/71] Made Windows BYTE typedef uppercase in attempt to get QHotkey to compile with MSVC 2019. --- QHotkey/qhotkey_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QHotkey/qhotkey_win.cpp b/QHotkey/qhotkey_win.cpp index 715b92e..9a88e30 100644 --- a/QHotkey/qhotkey_win.cpp +++ b/QHotkey/qhotkey_win.cpp @@ -235,7 +235,7 @@ quint32 QHotkeyPrivateWin::nativeKeycode(Qt::Key keycode, bool &ok) default: if(keycode <= 0xFFFF) - return (byte)keycode; + return (BYTE)keycode; else { ok = false; return 0; From 94efd5fb61178b10d94b83838740b580ce79cd6c Mon Sep 17 00:00:00 2001 From: "Javier O. Cordero" Date: Thu, 30 Jun 2022 20:16:06 -0400 Subject: [PATCH 67/71] Using static_cast as suggested by Shatur. --- QHotkey/qhotkey_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QHotkey/qhotkey_win.cpp b/QHotkey/qhotkey_win.cpp index 9a88e30..e6bbc36 100644 --- a/QHotkey/qhotkey_win.cpp +++ b/QHotkey/qhotkey_win.cpp @@ -235,7 +235,7 @@ quint32 QHotkeyPrivateWin::nativeKeycode(Qt::Key keycode, bool &ok) default: if(keycode <= 0xFFFF) - return (BYTE)keycode; + return static_cast(keycode); else { ok = false; return 0; From 34777f2e91b72cdc62a415975cc3ec53475ed022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20O=2E=20Cordero=20P=C3=A9rez?= Date: Thu, 7 Jul 2022 09:01:21 -0400 Subject: [PATCH 68/71] CPack instructions to build Debian package Co-authored-by: Hennadii Chernyshchyk --- CMakeLists.txt | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a3d1097..d34519e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,10 @@ cmake_minimum_required(VERSION 3.1) -project(qhotkey VERSION 1.5.0 LANGUAGES CXX) +project(qhotkey + VERSION 1.5.0 + DESCRIPTION "Global hotkey library for Qt software" + HOMEPAGE_URL "https://skycoder42.github.io/QHotkey/" + LANGUAGES CXX) option(QHOTKEY_EXAMPLES "Build examples" OFF) option(QHOTKEY_INSTALL "Enable install rule" ON) @@ -18,6 +22,21 @@ else() find_package(Qt${QT_DEFAULT_MAJOR_VERSION} COMPONENTS Core Gui REQUIRED) endif() +# General settings +set(CPACK_PACKAGE_VENDOR "Skycoder42") +set(CPACK_PACKAGE_CONTACT "Shatur") +set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md") +# CPACK: DEB Specific Settings +set(CPACK_DEBIAN_PACKAGE_NAME "libqhotkey") +set(CPACK_DEBIAN_PACKAGE_SECTION "Libraries") +# Set dependencies +if(QT_DEFAULT_MAJOR_VERSION EQUAL 6) + set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt6x11extras6 (>= 6.2.0)") +else() + set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5x11extras5 (>= 5.15.2)") +endif() +include(CPack) + add_library(qhotkey QHotkey/qhotkey.cpp) add_library(QHotkey::QHotkey ALIAS qhotkey) target_link_libraries(qhotkey PUBLIC Qt${QT_DEFAULT_MAJOR_VERSION}::Core Qt${QT_DEFAULT_MAJOR_VERSION}::Gui) From cd72a013275803fce33e028fc8b05ae32248da1f Mon Sep 17 00:00:00 2001 From: FredBill1 <36622430+FredBill1@users.noreply.github.com> Date: Tue, 18 Apr 2023 17:14:52 +0800 Subject: [PATCH 69/71] Properly emit `released` signal when pressing multiple hotkeys at the same time on Windows (#86) Co-authored-by: Hennadii Chernyshchyk --- QHotkey/qhotkey_win.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/QHotkey/qhotkey_win.cpp b/QHotkey/qhotkey_win.cpp index e6bbc36..949d87a 100644 --- a/QHotkey/qhotkey_win.cpp +++ b/QHotkey/qhotkey_win.cpp @@ -1,7 +1,9 @@ #include "qhotkey.h" #include "qhotkey_p.h" #include +#include #include +#include #include #define HKEY_ID(nativeShortcut) (((nativeShortcut.key ^ (nativeShortcut.modifier << 8)) & 0x0FFF) | 0x7000) @@ -28,7 +30,7 @@ class QHotkeyPrivateWin : public QHotkeyPrivate private: static QString formatWinError(DWORD winError); QTimer pollTimer; - QHotkey::NativeShortcut polledShortcut; + QList polledShortcuts; }; NATIVE_INSTANCE(QHotkeyPrivateWin) @@ -51,8 +53,9 @@ bool QHotkeyPrivateWin::nativeEventFilter(const QByteArray &eventType, void *mes if(msg->message == WM_HOTKEY) { QHotkey::NativeShortcut shortcut = {HIWORD(msg->lParam), LOWORD(msg->lParam)}; this->activateShortcut(shortcut); - this->polledShortcut = shortcut; - this->pollTimer.start(); + if (this->polledShortcuts.empty()) + this->pollTimer.start(); + this->polledShortcuts.append(shortcut); } return false; @@ -60,11 +63,15 @@ bool QHotkeyPrivateWin::nativeEventFilter(const QByteArray &eventType, void *mes void QHotkeyPrivateWin::pollForHotkeyRelease() { - bool pressed = (GetAsyncKeyState(this->polledShortcut.key) & (1 << 15)) != 0; - if(!pressed) { + auto it = std::remove_if(this->polledShortcuts.begin(), this->polledShortcuts.end(), [this](const QHotkey::NativeShortcut &shortcut) { + bool pressed = (GetAsyncKeyState(shortcut.key) & (1 << 15)) != 0; + if (!pressed) + this->releaseShortcut(shortcut); + return !pressed; + }); + this->polledShortcuts.erase(it, this->polledShortcuts.end()); + if (this->polledShortcuts.empty()) this->pollTimer.stop(); - this->releaseShortcut(this->polledShortcut); - } } quint32 QHotkeyPrivateWin::nativeKeycode(Qt::Key keycode, bool &ok) From b519155479a1a0af816f4b5f4b00d49a165cd8d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20O=2E=20Cordero=20P=C3=A9rez?= Date: Mon, 20 May 2024 09:09:14 -0400 Subject: [PATCH 70/71] Bump Qt and CI script versions, fix macOS support, and drop support for qmake (#98) --- .github/workflows/build.yml | 25 +++++-------------------- HotkeyTest/HotkeyTest.pro | 21 --------------------- QHotkey.pro | 10 ---------- QHotkey/QHotkey.pro | 16 ---------------- QHotkey/qhotkey.pri | 1 - README.md | 13 +------------ qhotkey.prc | 15 --------------- qhotkey.pri | 17 ----------------- 8 files changed, 6 insertions(+), 112 deletions(-) delete mode 100644 HotkeyTest/HotkeyTest.pro delete mode 100644 QHotkey.pro delete mode 100644 QHotkey/QHotkey.pro delete mode 100644 QHotkey/qhotkey.pri delete mode 100644 qhotkey.prc delete mode 100644 qhotkey.pri diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7affb86..89d7c90 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,10 +14,10 @@ jobs: build: strategy: matrix: - qt_version: [5.12.11, 5.15.2, 6.2.0] + qt_version: [5.12.12, 5.15.2, 6.2.2] platform: [ubuntu-20.04, windows-latest, macos-latest] include: - - qt_version: 6.2.0 + - qt_version: 6.2.2 additional_arguments: -D QT_DEFAULT_MAJOR_VERSION=6 - platform: ubuntu-20.04 make: make @@ -41,31 +41,16 @@ jobs: uses: actions/checkout@v2.3.4 - name: Install Qt - uses: jurplel/install-qt-action@v2.14.0 + uses: jurplel/install-qt-action@v3.3.0 with: version: ${{ matrix.qt_version }} - name: Build with CMake as static run: | - cmake . -D QHOTKEY_EXAMPLES=ON ${{ matrix.additional_arguments }} + cmake . -D QHOTKEY_EXAMPLES=ON -D CMAKE_OSX_ARCHITECTURES="x86_64" ${{ matrix.additional_arguments }} cmake --build . - name: Build with CMake as shared run: | - cmake . -D BUILD_SHARED_LIBS=ON -D QHOTKEY_EXAMPLES=ON ${{ matrix.additional_arguments }} + cmake . -D BUILD_SHARED_LIBS=ON -D QHOTKEY_EXAMPLES=ON -D CMAKE_OSX_ARCHITECTURES="x86_64" ${{ matrix.additional_arguments }} cmake --build . - - - name: Setup MSVC environment for QMake - uses: ilammy/msvc-dev-cmd@v1 - - - name: Build with QMake as static - working-directory: HotkeyTest - run: | - qmake - ${{ matrix.make }} - - - name: Build with QMake as shared - working-directory: HotkeyTest - run: | - qmake "DEFINES+=QHOTKEY_SHARED QHOTKEY_LIBRARY" - ${{ matrix.make }} diff --git a/HotkeyTest/HotkeyTest.pro b/HotkeyTest/HotkeyTest.pro deleted file mode 100644 index a43f662..0000000 --- a/HotkeyTest/HotkeyTest.pro +++ /dev/null @@ -1,21 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2016-02-05T22:01:03 -# -#------------------------------------------------- - -QT += core gui - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -TARGET = HotkeyTest -TEMPLATE = app - -include(../qhotkey.pri) - -SOURCES += main.cpp\ - hottestwidget.cpp - -HEADERS += hottestwidget.h - -FORMS += hottestwidget.ui diff --git a/QHotkey.pro b/QHotkey.pro deleted file mode 100644 index 5fa7cbe..0000000 --- a/QHotkey.pro +++ /dev/null @@ -1,10 +0,0 @@ -TEMPLATE = subdirs - -SUBDIRS += \ - HotkeyTest \ - QHotkey - -DISTFILES += README.md \ - LICENSE \ - doc/qhotkey.doxy \ - doc/qhotkey.dox diff --git a/QHotkey/QHotkey.pro b/QHotkey/QHotkey.pro deleted file mode 100644 index 3a79376..0000000 --- a/QHotkey/QHotkey.pro +++ /dev/null @@ -1,16 +0,0 @@ -TEMPLATE = lib -win32: CONFIG += dll - -TARGET = QHotkey -VERSION = 1.5.0 - -include(../qhotkey.pri) - -DEFINES += QHOTKEY_SHARED QHOTKEY_LIBRARY - -# use INSTALL_ROOT to modify the install location -headers.files = $$PUBLIC_HEADERS -headers.path = $$[QT_INSTALL_HEADERS] -target.path = $$[QT_INSTALL_LIBS] -INSTALLS += target headers - diff --git a/QHotkey/qhotkey.pri b/QHotkey/qhotkey.pri deleted file mode 100644 index a7c9725..0000000 --- a/QHotkey/qhotkey.pri +++ /dev/null @@ -1 +0,0 @@ -message(The pri file has been moved one directory up! use that one instead) diff --git a/README.md b/README.md index 47595e0..4058dfd 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ The QHotkey is a class that can be used to create hotkeys/global shortcuts, aka ## Building -QHotkey supports both Qt6 and Qt5. When using Qt6, version 6.2.0 or later required. It can be built by either the CMake or qmake building systems. +QHotkey supports both Qt6 and Qt5. When using Qt6, version 6.2.0 or later required. It can be built using the CMake building system. ### CMake @@ -29,17 +29,6 @@ $ cmake --build build # cmake --install build ``` -### qmake - -The major version of Qt is chosen by the qmake invocation itself, as the qmake executable is tied to a specific Qt version. The executable name can vary between operating systems. qmake example usage: - -``` -$ cd QHotkey -$ qmake -$ make -# make install -``` - ## Installation The package is providet as qpm package, [`de.skycoder42.qhotkey`](https://www.qpm.io/packages/de.skycoder42.qhotkey/index.html). You can install it either via qpmx (preferred) or directly via qpm. diff --git a/qhotkey.prc b/qhotkey.prc deleted file mode 100644 index d8e8ac0..0000000 --- a/qhotkey.prc +++ /dev/null @@ -1,15 +0,0 @@ -mac: LIBS += -framework Carbon -else:win32: LIBS += -luser32 -else:unix { - equals(QT_MAJOR_VERSION, 6) { - lessThan(QT_VERSION, 6.2.0) { - error("Qt 6.2.0 or greater is required when using Qt6") - } - } - else { - lessThan(QT_MAJOR_VERSION, 6) { - QT += x11extras - } - } - LIBS += -lX11 -} diff --git a/qhotkey.pri b/qhotkey.pri deleted file mode 100644 index 1dc2ae9..0000000 --- a/qhotkey.pri +++ /dev/null @@ -1,17 +0,0 @@ -CONFIG += C++11 - -PUBLIC_HEADERS += $$PWD/QHotkey/qhotkey.h \ - $$PWD/QHotkey/QHotkey - -HEADERS += $$PUBLIC_HEADERS \ - $$PWD/QHotkey/qhotkey_p.h - -SOURCES += $$PWD/QHotkey/qhotkey.cpp - -mac: SOURCES += $$PWD/QHotkey/qhotkey_mac.cpp -else:win32: SOURCES += $$PWD/QHotkey/qhotkey_win.cpp -else:unix: SOURCES += $$PWD/QHotkey/qhotkey_x11.cpp - -INCLUDEPATH += $$PWD/QHotkey - -include($$PWD/qhotkey.prc) From bb630252684d3556b79ac7a521616692f348fcf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20O=2E=20Cordero=20P=C3=A9rez?= Date: Mon, 20 May 2024 15:13:12 -0400 Subject: [PATCH 71/71] Fix: Prevent crash on Wayland when using Qt 6 (#97) --- QHotkey/qhotkey_x11.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/QHotkey/qhotkey_x11.cpp b/QHotkey/qhotkey_x11.cpp index d3ac1d1..d9d73f7 100644 --- a/QHotkey/qhotkey_x11.cpp +++ b/QHotkey/qhotkey_x11.cpp @@ -132,13 +132,16 @@ quint32 QHotkeyPrivateX11::nativeKeycode(Qt::Key keycode, bool &ok) #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) const QNativeInterface::QX11Application *x11Interface = qGuiApp->nativeInterface(); - Display *display = x11Interface->display(); #else const bool x11Interface = QX11Info::isPlatformX11(); - Display *display = QX11Info::display(); #endif if(x11Interface) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) + Display *display = x11Interface->display(); +#else + Display *display = QX11Info::display(); +#endif auto res = XKeysymToKeycode(display, keysym); if(res != 0) ok = true; pFad - Phonifier reborn

    Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

    Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


    Alternative Proxies:

    Alternative Proxy

    pFad Proxy

    pFad v3 Proxy

    pFad v4 Proxy

    Accessors
    CONSTANT
    FINAL