Make pointer focus handling less error prone
Currently, if the pointer surface has to change between two surfaces, the compositor must do the following seat->setFocusedPointerSurface(nullptr); seat->notifyPointerMotion(newPos); seat->setFocusedPointerSurface(focus); The pointer motion is needed so the enter event has correct position, setFocusedPointerSurface(nullptr) is needed to avoid sending a bad motion event before the leave event. This change makes the pointer focus api less error prone by splitting setFocusedPointerSurface() in two functions - notifyPointerEnter() and notifyPointerLeave(). notifyPointerEnter() takes new focus surface as well as the position where the pointer has entered the surface so the focus update can be atomic and without any corner cases. notifyPointerLeave() is used to clear pointer focus.
This commit is contained in:
parent
fccbe4e027
commit
8e304963ad
9 changed files with 104 additions and 88 deletions
|
@ -249,7 +249,7 @@ void TestDataDevice::testDrag()
|
|||
m_seatInterface->notifyPointerFrame();
|
||||
}
|
||||
if (hasPointerFocus) {
|
||||
m_seatInterface->setFocusedPointerSurface(surfaceInterface);
|
||||
m_seatInterface->notifyPointerEnter(surfaceInterface, QPointF(0, 0));
|
||||
}
|
||||
if (hasGrab) {
|
||||
m_seatInterface->notifyPointerButton(Qt::LeftButton, PointerButtonState::Pressed);
|
||||
|
@ -330,7 +330,7 @@ void TestDataDevice::testDragInternally()
|
|||
m_seatInterface->notifyPointerFrame();
|
||||
}
|
||||
if (hasPointerFocus) {
|
||||
m_seatInterface->setFocusedPointerSurface(surfaceInterface);
|
||||
m_seatInterface->notifyPointerEnter(surfaceInterface, QPointF(0, 0));
|
||||
}
|
||||
if (hasGrab) {
|
||||
m_seatInterface->notifyPointerButton(Qt::LeftButton, PointerButtonState::Pressed);
|
||||
|
|
|
@ -206,8 +206,8 @@ void TestDragAndDrop::testPointerDragAndDrop()
|
|||
// now we need to pass pointer focus to the Surface and simulate a button press
|
||||
QSignalSpy buttonPressSpy(m_pointer, &Pointer::buttonStateChanged);
|
||||
QVERIFY(buttonPressSpy.isValid());
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface);
|
||||
m_seatInterface->setTimestamp(2);
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(0, 0));
|
||||
m_seatInterface->notifyPointerButton(1, PointerButtonState::Pressed);
|
||||
m_seatInterface->notifyPointerFrame();
|
||||
QVERIFY(buttonPressSpy.wait());
|
||||
|
@ -404,8 +404,8 @@ void TestDragAndDrop::testDragAndDropWithCancelByDestroyDataSource()
|
|||
// now we need to pass pointer focus to the Surface and simulate a button press
|
||||
QSignalSpy buttonPressSpy(m_pointer, &Pointer::buttonStateChanged);
|
||||
QVERIFY(buttonPressSpy.isValid());
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface);
|
||||
m_seatInterface->setTimestamp(2);
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(0, 0));
|
||||
m_seatInterface->notifyPointerButton(1, PointerButtonState::Pressed);
|
||||
m_seatInterface->notifyPointerFrame();
|
||||
QVERIFY(buttonPressSpy.wait());
|
||||
|
@ -495,7 +495,7 @@ void TestDragAndDrop::testPointerEventsIgnored()
|
|||
QVERIFY(serverSurface);
|
||||
|
||||
// pass it pointer focus
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface);
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(0, 0));
|
||||
|
||||
// create signal spies for all the pointer events
|
||||
QSignalSpy pointerEnteredSpy(m_pointer, &Pointer::entered);
|
||||
|
@ -549,10 +549,10 @@ void TestDragAndDrop::testPointerEventsIgnored()
|
|||
m_seatInterface->notifyPointerAxis(Qt::Vertical, 5, 1, PointerAxisSource::Wheel);
|
||||
m_seatInterface->notifyPointerFrame();
|
||||
m_seatInterface->setTimestamp(timestamp++);
|
||||
m_seatInterface->setFocusedPointerSurface(nullptr);
|
||||
m_seatInterface->notifyPointerLeave();
|
||||
m_seatInterface->notifyPointerFrame();
|
||||
m_seatInterface->setTimestamp(timestamp++);
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface);
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, m_seatInterface->pointerPos());
|
||||
m_seatInterface->notifyPointerFrame();
|
||||
m_seatInterface->setTimestamp(timestamp++);
|
||||
m_seatInterface->notifyPointerMotion(QPointF(50, 50));
|
||||
|
|
|
@ -222,7 +222,7 @@ void TestPointerConstraints::testLockPointer()
|
|||
// let's lock the surface
|
||||
QSignalSpy lockedChangedSpy(serverLockedPointer, &LockedPointerV1Interface::lockedChanged);
|
||||
QVERIFY(lockedChangedSpy.isValid());
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface);
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(0, 0));
|
||||
QSignalSpy pointerMotionSpy(m_pointer, &Pointer::motion);
|
||||
QVERIFY(pointerMotionSpy.isValid());
|
||||
m_seatInterface->notifyPointerMotion(QPoint(0, 1));
|
||||
|
@ -339,7 +339,7 @@ void TestPointerConstraints::testConfinePointer()
|
|||
// let's confine the surface
|
||||
QSignalSpy confinedChangedSpy(serverConfinedPointer, &ConfinedPointerV1Interface::confinedChanged);
|
||||
QVERIFY(confinedChangedSpy.isValid());
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface);
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(0, 0));
|
||||
serverConfinedPointer->setConfined(true);
|
||||
QCOMPARE(serverConfinedPointer->isConfined(), true);
|
||||
QCOMPARE(confinedChangedSpy.count(), 1);
|
||||
|
|
|
@ -351,8 +351,7 @@ void TestWaylandSeat::testPointer()
|
|||
QSignalSpy committedSpy(serverSurface, &KWaylandServer::SurfaceInterface::committed);
|
||||
QVERIFY(committedSpy.wait());
|
||||
|
||||
m_seatInterface->notifyPointerMotion(QPoint(20, 18));
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface, QPoint(10, 15));
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(20, 18), QPointF(10, 15));
|
||||
|
||||
Pointer *p = m_seat->createPointer(m_seat);
|
||||
QSignalSpy frameSpy(p, &Pointer::frame);
|
||||
|
@ -364,7 +363,7 @@ void TestWaylandSeat::testPointer()
|
|||
QVERIFY(frameSpy.wait());
|
||||
QCOMPARE(frameSpy.count(), 1);
|
||||
|
||||
m_seatInterface->setFocusedPointerSurface(nullptr);
|
||||
m_seatInterface->notifyPointerLeave();
|
||||
serverSurface->client()->flush();
|
||||
QVERIFY(frameSpy.wait());
|
||||
QCOMPARE(frameSpy.count(), 2);
|
||||
|
@ -389,7 +388,7 @@ void TestWaylandSeat::testPointer()
|
|||
|
||||
QVERIFY(!p->enteredSurface());
|
||||
QVERIFY(!cp.enteredSurface());
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface, QPoint(10, 15));
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(20, 18), QPointF(10, 15));
|
||||
QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface);
|
||||
QVERIFY(enteredSpy.wait());
|
||||
QCOMPARE(enteredSpy.first().first().value<quint32>(), m_display->serial());
|
||||
|
@ -489,7 +488,7 @@ void TestWaylandSeat::testPointer()
|
|||
QCOMPARE(buttonSpy.at(3).at(3).value<KWayland::Client::Pointer::ButtonState>(), KWayland::Client::Pointer::ButtonState::Released);
|
||||
|
||||
// leave the surface
|
||||
m_seatInterface->setFocusedPointerSurface(nullptr);
|
||||
m_seatInterface->notifyPointerLeave();
|
||||
QVERIFY(leftSpy.wait());
|
||||
QCOMPARE(frameSpy.count(), 12);
|
||||
QCOMPARE(leftSpy.first().first().value<quint32>(), m_display->serial());
|
||||
|
@ -501,7 +500,7 @@ void TestWaylandSeat::testPointer()
|
|||
QVERIFY(!relativeMotionSpy.wait(500));
|
||||
|
||||
// enter it again
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface, QPoint(0, 0));
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(10, 16), QPointF(0, 0));
|
||||
QVERIFY(enteredSpy.wait());
|
||||
QCOMPARE(frameSpy.count(), 13);
|
||||
QCOMPARE(p->enteredSurface(), s);
|
||||
|
@ -560,9 +559,8 @@ void TestWaylandSeat::testPointerTransformation()
|
|||
QSignalSpy committedSpy(serverSurface, &KWaylandServer::SurfaceInterface::committed);
|
||||
QVERIFY(committedSpy.wait());
|
||||
|
||||
m_seatInterface->notifyPointerMotion(QPoint(20, 18));
|
||||
QFETCH(QMatrix4x4, enterTransformation);
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface, enterTransformation);
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(20, 18), enterTransformation);
|
||||
QCOMPARE(m_seatInterface->focusedPointerSurfaceTransformation(), enterTransformation);
|
||||
// no pointer yet
|
||||
QVERIFY(m_seatInterface->focusedPointerSurface());
|
||||
|
@ -573,7 +571,7 @@ void TestWaylandSeat::testPointerTransformation()
|
|||
QVERIFY(frameSpy.wait());
|
||||
const Pointer &cp = *p;
|
||||
|
||||
m_seatInterface->setFocusedPointerSurface(nullptr);
|
||||
m_seatInterface->notifyPointerLeave();
|
||||
serverSurface->client()->flush();
|
||||
QTest::qWait(100);
|
||||
|
||||
|
@ -588,7 +586,7 @@ void TestWaylandSeat::testPointerTransformation()
|
|||
|
||||
QVERIFY(!p->enteredSurface());
|
||||
QVERIFY(!cp.enteredSurface());
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface, enterTransformation);
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(20, 18), enterTransformation);
|
||||
QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface);
|
||||
QVERIFY(enteredSpy.wait());
|
||||
QCOMPARE(enteredSpy.first().first().value<quint32>(), m_display->serial());
|
||||
|
@ -605,14 +603,14 @@ void TestWaylandSeat::testPointerTransformation()
|
|||
QCOMPARE(motionSpy.first().last().value<quint32>(), quint32(1));
|
||||
|
||||
// leave the surface
|
||||
m_seatInterface->setFocusedPointerSurface(nullptr);
|
||||
m_seatInterface->notifyPointerLeave();
|
||||
QVERIFY(leftSpy.wait());
|
||||
QCOMPARE(leftSpy.first().first().value<quint32>(), m_display->serial());
|
||||
QVERIFY(!p->enteredSurface());
|
||||
QVERIFY(!cp.enteredSurface());
|
||||
|
||||
// enter it again
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface);
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(10, 16));
|
||||
QVERIFY(enteredSpy.wait());
|
||||
QCOMPARE(p->enteredSurface(), s);
|
||||
QCOMPARE(cp.enteredSurface(), s);
|
||||
|
@ -689,13 +687,11 @@ void TestWaylandSeat::testPointerButton()
|
|||
wl_display_flush(m_connection->display());
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
m_seatInterface->notifyPointerMotion(QPoint(20, 18));
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface, QPoint(10, 15));
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(20, 18), QPointF(10, 15));
|
||||
QVERIFY(m_seatInterface->focusedPointerSurface());
|
||||
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface, QPoint(10, 15));
|
||||
QFETCH(Qt::MouseButton, qtButton);
|
||||
QFETCH(quint32, waylandButton);
|
||||
quint32 msec = QDateTime::currentMSecsSinceEpoch();
|
||||
|
@ -782,8 +778,7 @@ void TestWaylandSeat::testPointerSubSurfaceTree()
|
|||
// first to the grandChild2 in the overlapped area
|
||||
quint32 timestamp = 1;
|
||||
m_seatInterface->setTimestamp(timestamp++);
|
||||
m_seatInterface->notifyPointerMotion(QPointF(25, 50));
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface);
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(25, 50));
|
||||
QVERIFY(enteredSpy.wait());
|
||||
QCOMPARE(enteredSpy.count(), 1);
|
||||
QCOMPARE(leftSpy.count(), 0);
|
||||
|
@ -811,15 +806,14 @@ void TestWaylandSeat::testPointerSubSurfaceTree()
|
|||
QCOMPARE(pointer->enteredSurface(), childSurface.data());
|
||||
// a leave for the whole surface
|
||||
m_seatInterface->setTimestamp(timestamp++);
|
||||
m_seatInterface->setFocusedPointerSurface(nullptr);
|
||||
m_seatInterface->notifyPointerLeave();
|
||||
QVERIFY(leftSpy.wait());
|
||||
QCOMPARE(enteredSpy.count(), 2);
|
||||
QCOMPARE(leftSpy.count(), 2);
|
||||
QCOMPARE(motionSpy.count(), 2);
|
||||
// a new enter on the main surface
|
||||
m_seatInterface->setTimestamp(timestamp++);
|
||||
m_seatInterface->notifyPointerMotion(QPointF(75, 50));
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface);
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(75, 50));
|
||||
QVERIFY(enteredSpy.wait());
|
||||
QCOMPARE(enteredSpy.count(), 3);
|
||||
QCOMPARE(leftSpy.count(), 2);
|
||||
|
@ -880,7 +874,7 @@ void TestWaylandSeat::testPointerSwipeGesture()
|
|||
QSignalSpy committedSpy(serverSurface, &KWaylandServer::SurfaceInterface::committed);
|
||||
QVERIFY(committedSpy.wait());
|
||||
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface);
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(0, 0));
|
||||
QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface);
|
||||
QVERIFY(m_seatInterface->pointer());
|
||||
|
||||
|
@ -939,7 +933,7 @@ void TestWaylandSeat::testPointerSwipeGesture()
|
|||
QVERIFY(startSpy.wait());
|
||||
|
||||
// unsetting the focused pointer surface should not change anything
|
||||
m_seatInterface->setFocusedPointerSurface(nullptr);
|
||||
m_seatInterface->notifyPointerLeave();
|
||||
m_seatInterface->setTimestamp(timestamp++);
|
||||
m_seatInterface->updatePointerSwipeGesture(QSizeF(6, 7));
|
||||
QVERIFY(updateSpy.wait());
|
||||
|
@ -1005,7 +999,7 @@ void TestWaylandSeat::testPointerPinchGesture()
|
|||
QSignalSpy committedSpy(serverSurface, &KWaylandServer::SurfaceInterface::committed);
|
||||
QVERIFY(committedSpy.wait());
|
||||
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface);
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(0, 0));
|
||||
QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface);
|
||||
QVERIFY(m_seatInterface->pointer());
|
||||
|
||||
|
@ -1068,7 +1062,7 @@ void TestWaylandSeat::testPointerPinchGesture()
|
|||
QVERIFY(startSpy.wait());
|
||||
|
||||
// unsetting the focused pointer surface should not change anything
|
||||
m_seatInterface->setFocusedPointerSurface(nullptr);
|
||||
m_seatInterface->notifyPointerLeave();
|
||||
m_seatInterface->setTimestamp(timestamp++);
|
||||
m_seatInterface->updatePointerPinchGesture(QSizeF(6, 7), 2, -45);
|
||||
QVERIFY(updateSpy.wait());
|
||||
|
@ -1156,7 +1150,7 @@ void TestWaylandSeat::testPointerHoldGesture()
|
|||
QSignalSpy committedSpy(serverSurface, &KWaylandServer::SurfaceInterface::committed);
|
||||
QVERIFY(committedSpy.wait());
|
||||
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface);
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(0, 0));
|
||||
QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface);
|
||||
QVERIFY(m_seatInterface->pointer());
|
||||
|
||||
|
@ -1237,7 +1231,7 @@ void TestWaylandSeat::testPointerAxis()
|
|||
QSignalSpy committedSpy(serverSurface, &KWaylandServer::SurfaceInterface::committed);
|
||||
QVERIFY(committedSpy.wait());
|
||||
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface);
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(0, 0));
|
||||
QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface);
|
||||
QSignalSpy frameSpy(pointer.data(), &Pointer::frame);
|
||||
QVERIFY(frameSpy.isValid());
|
||||
|
@ -1350,8 +1344,7 @@ void TestWaylandSeat::testCursor()
|
|||
QSignalSpy enteredSpy(p.data(), &KWayland::Client::Pointer::entered);
|
||||
QVERIFY(enteredSpy.isValid());
|
||||
|
||||
m_seatInterface->notifyPointerMotion(QPoint(20, 18));
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface, QPoint(10, 15));
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(20, 18), QPointF(10, 15));
|
||||
quint32 serial = m_seatInterface->display()->serial();
|
||||
QVERIFY(enteredSpy.wait());
|
||||
QCOMPARE(enteredSpy.first().first().value<quint32>(), serial);
|
||||
|
@ -1466,7 +1459,7 @@ void TestWaylandSeat::testCursorDamage()
|
|||
QVERIFY(committedSpy.wait());
|
||||
|
||||
// send enter to the surface
|
||||
m_seatInterface->setFocusedPointerSurface(serverSurface);
|
||||
m_seatInterface->notifyPointerEnter(serverSurface, QPointF(0, 0));
|
||||
QVERIFY(enteredSpy.wait());
|
||||
|
||||
// create a signal spy for the cursor changed signal
|
||||
|
|
|
@ -152,7 +152,7 @@ SurfaceInterface *PointerInterface::focusedSurface() const
|
|||
return d->focusedSurface;
|
||||
}
|
||||
|
||||
void PointerInterface::setFocusedSurface(SurfaceInterface *surface, const QPointF &position, quint32 serial)
|
||||
void PointerInterface::sendEnter(SurfaceInterface *surface, const QPointF &position, quint32 serial)
|
||||
{
|
||||
if (d->focusedSurface == surface) {
|
||||
return;
|
||||
|
@ -160,26 +160,39 @@ void PointerInterface::setFocusedSurface(SurfaceInterface *surface, const QPoint
|
|||
|
||||
if (d->focusedSurface) {
|
||||
d->sendLeave(serial);
|
||||
if (!surface || d->focusedSurface->client() != surface->client()) {
|
||||
if (d->focusedSurface->client() != surface->client()) {
|
||||
d->sendFrame();
|
||||
}
|
||||
disconnect(d->destroyConnection);
|
||||
}
|
||||
|
||||
d->focusedSurface = surface;
|
||||
|
||||
if (d->focusedSurface) {
|
||||
d->destroyConnection = connect(d->focusedSurface, &SurfaceInterface::aboutToBeDestroyed, this, [this]() {
|
||||
d->sendLeave(d->seat->display()->nextSerial());
|
||||
d->sendFrame();
|
||||
d->focusedSurface = nullptr;
|
||||
Q_EMIT focusedSurfaceChanged();
|
||||
});
|
||||
d->sendEnter(position, serial);
|
||||
d->destroyConnection = connect(d->focusedSurface, &SurfaceInterface::aboutToBeDestroyed, this, [this]() {
|
||||
d->sendLeave(d->seat->display()->nextSerial());
|
||||
d->sendFrame();
|
||||
d->lastPosition = position;
|
||||
d->focusedSurface = nullptr;
|
||||
Q_EMIT focusedSurfaceChanged();
|
||||
});
|
||||
|
||||
d->sendEnter(position, serial);
|
||||
d->sendFrame();
|
||||
d->lastPosition = position;
|
||||
|
||||
Q_EMIT focusedSurfaceChanged();
|
||||
}
|
||||
|
||||
void PointerInterface::sendLeave(quint32 serial)
|
||||
{
|
||||
if (!d->focusedSurface) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->sendLeave(serial);
|
||||
d->sendFrame();
|
||||
|
||||
d->focusedSurface = nullptr;
|
||||
disconnect(d->destroyConnection);
|
||||
|
||||
Q_EMIT focusedSurfaceChanged();
|
||||
}
|
||||
|
||||
|
|
|
@ -41,11 +41,6 @@ public:
|
|||
* the effective focused surface.
|
||||
*/
|
||||
SurfaceInterface *focusedSurface() const;
|
||||
/**
|
||||
* Sets the effective focused pointer surface to @a surface. The @a position indicates
|
||||
* where the pointer has entered the surface.
|
||||
*/
|
||||
void setFocusedSurface(SurfaceInterface *surface, const QPointF &position, quint32 serial);
|
||||
|
||||
Cursor *cursor() const;
|
||||
|
||||
|
@ -59,6 +54,8 @@ public:
|
|||
*/
|
||||
static PointerInterface *get(wl_resource *native);
|
||||
|
||||
void sendEnter(SurfaceInterface *surface, const QPointF &position, quint32 serial);
|
||||
void sendLeave(quint32 serial);
|
||||
void sendButton(quint32 button, PointerButtonState state, quint32 serial);
|
||||
void sendAxis(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source);
|
||||
void sendMotion(const QPointF &position);
|
||||
|
|
|
@ -481,7 +481,7 @@ void SeatInterface::notifyPointerMotion(const QPointF &pos)
|
|||
}
|
||||
|
||||
if (d->pointer->focusedSurface() != effectiveFocusedSurface) {
|
||||
d->pointer->setFocusedSurface(effectiveFocusedSurface, localPosition, display()->nextSerial());
|
||||
d->pointer->sendEnter(effectiveFocusedSurface, localPosition, display()->nextSerial());
|
||||
}
|
||||
|
||||
d->pointer->sendMotion(localPosition);
|
||||
|
@ -552,17 +552,17 @@ SurfaceInterface *SeatInterface::focusedPointerSurface() const
|
|||
return d->globalPointer.focus.surface;
|
||||
}
|
||||
|
||||
void SeatInterface::setFocusedPointerSurface(SurfaceInterface *surface, const QPointF &surfacePosition)
|
||||
void SeatInterface::notifyPointerEnter(SurfaceInterface *surface, const QPointF &position, const QPointF &surfacePosition)
|
||||
{
|
||||
QMatrix4x4 m;
|
||||
m.translate(-surfacePosition.x(), -surfacePosition.y());
|
||||
setFocusedPointerSurface(surface, m);
|
||||
notifyPointerEnter(surface, position, m);
|
||||
if (d->globalPointer.focus.surface) {
|
||||
d->globalPointer.focus.offset = surfacePosition;
|
||||
}
|
||||
}
|
||||
|
||||
void SeatInterface::setFocusedPointerSurface(SurfaceInterface *surface, const QMatrix4x4 &transformation)
|
||||
void SeatInterface::notifyPointerEnter(SurfaceInterface *surface, const QPointF &position, const QMatrix4x4 &transformation)
|
||||
{
|
||||
if (!d->pointer) {
|
||||
return;
|
||||
|
@ -579,28 +579,42 @@ void SeatInterface::setFocusedPointerSurface(SurfaceInterface *surface, const QM
|
|||
}
|
||||
d->globalPointer.focus = SeatInterfacePrivate::Pointer::Focus();
|
||||
d->globalPointer.focus.surface = surface;
|
||||
if (d->globalPointer.focus.surface) {
|
||||
d->globalPointer.focus.destroyConnection = connect(surface, &QObject::destroyed, this, [this] {
|
||||
d->globalPointer.focus = SeatInterfacePrivate::Pointer::Focus();
|
||||
});
|
||||
d->globalPointer.focus.serial = serial;
|
||||
d->globalPointer.focus.transformation = transformation;
|
||||
d->globalPointer.focus.offset = QPointF();
|
||||
d->globalPointer.focus.destroyConnection = connect(surface, &QObject::destroyed, this, [this] {
|
||||
d->globalPointer.focus = SeatInterfacePrivate::Pointer::Focus();
|
||||
});
|
||||
d->globalPointer.focus.serial = serial;
|
||||
d->globalPointer.focus.transformation = transformation;
|
||||
d->globalPointer.focus.offset = QPointF();
|
||||
|
||||
d->globalPointer.pos = position;
|
||||
QPointF localPosition = focusedPointerSurfaceTransformation().map(position);
|
||||
SurfaceInterface *effectiveFocusedSurface = surface->inputSurfaceAt(localPosition);
|
||||
if (!effectiveFocusedSurface) {
|
||||
effectiveFocusedSurface = surface;
|
||||
}
|
||||
if (surface != effectiveFocusedSurface) {
|
||||
localPosition = surface->mapToChild(effectiveFocusedSurface, localPosition);
|
||||
}
|
||||
d->pointer->sendEnter(effectiveFocusedSurface, localPosition, serial);
|
||||
}
|
||||
|
||||
void SeatInterface::notifyPointerLeave()
|
||||
{
|
||||
if (!d->pointer) {
|
||||
return;
|
||||
}
|
||||
if (d->drag.mode == SeatInterfacePrivate::Drag::Mode::Pointer) {
|
||||
// ignore
|
||||
return;
|
||||
}
|
||||
|
||||
if (surface) {
|
||||
QPointF localPosition = focusedPointerSurfaceTransformation().map(pointerPos());
|
||||
SurfaceInterface *effectiveFocusedSurface = surface->inputSurfaceAt(localPosition);
|
||||
if (!effectiveFocusedSurface) {
|
||||
effectiveFocusedSurface = surface;
|
||||
}
|
||||
if (surface != effectiveFocusedSurface) {
|
||||
localPosition = surface->mapToChild(effectiveFocusedSurface, localPosition);
|
||||
}
|
||||
d->pointer->setFocusedSurface(effectiveFocusedSurface, localPosition, serial);
|
||||
} else {
|
||||
d->pointer->setFocusedSurface(nullptr, QPointF(), serial);
|
||||
if (d->globalPointer.focus.surface) {
|
||||
disconnect(d->globalPointer.focus.destroyConnection);
|
||||
}
|
||||
d->globalPointer.focus = SeatInterfacePrivate::Pointer::Focus();
|
||||
|
||||
const quint32 serial = d->display->nextSerial();
|
||||
d->pointer->sendLeave(serial);
|
||||
}
|
||||
|
||||
void SeatInterface::setFocusedPointerSurfacePosition(const QPointF &surfacePosition)
|
||||
|
@ -1066,7 +1080,7 @@ void SeatInterface::notifyTouchDown(qint32 id, const QPointF &globalPosition)
|
|||
if (touchPrivate->touchesForClient(focusedTouchSurface()->client()).isEmpty()) {
|
||||
// If the client did not bind the touch interface fall back
|
||||
// to at least emulating touch through pointer events.
|
||||
d->pointer->setFocusedSurface(focusedTouchSurface(), pos, serial);
|
||||
d->pointer->sendEnter(focusedTouchSurface(), pos, serial);
|
||||
d->pointer->sendMotion(pos);
|
||||
d->pointer->sendFrame();
|
||||
}
|
||||
|
|
|
@ -104,9 +104,8 @@ enum class KeyboardKeyState : quint32 {
|
|||
*
|
||||
* @code
|
||||
* // example for pointer
|
||||
* seat->setFocusedPointerSurface(surface, QPointF(100, 200)); // surface at it's global position
|
||||
* seat->setTimestamp(100);
|
||||
* seat->notifyPointerMotion(QPointF(350, 210)); // global pos, local pos in surface: 250,10
|
||||
* seat->notifyPointerEnter(surface, QPointF(350, 210), QPointF(100, 200)); // surface at it's global position
|
||||
* seat->notifyPointerFrame();
|
||||
* seat->setTimestamp(110);
|
||||
* seat->notifyPointerButton(Qt::LeftButton, PointerButtonState::Pressed);
|
||||
|
@ -274,7 +273,7 @@ public:
|
|||
* @see setFocusedPointerSurfaceTransformation
|
||||
* @see focusedPointerSurfaceTransformation
|
||||
*/
|
||||
void setFocusedPointerSurface(SurfaceInterface *surface, const QPointF &surfacePosition = QPoint());
|
||||
void notifyPointerEnter(SurfaceInterface *surface, const QPointF &position, const QPointF &surfacePosition = QPointF());
|
||||
/**
|
||||
* Sets the focused pointer @p surface.
|
||||
* All pointer events will be sent to the @p surface till a new focused pointer surface gets
|
||||
|
@ -298,10 +297,12 @@ public:
|
|||
* @see setFocusedPointerSurfaceTransformation
|
||||
* @see focusedPointerSurfaceTransformation
|
||||
*/
|
||||
void setFocusedPointerSurface(SurfaceInterface *surface, const QMatrix4x4 &transformation);
|
||||
void notifyPointerEnter(SurfaceInterface *surface, const QPointF &position, const QMatrix4x4 &transformation);
|
||||
void notifyPointerLeave();
|
||||
/**
|
||||
* @returns The currently focused pointer surface, that is the surface receiving pointer events.
|
||||
* @see setFocusedPointerSurface
|
||||
* @see notifyPointerEnter
|
||||
* @see notifyPointerLeave
|
||||
*/
|
||||
SurfaceInterface *focusedPointerSurface() const;
|
||||
PointerInterface *pointer() const;
|
||||
|
@ -315,7 +316,6 @@ public:
|
|||
*
|
||||
* @param surfacePosition The new global position of the focused pointer surface
|
||||
* @see focusedPointerSurface
|
||||
* @see setFocusedPointerSurface
|
||||
* @see focusedPointerSurfaceTransformation
|
||||
* @see setFocusedPointerSurfaceTransformation
|
||||
*/
|
||||
|
@ -323,7 +323,6 @@ public:
|
|||
/**
|
||||
* @returns The position of the focused pointer surface in global coordinates.
|
||||
* @see setFocusedPointerSurfacePosition
|
||||
* @see setFocusedPointerSurface
|
||||
* @see focusedPointerSurfaceTransformation
|
||||
*/
|
||||
QPointF focusedPointerSurfacePosition() const;
|
||||
|
|
|
@ -130,7 +130,7 @@ void CompositorWindow::updateFocus()
|
|||
if (it == m_stackingOrder.constEnd()) {
|
||||
return;
|
||||
}
|
||||
m_seat->setFocusedPointerSurface((*it)->surface());
|
||||
m_seat->notifyPointerEnter((*it)->surface(), m_seat->pointerPos());
|
||||
m_seat->setFocusedKeyboardSurface((*it)->surface());
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ void CompositorWindow::mousePressEvent(QMouseEvent *event)
|
|||
QWidget::mousePressEvent(event);
|
||||
if (!m_seat->focusedPointerSurface()) {
|
||||
if (!m_stackingOrder.isEmpty()) {
|
||||
m_seat->setFocusedPointerSurface(m_stackingOrder.last()->surface());
|
||||
m_seat->notifyPointerEnter(m_stackingOrder.last()->surface(), event->globalPos());
|
||||
}
|
||||
}
|
||||
m_seat->setTimestamp(event->timestamp());
|
||||
|
|
Loading…
Reference in a new issue