Skip to content

Commit

Permalink
Fix user switching
Browse files Browse the repository at this point in the history
Make sure we don't start a new session if we are switching.
Update the terminalId (i.e. tty) Display property as we switch from the
greeter to the actual session, as they might be on different terminals now.

If we are reusing a session, also remember to switch to that session's tty.
This way we do not switch to a random open session. It's common to have 2
at most but we better fix it properly than hope our users have a predictable
workflow.
  • Loading branch information
aleixpol committed Feb 1, 2023
1 parent b042f69 commit 3ee57e9
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 8 deletions.
13 changes: 7 additions & 6 deletions src/daemon/Display.cpp
Expand Up @@ -67,7 +67,7 @@ namespace SDDM {
for(const SessionInfo &s : info) {
OrgFreedesktopLogin1SessionInterface session(Logind::serviceName(), s.sessionPath.path(), QDBusConnection::systemBus());
if (desiredTty == session.tTY() && session.state() != QLatin1String("closing")) {
qDebug() << "tty" << desiredTty << "already in use by" << session.user().path << session.state()
qDebug() << "tty" << desiredTty << "already in use by" << session.user().path.path() << session.state()
<< session.display() << session.desktop() << session.vTNr();
return true;
}
Expand Down Expand Up @@ -183,7 +183,7 @@ namespace SDDM {
}

const int Display::terminalId() const {
return m_terminalId;
return m_auth->isActive() ? m_sessionTerminalId : m_terminalId;
}

const QString &Display::name() const {
Expand Down Expand Up @@ -407,14 +407,14 @@ namespace SDDM {
// last session later, in slotAuthenticationFinished()
m_sessionName = session.fileName();

int terminalNewSession = m_terminalId;
int m_sessionTerminalId = m_terminalId;
if ((session.type() == Session::WaylandSession && m_displayServerType == X11DisplayServerType) || (m_greeter->isRunning() && m_displayServerType != X11DisplayServerType)) {
// Create a new VT when we need to have another compositor running
terminalNewSession = VirtualTerminal::setUpNewVt();
m_sessionTerminalId = VirtualTerminal::setUpNewVt();
}

// some information
qDebug() << "Session" << m_sessionName << "selected, command:" << session.exec() << "for VT" << terminalNewSession;
qDebug() << "Session" << m_sessionName << "selected, command:" << session.exec() << "for VT" << m_sessionTerminalId;

QProcessEnvironment env;
env.insert(session.additionalEnv());
Expand All @@ -428,7 +428,7 @@ namespace SDDM {
env.insert(QStringLiteral("XDG_SESSION_CLASS"), QStringLiteral("user"));
env.insert(QStringLiteral("XDG_SESSION_TYPE"), session.xdgSessionType());
env.insert(QStringLiteral("XDG_SEAT"), seat()->name());
env.insert(QStringLiteral("XDG_VTNR"), QString::number(terminalNewSession));
env.insert(QStringLiteral("XDG_VTNR"), QString::number(m_sessionTerminalId));
#ifdef HAVE_SYSTEMD
env.insert(QStringLiteral("XDG_SESSION_DESKTOP"), session.desktopNames());
#endif
Expand Down Expand Up @@ -457,6 +457,7 @@ namespace SDDM {
OrgFreedesktopLogin1ManagerInterface manager(Logind::serviceName(), Logind::managerPath(), QDBusConnection::systemBus());
manager.UnlockSession(m_reuseSessionId);
manager.ActivateSession(m_reuseSessionId);
m_started = true;
} else {
if (qobject_cast<XorgDisplayServer *>(m_displayServer))
m_auth->setCookie(qobject_cast<XorgDisplayServer *>(m_displayServer)->cookie());
Expand Down
2 changes: 2 additions & 0 deletions src/daemon/Display.h
Expand Up @@ -61,6 +61,7 @@ namespace SDDM {
const QString &name() const;

QString sessionType() const;
QString reuseSessionId() const { return m_reuseSessionId; }

Seat *seat() const;

Expand Down Expand Up @@ -94,6 +95,7 @@ namespace SDDM {
bool m_started { false };

int m_terminalId = 0;
int m_sessionTerminalId = 0;

QString m_passPhrase;
QString m_sessionName;
Expand Down
19 changes: 17 additions & 2 deletions src/daemon/Seat.cpp
Expand Up @@ -31,6 +31,9 @@
#include <QTimer>

#include <functional>
#include <optional>
#include <Login1Manager.h>
#include <Login1Session.h>

namespace SDDM {
Seat::Seat(const QString &name, QObject *parent) : QObject(parent), m_name(name) {
Expand Down Expand Up @@ -108,6 +111,14 @@ namespace SDDM {

void Seat::displayStopped() {
Display *display = qobject_cast<Display *>(sender());
OrgFreedesktopLogin1ManagerInterface manager(Logind::serviceName(), Logind::managerPath(), QDBusConnection::systemBus());
std::optional<int> nextVt;
auto reusing = display->reuseSessionId();
if (manager.isValid() && !reusing.isEmpty()) {
auto sessionPath = manager.GetSession(reusing);
OrgFreedesktopLogin1SessionInterface sessionIface(Logind::serviceName(), sessionPath.value().path(), QDBusConnection::systemBus());
nextVt = QStringView(sessionIface.tTY()).mid(3).toInt(); // we need to convert ttyN to N
}

// remove display
removeDisplay(display);
Expand All @@ -120,10 +131,14 @@ namespace SDDM {
// switch to last display in display vector.
// Set vt_auto to true, so let the kernel handle the
// vt switch automatically (VT_AUTO).
else {
else if (!nextVt) {
int disp = m_displays.last()->terminalId();
if (disp != -1)
VirtualTerminal::jumpToVt(disp, true);
nextVt = disp;
}

if (nextVt) {
VirtualTerminal::jumpToVt(*nextVt, true);
}
}
}

0 comments on commit 3ee57e9

Please sign in to comment.