Changeset View
Changeset View
Standalone View
Standalone View
ksmserver/shutdown.cpp
Show First 20 Lines • Show All 71 Lines • ▼ Show 20 Line(s) | |||||
72 | #include <KUserTimestamp> | 72 | #include <KUserTimestamp> | ||
73 | #include <KNotification> | 73 | #include <KNotification> | ||
74 | #include <kdisplaymanager.h> | 74 | #include <kdisplaymanager.h> | ||
75 | #include "server.h" | 75 | #include "server.h" | ||
76 | #include "global.h" | 76 | #include "global.h" | ||
77 | #include "client.h" | 77 | #include "client.h" | ||
78 | 78 | | |||
79 | #include <solid/powermanagement.h> | 79 | #include <solid/powermanagement.h> | ||
80 | #include "logoutprompt_interface.h" | ||||
80 | 81 | | |||
81 | #include <QDesktopWidget> | 82 | #include <QDesktopWidget> | ||
82 | #include <QX11Info> | 83 | #include <QX11Info> | ||
83 | #include <X11/Xutil.h> | 84 | #include <X11/Xutil.h> | ||
84 | #include <X11/Xatom.h> | 85 | #include <X11/Xatom.h> | ||
85 | 86 | | |||
86 | void KSMServer::logout( int confirm, int sdtype, int sdmode ) | 87 | void KSMServer::logout( int confirm, int sdtype, int sdmode ) | ||
87 | { | 88 | { | ||
Show All 15 Lines | 99 | { | |||
103 | return cg.readEntry( "offerShutdown", true ) && KDisplayManager().canShutdown(); | 104 | return cg.readEntry( "offerShutdown", true ) && KDisplayManager().canShutdown(); | ||
104 | } | 105 | } | ||
105 | 106 | | |||
106 | bool KSMServer::isShuttingDown() const | 107 | bool KSMServer::isShuttingDown() const | ||
107 | { | 108 | { | ||
108 | return state >= Shutdown; | 109 | return state >= Shutdown; | ||
109 | } | 110 | } | ||
110 | 111 | | |||
111 | bool readFromPipe(int pipe) | | |||
112 | { | | |||
113 | QFile readPipe; | | |||
114 | if (!readPipe.open(pipe, QIODevice::ReadOnly)) { | | |||
115 | return false; | | |||
116 | } | | |||
117 | QByteArray result = readPipe.readLine(); | | |||
118 | if (result.isEmpty()) { | | |||
119 | return false; | | |||
120 | } | | |||
121 | bool ok = false; | | |||
122 | const int number = result.toInt(&ok); | | |||
123 | if (!ok) { | | |||
124 | return false; | | |||
125 | } | | |||
126 | KSMServer::self()->shutdownType = KWorkSpace::ShutdownType(number); | | |||
127 | | ||||
128 | return true; | | |||
129 | } | | |||
130 | | ||||
131 | void KSMServer::shutdown( KWorkSpace::ShutdownConfirm confirm, | 112 | void KSMServer::shutdown( KWorkSpace::ShutdownConfirm confirm, | ||
132 | KWorkSpace::ShutdownType sdtype, KWorkSpace::ShutdownMode sdmode ) | 113 | KWorkSpace::ShutdownType sdtype, KWorkSpace::ShutdownMode sdmode ) | ||
133 | { | 114 | { | ||
134 | qCDebug(KSMSERVER) << "Shutdown called with confirm " << confirm | 115 | qCDebug(KSMSERVER) << "Shutdown called with confirm " << confirm | ||
135 | << " type " << sdtype << " and mode " << sdmode; | 116 | << " type " << sdtype << " and mode " << sdmode; | ||
136 | pendingShutdown.stop(); | 117 | pendingShutdown.stop(); | ||
137 | if( dialogActive ) | | |||
138 | return; | | |||
139 | if( state >= Shutdown ) // already performing shutdown | 118 | if( state >= Shutdown ) // already performing shutdown | ||
140 | return; | 119 | return; | ||
141 | if( state != Idle ) // performing startup | 120 | if( state != Idle ) // performing startup | ||
142 | { | 121 | { | ||
143 | // perform shutdown as soon as startup is finished, in order to avoid saving partial session | 122 | // perform shutdown as soon as startup is finished, in order to avoid saving partial session | ||
144 | if( !pendingShutdown.isActive()) | 123 | if( !pendingShutdown.isActive()) | ||
145 | { | 124 | { | ||
146 | pendingShutdown.start( 1000 ); | 125 | pendingShutdown.start( 1000 ); | ||
147 | pendingShutdown_confirm = confirm; | 126 | pendingShutdown_confirm = confirm; | ||
148 | pendingShutdown_sdtype = sdtype; | 127 | pendingShutdown_sdtype = sdtype; | ||
149 | pendingShutdown_sdmode = sdmode; | 128 | pendingShutdown_sdmode = sdmode; | ||
150 | } | 129 | } | ||
151 | return; | 130 | return; | ||
152 | } | 131 | } | ||
153 | 132 | | |||
154 | KSharedConfig::Ptr config = KSharedConfig::openConfig(); | 133 | KSharedConfig::Ptr config = KSharedConfig::openConfig(); | ||
155 | config->reparseConfiguration(); // config may have changed in the KControl module | 134 | config->reparseConfiguration(); // config may have changed in the KControl module | ||
156 | 135 | | |||
157 | KConfigGroup cg( config, "General"); | 136 | KConfigGroup cg( config, "General"); | ||
158 | 137 | | |||
159 | bool logoutConfirmed = | 138 | bool logoutConfirmed = | ||
160 | (confirm == KWorkSpace::ShutdownConfirmYes) ? false : | 139 | (confirm == KWorkSpace::ShutdownConfirmYes) ? false : | ||
161 | (confirm == KWorkSpace::ShutdownConfirmNo) ? true : | 140 | (confirm == KWorkSpace::ShutdownConfirmNo) ? true : | ||
162 | !cg.readEntry( "confirmLogout", true ); | 141 | !cg.readEntry( "confirmLogout", true ); | ||
163 | bool choose = false; | 142 | | ||
164 | bool maysd = false; | | |||
165 | if (cg.readEntry( "offerShutdown", true ) && KDisplayManager().canShutdown()) | | |||
166 | maysd = true; | | |||
167 | if (!maysd) { | | |||
168 | if (sdtype != KWorkSpace::ShutdownTypeNone && | | |||
169 | sdtype != KWorkSpace::ShutdownTypeDefault && | | |||
170 | logoutConfirmed) | | |||
171 | return; /* unsupported fast shutdown */ | | |||
172 | sdtype = KWorkSpace::ShutdownTypeNone; | | |||
173 | } else if (sdtype == KWorkSpace::ShutdownTypeDefault) { | | |||
174 | sdtype = (KWorkSpace::ShutdownType) | | |||
175 | cg.readEntry( "shutdownType", (int)KWorkSpace::ShutdownTypeNone ); | | |||
176 | choose = true; | | |||
177 | } | | |||
178 | if (sdmode == KWorkSpace::ShutdownModeDefault) | | |||
179 | sdmode = KWorkSpace::ShutdownModeInteractive; | | |||
180 | | ||||
181 | qCDebug(KSMSERVER) << "After modifications confirm is " << confirm | | |||
182 | << " type is " << sdtype << " and mode " << sdmode; | | |||
183 | QString bopt; | | |||
184 | if ( !logoutConfirmed ) { | 143 | if (!logoutConfirmed) { | ||
185 | int pipeFds[2]; | 144 | OrgKdeLogoutPromptInterface logoutPrompt(QStringLiteral("org.kde.LogoutPrompt"), | ||
186 | if (pipe(pipeFds) != 0) { | 145 | QStringLiteral("/LogoutPrompt"), | ||
187 | return; | 146 | QDBusConnection::sessionBus()); | ||
188 | } | | |||
189 | QProcess *p = new QProcess(this); | | |||
190 | p->setProgram(QStringLiteral(LOGOUT_GREETER_BIN)); | | |||
191 | QStringList arguments; | | |||
192 | if (maysd) { | | |||
193 | arguments << QStringLiteral("--shutdown-allowed"); | | |||
194 | } | | |||
195 | if (choose) { | | |||
196 | arguments << QStringLiteral("--choose"); | | |||
197 | } | | |||
198 | if (sdtype != KWorkSpace::ShutdownTypeDefault) { | | |||
199 | arguments << QStringLiteral("--mode"); | | |||
200 | switch (sdtype) { | 147 | switch (sdtype) { | ||
201 | case KWorkSpace::ShutdownTypeHalt: | 148 | case KWorkSpace::ShutdownTypeHalt: | ||
202 | arguments << QStringLiteral("shutdown"); | 149 | logoutPrompt.promptShutDown(); | ||
203 | break; | 150 | break; | ||
204 | case KWorkSpace::ShutdownTypeReboot: | 151 | case KWorkSpace::ShutdownTypeReboot: | ||
205 | arguments << QStringLiteral("reboot"); | 152 | logoutPrompt.promptReboot(); | ||
206 | break; | | |||
207 | case KWorkSpace::ShutdownTypeNone: | | |||
208 | default: | | |||
209 | // logout | | |||
210 | arguments << QStringLiteral("logout"); | | |||
211 | break; | | |||
212 | } | | |||
213 | } | | |||
214 | arguments << QStringLiteral("--mode-fd"); | | |||
215 | arguments << QString::number(pipeFds[1]); | | |||
216 | p->setArguments(arguments); | | |||
217 | | ||||
218 | const int resultPipe = pipeFds[0]; | | |||
219 | connect(p, static_cast<void (QProcess::*)(QProcess::ProcessError)>(&QProcess::error), this, | | |||
220 | [this, resultPipe, sdmode, sdtype] { | | |||
221 | close(resultPipe); | | |||
222 | dialogActive = false; | | |||
223 | auto fallbackPrompt = new QMessageBox; | | |||
224 | fallbackPrompt->setAttribute(Qt::WA_DeleteOnClose, true); | | |||
225 | fallbackPrompt->setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); | | |||
226 | switch (sdtype) { | | |||
227 | case KWorkSpace::ShutdownTypeHalt: | | |||
228 | //i18nd is used as this patch was backported to an LTS with stable translations | | |||
229 | fallbackPrompt->setText(i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Shutdown")); | | |||
230 | break; | | |||
231 | case KWorkSpace::ShutdownTypeReboot: | | |||
232 | fallbackPrompt->setText(i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Reboot")); | | |||
233 | break; | 153 | break; | ||
234 | case KWorkSpace::ShutdownTypeNone: | 154 | case KWorkSpace::ShutdownTypeNone: | ||
235 | Q_FALLTHROUGH(); | 155 | Q_FALLTHROUGH(); | ||
236 | default: | 156 | default: | ||
237 | fallbackPrompt->setText(i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Logout")); | 157 | logoutPrompt.promptLogout(); | ||
238 | break; | 158 | break; | ||
239 | } | 159 | } | ||
240 | connect(fallbackPrompt, &QMessageBox::buttonClicked, this, [=](QAbstractButton *button) { | | |||
241 | if (button != fallbackPrompt->button(QMessageBox::Ok)) { | | |||
242 | return; | | |||
243 | } | | |||
244 | shutdownType = sdtype; | | |||
245 | shutdownMode = sdmode; | | |||
246 | bootOption = QString(); | | |||
247 | performLogout(); | | |||
248 | }); | | |||
249 | fallbackPrompt->show(); | | |||
250 | } | | |||
251 | ); | | |||
252 | | ||||
253 | connect(p, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this, | | |||
254 | [this, resultPipe, sdmode, p] (int exitCode) { | | |||
255 | p->deleteLater(); | | |||
256 | dialogActive = false; | | |||
257 | if (exitCode != 0) { | | |||
258 | close(resultPipe); | | |||
259 | return; | | |||
260 | } | | |||
261 | QFutureWatcher<bool> *watcher = new QFutureWatcher<bool>(); | | |||
262 | QObject::connect(watcher, &QFutureWatcher<bool>::finished, this, | | |||
263 | [this, sdmode, watcher] { | | |||
264 | const bool result = watcher->result(); | | |||
265 | if (!result) { | | |||
266 | // it failed to read, don't logout | | |||
267 | return; | | |||
268 | } | | |||
269 | shutdownMode = sdmode; | | |||
270 | bootOption = QString(); | | |||
271 | performLogout(); | | |||
272 | }, Qt::QueuedConnection); | | |||
273 | QObject::connect(watcher, &QFutureWatcher<void>::finished, watcher, &QFutureWatcher<bool>::deleteLater, Qt::QueuedConnection); | | |||
274 | watcher->setFuture(QtConcurrent::run(readFromPipe, resultPipe)); | | |||
275 | } | | |||
276 | ); | | |||
277 | | ||||
278 | dialogActive = true; | | |||
279 | p->start(); | | |||
280 | close(pipeFds[1]); | | |||
281 | } else { | 160 | } else { | ||
282 | shutdownType = sdtype; | 161 | shutdownType = sdtype; | ||
283 | shutdownMode = sdmode; | 162 | shutdownMode = sdmode; | ||
284 | bootOption = bopt; | | |||
285 | | ||||
286 | performLogout(); | 163 | performLogout(); | ||
287 | } | 164 | } | ||
288 | } | 165 | } | ||
289 | 166 | | |||
290 | void KSMServer::performLogout() | 167 | void KSMServer::performLogout() | ||
291 | { | 168 | { | ||
292 | // If the logout was confirmed, let's start a powermanagement inhibition. | 169 | // If the logout was confirmed, let's start a powermanagement inhibition. | ||
293 | // We store the cookie so we can interrupt it if the logout will be canceled | 170 | // We store the cookie so we can interrupt it if the logout will be canceled | ||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Line(s) | 194 | #endif | |||
344 | } else { // no WM, simply start them all | 221 | } else { // no WM, simply start them all | ||
345 | foreach( KSMClient* c, clients ) | 222 | foreach( KSMClient* c, clients ) | ||
346 | SmsSaveYourself( c->connection(), saveType, | 223 | SmsSaveYourself( c->connection(), saveType, | ||
347 | true, SmInteractStyleAny, false ); | 224 | true, SmInteractStyleAny, false ); | ||
348 | } | 225 | } | ||
349 | qCDebug(KSMSERVER) << "clients should be empty, " << clients.isEmpty(); | 226 | qCDebug(KSMSERVER) << "clients should be empty, " << clients.isEmpty(); | ||
350 | if ( clients.isEmpty() ) | 227 | if ( clients.isEmpty() ) | ||
351 | completeShutdownOrCheckpoint(); | 228 | completeShutdownOrCheckpoint(); | ||
352 | dialogActive = false; | | |||
353 | } | 229 | } | ||
354 | 230 | | |||
355 | void KSMServer::pendingShutdownTimeout() | 231 | void KSMServer::pendingShutdownTimeout() | ||
356 | { | 232 | { | ||
357 | shutdown( pendingShutdown_confirm, pendingShutdown_sdtype, pendingShutdown_sdmode ); | 233 | shutdown( pendingShutdown_confirm, pendingShutdown_sdtype, pendingShutdown_sdmode ); | ||
358 | } | 234 | } | ||
359 | 235 | | |||
360 | void KSMServer::saveCurrentSession() | 236 | void KSMServer::saveCurrentSession() | ||
361 | { | 237 | { | ||
362 | if ( state != Idle || dialogActive ) | 238 | if ( state != Idle ) | ||
363 | return; | 239 | return; | ||
364 | 240 | | |||
365 | if ( currentSession().isEmpty() || currentSession() == QString::fromLocal8Bit( SESSION_PREVIOUS_LOGOUT ) ) | 241 | if ( currentSession().isEmpty() || currentSession() == QString::fromLocal8Bit( SESSION_PREVIOUS_LOGOUT ) ) | ||
366 | sessionGroup = QStringLiteral("Session: ") + QString::fromLocal8Bit( SESSION_BY_USER ); | 242 | sessionGroup = QStringLiteral("Session: ") + QString::fromLocal8Bit( SESSION_BY_USER ); | ||
367 | 243 | | |||
368 | state = Checkpoint; | 244 | state = Checkpoint; | ||
369 | wmPhase1WaitingCount = 0; | 245 | wmPhase1WaitingCount = 0; | ||
370 | saveType = SmSaveLocal; | 246 | saveType = SmSaveLocal; | ||
Show All 16 Lines | 262 | foreach( KSMClient* c, clients ) | |||
387 | SmsSaveYourself( c->connection(), saveType, false, SmInteractStyleNone, false ); | 263 | SmsSaveYourself( c->connection(), saveType, false, SmInteractStyleNone, false ); | ||
388 | } | 264 | } | ||
389 | if ( clients.isEmpty() ) | 265 | if ( clients.isEmpty() ) | ||
390 | completeShutdownOrCheckpoint(); | 266 | completeShutdownOrCheckpoint(); | ||
391 | } | 267 | } | ||
392 | 268 | | |||
393 | void KSMServer::saveCurrentSessionAs( const QString &session ) | 269 | void KSMServer::saveCurrentSessionAs( const QString &session ) | ||
394 | { | 270 | { | ||
395 | if ( state != Idle || dialogActive ) | 271 | if ( state != Idle ) | ||
396 | return; | 272 | return; | ||
397 | sessionGroup = QStringLiteral( "Session: " ) + session; | 273 | sessionGroup = QStringLiteral( "Session: " ) + session; | ||
398 | saveCurrentSession(); | 274 | saveCurrentSession(); | ||
399 | } | 275 | } | ||
400 | 276 | | |||
401 | // callbacks | 277 | // callbacks | ||
402 | void KSMServer::saveYourselfDone( KSMClient* client, bool success ) | 278 | void KSMServer::saveYourselfDone( KSMClient* client, bool success ) | ||
403 | { | 279 | { | ||
▲ Show 20 Lines • Show All 414 Lines • Show Last 20 Lines |