Split out the X11 mouse event filtering for EffectsHandlerImpl

Summary:
This change introduces a dedicated X11EventFilter for the mouse
interception on X11. The filter gets created together with the start
of mouse interception and destroyed again when the mouse interception
ends. Thus we don't need to check for each event like it was the case
so far.

Unfortunately the existing methods cannot be removed (yet) as they are
still used by TabBox. Needs investigation whether this is actually
needed.

Test Plan: Xephyr+kwin_x11+Present Windows

Reviewers: #kwin, #plasma

Subscribers: plasma-devel, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D7842
This commit is contained in:
Martin Flöser 2017-09-15 18:35:40 +02:00
parent aa645e9401
commit 0c6fdeef2d
6 changed files with 114 additions and 19 deletions

View file

@ -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)

View file

@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#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<EffectsMouseInterceptionX11Filter>(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();
}
}

View file

@ -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<Effect*> m_grabbedMouseEffects;
EffectLoader *m_effectLoader;
int m_trackingCursorChanges;
std::unique_ptr<EffectsMouseInterceptionX11Filter> m_x11MouseInterception;
};
class EffectWindowImpl : public EffectWindow

View file

@ -0,0 +1,65 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2017 Martin Flöser <mgraesslin@kde.org>
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 <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "effects_mouse_interception_x11_filter.h"
#include "effects.h"
#include "utils.h"
#include <QMouseEvent>
namespace KWin
{
EffectsMouseInterceptionX11Filter::EffectsMouseInterceptionX11Filter(xcb_window_t window, EffectsHandlerImpl *effects)
: X11EventFilter(QVector<int>{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<xcb_button_press_event_t*>(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<xcb_motion_notify_event_t*>(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;
}
}

View file

@ -0,0 +1,43 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2017 Martin Flöser <mgraesslin@kde.org>
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 <http://www.gnu.org/licenses/>.
*********************************************************************/
#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

View file

@ -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<xcb_button_press_event_t*>(e);
if (effects && static_cast<EffectsHandlerImpl*>(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<xcb_motion_notify_event_t*>(e);
if (effects && static_cast<EffectsHandlerImpl*>(effects)->checkInputWindowEvent(mouseEvent)) {
return true;
}
break;
}
case XCB_CONFIGURE_NOTIFY:
if (reinterpret_cast<xcb_configure_notify_event_t*>(e)->event == rootWindow())
markXStackingOrderAsDirty();