diff --git a/autotests/integration/pointer_input.cpp b/autotests/integration/pointer_input.cpp index e49ce309f7..0ab348cd59 100644 --- a/autotests/integration/pointer_input.cpp +++ b/autotests/integration/pointer_input.cpp @@ -341,7 +341,8 @@ void PointerInputTest::testUpdateFocusAfterScreenChange() AbstractClient *window = workspace()->activeClient(); QVERIFY(window); QVERIFY(window->frameGeometry().contains(Cursors::self()->mouse()->pos())); - QTRY_COMPARE(enteredSpy.count(), 1); + QVERIFY(enteredSpy.wait()); + QCOMPARE(enteredSpy.count(), 1); // move the cursor to the second screen Cursors::self()->mouse()->setPos(1500, 300); @@ -363,7 +364,8 @@ void PointerInputTest::testUpdateFocusAfterScreenChange() QVERIFY(window->frameGeometry().contains(Cursors::self()->mouse()->pos())); // and we should get an enter event - QTRY_COMPARE(enteredSpy.count(), 2); + QVERIFY(enteredSpy.wait()); + QCOMPARE(enteredSpy.count(), 2); } void PointerInputTest::testModifierClickUnrestrictedMove_data() diff --git a/autotests/integration/xwayland_input_test.cpp b/autotests/integration/xwayland_input_test.cpp index eb7f1d51de..bcb50d77f3 100644 --- a/autotests/integration/xwayland_input_test.cpp +++ b/autotests/integration/xwayland_input_test.cpp @@ -181,7 +181,6 @@ void XWaylandInputTest::testPointerEnterLeaveSsd() QVERIFY(enteredSpy.isEmpty()); Cursors::self()->mouse()->setPos(client->frameGeometry().center()); QCOMPARE(waylandServer()->seat()->focusedPointerSurface(), client->surface()); - QVERIFY(waylandServer()->seat()->focusedPointer()); QVERIFY(enteredSpy.wait()); QCOMPARE(enteredSpy.last().first(), client->frameGeometry().center() - client->clientPos()); @@ -277,7 +276,6 @@ void XWaylandInputTest::testPointerEventLeaveCsd() QVERIFY(enteredSpy.isEmpty()); Cursors::self()->mouse()->setPos(client->frameGeometry().center()); QCOMPARE(waylandServer()->seat()->focusedPointerSurface(), client->surface()); - QVERIFY(waylandServer()->seat()->focusedPointer()); QVERIFY(enteredSpy.wait()); QCOMPARE(enteredSpy.last().first(), QPoint(59, 104)); diff --git a/src/input.cpp b/src/input.cpp index fdbad49aa6..1ed9fa1274 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -58,6 +58,23 @@ namespace KWin { +static KWaylandServer::PointerAxisSource kwinAxisSourceToKWaylandAxisSource(InputRedirection::PointerAxisSource source) +{ + switch (source) { + case KWin::InputRedirection::PointerAxisSourceWheel: + return KWaylandServer::PointerAxisSource::Wheel; + case KWin::InputRedirection::PointerAxisSourceFinger: + return KWaylandServer::PointerAxisSource::Finger; + case KWin::InputRedirection::PointerAxisSourceContinuous: + return KWaylandServer::PointerAxisSource::Continuous; + case KWin::InputRedirection::PointerAxisSourceWheelTilt: + return KWaylandServer::PointerAxisSource::WheelTilt; + case KWin::InputRedirection::PointerAxisSourceUnknown: + default: + return KWaylandServer::PointerAxisSource::Unknown; + } +} + InputEventFilter::InputEventFilter() = default; InputEventFilter::~InputEventFilter() @@ -268,12 +285,18 @@ public: if (pointerSurfaceAllowed()) { // TODO: should the pointer position always stay in sync, i.e. not do the check? seat->setPointerPos(event->screenPos().toPoint()); + seat->pointerFrame(); } } else if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) { if (pointerSurfaceAllowed()) { // TODO: can we leak presses/releases here when we move the mouse in between from an allowed surface to // disallowed one or vice versa? - event->type() == QEvent::MouseButtonPress ? seat->pointerButtonPressed(nativeButton) : seat->pointerButtonReleased(nativeButton); + if (event->type() == QEvent::MouseButtonPress) { + seat->pointerButtonPressed(nativeButton); + } else { + seat->pointerButtonReleased(nativeButton); + } + seat->pointerFrame(); } } return true; @@ -284,9 +307,11 @@ public: } auto seat = waylandServer()->seat(); if (pointerSurfaceAllowed()) { - seat->setTimestamp(event->timestamp()); - const Qt::Orientation orientation = event->angleDelta().x() == 0 ? Qt::Vertical : Qt::Horizontal; - seat->pointerAxis(orientation, orientation == Qt::Horizontal ? event->angleDelta().x() : event->angleDelta().y()); + const WheelEvent *wheelEvent = static_cast(event); + seat->setTimestamp(wheelEvent->timestamp()); + seat->pointerAxis(wheelEvent->orientation(), wheelEvent->delta(), wheelEvent->discreteDelta(), + kwinAxisSourceToKWaylandAxisSource(wheelEvent->axisSource())); + seat->pointerFrame(); } return true; } @@ -1378,13 +1403,16 @@ public: if (e->delta() != QSizeF()) { seat->relativePointerMotion(e->delta(), e->deltaUnaccelerated(), e->timestampMicroseconds()); } + seat->pointerFrame(); break; } case QEvent::MouseButtonPress: seat->pointerButtonPressed(nativeButton); + seat->pointerFrame(); break; case QEvent::MouseButtonRelease: seat->pointerButtonReleased(nativeButton); + seat->pointerFrame(); break; default: break; @@ -1395,26 +1423,9 @@ public: auto seat = waylandServer()->seat(); seat->setTimestamp(event->timestamp()); auto _event = static_cast(event); - KWaylandServer::PointerAxisSource source; - switch (_event->axisSource()) { - case KWin::InputRedirection::PointerAxisSourceWheel: - source = KWaylandServer::PointerAxisSource::Wheel; - break; - case KWin::InputRedirection::PointerAxisSourceFinger: - source = KWaylandServer::PointerAxisSource::Finger; - break; - case KWin::InputRedirection::PointerAxisSourceContinuous: - source = KWaylandServer::PointerAxisSource::Continuous; - break; - case KWin::InputRedirection::PointerAxisSourceWheelTilt: - source = KWaylandServer::PointerAxisSource::WheelTilt; - break; - case KWin::InputRedirection::PointerAxisSourceUnknown: - default: - source = KWaylandServer::PointerAxisSource::Unknown; - break; - } - seat->pointerAxisV5(_event->orientation(), _event->delta(), _event->discreteDelta(), source); + seat->pointerAxis(_event->orientation(), _event->delta(), _event->discreteDelta(), + kwinAxisSourceToKWaylandAxisSource(_event->axisSource())); + seat->pointerFrame(); return true; } bool keyEvent(QKeyEvent *event) override { @@ -1880,6 +1891,7 @@ public: case QEvent::MouseMove: { const auto pos = input()->globalPointer(); seat->setPointerPos(pos); + seat->pointerFrame(); const auto eventPos = event->globalPos(); // TODO: use InputDeviceHandler::at() here and check isClient()? @@ -1909,9 +1921,11 @@ public: } case QEvent::MouseButtonPress: seat->pointerButtonPressed(nativeButton); + seat->pointerFrame(); break; case QEvent::MouseButtonRelease: seat->pointerButtonReleased(nativeButton); + seat->pointerFrame(); break; default: break; diff --git a/src/pointer_input.cpp b/src/pointer_input.cpp index 44ee3fd9fd..cc59172534 100644 --- a/src/pointer_input.cpp +++ b/src/pointer_input.cpp @@ -929,7 +929,8 @@ CursorImage::CursorImage(PointerInputRedirection *parent) : QObject(parent) , m_pointer(parent) { - connect(waylandServer()->seat(), &KWaylandServer::SeatInterface::focusedPointerChanged, this, &CursorImage::update); + connect(waylandServer()->seat(), &KWaylandServer::SeatInterface::hasPointerChanged, + this, &CursorImage::handlePointerChanged); connect(waylandServer()->seat(), &KWaylandServer::SeatInterface::dragStarted, this, &CursorImage::updateDrag); connect(waylandServer()->seat(), &KWaylandServer::SeatInterface::dragEnded, this, [this] { @@ -959,6 +960,8 @@ CursorImage::CursorImage(PointerInputRedirection *parent) updateMoveResize(); // TODO: update effects }); + + handlePointerChanged(); } CursorImage::~CursorImage() = default; @@ -972,25 +975,13 @@ void CursorImage::markAsRendered() icon->surface()->frameRendered(m_surfaceRenderedTimer.elapsed()); } } - auto p = waylandServer()->seat()->dragPointer(); - if (!p) { - return; - } - auto c = p->cursor(); - if (!c) { - return; - } - auto cursorSurface = c->surface(); - if (cursorSurface.isNull()) { - return; - } - cursorSurface->frameRendered(m_surfaceRenderedTimer.elapsed()); + } + if (m_currentSource != CursorSource::LockScreen + && m_currentSource != CursorSource::PointerSurface + && m_currentSource != CursorSource::DragAndDrop) { return; } - if (m_currentSource != CursorSource::LockScreen && m_currentSource != CursorSource::PointerSurface) { - return; - } - auto p = waylandServer()->seat()->focusedPointer(); + auto p = waylandServer()->seat()->pointer(); if (!p) { return; } @@ -999,22 +990,34 @@ void CursorImage::markAsRendered() return; } auto cursorSurface = c->surface(); - if (cursorSurface.isNull()) { + if (!cursorSurface) { return; } cursorSurface->frameRendered(m_surfaceRenderedTimer.elapsed()); } -void CursorImage::update() +void CursorImage::handlePointerChanged() +{ + KWaylandServer::PointerInterface *pointer = waylandServer()->seat()->pointer(); + + if (pointer) { + connect(pointer, &KWaylandServer::PointerInterface::focusedSurfaceChanged, + this, &CursorImage::handleFocusedSurfaceChanged); + } +} + +void CursorImage::handleFocusedSurfaceChanged() { if (s_cursorUpdateBlocking) { return; } - using namespace KWaylandServer; + + KWaylandServer::PointerInterface *pointer = waylandServer()->seat()->pointer(); disconnect(m_serverCursor.connection); - auto p = waylandServer()->seat()->focusedPointer(); - if (p) { - m_serverCursor.connection = connect(p, &PointerInterface::cursorChanged, this, &CursorImage::updateServerCursor); + + if (pointer->focusedSurface()) { + m_serverCursor.connection = connect(pointer, &KWaylandServer::PointerInterface::cursorChanged, + this, &CursorImage::updateServerCursor); } else { m_serverCursor.connection = QMetaObject::Connection(); reevaluteSource(); @@ -1064,7 +1067,7 @@ void CursorImage::updateServerCursor() m_serverCursor.cursor = {}; reevaluteSource(); const bool needsEmit = m_currentSource == CursorSource::LockScreen || m_currentSource == CursorSource::PointerSurface; - auto p = waylandServer()->seat()->focusedPointer(); + auto p = waylandServer()->seat()->pointer(); if (!p) { if (needsEmit) { emit changed(); @@ -1079,13 +1082,13 @@ void CursorImage::updateServerCursor() return; } auto cursorSurface = c->surface(); - if (cursorSurface.isNull()) { + if (!cursorSurface) { if (needsEmit) { emit changed(); } return; } - auto buffer = cursorSurface.data()->buffer(); + auto buffer = cursorSurface->buffer(); if (!buffer) { if (needsEmit) { emit changed(); @@ -1138,8 +1141,9 @@ void CursorImage::updateDrag() disconnect(m_drag.connection); m_drag.cursor = {}; reevaluteSource(); - if (auto p = waylandServer()->seat()->dragPointer()) { - m_drag.connection = connect(p, &PointerInterface::cursorChanged, this, &CursorImage::updateDragCursor); + if (waylandServer()->seat()->isDragPointer()) { + KWaylandServer::PointerInterface *pointer = waylandServer()->seat()->pointer(); + m_drag.connection = connect(pointer, &PointerInterface::cursorChanged, this, &CursorImage::updateDragCursor); } else { m_drag.connection = QMetaObject::Connection(); } @@ -1160,7 +1164,7 @@ void CursorImage::updateDragCursor() } } } - auto p = waylandServer()->seat()->dragPointer(); + auto p = waylandServer()->seat()->pointer(); if (!p) { if (needsEmit) { emit changed(); @@ -1175,13 +1179,13 @@ void CursorImage::updateDragCursor() return; } auto cursorSurface = c->surface(); - if (cursorSurface.isNull()) { + if (!cursorSurface) { if (needsEmit) { emit changed(); } return; } - auto buffer = cursorSurface.data()->buffer(); + auto buffer = cursorSurface->buffer(); if (!buffer) { if (needsEmit) { emit changed(); @@ -1345,7 +1349,8 @@ void CursorImage::reevaluteSource() setSource(CursorSource::Decoration); return; } - if (m_pointer->focus() && waylandServer()->seat()->focusedPointer()) { + const KWaylandServer::PointerInterface *pointer = waylandServer()->seat()->pointer(); + if (pointer && pointer->focusedSurface()) { setSource(CursorSource::PointerSurface); return; } diff --git a/src/pointer_input.h b/src/pointer_input.h index 3c4c268c5e..fa5bb0f5b8 100644 --- a/src/pointer_input.h +++ b/src/pointer_input.h @@ -212,7 +212,6 @@ Q_SIGNALS: private: void reevaluteSource(); - void update(); void updateServerCursor(); void updateDecoration(); void updateDecorationCursor(); @@ -220,6 +219,9 @@ private: void updateDrag(); void updateDragCursor(); + void handlePointerChanged(); + void handleFocusedSurfaceChanged(); + void loadThemeCursor(CursorShape shape, WaylandCursorImage::Image *image); void loadThemeCursor(const QByteArray &shape, WaylandCursorImage::Image *image);