Remove breaking pointer constraints functionality
Summary: Withicc-effect-5.14.52694839099
,0bd5eff862
andf0ba436c72
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
74994a7fbd
commit
6072b0cd6c
|
@ -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");
|
||||
|
|
74
input.cpp
74
input.cpp
|
@ -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)
|
||||
|
|
4
input.h
4
input.h
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue