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>
26
#include <QTextStream>
29
#include <kstandarddirs.h>
30
#include <QtDBus/QtDBus>
31
#include <stdlib.h> // getenv()
32
#include <ksmserver_interface.h>
34
#include <QSocketNotifier>
38
#include <X11/Xutil.h>
39
#include <X11/Xatom.h>
40
#include <X11/SM/SMlib.h>
45
#define DISPLAY "DISPLAY"
46
#elif defined(Q_WS_QWS)
47
#define DISPLAY "QWS_DISPLAY"
52
#include <sys/types.h>
54
#include "kworkspace_p.h"
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()
72
calls.save_yourself.callback = save_yourself_callback;
73
calls.die.callback = dummy_callback;
74
calls.save_complete.callback = dummy_callback;
75
calls.shutdown_cancelled.callback = dummy_callback;
78
conn = SmcOpenConnection( NULL, NULL, 1, 0,
79
SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask
80
| SmcShutdownCancelledProcMask, &calls, NULL, &id, 10, err );
85
// set the required properties, mostly dummy values
86
SmPropValue propvalue[ 5 ];
88
propvalue[ 0 ].length = sizeof( unsigned char );
89
unsigned char value0 = SmRestartNever; // so that this extra SM connection doesn't interfere
90
propvalue[ 0 ].value = &value0;
91
props[ 0 ].name = const_cast< char* >( SmRestartStyleHint );
92
props[ 0 ].type = const_cast< char* >( SmCARD8 );
93
props[ 0 ].num_vals = 1;
94
props[ 0 ].vals = &propvalue[ 0 ];
95
struct passwd* entry = getpwuid( geteuid() );
96
propvalue[ 1 ].length = entry != NULL ? strlen( entry->pw_name ) : 0;
97
propvalue[ 1 ].value = (SmPointer)( entry != NULL ? entry->pw_name : "" );
98
props[ 1 ].name = const_cast< char* >( SmUserID );
99
props[ 1 ].type = const_cast< char* >( SmARRAY8 );
100
props[ 1 ].num_vals = 1;
101
props[ 1 ].vals = &propvalue[ 1 ];
102
propvalue[ 2 ].length = 0;
103
propvalue[ 2 ].value = (SmPointer)( "" );
104
props[ 2 ].name = const_cast< char* >( SmRestartCommand );
105
props[ 2 ].type = const_cast< char* >( SmLISTofARRAY8 );
106
props[ 2 ].num_vals = 1;
107
props[ 2 ].vals = &propvalue[ 2 ];
108
propvalue[ 3 ].length = strlen( "requestshutdownhelper" );
109
propvalue[ 3 ].value = (SmPointer)"requestshutdownhelper";
110
props[ 3 ].name = const_cast< char* >( SmProgram );
111
props[ 3 ].type = const_cast< char* >( SmARRAY8 );
112
props[ 3 ].num_vals = 1;
113
props[ 3 ].vals = &propvalue[ 3 ];
114
propvalue[ 4 ].length = 0;
115
propvalue[ 4 ].value = (SmPointer)( "" );
116
props[ 4 ].name = const_cast< char* >( SmCloneCommand );
117
props[ 4 ].type = const_cast< char* >( SmLISTofARRAY8 );
118
props[ 4 ].num_vals = 1;
119
props[ 4 ].vals = &propvalue[ 4 ];
120
SmProp* p[ 5 ] = { &props[ 0 ], &props[ 1 ], &props[ 2 ], &props[ 3 ], &props[ 4 ] };
121
SmcSetProperties( conn, 5, p );
122
notifier = new QSocketNotifier( IceConnectionNumber( SmcGetIceConnection( conn )),
123
QSocketNotifier::Read, this );
124
connect( notifier, SIGNAL( activated( int )), SLOT( processData()));
128
KRequestShutdownHelper::~KRequestShutdownHelper()
134
SmcCloseConnection( conn, 0, NULL );
139
void KRequestShutdownHelper::processData()
143
IceProcessMessages( SmcGetIceConnection( conn ), 0, 0 );
147
bool KRequestShutdownHelper::requestShutdown( ShutdownConfirm confirm )
152
SmcRequestSaveYourself( conn, SmSaveBoth, True, SmInteractStyleAny,
153
confirm == ShutdownConfirmNo, True );
155
IceFlush(SmcGetIceConnection(conn));
160
static KRequestShutdownHelper* helper = NULL;
162
static void cleanup_sm()
168
bool requestShutDown(
169
ShutdownConfirm confirm, ShutdownType sdtype, ShutdownMode sdmode )
172
QApplication::syncX();
173
kapp->updateRemoteUserTimestamp( "org.kde.ksmserver" );
174
/* use ksmserver's dcop interface if necessary */
175
if ( confirm == ShutdownConfirmYes ||
176
sdtype != ShutdownTypeDefault ||
177
sdmode != ShutdownModeDefault )
179
org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus());
180
QDBusReply<void> reply = ksmserver.logout((int)confirm, (int)sdtype, (int)sdmode);
181
return (reply.isValid());
185
helper = new KRequestShutdownHelper();
186
qAddPostRoutine(cleanup_sm);
188
return helper->requestShutdown( confirm );
194
bool canShutDown( ShutdownConfirm confirm,
196
ShutdownMode sdmode )
199
if ( confirm == ShutdownConfirmYes ||
200
sdtype != ShutdownTypeDefault ||
201
sdmode != ShutdownModeDefault )
203
org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus());
204
QDBusReply<bool> reply = ksmserver.canShutdown();
205
if (!reply.isValid()) {
217
static QTime smModificationTime;
218
void propagateSessionManager()
221
QByteArray fName = QFile::encodeName(KStandardDirs::locateLocal("socket", "KSMserver"));
222
QString display = QString::fromLocal8Bit( ::getenv(DISPLAY) );
223
// strip the screen number from the display
224
display.remove(QRegExp("\\.[0-9]+$"));
226
while( (i = display.indexOf(':')) >= 0)
228
while( (i = display.indexOf('/')) >= 0)
232
fName += display.toLocal8Bit();
233
QByteArray smEnv = ::getenv("SESSION_MANAGER");
234
bool check = smEnv.isEmpty();
235
if ( !check && smModificationTime.isValid() ) {
236
QFileInfo info( fName );
237
QTime current = info.lastModified().time();
238
check = current > smModificationTime;
242
if ( !f.open( QIODevice::ReadOnly ) )
244
QFileInfo info ( f );
245
smModificationTime = QTime( info.lastModified().time() );
247
t.setCodec( "ISO 8859-1" );
248
QString s = t.readLine();
250
::setenv( "SESSION_MANAGER", s.toLatin1(), true );
257
#include "kworkspace_p.moc"