Index: kdebase-workspace-4.3.5/libs/kworkspace/kdisplaymanager.cpp =================================================================== --- kdebase-workspace-4.3.5.orig/libs/kworkspace/kdisplaymanager.cpp +++ kdebase-workspace-4.3.5/libs/kworkspace/kdisplaymanager.cpp @@ -23,8 +23,9 @@ #include #include -#include +#include +#include #include #include @@ -40,7 +41,51 @@ #include #include -static enum { Dunno, NoDM, NewKDM, OldKDM, GDM } DMType = Dunno; +class CKManager : public QDBusInterface +{ +public: + CKManager() : + QDBusInterface( + QLatin1String("org.freedesktop.ConsoleKit"), + QLatin1String("/org/freedesktop/ConsoleKit/Manager"), + QLatin1String("org.freedesktop.ConsoleKit.Manager"), + QDBusConnection::systemBus()) {} +}; + +class CKSeat : public QDBusInterface +{ +public: + CKSeat(const QDBusObjectPath &path) : + QDBusInterface( + QLatin1String("org.freedesktop.ConsoleKit"), + path.path(), + QLatin1String("org.freedesktop.ConsoleKit.Seat"), + QDBusConnection::systemBus()) {} +}; + +class CKSession : public QDBusInterface +{ +public: + CKSession(const QDBusObjectPath &path) : + QDBusInterface( + QLatin1String("org.freedesktop.ConsoleKit"), + path.path(), + QLatin1String("org.freedesktop.ConsoleKit.Session"), + QDBusConnection::systemBus()) {} +}; + +class GDMFactory : public QDBusInterface +{ +public: + GDMFactory() : + QDBusInterface( + QLatin1String("org.gnome.DisplayManager"), + QLatin1String("/org/gnome/DisplayManager/LocalDisplayFactory"), + QLatin1String("org.gnome.DisplayManager.LocalDisplayFactory"), + QDBusConnection::systemBus()) {} +}; + +static enum { Dunno, NoDM, NewKDM, OldKDM, NewGDM, OldGDM } DMType = Dunno; static const char *ctl, *dpy; class KDisplayManager::Private @@ -68,7 +113,7 @@ KDisplayManager::KDisplayManager() : d(n else if ((ctl = ::getenv( "XDM_MANAGED" )) && ctl[0] == '/') DMType = OldKDM; else if (::getenv( "GDMSESSION" )) - DMType = GDM; + DMType = GDMFactory().isValid() ? NewGDM : OldGDM; else DMType = NoDM; } @@ -76,11 +121,11 @@ KDisplayManager::KDisplayManager() : d(n default: return; case NewKDM: - case GDM: + case OldGDM: if ((d->fd = ::socket( PF_UNIX, SOCK_STREAM, 0 )) < 0) return; sa.sun_family = AF_UNIX; - if (DMType == GDM) { + if (DMType == OldGDM) { strcpy( sa.sun_path, "/var/run/gdm_socket" ); if (::connect( d->fd, (struct sockaddr *)&sa, sizeof(sa) )) { strcpy( sa.sun_path, "/tmp/.gdm_socket" ); @@ -184,10 +229,72 @@ KDisplayManager::exec( const char *cmd, return ret; } +static bool getCurrentSeat(QDBusObjectPath *currentSession, QDBusObjectPath *currentSeat) +{ + CKManager man; + QDBusReply r = man.call(QLatin1String("GetCurrentSession")); + if (r.isValid()) { + CKSession sess(r.value()); + if (sess.isValid()) { + QDBusReply r2 = sess.call(QLatin1String("GetSeatId")); + if (r2.isValid()) { + if (currentSession) + *currentSession = r.value(); + *currentSeat = r2.value(); + return true; + } + } + } + return false; +} + +static QList getSessionsForSeat(const QDBusObjectPath &path) +{ + CKSeat seat(path); + if (seat.isValid()) { + QDBusReply > 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(); +} + +static void getSessionLocation(CKSession &lsess, SessEnt &se) +{ + QString tty; + QDBusReply r = lsess.call(QLatin1String("GetX11Display")); + if (r.isValid() && !r.value().isEmpty()) { + QDBusReply r2 = lsess.call(QLatin1String("GetX11DisplayDevice")); + tty = r2.value(); + se.display = r.value(); + se.tty = false; + } else { + QDBusReply 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) { + // WILL: This method does not exist in CK 0.2.10!! + QDBusReply canStop = CKManager().call(QLatin1String("CanStop")); + return (canStop.isValid() && canStop.value()); + } + + if (DMType == NoDM) { // No DM or newest GDM running, we'll try shutting down through ConsoleKit. QDBusConnection systemBus = QDBusConnection::systemBus(); @@ -212,7 +319,7 @@ KDisplayManager::canShutdown() QByteArray re; - if (DMType == GDM) + if (DMType == OldGDM) return exec( "QUERY_LOGOUT_ACTION\n", re ) && re.indexOf( "HALT" ) >= 0; return exec( "caps\n", re ) && re.indexOf( "\tshutdown" ) >= 0; @@ -248,13 +355,21 @@ KDisplayManager::shutdown( KWorkSpace::S } else { if (!bootOption.isEmpty()) return; + + if (DMType == NewGDM) { + // FIXME: entirely ignoring shutdownMode + CKManager().call(QLatin1String( + shutdownType == KWorkSpace::ShutdownTypeReboot ? "Restart" : "Stop")); + return; + } + cap_ask = false; } if (!cap_ask && shutdownMode == KWorkSpace::ShutdownModeInteractive) shutdownMode = KWorkSpace::ShutdownModeForceNow; QByteArray cmd; - if (DMType == GDM) { + if (DMType == OldGDM) { cmd.append( shutdownMode == KWorkSpace::ShutdownModeForceNow ? "SET_LOGOUT_ACTION " : "SET_SAFE_LOGOUT_ACTION " ); cmd.append( shutdownType == KWorkSpace::ShutdownTypeReboot ? @@ -304,21 +419,35 @@ KDisplayManager::bootOptions( QStringLis return true; } #endif // KDM_NO_SHUTDOWN +// This only tells KDM to not auto-re-login upon session crash void KDisplayManager::setLock( bool on ) { - if (DMType != GDM) + if (DMType != NewKDM || DMType == OldKDM) exec( on ? "lock\n" : "unlock\n" ); } bool KDisplayManager::isSwitchable() { + if (DMType == NewGDM) { + QDBusObjectPath currentSeat; + if (getCurrentSeat(0, ¤tSeat)) { + CKSeat seat(currentSeat); + if (seat.isValid()) { + QDBusReply r = seat.call(QLatin1String("CanActivateSessions")); + if (r.isValid()) + return r.value(); + } + } + return false; + } + if (DMType == OldKDM) return dpy[0] == ':'; - if (DMType == GDM) + if (DMType == OldGDM) return exec( "QUERY_VT\n" ); QByteArray re; @@ -329,7 +458,7 @@ KDisplayManager::isSwitchable() int KDisplayManager::numReserve() { - if (DMType == GDM) + if (DMType == NewGDM || DMType == OldGDM) return 1; /* Bleh */ if (DMType == OldKDM) @@ -346,7 +475,10 @@ KDisplayManager::numReserve() void KDisplayManager::startReserve() { - if (DMType == GDM) + if (DMType == NewGDM) + GDMFactory().call(QLatin1String("CreateTransientDisplay")); + + else if (DMType == OldGDM) exec("FLEXI_XSERVER\n"); else exec("reserve\n"); @@ -355,12 +487,47 @@ KDisplayManager::startReserve() bool KDisplayManager::localSessions( SessList &list ) { - if (DMType == OldKDM) + if (DMType == OldKDM) + return false; + + if (DMType == NewGDM) { + QDBusObjectPath currentSession, currentSeat; + if (getCurrentSeat(¤tSession, ¤tSeat)) { + 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 r = lsess.call(QLatin1String("GetSessionType")); + if (!r.isValid()) { + continue; + } else { + if (r.value() != QLatin1String("LoginWindow")) { + QDBusReply r2 = lsess.call(QLatin1String("GetUnixUser")); + if (!r2.isValid()) { + continue; + } else { + se.user = KUser(K_UID(r2.value())).loginName(); + se.session = ""; + } + } + } + se.self = (sp == currentSession); + list.append(se); + } + } + return true; + } return false; + } - QByteArray re; - if (DMType == GDM) { + QByteArray re; + + if (DMType == OldGDM) { if (!exec( "CONSOLE_SERVERS\n", re )) return false; const QStringList sess = QString(re.data() +3).split( QChar(';'), QString::SkipEmptyParts); @@ -434,7 +601,27 @@ KDisplayManager::sess2Str( const SessEnt bool KDisplayManager::switchVT( int vt ) { - if (DMType == GDM) + if (DMType == NewGDM) { + QDBusObjectPath currentSeat; + if (getCurrentSeat(0, ¤tSeat)) { + 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; + } + } + } + } + return false; + } + + if (DMType == OldGDM) return exec( QString("SET_VT %1\n").arg(vt).toLatin1() ); return exec( QString("activate\tvt%1\n").arg(vt).toLatin1() );