Global shortcut in QML

1.1k views Asked by At

I am trying to make an application in QML (Qt 5.5) that is always running and shows up when the user presses alt+space.

I have tried using the Action class in QML, but it only works when the window has the focus, not when the window is not visible.

I've also tried QShortcut (which is not ideal, since my application is not based on QWidget) but I had no results.

Also using eventFilter on QApplication doesn't seem to work when the window is not visible.

Is there a way of doing it?

3

There are 3 answers

0
LtWorf On BEST ANSWER

I have resorted to use XGrab and create a subclass of QThread (because of the separate event loop) to integrate it with the Qt signals.

shortcutactivator.h

#ifndef SHORTCUTACTIVATOR_H
#define SHORTCUTACTIVATOR_H

#include <QThread>

class ShortcutActivator : public QThread
{
    Q_OBJECT
public:
    void run();
signals:
    void activated();

public slots:
    void end();
private:
    bool terminate = false;
};

#endif // SHORTCUTACTIVATOR_H

shortcutactivator.cpp

#include "shortcutactivator.h"

#include <X11/Xlib.h>
#include <X11/Xutil.h>

void ShortcutActivator::end() {
    this->terminate = true;
}

void ShortcutActivator::run() {
    Display*    dpy     = XOpenDisplay(0);
    Window      root    = DefaultRootWindow(dpy);
    XEvent      ev;

    unsigned int    modifiers       = Mod1Mask; // AnyModifier; // ControlMask | ShiftMask | AnyModifier;
    int             keycode         = XKeysymToKeycode(dpy,XK_space);
    Window          grab_window     =  root;
    Bool            owner_events    = False;
    int             pointer_mode    = GrabModeAsync;
    int             keyboard_mode   = GrabModeAsync;

    XGrabKey(dpy, keycode, modifiers, grab_window, owner_events, pointer_mode, keyboard_mode);
    XGrabKey(dpy, keycode, modifiers | Mod2Mask , grab_window, owner_events, pointer_mode, keyboard_mode);
    XGrabKey(dpy, keycode, modifiers | LockMask, grab_window, owner_events, pointer_mode, keyboard_mode);
    XGrabKey(dpy, keycode, modifiers | LockMask | Mod2Mask, grab_window, owner_events, pointer_mode, keyboard_mode);

    XSelectInput(dpy, root, KeyPressMask );
    while(true)
    {
        XNextEvent(dpy, &ev);
        switch(ev.type)
        {
            case KeyPress:
                printf("Key pressed\n");
                emit this->activated();
            default:
                break;
        }

        if(this->terminate)
            break;
    }

    XCloseDisplay(dpy);
    XUngrabKey(dpy,keycode,modifiers,grab_window);
    XUngrabKey(dpy,keycode,modifiers | Mod2Mask,grab_window);
    XUngrabKey(dpy,keycode,modifiers| LockMask,grab_window);
    XUngrabKey(dpy,keycode,modifiers | LockMask | Mod2Mask,grab_window);
}
2
Stefan Reinhardt On

I've never implemented an app in QML but I think what you are looking for is the Global Shortcut Module (http://libqxt.bitbucket.org/doc/tip/qxtglobalshortcut.html). It is a "A global shortcut triggers even if the application is not active."

1
dtech On

If a system wide global shortcut is what you need, I don't recall Qt having anything to offer out of the box, much less QML.

You will have to resort to the platform specific APIs to get this thing done. Like for example on windows that would be the BOOL WINAPI RegisterHotKey() function.