summaryrefslogtreecommitdiffstats
path: root/kdecore/kuniqueapplication.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kdecore/kuniqueapplication.cpp')
-rw-r--r--kdecore/kuniqueapplication.cpp495
1 files changed, 0 insertions, 495 deletions
diff --git a/kdecore/kuniqueapplication.cpp b/kdecore/kuniqueapplication.cpp
deleted file mode 100644
index 193aafcd3..000000000
--- a/kdecore/kuniqueapplication.cpp
+++ /dev/null
@@ -1,495 +0,0 @@
-/* This file is part of the KDE libraries
- Copyright (c) 1999 Preston Brown <pbrown@kde.org>
-
- $Id$
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-#include <config.h>
-
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <tqfile.h>
-#include <tqptrlist.h>
-#include <tqtimer.h>
-
-#include <dcopclient.h>
-#include <kcmdlineargs.h>
-#include <kstandarddirs.h>
-#include <kaboutdata.h>
-
-#if defined Q_WS_X11
-#include <kwin.h>
-#include <kstartupinfo.h>
-#endif
-
-#include <kconfig.h>
-#include "kdebug.h"
-#include "kuniqueapplication.h"
-
-#if defined Q_WS_X11
-#include <netwm.h>
-#include <X11/Xlib.h>
-#define DISPLAY "DISPLAY"
-#else
-# ifdef Q_WS_QWS
-# define DISPLAY "QWS_DISPLAY"
-# else
-# define DISPLAY "DISPLAY"
-# endif
-#endif
-
-bool KUniqueApplication::s_nofork = false;
-bool KUniqueApplication::s_multipleInstances = false;
-bool KUniqueApplication::s_uniqueTestDone = false;
-bool KUniqueApplication::s_handleAutoStarted = false;
-
-static KCmdLineOptions kunique_options[] =
-{
- { "nofork", "Don't run in the background.", 0 },
- KCmdLineLastOption
-};
-
-struct DCOPRequest {
- TQCString fun;
- TQByteArray data;
- DCOPClientTransaction *transaction;
-};
-
-class KUniqueApplicationPrivate {
-public:
- TQPtrList <DCOPRequest> requestList;
- bool processingRequest;
- bool firstInstance;
-};
-
-void
-KUniqueApplication::addCmdLineOptions()
-{
- KCmdLineArgs::addCmdLineOptions(kunique_options, 0, "kuniqueapp", "kde" );
-}
-
-bool
-KUniqueApplication::start()
-{
- if( s_uniqueTestDone )
- return true;
- s_uniqueTestDone = true;
- addCmdLineOptions(); // Make sure to add cmd line options
-#ifdef Q_WS_WIN
- s_nofork = true;
-#else
- KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kuniqueapp");
- s_nofork = !args->isSet("fork");
- delete args;
-#endif
-
- TQCString appName = KCmdLineArgs::about->appName();
-
- if (s_nofork)
- {
- if (s_multipleInstances)
- {
- TQCString pid;
- pid.setNum(getpid());
- appName = appName + "-" + pid;
- }
-
- // Check to make sure that we're actually able to register with the DCOP
- // server.
-
-#ifndef Q_WS_WIN //TODO
- if(dcopClient()->registerAs(appName, false).isEmpty()) {
- startKdeinit();
- if(dcopClient()->registerAs(appName, false).isEmpty()) {
- kdError() << "KUniqueApplication: Can't setup DCOP communication." << endl;
- ::exit(255);
- }
- }
-#endif
-
- // We'll call newInstance in the constructor. Do nothing here.
- return true;
- }
- DCOPClient *dc;
- int fd[2];
- signed char result;
- if (0 > pipe(fd))
- {
- kdError() << "KUniqueApplication: pipe() failed!" << endl;
- ::exit(255);
- }
- int fork_result = fork();
- switch(fork_result) {
- case -1:
- kdError() << "KUniqueApplication: fork() failed!" << endl;
- ::exit(255);
- break;
- case 0:
- // Child
- ::close(fd[0]);
- if (s_multipleInstances)
- appName.append("-").append(TQCString().setNum(getpid()));
- dc = dcopClient();
- {
- TQCString regName = dc->registerAs(appName, false);
- if (regName.isEmpty())
- {
- // Check DISPLAY
- if (TQCString(getenv(DISPLAY)).isEmpty())
- {
- kdError() << "KUniqueApplication: Can't determine DISPLAY. Aborting." << endl;
- result = -1; // Error
- ::write(fd[1], &result, 1);
- ::exit(255);
- }
-
- // Try to launch tdeinit.
- startKdeinit();
- regName = dc->registerAs(appName, false);
- if (regName.isEmpty())
- {
- kdError() << "KUniqueApplication: Can't setup DCOP communication." << endl;
- result = -1;
- delete dc; // Clean up DCOP commmunication
- ::write(fd[1], &result, 1);
- ::exit(255);
- }
- }
- if (regName != appName)
- {
- // Already running. Ok.
- result = 0;
- delete dc; // Clean up DCOP commmunication
- ::write(fd[1], &result, 1);
- ::close(fd[1]);
-#if 0
-#ifdef Q_WS_X11
- // say we're up and running ( probably no new window will appear )
- KStartupInfoId id;
- if( kapp != NULL ) // KApplication constructor unsets the env. variable
- id.initId( kapp->startupId());
- else
- id = KStartupInfo::currentStartupIdEnv();
- if( !id.none())
- {
- Display* disp = XOpenDisplay( NULL );
- if( disp != NULL ) // use extra X connection
- {
- KStartupInfo::sendFinishX( disp, id );
- XCloseDisplay( disp );
- }
- }
-#else //FIXME(E): implement
-#endif
-#endif
- return false;
- }
- dc->setPriorityCall(true);
- }
-
- {
-#ifdef Q_WS_X11
- KStartupInfoId id;
- if( kapp != NULL ) // KApplication constructor unsets the env. variable
- id.initId( kapp->startupId());
- else
- id = KStartupInfo::currentStartupIdEnv();
- if( !id.none())
- { // notice about pid change
- Display* disp = XOpenDisplay( NULL );
- if( disp != NULL ) // use extra X connection
- {
- KStartupInfoData data;
- data.addPid( getpid());
- KStartupInfo::sendChangeX( disp, id, data );
- XCloseDisplay( disp );
- }
- }
-#else //FIXME(E): Implement
-#endif
- }
- result = 0;
- ::write(fd[1], &result, 1);
- ::close(fd[1]);
- return true; // Finished.
- default:
- // Parent
-// DCOPClient::emergencyClose();
-// dcopClient()->detach();
- if (s_multipleInstances)
- appName.append("-").append(TQCString().setNum(fork_result));
- ::close(fd[1]);
- for(;;)
- {
- int n = ::read(fd[0], &result, 1);
- if (n == 1) break;
- if (n == 0)
- {
- kdError() << "KUniqueApplication: Pipe closed unexpectedly." << endl;
- ::exit(255);
- }
- if (errno != EINTR)
- {
- kdError() << "KUniqueApplication: Error reading from pipe." << endl;
- ::exit(255);
- }
- }
- ::close(fd[0]);
-
- if (result != 0)
- ::exit(result); // Error occurred in child.
-
- dc = new DCOPClient();
- if (!dc->attach())
- {
- kdError() << "KUniqueApplication: Parent process can't attach to DCOP." << endl;
- delete dc; // Clean up DCOP commmunication
- ::exit(255);
- }
- if (!dc->isApplicationRegistered(appName)) {
- kdError() << "KUniqueApplication: Registering failed!" << endl;
- }
-
- TQCString new_asn_id;
-#if defined Q_WS_X11
- KStartupInfoId id;
- if( kapp != NULL ) // KApplication constructor unsets the env. variable
- id.initId( kapp->startupId());
- else
- id = KStartupInfo::currentStartupIdEnv();
- if( !id.none())
- new_asn_id = id.id();
-#endif
-
- TQByteArray data, reply;
- TQDataStream ds(data, IO_WriteOnly);
-
- KCmdLineArgs::saveAppArgs(ds);
- ds << new_asn_id;
-
- dc->setPriorityCall(true);
- TQCString replyType;
- if (!dc->call(appName, KCmdLineArgs::about->appName(), "newInstance()", data, replyType, reply))
- {
- kdError() << "Communication problem with " << KCmdLineArgs::about->appName() << ", it probably crashed." << endl;
- delete dc; // Clean up DCOP commmunication
- ::exit(255);
- }
- dc->setPriorityCall(false);
- if (replyType != "int")
- {
- kdError() << "KUniqueApplication: DCOP communication error!" << endl;
- delete dc; // Clean up DCOP commmunication
- ::exit(255);
- }
- TQDataStream rs(reply, IO_ReadOnly);
- int exitCode;
- rs >> exitCode;
- delete dc; // Clean up DCOP commmunication
- ::exit(exitCode);
- break;
- }
- return false; // make insure++ happy
-}
-
-
-KUniqueApplication::KUniqueApplication(bool allowStyles, bool GUIenabled, bool configUnique)
- : KApplication( allowStyles, GUIenabled, initHack( configUnique )),
- DCOPObject(KCmdLineArgs::about->appName())
-{
- d = new KUniqueApplicationPrivate;
- d->processingRequest = false;
- d->firstInstance = true;
-
- if (s_nofork)
- // Can't call newInstance directly from the constructor since it's virtual...
- TQTimer::singleShot( 0, this, TQT_SLOT(newInstanceNoFork()) );
-}
-
-
-#ifdef Q_WS_X11
-KUniqueApplication::KUniqueApplication(Display *display, Qt::HANDLE visual,
- Qt::HANDLE colormap, bool allowStyles, bool configUnique)
- : KApplication( display, visual, colormap, allowStyles, initHack( configUnique )),
- DCOPObject(KCmdLineArgs::about->appName())
-{
- d = new KUniqueApplicationPrivate;
- d->processingRequest = false;
- d->firstInstance = true;
-
- if (s_nofork)
- // Can't call newInstance directly from the constructor since it's virtual...
- TQTimer::singleShot( 0, this, TQT_SLOT(newInstanceNoFork()) );
-}
-#endif
-
-
-KUniqueApplication::~KUniqueApplication()
-{
- delete d;
-}
-
-// this gets called before even entering TQApplication::TQApplication()
-KInstance* KUniqueApplication::initHack( bool configUnique )
-{
- KInstance* inst = new KInstance( KCmdLineArgs::about );
- if (configUnique)
- {
- KConfigGroupSaver saver( inst->config(), "KDE" );
- s_multipleInstances = inst->config()->readBoolEntry("MultipleInstances", false);
- }
- if( !start())
- // Already running
- ::exit( 0 );
- return inst;
-}
-
-void KUniqueApplication::newInstanceNoFork()
-{
- if (dcopClient()->isSuspended())
- {
- // Try again later.
- TQTimer::singleShot( 200, this, TQT_SLOT(newInstanceNoFork()) );
- return;
- }
-
- s_handleAutoStarted = false;
- newInstance();
- d->firstInstance = false;
-#if defined Q_WS_X11
- // KDE4 remove
- // A hack to make startup notification stop for apps which override newInstance()
- // and reuse an already existing window there, but use KWin::activateWindow()
- // instead of KStartupInfo::setNewStartupId(). Therefore KWin::activateWindow()
- // for now sets this flag. Automatically ending startup notification always
- // would cause problem if the new window would show up with a small delay.
- if( s_handleAutoStarted )
- KStartupInfo::handleAutoAppStartedSending();
-#endif
- // What to do with the return value ?
-}
-
-bool KUniqueApplication::process(const TQCString &fun, const TQByteArray &data,
- TQCString &replyType, TQByteArray &replyData)
-{
- if (fun == "newInstance()")
- {
- delayRequest(fun, data);
- return true;
- } else
- return DCOPObject::process(fun, data, replyType, replyData);
-}
-
-void
-KUniqueApplication::delayRequest(const TQCString &fun, const TQByteArray &data)
-{
- DCOPRequest *request = new DCOPRequest;
- request->fun = fun;
- request->data = data;
- request->transaction = dcopClient()->beginTransaction();
- d->requestList.append(request);
- if (!d->processingRequest)
- {
- TQTimer::singleShot(0, this, TQT_SLOT(processDelayed()));
- }
-}
-
-void
-KUniqueApplication::processDelayed()
-{
- if (dcopClient()->isSuspended())
- {
- // Try again later.
- TQTimer::singleShot( 200, this, TQT_SLOT(processDelayed()));
- return;
- }
- d->processingRequest = true;
- while( !d->requestList.isEmpty() )
- {
- DCOPRequest *request = d->requestList.take(0);
- TQByteArray replyData;
- TQCString replyType;
- if (request->fun == "newInstance()") {
- dcopClient()->setPriorityCall(false);
- TQDataStream ds(request->data, IO_ReadOnly);
- KCmdLineArgs::loadAppArgs(ds);
- if( !ds.atEnd()) // backwards compatibility
- {
- TQCString asn_id;
- ds >> asn_id;
- setStartupId( asn_id );
- }
- s_handleAutoStarted = false;
- int exitCode = newInstance();
- d->firstInstance = false;
-#if defined Q_WS_X11
- if( s_handleAutoStarted )
- KStartupInfo::handleAutoAppStartedSending(); // KDE4 remove?
-#endif
- TQDataStream rs(replyData, IO_WriteOnly);
- rs << exitCode;
- replyType = "int";
- }
- dcopClient()->endTransaction( request->transaction, replyType, replyData);
- delete request;
- }
-
- d->processingRequest = false;
-}
-
-bool KUniqueApplication::restoringSession()
-{
- return d->firstInstance && isRestored();
-}
-
-int KUniqueApplication::newInstance()
-{
- if (!d->firstInstance)
- {
-
- if ( mainWidget() )
- {
- mainWidget()->show();
-#if defined Q_WS_X11
- // This is the line that handles window activation if necessary,
- // and what's important, it does it properly. If you reimplement newInstance(),
- // and don't call the inherited one, use this (but NOT when newInstance()
- // is called for the first time, like here).
- KStartupInfo::setNewStartupId( mainWidget(), kapp->startupId());
-#endif
- }
- }
- return 0; // do nothing in default implementation
-}
-
-void KUniqueApplication::setHandleAutoStarted()
-{
- s_handleAutoStarted = false;
-}
-
-void KUniqueApplication::virtual_hook( int id, void* data )
-{ KApplication::virtual_hook( id, data );
- DCOPObject::virtual_hook( id, data ); }
-
-#include "kuniqueapplication.moc"