File indexing completed on 2024-06-16 04:16:03
0001 /* 0002 * SPDX-FileCopyrightText: 2015 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_custom_modifiers_catcher.h" 0008 0009 #include <QSet> 0010 0011 #include "input/kis_extended_modifiers_mapper.h" 0012 #include <QDebug> 0013 #include <QEvent> 0014 #include <QKeyEvent> 0015 0016 0017 struct KisCustomModifiersCatcher::Private 0018 { 0019 Private(QObject *_trackedObject) : trackedObject(_trackedObject) {} 0020 0021 QObject *trackedObject; 0022 0023 QSet<Qt::Key> trackedKeys; 0024 QHash<QString, Qt::Key> idToKeyMap; 0025 QSet<Qt::Key> pressedKeys; 0026 0027 void reset() { 0028 // something went wrong! 0029 pressedKeys.clear(); 0030 } 0031 }; 0032 0033 0034 KisCustomModifiersCatcher::KisCustomModifiersCatcher(QObject *parent) 0035 : QObject(parent), 0036 m_d(new Private(parent)) 0037 { 0038 if (m_d->trackedObject) { 0039 parent->installEventFilter(this); 0040 } 0041 } 0042 0043 KisCustomModifiersCatcher::~KisCustomModifiersCatcher() 0044 { 0045 } 0046 0047 void KisCustomModifiersCatcher::addModifier(const QString &id, Qt::Key modifier) 0048 { 0049 m_d->idToKeyMap.insert(id, modifier); 0050 m_d->trackedKeys.insert(modifier); 0051 0052 m_d->reset(); 0053 } 0054 0055 bool KisCustomModifiersCatcher::modifierPressed(const QString &id) 0056 { 0057 if (!m_d->idToKeyMap.contains(id)) { 0058 qWarning() << "KisCustomModifiersCatcher::modifierPressed(): unexpected modifier id:" << id; 0059 return false; 0060 } 0061 return m_d->pressedKeys.contains(m_d->idToKeyMap[id]); 0062 } 0063 0064 bool KisCustomModifiersCatcher::eventFilter(QObject* object, QEvent* event) 0065 { 0066 if (object != m_d->trackedObject) return false; 0067 0068 switch (event->type()) { 0069 case QEvent::ShortcutOverride: { 0070 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event); 0071 0072 if (keyEvent->isAutoRepeat()) break; 0073 0074 Qt::Key key = KisExtendedModifiersMapper::workaroundShiftAltMetaHell(keyEvent); 0075 0076 if (m_d->trackedKeys.contains(key)) { 0077 if (m_d->pressedKeys.contains(key)) { 0078 m_d->reset(); 0079 } else { 0080 m_d->pressedKeys.insert(key); 0081 } 0082 } 0083 break; 0084 } 0085 case QEvent::KeyRelease: { 0086 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event); 0087 0088 if (keyEvent->isAutoRepeat()) break; 0089 0090 Qt::Key key = KisExtendedModifiersMapper::workaroundShiftAltMetaHell(keyEvent); 0091 0092 if (m_d->trackedKeys.contains(key)) { 0093 if (!m_d->pressedKeys.contains(key)) { 0094 m_d->reset(); 0095 } else { 0096 m_d->pressedKeys.remove(key); 0097 } 0098 } 0099 0100 break; 0101 } 0102 case QEvent::FocusIn: { 0103 m_d->reset(); 0104 0105 { // Emulate pressing of the key that are already pressed 0106 KisExtendedModifiersMapper mapper; 0107 0108 Qt::KeyboardModifiers modifiers = mapper.queryStandardModifiers(); 0109 Q_FOREACH (Qt::Key key, mapper.queryExtendedModifiers()) { 0110 QKeyEvent kevent(QEvent::ShortcutOverride, key, modifiers); 0111 eventFilter(object, &kevent); 0112 } 0113 } 0114 } 0115 default: 0116 break; 0117 } 0118 0119 return false; 0120 }