00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #undef QT_NO_TRANSLATION
00022 #include "kapplication.h"
00023 #define QT_NO_TRANSLATION
00024
00025 #include <config.h>
00026
00027 #undef QT_NO_TRANSLATION
00028 #include <QtCore/QTranslator>
00029 #define QT_NO_TRANSLATION
00030 #include <QtCore/QDir>
00031 #include <QtCore/QFile>
00032 #include <QtGui/QSessionManager>
00033 #include <QtGui/QStyleFactory>
00034 #include <QtCore/QTimer>
00035 #include <QtGui/QWidget>
00036 #include <QtCore/QList>
00037 #include <QtDBus/QtDBus>
00038 #include <QtCore/QMetaType>
00039
00040 #include "kauthorized.h"
00041 #include "kaboutdata.h"
00042 #include "kcheckaccelerators.h"
00043 #include "kcrash.h"
00044 #include "kconfig.h"
00045 #include "kcmdlineargs.h"
00046 #include "kclipboard.h"
00047 #include "kglobalsettings.h"
00048 #include "kdebug.h"
00049 #include "kglobal.h"
00050 #include "kicon.h"
00051 #include "klocale.h"
00052 #include "ksessionmanager.h"
00053 #include "kstandarddirs.h"
00054 #include "kstandardshortcut.h"
00055 #include "ktoolinvocation.h"
00056 #include "kgesturemap.h"
00057 #include "kurl.h"
00058 #include "kmessage.h"
00059 #include "kmessageboxmessagehandler.h"
00060
00061 #if defined Q_WS_X11
00062 #include <QtGui/qx11info_x11.h>
00063 #include <kstartupinfo.h>
00064 #endif
00065
00066 #include <sys/types.h>
00067 #ifdef HAVE_SYS_STAT_H
00068 #include <sys/stat.h>
00069 #endif
00070 #include <sys/wait.h>
00071
00072 #ifndef Q_WS_WIN
00073 #include "kwindowsystem.h"
00074 #endif
00075
00076 #include <fcntl.h>
00077 #include <stdlib.h>
00078 #include <unistd.h>
00079 #if defined Q_WS_X11
00080
00081 #include <netwm.h>
00082 #endif
00083
00084 #ifdef HAVE_PATHS_H
00085 #include <paths.h>
00086 #endif
00087
00088 #ifdef Q_WS_X11
00089 #include <X11/Xlib.h>
00090 #include <X11/Xutil.h>
00091 #include <X11/Xatom.h>
00092 #include <X11/SM/SMlib.h>
00093 #include <fixx11h.h>
00094
00095 #include <QX11Info>
00096 #endif
00097
00098 #ifdef Q_WS_MACX
00099
00100 #undef Status
00101 #include <Carbon/Carbon.h>
00102 #include <QImage>
00103 #include <ksystemtrayicon.h>
00104 #include <kkernel_mac.h>
00105 #endif
00106
00107 #ifdef Q_OS_UNIX
00108 #include <signal.h>
00109 #endif
00110
00111 #include <QtGui/QActionEvent>
00112 #include <kcomponentdata.h>
00113
00114 KApplication* KApplication::KApp = 0L;
00115 bool KApplication::loadedByKdeinit = false;
00116
00117 #ifdef Q_WS_X11
00118 static Atom atom_DesktopWindow;
00119 static Atom atom_NetSupported;
00120 static Atom kde_xdnd_drop;
00121 static QByteArray* startup_id_tmp;
00122 #endif
00123
00124 template class QList<KSessionManager*>;
00125
00126 #ifdef Q_WS_X11
00127 extern "C" {
00128 static int kde_xio_errhandler( Display * dpy )
00129 {
00130 return kapp->xioErrhandler( dpy );
00131 }
00132
00133 static int kde_x_errhandler( Display *dpy, XErrorEvent *err )
00134 {
00135 return kapp->xErrhandler( dpy, err );
00136 }
00137
00138 }
00139 #endif
00140
00141 #ifdef Q_WS_WIN
00142 void KApplication_init_windows();
00143 #endif
00144
00145
00146
00147
00148 class KApplicationPrivate
00149 {
00150 public:
00151 KApplicationPrivate(KApplication* q, const QByteArray &cName)
00152 : q(q)
00153 , componentData(cName)
00154 , startup_id("0")
00155 , app_started_timer(0)
00156 , session_save(false)
00157 #ifdef Q_WS_X11
00158 , oldIceIOErrorHandler(0)
00159 , oldXErrorHandler(0)
00160 , oldXIOErrorHandler(0)
00161 #endif
00162 , pSessionConfig( 0 )
00163 , bSessionManagement( true )
00164 {
00165 }
00166
00167 KApplicationPrivate(KApplication* q, const KComponentData &cData)
00168 : q(q)
00169 , componentData(cData)
00170 , startup_id("0")
00171 , app_started_timer(0)
00172 , session_save(false)
00173 #ifdef Q_WS_X11
00174 , oldIceIOErrorHandler(0)
00175 , oldXErrorHandler(0)
00176 , oldXIOErrorHandler(0)
00177 #endif
00178 , pSessionConfig( 0 )
00179 , bSessionManagement( true )
00180 {
00181 }
00182
00183 KApplicationPrivate(KApplication *q)
00184 : q(q)
00185 , componentData(KCmdLineArgs::aboutData())
00186 , startup_id( "0" )
00187 , app_started_timer( 0 )
00188 , session_save( false )
00189 #ifdef Q_WS_X11
00190 , oldIceIOErrorHandler( 0 )
00191 , oldXErrorHandler( 0 )
00192 , oldXIOErrorHandler( 0 )
00193 #endif
00194 , pSessionConfig( 0 )
00195 , bSessionManagement( true )
00196 {
00197 }
00198
00199 ~KApplicationPrivate()
00200 {
00201 }
00202
00203 #ifndef KDE3_SUPPORT
00204 KConfig *config() { return KGlobal::config().data(); }
00205 #endif
00206
00207 void _k_x11FilterDestroyed();
00208 void _k_checkAppStartedSlot();
00209 void _k_slot_KToolInvocation_hook(QStringList&, QByteArray&);
00210
00211 QString sessionConfigName() const;
00212 void init(bool GUIenabled=true);
00213 void parseCommandLine( );
00214 static void preqapplicationhack();
00215 static void preread_app_startup_id();
00216 void read_app_startup_id();
00217
00218 KApplication *q;
00219 KComponentData componentData;
00220 QByteArray startup_id;
00221 QTimer* app_started_timer;
00222 bool session_save;
00223
00224 #ifdef Q_WS_X11
00225 IceIOErrorHandler oldIceIOErrorHandler;
00226 int (*oldXErrorHandler)(Display*,XErrorEvent*);
00227 int (*oldXIOErrorHandler)(Display*);
00228 #endif
00229
00230 QString sessionKey;
00231 QString pSessionConfigFile;
00232
00233 KConfig* pSessionConfig;
00234 bool bSessionManagement;
00235 };
00236
00237
00238 static QList<const QWidget*> *x11Filter = 0;
00239
00247 static void installSigpipeHandler()
00248 {
00249 #ifdef Q_OS_UNIX
00250 struct sigaction act;
00251 act.sa_handler = SIG_IGN;
00252 sigemptyset( &act.sa_mask );
00253 act.sa_flags = 0;
00254 sigaction( SIGPIPE, &act, 0 );
00255 #endif
00256 }
00257
00258 void KApplication::installX11EventFilter( QWidget* filter )
00259 {
00260 if ( !filter )
00261 return;
00262 if (!x11Filter)
00263 x11Filter = new QList<const QWidget *>;
00264 connect ( filter, SIGNAL( destroyed() ), this, SLOT( _k_x11FilterDestroyed() ) );
00265 x11Filter->append( filter );
00266 }
00267
00268 void KApplicationPrivate::_k_x11FilterDestroyed()
00269 {
00270 q->removeX11EventFilter( static_cast< const QWidget* >(q->sender()));
00271 }
00272
00273 void KApplication::removeX11EventFilter( const QWidget* filter )
00274 {
00275 if ( !x11Filter || !filter )
00276 return;
00277 x11Filter->removeAll( filter );
00278 if ( x11Filter->isEmpty() ) {
00279 delete x11Filter;
00280 x11Filter = 0;
00281 }
00282 }
00283
00284 bool KApplication::notify(QObject *receiver, QEvent *event)
00285 {
00286 QEvent::Type t = event->type();
00287 if( t == QEvent::Show && receiver->isWidgetType())
00288 {
00289 QWidget* w = static_cast< QWidget* >( receiver );
00290 #if defined Q_WS_X11
00291 if( w->isTopLevel() && !startupId().isEmpty())
00292 KStartupInfo::setWindowStartupId( w->winId(), startupId());
00293 #endif
00294 if( w->isTopLevel() && !( w->windowFlags() & Qt::X11BypassWindowManagerHint ) && w->windowType() != Qt::Popup && !event->spontaneous())
00295 {
00296 if( d->app_started_timer == NULL )
00297 {
00298 d->app_started_timer = new QTimer( this );
00299 connect( d->app_started_timer, SIGNAL( timeout()), SLOT( _k_checkAppStartedSlot()));
00300 }
00301 if( !d->app_started_timer->isActive()) {
00302 d->app_started_timer->setSingleShot( true );
00303 d->app_started_timer->start( 0 );
00304 }
00305 }
00306 }
00307 return QApplication::notify(receiver, event);
00308 }
00309
00310 void KApplicationPrivate::_k_checkAppStartedSlot()
00311 {
00312 #if defined Q_WS_X11
00313 KStartupInfo::handleAutoAppStartedSending();
00314 #endif
00315 }
00316
00317
00318
00319
00320
00321
00322 QString KApplicationPrivate::sessionConfigName() const
00323 {
00324 #ifdef QT_NO_SESSIONMANAGER
00325 #error QT_NO_SESSIONMANAGER was set, this will not compile. Reconfigure Qt with Session management support.
00326 #endif
00327 QString sessKey = q->sessionKey();
00328 if ( sessKey.isEmpty() && !sessionKey.isEmpty() )
00329 sessKey = sessionKey;
00330 return QString(QLatin1String("session/%1_%2_%3")).arg(q->applicationName()).arg(q->sessionId()).arg(sessKey);
00331 }
00332
00333 #ifdef Q_WS_X11
00334 static SmcConn mySmcConnection = 0;
00335 #else
00336
00337
00338 #endif
00339
00340 KApplication::KApplication(bool GUIenabled)
00341 : QApplication((KApplicationPrivate::preqapplicationhack(),KCmdLineArgs::qtArgc()), KCmdLineArgs::qtArgv(), GUIenabled),
00342 d(new KApplicationPrivate(this))
00343 {
00344 d->read_app_startup_id();
00345 setApplicationName(d->componentData.componentName());
00346 setOrganizationDomain(d->componentData.aboutData()->organizationDomain());
00347 installSigpipeHandler();
00348 d->init(GUIenabled);
00349 }
00350
00351 #ifdef Q_WS_X11
00352 KApplication::KApplication(Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap)
00353 : QApplication((KApplicationPrivate::preqapplicationhack(),dpy), KCmdLineArgs::qtArgc(), KCmdLineArgs::qtArgv(), visual, colormap),
00354 d(new KApplicationPrivate(this))
00355 {
00356 d->read_app_startup_id();
00357 setApplicationName(d->componentData.componentName());
00358 setOrganizationDomain(d->componentData.aboutData()->organizationDomain());
00359 installSigpipeHandler();
00360 d->init();
00361 }
00362
00363 KApplication::KApplication(Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap, const KComponentData &cData)
00364 : QApplication((KApplicationPrivate::preqapplicationhack(),dpy), KCmdLineArgs::qtArgc(), KCmdLineArgs::qtArgv(), visual, colormap),
00365 d (new KApplicationPrivate(this, cData))
00366 {
00367 d->read_app_startup_id();
00368 setApplicationName(d->componentData.componentName());
00369 setOrganizationDomain(d->componentData.aboutData()->organizationDomain());
00370 installSigpipeHandler();
00371 d->init();
00372 }
00373 #endif
00374
00375 KApplication::KApplication(bool GUIenabled, const KComponentData &cData)
00376 : QApplication((KApplicationPrivate::preqapplicationhack(),KCmdLineArgs::qtArgc()), KCmdLineArgs::qtArgv(), GUIenabled),
00377 d (new KApplicationPrivate(this, cData))
00378 {
00379 d->read_app_startup_id();
00380 setApplicationName(d->componentData.componentName());
00381 setOrganizationDomain(d->componentData.aboutData()->organizationDomain());
00382 installSigpipeHandler();
00383 d->init();
00384 }
00385
00386 #ifdef Q_WS_X11
00387 KApplication::KApplication(Display *display, int& argc, char** argv, const QByteArray& rAppName,
00388 bool GUIenabled)
00389 : QApplication((KApplicationPrivate::preqapplicationhack(),display)),
00390 d(new KApplicationPrivate(this, rAppName))
00391 {
00392 Q_UNUSED(GUIenabled);
00393 d->read_app_startup_id();
00394 setApplicationName(QLatin1String(rAppName));
00395 installSigpipeHandler();
00396 KCmdLineArgs::initIgnore(argc, argv, rAppName.data());
00397 d->init();
00398 }
00399 #endif
00400
00401
00402
00403 void KApplicationPrivate::preqapplicationhack()
00404 {
00405 preread_app_startup_id();
00406 }
00407
00408 int KApplication::xioErrhandler( Display* dpy )
00409 {
00410 if(kapp)
00411 {
00412 #ifdef Q_WS_X11
00413 d->oldXIOErrorHandler( dpy );
00414 #else
00415 Q_UNUSED(dpy);
00416 #endif
00417 }
00418 exit( 1 );
00419 return 0;
00420 }
00421
00422 int KApplication::xErrhandler( Display* dpy, void* err_ )
00423 {
00424 #ifdef Q_WS_X11
00425 XErrorEvent* err = static_cast< XErrorEvent* >( err_ );
00426 if(kapp)
00427 {
00428
00429 d->oldXErrorHandler( dpy, err );
00430 }
00431 const QByteArray fatalXError = qgetenv("KDE_FATAL_X_ERROR");
00432 if (!fatalXError.isEmpty()) {
00433 abort();
00434 }
00435 #endif
00436 return 0;
00437 }
00438
00439 void KApplication::iceIOErrorHandler( _IceConn *conn )
00440 {
00441 emit aboutToQuit();
00442
00443 #ifdef Q_WS_X11
00444 if ( d->oldIceIOErrorHandler != NULL )
00445 (*d->oldIceIOErrorHandler)( conn );
00446 #endif
00447 exit( 1 );
00448 }
00449
00450 class KDETranslator : public QTranslator
00451 {
00452 public:
00453 KDETranslator(QObject *parent) : QTranslator(parent)
00454 {
00455 setObjectName(QLatin1String("kdetranslator"));
00456 }
00457
00458 virtual QString translate(const char* context,
00459 const char *sourceText,
00460 const char* message) const
00461 {
00462 return KGlobal::locale()->translateQt(context, sourceText, message);
00463 }
00464 };
00465
00466 void KApplicationPrivate::init(bool GUIenabled)
00467 {
00468 if ((getuid() != geteuid()) ||
00469 (getgid() != getegid()))
00470 {
00471 fprintf(stderr, "The KDE libraries are not designed to run with suid privileges.\n");
00472 ::exit(127);
00473 }
00474
00475 #ifdef Q_WS_MAC
00476 mac_initialize_dbus();
00477 #endif
00478
00479 if ( q->type() == KApplication::GuiClient )
00480 {
00481 const QStringList plugins = KGlobal::dirs()->resourceDirs( "qtplugins" );
00482 QStringList::ConstIterator it = plugins.begin();
00483 while (it != plugins.end()) {
00484 q->addLibraryPath( *it );
00485 ++it;
00486 }
00487 }
00488
00489 KApplication::KApp = q;
00490
00491 parseCommandLine();
00492
00493 if(GUIenabled)
00494 (void) KClipboardSynchronizer::self();
00495
00496 extern KDECORE_EXPORT bool kde_kdebug_enable_dbus_interface;
00497 kde_kdebug_enable_dbus_interface = true;
00498
00499 QApplication::setDesktopSettingsAware( false );
00500
00501 #ifdef Q_WS_X11 //FIXME(E)
00502
00503 if ( q->type() == KApplication::GuiClient ) {
00504 const int max = 20;
00505 Atom* atoms[max];
00506 char* names[max];
00507 Atom atoms_return[max];
00508 int n = 0;
00509
00510 atoms[n] = &atom_DesktopWindow;
00511 names[n++] = (char *) "KDE_DESKTOP_WINDOW";
00512
00513 atoms[n] = &atom_NetSupported;
00514 names[n++] = (char *) "_NET_SUPPORTED";
00515
00516 atoms[n] = &kde_xdnd_drop;
00517 names[n++] = (char *) "XdndDrop";
00518
00519 XInternAtoms( QX11Info::display(), names, n, false, atoms_return );
00520
00521 for (int i = 0; i < n; i++ )
00522 *atoms[i] = atoms_return[i];
00523 }
00524 #endif
00525
00526
00527
00528 extern void qDBusBindToApplication();
00529 qDBusBindToApplication();
00530 QDBusConnectionInterface *bus = 0;
00531 if (!QDBusConnection::sessionBus().isConnected() || !(bus = QDBusConnection::sessionBus().interface())) {
00532 }
00533
00534 extern bool s_kuniqueapplication_startCalled;
00535 if ( bus && !s_kuniqueapplication_startCalled )
00536 {
00537 QStringList parts = q->organizationDomain().split(QLatin1Char('.'), QString::SkipEmptyParts);
00538 QString reversedDomain;
00539 if (parts.isEmpty())
00540 reversedDomain = QLatin1String("local.");
00541 else
00542 foreach (const QString& s, parts)
00543 {
00544 reversedDomain.prepend(QLatin1Char('.'));
00545 reversedDomain.prepend(s);
00546 }
00547 const QString pidSuffix = QString::number( getpid() ).prepend( QLatin1String("-") );
00548 const QString serviceName = reversedDomain + q->applicationName() + pidSuffix;
00549 if ( bus->registerService(serviceName) == QDBusConnectionInterface::ServiceNotRegistered ) {
00550 kError(101) << "Couldn't register name '" << serviceName << "' with DBUS - another process owns it already!" << endl;
00551 ::exit(126);
00552 }
00553 }
00554 QDBusConnection::sessionBus().registerObject(QLatin1String("/MainApplication"), q,
00555 QDBusConnection::ExportScriptableSlots |
00556 QDBusConnection::ExportScriptableProperties |
00557 QDBusConnection::ExportAdaptors);
00558
00559
00560 (void) KGlobal::locale();
00561
00562 KSharedConfig::Ptr config = componentData.config();
00563 QByteArray readOnly = qgetenv("KDE_HOME_READONLY");
00564 if (readOnly.isEmpty() && q->applicationName() != QLatin1String("kdialog"))
00565 {
00566 if (KAuthorized::authorize(QLatin1String("warn_unwritable_config")))
00567 config->isConfigWritable(true);
00568 }
00569
00570 if (q->type() == KApplication::GuiClient)
00571 {
00572 #ifdef Q_WS_X11
00573
00574 fcntl(ConnectionNumber(QX11Info::display()), F_SETFD, FD_CLOEXEC);
00575
00576 oldXErrorHandler = XSetErrorHandler( kde_x_errhandler );
00577 oldXIOErrorHandler = XSetIOErrorHandler( kde_xio_errhandler );
00578 #endif
00579
00580
00581 KGlobalSettings::self();
00582
00583 KMessage::setMessageHandler( new KMessageBoxMessageHandler(0) );
00584
00585 KCheckAccelerators::initiateIfNeeded(q);
00586 KGestureMap::self()->installEventFilterOnMe( q );
00587
00588 q->connect(KToolInvocation::self(), SIGNAL(kapplication_hook(QStringList&, QByteArray&)),
00589 q, SLOT(_k_slot_KToolInvocation_hook(QStringList&,QByteArray&)));
00590 }
00591
00592 #ifdef Q_WS_MAC
00593 if (q->type() == KApplication::GuiClient) {
00594
00595 QSystemTrayIcon *trayIcon;
00596 if (QSystemTrayIcon::isSystemTrayAvailable())
00597 {
00598 trayIcon = new QSystemTrayIcon(q);
00599 trayIcon->setIcon(q->windowIcon());
00600
00601
00602
00603 }
00604 }
00605 #endif
00606
00607
00608
00609
00610
00611 bool rtl = q->isRightToLeft();
00612 q->installTranslator(new KDETranslator(q));
00613 q->setLayoutDirection( rtl ? Qt::RightToLeft:Qt::LeftToRight);
00614 if (i18nc( "Dear Translator! Translate this string to the string 'LTR' in "
00615 "left-to-right languages (as English) or to 'RTL' in right-to-left "
00616 "languages (such as Hebrew and Arabic) to get proper widget layout.",
00617 "LTR" ) == QLatin1String("RTL"))
00618 rtl = !rtl;
00619 q->setLayoutDirection( rtl ? Qt::RightToLeft:Qt::LeftToRight);
00620
00621 qRegisterMetaType<KUrl>();
00622 qRegisterMetaType<KUrl::List>();
00623
00624 #ifdef Q_WS_WIN
00625 KApplication_init_windows();
00626 #endif
00627 }
00628
00629 KApplication* KApplication::kApplication()
00630 {
00631 return KApp;
00632 }
00633
00634 KConfig* KApplication::sessionConfig()
00635 {
00636 if (!d->pSessionConfig)
00637 d->pSessionConfig = new KConfig( d->sessionConfigName(), KConfig::SimpleConfig );
00638 return d->pSessionConfig;
00639 }
00640
00641 void KApplication::reparseConfiguration()
00642 {
00643 KGlobal::config()->reparseConfiguration();
00644 }
00645
00646 void KApplication::quit()
00647 {
00648 QApplication::quit();
00649 }
00650
00651 void KApplication::disableSessionManagement() {
00652 d->bSessionManagement = false;
00653 }
00654
00655 void KApplication::enableSessionManagement() {
00656 d->bSessionManagement = true;
00657 #ifdef Q_WS_X11
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667 if( mySmcConnection ) {
00668 SmcRequestSaveYourself( mySmcConnection, SmSaveLocal, False,
00669 SmInteractStyleAny,
00670 False, False );
00671
00672
00673 IceFlush(SmcGetIceConnection(mySmcConnection));
00674 }
00675 #endif
00676 }
00677
00678 void KApplication::commitData( QSessionManager& sm )
00679 {
00680 d->session_save = true;
00681 bool canceled = false;
00682
00683 foreach (KSessionManager *it, KSessionManager::sessionClients()) {
00684 if ( ( canceled = !it->commitData( sm ) ) )
00685 break;
00686 }
00687
00688 if ( canceled )
00689 sm.cancel();
00690
00691 if ( sm.allowsInteraction() ) {
00692 QWidgetList donelist, todolist;
00693 QWidget* w;
00694
00695 commitDataRestart:
00696 todolist = QApplication::topLevelWidgets();
00697
00698 for ( int i = 0; i < todolist.size(); ++i ) {
00699 w = todolist.at( i );
00700 if( !w )
00701 break;
00702
00703 if ( donelist.contains( w ) )
00704 continue;
00705
00706 if ( !w->isHidden() && !w->inherits( "KMainWindow" ) ) {
00707 QCloseEvent e;
00708 sendEvent( w, &e );
00709 if ( !e.isAccepted() )
00710 break;
00711
00712 donelist.append( w );
00713
00714
00715 goto commitDataRestart;
00716 }
00717 }
00718 }
00719
00720 if ( !d->bSessionManagement )
00721 sm.setRestartHint( QSessionManager::RestartNever );
00722 else
00723 sm.setRestartHint( QSessionManager::RestartIfRunning );
00724 d->session_save = false;
00725 }
00726
00727 #ifdef Q_WS_X11
00728 static void checkRestartVersion( QSessionManager& sm )
00729 {
00730 Display* dpy = QX11Info::display();
00731 Atom type;
00732 int format;
00733 unsigned long nitems, after;
00734 unsigned char* data;
00735 if( XGetWindowProperty( dpy, RootWindow( dpy, 0 ), XInternAtom( dpy, "KDE_SESSION_VERSION", False ),
00736 0, 1, False, AnyPropertyType, &type, &format, &nitems, &after, &data ) == Success ) {
00737 if( type == XA_INTEGER && format == 32 ) {
00738 int version = *( long* ) data;
00739 if( version == KDE_VERSION_MAJOR ) {
00740 XFree( data );
00741 return;
00742 }
00743 }
00744 XFree( data );
00745 }
00746 #define NUM_TO_STRING2( num ) #num
00747 #define NUM_TO_STRING( num ) NUM_TO_STRING2( num )
00748 QString wrapper = KStandardDirs::findExe( "kde" NUM_TO_STRING( KDE_VERSION_MAJOR ) );
00749 #undef NUM_TO_STRING
00750 #undef NUM_TO_STRING2
00751 QStringList restartCommand = sm.restartCommand();
00752 restartCommand.prepend( wrapper );
00753 sm.setRestartCommand( restartCommand );
00754 }
00755 #endif // Q_WS_X11
00756
00757 void KApplication::saveState( QSessionManager& sm )
00758 {
00759 d->session_save = true;
00760 #ifdef Q_WS_X11
00761 static bool firstTime = true;
00762 mySmcConnection = (SmcConn) sm.handle();
00763
00764 if ( !d->bSessionManagement ) {
00765 sm.setRestartHint( QSessionManager::RestartNever );
00766 d->session_save = false;
00767 return;
00768 }
00769 else
00770 sm.setRestartHint( QSessionManager::RestartIfRunning );
00771
00772 if ( firstTime ) {
00773 firstTime = false;
00774 d->session_save = false;
00775 return;
00776 }
00777
00778
00779
00780
00781
00782
00783
00784 if ( d->pSessionConfig ) {
00785 delete d->pSessionConfig;
00786 d->pSessionConfig = 0;
00787 }
00788
00789
00790 QStringList restartCommand = sm.restartCommand();
00791
00792 QByteArray multiHead = qgetenv("KDE_MULTIHEAD");
00793 if (multiHead.toLower() == "true") {
00794
00795
00796
00797
00798
00799
00800 QByteArray displayname = qgetenv("DISPLAY");
00801 if (! displayname.isNull()) {
00802
00803
00804 restartCommand.append(QLatin1String("-display"));
00805 restartCommand.append(QLatin1String(displayname));
00806 }
00807 sm.setRestartCommand( restartCommand );
00808 }
00809
00810 #ifdef Q_WS_X11
00811 checkRestartVersion( sm );
00812 #endif
00813
00814
00815 emit saveYourself();
00816 bool canceled = false;
00817 foreach(KSessionManager* it, KSessionManager::sessionClients()) {
00818 if(canceled) break;
00819 canceled = !it->saveState( sm );
00820 }
00821
00822
00823 if ( d->pSessionConfig ) {
00824 d->pSessionConfig->sync();
00825 QStringList discard;
00826 discard << QLatin1String("rm") << KStandardDirs::locateLocal("config", d->sessionConfigName());
00827 sm.setDiscardCommand( discard );
00828 } else {
00829 sm.setDiscardCommand( QStringList( QLatin1String("") ) );
00830 }
00831
00832 if ( canceled )
00833 sm.cancel();
00834 #else
00835
00836 #endif
00837 d->session_save = false;
00838 }
00839
00840 bool KApplication::sessionSaving() const
00841 {
00842 return d->session_save;
00843 }
00844
00845 void KApplicationPrivate::parseCommandLine( )
00846 {
00847 KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
00848
00849 #ifdef Q_WS_X11
00850 if (args && args->isSet("style"))
00851 {
00852 extern QString kde_overrideStyle;
00853 QString reqStyle(args->getOption("style").toLower());
00854 if (QStyleFactory::keys().contains(reqStyle, Qt::CaseInsensitive))
00855 kde_overrideStyle = reqStyle;
00856 else
00857 qWarning() << i18n("The style '%1' was not found", reqStyle);
00858 }
00859 #endif
00860
00861 if ( q->type() != KApplication::Tty ) {
00862 if (args && args->isSet("icon"))
00863 {
00864 q->setWindowIcon(KIcon(args->getOption("icon")));
00865 }
00866 else {
00867 q->setWindowIcon(KIcon(componentData.aboutData()->programIconName()));
00868 }
00869 }
00870
00871 if (!args)
00872 return;
00873
00874 if (args->isSet("config"))
00875 {
00876 QString config = args->getOption("config");
00877 componentData.setConfigName(config);
00878 }
00879
00880 bool nocrashhandler = (!qgetenv("KDE_DEBUG").isEmpty());
00881 if (!nocrashhandler && args->isSet("crashhandler"))
00882 {
00883
00884 KCrash::setCrashHandler(KCrash::defaultCrashHandler);
00885 }
00886
00887 KCrash::setApplicationName(args->appName());
00888
00889 #ifdef Q_WS_X11
00890 if ( args->isSet( "waitforwm" ) ) {
00891 Atom type;
00892 (void) q->desktop();
00893 int format;
00894 unsigned long length, after;
00895 unsigned char *data;
00896 while ( XGetWindowProperty( QX11Info::display(), QX11Info::appRootWindow(), atom_NetSupported,
00897 0, 1, false, AnyPropertyType, &type, &format,
00898 &length, &after, &data ) != Success || !length ) {
00899 if ( data )
00900 XFree( data );
00901 XEvent event;
00902 XWindowEvent( QX11Info::display(), QX11Info::appRootWindow(), PropertyChangeMask, &event );
00903 }
00904 if ( data )
00905 XFree( data );
00906 }
00907 #else
00908
00909 #endif
00910
00911 #ifndef Q_WS_WIN
00912 if (args->isSet("smkey"))
00913 {
00914 sessionKey = args->getOption("smkey");
00915 }
00916 #endif
00917 }
00918
00919 extern void kDebugCleanup();
00920
00921 KApplication::~KApplication()
00922 {
00923 #ifdef Q_WS_X11
00924 if ( d->oldXErrorHandler != NULL )
00925 XSetErrorHandler( d->oldXErrorHandler );
00926 if ( d->oldXIOErrorHandler != NULL )
00927 XSetIOErrorHandler( d->oldXIOErrorHandler );
00928 if ( d->oldIceIOErrorHandler != NULL )
00929 IceSetIOErrorHandler( d->oldIceIOErrorHandler );
00930 #endif
00931
00932 delete d;
00933 KApp = 0;
00934
00935 #ifdef Q_WS_X11
00936 mySmcConnection = 0;
00937 #else
00938
00939 #endif
00940 }
00941
00942
00943 #ifdef Q_WS_X11
00944 class KAppX11HackWidget: public QWidget
00945 {
00946 public:
00947 bool publicx11Event( XEvent * e) { return x11Event( e ); }
00948 };
00949 #endif
00950
00951
00952
00953 #ifdef Q_WS_X11
00954 bool KApplication::x11EventFilter( XEvent *_event )
00955 {
00956 switch ( _event->type ) {
00957 case ClientMessage:
00958 {
00959 #if KDE_IS_VERSION( 3, 90, 90 )
00960 #ifdef __GNUC__
00961 #warning This should be already in Qt, check.
00962 #endif
00963 #endif
00964
00965
00966
00967
00968
00969 if( _event->xclient.message_type == kde_xdnd_drop )
00970 {
00971 if( _event->xclient.data.l[ 1 ] == 1 << 24
00972 && _event->xclient.data.l[ 2 ] == 0
00973 && _event->xclient.data.l[ 4 ] == 0
00974 && _event->xclient.data.l[ 3 ] != 0 )
00975 {
00976 if( QX11Info::appUserTime() == 0
00977 || NET::timestampCompare( _event->xclient.data.l[ 3 ], QX11Info::appUserTime() ) > 0 )
00978 {
00979 QX11Info::setAppUserTime(_event->xclient.data.l[ 3 ]);
00980 }
00981 }
00982 else
00983 {
00984 if( QX11Info::appUserTime() == 0
00985 || NET::timestampCompare( _event->xclient.data.l[ 2 ], QX11Info::appUserTime() ) > 0 )
00986 {
00987 QX11Info::setAppUserTime(_event->xclient.data.l[ 2 ]);
00988 }
00989 }
00990 }
00991 }
00992 default: break;
00993 }
00994
00995 if (x11Filter) {
00996 foreach (const QWidget *w, *x11Filter) {
00997 if (((KAppX11HackWidget*) w)->publicx11Event(_event))
00998 return true;
00999 }
01000 }
01001
01002 return false;
01003 }
01004 #endif // Q_WS_X11
01005
01006 void KApplication::updateUserTimestamp( int time )
01007 {
01008 #if defined Q_WS_X11
01009 if( time == 0 )
01010 {
01011 Window w = XCreateSimpleWindow( QX11Info::display(), QX11Info::appRootWindow(), 0, 0, 1, 1, 0, 0, 0 );
01012 XSelectInput( QX11Info::display(), w, PropertyChangeMask );
01013 unsigned char data[ 1 ];
01014 XChangeProperty( QX11Info::display(), w, XA_ATOM, XA_ATOM, 8, PropModeAppend, data, 1 );
01015 XEvent ev;
01016 XWindowEvent( QX11Info::display(), w, PropertyChangeMask, &ev );
01017 time = ev.xproperty.time;
01018 XDestroyWindow( QX11Info::display(), w );
01019 }
01020 if( QX11Info::appUserTime() == 0
01021 || NET::timestampCompare( time, QX11Info::appUserTime()) > 0 )
01022 QX11Info::setAppUserTime(time);
01023 if( QX11Info::appTime() == 0
01024 || NET::timestampCompare( time, QX11Info::appTime()) > 0 )
01025 QX11Info::setAppTime(time);
01026 #endif
01027 }
01028
01029 unsigned long KApplication::userTimestamp() const
01030 {
01031 #if defined Q_WS_X11
01032 return QX11Info::appUserTime();
01033 #else
01034 return 0;
01035 #endif
01036 }
01037
01038 void