summaryrefslogtreecommitdiff
path: root/core/launcher/applauncher.cpp
Side-by-side diff
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 @@
/**********************************************************************
** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
** This file is part of the Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#ifndef QTOPIA_INTERNAL_PRELOADACCESS
#define QTOPIA_INTERNAL_PRELOADACCESS
#endif
#ifndef QTOPIA_INTERNAL_FILEOPERATIONS
#define QTOPIA_INTERNAL_FILEOPERATIONS
#endif
#ifndef QTOPIA_PROGRAM_MONITOR
#define QTOPIA_PROGRAM_MONITOR
#endif
#include <opie2/oglobal.h>
#ifndef Q_OS_WIN32
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/file.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <errno.h>
#else
#include <process.h>
#include <windows.h>
#include <winbase.h>
#endif
#include <signal.h>
#include <sys/types.h>
#include <stdlib.h>
#include <qtimer.h>
#include <qwindowsystem_qws.h>
#include <qmessagebox.h>
#include <qfileinfo.h>
#include <qtopia/qcopenvelope_qws.h>
#include <qtopia/qpeapplication.h>
#include "applauncher.h"
#include "documentlist.h"
const int AppLauncher::RAISE_TIMEOUT_MS = 5000;
//---------------------------------------------------------------------------
static AppLauncher* appLauncherPtr;
const int appStopEventID = 1290;
class AppStoppedEvent : public QCustomEvent
{
public:
AppStoppedEvent(int pid, int status)
: QCustomEvent( appStopEventID ), mPid(pid), mStatus(status) { }
int pid() { return mPid; }
int status() { return mStatus; }
private:
int mPid, mStatus;
};
AppLauncher::AppLauncher(QObject *parent, const char *name)
: QObject(parent, name), qlPid(0), qlReady(FALSE),
appKillerBox(0)
{
connect(qwsServer, SIGNAL(newChannel(const QString&)), this, SLOT(newQcopChannel(const QString&)));
connect(qwsServer, SIGNAL(removedChannel(const QString&)), this, SLOT(removedQcopChannel(const QString&)));
QCopChannel* channel = new QCopChannel( "QPE/System", this );
- connect( channel, SIGNAL(received(const QCString&, const QByteArray&)),
- this, SLOT(received(const QCString&, const QByteArray&)) );
+ connect( channel, SIGNAL(received(const QCString&,const QByteArray&)),
+ this, SLOT(received(const QCString&,const QByteArray&)) );
channel = new QCopChannel( "QPE/Server", this );
- connect( channel, SIGNAL(received(const QCString&, const QByteArray&)),
- this, SLOT(received(const QCString&, const QByteArray&)) );
+ connect( channel, SIGNAL(received(const QCString&,const QByteArray&)),
+ this, SLOT(received(const QCString&,const QByteArray&)) );
#ifndef Q_OS_WIN32
signal(SIGCHLD, signalHandler);
#else
runningAppsProc.setAutoDelete( TRUE );
#endif
QString tmp = qApp->argv()[0];
int pos = tmp.findRev('/');
if ( pos > -1 )
tmp = tmp.mid(++pos);
runningApps[::getpid()] = tmp;
appLauncherPtr = this;
QTimer::singleShot( 1000, this, SLOT(createQuickLauncher()) );
}
AppLauncher::~AppLauncher()
{
appLauncherPtr = 0;
#ifndef Q_OS_WIN32
signal(SIGCHLD, SIG_DFL);
#endif
if ( qlPid ) {
int status;
::kill( qlPid, SIGTERM );
waitpid( qlPid, &status, 0 );
}
}
/* We use the QCopChannel of the app as an indicator of when it has been launched
so that we can disable the busy indicators */
void AppLauncher::newQcopChannel(const QString& channelName)
{
// qDebug("channel %s added", channelName.data() );
QString prefix("QPE/Application/");
if (channelName.startsWith(prefix)) {
{
QCopEnvelope e("QPE/System", "newChannel(QString)");
e << channelName;
}
QString appName = channelName.mid(prefix.length());
if ( appName != "quicklauncher" ) {
emit connected( appName );
QCopEnvelope e("QPE/System", "notBusy(QString)");
e << appName;
}
} else if (channelName.startsWith("QPE/QuickLauncher-")) {
qDebug("Registered %s", channelName.latin1());
int pid = channelName.mid(18).toInt();
if (pid == qlPid)
qlReady = TRUE;
}
}
void AppLauncher::removedQcopChannel(const QString& channelName)
{
if (channelName.startsWith("QPE/Application/")) {
QCopEnvelope e("QPE/System", "removedChannel(QString)");
e << channelName;
}
}
void AppLauncher::received(const QCString& msg, const QByteArray& data)
{
QDataStream stream( data, IO_ReadOnly );
if ( msg == "execute(QString)" ) {
QString t;
stream >> t;
if ( !executeBuiltin( t, QString::null ) )
execute(t, QString::null);
} else if ( msg == "execute(QString,QString)" ) {
QString t,d;
stream >> t >> d;
if ( !executeBuiltin( t, d ) )
execute( t, d );
} else if ( msg == "processQCop(QString)" ) { // from QPE/Server
QString t;
stream >> t;
if ( !executeBuiltin( t, QString::null ) )
execute( t, QString::null, TRUE);
} else if ( msg == "raise(QString)" ) {
QString appName;
stream >> appName;
if ( !executeBuiltin( appName, QString::null ) ) {
if ( !waitingHeartbeat.contains( appName ) && appKillerName != appName ) {
//qDebug( "Raising: %s", appName.latin1() );
QCString channel = "QPE/Application/";
channel += appName.latin1();
// Need to lock it to avoid race conditions with QPEApplication::processQCopFile
QFile f("/tmp/qcop-msg-" + appName);
if ( f.open(IO_WriteOnly | IO_Append) ) {
#ifndef Q_OS_WIN32
flock(f.handle(), LOCK_EX);
#endif
QDataStream ds(&f);
QByteArray b;
QDataStream bstream(b, IO_WriteOnly);
ds << channel << QCString("raise()") << b;
f.flush();
#ifndef Q_OS_WIN32
flock(f.handle(), LOCK_UN);
#endif
f.close();
}
bool alreadyRunning = isRunning( appName );
if ( execute(appName, QString::null) ) {
int id = startTimer(RAISE_TIMEOUT_MS + alreadyRunning?2000:0);
waitingHeartbeat.insert( appName, id );
}
}
}
} else if ( msg == "sendRunningApps()" ) {
QStringList apps;
QMap<int,QString>::Iterator it;
for( it = runningApps.begin(); it != runningApps.end(); ++it )
apps.append( *it );
QCopEnvelope e( "QPE/Desktop", "runningApps(QStringList)" );
e << apps;
} else if ( msg == "appRaised(QString)" ) {
QString appName;
stream >> appName;
qDebug("Got a heartbeat from %s", appName.latin1());
QMap<QString,int>::Iterator it = waitingHeartbeat.find(appName);
if ( it != waitingHeartbeat.end() ) {
killTimer( *it );
waitingHeartbeat.remove(it);
}
// Check to make sure we're not waiting on user input...
if ( appKillerBox && appName == appKillerName ) {
// If we are, we kill the dialog box, and the code waiting on the result
// will clean us up (basically the user said "no").
delete appKillerBox;
appKillerBox = 0;
appKillerName = QString::null;
}
}
}
void AppLauncher::signalHandler(int)
{
#ifndef Q_OS_WIN32
int status;
pid_t pid = waitpid(-1, &status, WNOHANG);
/* if (pid == 0 || &status == 0 ) {
qDebug("hmm, could not get return value from signal");
}
*/
QApplication::postEvent(appLauncherPtr, new AppStoppedEvent(pid, status) );
#else
qDebug("Unhandled signal see by AppLauncher::signalHandler(int)");
#endif
}
bool AppLauncher::event(QEvent *e)
{
if ( e->type() == appStopEventID ) {
AppStoppedEvent *ae = (AppStoppedEvent *) e;
sigStopped(ae->pid(), ae->status() );
return TRUE;
}
return QObject::event(e);
}
void AppLauncher::timerEvent( QTimerEvent *e )
{
int id = e->timerId();
QMap<QString,int>::Iterator it;
for ( it = waitingHeartbeat.begin(); it != waitingHeartbeat.end(); ++it ) {
if ( *it == id ) {
if ( appKillerBox ) // we're already dealing with one
return;
appKillerName = it.key();
killTimer( id );
waitingHeartbeat.remove( it );
// qDebug("Checking in on %s", appKillerName.latin1());
// We store this incase the application responds while we're
// waiting for user input so we know not to delete ourselves.
appKillerBox = new QMessageBox(tr("Application Problem"),
tr("<p>%1 is not responding.</p>").arg(appKillerName) +
tr("<p>Would you like to force the application to exit?</p>"),
QMessageBox::Warning, QMessageBox::Yes,
QMessageBox::No | QMessageBox::Default,
QMessageBox::NoButton);
if (appKillerBox->exec() == QMessageBox::Yes) {
// qDebug("Killing the app!!! Bwuhahahaha!");