From 6ebc3d65f032ef79f2ce7db0fa86016aadbbf18f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Fl=C3=B6ser?= Date: Sun, 9 Jul 2017 17:24:58 +0200 Subject: [PATCH] Add ConsoleKit2 support for launching Wayland sessions Summary: ConsoleKit2 as of version 1.1.1 implements the Session Controller dbus calls required by Kwin to run under Wayland. This patch first looks for the login1 service before attempting the ConsoleKit service. Test Plan: On a system running ConsoleKit2, logging into a text console and running: export $(dbus-launch); export QT_QPA_PLATFORM=wayland; startplasmacompositor Most of this patch is just shuffling code around to support both logind and CK2. Reviewers: #kwin, graesslin Reviewed By: #kwin, graesslin Subscribers: graesslin, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D6291 --- logind.cpp | 142 ++++++++++++++++++++++++++++++++++++----------------- logind.h | 12 +++++ 2 files changed, 110 insertions(+), 44 deletions(-) diff --git a/logind.cpp b/logind.cpp index fee0f2ff4f..4afd8499f8 100644 --- a/logind.cpp +++ b/logind.cpp @@ -58,12 +58,26 @@ Q_DECLARE_METATYPE(DBusLogindSeat) namespace KWin { +const static QString s_login1Name = QStringLiteral("logind"); 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_login1SeatInterface = QStringLiteral("org.freedesktop.login1.Seat"); const static QString s_login1SessionInterface = QStringLiteral("org.freedesktop.login1.Session"); +const static QString s_login1ActivateProperty = QStringLiteral("Activate"); + +const static QString s_ck2Name = QStringLiteral("ConsoleKit"); +const static QString s_ck2Service = QStringLiteral("org.freedesktop.ConsoleKit"); +const static QString s_ck2Path = QStringLiteral("/org/freedesktop/ConsoleKit/Manager"); +const static QString s_ck2ManagerInterface = QStringLiteral("org.freedesktop.ConsoleKit.Manager"); +const static QString s_ck2SeatInterface = QStringLiteral("org.freedesktop.ConsoleKit.Seat"); +const static QString s_ck2SessionInterface = QStringLiteral("org.freedesktop.ConsoleKit.Session"); +const static QString s_ck2ActivateProperty = QStringLiteral("activate"); + const static QString s_dbusPropertiesInterface = QStringLiteral("org.freedesktop.DBus.Properties"); + + LogindIntegration *LogindIntegration::s_self = nullptr; LogindIntegration *LogindIntegration::create(QObject *parent) @@ -76,22 +90,10 @@ LogindIntegration *LogindIntegration::create(QObject *parent) LogindIntegration::LogindIntegration(const QDBusConnection &connection, QObject *parent) : QObject(parent) , m_bus(connection) - , m_logindServiceWatcher(new QDBusServiceWatcher(s_login1Service, - m_bus, - QDBusServiceWatcher::WatchForUnregistration | QDBusServiceWatcher::WatchForRegistration, - this)) , m_connected(false) , m_sessionControl(false) , m_sessionActive(false) { - connect(m_logindServiceWatcher, &QDBusServiceWatcher::serviceRegistered, this, &LogindIntegration::logindServiceRegistered); - connect(m_logindServiceWatcher, &QDBusServiceWatcher::serviceUnregistered, this, - [this]() { - m_connected = false; - emit connectedChanged(); - } - ); - // check whether the logind service is registered QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.DBus"), QStringLiteral("/"), @@ -107,8 +109,11 @@ LogindIntegration::LogindIntegration(const QDBusConnection &connection, QObject return; } if (reply.value().contains(s_login1Service)) { - logindServiceRegistered(); + setupSessionController(SessionControllerLogind); + } else if (reply.value().contains(s_ck2Service)) { + setupSessionController(SessionControllerConsoleKit); } + } ); } @@ -123,6 +128,53 @@ LogindIntegration::~LogindIntegration() s_self = nullptr; } +void LogindIntegration::setupSessionController(SessionController controller) +{ + if (controller == SessionControllerLogind) { + // We have the logind serivce, set it up and use it + m_sessionControllerName = s_login1Name; + m_sessionControllerService = s_login1Service; + m_sessionControllerPath = s_login1Path; + m_sessionControllerManagerInterface = s_login1ManagerInterface; + m_sessionControllerSeatInterface = s_login1SeatInterface; + m_sessionControllerSessionInterface = s_login1SessionInterface; + m_sessionControllerActivateProperty = s_login1ActivateProperty; + m_logindServiceWatcher = new QDBusServiceWatcher(m_sessionControllerService, + m_bus, + QDBusServiceWatcher::WatchForUnregistration | QDBusServiceWatcher::WatchForRegistration, + this); + connect(m_logindServiceWatcher, &QDBusServiceWatcher::serviceRegistered, this, &LogindIntegration::logindServiceRegistered); + connect(m_logindServiceWatcher, &QDBusServiceWatcher::serviceUnregistered, this, + [this]() { + m_connected = false; + emit connectedChanged(); + } + ); + logindServiceRegistered(); + } else if (controller == SessionControllerConsoleKit) { + // We have the ConsoleKit serivce, set it up and use it + m_sessionControllerName = s_ck2Name; + m_sessionControllerService = s_ck2Service; + m_sessionControllerPath = s_ck2Path; + m_sessionControllerManagerInterface = s_ck2ManagerInterface; + m_sessionControllerSeatInterface = s_ck2SeatInterface; + m_sessionControllerSessionInterface = s_ck2SessionInterface; + m_sessionControllerActivateProperty = s_ck2ActivateProperty; + m_logindServiceWatcher = new QDBusServiceWatcher(m_sessionControllerService, + m_bus, + QDBusServiceWatcher::WatchForUnregistration | QDBusServiceWatcher::WatchForRegistration, + this); + connect(m_logindServiceWatcher, &QDBusServiceWatcher::serviceRegistered, this, &LogindIntegration::logindServiceRegistered); + connect(m_logindServiceWatcher, &QDBusServiceWatcher::serviceUnregistered, this, + [this]() { + m_connected = false; + emit connectedChanged(); + } + ); + logindServiceRegistered(); + } +} + void LogindIntegration::logindServiceRegistered() { const QByteArray sessionId = qgetenv("XDG_SESSION_ID"); @@ -136,9 +188,9 @@ void LogindIntegration::logindServiceRegistered() args << QString::fromLocal8Bit(sessionId); } // get the current session - QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service, - s_login1Path, - s_login1ManagerInterface, + QDBusMessage message = QDBusMessage::createMethodCall(m_sessionControllerService, + m_sessionControllerPath, + m_sessionControllerManagerInterface, methodName); message.setArguments(args); QDBusPendingReply session = m_bus.asyncCall(message); @@ -151,7 +203,7 @@ void LogindIntegration::logindServiceRegistered() return; } if (!reply.isValid()) { - qCDebug(KWIN_CORE) << "The session is not registered with logind" << reply.error().message(); + qCDebug(KWIN_CORE) << "The session is not registered with " << m_sessionControllerName << " " << reply.error().message(); return; } m_sessionPath = reply.value().path(); @@ -159,9 +211,9 @@ void LogindIntegration::logindServiceRegistered() m_connected = true; connectSessionPropertiesChanged(); // activate the session, in case we are not on it - QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service, + QDBusMessage message = QDBusMessage::createMethodCall(m_sessionControllerService, m_sessionPath, - s_login1SessionInterface, + m_sessionControllerSessionInterface, QStringLiteral("Activate")); // blocking on purpose m_bus.call(message); @@ -176,13 +228,13 @@ void LogindIntegration::logindServiceRegistered() void LogindIntegration::connectSessionPropertiesChanged() { - m_bus.connect(s_login1Service, + m_bus.connect(m_sessionControllerService, m_sessionPath, s_dbusPropertiesInterface, QStringLiteral("PropertiesChanged"), this, SLOT(getSessionActive())); - m_bus.connect(s_login1Service, + m_bus.connect(m_sessionControllerService, m_sessionPath, s_dbusPropertiesInterface, QStringLiteral("PropertiesChanged"), @@ -195,11 +247,11 @@ void LogindIntegration::getSessionActive() if (!m_connected || m_sessionPath.isEmpty()) { return; } - QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service, + QDBusMessage message = QDBusMessage::createMethodCall(m_sessionControllerService, m_sessionPath, s_dbusPropertiesInterface, QStringLiteral("Get")); - message.setArguments(QVariantList({s_login1SessionInterface, QStringLiteral("Active")})); + message.setArguments(QVariantList({m_sessionControllerSessionInterface, m_sessionControllerActivateProperty})); QDBusPendingReply reply = m_bus.asyncCall(message); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, @@ -207,7 +259,7 @@ void LogindIntegration::getSessionActive() QDBusPendingReply reply = *self; self->deleteLater(); if (!reply.isValid()) { - qCDebug(KWIN_CORE) << "Failed to get Active Property of logind session:" << reply.error().message(); + qCDebug(KWIN_CORE) << "Failed to get Active Property of " << m_sessionControllerName << " session:" << reply.error().message(); return; } const bool active = reply.value().toBool(); @@ -224,11 +276,11 @@ void LogindIntegration::getVirtualTerminal() if (!m_connected || m_sessionPath.isEmpty()) { return; } - QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service, + QDBusMessage message = QDBusMessage::createMethodCall(m_sessionControllerService, m_sessionPath, s_dbusPropertiesInterface, QStringLiteral("Get")); - message.setArguments(QVariantList({s_login1SessionInterface, QStringLiteral("VTNr")})); + message.setArguments(QVariantList({m_sessionControllerSessionInterface, QStringLiteral("VTNr")})); QDBusPendingReply reply = m_bus.asyncCall(message); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, @@ -236,7 +288,7 @@ void LogindIntegration::getVirtualTerminal() QDBusPendingReply reply = *self; self->deleteLater(); if (!reply.isValid()) { - qCDebug(KWIN_CORE) << "Failed to get VTNr Property of logind session:" << reply.error().message(); + qCDebug(KWIN_CORE) << "Failed to get VTNr Property of " << m_sessionControllerName << " session:" << reply.error().message(); return; } const int vt = reply.value().toUInt(); @@ -259,9 +311,9 @@ void LogindIntegration::takeControl() } s_recursionCheck = true; - QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service, + QDBusMessage message = QDBusMessage::createMethodCall(m_sessionControllerService, m_sessionPath, - s_login1SessionInterface, + m_sessionControllerSessionInterface, QStringLiteral("TakeControl")); message.setArguments(QVariantList({QVariant(false)})); QDBusPendingReply session = m_bus.asyncCall(message); @@ -279,8 +331,8 @@ void LogindIntegration::takeControl() qCDebug(KWIN_CORE) << "Gained session control"; m_sessionControl = true; emit hasSessionControlChanged(true); - m_bus.connect(s_login1Service, m_sessionPath, - s_login1SessionInterface, QStringLiteral("PauseDevice"), + m_bus.connect(m_sessionControllerService, m_sessionPath, + m_sessionControllerSessionInterface, QStringLiteral("PauseDevice"), this, SLOT(pauseDevice(uint,uint,QString))); } ); @@ -292,9 +344,9 @@ void LogindIntegration::releaseControl() return; } - QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service, + QDBusMessage message = QDBusMessage::createMethodCall(m_sessionControllerService, m_sessionPath, - s_login1SessionInterface, + m_sessionControllerSessionInterface, QStringLiteral("ReleaseControl")); m_bus.asyncCall(message); m_sessionControl = false; @@ -308,9 +360,9 @@ int LogindIntegration::takeDevice(const char *path) qCDebug(KWIN_CORE) << "Could not stat the path"; return -1; } - QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service, + QDBusMessage message = QDBusMessage::createMethodCall(m_sessionControllerService, m_sessionPath, - s_login1SessionInterface, + m_sessionControllerSessionInterface, QStringLiteral("TakeDevice")); message.setArguments(QVariantList({QVariant(major(st.st_rdev)), QVariant(minor(st.st_rdev))})); // intended to be a blocking call @@ -329,9 +381,9 @@ void LogindIntegration::releaseDevice(int fd) qCDebug(KWIN_CORE) << "Could not stat the file descriptor"; return; } - QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service, + QDBusMessage message = QDBusMessage::createMethodCall(m_sessionControllerService, m_sessionPath, - s_login1SessionInterface, + m_sessionControllerSessionInterface, QStringLiteral("ReleaseDevice")); message.setArguments(QVariantList({QVariant(major(st.st_rdev)), QVariant(minor(st.st_rdev))})); m_bus.asyncCall(message); @@ -341,7 +393,7 @@ void LogindIntegration::pauseDevice(uint devMajor, uint devMinor, const QString { if (QString::compare(type, QStringLiteral("pause"), Qt::CaseInsensitive) == 0) { // unconditionally call complete - QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service, m_sessionPath, s_login1SessionInterface, QStringLiteral("PauseDeviceComplete")); + QDBusMessage message = QDBusMessage::createMethodCall(m_sessionControllerService, m_sessionPath, m_sessionControllerSessionInterface, QStringLiteral("PauseDeviceComplete")); message.setArguments(QVariantList({QVariant(devMajor), QVariant(devMinor)})); m_bus.asyncCall(message); } @@ -353,11 +405,12 @@ void LogindIntegration::getSeat() return; } qDBusRegisterMetaType(); - QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service, + QDBusMessage message = QDBusMessage::createMethodCall(m_sessionControllerService, m_sessionPath, s_dbusPropertiesInterface, QStringLiteral("Get")); - message.setArguments(QVariantList({s_login1SessionInterface, QStringLiteral("Seat")})); + message.setArguments(QVariantList({m_sessionControllerSessionInterface, QStringLiteral("Seat")})); + message.setArguments(QVariantList({m_sessionControllerSessionInterface, QStringLiteral("Seat")})); QDBusPendingReply reply = m_bus.asyncCall(message); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, @@ -365,12 +418,13 @@ void LogindIntegration::getSeat() QDBusPendingReply reply = *self; self->deleteLater(); if (!reply.isValid()) { - qCDebug(KWIN_CORE) << "Failed to get Seat Property of logind session:" << reply.error().message(); + qCDebug(KWIN_CORE) << "Failed to get Seat Property of " << m_sessionControllerName << " session:" << reply.error().message(); return; } DBusLogindSeat seat = qdbus_cast(reply.value().value()); const QString seatPath = seat.path.path(); - qCDebug(KWIN_CORE) << "Logind seat:" << seat.name << "/" << seatPath; + qCDebug(KWIN_CORE) << m_sessionControllerName << " seat:" << seat.name << "/" << seatPath; + qCDebug(KWIN_CORE) << m_sessionControllerName << " seat:" << seat.name << "/" << seatPath; if (m_seatPath != seatPath) { m_seatPath = seatPath; } @@ -383,9 +437,9 @@ void LogindIntegration::switchVirtualTerminal(quint32 vtNr) if (!m_connected || m_seatPath.isEmpty()) { return; } - QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service, + QDBusMessage message = QDBusMessage::createMethodCall(m_sessionControllerService, m_seatPath, - QStringLiteral("org.freedesktop.login1.Seat"), + m_sessionControllerSeatInterface, QStringLiteral("SwitchTo")); message.setArguments(QVariantList{vtNr}); m_bus.asyncCall(message); diff --git a/logind.h b/logind.h index 8bb02062d3..2fc868efc3 100644 --- a/logind.h +++ b/logind.h @@ -78,6 +78,11 @@ private: explicit LogindIntegration(const QDBusConnection &connection, QObject *parent = nullptr); void logindServiceRegistered(); void connectSessionPropertiesChanged(); + enum SessionController { + SessionControllerLogind, + SessionControllerConsoleKit, + }; + void setupSessionController(SessionController controller); void getSeat(); QDBusConnection m_bus; QDBusServiceWatcher *m_logindServiceWatcher; @@ -87,6 +92,13 @@ private: bool m_sessionActive; int m_vt = -1; QString m_seatPath; + QString m_sessionControllerName; + QString m_sessionControllerService; + QString m_sessionControllerPath; + QString m_sessionControllerManagerInterface; + QString m_sessionControllerSeatInterface; + QString m_sessionControllerSessionInterface; + QString m_sessionControllerActivateProperty; KWIN_SINGLETON(LogindIntegration) };