diff --git a/CMakeLists.txt b/CMakeLists.txt
index 28ba2ccd53..e03d5738ec 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -456,6 +456,7 @@ set(kwin_KDEINIT_SRCS
egl_context_attribute_builder.cpp
was_user_interaction_x11_filter.cpp
moving_client_x11_filter.cpp
+ effects_mouse_interception_x11_filter.cpp
)
if(KWIN_BUILD_TABBOX)
diff --git a/effects.cpp b/effects.cpp
index ed4adc1461..d5d06e2059 100644
--- a/effects.cpp
+++ b/effects.cpp
@@ -22,6 +22,7 @@ along with this program. If not, see .
#include "effects.h"
#include "effectsadaptor.h"
+#include "effects_mouse_interception_x11_filter.h"
#include "effectloader.h"
#ifdef KWIN_BUILD_ACTIVITIES
#include "activities.h"
@@ -690,6 +691,7 @@ void EffectsHandlerImpl::startMouseInterception(Effect *effect, Qt::CursorShape
}
m_mouseInterceptionWindow.map();
m_mouseInterceptionWindow.raise();
+ m_x11MouseInterception = std::make_unique(m_mouseInterceptionWindow, this);
// Raise electric border windows above the input windows
// so they can still be triggered.
ScreenEdges::self()->ensureOnTop();
@@ -707,6 +709,7 @@ void EffectsHandlerImpl::stopMouseInterception(Effect *effect)
}
if (m_grabbedMouseEffects.isEmpty()) {
m_mouseInterceptionWindow.unmap();
+ m_x11MouseInterception.reset();
Workspace::self()->stackScreenEdgesUnderOverrideRedirect();
}
}
diff --git a/effects.h b/effects.h
index b9eb3d36a7..92c28c13cb 100644
--- a/effects.h
+++ b/effects.h
@@ -58,6 +58,7 @@ class Client;
class Compositor;
class Deleted;
class EffectLoader;
+class EffectsMouseInterceptionX11Filter;
class Unmanaged;
class KWIN_EXPORT EffectsHandlerImpl : public EffectsHandler
@@ -319,6 +320,7 @@ private:
QList m_grabbedMouseEffects;
EffectLoader *m_effectLoader;
int m_trackingCursorChanges;
+ std::unique_ptr m_x11MouseInterception;
};
class EffectWindowImpl : public EffectWindow
diff --git a/effects_mouse_interception_x11_filter.cpp b/effects_mouse_interception_x11_filter.cpp
new file mode 100644
index 0000000000..e33dedbaae
--- /dev/null
+++ b/effects_mouse_interception_x11_filter.cpp
@@ -0,0 +1,65 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2017 Martin Flöser
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*********************************************************************/
+#include "effects_mouse_interception_x11_filter.h"
+#include "effects.h"
+#include "utils.h"
+
+#include
+
+namespace KWin
+{
+
+EffectsMouseInterceptionX11Filter::EffectsMouseInterceptionX11Filter(xcb_window_t window, EffectsHandlerImpl *effects)
+ : X11EventFilter(QVector{XCB_BUTTON_PRESS, XCB_BUTTON_RELEASE, XCB_MOTION_NOTIFY})
+ , m_effects(effects)
+ , m_window(window)
+{
+}
+
+bool EffectsMouseInterceptionX11Filter::event(xcb_generic_event_t *event)
+{
+ const uint8_t eventType = event->response_type & ~0x80;
+ if (eventType == XCB_BUTTON_PRESS || eventType == XCB_BUTTON_RELEASE) {
+ auto *me = reinterpret_cast(event);
+ if (m_window == me->event) {
+ const Qt::MouseButton button = x11ToQtMouseButton(me->detail);
+ Qt::MouseButtons buttons = x11ToQtMouseButtons(me->state);
+ const QEvent::Type type = (eventType == XCB_BUTTON_PRESS) ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease;
+ if (type == QEvent::MouseButtonPress) {
+ buttons |= button;
+ } else {
+ buttons &= ~button;
+ }
+ QMouseEvent ev(type, QPoint(me->event_x, me->event_y), QPoint(me->root_x, me->root_y),
+ button, buttons, x11ToQtKeyboardModifiers(me->state));
+ return m_effects->checkInputWindowEvent(&ev);
+ }
+ } else if (eventType == XCB_MOTION_NOTIFY) {
+ const auto *me = reinterpret_cast(event);
+ if (m_window == me->event) {
+ QMouseEvent ev(QEvent::MouseMove, QPoint(me->event_x, me->event_y), QPoint(me->root_x, me->root_y),
+ Qt::NoButton, x11ToQtMouseButtons(me->state), x11ToQtKeyboardModifiers(me->state));
+ return m_effects->checkInputWindowEvent(&ev);
+ }
+ }
+ return false;
+}
+
+}
diff --git a/effects_mouse_interception_x11_filter.h b/effects_mouse_interception_x11_filter.h
new file mode 100644
index 0000000000..740a87a3e2
--- /dev/null
+++ b/effects_mouse_interception_x11_filter.h
@@ -0,0 +1,43 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2017 Martin Flöser
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*********************************************************************/
+#ifndef KWIN_EFFECTS_MOUSE_INTERCEPTION_X11_FILTER_H
+#define KWIN_EFFECTS_MOUSE_INTERCEPTION_X11_FILTER_H
+
+#include "x11eventfilter.h"
+
+namespace KWin
+{
+class EffectsHandlerImpl;
+
+class EffectsMouseInterceptionX11Filter : public X11EventFilter
+{
+public:
+ explicit EffectsMouseInterceptionX11Filter(xcb_window_t window, EffectsHandlerImpl *effects);
+
+ bool event(xcb_generic_event_t *event) override;
+
+private:
+ EffectsHandlerImpl *m_effects;
+ xcb_window_t m_window;
+};
+
+}
+
+#endif
diff --git a/events.cpp b/events.cpp
index 5f8ea61a65..61527446db 100644
--- a/events.cpp
+++ b/events.cpp
@@ -259,25 +259,6 @@ bool Workspace::workspaceEvent(xcb_generic_event_t *e)
// events that should be handled before Clients can get them
switch (eventType) {
- case XCB_BUTTON_PRESS:
- case XCB_BUTTON_RELEASE: {
- auto *mouseEvent = reinterpret_cast(e);
- if (effects && static_cast(effects)->checkInputWindowEvent(mouseEvent)) {
- return true;
- }
- break;
- }
- case XCB_MOTION_NOTIFY: {
- if (kwinApp()->operationMode() != Application::OperationModeX11) {
- // ignore X11 pointer events generated on X windows if we are not on X
- return true;
- }
- auto *mouseEvent = reinterpret_cast(e);
- if (effects && static_cast(effects)->checkInputWindowEvent(mouseEvent)) {
- return true;
- }
- break;
- }
case XCB_CONFIGURE_NOTIFY:
if (reinterpret_cast(e)->event == rootWindow())
markXStackingOrderAsDirty();