From 6619faa6ac5b9f2a0c5c140882ba093d909abd7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Wed, 26 Jun 2013 11:40:30 +0200 Subject: [PATCH] Pass pointer events through the effect system InputRedirection forwards pointer events (currently motion, press and release) through the EffectsHandlerImpl for the case that an effect has intercepted pointer events. If the KWin operation mode is not X11 only, the window for intercepting the mouse events is no longer created. --- effects.cpp | 20 +++++++++++++++++ effects.h | 1 + input.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++ input.h | 4 ++++ 4 files changed, 87 insertions(+) diff --git a/effects.cpp b/effects.cpp index 822bb5c202..37e1721b43 100644 --- a/effects.cpp +++ b/effects.cpp @@ -767,6 +767,9 @@ void EffectsHandlerImpl::startMouseInterception(Effect *effect, Qt::CursorShape if (m_grabbedMouseEffects.size() != 1) { return; } + if (kwinApp()->operationMode() != Application::OperationModeX11) { + return; + } // NOTE: it is intended to not perform an XPointerGrab on X11. See documentation in kwineffects.h // The mouse grab is implemented by using a full screen input only window if (!m_mouseInterceptionWindow.isValid()) { @@ -794,6 +797,9 @@ void EffectsHandlerImpl::stopMouseInterception(Effect *effect) return; } m_grabbedMouseEffects.removeAll(effect); + if (kwinApp()->operationMode() != Application::OperationModeX11) { + return; + } if (m_grabbedMouseEffects.isEmpty()) { m_mouseInterceptionWindow.unmap(); #ifdef KWIN_BUILD_SCREENEDGES @@ -1291,11 +1297,25 @@ bool EffectsHandlerImpl::checkInputWindowEvent(xcb_motion_notify_event_t *e) return true; // eat event } +bool EffectsHandlerImpl::checkInputWindowEvent(QMouseEvent *e) +{ + if (m_grabbedMouseEffects.isEmpty()) { + return false; + } + foreach (Effect *effect, m_grabbedMouseEffects) { + effect->windowInputMouseEvent(e); + } + return true; +} + void EffectsHandlerImpl::checkInputWindowStacking() { if (m_grabbedMouseEffects.isEmpty()) { return; } + if (kwinApp()->operationMode() != Application::OperationModeX11) { + return; + } m_mouseInterceptionWindow.raise(); // Raise electric border windows above the input windows // so they can still be triggered. TODO: Do both at once. diff --git a/effects.h b/effects.h index 70a5f4120c..50b6d31749 100644 --- a/effects.h +++ b/effects.h @@ -156,6 +156,7 @@ public: void defineCursor(Qt::CursorShape shape) override; bool checkInputWindowEvent(xcb_button_press_event_t *e); bool checkInputWindowEvent(xcb_motion_notify_event_t *e); + bool checkInputWindowEvent(QMouseEvent *e); void checkInputWindowStacking(); void reserveElectricBorder(ElectricBorder border, Effect *effect) override; diff --git a/input.cpp b/input.cpp index 90cec16aab..c87db99346 100644 --- a/input.cpp +++ b/input.cpp @@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "input.h" +#include "effects.h" // TODO: remove xtest #include // system @@ -47,6 +48,14 @@ void InputRedirection::processPointerMotion(const QPointF &pos, uint32_t time) emit globalPointerChanged(m_globalPointer); // TODO: check which part of KWin would like to intercept the event + // TODO: keyboard modifiers + QMouseEvent event(QEvent::MouseMove, m_globalPointer.toPoint(), m_globalPointer.toPoint(), + Qt::NoButton, qtButtonStates(), 0); + // check whether an effect has a mouse grab + if (effects && static_cast(effects)->checkInputWindowEvent(&event)) { + // an effect grabbed the pointer, we do not forward the event to surfaces + return; + } // TODO: redirect to proper client // TODO: don't use xtest @@ -60,6 +69,14 @@ void InputRedirection::processPointerButton(uint32_t button, InputRedirection::P m_pointerButtons[button] = state; emit pointerButtonStateChanged(button, state); + // TODO: keyboard modifiers + QMouseEvent event(buttonStateToEvent(state), m_globalPointer.toPoint(), m_globalPointer.toPoint(), + buttonToQtMouseButton(button), qtButtonStates(), 0); + // check whether an effect has a mouse grab + if (effects && static_cast(effects)->checkInputWindowEvent(&event)) { + // an effect grabbed the pointer, we do not forward the event to surfaces + return; + } // TODO: check which part of KWin would like to intercept the event // TODO: redirect to proper client @@ -96,6 +113,7 @@ void InputRedirection::processPointerAxis(InputRedirection::PointerAxis axis, qr emit pointerAxisChanged(axis, delta); // TODO: check which part of KWin would like to intercept the event + // TODO: Axis support for effect redirection // TODO: redirect to proper client // TODO: don't use xtest @@ -118,4 +136,48 @@ void InputRedirection::processPointerAxis(InputRedirection::PointerAxis axis, qr } } +QEvent::Type InputRedirection::buttonStateToEvent(InputRedirection::PointerButtonState state) +{ + switch (state) { + case KWin::InputRedirection::PointerButtonReleased: + return QEvent::MouseButtonRelease; + case KWin::InputRedirection::PointerButtonPressed: + return QEvent::MouseButtonPress; + } + return QEvent::None; +} + +Qt::MouseButton InputRedirection::buttonToQtMouseButton(uint32_t button) +{ + switch (button) { + case BTN_LEFT: + return Qt::LeftButton; + case BTN_MIDDLE: + return Qt::MiddleButton; + case BTN_RIGHT: + return Qt::RightButton; + case BTN_BACK: + return Qt::XButton1; + case BTN_FORWARD: + return Qt::XButton2; + } + return Qt::NoButton; +} + +Qt::MouseButtons InputRedirection::qtButtonStates() const +{ + Qt::MouseButtons buttons; + for (auto it = m_pointerButtons.constBegin(); it != m_pointerButtons.constEnd(); ++it) { + if (it.value() == KWin::InputRedirection::PointerButtonReleased) { + continue; + } + Qt::MouseButton button = buttonToQtMouseButton(it.key()); + if (button != Qt::NoButton) { + buttons |= button; + } + } + return buttons; +} + + } // namespace diff --git a/input.h b/input.h index 5da4ccb714..02dca741d8 100644 --- a/input.h +++ b/input.h @@ -23,6 +23,7 @@ along with this program. If not, see . #include #include #include +#include namespace KWin { @@ -99,6 +100,9 @@ Q_SIGNALS: void pointerAxisChanged(PointerAxis axis, qreal delta); private: + static QEvent::Type buttonStateToEvent(PointerButtonState state); + static Qt::MouseButton buttonToQtMouseButton(uint32_t button); + Qt::MouseButtons qtButtonStates() const; QPointF m_globalPointer; QHash m_pointerButtons;