~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to libs/kworkspace/kworkspace.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of the KDE libraries
 
2
    Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
 
3
 
 
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.
 
8
 
 
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.
 
13
 
 
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.
 
18
*/
 
19
 
 
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>
 
35
 
 
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
 
43
 
 
44
#ifdef Q_WS_X11
 
45
#define DISPLAY "DISPLAY"
 
46
#elif defined(Q_WS_QWS)
 
47
#define DISPLAY "QWS_DISPLAY"
 
48
#endif
 
49
 
 
50
#include <unistd.h>
 
51
#include <pwd.h>
 
52
#include <sys/types.h>
 
53
 
 
54
#include "kworkspace_p.h"
 
55
 
 
56
namespace KWorkSpace
 
57
{
 
58
#ifdef Q_WS_X11
 
59
static void save_yourself_callback( SmcConn conn_P, SmPointer, int, Bool , int, Bool )
 
60
    {
 
61
    SmcSaveYourselfDone( conn_P, True );
 
62
    }
 
63
 
 
64
static void dummy_callback( SmcConn, SmPointer )
 
65
    {
 
66
    }
 
67
#endif
 
68
KRequestShutdownHelper::KRequestShutdownHelper()
 
69
    {
 
70
#ifdef Q_WS_X11     
 
71
    SmcCallbacks calls;
 
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;
 
76
    char* id = NULL;
 
77
    char err[ 11 ];
 
78
    conn = SmcOpenConnection( NULL, NULL, 1, 0,
 
79
        SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask
 
80
        | SmcShutdownCancelledProcMask, &calls, NULL, &id, 10, err );
 
81
    if( id != NULL )
 
82
        free( id );
 
83
    if( conn == NULL )
 
84
        return; // no SM
 
85
    // set the required properties, mostly dummy values
 
86
    SmPropValue propvalue[ 5 ];
 
87
    SmProp props[ 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()));
 
125
#endif
 
126
    }
 
127
 
 
128
KRequestShutdownHelper::~KRequestShutdownHelper()
 
129
    {
 
130
#ifdef Q_WS_X11     
 
131
    if( conn != NULL )
 
132
        {
 
133
        delete notifier;
 
134
        SmcCloseConnection( conn, 0, NULL );
 
135
        }
 
136
#endif
 
137
    }
 
138
 
 
139
void KRequestShutdownHelper::processData()
 
140
    {
 
141
#ifdef Q_WS_X11     
 
142
    if( conn != NULL )
 
143
        IceProcessMessages( SmcGetIceConnection( conn ), 0, 0 );
 
144
#endif    
 
145
    }
 
146
 
 
147
bool KRequestShutdownHelper::requestShutdown( ShutdownConfirm confirm )
 
148
    {
 
149
#ifdef Q_WS_X11     
 
150
    if( conn == NULL )
 
151
        return false;
 
152
    SmcRequestSaveYourself( conn, SmSaveBoth, True, SmInteractStyleAny,
 
153
        confirm == ShutdownConfirmNo, True );
 
154
    // flush the request
 
155
    IceFlush(SmcGetIceConnection(conn));
 
156
#endif    
 
157
    return true;
 
158
    }
 
159
#ifdef Q_WS_X11
 
160
static KRequestShutdownHelper* helper = NULL;
 
161
 
 
162
static void cleanup_sm()
 
163
{
 
164
    delete helper;
 
165
}
 
166
#endif
 
167
 
 
168
bool requestShutDown(
 
169
    ShutdownConfirm confirm, ShutdownType sdtype, ShutdownMode sdmode )
 
170
{
 
171
#ifdef Q_WS_X11
 
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 )
 
178
    {
 
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());
 
182
    }
 
183
    if( helper == NULL )
 
184
    {
 
185
        helper = new KRequestShutdownHelper();
 
186
        qAddPostRoutine(cleanup_sm);
 
187
    }
 
188
    return helper->requestShutdown( confirm );
 
189
#else
 
190
    return false;
 
191
#endif
 
192
}
 
193
 
 
194
bool canShutDown( ShutdownConfirm confirm,
 
195
                  ShutdownType sdtype,
 
196
                  ShutdownMode sdmode )
 
197
{
 
198
#ifdef Q_WS_X11
 
199
    if ( confirm == ShutdownConfirmYes ||
 
200
         sdtype != ShutdownTypeDefault ||
 
201
         sdmode != ShutdownModeDefault )
 
202
    {
 
203
        org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus());
 
204
        QDBusReply<bool> reply = ksmserver.canShutdown();
 
205
        if (!reply.isValid()) {
 
206
            return false;
 
207
        }
 
208
        return reply;
 
209
    }
 
210
 
 
211
    return true;
 
212
#else
 
213
    return false;
 
214
#endif
 
215
}
 
216
 
 
217
static QTime smModificationTime;
 
218
void propagateSessionManager()
 
219
{
 
220
#ifdef Q_WS_X11
 
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]+$"));
 
225
    int i;
 
226
    while( (i = display.indexOf(':')) >= 0)
 
227
       display[i] = '_';
 
228
    while( (i = display.indexOf('/')) >= 0)
 
229
       display[i] = '_';
 
230
 
 
231
    fName += '_';
 
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;
 
239
    }
 
240
    if ( check ) {
 
241
        QFile f( fName );
 
242
        if ( !f.open( QIODevice::ReadOnly ) )
 
243
            return;
 
244
        QFileInfo info ( f );
 
245
        smModificationTime = QTime( info.lastModified().time() );
 
246
        QTextStream t(&f);
 
247
        t.setCodec( "ISO 8859-1" );
 
248
        QString s = t.readLine();
 
249
        f.close();
 
250
        ::setenv( "SESSION_MANAGER", s.toLatin1(), true  );
 
251
    }
 
252
#endif
 
253
}
 
254
 
 
255
} // end namespace
 
256
 
 
257
#include "kworkspace_p.moc"