• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KDED

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

KDED

Skip menu "KDED"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal