Suspend/Resume libinput when logind session Active changes

LogindIntegration starts monitoring the Active property on the session
and emits a signal when the state changes. The LibInput::Connection
connects to this signal during the setup and uses it to suspend/resume
the libinput context.
This commit is contained in:
Martin Gräßlin 2014-08-15 12:51:31 +02:00
parent a918591fef
commit 6a032e78b7
5 changed files with 83 additions and 0 deletions

View file

@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "connection.h"
#include "context.h"
#include "events.h"
#include "../logind.h"
#include <QDebug>
#include <QSocketNotifier>
@ -85,6 +86,13 @@ void Connection::setup()
Q_ASSERT(!m_notifier);
m_notifier = new QSocketNotifier(m_input->fileDescriptor(), QSocketNotifier::Read, this);
connect(m_notifier, &QSocketNotifier::activated, this, &Connection::handleEvent);
LogindIntegration *logind = LogindIntegration::self();
connect(logind, &LogindIntegration::sessionActiveChanged, this,
[this](bool active) {
active ? m_input->resume() : m_input->suspend();
}
);
}
void Connection::handleEvent()

View file

@ -45,6 +45,7 @@ Udev::~Udev()
Context::Context(const Udev &udev)
: m_libinput(libinput_udev_create_context(&Context::s_interface, this, udev))
, m_suspended(false)
{
libinput_log_set_priority(m_libinput, LIBINPUT_LOG_PRIORITY_DEBUG);
}
@ -150,5 +151,23 @@ Event *Context::event()
return Event::create(libinput_get_event(m_libinput));
}
void Context::suspend()
{
if (m_suspended) {
return;
}
libinput_suspend(m_libinput);
m_suspended = true;
}
void Context::resume()
{
if (!m_suspended) {
return;
}
libinput_resume(m_libinput);
m_suspended = false;
}
}
}

View file

@ -62,6 +62,8 @@ public:
int fileDescriptor();
void dispatch();
void suspend();
void resume();
operator libinput*() {
return m_libinput;
@ -84,6 +86,7 @@ private:
int openRestricted(const char *path, int flags);
void closeRestricted(int fd);
struct libinput *m_libinput;
bool m_suspended;
};
}

View file

@ -37,6 +37,7 @@ const static QString s_login1Service = QStringLiteral("org.freedesktop.login1");
const static QString s_login1Path = QStringLiteral("/org/freedesktop/login1");
const static QString s_login1ManagerInterface = QStringLiteral("org.freedesktop.login1.Manager");
const static QString s_login1SessionInterface = QStringLiteral("org.freedesktop.login1.Session");
const static QString s_dbusPropertiesInterface = QStringLiteral("org.freedesktop.DBus.Properties");
LogindIntegration *LogindIntegration::s_self = nullptr;
@ -56,6 +57,7 @@ LogindIntegration::LogindIntegration(const QDBusConnection &connection, QObject
this))
, m_connected(false)
, m_sessionControl(false)
, m_sessionActive(false)
{
connect(m_logindServiceWatcher, &QDBusServiceWatcher::serviceRegistered, this, &LogindIntegration::logindServiceRegistered);
connect(m_logindServiceWatcher, &QDBusServiceWatcher::serviceUnregistered, this,
@ -120,11 +122,53 @@ void LogindIntegration::logindServiceRegistered()
m_sessionPath = reply.value().path();
qDebug() << "Session path:" << m_sessionPath;
m_connected = true;
connectSessionPropertiesChanged();
getSessionActive();
emit connectedChanged();
}
);
}
void LogindIntegration::connectSessionPropertiesChanged()
{
m_bus.connect(s_login1Service,
m_sessionPath,
s_dbusPropertiesInterface,
QStringLiteral("PropertiesChanged"),
this,
SLOT(getSessionActive()));
}
void LogindIntegration::getSessionActive()
{
if (!m_connected || m_sessionPath.isEmpty()) {
return;
}
QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service,
m_sessionPath,
s_dbusPropertiesInterface,
QStringLiteral("Get"));
message.setArguments(QVariantList({s_login1SessionInterface, QStringLiteral("Active")}));
QDBusPendingReply<QVariant> reply = m_bus.asyncCall(message);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
connect(watcher, &QDBusPendingCallWatcher::finished, this,
[this](QDBusPendingCallWatcher *self) {
QDBusPendingReply<QVariant> reply = *self;
self->deleteLater();
if (!reply.isValid()) {
qDebug() << "Failed to get Active Property of logind session:" << reply.error().message();
return;
}
const bool active = reply.value().toBool();
if (m_sessionActive != active) {
m_sessionActive = active;
emit sessionActiveChanged(m_sessionActive);
}
}
);
}
void LogindIntegration::takeControl()
{
if (!m_connected || m_sessionPath.isEmpty() || m_sessionControl) {

View file

@ -42,6 +42,9 @@ public:
bool hasSessionControl() const {
return m_sessionControl;
}
bool isActiveSession() const {
return m_sessionActive;
}
void takeControl();
void releaseControl();
@ -52,6 +55,10 @@ public:
Q_SIGNALS:
void connectedChanged();
void hasSessionControlChanged(bool);
void sessionActiveChanged(bool);
private Q_SLOTS:
void getSessionActive();
private:
friend class LogindTest;
@ -63,11 +70,13 @@ private:
**/
explicit LogindIntegration(const QDBusConnection &connection, QObject *parent = nullptr);
void logindServiceRegistered();
void connectSessionPropertiesChanged();
QDBusConnection m_bus;
QDBusServiceWatcher *m_logindServiceWatcher;
bool m_connected;
QString m_sessionPath;
bool m_sessionControl;
bool m_sessionActive;
KWIN_SINGLETON(LogindIntegration)
};