kwin Library API Documentation

sm.cpp

00001 /*****************************************************************
00002  KWin - the KDE window manager
00003  This file is part of the KDE project.
00004 
00005 Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
00006 Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
00007 
00008 You can Freely distribute this program under the GNU General Public
00009 License. See the file "COPYING" for the exact licensing terms.
00010 ******************************************************************/
00011 
00012 #include "sm.h"
00013 
00014 #include <qsocketnotifier.h>
00015 #include <qsessionmanager.h>
00016 #include <kdebug.h>
00017 #include <unistd.h>
00018 #include <stdlib.h>
00019 #include <pwd.h>
00020 #include <fixx11h.h>
00021 #include <kconfig.h>
00022 #include <kglobal.h>
00023 
00024 #include "workspace.h"
00025 #include "client.h"
00026 
00027 namespace KWinInternal
00028 {
00029 
00030 bool SessionManaged::saveState( QSessionManager& sm )
00031     {
00032     // If the session manager is ksmserver, save stacking
00033     // order, active window, active desktop etc. in phase 1,
00034     // as ksmserver assures no interaction will be done
00035     // before the WM finishes phase 1. Saving in phase 2 is
00036     // too late, as possible user interaction may change some things.
00037     // Phase2 is still needed though (ICCCM 5.2)
00038     char* sm_vendor = SmcVendor( static_cast< SmcConn >( sm.handle()));
00039     bool ksmserver = qstrcmp( sm_vendor, "KDE" ) == 0;
00040     free( sm_vendor );
00041     if ( !sm.isPhase2() )
00042         {
00043         Workspace::self()->sessionSaveStarted();
00044         if( ksmserver ) // save stacking order etc. before "save file?" etc. dialogs change it
00045             Workspace::self()->storeSession( kapp->sessionConfig(), SMSavePhase0 );
00046         sm.release(); // Qt doesn't automatically release in this case (bug?)
00047         sm.requestPhase2();
00048         return true;
00049         }
00050     Workspace::self()->storeSession( kapp->sessionConfig(), ksmserver ? SMSavePhase2 : SMSavePhase2Full );
00051     kapp->sessionConfig()->sync();
00052     return true;
00053     }
00054 
00055 // I bet this is broken, just like everywhere else in KDE
00056 bool SessionManaged::commitData( QSessionManager& sm )
00057     {
00058     if ( !sm.isPhase2() )
00059         Workspace::self()->sessionSaveStarted();
00060     return true;
00061     }
00062 
00063 // Workspace
00064 
00070 void Workspace::storeSession( KConfig* config, SMSavePhase phase )
00071     {
00072     config->setGroup("Session" );
00073     int count =  0;
00074     int active_client = -1;
00075     for (ClientList::Iterator it = clients.begin(); it != clients.end(); ++it) 
00076         {
00077         Client* c = (*it);
00078         QCString sessionId = c->sessionId();
00079         QCString wmCommand = c->wmCommand();
00080         if ( sessionId.isEmpty() )
00081         // remember also applications that are not XSMP capable
00082         // and use the obsolete WM_COMMAND / WM_SAVE_YOURSELF
00083             if ( wmCommand.isEmpty() )
00084                 continue;
00085         count++;
00086         if( c->isActive())
00087             active_client = count;
00088         QString n = QString::number(count);
00089         if( phase == SMSavePhase2 || phase == SMSavePhase2Full )
00090             {
00091             config->writeEntry( QString("sessionId")+n, sessionId.data() );
00092             config->writeEntry( QString("windowRole")+n, c->windowRole().data() );
00093             config->writeEntry( QString("wmCommand")+n, wmCommand.data() );
00094             config->writeEntry( QString("wmClientMachine")+n, c->wmClientMachine().data() );
00095             config->writeEntry( QString("resourceName")+n, c->resourceName().data() );
00096             config->writeEntry( QString("resourceClass")+n, c->resourceClass().data() );
00097             config->writeEntry( QString("geometry")+n,  QRect( c->calculateGravitation(TRUE), c->clientSize() ) ); // FRAME
00098             config->writeEntry( QString("restore")+n, c->geometryRestore() );
00099             config->writeEntry( QString("fsrestore")+n, c->geometryFSRestore() );
00100             config->writeEntry( QString("maximize")+n, (int) c->maximizeMode() );
00101             config->writeEntry( QString("fullscreen")+n, (int) c->fullScreenMode() );
00102             config->writeEntry( QString("desktop")+n, c->desktop() );
00103             // the config entry is called "iconified" for back. comp. reasons
00104             // (kconf_update script for updating session files would be too complicated)
00105             config->writeEntry( QString("iconified")+n, c->isMinimized() );
00106             // the config entry is called "sticky" for back. comp. reasons
00107             config->writeEntry( QString("sticky")+n, c->isOnAllDesktops() );
00108             config->writeEntry( QString("shaded")+n, c->isShade() );
00109             // the config entry is called "staysOnTop" for back. comp. reasons
00110             config->writeEntry( QString("staysOnTop")+n, c->keepAbove() );
00111             config->writeEntry( QString("keepBelow")+n, c->keepBelow() );
00112             config->writeEntry( QString("skipTaskbar")+n, c->skipTaskbar( true ) );
00113             config->writeEntry( QString("skipPager")+n, c->skipPager() );
00114             config->writeEntry( QString("userNoBorder")+n, c->isUserNoBorder() );
00115             config->writeEntry( QString("windowType")+n, windowTypeToTxt( c->windowType()));
00116             }
00117         }
00118     // TODO store also stacking order
00119     if( phase == SMSavePhase0 )
00120         {
00121         // it would be much simpler to save these values to the config file,
00122         // but both Qt and KDE treat phase1 and phase2 separately,
00123         // which results in different sessionkey and different config file :(
00124         session_active_client = active_client;
00125         session_desktop = currentDesktop();
00126         }
00127     else if( phase == SMSavePhase2 )
00128         {
00129         config->writeEntry( "count", count );
00130         config->writeEntry( "active", session_active_client );
00131         config->writeEntry( "desktop", session_desktop );
00132         }
00133     else // SMSavePhase2Full
00134         {
00135         config->writeEntry( "count", count );
00136         config->writeEntry( "active", session_active_client );
00137         config->writeEntry( "desktop", currentDesktop());
00138         }
00139     }
00140 
00141 
00147 void Workspace::loadSessionInfo()
00148     {
00149     session.clear();
00150     KConfig* config = kapp->sessionConfig();
00151     config->setGroup("Session" );
00152     int count =  config->readNumEntry( "count" );
00153     int active_client = config->readNumEntry( "active" );
00154     for ( int i = 1; i <= count; i++ ) 
00155         {
00156         QString n = QString::number(i);
00157         SessionInfo* info = new SessionInfo;
00158         session.append( info );
00159         info->sessionId = config->readEntry( QString("sessionId")+n ).latin1();
00160         info->windowRole = config->readEntry( QString("windowRole")+n ).latin1();
00161         info->wmCommand = config->readEntry( QString("wmCommand")+n ).latin1();
00162         info->wmClientMachine = config->readEntry( QString("wmClientMachine")+n ).latin1();
00163         info->resourceName = config->readEntry( QString("resourceName")+n ).latin1();
00164         info->resourceClass = config->readEntry( QString("resourceClass")+n ).lower().latin1();
00165         info->geometry = config->readRectEntry( QString("geometry")+n );
00166         info->restore = config->readRectEntry( QString("restore")+n );
00167         info->fsrestore = config->readRectEntry( QString("fsrestore")+n );
00168         info->maximized = config->readNumEntry( QString("maximize")+n, 0 );
00169         info->fullscreen = config->readNumEntry( QString("fullscreen")+n, 0 );
00170         info->desktop = config->readNumEntry( QString("desktop")+n, 0 );
00171         info->minimized = config->readBoolEntry( QString("iconified")+n, FALSE );
00172         info->onAllDesktops = config->readBoolEntry( QString("sticky")+n, FALSE );
00173         info->shaded = config->readBoolEntry( QString("shaded")+n, FALSE );
00174         info->keepAbove = config->readBoolEntry( QString("staysOnTop")+n, FALSE  );
00175         info->keepBelow = config->readBoolEntry( QString("keepBelow")+n, FALSE  );
00176         info->skipTaskbar = config->readBoolEntry( QString("skipTaskbar")+n, FALSE  );
00177         info->skipPager = config->readBoolEntry( QString("skipPager")+n, FALSE  );
00178         info->userNoBorder = config->readBoolEntry( QString("userNoBorder")+n, FALSE  );
00179         info->windowType = txtToWindowType( config->readEntry( QString("windowType")+n ).latin1());
00180         info->active = ( active_client == i );
00181         info->fake = false;
00182         }
00183     }
00184 
00185 void Workspace::loadFakeSessionInfo()
00186     {
00187     fakeSession.clear();
00188     KConfig *config = KGlobal::config();
00189     config->setGroup("FakeSession" );
00190     int count =  config->readNumEntry( "count" );
00191     for ( int i = 1; i <= count; i++ ) 
00192         {
00193         QString n = QString::number(i);
00194         SessionInfo* info = new SessionInfo;
00195         fakeSession.append( info );
00196         info->windowRole = config->readEntry( QString("windowRole")+n ).latin1();
00197         info->resourceName = config->readEntry( QString("resourceName")+n ).latin1();
00198         info->resourceClass = config->readEntry( QString("resourceClass")+n ).lower().latin1();
00199         info->wmClientMachine = config->readEntry( QString("clientMachine")+n ).latin1();
00200         info->geometry = config->readRectEntry( QString("geometry")+n );
00201         info->restore = config->readRectEntry( QString("restore")+n );
00202         info->fsrestore = config->readRectEntry( QString("fsrestore")+n );
00203         info->maximized = config->readNumEntry( QString("maximize")+n, 0 );
00204         info->fullscreen = config->readNumEntry( QString("fullscreen")+n, 0 );
00205         info->desktop = config->readNumEntry( QString("desktop")+n, 0 );
00206         info->minimized = config->readBoolEntry( QString("iconified")+n, FALSE );
00207         info->onAllDesktops = config->readBoolEntry( QString("sticky")+n, FALSE );
00208         info->shaded = config->readBoolEntry( QString("shaded")+n, FALSE );
00209         info->keepAbove = config->readBoolEntry( QString("staysOnTop")+n, FALSE  );
00210         info->keepBelow = config->readBoolEntry( QString("keepBelow")+n, FALSE  );
00211         info->skipTaskbar = config->readBoolEntry( QString("skipTaskbar")+n, FALSE  );
00212         info->skipPager = config->readBoolEntry( QString("skipPager")+n, FALSE  );
00213         info->userNoBorder = config->readBoolEntry( QString("userNoBorder")+n, FALSE  );
00214         info->windowType = txtToWindowType( config->readEntry( QString("windowType")+n ).latin1());
00215         info->active = false;
00216         info->fake = true;
00217         }
00218     }
00219 
00220 void Workspace::storeFakeSessionInfo( Client* c )
00221     {
00222     if ( !c->storeSettings() )
00223         return;
00224     SessionInfo* info = new SessionInfo;
00225     fakeSession.append( info );
00226     info->windowRole = c->windowRole();
00227     info->resourceName = c->resourceName();
00228     info->resourceClass = c->resourceClass();
00229     info->wmClientMachine = c->wmClientMachine();
00230     info->geometry = QRect( c->calculateGravitation(TRUE), c->clientSize() ) ; // FRAME
00231     info->restore = c->geometryRestore();
00232     info->fsrestore = c->geometryFSRestore();
00233     info->maximized = (int)c->maximizeMode();
00234     info->fullscreen = (int)c->fullScreenMode();
00235     info->desktop = c->desktop();
00236     info->minimized = c->isMinimized();
00237     info->onAllDesktops = c->isOnAllDesktops();
00238     info->shaded = c->isShade();
00239     info->keepAbove = c->keepAbove();
00240     info->keepBelow = c->keepBelow();
00241     info->skipTaskbar = c->skipTaskbar( true );
00242     info->skipPager = c->skipPager();
00243     info->userNoBorder = c->isUserNoBorder();
00244     info->windowType = c->windowType();
00245     info->active = false;
00246     info->fake = true;
00247     }
00248 
00249 void Workspace::writeFakeSessionInfo()
00250     {
00251     KConfig *config = KGlobal::config();
00252     config->setGroup("FakeSession" );
00253     int count = 0;
00254     for ( SessionInfo* info = fakeSession.first(); info; info = fakeSession.next() ) 
00255         {
00256         count++;
00257         QString n = QString::number(count);
00258         config->writeEntry( QString("windowRole")+n, info->windowRole.data() );
00259         config->writeEntry( QString("resourceName")+n, info->resourceName.data() );
00260         config->writeEntry( QString("resourceClass")+n, info->resourceClass.data() );
00261         config->writeEntry( QString("clientMachine")+n, info->wmClientMachine.data() );
00262         config->writeEntry( QString("geometry")+n,  info->geometry );
00263         config->writeEntry( QString("restore")+n, info->restore );
00264         config->writeEntry( QString("fsrestore")+n, info->fsrestore );
00265         config->writeEntry( QString("maximize")+n, info->maximized );
00266         config->writeEntry( QString("fullscreen")+n, info->fullscreen );
00267         config->writeEntry( QString("desktop")+n, info->desktop );
00268         config->writeEntry( QString("iconified")+n, info->minimized );
00269         config->writeEntry( QString("onAllDesktops")+n, info->onAllDesktops );
00270         config->writeEntry( QString("shaded")+n, info->shaded );
00271         config->writeEntry( QString("staysOnTop")+n, info->keepAbove );
00272         config->writeEntry( QString("keepBelow")+n, info->keepBelow );
00273         config->writeEntry( QString("skipTaskbar")+n, info->skipTaskbar );
00274         config->writeEntry( QString("skipPager")+n, info->skipPager );
00275         config->writeEntry( QString("userNoBorder")+n, info->userNoBorder );
00276         config->writeEntry( QString("windowType")+n, windowTypeToTxt( info->windowType ));
00277         }
00278     config->writeEntry( "count", count );
00279     }
00280 
00292 SessionInfo* Workspace::takeSessionInfo( Client* c )
00293     {
00294     SessionInfo *realInfo = 0;
00295     SessionInfo *fakeInfo = 0;
00296     QCString sessionId = c->sessionId();
00297     QCString windowRole = c->windowRole();
00298     QCString wmCommand = c->wmCommand();
00299     QCString wmClientMachine = c->wmClientMachine();
00300     QCString resourceName = c->resourceName();
00301     QCString resourceClass = c->resourceClass();
00302 
00303     // First search ``session''
00304     if (! sessionId.isEmpty() ) 
00305         {
00306         // look for a real session managed client (algorithm suggested by ICCCM)
00307         for (SessionInfo* info = session.first(); info && !realInfo; info = session.next() )
00308             if ( info->sessionId == sessionId && sessionInfoWindowTypeMatch( c, info )) 
00309             {
00310             if ( ! windowRole.isEmpty() ) 
00311                 {
00312                 if ( info->windowRole == windowRole )
00313                     realInfo = session.take();
00314                 }
00315             else 
00316                 {
00317                 if ( info->windowRole.isEmpty() &&
00318                      info->resourceName == resourceName &&
00319                      info->resourceClass == resourceClass )
00320                     realInfo = session.take();
00321                 }
00322             }
00323         }
00324     else 
00325         {
00326         // look for a sessioninfo with matching features.
00327         for (SessionInfo* info = session.first(); info && !realInfo; info = session.next() )
00328             if ( info->resourceName == resourceName &&
00329                  info->resourceClass == resourceClass &&
00330                  info->wmClientMachine == wmClientMachine &&
00331                  sessionInfoWindowTypeMatch( c, info ))
00332                 if ( wmCommand.isEmpty() || info->wmCommand == wmCommand )
00333                     realInfo = session.take();
00334         }
00335 
00336     // Now search ``fakeSession''
00337     for (SessionInfo* info = fakeSession.first(); info && !fakeInfo; info = fakeSession.next() )
00338         if ( info->resourceName == resourceName &&
00339              info->resourceClass == resourceClass &&
00340              ( windowRole.isEmpty() || windowRole == info->windowRole ) &&
00341              sessionInfoWindowTypeMatch( c, info ))
00342             fakeInfo = fakeSession.take();
00343 
00344     // Reconciliate
00345     if (fakeInfo)
00346         c->setStoreSettings( TRUE );
00347     if (fakeInfo && realInfo)
00348         delete fakeInfo;
00349     if (realInfo)
00350         return realInfo;
00351     if (fakeInfo)
00352         return fakeInfo;
00353     return 0;
00354     }
00355 
00356 bool Workspace::sessionInfoWindowTypeMatch( Client* c, SessionInfo* info )
00357     {
00358     if( info->windowType == -2 ) 
00359         { // undefined (not really part of NET::WindowType)
00360         return !c->isSpecialWindow() || c->isOverride();
00361         }
00362     return info->windowType == c->windowType();
00363     }
00364 
00365 // maybe needed later
00366 #if 0
00367 // KMainWindow's without name() given have WM_WINDOW_ROLE in the form
00368 // of <appname>-mainwindow#<number>
00369 // when comparing them for fake session info, it's probably better to check
00370 // them without the trailing number
00371 bool Workspace::windowRoleMatch( const QCString& role1, const QCString& role2 )
00372     {
00373     if( role1.isEmpty() && role2.isEmpty())
00374         return true;
00375     int pos1 = role1.find( '#' );
00376     int pos2 = role2.find( '#' );
00377     bool ret;
00378     if( pos1 < 0 || pos2 < 0 || pos1 != pos2 )
00379         ret = role1 == role2;
00380     else
00381         ret = qstrncmp( role1, role2, pos1 ) == 0;
00382     kdDebug() << "WR:" << role1 << ":" << pos1 << ":" << role2 << ":" << pos2 << ":::" << ret << endl;
00383     return ret;
00384     }
00385 #endif
00386 
00387 static const char* const window_type_names[] = 
00388     {
00389     "Unknown", "Normal" , "Desktop", "Dock", "Toolbar", "Menu", "Dialog",
00390     "Override", "TopMenu", "Utility", "Splash"
00391     };
00392     // change also the two functions below when adding new entries
00393 
00394 const char* Workspace::windowTypeToTxt( NET::WindowType type )
00395     {
00396     if( type >= NET::Unknown && type <= NET::Splash )
00397         return window_type_names[ type + 1 ]; // +1 (unknown==-1)
00398     if( type == -2 ) // undefined (not really part of NET::WindowType)
00399         return "Undefined";
00400     kdFatal() << "Unknown Window Type" << endl;
00401     return NULL;
00402     }
00403 
00404 NET::WindowType Workspace::txtToWindowType( const char* txt )
00405     {
00406     for( int i = NET::Unknown;
00407          i <= NET::Splash;
00408          ++i )
00409         if( qstrcmp( txt, window_type_names[ i + 1 ] ) == 0 ) // +1
00410             return static_cast< NET::WindowType >( i );
00411     return static_cast< NET::WindowType >( -2 ); // undefined
00412     }
00413 
00414 
00415 
00416 
00417 // KWin's focus stealing prevention causes problems with user interaction
00418 // during session save, as it prevents possible dialogs from getting focus.
00419 // Therefore it's temporarily disabled during session saving. Start of
00420 // session saving can be detected in SessionManaged::saveState() above,
00421 // but Qt doesn't have API for saying when session saved finished (either
00422 // successfully, or was cancelled). Therefore, create another connection
00423 // to session manager, that will provide this information.
00424 static void save_yourself( SmcConn conn_P, SmPointer ptr, int, Bool, int, Bool )
00425     {
00426     SessionSaveDoneHelper* session = reinterpret_cast< SessionSaveDoneHelper* >( ptr );
00427     if( conn_P != session->connection())
00428         return;
00429     SmcSaveYourselfDone( conn_P, True );
00430     }
00431 
00432 static void die( SmcConn conn_P, SmPointer ptr )
00433     {
00434     SessionSaveDoneHelper* session = reinterpret_cast< SessionSaveDoneHelper* >( ptr );
00435     if( conn_P != session->connection())
00436         return;
00437     // session->saveDone(); we will quit anyway
00438     session->close();
00439     }
00440 
00441 static void save_complete( SmcConn conn_P, SmPointer ptr )
00442     {
00443     SessionSaveDoneHelper* session = reinterpret_cast< SessionSaveDoneHelper* >( ptr );
00444     if( conn_P != session->connection())
00445         return;
00446     session->saveDone();
00447     }
00448 
00449 static void shutdown_cancelled( SmcConn conn_P, SmPointer ptr )
00450     {
00451     SessionSaveDoneHelper* session = reinterpret_cast< SessionSaveDoneHelper* >( ptr );
00452     if( conn_P != session->connection())
00453         return;
00454     // no need to differentiate between successful finish and cancel
00455     session->saveDone();
00456     }
00457 
00458 void SessionSaveDoneHelper::saveDone()
00459     {
00460     Workspace::self()->sessionSaveDone();
00461     }
00462 
00463 SessionSaveDoneHelper::SessionSaveDoneHelper()
00464     {
00465     SmcCallbacks calls;
00466     calls.save_yourself.callback = save_yourself;
00467     calls.save_yourself.client_data = reinterpret_cast< SmPointer >(this);
00468     calls.die.callback = die;
00469     calls.die.client_data = reinterpret_cast< SmPointer >(this);
00470     calls.save_complete.callback = save_complete;
00471     calls.save_complete.client_data = reinterpret_cast< SmPointer >(this);
00472     calls.shutdown_cancelled.callback = shutdown_cancelled;
00473     calls.shutdown_cancelled.client_data = reinterpret_cast< SmPointer >(this);
00474     char* id = NULL;
00475     char err[ 11 ];
00476     conn = SmcOpenConnection( NULL, 0, 1, 0,
00477         SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask
00478         | SmcShutdownCancelledProcMask, &calls, NULL, &id, 10, err );
00479     if( id != NULL )
00480         free( id );
00481     if( conn == NULL )
00482         return; // no SM
00483     // set the required properties, mostly dummy values
00484     SmPropValue propvalue[ 5 ];
00485     SmProp props[ 5 ];
00486     propvalue[ 0 ].length = sizeof( int );
00487     int value0 = SmRestartNever; // so that this extra SM connection doesn't interfere
00488     propvalue[ 0 ].value = &value0;
00489     props[ 0 ].name = const_cast< char* >( SmRestartStyleHint );
00490     props[ 0 ].type = const_cast< char* >( SmCARD8 );
00491     props[ 0 ].num_vals = 1;
00492     props[ 0 ].vals = &propvalue[ 0 ];
00493     struct passwd* entry = getpwuid( geteuid() );
00494     propvalue[ 1 ].length = entry != NULL ? strlen( entry->pw_name ) : 0;
00495     propvalue[ 1 ].value = (SmPointer)( entry != NULL ? entry->pw_name : "" );
00496     props[ 1 ].name = const_cast< char* >( SmUserID );
00497     props[ 1 ].type = const_cast< char* >( SmARRAY8 );
00498     props[ 1 ].num_vals = 1;
00499     props[ 1 ].vals = &propvalue[ 1 ];
00500     propvalue[ 2 ].length = 0;
00501     propvalue[ 2 ].value = (SmPointer)( "" );
00502     props[ 2 ].name = const_cast< char* >( SmRestartCommand );
00503     props[ 2 ].type = const_cast< char* >( SmLISTofARRAY8 );
00504     props[ 2 ].num_vals = 1;
00505     props[ 2 ].vals = &propvalue[ 2 ];
00506     propvalue[ 3 ].length = 0;
00507     propvalue[ 3 ].value = qApp->argv()[ 0 ];
00508     props[ 3 ].name = const_cast< char* >( SmProgram );
00509     props[ 3 ].type = const_cast< char* >( SmARRAY8 );
00510     props[ 3 ].num_vals = 1;
00511     props[ 3 ].vals = &propvalue[ 3 ];
00512     propvalue[ 4 ].length = 0;
00513     propvalue[ 4 ].value = (SmPointer)( "" );
00514     props[ 4 ].name = const_cast< char* >( SmCloneCommand );
00515     props[ 4 ].type = const_cast< char* >( SmLISTofARRAY8 );
00516     props[ 4 ].num_vals = 1;
00517     props[ 4 ].vals = &propvalue[ 4 ];
00518     SmProp* p[ 5 ] = { &props[ 0 ], &props[ 1 ], &props[ 2 ], &props[ 3 ], &props[ 4 ] };
00519     SmcSetProperties( conn, 5, p );
00520     notifier = new QSocketNotifier( IceConnectionNumber( SmcGetIceConnection( conn )),
00521         QSocketNotifier::Read, this );
00522     connect( notifier, SIGNAL( activated( int )), SLOT( processData()));
00523     }
00524 
00525 SessionSaveDoneHelper::~SessionSaveDoneHelper()
00526     {
00527     close();
00528     }
00529 
00530 void SessionSaveDoneHelper::close()
00531     {
00532     if( conn != NULL )
00533         {
00534         delete notifier;
00535         SmcCloseConnection( conn, 0, NULL );
00536         }
00537     conn = NULL;
00538     }
00539 
00540 void SessionSaveDoneHelper::processData()
00541     {
00542     if( conn != NULL )
00543         IceProcessMessages( SmcGetIceConnection( conn ), 0, 0 );
00544     }
00545 
00546 } // namespace
00547 
00548 #include "sm.moc"
KDE Logo
This file is part of the documentation for kwin Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 29 21:20:54 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003