Remove breaking pointer constraints functionality

Summary:
With 2694839099, 0bd5eff862 and f0ba436c72 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
icc-effect-5.14.5
Roman Gilg 2018-09-03 01:00:29 +02:00
parent 74994a7fbd
commit 6072b0cd6c
5 changed files with 16 additions and 223 deletions

View File

@ -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
// activate it again, this confines again
workspace()->activateClient(static_cast<AbstractClient*>(input()->pointer()->window().data()));
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);
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");

View File

@ -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)

View File

@ -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;

View File

@ -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 {

View File

@ -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;
};