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:
parent
e38ecfcbcf
commit
2694839099
4 changed files with 52 additions and 5 deletions
|
@ -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()
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue