QML 中的全局快捷方式

Global shortcut in QML

我正在尝试在 QML (Qt 5.5) 中创建一个始终 运行 并在用户按下 alt+space 时显示的应用程序。

我试过在 QML 中使用 Action class,但它只在 window 有焦点时有效,而不是在 window 不可见时。

我也尝试过 QShortcut(这并不理想,因为我的应用程序不是基于 QWidget 的)但是我没有结果。

当 window 不可见时,在 QApplication 上使用 eventFilter 似乎也不起作用。

有办法吗?

我从未在 QML 中实现过应用程序,但我认为您正在寻找的是全局快捷方式模块 (http://libqxt.bitbucket.org/doc/tip/qxtglobalshortcut.html)。 这是一个"A global shortcut triggers even if the application is not active."

如果系统范围的全局快捷方式是您所需要的,我不记得 Qt 有任何开箱即用的功能,更不用说 QML 了。

您将不得不求助于平台特定的 API 来完成这件事。例如 windows 上的 BOOL WINAPI RegisterHotKey() 函数。

我已经求助于使用 XGrab 并创建 QThread 的子类(因为单独的事件循环)以将其与 Qt 信号集成。

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);
}