В процессе изучения вопросов с глобальными хоткеями для Linux и Windows я написал свой велосипед для быстрой регистрации хоткеев. Получившаяся библиотека называется QGlobalShortcut и выложена на GitHub под лицензией LGPLv2. Библиотека поддерживает платформы Windows и Linux/Unix (которые используют X11)
Логика работы класса QGlobalShortcut, который предоставляется данной библиотекой, похожа на логику работы класса QShortcut, хотя явно и не дотягивает до данного класса по ряду параметров, но главное, что выполняет свою основную функцию. А именно, зарегистрировать глобальный HotKey и выслать сигнал о его активации.
На данный момент для использования библиотеки необходимо поместить заголовочные файлы и файлы исходных кодов в Ваш проект, а также прописать дополнительную информацию в профайл проекта.
Получить библиотеку
Настройка проекта
Библиотека состоит из одного заголовочного файла и двух файлов исходных кодов в зависимости от платформы (Windows, X11). Не считая README и т.д.
Библиотека использует стандарт языка C++11, поэтому обязательно необходимо сконфигурировать проект на данный стандарт или выше. Для linux/unix необходимо использовать модуль x11extras, который скорее всего необходимо будет установить отдельно, поскольку Qt по умолчанию не имеет в поставке данного модуля. Также необходимо будет сконфигурировать проект на использование библиотек для работы с XLib и XCB.
CONFIG += c++11 linux { QT += x11extras CONFIG += link_pkgconfig PKGCONFIG += x11 } win32: SOURCES += win/qglobalshortcut.cpp linux: SOURCES += x11/qglobalshortcut.cpp HEADERS += qglobalshortcut.h
Public functions
QKeySequence shortcut()
Метод возвращает установленную последовательность сочетаний горячих клавиш QKeySequence. Если последовательность не установлена, то возвращается пустая последовательность QKeySequence("").
bool isEmpty()
Метод проверяет, установлена ли последовательность горячих клавиш или нет.
bool isEnabled()
Метод проверяет, включён ли хоткей или нет. Сочетание горячих клавиш может быть установлено, тогда isEmpty() будет возвращать true, но их срабатывание может быть выключено. То есть сигнал активации хоткея не будет генерироваться.
bool setShortcut(const QKeySequence &keySequence)
Метод является слотом и устанавливает последовательность горячих клавиш. При этом, если QKeySequence содержит несколько сочетаний клавиш, то они все будут зарегистрированы.
bool unsetShortcut()
Метод является слотом и удаляет сочетание горячих клавиш, если оно было установлено.
void setEnabled(bool enable)
Метод является слотом и служит для включения и выключения активации сочетания горячих клавиш.
Signals
void activated()
Сигнал активации хоткея, срабатывает тогда, когда хоткей установлен и включён.
Использование
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include "qglobalshortcut.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); public slots: void slotFirst(); void slotSecond(); private: Ui::MainWindow *ui; QGlobalShortcut *shortcutFirst; QGlobalShortcut *shortcutSecond; }; #endif // MAINWINDOW_H
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); shortcutFirst = new QGlobalShortcut(this); connect(shortcutFirst, &QGlobalShortcut::activated, this, &MainWindow::slotFirst); shortcutFirst->setShortcut(QKeySequence("Ctrl+E")); shortcutSecond = new QGlobalShortcut(this); connect(shortcutSecond, &QGlobalShortcut::activated, this, &MainWindow::slotSecond); shortcutSecond->setShortcut(QKeySequence("Ctrl+G")); } MainWindow::~MainWindow() { delete ui; } void MainWindow::slotFirst() { qDebug() << "First"; } void MainWindow::slotSecond() { qDebug() << "Second"; }
Рекомендации к применению
При создании экземпляра класса QGlobalShortcut создаётся nativeEventFilter, который устанавливается на всё приложение. При этом число фильтров в приложении не ограничено (то есть Вы можете создать любое количество глобальных хоткеев с помощью данного класса), но фильтр установленный последним, будет срабатывать первым. При этом использовать данный класс можно в любом месте приложения.
При этом важно понимать, что при использовании данного класса нельзя быть точно уверенным в какой именно последовательности будут установлены все фильтры, что может влиять на производительность приложения, в котором используется проверка иных событий операционной системы, а не только глобальных горячих клавиш. То есть, если Вы уже используете класс, унаследованный от QAbstractNativeEventFilter, и установили данный фильтр на приложение для обработки ряда событий системы с помощью него, то, возможно, имеет смысл не использовать библиотеку в лоб, а применить часть программного кода библиотеки в Вашем уже существующем классе.