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;