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 }