Allow the user to manually abort a stalled SaveYourself process

This partially resolves Bug 760
pull/2/head
Timothy Pearson 11 years ago
parent 1eb5bc8165
commit 08390bda6c

@ -681,6 +681,7 @@ KSMServer::KSMServer( const TQString& windowManager, const TQString& windowManag
signal(SIGINT, sighandler);
signal(SIGPIPE, SIG_IGN);
connect( &notificationTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( notificationTimeout() ) );
connect( &protectionTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( protectionTimeout() ) );
connect( &restoreTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( tryRestoreNext() ) );
connect( &shutdownTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( timeoutQuit() ) );

@ -109,6 +109,7 @@ private slots:
void restoreSessionInternal();
void restoreSessionDoneInternal();
void notificationTimeout();
void protectionTimeout();
void timeoutQuit();
void timeoutWMQuit();
@ -123,6 +124,9 @@ private slots:
void tryRestoreNext();
void startupSuspendTimeout();
void cancelShutdown();
void forceSkipSaveYourself();
private:
void handlePendingInteractions();
void completeShutdownOrCheckpoint();
@ -131,6 +135,7 @@ private:
void completeKilling();
void killWM();
void completeKillingWM();
void cancelShutdown( TQString cancellationText );
void cancelShutdown( KSMClient* c );
void killingCompleted();
@ -139,6 +144,7 @@ private:
void startProtection();
void endProtection();
void handleProtectionTimeout();
void startApplication( TQStringList command,
const TQString& clientMachine = TQString::null,
@ -214,6 +220,7 @@ private:
TQString sessionName;
TQCString launcher;
TQTimer protectionTimer;
TQTimer notificationTimer;
TQTimer restoreTimer;
TQTimer shutdownTimer;
TQString xonCommand;

@ -102,6 +102,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// If set too high running applications may be ungracefully terminated on slow machines
#define KSMSERVER_SHUTDOWN_CLIENT_UNRESPONSIVE_TIMEOUT 60000
// Time to wait before showing manual termination options
// If set too low the user may be confused by buttons briefly flashing up on the screen during an otherwise normal logout process
#define KSMSERVER_NOTIFICATION_MANUAL_OPTIONS_TIMEOUT 1000
void KSMServer::logout( int confirm, int sdtype, int sdmode )
{
shutdown( (TDEApplication::ShutdownConfirm)confirm,
@ -253,6 +257,11 @@ void KSMServer::shutdownInternal( TDEApplication::ShutdownConfirm confirm,
shutdownMode = sdmode;
bootOption = bopt;
shutdownNotifierIPDlg = 0;
shutdownNotifierIPDlg = KSMShutdownIPDlg::showShutdownIP();
if (shutdownNotifierIPDlg) {
static_cast<KSMShutdownIPDlg*>(shutdownNotifierIPDlg)->setStatusMessage(i18n("Notifying applications of logout request..."));
notificationTimer.start( KSMSERVER_NOTIFICATION_MANUAL_OPTIONS_TIMEOUT, true );
}
// shall we save the session on logout?
saveSession = ( config->readEntry( "loginMode", "restorePreviousLogout" ) == "restorePreviousLogout" );
@ -489,11 +498,13 @@ void KSMServer::handlePendingInteractions()
}
}
void KSMServer::cancelShutdown( KSMClient* c )
void KSMServer::cancelShutdown( TQString cancellationText )
{
kdDebug( 1218 ) << "Client " << c->program() << " (" << c->clientId() << ") canceled shutdown." << endl;
KNotifyClient::event( 0, "cancellogout", i18n( "Logout canceled by '%1'" ).arg( c->program()));
if (shutdownNotifierIPDlg) {
static_cast<KSMShutdownIPDlg*>(shutdownNotifierIPDlg)->closeSMDialog();
shutdownNotifierIPDlg=0;
}
KNotifyClient::event( 0, "cancellogout", cancellationText);
clientInteracting = 0;
for ( KSMClient* c = clients.first(); c; c = clients.next() ) {
SmsShutdownCancelled( c->connection() );
@ -507,6 +518,18 @@ void KSMServer::cancelShutdown( KSMClient* c )
state = Idle;
}
void KSMServer::cancelShutdown( KSMClient* c )
{
kdDebug( 1218 ) << "Client " << c->program() << " (" << c->clientId() << ") canceled shutdown." << endl;
cancelShutdown(i18n( "Logout canceled by '%1'" ).arg( c->program()));
}
void KSMServer::cancelShutdown()
{
kdDebug( 1218 ) << "User canceled shutdown." << endl;
cancelShutdown(i18n( "Logout canceled by user" ));
}
void KSMServer::startProtection()
{
protectionTimer.start( KSMSERVER_SHUTDOWN_CLIENT_UNRESPONSIVE_TIMEOUT, true );
@ -526,6 +549,30 @@ void KSMServer::protectionTimeout()
if ( ( state != Shutdown && state != Checkpoint ) || clientInteracting )
return;
handleProtectionTimeout();
startProtection();
}
void KSMServer::forceSkipSaveYourself()
{
SHUTDOWN_MARKER("forceSkipSaveYourself");
handleProtectionTimeout();
startProtection();
}
void KSMServer::handleProtectionTimeout()
{
SHUTDOWN_MARKER("handleProtectionTimeout");
notificationTimer.stop();
static_cast<KSMShutdownIPDlg*>(shutdownNotifierIPDlg)->hideNotificationActionButtons();
disconnect(shutdownNotifierIPDlg, SIGNAL(abortLogoutClicked()), this, SLOT(cancelShutdown()));
disconnect(shutdownNotifierIPDlg, SIGNAL(skipNotificationClicked()), this, SLOT(forceSkipSaveYourself()));
static_cast<KSMShutdownIPDlg*>(shutdownNotifierIPDlg)->setStatusMessage(i18n("Forcing interacting application termination").append("..."));
for ( KSMClient* c = clients.first(); c; c = clients.next() ) {
if ( !c->saveYourselfDone && !c->waitForPhase2 ) {
kdDebug( 1218 ) << "protectionTimeout: client " << c->program() << "(" << c->clientId() << ")" << endl;
@ -533,18 +580,27 @@ void KSMServer::protectionTimeout()
}
}
completeShutdownOrCheckpoint();
startProtection();
}
void KSMServer::notificationTimeout()
{
// Display the buttons in the logout dialog
connect(shutdownNotifierIPDlg, SIGNAL(abortLogoutClicked()), this, SLOT(cancelShutdown()));
connect(shutdownNotifierIPDlg, SIGNAL(skipNotificationClicked()), this, SLOT(forceSkipSaveYourself()));
static_cast<KSMShutdownIPDlg*>(shutdownNotifierIPDlg)->showNotificationActionButtons();
}
void KSMServer::completeShutdownOrCheckpoint()
{
SHUTDOWN_MARKER("completeShutdownOrCheckpoint");
if ( state != Shutdown && state != Checkpoint ) {
SHUTDOWN_MARKER("completeShutdownOrCheckpoint state not Shutdown or Checkpoint");
return;
}
for ( KSMClient* c = clients.first(); c; c = clients.next() ) {
if ( !c->saveYourselfDone && !c->waitForPhase2 ) {
SHUTDOWN_MARKER("completeShutdownOrCheckpoint state not done yet");
return; // not done yet
}
}
@ -559,6 +615,11 @@ void KSMServer::completeShutdownOrCheckpoint()
}
}
if ( waitForPhase2 ) {
SHUTDOWN_MARKER("completeShutdownOrCheckpoint state still waiting for Phase 2");
if (shutdownNotifierIPDlg) {
static_cast<KSMShutdownIPDlg*>(shutdownNotifierIPDlg)->setStatusMessage(i18n("Notifying remaining applications of logout request..."));
notificationTimer.start( KSMSERVER_NOTIFICATION_MANUAL_OPTIONS_TIMEOUT, true );
}
return;
}
SHUTDOWN_MARKER("Phase 2 complete");
@ -566,12 +627,19 @@ void KSMServer::completeShutdownOrCheckpoint()
bool showLogoutStatusDlg = TDEConfigGroup(TDEGlobal::config(), "Logout").readBoolEntry("showLogoutStatusDlg", true);
if (showLogoutStatusDlg && state != Checkpoint) {
KSMShutdownIPFeedback::showit(); // hide the UGLY logout process from the user
shutdownNotifierIPDlg = KSMShutdownIPDlg::showShutdownIP();
if (!shutdownNotifierIPDlg) {
shutdownNotifierIPDlg = KSMShutdownIPDlg::showShutdownIP();
}
while (!KSMShutdownIPFeedback::ispainted()) {
tqApp->processEvents();
}
}
notificationTimer.stop();
static_cast<KSMShutdownIPDlg*>(shutdownNotifierIPDlg)->hideNotificationActionButtons();
disconnect(shutdownNotifierIPDlg, SIGNAL(abortLogoutClicked()), this, SLOT(cancelShutdown()));
disconnect(shutdownNotifierIPDlg, SIGNAL(skipNotificationClicked()), this, SLOT(forceSkipSaveYourself()));
// synchronize any folders that were requested for shutdown sync
if (shutdownNotifierIPDlg) {
static_cast<KSMShutdownIPDlg*>(shutdownNotifierIPDlg)->setStatusMessage(i18n("Synchronizing remote folders").append("..."));

@ -1201,14 +1201,39 @@ TQWidget* KSMShutdownIPDlg::showShutdownIP()
return l;
}
void KSMShutdownIPDlg::showNotificationActionButtons()
{
m_button1->show();
m_button2->show();
m_buttonframe->show();
m_gridlayout->invalidate();
}
void KSMShutdownIPDlg::hideNotificationActionButtons()
{
m_button1->hide();
m_button2->hide();
m_buttonframe->hide();
m_gridlayout->invalidate();
}
KSMShutdownIPDlg::KSMShutdownIPDlg(TQWidget* parent)
: KSMModalDialog( parent )
{
setStatusMessage(i18n("Saving your settings..."));
m_button1->setText(i18n("Skip Notification"));
m_button2->setText(i18n("Abort Logout"));
connect(m_button1, SIGNAL(clicked()), this, SIGNAL(skipNotificationClicked()));
connect(m_button2, SIGNAL(clicked()), this, SIGNAL(abortLogoutClicked()));
show();
setActiveWindow();
// KWin::setOnAllDesktops( winId(), true );
}
KSMShutdownIPDlg::~KSMShutdownIPDlg()

@ -171,6 +171,13 @@ class KSMShutdownIPDlg : public KSMModalDialog
public:
static TQWidget* showShutdownIP();
void showNotificationActionButtons();
void hideNotificationActionButtons();
signals:
void abortLogoutClicked();
void skipNotificationClicked();
protected:
~KSMShutdownIPDlg();

Loading…
Cancel
Save