Sophie

Sophie

distrib > Mageia > 3 > i586 > media > core-release-src > by-pkgid > db65a50f78baaff6c782fe7a1d80ab07 > files > 2

kdebase4-workspace-4.10.2-3.mga3.src.rpm

--- a/libs/kworkspace/kdisplaymanager.cpp.systemd-displaymanager	2012-08-13 10:53:46.000000000 +0200
+++ b/libs/kworkspace/kdisplaymanager.cpp	2012-12-05 12:58:32.193798795 +0100
@@ -40,6 +40,166 @@
 #include <errno.h>
 #include <stdio.h>
 
+#define _DBUS_PROPERTIES_IFACE "org.freedesktop.DBus.Properties"
+#define _DBUS_PROPERTIES_GET "Get"
+
+#define DBUS_PROPERTIES_IFACE QLatin1String(_DBUS_PROPERTIES_IFACE)
+#define DBUS_PROPERTIES_GET QLatin1String(_DBUS_PROPERTIES_GET)
+
+#define _SYSTEMD_SERVICE "org.freedesktop.login1"
+#define _SYSTEMD_BASE_PATH "/org/freedesktop/login1"
+#define _SYSTEMD_MANAGER_IFACE _SYSTEMD_SERVICE ".Manager"
+#define _SYSTEMD_SESSION_BASE_PATH _SYSTEMD_BASE_PATH "/Session"
+#define _SYSTEMD_SEAT_IFACE _SYSTEMD_SERVICE ".Seat"
+#define _SYSTEMD_SEAT_BASE_PATH _SYSTEMD_BASE_PATH "/Seat"
+#define _SYSTEMD_SESSION_IFACE _SYSTEMD_SERVICE ".Session"
+#define _SYSTEMD_USER_PROPERTY "User"
+#define _SYSTEMD_SEAT_PROPERTY "Seat"
+#define _SYSTEMD_SESSIONS_PROPERTY "Sessions"
+#define _SYSTEMD_SWITCH_CALL "Activate"
+
+#define SYSTEMD_SERVICE QLatin1String(_SYSTEMD_SERVICE)
+#define SYSTEMD_BASE_PATH QLatin1String(_SYSTEMD_BASE_PATH)
+#define SYSTEMD_MANAGER_IFACE QLatin1String(_SYSTEMD_MANAGER_IFACE)
+#define SYSTEMD_SESSION_BASE_PATH QLatin1String(_SYSTEMD_SESSION_BASE_PATH)
+#define SYSTEMD_SEAT_IFACE QLatin1String(_SYSTEMD_SEAT_IFACE)
+#define SYSTEMD_SEAT_BASE_PATH QLatin1String(_SYSTEMD_SEAT_BASE_PATH)
+#define SYSTEMD_SESSION_IFACE QLatin1String(_SYSTEMD_SESSION_IFACE)
+#define SYSTEMD_USER_PROPERTY QLatin1String(_SYSTEMD_USER_PROPERTY)
+#define SYSTEMD_SEAT_PROPERTY QLatin1String(_SYSTEMD_SEAT_PROPERTY)
+#define SYSTEMD_SESSIONS_PROPERTY QLatin1String(_SYSTEMD_SESSIONS_PROPERTY)
+#define SYSTEMD_SWITCH_CALL QLatin1String(_SYSTEMD_SWITCH_CALL)
+
+struct NamedDBusObjectPath
+{
+    QString name;
+    QDBusObjectPath path;
+};
+Q_DECLARE_METATYPE(NamedDBusObjectPath)
+Q_DECLARE_METATYPE(QList<NamedDBusObjectPath>)
+
+// Marshall the NamedDBusObjectPath data into a D-Bus argument
+QDBusArgument &operator<<(QDBusArgument &argument, const NamedDBusObjectPath &namedPath)
+{
+    argument.beginStructure();
+    argument << namedPath.name << namedPath.path;
+    argument.endStructure();
+    return argument;
+}
+
+// Retrieve the NamedDBusObjectPath data from the D-Bus argument
+const QDBusArgument &operator>>(const QDBusArgument &argument, NamedDBusObjectPath &namedPath)
+{
+    argument.beginStructure();
+    argument >> namedPath.name >> namedPath.path;
+    argument.endStructure();
+    return argument;
+}
+
+struct NumberedDBusObjectPath
+{
+    uint num;
+    QDBusObjectPath path;
+};
+Q_DECLARE_METATYPE(NumberedDBusObjectPath)
+
+// Marshall the NumberedDBusObjectPath data into a D-Bus argument
+QDBusArgument &operator<<(QDBusArgument &argument, const NumberedDBusObjectPath &numberedPath)
+{
+    argument.beginStructure();
+    argument << numberedPath.num << numberedPath.path;
+    argument.endStructure();
+    return argument;
+}
+
+// Retrieve the NumberedDBusObjectPath data from the D-Bus argument
+const QDBusArgument &operator>>(const QDBusArgument &argument, NumberedDBusObjectPath &numberedPath)
+{
+    argument.beginStructure();
+    argument >> numberedPath.num >> numberedPath.path;
+    argument.endStructure();
+    return argument;
+}
+
+class SystemdManager : public QDBusInterface
+{
+public:
+    SystemdManager() :
+        QDBusInterface(
+                SYSTEMD_SERVICE,
+                SYSTEMD_BASE_PATH,
+                SYSTEMD_MANAGER_IFACE,
+                QDBusConnection::systemBus()) {}
+};
+
+class SystemdSeat : public QDBusInterface
+{
+public:
+    SystemdSeat(const QDBusObjectPath &path) :
+        QDBusInterface(
+                SYSTEMD_SERVICE,
+                path.path(),
+                SYSTEMD_SEAT_IFACE,
+                QDBusConnection::systemBus()) {}
+    /* HACK to be able to extract a(so) type from QDBus, property doesn't do the trick */
+    QList<NamedDBusObjectPath> getSessions() {
+        QDBusMessage message = QDBusMessage::createMethodCall(service(), path(), DBUS_PROPERTIES_IFACE, DBUS_PROPERTIES_GET);
+        message <<  interface() << SYSTEMD_SESSIONS_PROPERTY;
+        QDBusMessage reply = QDBusConnection::systemBus().call(message);
+
+        QVariantList args = reply.arguments();
+        if (!args.isEmpty()) {
+            QList<NamedDBusObjectPath> namedPathList = qdbus_cast< QList<NamedDBusObjectPath> >(args.at(0).value<QDBusVariant>().variant().value<QDBusArgument>());
+            return namedPathList;
+        }
+        return QList<NamedDBusObjectPath>();
+    }
+};
+
+class SystemdSession : public QDBusInterface
+{
+public:
+    SystemdSession(const QDBusObjectPath &path) :
+        QDBusInterface(
+                SYSTEMD_SERVICE,
+                path.path(),
+                SYSTEMD_SESSION_IFACE,
+                QDBusConnection::systemBus()) {}
+    /* HACK to be able to extract (so) type from QDBus, property doesn't do the trick */
+    NamedDBusObjectPath getSeat() {
+        QDBusMessage message = QDBusMessage::createMethodCall(service(), path(), DBUS_PROPERTIES_IFACE, DBUS_PROPERTIES_GET);
+        message <<  interface() <<  SYSTEMD_SEAT_PROPERTY;
+        QDBusMessage reply = QDBusConnection::systemBus().call(message);
+
+        QVariantList args = reply.arguments();
+        if (!args.isEmpty()) {
+            NamedDBusObjectPath namedPath;
+            args.at(0).value<QDBusVariant>().variant().value<QDBusArgument>() >> namedPath;
+            return namedPath;
+        }
+        return NamedDBusObjectPath();
+    }
+    NumberedDBusObjectPath getUser() {
+        QDBusMessage message = QDBusMessage::createMethodCall(service(), path(), DBUS_PROPERTIES_IFACE, DBUS_PROPERTIES_GET);
+        message <<  interface() <<  SYSTEMD_USER_PROPERTY;
+        QDBusMessage reply = QDBusConnection::systemBus().call(message);
+
+        QVariantList args = reply.arguments();
+        if (!args.isEmpty()) {
+            NumberedDBusObjectPath numberedPath;
+            args.at(0).value<QDBusVariant>().variant().value<QDBusArgument>() >> numberedPath;
+            return numberedPath;
+        }
+        return NumberedDBusObjectPath();
+    }
+    void getSessionLocation(SessEnt &se)
+    {
+        se.tty = (property("Type").toString() != QLatin1String("x11"));
+        se.display = property(se.tty ? "TTY" : "Display").toString();
+        se.vt = property("VTNr").toInt();
+    }
+};
+
 class CKManager : public QDBusInterface
 {
 public:
@@ -68,9 +228,26 @@
     CKSession(const QDBusObjectPath &path) :
         QDBusInterface(
                 QLatin1String("org.freedesktop.ConsoleKit"),
-            path.path(),
+                path.path(),
                 QLatin1String("org.freedesktop.ConsoleKit.Session"),
                 QDBusConnection::systemBus()) {}
+    void getSessionLocation(SessEnt &se)
+    {
+        QString tty;
+        QDBusReply<QString> r = call(QLatin1String("GetX11Display"));
+        if (r.isValid() && !r.value().isEmpty()) {
+            QDBusReply<QString> r2 = call(QLatin1String("GetX11DisplayDevice"));
+            tty = r2.value();
+            se.display = r.value();
+            se.tty = false;
+        } else {
+            QDBusReply<QString> r2 = call(QLatin1String("GetDisplayDevice"));
+            tty = r2.value();
+            se.display = tty;
+            se.tty = true;
+        }
+        se.vt = tty.mid(strlen("/dev/tty")).toInt();
+    }
 };
 
 class GDMFactory : public QDBusInterface
