Qt Linux - Lesson 002. Global HotKey in Linux

Ubuntu, HotKey, linux, Qt, XCB, XLib

Work with the global keyboard hot keys in Windows is a trivial task than Linux, since this has WinAPI prepared methods that do not require a large amount of code. And each hotkey is set in line ID, in which the hot key can be removed.

In Linux / Unix, which uses the graphics server is the X11, with respect to Qt must use the function to register / unregister hotkeys from XLib library, but the process has to the values ​​obtained using XCB library functionality, which is being developed as an analogue XLib library, but is more low-level and written the C programming language. As in the case of Windows, for processing in the global hotkeys Qt 5 nativeEventFilter used method. I propose to make a separate class, inherited from QAbstractNativeEventFilter for processing hotkeys and set the filter to the entire application.

To set hotkeys to be used XKeysymToKeycode (to get the keys from KeySym sequence of code) and XGrabKey (to set the hotkey).

XUngrabKey function will be used for unregistration hotkey.

Project structure

  • GlobalHotkeyLinux.pro - the profile of the project;
  • mainwindow.h - header file of the main application window;
  • mainwindow.cpp - file source code of the main application window;
  • mainwindow.ui - file forms the main application window;
  • main.cpp - the main source file;
  • nativeeventfilter.h - header event filter file hotkeys;
  • nativeeventfilter.cpp - file source hotkeys event filter.


I draw your attention to the fact that in order to obtain information about the events of the X11 window server using Qt QX11Info class, and to use it you need to connect x11extras unit, but that may not be enough, as in the standard package Qt5 these libraries simply will not , so they will need to install the following command:

sudo apt-get install qtx11extras5-dev-tools

In addition to work with libraries and xcb xlib you will need to specify the configuration of the project in view of X11:

CONFIG    += link_pkgconfig

Then we get the profile with the following contents.

# Project created by QtCreator 2016-02-12T23:41:57

QT       += core gui
QT       += x11extras

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG    += c++11
CONFIG    += link_pkgconfig

TARGET = GlobalHotkeyLinux

SOURCES += main.cpp\
        mainwindow.cpp \

HEADERS  += mainwindow.h \

FORMS    += mainwindow.ui


In Qt, there are event filters classes that can be installed on the application window, or components directly on the entire application as we did this time. To do this, you need to create a class inherited from QAbstractNativeEventFilter, which is used to receive events from the operating system, which runs the application on Qt. Override the method natvieEventFilter, which will process and hotkey, and we make two methods: one to set the hotkey, and the second to turn it off.


#include <QObject>
#include <QAbstractNativeEventFilter>

class NativeEventFilter : public QObject, public QAbstractNativeEventFilter
    explicit NativeEventFilter(QObject *parent = 0);

    bool nativeEventFilter(const QByteArray &eventType, void *message, long *result);
    void setShortcut();     
    void unsetShortcut();   

    void activated();

public slots:



The whole point of creating a filter that we easily can register a hotkey using XLib library, while dismantling events have with XCB library because the Qt, receiving data from the X11, has no idea about them in the context of Xlib, and understand this data how XCB.

#include "nativeeventfilter.h"
#include <QVector>
#include <QX11Info>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <xcb/xcb.h>

    Display * m_display;        // Connect to Server X11
    Window m_win;               // Grabing window - in this case, the entire system will be
    int keycode;               
    unsigned int modifier;     

    /* Vector additional modifiers Num Lock, Caps lock
      * They are also taken into account in X11, you therefore need all the possible combinations
     * */
    QVector<quint32> maskModifiers(){
        return QVector<quint32>() << 0 << Mod2Mask << LockMask << (Mod2Mask | LockMask);

NativeEventFilter::NativeEventFilter(QObject *parent) : QObject(parent)
    m_display = QX11Info::display();        // Create a connection to the server
    m_win = DefaultRootWindow(m_display);   // and pull out of it captured by the window with a macro

bool NativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result)

    /* But event handling is built on the library instead of Xlib XCB.
     * Kind of like getting Qt event knows it as XCB events,
     * but does not know it as an event Xlib, although used more
     * Xlib easy syntax to set the hotkeys no one forbids us
     * */
    xcb_key_press_event_t *keyEvent = 0;

    //So we check that it was xcb event
    if (eventType == "xcb_generic_event_t") {
        // cast message xcb event
        xcb_generic_event_t *event = static_cast<xcb_generic_event_t *>(message);

        // check that a keystroke occurred
        if ((event->response_type & 127) == XCB_KEY_PRESS){

            // If so, then cast message keypress event
            keyEvent = static_cast<xcb_key_press_event_t *>(message);

            // Next, check whether it is necessary to hotkeys event
            foreach (quint32 maskMods, maskModifiers()) {
                if((keyEvent->state == (modifier | maskMods ))
                        &&  keyEvent->detail == keycode){
                    emit activated();   // and send a signal
                    return true;
    return false;

void NativeEventFilter::setShortcut()
    unsetShortcut();        /* First to alleged reinsurance disable hotkey,
                             * Despite the fact that the waste will be the first time in the parameters hotkey.
                             * */

    // get the key code of KeySym identify and connect to the X11 server
    keycode = XKeysymToKeycode(m_display, XK_E);
    modifier = ControlMask; // Зададим модификатор

    /* Now we go through all the possible combinations in view of Num Lock and Caps Lock, setting hotkeys
     * */
    foreach (quint32 maskMods, maskModifiers()) {
        XGrabKey(m_display,         // specify the connection to the X11
                 keycode ,          // keycode
                 modifier | maskMods,   // modifier with all the masks
                 m_win,             // grabing window
                 True,              // It is the owner of the application event. in this example it is not essential.
                 GrabModeAsync,     // Be sure to asynchronous processing mode, otherwise, risk of freeze system

void NativeEventFilter::unsetShortcut()
    // Проходим по всем возможным комбинациям и удаляем хоткей
    foreach (quint32 maskMods, maskModifiers()) {
                   modifier | maskMods,


The header file applications do not see anything special. Only a slot for receiving the signal and the filter itself, which will give the signal.


#include <QMainWindow>
#include "nativeeventfilter.h"

namespace Ui {
class MainWindow;

class MainWindow : public QMainWindow

    explicit MainWindow(QWidget *parent = 0);

private slots:
    void slotGlobalHotkey();

    Ui::MainWindow *ui;
    NativeEventFilter *nativeEventFilter;

#endif // MAINWINDOW_H


All that remains to do is to initialize the filter, set it to the entire application, connect the signal to the slot of the event handler and set the hotkey. Thus we get a working version of a global hotkey for Qt apps for linux.

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QApplication>
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent) :
    ui(new Ui::MainWindow)
    nativeEventFilter = new NativeEventFilter(this);    // Initialize filter
    qApp->installNativeEventFilter(nativeEventFilter);  // Install it on an application
    // connect the filter signal to a slot
    connect(nativeEventFilter, &NativeEventFilter::activated, this, &MainWindow::slotGlobalHotkey);
    nativeEventFilter->setShortcut();   // Устанавилваем хоткей

    delete ui;

void MainWindow::slotGlobalHotkey()
    // And informs the user if he want us to hit HotKey
    QMessageBox::information(this,"Global Hotkey", "Global Hotkey is worked", QMessageBox::Ok);

Archive of the project: GlobalHotkeyLinux


The result is an application that will respond to the global hotkey Ctrl + E and display a message that the hot key is working, even if you will roll application or will be working with another application. Just do not try to capture the pressing PrintScreen key. It will not work most likely. The reason is that when using XGrabKey try to capture some hot key, it will be captured only in the case if any other client application that has not captured the gripper hotkey on the target window. And when you consider that in the same distro Ubuntu already have an application to create screenshots, which just reacts to the PrintScreen key, you with 100% probability will not be able to intercept this key until you will kill this program, or any other way not force it to release the hotkey.

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
Support the author Donate


Only authorized users can post comments.
Please, Log in or Sign up
How to become an author?

Contribute to the evolution of the EVILEG community.

Learn how to become a site author.

Learn it

Good day, Dear Users!!!

I am Evgenii Legotckoi, developer of EVILEG. And it is my hobby project, which helps to learn programming another programmers and developers

If the site helped you, and you want also support the development of the site, than you can donate by following ways


Let me recommend you the excellent hosting on which EVILEG is located.

For many years, Timeweb has been proving his stability.

For projects on Django I recommend VDS hosting

View Hosting Timeweb
May 26, 2020, 11:29 a.m.
Artem Sun-Dun-Chan

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:50points,
  • Rating points-4
May 25, 2020, 11:33 a.m.
Mitja Nagibin

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:50points,
  • Rating points-4
May 25, 2020, 5:05 a.m.

C++ - Test 001. The first program and data types

  • Result:66points,
  • Rating points-1
Last comments
May 28, 2020, 3:14 p.m.
Evgenij Legotskoj

Qt/C++ - Lesson 039. How to paint stroke in QSqlTableModel by value in the column?

Ну в моём примере, который в статье сработало так model->setData(model->index(1, 1), 7); Поскольку model->index(1, 0) - это индекс колонки id, которая скрыта, поэтому…
May 28, 2020, 3:08 p.m.
Mihail A

Qt/C++ - Lesson 039. How to paint stroke in QSqlTableModel by value in the column?

Спасибо, завтра првоерю. А model->setData(model->index(1, 0), 7); Тоже заработало?
May 28, 2020, 3:06 p.m.
Evgenij Legotskoj

Qt/C++ - Lesson 039. How to paint stroke in QSqlTableModel by value in the column?

Да, метод data всё-таки влиял, я переписал его так и заработало удаление QVariant TableModel::data(const QModelIndex &idx, int role) const{ if (role == Qt::BackgroundColorRole) {…
May 28, 2020, 2:49 p.m.
Evgenij Legotskoj

Django - Tutorial 011. Adding comments to the site based on Django

Он более функциональный и его функционал объективно лучше поддерживается Django. Из первого, что приходит на ум: Это наличие полей типа Array Поддержка полей для JSON …
May 28, 2020, 2:42 p.m.

Django - Tutorial 011. Adding comments to the site based on Django

а в чем явное преимущество postgresql над mysql?)
Now discuss on the forum
May 29, 2020, 1:55 a.m.
Igor' Poroshin

QTablwView + QSqlQueryModel скрыть пустой столбец

Да, понятно. В данном случае лучше использовать серверную процедуру (если такие поддерживаются), в которой будет проверяться наличие всех пустых строк у нужного столбца и вызываться соответ…
May 28, 2020, 6:21 p.m.
Rovshan Gurbanov

Сборка под старые версии Android

У меня SDK почти все версии есть, NDK есть версии 10, 17, 21. Но собирается приложение только с NDK v21 под Android версии 7.0 и выше Версия Qt у меня 5.14.2
May 28, 2020, 7:58 a.m.
Evgenij Legotskoj

Освобождение памяти QMainWindow::setCentralWidget

Да, соглашусь. Просто удаление происходит позже, а не сразу.
May 28, 2020, 5:43 a.m.

При подключении к git как указать пароль?

Нужно сделать ssh-keygen и потом полученый из файла код скопировать в ssh ключ в бикбакете
May 28, 2020, 1:42 a.m.


Да, проблема ушла, спасибо.
© EVILEG 2015-2020
Recommend hosting TIMEWEB