summaryrefslogtreecommitdiff
path: root/core/launcher/applauncher.cpp
Unidiff
Diffstat (limited to 'core/launcher/applauncher.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/applauncher.cpp8
1 files changed, 4 insertions, 4 deletions
diff --git a/core/launcher/applauncher.cpp b/core/launcher/applauncher.cpp
index 7d3c032..08a3cb4 100644
--- a/core/launcher/applauncher.cpp
+++ b/core/launcher/applauncher.cpp
@@ -1,286 +1,286 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of the Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20 20
21#ifndef QTOPIA_INTERNAL_PRELOADACCESS 21#ifndef QTOPIA_INTERNAL_PRELOADACCESS
22#define QTOPIA_INTERNAL_PRELOADACCESS 22#define QTOPIA_INTERNAL_PRELOADACCESS
23#endif 23#endif
24#ifndef QTOPIA_INTERNAL_FILEOPERATIONS 24#ifndef QTOPIA_INTERNAL_FILEOPERATIONS
25#define QTOPIA_INTERNAL_FILEOPERATIONS 25#define QTOPIA_INTERNAL_FILEOPERATIONS
26#endif 26#endif
27#ifndef QTOPIA_PROGRAM_MONITOR 27#ifndef QTOPIA_PROGRAM_MONITOR
28#define QTOPIA_PROGRAM_MONITOR 28#define QTOPIA_PROGRAM_MONITOR
29#endif 29#endif
30#include <opie2/oglobal.h> 30#include <opie2/oglobal.h>
31 31
32#ifndef Q_OS_WIN32 32#ifndef Q_OS_WIN32
33#include <sys/stat.h> 33#include <sys/stat.h>
34#include <sys/wait.h> 34#include <sys/wait.h>
35#include <sys/file.h> 35#include <sys/file.h>
36#include <unistd.h> 36#include <unistd.h>
37#include <sys/time.h> 37#include <sys/time.h>
38#include <sys/resource.h> 38#include <sys/resource.h>
39#include <errno.h> 39#include <errno.h>
40#else 40#else
41#include <process.h> 41#include <process.h>
42#include <windows.h> 42#include <windows.h>
43#include <winbase.h> 43#include <winbase.h>
44#endif 44#endif
45 45
46#include <signal.h> 46#include <signal.h>
47#include <sys/types.h> 47#include <sys/types.h>
48#include <stdlib.h> 48#include <stdlib.h>
49 49
50#include <qtimer.h> 50#include <qtimer.h>
51#include <qwindowsystem_qws.h> 51#include <qwindowsystem_qws.h>
52#include <qmessagebox.h> 52#include <qmessagebox.h>
53#include <qfileinfo.h> 53#include <qfileinfo.h>
54 54
55#include <qtopia/qcopenvelope_qws.h> 55#include <qtopia/qcopenvelope_qws.h>
56#include <qtopia/qpeapplication.h> 56#include <qtopia/qpeapplication.h>
57 57
58#include "applauncher.h" 58#include "applauncher.h"
59#include "documentlist.h" 59#include "documentlist.h"
60 60
61const int AppLauncher::RAISE_TIMEOUT_MS = 5000; 61const int AppLauncher::RAISE_TIMEOUT_MS = 5000;
62 62
63//--------------------------------------------------------------------------- 63//---------------------------------------------------------------------------
64 64
65static AppLauncher* appLauncherPtr; 65static AppLauncher* appLauncherPtr;
66 66
67const int appStopEventID = 1290; 67const int appStopEventID = 1290;
68 68
69class AppStoppedEvent : public QCustomEvent 69class AppStoppedEvent : public QCustomEvent
70{ 70{
71public: 71public:
72 AppStoppedEvent(int pid, int status) 72 AppStoppedEvent(int pid, int status)
73 : QCustomEvent( appStopEventID ), mPid(pid), mStatus(status) { } 73 : QCustomEvent( appStopEventID ), mPid(pid), mStatus(status) { }
74 74
75 int pid() { return mPid; } 75 int pid() { return mPid; }
76 int status() { return mStatus; } 76 int status() { return mStatus; }
77 77
78private: 78private:
79 int mPid, mStatus; 79 int mPid, mStatus;
80}; 80};
81 81
82AppLauncher::AppLauncher(QObject *parent, const char *name) 82AppLauncher::AppLauncher(QObject *parent, const char *name)
83 : QObject(parent, name), qlPid(0), qlReady(FALSE), 83 : QObject(parent, name), qlPid(0), qlReady(FALSE),
84 appKillerBox(0) 84 appKillerBox(0)
85{ 85{
86 connect(qwsServer, SIGNAL(newChannel(const QString&)), this, SLOT(newQcopChannel(const QString&))); 86 connect(qwsServer, SIGNAL(newChannel(const QString&)), this, SLOT(newQcopChannel(const QString&)));
87 connect(qwsServer, SIGNAL(removedChannel(const QString&)), this, SLOT(removedQcopChannel(const QString&))); 87 connect(qwsServer, SIGNAL(removedChannel(const QString&)), this, SLOT(removedQcopChannel(const QString&)));
88 QCopChannel* channel = new QCopChannel( "QPE/System", this ); 88 QCopChannel* channel = new QCopChannel( "QPE/System", this );
89 connect( channel, SIGNAL(received(const QCString&, const QByteArray&)), 89 connect( channel, SIGNAL(received(const QCString&,const QByteArray&)),
90 this, SLOT(received(const QCString&, const QByteArray&)) ); 90 this, SLOT(received(const QCString&,const QByteArray&)) );
91 91
92 channel = new QCopChannel( "QPE/Server", this ); 92 channel = new QCopChannel( "QPE/Server", this );
93 connect( channel, SIGNAL(received(const QCString&, const QByteArray&)), 93 connect( channel, SIGNAL(received(const QCString&,const QByteArray&)),
94 this, SLOT(received(const QCString&, const QByteArray&)) ); 94 this, SLOT(received(const QCString&,const QByteArray&)) );
95 95
96#ifndef Q_OS_WIN32 96#ifndef Q_OS_WIN32
97 signal(SIGCHLD, signalHandler); 97 signal(SIGCHLD, signalHandler);
98#else 98#else
99 runningAppsProc.setAutoDelete( TRUE ); 99 runningAppsProc.setAutoDelete( TRUE );
100#endif 100#endif
101 QString tmp = qApp->argv()[0]; 101 QString tmp = qApp->argv()[0];
102 int pos = tmp.findRev('/'); 102 int pos = tmp.findRev('/');
103 if ( pos > -1 ) 103 if ( pos > -1 )
104 tmp = tmp.mid(++pos); 104 tmp = tmp.mid(++pos);
105 runningApps[::getpid()] = tmp; 105 runningApps[::getpid()] = tmp;
106 106
107 appLauncherPtr = this; 107 appLauncherPtr = this;
108 108
109 QTimer::singleShot( 1000, this, SLOT(createQuickLauncher()) ); 109 QTimer::singleShot( 1000, this, SLOT(createQuickLauncher()) );
110} 110}
111 111
112AppLauncher::~AppLauncher() 112AppLauncher::~AppLauncher()
113{ 113{
114 appLauncherPtr = 0; 114 appLauncherPtr = 0;
115#ifndef Q_OS_WIN32 115#ifndef Q_OS_WIN32
116 signal(SIGCHLD, SIG_DFL); 116 signal(SIGCHLD, SIG_DFL);
117#endif 117#endif
118 if ( qlPid ) { 118 if ( qlPid ) {
119 int status; 119 int status;
120 ::kill( qlPid, SIGTERM ); 120 ::kill( qlPid, SIGTERM );
121 waitpid( qlPid, &status, 0 ); 121 waitpid( qlPid, &status, 0 );
122 } 122 }
123} 123}
124 124
125/* We use the QCopChannel of the app as an indicator of when it has been launched 125/* We use the QCopChannel of the app as an indicator of when it has been launched
126 so that we can disable the busy indicators */ 126 so that we can disable the busy indicators */
127void AppLauncher::newQcopChannel(const QString& channelName) 127void AppLauncher::newQcopChannel(const QString& channelName)
128{ 128{
129// qDebug("channel %s added", channelName.data() ); 129// qDebug("channel %s added", channelName.data() );
130 QString prefix("QPE/Application/"); 130 QString prefix("QPE/Application/");
131 if (channelName.startsWith(prefix)) { 131 if (channelName.startsWith(prefix)) {
132 { 132 {
133 QCopEnvelope e("QPE/System", "newChannel(QString)"); 133 QCopEnvelope e("QPE/System", "newChannel(QString)");
134 e << channelName; 134 e << channelName;
135 } 135 }
136 QString appName = channelName.mid(prefix.length()); 136 QString appName = channelName.mid(prefix.length());
137 if ( appName != "quicklauncher" ) { 137 if ( appName != "quicklauncher" ) {
138 emit connected( appName ); 138 emit connected( appName );
139 QCopEnvelope e("QPE/System", "notBusy(QString)"); 139 QCopEnvelope e("QPE/System", "notBusy(QString)");
140 e << appName; 140 e << appName;
141 } 141 }
142 } else if (channelName.startsWith("QPE/QuickLauncher-")) { 142 } else if (channelName.startsWith("QPE/QuickLauncher-")) {
143 qDebug("Registered %s", channelName.latin1()); 143 qDebug("Registered %s", channelName.latin1());
144 int pid = channelName.mid(18).toInt(); 144 int pid = channelName.mid(18).toInt();
145 if (pid == qlPid) 145 if (pid == qlPid)
146 qlReady = TRUE; 146 qlReady = TRUE;
147 } 147 }
148} 148}
149 149
150void AppLauncher::removedQcopChannel(const QString& channelName) 150void AppLauncher::removedQcopChannel(const QString& channelName)
151{ 151{
152 if (channelName.startsWith("QPE/Application/")) { 152 if (channelName.startsWith("QPE/Application/")) {
153 QCopEnvelope e("QPE/System", "removedChannel(QString)"); 153 QCopEnvelope e("QPE/System", "removedChannel(QString)");
154 e << channelName; 154 e << channelName;
155 } 155 }
156} 156}
157 157
158void AppLauncher::received(const QCString& msg, const QByteArray& data) 158void AppLauncher::received(const QCString& msg, const QByteArray& data)
159{ 159{
160 QDataStream stream( data, IO_ReadOnly ); 160 QDataStream stream( data, IO_ReadOnly );
161 if ( msg == "execute(QString)" ) { 161 if ( msg == "execute(QString)" ) {
162 QString t; 162 QString t;
163 stream >> t; 163 stream >> t;
164 if ( !executeBuiltin( t, QString::null ) ) 164 if ( !executeBuiltin( t, QString::null ) )
165 execute(t, QString::null); 165 execute(t, QString::null);
166 } else if ( msg == "execute(QString,QString)" ) { 166 } else if ( msg == "execute(QString,QString)" ) {
167 QString t,d; 167 QString t,d;
168 stream >> t >> d; 168 stream >> t >> d;
169 if ( !executeBuiltin( t, d ) ) 169 if ( !executeBuiltin( t, d ) )
170 execute( t, d ); 170 execute( t, d );
171 } else if ( msg == "processQCop(QString)" ) { // from QPE/Server 171 } else if ( msg == "processQCop(QString)" ) { // from QPE/Server
172 QString t; 172 QString t;
173 stream >> t; 173 stream >> t;
174 if ( !executeBuiltin( t, QString::null ) ) 174 if ( !executeBuiltin( t, QString::null ) )
175 execute( t, QString::null, TRUE); 175 execute( t, QString::null, TRUE);
176 } else if ( msg == "raise(QString)" ) { 176 } else if ( msg == "raise(QString)" ) {
177 QString appName; 177 QString appName;
178 stream >> appName; 178 stream >> appName;
179 179
180 if ( !executeBuiltin( appName, QString::null ) ) { 180 if ( !executeBuiltin( appName, QString::null ) ) {
181 if ( !waitingHeartbeat.contains( appName ) && appKillerName != appName ) { 181 if ( !waitingHeartbeat.contains( appName ) && appKillerName != appName ) {
182 //qDebug( "Raising: %s", appName.latin1() ); 182 //qDebug( "Raising: %s", appName.latin1() );
183 QCString channel = "QPE/Application/"; 183 QCString channel = "QPE/Application/";
184 channel += appName.latin1(); 184 channel += appName.latin1();
185 185
186 // Need to lock it to avoid race conditions with QPEApplication::processQCopFile 186 // Need to lock it to avoid race conditions with QPEApplication::processQCopFile
187 QFile f("/tmp/qcop-msg-" + appName); 187 QFile f("/tmp/qcop-msg-" + appName);
188 if ( f.open(IO_WriteOnly | IO_Append) ) { 188 if ( f.open(IO_WriteOnly | IO_Append) ) {
189#ifndef Q_OS_WIN32 189#ifndef Q_OS_WIN32
190 flock(f.handle(), LOCK_EX); 190 flock(f.handle(), LOCK_EX);
191#endif 191#endif
192 QDataStream ds(&f); 192 QDataStream ds(&f);
193 QByteArray b; 193 QByteArray b;
194 QDataStream bstream(b, IO_WriteOnly); 194 QDataStream bstream(b, IO_WriteOnly);
195 ds << channel << QCString("raise()") << b; 195 ds << channel << QCString("raise()") << b;
196 f.flush(); 196 f.flush();
197#ifndef Q_OS_WIN32 197#ifndef Q_OS_WIN32
198 flock(f.handle(), LOCK_UN); 198 flock(f.handle(), LOCK_UN);
199#endif 199#endif
200 f.close(); 200 f.close();
201 } 201 }
202 bool alreadyRunning = isRunning( appName ); 202 bool alreadyRunning = isRunning( appName );
203 if ( execute(appName, QString::null) ) { 203 if ( execute(appName, QString::null) ) {
204 int id = startTimer(RAISE_TIMEOUT_MS + alreadyRunning?2000:0); 204 int id = startTimer(RAISE_TIMEOUT_MS + alreadyRunning?2000:0);
205 waitingHeartbeat.insert( appName, id ); 205 waitingHeartbeat.insert( appName, id );
206 } 206 }
207 } 207 }
208 } 208 }
209 } else if ( msg == "sendRunningApps()" ) { 209 } else if ( msg == "sendRunningApps()" ) {
210 QStringList apps; 210 QStringList apps;
211 QMap<int,QString>::Iterator it; 211 QMap<int,QString>::Iterator it;
212 for( it = runningApps.begin(); it != runningApps.end(); ++it ) 212 for( it = runningApps.begin(); it != runningApps.end(); ++it )
213 apps.append( *it ); 213 apps.append( *it );
214 QCopEnvelope e( "QPE/Desktop", "runningApps(QStringList)" ); 214 QCopEnvelope e( "QPE/Desktop", "runningApps(QStringList)" );
215 e << apps; 215 e << apps;
216 } else if ( msg == "appRaised(QString)" ) { 216 } else if ( msg == "appRaised(QString)" ) {
217 QString appName; 217 QString appName;
218 stream >> appName; 218 stream >> appName;
219 qDebug("Got a heartbeat from %s", appName.latin1()); 219 qDebug("Got a heartbeat from %s", appName.latin1());
220 QMap<QString,int>::Iterator it = waitingHeartbeat.find(appName); 220 QMap<QString,int>::Iterator it = waitingHeartbeat.find(appName);
221 if ( it != waitingHeartbeat.end() ) { 221 if ( it != waitingHeartbeat.end() ) {
222 killTimer( *it ); 222 killTimer( *it );
223 waitingHeartbeat.remove(it); 223 waitingHeartbeat.remove(it);
224 } 224 }
225 // Check to make sure we're not waiting on user input... 225 // Check to make sure we're not waiting on user input...
226 if ( appKillerBox && appName == appKillerName ) { 226 if ( appKillerBox && appName == appKillerName ) {
227 // If we are, we kill the dialog box, and the code waiting on the result 227 // If we are, we kill the dialog box, and the code waiting on the result
228 // will clean us up (basically the user said "no"). 228 // will clean us up (basically the user said "no").
229 delete appKillerBox; 229 delete appKillerBox;
230 appKillerBox = 0; 230 appKillerBox = 0;
231 appKillerName = QString::null; 231 appKillerName = QString::null;
232 } 232 }
233 } 233 }
234} 234}
235 235
236void AppLauncher::signalHandler(int) 236void AppLauncher::signalHandler(int)
237{ 237{
238#ifndef Q_OS_WIN32 238#ifndef Q_OS_WIN32
239 int status; 239 int status;
240 pid_t pid = waitpid(-1, &status, WNOHANG); 240 pid_t pid = waitpid(-1, &status, WNOHANG);
241/* if (pid == 0 || &status == 0 ) { 241/* if (pid == 0 || &status == 0 ) {
242 qDebug("hmm, could not get return value from signal"); 242 qDebug("hmm, could not get return value from signal");
243 } 243 }
244*/ 244*/
245 QApplication::postEvent(appLauncherPtr, new AppStoppedEvent(pid, status) ); 245 QApplication::postEvent(appLauncherPtr, new AppStoppedEvent(pid, status) );
246#else 246#else
247 qDebug("Unhandled signal see by AppLauncher::signalHandler(int)"); 247 qDebug("Unhandled signal see by AppLauncher::signalHandler(int)");
248#endif 248#endif
249} 249}
250 250
251bool AppLauncher::event(QEvent *e) 251bool AppLauncher::event(QEvent *e)
252{ 252{
253 if ( e->type() == appStopEventID ) { 253 if ( e->type() == appStopEventID ) {
254 AppStoppedEvent *ae = (AppStoppedEvent *) e; 254 AppStoppedEvent *ae = (AppStoppedEvent *) e;
255 sigStopped(ae->pid(), ae->status() ); 255 sigStopped(ae->pid(), ae->status() );
256 return TRUE; 256 return TRUE;
257 } 257 }
258 258
259 return QObject::event(e); 259 return QObject::event(e);
260} 260}
261 261
262void AppLauncher::timerEvent( QTimerEvent *e ) 262void AppLauncher::timerEvent( QTimerEvent *e )
263{ 263{
264 int id = e->timerId(); 264 int id = e->timerId();
265 QMap<QString,int>::Iterator it; 265 QMap<QString,int>::Iterator it;
266 for ( it = waitingHeartbeat.begin(); it != waitingHeartbeat.end(); ++it ) { 266 for ( it = waitingHeartbeat.begin(); it != waitingHeartbeat.end(); ++it ) {
267 if ( *it == id ) { 267 if ( *it == id ) {
268 if ( appKillerBox ) // we're already dealing with one 268 if ( appKillerBox ) // we're already dealing with one
269 return; 269 return;
270 270
271 appKillerName = it.key(); 271 appKillerName = it.key();
272 killTimer( id ); 272 killTimer( id );
273 waitingHeartbeat.remove( it ); 273 waitingHeartbeat.remove( it );
274 274
275 // qDebug("Checking in on %s", appKillerName.latin1()); 275 // qDebug("Checking in on %s", appKillerName.latin1());
276 276
277 // We store this incase the application responds while we're 277 // We store this incase the application responds while we're
278 // waiting for user input so we know not to delete ourselves. 278 // waiting for user input so we know not to delete ourselves.
279 appKillerBox = new QMessageBox(tr("Application Problem"), 279 appKillerBox = new QMessageBox(tr("Application Problem"),
280 tr("<p>%1 is not responding.</p>").arg(appKillerName) + 280 tr("<p>%1 is not responding.</p>").arg(appKillerName) +
281 tr("<p>Would you like to force the application to exit?</p>"), 281 tr("<p>Would you like to force the application to exit?</p>"),
282 QMessageBox::Warning, QMessageBox::Yes, 282 QMessageBox::Warning, QMessageBox::Yes,
283 QMessageBox::No | QMessageBox::Default, 283 QMessageBox::No | QMessageBox::Default,
284 QMessageBox::NoButton); 284 QMessageBox::NoButton);
285 if (appKillerBox->exec() == QMessageBox::Yes) { 285 if (appKillerBox->exec() == QMessageBox::Yes) {
286 // qDebug("Killing the app!!! Bwuhahahaha!"); 286 // qDebug("Killing the app!!! Bwuhahahaha!");