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);