Clementine-audio-player-Mac.../3rdparty/qxt/qxtglobalshortcut_x11.cpp

136 lines
4.6 KiB
C++

/****************************************************************************
**
** Copyright (C) Qxt Foundation. Some rights reserved.
**
** This file is part of the QxtGui module of the Qxt library.
**
** This library is free software; you can redistribute it and/or modify it
** under the terms of the Common Public License, version 1.0, as published
** by IBM, and/or under the terms of the GNU Lesser General Public License,
** version 2.1, as published by the Free Software Foundation.
**
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
** FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the CPL and the LGPL along with this
** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
** included with the source distribution for more information.
** If you did not receive a copy of the licenses, contact the Qxt Foundation.
**
** <http://libqxt.org> <foundation@libqxt.org>
**
****************************************************************************/
#include "qxtglobalshortcut_p.h"
#include <QX11Info>
#include <X11/Xlib.h>
#include "keymapper_x11.h"
static int (*original_x_errhandler)(Display* display, XErrorEvent* event);
static int qxt_x_errhandler(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 */)
{
QxtGlobalShortcutPrivate::error = true;
//TODO:
//char errstr[256];
//XGetErrorText(dpy, err->error_code, errstr, 256);
}
default:
return 0;
}
}
bool QxtGlobalShortcutPrivate::eventFilter(void* message)
{
XEvent* event = static_cast<XEvent*>(message);
if (event->type == KeyPress)
{
XKeyEvent* key = (XKeyEvent*) event;
activateShortcut(key->keycode,
// Mod1Mask == Alt, Mod4Mask == Meta
key->state & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask));
}
return false;
}
quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers)
{
// ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask
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;
// TODO: resolve these?
//if (modifiers & Qt::KeypadModifier)
//if (modifiers & Qt::GroupSwitchModifier)
return native;
}
quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key)
{
// (davidsansome) Try the table from QKeyMapper first - this seems to be
// the only way to get Keysyms for the media keys.
unsigned int keysym = 0;
int i = 0;
while (KeyTbl[i]) {
if (KeyTbl[i+1] == static_cast<uint>(key)) {
keysym = KeyTbl[i];
break;
}
i += 2;
}
// If that didn't work then fall back on XStringToKeysym
if (!keysym) {
keysym = XStringToKeysym(QKeySequence(key).toString().toLatin1().data());
}
Display* display = QX11Info::display();
return XKeysymToKeycode(display, keysym);
}
bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods)
{
Display* display = QX11Info::display();
Window window = QX11Info::appRootWindow();
Bool owner = True;
int pointer = GrabModeAsync;
int keyboard = GrabModeAsync;
error = false;
original_x_errhandler = XSetErrorHandler(qxt_x_errhandler);
XGrabKey(display, nativeKey, nativeMods, window, owner, pointer, keyboard);
XGrabKey(display, nativeKey, nativeMods | Mod2Mask, window, owner, pointer, keyboard); // allow numlock
XSync(display, False);
XSetErrorHandler(original_x_errhandler);
return !error;
}
bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods)
{
Display* display = QX11Info::display();
Window window = QX11Info::appRootWindow();
error = false;
original_x_errhandler = XSetErrorHandler(qxt_x_errhandler);
XUngrabKey(display, nativeKey, nativeMods, window);
XUngrabKey(display, nativeKey, nativeMods | Mod2Mask, window); // allow numlock
XSync(display, False);
XSetErrorHandler(original_x_errhandler);
return !error;
}