• 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 <tdecrash.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 <tdeuniqueapplication.h>
39 #include <tdecmdlineargs.h>
40 #include <tdeaboutdata.h>
41 #include <tdelocale.h>
42 #include <tdeglobal.h>
43 #include <tdeprocess.h>
44 #include <kdebug.h>
45 #include <kdirwatch.h>
46 #include <kstandarddirs.h>
47 #include <kdatastream.h>
48 #include <tdeio/global.h>
49 #include <kservicetype.h>
50 
51 #ifdef TQ_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("tdebuildsycoca") << args;
76  TQCString _launcher = TDEApplication::launcher();
77 
78  kapp->dcopClient()->callAsync(_launcher, _launcher, "tdeinit_exec_wait(TQString,TQStringList)", data, callBackObj, callBackSlot);
79  }
80  else
81  {
82  TDEApplication::tdeinitExecWait( "tdebuildsycoca", args );
83  }
84 }
85 
86 static void runKonfUpdate()
87 {
88  TDEApplication::tdeinitExecWait( "tdeconf_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  TDEApplication::tdeinitExecWait( "kdontchangethehostname", args );
97 }
98 
99 Kded::Kded(bool checkUpdates, bool new_startup)
100  : DCOPObject("tdebuildsycoca"), DCOPObjectProxy(),
101  b_checkUpdates(checkUpdates),
102  m_needDelayedCheck(false),
103  m_newStartup( new_startup )
104 {
105  _self = this;
106  TQCString cPath;
107  TQCString tdesycoca_env = getenv("TDESYCOCA");
108  if (tdesycoca_env.isEmpty())
109  cPath = TQFile::encodeName(TDEGlobal::dirs()->saveLocation("tmp")+"tdesycoca");
110  else
111  cPath = tdesycoca_env;
112  m_pTimer = new TQTimer(this);
113  connect(m_pTimer, TQ_SIGNAL(timeout()), this, TQ_SLOT(recreate()));
114 
115  TQTimer::singleShot(100, this, TQ_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 == "tdesycoca") 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  TDEConfig *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( "TDE_SESSION_UID" ) != NULL && uid_t( atoi( getenv( "TDE_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-TDE-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-TDE-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-TDE-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  TDEConfig *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-TDE-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-TDE-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-TDE-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-TDE-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-TDE-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, TQ_SIGNAL(moduleDeleted(KDEDModule *)), TQ_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, TQ_SIGNAL(dirty(const TQString&)),
404  this, TQ_SLOT(update(const TQString&)));
405  TQObject::connect( m_pDirWatch, TQ_SIGNAL(created(const TQString&)),
406  this, TQ_SLOT(update(const TQString&)));
407  TQObject::connect( m_pDirWatch, TQ_SIGNAL(deleted(const TQString&)),
408  this, TQ_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  tqWarning("Last DCOP call before KDED crash was from application '%s'\n"
446  "to object '%s', function '%s'.",
447  DCOPClient::postMortemSender(),
448  DCOPClient::postMortemObject(),
449  DCOPClient::postMortemFunction());
450  tqWarning("Restarting KDED...\n");
451  if (system("kded") < 0) {
452  tqWarning("Unable to restart KDED!\n");
453  }
454  }
455 }
456 
457 void Kded::installCrashHandler()
458 {
459  TDECrash::setEmergencySaveFunction(crashHandler);
460 }
461 
462 void Kded::recreate()
463 {
464  recreate(false);
465 }
466 
467 void Kded::runDelayedCheck()
468 {
469  if( m_needDelayedCheck )
470  recreate(false);
471  m_needDelayedCheck = false;
472 }
473 
474 void Kded::recreate(bool initial)
475 {
476  m_recreateBusy = true;
477  // Using TDELauncher here is difficult since we might not have a
478  // database
479 
480  if (!initial)
481  {
482  updateDirWatch(); // Update tree first, to be sure to miss nothing.
483  runBuildSycoca(this, TQ_SLOT(recreateDone()));
484  }
485  else
486  {
487  if(!delayedCheck)
488  updateDirWatch(); // this would search all the directories
489  runBuildSycoca();
490  recreateDone();
491  if(delayedCheck)
492  {
493  // do a proper tdesycoca check after a delay
494  TQTimer::singleShot( 60000, this, TQ_SLOT( runDelayedCheck()));
495  m_needDelayedCheck = true;
496  delayedCheck = false;
497  }
498  else
499  m_needDelayedCheck = false;
500  }
501 }
502 
503 void Kded::recreateDone()
504 {
505  updateResourceList();
506 
507  for(; m_recreateCount; m_recreateCount--)
508  {
509  TQCString replyType = "void";
510  TQByteArray replyData;
511  DCOPClientTransaction *transaction = m_recreateRequests.first();
512  if (transaction)
513  kapp->dcopClient()->endTransaction(transaction, replyType, replyData);
514  m_recreateRequests.remove(m_recreateRequests.begin());
515  }
516  m_recreateBusy = false;
517 
518  // Did a new request come in while building?
519  if (!m_recreateRequests.isEmpty())
520  {
521  m_pTimer->start(2000, true /* single shot */ );
522  m_recreateCount = m_recreateRequests.count();
523  }
524 }
525 
526 void Kded::dirDeleted(const TQString& path)
527 {
528  update(path);
529 }
530 
531 void Kded::update(const TQString& )
532 {
533  if (!m_recreateBusy)
534  {
535  m_pTimer->start( 2000, true /* single shot */ );
536  }
537  else
538  {
539  m_recreateRequests.append(0);
540  }
541 }
542 
543 bool Kded::process(const TQCString &fun, const TQByteArray &data,
544  TQCString &replyType, TQByteArray &replyData)
545 {
546  if (fun == "recreate()") {
547  if (!m_recreateBusy)
548  {
549  if (m_recreateRequests.isEmpty())
550  {
551  m_pTimer->start(0, true /* single shot */ );
552  m_recreateCount = 0;
553  }
554  m_recreateCount++;
555  }
556  m_recreateRequests.append(kapp->dcopClient()->beginTransaction());
557  replyType = "void";
558  return true;
559  } else {
560  return DCOPObject::process(fun, data, replyType, replyData);
561  }
562 }
563 
564 
565 void Kded::readDirectory( const TQString& _path )
566 {
567  TQString path( _path );
568  if ( path.right(1) != "/" )
569  path += "/";
570 
571  if ( m_pDirWatch->contains( path ) ) // Already seen this one?
572  return;
573 
574  TQDir d( _path, TQString::null, TQDir::Unsorted, TQDir::Readable | TQDir::Executable | TQDir::Dirs | TQDir::Hidden );
575  // set TQDir ...
576 
577 
578  //************************************************************************
579  // Setting dirs
580  //************************************************************************
581 
582  m_pDirWatch->addDir(path); // add watch on this dir
583 
584  if ( !d.exists() ) // exists&isdir?
585  {
586  kdDebug(7020) << TQString(TQString("Does not exist! (%1)").arg(_path)) << endl;
587  return; // return false
588  }
589 
590  // Note: If some directory is gone, dirwatch will delete it from the list.
591 
592  //************************************************************************
593  // Reading
594  //************************************************************************
595  TQString file;
596  unsigned int i; // counter and string length.
597  unsigned int count = d.count();
598  for( i = 0; i < count; i++ ) // check all entries
599  {
600  if (d[i] == "." || d[i] == ".." || d[i] == "magic")
601  continue; // discard those ".", "..", "magic"...
602 
603  file = path; // set full path
604  file += d[i]; // and add the file name.
605 
606  readDirectory( file ); // yes, dive into it.
607  }
608 }
609 
610 bool Kded::isWindowRegistered(long windowId)
611 {
612  return m_globalWindowIdList.find(windowId) != 0;
613 
614 }
615 
616 // DCOP
617 void Kded::registerWindowId(long windowId)
618 {
619  m_globalWindowIdList.replace(windowId, &windowId);
620  TQCString sender = callingDcopClient()->senderId();
621  if( sender.isEmpty()) // local call
622  sender = callingDcopClient()->appId();
623  TQValueList<long> *windowIds = m_windowIdList.find(sender);
624  if (!windowIds)
625  {
626  windowIds = new TQValueList<long>;
627  m_windowIdList.insert(sender, windowIds);
628  }
629  windowIds->append(windowId);
630 
631 
632  for(TQAsciiDictIterator<KDEDModule> it(m_modules); it.current(); ++it)
633  {
634  emit it.current()->windowRegistered(windowId);
635  }
636 }
637 
638 // DCOP
639 void Kded::unregisterWindowId(long windowId)
640 {
641  m_globalWindowIdList.remove(windowId);
642  TQCString sender = callingDcopClient()->senderId();
643  if( sender.isEmpty()) // local call
644  sender = callingDcopClient()->appId();
645  TQValueList<long> *windowIds = m_windowIdList.find(sender);
646  if (windowIds)
647  {
648  windowIds->remove(windowId);
649  if (windowIds->isEmpty())
650  m_windowIdList.remove(sender);
651  }
652 
653  for(TQAsciiDictIterator<KDEDModule> it(m_modules); it.current(); ++it)
654  {
655  emit it.current()->windowUnregistered(windowId);
656  }
657 }
658 
659 
660 static void sighandler(int /*sig*/)
661 {
662  if (kapp)
663  kapp->quit();
664 }
665 
666 KUpdateD::KUpdateD()
667 {
668  m_pDirWatch = new KDirWatch;
669  m_pTimer = new TQTimer;
670  connect(m_pTimer, TQ_SIGNAL(timeout()), this, TQ_SLOT(runKonfUpdate()));
671  TQObject::connect( m_pDirWatch, TQ_SIGNAL(dirty(const TQString&)),
672  this, TQ_SLOT(slotNewUpdateFile()));
673 
674  TQStringList dirs = TDEGlobal::dirs()->findDirs("data", "tdeconf_update");
675  for( TQStringList::ConstIterator it = dirs.begin();
676  it != dirs.end();
677  ++it )
678  {
679  TQString path = *it;
680  if (path[path.length()-1] != '/')
681  path += "/";
682 
683  if (!m_pDirWatch->contains(path))
684  m_pDirWatch->addDir(path);
685  }
686 }
687 
688 KUpdateD::~KUpdateD()
689 {
690  delete m_pDirWatch;
691  delete m_pTimer;
692 }
693 
694 void KUpdateD::runKonfUpdate()
695 {
696  ::runKonfUpdate();
697 }
698 
699 void KUpdateD::slotNewUpdateFile()
700 {
701  m_pTimer->start( 500, true /* single shot */ );
702 }
703 
704 KHostnameD::KHostnameD(int pollInterval)
705 {
706  m_Timer.start(pollInterval, false /* repetitive */ );
707  connect(&m_Timer, TQ_SIGNAL(timeout()), this, TQ_SLOT(checkHostname()));
708  checkHostname();
709 }
710 
711 KHostnameD::~KHostnameD()
712 {
713  // Empty
714 }
715 
716 void KHostnameD::checkHostname()
717 {
718  char buf[1024+1];
719  if (gethostname(buf, 1024) != 0)
720  return;
721  buf[sizeof(buf)-1] = '\0';
722 
723  if (m_hostname.isEmpty())
724  {
725  m_hostname = buf;
726  return;
727  }
728 
729  if (m_hostname == buf)
730  return;
731 
732  TQCString newHostname = buf;
733 
734  runDontChangeHostname(m_hostname, newHostname);
735  m_hostname = newHostname;
736 }
737 
738 
739 static TDECmdLineOptions options[] =
740 {
741  { "check", I18N_NOOP("Check Sycoca database only once"), 0 },
742  { "new-startup", "Internal", 0 },
743  TDECmdLineLastOption
744 };
745 
746 class KDEDQtDCOPObject : public DCOPObject
747 {
748 public:
749  KDEDQtDCOPObject() : DCOPObject("qt/kded") { }
750 
751  virtual bool process(const TQCString &fun, const TQByteArray &data,
752  TQCString& replyType, TQByteArray &replyData)
753  {
754  if ( kapp && (fun == "quit()") )
755  {
756  kapp->quit();
757  replyType = "void";
758  return true;
759  }
760  return DCOPObject::process(fun, data, replyType, replyData);
761  }
762 
763  QCStringList functions()
764  {
765  QCStringList res = DCOPObject::functions();
766  res += "void quit()";
767  return res;
768  }
769 };
770 
771 class KDEDApplication : public TDEUniqueApplication
772 {
773 public:
774  KDEDApplication() : TDEUniqueApplication( )
775  {
776  startup = true;
777  dcopClient()->connectDCOPSignal( "DCOPServer", "", "terminateTDE()",
778  objId(), "quit()", false );
779  }
780 
781  int newInstance()
782  {
783  if (startup) {
784  startup = false;
785  if( Kded::self()->newStartup())
786  Kded::self()->initModules();
787  else
788  TQTimer::singleShot(500, Kded::self(), TQ_SLOT(initModules()));
789  } else
790  runBuildSycoca();
791 
792  return 0;
793  }
794 
795  QCStringList functions()
796  {
797  QCStringList res = TDEUniqueApplication::functions();
798  res += "bool loadModule(TQCString)";
799  res += "bool unloadModule(TQCString)";
800  res += "void registerWindowId(long int)";
801  res += "void unregisterWindowId(long int)";
802  res += "QCStringList loadedModules()";
803  res += "void reconfigure()";
804  res += "void loadSecondPhase()";
805  res += "void quit()";
806  return res;
807  }
808 
809  bool process(const TQCString &fun, const TQByteArray &data,
810  TQCString &replyType, TQByteArray &replyData)
811  {
812  if (fun == "loadModule(TQCString)") {
813  TQCString module;
814  TQDataStream arg( data, IO_ReadOnly );
815  arg >> module;
816  bool result = (Kded::self()->loadModule(module, false) != 0);
817  replyType = "bool";
818  TQDataStream _replyStream( replyData, IO_WriteOnly );
819  _replyStream << result;
820  return true;
821  }
822  else if (fun == "unloadModule(TQCString)") {
823  TQCString module;
824  TQDataStream arg( data, IO_ReadOnly );
825  arg >> module;
826  bool result = Kded::self()->unloadModule(module);
827  replyType = "bool";
828  TQDataStream _replyStream( replyData, IO_WriteOnly );
829  _replyStream << result;
830  return true;
831  }
832  else if (fun == "registerWindowId(long int)") {
833  long windowId;
834  TQDataStream arg( data, IO_ReadOnly );
835  arg >> windowId;
836  Kded::self()->setCallingDcopClient(callingDcopClient());
837  Kded::self()->registerWindowId(windowId);
838  replyType = "void";
839  return true;
840  }
841  else if (fun == "unregisterWindowId(long int)") {
842  long windowId;
843  TQDataStream arg( data, IO_ReadOnly );
844  arg >> windowId;
845  Kded::self()->setCallingDcopClient(callingDcopClient());
846  Kded::self()->unregisterWindowId(windowId);
847  replyType = "void";
848  return true;
849  }
850  else if (fun == "loadedModules()") {
851  replyType = "QCStringList";
852  TQDataStream _replyStream(replyData, IO_WriteOnly);
853  _replyStream << Kded::self()->loadedModules();
854  return true;
855  }
856  else if (fun == "reconfigure()") {
857  config()->reparseConfiguration();
858  Kded::self()->initModules();
859  replyType = "void";
860  return true;
861  }
862  else if (fun == "loadSecondPhase()") {
863  Kded::self()->loadSecondPhase();
864  replyType = "void";
865  return true;
866  }
867  else if (fun == "quit()") {
868  quit();
869  replyType = "void";
870  return true;
871  }
872  return TDEUniqueApplication::process(fun, data, replyType, replyData);
873  }
874 
875  bool startup;
876  KDEDQtDCOPObject kdedQtDcopObject;
877 };
878 
879 extern "C" TDE_EXPORT int kdemain(int argc, char *argv[])
880 {
881  TDEAboutData aboutData( "kded", I18N_NOOP("TDE Daemon"),
882  "$Id$",
883  I18N_NOOP("TDE Daemon - triggers Sycoca database updates when needed"));
884 
885  TDEApplication::installSigpipeHandler();
886 
887  TDECmdLineArgs::init(argc, argv, &aboutData);
888 
889  TDEUniqueApplication::addCmdLineOptions();
890 
891  TDECmdLineArgs::addCmdLineOptions( options );
892 
893  // this program is in tdelibs so it uses tdelibs as catalog
894  TDELocale::setMainCatalogue("tdelibs");
895 
896  // WABA: Make sure not to enable session management.
897  putenv(strdup("SESSION_MANAGER="));
898 
899  // Parse command line before checking DCOP
900  TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();
901 
902  // Check DCOP communication.
903  {
904  DCOPClient testDCOP;
905  TQCString dcopName = testDCOP.registerAs("kded", false);
906  if (dcopName.isEmpty())
907  {
908  kdFatal() << "DCOP communication problem!" << endl;
909  return 1;
910  }
911  }
912 
913  TDEInstance *instance = new TDEInstance(&aboutData);
914  TDEConfig *config = instance->config(); // Enable translations.
915 
916  if (args->isSet("check"))
917  {
918  config->setGroup("General");
919  checkStamps = config->readBoolEntry("CheckFileStamps", true);
920  runBuildSycoca();
921  runKonfUpdate();
922  exit(0);
923  }
924 
925  if (!TDEUniqueApplication::start())
926  {
927  fprintf(stderr, "[kded] Daemon (kded) is already running.\n");
928  exit(0);
929  }
930 
931  TDEUniqueApplication::dcopClient()->setQtBridgeEnabled(false);
932 
933  config->setGroup("General");
934  int HostnamePollInterval = config->readNumEntry("HostnamePollInterval", 5000);
935  bool bCheckSycoca = config->readBoolEntry("CheckSycoca", true);
936  bool bCheckUpdates = config->readBoolEntry("CheckUpdates", true);
937  bool bCheckHostname = config->readBoolEntry("CheckHostname", true);
938  checkStamps = config->readBoolEntry("CheckFileStamps", true);
939  delayedCheck = config->readBoolEntry("DelayedCheck", false);
940 
941  Kded *kded = new Kded(bCheckSycoca, args->isSet("new-startup")); // Build data base
942 
943  signal(SIGTERM, sighandler);
944  signal(SIGHUP, sighandler);
945  KDEDApplication k;
946 
947  kded->recreate(true); // initial
948 
949  if (bCheckUpdates)
950  (void) new KUpdateD; // Watch for updates
951 
952  runKonfUpdate(); // Run it once.
953 
954  if (bCheckHostname)
955  (void) new KHostnameD(HostnamePollInterval); // Watch for hostname changes
956 
957  DCOPClient *client = kapp->dcopClient();
958  TQObject::connect(client, TQ_SIGNAL(applicationRemoved(const TQCString&)),
959  kded, TQ_SLOT(slotApplicationRemoved(const TQCString&)));
960  client->setNotifications(true);
961  client->setDaemonMode( true );
962 
963  // During startup kdesktop waits for KDED to finish.
964  // Send a notifyDatabaseChanged signal even if the database hasn't
965  // changed.
966  // If the database changed, tdebuildsycoca's signal didn't go anywhere
967  // anyway, because it was too early, so let's send this signal
968  // unconditionnally (David)
969  TQByteArray data;
970  client->send( "*", "tdesycoca", "notifyDatabaseChanged()", data );
971  client->send( "ksplash", "", "upAndRunning(TQString)", TQString("kded"));
972 #ifdef TQ_WS_X11
973  XEvent e;
974  e.xclient.type = ClientMessage;
975  e.xclient.message_type = XInternAtom( tqt_xdisplay(), "_KDE_SPLASH_PROGRESS", False );
976  e.xclient.display = tqt_xdisplay();
977  e.xclient.window = tqt_xrootwin();
978  e.xclient.format = 8;
979  strcpy( e.xclient.data.b, "kded" );
980  XSendEvent( tqt_xdisplay(), tqt_xrootwin(), False, SubstructureNotifyMask, &e );
981 #endif
982  int result = k.exec(); // keep running
983 
984  delete kded;
985  delete instance; // Deletes config as well
986 
987  return result;
988 }
989 
990 #include "kded.moc"
KDEDModule
The base class for KDED modules.
Definition: kdedmodule.h:56
KDEDModule::find
TDEShared * find(const TQCString &app, const TQCString &key)
Lookup object indexed with app and key.
Definition: kdedmodule.cpp:83

kded

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

kded

Skip menu "kded"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kded by doxygen 1.9.1
This website is maintained by Timothy Pearson.