// 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(); }
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::restoreLegacySessionInternal( TDEConfig* config, char sep ) { int count = config->readNumEntry( "count" ); for ( int i = 1; i <= count; i++ ) { TQString n = TQString::number(i); TQStringList wmCommand = config->readListEntry( TQString("command")+n, sep ); if( wmCommand.isEmpty()) continue; if( isWM( wmCommand.first())) continue; startApplication( wmCommand, config->readEntry( TQString("clientMachine")+n ), config->readEntry( TQString("userId")+n )); } }
void KSMServer::completeKilling() { kdDebug( 1218 ) << "KSMServer::completeKilling clients.count()=" << clients.count() << endl; if( state == Killing ) { bool wait = false; for( KSMClient* c = clients.first(); c; c = clients.next()) { if( isWM( c )) continue; wait = true; // still waiting for clients to go away } if( wait ) return; killWM(); } }
void KSMServer::startKilling() { knotifyTimeoutTimer.stop(); // kill all clients state = Killing; for ( KSMClient* c = clients.first(); c; c = clients.next() ) { if( isWM( c )) // kill the WM as the last one in order to reduce flicker continue; kdDebug( 1218 ) << "completeShutdown: client " << c->program() << "(" << c->clientId() << ")" << endl; SmsDie( c->connection() ); } kdDebug( 1218 ) << " We killed all clients. We have now clients.count()=" << clients.count() << endl; completeKilling(); QTimer::singleShot( 10000, this, SLOT( timeoutQuit() ) ); }
void KSMServer::killWM() { state = KillingWM; bool iswm = false; for ( KSMClient* c = clients.first(); c; c = clients.next() ) { if( isWM( c )) { iswm = true; kdDebug( 1218 ) << "killWM: client " << c->program() << "(" << c->clientId() << ")" << endl; SmsDie( c->connection() ); } } if( iswm ) { completeKillingWM(); QTimer::singleShot( 5000, this, SLOT( timeoutWMQuit() ) ); } else killingCompleted(); }
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; }