diff --git a/autotests/integration/move_resize_window_test.cpp b/autotests/integration/move_resize_window_test.cpp index 8c968f2024..e090dde134 100644 --- a/autotests/integration/move_resize_window_test.cpp +++ b/autotests/integration/move_resize_window_test.cpp @@ -30,9 +30,12 @@ along with this program. If not, see . #include #include +#include #include +#include #include #include +#include #include #include @@ -61,6 +64,8 @@ private Q_SLOTS: void testGrowShrink(); void testPointerMoveEnd_data(); void testPointerMoveEnd(); + void testClientSideMove_data(); + void testClientSideMove(); void testPlasmaShellSurfaceMovable_data(); void testPlasmaShellSurfaceMovable(); void testNetMove(); @@ -88,7 +93,8 @@ void MoveResizeWindowTest::initTestCase() void MoveResizeWindowTest::init() { - QVERIFY(Test::setupWaylandConnection(s_socketName, Test::AdditionalWaylandInterface::PlasmaShell)); + QVERIFY(Test::setupWaylandConnection(s_socketName, Test::AdditionalWaylandInterface::PlasmaShell | Test::AdditionalWaylandInterface::Seat)); + QVERIFY(Test::waitForWaylandPointer()); m_connection = Test::waylandConnection(); m_compositor = Test::waylandCompositor(); m_shell = Test::waylandShell(); @@ -402,6 +408,68 @@ void MoveResizeWindowTest::testPointerMoveEnd() surface.reset(); QVERIFY(Test::waitForWindowDestroyed(c)); } +void MoveResizeWindowTest::testClientSideMove_data() +{ + QTest::addColumn("type"); + + QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell; + QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5; +} + +void MoveResizeWindowTest::testClientSideMove() +{ + using namespace KWayland::Client; + Cursor::setPos(640, 512); + QScopedPointer pointer(Test::waylandSeat()->createPointer()); + QSignalSpy pointerEnteredSpy(pointer.data(), &Pointer::entered); + QVERIFY(pointerEnteredSpy.isValid()); + QSignalSpy pointerLeftSpy(pointer.data(), &Pointer::left); + QVERIFY(pointerLeftSpy.isValid()); + QSignalSpy buttonSpy(pointer.data(), &Pointer::buttonStateChanged); + QVERIFY(buttonSpy.isValid()); + + QScopedPointer surface(Test::createSurface()); + QFETCH(Test::ShellSurfaceType, type); + QScopedPointer shellSurface(Test::createShellSurface(type, surface.data())); + auto c = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue); + QVERIFY(c); + + // move pointer into center of geometry + const QRect startGeometry = c->geometry(); + Cursor::setPos(startGeometry.center()); + QVERIFY(pointerEnteredSpy.wait()); + QCOMPARE(pointerEnteredSpy.first().last().toPoint(), QPoint(49, 24)); + // simulate press + quint32 timestamp = 1; + kwinApp()->platform()->pointerButtonPressed(BTN_LEFT, timestamp++); + QVERIFY(buttonSpy.wait()); + QSignalSpy moveStartSpy(c, &AbstractClient::clientStartUserMovedResized); + QVERIFY(moveStartSpy.isValid()); + if (auto s = qobject_cast(shellSurface.data())) { + s->requestMove(Test::waylandSeat(), buttonSpy.first().first().value()); + } else if (auto s = qobject_cast(shellSurface.data())) { + s->requestMove(Test::waylandSeat(), buttonSpy.first().first().value()); + } + QVERIFY(moveStartSpy.wait()); + QCOMPARE(c->isMove(), true); + QVERIFY(pointerLeftSpy.wait()); + + // move a bit + QSignalSpy clientMoveStepSpy(c, &AbstractClient::clientStepUserMovedResized); + QVERIFY(clientMoveStepSpy.isValid()); + const QPoint startPoint = startGeometry.center(); + const int dragDistance = QApplication::startDragDistance(); + // Why? + kwinApp()->platform()->pointerMotion(startPoint + QPoint(dragDistance, dragDistance) + QPoint(6, 6), timestamp++); + QCOMPARE(clientMoveStepSpy.count(), 1); + + // and release again + kwinApp()->platform()->pointerButtonReleased(BTN_LEFT, timestamp++); + QVERIFY(pointerEnteredSpy.wait()); + QCOMPARE(c->isMove(), false); + QCOMPARE(c->geometry(), startGeometry.translated(QPoint(dragDistance, dragDistance) + QPoint(6, 6))); + QCOMPARE(pointerEnteredSpy.last().last().toPoint(), QPoint(49, 24)); +} void MoveResizeWindowTest::testPlasmaShellSurfaceMovable_data() { diff --git a/pointer_input.cpp b/pointer_input.cpp index 7716a4e61e..c2a04d094d 100644 --- a/pointer_input.cpp +++ b/pointer_input.cpp @@ -154,12 +154,27 @@ void PointerInputRedirection::init() } } ); + // connect the move resize of all window + auto setupMoveResizeConnection = [this] (AbstractClient *c) { + connect(c, &AbstractClient::clientStartUserMovedResized, this, &PointerInputRedirection::updateOnStartMoveResize); + connect(c, &AbstractClient::clientFinishUserMovedResized, this, &PointerInputRedirection::update); + }; + const auto clients = workspace()->allClientList(); + std::for_each(clients.begin(), clients.end(), setupMoveResizeConnection); + connect(workspace(), &Workspace::clientAdded, this, setupMoveResizeConnection); + connect(waylandServer(), &WaylandServer::shellClientAdded, this, setupMoveResizeConnection); // warp the cursor to center of screen warp(screens()->geometry().center()); updateAfterScreenChange(); } +void PointerInputRedirection::updateOnStartMoveResize() +{ + m_window.clear(); + waylandServer()->seat()->setFocusedPointerSurface(nullptr); +} + void PointerInputRedirection::processMotion(const QPointF &pos, uint32_t time, LibInput::Device *device) { if (!m_inited) { diff --git a/pointer_input.h b/pointer_input.h index cd730e9acc..e1bef9c62f 100644 --- a/pointer_input.h +++ b/pointer_input.h @@ -128,6 +128,7 @@ public: void processPinchGestureCancelled(quint32 time, KWin::LibInput::Device *device = nullptr); private: + void updateOnStartMoveResize(); void updatePosition(const QPointF &pos); void updateButton(uint32_t button, InputRedirection::PointerButtonState state); void warpXcbOnSurfaceLeft(KWayland::Server::SurfaceInterface *surface);