24 #include <sys/types.h>
33 #include <tqptrlist.h>
36 #include <dcopclient.h>
37 #include <tdecmdlineargs.h>
38 #include <kstandarddirs.h>
39 #include <tdeaboutdata.h>
43 #include <tdestartupinfo.h>
46 #include <tdeconfig.h>
48 #include "tdeuniqueapplication.h"
53 #define DISPLAY "DISPLAY"
56 # define DISPLAY "QWS_DISPLAY"
58 # define DISPLAY "DISPLAY"
62 bool TDEUniqueApplication::s_nofork =
false;
63 bool TDEUniqueApplication::s_multipleInstances =
false;
64 bool TDEUniqueApplication::s_uniqueTestDone =
false;
65 bool TDEUniqueApplication::s_handleAutoStarted =
false;
69 {
"nofork",
"Don't run in the background.", 0 },
76 DCOPClientTransaction *transaction;
79 class TDEUniqueApplicationPrivate {
81 TQPtrList <DCOPRequest> requestList;
82 bool processingRequest;
95 if( s_uniqueTestDone )
97 s_uniqueTestDone =
true;
103 s_nofork = !args->
isSet(
"fork");
107 TQCString appName = TDECmdLineArgs::about->
appName();
111 if (s_multipleInstances)
114 pid.setNum(getpid());
115 appName = appName +
"-" + pid;
122 if(
dcopClient()->registerAs(appName,
false).isEmpty()) {
124 if(
dcopClient()->registerAs(appName,
false).isEmpty()) {
125 kdError() <<
"TDEUniqueApplication: Can't setup DCOP communication." <<
endl;
139 kdError() <<
"TDEUniqueApplication: pipe() failed!" <<
endl;
142 int fork_result = fork();
143 switch(fork_result) {
145 kdError() <<
"TDEUniqueApplication: 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() <<
"TDEUniqueApplication: Can't determine DISPLAY. Aborting." <<
endl;
163 ::write(fd[1], &result, 1);
170 if (regName.isEmpty())
172 kdError() <<
"TDEUniqueApplication: 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 = TDEStartupInfo::currentStartupIdEnv();
196 Display* disp = XOpenDisplay( NULL );
199 TDEStartupInfo::sendFinishX( disp,
id );
200 XCloseDisplay( disp );
208 dc->setPriorityCall(
true);
215 id.initId( kapp->startupId());
217 id = TDEStartupInfo::currentStartupIdEnv();
220 Display* disp = XOpenDisplay( NULL );
223 TDEStartupInfoData data;
224 data.addPid( getpid());
225 TDEStartupInfo::sendChangeX( disp,
id, data );
226 XCloseDisplay( disp );
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() <<
"TDEUniqueApplication: Pipe closed unexpectedly." <<
endl;
254 kdError() <<
"TDEUniqueApplication: Error reading from pipe." <<
endl;
266 kdError() <<
"TDEUniqueApplication: Parent process can't attach to DCOP." <<
endl;
271 kdError() <<
"TDEUniqueApplication: Registering failed!" <<
endl;
274 TQCString new_asn_id;
275 #if defined TQ_WS_X11
278 id.initId( kapp->startupId());
280 id = TDEStartupInfo::currentStartupIdEnv();
282 new_asn_id =
id.id();
285 TQByteArray data, reply;
286 TQDataStream ds(data, IO_WriteOnly);
288 TDECmdLineArgs::saveAppArgs(ds);
291 dc->setPriorityCall(
true);
293 if (!dc->
call(appName, TDECmdLineArgs::about->
appName(),
"newInstance()", data, replyType, reply))
295 kdError() <<
"Communication problem with " << TDECmdLineArgs::about->
appName() <<
", it probably crashed." <<
endl;
299 dc->setPriorityCall(
false);
300 if (replyType !=
"int")
302 kdError() <<
"TDEUniqueApplication: DCOP communication error!" <<
endl;
306 TQDataStream rs(reply, IO_ReadOnly);
318 :
TDEApplication( allowStyles, GUIenabled, initHack( configUnique )),
321 d =
new TDEUniqueApplicationPrivate;
322 d->processingRequest =
false;
323 d->firstInstance =
true;
327 TQTimer::singleShot( 0,
this, TQ_SLOT(newInstanceNoFork()) );
331 TQTimer::singleShot( 0,
this, TQ_SLOT(processDelayed()));
338 TQt::HANDLE colormap,
bool allowStyles,
bool configUnique)
339 :
TDEApplication( display, visual, colormap, allowStyles, initHack( configUnique )),
342 d =
new TDEUniqueApplicationPrivate;
343 d->processingRequest =
false;
344 d->firstInstance =
true;
348 TQTimer::singleShot( 0,
this, TQ_SLOT(newInstanceNoFork()) );
352 TQTimer::singleShot( 0,
this, TQ_SLOT(processDelayed()));
364 TDEInstance* TDEUniqueApplication::initHack(
bool configUnique )
378 void TDEUniqueApplication::newInstanceNoFork()
383 TQTimer::singleShot( 200,
this, TQ_SLOT(newInstanceNoFork()) );
387 s_handleAutoStarted =
false;
389 d->firstInstance =
false;
390 #if defined TQ_WS_X11
397 if( s_handleAutoStarted )
398 TDEStartupInfo::handleAutoAppStartedSending();
404 TQCString &replyType, TQByteArray &replyData)
406 if (fun ==
"newInstance()")
408 delayRequest(fun, data);
415 TDEUniqueApplication::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, TQ_SLOT(processDelayed()));
429 TDEUniqueApplication::processDelayed()
434 TQTimer::singleShot( 200,
this, TQ_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;
456 #if defined TQ_WS_X11
457 if( s_handleAutoStarted )
458 TDEStartupInfo::handleAutoAppStartedSending();
460 TQDataStream rs(replyData, IO_WriteOnly);
468 d->processingRequest =
false;
478 if (!d->firstInstance)
483 mainWidget()->show();
484 #if defined TQ_WS_X11
489 TDEStartupInfo::setNewStartupId( mainWidget(), kapp->startupId());
496 void TDEUniqueApplication::setHandleAutoStarted()
498 s_handleAutoStarted =
false;
501 void TDEUniqueApplication::virtual_hook(
int id,
void* data )
502 { TDEApplication::virtual_hook(
id, data );
503 DCOPObject::virtual_hook(
id, data ); }
505 #include "tdeuniqueapplication.moc"
void endTransaction(DCOPClientTransaction *t, TQCString &replyType, TQByteArray &replyData)
DCOPClientTransaction * beginTransaction()
bool isApplicationRegistered(const TQCString &remApp)
bool call(const TQCString &remApp, const TQCString &remObj, const TQCString &remFun, const TQByteArray &data, TQCString &replyType, TQByteArray &replyData, bool useEventLoop, int timeout, bool forceRemote)
TQCString registerAs(const TQCString &appId, bool addPID=true)
virtual bool process(const TQCString &fun, const TQByteArray &data, TQCString &replyType, TQByteArray &replyData)
const char * appName() const
Returns the application's internal name.
Controls and provides information to all KDE applications.
bool isRestored() const
Is the application restored from the session manager?
static DCOPClient * dcopClient()
Returns a pointer to a DCOPClient for the application.
A class for command-line argument handling.
bool isSet(const char *option) const
Read out a boolean option or check for the presence of string option.
static TDECmdLineArgs * parsedArgs(const char *id=0)
Access parsed arguments.
static void addCmdLineOptions(const TDECmdLineOptions *options, const char *name=0, const char *id=0, const char *afterId=0)
Add options to your application.
static void loadAppArgs(TQDataStream &)
Load arguments from a stream.
bool readBoolEntry(const TQString &pKey, bool bDefault=false) const
Reads a boolean entry.
Helper class to facilitate working with TDEConfig / KSimpleConfig groups.
Access to KDE global objects for use in shared libraries.
TDEConfig * config() const
Returns the general config object ("appnamerc").
TDEInstance(const TQCString &instanceName)
Constructor.
static bool start()
Forks and registers with dcop.
bool process(const TQCString &fun, const TQByteArray &data, TQCString &replyType, TQByteArray &replyData)
Dispatches any incoming DCOP message for a new instance.
virtual ~TDEUniqueApplication()
Destructor.
bool restoringSession()
Returns whether newInstance() is being called while session restoration is in progress.
virtual int newInstance()
Creates a new "instance" of the application.
static void addCmdLineOptions()
Adds command line options specific for TDEUniqueApplication.
TDEUniqueApplication(bool allowStyles=true, bool GUIenabled=true, bool configUnique=false)
Constructor.
kndbgstream & endl(kndbgstream &s)
Does nothing.
Structure that holds command line options.