[server] Add support for the frame semantics of Pointer version 5

Summary:
This change implements the required changes for wl_seat version 5.
There seem to be applications which require version 5 and refuse to
start if the server doesn't provide it. Thus we need to provide it.

The main difference with version 5 is that pointer need to send a
frame event after each logical group of events. As we don't support the
new events from version 5 yet, we just emit the frame after each event
and implement the suggested semantics for the enter/leave behavior.

To really make use of this, we will have to implement additions in the
API and then in KWin to expose the new API elements. But to just support
the semantics we don't need it.

BUG: 389189
FIXED-IN: 5.45

Test Plan: Extended autotest

Reviewers: #kwin, #plasma, #frameworks

Subscribers: plasma-devel

Tags: #frameworks, #plasma

Differential Revision: https://phabricator.kde.org/D10235
This commit is contained in:
Martin Flöser 2018-02-01 17:46:53 +01:00
parent 300cd607f0
commit c29035a6f0
5 changed files with 57 additions and 6 deletions

View file

@ -392,6 +392,8 @@ void TestWaylandSeat::testPointer()
QVERIFY(!m_seatInterface->focusedPointer());
Pointer *p = m_seat->createPointer(m_seat);
QSignalSpy frameSpy(p, &Pointer::frame);
QVERIFY(frameSpy.isValid());
const Pointer &cp = *p;
QVERIFY(p->isValid());
QScopedPointer<RelativePointer> relativePointer(m_relativePointerManager->createRelativePointer(p));
@ -404,12 +406,15 @@ void TestWaylandSeat::testPointer()
QCOMPARE(pointerCreatedSpy.first().first().value<PointerInterface*>(), m_seatInterface->focusedPointer());
QCOMPARE(focusedPointerChangedSpy.count(), 2);
QCOMPARE(focusedPointerChangedSpy.last().first().value<PointerInterface*>(), m_seatInterface->focusedPointer());
QVERIFY(frameSpy.wait());
QCOMPARE(frameSpy.count(), 1);
m_seatInterface->setFocusedPointerSurface(nullptr);
QCOMPARE(focusedPointerChangedSpy.count(), 3);
QVERIFY(!focusedPointerChangedSpy.last().first().value<PointerInterface*>());
serverSurface->client()->flush();
QTest::qWait(100);
QVERIFY(frameSpy.wait());
QCOMPARE(frameSpy.count(), 2);
QSignalSpy enteredSpy(p, SIGNAL(entered(quint32,QPointF)));
QVERIFY(enteredSpy.isValid());
@ -436,6 +441,7 @@ void TestWaylandSeat::testPointer()
QVERIFY(enteredSpy.wait());
QCOMPARE(enteredSpy.first().first().value<quint32>(), m_display->serial());
QCOMPARE(enteredSpy.first().last().toPoint(), QPoint(10, 3));
QCOMPARE(frameSpy.count(), 3);
PointerInterface *serverPointer = m_seatInterface->focusedPointer();
QVERIFY(serverPointer);
QCOMPARE(p->enteredSurface(), s);
@ -447,6 +453,7 @@ void TestWaylandSeat::testPointer()
m_seatInterface->setTimestamp(1);
m_seatInterface->setPointerPos(QPoint(10, 16));
QVERIFY(motionSpy.wait());
QCOMPARE(frameSpy.count(), 4);
QCOMPARE(motionSpy.first().first().toPoint(), QPoint(0, 1));
QCOMPARE(motionSpy.first().last().value<quint32>(), quint32(1));
@ -462,9 +469,11 @@ void TestWaylandSeat::testPointer()
m_seatInterface->setTimestamp(2);
m_seatInterface->pointerAxis(Qt::Horizontal, 10);
QVERIFY(axisSpy.wait());
QCOMPARE(frameSpy.count(), 5);
m_seatInterface->setTimestamp(3);
m_seatInterface->pointerAxis(Qt::Vertical, 20);
QVERIFY(axisSpy.wait());
QCOMPARE(frameSpy.count(), 6);
QCOMPARE(axisSpy.first().at(0).value<quint32>(), quint32(2));
QCOMPARE(axisSpy.first().at(1).value<Pointer::Axis>(), Pointer::Axis::Horizontal);
QCOMPARE(axisSpy.first().at(2).value<qreal>(), qreal(10));
@ -477,18 +486,22 @@ void TestWaylandSeat::testPointer()
m_seatInterface->setTimestamp(4);
m_seatInterface->pointerButtonPressed(1);
QVERIFY(buttonSpy.wait());
QCOMPARE(frameSpy.count(), 7);
QCOMPARE(buttonSpy.at(0).at(0).value<quint32>(), m_display->serial());
m_seatInterface->setTimestamp(5);
m_seatInterface->pointerButtonPressed(2);
QVERIFY(buttonSpy.wait());
QCOMPARE(frameSpy.count(), 8);
QCOMPARE(buttonSpy.at(1).at(0).value<quint32>(), m_display->serial());
m_seatInterface->setTimestamp(6);
m_seatInterface->pointerButtonReleased(2);
QVERIFY(buttonSpy.wait());
QCOMPARE(frameSpy.count(), 9);
QCOMPARE(buttonSpy.at(2).at(0).value<quint32>(), m_display->serial());
m_seatInterface->setTimestamp(7);
m_seatInterface->pointerButtonReleased(1);
QVERIFY(buttonSpy.wait());
QCOMPARE(frameSpy.count(), 10);
QCOMPARE(buttonSpy.count(), 4);
// timestamp
@ -521,6 +534,7 @@ void TestWaylandSeat::testPointer()
m_seatInterface->setFocusedPointerSurface(nullptr);
QCOMPARE(focusedPointerChangedSpy.count(), 5);
QVERIFY(leftSpy.wait());
QCOMPARE(frameSpy.count(), 11);
QCOMPARE(leftSpy.first().first().value<quint32>(), m_display->serial());
QVERIFY(!p->enteredSurface());
QVERIFY(!cp.enteredSurface());
@ -533,6 +547,7 @@ void TestWaylandSeat::testPointer()
m_seatInterface->setFocusedPointerSurface(serverSurface, QPoint(0, 0));
QCOMPARE(focusedPointerChangedSpy.count(), 6);
QVERIFY(enteredSpy.wait());
QCOMPARE(frameSpy.count(), 12);
QCOMPARE(p->enteredSurface(), s);
QCOMPARE(cp.enteredSurface(), s);

