Commit 0bd5eff8 authored by Roman Gilg's avatar Roman Gilg

Make keyboard focus a pointer constraints necessity

Summary:
This patch changes KWin's pointer constraining behavior by only allowing
constraints if the surface has keyboard focus. In case the client activation
state changes, it rechecks it.

Test Plan:
Manually with the pointer constraints test application and opening the
launcher by pressing meta. Also amended autotest.

Reviewers: #kwin, graesslin

Reviewed By: #kwin, graesslin

Subscribers: graesslin, davidedmundson, kwin

Tags: #kwin

Maniphest Tasks: T8923

Differential Revision: https://phabricator.kde.org/D13492
parent ea05ac38
...@@ -224,6 +224,16 @@ void TestPointerConstraints::testConfinedPointer() ...@@ -224,6 +224,16 @@ void TestPointerConstraints::testConfinedPointer()
QCOMPARE(input()->pointer()->isConstrained(), true); QCOMPARE(input()->pointer()->isConstrained(), true);
QVERIFY(confinedSpy2.wait()); QVERIFY(confinedSpy2.wait());
// deactivate the client, this should unconfine
workspace()->activateClient(nullptr);
QVERIFY(unconfinedSpy2.wait());
QCOMPARE(input()->pointer()->isConstrained(), false);
// activate it again, this confines again
workspace()->activateClient(static_cast<AbstractClient*>(input()->pointer()->window().data()));
QVERIFY(confinedSpy2.wait());
QCOMPARE(input()->pointer()->isConstrained(), true);
// create a second window and move it above our constrained window // create a second window and move it above our constrained window
QScopedPointer<Surface> surface2(Test::createSurface()); QScopedPointer<Surface> surface2(Test::createSurface());
QScopedPointer<QObject> shellSurface2(Test::createShellSurface(type, surface2.data())); QScopedPointer<QObject> shellSurface2(Test::createShellSurface(type, surface2.data()));
......
...@@ -544,6 +544,8 @@ void PointerInputRedirection::update() ...@@ -544,6 +544,8 @@ 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::updatePointerConstraints); this, &PointerInputRedirection::updatePointerConstraints);
m_constraintsActivatedConnection = connect(workspace(), &Workspace::clientActivated,
this, &PointerInputRedirection::updatePointerConstraints);
// check whether a pointer confinement/lock fires // check whether a pointer confinement/lock fires
m_blockConstraint = false; m_blockConstraint = false;
updatePointerConstraints(); updatePointerConstraints();
...@@ -588,6 +590,9 @@ void PointerInputRedirection::disconnectPointerConstraintsConnection() ...@@ -588,6 +590,9 @@ void PointerInputRedirection::disconnectPointerConstraintsConnection()
{ {
disconnect(m_constraintsConnection); disconnect(m_constraintsConnection);
m_constraintsConnection = QMetaObject::Connection(); m_constraintsConnection = QMetaObject::Connection();
disconnect(m_constraintsActivatedConnection);
m_constraintsActivatedConnection = QMetaObject::Connection();
} }
template <typename T> template <typename T>
...@@ -617,13 +622,19 @@ void PointerInputRedirection::updatePointerConstraints() ...@@ -617,13 +622,19 @@ void PointerInputRedirection::updatePointerConstraints()
if (m_blockConstraint) { if (m_blockConstraint) {
return; return;
} }
const bool windowIsActive = m_window == workspace()->activeClient();
const auto cf = s->confinedPointer(); const auto cf = s->confinedPointer();
if (cf) { if (cf) {
if (cf->isConfined()) { if (cf->isConfined()) {
if (!windowIsActive) {
cf->setConfined(false);
m_confined = false;
disconnectConfinedPointerRegionConnection();
}
return; return;
} }
const QRegion r = getConstraintRegion(m_window.data(), cf.data()); const QRegion r = getConstraintRegion(m_window.data(), cf.data());
if (r.contains(m_pos.toPoint())) { if (windowIsActive && r.contains(m_pos.toPoint())) {
cf->setConfined(true); cf->setConfined(true);
m_confined = true; m_confined = true;
m_confinedPointerRegionConnection = connect(cf.data(), &KWayland::Server::ConfinedPointerInterface::regionChanged, this, m_confinedPointerRegionConnection = connect(cf.data(), &KWayland::Server::ConfinedPointerInterface::regionChanged, this,
...@@ -660,10 +671,14 @@ void PointerInputRedirection::updatePointerConstraints() ...@@ -660,10 +671,14 @@ void PointerInputRedirection::updatePointerConstraints()
const auto lock = s->lockedPointer(); const auto lock = s->lockedPointer();
if (lock) { if (lock) {
if (lock->isLocked()) { if (lock->isLocked()) {
if (!windowIsActive) {
lock->setLocked(false);
m_locked = false;
}
return; return;
} }
const QRegion r = getConstraintRegion(m_window.data(), lock.data()); const QRegion r = getConstraintRegion(m_window.data(), lock.data());
if (r.contains(m_pos.toPoint())) { if (windowIsActive && r.contains(m_pos.toPoint())) {
lock->setLocked(true); lock->setLocked(true);
m_locked = true; m_locked = true;
OSD::show(i18nc("notification about mouse pointer locked", OSD::show(i18nc("notification about mouse pointer locked",
......
...@@ -165,6 +165,7 @@ private: ...@@ -165,6 +165,7 @@ private:
QMetaObject::Connection m_windowGeometryConnection; QMetaObject::Connection m_windowGeometryConnection;
QMetaObject::Connection m_internalWindowConnection; QMetaObject::Connection m_internalWindowConnection;
QMetaObject::Connection m_constraintsConnection; QMetaObject::Connection m_constraintsConnection;
QMetaObject::Connection m_constraintsActivatedConnection;
QMetaObject::Connection m_confinedPointerRegionConnection; QMetaObject::Connection m_confinedPointerRegionConnection;
QMetaObject::Connection m_decorationGeometryConnection; QMetaObject::Connection m_decorationGeometryConnection;
bool m_confined = false; bool m_confined = false;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment