00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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( QSessionManager& 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 QCString
sessionId = c->sessionId();
00079 QCString
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 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(
true ).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() ) );
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
00104
00105 config->writeEntry( QString(
"iconified")+n, c->isMinimized() );
00106
00107 config->writeEntry( QString(
"sticky")+n, c->isOnAllDesktops() );
00108 config->writeEntry( QString(
"shaded")+n, c->isShade() );
00109
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
00119
if( phase == SMSavePhase0 )
00120 {
00121
00122
00123
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
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 }
00182 }
00183
00193 SessionInfo* Workspace::takeSessionInfo( Client* c )
00194 {
00195 SessionInfo *realInfo = 0;
00196 QCString sessionId = c->sessionId();
00197 QCString windowRole = c->windowRole();
00198 QCString wmCommand = c->wmCommand();
00199 QCString
wmClientMachine = c->wmClientMachine(
true );
00200 QCString resourceName = c->resourceName();
00201 QCString resourceClass = c->resourceClass();
00202
00203
00204
if (! sessionId.isEmpty() )
00205 {
00206
00207
for (SessionInfo* info = session.first(); info && !realInfo; info = session.next() )
00208
if ( info->sessionId == sessionId && sessionInfoWindowTypeMatch( c, info ))
00209 {
00210
if ( ! windowRole.isEmpty() )
00211 {
00212
if ( info->windowRole == windowRole )
00213 realInfo = session.take();
00214 }
00215
else
00216 {
00217
if ( info->windowRole.isEmpty() &&
00218 info->resourceName == resourceName &&
00219 info->resourceClass == resourceClass )
00220 realInfo = session.take();
00221 }
00222 }
00223 }
00224
else
00225 {
00226
00227
for (SessionInfo* info = session.first(); info && !realInfo; info = session.next() )
00228
if ( info->resourceName == resourceName &&
00229 info->resourceClass == resourceClass &&
00230 info->wmClientMachine == wmClientMachine &&
00231 sessionInfoWindowTypeMatch( c, info ))
00232
if ( wmCommand.isEmpty() || info->wmCommand == wmCommand )
00233 realInfo = session.take();
00234 }
00235
00236
return realInfo;
00237 }
00238
00239
bool Workspace::sessionInfoWindowTypeMatch( Client* c, SessionInfo* info )
00240 {
00241
if( info->windowType == -2 )
00242 {
00243
return !c->isSpecialWindow() || c->isOverride();
00244 }
00245
return info->windowType == c->windowType();
00246 }
00247
00248
00249
#if 0
00250
00251
00252
00253
00254
bool Workspace::windowRoleMatch(
const QCString& role1,
const QCString& role2 )
00255 {
00256
if( role1.isEmpty() && role2.isEmpty())
00257
return true;
00258
int pos1 = role1.find(
'#' );
00259
int pos2 = role2.find(
'#' );
00260
bool ret;
00261
if( pos1 < 0 || pos2 < 0 || pos1 != pos2 )
00262 ret = role1 == role2;
00263
else
00264 ret = qstrncmp( role1, role2, pos1 ) == 0;
00265 kdDebug() <<
"WR:" << role1 <<
":" << pos1 <<
":" << role2 <<
":" << pos2 <<
":::" << ret << endl;
00266
return ret;
00267 }
00268
#endif
00269
00270
static const char*
const window_type_names[] =
00271 {
00272
"Unknown",
"Normal" ,
"Desktop",
"Dock",
"Toolbar",
"Menu",
"Dialog",
00273
"Override",
"TopMenu",
"Utility",
"Splash"
00274 };
00275
00276
00277
const char* Workspace::windowTypeToTxt( NET::WindowType type )
00278 {
00279
if( type >= NET::Unknown && type <= NET::Splash )
00280
return window_type_names[ type + 1 ];
00281
if( type == -2 )
00282
return "Undefined";
00283 kdFatal() <<
"Unknown Window Type" << endl;
00284
return NULL;
00285 }
00286
00287 NET::WindowType Workspace::txtToWindowType(
const char* txt )
00288 {
00289
for(
int i = NET::Unknown;
00290 i <= NET::Splash;
00291 ++i )
00292
if( qstrcmp( txt, window_type_names[ i + 1 ] ) == 0 )
00293
return static_cast< NET::WindowType >( i );
00294
return static_cast< NET::WindowType >( -2 );
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
static void save_yourself( SmcConn conn_P, SmPointer ptr,
int, Bool,
int, Bool )
00308 {
00309 SessionSaveDoneHelper* session = reinterpret_cast< SessionSaveDoneHelper* >( ptr );
00310
if( conn_P != session->connection())
00311
return;
00312 SmcSaveYourselfDone( conn_P, True );
00313 }
00314
00315
static void die( SmcConn conn_P, SmPointer ptr )
00316 {
00317 SessionSaveDoneHelper* session = reinterpret_cast< SessionSaveDoneHelper* >( ptr );
00318
if( conn_P != session->connection())
00319
return;
00320
00321 session->close();
00322 }
00323
00324
static void save_complete( SmcConn conn_P, SmPointer ptr )
00325 {
00326 SessionSaveDoneHelper* session = reinterpret_cast< SessionSaveDoneHelper* >( ptr );
00327
if( conn_P != session->connection())
00328
return;
00329 session->saveDone();
00330 }
00331
00332
static void shutdown_cancelled( SmcConn conn_P, SmPointer ptr )
00333 {
00334 SessionSaveDoneHelper* session = reinterpret_cast< SessionSaveDoneHelper* >( ptr );
00335
if( conn_P != session->connection())
00336
return;
00337
00338 session->saveDone();
00339 }
00340
00341
void SessionSaveDoneHelper::saveDone()
00342 {
00343 Workspace::self()->sessionSaveDone();
00344 }
00345
00346 SessionSaveDoneHelper::SessionSaveDoneHelper()
00347 {
00348 SmcCallbacks calls;
00349 calls.save_yourself.callback = save_yourself;
00350 calls.save_yourself.client_data = reinterpret_cast< SmPointer >(
this);
00351 calls.die.callback = die;
00352 calls.die.client_data = reinterpret_cast< SmPointer >(
this);
00353 calls.save_complete.callback = save_complete;
00354 calls.save_complete.client_data = reinterpret_cast< SmPointer >(
this);
00355 calls.shutdown_cancelled.callback = shutdown_cancelled;
00356 calls.shutdown_cancelled.client_data = reinterpret_cast< SmPointer >(
this);
00357
char*
id = NULL;
00358
char err[ 11 ];
00359 conn = SmcOpenConnection( NULL, 0, 1, 0,
00360 SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask
00361 | SmcShutdownCancelledProcMask, &calls, NULL, &
id, 10, err );
00362
if(
id != NULL )
00363 free(
id );
00364
if( conn == NULL )
00365
return;
00366
00367 SmPropValue propvalue[ 5 ];
00368 SmProp props[ 5 ];
00369 propvalue[ 0 ].length =
sizeof(
int );
00370
int value0 = SmRestartNever;
00371 propvalue[ 0 ].value = &value0;
00372 props[ 0 ].name = const_cast< char* >( SmRestartStyleHint );
00373 props[ 0 ].type = const_cast< char* >( SmCARD8 );
00374 props[ 0 ].num_vals = 1;
00375 props[ 0 ].vals = &propvalue[ 0 ];
00376
struct passwd* entry = getpwuid( geteuid() );
00377 propvalue[ 1 ].length = entry != NULL ? strlen( entry->pw_name ) : 0;
00378 propvalue[ 1 ].value = (SmPointer)( entry != NULL ? entry->pw_name :
"" );
00379 props[ 1 ].name = const_cast< char* >( SmUserID );
00380 props[ 1 ].type = const_cast< char* >( SmARRAY8 );
00381 props[ 1 ].num_vals = 1;
00382 props[ 1 ].vals = &propvalue[ 1 ];
00383 propvalue[ 2 ].length = 0;
00384 propvalue[ 2 ].value = (SmPointer)(
"" );
00385 props[ 2 ].name = const_cast< char* >( SmRestartCommand );
00386 props[ 2 ].type = const_cast< char* >( SmLISTofARRAY8 );
00387 props[ 2 ].num_vals = 1;
00388 props[ 2 ].vals = &propvalue[ 2 ];
00389 propvalue[ 3 ].length = 0;
00390 propvalue[ 3 ].value = qApp->argv()[ 0 ];
00391 props[ 3 ].name = const_cast< char* >( SmProgram );
00392 props[ 3 ].type = const_cast< char* >( SmARRAY8 );
00393 props[ 3 ].num_vals = 1;
00394 props[ 3 ].vals = &propvalue[ 3 ];
00395 propvalue[ 4 ].length = 0;
00396 propvalue[ 4 ].value = (SmPointer)(
"" );
00397 props[ 4 ].name = const_cast< char* >( SmCloneCommand );
00398 props[ 4 ].type = const_cast< char* >( SmLISTofARRAY8 );
00399 props[ 4 ].num_vals = 1;
00400 props[ 4 ].vals = &propvalue[ 4 ];
00401 SmProp* p[ 5 ] = { &props[ 0 ], &props[ 1 ], &props[ 2 ], &props[ 3 ], &props[ 4 ] };
00402 SmcSetProperties( conn, 5, p );
00403 notifier =
new QSocketNotifier( IceConnectionNumber( SmcGetIceConnection( conn )),
00404 QSocketNotifier::Read,
this );
00405 connect( notifier, SIGNAL( activated(
int )), SLOT( processData()));
00406 }
00407
00408 SessionSaveDoneHelper::~SessionSaveDoneHelper()
00409 {
00410 close();
00411 }
00412
00413
void SessionSaveDoneHelper::close()
00414 {
00415
if( conn != NULL )
00416 {
00417
delete notifier;
00418 SmcCloseConnection( conn, 0, NULL );
00419 }
00420 conn = NULL;
00421 }
00422
00423
void SessionSaveDoneHelper::processData()
00424 {
00425
if( conn != NULL )
00426 IceProcessMessages( SmcGetIceConnection( conn ), 0, 0 );
00427 }
00428
00429 }
00430
00431
#include "sm.moc"