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()
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
;
77 conn
= SmcOpenConnection( NULL
, NULL
, 1, 0,
78 SmcSaveYourselfProcMask
| SmcDieProcMask
| SmcSaveCompleteProcMask
79 | SmcShutdownCancelledProcMask
, &calls
, NULL
, &id
, 10, err
);
84 // set the required properties, mostly dummy values
85 SmPropValue propvalue
[ 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()
131 SmcCloseConnection( conn
, 0, NULL
);
135 void KRequestShutdownHelper::processData()
138 IceProcessMessages( SmcGetIceConnection( conn
), 0, 0 );
141 bool KRequestShutdownHelper::requestShutdown( ShutdownConfirm confirm
)
145 SmcRequestSaveYourself( conn
, SmSaveBoth
, True
, SmInteractStyleAny
,
146 confirm
== ShutdownConfirmNo
, True
);
148 IceFlush(SmcGetIceConnection(conn
));
152 static KRequestShutdownHelper
* helper
= NULL
;
154 static void cleanup_sm()
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());
175 helper
= new KRequestShutdownHelper();
176 qAddPostRoutine(cleanup_sm
);
178 return helper
->requestShutdown( confirm
);
181 bool canShutDown( ShutdownConfirm confirm
,
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()) {
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]+$"));
208 while( (i
= display
.indexOf(':')) >= 0)
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
;
222 if ( !f
.open( QIODevice::ReadOnly
) )
224 QFileInfo
info ( f
);
225 smModificationTime
= QTime( info
.lastModified().time() );
227 t
.setCodec( "ISO 8859-1" );
228 QString s
= t
.readLine();
230 ::setenv( "SESSION_MANAGER", s
.toLatin1(), true );
236 #include "kworkspace_p.moc"