From 2694839099c3a0e9da3682569e1bd569247c3ae8 Mon Sep 17 00:00:00 2001 From: Roman Gilg Date: Mon, 11 Jun 2018 22:45:09 +0200 Subject: [PATCH] Remove pointer constraint on resource unbind Summary: A client might delete its pointer lock/confinement object. This is supposed to directly remove the pointer lock/confinement in KWin, but did not explicitly until now. BUG: 388885 Test Plan: Tested manually with Neverball, Nexuiz and the new pointer constraints test application. The pointer constraints autotest is also appended. Reviewers: #kwin, davidedmundson Reviewed By: #kwin, davidedmundson Subscribers: davidedmundson, graesslin, kwin Tags: #kwin Maniphest Tasks: T8923 Differential Revision: https://phabricator.kde.org/D13466 --- .../integration/pointer_constraints_test.cpp | 42 +++++++++++++++++++ input.cpp | 2 +- pointer_input.cpp | 9 ++-- pointer_input.h | 4 +- 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/autotests/integration/pointer_constraints_test.cpp b/autotests/integration/pointer_constraints_test.cpp index 41990ed02b..2f6ca820d8 100644 --- a/autotests/integration/pointer_constraints_test.cpp +++ b/autotests/integration/pointer_constraints_test.cpp @@ -37,6 +37,7 @@ along with this program. If not, see . #include #include #include +#include #include @@ -246,6 +247,24 @@ void TestPointerConstraints::testConfinedPointer() QVERIFY(confinedSpy2.wait()); QCOMPARE(input()->pointer()->isConstrained(), true); + // delete pointer confine + confinedPointer.reset(nullptr); + Test::flushWaylandConnection(); + + QSignalSpy constraintsChangedSpy(input()->pointer()->window()->surface(), &KWayland::Server::SurfaceInterface::pointerConstraintsChanged); + QVERIFY(constraintsChangedSpy.isValid()); + QVERIFY(constraintsChangedSpy.wait()); + + // should be unconfined + QCOMPARE(input()->pointer()->isConstrained(), false); + + // confine again + confinedPointer.reset(Test::waylandPointerConstraints()->confinePointer(surface.data(), pointer.data(), nullptr, PointerConstraints::LifeTime::Persistent)); + QSignalSpy confinedSpy3(confinedPointer.data(), &ConfinedPointer::confined); + QVERIFY(confinedSpy3.isValid()); + QVERIFY(confinedSpy3.wait()); + QCOMPARE(input()->pointer()->isConstrained(), true); + // and now unmap shellSurface.reset(); surface.reset(); @@ -302,6 +321,29 @@ void TestPointerConstraints::testLockedPointer() // moving cursor should be allowed again KWin::Cursor::setPos(c->geometry().center() + QPoint(1, 1)); QCOMPARE(KWin::Cursor::pos(), c->geometry().center() + QPoint(1, 1)); + + lockedPointer.reset(Test::waylandPointerConstraints()->lockPointer(surface.data(), pointer.data(), nullptr, PointerConstraints::LifeTime::Persistent)); + QSignalSpy lockedSpy2(lockedPointer.data(), &LockedPointer::locked); + QVERIFY(lockedSpy2.isValid()); + QVERIFY(lockedSpy2.wait()); + + // try to move the pointer + QCOMPARE(input()->pointer()->isConstrained(), true); + KWin::Cursor::setPos(c->geometry().center()); + QCOMPARE(KWin::Cursor::pos(), c->geometry().center() + QPoint(1, 1)); + + // delete pointer lock + lockedPointer.reset(nullptr); + Test::flushWaylandConnection(); + + QSignalSpy constraintsChangedSpy(input()->pointer()->window()->surface(), &KWayland::Server::SurfaceInterface::pointerConstraintsChanged); + QVERIFY(constraintsChangedSpy.isValid()); + QVERIFY(constraintsChangedSpy.wait()); + + // moving cursor should be allowed again + QCOMPARE(input()->pointer()->isConstrained(), false); + KWin::Cursor::setPos(c->geometry().center()); + QCOMPARE(KWin::Cursor::pos(), c->geometry().center()); } void TestPointerConstraints::testBreakConstrainedPointer_data() diff --git a/input.cpp b/input.cpp index 34fd62e71f..045873b880 100644 --- a/input.cpp +++ b/input.cpp @@ -1340,7 +1340,7 @@ public: if (event->buttons() == Qt::NoButton) { // update pointer window only if no button is pressed input()->pointer()->update(); - input()->pointer()->enablePointerConstraints(); + input()->pointer()->updatePointerConstraints(); } seat->setPointerPos(event->globalPos()); MouseEvent *e = static_cast(event); diff --git a/pointer_input.cpp b/pointer_input.cpp index 0c5d053786..2c6e33ebae 100644 --- a/pointer_input.cpp +++ b/pointer_input.cpp @@ -542,10 +542,10 @@ void PointerInputRedirection::update() } ); m_constraintsConnection = connect(m_window->surface(), &KWayland::Server::SurfaceInterface::pointerConstraintsChanged, - this, &PointerInputRedirection::enablePointerConstraints); + this, &PointerInputRedirection::updatePointerConstraints); // check whether a pointer confinement/lock fires m_blockConstraint = false; - enablePointerConstraints(); + updatePointerConstraints(); } else { m_window.clear(); warpXcbOnSurfaceLeft(nullptr); @@ -598,7 +598,7 @@ static QRegion getConstraintRegion(Toplevel *t, T *constraint) return intersected.translated(t->pos() + t->clientPos()); } -void PointerInputRedirection::enablePointerConstraints() +void PointerInputRedirection::updatePointerConstraints() { if (m_window.isNull()) { return; @@ -653,6 +653,7 @@ void PointerInputRedirection::enablePointerConstraints() return; } } else { + m_confined = false; disconnectConfinedPointerRegionConnection(); } const auto lock = s->lockedPointer(); @@ -669,6 +670,8 @@ void PointerInputRedirection::enablePointerConstraints() QStringLiteral("preferences-desktop-mouse"), 5000); // TODO: connect to region change - is it needed at all? If the pointer is locked it's always in the region } + } else { + m_locked = false; } } diff --git a/pointer_input.h b/pointer_input.h index f0c17d110f..1ea4032dcc 100644 --- a/pointer_input.h +++ b/pointer_input.h @@ -84,8 +84,10 @@ public: void setWindowSelectionCursor(const QByteArray &shape); void removeWindowSelectionCursor(); - void enablePointerConstraints(); + void updatePointerConstraints(); void breakPointerConstraints(); + + /* This is only used for ESC pressing */ void blockPointerConstraints() { m_blockConstraint = true; }