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
208 dc->setPriorityCall(
true);
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);
291 dc->setPriorityCall(
true);
293 if (!dc->
call(appName, KCmdLineArgs::about->
appName(),
"newInstance()", data, replyType, reply))
295 kdError() <<
"Communication problem with " << KCmdLineArgs::about->
appName() <<
", it probably crashed." <<
endl;
299 dc->setPriorityCall(
false);
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()) );
333 Qt::HANDLE colormap,
bool allowStyles,
bool configUnique)
334 :
KApplication( display, visual, colormap, allowStyles, initHack( configUnique )),
337 d =
new KUniqueApplicationPrivate;
338 d->processingRequest =
false;
339 d->firstInstance =
true;
343 TQTimer::singleShot( 0,
this, TQT_SLOT(newInstanceNoFork()) );
354 KInstance* KUniqueApplication::initHack(
bool configUnique )
368 void KUniqueApplication::newInstanceNoFork()
373 TQTimer::singleShot( 200,
this, TQT_SLOT(newInstanceNoFork()) );
377 s_handleAutoStarted =
false;
379 d->firstInstance =
false;
387 if( s_handleAutoStarted )
388 KStartupInfo::handleAutoAppStartedSending();
394 TQCString &replyType, TQByteArray &replyData)
396 if (fun ==
"newInstance()")
398 delayRequest(fun, data);
405 KUniqueApplication::delayRequest(
const TQCString &fun,
const TQByteArray &data)
407 DCOPRequest *request =
new DCOPRequest;
409 request->data = data;
411 d->requestList.append(request);
412 if (!d->processingRequest)
414 TQTimer::singleShot(0,
this, TQT_SLOT(processDelayed()));
419 KUniqueApplication::processDelayed()
424 TQTimer::singleShot( 200,
this, TQT_SLOT(processDelayed()));
427 d->processingRequest =
true;
428 while( !d->requestList.isEmpty() )
430 DCOPRequest *request = d->requestList.take(0);
431 TQByteArray replyData;
433 if (request->fun ==
"newInstance()") {
435 TQDataStream ds(request->data, IO_ReadOnly);
441 setStartupId( asn_id );
443 s_handleAutoStarted =
false;
445 d->firstInstance =
false;
447 if( s_handleAutoStarted )
448 KStartupInfo::handleAutoAppStartedSending();
450 TQDataStream rs(replyData, IO_WriteOnly);
458 d->processingRequest =
false;
468 if (!d->firstInstance)
473 mainWidget()->show();
479 KStartupInfo::setNewStartupId( mainWidget(), kapp->startupId());
486 void KUniqueApplication::setHandleAutoStarted()
488 s_handleAutoStarted =
false;
491 void KUniqueApplication::virtual_hook(
int id,
void* data )
492 { KApplication::virtual_hook(
id, data );
493 DCOPObject::virtual_hook(
id, data ); }
495 #include "kuniqueapplication.moc"