1 /* 2 ksmserver - the KDE session management server 3 4 SPDX-FileCopyrightText: 2000 Matthias Ettrich <ettrich@kde.org> 5 6 SPDX-License-Identifier: MIT 7 */ 8 9 #pragma once 10 11 #define INT32 QINT32 12 #include <X11/ICE/ICElib.h> 13 #include <X11/Xlib.h> 14 #include <X11/Xmd.h> 15 extern "C" { 16 #include <X11/ICE/ICEmsg.h> 17 #include <X11/ICE/ICEproto.h> 18 #include <X11/ICE/ICEutil.h> 19 #include <X11/SM/SM.h> 20 #include <X11/SM/SMlib.h> 21 } 22 23 #include <fixx11h.h> 24 25 // needed to avoid clash with INT8 defined in X11/Xmd.h on solaris 26 #define QT_CLEAN_NAMESPACE 1 27 #include <QDBusContext> 28 #include <QDBusMessage> 29 #include <QObject> 30 #include <QStringList> 31 32 #include <KConfigGroup> 33 #include <QMap> 34 #include <QTime> 35 #include <QTimer> 36 #include <kmessagebox.h> 37 #include <kworkspace.h> 38 39 #define SESSION_PREVIOUS_LOGOUT "saved at previous logout" 40 #define SESSION_BY_USER "saved by user" 41 42 class KProcess; 43 44 class KSMListener; 45 class KSMConnection; 46 class KSMClient; 47 48 class OrgKdeKWinSessionInterface; 49 50 enum SMType { 51 SM_ERROR, 52 SM_WMCOMMAND, 53 SM_WMSAVEYOURSELF, 54 }; 55 struct SMData { 56 SMType type; 57 QStringList wmCommand; 58 QString wmClientMachine; 59 QString wmclass1, wmclass2; 60 }; 61 typedef QMap<WId, SMData> WindowMap; 62 63 class KSMServer : public QObject, protected QDBusContext 64 { 65 Q_OBJECT 66 public: 67 enum class InitFlag { 68 None = 0, 69 OnlyLocal = 1 << 0, 70 ImmediateLockScreen = 1 << 1, 71 NoLockScreen = 1 << 2, 72 }; 73 74 Q_DECLARE_FLAGS(InitFlags, InitFlag) 75 KSMServer(InitFlags flags); 76 ~KSMServer() override; 77 78 static KSMServer *self(); 79 80 void *watchConnection(IceConn iceConn); 81 void removeConnection(KSMConnection *conn); 82 83 KSMClient *newClient(SmsConn); 84 void deleteClient(KSMClient *client); 85 86 // callbacks 87 void saveYourselfDone(KSMClient *client, bool success); 88 void interactRequest(KSMClient *client, int dialogType); 89 void interactDone(KSMClient *client, bool cancelShutdown); 90 void phase2Request(KSMClient *client); 91 92 // error handling 93 void ioError(IceConn iceConn); 94 95 // notification 96 void clientRegistered(const char *previousId); 97 98 // public API 99 void performLogout(); 100 void restoreSession(); 101 void restoreSession(const QString &sessionName); 102 void startDefaultSession(); 103 void shutdown(KWorkSpace::ShutdownConfirm confirm, KWorkSpace::ShutdownType sdtype, KWorkSpace::ShutdownMode sdmode); 104 105 void setupShortcuts(); 106 107 Q_SIGNALS: 108 void logoutFinished(bool sessionClosed); 109 110 public Q_SLOTS: 111 112 void cleanUp(); 113 114 private Q_SLOTS: 115 void newConnection(int socket); 116 void processData(int socket); 117 118 void protectionTimeout(); 119 void timeoutQuit(); 120 121 void defaultLogout(); 122 void logoutWithoutConfirmation(); 123 void haltWithoutConfirmation(); 124 void rebootWithoutConfirmation(); 125 126 private: 127 void handlePendingInteractions(); 128 void completeShutdownOrCheckpoint(); 129 void startKilling(); 130 void startKillingSubSession(); 131 void performStandardKilling(); 132 void completeKilling(); 133 void completeKillingSubSession(); 134 void signalSubSessionClosed(); 135 void cancelShutdown(KSMClient *c); 136 void killingCompleted(); 137 138 void discardSession(); 139 void storeSession(); 140 141 void startProtection(); 142 void endProtection(); 143 144 void startApplication(const QStringList &command, const QString &clientMachine = QString(), const QString &userId = QString()); 145 void executeCommand(const QStringList &command); 146 147 bool defaultSession() const; // empty session 148 void setupXIOErrorHandler(); 149 150 void performLegacySessionSave(); 151 void storeLegacySession(KConfig *config); 152 void restoreLegacySession(KConfig *config); 153 void restoreLegacySessionInternal(KConfigGroup *config, char sep = ','); 154 QStringList windowWmCommand(WId w); 155 QString windowWmClientMachine(WId w); 156 WId windowWmClientLeader(WId w); 157 QByteArray windowSessionId(WId w, WId leader); 158 159 void tryRestoreNext(); 160 void startupDone(); 161 162 void runShutdownScripts(); 163 164 // public dcop interface 165 166 public Q_SLOTS: // public dcop interface 167 void logout(int, int, int); 168 bool canShutdown(); 169 bool isShuttingDown() const; 170 QString currentSession(); 171 void saveCurrentSession(); 172 void saveCurrentSessionAs(const QString &); 173 QStringList sessionList(); 174 void saveSubSession(const QString &name, QStringList saveAndClose, QStringList saveOnly = QStringList()); 175 void restoreSubSession(const QString &name); 176 177 void openSwitchUserDialog(); 178 bool closeSession(); 179 180 Q_SIGNALS: 181 void subSessionClosed(); 182 void subSessionCloseCanceled(); 183 void subSessionOpened(); 184 void sessionRestored(); 185 186 private: 187 QList<KSMListener *> listener; 188 QList<KSMClient *> clients; 189 190 enum State { 191 Idle, 192 RestoringWMSession, 193 Restoring, 194 Shutdown, 195 Checkpoint, 196 Killing, 197 WaitingForKNotify, // shutdown 198 ClosingSubSession, 199 KillingSubSession, 200 RestoringSubSession, 201 }; 202 State state; 203 bool saveSession; 204 int saveType; 205 206 bool clean; 207 KSMClient *clientInteracting; 208 QString sessionGroup; 209 QTimer protectionTimer; 210 QTimer restoreTimer; 211 QString xonCommand; 212 // sequential startup 213 int appsToStart; 214 int lastAppStarted; 215 QString lastIdStarted; 216 217 QStringList excludeApps; 218 219 WindowMap legacyWindows; 220 221 QDBusMessage m_restoreSessionCall; 222 223 // subSession stuff 224 QList<KSMClient *> clientsToKill; 225 QList<KSMClient *> clientsToSave; 226 227 OrgKdeKWinSessionInterface *m_kwinInterface; 228 229 int sockets[2]; 230 friend bool readFromPipe(int pipe); 231 }; 232