/* SPDX-FileCopyrightText: 2008 Michael Jansen SPDX-License-Identifier: LGPL-2.0-or-later */ #ifndef GLOBALSHORTCUTSREGISTRY_H #define GLOBALSHORTCUTSREGISTRY_H #include "kglobalaccel.h" #include "component.h" #include "kserviceactioncomponent.h" #include #include #include #include #include #include #include #include "kglobalaccel_export.h" class Component; class GlobalShortcut; class KGlobalAccelInterface; /** * Global Shortcut Registry. * * Shortcuts are registered by component. A component is for example kmail or * amarok. * * A component can have contexts. Currently on plasma is planned to support * that feature. A context enables plasma to keep track of global shortcut * settings when switching containments. * * A shortcut (WIN+x) can be registered by one component only. The component * is allowed to register it more than once in different contexts. * * @author Michael Jansen */ class KGLOBALACCEL_EXPORT GlobalShortcutsRegistry : public QObject { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.KdedGlobalAccel.GlobalShortcutsRegistry") public: /** * Use GlobalShortcutsRegistry::self() * * @internal */ GlobalShortcutsRegistry(); ~GlobalShortcutsRegistry() override; /** * Activate all shortcuts having their application present. */ void activateShortcuts(); /** * Returns a list of D-Bus paths of registered Components. * * The returned paths are absolute (i.e. no need to prepend anything). */ QList componentsDbusPaths() const; /** * Returns a list of QStringLists (one string list per registered component, * with each string list containing four strings, one for each enumerator in * KGlobalAccel::actionIdFields). */ QList allComponentNames() const; /** * Return the root dbus path for the registry. */ QDBusObjectPath dbusPath() const; /** * Deactivate all currently active shortcuts. */ void deactivateShortcuts(bool temporarily = false); /** */ Component *getComponent(const QString &uniqueName); /** * Get the shortcut corresponding to key. Active and inactive shortcuts * are considered. But if the matching application uses contexts only one * shortcut is returned. * * @see getShortcutsByKey(int key) */ GlobalShortcut *getShortcutByKey(const QKeySequence &key, KGlobalAccel::MatchType type = KGlobalAccel::MatchType::Equal) const; /** * Get the shortcuts corresponding to key. Active and inactive shortcuts * are considered. * * @see getShortcutsByKey(int key) */ QList getShortcutsByKey(const QKeySequence &key, KGlobalAccel::MatchType type) const; /** * Checks if @p shortcut is available for @p component. * * It is available if not used by another component in any context or used * by @p component only in not active contexts. */ bool isShortcutAvailable(const QKeySequence &shortcut, const QString &component, const QString &context) const; static GlobalShortcutsRegistry *self(); bool registerKey(const QKeySequence &key, GlobalShortcut *shortcut); void setDBusPath(const QDBusObjectPath &path); bool unregisterKey(const QKeySequence &key, GlobalShortcut *shortcut); public Q_SLOTS: void clear(); void loadSettings(); void writeSettings(); // Grab the keys void grabKeys(); // Ungrab the keys void ungrabKeys(); private: friend struct KGlobalAccelDPrivate; friend class Component; friend class KGlobalAccelInterface; Component *createComponent(const QString &uniqueName, const QString &friendlyName); KServiceActionComponent *createServiceActionComponent(const QString &uniqueName); KServiceActionComponent *createServiceActionComponent(KService::Ptr service); void migrateConfig(); void migrateKHotkeys(); void scheduleRefreshServices(); void refreshServices(); void detectAppsWithShortcuts(); static void unregisterComponent(Component *component); using ComponentPtr = std::unique_ptr; Component *registerComponent(ComponentPtr component); // called by the implementation to inform us about key presses // returns true if the key was handled bool keyPressed(int keyQt); bool keyReleased(int keyQt); bool pointerPressed(Qt::MouseButtons pointerButtons); bool axisTriggered(int axis); bool processKey(int keyQt); QHash _active_keys; QKeySequence _active_sequence; QHash _keys_count; Qt::KeyboardModifiers m_currentModifiers; // State machine: // Any -> PressingModifierOnly when a modifier is pressed // PressingModifierOnly -> ReleasingModifierOnly when modifier keys are released // ReleasingModifierOnly -> Normal when other keys are pressed // ReleasingModifierOnly -> Normal when all keys are released, and when a non-modifier key is pressed // Modifier-only shortcuts are triggered in ReleasingModifierOnly state, if all keys are released // and the time since the first release is less than some threshold enum { Normal, PressingModifierOnly, ReleasingModifierOnly } m_state = Normal; void resetModifierOnlyState() { m_state = Normal; } using ComponentVec = std::vector; ComponentVec m_components; ComponentVec::const_iterator findByName(const QString &name) const { return std::find_if(m_components.cbegin(), m_components.cend(), [&name](const ComponentPtr &comp) { return comp->uniqueName() == name; }); } KGlobalAccelInterface *_manager = nullptr; mutable KConfig _config; QDBusObjectPath _dbusPath; GlobalShortcut *m_lastShortcut = nullptr; QTimer m_refreshServicesTimer; }; #endif /* #ifndef GLOBALSHORTCUTSREGISTRY_H */