Properly handle release of a touch resource

Summary:
On client side use wl_touch_release to get into the proper destroy
handler on server side. There the shared destroy implementation is
used.

The test case is extended to verify the condition and ensure that
our code doesn't crash in case SeatInterface calls into the already
unbound TouchInterface.

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D2035
This commit is contained in:
Martin Gräßlin 2016-06-28 16:15:46 +02:00
parent f53bc666eb
commit 34df9d8b2e
2 changed files with 28 additions and 11 deletions

View file

@ -1400,7 +1400,8 @@ void TestWaylandSeat::testTouch()
Touch *touch = m_seat->createTouch(m_seat);
QVERIFY(touch->isValid());
QVERIFY(touchCreatedSpy.wait());
QVERIFY(m_seatInterface->focusedTouch());
auto serverTouch = m_seatInterface->focusedTouch();
QVERIFY(serverTouch);
QCOMPARE(touchCreatedSpy.first().first().value<KWayland::Server::TouchInterface*>(), m_seatInterface->focusedTouch());
QSignalSpy sequenceStartedSpy(touch, SIGNAL(sequenceStarted(KWayland::Client::TouchPoint*)));
@ -1559,6 +1560,31 @@ void TestWaylandSeat::testTouch()
QCOMPARE(pointMovedSpy.count(), 1);
QCOMPARE(pointRemovedSpy.count(), 3);
QCOMPARE(touch->sequence().first()->position(), QPointF(0, 0));
// destroy touch on client side
QSignalSpy unboundSpy(serverTouch, &TouchInterface::unbound);
QVERIFY(unboundSpy.isValid());
QSignalSpy destroyedSpy(serverTouch, &TouchInterface::destroyed);
QVERIFY(destroyedSpy.isValid());
delete touch;
QVERIFY(unboundSpy.wait());
QCOMPARE(unboundSpy.count(), 1);
QCOMPARE(destroyedSpy.count(), 0);
QVERIFY(!serverTouch->resource());
// try to call into all the the methods of the touch interface, should not crash
QCOMPARE(m_seatInterface->focusedTouch(), serverTouch);
m_seatInterface->setTimestamp(8);
QCOMPARE(m_seatInterface->touchDown(QPointF(15, 26)), 0);
m_seatInterface->touchFrame();
m_seatInterface->touchMove(0, QPointF(0, 0));
QCOMPARE(m_seatInterface->touchDown(QPointF(15, 26)), 1);
m_seatInterface->cancelTouchSequence();
QVERIFY(destroyedSpy.wait());
QCOMPARE(destroyedSpy.count(), 1);
// should have unset the focused touch
QVERIFY(!m_seatInterface->focusedTouch());
// but not the focused touch surface
QCOMPARE(m_seatInterface->focusedTouchSurface(), serverSurface);
}
void TestWaylandSeat::testDisconnect()

View file

@ -44,16 +44,13 @@ private:
TouchInterface *q_func() {
return reinterpret_cast<TouchInterface *>(q);
}
// interface
// since version 3
static void releaseCallback(wl_client *client, wl_resource *resource);
static const struct wl_touch_interface s_interface;
};
#ifndef DOXYGEN_SHOULD_SKIP_THIS
const struct wl_touch_interface TouchInterface::Private::s_interface = {
releaseCallback
resourceDestroyedCallback
};
#endif
@ -63,12 +60,6 @@ TouchInterface::Private::Private(SeatInterface *parent, wl_resource *parentResou
{
}
void TouchInterface::Private::releaseCallback(wl_client *client, wl_resource *resource)
{
Q_UNUSED(client)
unbind(resource);
}
TouchInterface::TouchInterface(SeatInterface *parent, wl_resource *parentResource)
: Resource(new Private(parent, parentResource, this))
{