File indexing completed on 2024-04-28 05:52:14

0001 // SPDX-License-Identifier: LGPL-2.1-only
0002 
0003 #include "qglobalshortcut.h"
0004 #include <QCoreApplication>
0005 
0006 QMultiHash<quint32, QGlobalShortcut*> QGlobalShortcut::shortcuts_;
0007 QGlobalShortcut::QGlobalShortcutEventFilter QGlobalShortcut::global_shortcut_event_;
0008 
0009 QGlobalShortcut::QGlobalShortcut(QObject* parent)
0010     : QObject(parent)
0011 {
0012     initialize();
0013 }
0014 
0015 QGlobalShortcut::QGlobalShortcut(const QKeySequence &keyseq, QObject *parent)
0016     : QObject(parent)
0017 {
0018     initialize();
0019     setKey(keyseq);
0020 }
0021 
0022 void QGlobalShortcut::initialize() {
0023     static bool initialized = false;
0024     if (!initialized) {
0025         qApp->installNativeEventFilter(&global_shortcut_event_);
0026         initialized = true;
0027     }
0028 }
0029 
0030 QGlobalShortcut::~QGlobalShortcut() {
0031     unsetKey();
0032 }
0033 
0034 QKeySequence QGlobalShortcut::key() const
0035 {
0036     return keyseq_;
0037 }
0038 
0039 void QGlobalShortcut::setKey(const QKeySequence& keyseq)
0040 {
0041     if (!keyseq_.isEmpty()) {
0042         unsetKey();
0043     }
0044     quint32 keyid = calcId(keyseq);
0045     if (shortcuts_.count(keyid) == 0) {
0046         quint32 keycode = toNativeKeycode(getKey(keyseq));
0047         quint32 mods = toNativeModifiers(getMods(keyseq));
0048         registerKey(keycode, mods, keyid);
0049     }
0050     this->keyseq_ = keyseq;
0051     shortcuts_.insert(keyid, this);
0052 }
0053 
0054 void QGlobalShortcut::unsetKey() {
0055     quint32 keyid = calcId(keyseq_);
0056     if (shortcuts_.remove(keyid, this) > 0) {
0057         if (shortcuts_.count(keyid) == 0) {
0058             quint32 keycode = toNativeKeycode(getKey(keyseq_));
0059             quint32 mods = toNativeModifiers(getMods(keyseq_));
0060             unregisterKey(keycode, mods, keyid);
0061         }
0062     }
0063 }
0064 
0065 bool QGlobalShortcut::activate(quint32 id) {
0066     if (shortcuts_.contains(id)) {
0067         for (QGlobalShortcut* s : shortcuts_.values(id)) {
0068             emit s->activated();
0069         }
0070         return true;
0071     }
0072     return false;
0073 }
0074 
0075 quint32 QGlobalShortcut::calcId(const QKeySequence& keyseq) {
0076     quint32 keycode = toNativeKeycode(getKey(keyseq));
0077     quint32 mods    = toNativeModifiers(getMods(keyseq));
0078     return calcId(keycode, mods);
0079 }
0080 
0081 #ifndef Q_OS_UNIX
0082 quint32 QGlobalShortcut::calcId(quint32 k, quint32 m) {
0083     return k | m;
0084 }
0085 #endif
0086 
0087 Qt::Key QGlobalShortcut::getKey(const QKeySequence& keyseq) {
0088     if (keyseq.isEmpty()) {
0089         return Qt::Key(0);
0090     }
0091     return Qt::Key(keyseq[0] & ~Qt::KeyboardModifierMask);
0092 }
0093 
0094 Qt::KeyboardModifiers QGlobalShortcut::getMods(const QKeySequence& keyseq) {
0095     if (keyseq.isEmpty()) {
0096         return Qt::KeyboardModifiers();
0097     }
0098     return Qt::KeyboardModifiers(keyseq[0] & Qt::KeyboardModifierMask);
0099 }