24 #include <sys/types.h>
33 #include <tqptrlist.h>
36 #include <dcopclient.h>
37 #include <kcmdlineargs.h>
38 #include <kstandarddirs.h>
39 #include <kaboutdata.h>
43 #include <kstartupinfo.h>
48 #include "kuniqueapplication.h"
53 #define DISPLAY "DISPLAY"
56 # define DISPLAY "QWS_DISPLAY"
58 # define DISPLAY "DISPLAY"
62 bool KUniqueApplication::s_nofork =
false;
63 bool KUniqueApplication::s_multipleInstances =
false;
64 bool KUniqueApplication::s_uniqueTestDone =
false;
65 bool KUniqueApplication::s_handleAutoStarted =
false;
69 {
"nofork",
"Don't run in the background.", 0 },
76 DCOPClientTransaction *transaction;
79 class KUniqueApplicationPrivate {
81 TQPtrList <DCOPRequest> requestList;
82 bool processingRequest;
95 if( s_uniqueTestDone )
97 s_uniqueTestDone =
true;
103 s_nofork = !args->
isSet(
"fork");
107 TQCString appName = KCmdLineArgs::about->
appName();
111 if (s_multipleInstances)
114 pid.setNum(getpid());
115 appName = appName +
"-" + pid;
121 #ifndef Q_WS_WIN //TODO
122 if(
dcopClient()->registerAs(appName,
false).isEmpty()) {
124 if(
dcopClient()->registerAs(appName,
false).isEmpty()) {
125 kdError() <<
"KUniqueApplication: Can't setup DCOP communication." <<
endl;
139 kdError() <<
"KUniqueApplication: pipe() failed!" <<
endl;
142 int fork_result = fork();
143 switch(fork_result) {
145 kdError() <<
"KUniqueApplication: fork() failed!" <<
endl;
151 if (s_multipleInstances)
152 appName.append(
"-").append(TQCString().setNum(getpid()));
155 TQCString regName = dc->
registerAs(appName,
false);
156 if (regName.isEmpty())
159 if (TQCString(getenv(DISPLAY)).isEmpty())
161 kdError() <<
"KUniqueApplication: Can't determine DISPLAY. Aborting." <<
endl;
163 ::write(fd[1], &result, 1);
170 if (regName.isEmpty())
172 kdError() <<
"KUniqueApplication: Can't setup DCOP communication." <<
endl;
175 ::write(fd[1], &result, 1);
179 if (regName != appName)
184 ::write(fd[1], &result, 1);
191 id.initId( kapp->startupId());
193 id = KStartupInfo::currentStartupIdEnv();
196 Display* disp = XOpenDisplay( NULL );
199 KStartupInfo::sendFinishX( disp,
id );
200 XCloseDisplay( disp );
203 #else //FIXME(E): implement
215 id.initId( kapp->startupId());
217 id = KStartupInfo::currentStartupIdEnv();
220 Display* disp = XOpenDisplay( NULL );
223 KStartupInfoData data;
224 data.addPid( getpid());
225 KStartupInfo::sendChangeX( disp,
id, data );
226 XCloseDisplay( disp );
229 #else //FIXME(E): Implement
233 ::write(fd[1], &result, 1);
240 if (s_multipleInstances)
241 appName.append(
"-").append(TQCString().setNum(fork_result));
245 int n = ::read(fd[0], &result, 1);
249 kdError() <<
"KUniqueApplication: Pipe closed unexpectedly." <<
endl;
254 kdError() <<
"KUniqueApplication: Error reading from pipe." <<
endl;
266 kdError() <<
"KUniqueApplication: Parent process can't attach to DCOP." <<
endl;
271 kdError() <<
"KUniqueApplication: Registering failed!" <<
endl;
274 TQCString new_asn_id;
278 id.initId( kapp->startupId());
280 id = KStartupInfo::currentStartupIdEnv();
282 new_asn_id =
id.id();
285 TQByteArray data, reply;
286 TQDataStream ds(data, IO_WriteOnly);
288 KCmdLineArgs::saveAppArgs(ds);
293 if (!dc->
call(appName, KCmdLineArgs::about->
appName(),
"newInstance()", data, replyType, reply))
295 kdError() <<
"Communication problem with " << KCmdLineArgs::about->
appName() <<
", it probably crashed." <<
endl;
300 if (replyType !=
"int")
302 kdError() <<
"KUniqueApplication: DCOP communication error!" <<
endl;
306 TQDataStream rs(reply, IO_ReadOnly);
318 :
KApplication( allowStyles, GUIenabled, initHack( configUnique )),
321 d =
new KUniqueApplicationPrivate;
322 d->processingRequest =
false;
323 d->firstInstance =
true;
327 TQTimer::singleShot( 0,
this, TQT_SLOT(newInstanceNoFork()) );
331 TQTimer::singleShot( 0,
this, TQT_SLOT(processDelayed()));
338 Qt::HANDLE colormap,
bool allowStyles,
bool configUnique)
339 :
KApplication( display, visual, colormap, allowStyles, initHack( configUnique )),
342 d =
new KUniqueApplicationPrivate;
343 d->processingRequest =
false;
344 d->firstInstance =
true;
348 TQTimer::singleShot( 0,
this, TQT_SLOT(newInstanceNoFork()) );
352 TQTimer::singleShot( 0,
this, TQT_SLOT(processDelayed()));
364 KInstance* KUniqueApplication::initHack(
bool configUnique )
378 void KUniqueApplication::newInstanceNoFork()
383 TQTimer::singleShot( 200,
this, TQT_SLOT(newInstanceNoFork()) );
387 s_handleAutoStarted =
false;
389 d->firstInstance =
false;
397 if( s_handleAutoStarted )
398 KStartupInfo::handleAutoAppStartedSending();
404 TQCString &replyType, TQByteArray &replyData)
406 if (fun ==
"newInstance()")
408 delayRequest(fun, data);
415 KUniqueApplication::delayRequest(
const TQCString &fun,
const TQByteArray &data)
417 DCOPRequest *request =
new DCOPRequest;
419 request->data = data;
421 d->requestList.append(request);
422 if (!d->processingRequest)
424 TQTimer::singleShot(0,
this, TQT_SLOT(processDelayed()));
429 KUniqueApplication::processDelayed()
434 TQTimer::singleShot( 200,
this, TQT_SLOT(processDelayed()));
437 d->processingRequest =
true;
438 while( !d->requestList.isEmpty() )
440 DCOPRequest *request = d->requestList.take(0);
441 TQByteArray replyData;
443 if (request->fun ==
"newInstance()") {
445 TQDataStream ds(request->data, IO_ReadOnly);
451 setStartupId( asn_id );
453 s_handleAutoStarted =
false;
455 d->firstInstance =
false;
457 if( s_handleAutoStarted )
458 KStartupInfo::handleAutoAppStartedSending();
460 TQDataStream rs(replyData, IO_WriteOnly);
468 d->processingRequest =
false;
478 if (!d->firstInstance)
483 mainWidget()->show();
489 KStartupInfo::setNewStartupId( mainWidget(), kapp->startupId());
496 void KUniqueApplication::setHandleAutoStarted()
498 s_handleAutoStarted =
false;
501 void KUniqueApplication::virtual_hook(
int id,
void* data )
502 { KApplication::virtual_hook(
id, data );
505 #include "kuniqueapplication.moc"