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