diff --git a/kdecore/kernel/kaboutdata.h b/kdecore/kernel/kaboutdata.h index 2106ee0e..90c63955 100644 --- a/kdecore/kernel/kaboutdata.h +++ b/kdecore/kernel/kaboutdata.h @@ -373,9 +373,6 @@ public: * * Used by the automatic registration to D-Bus done by KApplication and KUniqueApplication. * - * IMPORTANT: if the organization domain is set, the .desktop file that describes your - * application should have an entry like X-DBUS-ServiceName=reversed_domain.kmyapp. - * * @param domain the domain name, for instance kde.org, koffice.org, kdevelop.org, etc. */ KAboutData& setOrganizationDomain(const QByteArray &domain); diff --git a/kdecore/services/kservice.cpp b/kdecore/services/kservice.cpp index a4c4417f..443f465d 100644 --- a/kdecore/services/kservice.cpp +++ b/kdecore/services/kservice.cpp @@ -242,17 +242,6 @@ void KServicePrivate::init( const KDesktopFile *config, KService* q ) parseActions(config, q); } - QString dbusStartupType = desktopGroup.readEntry("X-DBUS-StartupType").toLower(); - entryMap.remove(QLatin1String("X-DBUS-StartupType")); - if (dbusStartupType == QLatin1String("unique")) - m_DBUSStartusType = KService::DBusUnique; - else if (dbusStartupType == QLatin1String("multi")) - m_DBUSStartusType = KService::DBusMulti; - else if (dbusStartupType == QLatin1String("wait")) - m_DBUSStartusType = KService::DBusWait; - else - m_DBUSStartusType = KService::DBusNone; - m_strDesktopEntryName = _name.toLower(); m_bAllowAsDefault = desktopGroup.readEntry("AllowDefault", true); @@ -319,14 +308,13 @@ void KServicePrivate::parseActions(const KDesktopFile *config, KService* q) void KServicePrivate::load(QDataStream& s) { qint8 def, term; - qint8 dst, initpref; + qint8 initpref; // NOTE: make sure to update the version number in ksycoca.cpp s >> m_strType >> m_strName >> m_strExec >> m_strIcon >> term >> m_strTerminalOptions >> m_strPath >> m_strComment >> def >> m_mapProps >> m_strLibrary - >> dst >> m_strDesktopEntryName >> initpref >> m_lstKeywords >> m_strGenName @@ -334,7 +322,6 @@ void KServicePrivate::load(QDataStream& s) m_bAllowAsDefault = (bool)def; m_bTerminal = (bool)term; - m_DBUSStartusType = (KService::DBusStartupType) dst; m_initialPreference = initpref; m_bValid = true; @@ -345,14 +332,12 @@ void KServicePrivate::save(QDataStream& s) KSycocaEntryPrivate::save( s ); qint8 def = m_bAllowAsDefault, initpref = m_initialPreference; qint8 term = m_bTerminal; - qint8 dst = (qint8) m_DBUSStartusType; // NOTE: make sure to update the version number in ksycoca.cpp s << m_strType << m_strName << m_strExec << m_strIcon << term << m_strTerminalOptions << m_strPath << m_strComment << def << m_mapProps << m_strLibrary - << dst << m_strDesktopEntryName << initpref << m_lstKeywords << m_strGenName @@ -829,12 +814,6 @@ QString KService::desktopEntryName() const return d->m_strDesktopEntryName; } -KService::DBusStartupType KService::dbusStartupType() const -{ - Q_D(const KService); - return d->m_DBUSStartusType; -} - QString KService::path() const { Q_D(const KService); diff --git a/kdecore/services/kservice.h b/kdecore/services/kservice.h index 9eb18d17..c40b3456 100644 --- a/kdecore/services/kservice.h +++ b/kdecore/services/kservice.h @@ -163,26 +163,6 @@ public: */ QString storageId() const; - /** - * Describes the DBUS Startup type of the service. - * @li None - This service has no DBUS support - * @li Unique - This service provides a unique DBUS service. - * The service name is equal to the desktopEntryName. - * @li Multi - This service provides a DBUS service which can be run - * with multiple instances in parallel. The service name of - * an instance is equal to the desktopEntryName + "-" + - * the PID of the process. - * @li Wait - This service has no DBUS support, the launcher will wait - * till it is finished. - */ - enum DBusStartupType { DBusNone = 0, DBusUnique, DBusMulti, DBusWait }; - - /** - * Returns the DBUSStartupType supported by this service. - * @return the DBUSStartupType supported by this service - */ - DBusStartupType dbusStartupType() const; - /** * Returns the working directory to run the program in. * @return the working directory to run the program in, @@ -268,8 +248,8 @@ public: QList actions() const; /** - * Checks whether this service can handle several files as - * startup arguments. + * Checks whether this service can handle several files as startup arguments. + * * @return true if multiple files may be passed to this service at * startup. False if only one file at a time may be passed. */ diff --git a/kdecore/services/kservice_p.h b/kdecore/services/kservice_p.h index 214cdb2a..93771cbf 100644 --- a/kdecore/services/kservice_p.h +++ b/kdecore/services/kservice_p.h @@ -87,7 +87,6 @@ public: QVector m_serviceTypes; QString m_strDesktopEntryName; - KService::DBusStartupType m_DBUSStartusType; QMap m_mapProps; QStringList m_lstKeywords; QString m_strGenName; diff --git a/kdecore/tests/kservicetest.cpp b/kdecore/tests/kservicetest.cpp index 71cacd95..93f61e10 100644 --- a/kdecore/tests/kservicetest.cpp +++ b/kdecore/tests/kservicetest.cpp @@ -230,20 +230,6 @@ static bool offerListHasService( const KService::List& offers, return found; } -void KServiceTest::testDBUSStartupType() -{ - if ( !KSycoca::isAvailable() ) - QSKIP( "ksycoca not available", SkipAll ); - if ( !m_hasKde4Konsole ) - QSKIP( "kde4-konsole.desktop not available", SkipAll ); - //KService::Ptr konsole = KService::serviceByMenuId( "kde4-konsole.desktop" ); - KService::Ptr konsole = KService::serviceByDesktopName( "konsole" ); - QVERIFY(konsole); - QCOMPARE(konsole->menuId(), QString("kde4-konsole.desktop")); - //qDebug() << konsole->entryPath(); - QCOMPARE((int)konsole->dbusStartupType(), (int)KService::DBusMulti); -} - void KServiceTest::testByStorageId() { if ( !KSycoca::isAvailable() ) diff --git a/kdecore/tests/kservicetest.h b/kdecore/tests/kservicetest.h index 72f7a18d..258e9e63 100644 --- a/kdecore/tests/kservicetest.h +++ b/kdecore/tests/kservicetest.h @@ -37,7 +37,6 @@ private Q_SLOTS: void testTraderConstraints(); void testHasServiceType1(); void testHasServiceType2(); - void testDBUSStartupType(); void testByStorageId(); void testActionsAndDataStream(); void testServiceGroups(); diff --git a/kdeui/kernel/ktoolinvocation.h b/kdeui/kernel/ktoolinvocation.h index 3324b259..34f46d60 100644 --- a/kdeui/kernel/ktoolinvocation.h +++ b/kdeui/kernel/ktoolinvocation.h @@ -33,33 +33,7 @@ class KUrl; /** - * KToolInvocation: for starting other programs - * - * @section desktopfiles Desktop files for startServiceBy - * - * The way a service gets started depends on the 'X-DBUS-StartupType' - * entry in the desktop file of the service: - * - * There are three possibilities: - * @li X-DBUS-StartupType=None (default) - * Always start a new service, - * don't wait till the service registers with D-Bus. - * @li X-DBUS-StartupType=Multi - * Always start a new service, - * wait until the service has registered with D-Bus. - * @li X-DBUS-StartupType=Unique - * Only start the service if it isn't already running, - * wait until the service has registered with D-Bus. - * The .desktop file can specify the name that the application will use when registering - * using X-DBUS-ServiceName=org.domain.mykapp. Otherwise org.kde.binaryname is assumed. - * - * @section thread Multi-threading - * - * The static members (apart from self()), have to be called from the QApplication main thread. - * Calls to members are only allowed if there is a Q(Core)Application object created - * If you call the members with signal/slot connections across threads, you can't use the return values - * If a function is called from the wrong thread and it has a return value -1 is returned - * Investigate if this is really needed or if D-Bus is threadsafe anyway + * KToolInvocation starts other programs */ class KDECORE_EXPORT KToolInvocation : public QObject { @@ -276,13 +250,6 @@ public: static int kdeinitExecWait(const QString &name, const QStringList &args = QStringList(), QString *error = 0, const QByteArray &startup_id = QByteArray()); -Q_SIGNALS: - /** - * Hook for KApplication in kdeui - * @internal - */ - void kapplication_hook(QStringList &env , QByteArray &startup_id); - private: /** * @internal diff --git a/kdeui/kernel/kuniqueapplication.h b/kdeui/kernel/kuniqueapplication.h index 20d3a37c..3e36e2e0 100644 --- a/kdeui/kernel/kuniqueapplication.h +++ b/kdeui/kernel/kuniqueapplication.h @@ -39,9 +39,6 @@ * your application can only be opened once per user or once per host, you * need to ensure this independently of KUniqueApplication. * - * The .desktop file for the application should state X-DBUS-StartupType=Unique, - * see ktoolinvocation.h - * * If your application is used to open files, it should also support the --tempfile * option (see KCmdLineArgs::addTempFileOption()), to delete tempfiles after use. * Add X-KDE-HasTempFileOption=true to the .desktop file to indicate this. diff --git a/kinit/klauncher_adaptor.cpp b/kinit/klauncher_adaptor.cpp index 22cbd3ec..ecdb21d3 100644 --- a/kinit/klauncher_adaptor.cpp +++ b/kinit/klauncher_adaptor.cpp @@ -19,7 +19,6 @@ #include "klauncher_adaptor.h" #include "krun.h" #include "kstandarddirs.h" -#include "kservice.h" #include "kautostart.h" #include "kshell.h" #include "kconfiggroup.h" @@ -28,10 +27,6 @@ #include #include #include -#include -#include -#include -#include #include #include @@ -59,13 +54,138 @@ static inline int getExitStatus(const pid_t pid) return WEXITSTATUS(pidstate); } +static inline bool isASNValid(const QByteArray &asn) +{ + return (!asn.isEmpty() && asn != "0"); +} + +KLauncherProcess::KLauncherProcess(QObject *parent) + : QProcess(parent), + m_kstartupinfo(nullptr), + m_startuptimer(nullptr) +{ + connect( + this, SIGNAL(stateChanged(QProcess::ProcessState)), + this, SLOT(slotProcessStateChanged(QProcess::ProcessState)) + ); +} + +void KLauncherProcess::setupStartup(const QByteArray &startup_id, const QString &appexe, + const KService::Ptr kservice, const qint64 timeout) +{ + Q_ASSERT(m_kstartupinfoid.none() == true); + bool startupsilent = false; + QByteArray startupwmclass; + if (KRun::checkStartupNotify(kservice.data(), &startupsilent, &startupwmclass)) { + m_kstartupinfoid.initId(!isASNValid(startup_id) ? KStartupInfo::createNewStartupId() : startup_id); + kDebug() << "setting up ASN for" << kservice->entryPath() << m_kstartupinfoid.id(); + m_kstartupinfodata.setHostname(); + m_kstartupinfodata.setBin(QFileInfo(appexe).fileName()); + m_kstartupinfodata.setDescription(i18n("Launching %1", kservice->name())); + m_kstartupinfodata.setIcon(kservice->icon()); + m_kstartupinfodata.setApplicationId(kservice->entryPath()); + m_kstartupinfodata.setSilent(startupsilent ? KStartupInfoData::Yes : KStartupInfoData::No); + m_kstartupinfodata.setWMClass(startupwmclass); + QProcessEnvironment processenv = QProcess::processEnvironment(); + processenv.insert(QString::fromLatin1("DESKTOP_STARTUP_ID"), m_kstartupinfoid.id()); + QProcess::setProcessEnvironment(processenv); + sendSIStart(timeout); + } else if (isASNValid(startup_id)) { + kDebug() << "setting up ASN for" << startup_id; + m_kstartupinfoid.initId(startup_id); + m_kstartupinfodata.setHostname(); + m_kstartupinfodata.setBin(QFileInfo(appexe).fileName()); + m_kstartupinfodata.setDescription(i18n("Launching %1", m_kstartupinfodata.bin())); + QProcessEnvironment processenv = QProcess::processEnvironment(); + processenv.insert(QString::fromLatin1("DESKTOP_STARTUP_ID"), QString::fromLatin1(startup_id.constData(), startup_id.size())); + QProcess::setProcessEnvironment(processenv); + sendSIStart(timeout); + } else { + kDebug() << "no ASN for" << appexe; + } +} + +void KLauncherProcess::slotProcessStateChanged(QProcess::ProcessState state) +{ + kDebug() << "process state changed" << this << state; + if (state == QProcess::Starting && !m_kstartupinfoid.none()) { + m_kstartupinfodata.addPid(QProcess::pid()); + sendSIChange(); + } else if (state == QProcess::NotRunning && !m_kstartupinfoid.none()) { + sendSIFinish(); + } +} + +void KLauncherProcess::slotStartupRemoved(const KStartupInfoId &kstartupinfoid, + const KStartupInfoData &kstartupinfodata) +{ + if (m_kstartupinfoid.none()) { + return; + } + + kDebug() << "startup removed" << kstartupinfoid.id() << m_kstartupinfoid.id(); + if (kstartupinfoid.id() == m_kstartupinfoid.id() || kstartupinfodata.is_pid(QProcess::pid())) { + kDebug() << "startup done for process" << this; + sendSIFinish(); + } +} + +void KLauncherProcess::slotStartupTimeout() +{ + kWarning() << "timed out while waiting for process" << this; + sendSIFinish(); +} + +void KLauncherProcess::sendSIStart(const qint64 timeout) +{ + if (m_kstartupinfoid.none()) { + return; + } + + kDebug() << "sending ASN start for" << m_kstartupinfodata.bin(); + m_kstartupinfo = new KStartupInfo(this); + connect( + m_kstartupinfo, SIGNAL(gotRemoveStartup(KStartupInfoId,KStartupInfoData)), + this, SLOT(slotStartupRemoved(KStartupInfoId,KStartupInfoData)) + ); + + m_startuptimer = new QTimer(this); + m_startuptimer->setSingleShot(true); + m_startuptimer->setInterval(timeout); + connect(m_startuptimer, SIGNAL(timeout()), this, SLOT(slotStartupTimeout())); + m_startuptimer->start(); + + KStartupInfo::sendStartup(m_kstartupinfoid, m_kstartupinfodata); +} + +void KLauncherProcess::sendSIChange() +{ + if (m_kstartupinfoid.none()) { + return; + } + kDebug() << "sending ASN change for" << m_kstartupinfodata.bin(); + KStartupInfo::sendChange(m_kstartupinfoid, m_kstartupinfodata); +} + +void KLauncherProcess::sendSIFinish() +{ + if (m_kstartupinfoid.none()) { + return; + } + kDebug() << "sending ASN finish for" << m_kstartupinfodata.bin(); + KStartupInfo::sendFinish(m_kstartupinfoid, m_kstartupinfodata); + m_kstartupinfoid = KStartupInfoId(); + m_kstartupinfodata = KStartupInfoData(); + if (m_startuptimer) { + m_startuptimer->stop(); + } +} + KLauncherAdaptor::KLauncherAdaptor(QObject *parent) : QDBusAbstractAdaptor(parent), - m_dbusconnectioninterface(nullptr), - m_startuptimeout(s_startuptimeout * 1000) + m_startuptimeout(0) { m_environment = QProcessEnvironment::systemEnvironment(); - m_dbusconnectioninterface = QDBusConnection::sessionBus().interface(); // TODO: config watch KConfig klauncherconfig("klaunchrc", KConfig::NoGlobals); @@ -78,7 +198,6 @@ KLauncherAdaptor::KLauncherAdaptor(QObject *parent) KLauncherAdaptor::~KLauncherAdaptor() { - kDebug() << "terminating processes" << m_processes.size(); cleanup(); } @@ -154,8 +273,9 @@ void KLauncherAdaptor::exec_blind(const QString &name, const QStringList &arg_li void KLauncherAdaptor::cleanup() { + kDebug() << "terminating processes" << m_processes.size(); while (!m_processes.isEmpty()) { - QProcess* process = m_processes.takeLast(); + KLauncherProcess* process = m_processes.takeLast(); disconnect(process, 0, this, 0); process->terminate(); if (!process->waitForFinished(s_processtimeout)) { @@ -173,9 +293,8 @@ int KLauncherAdaptor::kdeinit_exec(const QString &app, const QStringList &args, int KLauncherAdaptor::kdeinit_exec_wait(const QString &app, const QStringList &args, const QStringList &envs, const QString &startup_id) { - QMutexLocker locker(&m_mutex); qint64 pid = 0; - int result = startProgram(app, args, envs, startup_id, QDir::currentPath(), pid); + int result = startProgram(app, args, envs, startup_id, QDir::currentPath(), pid, m_startuptimeout); if (result != KLauncherAdaptor::NoError) { return result; } @@ -191,9 +310,8 @@ int KLauncherAdaptor::kdeinit_exec_wait(const QString &app, const QStringList &a int KLauncherAdaptor::kdeinit_exec_with_workdir(const QString &app, const QStringList &args, const QStringList &envs, const QString &startup_id, const QString &workdir) { - QMutexLocker locker(&m_mutex); qint64 pid = 0; - return startProgram(app, args, envs, startup_id, workdir, pid); + return startProgram(app, args, envs, startup_id, workdir, pid, m_startuptimeout); } void KLauncherAdaptor::setLaunchEnv(const QString &name, const QString &value) @@ -218,29 +336,12 @@ int KLauncherAdaptor::start_service_by_desktop_name(const QString &serviceName, int KLauncherAdaptor::start_service_by_desktop_path(const QString &serviceName, const QStringList &urls, const QStringList &envs, const QString &startup_id) { - QMutexLocker locker(&m_mutex); KService::Ptr kservice = KService::serviceByStorageId(serviceName); if (!kservice) { kWarning() << "invalid service path" << serviceName; return KLauncherAdaptor::ServiceError; } - const KService::DBusStartupType dbusstartuptype = kservice->dbusStartupType(); - QString dbusServiceName = kservice->property(QString::fromLatin1("X-DBUS-ServiceName"), QVariant::String).toString(); - // any unique Katana application/service checks if another instance is running, if it is - // already running starting it may raise its window instead (if it uses KUniqueApplication) - if (dbusstartuptype == KService::DBusUnique && !dbusServiceName.startsWith(QLatin1String("org.kde."))) { - QDBusReply sessionreply = m_dbusconnectioninterface->isServiceRegistered(dbusServiceName); - if (!sessionreply.isValid()) { - kWarning() << "invalid D-Bus reply for" << dbusServiceName; - return KLauncherAdaptor::DBusError; - } - if (sessionreply.value() == true) { - kDebug() << "service already started" << dbusServiceName; - return KLauncherAdaptor::NoError; - } - } if (urls.size() > 1 && !kservice->allowMultipleFiles()) { - // TODO: start multiple instances for each URL kWarning() << "service does not support multiple files" << serviceName; return KLauncherAdaptor::ServiceError; } @@ -249,80 +350,10 @@ int KLauncherAdaptor::start_service_by_desktop_path(const QString &serviceName, kWarning() << "could not process service" << kservice->entryPath(); return KLauncherAdaptor::ArgumentsError; } - kDebug() << "starting" << kservice->entryPath() << urls << dbusServiceName; + kDebug() << "starting" << kservice->entryPath() << urls; const QString program = programandargs.takeFirst(); - const QStringList programargs = programandargs; - Q_ASSERT(m_kstartupinfoid.none() == true); - m_kstartupinfoid = KStartupInfoId(); - m_kstartupinfodata = KStartupInfoData(); - bool startupsilent = false; - QByteArray startupwmclass; - if (KRun::checkStartupNotify(kservice.data(), &startupsilent, &startupwmclass)) { - m_kstartupinfoid.initId(startup_id.toLatin1()); - m_kstartupinfodata.setBin(QFileInfo(program).fileName()); - m_kstartupinfodata.setDescription(i18n("Launching %1", kservice->name())); - m_kstartupinfodata.setIcon(kservice->icon()); - m_kstartupinfodata.setApplicationId(kservice->entryPath()); - m_kstartupinfodata.setSilent(startupsilent ? KStartupInfoData::Yes : KStartupInfoData::No); - m_kstartupinfodata.setWMClass(startupwmclass); - sendSIStart(); - } else { - kDebug() << "no ASN for" << kservice->entryPath(); - } qint64 pid = 0; - int result = startProgram(program, programargs, envs, QString(), QDir::currentPath(), pid); - if (result != KLauncherAdaptor::NoError) { - // sendSIFinish() is called on exec error - return result; - } - if (dbusstartuptype == KService::DBusNone) { - sendSIFinish(); - return result; - } else if (dbusstartuptype != KService::DBusNone && dbusServiceName.isEmpty()) { - // not going to guess what service to wait for, bud - kWarning() << "X-DBUS-ServiceName not specified in" << kservice->entryPath(); - sendSIFinish(); - return result; - } else if (dbusstartuptype == KService::DBusMulti) { - dbusServiceName.append(QLatin1Char('-')); - dbusServiceName.append(QString::number(pid)); - } - kDebug() << "waiting for" << pid << dbusServiceName << m_startuptimeout; - QElapsedTimer elapsedtime; - elapsedtime.start(); - while (true) { - QDBusReply sessionreply = m_dbusconnectioninterface->isServiceRegistered(dbusServiceName); - if (!sessionreply.isValid()) { - kWarning() << "invalid D-Bus reply for" << dbusServiceName; - sendSIFinish(); - return KLauncherAdaptor::DBusError; - } - // the service unregistered - if (sessionreply.value() == false && dbusstartuptype == KService::DBusWait) { - kDebug() << "service unregistered" << dbusServiceName; - break; - } - // the service registered - if (sessionreply.value() == true && dbusstartuptype != KService::DBusWait) { - kDebug() << "service registered" << dbusServiceName; - break; - } - // or the program is just not registering the service at all - if (elapsedtime.elapsed() >= m_startuptimeout && dbusstartuptype != KService::DBusWait) { - kWarning() << "timed out while waiting for service" << dbusServiceName; - break; - } - // or the program is not even running - if (!isPIDAlive(pid)) { - kWarning() << "service process is not running" << dbusServiceName; - result = getExitStatus(pid); - break; - } - QApplication::processEvents(QEventLoop::AllEvents, s_eventstime); - QThread::msleep(s_sleeptime); - } - sendSIFinish(); - return result; + return startProgram(program, programandargs, envs, QString(), QDir::currentPath(), pid, m_startuptimeout, kservice); } #ifdef KLAUNCHER_DEBUG @@ -332,21 +363,9 @@ QStringList KLauncherAdaptor::environment() const } #endif -void KLauncherAdaptor::slotProcessStateChanged(QProcess::ProcessState state) -{ - QProcess* process = qobject_cast(sender()); - kDebug() << "process state changed" << process << state; - if (state == QProcess::Starting && !m_kstartupinfoid.none()) { - m_kstartupinfodata.addPid(process->pid()); - sendSIChange(); - } else if (state == QProcess::NotRunning && m_kstartupinfodata.is_pid(process->pid())) { - sendSIFinish(); - } -} - void KLauncherAdaptor::slotProcessFinished(int exitcode) { - QProcess* process = qobject_cast(sender()); + KLauncherProcess* process = qobject_cast(sender()); kDebug() << "process finished" << process << exitcode; m_processes.removeAll(process); } @@ -364,7 +383,9 @@ QString KLauncherAdaptor::findExe(const QString &app) const return KStandardDirs::findExe(app, environmentpath); } -int KLauncherAdaptor::startProgram(const QString &app, const QStringList &args, const QStringList &envs, const QString &startup_id, const QString &workdir, qint64 &pid) +int KLauncherAdaptor::startProgram(const QString &app, const QStringList &args, const QStringList &envs, + const QString &startup_id, const QString &workdir, qint64 &pid, + const qint64 timeout, const KService::Ptr kservice) { const QString appexe = findExe(app); if (appexe.isEmpty()) { @@ -372,8 +393,7 @@ int KLauncherAdaptor::startProgram(const QString &app, const QStringList &args, return KLauncherAdaptor::FindError; } - QProcess* process = new QProcess(this); - connect(process, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(slotProcessStateChanged(QProcess::ProcessState))); + KLauncherProcess* process = new KLauncherProcess(this); connect(process, SIGNAL(finished(int)), this, SLOT(slotProcessFinished(int))); m_processes.append(process); QProcessEnvironment processenv = m_environment; @@ -390,61 +410,20 @@ int KLauncherAdaptor::startProgram(const QString &app, const QStringList &args, } process->setProcessEnvironment(processenv); process->setWorkingDirectory(workdir); - kDebug() << "starting" << appexe << args << envs; - if (!startup_id.isEmpty()) { - Q_ASSERT(m_kstartupinfoid.none() == true); - m_kstartupinfoid = KStartupInfoId(); - m_kstartupinfodata = KStartupInfoData(); - m_kstartupinfoid.initId(startup_id.toLatin1()); - m_kstartupinfodata.setBin(QFileInfo(appexe).fileName()); - m_kstartupinfodata.setDescription(i18n("Launching %1", m_kstartupinfodata.bin())); - sendSIStart(); - } + process->setupStartup(startup_id.toLatin1(), appexe, kservice, timeout); + kDebug() << "starting" << appexe << args << envs << workdir; process->start(appexe, args); while (process->state() == QProcess::Starting) { QApplication::processEvents(QEventLoop::AllEvents, s_eventstime); QThread::msleep(s_sleeptime); } if (process->error() == QProcess::FailedToStart || process->error() == QProcess::Crashed) { - sendSIFinish(); kWarning() << "could not start" << appexe; return KLauncherAdaptor::ExecError; } - if (!startup_id.isEmpty()) { - sendSIFinish(); - } pid = process->pid(); return KLauncherAdaptor::NoError; } -void KLauncherAdaptor::sendSIStart() const -{ - if (m_kstartupinfoid.none()) { - return; - } - kDebug() << "sending ASN start for" << m_kstartupinfodata.bin(); - KStartupInfo::sendStartup(m_kstartupinfoid, m_kstartupinfodata); -} - -void KLauncherAdaptor::sendSIChange() -{ - if (m_kstartupinfoid.none()) { - return; - } - kDebug() << "sending ASN change for" << m_kstartupinfodata.bin(); - KStartupInfo::sendChange(m_kstartupinfoid, m_kstartupinfodata); -} - -void KLauncherAdaptor::sendSIFinish() -{ - if (m_kstartupinfoid.none()) { - return; - } - kDebug() << "sending ASN finish for" << m_kstartupinfodata.bin(); - KStartupInfo::sendFinish(m_kstartupinfoid, m_kstartupinfodata); - m_kstartupinfoid = KStartupInfoId(); - m_kstartupinfodata = KStartupInfoData(); -} - #include "moc_klauncher_adaptor.cpp" diff --git a/kinit/klauncher_adaptor.h b/kinit/klauncher_adaptor.h index d4163f67..4216e23e 100644 --- a/kinit/klauncher_adaptor.h +++ b/kinit/klauncher_adaptor.h @@ -20,15 +20,41 @@ #define KLAUNCHER_ADAPTOR_H #include "kstartupinfo.h" +#include "kservice.h" #include -#include -#include #include -#include +#include // #define KLAUNCHER_DEBUG +class KLauncherProcess : public QProcess +{ + Q_OBJECT +public: + explicit KLauncherProcess(QObject *parent); + + void setupStartup(const QByteArray &startup_id, const QString &appexe, + const KService::Ptr kservice, const qint64 timeout); + +private Q_SLOTS: + void slotProcessStateChanged(QProcess::ProcessState state); + void slotStartupRemoved(const KStartupInfoId &id, const KStartupInfoData &data); + void slotStartupTimeout(); + +private: + Q_DISABLE_COPY(KLauncherProcess); + + void sendSIStart(const qint64 timeout); + void sendSIChange(); + void sendSIFinish(); + + KStartupInfo* m_kstartupinfo; + QTimer* m_startuptimer; + KStartupInfoId m_kstartupinfoid; + KStartupInfoData m_kstartupinfodata; +}; + // Adaptor class for interface org.kde.KLauncher class KLauncherAdaptor: public QDBusAbstractAdaptor { @@ -40,8 +66,7 @@ public: ServiceError = -1, FindError = -2, ArgumentsError = -3, - ExecError = -4, - DBusError = -5 + ExecError = -4 }; KLauncherAdaptor(QObject *parent); @@ -75,23 +100,17 @@ Q_SIGNALS: void autoStart2Done(); private Q_SLOTS: - void slotProcessStateChanged(QProcess::ProcessState state); void slotProcessFinished(int exitcode); private: QString findExe(const QString &app) const; - int startProgram(const QString &app, const QStringList &args, const QStringList &envs, const QString &startup_id, const QString &workdir, qint64 &pid); - void sendSIStart() const; - void sendSIChange(); - void sendSIFinish(); + int startProgram(const QString &app, const QStringList &args, const QStringList &envs, + const QString &startup_id, const QString &workdir, qint64 &pid, + const qint64 timeout, const KService::Ptr kservice = KService::Ptr(nullptr)); - QMutex m_mutex; QProcessEnvironment m_environment; - QDBusConnectionInterface* m_dbusconnectioninterface; qint64 m_startuptimeout; - KStartupInfoId m_kstartupinfoid; - KStartupInfoData m_kstartupinfodata; - QList m_processes; + QList m_processes; QStringList m_autostart; }; diff --git a/kio/application.desktop b/kio/application.desktop index 74a8269a..c5bcce6f 100644 --- a/kio/application.desktop +++ b/kio/application.desktop @@ -118,12 +118,6 @@ Type=QString [PropertyDef::StartupNotify] Type=bool -[PropertyDef::X-DBUS-ServiceName] -Type=QString - -[PropertyDef::X-DBUS-StartupType] -Type=QString - [PropertyDef::X-KDE-ParentApp] Type=QString diff --git a/kio/kfile/kpropertiesdesktopadvbase.ui b/kio/kfile/kpropertiesdesktopadvbase.ui index 6773a664..015ce6ab 100644 --- a/kio/kfile/kpropertiesdesktopadvbase.ui +++ b/kio/kfile/kpropertiesdesktopadvbase.ui @@ -144,67 +144,12 @@ - - - - &D-Bus registration: - - - dbusCombo - - - - - - - - None - - - - - Multiple Instances - - - - - Single Instance - - - - - Run Until Finished - - - - - - - - Qt::Horizontal - - - QSizePolicy::Expanding - - - - 50 - 20 - - - - - - KComboBox - QComboBox -
kcombobox.h
-
KLineEdit QLineEdit diff --git a/kio/kfile/kpropertiesdialog.cpp b/kio/kfile/kpropertiesdialog.cpp index a58deb43..68db57fb 100644 --- a/kio/kfile/kpropertiesdialog.cpp +++ b/kio/kfile/kpropertiesdialog.cpp @@ -2989,6 +2989,10 @@ public: KDesktopPropsPluginPrivate() : w(new Ui_KPropertiesDesktopBase()) , m_frame(new QFrame()) + , m_terminalBool(false) + , m_suidBool(false) + , m_startupBool(false) + , m_systrayBool(false) { } ~KDesktopPropsPluginPrivate() @@ -3002,8 +3006,6 @@ public: QString m_origCommandStr; QString m_terminalOptionStr; QString m_suidUserStr; - QString m_dbusStartupType; - QString m_dbusServiceName; QString m_origDesktopFile; bool m_terminalBool; bool m_suidBool; @@ -3078,11 +3080,7 @@ KDesktopPropsPlugin::KDesktopPropsPlugin(KPropertiesDialog *props) d->m_terminalOptionStr = config.readEntry( "TerminalOptions"); d->m_suidBool = config.readEntry("X-KDE-SubstituteUID", false); d->m_suidUserStr = config.readEntry("X-KDE-Username"); - d->m_startupBool = config.readEntry("StartupNotify", true); - d->m_dbusStartupType = config.readEntry("X-DBUS-StartupType").toLower(); - // ### should there be a GUI for this setting? - // At least we're copying it over to the local file, to avoid side effects (#157853) - d->m_dbusServiceName = config.readEntry("X-DBUS-ServiceName"); + d->m_startupBool = config.readEntry("StartupNotify", false); const QStringList mimeTypes = config.readXdgListEntry("MimeType"); @@ -3183,8 +3181,6 @@ void KDesktopPropsPlugin::checkCommandChanged() { if (KRun::binaryName(d->w->commandEdit->text(), true) != KRun::binaryName(d->m_origCommandStr, true)) { d->m_origCommandStr = d->w->commandEdit->text(); - d->m_dbusStartupType.clear(); // Reset - d->m_dbusServiceName.clear(); } } @@ -3254,8 +3250,7 @@ void KDesktopPropsPlugin::applyChanges() config.writeEntry("X-KDE-SubstituteUID", d->m_suidBool); config.writeEntry("X-KDE-Username", d->m_suidUserStr); config.writeEntry("StartupNotify", d->m_startupBool); - config.writeEntry("X-DBUS-StartupType", d->m_dbusStartupType); - config.writeEntry("X-DBUS-ServiceName", d->m_dbusServiceName); +#warning TODO: StartupWMClass config.sync(); // KSycoca update needed? @@ -3327,16 +3322,6 @@ void KDesktopPropsPlugin::slotAdvanced() w.startupInfoCheck->setChecked(d->m_startupBool); w.systrayCheck->setChecked(d->m_systrayBool); - if (d->m_dbusStartupType == QLatin1String("unique")) { - w.dbusCombo->setCurrentIndex(2); - } else if (d->m_dbusStartupType == QLatin1String("multi")) { - w.dbusCombo->setCurrentIndex(1); - } else if (d->m_dbusStartupType == QLatin1String("wait")) { - w.dbusCombo->setCurrentIndex(3); - } else { - w.dbusCombo->setCurrentIndex(0); - } - // Provide username completion up to 1000 users. KCompletion *kcom = new KCompletion; kcom->setOrder(KCompletion::Sorted); @@ -3361,7 +3346,6 @@ void KDesktopPropsPlugin::slotAdvanced() connect(w.suidEdit, SIGNAL(textChanged(QString)), this, SIGNAL(changed()) ); connect(w.startupInfoCheck, SIGNAL(toggled(bool)), this, SIGNAL(changed()) ); connect(w.systrayCheck, SIGNAL(toggled(bool)), this, SIGNAL(changed()) ); - connect(w.dbusCombo, SIGNAL(activated(int)), this, SIGNAL(changed()) ); if (dlg.exec() == QDialog::Accepted) { d->m_terminalOptionStr = w.terminalEdit->text().trimmed(); @@ -3374,13 +3358,6 @@ void KDesktopPropsPlugin::slotAdvanced() if (w.terminalCloseCheck->isChecked()) { d->m_terminalOptionStr.append(" --noclose"); } - - switch(w.dbusCombo->currentIndex()) { - case 1: d->m_dbusStartupType = "multi"; break; - case 2: d->m_dbusStartupType = "unique"; break; - case 3: d->m_dbusStartupType = "wait"; break; - default: d->m_dbusStartupType = "none"; break; - } } }