• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kded
 

kded

  • kded
kded.cpp
1 /* This file is part of the KDE libraries
2  * Copyright (C) 1999 David Faure <faure@kde.org>
3  * Copyright (C) 2000 Waldo Bastian <bastian@kde.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License version 2 as published by the Free Software Foundation;
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB. If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  **/
19 
20 #include <tqdir.h>
21 
22 #include "kded.h"
23 #include "kdedmodule.h"
24 
25 #include <kresourcelist.h>
26 #include <kcrash.h>
27 
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <signal.h>
31 #include <time.h>
32 
33 #include <tqfile.h>
34 #include <tqtimer.h>
35 
36 #include <dcopclient.h>
37 
38 #include <kuniqueapplication.h>
39 #include <kcmdlineargs.h>
40 #include <kaboutdata.h>
41 #include <klocale.h>
42 #include <kglobal.h>
43 #include <kprocess.h>
44 #include <kdebug.h>
45 #include <kdirwatch.h>
46 #include <kstandarddirs.h>
47 #include <kdatastream.h>
48 #include <kio/global.h>
49 #include <kservicetype.h>
50 
51 #ifdef Q_WS_X11
52 #include <X11/Xlib.h>
53 #include <fixx11h.h>
54 #endif
55 
56 Kded *Kded::_self = 0;
57 
58 static bool checkStamps = true;
59 static bool delayedCheck = false;
60 
61 static void runBuildSycoca(TQObject *callBackObj=0, const char *callBackSlot=0)
62 {
63  TQStringList args;
64  args.append("--incremental");
65  if(checkStamps)
66  args.append("--checkstamps");
67  if(delayedCheck)
68  args.append("--nocheckfiles");
69  else
70  checkStamps = false; // useful only during kded startup
71  if (callBackObj)
72  {
73  TQByteArray data;
74  TQDataStream dataStream( data, IO_WriteOnly );
75  dataStream << TQString("kbuildsycoca") << args;
76  TQCString _launcher = KApplication::launcher();
77 
78  kapp->dcopClient()->callAsync(_launcher, _launcher, "kdeinit_exec_wait(TQString,TQStringList)", data, callBackObj, callBackSlot);
79  }
80  else
81  {
82  KApplication::kdeinitExecWait( "kbuildsycoca", args );
83  }
84 }
85 
86 static void runKonfUpdate()
87 {
88  KApplication::kdeinitExecWait( "kconf_update", TQStringList(), 0, 0, "0" /*no startup notification*/ );
89 }
90 
91 static void runDontChangeHostname(const TQCString &oldName, const TQCString &newName)
92 {
93  TQStringList args;
94  args.append(TQFile::decodeName(oldName));
95  args.append(TQFile::decodeName(newName));
96  KApplication::kdeinitExecWait( "kdontchangethehostname", args );
97 }
98 
99 Kded::Kded(bool checkUpdates, bool new_startup)
100  : DCOPObject("kbuildsycoca"), DCOPObjectProxy(),
101  b_checkUpdates(checkUpdates),
102  m_needDelayedCheck(false),
103  m_newStartup( new_startup )
104 {
105  _self = this;
106  TQCString cPath;
107  TQCString ksycoca_env = getenv("KDESYCOCA");
108  if (ksycoca_env.isEmpty())
109  cPath = TQFile::encodeName(KGlobal::dirs()->saveLocation("tmp")+"ksycoca");
110  else
111  cPath = ksycoca_env;
112  m_pTimer = new TQTimer(this);
113  connect(m_pTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(recreate()));
114 
115  TQTimer::singleShot(100, this, TQT_SLOT(installCrashHandler()));
116 
117  m_pDirWatch = 0;
118 
119  m_windowIdList.setAutoDelete(true);
120 
121  m_recreateCount = 0;
122  m_recreateBusy = false;
123 }
124 
125 Kded::~Kded()
126 {
127  _self = 0;
128  m_pTimer->stop();
129  delete m_pTimer;
130  delete m_pDirWatch;
131  // We have to delete the modules while we're still able to process incoming
132  // DCOP messages, since modules might make DCOP calls in their destructors.
133  TQAsciiDictIterator<KDEDModule> it(m_modules);
134  while (!it.isEmpty())
135  delete it.toFirst();
136 }
137 
138 bool Kded::process(const TQCString &obj, const TQCString &fun,
139  const TQByteArray &data,
140  TQCString &replyType, TQByteArray &replyData)
141 {
142  if (obj == "ksycoca") return false; // Ignore this one.
143 
144  if (m_dontLoad[obj])
145  return false;
146 
147  KDEDModule *module = loadModule(obj, true);
148  if (!module)
149  return false;
150 
151  module->setCallingDcopClient(kapp->dcopClient());
152  return module->process(fun, data, replyType, replyData);
153 }
154 
155 void Kded::initModules()
156 {
157  m_dontLoad.clear();
158  KConfig *config = kapp->config();
159  bool tde_running = !( getenv( "TDE_FULL_SESSION" ) == NULL || getenv( "TDE_FULL_SESSION" )[ 0 ] == '\0' );
160  // not the same user like the one running the session (most likely we're run via sudo or something)
161  if( getenv( "KDE_SESSION_UID" ) != NULL && uid_t( atoi( getenv( "KDE_SESSION_UID" ))) != getuid())
162  tde_running = false;
163  // Preload kded modules.
164  KService::List kdedModules = KServiceType::offers("KDEDModule");
165  TQString version = getenv( "KDE_SESSION_VERSION" );
166  TQStringList blacklist;
167  if ( !(version == NULL) && version >= "4" )
168  {
169  kdDebug(7020) << "KDE4 is running:" << endl;
170  kdDebug(7020) << " KDE_SESSION_VERSION: " << version << endl;
171  kdDebug(7020) << " Blacklisting mediamanager, medianotifier, kmilod, kwrited." << endl;
172  blacklist << "mediamanager" << "medianotifier" << "kmilod" << "kwrited";
173  }
174  for(KService::List::ConstIterator it = kdedModules.begin(); it != kdedModules.end(); ++it)
175  {
176  KService::Ptr service = *it;
177  bool autoload = service->property("X-KDE-Kded-autoload", TQVariant::Bool).toBool();
178  config->setGroup(TQString("Module-%1").arg(service->desktopEntryName()));
179  autoload = config->readBoolEntry("autoload", autoload);
180  for (TQStringList::Iterator module = blacklist.begin(); module != blacklist.end(); ++module)
181  {
182  if (service->desktopEntryName() == *module)
183  {
184  autoload = false;
185  break;
186  }
187  }
188  if( m_newStartup )
189  {
190  // see ksmserver's README for description of the phases
191  TQVariant phasev = service->property("X-KDE-Kded-phase", TQVariant::Int );
192  int phase = phasev.isValid() ? phasev.toInt() : 2;
193  bool prevent_autoload = false;
194  switch( phase )
195  {
196  case 0: // always autoload
197  break;
198  case 1: // autoload only in TDE
199  if( !tde_running )
200  prevent_autoload = true;
201  break;
202  case 2: // autoload delayed, only in TDE
203  default:
204  prevent_autoload = true;
205  break;
206  }
207  if (autoload && !prevent_autoload)
208  loadModule(service, false);
209  }
210  else
211  {
212  if (autoload && tde_running)
213  loadModule(service, false);
214  }
215  bool dontLoad = false;
216  TQVariant p = service->property("X-KDE-Kded-load-on-demand", TQVariant::Bool);
217  if (p.isValid() && (p.toBool() == false))
218  dontLoad = true;
219  if (dontLoad)
220  noDemandLoad(service->desktopEntryName());
221 
222  if (dontLoad && !autoload)
223  unloadModule(service->desktopEntryName().latin1());
224  }
225 }
226 
227 void Kded::loadSecondPhase()
228 {
229  kdDebug(7020) << "Loading second phase autoload" << endl;
230  KConfig *config = kapp->config();
231  KService::List kdedModules = KServiceType::offers("KDEDModule");
232  for(KService::List::ConstIterator it = kdedModules.begin(); it != kdedModules.end(); ++it)
233  {
234  KService::Ptr service = *it;
235  bool autoload = service->property("X-KDE-Kded-autoload", TQVariant::Bool).toBool();
236  config->setGroup(TQString("Module-%1").arg(service->desktopEntryName()));
237  autoload = config->readBoolEntry("autoload", autoload);
238  TQVariant phasev = service->property("X-KDE-Kded-phase", TQVariant::Int );
239  int phase = phasev.isValid() ? phasev.toInt() : 2;
240  if( phase == 2 && autoload )
241  loadModule(service, false);
242  }
243 }
244 
245 void Kded::noDemandLoad(const TQString &obj)
246 {
247  m_dontLoad.insert(obj.latin1(), this);
248 }
249 
250 KDEDModule *Kded::loadModule(const TQCString &obj, bool onDemand)
251 {
252  KDEDModule *module = m_modules.find(obj);
253  if (module)
254  return module;
255  KService::Ptr s = KService::serviceByDesktopPath("kded/"+obj+".desktop");
256  return loadModule(s, onDemand);
257 }
258 
259 KDEDModule *Kded::loadModule(const KService *s, bool onDemand)
260 {
261  KDEDModule *module = 0;
262  if (s && !s->library().isEmpty())
263  {
264  TQCString obj = s->desktopEntryName().latin1();
265  KDEDModule *oldModule = m_modules.find(obj);
266  if (oldModule)
267  return oldModule;
268 
269  if (onDemand)
270  {
271  TQVariant p = s->property("X-KDE-Kded-load-on-demand", TQVariant::Bool);
272  if (p.isValid() && (p.toBool() == false))
273  {
274  noDemandLoad(s->desktopEntryName());
275  return 0;
276  }
277  }
278  // get the library loader instance
279 
280  KLibLoader *loader = KLibLoader::self();
281 
282  TQVariant v = s->property("X-KDE-FactoryName", TQVariant::String);
283  TQString factory = v.isValid() ? v.toString() : TQString::null;
284  if (factory.isEmpty())
285  {
286  // Stay bugward compatible
287  v = s->property("X-KDE-Factory", TQVariant::String);
288  factory = v.isValid() ? v.toString() : TQString::null;
289  }
290  if (factory.isEmpty())
291  factory = s->library();
292 
293  factory = "create_" + factory;
294  TQString libname = "kded_"+s->library();
295 
296  KLibrary *lib = loader->library(TQFile::encodeName(libname));
297  if (!lib)
298  {
299  kdWarning() << k_funcinfo << "Could not load library. [ "
300  << loader->lastErrorMessage() << " ]" << endl;
301  libname.prepend("lib");
302  lib = loader->library(TQFile::encodeName(libname));
303  }
304  if (lib)
305  {
306  // get the create_ function
307  void *create = lib->symbol(TQFile::encodeName(factory));
308 
309  if (create)
310  {
311  // create the module
312  KDEDModule* (*func)(const TQCString &);
313  func = (KDEDModule* (*)(const TQCString &)) create;
314  module = func(obj);
315  if (module)
316  {
317  m_modules.insert(obj, module);
318  m_libs.insert(obj, lib);
319  connect(module, TQT_SIGNAL(moduleDeleted(KDEDModule *)), TQT_SLOT(slotKDEDModuleRemoved(KDEDModule *)));
320  kdDebug(7020) << "Successfully loaded module '" << obj << "'\n";
321  return module;
322  }
323  }
324  loader->unloadLibrary(TQFile::encodeName(libname));
325  }
326  else
327  {
328  kdWarning() << k_funcinfo << "Could not load library. [ "
329  << loader->lastErrorMessage() << " ]" << endl;
330  }
331  kdDebug(7020) << "Could not load module '" << obj << "'\n";
332  }
333  return 0;
334 }
335 
336 bool Kded::unloadModule(const TQCString &obj)
337 {
338  KDEDModule *module = m_modules.take(obj);
339  if (!module)
340  return false;
341  kdDebug(7020) << "Unloading module '" << obj << "'\n";
342  delete module;
343  return true;
344 }
345 
346 // DCOP
347 QCStringList Kded::loadedModules()
348 {
349  QCStringList modules;
350  TQAsciiDictIterator<KDEDModule> it( m_modules );
351  for ( ; it.current(); ++it)
352  modules.append( it.currentKey() );
353 
354  return modules;
355 }
356 
357 QCStringList Kded::functions()
358 {
359  QCStringList res = DCOPObject::functions();
360  res += "ASYNC recreate()";
361  return res;
362 }
363 
364 void Kded::slotKDEDModuleRemoved(KDEDModule *module)
365 {
366  m_modules.remove(module->objId());
367  KLibrary *lib = m_libs.take(module->objId());
368  if (lib)
369  lib->unload();
370 }
371 
372 void Kded::slotApplicationRemoved(const TQCString &appId)
373 {
374  for(TQAsciiDictIterator<KDEDModule> it(m_modules); it.current(); ++it)
375  {
376  it.current()->removeAll(appId);
377  }
378 
379  TQValueList<long> *windowIds = m_windowIdList.find(appId);
380  if (windowIds)
381  {
382  for( TQValueList<long>::ConstIterator it = windowIds->begin();
383  it != windowIds->end(); ++it)
384  {
385  long windowId = *it;
386  m_globalWindowIdList.remove(windowId);
387  for(TQAsciiDictIterator<KDEDModule> it(m_modules); it.current(); ++it)
388  {
389  emit it.current()->windowUnregistered(windowId);
390  }
391  }
392  m_windowIdList.remove(appId);
393  }
394 }
395 
396 void Kded::updateDirWatch()
397 {
398  if (!b_checkUpdates) return;
399 
400  delete m_pDirWatch;
401  m_pDirWatch = new KDirWatch;
402 
403  TQObject::connect( m_pDirWatch, TQT_SIGNAL(dirty(const TQString&)),
404  this, TQT_SLOT(update(const TQString&)));
405  TQObject::connect( m_pDirWatch, TQT_SIGNAL(created(const TQString&)),
406  this, TQT_SLOT(update(const TQString&)));
407  TQObject::connect( m_pDirWatch, TQT_SIGNAL(deleted(const TQString&)),
408  this, TQT_SLOT(dirDeleted(const TQString&)));
409 
410  // For each resource
411  for( TQStringList::ConstIterator it = m_allResourceDirs.begin();
412  it != m_allResourceDirs.end();
413  ++it )
414  {
415  readDirectory( *it );
416  }
417 }
418 
419 void Kded::updateResourceList()
420 {
421  delete KSycoca::self();
422 
423  if (!b_checkUpdates) return;
424 
425  if (delayedCheck) return;
426 
427  TQStringList dirs = KSycoca::self()->allResourceDirs();
428  // For each resource
429  for( TQStringList::ConstIterator it = dirs.begin();
430  it != dirs.end();
431  ++it )
432  {
433  if (m_allResourceDirs.find(*it) == m_allResourceDirs.end())
434  {
435  m_allResourceDirs.append(*it);
436  readDirectory(*it);
437  }
438  }
439 }
440 
441 void Kded::crashHandler(int)
442 {
443  DCOPClient::emergencyClose();
444  if (_self) // Don't restart if we were closing down
445  system("kded");
446 qWarning("Last DCOP call before KDED crash was from application '%s'\n"
447  "to object '%s', function '%s'.",
448  DCOPClient::postMortemSender(),
449  DCOPClient::postMortemObject(),
450  DCOPClient::postMortemFunction());
451 }
452 
453 void Kded::installCrashHandler()
454 {
455  KCrash::setEmergencySaveFunction(crashHandler);
456 }
457 
458 void Kded::recreate()
459 {
460  recreate(false);
461 }
462 
463 void Kded::runDelayedCheck()
464 {
465  if( m_needDelayedCheck )
466  recreate(false);
467  m_needDelayedCheck = false;
468 }
469 
470 void Kded::recreate(bool initial)
471 {
472  m_recreateBusy = true;
473  // Using KLauncher here is difficult since we might not have a
474  // database
475 
476  if (!initial)
477  {
478  updateDirWatch(); // Update tree first, to be sure to miss nothing.
479  runBuildSycoca(this, TQT_SLOT(recreateDone()));
480  }
481  else
482  {
483  if(!delayedCheck)
484  updateDirWatch(); // this would search all the directories
485  runBuildSycoca();
486  recreateDone();
487  if(delayedCheck)
488  {
489  // do a proper ksycoca check after a delay
490  TQTimer::singleShot( 60000, this, TQT_SLOT( runDelayedCheck()));
491  m_needDelayedCheck = true;
492  delayedCheck = false;
493  }
494  else
495  m_needDelayedCheck = false;
496  }
497 }
498 
499 void Kded::recreateDone()
500 {
501  updateResourceList();
502 
503  for(; m_recreateCount; m_recreateCount--)
504  {
505  TQCString replyType = "void";
506  TQByteArray replyData;
507  DCOPClientTransaction *transaction = m_recreateRequests.first();
508  if (transaction)
509  kapp->dcopClient()->endTransaction(transaction, replyType, replyData);
510  m_recreateRequests.remove(m_recreateRequests.begin());
511  }
512  m_recreateBusy = false;
513 
514  // Did a new request come in while building?
515  if (!m_recreateRequests.isEmpty())
516  {
517  m_pTimer->start(2000, true /* single shot */ );
518  m_recreateCount = m_recreateRequests.count();
519  }
520 }
521 
522 void Kded::dirDeleted(const TQString& path)
523 {
524  update(path);
525 }
526 
527 void Kded::update(const TQString& )
528 {
529  if (!m_recreateBusy)
530  {
531  m_pTimer->start( 2000, true /* single shot */ );
532  }
533  else
534  {
535  m_recreateRequests.append(0);
536  }
537 }
538 
539 bool Kded::process(const TQCString &fun, const TQByteArray &data,
540  TQCString &replyType, TQByteArray &replyData)
541 {
542  if (fun == "recreate()") {
543  if (!m_recreateBusy)
544  {
545  if (m_recreateRequests.isEmpty())
546  {
547  m_pTimer->start(0, true /* single shot */ );
548  m_recreateCount = 0;
549  }
550  m_recreateCount++;
551  }
552  m_recreateRequests.append(kapp->dcopClient()->beginTransaction());
553  replyType = "void";
554  return true;
555  } else {
556  return DCOPObject::process(fun, data, replyType, replyData);
557  }
558 }
559 
560 
561 void Kded::readDirectory( const TQString& _path )
562 {
563  TQString path( _path );
564  if ( path.right(1) != "/" )
565  path += "/";
566 
567  if ( m_pDirWatch->contains( path ) ) // Already seen this one?
568  return;
569 
570  TQDir d( _path, TQString::null, TQDir::Unsorted, TQDir::Readable | TQDir::Executable | TQDir::Dirs | TQDir::Hidden );
571  // set TQDir ...
572 
573 
574  //************************************************************************
575  // Setting dirs
576  //************************************************************************
577 
578  m_pDirWatch->addDir(path); // add watch on this dir
579 
580  if ( !d.exists() ) // exists&isdir?
581  {
582  kdDebug(7020) << TQString(TQString("Does not exist! (%1)").arg(_path)) << endl;
583  return; // return false
584  }
585 
586  // Note: If some directory is gone, dirwatch will delete it from the list.
587 
588  //************************************************************************
589  // Reading
590  //************************************************************************
591  TQString file;
592  unsigned int i; // counter and string length.
593  unsigned int count = d.count();
594  for( i = 0; i < count; i++ ) // check all entries
595  {
596  if (d[i] == "." || d[i] == ".." || d[i] == "magic")
597  continue; // discard those ".", "..", "magic"...
598 
599  file = path; // set full path
600  file += d[i]; // and add the file name.
601 
602  readDirectory( file ); // yes, dive into it.
603  }
604 }
605 
606 bool Kded::isWindowRegistered(long windowId)
607 {
608  return m_globalWindowIdList.find(windowId) != 0;
609 
610 }
611 
612 // DCOP
613 void Kded::registerWindowId(long windowId)
614 {
615  m_globalWindowIdList.replace(windowId, &windowId);
616  TQCString sender = callingDcopClient()->senderId();
617  if( sender.isEmpty()) // local call
618  sender = callingDcopClient()->appId();
619  TQValueList<long> *windowIds = m_windowIdList.find(sender);
620  if (!windowIds)
621  {
622  windowIds = new TQValueList<long>;
623  m_windowIdList.insert(sender, windowIds);
624  }
625  windowIds->append(windowId);
626 
627 
628  for(TQAsciiDictIterator<KDEDModule> it(m_modules); it.current(); ++it)
629  {
630  emit it.current()->windowRegistered(windowId);
631  }
632 }
633 
634 // DCOP
635 void Kded::unregisterWindowId(long windowId)
636 {
637  m_globalWindowIdList.remove(windowId);
638  TQCString sender = callingDcopClient()->senderId();
639  if( sender.isEmpty()) // local call
640  sender = callingDcopClient()->appId();
641  TQValueList<long> *windowIds = m_windowIdList.find(sender);
642  if (windowIds)
643  {
644  windowIds->remove(windowId);
645  if (windowIds->isEmpty())
646  m_windowIdList.remove(sender);
647  }
648 
649  for(TQAsciiDictIterator<KDEDModule> it(m_modules); it.current(); ++it)
650  {
651  emit it.current()->windowUnregistered(windowId);
652  }
653 }
654 
655 
656 static void sighandler(int /*sig*/)
657 {
658  if (kapp)
659  kapp->quit();
660 }
661 
662 KUpdateD::KUpdateD()
663 {
664  m_pDirWatch = new KDirWatch;
665  m_pTimer = new TQTimer;
666  connect(m_pTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(runKonfUpdate()));
667  TQObject::connect( m_pDirWatch, TQT_SIGNAL(dirty(const TQString&)),
668  this, TQT_SLOT(slotNewUpdateFile()));
669 
670  TQStringList dirs = KGlobal::dirs()->findDirs("data", "kconf_update");
671  for( TQStringList::ConstIterator it = dirs.begin();
672  it != dirs.end();
673  ++it )
674  {
675  TQString path = *it;
676  if (path[path.length()-1] != '/')
677  path += "/";
678 
679  if (!m_pDirWatch->contains(path))
680  m_pDirWatch->addDir(path);
681  }
682 }
683 
684 KUpdateD::~KUpdateD()
685 {
686  delete m_pDirWatch;
687  delete m_pTimer;
688 }
689 
690 void KUpdateD::runKonfUpdate()
691 {
692  ::runKonfUpdate();
693 }
694 
695 void KUpdateD::slotNewUpdateFile()
696 {
697  m_pTimer->start( 500, true /* single shot */ );
698 }
699 
700 KHostnameD::KHostnameD(int pollInterval)
701 {
702  m_Timer.start(pollInterval, false /* repetitive */ );
703  connect(&m_Timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(checkHostname()));
704  checkHostname();
705 }
706 
707 KHostnameD::~KHostnameD()
708 {
709  // Empty
710 }
711 
712 void KHostnameD::checkHostname()
713 {
714  char buf[1024+1];
715  if (gethostname(buf, 1024) != 0)
716  return;
717  buf[sizeof(buf)-1] = '\0';
718 
719  if (m_hostname.isEmpty())
720  {
721  m_hostname = buf;
722  return;
723  }
724 
725  if (m_hostname == buf)
726  return;
727 
728  TQCString newHostname = buf;
729 
730  runDontChangeHostname(m_hostname, newHostname);
731  m_hostname = newHostname;
732 }
733 
734 
735 static KCmdLineOptions options[] =
736 {
737  { "check", I18N_NOOP("Check Sycoca database only once"), 0 },
738  { "new-startup", "Internal", 0 },
739  KCmdLineLastOption
740 };
741 
742 class KDEDQtDCOPObject : public DCOPObject
743 {
744 public:
745  KDEDQtDCOPObject() : DCOPObject("qt/kded") { }
746 
747  virtual bool process(const TQCString &fun, const TQByteArray &data,
748  TQCString& replyType, TQByteArray &replyData)
749  {
750  if ( kapp && (fun == "quit()") )
751  {
752  kapp->quit();
753  replyType = "void";
754  return true;
755  }
756  return DCOPObject::process(fun, data, replyType, replyData);
757  }
758 
759  QCStringList functions()
760  {
761  QCStringList res = DCOPObject::functions();
762  res += "void quit()";
763  return res;
764  }
765 };
766 
767 class KDEDApplication : public KUniqueApplication
768 {
769 public:
770  KDEDApplication() : KUniqueApplication( )
771  {
772  startup = true;
773  dcopClient()->connectDCOPSignal( "DCOPServer", "", "terminateKDE()",
774  objId(), "quit()", false );
775  }
776 
777  int newInstance()
778  {
779  if (startup) {
780  startup = false;
781  if( Kded::self()->newStartup())
782  Kded::self()->initModules();
783  else
784  TQTimer::singleShot(500, Kded::self(), TQT_SLOT(initModules()));
785  } else
786  runBuildSycoca();
787 
788  return 0;
789  }
790 
791  QCStringList functions()
792  {
793  QCStringList res = KUniqueApplication::functions();
794  res += "bool loadModule(TQCString)";
795  res += "bool unloadModule(TQCString)";
796  res += "void registerWindowId(long int)";
797  res += "void unregisterWindowId(long int)";
798  res += "QCStringList loadedModules()";
799  res += "void reconfigure()";
800  res += "void loadSecondPhase()";
801  res += "void quit()";
802  return res;
803  }
804 
805  bool process(const TQCString &fun, const TQByteArray &data,
806  TQCString &replyType, TQByteArray &replyData)
807  {
808  if (fun == "loadModule(TQCString)") {
809  TQCString module;
810  TQDataStream arg( data, IO_ReadOnly );
811  arg >> module;
812  bool result = (Kded::self()->loadModule(module, false) != 0);
813  replyType = "bool";
814  TQDataStream _replyStream( replyData, IO_WriteOnly );
815  _replyStream << result;
816  return true;
817  }
818  else if (fun == "unloadModule(TQCString)") {
819  TQCString module;
820  TQDataStream arg( data, IO_ReadOnly );
821  arg >> module;
822  bool result = Kded::self()->unloadModule(module);
823  replyType = "bool";
824  TQDataStream _replyStream( replyData, IO_WriteOnly );
825  _replyStream << result;
826  return true;
827  }
828  else if (fun == "registerWindowId(long int)") {
829  long windowId;
830  TQDataStream arg( data, IO_ReadOnly );
831  arg >> windowId;
832  Kded::self()->setCallingDcopClient(callingDcopClient());
833  Kded::self()->registerWindowId(windowId);
834  replyType = "void";
835  return true;
836  }
837  else if (fun == "unregisterWindowId(long int)") {
838  long windowId;
839  TQDataStream arg( data, IO_ReadOnly );
840  arg >> windowId;
841  Kded::self()->setCallingDcopClient(callingDcopClient());
842  Kded::self()->unregisterWindowId(windowId);
843  replyType = "void";
844  return true;
845  }
846  else if (fun == "loadedModules()") {
847  replyType = "QCStringList";
848  TQDataStream _replyStream(replyData, IO_WriteOnly);
849  _replyStream << Kded::self()->loadedModules();
850  return true;
851  }
852  else if (fun == "reconfigure()") {
853  config()->reparseConfiguration();
854  Kded::self()->initModules();
855  replyType = "void";
856  return true;
857  }
858  else if (fun == "loadSecondPhase()") {
859  Kded::self()->loadSecondPhase();
860  replyType = "void";
861  return true;
862  }
863  else if (fun == "quit()") {
864  quit();
865  replyType = "void";
866  return true;
867  }
868  return KUniqueApplication::process(fun, data, replyType, replyData);
869  }
870 
871  bool startup;
872  KDEDQtDCOPObject kdedQtDcopObject;
873 };
874 
875 extern "C" KDE_EXPORT int kdemain(int argc, char *argv[])
876 {
877  KAboutData aboutData( "kded", I18N_NOOP("KDE Daemon"),
878  "$Id$",
879  I18N_NOOP("KDE Daemon - triggers Sycoca database updates when needed"));
880 
881  KApplication::installSigpipeHandler();
882 
883  KCmdLineArgs::init(argc, argv, &aboutData);
884 
885  KUniqueApplication::addCmdLineOptions();
886 
887  KCmdLineArgs::addCmdLineOptions( options );
888 
889  // this program is in kdelibs so it uses kdelibs as catalog
890  KLocale::setMainCatalogue("kdelibs");
891 
892  // WABA: Make sure not to enable session management.
893  putenv(strdup("SESSION_MANAGER="));
894 
895  // Parse command line before checking DCOP
896  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
897 
898  // Check DCOP communication.
899  {
900  DCOPClient testDCOP;
901  TQCString dcopName = testDCOP.registerAs("kded", false);
902  if (dcopName.isEmpty())
903  {
904  kdFatal() << "DCOP communication problem!" << endl;
905  return 1;
906  }
907  }
908 
909  KInstance *instance = new KInstance(&aboutData);
910  KConfig *config = instance->config(); // Enable translations.
911 
912  if (args->isSet("check"))
913  {
914  config->setGroup("General");
915  checkStamps = config->readBoolEntry("CheckFileStamps", true);
916  runBuildSycoca();
917  runKonfUpdate();
918  exit(0);
919  }
920 
921  if (!KUniqueApplication::start())
922  {
923  fprintf(stderr, "[kded] Daemon (kded) is already running.\n");
924  exit(0);
925  }
926 
927  KUniqueApplication::dcopClient()->setQtBridgeEnabled(false);
928 
929  config->setGroup("General");
930  int HostnamePollInterval = config->readNumEntry("HostnamePollInterval", 5000);
931  bool bCheckSycoca = config->readBoolEntry("CheckSycoca", true);
932  bool bCheckUpdates = config->readBoolEntry("CheckUpdates", true);
933  bool bCheckHostname = config->readBoolEntry("CheckHostname", true);
934  checkStamps = config->readBoolEntry("CheckFileStamps", true);
935  delayedCheck = config->readBoolEntry("DelayedCheck", false);
936 
937  Kded *kded = new Kded(bCheckSycoca, args->isSet("new-startup")); // Build data base
938 
939  signal(SIGTERM, sighandler);
940  signal(SIGHUP, sighandler);
941  KDEDApplication k;
942 
943  kded->recreate(true); // initial
944 
945  if (bCheckUpdates)
946  (void) new KUpdateD; // Watch for updates
947 
948  runKonfUpdate(); // Run it once.
949 
950  if (bCheckHostname)
951  (void) new KHostnameD(HostnamePollInterval); // Watch for hostname changes
952 
953  DCOPClient *client = kapp->dcopClient();
954  TQObject::connect(client, TQT_SIGNAL(applicationRemoved(const TQCString&)),
955  kded, TQT_SLOT(slotApplicationRemoved(const TQCString&)));
956  client->setNotifications(true);
957  client->setDaemonMode( true );
958 
959  // During startup kdesktop waits for KDED to finish.
960  // Send a notifyDatabaseChanged signal even if the database hasn't
961  // changed.
962  // If the database changed, kbuildsycoca's signal didn't go anywhere
963  // anyway, because it was too early, so let's send this signal
964  // unconditionnally (David)
965  TQByteArray data;
966  client->send( "*", "ksycoca", "notifyDatabaseChanged()", data );
967  client->send( "ksplash", "", "upAndRunning(TQString)", TQString("kded"));
968 #ifdef Q_WS_X11
969  XEvent e;
970  e.xclient.type = ClientMessage;
971  e.xclient.message_type = XInternAtom( qt_xdisplay(), "_KDE_SPLASH_PROGRESS", False );
972  e.xclient.display = qt_xdisplay();
973  e.xclient.window = qt_xrootwin();
974  e.xclient.format = 8;
975  strcpy( e.xclient.data.b, "kded" );
976  XSendEvent( qt_xdisplay(), qt_xrootwin(), False, SubstructureNotifyMask, &e );
977 #endif
978  int result = k.exec(); // keep running
979 
980  delete kded;
981  delete instance; // Deletes config as well
982 
983  return result;
984 }
985 
986 #include "kded.moc"

kded

Skip menu "kded"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

kded

Skip menu "kded"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kded by doxygen 1.8.3.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |