// callbacks void KSMServer::saveYourselfDone( KSMClient* client, bool success ) { if ( state == Idle ) { // State saving when it's not shutdown or checkpoint. Probably // a shutdown was cancelled and the client is finished saving // only now. Discard the saved state in order to avoid // the saved data building up. QStringList discard = client->discardCommand(); if( !discard.isEmpty()) executeCommand( discard ); return; } if ( success ) { client->saveYourselfDone = true; completeShutdownOrCheckpoint(); } else { // fake success to make KDE's logout not block with broken // apps. A perfect ksmserver would display a warning box at // the very end. client->saveYourselfDone = true; completeShutdownOrCheckpoint(); } startProtection(); if( isWM( client ) && !client->wasPhase2 && wmPhase1WaitingCount > 0 ) { --wmPhase1WaitingCount; // WM finished its phase1, save the rest if( wmPhase1WaitingCount == 0 ) { for ( KSMClient* c = clients.first(); c; c = clients.next() ) if( !isWM( c )) SmsSaveYourself( c->connection(), saveType, saveType != SmSaveLocal, saveType != SmSaveLocal ? SmInteractStyleAny : SmInteractStyleNone, false ); } } }
void KSMServer::saveCurrentSession() { if ( state != Idle || dialogActive ) return; if ( currentSession().isEmpty() || currentSession() == SESSION_PREVIOUS_LOGOUT ) sessionGroup = QString("Session: ") + SESSION_BY_USER; state = Checkpoint; wmPhase1WaitingCount = 0; saveType = SmSaveLocal; saveSession = true; performLegacySessionSave(); for ( KSMClient* c = clients.first(); c; c = clients.next() ) { c->resetState(); if( isWM( c )) { ++wmPhase1WaitingCount; SmsSaveYourself( c->connection(), saveType, false, SmInteractStyleNone, false ); } } if( wmPhase1WaitingCount == 0 ) { for ( KSMClient* c = clients.first(); c; c = clients.next() ) SmsSaveYourself( c->connection(), saveType, false, SmInteractStyleNone, false ); } if ( clients.isEmpty() ) completeShutdownOrCheckpoint(); }
/* Internal protection slot, invoked when clients do not react during shutdown. */ void KSMServer::protectionTimeout() { if ( ( state != Shutdown && state != Checkpoint ) || clientInteracting ) return; for ( KSMClient* c = clients.first(); c; c = clients.next() ) { if ( !c->saveYourselfDone && !c->waitForPhase2 ) { kdDebug( 1218 ) << "protectionTimeout: client " << c->program() << "(" << c->clientId() << ")" << endl; c->saveYourselfDone = true; } } completeShutdownOrCheckpoint(); startProtection(); }
void KSMServer::phase2Request( KSMClient* client ) { client->waitForPhase2 = true; client->wasPhase2 = true; completeShutdownOrCheckpoint(); if( isWM( client ) && wmPhase1WaitingCount > 0 ) { --wmPhase1WaitingCount; // WM finished its phase1 and requests phase2, save the rest if( wmPhase1WaitingCount == 0 ) { for ( KSMClient* c = clients.first(); c; c = clients.next() ) if( !isWM( c )) SmsSaveYourself( c->connection(), saveType, saveType != SmSaveLocal, saveType != SmSaveLocal ? SmInteractStyleAny : SmInteractStyleNone, false ); } } }
void KSMServer::deleteClient( KSMClient* client ) { if ( !clients.contains( client ) ) // paranoia return; clients.removeAll( client ); clientsToKill.removeAll( client ); clientsToSave.removeAll( client ); if ( client == clientInteracting ) { clientInteracting = 0; handlePendingInteractions(); } delete client; if ( state == Shutdown || state == Checkpoint || state == ClosingSubSession ) completeShutdownOrCheckpoint(); if ( state == Killing ) completeKilling(); else if ( state == KillingSubSession ) completeKillingSubSession(); if ( state == KillingWM ) completeKillingWM(); }
void KSMServer::shutdown( KApplication::ShutdownConfirm confirm, KApplication::ShutdownType sdtype, KApplication::ShutdownMode sdmode ) { pendingShutdown.stop(); if( dialogActive ) return; if( state >= Shutdown ) // already performing shutdown return; if( state != Idle ) // performing startup { // perform shutdown as soon as startup is finished, in order to avoid saving partial session if( !pendingShutdown.isActive()) { pendingShutdown.start( 1000 ); pendingShutdown_confirm = confirm; pendingShutdown_sdtype = sdtype; pendingShutdown_sdmode = sdmode; } return; } KConfig *config = KGlobal::config(); config->reparseConfiguration(); // config may have changed in the KControl module config->setGroup("General" ); bool logoutConfirmed = (confirm == KApplication::ShutdownConfirmYes) ? false : (confirm == KApplication::ShutdownConfirmNo) ? true : !config->readBoolEntry( "confirmLogout", true ); bool maysd = false; if (config->readBoolEntry( "offerShutdown", true ) && DM().canShutdown()) maysd = true; if (!maysd) { if (sdtype != KApplication::ShutdownTypeNone && sdtype != KApplication::ShutdownTypeDefault && logoutConfirmed) return; /* unsupported fast shutdown */ sdtype = KApplication::ShutdownTypeNone; } else if (sdtype == KApplication::ShutdownTypeDefault) sdtype = (KApplication::ShutdownType) config->readNumEntry( "shutdownType", (int)KApplication::ShutdownTypeNone ); if (sdmode == KApplication::ShutdownModeDefault) sdmode = KApplication::ShutdownModeInteractive; dialogActive = true; QString bopt; if ( !logoutConfirmed ) { KSMShutdownFeedback::start(); // make the screen gray logoutConfirmed = KSMShutdownDlg::confirmShutdown( maysd, sdtype, bopt ); // ###### We can't make the screen remain gray while talking to the apps, // because this prevents interaction ("do you want to save", etc.) // TODO: turn the feedback widget into a list of apps to be closed, // with an indicator of the current status for each. KSMShutdownFeedback::stop(); // make the screen become normal again } if ( logoutConfirmed ) { shutdownType = sdtype; shutdownMode = sdmode; bootOption = bopt; // shall we save the session on logout? saveSession = ( config->readEntry( "loginMode", "restorePreviousLogout" ) == "restorePreviousLogout" ); if ( saveSession ) sessionGroup = QString("Session: ") + SESSION_PREVIOUS_LOGOUT; // Set the real desktop background to black so that exit looks // clean regardless of what was on "our" desktop. kapp->desktop()->setBackgroundColor( Qt::black ); state = Shutdown; wmPhase1WaitingCount = 0; saveType = saveSession?SmSaveBoth:SmSaveGlobal; performLegacySessionSave(); startProtection(); for ( KSMClient* c = clients.first(); c; c = clients.next() ) { c->resetState(); // Whoever came with the idea of phase 2 got it backwards // unfortunately. Window manager should be the very first // one saving session data, not the last one, as possible // user interaction during session save may alter // window positions etc. // Moreover, KWin's focus stealing prevention would lead // to undesired effects while session saving (dialogs // wouldn't be activated), so it needs be assured that // KWin will turn it off temporarily before any other // user interaction takes place. // Therefore, make sure the WM finishes its phase 1 // before others a chance to change anything. // KWin will check if the session manager is ksmserver, // and if yes it will save in phase 1 instead of phase 2. if( isWM( c )) { ++wmPhase1WaitingCount; SmsSaveYourself( c->connection(), saveType, true, SmInteractStyleAny, false ); } } if( wmPhase1WaitingCount == 0 ) { // no WM, simply start them all for ( KSMClient* c = clients.first(); c; c = clients.next() ) SmsSaveYourself( c->connection(), saveType, true, SmInteractStyleAny, false ); } if ( clients.isEmpty() ) completeShutdownOrCheckpoint(); } dialogActive = false; }