View file

@ -211,6 +211,14 @@ void PointerInterface::Private::cancelPinchGesture(quint32 serial)
}
}
void PointerInterface::Private::sendFrame()
{
if (!resource || wl_resource_get_version(resource) < WL_POINTER_FRAME_SINCE_VERSION) {
return;
}
wl_pointer_send_frame(resource);
}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
const struct wl_pointer_interface PointerInterface::Private::s_interface = {
setCursorCallback,
@ -242,11 +250,13 @@ PointerInterface::PointerInterface(SeatInterface *parent, wl_resource *parentRes
d->sendLeave(d->focusedChildSurface.data(), serial);
d->focusedChildSurface = QPointer<SurfaceInterface>(targetSurface);
d->sendEnter(targetSurface, pos, serial);
d->sendFrame();
d->client->flush();
} else {
const QPointF adjustedPos = pos - surfacePosition(d->focusedChildSurface);
wl_pointer_send_motion(d->resource, d->seat->timestamp(),
wl_fixed_from_double(adjustedPos.x()), wl_fixed_from_double(adjustedPos.y()));
d->sendFrame();
}
}
});
@ -269,6 +279,7 @@ void PointerInterface::setFocusedSurface(SurfaceInterface *surface, quint32 seri
[this] {
Q_D();
d->sendLeave(d->focusedChildSurface.data(), d->global->display()->nextSerial());
d->sendFrame();
d->focusedSurface = nullptr;
d->focusedChildSurface.clear();
}
@ -291,6 +302,7 @@ void PointerInterface::buttonPressed(quint32 button, quint32 serial)
return;
}
wl_pointer_send_button(d->resource, serial, d->seat->timestamp(), button, WL_POINTER_BUTTON_STATE_PRESSED);
d->sendFrame();
}
void PointerInterface::buttonReleased(quint32 button, quint32 serial)
@ -301,6 +313,7 @@ void PointerInterface::buttonReleased(quint32 button, quint32 serial)
return;
}
wl_pointer_send_button(d->resource, serial, d->seat->timestamp(), button, WL_POINTER_BUTTON_STATE_RELEASED);
d->sendFrame();
}
void PointerInterface::axis(Qt::Orientation orientation, quint32 delta)
@ -313,6 +326,7 @@ void PointerInterface::axis(Qt::Orientation orientation, quint32 delta)
wl_pointer_send_axis(d->resource, d->seat->timestamp(),
(orientation == Qt::Vertical) ? WL_POINTER_AXIS_VERTICAL_SCROLL : WL_POINTER_AXIS_HORIZONTAL_SCROLL,
wl_fixed_from_int(delta));
d->sendFrame();
}
void PointerInterface::Private::setCursorCallback(wl_client *client, wl_resource *resource, uint32_t serial,

View file

@ -49,6 +49,7 @@ public:
void sendLeave(SurfaceInterface *surface, quint32 serial);
void sendEnter(SurfaceInterface *surface, const QPointF &parentSurfacePosition, quint32 serial);
void sendFrame();
void registerRelativePointer(RelativePointerInterface *relativePointer);
void registerSwipeGesture(PointerSwipeGestureInterface *gesture);

View file

@ -46,10 +46,10 @@ namespace KWayland
namespace Server
{
const quint32 SeatInterface::Private::s_version = 4;
const qint32 SeatInterface::Private::s_pointerVersion = 3;
const qint32 SeatInterface::Private::s_touchVersion = 3;
const qint32 SeatInterface::Private::s_keyboardVersion = 4;
const quint32 SeatInterface::Private::s_version = 5;
const qint32 SeatInterface::Private::s_pointerVersion = 5;
const qint32 SeatInterface::Private::s_touchVersion = 5;
const qint32 SeatInterface::Private::s_keyboardVersion = 5;
SeatInterface::Private::Private(SeatInterface *q, Display *display)
: Global::Private(display, &wl_seat_interface, s_version)
@ -61,7 +61,8 @@ SeatInterface::Private::Private(SeatInterface *q, Display *display)
const struct wl_seat_interface SeatInterface::Private::s_interface = {
getPointerCallback,
getKeyboardCallback,
getTouchCallback
getTouchCallback,
releaseCallback
};
#endif
@ -114,6 +115,12 @@ void SeatInterface::Private::unbind(wl_resource *r)
cast(r)->resources.removeAll(r);
}
void SeatInterface::Private::releaseCallback(wl_client *client, wl_resource *resource)
{
Q_UNUSED(client)
wl_resource_destroy(resource);
}
void SeatInterface::Private::updatePointerButtonSerial(quint32 button, quint32 serial)
{
auto it = globalPointer.buttonSerials.find(button);
@ -473,6 +480,7 @@ void SeatInterface::Private::getPointer(wl_client *client, wl_resource *resource
// this is a pointer for the currently focused pointer surface
globalPointer.focus.pointers << pointer;
pointer->setFocusedSurface(globalPointer.focus.surface, globalPointer.focus.serial);
pointer->d_func()->sendFrame();
if (globalPointer.focus.pointers.count() == 1) {
// got a new pointer
emit q->focusedPointerChanged(pointer);
@ -687,8 +695,10 @@ void SeatInterface::setFocusedPointerSurface(SurfaceInterface *surface, const QM
return;
}
const quint32 serial = d->display->nextSerial();
QSet<PointerInterface *> framePointers;
for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) {
(*it)->setFocusedSurface(nullptr, serial);
framePointers << *it;
}
if (d->globalPointer.focus.surface) {
disconnect(d->globalPointer.focus.destroyConnection);
@ -711,12 +721,21 @@ void SeatInterface::setFocusedPointerSurface(SurfaceInterface *surface, const QM
}
if (p.isEmpty()) {
emit focusedPointerChanged(nullptr);
for (auto p : qAsConst(framePointers))
{
p->d_func()->sendFrame();
}
return;
}
// TODO: signal with all pointers
emit focusedPointerChanged(p.first());
for (auto it = p.constBegin(), end = p.constEnd(); it != end; ++it) {
(*it)->setFocusedSurface(surface, serial);
framePointers << *it;
}
for (auto p : qAsConst(framePointers))
{
p->d_func()->sendFrame();
}
}
@ -1322,6 +1341,7 @@ qint32 SeatInterface::touchDown(const QPointF &globalPosition)
wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()));
wl_pointer_send_button(p->resource(), serial, timestamp(), BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
p->d_func()->sendFrame();
}
);
if (!result) {

View file

@ -186,6 +186,7 @@ private:
static void getPointerCallback(wl_client *client, wl_resource *resource, uint32_t id);
static void getKeyboardCallback(wl_client *client, wl_resource *resource, uint32_t id);
static void getTouchCallback(wl_client *client, wl_resource *resource, uint32_t id);
static void releaseCallback(wl_client *client, wl_resource *resource);
static const struct wl_seat_interface s_interface;
static const quint32 s_version;
static const qint32 s_pointerVersion;