[wayland] Ensure that pointer enter event carries the correct coordinates

So far KWin's pointer surface enter handling was:
1. update fouced surface
2. update the global position

On client side this resulted in:
1. Enter with incorrect coordinates
2. move event to correct coordinate

With QtWayland this results in the case of multiple surfaces in one
application that Qt doesn't properly process the enter event and the
Window never getting pointer focus and not reacting on any pointer
input events.

The root problem is that the KWayland server API is not ideal for
supporting this situation. There is an API call for setting the global
position (which causes a pointer motion for the focused surface) and
an API call to update the focused surface. But a combination for both
is (still) missing.

This change addresses the problem by first unsetting the entered surface,
then updating the global position and afterwards setting the new surface.
Thus the position is correct. While this needs to be made better in
KWayland, this is an urgency bug fix to get the behavior correct and thus
first working around the API deficit and not first extending in KWayland.

Reviewed-By: bshah
icc-effect-5.14.5
Martin Gräßlin 2016-08-04 10:39:23 +02:00
parent b1f6d4b8ba
commit f0dc01b352
2 changed files with 6 additions and 5 deletions

View File

@ -159,6 +159,7 @@ void PointerInputTest::testWarpingUpdatesFocus()
Cursor::setPos(QPoint(25, 25));
QVERIFY(enteredSpy.wait());
QCOMPARE(enteredSpy.count(), 1);
QCOMPARE(enteredSpy.first().at(1).toPointF(), QPointF(25, 25));
// window should have focus
QCOMPARE(pointer->enteredSurface(), surface);
// also on the server
@ -201,15 +202,12 @@ void PointerInputTest::testWarpingGeneratesPointerMotion()
// enter
kwinApp()->platform()->pointerMotion(QPointF(25, 25), 1);
QVERIFY(enteredSpy.wait());
// we get a move event together with the enter, that's actually wrong but also shouldn't harm
QVERIFY(movedSpy.wait());
QCOMPARE(movedSpy.count(), 1);
QCOMPARE(movedSpy.first().first().toPointF(), QPointF(25, 25));
QCOMPARE(enteredSpy.first().at(1).toPointF(), QPointF(25, 25));
// now warp
Cursor::setPos(QPoint(26, 26));
QVERIFY(movedSpy.wait());
QCOMPARE(movedSpy.count(), 2);
QCOMPARE(movedSpy.count(), 1);
QCOMPARE(movedSpy.last().first().toPointF(), QPointF(26, 26));
}

View File

@ -281,6 +281,9 @@ void PointerInputRedirection::update()
}
if (t && t->surface()) {
m_window = QPointer<Toplevel>(t);
// TODO: add convenient API to update global pos together with updating focused surface
seat->setFocusedPointerSurface(nullptr);
seat->setPointerPos(m_pos.toPoint());
seat->setFocusedPointerSurface(t->surface(), t->inputTransformation());
m_windowGeometryConnection = connect(t, &Toplevel::geometryChanged, this,
[this] {