File indexing completed on 2024-04-14 05:24:38

0001 /*
0002     SPDX-FileCopyrightText: 2019 Michail Vourlakos <mvourlakos@gmail.com>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 // local
0007 #include "modifiertracker.h"
0008 
0009 // Qt
0010 #include <QDebug>
0011 #include <QKeySequence>
0012 
0013 namespace Latte {
0014 namespace ShortcutsPart {
0015 
0016 ModifierTracker::ModifierTracker(QObject *parent)
0017     : QObject(parent)
0018 {
0019     init();
0020 }
0021 
0022 ModifierTracker::~ModifierTracker()
0023 {
0024 }
0025 
0026 void ModifierTracker::init()
0027 {
0028     m_metaPressedTimer.setSingleShot(true);
0029     m_metaPressedTimer.setInterval(700);
0030 
0031     m_pressed[Qt::Key_Super_L] = false;
0032     m_pressed[Qt::Key_Control] = false;
0033     m_pressed[Qt::Key_Alt] = false;
0034     m_pressed[Qt::Key_Shift] = false;
0035 
0036     connect(&m_metaPressedTimer, &QTimer::timeout, this, &ModifierTracker::metaModifierPressed);
0037 
0038     connect(&m_modifierKeyInfo, &KModifierKeyInfo::keyPressed, this, [&](Qt::Key key, bool state) {
0039         Qt::Key nKey = normalizeKey(key);
0040         //! ignore modifiers that we do not take into account
0041         if (!modifierIsTracked(nKey)) {
0042             return;
0043         }
0044 
0045         m_pressed[nKey] = state;
0046 
0047         if (nKey == Qt::Key_Super_L) {
0048             bool singleKey{singleModifierPressed(Qt::Key_Super_L)};
0049             if (state && singleKey) {
0050                 m_metaPressedTimer.start();
0051             } else if (!state || !singleKey) {
0052                 cancelMetaPressed();
0053             }
0054         } else {
0055             cancelMetaPressed();
0056         }
0057 
0058         emit modifiersChanged();
0059     });
0060 }
0061 
0062 
0063 bool ModifierTracker::modifierIsTracked(Qt::Key key)
0064 {
0065     if (m_blockedModifiers.contains(key)) {
0066         return false;
0067     }
0068 
0069     return (key == Qt::Key_Super_L || key == Qt::Key_Super_R || key == Qt::Key_Control || key == Qt::Key_Alt || key == Qt::Key_Shift);
0070 }
0071 
0072 void ModifierTracker::blockModifierTracking(Qt::Key key)
0073 {
0074     if (!m_blockedModifiers.contains(key)) {
0075         m_blockedModifiers.append(key);
0076     }
0077 }
0078 
0079 void ModifierTracker::unblockModifierTracking(Qt::Key key)
0080 {
0081     if (m_blockedModifiers.contains(key)) {
0082         m_blockedModifiers.removeAll(key);
0083     }
0084 }
0085 
0086 bool ModifierTracker::noModifierPressed()
0087 {
0088     for (const Qt::Key &modifier : m_pressed.keys()) {
0089         if ( m_pressed[modifier]) {
0090             return false;
0091         }
0092     }
0093 
0094     return true;
0095 }
0096 
0097 bool ModifierTracker::sequenceModifierPressed(const QKeySequence &seq)
0098 {
0099     if (seq.isEmpty()) {
0100         return false;
0101     }
0102 
0103     int mod = seq[seq.count() - 1] & Qt::KeyboardModifierMask;
0104 
0105     if ( ((mod & Qt::SHIFT) && m_pressed[Qt::Key_Shift])
0106          || ((mod & Qt::CTRL) && m_pressed[Qt::Key_Control])
0107          || ((mod & Qt::ALT) && m_pressed[Qt::Key_Alt])
0108          || ((mod & Qt::META) && m_pressed[Qt::Key_Super_L])) {
0109         return true;
0110     }
0111 
0112     return false;
0113 }
0114 
0115 bool ModifierTracker::singleModifierPressed(Qt::Key key)
0116 {
0117     for (const Qt::Key &modifier : m_pressed.keys()) {
0118         if ( (modifier != key && m_pressed[modifier])
0119              || (modifier == key && !m_pressed[modifier]) ) {
0120             return false;
0121         }
0122     }
0123 
0124     return true;
0125 }
0126 
0127 Qt::Key ModifierTracker::normalizeKey(Qt::Key key)
0128 {
0129     return ((key == Qt::Key_Super_L || key == Qt::Key_Super_R) ? Qt::Key_Super_L : key);
0130 }
0131 
0132 void ModifierTracker::cancelMetaPressed()
0133 {
0134     m_metaPressedTimer.stop();
0135 }
0136 
0137 
0138 }
0139 }