Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mumble-voip/mumble.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mumble/GlobalShortcut_unix.cpp200
-rw-r--r--src/mumble/GlobalShortcut_unix.h8
2 files changed, 64 insertions, 144 deletions
diff --git a/src/mumble/GlobalShortcut_unix.cpp b/src/mumble/GlobalShortcut_unix.cpp
index a191086b7..e40f5d9f8 100644
--- a/src/mumble/GlobalShortcut_unix.cpp
+++ b/src/mumble/GlobalShortcut_unix.cpp
@@ -36,7 +36,6 @@ GlobalShortcutEngine *GlobalShortcutEngine::platformInit() {
GlobalShortcutX::GlobalShortcutX() {
bRunning=false;
- bXInput = false;
display = NULL;
@@ -67,131 +66,57 @@ GlobalShortcutX::GlobalShortcutX() {
return;
}
- XExtensionVersion *version = XGetExtensionVersion(display, INAME);
- if (version && (version != reinterpret_cast<XExtensionVersion *>(NoSuchExtension))) {
- bool bReturn = false;
- qWarning("GlobalShortcutX: Using XInput %d.%d", version->major_version, version->minor_version);
-
- bXInput = true;
- XFree(version);
-
- qmXDevices.clear();
-
- qmConnections = startScreensConnection(display);
- foreach(QSocketNotifier *qsNotif, qmConnections.keys()) {
- Display *dpy = qmConnections.value(qsNotif);
- initXInput(dpy);
-
- QMap<XID, XDevice *> *qmDisplayXDevices = qmXDevices.value(dpy);
-
- qWarning("GlobalShortcutX: TOTAL %ld --- %ld ", qmDisplayXDevices->count(), qmXDevices.count());
-
- if (qmDisplayXDevices->isEmpty()) {
- qWarning("GlobalShortcutX: No XInput devices");
- } else {
- connect(qsNotif, SIGNAL(activated(int)), this, SLOT(displayReadyRead(int)));
- bReturn = true;
- }
- }
- if (bReturn)
+ for(int i=0; i < ScreenCount(display); ++i)
+ qsRootWindows.insert(RootWindow(display, i));
+
+ int evt, error;
+
+ if (XQueryExtension(display, "XInputExtension", &iXIopcode, &evt, &error)) {
+ int major = 2;
+ int minor = 0;
+ int rc = XIQueryVersion(display, &major, &minor);
+ if (rc != BadRequest) {
+ qWarning("GlobalShortcutX: Using XI2 %d.%d", major, minor);
+
+ XIEventMask evmask;
+ unsigned char mask[(XI_LASTEVENT + 7)/8];
+
+ memset(&evmask, 0, sizeof(evmask));
+ memset(mask, 0, sizeof(mask));
+
+ XISetMask(mask, XI_RawButtonPress);
+ XISetMask(mask, XI_RawButtonRelease);
+ XISetMask(mask, XI_RawKeyPress);
+ XISetMask(mask, XI_RawKeyRelease);
+
+ evmask.deviceid = XIAllMasterDevices;
+ evmask.mask_len = sizeof(mask);
+ evmask.mask = mask;
+
+ foreach(Window w, qsRootWindows)
+ XISelectEvents(display, w, &evmask, 1);
+ XFlush(display);
+
+ connect(new QSocketNotifier(ConnectionNumber(display), QSocketNotifier::Read, this), SIGNAL(activated(int)), this, SLOT(displayReadyRead(int)));
+
return;
- } else {
- qWarning("GlobalShortcutX: No XInput support, falling back to polled input. This wastes a lot of CPU resources, so please enable one of the other methods.");
- bRunning=true;
- start(QThread::TimeCriticalPriority);
+ }
}
+
+ qWarning("GlobalShortcutX: No XInput support, falling back to polled input. This wastes a lot of CPU resources, so please enable one of the other methods.");
+ bRunning=true;
+ start(QThread::TimeCriticalPriority);
}
GlobalShortcutX::~GlobalShortcutX() {
bRunning = false;
wait();
- foreach(Display *dpy, qmXDevices.keys()) {
- QMap<XID, XDevice *> *qmDisplayXDevices = qmXDevices.value(dpy);
- foreach(XDevice *dev, *qmDisplayXDevices) {
- XCloseDevice(dpy, dev);
- }
-
- }
-
-
if (display)
XCloseDisplay(display);
}
-QMap<QSocketNotifier *, Display *>GlobalShortcutX::startScreensConnection(Display *dpy) {
- int iScreens = ScreenCount(display);
- QMap<QSocketNotifier *, Display *>connections;
- QString sDisplayPrefix = QString::fromAscii(DisplayString(dpy));
-
- // get the dpy prefix
- int iDotPos = sDisplayPrefix.indexOf(QString::fromAscii("."));
- sDisplayPrefix = sDisplayPrefix.left(iDotPos + 1);
-
- connections.insert(new QSocketNotifier(ConnectionNumber(dpy), QSocketNotifier::Read, this), dpy);
-
- for (int i=0; i < iScreens; i++) {
- QString sDpyTmp = sDisplayPrefix + QString::number(i);
-
- if (sDpyTmp != QString::fromAscii(DisplayString(dpy))) {
- Display *dpyconn = XOpenDisplay(sDpyTmp.toAscii());
- connections.insert(new QSocketNotifier(ConnectionNumber(dpyconn), QSocketNotifier::Read, this), dpyconn);
- }
- }
-
- return connections;
-}
-
-
-
-void GlobalShortcutX::initXInput(Display *dpy) {
-
- int numdev;
- XDeviceInfo *infolist = XListInputDevices(dpy, &numdev);
- if (! infolist)
- return;
-
- QMap<XID, XDevice *> *qmDisplayXDevices = new QMap<XID, XDevice *>();
- qmXDevices.insert(dpy, qmDisplayXDevices);
- for (int i=0;i<numdev;++i) {
- XDeviceInfo *info = infolist + i;
- XDevice *dev = XOpenDevice(dpy, info->id);
- if (dev) {
- bool key = false, button = false;
- for (int j=0;j<dev->num_classes;++j) {
- XInputClassInfo *ici = dev->classes + j;
- key = key || (ici->input_class == KeyClass);
- button = button || (ici->input_class == ButtonClass);
- }
-
- XEventClass events[4];
- int nevents = 0;
- if (key) {
- DeviceKeyPress(dev, iKeyPress, events[nevents]);
- ++nevents;
- DeviceKeyRelease(dev, iKeyRelease, events[nevents]);
- ++nevents;
- }
- if (button) {
- DeviceButtonPress(dev, iButtonPress, events[nevents]);
- ++nevents;
- DeviceButtonRelease(dev, iButtonRelease, events[nevents]);
- ++nevents;
- }
-
- if ((nevents != 0) && ! XSelectExtensionEvent(dpy, XDefaultRootWindow(dpy), events, nevents)) {
- qWarning("GlobalShortcutX: XInput %ld:%s", info->id, info->name);
- qmDisplayXDevices->insert(info->id, dev);
- } else {
- XCloseDevice(dpy, dev);
- }
- }
- }
-
- XFree(infolist);
-}
-
-
+// Tight loop polling
void GlobalShortcutX::run() {
Window root = XDefaultRootWindow(display);
Window root_ret, child_ret;
@@ -235,41 +160,37 @@ void GlobalShortcutX::run() {
}
}
+// XInput2 event is ready on socketnotifier.
void GlobalShortcutX::displayReadyRead(int) {
XEvent evt;
if (bNeedRemap)
remap();
- QSocketNotifier *source = (QSocketNotifier *)this->sender();
-
- Display *dpy = qmConnections.value(source);
-
- while (XPending(dpy)) {
- XNextEvent(dpy, &evt);
- if ((evt.type == iButtonPress) || (evt.type == iButtonRelease)) {
- XDeviceButtonEvent *be = reinterpret_cast<XDeviceButtonEvent *>(&evt);
- handleButton(be->button + 0x117, evt.type == iButtonPress);
- } else if ((evt.type == iKeyPress) || (evt.type == iKeyRelease)) {
- XDeviceKeyEvent *ke = reinterpret_cast<XDeviceKeyEvent *>(&evt);
-
- if ((evt.type == iKeyRelease) && XPending(dpy)) {
- // Is it a silly key repeat?
- XEvent nxt;
- XPeekEvent(dpy, &nxt);
- if (nxt.type == iKeyPress) {
- XDeviceKeyEvent *ne = reinterpret_cast<XDeviceKeyEvent *>(&nxt);
- if (ke->keycode == ne->keycode) {
- XNextEvent(dpy, &nxt);
- continue;
- }
- }
- }
- handleButton(ke->keycode, evt.type == iKeyPress);
+ while (XPending(display)) {
+ XNextEvent(display, &evt);
+ XGenericEventCookie *cookie = & evt.xcookie;
+
+ if ((cookie->type != GenericEvent) || (cookie->extension != iXIopcode) || !XGetEventData(display, cookie))
+ continue;
+
+ XIDeviceEvent *xide = reinterpret_cast<XIDeviceEvent *>(cookie->data);
+ switch(cookie->evtype) {
+ case XI_RawKeyPress:
+ case XI_RawKeyRelease:
+ handleButton(xide->detail, cookie->evtype == XI_RawKeyPress);
+ break;
+ case XI_RawButtonPress:
+ case XI_RawButtonRelease:
+ handleButton(xide->detail + 0x117, cookie->evtype == XI_RawButtonPress);
+ break;
}
+
+ XFreeEventData(display, cookie);
}
}
+// One of the raw /dev/input devices has ready input
void GlobalShortcutX::inputReadyRead(int) {
#ifdef Q_OS_LINUX
struct input_event ev;
@@ -317,6 +238,7 @@ void GlobalShortcutX::inputReadyRead(int) {
#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8)))
+// The /dev/input directory changed
void GlobalShortcutX::directoryChanged(const QString &dir) {
#ifdef Q_OS_LINUX
QDir d(dir, QLatin1String("event*"), 0, QDir::System);
diff --git a/src/mumble/GlobalShortcut_unix.h b/src/mumble/GlobalShortcut_unix.h
index 3a73b11d1..014567978 100644
--- a/src/mumble/GlobalShortcut_unix.h
+++ b/src/mumble/GlobalShortcut_unix.h
@@ -35,7 +35,7 @@
#include <QX11Info>
#include <X11/X.h>
#include <X11/Xlib.h>
-#include <X11/extensions/XInput.h>
+#include <X11/extensions/XInput2.h>
#include <X11/Xutil.h>
#ifdef Q_OS_LINUX
#include <linux/input.h>
@@ -48,15 +48,13 @@ class GlobalShortcutX : public GlobalShortcutEngine {
private:
Q_OBJECT
Q_DISABLE_COPY(GlobalShortcutX)
- QMap<QSocketNotifier *, Display *> startScreensConnection(Display *);
public:
Display *display;
+ QSet<Window> qsRootWindows;
+ int iXIopcode;
volatile bool bRunning;
- QMap<QSocketNotifier *, Display *> qmConnections;
- bool bXInput;
QSet<QString> qsKeyboards;
QMap<QString, QFile *> qmInputDevices;
- QMap<Display *, QMap<XID, XDevice *> *> qmXDevices;
GlobalShortcutX();
~GlobalShortcutX();