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:
Vlad Zahorodnii 2022-02-23 21:03:51 +02:00
parent fccbe4e027
commit 8e304963ad
9 changed files with 104 additions and 88 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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