21 #include "kuniqueapplication_p.h"
26 #include <sys/types.h>
34 #include <QtCore/QFile>
35 #include <QtCore/QList>
36 #include <QtCore/QTimer>
37 #include <QtDBus/QtDBus>
60 #define DISPLAY "DISPLAY"
63 # define DISPLAY "QWS_DISPLAY"
65 # define DISPLAY "DISPLAY"
69 #if defined(Q_OS_DARWIN) || defined (Q_OS_MAC)
73 bool KUniqueApplication::Private::s_nofork =
false;
74 bool KUniqueApplication::Private::s_multipleInstances =
false;
76 bool KUniqueApplication::Private::s_handleAutoStarted =
false;
88 kunique_options.
add(
"nofork",
ki18n(
"Do not run in the background."));
90 kunique_options.
add(
"psn",
ki18n(
"Internally added if launched from Finder"));
98 QDBusConnectionInterface* dbusService = 0;
99 QDBusConnection sessionBus = QDBusConnection::sessionBus();
100 if (!sessionBus.isConnected() || !(dbusService = sessionBus.interface()))
102 kError() <<
"KUniqueApplication: Cannot find the D-Bus session server: " << sessionBus.lastError().message() << endl;
116 if( s_kuniqueapplication_startCalled )
118 s_kuniqueapplication_startCalled =
true;
121 #if defined(Q_WS_WIN) || defined(Q_WS_MACX)
122 Private::s_nofork =
true;
125 Private::s_nofork = !args->
isSet(
"fork");
131 appName.prepend(QLatin1String(
"local."));
133 foreach (
const QString& s, parts)
135 appName.prepend(QLatin1Char(
'.'));
139 bool forceNewProcess = Private::s_multipleInstances || flags &
NonUniqueInstance;
141 if (Private::s_nofork)
144 #if defined(Q_OS_DARWIN) || defined (Q_OS_MAC)
150 QString pid = QString::number(getpid());
152 appName = appName +
'-' + pid;
156 bool registered = dbusService->registerService(appName) == QDBusConnectionInterface::ServiceRegistered;
159 kError() <<
"KUniqueApplication: Can't setup D-Bus service. Probably already running."
161 #if defined(Q_WS_WIN) && !defined(_WIN32_WCE)
170 #if defined(Q_OS_DARWIN) || defined (Q_OS_MAC)
182 kError() <<
"KUniqueApplication: pipe() failed!" << endl;
185 int fork_result = fork();
186 switch(fork_result) {
188 kError() <<
"KUniqueApplication: fork() failed!" << endl;
198 appName.append(
"-").append(QString::number(getpid()));
200 QDBusReply<QDBusConnectionInterface::RegisterServiceReply> reply =
201 dbusService->registerService(appName);
202 if (!reply.isValid())
204 kError() <<
"KUniqueApplication: Can't setup D-Bus service." << endl;
206 ::write(fd[1], &result, 1);
209 if (reply == QDBusConnectionInterface::ServiceNotRegistered)
213 ::write(fd[1], &result, 1);
226 Display* disp = XOpenDisplay( NULL );
232 XCloseDisplay( disp );
235 #else //FIXME(E): Implement
239 ::write(fd[1], &result, 1);
246 appName.append(
"-").append(QString::number(fork_result));
251 int n = ::read(fd[0], &result, 1);
255 kError() <<
"KUniqueApplication: Pipe closed unexpectedly." << endl;
260 kError() <<
"KUniqueApplication: Error reading from pipe." << endl;
271 if (!dbusService->isServiceRegistered(appName))
273 kError() <<
"KUniqueApplication: Registering failed!" << endl;
276 QByteArray saved_args;
277 QDataStream ds(&saved_args, QIODevice::WriteOnly);
280 QByteArray new_asn_id;
288 new_asn_id =
id.id();
291 QDBusMessage msg = QDBusMessage::createMethodCall(appName,
"/MainApplication",
"org.kde.KUniqueApplication",
293 msg << new_asn_id << saved_args;
294 QDBusReply<int> reply = QDBusConnection::sessionBus().call(msg, QDBus::Block, INT_MAX);
296 if (!reply.isValid())
298 QDBusError err = reply.error();
300 <<
"Error message was: " << err.name() <<
": \"" << err.message() <<
"\"" << endl;
313 :
KApplication( GUIenabled, Private::initHack( configUnique )),
316 d->processingRequest =
false;
317 d->firstInstance =
true;
322 if (Private::s_nofork)
324 QTimer::singleShot( 0,
this, SLOT(_k_newInstanceNoFork()) );
330 Qt::HANDLE colormap,
bool configUnique)
331 :
KApplication( display, visual, colormap, Private::initHack( configUnique )),
334 d->processingRequest =
false;
335 d->firstInstance =
true;
340 if (Private::s_nofork)
342 QTimer::singleShot( 0,
this, SLOT(_k_newInstanceNoFork()) );
353 KComponentData KUniqueApplication::Private::initHack(
bool configUnique)
359 s_multipleInstances = cg.
readEntry(
"MultipleInstances",
false);
367 void KUniqueApplication::Private::_k_newInstanceNoFork()
369 s_handleAutoStarted =
false;
371 firstInstance =
false;
379 if( s_handleAutoStarted )
387 return d->firstInstance && isSessionRestored();
392 if (!d->firstInstance) {
394 if (!allWindows.isEmpty()) {
417 #ifndef KDE_NO_DEPRECATED
420 Private::s_handleAutoStarted =
false;
426 int KUniqueApplicationAdaptor::newInstance(
const QByteArray &asn_id,
const QByteArray &args)
428 if (!asn_id.isEmpty())
429 parent()->setStartupId(asn_id);
431 const int index = parent()->metaObject()->indexOfMethod(
"loadCommandLineOptionsForNewInstance");
436 QMetaObject::invokeMethod(parent(),
"loadCommandLineOptionsForNewInstance");
439 QDataStream ds(args);
442 int ret = parent()->newInstance();
444 parent()->d->firstInstance =
false;
448 #include "kuniqueapplication.moc"
449 #include "kuniqueapplication_p.moc"