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

KDED

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • 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.3
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