diff --git a/input.cpp b/input.cpp index c6489a7110..2c339d7e88 100644 --- a/input.cpp +++ b/input.cpp @@ -32,13 +32,15 @@ along with this program. If not, see . #if HAVE_INPUT #include "libinput/connection.h" #endif +#if HAVE_WAYLAND +#include "wayland_server.h" +#include +#endif // Qt #include #include // KDE #include -// TODO: remove xtest -#include #if HAVE_XKB #include #endif @@ -241,28 +243,68 @@ void InputRedirection::setupLibInput() #endif } +#if HAVE_WAYLAND +static KWayland::Server::SeatInterface *findSeat() +{ + auto server = waylandServer(); + if (!server) { + return nullptr; + } + return server->seat(); +} +#endif + void InputRedirection::updatePointerWindow() { // TODO: handle pointer grab aka popups Toplevel *t = findToplevel(m_globalPointer.toPoint()); - const bool oldWindowValid = !m_pointerWindow.isNull(); - if (oldWindowValid && t == m_pointerWindow.data()) { + auto oldWindow = m_pointerWindow; + if (!oldWindow.isNull() && t == m_pointerWindow.data()) { return; } - if (oldWindowValid) { - m_pointerWindow.data()->sendPointerLeaveEvent(m_globalPointer); +#if HAVE_WAYLAND + if (auto seat = findSeat()) { + // disconnect old surface + if (oldWindow) { + disconnect(oldWindow.data(), &Toplevel::geometryChanged, this, &InputRedirection::updateFocusedPointerPosition); + } + if (t && t->surface()) { + seat->setFocusedPointerSurface(t->surface(), t->pos()); + connect(t, &Toplevel::geometryChanged, this, &InputRedirection::updateFocusedPointerPosition); + } else { + seat->setFocusedPointerSurface(nullptr); + t = nullptr; + } } +#endif if (!t) { m_pointerWindow.clear(); return; } m_pointerWindow = QWeakPointer(t); - t->sendPointerEnterEvent(m_globalPointer); +} + +void InputRedirection::updateFocusedPointerPosition() +{ +#if HAVE_WAYLAND + if (m_pointerWindow.isNull()) { + return; + } + if (workspace()->getMovingClient()) { + // don't update while moving + return; + } + if (auto seat = findSeat()) { + if (m_pointerWindow.data()->surface() != seat->focusedPointerSurface()) { + return; + } + seat->setFocusedPointerSurfacePosition(m_pointerWindow.data()->pos()); + } +#endif } void InputRedirection::processPointerMotion(const QPointF &pos, uint32_t time) { - Q_UNUSED(time) // first update to new mouse position // const QPointF oldPos = m_globalPointer; updatePointerPosition(pos); @@ -277,19 +319,16 @@ void InputRedirection::processPointerMotion(const QPointF &pos, uint32_t time) } QWeakPointer old = m_pointerWindow; updatePointerWindow(); - if (!m_pointerWindow.isNull() && old.data() == m_pointerWindow.data()) { - m_pointerWindow.data()->sendPointerMoveEvent(pos); +#if HAVE_WAYLAND + if (auto seat = findSeat()) { + seat->setTimestamp(time); + seat->setPointerPos(pos); } - - // TODO: don't use xtest - // still doing the fake event here as it requires the event to be send on the root window - xcb_test_fake_input(connection(), XCB_MOTION_NOTIFY, 0, XCB_TIME_CURRENT_TIME, XCB_WINDOW_NONE, - pos.toPoint().x(), pos.toPoint().y(), 0); +#endif } void InputRedirection::processPointerButton(uint32_t button, InputRedirection::PointerButtonState state, uint32_t time) { - Q_UNUSED(time) m_pointerButtons[button] = state; emit pointerButtonStateChanged(button, state); @@ -308,16 +347,16 @@ void InputRedirection::processPointerButton(uint32_t button, InputRedirection::P } #endif // TODO: check which part of KWin would like to intercept the event - if (m_pointerWindow.isNull()) { - // there is no window which can receive the - return; +#if HAVE_WAYLAND + if (auto seat = findSeat()) { + seat->setTimestamp(time); + state == PointerButtonPressed ? seat->pointerButtonPressed(button) : seat->pointerButtonReleased(button); } - m_pointerWindow.data()->sendPointerButtonEvent(button, state); +#endif } void InputRedirection::processPointerAxis(InputRedirection::PointerAxis axis, qreal delta, uint32_t time) { - Q_UNUSED(time) if (delta == 0) { return; } @@ -346,11 +385,12 @@ void InputRedirection::processPointerAxis(InputRedirection::PointerAxis axis, qr // TODO: check which part of KWin would like to intercept the event // TODO: Axis support for effect redirection - if (m_pointerWindow.isNull()) { - // there is no window which can receive the - return; +#if HAVE_WAYLAND + if (auto seat = findSeat()) { + seat->setTimestamp(time); + seat->pointerAxis(axis == InputRedirection::PointerAxisHorizontal ? Qt::Horizontal : Qt::Vertical, delta); } - m_pointerWindow.data()->sendPointerAxisEvent(axis, delta); +#endif } void InputRedirection::processKeyboardKey(uint32_t key, InputRedirection::KeyboardKeyState state, uint32_t time) diff --git a/input.h b/input.h index 05512b6a17..0380bd987b 100644 --- a/input.h +++ b/input.h @@ -169,6 +169,7 @@ private: void updatePointerPosition(const QPointF &pos); void updatePointerAfterScreenChange(); void registerShortcutForGlobalAccelTimestamp(QAction *action); + void updateFocusedPointerPosition(); QPointF m_globalPointer; QHash m_pointerButtons; #if HAVE_XKB