00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kded.h"
00022 #include "kdedadaptor.h"
00023 #include "kdedmodule.h"
00024 #include "kbuildsycoca.h"
00025
00026 #include "kresourcelist.h"
00027 #include <kcrash.h>
00028
00029 #include <unistd.h>
00030 #include <stdlib.h>
00031 #include <signal.h>
00032 #include <time.h>
00033
00034 #include <QtCore/QDir>
00035 #include <QtCore/QFile>
00036 #include <QtCore/QTimer>
00037
00038 #include <QtDBus/QtDBus>
00039
00040 #include <kuniqueapplication.h>
00041 #include <kapplication.h>
00042 #include <kcmdlineargs.h>
00043 #include <kaboutdata.h>
00044 #include <klocale.h>
00045 #include <kglobal.h>
00046 #include <kconfig.h>
00047 #include <kconfiggroup.h>
00048 #include <kdebug.h>
00049 #include <kdirwatch.h>
00050 #include <kstandarddirs.h>
00051 #include <kservicetypetrader.h>
00052 #include <ktoolinvocation.h>
00053 #include <kde_file.h>
00054 #include "klauncher_iface.h"
00055
00056 #ifdef Q_WS_X11
00057 #include <qx11info_x11.h>
00058 #include <X11/Xlib.h>
00059 #include <fixx11h.h>
00060 #endif
00061
00062 #define KDED_EXENAME "kded4"
00063
00064 #define MODULES_PATH "/modules/"
00065
00066 Kded *Kded::_self = 0;
00067
00068 static bool checkStamps = true;
00069 static bool delayedCheck = false;
00070 static int HostnamePollInterval;
00071 static bool bCheckSycoca;
00072 static bool bCheckUpdates;
00073 static bool bCheckHostname;
00074
00075 extern QDBUS_EXPORT void qDBusAddSpyHook(void (*)(const QDBusMessage&));
00076
00077 static void runBuildSycoca(QObject *callBackObj=0, const char *callBackSlot=0)
00078 {
00079 const QString exe = KStandardDirs::findExe(KBUILDSYCOCA_EXENAME);
00080 Q_ASSERT(!exe.isEmpty());
00081 QStringList args;
00082 args.append("--incremental");
00083 if(checkStamps)
00084 args.append("--checkstamps");
00085 if(delayedCheck)
00086 args.append("--nocheckfiles");
00087 else
00088 checkStamps = false;
00089 if (callBackObj)
00090 {
00091 QVariantList argList;
00092 argList << exe << args << QStringList() << QString();
00093 KToolInvocation::klauncher()->callWithCallback("kdeinit_exec_wait", argList, callBackObj,
00094 callBackSlot);
00095 }
00096 else
00097 {
00098 KToolInvocation::kdeinitExecWait( exe, args );
00099
00100 if (callBackObj && callBackSlot) {
00101 QTimer::singleShot(0, callBackObj, callBackSlot);
00102 }
00103 }
00104 }
00105
00106 static void runKonfUpdate()
00107 {
00108 KToolInvocation::kdeinitExecWait( "kconf_update", QStringList(), 0, 0, "0" );
00109 }
00110
00111 static void runDontChangeHostname(const QByteArray &oldName, const QByteArray &newName)
00112 {
00113 QStringList args;
00114 args.append(QFile::decodeName(oldName));
00115 args.append(QFile::decodeName(newName));
00116 KToolInvocation::kdeinitExecWait( "kdontchangethehostname", args );
00117 }
00118
00119 Kded::Kded()
00120 : m_needDelayedCheck(false)
00121 {
00122 _self = this;
00123
00124 new KBuildsycocaAdaptor(this);
00125 new KdedAdaptor(this);
00126
00127 QDBusConnection session = QDBusConnection::sessionBus();
00128 session.registerObject("/kbuildsycoca", this);
00129 session.registerObject("/kded", this);
00130
00131 qDBusAddSpyHook(messageFilter);
00132
00133 m_pTimer = new QTimer(this);
00134 m_pTimer->setSingleShot( true );
00135 connect(m_pTimer, SIGNAL(timeout()), this, SLOT(recreate()));
00136
00137 m_pDirWatch = 0;
00138
00139 m_recreateCount = 0;
00140 m_recreateBusy = false;
00141 }
00142
00143 Kded::~Kded()
00144 {
00145 _self = 0;
00146 m_pTimer->stop();
00147 delete m_pTimer;
00148 delete m_pDirWatch;
00149
00150 for (QHash<QByteArray,KDEDModule*>::iterator
00151 it(m_modules.begin()), itEnd(m_modules.end());
00152 it != itEnd; ++it)
00153 {
00154 KDEDModule* module(it.value());
00155
00156
00157
00158 disconnect(module, SIGNAL(moduleDeleted(KDEDModule*)),
00159 this, SLOT(slotKDEDModuleRemoved(KDEDModule*)));
00160
00161 delete module;
00162 }
00163 }
00164
00165
00166
00167
00168 void Kded::messageFilter(const QDBusMessage &message)
00169 {
00170
00171 if (!self())
00172 return;
00173
00174 if (message.type() != QDBusMessage::MethodCallMessage)
00175 return;
00176
00177 QString obj = message.path();
00178 if (!obj.startsWith(MODULES_PATH))
00179 return;
00180
00181
00182 obj = obj.mid(strlen(MODULES_PATH));
00183 if (obj == "ksycoca")
00184 return;
00185
00186
00187 int index = obj.indexOf('/');
00188 if (index!=-1) {
00189 obj = obj.left(index);
00190 }
00191
00192 if (self()->m_dontLoad.value(obj, 0))
00193 return;
00194
00195 KDEDModule *module = self()->loadModule(obj, true);
00196 if (!module) {
00197 kDebug(7020) << "Failed to load module for " << obj;
00198 }
00199 Q_UNUSED(module);
00200 }
00201
00202 void Kded::initModules()
00203 {
00204 m_dontLoad.clear();
00205 bool kde_running = !qgetenv( "KDE_FULL_SESSION" ).isEmpty();
00206
00207 const QByteArray sessionUID = qgetenv( "KDE_SESSION_UID" );
00208 if( !sessionUID.isEmpty() && uid_t( sessionUID.toInt() ) != getuid())
00209 kde_running = false;
00210
00211 const KService::List kdedModules = KServiceTypeTrader::self()->query("KDEDModule");
00212 for(KService::List::ConstIterator it = kdedModules.begin(); it != kdedModules.end(); ++it)
00213 {
00214 KService::Ptr service = *it;
00215
00216 bool autoload = isModuleAutoloaded(service);
00217
00218
00219 QVariant phasev = service->property("X-KDE-Kded-phase", QVariant::Int );
00220 int phase = phasev.isValid() ? phasev.toInt() : 2;
00221 bool prevent_autoload = false;
00222 switch( phase )
00223 {
00224 case 0:
00225 break;
00226 case 1:
00227 if( !kde_running )
00228 prevent_autoload = true;
00229 break;
00230 case 2:
00231 default:
00232 prevent_autoload = true;
00233 break;
00234 }
00235
00236
00237 if (autoload && !prevent_autoload) {
00238 if (!loadModule(service, false)) {
00239 continue;
00240 }
00241 }
00242
00243
00244 bool loadOnDemand = isModuleLoadedOnDemand(service);
00245 if (!loadOnDemand)
00246 noDemandLoad(service->desktopEntryName());
00247
00248
00249
00250 if (!loadOnDemand && !autoload)
00251 unloadModule(service->desktopEntryName().toLatin1());
00252 }
00253 }
00254
00255 void Kded::loadSecondPhase()
00256 {
00257 kDebug(7020) << "Loading second phase autoload";
00258 KSharedConfig::Ptr config = KGlobal::config();
00259 KService::List kdedModules = KServiceTypeTrader::self()->query("KDEDModule");
00260 for(KService::List::ConstIterator it = kdedModules.constBegin(); it != kdedModules.constEnd(); ++it)
00261 {
00262 KService::Ptr service = *it;
00263 bool autoload = service->property("X-KDE-Kded-autoload", QVariant::Bool).toBool();
00264 KConfigGroup cg(config, QString("Module-%1").arg(service->desktopEntryName()));
00265 autoload = cg.readEntry("autoload", autoload);
00266 QVariant phasev = service->property("X-KDE-Kded-phase", QVariant::Int );
00267 int phase = phasev.isValid() ? phasev.toInt() : 2;
00268 if( phase == 2 && autoload )
00269 loadModule(service, false);
00270 }
00271 }
00272
00273 void Kded::noDemandLoad(const QString &obj)
00274 {
00275 m_dontLoad.insert(obj.toLatin1(), this);
00276 }
00277
00278 void Kded::setModuleAutoloading(const QString &obj, bool autoload)
00279 {
00280 KSharedConfig::Ptr config = KGlobal::config();
00281
00282 KService::Ptr service = KService::serviceByDesktopPath("kded/"+obj+".desktop");
00283 if (!service)
00284 return;
00285 KConfigGroup cg(config, QString("Module-%1").arg(service->desktopEntryName()));
00286 cg.writeEntry("autoload", autoload);
00287 cg.sync();
00288 }
00289
00290 bool Kded::isModuleAutoloaded(const QString &obj) const
00291 {
00292 KService::Ptr s = KService::serviceByDesktopPath("kded/"+obj+".desktop");
00293 if (!s)
00294 return false;
00295 return isModuleAutoloaded(s);
00296 }
00297
00298 bool Kded::isModuleAutoloaded(const KService::Ptr &module) const
00299 {
00300 KSharedConfig::Ptr config = KGlobal::config();
00301 bool autoload = module->property("X-KDE-Kded-autoload", QVariant::Bool).toBool();
00302 KConfigGroup cg(config, QString("Module-%1").arg(module->desktopEntryName()));
00303 autoload = cg.readEntry("autoload", autoload);
00304 return autoload;
00305 }
00306
00307 bool Kded::isModuleLoadedOnDemand(const QString &obj) const
00308 {
00309 KService::Ptr s = KService::serviceByDesktopPath("kded/"+obj+".desktop");
00310 if (!s)
00311 return false;
00312 return isModuleLoadedOnDemand(s);
00313 }
00314
00315 bool Kded::isModuleLoadedOnDemand(const KService::Ptr &module) const
00316 {
00317 KSharedConfig::Ptr config = KGlobal::config();
00318 bool loadOnDemand = true;
00319 QVariant p = module->property("X-KDE-Kded-load-on-demand", QVariant::Bool);
00320 if (p.isValid() && (p.toBool() == false))
00321 loadOnDemand = false;
00322 return loadOnDemand;
00323 }
00324
00325 KDEDModule *Kded::loadModule(const QString &obj, bool onDemand)
00326 {
00327
00328 Q_ASSERT(obj.indexOf('/')==-1);
00329
00330 KDEDModule *module = m_modules.value(obj, 0);
00331 if (module)
00332 return module;
00333 KService::Ptr s = KService::serviceByDesktopPath("kded/"+obj+".desktop");
00334 return loadModule(s, onDemand);
00335 }
00336
00337 KDEDModule *Kded::loadModule(const KService::Ptr& s, bool onDemand)
00338 {
00339 if (s && !s->library().isEmpty())
00340 {
00341 QString obj = s->desktopEntryName();
00342 KDEDModule *oldModule = m_modules.value(obj, 0);
00343 if (oldModule)
00344 return oldModule;
00345
00346 if (onDemand)
00347 {
00348 QVariant p = s->property("X-KDE-Kded-load-on-demand", QVariant::Bool);
00349 if (p.isValid() && (p.toBool() == false))
00350 {
00351 noDemandLoad(s->desktopEntryName());
00352 return 0;
00353 }
00354 }
00355
00356 KDEDModule *module = 0;
00357 QString libname = "kded_"+s->library();
00358 KPluginLoader loader(libname);
00359
00360 KPluginFactory *factory = loader.factory();
00361 if (!factory) {
00362
00363 QString factoryName = s->property("X-KDE-FactoryName", QVariant::String).toString();
00364 if (factoryName.isEmpty())
00365 factoryName = s->library();
00366 factoryName = "create_" + factoryName;
00367 KLibrary* lib = KLibLoader::self()->library(libname);
00368 KDEDModule* (*create)();
00369 if (lib) {
00370 create = (KDEDModule* (*)())lib->resolveFunction(QFile::encodeName(factoryName));
00371 if (create)
00372 module = create();
00373 }
00374 if (!module) {
00375 kWarning() << "Could not load library" << libname << ". ["
00376 << loader.errorString() << "]";
00377 }
00378 } else {
00379
00380 module = factory->create<KDEDModule>(this);
00381 }
00382 if (module) {
00383 module->setModuleName(obj);
00384 m_modules.insert(obj, module);
00385
00386 connect(module, SIGNAL(moduleDeleted(KDEDModule *)), SLOT(slotKDEDModuleRemoved(KDEDModule *)));
00387 kDebug(7020) << "Successfully loaded module" << obj;
00388 return module;
00389 } else {
00390 kDebug(7020) << "Could not load module" << obj;
00391
00392 }
00393 }
00394 return 0;
00395 }
00396
00397 bool Kded::unloadModule(const QString &obj)
00398 {
00399 KDEDModule *module = m_modules.value(obj, 0);
00400 if (!module)
00401 return false;
00402 kDebug(7020) << "Unloading module" << obj;
00403 m_modules.remove(obj);
00404 delete module;
00405 return true;
00406 }
00407
00408 QStringList Kded::loadedModules()
00409 {
00410 return m_modules.keys();
00411 }
00412
00413 void Kded::slotKDEDModuleRemoved(KDEDModule *module)
00414 {
00415 m_modules.remove(module->moduleName());
00416
00417
00418
00419 }
00420
00421 void Kded::slotApplicationRemoved(const QString &name, const QString &oldOwner,
00422 const QString &newOwner)
00423 {
00424 #if 0 // see kdedmodule.cpp (KDED_OBJECTS)
00425 foreach( KDEDModule* module, m_modules )
00426 {
00427 module->removeAll(appId);
00428 }
00429 #endif
00430 if (oldOwner.isEmpty() || !newOwner.isEmpty())
00431 return;
00432
00433 const QList<qlonglong> windowIds = m_windowIdList.value(name);
00434 for( QList<qlonglong>::ConstIterator it = windowIds.begin();
00435 it != windowIds.end(); ++it)
00436 {
00437 qlonglong windowId = *it;
00438 m_globalWindowIdList.remove(windowId);
00439 foreach( KDEDModule* module, m_modules )
00440 {
00441 emit module->windowUnregistered(windowId);
00442 }
00443 }
00444 m_windowIdList.remove(name);
00445 }
00446
00447 void Kded::updateDirWatch()
00448 {
00449 if (!bCheckUpdates) return;
00450
00451 delete m_pDirWatch;
00452 m_pDirWatch = new KDirWatch;
00453
00454 QObject::connect( m_pDirWatch, SIGNAL(dirty(const QString&)),
00455 this, SLOT(update(const QString&)));
00456 QObject::connect( m_pDirWatch, SIGNAL(created(const QString&)),
00457 this, SLOT(update(const QString&)));
00458 QObject::connect( m_pDirWatch, SIGNAL(deleted(const QString&)),
00459 this, SLOT(dirDeleted(const QString&)));
00460
00461
00462 for( QStringList::ConstIterator it = m_allResourceDirs.constBegin();
00463 it != m_allResourceDirs.constEnd();
00464 ++it )
00465 {
00466 readDirectory( *it );
00467 }
00468 }
00469
00470 void Kded::updateResourceList()
00471 {
00472 KBuildSycoca::clearCaches();
00473
00474 if (!bCheckUpdates) return;
00475
00476 if (delayedCheck) return;
00477
00478 const QStringList dirs = KSycoca::self()->allResourceDirs();
00479
00480 for( QStringList::ConstIterator it = dirs.begin();
00481 it != dirs.end();
00482 ++it )
00483 {
00484 if (!m_allResourceDirs.contains(*it))
00485 {
00486 m_allResourceDirs.append(*it);
00487 readDirectory(*it);
00488 }
00489 }
00490 }
00491
00492 void Kded::recreate()
00493 {
00494 recreate(false);
00495 }
00496
00497 void Kded::runDelayedCheck()
00498 {
00499 if( m_needDelayedCheck )
00500 recreate(false);
00501 m_needDelayedCheck = false;
00502 }
00503
00504 void Kded::recreate(bool initial)
00505 {
00506 m_recreateBusy = true;
00507
00508
00509
00510 if (!initial)
00511 {
00512 updateDirWatch();
00513 runBuildSycoca(this, SLOT(recreateDone()));
00514 }
00515 else
00516 {
00517 if(!delayedCheck)
00518 updateDirWatch();
00519 if (bCheckSycoca)
00520 runBuildSycoca();
00521 recreateDone();
00522 if(delayedCheck)
00523 {
00524
00525 QTimer::singleShot( 60000, this, SLOT(runDelayedCheck()));
00526 m_needDelayedCheck = true;
00527 delayedCheck = false;
00528 }
00529 else
00530 m_needDelayedCheck = false;
00531 }
00532 }
00533
00534 void Kded::recreateDone()
00535 {
00536 updateResourceList();
00537
00538 for(; m_recreateCount; m_recreateCount--)
00539 {
00540 QDBusMessage msg = m_recreateRequests.takeFirst();
00541 QDBusConnection::sessionBus().send(msg.createReply());
00542 }
00543 m_recreateBusy = false;
00544
00545
00546 if (!m_recreateRequests.isEmpty())
00547 {
00548 m_pTimer->start(2000);
00549 m_recreateCount = m_recreateRequests.count();
00550 }
00551 }
00552
00553 void Kded::dirDeleted(const QString& path)
00554 {
00555 update(path);
00556 }
00557
00558 void Kded::update(const QString& )
00559 {
00560 if (!m_recreateBusy)
00561 {
00562 m_pTimer->start( 10000 );
00563 }
00564 }
00565
00566 void Kded::recreate(const QDBusMessage &msg)
00567 {
00568 if (!m_recreateBusy)
00569 {
00570 if (m_recreateRequests.isEmpty())
00571 {
00572 m_pTimer->start(0);
00573 m_recreateCount = 0;
00574 }
00575 m_recreateCount++;
00576 }
00577 msg.setDelayedReply(true);
00578 m_recreateRequests.append(msg);
00579 return;
00580 }
00581
00582
00583 void Kded::readDirectory( const QString& _path )
00584 {
00585 QString path( _path );
00586 if ( !path.endsWith( '/' ) )
00587 path += '/';
00588
00589 if ( m_pDirWatch->contains( path ) )
00590 return;
00591
00592 m_pDirWatch->addDir(path,KDirWatch::WatchFiles|KDirWatch::WatchSubDirs);
00593 return;
00594 #if 0
00595 QDir d( _path, QString(), QDir::Unsorted, QDir::Readable | QDir::Executable | QDir::Dirs | QDir::Hidden );
00596
00597
00598
00599
00600
00601
00602
00603 if ( !d.exists() )
00604 {
00605 kDebug(7020) << "Does not exist:" << _path;
00606 return;
00607 }
00608
00609
00610
00611
00612
00613
00614 QString file;
00615 unsigned int i;
00616 unsigned int count = d.count();
00617 for( i = 0; i < count; i++ )
00618 {
00619 if (d[i] == "." || d[i] == ".." || d[i] == "magic")
00620 continue;
00621
00622 file = path;
00623 file += d[i];
00624
00625 readDirectory( file );
00626 }
00627 #endif
00628 }
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 void Kded::registerWindowId(qlonglong windowId, const QString &sender)
00639 {
00640 m_globalWindowIdList.insert(windowId);
00641 QList<qlonglong> windowIds = m_windowIdList.value(sender);
00642 windowIds.append(windowId);
00643 m_windowIdList.insert(sender, windowIds);
00644
00645 foreach( KDEDModule* module, m_modules )
00646 {
00647
00648 emit module->windowRegistered(windowId);
00649 }
00650 }
00651
00652 void Kded::unregisterWindowId(qlonglong windowId, const QString &sender)
00653 {
00654 m_globalWindowIdList.remove(windowId);
00655 QList<qlonglong> windowIds = m_windowIdList.value(sender);
00656 if (!windowIds.isEmpty())
00657 {
00658 windowIds.removeAll(windowId);
00659 if (windowIds.isEmpty())
00660 m_windowIdList.remove(sender);
00661 else
00662 m_windowIdList.insert(sender, windowIds);
00663 }
00664
00665 foreach( KDEDModule* module, m_modules )
00666 {
00667
00668 emit module->windowUnregistered(windowId);
00669 }
00670 }
00671
00672
00673 static void sighandler(int )
00674 {
00675 if (qApp)
00676 qApp->quit();
00677 }
00678
00679 KUpdateD::KUpdateD()
00680 {
00681 m_pDirWatch = new KDirWatch;
00682 m_pTimer = new QTimer;
00683 m_pTimer->setSingleShot( true );
00684 connect(m_pTimer, SIGNAL(timeout()), this, SLOT(runKonfUpdate()));
00685 QObject::connect( m_pDirWatch, SIGNAL(dirty(const QString&)),
00686 this, SLOT(slotNewUpdateFile()));
00687
00688 const QStringList dirs = KGlobal::dirs()->findDirs("data", "kconf_update");
00689 for( QStringList::ConstIterator it = dirs.begin();
00690 it != dirs.end();
00691 ++it )
00692 {
00693 QString path = *it;
00694 if (path[path.length()-1] != '/')
00695 path += '/';
00696
00697 if (!m_pDirWatch->contains(path))
00698 m_pDirWatch->addDir(path,KDirWatch::WatchFiles|KDirWatch::WatchSubDirs);
00699 }
00700 }
00701
00702 KUpdateD::~KUpdateD()
00703 {
00704 delete m_pDirWatch;
00705 delete m_pTimer;
00706 }
00707
00708 void KUpdateD::runKonfUpdate()
00709 {
00710 ::runKonfUpdate();
00711 }
00712
00713 void KUpdateD::slotNewUpdateFile()
00714 {
00715 m_pTimer->start( 500 );
00716 }
00717
00718 KHostnameD::KHostnameD(int pollInterval)
00719 {
00720 m_Timer.start(pollInterval);
00721 connect(&m_Timer, SIGNAL(timeout()), this, SLOT(checkHostname()));
00722 checkHostname();
00723 }
00724
00725 KHostnameD::~KHostnameD()
00726 {
00727
00728 }
00729
00730 void KHostnameD::checkHostname()
00731 {
00732 char buf[1024+1];
00733 if (gethostname(buf, 1024) != 0)
00734 return;
00735 buf[sizeof(buf)-1] = '\0';
00736
00737 if (m_hostname.isEmpty())
00738 {
00739 m_hostname = buf;
00740 return;
00741 }
00742
00743 if (m_hostname == buf)
00744 return;
00745
00746 QByteArray newHostname = buf;
00747
00748 runDontChangeHostname(m_hostname, newHostname);
00749 m_hostname = newHostname;
00750 }
00751
00752
00753 #if 0
00754
00755
00756
00757
00758 class KDEDQtDCOPObject : public DCOPObject
00759 {
00760 public:
00761 KDEDQtDCOPObject() : DCOPObject("qt/kded") { }
00762
00763 virtual bool process(const DCOPCString &fun, const QByteArray &data,
00764 DCOPCString& replyType, QByteArray &replyData)
00765 {
00766 if (qApp && (fun == "quit()"))
00767 {
00768 qApp->quit();
00769 replyType = "void";
00770 return true;
00771 }
00772 return DCOPObject::process(fun, data, replyType, replyData);
00773 }
00774
00775 DCOPCStringList functions()
00776 {
00777 DCOPCStringList res = DCOPObject::functions();
00778 res += "void quit()";
00779 return res;
00780 }
00781 };
00782 #endif
00783
00784 KBuildsycocaAdaptor::KBuildsycocaAdaptor(QObject *parent)
00785 : QDBusAbstractAdaptor(parent)
00786 {
00787 }
00788
00789 void KBuildsycocaAdaptor::recreate(const QDBusMessage &msg)
00790 {
00791 Kded::self()->recreate(msg);
00792 }
00793
00794 class KDEDApplication : public KUniqueApplication
00795 {
00796 public:
00797 KDEDApplication() : KUniqueApplication( )
00798 {
00799 startup = true;
00800 }
00801
00802 int newInstance()
00803 {
00804 if (startup) {
00805 startup = false;
00806
00807
00808
00809
00810
00811
00812 Kded *kded = Kded::self();
00813
00814 kded->recreate(true);
00815
00816 if (bCheckUpdates)
00817 (void) new KUpdateD;
00818
00819 #ifdef Q_WS_X11
00820 XEvent e;
00821 e.xclient.type = ClientMessage;
00822 e.xclient.message_type = XInternAtom( QX11Info::display(), "_KDE_SPLASH_PROGRESS", False );
00823 e.xclient.display = QX11Info::display();
00824 e.xclient.window = QX11Info::appRootWindow();
00825 e.xclient.format = 8;
00826 strcpy( e.xclient.data.b, "kded" );
00827 XSendEvent( QX11Info::display(), QX11Info::appRootWindow(), False, SubstructureNotifyMask, &e );
00828 #endif
00829
00830 runKonfUpdate();
00831
00832 #ifdef Q_WS_X11
00833 e.xclient.type = ClientMessage;
00834 e.xclient.message_type = XInternAtom( QX11Info::display(), "_KDE_SPLASH_PROGRESS", False );
00835 e.xclient.display = QX11Info::display();
00836 e.xclient.window = QX11Info::appRootWindow();
00837 e.xclient.format = 8;
00838 strcpy( e.xclient.data.b, "confupdate" );
00839 XSendEvent( QX11Info::display(), QX11Info::appRootWindow(), False, SubstructureNotifyMask, &e );
00840 #endif
00841
00842 if (bCheckHostname)
00843 (void) new KHostnameD(HostnamePollInterval);
00844
00845 QObject::connect(QDBusConnection::sessionBus().interface(),
00846 SIGNAL(serviceOwnerChanged(QString,QString,QString)),
00847 kded, SLOT(slotApplicationRemoved(QString,QString,QString)));
00848
00849
00850
00851
00852
00853
00854
00855
00856 QDBusMessage msg = QDBusMessage::createSignal("/kbuildsycoca", "org.kde.KSycoca", "notifyDatabaseChanged" );
00857 msg << QStringList();
00858 QDBusConnection::sessionBus().send(msg);
00859
00860 kded->initModules();
00861 } else
00862 runBuildSycoca();
00863
00864 return 0;
00865 }
00866
00867 bool startup;
00868 };
00869
00870 extern "C" KDE_EXPORT int kdemain(int argc, char *argv[])
00871 {
00872 KAboutData aboutData( "kded" ,
00873 "kdelibs4", ki18n("KDE Daemon"),
00874 "$Id: kded.cpp 1031638 2009-10-05 16:59:11Z lunakl $",
00875 ki18n("KDE Daemon - triggers Sycoca database updates when needed"));
00876
00877 KCmdLineOptions options;
00878 options.add("check", ki18n("Check Sycoca database only once"));
00879
00880 KCmdLineArgs::init(argc, argv, &aboutData);
00881
00882 KUniqueApplication::addCmdLineOptions();
00883
00884 KCmdLineArgs::addCmdLineOptions( options );
00885
00886
00887 putenv(strdup("SESSION_MANAGER="));
00888
00889
00890 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
00891
00892 KComponentData componentData(&aboutData);
00893 KSharedConfig::Ptr config = componentData.config();
00894
00895 KConfigGroup cg(config, "General");
00896 if (args->isSet("check"))
00897 {
00898
00899 KApplication app;
00900 checkStamps = cg.readEntry("CheckFileStamps", true);
00901 runBuildSycoca();
00902 runKonfUpdate();
00903 return 0;
00904 }
00905
00906 if (!KUniqueApplication::start())
00907 {
00908 fprintf(stderr, "KDE Daemon (kded) already running.\n");
00909 return 0;
00910 }
00911
00912
00913
00914
00915 HostnamePollInterval = cg.readEntry("HostnamePollInterval", 5000);
00916 bCheckSycoca = cg.readEntry("CheckSycoca", true);
00917 bCheckUpdates = cg.readEntry("CheckUpdates", true);
00918 bCheckHostname = cg.readEntry("CheckHostname", true);
00919 checkStamps = cg.readEntry("CheckFileStamps", true);
00920 delayedCheck = cg.readEntry("DelayedCheck", false);
00921
00922 Kded *kded = new Kded();
00923
00924 KDE_signal(SIGTERM, sighandler);
00925 KDE_signal(SIGHUP, sighandler);
00926 KDEDApplication k;
00927 k.setQuitOnLastWindowClosed(false);
00928
00929 KCrash::setFlags(KCrash::AutoRestart);
00930
00931
00932
00933
00934 kded->moveToThread( k.thread() );
00935
00936 int result = k.exec();
00937
00938 delete kded;
00939
00940 return result;
00941 }
00942
00943 #include "kded.moc"