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

kdecore

  • kdecore
kapplication.cpp
1 /* This file is part of the KDE libraries
2  Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
3  Copyright (C) 1998, 1999, 2000 KDE Team
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 as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19  */
20 
21 #include "config.h"
22 
23 #ifdef HAVE_XCOMPOSITE
24 #define COMPOSITE
25 #endif
26 
27 // #ifdef QTRANSLATOR_H
28 // #error qtranslator.h was already included
29 // #endif // QTRANSLATOR_H
30 //
31 // #ifdef TQTRANSLATOR_H
32 // #error tqtranslator.h was already included
33 // #endif // TQTRANSLATOR_H
34 
35 #undef QT_NO_TRANSLATION
36 #undef TQT_NO_TRANSLATION
37 #include <tqtranslator.h>
38 #include "kapplication.h"
39 #define QT_NO_TRANSLATION
40 #define TQT_NO_TRANSLATION
41 #include <tqdir.h>
42 #include <tqptrcollection.h>
43 #include <tqwidgetlist.h>
44 #include <tqstrlist.h>
45 #include <tqfile.h>
46 #include <tqmessagebox.h>
47 #include <tqtextstream.h>
48 #include <tqregexp.h>
49 #include <tqlineedit.h>
50 #include <tqtextedit.h>
51 #include <tqsessionmanager.h>
52 #include <tqptrlist.h>
53 #include <tqtimer.h>
54 #include <tqstylesheet.h>
55 #include <tqpixmapcache.h>
56 #include <tqtooltip.h>
57 #include <tqstylefactory.h>
58 #include <tqmetaobject.h>
59 #include <tqimage.h>
60 #ifndef QT_NO_SQL
61 #include <tqsqlpropertymap.h>
62 #endif
63 
64 #include <kglobal.h>
65 #include <kstandarddirs.h>
66 #include <kdebug.h>
67 #include <klocale.h>
68 #include <kstyle.h>
69 #include <kiconloader.h>
70 #include <kclipboard.h>
71 #include <kconfig.h>
72 #include <ksimpleconfig.h>
73 #include <kcmdlineargs.h>
74 #include <kaboutdata.h>
75 #include <kglobalsettings.h>
76 #include <kcrash.h>
77 #include <kdatastream.h>
78 #include <klibloader.h>
79 #include <kmimesourcefactory.h>
80 #include <kstdaccel.h>
81 #include <kaccel.h>
82 #include "kcheckaccelerators.h"
83 #include <tqptrdict.h>
84 #include <kmacroexpander.h>
85 #include <kshell.h>
86 #include <kprotocolinfo.h>
87 #include <kkeynative.h>
88 #include <kmdcodec.h>
89 #include <kglobalaccel.h>
90 
91 #if defined Q_WS_X11
92 #include <kstartupinfo.h>
93 #endif
94 
95 #include <dcopclient.h>
96 #include <dcopref.h>
97 
98 #include <sys/types.h>
99 #ifdef HAVE_SYS_STAT_H
100 #include <sys/stat.h>
101 #endif
102 #include <sys/wait.h>
103 #include <grp.h>
104 #include <sys/types.h>
105 
106 #ifndef Q_WS_WIN
107 #include "kwin.h"
108 #endif
109 
110 #include <fcntl.h>
111 #include <stdlib.h> // getenv(), srand(), rand()
112 #include <signal.h>
113 #include <unistd.h>
114 #include <time.h>
115 #include <sys/time.h>
116 #include <errno.h>
117 #include <string.h>
118 #include <netdb.h>
119 #if defined Q_WS_X11
120 //#ifndef Q_WS_QWS //FIXME(E): NetWM should talk to QWS...
121 #include <netwm.h>
122 #endif
123 
124 #include "kprocctrl.h"
125 
126 #ifdef HAVE_PATHS_H
127 #include <paths.h>
128 #endif
129 
130 #ifdef Q_WS_X11
131 #include <X11/Xlib.h>
132 #ifdef COMPOSITE
133 #include <X11/extensions/Xrender.h>
134 #include <X11/extensions/Xcomposite.h>
135 #include <dlfcn.h>
136 #endif
137 #include <X11/Xutil.h>
138 #include <X11/Xatom.h>
139 #include <X11/SM/SMlib.h>
140 #include <fixx11h.h>
141 #endif
142 
143 #include <pwd.h>
144 
145 #ifndef Q_WS_WIN
146 #include <KDE-ICE/ICElib.h>
147 #else
148 typedef void* IceIOErrorHandler;
149 #include <windows.h>
150 //KDE4: remove
151 #define Button1Mask (1<<8)
152 #define Button2Mask (1<<9)
153 #define Button3Mask (1<<10)
154 #endif
155 
156 #ifdef Q_WS_X11
157 #define DISPLAY "DISPLAY"
158 #elif defined(Q_WS_QWS)
159 #define DISPLAY "QWS_DISPLAY"
160 #endif
161 
162 #if defined Q_WS_X11
163 #include <kipc.h>
164 #endif
165 
166 #ifdef Q_WS_MACX
167 #include <Carbon/Carbon.h>
168 #include <tqimage.h>
169 #endif
170 
171 #include "kappdcopiface.h"
172 
173 // exported for kdm kfrontend
174 KDE_EXPORT bool kde_have_kipc = true; // magic hook to disable kipc in kdm
175 bool kde_kiosk_exception = false; // flag to disable kiosk restrictions
176 bool kde_kiosk_admin = false;
177 
178 KApplication* KApplication::KApp = 0L;
179 bool KApplication::loadedByKdeinit = false;
180 DCOPClient *KApplication::s_DCOPClient = 0L;
181 bool KApplication::s_dcopClientNeedsPostInit = false;
182 
183 #ifdef Q_WS_X11
184 static Atom atom_DesktopWindow;
185 static Atom atom_NetSupported;
186 static Atom kde_xdnd_drop;
187 #endif
188 
189 #ifdef Q_WS_X11
190 static int composite_event, composite_error, composite_opcode;
191 static bool x11_composite_error_generated;
192 static int x11_error(Display *dpy, XErrorEvent *ev) {
193  if (ev->request_code == composite_opcode && ev->minor_code == X_CompositeRedirectSubwindows)
194  {
195  x11_composite_error_generated = true;
196  return 0;
197  }
198 }
199 #endif
200 
201 // duplicated from patched Qt, so that there won't be unresolved symbols if Qt gets
202 // replaced by unpatched one
203 KDECORE_EXPORT bool qt_qclipboard_bailout_hack = false;
204 
205 template class TQPtrList<KSessionManaged>;
206 
207 #ifdef Q_WS_X11
208 extern "C" {
209 static int kde_xio_errhandler( Display * dpy )
210 {
211  return kapp->xioErrhandler( dpy );
212 }
213 
214 static int kde_x_errhandler( Display *dpy, XErrorEvent *err )
215 {
216  return kapp->xErrhandler( dpy, err );
217 }
218 
219 }
220 
221 extern "C" {
222 static void kde_ice_ioerrorhandler( IceConn conn )
223 {
224  if(kapp)
225  kapp->iceIOErrorHandler( conn );
226  // else ignore the error for now
227 }
228 }
229 #endif
230 
231 #ifdef Q_WS_WIN
232 void KApplication_init_windows(bool GUIenabled);
233 
234 class QAssistantClient;
235 #endif
236 
237 /*
238  Private data to make keeping binary compatibility easier
239  */
240 class KApplicationPrivate
241 {
242 public:
243  KApplicationPrivate()
244  : actionRestrictions( false ),
245  refCount( 1 ),
246  oldIceIOErrorHandler( 0 ),
247  checkAccelerators( 0 ),
248  overrideStyle( TQString::null ),
249  startup_id( "0" ),
250  app_started_timer( NULL ),
251  m_KAppDCOPInterface( 0L ),
252  session_save( false )
253 #ifdef Q_WS_X11
254  ,oldXErrorHandler( NULL )
255  ,oldXIOErrorHandler( NULL )
256 #elif defined Q_WS_WIN
257  ,qassistantclient( 0 )
258 #endif
259  {
260  }
261 
262  ~KApplicationPrivate()
263  {
264 #ifdef Q_WS_WIN
265  delete qassistantclient;
266 #endif
267  }
268 
269 
270  bool actionRestrictions : 1;
271  bool guiEnabled : 1;
278  int refCount;
279  IceIOErrorHandler oldIceIOErrorHandler;
280  KCheckAccelerators* checkAccelerators;
281  TQString overrideStyle;
282  TQString geometry_arg;
283  TQCString startup_id;
284  TQTimer* app_started_timer;
285  KAppDCOPInterface *m_KAppDCOPInterface;
286  bool session_save;
287 #ifdef Q_WS_X11
288  int (*oldXErrorHandler)(Display*,XErrorEvent*);
289  int (*oldXIOErrorHandler)(Display*);
290 #elif defined Q_WS_WIN
291  QAssistantClient* qassistantclient;
292 #endif
293 
294  class URLActionRule
295  {
296  public:
297 #define checkExactMatch(s, b) \
298  if (s.isEmpty()) b = true; \
299  else if (s[s.length()-1] == '!') \
300  { b = false; s.truncate(s.length()-1); } \
301  else b = true;
302 #define checkStartWildCard(s, b) \
303  if (s.isEmpty()) b = true; \
304  else if (s[0] == '*') \
305  { b = true; s = s.mid(1); } \
306  else b = false;
307 #define checkEqual(s, b) \
308  b = (s == "=");
309 
310  URLActionRule(const TQString &act,
311  const TQString &bProt, const TQString &bHost, const TQString &bPath,
312  const TQString &dProt, const TQString &dHost, const TQString &dPath,
313  bool perm)
314  : action(act),
315  baseProt(bProt), baseHost(bHost), basePath(bPath),
316  destProt(dProt), destHost(dHost), destPath(dPath),
317  permission(perm)
318  {
319  checkExactMatch(baseProt, baseProtWildCard);
320  checkStartWildCard(baseHost, baseHostWildCard);
321  checkExactMatch(basePath, basePathWildCard);
322  checkExactMatch(destProt, destProtWildCard);
323  checkStartWildCard(destHost, destHostWildCard);
324  checkExactMatch(destPath, destPathWildCard);
325  checkEqual(destProt, destProtEqual);
326  checkEqual(destHost, destHostEqual);
327  }
328 
329  bool baseMatch(const KURL &url, const TQString &protClass)
330  {
331  if (baseProtWildCard)
332  {
333  if ( !baseProt.isEmpty() && !url.protocol().startsWith(baseProt) &&
334  (protClass.isEmpty() || (protClass != baseProt)) )
335  return false;
336  }
337  else
338  {
339  if ( (url.protocol() != baseProt) &&
340  (protClass.isEmpty() || (protClass != baseProt)) )
341  return false;
342  }
343  if (baseHostWildCard)
344  {
345  if (!baseHost.isEmpty() && !url.host().endsWith(baseHost))
346  return false;
347  }
348  else
349  {
350  if (url.host() != baseHost)
351  return false;
352  }
353  if (basePathWildCard)
354  {
355  if (!basePath.isEmpty() && !url.path().startsWith(basePath))
356  return false;
357  }
358  else
359  {
360  if (url.path() != basePath)
361  return false;
362  }
363  return true;
364  }
365 
366  bool destMatch(const KURL &url, const TQString &protClass, const KURL &base, const TQString &baseClass)
367  {
368  if (destProtEqual)
369  {
370  if ( (url.protocol() != base.protocol()) &&
371  (protClass.isEmpty() || baseClass.isEmpty() || protClass != baseClass) )
372  return false;
373  }
374  else if (destProtWildCard)
375  {
376  if ( !destProt.isEmpty() && !url.protocol().startsWith(destProt) &&
377  (protClass.isEmpty() || (protClass != destProt)) )
378  return false;
379  }
380  else
381  {
382  if ( (url.protocol() != destProt) &&
383  (protClass.isEmpty() || (protClass != destProt)) )
384  return false;
385  }
386  if (destHostWildCard)
387  {
388  if (!destHost.isEmpty() && !url.host().endsWith(destHost))
389  return false;
390  }
391  else if (destHostEqual)
392  {
393  if (url.host() != base.host())
394  return false;
395  }
396  else
397  {
398  if (url.host() != destHost)
399  return false;
400  }
401  if (destPathWildCard)
402  {
403  if (!destPath.isEmpty() && !url.path().startsWith(destPath))
404  return false;
405  }
406  else
407  {
408  if (url.path() != destPath)
409  return false;
410  }
411  return true;
412  }
413 
414  TQString action;
415  TQString baseProt;
416  TQString baseHost;
417  TQString basePath;
418  TQString destProt;
419  TQString destHost;
420  TQString destPath;
421  bool baseProtWildCard : 1;
422  bool baseHostWildCard : 1;
423  bool basePathWildCard : 1;
424  bool destProtWildCard : 1;
425  bool destHostWildCard : 1;
426  bool destPathWildCard : 1;
427  bool destProtEqual : 1;
428  bool destHostEqual : 1;
429  bool permission;
430  };
431  TQPtrList<URLActionRule> urlActionRestrictions;
432 
433  TQString sessionKey;
434  TQString pSessionConfigFile;
435 };
436 
437 
438 static TQPtrList<TQWidget>*x11Filter = 0;
439 static bool autoDcopRegistration = true;
440 
441 void KApplication::installX11EventFilter( TQWidget* filter )
442 {
443  if ( !filter )
444  return;
445  if (!x11Filter)
446  x11Filter = new TQPtrList<TQWidget>;
447  connect ( filter, TQT_SIGNAL( destroyed() ), this, TQT_SLOT( x11FilterDestroyed() ) );
448  x11Filter->append( filter );
449 }
450 
451 void KApplication::x11FilterDestroyed()
452 {
453  removeX11EventFilter( static_cast< const TQWidget* >( sender()));
454 }
455 
456 void KApplication::removeX11EventFilter( const TQWidget* filter )
457 {
458  if ( !x11Filter || !filter )
459  return;
460  x11Filter->removeRef( filter );
461  if ( x11Filter->isEmpty() ) {
462  delete x11Filter;
463  x11Filter = 0;
464  }
465 }
466 
467 // FIXME: remove this when we've get a better method of
468 // customizing accelerator handling -- hopefully in Qt.
469 // For now, this is set whenever an accelerator is overridden
470 // in KAccelEventHandler so that the AccelOverride isn't sent twice. -- ellis, 19/10/02
471 extern bool kde_g_bKillAccelOverride;
472 
473 bool KApplication::notify(TQObject *receiver, TQEvent *event)
474 {
475  TQEvent::Type t = event->type();
476  if (kde_g_bKillAccelOverride)
477  {
478  kde_g_bKillAccelOverride = false;
479  // Indicate that the accelerator has been overridden.
480  if (t == TQEvent::AccelOverride)
481  {
482  TQT_TQKEYEVENT(event)->accept();
483  return true;
484  }
485  else
486  kdWarning(125) << "kde_g_bKillAccelOverride set, but received an event other than AccelOverride." << endl;
487  }
488 
489  if ((t == TQEvent::AccelOverride) || (t == TQEvent::KeyPress))
490  {
491  static const KShortcut& _selectAll = KStdAccel::selectAll();
492  TQLineEdit *edit = ::tqqt_cast<TQLineEdit *>(receiver);
493  if (edit)
494  {
495  // We have a keypress for a lineedit...
496  TQKeyEvent *kevent = TQT_TQKEYEVENT(event);
497  KKey key(kevent);
498  if (_selectAll.contains(key))
499  {
500  if (t == TQEvent::KeyPress)
501  {
502  edit->selectAll();
503  return true;
504  }
505  else
506  {
507  kevent->accept();
508  }
509  }
510  // Ctrl-U deletes from start of line.
511  if (key == KKey(Qt::CTRL + Qt::Key_U))
512  {
513  if (t == TQEvent::KeyPress)
514  {
515  if (!edit->isReadOnly())
516  {
517  TQString t(edit->text());
518  t = t.mid(edit->cursorPosition());
519  edit->validateAndSet(t, 0, 0, 0);
520  }
521  return true;
522  }
523  else
524  {
525  kevent->accept();
526  }
527 
528  }
529  }
530  TQTextEdit *medit = ::tqqt_cast<TQTextEdit *>(receiver);
531  if (medit)
532  {
533  // We have a keypress for a multilineedit...
534  TQKeyEvent *kevent = TQT_TQKEYEVENT(event);
535  if (_selectAll.contains(KKey(kevent)))
536  {
537  if (t == TQEvent::KeyPress)
538  {
539  medit->selectAll();
540  return true;
541  }
542  else
543  {
544  kevent->accept();
545  }
546  }
547  }
548  }
549  if( t == TQEvent::Show && receiver->isWidgetType())
550  {
551  TQWidget* w = TQT_TQWIDGET( receiver );
552 #if defined Q_WS_X11
553  if( w->isTopLevel() && !startupId().isEmpty() && !TQT_TQSHOWEVENT(event)->spontaneous()) // TODO better done using window group leader?
554  KStartupInfo::setWindowStartupId( w->winId(), startupId());
555 #endif
556  if( w->isTopLevel() && !w->testWFlags( WX11BypassWM ) && !w->isPopup() && !event->spontaneous())
557  {
558  if( d->app_started_timer == NULL )
559  {
560  d->app_started_timer = new TQTimer( this, "app_started_timer" );
561  connect( d->app_started_timer, TQT_SIGNAL( timeout()), TQT_SLOT( checkAppStartedSlot()));
562  }
563  if( !d->app_started_timer->isActive())
564  d->app_started_timer->start( 0, true );
565  }
566  if( w->isTopLevel() && ( w->icon() == NULL || w->icon()->isNull()))
567  {
568  // icon() cannot be null pixmap, it'll be the "unknown" icon - so check if there is this application icon
569  static TQPixmap* ic = NULL;
570  if( ic == NULL )
571  ic = new TQPixmap( KGlobal::iconLoader()->loadIcon( iconName(),
572  KIcon::NoGroup, 0, KIcon::DefaultState, NULL, true ));
573  if( !ic->isNull())
574  {
575  w->setIcon( *ic );
576 #if defined Q_WS_X11
577  KWin::setIcons( w->winId(), *ic, miniIcon());
578 #endif
579  }
580  }
581  }
582  return TQApplication::notify(receiver, event);
583 }
584 
585 void KApplication::checkAppStartedSlot()
586 {
587 #if defined Q_WS_X11
588  KStartupInfo::handleAutoAppStartedSending();
589 #endif
590 }
591 
592 // the help class for session management communication
593 static TQPtrList<KSessionManaged>* sessionClients()
594 {
595  static TQPtrList<KSessionManaged>* session_clients = 0L;
596  if ( !session_clients )
597  session_clients = new TQPtrList<KSessionManaged>;
598  return session_clients;
599 }
600 
601 /*
602  Auxiliary function to calculate a a session config name used for the
603  instance specific config object.
604  Syntax: "session/<appname>_<sessionId>"
605  */
606 TQString KApplication::sessionConfigName() const
607 {
608  TQString sessKey = sessionKey();
609  if ( sessKey.isEmpty() && !d->sessionKey.isEmpty() )
610  sessKey = d->sessionKey;
611  return TQString("session/%1_%2_%3").arg(name()).arg(sessionId()).arg(sessKey);
612 }
613 
614 #ifdef Q_WS_X11
615 static SmcConn mySmcConnection = 0;
616 static SmcConn tmpSmcConnection = 0;
617 #else
618 // FIXME(E): Implement for Qt Embedded
619 // Possibly "steal" XFree86's libSM?
620 #endif
621 static TQTime* smModificationTime = 0;
622 
623 KApplication::KApplication( int& argc, char** argv, const TQCString& rAppName,
624  bool allowStyles, bool GUIenabled ) :
625  TQApplication( argc, argv, GUIenabled ), KInstance(rAppName),
626 #ifdef Q_WS_X11
627  display(0L),
628  argb_visual(false),
629 #endif
630  d (new KApplicationPrivate())
631 {
632  aIconPixmap.pm.icon = 0L;
633  aIconPixmap.pm.miniIcon = 0L;
634  read_app_startup_id();
635  if (!GUIenabled)
636  allowStyles = false;
637  useStyles = allowStyles;
638  Q_ASSERT (!rAppName.isEmpty());
639  setName(rAppName);
640 
641  installSigpipeHandler();
642  KCmdLineArgs::initIgnore(argc, argv, rAppName.data());
643  parseCommandLine( );
644  init(GUIenabled);
645  d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
646 }
647 
648 KApplication::KApplication( bool allowStyles, bool GUIenabled ) :
649  TQApplication( *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(), TRUE ), // Qt4 requires that there always be a GUI
650  KInstance( KCmdLineArgs::about),
651 #ifdef Q_WS_X11
652  display(0L),
653  argb_visual(false),
654 #endif
655  d (new KApplicationPrivate)
656 {
657  aIconPixmap.pm.icon = 0L;
658  aIconPixmap.pm.miniIcon = 0L;
659  read_app_startup_id();
660  if (!GUIenabled)
661  allowStyles = false;
662  useStyles = allowStyles;
663  setName( instanceName() );
664 
665  installSigpipeHandler();
666  parseCommandLine( );
667  init(GUIenabled);
668  d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
669 }
670 
671 #ifdef Q_WS_X11
672 KApplication::KApplication( Display *dpy, bool allowStyles ) :
673  TQApplication( dpy, *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(),
674  getX11RGBAVisual(dpy), getX11RGBAColormap(dpy) ),
675  KInstance( KCmdLineArgs::about), display(0L), d (new KApplicationPrivate)
676 {
677  aIconPixmap.pm.icon = 0L;
678  aIconPixmap.pm.miniIcon = 0L;
679  read_app_startup_id();
680  useStyles = allowStyles;
681  setName( instanceName() );
682  installSigpipeHandler();
683  parseCommandLine( );
684  init( true );
685  d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
686 }
687 
688 KApplication::KApplication( Display *dpy, bool disable_argb, Qt::HANDLE visual, Qt::HANDLE colormap, bool allowStyles ) :
689  TQApplication( dpy, *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(),
690  disable_argb?visual:getX11RGBAVisual(dpy), disable_argb?colormap:getX11RGBAColormap(dpy) ),
691  KInstance( KCmdLineArgs::about), display(0L), d (new KApplicationPrivate)
692 {
693  aIconPixmap.pm.icon = 0L;
694  aIconPixmap.pm.miniIcon = 0L;
695  read_app_startup_id();
696  useStyles = allowStyles;
697  if (disable_argb) argb_visual = false;
698  setName( instanceName() );
699  installSigpipeHandler();
700  parseCommandLine( );
701  init( true );
702  d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
703 }
704 
705 KApplication::KApplication( Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap,
706  bool allowStyles ) :
707  TQApplication( dpy, *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(),
708  visual?visual:getX11RGBAVisual(dpy), colormap?colormap:getX11RGBAColormap(dpy) ),
709  KInstance( KCmdLineArgs::about), display(0L), d (new KApplicationPrivate)
710 {
711  if ((visual) && (colormap))
712  getX11RGBAInformation(dpy);
713  aIconPixmap.pm.icon = 0L;
714  aIconPixmap.pm.miniIcon = 0L;
715  read_app_startup_id();
716  useStyles = allowStyles;
717  setName( instanceName() );
718  installSigpipeHandler();
719  parseCommandLine( );
720  init( true );
721  d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
722 }
723 
724 KApplication::KApplication( Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap,
725  bool allowStyles, KInstance * _instance ) :
726  TQApplication( dpy, *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(),
727  visual?visual:getX11RGBAVisual(dpy), colormap?colormap:getX11RGBAColormap(dpy) ),
728  KInstance( _instance ), display(0L), d (new KApplicationPrivate)
729 {
730  if ((visual) && (colormap))
731  getX11RGBAInformation(dpy);
732  aIconPixmap.pm.icon = 0L;
733  aIconPixmap.pm.miniIcon = 0L;
734  read_app_startup_id();
735  useStyles = allowStyles;
736  setName( instanceName() );
737  installSigpipeHandler();
738  parseCommandLine( );
739  init( true );
740  d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
741 }
742 #endif
743 
744 KApplication::KApplication( bool allowStyles, bool GUIenabled, KInstance* _instance ) :
745  TQApplication( *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(),
746  GUIenabled ),
747  KInstance( _instance ),
748 #ifdef Q_WS_X11
749  display(0L),
750 #endif
751  argb_visual(false),
752  d (new KApplicationPrivate)
753 {
754  aIconPixmap.pm.icon = 0L;
755  aIconPixmap.pm.miniIcon = 0L;
756  read_app_startup_id();
757  if (!GUIenabled)
758  allowStyles = false;
759  useStyles = allowStyles;
760  setName( instanceName() );
761 
762  installSigpipeHandler();
763  parseCommandLine( );
764  init(GUIenabled);
765  d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
766 }
767 
768 #ifdef Q_WS_X11
769 KApplication::KApplication(Display *display, int& argc, char** argv, const TQCString& rAppName,
770  bool allowStyles, bool GUIenabled ) :
771  TQApplication( display ), KInstance(rAppName),
772  display(0L),
773  argb_visual(false),
774  d (new KApplicationPrivate())
775 {
776  aIconPixmap.pm.icon = 0L;
777  aIconPixmap.pm.miniIcon = 0L;
778  read_app_startup_id();
779  if (!GUIenabled)
780  allowStyles = false;
781  useStyles = allowStyles;
782 
783  Q_ASSERT (!rAppName.isEmpty());
784  setName(rAppName);
785 
786  installSigpipeHandler();
787  KCmdLineArgs::initIgnore(argc, argv, rAppName.data());
788  parseCommandLine( );
789  init(GUIenabled);
790  d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
791 }
792 #endif
793 
794 int KApplication::xioErrhandler( Display* dpy )
795 {
796  if(kapp)
797  {
798  emit shutDown();
799 #ifdef Q_WS_X11
800  d->oldXIOErrorHandler( dpy );
801 #else
802  Q_UNUSED(dpy);
803 #endif
804  }
805  exit( 1 );
806  return 0;
807 }
808 
809 int KApplication::xErrhandler( Display* dpy, void* err_ )
810 { // no idea how to make forward decl. for XErrorEvent
811 #ifdef Q_WS_X11
812  XErrorEvent* err = static_cast< XErrorEvent* >( err_ );
813  if(kapp)
814  {
815  // add KDE specific stuff here
816  d->oldXErrorHandler( dpy, err );
817  }
818 #endif
819  return 0;
820 }
821 
822 void KApplication::iceIOErrorHandler( _IceConn *conn )
823 {
824  emit shutDown();
825 
826 #ifdef Q_WS_X11
827  if ( d->oldIceIOErrorHandler != NULL )
828  (*d->oldIceIOErrorHandler)( conn );
829 #endif
830  exit( 1 );
831 }
832 
833 class KDETranslator : public TQTranslator
834 {
835 public:
836  KDETranslator(TQObject *parent) : TQTranslator(parent, "kdetranslator") {}
837  virtual TQTranslatorMessage findMessage(const char* context,
838  const char *sourceText,
839  const char* message) const
840  {
841  TQTranslatorMessage res;
842  res.setTranslation(KGlobal::locale()->translateQt(context, sourceText, message));
843  return res;
844  }
845 };
846 
847 void KApplication::init(bool GUIenabled)
848 {
849  d->guiEnabled = GUIenabled;
850  if ((getuid() != geteuid()) ||
851  (getgid() != getegid()) )
852  {
853  // man permissions are not exploitable and better than
854  // world writable directories
855  struct group *man = getgrnam("man");
856  if ( !man || man->gr_gid != getegid() ){
857  fprintf(stderr, "The KDE libraries are not designed to run with suid privileges.\n");
858  ::exit(127);
859  }
860  }
861 
862  KProcessController::ref();
863 
864  (void) KClipboardSynchronizer::self();
865 
866  TQApplication::setDesktopSettingsAware( false );
867 
868  KApp = this;
869 
870 
871 #ifdef Q_WS_X11 //FIXME(E)
872  // create all required atoms in _one_ roundtrip to the X server
873  if ( GUIenabled ) {
874  const int max = 20;
875  Atom* atoms[max];
876  char* names[max];
877  Atom atoms_return[max];
878  int n = 0;
879 
880  atoms[n] = &kipcCommAtom;
881  names[n++] = (char *) "KIPC_COMM_ATOM";
882 
883  atoms[n] = &atom_DesktopWindow;
884  names[n++] = (char *) "KDE_DESKTOP_WINDOW";
885 
886  atoms[n] = &atom_NetSupported;
887  names[n++] = (char *) "_NET_SUPPORTED";
888 
889  atoms[n] = &kde_xdnd_drop;
890  names[n++] = (char *) "XdndDrop";
891 
892  XInternAtoms( qt_xdisplay(), names, n, false, atoms_return );
893 
894  for (int i = 0; i < n; i++ )
895  *atoms[i] = atoms_return[i];
896  }
897 #endif
898 
899  dcopAutoRegistration();
900  dcopClientPostInit();
901 
902  smw = 0;
903 
904  // Initial KIPC event mask.
905 #if defined Q_WS_X11
906  kipcEventMask = (1 << KIPC::StyleChanged) | (1 << KIPC::PaletteChanged) |
907  (1 << KIPC::FontChanged) | (1 << KIPC::BackgroundChanged) |
908  (1 << KIPC::ToolbarStyleChanged) | (1 << KIPC::SettingsChanged) |
909  (1 << KIPC::ClipboardConfigChanged) | (1 << KIPC::BlockShortcuts);
910 #endif
911 
912  // Trigger creation of locale.
913  (void) KGlobal::locale();
914 
915  KConfig* config = KGlobal::config();
916  d->actionRestrictions = config->hasGroup("KDE Action Restrictions" ) && !kde_kiosk_exception;
917  // For brain-dead configurations where the user's local config file is not writable.
918  // * We use kdialog to warn the user, so we better not generate warnings from
919  // kdialog itself.
920  // * Don't warn if we run with a read-only $HOME
921  TQCString readOnly = getenv("KDE_HOME_READONLY");
922  if (readOnly.isEmpty() && (tqstrcmp(name(), "kdialog") != 0))
923  {
924  KConfigGroupSaver saver(config, "KDE Action Restrictions");
925  if (config->readBoolEntry("warn_unwritable_config",true))
926  config->checkConfigFilesWritable(true);
927  }
928 
929  if (GUIenabled)
930  {
931 #ifdef Q_WS_X11
932  // this is important since we fork() to launch the help (Matthias)
933  fcntl(ConnectionNumber(qt_xdisplay()), F_SETFD, FD_CLOEXEC);
934  // set up the fancy (=robust and error ignoring ) KDE xio error handlers (Matthias)
935  d->oldXErrorHandler = XSetErrorHandler( kde_x_errhandler );
936  d->oldXIOErrorHandler = XSetIOErrorHandler( kde_xio_errhandler );
937 #endif
938 
939  connect( this, TQT_SIGNAL( aboutToQuit() ), this, TQT_SIGNAL( shutDown() ) );
940 
941 #ifdef Q_WS_X11 //FIXME(E)
942  display = desktop()->x11Display();
943 #endif
944 
945  {
946  TQStringList plugins = KGlobal::dirs()->resourceDirs( "qtplugins" );
947  TQStringList::Iterator it = plugins.begin();
948  while (it != plugins.end()) {
949  addLibraryPath( *it );
950  ++it;
951  }
952 
953  }
954  kdisplaySetStyle();
955  kdisplaySetFont();
956 // kdisplaySetPalette(); done by kdisplaySetStyle
957  propagateSettings(SETTINGS_QT);
958 
959  // Set default mime-source factory
960  // XXX: This is a hack. Make our factory the default factory, but add the
961  // previous default factory to the list of factories. Why? When the default
962  // factory can't resolve something, it iterates in the list of factories.
963  // But it TQWhatsThis only uses the default factory. So if there was already
964  // a default factory (which happens when using an image library using uic),
965  // we prefer KDE's factory and so we put that old default factory in the
966  // list and use KDE as the default. This may speed up things as well.
967  TQMimeSourceFactory* oldDefaultFactory = TQMimeSourceFactory::takeDefaultFactory();
968  TQMimeSourceFactory::setDefaultFactory( mimeSourceFactory() );
969  if ( oldDefaultFactory ) {
970  TQMimeSourceFactory::addFactory( oldDefaultFactory );
971  }
972 
973  d->checkAccelerators = new KCheckAccelerators( TQT_TQOBJECT(this) );
974  }
975 
976 #ifdef Q_WS_MACX
977  if (GUIenabled) {
978  TQPixmap pixmap = KGlobal::iconLoader()->loadIcon( KCmdLineArgs::appName(),
979  KIcon::NoGroup, KIcon::SizeLarge, KIcon::DefaultState, 0L, false );
980  if (!pixmap.isNull()) {
981  TQImage i = pixmap.convertToImage().convertDepth(32).smoothScale(40, 40);
982  for(int y = 0; y < i.height(); y++) {
983  uchar *l = i.scanLine(y);
984  for(int x = 0; x < i.width(); x+=4)
985  *(l+x) = 255;
986  }
987  CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
988  CGDataProviderRef dp = CGDataProviderCreateWithData(NULL,
989  i.bits(), i.numBytes(), NULL);
990  CGImageRef ir = CGImageCreate(i.width(), i.height(), 8, 32, i.bytesPerLine(),
991  cs, kCGImageAlphaNoneSkipFirst, dp,
992  0, 0, kCGRenderingIntentDefault);
993  //cleanup
994  SetApplicationDockTileImage(ir);
995  CGImageRelease(ir);
996  CGColorSpaceRelease(cs);
997  CGDataProviderRelease(dp);
998  }
999  }
1000 #endif
1001 
1002 
1003  // save and restore the RTL setting, as installTranslator calls qt_detectRTLLanguage,
1004  // which makes it impossible to use the -reverse cmdline switch with KDE apps
1005  bool rtl = reverseLayout();
1006  installTranslator(new KDETranslator(TQT_TQOBJECT(this)));
1007  setReverseLayout( rtl );
1008  if (i18n( "_: Dear Translator! Translate this string to the string 'LTR' in "
1009  "left-to-right languages (as english) or to 'RTL' in right-to-left "
1010  "languages (such as Hebrew and Arabic) to get proper widget layout." ) == "RTL")
1011  setReverseLayout( !rtl );
1012 
1013  // install appdata resource type
1014  KGlobal::dirs()->addResourceType("appdata", KStandardDirs::kde_default("data")
1015  + TQString::fromLatin1(name()) + '/');
1016  pSessionConfig = 0L;
1017  bSessionManagement = true;
1018 
1019 #ifdef Q_WS_X11
1020  // register a communication window for desktop changes (Matthias)
1021  if (GUIenabled && kde_have_kipc )
1022  {
1023  smw = new TQWidget(0,0);
1024  long data = 1;
1025  XChangeProperty(qt_xdisplay(), smw->winId(),
1026  atom_DesktopWindow, atom_DesktopWindow,
1027  32, PropModeReplace, (unsigned char *)&data, 1);
1028  }
1029  d->oldIceIOErrorHandler = IceSetIOErrorHandler( kde_ice_ioerrorhandler );
1030 #elif defined(Q_WS_WIN)
1031  KApplication_init_windows(GUIenabled);
1032 #else
1033  // FIXME(E): Implement for Qt Embedded
1034 #endif
1035 }
1036 
1037 static int my_system (const char *command) {
1038  int pid, status;
1039 
1040  pid = fork();
1041  if (pid == -1)
1042  return -1;
1043  if (pid == 0) {
1044  const char* shell = "/bin/sh";
1045  execl(shell, shell, "-c", command, (void *)0);
1046  ::_exit(127);
1047  }
1048  do {
1049  if (waitpid(pid, &status, 0) == -1) {
1050  if (errno != EINTR)
1051  return -1;
1052  } else
1053  return status;
1054  } while(1);
1055 }
1056 
1057 
1058 DCOPClient *KApplication::dcopClient()
1059 {
1060  if (s_DCOPClient)
1061  return s_DCOPClient;
1062 
1063  s_DCOPClient = new DCOPClient();
1064  KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
1065  if (args && args->isSet("dcopserver"))
1066  {
1067  s_DCOPClient->setServerAddress( args->getOption("dcopserver"));
1068  }
1069  if( kapp ) {
1070  connect(s_DCOPClient, TQT_SIGNAL(attachFailed(const TQString &)),
1071  kapp, TQT_SLOT(dcopFailure(const TQString &)));
1072  connect(s_DCOPClient, TQT_SIGNAL(blockUserInput(bool) ),
1073  kapp, TQT_SLOT(dcopBlockUserInput(bool)) );
1074  }
1075  else
1076  s_dcopClientNeedsPostInit = true;
1077 
1078  DCOPClient::setMainClient( s_DCOPClient );
1079  return s_DCOPClient;
1080 }
1081 
1082 void KApplication::dcopClientPostInit()
1083 {
1084  if( s_dcopClientNeedsPostInit )
1085  {
1086  s_dcopClientNeedsPostInit = false;
1087  connect(s_DCOPClient, TQT_SIGNAL(blockUserInput(bool) ),
1088  TQT_SLOT(dcopBlockUserInput(bool)) );
1089  s_DCOPClient->bindToApp(); // Make sure we get events from the DCOPClient.
1090  }
1091 }
1092 
1093 void KApplication::dcopAutoRegistration()
1094 {
1095  if (autoDcopRegistration)
1096  {
1097  ( void ) dcopClient();
1098  if( dcopClient()->appId().isEmpty())
1099  dcopClient()->registerAs(name());
1100  }
1101 }
1102 
1103 void KApplication::disableAutoDcopRegistration()
1104 {
1105  autoDcopRegistration = false;
1106 }
1107 
1108 KConfig* KApplication::sessionConfig()
1109 {
1110  if (pSessionConfig)
1111  return pSessionConfig;
1112 
1113  // create an instance specific config object
1114  pSessionConfig = new KConfig( sessionConfigName(), false, false);
1115  return pSessionConfig;
1116 }
1117 
1118 void KApplication::ref()
1119 {
1120  d->refCount++;
1121  //kdDebug() << "KApplication::ref() : refCount = " << d->refCount << endl;
1122 }
1123 
1124 void KApplication::deref()
1125 {
1126  d->refCount--;
1127  //kdDebug() << "KApplication::deref() : refCount = " << d->refCount << endl;
1128  if ( d->refCount <= 0 )
1129  quit();
1130 }
1131 
1132 KSessionManaged::KSessionManaged()
1133 {
1134  sessionClients()->remove( this );
1135  sessionClients()->append( this );
1136 }
1137 
1138 KSessionManaged::~KSessionManaged()
1139 {
1140  sessionClients()->remove( this );
1141 }
1142 
1143 bool KSessionManaged::saveState(TQSessionManager&)
1144 {
1145  return true;
1146 }
1147 
1148 bool KSessionManaged::commitData(TQSessionManager&)
1149 {
1150  return true;
1151 }
1152 
1153 
1154 void KApplication::disableSessionManagement() {
1155  bSessionManagement = false;
1156 }
1157 
1158 void KApplication::enableSessionManagement() {
1159  bSessionManagement = true;
1160 #ifdef Q_WS_X11
1161  // Session management support in Qt/KDE is awfully broken.
1162  // If konqueror disables session management right after its startup,
1163  // and enables it later (preloading stuff), it won't be properly
1164  // saved on session shutdown.
1165  // I'm not actually sure why it doesn't work, but saveState()
1166  // doesn't seem to be called on session shutdown, possibly
1167  // because disabling session management after konqueror startup
1168  // disabled it somehow. Forcing saveState() here for this application
1169  // seems to fix it.
1170  if( mySmcConnection ) {
1171  SmcRequestSaveYourself( mySmcConnection, SmSaveLocal, False,
1172  SmInteractStyleAny,
1173  False, False );
1174 
1175  // flush the request
1176  IceFlush(SmcGetIceConnection(mySmcConnection));
1177  }
1178 #endif
1179 }
1180 
1181 
1182 bool KApplication::requestShutDown(
1183  ShutdownConfirm confirm, ShutdownType sdtype, ShutdownMode sdmode )
1184 {
1185 #ifdef Q_WS_X11
1186  TQApplication::syncX();
1187  /* use ksmserver's dcop interface if necessary */
1188  if ( confirm == ShutdownConfirmYes ||
1189  sdtype != ShutdownTypeDefault ||
1190  sdmode != ShutdownModeDefault )
1191  {
1192  TQByteArray data;
1193  TQDataStream arg(data, IO_WriteOnly);
1194  arg << (int)confirm << (int)sdtype << (int)sdmode;
1195  return dcopClient()->send( "ksmserver", "ksmserver",
1196  "logout(int,int,int)", data );
1197  }
1198 
1199  if ( mySmcConnection ) {
1200  // we already have a connection to the session manager, use it.
1201  SmcRequestSaveYourself( mySmcConnection, SmSaveBoth, True,
1202  SmInteractStyleAny,
1203  confirm == ShutdownConfirmNo, True );
1204 
1205  // flush the request
1206  IceFlush(SmcGetIceConnection(mySmcConnection));
1207  return true;
1208  }
1209 
1210  // open a temporary connection, if possible
1211 
1212  propagateSessionManager();
1213  TQCString smEnv = ::getenv("SESSION_MANAGER");
1214  if (smEnv.isEmpty())
1215  return false;
1216 
1217  if (! tmpSmcConnection) {
1218  char cerror[256];
1219  char* myId = 0;
1220  char* prevId = 0;
1221  SmcCallbacks cb;
1222  tmpSmcConnection = SmcOpenConnection( 0, 0, 1, 0,
1223  0, &cb,
1224  prevId,
1225  &myId,
1226  255,
1227  cerror );
1228  ::free( myId ); // it was allocated by C
1229  if (!tmpSmcConnection )
1230  return false;
1231  }
1232 
1233  SmcRequestSaveYourself( tmpSmcConnection, SmSaveBoth, True,
1234  SmInteractStyleAny, False, True );
1235 
1236  // flush the request
1237  IceFlush(SmcGetIceConnection(tmpSmcConnection));
1238  return true;
1239 #else
1240  // FIXME(E): Implement for Qt Embedded
1241  return false;
1242 #endif
1243 }
1244 
1245 void KApplication::propagateSessionManager()
1246 {
1247 #ifdef Q_WS_X11
1248  TQCString fName = TQFile::encodeName(locateLocal("socket", "KSMserver"));
1249  TQCString display = ::getenv(DISPLAY);
1250  // strip the screen number from the display
1251  display.replace(TQRegExp("\\.[0-9]+$"), "");
1252  int i;
1253  while( (i = display.find(':')) >= 0)
1254  display[i] = '_';
1255 
1256  fName += "_"+display;
1257  TQCString smEnv = ::getenv("SESSION_MANAGER");
1258  bool check = smEnv.isEmpty();
1259  if ( !check && smModificationTime ) {
1260  TQFileInfo info( fName );
1261  TQTime current = TQT_TQTIME_OBJECT(info.lastModified().time());
1262  check = current > *smModificationTime;
1263  }
1264  if ( check ) {
1265  delete smModificationTime;
1266  TQFile f( fName );
1267  if ( !f.open( IO_ReadOnly ) )
1268  return;
1269  TQFileInfo info ( f );
1270  smModificationTime = new TQTime( TQT_TQTIME_OBJECT(info.lastModified().time()) );
1271  TQTextStream t(&f);
1272  t.setEncoding( TQTextStream::Latin1 );
1273  TQString s = t.readLine();
1274  f.close();
1275  ::setenv( "SESSION_MANAGER", s.latin1(), true );
1276  }
1277 #endif
1278 }
1279 
1280 void KApplication::commitData( TQSessionManager& sm )
1281 {
1282  d->session_save = true;
1283  bool canceled = false;
1284  for (KSessionManaged* it = sessionClients()->first();
1285  it && !canceled;
1286  it = sessionClients()->next() ) {
1287  canceled = !it->commitData( sm );
1288  }
1289  if ( canceled )
1290  sm.cancel();
1291 
1292  if ( sm.allowsInteraction() ) {
1293  TQWidgetList done;
1294  TQWidgetList *list = TQApplication::topLevelWidgets();
1295  bool canceled = false;
1296  TQWidget* w = list->first();
1297  while ( !canceled && w ) {
1298  if ( !w->testWState( WState_ForceHide ) && !w->inherits("KMainWindow") ) {
1299  TQCloseEvent e;
1300  sendEvent( w, &e );
1301  canceled = !e.isAccepted();
1302  if ( !canceled )
1303  done.append( w );
1304  delete list; // one never knows...
1305  list = TQApplication::topLevelWidgets();
1306  w = list->first();
1307  } else {
1308  w = list->next();
1309  }
1310  while ( w && done.containsRef( w ) )
1311  w = list->next();
1312  }
1313  delete list;
1314  }
1315 
1316 
1317  if ( !bSessionManagement )
1318  sm.setRestartHint( TQSessionManager::RestartNever );
1319  else
1320  sm.setRestartHint( TQSessionManager::RestartIfRunning );
1321  d->session_save = false;
1322 }
1323 
1324 static void checkRestartVersion( TQSessionManager& sm )
1325 {
1326  Display* dpy = qt_xdisplay();
1327  Atom type;
1328  int format;
1329  unsigned long nitems, after;
1330  unsigned char* data;
1331  if( XGetWindowProperty( dpy, RootWindow( dpy, 0 ), XInternAtom( dpy, "TDE_FULL_SESSION", False ),
1332  0, 1, False, AnyPropertyType, &type, &format, &nitems, &after, &data ) == Success ) {
1333  if( data != NULL )
1334  XFree( data );
1335  if( type == XA_STRING && format == 8 ) { // session set, check if KDE_SESSION_VERSION is not set (meaning KDE3)
1336  if( XGetWindowProperty( dpy, RootWindow( dpy, 0 ), XInternAtom( dpy, "KDE_SESSION_VERSION", False ),
1337  0, 1, False, AnyPropertyType, &type, &format, &nitems, &after, &data ) == Success ) {
1338  if( data != NULL )
1339  XFree( data ); // KDE4 or newer
1340  if( type == None )
1341  return; // we run in our native session, no need to wrap
1342  } else {
1343  return; // we run in our native session, no need to wrap
1344  }
1345  }
1346  }
1347  TQString wrapper = KStandardDirs::findExe( "trinity" );
1348  TQStringList restartCommand = sm.restartCommand();
1349  restartCommand.prepend( wrapper );
1350  sm.setRestartCommand( restartCommand );
1351 }
1352 
1353 void KApplication::saveState( TQSessionManager& sm )
1354 {
1355  d->session_save = true;
1356 #ifdef Q_WS_X11
1357  static bool firstTime = true;
1358  mySmcConnection = (SmcConn) sm.handle();
1359 
1360  if ( !bSessionManagement ) {
1361  sm.setRestartHint( TQSessionManager::RestartNever );
1362  d->session_save = false;
1363  return;
1364  }
1365  else
1366  sm.setRestartHint( TQSessionManager::RestartIfRunning );
1367 
1368  if ( firstTime ) {
1369  firstTime = false;
1370  d->session_save = false;
1371  return; // no need to save the state.
1372  }
1373 
1374  // remove former session config if still existing, we want a new
1375  // and fresh one. Note that we do not delete the config file here,
1376  // this is done by the session manager when it executes the
1377  // discard commands. In fact it would be harmful to remove the
1378  // file here, as the session might be stored under a different
1379  // name, meaning the user still might need it eventually.
1380  if ( pSessionConfig ) {
1381  delete pSessionConfig;
1382  pSessionConfig = 0;
1383  }
1384 
1385  // tell the session manager about our new lifecycle
1386  TQStringList restartCommand = sm.restartCommand();
1387 
1388  TQCString multiHead = getenv("KDE_MULTIHEAD");
1389  if (multiHead.lower() == "true") {
1390  // if multihead is enabled, we save our -display argument so that
1391  // we are restored onto the correct head... one problem with this
1392  // is that the display is hard coded, which means we cannot restore
1393  // to a different display (ie. if we are in a university lab and try,
1394  // try to restore a multihead session, our apps could be started on
1395  // someone else's display instead of our own)
1396  TQCString displayname = getenv(DISPLAY);
1397  if (! displayname.isNull()) {
1398  // only store the command if we actually have a DISPLAY
1399  // environment variable
1400  restartCommand.append("-display");
1401  restartCommand.append(displayname);
1402  }
1403  sm.setRestartCommand( restartCommand );
1404  }
1405 
1406  checkRestartVersion( sm );
1407 
1408  // finally: do session management
1409  emit saveYourself(); // for compatibility
1410  bool canceled = false;
1411  for (KSessionManaged* it = sessionClients()->first();
1412  it && !canceled;
1413  it = sessionClients()->next() ) {
1414  canceled = !it->saveState( sm );
1415  }
1416 
1417  // if we created a new session config object, register a proper discard command
1418  if ( pSessionConfig ) {
1419  pSessionConfig->sync();
1420  TQStringList discard;
1421  discard << "rm" << locateLocal("config", sessionConfigName());
1422  sm.setDiscardCommand( discard );
1423  } else {
1424  sm.setDiscardCommand( TQStringList("") );
1425  }
1426 
1427  if ( canceled )
1428  sm.cancel();
1429 #else
1430  // FIXME(E): Implement for Qt Embedded
1431 #endif
1432  d->session_save = false;
1433 }
1434 
1435 bool KApplication::sessionSaving() const
1436 {
1437  return d->session_save;
1438 }
1439 
1440 void KApplication::startKdeinit()
1441 {
1442 #ifndef Q_WS_WIN //TODO
1443  KInstance inst( "startkdeinitlock" );
1444  KLockFile lock( locateLocal( "tmp", "startkdeinitlock", &inst ));
1445  if( lock.lock( KLockFile::LockNoBlock ) != KLockFile::LockOK ) {
1446  lock.lock();
1447  DCOPClient cl;
1448  if( cl.attach())
1449  return; // whoever held the lock has already started dcopserver
1450  }
1451  // Try to launch kdeinit.
1452  TQString srv = KStandardDirs::findExe(TQString::fromLatin1("kdeinit"));
1453  if (srv.isEmpty())
1454  srv = KStandardDirs::findExe(TQString::fromLatin1("kdeinit"), KGlobal::dirs()->kfsstnd_defaultbindir());
1455  if (srv.isEmpty())
1456  return;
1457  if (kapp && (Tty != kapp->type()))
1458  setOverrideCursor( tqwaitCursor );
1459  my_system(TQFile::encodeName(srv)+" --suicide"+" --new-startup");
1460  if (kapp && (Tty != kapp->type()))
1461  restoreOverrideCursor();
1462 #endif
1463 }
1464 
1465 void KApplication::dcopFailure(const TQString &msg)
1466 {
1467  static int failureCount = 0;
1468  failureCount++;
1469  if (failureCount == 1)
1470  {
1471  startKdeinit();
1472  return;
1473  }
1474  if (failureCount == 2)
1475  {
1476 #ifdef Q_WS_WIN
1477  KGlobal::config()->setGroup("General");
1478  if (KGlobal::config()->readBoolEntry("ignoreDCOPFailures", false))
1479  return;
1480 #endif
1481  TQString msgStr(i18n("There was an error setting up inter-process "
1482  "communications for KDE. The message returned "
1483  "by the system was:\n\n"));
1484  msgStr += msg;
1485  msgStr += i18n("\n\nPlease check that the \"dcopserver\" program is running!");
1486 
1487  if (Tty != kapp->type())
1488  {
1489  TQMessageBox::critical
1490  (
1491  kapp->mainWidget(),
1492  i18n("DCOP communications error (%1)").arg(kapp->caption()),
1493  msgStr,
1494  i18n("&OK")
1495  );
1496  }
1497  else
1498  {
1499  fprintf(stderr, "%s\n", msgStr.local8Bit().data());
1500  }
1501 
1502  return;
1503  }
1504 }
1505 
1506 static const KCmdLineOptions qt_options[] =
1507 {
1508  //FIXME: Check if other options are specific to Qt/X11
1509 #ifdef Q_WS_X11
1510  { "display <displayname>", I18N_NOOP("Use the X-server display 'displayname'"), 0},
1511 #else
1512  { "display <displayname>", I18N_NOOP("Use the QWS display 'displayname'"), 0},
1513 #endif
1514  { "session <sessionId>", I18N_NOOP("Restore the application for the given 'sessionId'"), 0},
1515  { "cmap", I18N_NOOP("Causes the application to install a private color\nmap on an 8-bit display"), 0},
1516  { "ncols <count>", I18N_NOOP("Limits the number of colors allocated in the color\ncube on an 8-bit display, if the application is\nusing the TQApplication::ManyColor color\nspecification"), 0},
1517  { "nograb", I18N_NOOP("tells Qt to never grab the mouse or the keyboard"), 0},
1518  { "dograb", I18N_NOOP("running under a debugger can cause an implicit\n-nograb, use -dograb to override"), 0},
1519  { "sync", I18N_NOOP("switches to synchronous mode for debugging"), 0},
1520  { "fn", 0, 0},
1521  { "font <fontname>", I18N_NOOP("defines the application font"), 0},
1522  { "bg", 0, 0},
1523  { "background <color>", I18N_NOOP("sets the default background color and an\napplication palette (light and dark shades are\ncalculated)"), 0},
1524  { "fg", 0, 0},
1525  { "foreground <color>", I18N_NOOP("sets the default foreground color"), 0},
1526  { "btn", 0, 0},
1527  { "button <color>", I18N_NOOP("sets the default button color"), 0},
1528  { "name <name>", I18N_NOOP("sets the application name"), 0},
1529  { "title <title>", I18N_NOOP("sets the application title (caption)"), 0},
1530 #ifdef Q_WS_X11
1531  { "visual TrueColor", I18N_NOOP("forces the application to use a TrueColor visual on\nan 8-bit display"), 0},
1532  { "inputstyle <inputstyle>", I18N_NOOP("sets XIM (X Input Method) input style. Possible\nvalues are onthespot, overthespot, offthespot and\nroot"), 0 },
1533  { "im <XIM server>", I18N_NOOP("set XIM server"),0},
1534  { "noxim", I18N_NOOP("disable XIM"), 0 },
1535 #endif
1536 #ifdef Q_WS_QWS
1537  { "qws", I18N_NOOP("forces the application to run as QWS Server"), 0},
1538 #endif
1539  { "reverse", I18N_NOOP("mirrors the whole layout of widgets"), 0},
1540  KCmdLineLastOption
1541 };
1542 
1543 static const KCmdLineOptions kde_options[] =
1544 {
1545  { "caption <caption>", I18N_NOOP("Use 'caption' as name in the titlebar"), 0},
1546  { "icon <icon>", I18N_NOOP("Use 'icon' as the application icon"), 0},
1547  { "miniicon <icon>", I18N_NOOP("Use 'icon' as the icon in the titlebar"), 0},
1548  { "config <filename>", I18N_NOOP("Use alternative configuration file"), 0},
1549  { "dcopserver <server>", I18N_NOOP("Use the DCOP Server specified by 'server'"), 0},
1550  { "nocrashhandler", I18N_NOOP("Disable crash handler, to get core dumps"), 0},
1551  { "waitforwm", I18N_NOOP("Waits for a WM_NET compatible windowmanager"), 0},
1552  { "style <style>", I18N_NOOP("sets the application GUI style"), 0},
1553  { "geometry <geometry>", I18N_NOOP("sets the client geometry of the main widget - see man X for the argument format"), 0},
1554  { "smkey <sessionKey>", 0, 0}, // this option is obsolete and exists only to allow smooth upgrades from sessions
1555  // saved under Qt 3.0.x -- Qt 3.1.x includes the session key now automatically in
1556  // the session id (Simon)
1557  KCmdLineLastOption
1558 };
1559 
1560 void
1561 KApplication::addCmdLineOptions()
1562 {
1563  KCmdLineArgs::addCmdLineOptions(qt_options, "Qt", "qt");
1564  KCmdLineArgs::addCmdLineOptions(kde_options, "KDE", "kde");
1565 }
1566 
1567 void KApplication::parseCommandLine( )
1568 {
1569  KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
1570 
1571  if ( !args ) return;
1572 
1573  if (args->isSet("config"))
1574  {
1575  TQString config = TQString::fromLocal8Bit(args->getOption("config"));
1576  setConfigName(config);
1577  }
1578 
1579  if (args->isSet("style"))
1580  {
1581 
1582  TQStringList plugins = KGlobal::dirs()->resourceDirs( "qtplugins" );
1583  TQStringList::Iterator itp = plugins.begin();
1584  while (itp != plugins.end()) {
1585  addLibraryPath( *itp );
1586  ++itp;
1587  }
1588 
1589  TQStringList styles = TQStyleFactory::keys();
1590  TQString reqStyle(args->getOption("style").lower());
1591 
1592  TQStringList list = libraryPaths();
1593  TQStringList::Iterator it = list.begin();
1594  while( it != list.end() ) {
1595  ++it;
1596  }
1597 
1598  for (TQStringList::ConstIterator it = styles.begin(); it != styles.end(); ++it) {
1599  if ((*it).lower() == reqStyle)
1600  {
1601  d->overrideStyle = *it;
1602  break;
1603  }
1604  }
1605 
1606  if (d->overrideStyle.isEmpty())
1607  fprintf(stderr, "%s", TQString(i18n("The style %1 was not found\n").arg(reqStyle)).local8Bit().data());
1608  }
1609 
1610  if (args->isSet("caption"))
1611  {
1612  aCaption = TQString::fromLocal8Bit(args->getOption("caption"));
1613  }
1614 
1615  if (args->isSet("miniicon"))
1616  {
1617  const char *tmp = args->getOption("miniicon");
1618  if (!aIconPixmap.pm.miniIcon) {
1619  aIconPixmap.pm.miniIcon = new TQPixmap;
1620  }
1621  *aIconPixmap.pm.miniIcon = SmallIcon(tmp);
1622  aMiniIconName = tmp;
1623  }
1624 
1625  if (args->isSet("icon"))
1626  {
1627  const char *tmp = args->getOption("icon");
1628  if (!aIconPixmap.pm.icon) {
1629  aIconPixmap.pm.icon = new TQPixmap;
1630  }
1631  *aIconPixmap.pm.icon = DesktopIcon( tmp );
1632  aIconName = tmp;
1633  if (!aIconPixmap.pm.miniIcon) {
1634  aIconPixmap.pm.miniIcon = new TQPixmap;
1635  }
1636  if (aIconPixmap.pm.miniIcon->isNull())
1637  {
1638  *aIconPixmap.pm.miniIcon = SmallIcon( tmp );
1639  aMiniIconName = tmp;
1640  }
1641  }
1642 
1643  bool nocrashhandler = (getenv("KDE_DEBUG") != NULL);
1644  if (!nocrashhandler && args->isSet("crashhandler"))
1645  {
1646  // set default crash handler / set emergency save function to nothing
1647  KCrash::setCrashHandler(KCrash::defaultCrashHandler);
1648  KCrash::setEmergencySaveFunction(NULL);
1649 
1650  KCrash::setApplicationName(TQString(args->appName()));
1651  }
1652 
1653 #ifdef Q_WS_X11
1654  if ( args->isSet( "waitforwm" ) ) {
1655  Atom type;
1656  (void) desktop(); // trigger desktop creation, we need PropertyNotify events for the root window
1657  int format;
1658  unsigned long length, after;
1659  unsigned char *data;
1660  while ( XGetWindowProperty( qt_xdisplay(), qt_xrootwin(), atom_NetSupported,
1661  0, 1, false, AnyPropertyType, &type, &format,
1662  &length, &after, &data ) != Success || !length ) {
1663  if ( data )
1664  XFree( data );
1665  XEvent event;
1666  XWindowEvent( qt_xdisplay(), qt_xrootwin(), PropertyChangeMask, &event );
1667  }
1668  if ( data )
1669  XFree( data );
1670  }
1671 #else
1672  // FIXME(E): Implement for Qt Embedded
1673 #endif
1674 
1675  if (args->isSet("geometry"))
1676  {
1677  d->geometry_arg = args->getOption("geometry");
1678  }
1679 
1680  if (args->isSet("smkey"))
1681  {
1682  d->sessionKey = args->getOption("smkey");
1683  }
1684 
1685 }
1686 
1687 TQString KApplication::geometryArgument() const
1688 {
1689  return d->geometry_arg;
1690 }
1691 
1692 TQPixmap KApplication::icon() const
1693 {
1694  if( !aIconPixmap.pm.icon) {
1695  aIconPixmap.pm.icon = new TQPixmap;
1696  }
1697  if( aIconPixmap.pm.icon->isNull()) {
1698  *aIconPixmap.pm.icon = DesktopIcon( instanceName() );
1699  }
1700  return *aIconPixmap.pm.icon;
1701 }
1702 
1703 TQString KApplication::iconName() const
1704 {
1705  return aIconName.isNull() ? (TQString)instanceName() : aIconName;
1706 }
1707 
1708 TQPixmap KApplication::miniIcon() const
1709 {
1710  if (!aIconPixmap.pm.miniIcon) {
1711  aIconPixmap.pm.miniIcon = new TQPixmap;
1712  }
1713  if (aIconPixmap.pm.miniIcon->isNull()) {
1714  *aIconPixmap.pm.miniIcon = SmallIcon( instanceName() );
1715  }
1716  return *aIconPixmap.pm.miniIcon;
1717 }
1718 
1719 TQString KApplication::miniIconName() const
1720 {
1721  return aMiniIconName.isNull() ? (TQString)instanceName() : aMiniIconName;
1722 }
1723 
1724 extern void kDebugCleanup();
1725 
1726 KApplication::~KApplication()
1727 {
1728  delete aIconPixmap.pm.miniIcon;
1729  aIconPixmap.pm.miniIcon = 0L;
1730  delete aIconPixmap.pm.icon;
1731  aIconPixmap.pm.icon = 0L;
1732  delete d->m_KAppDCOPInterface;
1733 
1734  // First call the static deleters and then call KLibLoader::cleanup()
1735  // The static deleters may delete libraries for which they need KLibLoader.
1736  // KLibLoader will take care of the remaining ones.
1737  KGlobal::deleteStaticDeleters();
1738  KLibLoader::cleanUp();
1739 
1740  delete smw;
1741 
1742  // close down IPC
1743  delete s_DCOPClient;
1744  s_DCOPClient = 0L;
1745 
1746  KProcessController::deref();
1747 
1748 #ifdef Q_WS_X11
1749  if ( d->oldXErrorHandler != NULL )
1750  XSetErrorHandler( d->oldXErrorHandler );
1751  if ( d->oldXIOErrorHandler != NULL )
1752  XSetIOErrorHandler( d->oldXIOErrorHandler );
1753  if ( d->oldIceIOErrorHandler != NULL )
1754  IceSetIOErrorHandler( d->oldIceIOErrorHandler );
1755 #endif
1756 
1757  delete d;
1758  KApp = 0;
1759 
1760 #ifdef Q_WS_X11
1761  mySmcConnection = 0;
1762  delete smModificationTime;
1763  smModificationTime = 0;
1764 
1765  // close the temporary smc connection
1766  if (tmpSmcConnection) {
1767  SmcCloseConnection( tmpSmcConnection, 0, 0 );
1768  tmpSmcConnection = 0;
1769  }
1770 #else
1771  // FIXME(E): Implement for Qt Embedded
1772 #endif
1773 }
1774 
1775 
1776 #ifdef Q_WS_X11
1777 class KAppX11HackWidget: public QWidget
1778 {
1779 public:
1780  bool publicx11Event( XEvent * e) { return x11Event( e ); }
1781 };
1782 #endif
1783 
1784 #if defined(Q_WS_X11) && defined(COMPOSITE)
1785 bool KApplication::isCompositionManagerAvailable() {
1786  bool have_manager = false;
1787  const char *home;
1788  struct passwd *p;
1789  p = getpwuid(getuid());
1790  if (p)
1791  home = p->pw_dir;
1792  else
1793  home = getenv("HOME");
1794 
1795  char *filename;
1796  const char *configfile = "/.kompmgr.available";
1797  int n = strlen(home)+strlen(configfile)+1;
1798  filename = (char*)malloc(n*sizeof(char));
1799  memset(filename,0,n);
1800  strcat(filename, home);
1801  strcat(filename, configfile);
1802 
1803  // Now that we did all that by way of introduction...read the file!
1804  FILE *pFile;
1805  pFile = fopen(filename, "r");
1806  if (pFile) {
1807  have_manager = true;
1808  fclose(pFile);
1809  }
1810 
1811  free(filename);
1812  filename = NULL;
1813 
1814  return have_manager;
1815 }
1816 
1817 bool KApplication::detectCompositionManagerAvailable(bool force_available, bool available) {
1818  bool compositing_manager_available;
1819  if (force_available) {
1820  compositing_manager_available = available;
1821  }
1822  else {
1823  // See if compositing has been enabled
1824  KCmdLineArgs *qtargs = KCmdLineArgs::parsedArgs("qt");
1825  char *displayname = 0;
1826  if ( qtargs->isSet("display"))
1827  displayname = qtargs->getOption( "display" ).data();
1828 
1829  Display *dpy = XOpenDisplay( displayname );
1830 
1831  x11_composite_error_generated = false;
1832  compositing_manager_available = false;
1833  XSetErrorHandler(x11_error);
1834  if (!XQueryExtension (dpy, COMPOSITE_NAME, &composite_opcode, &composite_event, &composite_error)) {
1835  XSetErrorHandler(NULL);
1836  compositing_manager_available = false;
1837  }
1838  else {
1839  if (available) { // FIXME This variable does double duty to avoid breaking the ABI for R14.0. In reality it should be called perform_deep_check
1840  Window root_window = XDefaultRootWindow(dpy);
1841  XCompositeRedirectSubwindows(dpy, root_window, CompositeRedirectManual);
1842  XSync(dpy, false);
1843  if (x11_composite_error_generated == true) {
1844  compositing_manager_available = true;
1845  }
1846  else {
1847  XCompositeUnredirectSubwindows(dpy, root_window, CompositeRedirectManual);
1848  compositing_manager_available = false;
1849  }
1850  XSetErrorHandler(NULL);
1851  XCloseDisplay(dpy);
1852  }
1853  else {
1854  compositing_manager_available = true;
1855  }
1856  }
1857  }
1858 
1859  const char *home;
1860  struct passwd *p;
1861  p = getpwuid(getuid());
1862  if (p)
1863  home = p->pw_dir;
1864  else
1865  home = getenv("HOME");
1866 
1867  char *filename;
1868  const char *configfile = "/.kompmgr.available";
1869  int n = strlen(home)+strlen(configfile)+1;
1870  filename = (char*)malloc(n*sizeof(char));
1871  memset(filename,0,n);
1872  strcat(filename, home);
1873  strcat(filename, configfile);
1874 
1875  /* now that we did all that by way of introduction...create or remove the file! */
1876  if (compositing_manager_available) {
1877  FILE *pFile;
1878  char buffer[255];
1879  sprintf(buffer, "available");
1880  pFile = fopen(filename, "w");
1881  if (pFile) {
1882  fwrite(buffer,1,strlen(buffer), pFile);
1883  fclose(pFile);
1884  }
1885  }
1886  else {
1887  unlink(filename);
1888  }
1889 
1890  free(filename);
1891  filename = NULL;
1892 
1893  return compositing_manager_available;
1894 }
1895 
1896 Display* KApplication::openX11RGBADisplay() {
1897  KCmdLineArgs *qtargs = KCmdLineArgs::parsedArgs("qt");
1898  char *display = 0;
1899  if ( qtargs->isSet("display"))
1900  display = qtargs->getOption( "display" ).data();
1901 
1902  Display *dpy = XOpenDisplay( display );
1903  if ( !dpy ) {
1904  kdError() << "cannot connect to X server " << display << endl;
1905  exit( 1 );
1906  }
1907 
1908  return dpy;
1909 }
1910 
1911 Qt::HANDLE KApplication::getX11RGBAVisual(Display *dpy) {
1912  getX11RGBAInformation(dpy);
1913  if (KApplication::isCompositionManagerAvailable() == true) {
1914  return argb_x11_visual;
1915  }
1916  else {
1917  return (Qt::HANDLE)NULL;
1918  }
1919 }
1920 
1921 Qt::HANDLE KApplication::getX11RGBAColormap(Display *dpy) {
1922  getX11RGBAInformation(dpy);
1923  if (KApplication::isCompositionManagerAvailable() == true) {
1924  return argb_x11_colormap;
1925  }
1926  else {
1927  return (Qt::HANDLE)NULL;
1928  }
1929 }
1930 
1931 bool KApplication::isX11CompositionAvailable() {
1932  return (argb_visual & isCompositionManagerAvailable());
1933 }
1934 
1935 void KApplication::getX11RGBAInformation(Display *dpy) {
1936  if ( !dpy ) {
1937  argb_visual = false;
1938  return;
1939  }
1940 
1941  int screen = DefaultScreen( dpy );
1942  Colormap colormap = 0;
1943  Visual *visual = 0;
1944  int event_base, error_base;
1945 
1946  if ( XRenderQueryExtension( dpy, &event_base, &error_base ) ) {
1947  int nvi;
1948  XVisualInfo templ;
1949  templ.screen = screen;
1950  templ.depth = 32;
1951  templ.c_class = TrueColor;
1952  XVisualInfo *xvi = XGetVisualInfo( dpy, VisualScreenMask | VisualDepthMask
1953  | VisualClassMask, &templ, &nvi );
1954 
1955  for ( int i = 0; i < nvi; i++ ) {
1956  XRenderPictFormat *format = XRenderFindVisualFormat( dpy, xvi[i].visual );
1957  if ( format->type == PictTypeDirect && format->direct.alphaMask ) {
1958  visual = xvi[i].visual;
1959  colormap = XCreateColormap( dpy, RootWindow( dpy, screen ), visual, AllocNone );
1960  kdDebug() << "found visual with alpha support" << endl;
1961  argb_visual = true;
1962  break;
1963  }
1964  }
1965  }
1966 
1967  if( argb_visual ) {
1968  argb_x11_visual = Qt::HANDLE( visual );
1969  argb_x11_colormap = Qt::HANDLE( colormap );
1970  argb_visual = true;
1971  return;
1972  }
1973  argb_visual = false;
1974  return;
1975 }
1976 #else
1977 void KApplication::getX11RGBAInformation(Display *dpy) {
1978 }
1979 
1980 bool KApplication::isCompositionManagerAvailable() {
1981  return false;
1982 }
1983 
1984 bool KApplication::detectCompositionManagerAvailable(bool force_available) {
1985  const char *home;
1986  struct passwd *p;
1987  p = getpwuid(getuid());
1988  if (p)
1989  home = p->pw_dir;
1990  else
1991  home = getenv("HOME");
1992 
1993  char *filename;
1994  const char *configfile = "/.kompmgr.available";
1995  int n = strlen(home)+strlen(configfile)+1;
1996  filename = (char*)malloc(n*sizeof(char));
1997  memset(filename,0,n);
1998  strcat(filename, home);
1999  strcat(filename, configfile);
2000 
2001  /* now that we did all that by way of introduction...create or remove the file! */
2002  if (force_available) {
2003  FILE *pFile;
2004  char buffer[255];
2005  sprintf(buffer, "available");
2006  pFile = fopen(filename, "w");
2007  if (pFile) {
2008  fwrite(buffer,1,strlen(buffer), pFile);
2009  fclose(pFile);
2010  }
2011  }
2012  else {
2013  unlink(filename);
2014  }
2015 
2016  free(filename);
2017  filename = NULL;
2018 
2019  return false;
2020 }
2021 
2022 Display* KApplication::openX11RGBADisplay() {
2023  return 0;
2024 }
2025 
2026 Qt::HANDLE KApplication::getX11RGBAVisual(char *display) {
2027  return 0;
2028 }
2029 
2030 Qt::HANDLE KApplication::getX11RGBAColormap(char *display) {
2031  return 0;
2032 }
2033 
2034 bool KApplication::isX11CompositionAvailable() {
2035  return false;
2036 }
2037 
2038 KApplication KApplication::KARGBApplication( bool allowStyles ) {
2039  return KApplication::KApplication(allowStyles, true);
2040 }
2041 #endif
2042 
2043 static bool kapp_block_user_input = false;
2044 
2045 void KApplication::dcopBlockUserInput( bool b )
2046 {
2047  kapp_block_user_input = b;
2048 }
2049 
2050 #ifdef Q_WS_X11
2051 bool KApplication::x11EventFilter( XEvent *_event )
2052 {
2053  switch ( _event->type ) {
2054  case ClientMessage:
2055  {
2056 #if KDE_IS_VERSION( 3, 90, 90 )
2057 #warning This should be already in Qt, check.
2058 #endif
2059  // Workaround for focus stealing prevention not working when dragging e.g. text from KWrite
2060  // to KDesktop -> the dialog asking for filename doesn't get activated. This is because
2061  // Qt-3.2.x doesn't have concept of qt_x_user_time at all, and Qt-3.3.0b1 passes the timestamp
2062  // in the XdndDrop message in incorrect field (and doesn't update qt_x_user_time either).
2063  // Patch already sent, future Qt version should have this fixed.
2064  if( _event->xclient.message_type == kde_xdnd_drop )
2065  { // if the message is XdndDrop
2066  if( _event->xclient.data.l[ 1 ] == 1 << 24 // and it's broken the way it's in Qt-3.2.x
2067  && _event->xclient.data.l[ 2 ] == 0
2068  && _event->xclient.data.l[ 4 ] == 0
2069  && _event->xclient.data.l[ 3 ] != 0 )
2070  {
2071  if( GET_QT_X_USER_TIME() == 0
2072  || NET::timestampCompare( _event->xclient.data.l[ 3 ], GET_QT_X_USER_TIME() ) > 0 )
2073  { // and the timestamp looks reasonable
2074  SET_QT_X_USER_TIME(_event->xclient.data.l[ 3 ]); // update our qt_x_user_time from it
2075  }
2076  }
2077  else // normal DND, only needed until Qt updates qt_x_user_time from XdndDrop
2078  {
2079  if( GET_QT_X_USER_TIME() == 0
2080  || NET::timestampCompare( _event->xclient.data.l[ 2 ], GET_QT_X_USER_TIME() ) > 0 )
2081  { // the timestamp looks reasonable
2082  SET_QT_X_USER_TIME(_event->xclient.data.l[ 2 ]); // update our qt_x_user_time from it
2083  }
2084  }
2085  }
2086  }
2087  default: break;
2088  }
2089 
2090  if ( kapp_block_user_input ) {
2091  switch ( _event->type ) {
2092  case ButtonPress:
2093  case ButtonRelease:
2094  case XKeyPress:
2095  case XKeyRelease:
2096  case MotionNotify:
2097  case EnterNotify:
2098  case LeaveNotify:
2099  return true;
2100  default:
2101  break;
2102  }
2103  }
2104 
2105  if (x11Filter) {
2106  for (TQWidget *w=x11Filter->first(); w; w=x11Filter->next()) {
2107  if (((KAppX11HackWidget*) w)->publicx11Event(_event))
2108  return true;
2109  }
2110  }
2111 
2112  if ((_event->type == ClientMessage) &&
2113  (_event->xclient.message_type == kipcCommAtom))
2114  {
2115  XClientMessageEvent *cme = (XClientMessageEvent *) _event;
2116 
2117  int id = cme->data.l[0];
2118  int arg = cme->data.l[1];
2119  if ((id < 32) && (kipcEventMask & (1 << id)))
2120  {
2121  switch (id)
2122  {
2123  case KIPC::StyleChanged:
2124  KGlobal::config()->reparseConfiguration();
2125  kdisplaySetStyle();
2126  break;
2127 
2128  case KIPC::ToolbarStyleChanged:
2129  KGlobal::config()->reparseConfiguration();
2130  if (useStyles)
2131  emit toolbarAppearanceChanged(arg);
2132  break;
2133 
2134  case KIPC::PaletteChanged:
2135  KGlobal::config()->reparseConfiguration();
2136  kdisplaySetPalette();
2137  break;
2138 
2139  case KIPC::FontChanged:
2140  KGlobal::config()->reparseConfiguration();
2141  KGlobalSettings::rereadFontSettings();
2142  kdisplaySetFont();
2143  break;
2144 
2145  case KIPC::BackgroundChanged:
2146  emit backgroundChanged(arg);
2147  break;
2148 
2149  case KIPC::SettingsChanged:
2150  KGlobal::config()->reparseConfiguration();
2151  if (arg == SETTINGS_PATHS)
2152  KGlobalSettings::rereadPathSettings();
2153  else if (arg == SETTINGS_MOUSE)
2154  KGlobalSettings::rereadMouseSettings();
2155  propagateSettings((SettingsCategory)arg);
2156  break;
2157 
2158  case KIPC::IconChanged:
2159  TQPixmapCache::clear();
2160  KGlobal::config()->reparseConfiguration();
2161  KGlobal::instance()->newIconLoader();
2162  emit updateIconLoaders();
2163  emit iconChanged(arg);
2164  break;
2165 
2166  case KIPC::ClipboardConfigChanged:
2167  KClipboardSynchronizer::newConfiguration(arg);
2168  break;
2169 
2170  case KIPC::BlockShortcuts:
2171  KGlobalAccel::blockShortcuts(arg);
2172  emit kipcMessage(id, arg); // some apps may do additional things
2173  break;
2174  }
2175  }
2176  else if (id >= 32)
2177  {
2178  emit kipcMessage(id, arg);
2179  }
2180  return true;
2181  }
2182  return false;
2183 }
2184 #endif // Q_WS_X11
2185 
2186 void KApplication::updateUserTimestamp( unsigned long time )
2187 {
2188 #if defined Q_WS_X11
2189  if( time == 0 )
2190  { // get current X timestamp
2191  Window w = XCreateSimpleWindow( qt_xdisplay(), qt_xrootwin(), 0, 0, 1, 1, 0, 0, 0 );
2192  XSelectInput( qt_xdisplay(), w, PropertyChangeMask );
2193  unsigned char data[ 1 ];
2194  XChangeProperty( qt_xdisplay(), w, XA_ATOM, XA_ATOM, 8, PropModeAppend, data, 1 );
2195  XEvent ev;
2196  XWindowEvent( qt_xdisplay(), w, PropertyChangeMask, &ev );
2197  time = ev.xproperty.time;
2198  XDestroyWindow( qt_xdisplay(), w );
2199  }
2200  if( GET_QT_X_USER_TIME() == 0
2201  || NET::timestampCompare( time, GET_QT_X_USER_TIME() ) > 0 ) // check time > qt_x_user_time
2202  SET_QT_X_USER_TIME(time);
2203 #endif
2204 }
2205 
2206 unsigned long KApplication::userTimestamp() const
2207 {
2208 #if defined Q_WS_X11
2209  return GET_QT_X_USER_TIME();
2210 #else
2211  return 0;
2212 #endif
2213 }
2214 
2215 void KApplication::updateRemoteUserTimestamp( const TQCString& dcopId, unsigned long time )
2216 {
2217 #if defined Q_WS_X11
2218  if( time == 0 )
2219  time = GET_QT_X_USER_TIME();
2220  DCOPRef( dcopId, "MainApplication-Interface" ).call( "updateUserTimestamp", time );
2221 #endif
2222 }
2223 
2224 void KApplication::invokeEditSlot( const char *slot )
2225 {
2226  TQObject *object = TQT_TQOBJECT(focusWidget());
2227  if( !object )
2228  return;
2229 
2230  TQMetaObject *meta = object->metaObject();
2231 
2232  int idx = meta->findSlot( slot + 1, true );
2233  if( idx < 0 )
2234  return;
2235 
2236  object->qt_invoke( idx, 0 );
2237 }
2238 
2239 void KApplication::addKipcEventMask(int id)
2240 {
2241  if (id >= 32)
2242  {
2243  kdDebug(101) << "Cannot use KIPC event mask for message IDs >= 32\n";
2244  return;
2245  }
2246  kipcEventMask |= (1 << id);
2247 }
2248 
2249 void KApplication::removeKipcEventMask(int id)
2250 {
2251  if (id >= 32)
2252  {
2253  kdDebug(101) << "Cannot use KIPC event mask for message IDs >= 32\n";
2254  return;
2255  }
2256  kipcEventMask &= ~(1 << id);
2257 }
2258 
2259 void KApplication::enableStyles()
2260 {
2261  if (!useStyles)
2262  {
2263  useStyles = true;
2264  applyGUIStyle();
2265  }
2266 }
2267 
2268 void KApplication::disableStyles()
2269 {
2270  useStyles = false;
2271 }
2272 
2273 void KApplication::applyGUIStyle()
2274 {
2275  if ( !useStyles ) return;
2276 
2277  KConfigGroup pConfig (KGlobal::config(), "General");
2278  TQString defaultStyle = KStyle::defaultStyle();
2279  TQString styleStr = pConfig.readEntry("widgetStyle", defaultStyle);
2280 
2281  if (d->overrideStyle.isEmpty()) {
2282  // ### add check whether we already use the correct style to return then
2283  // (workaround for Qt misbehavior to avoid double style initialization)
2284 
2285  TQStyle* sp = TQStyleFactory::create( styleStr );
2286 
2287  // If there is no default style available, try falling back any available style
2288  if ( !sp && styleStr != defaultStyle)
2289  sp = TQStyleFactory::create( defaultStyle );
2290  if ( !sp )
2291  sp = TQStyleFactory::create( *(TQStyleFactory::keys().begin()) );
2292  setStyle(sp);
2293  }
2294  else
2295  setStyle(d->overrideStyle);
2296  // Reread palette from config file.
2297  kdisplaySetPalette();
2298 }
2299 
2300 TQString KApplication::caption() const
2301 {
2302  // Caption set from command line ?
2303  if( !aCaption.isNull() )
2304  return aCaption;
2305  else
2306  // We have some about data ?
2307  if ( KGlobal::instance()->aboutData() )
2308  return KGlobal::instance()->aboutData()->programName();
2309  else
2310  // Last resort : application name
2311  return name();
2312 }
2313 
2314 
2315 //
2316 // 1999-09-20: Espen Sand
2317 // An attempt to simplify consistent captions.
2318 //
2319 TQString KApplication::makeStdCaption( const TQString &userCaption,
2320  bool withAppName, bool modified ) const
2321 {
2322  TQString s = userCaption.isEmpty() ? caption() : userCaption;
2323 
2324  // If the document is modified, add '[modified]'.
2325  if (modified)
2326  s += TQString::fromUtf8(" [") + i18n("modified") + TQString::fromUtf8("]");
2327 
2328  if ( !userCaption.isEmpty() ) {
2329  // Add the application name if:
2330  // User asked for it, it's not a duplication and the app name (caption()) is not empty
2331  if ( withAppName && !caption().isNull() && !userCaption.endsWith(caption()) )
2332  s += TQString::fromUtf8(" - ") + caption();
2333  }
2334 
2335  return s;
2336 }
2337 
2338 TQPalette KApplication::createApplicationPalette()
2339 {
2340  KConfig *config = KGlobal::config();
2341  KConfigGroupSaver saver( config, "General" );
2342  return createApplicationPalette( config, KGlobalSettings::contrast() );
2343 }
2344 
2345 TQPalette KApplication::createApplicationPalette( KConfig *config, int contrast_ )
2346 {
2347  TQColor trinity4Background( 239, 239, 239 );
2348  TQColor trinity4Blue( 103,141,178 );
2349 
2350  TQColor trinity4Button;
2351  if ( TQPixmap::defaultDepth() > 8 )
2352  trinity4Button.setRgb( 221, 223, 228 );
2353  else
2354  trinity4Button.setRgb( 220, 220, 220 );
2355 
2356  TQColor trinity4Link( 0, 0, 238 );
2357  TQColor trinity4VisitedLink( 82, 24, 139 );
2358 
2359  TQColor background = config->readColorEntry( "background", &trinity4Background );
2360  TQColor foreground = config->readColorEntry( "foreground", tqblackptr );
2361  TQColor button = config->readColorEntry( "buttonBackground", &trinity4Button );
2362  TQColor buttonText = config->readColorEntry( "buttonForeground", tqblackptr );
2363  TQColor highlight = config->readColorEntry( "selectBackground", &trinity4Blue );
2364  TQColor highlightedText = config->readColorEntry( "selectForeground", tqwhiteptr );
2365  TQColor base = config->readColorEntry( "windowBackground", tqwhiteptr );
2366  TQColor baseText = config->readColorEntry( "windowForeground", tqblackptr );
2367  TQColor link = config->readColorEntry( "linkColor", &trinity4Link );
2368  TQColor visitedLink = config->readColorEntry( "visitedLinkColor", &trinity4VisitedLink );
2369 
2370  int highlightVal, lowlightVal;
2371  highlightVal = 100 + (2*contrast_+4)*16/10;
2372  lowlightVal = 100 + (2*contrast_+4)*10;
2373 
2374  TQColor disfg = foreground;
2375 
2376  int h, s, v;
2377  disfg.hsv( &h, &s, &v );
2378  if (v > 128)
2379  // dark bg, light fg - need a darker disabled fg
2380  disfg = disfg.dark(lowlightVal);
2381  else if (disfg != Qt::black)
2382  // light bg, dark fg - need a lighter disabled fg - but only if !black
2383  disfg = disfg.light(highlightVal);
2384  else
2385  // black fg - use darkgray disabled fg
2386  disfg = Qt::darkGray;
2387 
2388 
2389  TQColorGroup disabledgrp(disfg, background,
2390  background.light(highlightVal),
2391  background.dark(lowlightVal),
2392  background.dark(120),
2393  background.dark(120), base);
2394 
2395  TQColorGroup colgrp(foreground, background, background.light(highlightVal),
2396  background.dark(lowlightVal),
2397  background.dark(120),
2398  baseText, base);
2399 
2400  int inlowlightVal = lowlightVal-25;
2401  if(inlowlightVal < 120)
2402  inlowlightVal = 120;
2403 
2404  colgrp.setColor(TQColorGroup::Highlight, highlight);
2405  colgrp.setColor(TQColorGroup::HighlightedText, highlightedText);
2406  colgrp.setColor(TQColorGroup::Button, button);
2407  colgrp.setColor(TQColorGroup::ButtonText, buttonText);
2408  colgrp.setColor(TQColorGroup::Midlight, background.light(110));
2409  colgrp.setColor(TQColorGroup::Link, link);
2410  colgrp.setColor(TQColorGroup::LinkVisited, visitedLink);
2411 
2412  disabledgrp.setColor(TQColorGroup::Button, button);
2413 
2414  TQColor disbtntext = buttonText;
2415  disbtntext.hsv( &h, &s, &v );
2416  if (v > 128)
2417  // dark button, light buttonText - need a darker disabled buttonText
2418  disbtntext = disbtntext.dark(lowlightVal);
2419  else if (disbtntext != Qt::black)
2420  // light buttonText, dark button - need a lighter disabled buttonText - but only if !black
2421  disbtntext = disbtntext.light(highlightVal);
2422  else
2423  // black button - use darkgray disabled buttonText
2424  disbtntext = Qt::darkGray;
2425 
2426  disabledgrp.setColor(TQColorGroup::ButtonText, disbtntext);
2427  disabledgrp.setColor(TQColorGroup::Midlight, background.light(110));
2428  disabledgrp.setColor(TQColorGroup::Highlight, highlight.dark(120));
2429  disabledgrp.setColor(TQColorGroup::Link, link);
2430  disabledgrp.setColor(TQColorGroup::LinkVisited, visitedLink);
2431 
2432  return TQPalette(colgrp, disabledgrp, colgrp);
2433 }
2434 
2435 
2436 void KApplication::kdisplaySetPalette()
2437 {
2438 #ifdef Q_WS_MACX
2439  //Can I have this on other platforms, please!? --Sam
2440  {
2441  KConfig *config = KGlobal::config();
2442  KConfigGroupSaver saver( config, "General" );
2443  bool do_not_set_palette = FALSE;
2444  if(config->readBoolEntry("nopaletteChange", &do_not_set_palette))
2445  return;
2446  }
2447 #endif
2448  TQApplication::setPalette( createApplicationPalette(), true);
2449  emit kdisplayPaletteChanged();
2450  emit appearanceChanged();
2451 }
2452 
2453 
2454 void KApplication::kdisplaySetFont()
2455 {
2456  TQApplication::setFont(KGlobalSettings::generalFont(), true);
2457  TQApplication::setFont(KGlobalSettings::menuFont(), true, TQMENUBAR_OBJECT_NAME_STRING);
2458  TQApplication::setFont(KGlobalSettings::menuFont(), true, TQPOPUPMENU_OBJECT_NAME_STRING);
2459  TQApplication::setFont(KGlobalSettings::menuFont(), true, "KPopupTitle");
2460 
2461  // "patch" standard TQStyleSheet to follow our fonts
2462  TQStyleSheet* sheet = TQStyleSheet::defaultSheet();
2463  sheet->item ("pre")->setFontFamily (KGlobalSettings::fixedFont().family());
2464  sheet->item ("code")->setFontFamily (KGlobalSettings::fixedFont().family());
2465  sheet->item ("tt")->setFontFamily (KGlobalSettings::fixedFont().family());
2466 
2467  emit kdisplayFontChanged();
2468  emit appearanceChanged();
2469 }
2470 
2471 
2472 void KApplication::kdisplaySetStyle()
2473 {
2474  if (useStyles)
2475  {
2476  applyGUIStyle();
2477  emit kdisplayStyleChanged();
2478  emit appearanceChanged();
2479  }
2480 }
2481 
2482 
2483 void KApplication::propagateSettings(SettingsCategory arg)
2484 {
2485  KConfigBase* config = KGlobal::config();
2486  KConfigGroupSaver saver( config, "KDE" );
2487 
2488 #ifdef QT_HAVE_MAX_IMAGE_SIZE
2489  TQSize maxImageSize(4096, 4096);
2490  maxImageSize = config->readSizeEntry("MaxImageSize", &maxImageSize);
2491  TQImage::setMaxImageSize(maxImageSize);
2492 #endif
2493 
2494  int num = config->readNumEntry("CursorBlinkRate", TQApplication::cursorFlashTime());
2495  if ((num != 0) && (num < 200))
2496  num = 200;
2497  if (num > 2000)
2498  num = 2000;
2499  TQApplication::setCursorFlashTime(num);
2500  num = config->readNumEntry("DoubleClickInterval", TQApplication::doubleClickInterval());
2501  TQApplication::setDoubleClickInterval(num);
2502  num = config->readNumEntry("StartDragTime", TQApplication::startDragTime());
2503  TQApplication::setStartDragTime(num);
2504  num = config->readNumEntry("StartDragDist", TQApplication::startDragDistance());
2505  TQApplication::setStartDragDistance(num);
2506  num = config->readNumEntry("WheelScrollLines", TQApplication::wheelScrollLines());
2507  TQApplication::setWheelScrollLines(num);
2508 
2509  bool b = config->readBoolEntry("EffectAnimateMenu", false);
2510  TQApplication::setEffectEnabled( Qt::UI_AnimateMenu, b);
2511  b = config->readBoolEntry("EffectFadeMenu", false);
2512  TQApplication::setEffectEnabled( Qt::UI_FadeMenu, b);
2513  b = config->readBoolEntry("EffectAnimateCombo", false);
2514  TQApplication::setEffectEnabled( Qt::UI_AnimateCombo, b);
2515  b = config->readBoolEntry("EffectAnimateTooltip", false);
2516  TQApplication::setEffectEnabled( Qt::UI_AnimateTooltip, b);
2517  b = config->readBoolEntry("EffectFadeTooltip", false);
2518  TQApplication::setEffectEnabled( Qt::UI_FadeTooltip, b);
2519  b = !config->readBoolEntry("EffectNoTooltip", false);
2520  TQToolTip::setGloballyEnabled( b );
2521 
2522  emit settingsChanged(arg);
2523 }
2524 
2525 void KApplication::installKDEPropertyMap()
2526 {
2527 #ifndef QT_NO_SQL
2528  static bool installed = false;
2529  if (installed) return;
2530  installed = true;
2537  // TQSqlPropertyMap takes ownership of the new default map.
2538  TQSqlPropertyMap *kdeMap = new TQSqlPropertyMap;
2539  kdeMap->insert( "KColorButton", "color" );
2540  kdeMap->insert( "KComboBox", "currentItem" );
2541  kdeMap->insert( "KDatePicker", "date" );
2542  kdeMap->insert( "KDateWidget", "date" );
2543  kdeMap->insert( "KDateTimeWidget", "dateTime" );
2544  kdeMap->insert( "KEditListBox", "items" );
2545  kdeMap->insert( "KFontCombo", "family" );
2546  kdeMap->insert( "KFontRequester", "font" );
2547  kdeMap->insert( "KFontChooser", "font" );
2548  kdeMap->insert( "KHistoryCombo", "currentItem" );
2549  kdeMap->insert( "KListBox", "currentItem" );
2550  kdeMap->insert( "KLineEdit", "text" );
2551  kdeMap->insert( "KRestrictedLine", "text" );
2552  kdeMap->insert( "KSqueezedTextLabel", "text" );
2553  kdeMap->insert( "KTextBrowser", "source" );
2554  kdeMap->insert( "KTextEdit", "text" );
2555  kdeMap->insert( "KURLRequester", "url" );
2556  kdeMap->insert( "KPasswordEdit", "password" );
2557  kdeMap->insert( "KIntNumInput", "value" );
2558  kdeMap->insert( "KIntSpinBox", "value" );
2559  kdeMap->insert( "KDoubleNumInput", "value" );
2560  // Temp til fixed in QT then enable ifdef with the correct version num
2561  kdeMap->insert( TQGROUPBOX_OBJECT_NAME_STRING, "checked" );
2562  kdeMap->insert( TQTABWIDGET_OBJECT_NAME_STRING, "currentPage" );
2563  TQSqlPropertyMap::installDefaultMap( kdeMap );
2564 #endif
2565 }
2566 
2567 void KApplication::invokeHelp( const TQString& anchor,
2568  const TQString& _appname) const
2569 {
2570  return invokeHelp( anchor, _appname, "" );
2571 }
2572 
2573 #ifndef Q_WS_WIN
2574 // for win32 we're using simple help tools like Qt Assistant,
2575 // see kapplication_win.cpp
2576 void KApplication::invokeHelp( const TQString& anchor,
2577  const TQString& _appname,
2578  const TQCString& startup_id ) const
2579 {
2580  TQString url;
2581  TQString appname;
2582  if (_appname.isEmpty())
2583  appname = name();
2584  else
2585  appname = _appname;
2586 
2587  if (!anchor.isEmpty())
2588  url = TQString("help:/%1?anchor=%2").arg(appname).arg(anchor);
2589  else
2590  url = TQString("help:/%1/index.html").arg(appname);
2591 
2592  TQString error;
2593  if ( !dcopClient()->isApplicationRegistered("khelpcenter") )
2594  {
2595  if (startServiceByDesktopName("khelpcenter", url, &error, 0, 0, startup_id, false))
2596  {
2597  if (Tty != kapp->type())
2598  TQMessageBox::critical(kapp->mainWidget(), i18n("Could not Launch Help Center"),
2599  i18n("Could not launch the KDE Help Center:\n\n%1").arg(error), i18n("&OK"));
2600  else
2601  kdWarning() << "Could not launch help:\n" << error << endl;
2602  return;
2603  }
2604  }
2605  else
2606  DCOPRef( "khelpcenter", "KHelpCenterIface" ).send( "openUrl", url, startup_id );
2607 }
2608 #endif
2609 
2610 void KApplication::invokeHTMLHelp( const TQString& _filename, const TQString& topic ) const
2611 {
2612  kdWarning() << "invoking HTML help is deprecated! use docbook and invokeHelp!\n";
2613 
2614  TQString filename;
2615 
2616  if( _filename.isEmpty() )
2617  filename = TQString(name()) + "/index.html";
2618  else
2619  filename = _filename;
2620 
2621  TQString url;
2622  if (!topic.isEmpty())
2623  url = TQString("help:/%1#%2").arg(filename).arg(topic);
2624  else
2625  url = TQString("help:/%1").arg(filename);
2626 
2627  TQString error;
2628  if ( !dcopClient()->isApplicationRegistered("khelpcenter") )
2629  {
2630  if (startServiceByDesktopName("khelpcenter", url, &error, 0, 0, "", false))
2631  {
2632  if (Tty != kapp->type())
2633  TQMessageBox::critical(kapp->mainWidget(), i18n("Could not Launch Help Center"),
2634  i18n("Could not launch the KDE Help Center:\n\n%1").arg(error), i18n("&OK"));
2635  else
2636  kdWarning() << "Could not launch help:\n" << error << endl;
2637  return;
2638  }
2639  }
2640  else
2641  DCOPRef( "khelpcenter", "KHelpCenterIface" ).send( "openUrl", url );
2642 }
2643 
2644 
2645 void KApplication::invokeMailer(const TQString &address, const TQString &subject)
2646 {
2647  return invokeMailer(address,subject,"");
2648 }
2649 
2650 void KApplication::invokeMailer(const TQString &address, const TQString &subject, const TQCString& startup_id)
2651 {
2652  invokeMailer(address, TQString::null, TQString::null, subject, TQString::null, TQString::null,
2653  TQStringList(), startup_id );
2654 }
2655 
2656 void KApplication::invokeMailer(const KURL &mailtoURL)
2657 {
2658  return invokeMailer( mailtoURL, "" );
2659 }
2660 
2661 void KApplication::invokeMailer(const KURL &mailtoURL, const TQCString& startup_id )
2662 {
2663  return invokeMailer( mailtoURL, startup_id, false);
2664 }
2665 
2666 void KApplication::invokeMailer(const KURL &mailtoURL, const TQCString& startup_id, bool allowAttachments )
2667 {
2668  TQString address = KURL::decode_string(mailtoURL.path()), subject, cc, bcc, body;
2669  TQStringList queries = TQStringList::split('&', mailtoURL.query().mid(1));
2670  TQStringList attachURLs;
2671  for (TQStringList::Iterator it = queries.begin(); it != queries.end(); ++it)
2672  {
2673  TQString q = (*it).lower();
2674  if (q.startsWith("subject="))
2675  subject = KURL::decode_string((*it).mid(8));
2676  else
2677  if (q.startsWith("cc="))
2678  cc = cc.isEmpty()? KURL::decode_string((*it).mid(3)): cc + ',' + KURL::decode_string((*it).mid(3));
2679  else
2680  if (q.startsWith("bcc="))
2681  bcc = bcc.isEmpty()? KURL::decode_string((*it).mid(4)): bcc + ',' + KURL::decode_string((*it).mid(4));
2682  else
2683  if (q.startsWith("body="))
2684  body = KURL::decode_string((*it).mid(5));
2685  else
2686  if (allowAttachments && q.startsWith("attach="))
2687  attachURLs.push_back(KURL::decode_string((*it).mid(7)));
2688  else
2689  if (allowAttachments && q.startsWith("attachment="))
2690  attachURLs.push_back(KURL::decode_string((*it).mid(11)));
2691  else
2692  if (q.startsWith("to="))
2693  address = address.isEmpty()? KURL::decode_string((*it).mid(3)): address + ',' + KURL::decode_string((*it).mid(3));
2694  }
2695 
2696  invokeMailer( address, cc, bcc, subject, body, TQString::null, attachURLs, startup_id );
2697 }
2698 
2699 void KApplication::invokeMailer(const TQString &to, const TQString &cc, const TQString &bcc,
2700  const TQString &subject, const TQString &body,
2701  const TQString & messageFile, const TQStringList &attachURLs)
2702 {
2703  return invokeMailer(to,cc,bcc,subject,body,messageFile,attachURLs,"");
2704 }
2705 
2706 #ifndef Q_WS_WIN
2707 // on win32, for invoking browser we're using win32 API
2708 // see kapplication_win.cpp
2709 
2710 static TQStringList splitEmailAddressList( const TQString & aStr )
2711 {
2712  // This is a copy of KPIM::splitEmailAddrList().
2713  // Features:
2714  // - always ignores quoted characters
2715  // - ignores everything (including parentheses and commas)
2716  // inside quoted strings
2717  // - supports nested comments
2718  // - ignores everything (including double quotes and commas)
2719  // inside comments
2720 
2721  TQStringList list;
2722 
2723  if (aStr.isEmpty())
2724  return list;
2725 
2726  TQString addr;
2727  uint addrstart = 0;
2728  int commentlevel = 0;
2729  bool insidequote = false;
2730 
2731  for (uint index=0; index<aStr.length(); index++) {
2732  // the following conversion to latin1 is o.k. because
2733  // we can safely ignore all non-latin1 characters
2734  switch (aStr[index].latin1()) {
2735  case '"' : // start or end of quoted string
2736  if (commentlevel == 0)
2737  insidequote = !insidequote;
2738  break;
2739  case '(' : // start of comment
2740  if (!insidequote)
2741  commentlevel++;
2742  break;
2743  case ')' : // end of comment
2744  if (!insidequote) {
2745  if (commentlevel > 0)
2746  commentlevel--;
2747  else {
2748  //kdDebug() << "Error in address splitting: Unmatched ')'"
2749  // << endl;
2750  return list;
2751  }
2752  }
2753  break;
2754  case '\\' : // quoted character
2755  index++; // ignore the quoted character
2756  break;
2757  case ',' :
2758  if (!insidequote && (commentlevel == 0)) {
2759  addr = aStr.mid(addrstart, index-addrstart);
2760  if (!addr.isEmpty())
2761  list += addr.simplifyWhiteSpace();
2762  addrstart = index+1;
2763  }
2764  break;
2765  }
2766  }
2767  // append the last address to the list
2768  if (!insidequote && (commentlevel == 0)) {
2769  addr = aStr.mid(addrstart, aStr.length()-addrstart);
2770  if (!addr.isEmpty())
2771  list += addr.simplifyWhiteSpace();
2772  }
2773  //else
2774  // kdDebug() << "Error in address splitting: "
2775  // << "Unexpected end of address list"
2776  // << endl;
2777 
2778  return list;
2779 }
2780 
2781 void KApplication::invokeMailer(const TQString &_to, const TQString &_cc, const TQString &_bcc,
2782  const TQString &subject, const TQString &body,
2783  const TQString & /*messageFile TODO*/, const TQStringList &attachURLs,
2784  const TQCString& startup_id )
2785 {
2786  KConfig config("emaildefaults");
2787 
2788  config.setGroup("Defaults");
2789  TQString group = config.readEntry("Profile","Default");
2790 
2791  config.setGroup( TQString("PROFILE_%1").arg(group) );
2792  TQString command = config.readPathEntry("EmailClient");
2793 
2794  TQString to, cc, bcc;
2795  if (command.isEmpty() || command == TQString::fromLatin1("kmail")
2796  || command.endsWith("/kmail"))
2797  {
2798  command = TQString::fromLatin1("kmail --composer -s %s -c %c -b %b --body %B --attach %A -- %t");
2799  if ( !_to.isEmpty() )
2800  {
2801  // put the whole address lists into RFC2047 encoded blobs; technically
2802  // this isn't correct, but KMail understands it nonetheless
2803  to = TQString( "=?utf8?b?%1?=" )
2804  .arg( QString(KCodecs::base64Encode( _to.utf8(), false )) );
2805  }
2806  if ( !_cc.isEmpty() )
2807  cc = TQString( "=?utf8?b?%1?=" )
2808  .arg( QString(KCodecs::base64Encode( _cc.utf8(), false )) );
2809  if ( !_bcc.isEmpty() )
2810  bcc = TQString( "=?utf8?b?%1?=" )
2811  .arg( QString(KCodecs::base64Encode( _bcc.utf8(), false )) );
2812  } else {
2813  to = _to;
2814  cc = _cc;
2815  bcc = _bcc;
2816  if( !command.contains( '%' ))
2817  command += " %u";
2818  }
2819 
2820  if (config.readBoolEntry("TerminalClient", false))
2821  {
2822  KConfigGroup confGroup( KGlobal::config(), "General" );
2823  TQString preferredTerminal = confGroup.readPathEntry("TerminalApplication", "konsole");
2824  command = preferredTerminal + " -e " + command;
2825  }
2826 
2827  TQStringList cmdTokens = KShell::splitArgs(command);
2828  TQString cmd = cmdTokens[0];
2829  cmdTokens.remove(cmdTokens.begin());
2830 
2831  KURL url;
2832  TQStringList qry;
2833  if (!to.isEmpty())
2834  {
2835  TQStringList tos = splitEmailAddressList( to );
2836  url.setPath( tos.first() );
2837  tos.remove( tos.begin() );
2838  for (TQStringList::ConstIterator it = tos.begin(); it != tos.end(); ++it)
2839  qry.append( "to=" + KURL::encode_string( *it ) );
2840  }
2841  const TQStringList ccs = splitEmailAddressList( cc );
2842  for (TQStringList::ConstIterator it = ccs.begin(); it != ccs.end(); ++it)
2843  qry.append( "cc=" + KURL::encode_string( *it ) );
2844  const TQStringList bccs = splitEmailAddressList( bcc );
2845  for (TQStringList::ConstIterator it = bccs.begin(); it != bccs.end(); ++it)
2846  qry.append( "bcc=" + KURL::encode_string( *it ) );
2847  for (TQStringList::ConstIterator it = attachURLs.begin(); it != attachURLs.end(); ++it)
2848  qry.append( "attach=" + KURL::encode_string( *it ) );
2849  if (!subject.isEmpty())
2850  qry.append( "subject=" + KURL::encode_string( subject ) );
2851  if (!body.isEmpty())
2852  qry.append( "body=" + KURL::encode_string( body ) );
2853  url.setQuery( qry.join( "&" ) );
2854  if ( ! (to.isEmpty() && qry.isEmpty()) )
2855  url.setProtocol("mailto");
2856 
2857  TQMap<TQChar, TQString> keyMap;
2858  keyMap.insert('t', to);
2859  keyMap.insert('s', subject);
2860  keyMap.insert('c', cc);
2861  keyMap.insert('b', bcc);
2862  keyMap.insert('B', body);
2863  keyMap.insert('u', url.url());
2864 
2865  TQString attachlist = attachURLs.join(",");
2866  attachlist.prepend('\'');
2867  attachlist.append('\'');
2868  keyMap.insert('A', attachlist);
2869 
2870  for (TQStringList::Iterator it = cmdTokens.begin(); it != cmdTokens.end(); )
2871  {
2872  if (*it == "%A")
2873  {
2874  if (it == cmdTokens.begin()) // better safe than sorry ...
2875  continue;
2876  TQStringList::ConstIterator urlit = attachURLs.begin();
2877  TQStringList::ConstIterator urlend = attachURLs.end();
2878  if ( urlit != urlend )
2879  {
2880  TQStringList::Iterator previt = it;
2881  --previt;
2882  *it = *urlit;
2883  ++it;
2884  while ( ++urlit != urlend )
2885  {
2886  cmdTokens.insert( it, *previt );
2887  cmdTokens.insert( it, *urlit );
2888  }
2889  } else {
2890  --it;
2891  it = cmdTokens.remove( cmdTokens.remove( it ) );
2892  }
2893  } else {
2894  *it = KMacroExpander::expandMacros(*it, keyMap);
2895  ++it;
2896  }
2897  }
2898 
2899  TQString error;
2900  // TODO this should check if cmd has a .desktop file, and use data from it, together
2901  // with sending more ASN data
2902  if (kdeinitExec(cmd, cmdTokens, &error, NULL, startup_id )) {
2903  if (Tty != kapp->type()) {
2904  TQMessageBox::critical(kapp->mainWidget(), i18n("Could not Launch Mail Client"),
2905  i18n("Could not launch the mail client:\n\n%1").arg(error), i18n("&OK"));
2906  }
2907  else {
2908  kdWarning() << "Could not launch mail client:\n" << error << endl;
2909  }
2910  }
2911 }
2912 #endif
2913 
2914 void KApplication::invokeBrowser( const TQString &url )
2915 {
2916  return invokeBrowser( url, "" );
2917 }
2918 
2919 #ifndef Q_WS_WIN
2920 // on win32, for invoking browser we're using win32 API
2921 // see kapplication_win.cpp
2922 void KApplication::invokeBrowser( const TQString &url, const TQCString& startup_id )
2923 {
2924  TQString error;
2925 
2926  if (startServiceByDesktopName("kfmclient", url, &error, 0, 0, startup_id, false))
2927  {
2928  if (Tty != kapp->type())
2929  TQMessageBox::critical(kapp->mainWidget(), i18n("Could not Launch Browser"),
2930  i18n("Could not launch the browser:\n\n%1").arg(error), i18n("&OK"));
2931  else
2932  kdWarning() << "Could not launch browser:\n" << error << endl;
2933  return;
2934  }
2935 }
2936 #endif
2937 
2938 void KApplication::cut()
2939 {
2940  invokeEditSlot( TQT_SLOT( cut() ) );
2941 }
2942 
2943 void KApplication::copy()
2944 {
2945  invokeEditSlot( TQT_SLOT( copy() ) );
2946 }
2947 
2948 void KApplication::paste()
2949 {
2950  invokeEditSlot( TQT_SLOT( paste() ) );
2951 }
2952 
2953 void KApplication::clear()
2954 {
2955  invokeEditSlot( TQT_SLOT( clear() ) );
2956 }
2957 
2958 void KApplication::selectAll()
2959 {
2960  invokeEditSlot( TQT_SLOT( selectAll() ) );
2961 }
2962 
2963 void KApplication::broadcastKeyCode(unsigned int keyCode)
2964 {
2965  emit coreFakeKeyPress(keyCode);
2966 }
2967 
2968 TQCString
2969 KApplication::launcher()
2970 {
2971  return "klauncher";
2972 }
2973 
2974 static int
2975 startServiceInternal( const TQCString &function,
2976  const TQString& _name, const TQStringList &URLs,
2977  TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait )
2978 {
2979  struct serviceResult
2980  {
2981  int result;
2982  TQCString dcopName;
2983  TQString error;
2984  pid_t pid;
2985  };
2986 
2987  // Register app as able to send DCOP messages
2988  DCOPClient *dcopClient;
2989  if (kapp)
2990  dcopClient = kapp->dcopClient();
2991  else
2992  dcopClient = new DCOPClient;
2993 
2994  if (!dcopClient->isAttached())
2995  {
2996  if (!dcopClient->attach())
2997  {
2998  if (error)
2999  *error = i18n("Could not register with DCOP.\n");
3000  if (!kapp)
3001  delete dcopClient;
3002 
3003  return -1;
3004  }
3005  }
3006  TQByteArray params;
3007  TQDataStream stream(params, IO_WriteOnly);
3008  stream << _name << URLs;
3009  TQCString replyType;
3010  TQByteArray replyData;
3011  TQCString _launcher = KApplication::launcher();
3012  TQValueList<TQCString> envs;
3013 #ifdef Q_WS_X11
3014  if (qt_xdisplay()) {
3015  TQCString dpystring(XDisplayString(qt_xdisplay()));
3016  envs.append( TQCString("DISPLAY=") + dpystring );
3017  } else if( getenv( "DISPLAY" )) {
3018  TQCString dpystring( getenv( "DISPLAY" ));
3019  envs.append( TQCString("DISPLAY=") + dpystring );
3020  }
3021 #endif
3022  stream << envs;
3023 #if defined Q_WS_X11
3024  // make sure there is id, so that user timestamp exists
3025  stream << ( startup_id.isEmpty() ? KStartupInfo::createNewStartupId() : startup_id );
3026 #endif
3027  if( function.left( 12 ) != "kdeinit_exec" )
3028  stream << noWait;
3029 
3030  if (!dcopClient->call(_launcher, _launcher,
3031  function, params, replyType, replyData))
3032  {
3033  if (error)
3034  *error = i18n("KLauncher could not be reached via DCOP.\n");
3035  if (!kapp)
3036  delete dcopClient;
3037  return -1;
3038  }
3039  if (!kapp)
3040  delete dcopClient;
3041 
3042  if (noWait)
3043  return 0;
3044 
3045  TQDataStream stream2(replyData, IO_ReadOnly);
3046  serviceResult result;
3047  stream2 >> result.result >> result.dcopName >> result.error >> result.pid;
3048  if (dcopService)
3049  *dcopService = result.dcopName;
3050  if (error)
3051  *error = result.error;
3052  if (pid)
3053  *pid = result.pid;
3054  return result.result;
3055 }
3056 
3057 int
3058 KApplication::startServiceByName( const TQString& _name, const TQString &URL,
3059  TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait )
3060 {
3061  TQStringList URLs;
3062  if (!URL.isEmpty())
3063  URLs.append(URL);
3064  return startServiceInternal(
3065  "start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)",
3066  _name, URLs, error, dcopService, pid, startup_id, noWait);
3067 }
3068 
3069 int
3070 KApplication::startServiceByName( const TQString& _name, const TQStringList &URLs,
3071  TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait )
3072 {
3073  return startServiceInternal(
3074  "start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)",
3075  _name, URLs, error, dcopService, pid, startup_id, noWait);
3076 }
3077 
3078 int
3079 KApplication::startServiceByDesktopPath( const TQString& _name, const TQString &URL,
3080  TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait )
3081 {
3082  TQStringList URLs;
3083  if (!URL.isEmpty())
3084  URLs.append(URL);
3085  return startServiceInternal(
3086  "start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)",
3087  _name, URLs, error, dcopService, pid, startup_id, noWait);
3088 }
3089 
3090 int
3091 KApplication::startServiceByDesktopPath( const TQString& _name, const TQStringList &URLs,
3092  TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait )
3093 {
3094  return startServiceInternal(
3095  "start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)",
3096  _name, URLs, error, dcopService, pid, startup_id, noWait);
3097 }
3098 
3099 int
3100 KApplication::startServiceByDesktopName( const TQString& _name, const TQString &URL,
3101  TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait )
3102 {
3103  TQStringList URLs;
3104  if (!URL.isEmpty())
3105  URLs.append(URL);
3106  return startServiceInternal(
3107  "start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)",
3108  _name, URLs, error, dcopService, pid, startup_id, noWait);
3109 }
3110 
3111 int
3112 KApplication::startServiceByDesktopName( const TQString& _name, const TQStringList &URLs,
3113  TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait )
3114 {
3115  return startServiceInternal(
3116  "start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)",
3117  _name, URLs, error, dcopService, pid, startup_id, noWait);
3118 }
3119 
3120 int
3121 KApplication::kdeinitExec( const TQString& name, const TQStringList &args,
3122  TQString *error, int *pid )
3123 {
3124  return kdeinitExec( name, args, error, pid, "" );
3125 }
3126 
3127 int
3128 KApplication::kdeinitExec( const TQString& name, const TQStringList &args,
3129  TQString *error, int *pid, const TQCString& startup_id )
3130 {
3131  return startServiceInternal("kdeinit_exec(TQString,TQStringList,TQValueList<TQCString>,TQCString)",
3132  name, args, error, 0, pid, startup_id, false);
3133 }
3134 
3135 int
3136 KApplication::kdeinitExecWait( const TQString& name, const TQStringList &args,
3137  TQString *error, int *pid )
3138 {
3139  return kdeinitExecWait( name, args, error, pid, "" );
3140 }
3141 
3142 int
3143 KApplication::kdeinitExecWait( const TQString& name, const TQStringList &args,
3144  TQString *error, int *pid, const TQCString& startup_id )
3145 {
3146  return startServiceInternal("kdeinit_exec_wait(TQString,TQStringList,TQValueList<TQCString>,TQCString)",
3147  name, args, error, 0, pid, startup_id, false);
3148 }
3149 
3150 TQString KApplication::tempSaveName( const TQString& pFilename ) const
3151 {
3152  TQString aFilename;
3153 
3154  if( TQDir::isRelativePath(pFilename) )
3155  {
3156  kdWarning(101) << "Relative filename passed to KApplication::tempSaveName" << endl;
3157  aFilename = TQFileInfo( TQDir( "." ), pFilename ).absFilePath();
3158  }
3159  else
3160  aFilename = pFilename;
3161 
3162  TQDir aAutosaveDir( TQDir::homeDirPath() + "/autosave/" );
3163  if( !aAutosaveDir.exists() )
3164  {
3165  if( !aAutosaveDir.mkdir( aAutosaveDir.absPath() ) )
3166  {
3167  // Last chance: use temp dir
3168  aAutosaveDir.setPath( KGlobal::dirs()->saveLocation("tmp") );
3169  }
3170  }
3171 
3172  aFilename.replace( "/", "\\!" ).prepend( "#" ).append( "#" ).prepend( "/" ).prepend( aAutosaveDir.absPath() );
3173 
3174  return aFilename;
3175 }
3176 
3177 
3178 TQString KApplication::checkRecoverFile( const TQString& pFilename,
3179  bool& bRecover ) const
3180 {
3181  TQString aFilename;
3182 
3183  if( TQDir::isRelativePath(pFilename) )
3184  {
3185  kdWarning(101) << "Relative filename passed to KApplication::tempSaveName" << endl;
3186  aFilename = TQFileInfo( TQDir( "." ), pFilename ).absFilePath();
3187  }
3188  else
3189  aFilename = pFilename;
3190 
3191  TQDir aAutosaveDir( TQDir::homeDirPath() + "/autosave/" );
3192  if( !aAutosaveDir.exists() )
3193  {
3194  if( !aAutosaveDir.mkdir( aAutosaveDir.absPath() ) )
3195  {
3196  // Last chance: use temp dir
3197  aAutosaveDir.setPath( KGlobal::dirs()->saveLocation("tmp") );
3198  }
3199  }
3200 
3201  aFilename.replace( "/", "\\!" ).prepend( "#" ).append( "#" ).prepend( "/" ).prepend( aAutosaveDir.absPath() );
3202 
3203  if( TQFile( aFilename ).exists() )
3204  {
3205  bRecover = true;
3206  return aFilename;
3207  }
3208  else
3209  {
3210  bRecover = false;
3211  return pFilename;
3212  }
3213 }
3214 
3215 
3216 bool checkAccess(const TQString& pathname, int mode)
3217 {
3218  int accessOK = access( TQFile::encodeName(pathname), mode );
3219  if ( accessOK == 0 )
3220  return true; // OK, I can really access the file
3221 
3222  // else
3223  // if we want to write the file would be created. Check, if the
3224  // user may write to the directory to create the file.
3225  if ( (mode & W_OK) == 0 )
3226  return false; // Check for write access is not part of mode => bail out
3227 
3228 
3229  if (!access( TQFile::encodeName(pathname), F_OK)) // if it already exists
3230  return false;
3231 
3232  //strip the filename (everything until '/' from the end
3233  TQString dirName(pathname);
3234  int pos = dirName.findRev('/');
3235  if ( pos == -1 )
3236  return false; // No path in argument. This is evil, we won't allow this
3237  else if ( pos == 0 ) // don't turn e.g. /root into an empty string
3238  pos = 1;
3239 
3240  dirName.truncate(pos); // strip everything starting from the last '/'
3241 
3242  accessOK = access( TQFile::encodeName(dirName), W_OK );
3243  // -?- Can I write to the accessed diretory
3244  if ( accessOK == 0 )
3245  return true; // Yes
3246  else
3247  return false; // No
3248 }
3249 
3250 void KApplication::setTopWidget( TQWidget *topWidget )
3251 {
3252  if( !topWidget )
3253  return;
3254 
3255  // set the specified caption
3256  if ( !topWidget->inherits("KMainWindow") ) { // KMainWindow does this already for us
3257  topWidget->setCaption( caption() );
3258  }
3259 
3260  // set the specified icons
3261  topWidget->setIcon( icon() ); //standard X11
3262 #if defined Q_WS_X11
3263 //#ifdef Q_WS_X11 // FIXME(E): Implement for Qt/Embedded
3264  KWin::setIcons(topWidget->winId(), icon(), miniIcon() ); // NET_WM hints for KWin
3265 
3266  // set the app startup notification window property
3267  KStartupInfo::setWindowStartupId( topWidget->winId(), startupId());
3268 #endif
3269 }
3270 
3271 TQCString KApplication::startupId() const
3272 {
3273  return d->startup_id;
3274 }
3275 
3276 void KApplication::setStartupId( const TQCString& startup_id )
3277 {
3278  if( startup_id == d->startup_id )
3279  return;
3280 #if defined Q_WS_X11
3281  KStartupInfo::handleAutoAppStartedSending(); // finish old startup notification if needed
3282 #endif
3283  if( startup_id.isEmpty())
3284  d->startup_id = "0";
3285  else
3286  {
3287  d->startup_id = startup_id;
3288 #if defined Q_WS_X11
3289  KStartupInfoId id;
3290  id.initId( startup_id );
3291  long timestamp = id.timestamp();
3292  if( timestamp != 0 )
3293  updateUserTimestamp( timestamp );
3294 #endif
3295  }
3296 }
3297 
3298 // read the startup notification env variable, save it and unset it in order
3299 // not to propagate it to processes started from this app
3300 void KApplication::read_app_startup_id()
3301 {
3302 #if defined Q_WS_X11
3303  KStartupInfoId id = KStartupInfo::currentStartupIdEnv();
3304  KStartupInfo::resetStartupEnv();
3305  d->startup_id = id.id();
3306 #endif
3307 }
3308 
3309 int KApplication::random()
3310 {
3311  static bool init = false;
3312  if (!init)
3313  {
3314  unsigned int seed;
3315  init = true;
3316  int fd = open("/dev/urandom", O_RDONLY);
3317  if (fd < 0 || ::read(fd, &seed, sizeof(seed)) != sizeof(seed))
3318  {
3319  // No /dev/urandom... try something else.
3320  srand(getpid());
3321  seed = rand()+time(0);
3322  }
3323  if (fd >= 0) close(fd);
3324  srand(seed);
3325  }
3326  return rand();
3327 }
3328 
3329 TQString KApplication::randomString(int length)
3330 {
3331  if (length <=0 ) return TQString::null;
3332 
3333  TQString str; str.setLength( length );
3334  int i = 0;
3335  while (length--)
3336  {
3337  int r=random() % 62;
3338  r+=48;
3339  if (r>57) r+=7;
3340  if (r>90) r+=6;
3341  str[i++] = char(r);
3342  // so what if I work backwards?
3343  }
3344  return str;
3345 }
3346 
3347 bool KApplication::authorize(const TQString &genericAction)
3348 {
3349  if (!d->actionRestrictions)
3350  return true;
3351 
3352  KConfig *config = KGlobal::config();
3353  KConfigGroupSaver saver( config, "KDE Action Restrictions" );
3354  return config->readBoolEntry(genericAction, true);
3355 }
3356 
3357 bool KApplication::authorizeKAction(const char *action)
3358 {
3359  if (!d->actionRestrictions || !action)
3360  return true;
3361 
3362  static const TQString &action_prefix = KGlobal::staticQString( "action/" );
3363 
3364  return authorize(action_prefix + action);
3365 }
3366 
3367 bool KApplication::authorizeControlModule(const TQString &menuId)
3368 {
3369  if (menuId.isEmpty() || kde_kiosk_exception)
3370  return true;
3371  KConfig *config = KGlobal::config();
3372  KConfigGroupSaver saver( config, "KDE Control Module Restrictions" );
3373  return config->readBoolEntry(menuId, true);
3374 }
3375 
3376 TQStringList KApplication::authorizeControlModules(const TQStringList &menuIds)
3377 {
3378  KConfig *config = KGlobal::config();
3379  KConfigGroupSaver saver( config, "KDE Control Module Restrictions" );
3380  TQStringList result;
3381  for(TQStringList::ConstIterator it = menuIds.begin();
3382  it != menuIds.end(); ++it)
3383  {
3384  if (config->readBoolEntry(*it, true))
3385  result.append(*it);
3386  }
3387  return result;
3388 }
3389 
3390 void KApplication::initUrlActionRestrictions()
3391 {
3392  d->urlActionRestrictions.setAutoDelete(true);
3393  d->urlActionRestrictions.clear();
3394  d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
3395  ("open", TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, true));
3396  d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
3397  ("list", TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, true));
3398 // TEST:
3399 // d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
3400 // ("list", TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, false));
3401 // d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
3402 // ("list", TQString::null, TQString::null, TQString::null, "file", TQString::null, TQDir::homeDirPath(), true));
3403  d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
3404  ("link", TQString::null, TQString::null, TQString::null, ":internet", TQString::null, TQString::null, true));
3405  d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
3406  ("redirect", TQString::null, TQString::null, TQString::null, ":internet", TQString::null, TQString::null, true));
3407 
3408  // We allow redirections to file: but not from internet protocols, redirecting to file:
3409  // is very popular among io-slaves and we don't want to break them
3410  d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
3411  ("redirect", TQString::null, TQString::null, TQString::null, "file", TQString::null, TQString::null, true));
3412  d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
3413  ("redirect", ":internet", TQString::null, TQString::null, "file", TQString::null, TQString::null, false));
3414 
3415  // local protocols may redirect everywhere
3416  d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
3417  ("redirect", ":local", TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, true));
3418 
3419  // Anyone may redirect to about:
3420  d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
3421  ("redirect", TQString::null, TQString::null, TQString::null, "about", TQString::null, TQString::null, true));
3422 
3423  // Anyone may redirect to itself, cq. within it's own group
3424  d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
3425  ("redirect", TQString::null, TQString::null, TQString::null, "=", TQString::null, TQString::null, true));
3426 
3427  KConfig *config = KGlobal::config();
3428  KConfigGroupSaver saver( config, "KDE URL Restrictions" );
3429  int count = config->readNumEntry("rule_count");
3430  TQString keyFormat = TQString("rule_%1");
3431  for(int i = 1; i <= count; i++)
3432  {
3433  TQString key = keyFormat.arg(i);
3434  TQStringList rule = config->readListEntry(key);
3435  if (rule.count() != 8)
3436  continue;
3437  TQString action = rule[0];
3438  TQString refProt = rule[1];
3439  TQString refHost = rule[2];
3440  TQString refPath = rule[3];
3441  TQString urlProt = rule[4];
3442  TQString urlHost = rule[5];
3443  TQString urlPath = rule[6];
3444  TQString strEnabled = rule[7].lower();
3445 
3446  bool bEnabled = (strEnabled == "true");
3447 
3448  if (refPath.startsWith("$HOME"))
3449  refPath.replace(0, 5, TQDir::homeDirPath());
3450  else if (refPath.startsWith("~"))
3451  refPath.replace(0, 1, TQDir::homeDirPath());
3452  if (urlPath.startsWith("$HOME"))
3453  urlPath.replace(0, 5, TQDir::homeDirPath());
3454  else if (urlPath.startsWith("~"))
3455  urlPath.replace(0, 1, TQDir::homeDirPath());
3456 
3457  if (refPath.startsWith("$TMP"))
3458  refPath.replace(0, 4, KGlobal::dirs()->saveLocation("tmp"));
3459  if (urlPath.startsWith("$TMP"))
3460  urlPath.replace(0, 4, KGlobal::dirs()->saveLocation("tmp"));
3461 
3462  d->urlActionRestrictions.append(new KApplicationPrivate::URLActionRule
3463  ( action, refProt, refHost, refPath, urlProt, urlHost, urlPath, bEnabled));
3464  }
3465 }
3466 
3467 void KApplication::allowURLAction(const TQString &action, const KURL &_baseURL, const KURL &_destURL)
3468 {
3469  if (authorizeURLAction(action, _baseURL, _destURL))
3470  return;
3471 
3472  d->urlActionRestrictions.append(new KApplicationPrivate::URLActionRule
3473  ( action, _baseURL.protocol(), _baseURL.host(), _baseURL.path(-1),
3474  _destURL.protocol(), _destURL.host(), _destURL.path(-1), true));
3475 }
3476 
3477 bool KApplication::authorizeURLAction(const TQString &action, const KURL &_baseURL, const KURL &_destURL)
3478 {
3479  if (_destURL.isEmpty())
3480  return true;
3481 
3482  bool result = false;
3483  if (d->urlActionRestrictions.isEmpty())
3484  initUrlActionRestrictions();
3485 
3486  KURL baseURL(_baseURL);
3487  baseURL.setPath(TQDir::cleanDirPath(baseURL.path()));
3488  TQString baseClass = KProtocolInfo::protocolClass(baseURL.protocol());
3489  KURL destURL(_destURL);
3490  destURL.setPath(TQDir::cleanDirPath(destURL.path()));
3491  TQString destClass = KProtocolInfo::protocolClass(destURL.protocol());
3492 
3493  for(KApplicationPrivate::URLActionRule *rule = d->urlActionRestrictions.first();
3494  rule; rule = d->urlActionRestrictions.next())
3495  {
3496  if ((result != rule->permission) && // No need to check if it doesn't make a difference
3497  (action == rule->action) &&
3498  rule->baseMatch(baseURL, baseClass) &&
3499  rule->destMatch(destURL, destClass, baseURL, baseClass))
3500  {
3501  result = rule->permission;
3502  }
3503  }
3504  return result;
3505 }
3506 
3507 
3508 uint KApplication::keyboardModifiers()
3509 {
3510 #ifdef Q_WS_X11
3511  Window root;
3512  Window child;
3513  int root_x, root_y, win_x, win_y;
3514  uint keybstate;
3515  XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child,
3516  &root_x, &root_y, &win_x, &win_y, &keybstate );
3517  return keybstate & 0x00ff;
3518 #elif defined W_WS_MACX
3519  return GetCurrentEventKeyModifiers() & 0x00ff;
3520 #else
3521  //TODO for win32
3522  return 0;
3523 #endif
3524 }
3525 
3526 uint KApplication::mouseState()
3527 {
3528  uint mousestate;
3529 #ifdef Q_WS_X11
3530  Window root;
3531  Window child;
3532  int root_x, root_y, win_x, win_y;
3533  XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child,
3534  &root_x, &root_y, &win_x, &win_y, &mousestate );
3535 #elif defined(Q_WS_WIN)
3536  const bool mousebtn_swapped = GetSystemMetrics(SM_SWAPBUTTON);
3537  if (GetAsyncKeyState(VK_LBUTTON))
3538  mousestate |= (mousebtn_swapped ? Button3Mask : Button1Mask);
3539  if (GetAsyncKeyState(VK_MBUTTON))
3540  mousestate |= Button2Mask;
3541  if (GetAsyncKeyState(VK_RBUTTON))
3542  mousestate |= (mousebtn_swapped ? Button1Mask : Button3Mask);
3543 #elif defined(Q_WS_MACX)
3544  mousestate = GetCurrentEventButtonState();
3545 #else
3546  //TODO: other platforms
3547 #endif
3548  return mousestate & 0xff00;
3549 }
3550 
3551 TQ_ButtonState KApplication::keyboardMouseState()
3552 {
3553  int ret = 0;
3554 #ifdef Q_WS_X11
3555  Window root;
3556  Window child;
3557  int root_x, root_y, win_x, win_y;
3558  uint state;
3559  XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child,
3560  &root_x, &root_y, &win_x, &win_y, &state );
3561  // transform the same way like Qt's qt_x11_translateButtonState()
3562  if( state & Button1Mask )
3563  ret |= TQ_LeftButton;
3564  if( state & Button2Mask )
3565  ret |= TQ_MidButton;
3566  if( state & Button3Mask )
3567  ret |= TQ_RightButton;
3568  if( state & ShiftMask )
3569  ret |= TQ_ShiftButton;
3570  if( state & ControlMask )
3571  ret |= TQ_ControlButton;
3572  if( state & KKeyNative::modX( KKey::ALT ))
3573  ret |= TQ_AltButton;
3574  if( state & KKeyNative::modX( KKey::WIN ))
3575  ret |= TQ_MetaButton;
3576 #elif defined(Q_WS_WIN)
3577  const bool mousebtn_swapped = GetSystemMetrics(SM_SWAPBUTTON);
3578  if (GetAsyncKeyState(VK_LBUTTON))
3579  ret |= (mousebtn_swapped ? RightButton : LeftButton);
3580  if (GetAsyncKeyState(VK_MBUTTON))
3581  ret |= TQ_MidButton;
3582  if (GetAsyncKeyState(VK_RBUTTON))
3583  ret |= (mousebtn_swapped ? TQ_LeftButton : TQ_RightButton);
3584  if (GetAsyncKeyState(VK_SHIFT))
3585  ret |= TQ_ShiftButton;
3586  if (GetAsyncKeyState(VK_CONTROL))
3587  ret |= TQ_ControlButton;
3588  if (GetAsyncKeyState(VK_MENU))
3589  ret |= TQ_AltButton;
3590  if (GetAsyncKeyState(VK_LWIN) || GetAsyncKeyState(VK_RWIN))
3591  ret |= TQ_MetaButton;
3592 #else
3593  //TODO: other platforms
3594 #endif
3595  return static_cast< ButtonState >( ret );
3596 }
3597 
3598 void KApplication::installSigpipeHandler()
3599 {
3600 #ifdef Q_OS_UNIX
3601  struct sigaction act;
3602  act.sa_handler = SIG_IGN;
3603  sigemptyset( &act.sa_mask );
3604  act.sa_flags = 0;
3605  sigaction( SIGPIPE, &act, 0 );
3606 #endif
3607 }
3608 
3609 void KApplication::sigpipeHandler(int)
3610 {
3611  int saved_errno = errno;
3612  // Using kdDebug from a signal handler is not a good idea.
3613 #ifndef NDEBUG
3614  char msg[1000];
3615  sprintf(msg, "*** SIGPIPE *** (ignored, pid = %ld)\n", (long) getpid());
3616  if (write(2, msg, strlen(msg)) < 0) {
3617  // ERROR
3618  }
3619 #endif
3620 
3621  // Do nothing.
3622  errno = saved_errno;
3623 }
3624 
3625 bool KApplication::guiEnabled()
3626 {
3627  return kapp && kapp->d->guiEnabled;
3628 }
3629 
3630 void KApplication::virtual_hook( int id, void* data )
3631 { KInstance::virtual_hook( id, data ); }
3632 
3633 void KSessionManaged::virtual_hook( int, void* )
3634 { /*BASE::virtual_hook( id, data );*/ }
3635 
3636 #include "kapplication.moc"

kdecore

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

kdecore

Skip menu "kdecore"
  • 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 kdecore 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. |