00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kworkspace.h"
00021 #include <QApplication>
00022 #include <QDataStream>
00023 #include <kapplication.h>
00024 #include <QFile>
00025 #include <QFileInfo>
00026 #include <QTextStream>
00027 #include <klocale.h>
00028 #include <QDateTime>
00029 #include <kstandarddirs.h>
00030 #include <QtDBus/QtDBus>
00031 #include <stdlib.h>
00032 #include <ksmserver_interface.h>
00033 #include <kdefakes.h>
00034 #include <QSocketNotifier>
00035
00036 #ifdef Q_WS_X11
00037 #include <X11/Xlib.h>
00038 #include <X11/Xutil.h>
00039 #include <X11/Xatom.h>
00040 #include <X11/SM/SMlib.h>
00041 #include <fixx11h.h>
00042 #endif
00043
00044 #ifdef Q_WS_X11
00045 #define DISPLAY "DISPLAY"
00046 #elif defined(Q_WS_QWS)
00047 #define DISPLAY "QWS_DISPLAY"
00048 #endif
00049
00050 #include <unistd.h>
00051 #include <pwd.h>
00052 #include <sys/types.h>
00053
00054 #include "kworkspace_p.h"
00055
00056 namespace KWorkSpace
00057 {
00058 #ifdef Q_WS_X11
00059 static void save_yourself_callback( SmcConn conn_P, SmPointer, int, Bool , int, Bool )
00060 {
00061 SmcSaveYourselfDone( conn_P, True );
00062 }
00063
00064 static void dummy_callback( SmcConn, SmPointer )
00065 {
00066 }
00067 #endif
00068 KRequestShutdownHelper::KRequestShutdownHelper()
00069 {
00070 #ifdef Q_WS_X11
00071 SmcCallbacks calls;
00072 calls.save_yourself.callback = save_yourself_callback;
00073 calls.die.callback = dummy_callback;
00074 calls.save_complete.callback = dummy_callback;
00075 calls.shutdown_cancelled.callback = dummy_callback;
00076 char* id = NULL;
00077 char err[ 11 ];
00078 conn = SmcOpenConnection( NULL, NULL, 1, 0,
00079 SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask
00080 | SmcShutdownCancelledProcMask, &calls, NULL, &id, 10, err );
00081 if( id != NULL )
00082 free( id );
00083 if( conn == NULL )
00084 return;
00085
00086 SmPropValue propvalue[ 5 ];
00087 SmProp props[ 5 ];
00088 propvalue[ 0 ].length = sizeof( unsigned char );
00089 unsigned char value0 = SmRestartNever;
00090 propvalue[ 0 ].value = &value0;
00091 props[ 0 ].name = const_cast< char* >( SmRestartStyleHint );
00092 props[ 0 ].type = const_cast< char* >( SmCARD8 );
00093 props[ 0 ].num_vals = 1;
00094 props[ 0 ].vals = &propvalue[ 0 ];
00095 struct passwd* entry = getpwuid( geteuid() );
00096 propvalue[ 1 ].length = entry != NULL ? strlen( entry->pw_name ) : 0;
00097 propvalue[ 1 ].value = (SmPointer)( entry != NULL ? entry->pw_name : "" );
00098 props[ 1 ].name = const_cast< char* >( SmUserID );
00099 props[ 1 ].type = const_cast< char* >( SmARRAY8 );
00100 props[ 1 ].num_vals = 1;
00101 props[ 1 ].vals = &propvalue[ 1 ];
00102 propvalue[ 2 ].length = 0;
00103 propvalue[ 2 ].value = (SmPointer)( "" );
00104 props[ 2 ].name = const_cast< char* >( SmRestartCommand );
00105 props[ 2 ].type = const_cast< char* >( SmLISTofARRAY8 );
00106 props[ 2 ].num_vals = 1;
00107 props[ 2 ].vals = &propvalue[ 2 ];
00108 propvalue[ 3 ].length = strlen( "requestshutdownhelper" );
00109 propvalue[ 3 ].value = (SmPointer)"requestshutdownhelper";
00110 props[ 3 ].name = const_cast< char* >( SmProgram );
00111 props[ 3 ].type = const_cast< char* >( SmARRAY8 );
00112 props[ 3 ].num_vals = 1;
00113 props[ 3 ].vals = &propvalue[ 3 ];
00114 propvalue[ 4 ].length = 0;
00115 propvalue[ 4 ].value = (SmPointer)( "" );
00116 props[ 4 ].name = const_cast< char* >( SmCloneCommand );
00117 props[ 4 ].type = const_cast< char* >( SmLISTofARRAY8 );
00118 props[ 4 ].num_vals = 1;
00119 props[ 4 ].vals = &propvalue[ 4 ];
00120 SmProp* p[ 5 ] = { &props[ 0 ], &props[ 1 ], &props[ 2 ], &props[ 3 ], &props[ 4 ] };
00121 SmcSetProperties( conn, 5, p );
00122 notifier = new QSocketNotifier( IceConnectionNumber( SmcGetIceConnection( conn )),
00123 QSocketNotifier::Read, this );
00124 connect( notifier, SIGNAL( activated( int )), SLOT( processData()));
00125 #endif
00126 }
00127
00128 KRequestShutdownHelper::~KRequestShutdownHelper()
00129 {
00130 #ifdef Q_WS_X11
00131 if( conn != NULL )
00132 {
00133 delete notifier;
00134 SmcCloseConnection( conn, 0, NULL );
00135 }
00136 #endif
00137 }
00138
00139 void KRequestShutdownHelper::processData()
00140 {
00141 #ifdef Q_WS_X11
00142 if( conn != NULL )
00143 IceProcessMessages( SmcGetIceConnection( conn ), 0, 0 );
00144 #endif
00145 }
00146
00147 bool KRequestShutdownHelper::requestShutdown( ShutdownConfirm confirm )
00148 {
00149 #ifdef Q_WS_X11
00150 if( conn == NULL )
00151 return false;
00152 SmcRequestSaveYourself( conn, SmSaveBoth, True, SmInteractStyleAny,
00153 confirm == ShutdownConfirmNo, True );
00154
00155 IceFlush(SmcGetIceConnection(conn));
00156 #endif
00157 return true;
00158 }
00159 #ifdef Q_WS_X11
00160 static KRequestShutdownHelper* helper = NULL;
00161
00162 static void cleanup_sm()
00163 {
00164 delete helper;
00165 }
00166 #endif
00167
00168 bool requestShutDown(
00169 ShutdownConfirm confirm, ShutdownType sdtype, ShutdownMode sdmode )
00170 {
00171 #ifdef Q_WS_X11
00172 QApplication::syncX();
00173 kapp->updateRemoteUserTimestamp( "org.kde.ksmserver" );
00174
00175 if ( confirm == ShutdownConfirmYes ||
00176 sdtype != ShutdownTypeDefault ||
00177 sdmode != ShutdownModeDefault )
00178 {
00179 org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus());
00180 QDBusReply<void> reply = ksmserver.logout((int)confirm, (int)sdtype, (int)sdmode);
00181 return (reply.isValid());
00182 }
00183 if( helper == NULL )
00184 {
00185 helper = new KRequestShutdownHelper();
00186 qAddPostRoutine(cleanup_sm);
00187 }
00188 return helper->requestShutdown( confirm );
00189 #else
00190 return false;
00191 #endif
00192 }
00193
00194 bool canShutDown( ShutdownConfirm confirm,
00195 ShutdownType sdtype,
00196 ShutdownMode sdmode )
00197 {
00198 #ifdef Q_WS_X11
00199 if ( confirm == ShutdownConfirmYes ||
00200 sdtype != ShutdownTypeDefault ||
00201 sdmode != ShutdownModeDefault )
00202 {
00203 org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus());
00204 QDBusReply<bool> reply = ksmserver.canShutdown();
00205 if (!reply.isValid()) {
00206 return false;
00207 }
00208 return reply;
00209 }
00210
00211 return true;
00212 #else
00213 return false;
00214 #endif
00215 }
00216
00217 static QTime smModificationTime;
00218 void propagateSessionManager()
00219 {
00220 #ifdef Q_WS_X11
00221 QByteArray fName = QFile::encodeName(KStandardDirs::locateLocal("socket", "KSMserver"));
00222 QString display = QString::fromLocal8Bit( ::getenv(DISPLAY) );
00223
00224 display.remove(QRegExp("\\.[0-9]+$"));
00225 int i;
00226 while( (i = display.indexOf(':')) >= 0)
00227 display[i] = '_';
00228
00229 fName += '_';
00230 fName += display.toLocal8Bit();
00231 QByteArray smEnv = ::getenv("SESSION_MANAGER");
00232 bool check = smEnv.isEmpty();
00233 if ( !check && smModificationTime.isValid() ) {
00234 QFileInfo info( fName );
00235 QTime current = info.lastModified().time();
00236 check = current > smModificationTime;
00237 }
00238 if ( check ) {
00239 QFile f( fName );
00240 if ( !f.open( QIODevice::ReadOnly ) )
00241 return;
00242 QFileInfo info ( f );
00243 smModificationTime = QTime( info.lastModified().time() );
00244 QTextStream t(&f);
00245 t.setCodec( "ISO 8859-1" );
00246 QString s = t.readLine();
00247 f.close();
00248 ::setenv( "SESSION_MANAGER", s.toLatin1(), true );
00249 }
00250 #endif
00251 }
00252
00253 }
00254
00255 #include "kworkspace_p.moc"