diff --git a/libinput/connection.cpp b/libinput/connection.cpp index ca71e563f9..ac06616cd3 100644 --- a/libinput/connection.cpp +++ b/libinput/connection.cpp @@ -20,6 +20,7 @@ along with this program. If not, see . #include "connection.h" #include "context.h" #include "events.h" +#include "../logind.h" #include #include @@ -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() diff --git a/libinput/context.cpp b/libinput/context.cpp index eda3ab66a2..137ef947a1 100644 --- a/libinput/context.cpp +++ b/libinput/context.cpp @@ -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; +} + } } diff --git a/libinput/context.h b/libinput/context.h index d0c65f8c56..25b40470f2 100644 --- a/libinput/context.h +++ b/libinput/context.h @@ -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; }; } diff --git a/logind.cpp b/logind.cpp index 731d912d00..2b9aaca913 100644 --- a/logind.cpp +++ b/logind.cpp @@ -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 reply = m_bus.asyncCall(message); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, + [this](QDBusPendingCallWatcher *self) { + QDBusPendingReply 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) { diff --git a/logind.h b/logind.h index ccb318c264..bc6478af67 100644 --- a/logind.h +++ b/logind.h @@ -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) };