File indexing completed on 2024-04-28 05:35:31

0001 /*
0002     ksmserver - the KDE session management server
0003 
0004     SPDX-FileCopyrightText: 2000 Matthias Ettrich <ettrich@kde.org>
0005 
0006     SPDX-License-Identifier: MIT
0007 */
0008 
0009 #pragma once
0010 
0011 #define INT32 QINT32
0012 #include <X11/ICE/ICElib.h>
0013 #include <X11/Xlib.h>
0014 #include <X11/Xmd.h>
0015 extern "C" {
0016 #include <X11/SM/SM.h>
0017 #include <X11/SM/SMlib.h>
0018 }
0019 
0020 #include <fixx11h.h>
0021 
0022 #include <QDBusContext>
0023 #include <QDBusMessage>
0024 #include <QMap>
0025 #include <QObject>
0026 #include <QStringList>
0027 #include <QTime>
0028 #include <QTimer>
0029 #include <QWindow>
0030 
0031 #include <KConfigGroup>
0032 #include <kworkspace.h>
0033 
0034 class KProcess;
0035 
0036 class KSMListener;
0037 class KSMConnection;
0038 class KSMClient;
0039 
0040 class OrgKdeKWinSessionInterface;
0041 
0042 enum SMType {
0043     SM_ERROR,
0044     SM_WMCOMMAND,
0045     SM_WMSAVEYOURSELF,
0046 };
0047 struct SMData {
0048     SMType type;
0049     QStringList wmCommand;
0050     QString wmClientMachine;
0051     QString wmclass1, wmclass2;
0052 };
0053 using WindowMap = QMap<WId, SMData>;
0054 
0055 constexpr QLatin1String SESSION_PREFIX("Session: ");
0056 constexpr QLatin1String SUBSESSION_PREFIX("SubSession: ");
0057 constexpr QLatin1String SESSION_PREVIOUS_LOGOUT("saved at previous logout");
0058 constexpr QLatin1String SESSION_BY_USER("saved by user");
0059 
0060 class KSMServer : public QObject, protected QDBusContext
0061 {
0062     Q_OBJECT
0063 public:
0064     enum class InitFlag {
0065         None = 0,
0066         OnlyLocal = 1 << 0,
0067         ImmediateLockScreen = 1 << 1,
0068         NoLockScreen = 1 << 2,
0069     };
0070 
0071     Q_DECLARE_FLAGS(InitFlags, InitFlag)
0072     explicit KSMServer(InitFlags flags);
0073     ~KSMServer() override;
0074     Q_DISABLE_COPY_MOVE(KSMServer);
0075 
0076     static KSMServer *self();
0077 
0078     void *watchConnection(IceConn iceConn);
0079     void removeConnection(KSMConnection *conn);
0080 
0081     KSMClient *newClient(SmsConn);
0082     void deleteClient(KSMClient *client);
0083 
0084     // callbacks
0085     void saveYourselfDone(KSMClient *client, bool success);
0086     void interactRequest(KSMClient *client, int dialogType);
0087     void interactDone(KSMClient *client, bool cancelShutdown);
0088     void phase2Request(KSMClient *client);
0089 
0090     // error handling
0091     void ioError(IceConn iceConn);
0092 
0093     // notification
0094     void clientRegistered(const char *previousId);
0095 
0096     // public API
0097     void performLogout();
0098     void restoreSession();
0099     void setRestoreSession(const QString &sessionName);
0100     void startDefaultSession();
0101     void resetLogout();
0102 
0103 Q_SIGNALS:
0104     void logoutFinished(bool sessionClosed);
0105 
0106 public Q_SLOTS:
0107 
0108     void cleanUp();
0109 
0110 private Q_SLOTS:
0111     void newConnection(int socket);
0112     void processData(int socket);
0113 
0114     void protectionTimeout();
0115     void timeoutQuit();
0116 
0117 private:
0118     void handlePendingInteractions();
0119     void completeShutdownOrCheckpoint();
0120     void startKilling();
0121     void startKillingSubSession();
0122     void performStandardKilling();
0123     void completeKilling();
0124     void completeKillingSubSession();
0125     void signalSubSessionClosed();
0126     void cancelShutdown(KSMClient *c);
0127     void killingCompleted();
0128 
0129     void discardSession();
0130     void storeSession();
0131 
0132     void startProtection();
0133     void endProtection();
0134 
0135     void startApplication(const QStringList &command, const QString &clientMachine = QString(), const QString &userId = QString());
0136     void executeCommand(const QStringList &command);
0137 
0138     bool defaultSession() const; // empty session
0139     void setupXIOErrorHandler();
0140 
0141     void performLegacySessionSave();
0142     void storeLegacySession(KConfig *config);
0143     void restoreLegacySession(KConfig *config);
0144     void restoreLegacySessionInternal(KConfigGroup *config, char sep = ',');
0145     QStringList windowWmCommand(WId w);
0146     QString windowWmClientMachine(WId w);
0147     WId windowWmClientLeader(WId w);
0148     QByteArray windowSessionId(WId w, WId leader);
0149 
0150     void tryRestore();
0151     void startupDone();
0152 
0153     void runShutdownScripts();
0154 
0155 public Q_SLOTS: // public dbus interface
0156     bool isShuttingDown() const;
0157     QString currentSession();
0158     void saveCurrentSession();
0159     void saveCurrentSessionAs(const QString &);
0160     QStringList sessionList();
0161     void saveSubSession(const QString &name, QStringList saveAndClose, QStringList saveOnly = QStringList());
0162     void restoreSubSession(const QString &name);
0163 
0164     void openSwitchUserDialog();
0165     bool closeSession();
0166 
0167 Q_SIGNALS:
0168     void subSessionClosed();
0169     void subSessionCloseCanceled();
0170     void subSessionOpened();
0171     void sessionRestored();
0172 
0173 private:
0174     QList<KSMListener *> listener;
0175     QList<KSMClient *> clients;
0176 
0177     enum State {
0178         Idle,
0179         Restoring,
0180         Shutdown,
0181         Checkpoint,
0182         Killing,
0183         WaitingForKNotify, // shutdown
0184         ClosingSubSession,
0185         KillingSubSession,
0186         RestoringSubSession,
0187     };
0188     State state;
0189     bool saveSession;
0190     int saveType;
0191 
0192     bool clean;
0193     KSMClient *clientInteracting;
0194     QString sessionGroup;
0195     QTimer protectionTimer;
0196     QString xonCommand;
0197     // sequential startup
0198     int appsToStart;
0199 
0200     QStringList excludeApps;
0201 
0202     WindowMap legacyWindows;
0203 
0204     QDBusMessage m_restoreSessionCall;
0205 
0206     // subSession stuff
0207     QList<KSMClient *> clientsToKill;
0208     QList<KSMClient *> clientsToSave;
0209 
0210     OrgKdeKWinSessionInterface *m_kwinInterface;
0211 
0212     int sockets[2];
0213     friend bool readFromPipe(int pipe);
0214 };