@@ -131,6 +308,9 @@
     }
     switch (DMType) {
     default:
+        qDBusRegisterMetaType<NamedDBusObjectPath>();
+        qDBusRegisterMetaType<QList<NamedDBusObjectPath> >();
+        qDBusRegisterMetaType<NumberedDBusObjectPath>();
         return;
     case NewKDM:
     case OldGDM:
@@ -242,17 +422,31 @@
 
 static bool getCurrentSeat(QDBusObjectPath *currentSession, QDBusObjectPath *currentSeat)
 {
-    CKManager man;
-    QDBusReply<QDBusObjectPath> r = man.call(QLatin1String("GetCurrentSession"));
+    SystemdManager man;
+    QDBusReply<QDBusObjectPath> r = man.call(QLatin1String("GetSessionByPID"), (uint) QCoreApplication::applicationPid());
     if (r.isValid()) {
-        CKSession sess(r.value());
+        SystemdSession sess(r.value());
         if (sess.isValid()) {
-            QDBusReply<QDBusObjectPath> r2 = sess.call(QLatin1String("GetSeatId"));
-            if (r2.isValid()) {
-                if (currentSession)
-                    *currentSession = r.value();
-                *currentSeat = r2.value();
-                return true;
+            NamedDBusObjectPath namedPath = sess.getSeat();
+            if (currentSession)
+                *currentSession = r.value();
+            *currentSeat = namedPath.path;
+            return true;
+        }
+    }
+    else {
+        CKManager man;
+        QDBusReply<QDBusObjectPath> r = man.call(QLatin1String("GetCurrentSession"));
+        if (r.isValid()) {
+            CKSession sess(r.value());
+            if (sess.isValid()) {
+                QDBusReply<QDBusObjectPath> r2 = sess.call(QLatin1String("GetSeatId"));
+                if (r2.isValid()) {
+                    if (currentSession)
+                        *currentSession = r.value();
+                    *currentSeat = r2.value();
+                    return true;
+                }
             }
         }
     }
@@ -261,44 +455,44 @@
 
 static QList<QDBusObjectPath> getSessionsForSeat(const QDBusObjectPath &path)
 {
-    CKSeat seat(path);
-    if (seat.isValid()) {
-        QDBusReply<QList<QDBusObjectPath> > r = seat.call(QLatin1String("GetSessions"));
-        if (r.isValid()) {
-            // This will contain only local sessions:
-            // - this is only ever called when isSwitchable() is true => local seat
-            // - remote logins into the machine are assigned to other seats
-            return r.value();
+    if (path.path().startsWith(SYSTEMD_BASE_PATH)) { // systemd path incoming
+        SystemdSeat seat(path);
+        if (seat.isValid()) {
+            QList<NamedDBusObjectPath> r = seat.getSessions();
+            QList<QDBusObjectPath> result;
+            foreach (const NamedDBusObjectPath &namedPath, r)
+                result.append(namedPath.path);
+            // This pretty much can't contain any other than local sessions as seats are assigned only locally in systemd
+            return result;
+        }
+    }
+    else if (path.path().startsWith("/org/freedesktop/ConsoleKit")) {
+        CKSeat seat(path);
+        if (seat.isValid()) {
+            QDBusReply<QList<QDBusObjectPath> > r = seat.call(QLatin1String("GetSessions"));
+            if (r.isValid()) {
+                // This will contain only local sessions:
+                // - this is only ever called when isSwitchable() is true => local seat
+                // - remote logins into the machine are assigned to other seats
+                return r.value();
+            }
         }
     }
     return QList<QDBusObjectPath>();
 }
 
-static void getSessionLocation(CKSession &lsess, SessEnt &se)
-{
-    QString tty;
-    QDBusReply<QString> r = lsess.call(QLatin1String("GetX11Display"));
-    if (r.isValid() && !r.value().isEmpty()) {
-        QDBusReply<QString> r2 = lsess.call(QLatin1String("GetX11DisplayDevice"));
-        tty = r2.value();
-        se.display = r.value();
-        se.tty = false;
-    } else {
-        QDBusReply<QString> r2 = lsess.call(QLatin1String("GetDisplayDevice"));
-        tty = r2.value();
-        se.display = tty;
-        se.tty = true;
-    }
-    se.vt = tty.mid(strlen("/dev/tty")).toInt();
-}
-
 #ifndef KDM_NO_SHUTDOWN
 bool
 KDisplayManager::canShutdown()
 {
     if (DMType == NewGDM || DMType == NoDM || DMType == LightDM) {
+        QDBusReply<QString> canPowerOff = SystemdManager().call(QLatin1String("CanPowerOff"));
+        if (canPowerOff.isValid())
+            return canPowerOff.value() != QLatin1String("no");
         QDBusReply<bool> canStop = CKManager().call(QLatin1String("CanStop"));
-        return (canStop.isValid() && canStop.value());
+        if (canStop.isValid())
+            return canStop.value();
+        return false;
     }
 
     if (DMType == OldKDM)
@@ -329,9 +523,21 @@
             return;
 
         if (DMType == NewGDM || DMType == NoDM || DMType == LightDM) {
-            // FIXME: entirely ignoring shutdownMode
-            CKManager().call(QLatin1String(
-                    shutdownType == KWorkSpace::ShutdownTypeReboot ? "Restart" : "Stop"));
+            // systemd supports only 2 modes:
+            // * interactive = true: brings up a PolicyKit prompt if other sessions are active
+            // * interactive = false: rejects the shutdown if other sessions are active
+            // There are no schedule or force modes.
+            // We try to map our 4 shutdown modes in the sanest way.
+            bool interactive = (shutdownMode == KWorkSpace::ShutdownModeInteractive
+                                || shutdownMode == KWorkSpace::ShutdownModeForceNow);
+            QDBusReply<QString> check = SystemdManager().call(QLatin1String(
+                    shutdownType == KWorkSpace::ShutdownTypeReboot ? "Reboot" : "PowerOff"), interactive);
+            if (!check.isValid()) {
+                // FIXME: entirely ignoring shutdownMode
+                CKManager().call(QLatin1String(
+                        shutdownType == KWorkSpace::ShutdownTypeReboot ? "Restart" : "Stop"));
+                // if even CKManager call fails, there is nothing more to be done
+            }
             return;
         }
 
@@ -406,9 +612,15 @@
     if (DMType == NewGDM || DMType == LightDM) {
         QDBusObjectPath currentSeat;
         if (getCurrentSeat(0, &currentSeat)) {
-            CKSeat seat(currentSeat);
-            if (seat.isValid()) {
-                QDBusReply<bool> r = seat.call(QLatin1String("CanActivateSessions"));
+            SystemdSeat SDseat(currentSeat);
+            if (SDseat.isValid()) {
+                QVariant prop = SDseat.property("CanMultiSession");
+                if (prop.isValid())
+                    return prop.toBool();
+            }
+            CKSeat CKseat(currentSeat);
+            if (CKseat.isValid()) {
+                QDBusReply<bool> r = CKseat.call(QLatin1String("CanActivateSessions"));
                 if (r.isValid())
                     return r.value();
             }
@@ -468,23 +680,56 @@
     if (DMType == NewGDM || DMType == LightDM) {
         QDBusObjectPath currentSession, currentSeat;
         if (getCurrentSeat(&currentSession, &currentSeat)) {
-            foreach (const QDBusObjectPath &sp, getSessionsForSeat(currentSeat)) {
-                CKSession lsess(sp);
-                if (lsess.isValid()) {
-                    SessEnt se;
-                    getSessionLocation(lsess, se);
-                    // "Warning: we haven't yet defined the allowed values for this property.
-                    // It is probably best to avoid this until we do."
-                    QDBusReply<QString> r = lsess.call(QLatin1String("GetSessionType"));
-                    if (r.value() != QLatin1String("LoginWindow")) {
-                        QDBusReply<unsigned> r2 = lsess.call(QLatin1String("GetUnixUser"));
-                        se.user = KUser(K_UID(r2.value())).loginName();
-                        se.session = "<unknown>";
+            // we'll divide the code in two branches to reduce the overhead of calls to non-existent services
+            // systemd part // preferred
+            if (QDBusConnection::systemBus().interface()->isServiceRegistered(SYSTEMD_SERVICE)) {
+                foreach (const QDBusObjectPath &sp, getSessionsForSeat(currentSeat)) {
+                    SystemdSession lsess(sp);
+                    if (lsess.isValid()) {
+                        SessEnt se;
+                        lsess.getSessionLocation(se);
+                        if ((lsess.property("Class").toString() != QLatin1String("greeter")) &&
+                                (lsess.property("State").toString() != QLatin1String("closing"))) {
+                            NumberedDBusObjectPath numberedPath = lsess.getUser();
+                            se.display = lsess.property("Display").toString();
+                            se.vt = lsess.property("VTNr").toInt();
+                            se.user = KUser(K_UID(numberedPath.num)).loginName();
+                            /* TODO:
+                             * regarding the session name in this, it IS possible to find it out - logind tracks the session leader PID
+                             * the problem is finding out the name of the process, I could come only with reading /proc/PID/comm which
+                             * doesn't seem exactly... right to me --mbriza
+                             */
+                            se.session = "<unknown>";
+                            se.self = lsess.property("Display").toString() == ::getenv("DISPLAY"); /* Bleh once again */
+                            se.tty = !lsess.property("TTY").toString().isEmpty();
+                        }
+                        list.append(se);
+                    }    
+                }
+            }
+            // ConsoleKit part
+            else if (QDBusConnection::systemBus().interface()->isServiceRegistered("org.freedesktop.ConsoleKit")) {
+                foreach (const QDBusObjectPath &sp, getSessionsForSeat(currentSeat)) {
+                    CKSession lsess(sp);
+                    if (lsess.isValid()) {
+                        SessEnt se;
+                        lsess.getSessionLocation(se);
+                        // "Warning: we haven't yet defined the allowed values for this property.
+                        // It is probably best to avoid this until we do."
+                        QDBusReply<QString> r = lsess.call(QLatin1String("GetSessionType"));
+                        if (r.value() != QLatin1String("LoginWindow")) {
+                            QDBusReply<unsigned> r2 = lsess.call(QLatin1String("GetUnixUser"));
+                            se.user = KUser(K_UID(r2.value())).loginName();
+                            se.session = "<unknown>";
+                        }
+                        se.self = (sp == currentSession);
+                        list.append(se);
                     }
-                    se.self = (sp == currentSession);
-                    list.append(se);
                 }
             }
+            else {
+                return false;
+            }
             return true;
         }
         return false;
@@ -566,16 +811,33 @@
     if (DMType == NewGDM || DMType == LightDM) {
         QDBusObjectPath currentSeat;
         if (getCurrentSeat(0, &currentSeat)) {
-            foreach (const QDBusObjectPath &sp, getSessionsForSeat(currentSeat)) {
-                CKSession lsess(sp);
-                if (lsess.isValid()) {
-                    SessEnt se;
-                    getSessionLocation(lsess, se);
-                    if (se.vt == vt) {
-                        if (se.tty) // ConsoleKit simply ignores these
-                            return false;
-                        lsess.call(QLatin1String("Activate"));
-                        return true;
+            // systemd part // preferred
+            if (QDBusConnection::systemBus().interface()->isServiceRegistered(SYSTEMD_SERVICE)) {
+                foreach (const QDBusObjectPath &sp, getSessionsForSeat(currentSeat)) {
+                    SystemdSession lsess(sp);
+                    if (lsess.isValid()) {
+                        SessEnt se;
+                        lsess.getSessionLocation(se);
+                        if (se.vt == vt) {
+                            lsess.call(SYSTEMD_SWITCH_CALL);
+                            return true;
+                        }
+                    }
+                }
+            }
+            // ConsoleKit part
+            else if (QDBusConnection::systemBus().interface()->isServiceRegistered("org.freedesktop.ConsoleKit")) {
+                foreach (const QDBusObjectPath &sp, getSessionsForSeat(currentSeat)) {
+                    CKSession lsess(sp);
+                    if (lsess.isValid()) {
+                        SessEnt se;
+                        lsess.getSessionLocation(se);
+                        if (se.vt == vt) {
+                            if (se.tty) // ConsoleKit simply ignores these
+                                return false;
+                            lsess.call(QLatin1String("Activate"));
+                            return true;
+                        }
                     }
                 }
             }