Commit 6030c156 authored by abbycin's avatar abbycin

add test

parents
Pipeline #45 failed with stages
in 8 seconds
# C++ objects and libs
dest
*.slo
*.lo
*.o
*.a
*.la
*.lai
*.so
*.dll
*.dylib
# Qt-es
*.pro.user
*.pro.user.*
moc_*.cpp
qrc_*.cpp
Makefile
*-build-*
original repo: https://github.com/mitei/qglobalshortcut
qglobalshortcut
===============
Qt global-shortcut class
* supports Qt5.0 later.
* supports Windows and X11. (I don't have Mac.)
* not a library. (copy src/ to your project directly.)
* You can use this without any restriction.
### Usage
add to your .pro like this
```plain
QT = core gui widgets
unix:QT = x11extras
unix:LIBS += -lX11 -lxcb
unix:QMAKE_CXXFLAGS += "-std=c++11"
HEADERS += \
src/qglobalshortcut.h
SOURCES += \
src/qglobalshortcut.cc
win32:SOURCES += src/qglobalshortcut_win.cc
unix:SOURCES += src/qglobalshortcut_x11.cc
#macx:SOURCES += src/qglobalshortcut_macx.cc
```
`QGlobalShortcut` class has some method like `QShortcut` class.
```cpp
class QGlobalShortcut : public QObject {
public:
explicit QGlobalShortcut(QObject* parent = nullptr);
explicit QGlobalShortcut(const QKeySequence& keyseq, QObject* parent = nullptr);
QKeySequence key() const;
void setKey(const QKeySequence& keyseq);
signals:
void activated();
};
```
use this as follows:
```cpp
QGlobalShortcut gs;
gs.setKey(QKeySequence("Alt+Ctrl+Space"));
connect(&gs, SIGNAL(activated()), ...);
```
#ifndef GLOBAL_HOTKEY_GLOBAL_H
#define GLOBAL_HOTKEY_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(GLOBAL_HOTKEY_LIBRARY)
# define GLOBAL_HOTKEY_EXPORT Q_DECL_EXPORT
#else
# define GLOBAL_HOTKEY_EXPORT Q_DECL_IMPORT
#endif
#endif // GLOBAL_HOTKEY_GLOBAL_H
QT = core gui widgets
TARGET = ghk
TEMPLATE = lib
CONFIG += c++11
DEFINES += GLOBAL_HOTKEY_LIBRARY
DESTDIR = $$PWD/../dest
HEADERS += \
qglobalshortcut.h \
global_hotkey_global.h
SOURCES += \
qglobalshortcut.cc
win32 {
SOURCES += qglobalshortcut_win.cc
LIBS += -luser32
}
linux {
SOURCES += qglobalshortcut_x11.cc
QT = x11extras
LIBS += -lX11 -lxcb
QMAKE_RPATHDIR = .
}
#include "qglobalshortcut.h"
#include <QCoreApplication>
QMultiHash<quint32, QGlobalShortcut*> QGlobalShortcut::shortcuts_;
QGlobalShortcut::QGlobalShortcutEventFilter QGlobalShortcut::global_shortcut_event_;
QGlobalShortcut::QGlobalShortcut(QObject* parent)
: QObject(parent)
{
initialize();
}
QGlobalShortcut::QGlobalShortcut(const QKeySequence &keyseq, QObject *parent)
: QObject(parent)
{
initialize();
setKey(keyseq);
}
void QGlobalShortcut::initialize() {
static bool initialized = false;
if (!initialized) {
qApp->installNativeEventFilter(&global_shortcut_event_);
initialized = true;
}
}
QGlobalShortcut::~QGlobalShortcut() {
unsetKey();
}
QKeySequence QGlobalShortcut::key() const
{
return keyseq_;
}
void QGlobalShortcut::setKey(const QKeySequence& keyseq)
{
if (!keyseq_.isEmpty()) {
unsetKey();
}
quint32 keyid = calcId(keyseq);
if (shortcuts_.count(keyid) == 0) {
quint32 keycode = toNativeKeycode(getKey(keyseq));
quint32 mods = toNativeModifiers(getMods(keyseq));
registerKey(keycode, mods, keyid);
}
this->keyseq_ = keyseq;
shortcuts_.insert(keyid, this);
}
void QGlobalShortcut::unsetKey() {
quint32 keyid = calcId(keyseq_);
if (shortcuts_.remove(keyid, this) > 0) {
if (shortcuts_.count(keyid) == 0) {
quint32 keycode = toNativeKeycode(getKey(keyseq_));
quint32 mods = toNativeModifiers(getMods(keyseq_));
unregisterKey(keycode, mods, keyid);
keyseq_ = QKeySequence(); // clear
}
}
}
bool QGlobalShortcut::activate(quint32 id) {
if (shortcuts_.contains(id)) {
foreach (QGlobalShortcut* s, shortcuts_.values(id)) {
emit s->activated();
}
return true;
}
return false;
}
quint32 QGlobalShortcut::calcId(const QKeySequence& keyseq) {
quint32 keycode = toNativeKeycode(getKey(keyseq));
quint32 mods = toNativeModifiers(getMods(keyseq));
return calcId(keycode, mods);
}
#ifndef Q_OS_UNIX
quint32 QGlobalShortcut::calcId(quint32 k, quint32 m) {
return k | m;
}
#endif
Qt::Key QGlobalShortcut::getKey(const QKeySequence& keyseq) {
if (keyseq.isEmpty()) {
return Qt::Key(0);
}
return Qt::Key(keyseq[0] & ~Qt::KeyboardModifierMask);
}
Qt::KeyboardModifiers QGlobalShortcut::getMods(const QKeySequence& keyseq) {
if (keyseq.isEmpty()) {
return Qt::KeyboardModifiers(0);
}
return Qt::KeyboardModifiers(keyseq[0] & Qt::KeyboardModifierMask);
}
#pragma once
#include "global_hotkey_global.h"
#include <QObject>
#include <QMultiHash>
#include <QAbstractNativeEventFilter>
#include <QKeySequence>
class GLOBAL_HOTKEY_EXPORT QGlobalShortcut : public QObject {
Q_OBJECT
Q_PROPERTY(QKeySequence key READ key WRITE setKey)
//Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
private:
class QGlobalShortcutEventFilter : public QAbstractNativeEventFilter {
public:
bool nativeEventFilter(const QByteArray& eventType, void* message, long* result);
};
public:
explicit QGlobalShortcut(QObject* parent = nullptr);
explicit QGlobalShortcut(const QKeySequence& keyseq, QObject* parent = nullptr);
~QGlobalShortcut();
bool nativeEventFilter(const QByteArray& event_type, void* message, long* result);
QKeySequence key() const;
void setKey(const QKeySequence& keyseq);
void unsetKey();
//bool isEnabled() const; void setEnabled(bool on);
signals:
void activated();
private:
QKeySequence keyseq_;
void initialize();
private:
static QGlobalShortcutEventFilter global_shortcut_event_;
/* quint32 keyid
QGlobalShortcut* shortcut */
static QMultiHash<quint32, QGlobalShortcut*> shortcuts_;
static bool activate(quint32 id);
static inline quint32 calcId(const QKeySequence& keyseq);
static inline quint32 calcId(quint32 k, quint32 m);
static inline Qt::Key getKey(const QKeySequence& keyseq);
static inline Qt::KeyboardModifiers getMods(const QKeySequence& keyseq);
static quint32 toNativeKeycode(Qt::Key k);
static quint32 toNativeModifiers(Qt::KeyboardModifiers m);
static void registerKey(quint32 k, quint32 m, quint32 id);
static void unregisterKey(quint32 k, quint32 m, quint32 id);
};
#include "qglobalshortcut.h"
#include <QKeySequence>
quint32 QGlobalShortcut::toNativeKeycode(Qt::Key k) {
// TODO
}
quint32 QGlobalShortcut::toNativeModifiers(Qt::KeyboardModifiers m) {
// TODO
}
void QGlobalShortcut::registerKey(quint32 k, quint32 m) {
// TODO
}
void QGlobalShortcut::unregisterKey(quint32 k, quint32 m) {
// TODO
}
#include "qglobalshortcut.h"
#include <QKeySequence>
#include <Windows.h>
bool QGlobalShortcut::QGlobalShortcutEventFilter::nativeEventFilter(const QByteArray &/*event_type*/,
void *message, long*)
{
MSG* msg = static_cast<MSG*>(message);
if (msg->message == WM_HOTKEY) {
quint32 id = static_cast<quint32>(msg->wParam);
activate(id);
return true;
}
return false;
}
quint32 QGlobalShortcut::toNativeKeycode(Qt::Key k) {
// F1 ~ F24
if (k >= Qt::Key_F1 && k <= Qt::Key_F24)
return VK_F1 + (k - Qt::Key_F1);
// 0 ~ 9
if (k >= Qt::Key_0 && k <= Qt::Key_9)
return k;
// A ~ Z
if (k >= Qt::Key_A && k <= Qt::Key_Z)
return k;
switch (k) {
case Qt::Key_Escape:
return VK_ESCAPE;
case Qt::Key_Tab:
case Qt::Key_Backtab:
return VK_TAB;
case Qt::Key_Backspace:
return VK_BACK;
case Qt::Key_Return:
case Qt::Key_Enter:
return VK_RETURN;
case Qt::Key_Insert:
return VK_INSERT;
case Qt::Key_Delete:
return VK_DELETE;
case Qt::Key_Pause:
return VK_PAUSE;
case Qt::Key_Print:
return VK_PRINT;
case Qt::Key_Clear:
return VK_CLEAR;
case Qt::Key_Home:
return VK_HOME;
case Qt::Key_End:
return VK_END;
case Qt::Key_Left:
return VK_LEFT;
case Qt::Key_Up:
return VK_UP;
case Qt::Key_Right:
return VK_RIGHT;
case Qt::Key_Down:
return VK_DOWN;
case Qt::Key_PageUp:
return VK_PRIOR;
case Qt::Key_PageDown:
return VK_NEXT;
case Qt::Key_Space:
return VK_SPACE;
case Qt::Key_Asterisk:
return VK_MULTIPLY;
case Qt::Key_Plus:
return VK_ADD;
case Qt::Key_Comma:
return VK_SEPARATOR;
case Qt::Key_Minus:
return VK_SUBTRACT;
case Qt::Key_Slash:
return VK_DIVIDE;
case Qt::Key_Backslash:
return VK_OEM_102; // ?
case Qt::Key_MediaNext:
return VK_MEDIA_NEXT_TRACK;
case Qt::Key_MediaPrevious:
return VK_MEDIA_PREV_TRACK;
case Qt::Key_MediaPlay:
return VK_MEDIA_PLAY_PAUSE;
case Qt::Key_MediaStop:
return VK_MEDIA_STOP;
//case Qt::Key_MediaLast: // ??
//case Qt::Key_MediaRecord: // ??
case Qt::Key_VolumeDown:
return VK_VOLUME_DOWN;
case Qt::Key_VolumeUp:
return VK_VOLUME_UP;
case Qt::Key_VolumeMute:
return VK_VOLUME_MUTE;
default:
return 0;
}
}
quint32 QGlobalShortcut::toNativeModifiers(Qt::KeyboardModifiers m) {
quint32 mods = 0;
if (m & Qt::AltModifier) mods |= MOD_ALT;
if (m & Qt::ControlModifier) mods |= MOD_CONTROL;
if (m & Qt::ShiftModifier) mods |= MOD_SHIFT;
if (m & Qt::MetaModifier) mods |= MOD_WIN;
return mods;
}
void QGlobalShortcut::registerKey(quint32 k, quint32 m, quint32 id) {
RegisterHotKey(NULL, id, m, k);
}
void QGlobalShortcut::unregisterKey(quint32 /*k*/, quint32 /*m*/, quint32 id) {
UnregisterHotKey(NULL, id);
}
#include "qglobalshortcut.h"
#include <QKeySequence>
#include <QX11Info>
#include <xcb/xcb.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
bool QGlobalShortcut::QGlobalShortcutEventFilter::nativeEventFilter(
const QByteArray& eventType, void* message, long* result)
{
xcb_generic_event_t* e = static_cast<xcb_generic_event_t*>(message);
if ((e->response_type & ~0x80) == XCB_KEY_PRESS) {
xcb_key_press_event_t* ke = (xcb_key_press_event_t*)e;
xcb_get_keyboard_mapping_reply_t rep;
xcb_keysym_t* k = xcb_get_keyboard_mapping_keysyms(&rep);
quint32 keycode = ke->detail;
quint32 mods = ke->state & (ShiftMask|ControlMask|Mod1Mask|Mod3Mask);
return activate(calcId(keycode, mods));
}
return false;
}
quint32 QGlobalShortcut::calcId(quint32 k, quint32 m) {
return k | (m << 16);
}
quint32 QGlobalShortcut::toNativeKeycode(Qt::Key k) {
/* keysymdef.h */
quint32 key = 0;
if (k >= Qt::Key_F1 && k <= Qt::Key_F35) {
key = XK_F1 + (k - Qt::Key_F1);
} else if (k >= Qt::Key_Space && k <= Qt::Key_QuoteLeft) {
key = k;
} else if (k >= Qt::Key_BraceLeft && k <= Qt::Key_AsciiTilde) {
key = k;
} else if (k >= Qt::Key_nobreakspace && k <= Qt::Key_ydiaeresis) {
key = k;
} else {
switch (k) {
case Qt::Key_Escape:
key = XK_Escape;
break;
case Qt::Key_Tab:
case Qt::Key_Backtab:
key = XK_Tab;
break;
case Qt::Key_Backspace:
key = XK_BackSpace;
break;
case Qt::Key_Return:
case Qt::Key_Enter:
key = XK_Return;
break;
case Qt::Key_Insert:
key = XK_Insert;
break;
case Qt::Key_Delete:
key = XK_Delete;
break;
case Qt::Key_Pause:
key = XK_Pause;
break;
case Qt::Key_Print:
key = XK_Print;
break;
case Qt::Key_SysReq:
key = XK_Sys_Req;
break;
case Qt::Key_Clear:
key = XK_Clear;
break;
case Qt::Key_Home:
key = XK_Home;
break;
case Qt::Key_End:
key = XK_End;
break;
case Qt::Key_Left:
key = XK_Left;
break;
case Qt::Key_Up:
key = XK_Up;
break;
case Qt::Key_Right:
key = XK_Right;
break;
case Qt::Key_Down:
key = XK_Down;
break;
case Qt::Key_PageUp:
key = XK_Page_Up;
break;
case Qt::Key_PageDown:
key = XK_Page_Down;
break;
default:
key = 0;
}
}
return XKeysymToKeycode(QX11Info::display(), key);
}
quint32 QGlobalShortcut::toNativeModifiers(Qt::KeyboardModifiers m) {
quint32 mods = Qt::NoModifier;
if (m & Qt::ShiftModifier)
mods |= ShiftMask;
if (m & Qt::ControlModifier)
mods |= ControlMask;
if (m & Qt::AltModifier)
mods |= Mod1Mask;
if (m & Qt::MetaModifier)
mods |= Mod4Mask;
return mods;
}
void QGlobalShortcut::registerKey(quint32 k, quint32 m, quint32 id) {
xcb_grab_key(QX11Info::connection(), 1, QX11Info::appRootWindow(),
m, k, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
}
void QGlobalShortcut::unregisterKey(quint32 k, quint32 m, quint32 id) {
xcb_ungrab_key(QX11Info::connection(), k, QX11Info::appRootWindow(), m);
}
TEMPLATE = subdirs
SUBDIRS += \
lib \
test
BUILD = ordered
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#include "mainwindow.h"
#include "qglobalshortcut.h"
#include <QWidget>
#include <QLabel>
#include <QLineEdit>
#include <QGridLayout>
#include <QAction>
#include <QMenu>
#include <QMenuBar>
#include <QKeySequence>
#include <QKeySequenceEdit>
#include <QApplication>
#include <QPushButton>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), mEdit{}, mHide{}, mFull{}
{
auto menu = this->menuBar();
auto preference = menu->addAction("Preference");
connect(preference, &QAction::triggered, [this] {
this->showEditor();
});
preference->setShortcut(QKeySequence::fromString("Ctrl+P"));
auto quit = menu->addAction("Quit");
connect(quit, &QAction::triggered, [this] {
qApp->quit();
});
quit->setShortcut(QKeySequence::fromString("Ctrl+Q"));
initEditor();
}
MainWindow::~MainWindow()
{
delete mEdit;
}
void MainWindow::showEditor()
{
mEdit->show();
}
void MainWindow::initEditor()
{
mEdit = new QWidget{};
QLabel* hide = new QLabel{};
hide->setText("hide/show");
mHide = new KeyEdit{mEdit};
QLabel* full = new QLabel{};
full->setText("fullscreen/restore");
mFull = new KeyEdit{mEdit};
QPushButton* acc = new QPushButton{};
acc->setText("Ok");
QPushButton* rej = new QPushButton{};
rej->setText("Cancel");
QGridLayout* g = new QGridLayout{};
g->addWidget(hide, 0, 0);
g->addWidget(mHide, 0, 1);
g->addWidget(full, 1, 0);
g->addWidget(mFull, 1, 1);
g->addWidget(acc, 2, 0);
g->addWidget(rej, 2, 1);
connect(acc, &QPushButton::clicked, mEdit, [this] {
mEdit->hide();
mFull->setKey();
mHide->setKey();
});
connect(rej, &QPushButton::clicked, mEdit, [this] {
mHide->clear();
mFull->clear();
mEdit->hide();
});
connect(mHide, &KeyEdit::actived, [this] {
if(this->isHidden())
{
this->activateWindow();
this->raise();
this->show();
}
else
{
this->hide();
}
});
connect(mFull, &KeyEdit::actived, [this] {
if(this->isFullScreen())
{
this->showNormal();
}
else
{
this->showFullScreen();
}
});
mEdit->setLayout(g);
mEdit->resize(mEdit->sizeHint());
mEdit->hide();
}
KeyEdit::KeyEdit(QWidget *parent)
: QKeySequenceEdit{parent}
{
mGhk = new QGlobalShortcut{this};
connect(mGhk, &QGlobalShortcut::activated, [this] {
this->actived(mGhk->key());
});
}
KeyEdit::~KeyEdit()
{
delete mGhk;
}
void KeyEdit::clear()
{
mGhk->unsetKey();
QKeySequenceEdit::clear();
}
void KeyEdit::setKey()
{
mGhk->unsetKey();
mGhk->setKey(this->keySequence());
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QKeySequenceEdit>
class QGlobalShortcut;
class KeyEdit : public QKeySequenceEdit
{
Q_OBJECT
public:
KeyEdit(QWidget* parent = nullptr);
~KeyEdit();
void clear();
void setKey();
signals:
void actived(QKeySequence key);
private:
QGlobalShortcut* mGhk;
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
void showEditor();
private:
QWidget* mEdit;
KeyEdit* mHide;
KeyEdit* mFull;
void initEditor();
};
#endif // MAINWINDOW_H
#-------------------------------------------------
#
# Project created by QtCreator 2019-08-16T10:28:37
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = test
TEMPLATE = app
DESTDIR = $$PWD/../dest
INCLUDEPATH += $$PWD/../lib
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
LIBS += -L$$PWD/../dest -lghk
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment