Added linux support.
This commit is contained in:
		
							parent
							
								
									ced4b1c5c8
								
							
						
					
					
						commit
						670fda2ac5
					
				@ -1,27 +1,10 @@
 | 
				
			|||||||
#include "GlobalActionHelper.h"
 | 
					#include "GlobalActionHelper.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <qt_windows.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <QDebug>
 | 
					#include <QDebug>
 | 
				
			||||||
#include <QApplication>
 | 
					#include <QApplication>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QHash<QPair<quint32, quint32>, QAction *> GlobalActionHelper::actions_;
 | 
					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 () {
 | 
					void GlobalActionHelper::init () {
 | 
				
			||||||
  qApp->installNativeEventFilter (new GlobalActionHelper);
 | 
					  qApp->installNativeEventFilter (new GlobalActionHelper);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -79,6 +62,129 @@ bool GlobalActionHelper::removeGlobal (QAction *action) {
 | 
				
			|||||||
  return res;
 | 
					  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) {
 | 
					quint32 GlobalActionHelper::nativeKeycode (Qt::Key key) {
 | 
				
			||||||
  switch (key) {
 | 
					  switch (key) {
 | 
				
			||||||
    case Qt::Key_Escape:
 | 
					    case Qt::Key_Escape:
 | 
				
			||||||
@ -185,9 +291,6 @@ quint32 GlobalActionHelper::nativeKeycode (Qt::Key key) {
 | 
				
			|||||||
      return VK_MEDIA_PLAY_PAUSE;
 | 
					      return VK_MEDIA_PLAY_PAUSE;
 | 
				
			||||||
    case Qt::Key_MediaStop:
 | 
					    case Qt::Key_MediaStop:
 | 
				
			||||||
      return VK_MEDIA_STOP;
 | 
					      return VK_MEDIA_STOP;
 | 
				
			||||||
    // couldn't find those in VK_*
 | 
					 | 
				
			||||||
    //case Qt::Key_MediaLast:
 | 
					 | 
				
			||||||
    //case Qt::Key_MediaRecord:
 | 
					 | 
				
			||||||
    case Qt::Key_VolumeDown:
 | 
					    case Qt::Key_VolumeDown:
 | 
				
			||||||
      return VK_VOLUME_DOWN;
 | 
					      return VK_VOLUME_DOWN;
 | 
				
			||||||
    case Qt::Key_VolumeUp:
 | 
					    case Qt::Key_VolumeUp:
 | 
				
			||||||
@ -261,11 +364,4 @@ quint32 GlobalActionHelper::nativeModifiers (Qt::KeyboardModifiers modifiers) {
 | 
				
			|||||||
  //if (modifiers & Qt::GroupSwitchModifier)
 | 
					  //if (modifiers & Qt::GroupSwitchModifier)
 | 
				
			||||||
  return native;
 | 
					  return native;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
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);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user