[server] Add a method IdleInterface::simulateUserActivity

Summary:
So far only the client was able to simulate user activity. This new
method allows the server to also simulate user activity on all created
idle timeouts. This is required by KWin to prevent idle timeouts when
the user interacts through KDE Connect's virtual touchpad. In that
situation the mouse pointer is used without updating the input time
stamp as it doesn't come from "real" input devices and thus the idle
timeout prevention is not activated.

Reviewers: #frameworks, #plasma, #kwin

Subscribers: plasma-devel

Tags: #plasma_on_wayland, #frameworks

Differential Revision: https://phabricator.kde.org/D9510
This commit is contained in:
Martin Flöser 2017-12-26 20:20:39 +01:00
parent e087a3666b
commit 1a5762b9d7
3 changed files with 63 additions and 17 deletions

View file

@ -42,6 +42,7 @@ private Q_SLOTS:
void testTimeout();
void testSimulateUserActivity();
void testServerSimulateUserActivity();
void testIdleInhibit();
void testIdleInhibitBlocksTimeout();
@ -188,6 +189,34 @@ void IdleTest::testSimulateUserActivity()
m_display->dispatchEvents();
}
void IdleTest::testServerSimulateUserActivity()
{
// this test verifies that simulate user activity doesn't fire the timer
QScopedPointer<IdleTimeout> timeout(m_idle->getTimeout(6000, m_seat));
QVERIFY(timeout->isValid());
QSignalSpy idleSpy(timeout.data(), &IdleTimeout::idle);
QVERIFY(idleSpy.isValid());
QSignalSpy resumedFormIdleSpy(timeout.data(), &IdleTimeout::resumeFromIdle);
QVERIFY(resumedFormIdleSpy.isValid());
m_connection->flush();
QTest::qWait(4000);
m_idleInterface->simulateUserActivity();
// waiting default five sec should fail
QVERIFY(!idleSpy.wait());
// another 2 sec should fire
QVERIFY(idleSpy.wait(2000));
// now simulating user activity should emit a resumedFromIdle
QVERIFY(resumedFormIdleSpy.isEmpty());
m_idleInterface->simulateUserActivity();
QVERIFY(resumedFormIdleSpy.wait());
timeout.reset();
m_connection->flush();
m_display->dispatchEvents();
}
void IdleTest::testIdleInhibit()
{
QCOMPARE(m_idleInterface->isInhibited(), false);

View file

@ -39,6 +39,7 @@ public:
Private(IdleInterface *q, Display *d);
int inhibitCount = 0;
QVector<IdleTimeoutInterface*> idleTimeouts;
private:
void bind(wl_client *client, uint32_t version, uint32_t id) override;
@ -61,6 +62,8 @@ public:
~Private();
void setup(quint32 timeout);
void simulateUserActivity();
SeatInterface *seat;
QTimer *timer = nullptr;
@ -98,6 +101,9 @@ void IdleInterface::Private::getIdleTimeoutCallback(wl_client *client, wl_resour
delete idleTimeout;
return;
}
p->idleTimeouts << idleTimeout;
QObject::connect(idleTimeout, &IdleTimeoutInterface::aboutToBeUnbound, p->q,
std::bind(&QVector<IdleTimeoutInterface*>::removeOne, p->idleTimeouts, idleTimeout));
idleTimeout->d_func()->setup(timeout);
}
@ -149,6 +155,14 @@ bool IdleInterface::isInhibited() const
return d->inhibitCount > 0;
}
void IdleInterface::simulateUserActivity()
{
Q_D();
for (auto i : qAsConst(d->idleTimeouts)) {
i->d_func()->simulateUserActivity();
}
}
IdleInterface::Private *IdleInterface::d_func() const
{
return reinterpret_cast<Private*>(d.data());
@ -173,18 +187,23 @@ void IdleTimeoutInterface::Private::simulateUserActivityCallback(wl_client *clie
{
Q_UNUSED(client);
Private *p = reinterpret_cast<Private*>(wl_resource_get_user_data(resource));
if (!p->timer) {
p->simulateUserActivity();
}
void IdleTimeoutInterface::Private::simulateUserActivity()
{
if (!timer) {
// not yet configured
return;
}
if (qobject_cast<IdleInterface*>(p->global)->isInhibited()) {
if (qobject_cast<IdleInterface*>(global)->isInhibited()) {
// ignored while inhibited
return;
}
if (!p->timer->isActive() && p->resource) {
org_kde_kwin_idle_timeout_send_resumed(p->resource);
if (!timer->isActive() && resource) {
org_kde_kwin_idle_timeout_send_resumed(resource);
}
p->timer->start();
timer->start();
}
void IdleTimeoutInterface::Private::setup(quint32 timeout)
@ -216,18 +235,7 @@ IdleTimeoutInterface::IdleTimeoutInterface(SeatInterface *seat, IdleInterface *p
connect(seat, &SeatInterface::timestampChanged, this,
[this] {
Q_D();
if (!d->timer) {
// not yet configured
return;
}
if (qobject_cast<IdleInterface*>(d->global)->isInhibited()) {
// ignored while inhibited
return;
}
if (!d->timer->isActive() && d->resource) {
org_kde_kwin_idle_timeout_send_resumed(d->resource);
}
d->timer->start();
d->simulateUserActivity();
}
);
connect(parent, &IdleInterface::inhibitedChanged, this,

View file

@ -94,6 +94,15 @@ public:
**/
bool isInhibited() const;
/**
* Calling this method allows the Compositor to simulate user activity.
* This means the same action is performed as if the user interacted with
* an input device on the SeatInterface.
* Idle timeouts are resumed and the idle time gets restarted.
* @since 5.42
**/
void simulateUserActivity();
Q_SIGNALS:
/**
* Emitted when the system gets inhibited or uninhibited.