00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024
00025 #undef QT_NO_TRANSLATION
00026 #include <qtranslator.h>
00027 #define QT_NO_TRANSLATION
00028 #include <qdir.h>
00029 #include <qptrcollection.h>
00030 #include <qwidgetlist.h>
00031 #include <qstrlist.h>
00032 #include <qfile.h>
00033 #include <qmessagebox.h>
00034 #include <qtextstream.h>
00035 #include <qregexp.h>
00036 #include <qlineedit.h>
00037 #include <qtextedit.h>
00038 #include <qsessionmanager.h>
00039 #include <qptrlist.h>
00040 #include <qtimer.h>
00041 #include <qstylesheet.h>
00042 #include <qpixmapcache.h>
00043 #include <qtooltip.h>
00044 #include <qstylefactory.h>
00045 #include <qmetaobject.h>
00046 #ifndef QT_NO_SQL
00047 #include <qsqlpropertymap.h>
00048 #endif
00049
00050 #undef QT_NO_TRANSLATION
00051 #include "kapplication.h"
00052 #define QT_NO_TRANSLATION
00053 #include <kglobal.h>
00054 #include <kstandarddirs.h>
00055 #include <kdebug.h>
00056 #include <klocale.h>
00057 #include <kstyle.h>
00058 #include <kiconloader.h>
00059 #include <kclipboard.h>
00060 #include <kconfig.h>
00061 #include <ksimpleconfig.h>
00062 #include <kcmdlineargs.h>
00063 #include <kaboutdata.h>
00064 #include <kglobalsettings.h>
00065 #include <kcrash.h>
00066 #include <kdatastream.h>
00067 #include <klibloader.h>
00068 #include <kmimesourcefactory.h>
00069 #include <kstdaccel.h>
00070 #include <kaccel.h>
00071 #include "kcheckaccelerators.h"
00072 #include <qptrdict.h>
00073 #include <kmacroexpander.h>
00074 #include <kshell.h>
00075 #include <kprotocolinfo.h>
00076
00077 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00078 #include <kstartupinfo.h>
00079 #endif
00080
00081 #include <dcopclient.h>
00082 #include <dcopref.h>
00083
00084 #include <sys/types.h>
00085 #ifdef HAVE_SYS_STAT_H
00086 #include <sys/stat.h>
00087 #endif
00088 #include <sys/wait.h>
00089
00090 #include "kwin.h"
00091
00092 #include <fcntl.h>
00093 #include <stdlib.h>
00094 #include <signal.h>
00095 #include <unistd.h>
00096 #include <time.h>
00097 #include <sys/time.h>
00098 #include <errno.h>
00099 #include <string.h>
00100 #include <netdb.h>
00101 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00102
00103 #include <netwm.h>
00104 #endif
00105
00106 #include "kprocctrl.h"
00107
00108 #ifdef HAVE_PATHS_H
00109 #include <paths.h>
00110 #endif
00111
00112
00113 #ifdef Q_WS_X11
00114 #include <X11/Xlib.h>
00115 #include <X11/Xutil.h>
00116 #include <X11/Xatom.h>
00117 #include <X11/SM/SMlib.h>
00118 #include <fixx11h.h>
00119 #endif
00120 #include <KDE-ICE/ICElib.h>
00121
00122 #ifdef Q_WS_X11
00123 #define DISPLAY "DISPLAY"
00124 #elif defined(Q_WS_QWS)
00125 #define DISPLAY "QWS_DISPLAY"
00126 #endif
00127
00128 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00129 #include <kipc.h>
00130 #endif
00131
00132 #include "kappdcopiface.h"
00133
00134 bool kde_have_kipc = true;
00135 bool kde_kiosk_exception = false;
00136 bool kde_kiosk_admin = false;
00137
00138 KApplication* KApplication::KApp = 0L;
00139 bool KApplication::loadedByKdeinit = false;
00140 DCOPClient *KApplication::s_DCOPClient = 0L;
00141 bool KApplication::s_dcopClientNeedsPostInit = false;
00142
00143 static Atom atom_DesktopWindow;
00144 static Atom atom_NetSupported;
00145 #if KDE_IS_VERSION( 3, 2, 91 )
00146 #warning Obsolete, remove.
00147
00148 #endif
00149 static Atom atom_KdeNetUserTime;
00150 static Atom kde_net_wm_user_time = 0;
00151 #if KDE_IS_VERSION( 3, 2, 91 )
00152 #warning This should be in Qt already, check.
00153
00154 #endif
00155 Time qt_x_user_time = CurrentTime;
00156 extern Time qt_x_time;
00157 static Atom kde_xdnd_drop;
00158
00159
00160
00161 bool qt_qclipboard_bailout_hack = false;
00162
00163 template class QPtrList<KSessionManaged>;
00164
00165 #ifdef Q_WS_X11
00166 extern "C" {
00167 static int kde_xio_errhandler( Display * dpy )
00168 {
00169 return kapp->xioErrhandler( dpy );
00170 }
00171
00172 static int kde_x_errhandler( Display *dpy, XErrorEvent *err )
00173 {
00174 return kapp->xErrhandler( dpy, err );
00175 }
00176
00177 }
00178 #endif
00179
00180 extern "C" {
00181 static void kde_ice_ioerrorhandler( IceConn conn )
00182 {
00183 if(kapp)
00184 kapp->iceIOErrorHandler( conn );
00185
00186 }
00187 }
00188
00189
00190
00191
00192 class KApplicationPrivate
00193 {
00194 public:
00195 KApplicationPrivate()
00196 : actionRestrictions( false ),
00197 refCount( 1 ),
00198 oldIceIOErrorHandler( 0 ),
00199 checkAccelerators( 0 ),
00200 overrideStyle( QString::null ),
00201 startup_id( "0" ),
00202 app_started_timer( NULL ),
00203 m_KAppDCOPInterface( 0L ),
00204 session_save( false ),
00205 oldXErrorHandler( NULL ),
00206 oldXIOErrorHandler( NULL )
00207 {
00208 }
00209
00210 ~KApplicationPrivate()
00211 {}
00212
00213
00214 bool actionRestrictions : 1;
00215 bool guiEnabled : 1;
00222 int refCount;
00223 IceIOErrorHandler oldIceIOErrorHandler;
00224 KCheckAccelerators* checkAccelerators;
00225 QString overrideStyle;
00226 QString geometry_arg;
00227 QCString startup_id;
00228 QTimer* app_started_timer;
00229 KAppDCOPInterface *m_KAppDCOPInterface;
00230 bool session_save;
00231 int (*oldXErrorHandler)(Display*,XErrorEvent*);
00232 int (*oldXIOErrorHandler)(Display*);
00233
00234 class URLActionRule
00235 {
00236 public:
00237 #define checkExactMatch(s, b) \
00238 if (s.isEmpty()) b = true; \
00239 else if (s[s.length()-1] == '!') \
00240 { b = false; s.truncate(s.length()-1); } \
00241 else b = true;
00242 #define checkStartWildCard(s, b) \
00243 if (s.isEmpty()) b = true; \
00244 else if (s[0] == '*') \
00245 { b = true; s = s.mid(1); } \
00246 else b = false;
00247 #define checkEqual(s, b) \
00248 b = (s == "=");
00249
00250 URLActionRule(const QString &act,
00251 const QString &bProt, const QString &bHost, const QString &bPath,
00252 const QString &dProt, const QString &dHost, const QString &dPath,
00253 bool perm)
00254 : action(act),
00255 baseProt(bProt), baseHost(bHost), basePath(bPath),
00256 destProt(dProt), destHost(dHost), destPath(dPath),
00257 permission(perm)
00258 {
00259 checkExactMatch(baseProt, baseProtWildCard);
00260 checkStartWildCard(baseHost, baseHostWildCard);
00261 checkExactMatch(basePath, basePathWildCard);
00262 checkExactMatch(destProt, destProtWildCard);
00263 checkStartWildCard(destHost, destHostWildCard);
00264 checkExactMatch(destPath, destPathWildCard);
00265 checkEqual(destProt, destProtEqual);
00266 checkEqual(destHost, destHostEqual);
00267 }
00268
00269 bool baseMatch(const KURL &url, const QString &protClass)
00270 {
00271 if (baseProtWildCard)
00272 {
00273 if ( !baseProt.isEmpty() && !url.protocol().startsWith(baseProt) &&
00274 (protClass.isEmpty() || (protClass != baseProt)) )
00275 return false;
00276 }
00277 else
00278 {
00279 if ( (url.protocol() != baseProt) &&
00280 (protClass.isEmpty() || (protClass != baseProt)) )
00281 return false;
00282 }
00283 if (baseHostWildCard)
00284 {
00285 if (!baseHost.isEmpty() && !url.host().endsWith(baseHost))
00286 return false;
00287 }
00288 else
00289 {
00290 if (url.host() != baseHost)
00291 return false;
00292 }
00293 if (basePathWildCard)
00294 {
00295 if (!basePath.isEmpty() && !url.path().startsWith(basePath))
00296 return false;
00297 }
00298 else
00299 {
00300 if (url.path() != basePath)
00301 return false;
00302 }
00303 return true;
00304 }
00305
00306 bool destMatch(const KURL &url, const QString &protClass, const KURL &base, const QString &baseClass)
00307 {
00308 if (destProtEqual)
00309 {
00310 if ( (url.protocol() != base.protocol()) &&
00311 (protClass.isEmpty() || baseClass.isEmpty() || protClass != baseClass) )
00312 return false;
00313 }
00314 else if (destProtWildCard)
00315 {
00316 if ( !destProt.isEmpty() && !url.protocol().startsWith(destProt) &&
00317 (protClass.isEmpty() || (protClass != destProt)) )
00318 return false;
00319 }
00320 else
00321 {
00322 if ( (url.protocol() != destProt) &&
00323 (protClass.isEmpty() || (protClass != destProt)) )
00324 return false;
00325 }
00326 if (destHostWildCard)
00327 {
00328 if (!destHost.isEmpty() && !url.host().endsWith(destHost))
00329 return false;
00330 }
00331 else if (destHostEqual)
00332 {
00333 if (url.host() != base.host())
00334 return false;
00335 }
00336 else
00337 {
00338 if (url.host() != destHost)
00339 return false;
00340 }
00341 if (destPathWildCard)
00342 {
00343 if (!destPath.isEmpty() && !url.path().startsWith(destPath))
00344 return false;
00345 }
00346 else
00347 {
00348 if (url.path() != destPath)
00349 return false;
00350 }
00351 return true;
00352 }
00353
00354 QString action;
00355 QString baseProt;
00356 QString baseHost;
00357 QString basePath;
00358 QString destProt;
00359 QString destHost;
00360 QString destPath;
00361 bool baseProtWildCard : 1;
00362 bool baseHostWildCard : 1;
00363 bool basePathWildCard : 1;
00364 bool destProtWildCard : 1;
00365 bool destHostWildCard : 1;
00366 bool destPathWildCard : 1;
00367 bool destProtEqual : 1;
00368 bool destHostEqual : 1;
00369 bool permission;
00370 };
00371 QPtrList<URLActionRule> urlActionRestrictions;
00372
00373 QString sessionKey;
00374 QString pSessionConfigFile;
00375 };
00376
00377
00378 static QPtrList<QWidget>*x11Filter = 0;
00379 static bool autoDcopRegistration = true;
00380
00381 void KApplication::installX11EventFilter( QWidget* filter )
00382 {
00383 if ( !filter )
00384 return;
00385 if (!x11Filter)
00386 x11Filter = new QPtrList<QWidget>;
00387 connect ( filter, SIGNAL( destroyed() ), this, SLOT( x11FilterDestroyed() ) );
00388 x11Filter->append( filter );
00389 }
00390
00391 void KApplication::x11FilterDestroyed()
00392 {
00393 removeX11EventFilter( static_cast< const QWidget* >( sender()));
00394 }
00395
00396 void KApplication::removeX11EventFilter( const QWidget* filter )
00397 {
00398 if ( !x11Filter || !filter )
00399 return;
00400 x11Filter->removeRef( filter );
00401 if ( x11Filter->isEmpty() ) {
00402 delete x11Filter;
00403 x11Filter = 0;
00404 }
00405 }
00406
00407
00408
00409
00410
00411 extern bool kde_g_bKillAccelOverride;
00412
00413 bool KApplication::notify(QObject *receiver, QEvent *event)
00414 {
00415 QEvent::Type t = event->type();
00416 if (kde_g_bKillAccelOverride)
00417 {
00418 kde_g_bKillAccelOverride = false;
00419
00420 if (t == QEvent::AccelOverride)
00421 {
00422 static_cast<QKeyEvent *>(event)->accept();
00423 return true;
00424 }
00425 else
00426 kdWarning(125) << "kde_g_bKillAccelOverride set, but received an event other than AccelOverride." << endl;
00427 }
00428
00429 if ((t == QEvent::AccelOverride) || (t == QEvent::KeyPress))
00430 {
00431 static const KShortcut& _selectAll = KStdAccel::selectAll();
00432 if (receiver && receiver->inherits("QLineEdit"))
00433 {
00434 QLineEdit *edit = static_cast<QLineEdit *>(receiver);
00435
00436 QKeyEvent *kevent = static_cast<QKeyEvent *>(event);
00437 KKey key(kevent);
00438 if (_selectAll.contains(key))
00439 {
00440 if (t == QEvent::KeyPress)
00441 {
00442 edit->selectAll();
00443 return true;
00444 }
00445 else
00446 {
00447 kevent->accept();
00448 }
00449 }
00450
00451 if (key == KKey(Qt::CTRL + Qt::Key_U))
00452 {
00453 if (t == QEvent::KeyPress)
00454 {
00455 if (!edit->isReadOnly())
00456 {
00457 QString t(edit->text());
00458 t = t.mid(edit->cursorPosition());
00459 edit->validateAndSet(t, 0, 0, 0);
00460 }
00461 return true;
00462 }
00463 else
00464 {
00465 kevent->accept();
00466 }
00467
00468 }
00469 }
00470 if (receiver && receiver->inherits("QTextEdit"))
00471 {
00472 QTextEdit *medit = static_cast<QTextEdit *>(receiver);
00473
00474 QKeyEvent *kevent = static_cast<QKeyEvent *>(event);
00475 if (_selectAll.contains(KKey(kevent)))
00476 {
00477 if (t == QEvent::KeyPress)
00478 {
00479 medit->selectAll();
00480 return true;
00481 }
00482 else
00483 {
00484 kevent->accept();
00485 }
00486 }
00487 }
00488 }
00489 if( event->type() == QEvent::Show && receiver->isWidgetType())
00490 {
00491 QWidget* w = static_cast< QWidget* >( receiver );
00492 if( w->isTopLevel() && !startupId().isEmpty())
00493 KStartupInfo::setWindowStartupId( w->winId(), startupId());
00494 if( w->isTopLevel() && qt_x_user_time != CurrentTime )
00495 XChangeProperty( qt_xdisplay(), w->winId(), kde_net_wm_user_time, XA_CARDINAL,
00496 32, PropModeReplace, (unsigned char*)&qt_x_user_time, 1 );
00497 }
00498 if( event->type() == QEvent::Show && receiver->isWidgetType())
00499 {
00500 QWidget* w = static_cast< QWidget* >( receiver );
00501 if( w->isTopLevel() && !w->testWFlags( WX11BypassWM ) && !w->isPopup() && !event->spontaneous())
00502 {
00503 if( d->app_started_timer == NULL )
00504 {
00505 d->app_started_timer = new QTimer( this );
00506 connect( d->app_started_timer, SIGNAL( timeout()), SLOT( checkAppStartedSlot()));
00507 }
00508 if( !d->app_started_timer->isActive())
00509 d->app_started_timer->start( 0, true );
00510 }
00511 }
00512 return QApplication::notify(receiver, event);
00513 }
00514
00515 void KApplication::checkAppStartedSlot()
00516 {
00517 KStartupInfo::handleAutoAppStartedSending();
00518 }
00519
00520
00521 static QPtrList<KSessionManaged>* sessionClients()
00522 {
00523 static QPtrList<KSessionManaged>* session_clients = 0L;
00524 if ( !session_clients )
00525 session_clients = new QPtrList<KSessionManaged>;
00526 return session_clients;
00527 }
00528
00529
00530
00531
00532
00533
00534 QString KApplication::sessionConfigName() const
00535 {
00536 #if QT_VERSION < 0x030100
00537 return QString("session/%1_%2_%3").arg(name()).arg(sessionId()).arg(d->sessionKey);
00538 #else
00539 QString sessKey = sessionKey();
00540 if ( sessKey.isEmpty() && !d->sessionKey.isEmpty() )
00541 sessKey = d->sessionKey;
00542 return QString("session/%1_%2_%3").arg(name()).arg(sessionId()).arg(sessKey);
00543 #endif
00544 }
00545
00546 #ifndef Q_WS_QWS
00547 static SmcConn mySmcConnection = 0;
00548 static SmcConn tmpSmcConnection = 0;
00549 #else
00550
00551
00552 #endif
00553 static QTime* smModificationTime = 0;
00554
00555 KApplication::KApplication( int& argc, char** argv, const QCString& rAppName,
00556 bool allowStyles, bool GUIenabled ) :
00557 QApplication( argc, argv, GUIenabled ), KInstance(rAppName),
00558 #ifdef Q_WS_X11
00559 display(0L),
00560 #endif
00561 d (new KApplicationPrivate())
00562 {
00563 read_app_startup_id();
00564 if (!GUIenabled)
00565 allowStyles = false;
00566 useStyles = allowStyles;
00567 Q_ASSERT (!rAppName.isEmpty());
00568 setName(rAppName);
00569
00570 installSigpipeHandler();
00571 KCmdLineArgs::initIgnore(argc, argv, rAppName.data());
00572 parseCommandLine( );
00573 init(GUIenabled);
00574 d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
00575 }
00576
00577 KApplication::KApplication( bool allowStyles, bool GUIenabled ) :
00578 QApplication( *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(),
00579 GUIenabled ),
00580 KInstance( KCmdLineArgs::about),
00581 #ifdef Q_WS_X11
00582 display(0L),
00583 #endif
00584 d (new KApplicationPrivate)
00585 {
00586 read_app_startup_id();
00587 if (!GUIenabled)
00588 allowStyles = false;
00589 useStyles = allowStyles;
00590 setName( instanceName() );
00591
00592 installSigpipeHandler();
00593 parseCommandLine( );
00594 init(GUIenabled);
00595 d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
00596 }
00597
00598 KApplication::KApplication( bool allowStyles, bool GUIenabled, KInstance* _instance ) :
00599 QApplication( *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(),
00600 GUIenabled ),
00601 KInstance( _instance ),
00602 #ifdef Q_WS_X11
00603 display(0L),
00604 #endif
00605 d (new KApplicationPrivate)
00606 {
00607 read_app_startup_id();
00608 if (!GUIenabled)
00609 allowStyles = false;
00610 useStyles = allowStyles;
00611 setName( instanceName() );
00612
00613 installSigpipeHandler();
00614 parseCommandLine( );
00615 init(GUIenabled);
00616 d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
00617 }
00618
00619 #ifdef Q_WS_X11
00620 KApplication::KApplication(Display *display, int& argc, char** argv, const QCString& rAppName,
00621 bool allowStyles, bool GUIenabled ) :
00622 QApplication( display ), KInstance(rAppName),
00623 display(0L),
00624 d (new KApplicationPrivate())
00625 {
00626 read_app_startup_id();
00627 if (!GUIenabled)
00628 allowStyles = false;
00629 useStyles = allowStyles;
00630
00631 Q_ASSERT (!rAppName.isEmpty());
00632 setName(rAppName);
00633
00634 installSigpipeHandler();
00635 KCmdLineArgs::initIgnore(argc, argv, rAppName.data());
00636 parseCommandLine( );
00637 init(GUIenabled);
00638 d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
00639 }
00640 #endif
00641
00642 int KApplication::xioErrhandler( Display* dpy )
00643 {
00644 if(kapp)
00645 {
00646 emit shutDown();
00647 d->oldXIOErrorHandler( dpy );
00648 }
00649 exit( 1 );
00650 return 0;
00651 }
00652
00653 int KApplication::xErrhandler( Display* dpy, void* err_ )
00654 {
00655 XErrorEvent* err = static_cast< XErrorEvent* >( err_ );
00656 if(kapp)
00657 {
00658
00659 d->oldXErrorHandler( dpy, err );
00660 }
00661 return 0;
00662 }
00663
00664 void KApplication::iceIOErrorHandler( _IceConn *conn )
00665 {
00666 emit shutDown();
00667
00668 if ( d->oldIceIOErrorHandler != NULL )
00669 (*d->oldIceIOErrorHandler)( conn );
00670
00671 exit( 1 );
00672 }
00673
00674 class KDETranslator : public QTranslator
00675 {
00676 public:
00677 KDETranslator(QObject *parent) : QTranslator(parent, "kdetranslator") {}
00678 virtual QTranslatorMessage findMessage(const char* context,
00679 const char *sourceText,
00680 const char* message) const
00681 {
00682 QTranslatorMessage res;
00683 res.setTranslation(KGlobal::locale()->translateQt(context, sourceText, message));
00684 return res;
00685 }
00686 };
00687
00688 void KApplication::init(bool GUIenabled)
00689 {
00690 d->guiEnabled = GUIenabled;
00691 if ((getuid() != geteuid()) ||
00692 (getgid() != getegid()))
00693 {
00694 fprintf(stderr, "The KDE libraries are not designed to run with suid privileges.\n");
00695 ::exit(127);
00696 }
00697
00698 KProcessController::ref();
00699
00700 (void) KClipboardSynchronizer::self();
00701
00702 QApplication::setDesktopSettingsAware( false );
00703
00704 KApp = this;
00705
00706
00707 #ifdef Q_WS_X11 //FIXME(E)
00708
00709 if ( GUIenabled ) {
00710 const int max = 20;
00711 Atom* atoms[max];
00712 char* names[max];
00713 Atom atoms_return[max];
00714 int n = 0;
00715
00716 atoms[n] = &kipcCommAtom;
00717 names[n++] = (char *) "KIPC_COMM_ATOM";
00718
00719 atoms[n] = &atom_DesktopWindow;
00720 names[n++] = (char *) "KDE_DESKTOP_WINDOW";
00721
00722 atoms[n] = &atom_NetSupported;
00723 names[n++] = (char *) "_NET_SUPPORTED";
00724
00725 atoms[n] = &atom_KdeNetUserTime;
00726 names[n++] = (char *) "_KDE_NET_USER_TIME";
00727
00728 atoms[n] = &kde_net_wm_user_time;
00729 names[n++] = (char *) "_NET_WM_USER_TIME";
00730
00731 atoms[n] = &kde_xdnd_drop;
00732 names[n++] = (char *) "XdndDrop";
00733
00734 XInternAtoms( qt_xdisplay(), names, n, false, atoms_return );
00735
00736 for (int i = 0; i < n; i++ )
00737 *atoms[i] = atoms_return[i];
00738 }
00739 #endif
00740
00741 dcopAutoRegistration();
00742 dcopClientPostInit();
00743
00744 smw = 0;
00745
00746
00747 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00748 kipcEventMask = (1 << KIPC::StyleChanged) | (1 << KIPC::PaletteChanged) |
00749 (1 << KIPC::FontChanged) | (1 << KIPC::BackgroundChanged) |
00750 (1 << KIPC::ToolbarStyleChanged) | (1 << KIPC::SettingsChanged) |
00751 (1 << KIPC::ClipboardConfigChanged);
00752 #endif
00753
00754
00755 (void) KGlobal::locale();
00756
00757 KConfig* config = KGlobal::config();
00758 d->actionRestrictions = config->hasGroup("KDE Action Restrictions" ) && !kde_kiosk_exception;
00759
00760
00761
00762
00763 QCString readOnly = getenv("KDE_HOME_READONLY");
00764 if (readOnly.isEmpty() && (qstrcmp(name(), "kdialog") != 0))
00765 {
00766 KConfigGroupSaver saver(config, "KDE Action Restrictions");
00767 if (config->readBoolEntry("warn_unwritable_config",true))
00768 config->checkConfigFilesWritable(true);
00769 }
00770
00771 if (GUIenabled)
00772 {
00773 #ifdef Q_WS_X11
00774
00775 fcntl(ConnectionNumber(qt_xdisplay()), F_SETFD, FD_CLOEXEC);
00776
00777 d->oldXErrorHandler = XSetErrorHandler( kde_x_errhandler );
00778 d->oldXIOErrorHandler = XSetIOErrorHandler( kde_xio_errhandler );
00779 #endif
00780
00781 connect( this, SIGNAL( aboutToQuit() ), this, SIGNAL( shutDown() ) );
00782
00783 #ifdef Q_WS_X11 //FIXME(E)
00784 display = desktop()->x11Display();
00785 #endif
00786
00787 {
00788 QStringList plugins = KGlobal::dirs()->resourceDirs( "qtplugins" );
00789 QStringList::Iterator it = plugins.begin();
00790 while (it != plugins.end()) {
00791 addLibraryPath( *it );
00792 ++it;
00793 }
00794
00795 }
00796 kdisplaySetStyle();
00797 kdisplaySetFont();
00798
00799 propagateSettings(SETTINGS_QT);
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809 QMimeSourceFactory* oldDefaultFactory = QMimeSourceFactory::takeDefaultFactory();
00810 QMimeSourceFactory::setDefaultFactory( mimeSourceFactory() );
00811 if ( oldDefaultFactory ) {
00812 QMimeSourceFactory::addFactory( oldDefaultFactory );
00813 }
00814
00815 KConfigGroupSaver saver( config, "Development" );
00816 if( config->hasKey( "CheckAccelerators" ) || config->hasKey( "AutoCheckAccelerators" ))
00817 d->checkAccelerators = new KCheckAccelerators( this );
00818 }
00819
00820
00821
00822 bool rtl = reverseLayout();
00823 installTranslator(new KDETranslator(this));
00824 setReverseLayout( rtl );
00825 if (i18n( "_: Dear Translator! Translate this string to the string 'LTR' in "
00826 "left-to-right languages (as english) or to 'RTL' in right-to-left "
00827 "languages (such as Hebrew and Arabic) to get proper widget layout." ) == "RTL")
00828 setReverseLayout( !rtl );
00829
00830
00831 KGlobal::dirs()->addResourceType("appdata", KStandardDirs::kde_default("data")
00832 + QString::fromLatin1(name()) + '/');
00833 pSessionConfig = 0L;
00834 bSessionManagement = true;
00835
00836 #ifdef Q_WS_X11
00837
00838 if (GUIenabled && kde_have_kipc )
00839 {
00840 smw = new QWidget(0,0);
00841 long data = 1;
00842 XChangeProperty(qt_xdisplay(), smw->winId(),
00843 atom_DesktopWindow, atom_DesktopWindow,
00844 32, PropModeReplace, (unsigned char *)&data, 1);
00845 }
00846 #else
00847
00848 #endif
00849
00850 d->oldIceIOErrorHandler = IceSetIOErrorHandler( kde_ice_ioerrorhandler );
00851 }
00852
00853 static int my_system (const char *command) {
00854 int pid, status;
00855
00856 QApplication::flushX();
00857 pid = fork();
00858 if (pid == -1)
00859 return -1;
00860 if (pid == 0) {
00861 const char* shell = "/bin/sh";
00862 execl(shell, shell, "-c", command, (void *)0);
00863 ::exit(127);
00864 }
00865 do {
00866 if (waitpid(pid, &status, 0) == -1) {
00867 if (errno != EINTR)
00868 return -1;
00869 } else
00870 return status;
00871 } while(1);
00872 }
00873
00874
00875 DCOPClient *KApplication::dcopClient()
00876 {
00877 if (s_DCOPClient)
00878 return s_DCOPClient;
00879
00880 s_DCOPClient = new DCOPClient();
00881 KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
00882 if (args && args->isSet("dcopserver"))
00883 {
00884 s_DCOPClient->setServerAddress( args->getOption("dcopserver"));
00885 }
00886 if( kapp ) {
00887 connect(s_DCOPClient, SIGNAL(attachFailed(const QString &)),
00888 kapp, SLOT(dcopFailure(const QString &)));
00889 connect(s_DCOPClient, SIGNAL(blockUserInput(bool) ),
00890 kapp, SLOT(dcopBlockUserInput(bool)) );
00891 }
00892 else
00893 s_dcopClientNeedsPostInit = true;
00894
00895 DCOPClient::setMainClient( s_DCOPClient );
00896 return s_DCOPClient;
00897 }
00898
00899 void KApplication::dcopClientPostInit()
00900 {
00901 if( s_dcopClientNeedsPostInit )
00902 {
00903 s_dcopClientNeedsPostInit = false;
00904 connect(s_DCOPClient, SIGNAL(blockUserInput(bool) ),
00905 SLOT(dcopBlockUserInput(bool)) );
00906 s_DCOPClient->bindToApp();
00907 }
00908 }
00909
00910 void KApplication::dcopAutoRegistration()
00911 {
00912 if (autoDcopRegistration)
00913 {
00914 ( void ) dcopClient();
00915 if( dcopClient()->appId().isEmpty())
00916 dcopClient()->registerAs(name());
00917 }
00918 }
00919
00920 void KApplication::disableAutoDcopRegistration()
00921 {
00922 autoDcopRegistration = false;
00923 }
00924
00925 KConfig* KApplication::sessionConfig()
00926 {
00927 if (pSessionConfig)
00928 return pSessionConfig;
00929
00930
00931 pSessionConfig = new KConfig( sessionConfigName(), false, false);
00932 return pSessionConfig;
00933 }
00934
00935 void KApplication::ref()
00936 {
00937 d->refCount++;
00938
00939 }
00940
00941 void KApplication::deref()
00942 {
00943 d->refCount--;
00944
00945 if ( d->refCount <= 0 )
00946 quit();
00947 }
00948
00949 KSessionManaged::KSessionManaged()
00950 {
00951 sessionClients()->remove( this );
00952 sessionClients()->append( this );
00953 }
00954
00955 KSessionManaged::~KSessionManaged()
00956 {
00957 sessionClients()->remove( this );
00958 }
00959
00960 bool KSessionManaged::saveState(QSessionManager&)
00961 {
00962 return true;
00963 }
00964
00965 bool KSessionManaged::commitData(QSessionManager&)
00966 {
00967 return true;
00968 }
00969
00970
00971 void KApplication::disableSessionManagement() {
00972 bSessionManagement = false;
00973 }
00974
00975 void KApplication::enableSessionManagement() {
00976 bSessionManagement = true;
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986 if( mySmcConnection ) {
00987 SmcRequestSaveYourself( mySmcConnection, SmSaveLocal, False,
00988 SmInteractStyleAny,
00989 False, False );
00990
00991
00992 IceFlush(SmcGetIceConnection(mySmcConnection));
00993 }
00994 }
00995
00996
00997 bool KApplication::requestShutDown(
00998 ShutdownConfirm confirm, ShutdownType sdtype, ShutdownMode sdmode )
00999 {
01000 #ifdef Q_WS_X11
01001 QApplication::syncX();
01002
01003 if ( confirm == ShutdownConfirmYes ||
01004 sdtype != ShutdownTypeDefault ||
01005 sdmode != ShutdownModeDefault )
01006 {
01007 QByteArray data;
01008 QDataStream arg(data, IO_WriteOnly);
01009 arg << (int)confirm << (int)sdtype << (int)sdmode;
01010 return dcopClient()->send( "ksmserver", "ksmserver",
01011 "logout(int,int,int)", data );
01012 }
01013
01014 if ( mySmcConnection ) {
01015
01016 SmcRequestSaveYourself( mySmcConnection, SmSaveBoth, True,
01017 SmInteractStyleAny,
01018 confirm == ShutdownConfirmNo, True );
01019
01020
01021 IceFlush(SmcGetIceConnection(mySmcConnection));
01022 return true;
01023 }
01024
01025
01026
01027 propagateSessionManager();
01028 QCString smEnv = ::getenv("SESSION_MANAGER");
01029 if (smEnv.isEmpty())
01030 return false;
01031
01032 if (! tmpSmcConnection) {
01033 char cerror[256];
01034 char* myId = 0;
01035 char* prevId = 0;
01036 SmcCallbacks cb;
01037 tmpSmcConnection = SmcOpenConnection( 0, 0, 1, 0,
01038 0, &cb,
01039 prevId,
01040 &myId,
01041 255,
01042 cerror );
01043 ::free( myId );
01044 if (!tmpSmcConnection )
01045 return false;
01046 }
01047
01048 SmcRequestSaveYourself( tmpSmcConnection, SmSaveBoth, True,
01049 SmInteractStyleAny, False, True );
01050
01051
01052 IceFlush(SmcGetIceConnection(tmpSmcConnection));
01053 return true;
01054 #else
01055
01056 return false;
01057 #endif
01058 }
01059
01060 void KApplication::propagateSessionManager()
01061 {
01062 QCString fName = QFile::encodeName(locateLocal("socket", "KSMserver"));
01063 QCString display = ::getenv(DISPLAY);
01064
01065 display.replace(QRegExp("\\.[0-9]+$"), "");
01066 int i;
01067 while( (i = display.find(':')) >= 0)
01068 display[i] = '_';
01069
01070 fName += "_"+display;
01071 QCString smEnv = ::getenv("SESSION_MANAGER");
01072 bool check = smEnv.isEmpty();
01073 if ( !check && smModificationTime ) {
01074 QFileInfo info( fName );
01075 QTime current = info.lastModified().time();
01076 check = current > *smModificationTime;
01077 }
01078 if ( check ) {
01079 delete smModificationTime;
01080 QFile f( fName );
01081 if ( !f.open( IO_ReadOnly ) )
01082 return;
01083 QFileInfo info ( f );
01084 smModificationTime = new QTime( info.lastModified().time() );
01085 QTextStream t(&f);
01086 t.setEncoding( QTextStream::Latin1 );
01087 QString s = t.readLine();
01088 f.close();
01089 ::setenv( "SESSION_MANAGER", s.latin1(), true );
01090 }
01091 }
01092
01093 void KApplication::commitData( QSessionManager& sm )
01094 {
01095 d->session_save = true;
01096 bool canceled = false;
01097 for (KSessionManaged* it = sessionClients()->first();
01098 it && !canceled;
01099 it = sessionClients()->next() ) {
01100 canceled = !it->commitData( sm );
01101 }
01102 if ( canceled )
01103 sm.cancel();
01104
01105 if ( sm.allowsInteraction() ) {
01106 QWidgetList done;
01107 QWidgetList *list = QApplication::topLevelWidgets();
01108 bool canceled = false;
01109 QWidget* w = list->first();
01110 while ( !canceled && w ) {
01111 if ( !w->testWState( WState_ForceHide ) && !w->inherits("KMainWindow") ) {
01112 QCloseEvent e;
01113 sendEvent( w, &e );
01114 canceled = !e.isAccepted();
01115 if ( !canceled )
01116 done.append( w );
01117 delete list;
01118 list = QApplication::topLevelWidgets();
01119 w = list->first();
01120 } else {
01121 w = list->next();
01122 }
01123 while ( w && done.containsRef( w ) )
01124 w = list->next();
01125 }
01126 delete list;
01127 }
01128
01129
01130 if ( !bSessionManagement )
01131 sm.setRestartHint( QSessionManager::RestartNever );
01132 else
01133 sm.setRestartHint( QSessionManager::RestartIfRunning );
01134 d->session_save = false;
01135 }
01136
01137 void KApplication::saveState( QSessionManager& sm )
01138 {
01139 d->session_save = true;
01140 #ifndef Q_WS_QWS
01141 static bool firstTime = true;
01142 mySmcConnection = (SmcConn) sm.handle();
01143
01144 if ( !bSessionManagement ) {
01145 sm.setRestartHint( QSessionManager::RestartNever );
01146 d->session_save = false;
01147 return;
01148 }
01149 else
01150 sm.setRestartHint( QSessionManager::RestartIfRunning );
01151
01152 #if QT_VERSION < 0x030100
01153 {
01154
01155 timeval tv;
01156 gettimeofday( &tv, 0 );
01157 d->sessionKey = QString::number( tv.tv_sec ) + "_" + QString::number(tv.tv_usec);
01158 }
01159 #endif
01160
01161 if ( firstTime ) {
01162 firstTime = false;
01163 d->session_save = false;
01164 return;
01165 }
01166
01167
01168
01169
01170
01171
01172
01173 if ( pSessionConfig ) {
01174 delete pSessionConfig;
01175 pSessionConfig = 0;
01176 }
01177
01178
01179 QStringList restartCommand = sm.restartCommand();
01180 #if QT_VERSION < 0x030100
01181 restartCommand.clear();
01182 restartCommand << argv()[0] << "-session" << sm.sessionId() << "-smkey" << d->sessionKey;
01183 sm.setRestartCommand( restartCommand );
01184 #endif
01185
01186
01187 QCString multiHead = getenv("KDE_MULTIHEAD");
01188 if (multiHead.lower() == "true") {
01189
01190
01191
01192
01193
01194
01195 QCString displayname = getenv(DISPLAY);
01196 if (! displayname.isNull()) {
01197
01198
01199 restartCommand.append("-display");
01200 restartCommand.append(displayname);
01201 }
01202 sm.setRestartCommand( restartCommand );
01203 }
01204
01205
01206
01207 emit saveYourself();
01208 bool canceled = false;
01209 for (KSessionManaged* it = sessionClients()->first();
01210 it && !canceled;
01211 it = sessionClients()->next() ) {
01212 canceled = !it->saveState( sm );
01213 }
01214
01215
01216 if ( pSessionConfig ) {
01217 pSessionConfig->sync();
01218 QStringList discard;
01219 discard << "rm" << locateLocal("config", sessionConfigName());
01220 sm.setDiscardCommand( discard );
01221 } else {
01222 sm.setDiscardCommand( "" );
01223 }
01224
01225 if ( canceled )
01226 sm.cancel();
01227 #else
01228
01229 #endif
01230 d->session_save = false;
01231 }
01232
01233 bool KApplication::sessionSaving() const
01234 {
01235 return d->session_save;
01236 }
01237
01238 void KApplication::startKdeinit()
01239 {
01240
01241 QString srv = KStandardDirs::findExe(QString::fromLatin1("kdeinit"));
01242 if (srv.isEmpty())
01243 srv = KStandardDirs::findExe(QString::fromLatin1("kdeinit"), KDEDIR+QString::fromLatin1("/bin"));
01244 if (srv.isEmpty())
01245 return;
01246 if (kapp && (Tty != kapp->type()))
01247 setOverrideCursor( Qt::waitCursor );
01248 my_system(QFile::encodeName(srv)+" --suicide");
01249 if (kapp && (Tty != kapp->type()))
01250 restoreOverrideCursor();
01251 }
01252
01253 void KApplication::dcopFailure(const QString &msg)
01254 {
01255 static int failureCount = 0;
01256 failureCount++;
01257 if (failureCount == 1)
01258 {
01259 startKdeinit();
01260 return;
01261 }
01262 if (failureCount == 2)
01263 {
01264 QString msgStr(i18n("There was an error setting up inter-process\n"
01265 "communications for KDE. The message returned\n"
01266 "by the system was:\n\n"));
01267 msgStr += msg;
01268 msgStr += i18n("\n\nPlease check that the \"dcopserver\" program is running!");
01269
01270 if (Tty != kapp->type())
01271 {
01272 QMessageBox::critical
01273 (
01274 kapp->mainWidget(),
01275 i18n("DCOP communications error (%1)").arg(kapp->caption()),
01276 msgStr,
01277 i18n("OK")
01278 );
01279 }
01280 else
01281 {
01282 fprintf(stderr, "%s\n", msgStr.local8Bit().data());
01283 }
01284
01285 return;
01286 }
01287 }
01288
01289 static const KCmdLineOptions qt_options[] =
01290 {
01291
01292 #ifdef Q_WS_X11
01293 { "display <displayname>", I18N_NOOP("Use the X-server display 'displayname'."), 0},
01294 #else
01295 { "display <displayname>", I18N_NOOP("Use the QWS display 'displayname'."), 0},
01296 #endif
01297 { "session <sessionId>", I18N_NOOP("Restore the application for the given 'sessionId'."), 0},
01298 { "cmap", I18N_NOOP("Causes the application to install a private color\nmap on an 8-bit display."), 0},
01299 { "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 QApplication::ManyColor color\nspecification."), 0},
01300 { "nograb", I18N_NOOP("tells Qt to never grab the mouse or the keyboard."), 0},
01301 { "dograb", I18N_NOOP("running under a debugger can cause an implicit\n-nograb, use -dograb to override."), 0},
01302 { "sync", I18N_NOOP("switches to synchronous mode for debugging."), 0},
01303 { "fn", 0, 0},
01304 { "font <fontname>", I18N_NOOP("defines the application font."), 0},
01305 { "bg", 0, 0},
01306 { "background <color>", I18N_NOOP("sets the default background color and an\napplication palette (light and dark shades are\ncalculated)."), 0},
01307 { "fg", 0, 0},
01308 { "foreground <color>", I18N_NOOP("sets the default foreground color."), 0},
01309 { "btn", 0, 0},
01310 { "button <color>", I18N_NOOP("sets the default button color."), 0},
01311 { "name <name>", I18N_NOOP("sets the application name."), 0},
01312 { "title <title>", I18N_NOOP("sets the application title (caption)."), 0},
01313 #ifdef Q_WS_X11
01314 { "visual TrueColor", I18N_NOOP("forces the application to use a TrueColor visual on\nan 8-bit display."), 0},
01315 { "inputstyle <inputstyle>", I18N_NOOP("sets XIM (X Input Method) input style. Possible\nvalues are onthespot, overthespot, offthespot and\nroot."), 0 },
01316 { "im <XIM server>", I18N_NOOP("set XIM server."),0},
01317 { "noxim", I18N_NOOP("disable XIM."), 0 },
01318 #endif
01319 #ifdef Q_WS_QWS
01320 { "qws", I18N_NOOP("forces the application to run as QWS Server."), 0},
01321 #endif
01322 { "reverse", I18N_NOOP("mirrors the whole layout of widgets."), 0},
01323 KCmdLineLastOption
01324 };
01325
01326 static const KCmdLineOptions kde_options[] =
01327 {
01328 { "caption <caption>", I18N_NOOP("Use 'caption' as name in the titlebar."), 0},
01329 { "icon <icon>", I18N_NOOP("Use 'icon' as the application icon."), 0},
01330 { "miniicon <icon>", I18N_NOOP("Use 'icon' as the icon in the titlebar."), 0},
01331 { "config <filename>", I18N_NOOP("Use alternative configuration file."), 0},
01332 { "dcopserver <server>", I18N_NOOP("Use the DCOP Server specified by 'server'."), 0},
01333 { "nocrashhandler", I18N_NOOP("Disable crash handler, to get core dumps."), 0},
01334 { "waitforwm", I18N_NOOP("Waits for a WM_NET compatible windowmanager."), 0},
01335 { "style <style>", I18N_NOOP("sets the application GUI style."), 0},
01336 { "geometry <geometry>", I18N_NOOP("sets the client geometry of the main widget."), 0},
01337 #if QT_VERSION < 0x030100
01338 { "smkey <sessionKey>", I18N_NOOP("Define a 'sessionKey' for the session id. Only valid with -session"), 0},
01339 #else
01340 { "smkey <sessionKey>", 0, 0},
01341
01342
01343 #endif
01344 KCmdLineLastOption
01345 };
01346
01347 void
01348 KApplication::addCmdLineOptions()
01349 {
01350 KCmdLineArgs::addCmdLineOptions(qt_options, "Qt", "qt");
01351 KCmdLineArgs::addCmdLineOptions(kde_options, "KDE", "kde");
01352 }
01353
01354 void KApplication::parseCommandLine( )
01355 {
01356 KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
01357
01358 if ( !args ) return;
01359
01360 if (args->isSet("config"))
01361 {
01362 QString config = QString::fromLocal8Bit(args->getOption("config"));
01363 setConfigName(config);
01364 }
01365
01366 if (args->isSet("style"))
01367 {
01368
01369 QStringList styles = QStyleFactory::keys();
01370 QString reqStyle(args->getOption("style").lower());
01371
01372 for (QStringList::ConstIterator it = styles.begin(); it != styles.end(); ++it)
01373 if ((*it).lower() == reqStyle)
01374 {
01375 d->overrideStyle = *it;
01376 break;
01377 }
01378
01379 if (d->overrideStyle.isEmpty())
01380 fprintf(stderr, "%s", i18n("The style %1 was not found\n").arg(reqStyle).local8Bit().data());
01381 }
01382
01383 if (args->isSet("caption"))
01384 {
01385 aCaption = QString::fromLocal8Bit(args->getOption("caption"));
01386 }
01387
01388 if (args->isSet("miniicon"))
01389 {
01390 const char *tmp = args->getOption("miniicon");
01391 aMiniIconPixmap = SmallIcon(tmp);
01392 aMiniIconName = tmp;
01393 }
01394
01395 if (args->isSet("icon"))
01396 {
01397 const char *tmp = args->getOption("icon");
01398 aIconPixmap = DesktopIcon( tmp );
01399 aIconName = tmp;
01400 if (aMiniIconPixmap.isNull())
01401 {
01402 aMiniIconPixmap = SmallIcon( tmp );
01403 aMiniIconName = tmp;
01404 }
01405 }
01406
01407 bool nocrashhandler = (getenv("KDE_DEBUG") != NULL);
01408 if (!nocrashhandler && args->isSet("crashhandler"))
01409 {
01410
01411 KCrash::setCrashHandler(KCrash::defaultCrashHandler);
01412 KCrash::setEmergencySaveFunction(NULL);
01413
01414 KCrash::setApplicationName(QString(args->appName()));
01415 }
01416
01417 #ifdef Q_WS_X11
01418 if ( args->isSet( "waitforwm" ) ) {
01419 Atom type;
01420 (void) desktop();
01421 int format;
01422 unsigned long length, after;
01423 unsigned char *data;
01424 while ( XGetWindowProperty( qt_xdisplay(), qt_xrootwin(), atom_NetSupported,
01425 0, 1, false, AnyPropertyType, &type, &format,
01426 &length, &after, &data ) != Success || !length ) {
01427 if ( data )
01428 XFree( data );
01429 XEvent event;
01430 XWindowEvent( qt_xdisplay(), qt_xrootwin(), PropertyChangeMask, &event );
01431 }
01432 if ( data )
01433 XFree( data );
01434 }
01435 #else
01436
01437 #endif
01438
01439 if (args->isSet("geometry"))
01440 {
01441 d->geometry_arg = args->getOption("geometry");
01442 }
01443
01444 if (args->isSet("smkey"))
01445 {
01446 d->sessionKey = args->getOption("smkey");
01447 }
01448
01449 }
01450
01451 QString KApplication::geometryArgument() const
01452 {
01453 return d->geometry_arg;
01454 }
01455
01456 QPixmap KApplication::icon() const
01457 {
01458 if( aIconPixmap.isNull()) {
01459 KApplication *that = const_cast<KApplication *>(this);
01460 that->aIconPixmap = DesktopIcon( instanceName() );
01461 }
01462 return aIconPixmap;
01463 }
01464
01465 QString KApplication::iconName() const
01466 {
01467 return aIconName.isNull() ? (QString)instanceName() : aIconName;
01468 }
01469
01470 QPixmap KApplication::miniIcon() const
01471 {
01472 if (aMiniIconPixmap.isNull()) {
01473 KApplication *that = const_cast<KApplication *>(this);
01474 that->aMiniIconPixmap = SmallIcon( instanceName() );
01475 }
01476 return aMiniIconPixmap;
01477 }
01478
01479 QString KApplication::miniIconName() const
01480 {
01481 return aMiniIconName.isNull() ? (QString)instanceName() : aMiniIconName;
01482 }
01483
01484 extern void kDebugCleanup();
01485
01486 KApplication::~KApplication()
01487 {
01488 delete d->m_KAppDCOPInterface;
01489
01490
01491