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 KApplication::KApp = q;
00480
00481 parseCommandLine();
00482
00483 if(GUIenabled)
00484 (void) KClipboardSynchronizer::self();
00485
00486 extern KDECORE_EXPORT bool kde_kdebug_enable_dbus_interface;
00487 kde_kdebug_enable_dbus_interface = true;
00488
00489 QApplication::setDesktopSettingsAware( false );
00490
00491 #ifdef Q_WS_X11 //FIXME(E)
00492
00493 if ( q->type() == KApplication::GuiClient ) {
00494 const int max = 20;
00495 Atom* atoms[max];
00496 char* names[max];
00497 Atom atoms_return[max];
00498 int n = 0;
00499
00500 atoms[n] = &atom_DesktopWindow;
00501 names[n++] = (char *) "KDE_DESKTOP_WINDOW";
00502
00503 atoms[n] = &atom_NetSupported;
00504 names[n++] = (char *) "_NET_SUPPORTED";
00505
00506 atoms[n] = &kde_xdnd_drop;
00507 names[n++] = (char *) "XdndDrop";
00508
00509 XInternAtoms( QX11Info::display(), names, n, false, atoms_return );
00510
00511 for (int i = 0; i < n; i++ )
00512 *atoms[i] = atoms_return[i];
00513 }
00514 #endif
00515
00516
00517
00518 extern void qDBusBindToApplication();
00519 qDBusBindToApplication();
00520 QDBusConnectionInterface *bus = 0;
00521 if (!QDBusConnection::sessionBus().isConnected() || !(bus = QDBusConnection::sessionBus().interface())) {
00522 }
00523
00524 extern bool s_kuniqueapplication_startCalled;
00525 if ( bus && !s_kuniqueapplication_startCalled )
00526 {
00527 QStringList parts = q->organizationDomain().split(QLatin1Char('.'), QString::SkipEmptyParts);
00528 QString reversedDomain;
00529 if (parts.isEmpty())
00530 reversedDomain = QLatin1String("local.");
00531 else
00532 foreach (const QString& s, parts)
00533 {
00534 reversedDomain.prepend(QLatin1Char('.'));
00535 reversedDomain.prepend(s);
00536 }
00537 const QString pidSuffix = QString::number( getpid() ).prepend( QLatin1String("-") );
00538 const QString serviceName = reversedDomain + q->applicationName() + pidSuffix;
00539 if ( bus->registerService(serviceName) == QDBusConnectionInterface::ServiceNotRegistered ) {
00540 kError(101) << "Couldn't register name '" << serviceName << "' with DBUS - another process owns it already!" << endl;
00541 ::exit(126);
00542 }
00543 }
00544 QDBusConnection::sessionBus().registerObject(QLatin1String("/MainApplication"), q,
00545 QDBusConnection::ExportScriptableSlots |
00546 QDBusConnection::ExportScriptableProperties |
00547 QDBusConnection::ExportAdaptors);
00548
00549
00550 (void) KGlobal::locale();
00551
00552 KSharedConfig::Ptr config = componentData.config();
00553 QByteArray readOnly = qgetenv("KDE_HOME_READONLY");
00554 if (readOnly.isEmpty() && q->applicationName() != QLatin1String("kdialog"))
00555 {
00556 if (KAuthorized::authorize(QLatin1String("warn_unwritable_config")))
00557 config->isConfigWritable(true);
00558 }
00559
00560 if (q->type() == KApplication::GuiClient)
00561 {
00562 #ifdef Q_WS_X11
00563
00564 fcntl(ConnectionNumber(QX11Info::display()), F_SETFD, FD_CLOEXEC);
00565
00566 oldXErrorHandler = XSetErrorHandler( kde_x_errhandler );
00567 oldXIOErrorHandler = XSetIOErrorHandler( kde_xio_errhandler );
00568 #endif
00569
00570
00571 KGlobalSettings::self();
00572
00573 KMessage::setMessageHandler( new KMessageBoxMessageHandler(0) );
00574
00575 KCheckAccelerators::initiateIfNeeded(q);
00576 KGestureMap::self()->installEventFilterOnMe( q );
00577
00578 q->connect(KToolInvocation::self(), SIGNAL(kapplication_hook(QStringList&, QByteArray&)),
00579 q, SLOT(_k_slot_KToolInvocation_hook(QStringList&,QByteArray&)));
00580 }
00581
00582 #ifdef Q_WS_MAC
00583 if (q->type() == KApplication::GuiClient) {
00584
00585 QSystemTrayIcon *trayIcon;
00586 if (QSystemTrayIcon::isSystemTrayAvailable())
00587 {
00588 trayIcon = new QSystemTrayIcon(q);
00589 trayIcon->setIcon(q->windowIcon());
00590
00591
00592
00593 }
00594 }
00595 #endif
00596
00597
00598
00599
00600
00601 bool rtl = q->isRightToLeft();
00602 q->installTranslator(new KDETranslator(q));
00603 q->setLayoutDirection( rtl ? Qt::RightToLeft:Qt::LeftToRight);
00604 if (i18nc( "Dear Translator! Translate this string to the string 'LTR' in "
00605 "left-to-right languages (as English) or to 'RTL' in right-to-left "
00606 "languages (such as Hebrew and Arabic) to get proper widget layout.",
00607 "LTR" ) == QLatin1String("RTL"))
00608 rtl = !rtl;
00609 q->setLayoutDirection( rtl ? Qt::RightToLeft:Qt::LeftToRight);
00610
00611 qRegisterMetaType<KUrl>();
00612 qRegisterMetaType<KUrl::List>();
00613
00614 #ifdef Q_WS_WIN
00615 KApplication_init_windows();
00616 #endif
00617 }
00618
00619 KApplication* KApplication::kApplication()
00620 {
00621 return KApp;
00622 }
00623
00624 KConfig* KApplication::sessionConfig()
00625 {
00626 if (!d->pSessionConfig)
00627 d->pSessionConfig = new KConfig( d->sessionConfigName(), KConfig::SimpleConfig );
00628 return d->pSessionConfig;
00629 }
00630
00631 void KApplication::reparseConfiguration()
00632 {
00633 KGlobal::config()->reparseConfiguration();
00634 }
00635
00636 void KApplication::quit()
00637 {
00638 QApplication::quit();
00639 }
00640
00641 void KApplication::disableSessionManagement() {
00642 d->bSessionManagement = false;
00643 }
00644
00645 void KApplication::enableSessionManagement() {
00646 d->bSessionManagement = true;
00647 #ifdef Q_WS_X11
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657 if( mySmcConnection ) {
00658 SmcRequestSaveYourself( mySmcConnection, SmSaveLocal, False,
00659 SmInteractStyleAny,
00660 False, False );
00661
00662
00663 IceFlush(SmcGetIceConnection(mySmcConnection));
00664 }
00665 #endif
00666 }
00667
00668 void KApplication::commitData( QSessionManager& sm )
00669 {
00670 d->session_save = true;
00671 bool canceled = false;
00672
00673 foreach (KSessionManager *it, KSessionManager::sessionClients()) {
00674 if ( ( canceled = !it->commitData( sm ) ) )
00675 break;
00676 }
00677
00678 if ( canceled )
00679 sm.cancel();
00680
00681 if ( sm.allowsInteraction() ) {
00682 QWidgetList donelist, todolist;
00683 QWidget* w;
00684
00685 commitDataRestart:
00686 todolist = QApplication::topLevelWidgets();
00687
00688 for ( int i = 0; i < todolist.size(); ++i ) {
00689 w = todolist.at( i );
00690 if( !w )
00691 break;
00692
00693 if ( donelist.contains( w ) )
00694 continue;
00695
00696 if ( !w->isHidden() && !w->inherits( "KMainWindow" ) ) {
00697 QCloseEvent e;
00698 sendEvent( w, &e );
00699 if ( !e.isAccepted() )
00700 break;
00701
00702 donelist.append( w );
00703
00704
00705 goto commitDataRestart;
00706 }
00707 }
00708 }
00709
00710 if ( !d->bSessionManagement )
00711 sm.setRestartHint( QSessionManager::RestartNever );
00712 else
00713 sm.setRestartHint( QSessionManager::RestartIfRunning );
00714 d->session_save = false;
00715 }
00716
00717 #ifdef Q_WS_X11
00718 static void checkRestartVersion( QSessionManager& sm )
00719 {
00720 Display* dpy = QX11Info::display();
00721 Atom type;
00722 int format;
00723 unsigned long nitems, after;
00724 unsigned char* data;
00725 if( XGetWindowProperty( dpy, RootWindow( dpy, 0 ), XInternAtom( dpy, "KDE_SESSION_VERSION", False ),
00726 0, 1, False, AnyPropertyType, &type, &format, &nitems, &after, &data ) == Success ) {
00727 if( type == XA_INTEGER && format == 32 ) {
00728 int version = *( long* ) data;
00729 if( version == KDE_VERSION_MAJOR ) {
00730 XFree( data );
00731 return;
00732 }
00733 }
00734 XFree( data );
00735 }
00736 #define NUM_TO_STRING2( num ) #num
00737 #define NUM_TO_STRING( num ) NUM_TO_STRING2( num )
00738 QString wrapper = KStandardDirs::findExe( "kde" NUM_TO_STRING( KDE_VERSION_MAJOR ) );
00739 #undef NUM_TO_STRING
00740 #undef NUM_TO_STRING2
00741 QStringList restartCommand = sm.restartCommand();
00742 restartCommand.prepend( wrapper );
00743 sm.setRestartCommand( restartCommand );
00744 }
00745 #endif // Q_WS_X11
00746
00747 void KApplication::saveState( QSessionManager& sm )
00748 {
00749 d->session_save = true;
00750 #ifdef Q_WS_X11
00751 static bool firstTime = true;
00752 mySmcConnection = (SmcConn) sm.handle();
00753
00754 if ( !d->bSessionManagement ) {
00755 sm.setRestartHint( QSessionManager::RestartNever );
00756 d->session_save = false;
00757 return;
00758 }
00759 else
00760 sm.setRestartHint( QSessionManager::RestartIfRunning );
00761
00762 if ( firstTime ) {
00763 firstTime = false;
00764 d->session_save = false;
00765 return;
00766 }
00767
00768
00769
00770
00771
00772
00773
00774 if ( d->pSessionConfig ) {
00775 delete d->pSessionConfig;
00776 d->pSessionConfig = 0;
00777 }
00778
00779
00780 QStringList restartCommand = sm.restartCommand();
00781
00782 QByteArray multiHead = qgetenv("KDE_MULTIHEAD");
00783 if (multiHead.toLower() == "true") {
00784
00785
00786
00787
00788
00789
00790 QByteArray displayname = qgetenv("DISPLAY");
00791 if (! displayname.isNull()) {
00792
00793
00794 restartCommand.append(QLatin1String("-display"));
00795 restartCommand.append(QLatin1String(displayname));
00796 }
00797 sm.setRestartCommand( restartCommand );
00798 }
00799
00800 #ifdef Q_WS_X11
00801 checkRestartVersion( sm );
00802 #endif
00803
00804
00805 emit saveYourself();
00806 bool canceled = false;
00807 foreach(KSessionManager* it, KSessionManager::sessionClients()) {
00808 if(canceled) break;
00809 canceled = !it->saveState( sm );
00810 }
00811
00812
00813 if ( d->pSessionConfig ) {
00814 d->pSessionConfig->sync();
00815 QStringList discard;
00816 discard << QLatin1String("rm") << KStandardDirs::locateLocal("config", d->sessionConfigName());
00817 sm.setDiscardCommand( discard );
00818 } else {
00819 sm.setDiscardCommand( QStringList( QLatin1String("") ) );
00820 }
00821
00822 if ( canceled )
00823 sm.cancel();
00824 #else
00825
00826 #endif
00827 d->session_save = false;
00828 }
00829
00830 bool KApplication::sessionSaving() const
00831 {
00832 return d->session_save;
00833 }
00834
00835 void KApplicationPrivate::parseCommandLine( )
00836 {
00837 KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
00838
00839 if (args && args->isSet("style"))
00840 {
00841 extern QString kde_overrideStyle;
00842 QString reqStyle(args->getOption("style").toLower());
00843 if (QStyleFactory::keys().contains(reqStyle, Qt::CaseInsensitive))
00844 kde_overrideStyle = reqStyle;
00845 else
00846 qWarning() << i18n("The style '%1' was not found", reqStyle);
00847 }
00848
00849 if ( q->type() != KApplication::Tty ) {
00850 if (args && args->isSet("icon"))
00851 {
00852 q->setWindowIcon(KIcon(args->getOption("icon")));
00853 }
00854 else {
00855 q->setWindowIcon(KIcon(componentData.aboutData()->programIconName()));
00856 }
00857 }
00858
00859 if (!args)
00860 return;
00861
00862 if (args->isSet("config"))
00863 {
00864 QString config = args->getOption("config");
00865 componentData.setConfigName(config);
00866 }
00867
00868 bool nocrashhandler = (!qgetenv("KDE_DEBUG").isEmpty());
00869 if (!nocrashhandler && args->isSet("crashhandler"))
00870 {
00871
00872 KCrash::setCrashHandler(KCrash::defaultCrashHandler);
00873 }
00874
00875 KCrash::setApplicationName(args->appName());
00876
00877 #ifdef Q_WS_X11
00878 if ( args->isSet( "waitforwm" ) ) {
00879 Atom type;
00880 (void) q->desktop();
00881 int format;
00882 unsigned long length, after;
00883 unsigned char *data;
00884 while ( XGetWindowProperty( QX11Info::display(), QX11Info::appRootWindow(), atom_NetSupported,
00885 0, 1, false, AnyPropertyType, &type, &format,
00886 &length, &after, &data ) != Success || !length ) {
00887 if ( data )
00888 XFree( data );
00889 XEvent event;
00890 XWindowEvent( QX11Info::display(), QX11Info::appRootWindow(), PropertyChangeMask, &event );
00891 }
00892 if ( data )
00893 XFree( data );
00894 }
00895 #else
00896
00897 #endif
00898
00899 #ifndef Q_WS_WIN
00900 if (args->isSet("smkey"))
00901 {
00902 sessionKey = args->getOption("smkey");
00903 }
00904 #endif
00905 }
00906
00907 extern void kDebugCleanup();
00908
00909 KApplication::~KApplication()
00910 {
00911 #ifdef Q_WS_X11
00912 if ( d->oldXErrorHandler != NULL )
00913 XSetErrorHandler( d->oldXErrorHandler );
00914 if ( d->oldXIOErrorHandler != NULL )
00915 XSetIOErrorHandler( d->oldXIOErrorHandler );
00916 if ( d->oldIceIOErrorHandler != NULL )
00917 IceSetIOErrorHandler( d->oldIceIOErrorHandler );
00918 #endif
00919
00920 delete d;
00921 KApp = 0;
00922
00923 #ifdef Q_WS_X11
00924 mySmcConnection = 0;
00925 #else
00926
00927 #endif
00928 }
00929
00930
00931 #ifdef Q_WS_X11
00932 class KAppX11HackWidget: public QWidget
00933 {
00934 public:
00935 bool publicx11Event( XEvent * e) { return x11Event( e ); }
00936 };
00937 #endif
00938
00939
00940
00941 #ifdef Q_WS_X11
00942 bool KApplication::x11EventFilter( XEvent *_event )
00943 {
00944 switch ( _event->type ) {
00945 case ClientMessage:
00946 {
00947 #if KDE_IS_VERSION( 3, 90, 90 )
00948 #ifdef __GNUC__
00949 #warning This should be already in Qt, check.
00950 #endif
00951 #endif
00952
00953
00954
00955
00956
00957 if( _event->xclient.message_type == kde_xdnd_drop )
00958 {
00959 if( _event->xclient.data.l[ 1 ] == 1 << 24
00960 && _event->xclient.data.l[ 2 ] == 0
00961 && _event->xclient.data.l[ 4 ] == 0
00962 && _event->xclient.data.l[ 3 ] != 0 )
00963 {
00964 if( QX11Info::appUserTime() == 0
00965 || NET::timestampCompare( _event->xclient.data.l[ 3 ], QX11Info::appUserTime() ) > 0 )
00966 {
00967 QX11Info::setAppUserTime(_event->xclient.data.l[ 3 ]);
00968 }
00969 }
00970 else
00971 {
00972 if( QX11Info::appUserTime() == 0
00973 || NET::timestampCompare( _event->xclient.data.l[ 2 ], QX11Info::appUserTime() ) > 0 )
00974 {
00975 QX11Info::setAppUserTime(_event->xclient.data.l[ 2 ]);
00976 }
00977 }
00978 }
00979 }
00980 default: break;
00981 }
00982
00983 if (x11Filter) {
00984 foreach (const QWidget *w, *x11Filter) {
00985 if (((KAppX11HackWidget*) w)->publicx11Event(_event))
00986 return true;
00987 }
00988 }
00989
00990 return false;
00991 }
00992 #endif // Q_WS_X11
00993
00994 void KApplication::updateUserTimestamp( int time )
00995 {
00996 #if defined Q_WS_X11
00997 if( time == 0 )
00998 {
00999 Window w = XCreateSimpleWindow( QX11Info::display(), QX11Info::appRootWindow(), 0, 0, 1, 1, 0, 0, 0 );
01000 XSelectInput( QX11Info::display(), w, PropertyChangeMask );
01001 unsigned char data[ 1 ];
01002 XChangeProperty( QX11Info::display(), w, XA_ATOM, XA_ATOM, 8, PropModeAppend, data, 1 );
01003 XEvent ev;
01004 XWindowEvent( QX11Info::display(), w, PropertyChangeMask, &ev );
01005 time = ev.xproperty.time;
01006 XDestroyWindow( QX11Info::display(), w );
01007 }
01008 if( QX11Info::appUserTime() == 0
01009 || NET::timestampCompare( time, QX11Info::appUserTime()) > 0 )
01010 QX11Info::setAppUserTime(time);
01011 if( QX11Info::appTime() == 0
01012 || NET::timestampCompare( time, QX11Info::appTime()) > 0 )
01013 QX11Info::setAppTime(time);
01014 #endif
01015 }
01016
01017 unsigned long KApplication::userTimestamp() const
01018 {
01019 #if defined Q_WS_X11
01020 return QX11Info::appUserTime();
01021 #else
01022 return 0;
01023 #endif
01024 }
01025
01026 void KApplication::updateRemoteUserTimestamp( const QString& service, int time )
01027 {
01028 #if defined Q_WS_X11
01029 Q_ASSERT(service.contains('.'));
01030 if( time == 0 )
01031 time = QX11Info::appUserTime();
01032 QDBusInterface(service, QLatin1String("/MainApplication"),
01033 QString(QLatin1String("org.kde.KApplication")))
01034 .call(QLatin1String("updateUserTimestamp"), time);
01035 #endif
01036 }
01037
01038
01039 QString KApplication::tempSaveName( const QString& pFilename )
01040 {
01041 QString aFilename;
01042
01043 if( QDir::isRelativePath(pFilename) )
01044 {
01045 kWarning(101) << "Relative filename passed to KApplication::tempSaveName";
01046 aFilename = QFileInfo( QDir( QLatin1String(".") ), pFilename ).absoluteFilePath();
01047 }
01048 else
01049 aFilename = pFilename;
01050
01051 QDir aAutosaveDir( QDir::homePath() + QLatin1String("/autosave/") );
01052 if( !aAutosaveDir.exists() )
01053 {
01054 if( !aAutosaveDir.mkdir( aAutosaveDir.absolutePath() ) )
01055 {
01056
01057 aAutosaveDir.setPath( KGlobal::dirs()->saveLocation("tmp") );
01058 }
01059 }
01060
01061 aFilename.replace( '/', QLatin1String("\\!") )
01062 .prepend( QLatin1Char('#') )
01063 .append( QLatin1Char('#') )
01064 .prepend( QLatin1Char('/') ).prepend( aAutosaveDir.absolutePath() );
01065
01066 return aFilename;
01067 }
01068
01069
01070 QString KApplication::checkRecoverFile( const QString& pFilename,
01071 bool& bRecover )
01072 {
01073 QString aFilename;
01074
01075 if( QDir::isRelativePath(pFilename) )
01076 {
01077 kWarning(101) << "Relative filename passed to KApplication::tempSaveName";
01078 aFilename = QFileInfo( QDir( QLatin1String(".") ), pFilename ).absoluteFilePath();
01079 }
01080 else
01081 aFilename = pFilename;
01082
01083 QDir aAutosaveDir( QDir::homePath() + QLatin1String("/autosave/") );
01084 if( !aAutosaveDir.exists() )
01085 {
01086 if( !aAutosaveDir.mkdir( aAutosaveDir.absolutePath() ) )
01087 {
01088
01089 aAutosaveDir.setPath( KGlobal::dirs()->saveLocation("tmp") );
01090 }
01091 }
01092
01093 aFilename.replace( QLatin1String("/"), QLatin1String("\\!") )
01094 .prepend( QLatin1Char('#') )
01095 .append( QLatin1Char('#') )
01096 .prepend( QLatin1Char('/') )
01097 .prepend( aAutosaveDir.absolutePath() );
01098
01099 if( QFile( aFilename ).exists() )
01100 {
01101 bRecover = true;
01102 return aFilename;
01103 }
01104 else
01105 {
01106 bRecover = false;
01107 return pFilename;
01108 }
01109 }
01110
01111
01112 void KApplication::setTopWidget( QWidget *topWidget )
01113 {
01114 if( !topWidget )
01115 return;
01116
01117
01118 if ( !topWidget->inherits("KMainWindow") ) {
01119 topWidget->setWindowTitle(KGlobal::caption());
01120 }
01121
01122 #if defined Q_WS_X11
01123
01124
01125 KStartupInfo::setWindowStartupId( topWidget->winId(), startupId());
01126 #endif
01127 }
01128
01129 QByteArray KApplication::startupId() const
01130 {
01131 return d->startup_id;
01132 }
01133
01134 void KApplication::setStartupId( const QByteArray& startup_id )
01135 {
01136 if( startup_id == d->startup_id )
01137 return;
01138 #if defined Q_WS_X11
01139 KStartupInfo::handleAutoAppStartedSending();
01140 #endif
01141 if( startup_id.isEmpty())
01142 d->startup_id = "0";
01143 else
01144 {
01145 d->startup_id = startup_id;
01146 #if defined Q_WS_X11
01147 KStartupInfoId id;
01148 id.initId( startup_id );
01149 long timestamp = id.timestamp();
01150 if( timestamp != 0 )
01151 updateUserTimestamp( timestamp );
01152 #endif
01153 }
01154 }
01155
01156 void KApplication::clearStartupId()
01157 {
01158 d->startup_id = "0";
01159 }
01160
01161
01162
01163
01164 void KApplicationPrivate::preread_app_startup_id()
01165 {
01166 #if defined Q_WS_X11
01167 KStartupInfoId id = KStartupInfo::currentStartupIdEnv();
01168 KStartupInfo::resetStartupEnv();
01169 startup_id_tmp = new QByteArray( id.id());
01170 #endif
01171 }
01172
01173
01174
01175 void KApplicationPrivate::read_app_startup_id()
01176 {
01177 #if defined Q_WS_X11
01178 startup_id = *startup_id_tmp;
01179 delete startup_id_tmp;
01180 startup_id_tmp = NULL;
01181 #endif
01182 }
01183
01184
01185 void KApplicationPrivate::_k_slot_KToolInvocation_hook(QStringList& envs,QByteArray& startup_id)
01186 {
01187 #ifdef Q_WS_X11
01188 if (QX11Info::display()) {
01189 QByteArray dpystring(XDisplayString(QX11Info::display()));
01190 envs << QString::fromLatin1( QByteArray("DISPLAY=") + dpystring );
01191 } else {
01192 const QByteArray dpystring( qgetenv( "DISPLAY" ));
01193 if(!dpystring.isEmpty())
01194 envs << QString::fromLatin1( QByteArray("DISPLAY=") + dpystring );
01195 }
01196
01197 if(startup_id.isEmpty())
01198 startup_id = KStartupInfo::createNewStartupId();
01199 #else
01200 Q_UNUSED(envs);
01201 Q_UNUSED(startup_id);
01202 #endif
01203 }
01204
01205 void KApplication::setSynchronizeClipboard(bool synchronize)
01206 {
01207 KClipboardSynchronizer::self()->setSynchronizing(synchronize);
01208 KClipboardSynchronizer::self()->setReverseSynchronizing(synchronize);
01209 }
01210
01211 #include "kapplication.moc"
01212