10#include <QCoreApplication>
11#include <QDBusConnection>
12#include <QDBusConnectionInterface>
13#include <QDBusInterface>
14#include <QDBusMessage>
15#include <QDBusMetaType>
16#include <QDBusObjectPath>
17#include <QDBusPendingCall>
18#include <QDBusUnixFileDescriptor>
24#if __has_include(<sys/sysmacros.h>)
25#include <sys/sysmacros.h>
38 argument.beginStructure();
39 argument << seat.id << seat.path;
40 argument.endStructure();
46 argument.beginStructure();
47 argument >> seat.id >> seat.path;
48 argument.endStructure();
57static const QString s_serviceName = QStringLiteral(
"org.freedesktop.ConsoleKit");
58static const QString s_propertiesInterface = QStringLiteral(
"org.freedesktop.DBus.Properties");
59static const QString s_sessionInterface = QStringLiteral(
"org.freedesktop.ConsoleKit.Session");
60static const QString s_seatInterface = QStringLiteral(
"org.freedesktop.ConsoleKit.Seat");
61static const QString s_managerInterface = QStringLiteral(
"org.freedesktop.ConsoleKit.Manager");
62static const QString s_managerPath = QStringLiteral(
"/org/freedesktop/ConsoleKit/Manager");
64static QString findProcessSessionPath()
66 QDBusMessage message = QDBusMessage::createMethodCall(s_serviceName, s_managerPath,
68 QStringLiteral(
"GetSessionByPID"));
69 message.setArguments({uint32_t(QCoreApplication::applicationPid())});
71 const QDBusMessage reply = QDBusConnection::systemBus().call(message);
72 if (reply.type() == QDBusMessage::ErrorMessage) {
76 return reply.arguments().constFirst().value<QDBusObjectPath>().path();
79static bool takeControl(
const QString &sessionPath)
81 QDBusMessage message = QDBusMessage::createMethodCall(s_serviceName, sessionPath,
83 QStringLiteral(
"TakeControl"));
84 message.setArguments({
false});
86 const QDBusMessage reply = QDBusConnection::systemBus().call(message);
88 return reply.type() != QDBusMessage::ErrorMessage;
91static void releaseControl(
const QString &sessionPath)
93 const QDBusMessage message = QDBusMessage::createMethodCall(s_serviceName, sessionPath,
95 QStringLiteral(
"ReleaseControl"));
97 QDBusConnection::systemBus().asyncCall(message);
100static bool activate(
const QString &sessionPath)
102 const QDBusMessage message = QDBusMessage::createMethodCall(s_serviceName, sessionPath,
104 QStringLiteral(
"Activate"));
106 const QDBusMessage reply = QDBusConnection::systemBus().call(message);
108 return reply.type() != QDBusMessage::ErrorMessage;
113 if (!QDBusConnection::systemBus().interface()->isServiceRegistered(s_serviceName)) {
117 const QString sessionPath = findProcessSessionPath();
118 if (sessionPath.isEmpty()) {
119 qCWarning(KWIN_CORE) <<
"Could not determine the active graphical session";
123 if (!activate(sessionPath)) {
124 qCWarning(KWIN_CORE,
"Failed to activate %s session. Maybe another compositor is running?",
125 qPrintable(sessionPath));
129 if (!takeControl(sessionPath)) {
130 qCWarning(KWIN_CORE,
"Failed to take control of %s session. Maybe another compositor is running?",
131 qPrintable(sessionPath));
136 if (session->initialize()) {
166 if (stat(fileName.toUtf8(), &st) < 0) {
170 QDBusMessage message = QDBusMessage::createMethodCall(s_serviceName, m_sessionPath,
172 QStringLiteral(
"TakeDevice"));
174 message.setArguments({uint(major(st.st_rdev)), uint(minor(st.st_rdev))});
176 const QDBusMessage reply = QDBusConnection::systemBus().call(message);
177 if (reply.type() == QDBusMessage::ErrorMessage) {
178 qCDebug(KWIN_CORE,
"Failed to open %s device (%s)",
179 qPrintable(fileName), qPrintable(reply.errorMessage()));
183 const QDBusUnixFileDescriptor descriptor = reply.arguments().constFirst().value<QDBusUnixFileDescriptor>();
184 if (!descriptor.isValid()) {
188 return fcntl(descriptor.fileDescriptor(), F_DUPFD_CLOEXEC, 0);
194 if (fstat(fileDescriptor, &st) < 0) {
195 close(fileDescriptor);
199 QDBusMessage message = QDBusMessage::createMethodCall(s_serviceName, m_sessionPath,
201 QStringLiteral(
"ReleaseDevice"));
203 message.setArguments({uint(major(st.st_rdev)), uint(minor(st.st_rdev))});
205 QDBusConnection::systemBus().asyncCall(message);
207 close(fileDescriptor);
212 QDBusMessage message = QDBusMessage::createMethodCall(s_serviceName, m_seatPath,
214 QStringLiteral(
"SwitchTo"));
217 QDBusConnection::systemBus().asyncCall(message);
220ConsoleKitSession::ConsoleKitSession(
const QString &sessionPath)
221 : m_sessionPath(sessionPath)
223 qDBusRegisterMetaType<DBusConsoleKitSeat>();
228 releaseControl(m_sessionPath);
231bool ConsoleKitSession::initialize()
233 QDBusMessage activeMessage = QDBusMessage::createMethodCall(s_serviceName, m_sessionPath,
234 s_propertiesInterface,
235 QStringLiteral(
"Get"));
236 activeMessage.setArguments({s_sessionInterface, QStringLiteral(
"active")});
238 QDBusMessage seatMessage = QDBusMessage::createMethodCall(s_serviceName, m_sessionPath,
239 s_propertiesInterface,
240 QStringLiteral(
"Get"));
241 seatMessage.setArguments({s_sessionInterface, QStringLiteral(
"Seat")});
243 QDBusMessage terminalMessage = QDBusMessage::createMethodCall(s_serviceName, m_sessionPath,
244 s_propertiesInterface,
245 QStringLiteral(
"Get"));
246 terminalMessage.setArguments({s_sessionInterface, QStringLiteral(
"VTNr")});
248 QDBusPendingReply<QVariant> activeReply =
249 QDBusConnection::systemBus().asyncCall(activeMessage);
250 QDBusPendingReply<QVariant> terminalReply =
251 QDBusConnection::systemBus().asyncCall(terminalMessage);
252 QDBusPendingReply<QVariant> seatReply =
253 QDBusConnection::systemBus().asyncCall(seatMessage);
257 activeReply.waitForFinished();
258 terminalReply.waitForFinished();
259 seatReply.waitForFinished();
261 if (activeReply.isError()) {
262 qCWarning(KWIN_CORE) <<
"Failed to query active session property:" << activeReply.error();
265 if (terminalReply.isError()) {
266 qCWarning(KWIN_CORE) <<
"Failed to query VTNr session property:" << terminalReply.error();
269 if (seatReply.isError()) {
270 qCWarning(KWIN_CORE) <<
"Failed to query Seat session property:" << seatReply.error();
274 m_isActive = activeReply.value().toBool();
275 m_terminal = terminalReply.value().toUInt();
279 m_seatPath =
seat.path.path();
281 QDBusConnection::systemBus().connect(s_serviceName, s_managerPath, s_managerInterface,
282 QStringLiteral(
"PrepareForSleep"),
284 SLOT(handlePrepareForSleep(
bool)));
286 QDBusConnection::systemBus().connect(s_serviceName, m_sessionPath, s_sessionInterface,
287 QStringLiteral(
"PauseDevice"),
289 SLOT(handlePauseDevice(uint, uint, QString)));
291 QDBusConnection::systemBus().connect(s_serviceName, m_sessionPath, s_sessionInterface,
292 QStringLiteral(
"ResumeDevice"),
294 SLOT(handleResumeDevice(uint, uint, QDBusUnixFileDescriptor)));
296 QDBusConnection::systemBus().connect(s_serviceName, m_sessionPath, s_propertiesInterface,
297 QStringLiteral(
"PropertiesChanged"),
299 SLOT(handlePropertiesChanged(QString, QVariantMap)));
304void ConsoleKitSession::updateActive(
bool active)
306 if (m_isActive != active) {
312void ConsoleKitSession::handlePauseDevice(uint major, uint minor,
const QString &
type)
316 if (
type == QLatin1String(
"pause")) {
317 QDBusMessage message = QDBusMessage::createMethodCall(s_serviceName, m_sessionPath,
319 QStringLiteral(
"PauseDeviceComplete"));
320 message.setArguments({major, minor});
322 QDBusConnection::systemBus().asyncCall(message);
326void ConsoleKitSession::handleResumeDevice(uint major, uint minor, QDBusUnixFileDescriptor fileDescriptor)
334void ConsoleKitSession::handlePropertiesChanged(
const QString &interfaceName,
const QVariantMap &properties)
336 if (interfaceName == s_sessionInterface) {
337 const QVariant active = properties.value(QStringLiteral(
"active"));
338 if (active.isValid()) {
339 updateActive(active.toBool());
344void ConsoleKitSession::handlePrepareForSleep(
bool sleep)
353#include "moc_session_consolekit.cpp"
~ConsoleKitSession() override
uint terminal() const override
bool isActive() const override
Capabilities capabilities() const override
QString seat() const override
void closeRestricted(int fileDescriptor) override
static std::unique_ptr< ConsoleKitSession > create()
void switchTo(uint terminal) override
int openRestricted(const QString &fileName) override
void activeChanged(bool active)
void devicePaused(dev_t deviceId)
void deviceResumed(dev_t deviceId)
const QDBusArgument & operator>>(const QDBusArgument &argument, DBusConsoleKitSeat &seat)
QDBusArgument & operator<<(QDBusArgument &argument, const DBusConsoleKitSeat &seat)