From 7d21d612fee32dd9be2b7eca1ebbd9241e7b63dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Mon, 30 Sep 2013 09:47:22 +0200 Subject: [PATCH] [kwinrules] Use native event filter for mouse button release detection The event filtering on Qt level does not work any more. The information is not updated properly. Grabbing the mouse through QWidget resets the cursor shape to the default shape, so it cannot be used. As we don't want Qt to ever see the events it's a good idea to use a native event filter to filter the events away before they are delivered to Qt. To simplify the handling the grabber widget is put into a QScopedPointer. --- kcmkwin/kwinrules/detectwidget.cpp | 26 ++++++++++++++------------ kcmkwin/kwinrules/detectwidget.h | 9 +++++---- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/kcmkwin/kwinrules/detectwidget.cpp b/kcmkwin/kwinrules/detectwidget.cpp index 85d1929f81..1d9cd356b8 100644 --- a/kcmkwin/kwinrules/detectwidget.cpp +++ b/kcmkwin/kwinrules/detectwidget.cpp @@ -49,7 +49,7 @@ DetectWidget::DetectWidget(QWidget* parent) DetectDialog::DetectDialog(QWidget* parent, const char* name) : KDialog(parent), - grabber(NULL) + grabber() { setObjectName(name); setModal(true); @@ -168,7 +168,7 @@ void DetectDialog::selectWindow() // use a dialog, so that all user input is blocked // use WX11BypassWM and moving away so that it's not actually visible // grab only mouse, so that keyboard can be used e.g. for switching windows - grabber = new KDialog(0, Qt::X11BypassWindowManagerHint); + grabber.reset(new KDialog(0, Qt::X11BypassWindowManagerHint)); grabber->move(-1000, -1000); grabber->setModal(true); grabber->show(); @@ -177,24 +177,26 @@ void DetectDialog::selectWindow() if (XGrabPointer(QX11Info::display(), grabber->winId(), false, ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, QCursor(Qt::CrossCursor).handle(), CurrentTime) == Success) { // ...so we use the far more convincing CurrentTime - grabber->grabMouse(Qt::CrossCursor); // do anyway, so that Qt updates the mouseGrabber info - grabber->installEventFilter(this); + QCoreApplication::instance()->installNativeEventFilter(this); } else { // ... and if we fail, cleanup, so we won't receive random events - delete grabber; - grabber = 0; + grabber.reset(); } } -bool DetectDialog::eventFilter(QObject* o, QEvent* e) +bool DetectDialog::nativeEventFilter(const QByteArray &eventType, void *message, long int*) { - if (o != grabber) + if (eventType != QByteArrayLiteral("xcb_generic_event_t")) { return false; - if (e->type() != QEvent::MouseButtonRelease) + } + auto *event = reinterpret_cast(message); + if ((event->response_type & ~0x80) != XCB_BUTTON_RELEASE) { return false; - delete grabber; - grabber = NULL; - if (static_cast< QMouseEvent* >(e)->button() != Qt::LeftButton) { + } + QCoreApplication::instance()->removeNativeEventFilter(this); + grabber.reset(); + auto *me = reinterpret_cast(event); + if (me->detail != XCB_BUTTON_INDEX_1) { emit detectionDone(false); return true; } diff --git a/kcmkwin/kwinrules/detectwidget.h b/kcmkwin/kwinrules/detectwidget.h index 8614fc0730..3e995f1292 100644 --- a/kcmkwin/kwinrules/detectwidget.h +++ b/kcmkwin/kwinrules/detectwidget.h @@ -22,6 +22,7 @@ #include #include +#include #include "../../rules.h" //Added by qt3to4: @@ -42,7 +43,7 @@ public: }; class DetectDialog - : public KDialog + : public KDialog, public QAbstractNativeEventFilter { Q_OBJECT public: @@ -57,10 +58,10 @@ public: Rules::StringMatch titleMatch() const; QByteArray selectedMachine() const; const KWindowInfo& windowInfo() const; + + virtual bool nativeEventFilter(const QByteArray& eventType, void* message, long int* result) override; Q_SIGNALS: void detectionDone(bool); -protected: - virtual bool eventFilter(QObject* o, QEvent* e); private Q_SLOTS: void selectWindow(); private: @@ -75,7 +76,7 @@ private: QByteArray extrarole; QByteArray machine; DetectWidget* widget; - KDialog* grabber; + QScopedPointer grabber; KWindowInfo info; };