Commit 6072b0cd authored by Roman Gilg's avatar Roman Gilg

Remove breaking pointer constraints functionality

Summary:
With 26948390, 0bd5eff8 and f0ba436c it is now possible to
unconstrain a pointer by killing the client or deactivating the window, for
example by switching the window via the TabBox.

A user should always be able to do it therefore without needing to explicitly
break the pointer constrain as in the past with the Esc key.

Therefore remove the functionality and also remove the OSD announcing it,
which was often shown at the wrong time.

Test Plan: Manually and auto test adapted.

Reviewers: #kwin, #vdg, hein

Reviewed By: hein

Subscribers: ngraham, hein, kwin

Tags: #kwin

Maniphest Tasks: T8923

Differential Revision: https://phabricator.kde.org/D15234
parent 74994a7f
......@@ -63,8 +63,6 @@ private Q_SLOTS:
void testConfinedPointer();
void testLockedPointer_data();
void testLockedPointer();
void testBreakConstrainedPointer_data();
void testBreakConstrainedPointer();
void testCloseWindowWithLockedPointer_data();
void testCloseWindowWithLockedPointer();
};
......@@ -188,47 +186,27 @@ void TestPointerConstraints::testConfinedPointer()
QCOMPARE(pointerPositionChangedSpy.count(), 1);
QCOMPARE(KWin::Cursor::pos(), position);
// let's break the constraint explicitly
input()->pointer()->breakPointerConstraints();
QCOMPARE(input()->pointer()->isConstrained(), false);
// deactivate the client, this should unconfine
workspace()->activateClient(nullptr);
QVERIFY(unconfinedSpy.wait());
QCOMPARE(input()->pointer()->isConstrained(), false);
// reconfine pointer (this time with persistent life time)
confinedPointer.reset(Test::waylandPointerConstraints()->confinePointer(surface.data(), pointer.data(), nullptr, PointerConstraints::LifeTime::Persistent));
QSignalSpy confinedSpy2(confinedPointer.data(), &ConfinedPointer::confined);
QVERIFY(confinedSpy2.isValid());
QSignalSpy unconfinedSpy2(confinedPointer.data(), &ConfinedPointer::unconfined);
QVERIFY(unconfinedSpy2.isValid());
// should get confined
QVERIFY(confinedSpy2.wait());
QCOMPARE(input()->pointer()->isConstrained(), true);
// now let's unconfine again, any pointer movement should confine again
input()->pointer()->breakPointerConstraints();
QCOMPARE(input()->pointer()->isConstrained(), false);
QVERIFY(unconfinedSpy2.wait());
KWin::Cursor::setPos(c->geometry().center());
QCOMPARE(KWin::Cursor::pos(), c->geometry().center());
QCOMPARE(input()->pointer()->isConstrained(), true);
// activate it again, this confines again
workspace()->activateClient(static_cast<AbstractClient*>(input()->pointer()->window().data()));
QVERIFY(confinedSpy2.wait());
// let's use the other break constraint and block
input()->pointer()->breakPointerConstraints();
input()->pointer()->blockPointerConstraints();
QCOMPARE(input()->pointer()->isConstrained(), false);
KWin::Cursor::setPos(c->geometry().center() + QPoint(1, 1));
QCOMPARE(input()->pointer()->isConstrained(), false);
QVERIFY(!confinedSpy2.wait());
// now move outside and back in again, that should confine
KWin::Cursor::setPos(c->geometry().bottomRight() + QPoint(1, 1));
KWin::Cursor::setPos(c->geometry().center() + QPoint(1, 1));
QCOMPARE(input()->pointer()->isConstrained(), true);
QVERIFY(confinedSpy2.wait());
// deactivate the client, this should unconfine
// deactivate the client one more time with the persistent life time constraint, 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());
......@@ -246,7 +224,7 @@ void TestPointerConstraints::testConfinedPointer()
QVERIFY(confinedSpy2.wait());
// let's set a region which results in unconfined
auto r = Test::waylandCompositor()->createRegion(QRegion(0, 0, 1, 1));
auto r = Test::waylandCompositor()->createRegion(QRegion(2, 2, 3, 3));
confinedPointer->setRegion(r.get());
surface->commit(Surface::CommitFlag::None);
QVERIFY(unconfinedSpy2.wait());
......@@ -323,8 +301,8 @@ void TestPointerConstraints::testLockedPointer()
KWin::Cursor::setPos(c->geometry().center() + QPoint(1, 1));
QCOMPARE(KWin::Cursor::pos(), c->geometry().center());
// now unlock again
input()->pointer()->breakPointerConstraints();
// deactivate the client, this should unlock
workspace()->activateClient(nullptr);
QCOMPARE(input()->pointer()->isConstrained(), false);
QVERIFY(unlockedSpy.wait());
......@@ -335,7 +313,11 @@ void TestPointerConstraints::testLockedPointer()
lockedPointer.reset(Test::waylandPointerConstraints()->lockPointer(surface.data(), pointer.data(), nullptr, PointerConstraints::LifeTime::Persistent));
QSignalSpy lockedSpy2(lockedPointer.data(), &LockedPointer::locked);
QVERIFY(lockedSpy2.isValid());
// activate the client again, this should lock again
workspace()->activateClient(static_cast<AbstractClient*>(input()->pointer()->window().data()));
QVERIFY(lockedSpy2.wait());
QCOMPARE(input()->pointer()->isConstrained(), true);
// try to move the pointer
QCOMPARE(input()->pointer()->isConstrained(), true);
......@@ -356,95 +338,6 @@ void TestPointerConstraints::testLockedPointer()
QCOMPARE(KWin::Cursor::pos(), c->geometry().center());
}
void TestPointerConstraints::testBreakConstrainedPointer_data()
{
QTest::addColumn<Test::ShellSurfaceType>("type");
QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell;
QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5;
QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6;
}
void TestPointerConstraints::testBreakConstrainedPointer()
{
// this test verifies the breaking of Pointer constraints through the keyboard event filter
QScopedPointer<Surface> surface(Test::createSurface());
QFETCH(Test::ShellSurfaceType, type);
QScopedPointer<QObject> shellSurface(Test::createShellSurface(type, surface.data()));
QScopedPointer<Pointer> pointer(Test::waylandSeat()->createPointer());
QScopedPointer<Keyboard> keyboard(Test::waylandSeat()->createKeyboard());
QSignalSpy keyboardEnteredSpy(keyboard.data(), &Keyboard::entered);
QVERIFY(keyboardEnteredSpy.isValid());
QSignalSpy keyboardLeftSpy(keyboard.data(), &Keyboard::left);
QVERIFY(keyboardLeftSpy.isValid());
QSignalSpy keyChangedSpy(keyboard.data(), &Keyboard::keyChanged);
QVERIFY(keyChangedSpy.isValid());
QScopedPointer<LockedPointer> lockedPointer(Test::waylandPointerConstraints()->lockPointer(surface.data(), pointer.data(), nullptr, PointerConstraints::LifeTime::Persistent));
QSignalSpy lockedSpy(lockedPointer.data(), &LockedPointer::locked);
QVERIFY(lockedSpy.isValid());
QSignalSpy unlockedSpy(lockedPointer.data(), &LockedPointer::unlocked);
QVERIFY(unlockedSpy.isValid());
// now map the window
auto c = Test::renderAndWaitForShown(surface.data(), QSize(100, 100), Qt::blue);
QVERIFY(c);
QVERIFY(!c->geometry().contains(KWin::Cursor::pos()));
QVERIFY(keyboardEnteredSpy.wait());
// now let's lock
QCOMPARE(input()->pointer()->isConstrained(), false);
KWin::Cursor::setPos(c->geometry().center());
QCOMPARE(KWin::Cursor::pos(), c->geometry().center());
QCOMPARE(input()->pointer()->isConstrained(), true);
QVERIFY(lockedSpy.wait());
// now try to break
quint32 timestamp = 0;
kwinApp()->platform()->keyboardKeyPressed(KEY_ESC, timestamp++);
QVERIFY(keyChangedSpy.wait());
// and just waiting should break constrain
QVERIFY(unlockedSpy.wait());
QCOMPARE(keyboardLeftSpy.count(), 1);
QCOMPARE(input()->pointer()->isConstrained(), false);
// and should enter again
QTRY_COMPARE(keyboardEnteredSpy.count(), 2);
QCOMPARE(waylandServer()->seat()->focusedKeyboardSurface(), c->surface());
kwinApp()->platform()->keyboardKeyReleased(KEY_ESC, timestamp++);
QVERIFY(!keyChangedSpy.wait());
QCOMPARE(keyChangedSpy.count(), 1);
// now lock again
// need to move out and in
KWin::Cursor::setPos(c->geometry().bottomRight() + QPoint(1, 1));
KWin::Cursor::setPos(c->geometry().center());
QCOMPARE(KWin::Cursor::pos(), c->geometry().center());
QCOMPARE(input()->pointer()->isConstrained(), true);
QVERIFY(lockedSpy.wait());
// and just do a key press/release on esc
kwinApp()->platform()->keyboardKeyPressed(KEY_ESC, timestamp++);
kwinApp()->platform()->keyboardKeyReleased(KEY_ESC, timestamp++);
QCOMPARE(input()->pointer()->isConstrained(), true);
QVERIFY(keyChangedSpy.wait());
QCOMPARE(keyChangedSpy.last().at(0).value<quint32>(), quint32(KEY_ESC));
// and another variant which won't break
kwinApp()->platform()->keyboardKeyPressed(KEY_ESC, timestamp++);
kwinApp()->platform()->keyboardKeyPressed(KEY_LEFTSHIFT, timestamp++);
kwinApp()->platform()->keyboardKeyReleased(KEY_LEFTSHIFT, timestamp++);
QCOMPARE(input()->pointer()->isConstrained(), true);
QVERIFY(keyChangedSpy.wait());
QCOMPARE(keyChangedSpy.last().at(0).value<quint32>(), quint32(KEY_LEFTSHIFT));
QVERIFY(!unlockedSpy.wait());
kwinApp()->platform()->keyboardKeyReleased(KEY_ESC, timestamp++);
QVERIFY(keyChangedSpy.wait());
QCOMPARE(keyChangedSpy.last().at(0).value<quint32>(), quint32(KEY_ESC));
// and now break for real
kwinApp()->platform()->keyboardKeyPressed(KEY_ESC, timestamp++);
QVERIFY(unlockedSpy.wait());
kwinApp()->platform()->keyboardKeyReleased(KEY_ESC, timestamp++);
}
void TestPointerConstraints::testCloseWindowWithLockedPointer_data()
{
QTest::addColumn<Test::ShellSurfaceType>("type");
......
......@@ -398,73 +398,6 @@ private:
}
};
class PointerConstraintsFilter : public InputEventFilter {
public:
explicit PointerConstraintsFilter()
: InputEventFilter()
, m_timer(new QTimer)
{
QObject::connect(m_timer.data(), &QTimer::timeout,
[this] {
if (waylandServer()) {
// break keyboard focus, this cancels the pressed ESC
waylandServer()->seat()->setFocusedKeyboardSurface(nullptr);
}
input()->pointer()->breakPointerConstraints();
input()->pointer()->blockPointerConstraints();
// TODO: show notification
waylandServer()->seat()->keyReleased(m_keyCode);
cancel();
}
);
}
bool keyEvent(QKeyEvent *event) override {
if (isActive()) {
if (event->type() == QEvent::KeyPress) {
// is that another key that gets pressed?
if (!event->isAutoRepeat() && event->key() != Qt::Key_Escape) {
cancel();
return false;
}
if (event->isAutoRepeat() && event->key() == Qt::Key_Escape) {
// filter out
return true;
}
} else {
cancel();
return false;
}
} else if (input()->pointer()->isConstrained()) {
if (event->type() == QEvent::KeyPress &&
event->key() == Qt::Key_Escape &&
static_cast<KeyEvent*>(event)->modifiersRelevantForGlobalShortcuts() == Qt::KeyboardModifiers()) {
// TODO: don't hard code
m_timer->start(3000);
m_keyCode = event->nativeScanCode();
return false;
}
}
return false;
}
void cancel() {
if (!isActive()) {
return;
}
m_timer->stop();
input()->keyboard()->update();
}
bool isActive() const {
return m_timer->isActive();
}
private:
QScopedPointer<QTimer> m_timer;
int m_keyCode = 0;
};
class EffectsFilter : public InputEventFilter {
public:
bool pointerEvent(QMouseEvent *event, quint32 nativeButton) override {
......@@ -1723,8 +1656,6 @@ void InputRedirection::setupInputFilters()
installInputEventFilter(new DragAndDropInputFilter);
installInputEventFilter(new LockScreenFilter);
installInputEventFilter(new PopupInputFilter);
m_pointerConstraintsFilter = new PointerConstraintsFilter;
installInputEventFilter(m_pointerConstraintsFilter);
m_windowSelector = new WindowSelectorFilter;
installInputEventFilter(m_windowSelector);
}
......@@ -2141,11 +2072,6 @@ bool InputRedirection::isSelectingWindow() const
return m_windowSelector ? m_windowSelector->isActive() : false;
}
bool InputRedirection::isBreakingPointerConstraints() const
{
return m_pointerConstraintsFilter ? m_pointerConstraintsFilter->isActive() : false;
}
InputDeviceHandler::InputDeviceHandler(InputRedirection *input)
: QObject(input)
, m_input(input)
......
......@@ -43,7 +43,6 @@ class Toplevel;
class InputEventFilter;
class InputEventSpy;
class KeyboardInputRedirection;
class PointerConstraintsFilter;
class PointerInputRedirection;
class TouchInputRedirection;
class WindowSelectorFilter;
......@@ -224,8 +223,6 @@ public:
void startInteractivePositionSelection(std::function<void(const QPoint &)> callback);
bool isSelectingWindow() const;
bool isBreakingPointerConstraints() const;
Q_SIGNALS:
/**
* @brief Emitted when the global pointer position changed
......@@ -285,7 +282,6 @@ private:
LibInput::Connection *m_libInput = nullptr;
WindowSelectorFilter *m_windowSelector = nullptr;
PointerConstraintsFilter *m_pointerConstraintsFilter = nullptr;
QVector<InputEventFilter*> m_filters;
QVector<InputEventSpy*> m_spies;
......
......@@ -556,7 +556,6 @@ void PointerInputRedirection::update()
m_constraintsActivatedConnection = connect(workspace(), &Workspace::clientActivated,
this, &PointerInputRedirection::updatePointerConstraints);
// check whether a pointer confinement/lock fires
m_blockConstraint = false;
updatePointerConstraints();
} else {
m_window.clear();
......@@ -584,11 +583,6 @@ void PointerInputRedirection::breakPointerConstraints(KWayland::Server::SurfaceI
m_locked = false;
}
void PointerInputRedirection::breakPointerConstraints()
{
breakPointerConstraints(m_window ? m_window->surface() : nullptr);
}
void PointerInputRedirection::disconnectConfinedPointerRegionConnection()
{
disconnect(m_confinedPointerRegionConnection);
......@@ -643,9 +637,6 @@ void PointerInputRedirection::updatePointerConstraints()
if (!supportsWarping()) {
return;
}
if (m_blockConstraint) {
return;
}
const bool canConstrain = m_enableConstraints && m_window == workspace()->activeClient();
const auto cf = s->confinedPointer();
if (cf) {
......@@ -683,9 +674,6 @@ void PointerInputRedirection::updatePointerConstraints()
}
}
);
OSD::show(i18nc("notification about mouse pointer confined",
"Pointer motion confined to the current window.\nTo release pointer hold Escape for 3 seconds."),
QStringLiteral("preferences-desktop-mouse"), 5000);
return;
}
} else {
......@@ -728,9 +716,6 @@ void PointerInputRedirection::updatePointerConstraints()
});
}
);
OSD::show(i18nc("notification about mouse pointer locked",
"Pointer locked to current position.\nTo end pointer lock hold Escape for 3 seconds."),
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 {
......
......@@ -85,12 +85,6 @@ public:
void removeWindowSelectionCursor();
void updatePointerConstraints();
void breakPointerConstraints();
/* This is only used for ESC pressing */
void blockPointerConstraints() {
m_blockConstraint = true;
}
void setEnableConstraints(bool set);
......@@ -174,7 +168,6 @@ private:
QMetaObject::Connection m_decorationGeometryConnection;
bool m_confined = false;
bool m_locked = false;
bool m_blockConstraint = false;
bool m_enableConstraints = true;
};
......
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