Privacy policyContactsAbout siteOpinionsGitHubDonate
© EVILEG 2015-2018
Recommend hosting

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

  • - 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.


Only authorized users can post comments.
Please, Log in or Sign up
Feb. 18, 2019, 3:39 p.m.

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

  • Result:73points,
  • Rating points1
Feb. 15, 2019, 1:03 p.m.
Николай Булахтин

C++ - Test 002. Constants

  • Result:25points,
  • Rating points-10
Last comments
Feb. 14, 2019, 6:41 p.m.

Спасибо огромное! Заработало!
Feb. 12, 2019, 9:26 a.m.

Сам разборался, спасибо.
Feb. 12, 2019, 8:19 a.m.

День добрый! Можешь выложить форму mainwindow.ui от урока? Заранее спасибо
Feb. 11, 2019, 10:51 a.m.
Евгений Легоцкой

Нет, у меня проблема с жёстким диском случилась, занимался восстановлением ПК, ещё пару вечеров придётся этим заниматься, увы.
Now discuss on the forum
Feb. 17, 2019, 5:28 p.m.
Евгений Легоцкой

Добрый день. Очень извиняюсь за долгий ответ Первое, что нашёл, так это необходимость перерисовать чекбокс. void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem ...
Feb. 15, 2019, 3:36 p.m.
Евгений Легоцкой

Ну я тут нашёл одно решение, но сам его не проверял. Вам нужно помещать фамилии скорее всего в ячейки заголовка, и потом просто перерисовывать их QHeaderView * header = m_ui->tableWidget...
Feb. 15, 2019, 7:53 a.m.
Евгений Легоцкой

Добрый день! Не работал с remoteobjects, поэтому глянул документацию, чтобы рассмотреть, что это за зверь. После просмотра документации сложилось стойкой впечатление, что это вполне возм...
Feb. 14, 2019, 6:28 p.m.

Нашел решение на Java. Удалось интегрировать в проект сервиса на Qt, теперь из Qt запускаю Java-код акселерометра.
Join us in social networks

For registered users on the site there is a minimum amount of advertising