screenedge: reset timer when pointer leaves edge

Currently the edge erroneously triggers when the pointer repeatedly
enters and leaves the edge in short durations. Send all events to edges,
and reset the timer when pointer leaves edge. Add corresponding test.

BUG: 441892
FIXED-IN: 6.0.4
This commit is contained in:
Yifan Zhu 2024-04-07 09:49:48 -07:00
parent 4c6000b3e1
commit 9ca69cf50c
2 changed files with 53 additions and 5 deletions

View file

@ -65,6 +65,8 @@ private Q_SLOTS:
void testPushBack();
void testObjectEdge_data();
void testObjectEdge();
void testMultipleEntry_data();
void testMultipleEntry();
void testKdeNetWmScreenEdgeShow();
};
@ -304,6 +306,50 @@ void ScreenEdgesTest::testObjectEdge()
QCOMPARE(spy.count(), 2);
}
void ScreenEdgesTest::testMultipleEntry_data()
{
QTest::addColumn<ElectricBorder>("border");
QTest::addColumn<QPointF>("triggerPoint");
QTest::addColumn<QPointF>("delta");
QTest::newRow("top") << ElectricTop << QPointF(640, 0) << QPointF(0, 50);
QTest::newRow("right") << ElectricRight << QPointF(1279, 512) << QPointF(-50, 0);
QTest::newRow("bottom") << ElectricBottom << QPointF(640, 1023) << QPointF(0, -50);
QTest::newRow("left") << ElectricLeft << QPointF(0, 512) << QPointF(50, 0);
}
void ScreenEdgesTest::testMultipleEntry()
{
TestObject callback;
QSignalSpy spy(&callback, &TestObject::gotCallback);
// Reserve a screen edge border.
QFETCH(ElectricBorder, border);
workspace()->screenEdges()->reserve(border, &callback, "callback");
QFETCH(QPointF, triggerPoint);
QFETCH(QPointF, delta);
qint64 timestamp = 0;
while (timestamp < 300) {
// doesn't activate from repeated entries of short duration
Test::pointerMotion(triggerPoint, timestamp);
QVERIFY(spy.isEmpty());
timestamp += 50;
Test::pointerMotion(triggerPoint + delta, timestamp);
QVERIFY(spy.isEmpty());
timestamp += 50;
}
// and this one triggers
Test::pointerMotion(triggerPoint, timestamp);
timestamp += 110;
Test::pointerMotion(triggerPoint, timestamp);
QVERIFY(!spy.isEmpty());
QCOMPARE(spy.count(), 1);
}
static void enableAutoHide(xcb_connection_t *connection, xcb_window_t windowId, ElectricBorder border)
{
if (border == ElectricNone) {

View file

@ -315,6 +315,9 @@ bool Edge::triggersFor(const QPoint &cursorPos) const
bool Edge::check(const QPoint &cursorPos, const QDateTime &triggerTime, bool forceNoPushBack)
{
if (!triggersFor(cursorPos)) {
if ((cursorPos - m_triggeredPoint).manhattanLength() > DISTANCE_RESET) {
m_lastReset = QDateTime(); // invalidate
}
return false;
}
if (m_lastTrigger.isValid() && // still in cooldown
@ -1463,11 +1466,10 @@ bool ScreenEdges::isEntered(QMouseEvent *event)
edge->stopApproaching();
}
}
if (edge->geometry().contains(event->globalPos())) {
if (edge->check(event->globalPos(), QDateTime::fromMSecsSinceEpoch(event->timestamp(), Qt::UTC))) {
if (edge->client()) {
activatedForClient = true;
}
// always send event to all edges so that they can update their state
if (edge->check(event->globalPos(), QDateTime::fromMSecsSinceEpoch(event->timestamp(), Qt::UTC))) {
if (edge->client()) {
activatedForClient = true;
}
}
}