00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "sm.h"
00013
00014 #include <tqsocketnotifier.h>
00015 #include <tqsessionmanager.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( TQSessionManager& sm )
00031 {
00032
00033
00034
00035
00036
00037
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 )
00045 Workspace::self()->storeSession( kapp->sessionConfig(), SMSavePhase0 );
00046 sm.release();
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
00056 bool SessionManaged::commitData( TQSessionManager& sm )
00057 {
00058 if ( !sm.isPhase2() )
00059 Workspace::self()->sessionSaveStarted();
00060 return true;
00061 }
00062
00063
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 TQCString sessionId = c->sessionId();
00079 TQCString wmCommand = c->wmCommand();
00080 if ( sessionId.isEmpty() )
00081
00082
00083 if ( wmCommand.isEmpty() )
00084 continue;
00085 count++;
00086 if( c->isActive())
00087 active_client = count;
00088 TQString n = TQString::number(count);
00089 if( phase == SMSavePhase2 || phase == SMSavePhase2Full )
00090 {
00091 config->writeEntry( TQString("sessionId")+n, sessionId.data() );
00092 config->writeEntry( TQString("windowRole")+n, c->windowRole().data() );
00093 config->writeEntry( TQString("wmCommand")+n, wmCommand.data() );
00094 config->writeEntry( TQString("wmClientMachine")+n, c->wmClientMachine( true ).data() );
00095 config->writeEntry( TQString("resourceName")+n, c->resourceName().data() );
00096 config->writeEntry( TQString("resourceClass")+n, c->resourceClass().data() );
00097 config->writeEntry( TQString("geometry")+n, TQRect( c->calculateGravitation(TRUE), c->clientSize() ) );
00098 config->writeEntry( TQString("restore")+n, c->geometryRestore() );
00099 config->writeEntry( TQString("fsrestore")+n, c->geometryFSRestore() );
00100 config->writeEntry( TQString("maximize")+n, (int) c->maximizeMode() );
00101 config->writeEntry( TQString("fullscreen")+n, (int) c->fullScreenMode() );
00102 config->writeEntry( TQString("desktop")+n, c->desktop() );
00103
00104
00105 config->writeEntry( TQString("iconified")+n, c->isMinimized() );
00106
00107 config->writeEntry( TQString("sticky")+n, c->isOnAllDesktops() );
00108 config->writeEntry( TQString("shaded")+n, c->isShade() );
00109 config->writeEntry( TQString("shadowed")+n, c->isShadowed() );
00110
00111 config->writeEntry( TQString("staysOnTop")+n, c->keepAbove() );
00112 config->writeEntry( TQString("keepBelow")+n, c->keepBelow() );
00113 config->writeEntry( TQString("skipTaskbar")+n, c->skipTaskbar( true ) );
00114 config->writeEntry( TQString("skipPager")+n, c->skipPager() );
00115 config->writeEntry( TQString("userNoBorder")+n, c->isUserNoBorder() );
00116 config->writeEntry( TQString("windowType")+n, windowTypeToTxt( c->windowType()));
00117 config->writeEntry( TQString("shortcut")+n, c->shortcut().toStringInternal());
00118 }
00119 }
00120
00121 if( phase == SMSavePhase0 )
00122 {
00123
00124
00125
00126 session_active_client = active_client;
00127 session_desktop = currentDesktop();
00128 }
00129 else if( phase == SMSavePhase2 )
00130 {
00131 config->writeEntry( "count", count );
00132 config->writeEntry( "active", session_active_client );
00133 config->writeEntry( "desktop", session_desktop );
00134 }
00135 else
00136 {
00137 config->writeEntry( "count", count );
00138 config->writeEntry( "active", session_active_client );
00139 config->writeEntry( "desktop", currentDesktop());
00140 }
00141 }
00142
00143
00149 void Workspace::loadSessionInfo()
00150 {
00151 session.clear();
00152 KConfig* config = kapp->sessionConfig();
00153 config->setGroup("Session" );
00154 int count = config->readNumEntry( "count" );
00155 int active_client = config->readNumEntry( "active" );
00156 for ( int i = 1; i <= count; i++ )
00157 {
00158 TQString n = TQString::number(i);
00159 SessionInfo* info = new SessionInfo;
00160 session.append( info );
00161 info->sessionId = config->readEntry( TQString("sessionId")+n ).latin1();
00162 info->windowRole = config->readEntry( TQString("windowRole")+n ).latin1();
00163 info->wmCommand = config->readEntry( TQString("wmCommand")+n ).latin1();
00164 info->wmClientMachine = config->readEntry( TQString("wmClientMachine")+n ).latin1();
00165 info->resourceName = config->readEntry( TQString("resourceName")+n ).latin1();
00166 info->resourceClass = config->readEntry( TQString("resourceClass")+n ).lower().latin1();
00167 info->geometry = config->readRectEntry( TQString("geometry")+n );
00168 info->restore = config->readRectEntry( TQString("restore")+n );
00169 info->fsrestore = config->readRectEntry( TQString("fsrestore")+n );
00170 info->maximized = config->readNumEntry( TQString("maximize")+n, 0 );
00171 info->fullscreen = config->readNumEntry( TQString("fullscreen")+n, 0 );
00172 info->desktop = config->readNumEntry( TQString("desktop")+n, 0 );
00173 info->minimized = config->readBoolEntry( TQString("iconified")+n, FALSE );
00174 info->onAllDesktops = config->readBoolEntry( TQString("sticky")+n, FALSE );
00175 info->shaded = config->readBoolEntry( TQString("shaded")+n, FALSE );
00176 info->shadowed = config->readBoolEntry( TQString("shadowed")+n, TRUE );
00177 info->keepAbove = config->readBoolEntry( TQString("staysOnTop")+n, FALSE );
00178 info->keepBelow = config->readBoolEntry( TQString("keepBelow")+n, FALSE );
00179 info->skipTaskbar = config->readBoolEntry( TQString("skipTaskbar")+n, FALSE );
00180 info->skipPager = config->readBoolEntry( TQString("skipPager")+n, FALSE );
00181 info->userNoBorder = config->readBoolEntry( TQString("userNoBorder")+n, FALSE );
00182 info->windowType = txtToWindowType( config->readEntry( TQString("windowType")+n ).latin1());
00183 info->shortcut = config->readEntry( TQString("shortcut")+n );
00184 info->active = ( active_client == i );
00185 }
00186 }
00187
00197 SessionInfo* Workspace::takeSessionInfo( Client* c )
00198 {
00199 SessionInfo *realInfo = 0;
00200 TQCString sessionId = c->sessionId();
00201 TQCString windowRole = c->windowRole();
00202 TQCString wmCommand = c->wmCommand();
00203 TQCString wmClientMachine = c->wmClientMachine( true );
00204 TQCString resourceName = c->resourceName();
00205 TQCString resourceClass = c->resourceClass();
00206
00207
00208 if (! sessionId.isEmpty() )
00209 {
00210
00211 for (SessionInfo* info = session.first(); info && !realInfo; info = session.next() )
00212 if ( info->sessionId == sessionId && sessionInfoWindowTypeMatch( c, info ))
00213 {
00214 if ( ! windowRole.isEmpty() )
00215 {
00216 if ( info->windowRole == windowRole )
00217 realInfo = session.take();
00218 }
00219 else
00220 {
00221 if ( info->windowRole.isEmpty() &&
00222 info->resourceName == resourceName &&
00223 info->resourceClass == resourceClass )
00224 realInfo = session.take();
00225 }
00226 }
00227 }
00228 else
00229 {
00230
00231 for (SessionInfo* info = session.first(); info && !realInfo; info = session.next() )
00232 if ( info->resourceName == resourceName &&
00233 info->resourceClass == resourceClass &&
00234 info->wmClientMachine == wmClientMachine &&
00235 sessionInfoWindowTypeMatch( c, info ))
00236 if ( wmCommand.isEmpty() || info->wmCommand == wmCommand )
00237 realInfo = session.take();
00238 }
00239
00240 return realInfo;
00241 }
00242
00243 bool Workspace::sessionInfoWindowTypeMatch( Client* c, SessionInfo* info )
00244 {
00245 if( info->windowType == -2 )
00246 {
00247 return !c->isSpecialWindow();
00248 }
00249 return info->windowType == c->windowType();
00250 }
00251
00252
00253 #if 0
00254
00255
00256
00257
00258 bool Workspace::windowRoleMatch( const TQCString& role1, const TQCString& role2 )
00259 {
00260 if( role1.isEmpty() && role2.isEmpty())
00261 return true;
00262 int pos1 = role1.find( '#' );
00263 int pos2 = role2.find( '#' );
00264 bool ret;
00265 if( pos1 < 0 || pos2 < 0 || pos1 != pos2 )
00266 ret = role1 == role2;
00267 else
00268 ret = tqstrncmp( role1, role2, pos1 ) == 0;
00269 kdDebug() << "WR:" << role1 << ":" << pos1 << ":" << role2 << ":" << pos2 << ":::" << ret << endl;
00270 return ret;
00271 }
00272 #endif
00273
00274 static const char* const window_type_names[] =
00275 {
00276 "Unknown", "Normal" , "Desktop", "Dock", "Toolbar", "Menu", "Dialog",
00277 "Override", "TopMenu", "Utility", "Splash"
00278 };
00279
00280
00281 const char* Workspace::windowTypeToTxt( NET::WindowType type )
00282 {
00283 if( type >= NET::Unknown && type <= NET::Splash )
00284 return window_type_names[ type + 1 ];
00285 if( type == -2 )
00286 return "Undefined";
00287 kdFatal() << "Unknown Window Type" << endl;
00288 return NULL;
00289 }
00290
00291 NET::WindowType Workspace::txtToWindowType( const char* txt )
00292 {
00293 for( int i = NET::Unknown;
00294 i <= NET::Splash;
00295 ++i )
00296 if( qstrcmp( txt, window_type_names[ i + 1 ] ) == 0 )
00297 return static_cast< NET::WindowType >( i );
00298 return static_cast< NET::WindowType >( -2 );
00299 }
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 static void save_yourself( SmcConn conn_P, SmPointer ptr, int, Bool shutdown, int, Bool )
00320 {
00321 SessionSaveDoneHelper* session = reinterpret_cast< SessionSaveDoneHelper* >( ptr );
00322 if( conn_P != session->connection())
00323 return;
00324 if( shutdown )
00325 Workspace::self()->disableRulesUpdates( true );
00326 SmcSaveYourselfDone( conn_P, True );
00327 }
00328
00329 static void die( SmcConn conn_P, SmPointer ptr )
00330 {
00331 SessionSaveDoneHelper* session = reinterpret_cast< SessionSaveDoneHelper* >( ptr );
00332 if( conn_P != session->connection())
00333 return;
00334
00335 session->close();
00336 }
00337
00338 static void save_complete( SmcConn conn_P, SmPointer ptr )
00339 {
00340 SessionSaveDoneHelper* session = reinterpret_cast< SessionSaveDoneHelper* >( ptr );
00341 if( conn_P != session->connection())
00342 return;
00343 session->saveDone();
00344 }
00345
00346 static void shutdown_cancelled( SmcConn conn_P, SmPointer ptr )
00347 {
00348 SessionSaveDoneHelper* session = reinterpret_cast< SessionSaveDoneHelper* >( ptr );
00349 if( conn_P != session->connection())
00350 return;
00351 Workspace::self()->disableRulesUpdates( false );
00352
00353 session->saveDone();
00354 }
00355
00356 void SessionSaveDoneHelper::saveDone()
00357 {
00358 Workspace::self()->sessionSaveDone();
00359 }
00360
00361 SessionSaveDoneHelper::SessionSaveDoneHelper()
00362 {
00363 SmcCallbacks calls;
00364 calls.save_yourself.callback = save_yourself;
00365 calls.save_yourself.client_data = reinterpret_cast< SmPointer >(this);
00366 calls.die.callback = die;
00367 calls.die.client_data = reinterpret_cast< SmPointer >(this);
00368 calls.save_complete.callback = save_complete;
00369 calls.save_complete.client_data = reinterpret_cast< SmPointer >(this);
00370 calls.shutdown_cancelled.callback = shutdown_cancelled;
00371 calls.shutdown_cancelled.client_data = reinterpret_cast< SmPointer >(this);
00372 char* id = NULL;
00373 char err[ 11 ];
00374 conn = SmcOpenConnection( NULL, 0, 1, 0,
00375 SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask
00376 | SmcShutdownCancelledProcMask, &calls, NULL, &id, 10, err );
00377 if( id != NULL )
00378 free( id );
00379 if( conn == NULL )
00380 return;
00381
00382 SmPropValue propvalue[ 5 ];
00383 SmProp props[ 5 ];
00384 propvalue[ 0 ].length = sizeof( int );
00385 int value0 = SmRestartNever;
00386 propvalue[ 0 ].value = &value0;
00387 props[ 0 ].name = const_cast< char* >( SmRestartStyleHint );
00388 props[ 0 ].type = const_cast< char* >( SmCARD8 );
00389 props[ 0 ].num_vals = 1;
00390 props[ 0 ].vals = &propvalue[ 0 ];
00391 struct passwd* entry = getpwuid( geteuid() );
00392 propvalue[ 1 ].length = entry != NULL ? strlen( entry->pw_name ) : 0;
00393 propvalue[ 1 ].value = (SmPointer)( entry != NULL ? entry->pw_name : "" );
00394 props[ 1 ].name = const_cast< char* >( SmUserID );
00395 props[ 1 ].type = const_cast< char* >( SmARRAY8 );
00396 props[ 1 ].num_vals = 1;
00397 props[ 1 ].vals = &propvalue[ 1 ];
00398 propvalue[ 2 ].length = 0;
00399 propvalue[ 2 ].value = (SmPointer)( "" );
00400 props[ 2 ].name = const_cast< char* >( SmRestartCommand );
00401 props[ 2 ].type = const_cast< char* >( SmLISTofARRAY8 );
00402 props[ 2 ].num_vals = 1;
00403 props[ 2 ].vals = &propvalue[ 2 ];
00404 propvalue[ 3 ].length = 0;
00405 propvalue[ 3 ].value = tqApp->argv()[ 0 ];
00406 props[ 3 ].name = const_cast< char* >( SmProgram );
00407 props[ 3 ].type = const_cast< char* >( SmARRAY8 );
00408 props[ 3 ].num_vals = 1;
00409 props[ 3 ].vals = &propvalue[ 3 ];
00410 propvalue[ 4 ].length = 0;
00411 propvalue[ 4 ].value = (SmPointer)( "" );
00412 props[ 4 ].name = const_cast< char* >( SmCloneCommand );
00413 props[ 4 ].type = const_cast< char* >( SmLISTofARRAY8 );
00414 props[ 4 ].num_vals = 1;
00415 props[ 4 ].vals = &propvalue[ 4 ];
00416 SmProp* p[ 5 ] = { &props[ 0 ], &props[ 1 ], &props[ 2 ], &props[ 3 ], &props[ 4 ] };
00417 SmcSetProperties( conn, 5, p );
00418 notifier = new TQSocketNotifier( IceConnectionNumber( SmcGetIceConnection( conn )),
00419 TQSocketNotifier::Read, TQT_TQOBJECT(this) );
00420 connect( notifier, TQT_SIGNAL( activated( int )), TQT_SLOT( processData()));
00421 }
00422
00423 SessionSaveDoneHelper::~SessionSaveDoneHelper()
00424 {
00425 close();
00426 }
00427
00428 void SessionSaveDoneHelper::close()
00429 {
00430 if( conn != NULL )
00431 {
00432 delete notifier;
00433 SmcCloseConnection( conn, 0, NULL );
00434 }
00435 conn = NULL;
00436 }
00437
00438 void SessionSaveDoneHelper::processData()
00439 {
00440 if( conn != NULL )
00441 IceProcessMessages( SmcGetIceConnection( conn ), 0, 0 );
00442 }
00443
00444 }
00445
00446 #include "sm.moc"