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
This commit is contained in:
Roman Gilg 2018-06-11 22:45:09 +02:00
parent e38ecfcbcf
commit 2694839099
4 changed files with 52 additions and 5 deletions

View file

@ -37,6 +37,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <KWayland/Client/shm_pool.h> #include <KWayland/Client/shm_pool.h>
#include <KWayland/Client/surface.h> #include <KWayland/Client/surface.h>
#include <KWayland/Server/seat_interface.h> #include <KWayland/Server/seat_interface.h>
#include <KWayland/Server/surface_interface.h>
#include <linux/input.h> #include <linux/input.h>
@ -246,6 +247,24 @@ void TestPointerConstraints::testConfinedPointer()
QVERIFY(confinedSpy2.wait()); QVERIFY(confinedSpy2.wait());
QCOMPARE(input()->pointer()->isConstrained(), true); 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 // and now unmap
shellSurface.reset(); shellSurface.reset();
surface.reset(); surface.reset();
@ -302,6 +321,29 @@ void TestPointerConstraints::testLockedPointer()
// moving cursor should be allowed again // moving cursor should be allowed again
KWin::Cursor::setPos(c->geometry().center() + QPoint(1, 1)); KWin::Cursor::setPos(c->geometry().center() + QPoint(1, 1));
QCOMPARE(KWin::Cursor::pos(), 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() void TestPointerConstraints::testBreakConstrainedPointer_data()

View file

@ -1340,7 +1340,7 @@ public:
if (event->buttons() == Qt::NoButton) { if (event->buttons() == Qt::NoButton) {
// update pointer window only if no button is pressed // update pointer window only if no button is pressed
input()->pointer()->update(); input()->pointer()->update();
input()->pointer()->enablePointerConstraints(); input()->pointer()->updatePointerConstraints();
} }
seat->setPointerPos(event->globalPos()); seat->setPointerPos(event->globalPos());
MouseEvent *e = static_cast<MouseEvent*>(event); MouseEvent *e = static_cast<MouseEvent*>(event);

View file

@ -542,10 +542,10 @@ void PointerInputRedirection::update()
} }
); );
m_constraintsConnection = connect(m_window->surface(), &KWayland::Server::SurfaceInterface::pointerConstraintsChanged, m_constraintsConnection = connect(m_window->surface(), &KWayland::Server::SurfaceInterface::pointerConstraintsChanged,
this, &PointerInputRedirection::enablePointerConstraints); this, &PointerInputRedirection::updatePointerConstraints);
// check whether a pointer confinement/lock fires // check whether a pointer confinement/lock fires
m_blockConstraint = false; m_blockConstraint = false;
enablePointerConstraints(); updatePointerConstraints();
} else { } else {
m_window.clear(); m_window.clear();
warpXcbOnSurfaceLeft(nullptr); warpXcbOnSurfaceLeft(nullptr);
@ -598,7 +598,7 @@ static QRegion getConstraintRegion(Toplevel *t, T *constraint)
return intersected.translated(t->pos() + t->clientPos()); return intersected.translated(t->pos() + t->clientPos());
} }
void PointerInputRedirection::enablePointerConstraints() void PointerInputRedirection::updatePointerConstraints()
{ {
if (m_window.isNull()) { if (m_window.isNull()) {
return; return;
@ -653,6 +653,7 @@ void PointerInputRedirection::enablePointerConstraints()
return; return;
} }
} else { } else {
m_confined = false;
disconnectConfinedPointerRegionConnection(); disconnectConfinedPointerRegionConnection();
} }
const auto lock = s->lockedPointer(); const auto lock = s->lockedPointer();
@ -669,6 +670,8 @@ void PointerInputRedirection::enablePointerConstraints()
QStringLiteral("preferences-desktop-mouse"), 5000); 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 // 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;
} }
} }

View file

@ -84,8 +84,10 @@ public:
void setWindowSelectionCursor(const QByteArray &shape); void setWindowSelectionCursor(const QByteArray &shape);
void removeWindowSelectionCursor(); void removeWindowSelectionCursor();
void enablePointerConstraints(); void updatePointerConstraints();
void breakPointerConstraints(); void breakPointerConstraints();
/* This is only used for ESC pressing */
void blockPointerConstraints() { void blockPointerConstraints() {
m_blockConstraint = true; m_blockConstraint = true;
} }