not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / libs / kworkspace / kworkspace.cpp
blobe66963d38daf8f29b8e2663fab099b4761e08449
1 /* This file is part of the KDE libraries
2 Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
20 #include "kworkspace.h"
21 #include <QApplication>
22 #include <QDataStream>
23 #include <kapplication.h>
24 #include <QFile>
25 #include <QFileInfo>
26 #include <QTextStream>
27 #include <klocale.h>
28 #include <QDateTime>
29 #include <kstandarddirs.h>
30 #include <QtDBus/QtDBus>
31 #include <stdlib.h> // getenv()
32 #include <ksmserver_interface.h>
33 #include <kdefakes.h>
34 #include <QSocketNotifier>
36 #ifdef Q_WS_X11
37 #include <X11/Xlib.h>
38 #include <X11/Xutil.h>
39 #include <X11/Xatom.h>
40 #include <X11/SM/SMlib.h>
41 #include <fixx11h.h>
42 #endif
44 #ifdef Q_WS_X11
45 #define DISPLAY "DISPLAY"
46 #elif defined(Q_WS_QWS)
47 #define DISPLAY "QWS_DISPLAY"
48 #endif
50 #include <unistd.h>
51 #include <pwd.h>
52 #include <sys/types.h>
54 #include "kworkspace_p.h"
56 namespace KWorkSpace
59 static void save_yourself_callback( SmcConn conn_P, SmPointer, int, Bool , int, Bool )
61 SmcSaveYourselfDone( conn_P, True );
64 static void dummy_callback( SmcConn, SmPointer )
68 KRequestShutdownHelper::KRequestShutdownHelper()
70 SmcCallbacks calls;
71 calls.save_yourself.callback = save_yourself_callback;
72 calls.die.callback = dummy_callback;
73 calls.save_complete.callback = dummy_callback;
74 calls.shutdown_cancelled.callback = dummy_callback;
75 char* id = NULL;
76 char err[ 11 ];
77 conn = SmcOpenConnection( NULL, NULL, 1, 0,
78 SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask
79 | SmcShutdownCancelledProcMask, &calls, NULL, &id, 10, err );
80 if( id != NULL )
81 free( id );
82 if( conn == NULL )
83 return; // no SM
84 // set the required properties, mostly dummy values
85 SmPropValue propvalue[ 5 ];
86 SmProp props[ 5 ];
87 propvalue[ 0 ].length = sizeof( int );
88 int value0 = SmRestartNever; // so that this extra SM connection doesn't interfere
89 propvalue[ 0 ].value = &value0;
90 props[ 0 ].name = const_cast< char* >( SmRestartStyleHint );
91 props[ 0 ].type = const_cast< char* >( SmCARD8 );
92 props[ 0 ].num_vals = 1;
93 props[ 0 ].vals = &propvalue[ 0 ];
94 struct passwd* entry = getpwuid( geteuid() );
95 propvalue[ 1 ].length = entry != NULL ? strlen( entry->pw_name ) : 0;
96 propvalue[ 1 ].value = (SmPointer)( entry != NULL ? entry->pw_name : "" );
97 props[ 1 ].name = const_cast< char* >( SmUserID );
98 props[ 1 ].type = const_cast< char* >( SmARRAY8 );
99 props[ 1 ].num_vals = 1;
100 props[ 1 ].vals = &propvalue[ 1 ];
101 propvalue[ 2 ].length = 0;
102 propvalue[ 2 ].value = (SmPointer)( "" );
103 props[ 2 ].name = const_cast< char* >( SmRestartCommand );
104 props[ 2 ].type = const_cast< char* >( SmLISTofARRAY8 );
105 props[ 2 ].num_vals = 1;
106 props[ 2 ].vals = &propvalue[ 2 ];
107 propvalue[ 3 ].length = strlen( "requestshutdownhelper" );
108 propvalue[ 3 ].value = (SmPointer)"requestshutdownhelper";
109 props[ 3 ].name = const_cast< char* >( SmProgram );
110 props[ 3 ].type = const_cast< char* >( SmARRAY8 );
111 props[ 3 ].num_vals = 1;
112 props[ 3 ].vals = &propvalue[ 3 ];
113 propvalue[ 4 ].length = 0;
114 propvalue[ 4 ].value = (SmPointer)( "" );
115 props[ 4 ].name = const_cast< char* >( SmCloneCommand );
116 props[ 4 ].type = const_cast< char* >( SmLISTofARRAY8 );
117 props[ 4 ].num_vals = 1;
118 props[ 4 ].vals = &propvalue[ 4 ];
119 SmProp* p[ 5 ] = { &props[ 0 ], &props[ 1 ], &props[ 2 ], &props[ 3 ], &props[ 4 ] };
120 SmcSetProperties( conn, 5, p );
121 notifier = new QSocketNotifier( IceConnectionNumber( SmcGetIceConnection( conn )),
122 QSocketNotifier::Read, this );
123 connect( notifier, SIGNAL( activated( int )), SLOT( processData()));
126 KRequestShutdownHelper::~KRequestShutdownHelper()
128 if( conn != NULL )
130 delete notifier;
131 SmcCloseConnection( conn, 0, NULL );
135 void KRequestShutdownHelper::processData()
137 if( conn != NULL )
138 IceProcessMessages( SmcGetIceConnection( conn ), 0, 0 );
141 bool KRequestShutdownHelper::requestShutdown( ShutdownConfirm confirm )
143 if( conn == NULL )
144 return false;
145 SmcRequestSaveYourself( conn, SmSaveBoth, True, SmInteractStyleAny,
146 confirm == ShutdownConfirmNo, True );
147 // flush the request
148 IceFlush(SmcGetIceConnection(conn));
149 return true;
152 static KRequestShutdownHelper* helper = NULL;
154 static void cleanup_sm()
156 delete helper;
159 bool requestShutDown(
160 ShutdownConfirm confirm, ShutdownType sdtype, ShutdownMode sdmode )
162 QApplication::syncX();
163 kapp->updateRemoteUserTimestamp( "org.kde.ksmserver" );
164 /* use ksmserver's dcop interface if necessary */
165 if ( confirm == ShutdownConfirmYes ||
166 sdtype != ShutdownTypeDefault ||
167 sdmode != ShutdownModeDefault )
169 org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus());
170 QDBusReply<void> reply = ksmserver.logout((int)confirm, (int)sdtype, (int)sdmode);
171 return (reply.isValid());
173 if( helper == NULL )
175 helper = new KRequestShutdownHelper();
176 qAddPostRoutine(cleanup_sm);
178 return helper->requestShutdown( confirm );
181 bool canShutDown( ShutdownConfirm confirm,
182 ShutdownType sdtype,
183 ShutdownMode sdmode )
185 if ( confirm == ShutdownConfirmYes ||
186 sdtype != ShutdownTypeDefault ||
187 sdmode != ShutdownModeDefault )
189 org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus());
190 QDBusReply<bool> reply = ksmserver.canShutdown();
191 if (!reply.isValid()) {
192 return false;
194 return reply;
197 return true;
200 static QTime smModificationTime;
201 void propagateSessionManager()
203 QByteArray fName = QFile::encodeName(KStandardDirs::locateLocal("socket", "KSMserver"));
204 QString display = QString::fromLocal8Bit( ::getenv(DISPLAY) );
205 // strip the screen number from the display
206 display.remove(QRegExp("\\.[0-9]+$"));
207 int i;
208 while( (i = display.indexOf(':')) >= 0)
209 display[i] = '_';
211 fName += '_';
212 fName += display.toLocal8Bit();
213 QByteArray smEnv = ::getenv("SESSION_MANAGER");
214 bool check = smEnv.isEmpty();
215 if ( !check && smModificationTime.isValid() ) {
216 QFileInfo info( fName );
217 QTime current = info.lastModified().time();
218 check = current > smModificationTime;
220 if ( check ) {
221 QFile f( fName );
222 if ( !f.open( QIODevice::ReadOnly ) )
223 return;
224 QFileInfo info ( f );
225 smModificationTime = QTime( info.lastModified().time() );
226 QTextStream t(&f);
227 t.setCodec( "ISO 8859-1" );
228 QString s = t.readLine();
229 f.close();
230 ::setenv( "SESSION_MANAGER", s.toLatin1(), true );
234 } // end namespace
236 #include "kworkspace_p.moc"