Added linux support.

This commit is contained in:
Gres 2015-09-27 18:16:52 +03:00
parent ced4b1c5c8
commit 670fda2ac5

View File

@ -1,27 +1,10 @@
#include "GlobalActionHelper.h"
#include <qt_windows.h>
#include <QDebug>
#include <QApplication>
QHash<QPair<quint32, quint32>, QAction *> GlobalActionHelper::actions_;
bool GlobalActionHelper::nativeEventFilter (const QByteArray &eventType,
void *message, long *result) {
Q_UNUSED (eventType);
Q_UNUSED (result);
MSG *msg = static_cast<MSG *>(message);
if (msg->message == WM_HOTKEY) {
const quint32 keycode = HIWORD (msg->lParam);
const quint32 modifiers = LOWORD (msg->lParam);
QAction *action = actions_.value (qMakePair (keycode, modifiers));
Q_CHECK_PTR (action);
action->activate (QAction::Trigger);
}
return false;
}
void GlobalActionHelper::init () {
qApp->installNativeEventFilter (new GlobalActionHelper);
}
@ -79,6 +62,129 @@ bool GlobalActionHelper::removeGlobal (QAction *action) {
return res;
}
#if defined(Q_OS_LINUX)
# include <QX11Info>
# include <X11/Xlib.h>
# include <xcb/xcb_event.h>
static bool error = false;
static int customHandler (Display *display, XErrorEvent *event) {
Q_UNUSED (display);
switch (event->error_code) {
case BadAccess:
case BadValue:
case BadWindow:
if (event->request_code == 33 /* X_GrabKey */ ||
event->request_code == 34 /* X_UngrabKey */) {
error = true;
}
default:
return 0;
}
}
bool GlobalActionHelper::registerHotKey (quint32 nativeKey, quint32 nativeMods) {
Display *display = QX11Info::display ();
Window window = QX11Info::appRootWindow ();
Bool owner = True;
int pointer = GrabModeAsync;
int keyboard = GrabModeAsync;
error = false;
int (*handler)(Display *display, XErrorEvent *event) = XSetErrorHandler (customHandler);
XGrabKey (display, nativeKey, nativeMods, window, owner, pointer, keyboard);
// allow numlock
XGrabKey (display, nativeKey, nativeMods | Mod2Mask, window, owner, pointer, keyboard);
XSync (display, False);
XSetErrorHandler (handler);
return !error;
}
bool GlobalActionHelper::unregisterHotKey (quint32 nativeKey, quint32 nativeMods) {
Display *display = QX11Info::display ();
Window window = QX11Info::appRootWindow ();
error = false;
int (*handler)(Display *display, XErrorEvent *event) = XSetErrorHandler (customHandler);
XUngrabKey (display, nativeKey, nativeMods, window);
// allow numlock
XUngrabKey (display, nativeKey, nativeMods | Mod2Mask, window);
XSync (display, False);
XSetErrorHandler (handler);
return !error;
}
bool GlobalActionHelper::nativeEventFilter (const QByteArray &eventType,
void *message, long *result) {
Q_UNUSED (eventType);
Q_UNUSED (result);
xcb_generic_event_t *event = static_cast<xcb_generic_event_t *>(message);
if (event->response_type == XCB_KEY_PRESS) {
xcb_key_press_event_t *keyEvent = static_cast<xcb_key_press_event_t *>(message);
const quint32 keycode = keyEvent->detail;
const quint32 modifiers = keyEvent->state & ~XCB_MOD_MASK_2;
QAction *action = actions_.value (qMakePair (keycode, modifiers));
if (action) {
action->activate (QAction::Trigger);
}
}
return false;
}
quint32 GlobalActionHelper::nativeKeycode (Qt::Key key) {
Display *display = QX11Info::display ();
KeySym keySym = XStringToKeysym (qPrintable (QKeySequence (key).toString ()));
return XKeysymToKeycode (display, keySym);
}
quint32 GlobalActionHelper::nativeModifiers (Qt::KeyboardModifiers modifiers) {
quint32 native = 0;
if (modifiers & Qt::ShiftModifier) {
native |= ShiftMask;
}
if (modifiers & Qt::ControlModifier) {
native |= ControlMask;
}
if (modifiers & Qt::AltModifier) {
native |= Mod1Mask;
}
if (modifiers & Qt::MetaModifier) {
native |= Mod4Mask;
}
return native;
}
#elif defined(Q_OS_WIN)
# include <qt_windows.h>
bool GlobalActionHelper::registerHotKey (quint32 nativeKey, quint32 nativeMods) {
return RegisterHotKey (0, nativeMods ^ nativeKey, nativeMods, nativeKey);
}
bool GlobalActionHelper::unregisterHotKey (quint32 nativeKey, quint32 nativeMods) {
return UnregisterHotKey (0, nativeMods ^ nativeKey);
}
bool GlobalActionHelper::nativeEventFilter (const QByteArray &eventType,
void *message, long *result) {
Q_UNUSED (eventType);
Q_UNUSED (result);
MSG *msg = static_cast<MSG *>(message);
if (msg->message == WM_HOTKEY) {
const quint32 keycode = HIWORD (msg->lParam);
const quint32 modifiers = LOWORD (msg->lParam);
QAction *action = actions_.value (qMakePair (keycode, modifiers));
if (action) {
action->activate (QAction::Trigger);
}
}
return false;
}
quint32 GlobalActionHelper::nativeKeycode (Qt::Key key) {
switch (key) {
case Qt::Key_Escape:
@ -185,9 +291,6 @@ quint32 GlobalActionHelper::nativeKeycode (Qt::Key key) {
return VK_MEDIA_PLAY_PAUSE;
case Qt::Key_MediaStop:
return VK_MEDIA_STOP;
// couldn't find those in VK_*
//case Qt::Key_MediaLast:
//case Qt::Key_MediaRecord:
case Qt::Key_VolumeDown:
return VK_VOLUME_DOWN;
case Qt::Key_VolumeUp:
@ -261,11 +364,4 @@ quint32 GlobalActionHelper::nativeModifiers (Qt::KeyboardModifiers modifiers) {
//if (modifiers & Qt::GroupSwitchModifier)
return native;
}
bool GlobalActionHelper::registerHotKey (quint32 nativeKey, quint32 nativeMods) {
return RegisterHotKey (0, nativeMods ^ nativeKey, nativeMods, nativeKey);
}
bool GlobalActionHelper::unregisterHotKey (quint32 nativeKey, quint32 nativeMods) {
return UnregisterHotKey (0, nativeMods ^ nativeKey);
}
#endif