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 checkAccelerators(0),
00155 startup_id("0"),
00156 app_started_timer(0),
00157 session_save(false)
00158 #ifdef Q_WS_X11
00159 , oldIceIOErrorHandler(0)
00160 , oldXErrorHandler(0)
00161 , oldXIOErrorHandler(0)
00162 #endif
00163 ,pSessionConfig( 0 )
00164 ,bSessionManagement( true )
00165 {
00166 }
00167
00168 KApplicationPrivate(KApplication* q, const KComponentData &cData)
00169 : q(q),
00170 componentData(cData),
00171 checkAccelerators(0),
00172 startup_id("0"),
00173 app_started_timer(0),
00174 session_save(false)
00175 #ifdef Q_WS_X11
00176 , oldIceIOErrorHandler(0)
00177 , oldXErrorHandler(0)
00178 , oldXIOErrorHandler(0)
00179 #endif
00180 ,pSessionConfig( 0 )
00181 ,bSessionManagement( true )
00182 {
00183 }
00184
00185 KApplicationPrivate(KApplication *q)
00186 : q(q),
00187 componentData(KCmdLineArgs::aboutData()),
00188 checkAccelerators(0),
00189 startup_id( "0" ),
00190 app_started_timer( 0 ),
00191 session_save( false )
00192 #ifdef Q_WS_X11
00193 ,oldIceIOErrorHandler( 0 )
00194 ,oldXErrorHandler( 0 )
00195 ,oldXIOErrorHandler( 0 )
00196 #endif
00197 ,pSessionConfig( 0 )
00198 ,bSessionManagement( true )
00199 {
00200 }
00201
00202 ~KApplicationPrivate()
00203 {
00204 }
00205
00206 #ifndef KDE3_SUPPORT
00207 KConfig *config() { return KGlobal::config().data(); }
00208 #endif
00209
00210 void _k_x11FilterDestroyed();
00211 void _k_checkAppStartedSlot();
00212 void _k_slot_KToolInvocation_hook(QStringList&, QByteArray&);
00213
00214 QString sessionConfigName() const;
00215 void init(bool GUIenabled=true);
00216 void parseCommandLine( );
00217 static void preqapplicationhack();
00218 static void preread_app_startup_id();
00219 void read_app_startup_id();
00220
00221 KApplication *q;
00222 KComponentData componentData;
00223 KCheckAccelerators* checkAccelerators;
00224 QByteArray startup_id;
00225 QTimer* app_started_timer;
00226 bool session_save;
00227
00228 #ifdef Q_WS_X11
00229 IceIOErrorHandler oldIceIOErrorHandler;
00230 int (*oldXErrorHandler)(Display*,XErrorEvent*);
00231 int (*oldXIOErrorHandler)(Display*);
00232 #endif
00233
00234 QString sessionKey;
00235 QString pSessionConfigFile;
00236
00237 KConfig* pSessionConfig;
00238 bool bSessionManagement;
00239 };
00240
00241
00242 static QList<const QWidget*> *x11Filter = 0;
00243
00251 static void installSigpipeHandler()
00252 {
00253 #ifdef Q_OS_UNIX
00254 struct sigaction act;
00255 act.sa_handler = SIG_IGN;
00256 sigemptyset( &act.sa_mask );
00257 act.sa_flags = 0;
00258 sigaction( SIGPIPE, &act, 0 );
00259 #endif
00260 }
00261
00262 void KApplication::installX11EventFilter( QWidget* filter )
00263 {
00264 if ( !filter )
00265 return;
00266 if (!x11Filter)
00267 x11Filter = new QList<const QWidget *>;
00268 connect ( filter, SIGNAL( destroyed() ), this, SLOT( _k_x11FilterDestroyed() ) );
00269 x11Filter->append( filter );
00270 }
00271
00272 void KApplicationPrivate::_k_x11FilterDestroyed()
00273 {
00274 q->removeX11EventFilter( static_cast< const QWidget* >(q->sender()));
00275 }
00276
00277 void KApplication::removeX11EventFilter( const QWidget* filter )
00278 {
00279 if ( !x11Filter || !filter )
00280 return;
00281 x11Filter->removeAll( filter );
00282 if ( x11Filter->isEmpty() ) {
00283 delete x11Filter;
00284 x11Filter = 0;
00285 }
00286 }
00287
00288 bool KApplication::notify(QObject *receiver, QEvent *event)
00289 {
00290 QEvent::Type t = event->type();
00291 if( t == QEvent::Show && receiver->isWidgetType())
00292 {
00293 QWidget* w = static_cast< QWidget* >( receiver );
00294 #if defined Q_WS_X11
00295 if( w->isTopLevel() && !startupId().isEmpty())
00296 KStartupInfo::setWindowStartupId( w->winId(), startupId());
00297 #endif
00298 if( w->isTopLevel() && !( w->windowFlags() & Qt::X11BypassWindowManagerHint ) && w->windowType() != Qt::Popup && !event->spontaneous())
00299 {
00300 if( d->app_started_timer == NULL )
00301 {
00302 d->app_started_timer = new QTimer( this );
00303 connect( d->app_started_timer, SIGNAL( timeout()), SLOT( _k_checkAppStartedSlot()));
00304 }
00305 if( !d->app_started_timer->isActive()) {
00306 d->app_started_timer->setSingleShot( true );
00307 d->app_started_timer->start( 0 );
00308 }
00309 }
00310 }
00311 return QApplication::notify(receiver, event);
00312 }
00313
00314 void KApplicationPrivate::_k_checkAppStartedSlot()
00315 {
00316 #if defined Q_WS_X11
00317 KStartupInfo::handleAutoAppStartedSending();
00318 #endif
00319 }
00320
00321
00322
00323
00324
00325
00326 QString KApplicationPrivate::sessionConfigName() const
00327 {
00328 #ifdef QT_NO_SESSIONMANAGER
00329 #error QT_NO_SESSIONMANAGER was set, this will not compile. Reconfigure Qt with Session management support.
00330 #endif
00331 QString sessKey = q->sessionKey();
00332 if ( sessKey.isEmpty() && !sessionKey.isEmpty() )
00333 sessKey = sessionKey;
00334 return QString(QLatin1String("session/%1_%2_%3")).arg(q->applicationName()).arg(q->sessionId()).arg(sessKey);
00335 }
00336
00337 #ifdef Q_WS_X11
00338 static SmcConn mySmcConnection = 0;
00339 #else
00340
00341
00342 #endif
00343
00344 KApplication::KApplication(bool GUIenabled)
00345 : QApplication((KApplicationPrivate::preqapplicationhack(),KCmdLineArgs::qtArgc()), KCmdLineArgs::qtArgv(), GUIenabled),
00346 d(new KApplicationPrivate(this))
00347 {
00348 d->read_app_startup_id();
00349 setApplicationName(d->componentData.componentName());
00350 setOrganizationDomain(d->componentData.aboutData()->organizationDomain());
00351 installSigpipeHandler();
00352 d->init(GUIenabled);
00353 }
00354
00355 #ifdef Q_WS_X11
00356 KApplication::KApplication(Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap)
00357 : QApplication((KApplicationPrivate::preqapplicationhack(),dpy), KCmdLineArgs::qtArgc(), KCmdLineArgs::qtArgv(), visual, colormap),
00358 d(new KApplicationPrivate(this))
00359 {
00360 d->read_app_startup_id();
00361 setApplicationName(d->componentData.componentName());
00362 setOrganizationDomain(d->componentData.aboutData()->organizationDomain());
00363 installSigpipeHandler();
00364 d->init();
00365 }
00366
00367 KApplication::KApplication(Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap, const KComponentData &cData)
00368 : QApplication((KApplicationPrivate::preqapplicationhack(),dpy), KCmdLineArgs::qtArgc(), KCmdLineArgs::qtArgv(), visual, colormap),
00369 d (new KApplicationPrivate(this, cData))
00370 {
00371 d->read_app_startup_id();
00372 setApplicationName(d->componentData.componentName());
00373 setOrganizationDomain(d->componentData.aboutData()->organizationDomain());
00374 installSigpipeHandler();
00375 d->init();
00376 }
00377 #endif
00378
00379 KApplication::KApplication(bool GUIenabled, const KComponentData &cData)
00380 : QApplication((KApplicationPrivate::preqapplicationhack(),KCmdLineArgs::qtArgc()), KCmdLineArgs::qtArgv(), GUIenabled),
00381 d (new KApplicationPrivate(this, cData))
00382 {
00383 d->read_app_startup_id();
00384 setApplicationName(d->componentData.componentName());
00385 setOrganizationDomain(d->componentData.aboutData()->organizationDomain());
00386 installSigpipeHandler();
00387 d->init();
00388 }
00389
00390 #ifdef Q_WS_X11
00391 KApplication::KApplication(Display *display, int& argc, char** argv, const QByteArray& rAppName,
00392 bool GUIenabled)
00393 : QApplication((KApplicationPrivate::preqapplicationhack(),display)),
00394 d(new KApplicationPrivate(this, rAppName))
00395 {
00396 Q_UNUSED(GUIenabled);
00397 d->read_app_startup_id();
00398 setApplicationName(QLatin1String(rAppName));
00399 installSigpipeHandler();
00400 KCmdLineArgs::initIgnore(argc, argv, rAppName.data());
00401 d->init();
00402 }
00403 #endif
00404
00405
00406
00407 void KApplicationPrivate::preqapplicationhack()
00408 {
00409 preread_app_startup_id();
00410 }
00411
00412 int KApplication::xioErrhandler( Display* dpy )
00413 {
00414 if(kapp)
00415 {
00416 #ifdef Q_WS_X11
00417 d->oldXIOErrorHandler( dpy );
00418 #else
00419 Q_UNUSED(dpy);
00420 #endif
00421 }
00422 exit( 1 );
00423 return 0;
00424 }
00425
00426 int KApplication::xErrhandler( Display* dpy, void* err_ )
00427 {
00428 #ifdef Q_WS_X11
00429 XErrorEvent* err = static_cast< XErrorEvent* >( err_ );
00430 if(kapp)
00431 {
00432
00433 d->oldXErrorHandler( dpy, err );
00434 }
00435 const QByteArray fatalXError = qgetenv("KDE_FATAL_X_ERROR");
00436 if (!fatalXError.isEmpty()) {
00437 abort();
00438 }
00439 #endif
00440 return 0;
00441 }
00442
00443 void KApplication::iceIOErrorHandler( _IceConn *conn )
00444 {
00445 emit aboutToQuit();
00446
00447 #ifdef Q_WS_X11
00448 if ( d->oldIceIOErrorHandler != NULL )
00449 (*d->oldIceIOErrorHandler)( conn );
00450 #endif
00451 exit( 1 );
00452 }
00453
00454 class KDETranslator : public QTranslator
00455 {
00456 public:
00457 KDETranslator(QObject *parent) : QTranslator(parent)
00458 {
00459 setObjectName(QLatin1String("kdetranslator"));
00460 }
00461
00462 virtual QString translate(const char* context,
00463 const char *sourceText,
00464 const char* message) const
00465 {
00466 return KGlobal::locale()->translateQt(context, sourceText, message);
00467 }
00468 };
00469
00470 void KApplicationPrivate::init(bool GUIenabled)
00471 {
00472 if ((getuid() != geteuid()) ||
00473 (getgid() != getegid()))
00474 {
00475 fprintf(stderr, "The KDE libraries are not designed to run with suid privileges.\n");
00476 ::exit(127);
00477 }
00478
00479 #ifdef Q_WS_MAC
00480 mac_initialize_dbus();
00481 #endif
00482
00483 if ( q->type() == KApplication::GuiClient )
00484 {
00485 const QStringList plugins = KGlobal::dirs()->resourceDirs( "qtplugins" );
00486 QStringList::ConstIterator it = plugins.begin();
00487 while (it != plugins.end()) {
00488 q->addLibraryPath( *it );
00489 ++it;
00490 }
00491 }
00492
00493 KApplication::KApp = q;
00494
00495 parseCommandLine();
00496
00497 if(GUIenabled)
00498 (void) KClipboardSynchronizer::self();
00499
00500 extern KDECORE_EXPORT bool kde_kdebug_enable_dbus_interface;
00501 kde_kdebug_enable_dbus_interface = true;
00502
00503 QApplication::setDesktopSettingsAware( false );
00504
00505 #ifdef Q_WS_X11 //FIXME(E)
00506
00507 if ( q->type() == KApplication::GuiClient ) {
00508 const int max = 20;
00509 Atom* atoms[max];
00510 char* names[max];
00511 Atom atoms_return[max];
00512 int n = 0;
00513
00514 atoms[n] = &atom_DesktopWindow;
00515 names[n++] = (char *) "KDE_DESKTOP_WINDOW";
00516
00517 atoms[n] = &atom_NetSupported;
00518 names[n++] = (char *) "_NET_SUPPORTED";
00519
00520 atoms[n] = &kde_xdnd_drop;
00521 names[n++] = (char *) "XdndDrop";
00522
00523 XInternAtoms( QX11Info::display(), names, n, false, atoms_return );
00524
00525 for (int i = 0; i < n; i++ )
00526 *atoms[i] = atoms_return[i];
00527 }
00528 #endif
00529
00530
00531
00532 extern void qDBusBindToApplication();
00533 qDBusBindToApplication();
00534 QDBusConnectionInterface *bus = 0;
00535 if (!QDBusConnection::sessionBus().isConnected() || !(bus = QDBusConnection::sessionBus().interface())) {
00536 }
00537
00538 extern bool s_kuniqueapplication_startCalled;
00539 if ( bus && !s_kuniqueapplication_startCalled )
00540 {
00541 QStringList parts = q->organizationDomain().split(QLatin1Char('.'), QString::SkipEmptyParts);
00542 QString reversedDomain;
00543 if (parts.isEmpty())
00544 reversedDomain = QLatin1String("local.");
00545 else
00546 foreach (const QString& s, parts)
00547 {
00548 reversedDomain.prepend(QLatin1Char('.'));
00549 reversedDomain.prepend(s);
00550 }
00551 const QString pidSuffix = QString::number( getpid() ).prepend( QLatin1String("-") );
00552 const QString serviceName = reversedDomain + q->applicationName() + pidSuffix;
00553 if ( bus->registerService(serviceName) == QDBusConnectionInterface::ServiceNotRegistered ) {
00554 kError(101) << "Couldn't register name '" << serviceName << "' with DBUS - another process owns it already!" << endl;
00555 ::exit(126);
00556 }
00557 }
00558 QDBusConnection::sessionBus().registerObject(QLatin1String("/MainApplication"), q,
00559 QDBusConnection::ExportScriptableSlots |
00560 QDBusConnection::ExportScriptableProperties |
00561 QDBusConnection::ExportAdaptors);
00562
00563
00564 (void) KGlobal::locale();
00565
00566 KSharedConfig::Ptr config = componentData.config();
00567 QByteArray readOnly = qgetenv("KDE_HOME_READONLY");
00568 if (readOnly.isEmpty() && q->applicationName() != QLatin1String("kdialog"))
00569 {
00570 if (KAuthorized::authorize(QLatin1String("warn_unwritable_config")))
00571 config->isConfigWritable(true);
00572 }
00573
00574 if (q->type() == KApplication::GuiClient)
00575 {
00576 #ifdef Q_WS_X11
00577
00578 fcntl(ConnectionNumber(QX11Info::display()), F_SETFD, FD_CLOEXEC);
00579
00580 oldXErrorHandler = XSetErrorHandler( kde_x_errhandler );
00581 oldXIOErrorHandler = XSetIOErrorHandler( kde_xio_errhandler );
00582 #endif
00583
00584
00585 KGlobalSettings::self();
00586
00587 KMessage::setMessageHandler( new KMessageBoxMessageHandler(0) );
00588
00589 checkAccelerators = new KCheckAccelerators( q );
00590 KGestureMap::self()->installEventFilterOnMe( q );
00591
00592 q->connect(KToolInvocation::self(), SIGNAL(kapplication_hook(QStringList&, QByteArray&)),
00593 q, SLOT(_k_slot_KToolInvocation_hook(QStringList&,QByteArray&)));
00594 }
00595
00596 #ifdef Q_WS_MAC
00597 if (q->type() == KApplication::GuiClient) {
00598
00599 QSystemTrayIcon *trayIcon;
00600 if (QSystemTrayIcon::isSystemTrayAvailable())
00601 {
00602 trayIcon = new QSystemTrayIcon(q);
00603 trayIcon->setIcon(q->windowIcon());
00604
00605
00606
00607 }
00608 }
00609 #endif
00610
00611
00612
00613
00614
00615 bool rtl = q->isRightToLeft();
00616 q->installTranslator(new KDETranslator(q));
00617 q->setLayoutDirection( rtl ? Qt::RightToLeft:Qt::LeftToRight);
00618 if (i18nc( "Dear Translator! Translate this string to the string 'LTR' in "
00619 "left-to-right languages (as English) or to 'RTL' in right-to-left "
00620 "languages (such as Hebrew and Arabic) to get proper widget layout.",
00621 "LTR" ) == QLatin1String("RTL"))
00622 rtl = !rtl;
00623 q->setLayoutDirection( rtl ? Qt::RightToLeft:Qt::LeftToRight);
00624
00625 qRegisterMetaType<KUrl>();
00626 qRegisterMetaType<KUrl::List>();
00627
00628 #ifdef Q_WS_WIN
00629 KApplication_init_windows();
00630 #endif
00631 }
00632
00633 KApplication* KApplication::kApplication()
00634 {
00635 return KApp;
00636 }
00637
00638 KConfig* KApplication::sessionConfig()
00639 {
00640 if (!d->pSessionConfig)
00641 d->pSessionConfig = new KConfig( d->sessionConfigName(), KConfig::SimpleConfig );
00642 return d->pSessionConfig;
00643 }
00644
00645 void KApplication::reparseConfiguration()
00646 {
00647 KGlobal::config()->reparseConfiguration();
00648 }
00649
00650 void KApplication::quit()
00651 {
00652 QApplication::quit();
00653 }
00654
00655 void KApplication::disableSessionManagement() {
00656 d->bSessionManagement = false;
00657 }
00658
00659 void KApplication::enableSessionManagement() {
00660 d->bSessionManagement = true;
00661 #ifdef Q_WS_X11
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671 if( mySmcConnection ) {
00672 SmcRequestSaveYourself( mySmcConnection, SmSaveLocal, False,
00673 SmInteractStyleAny,
00674 False, False );
00675
00676
00677 IceFlush(SmcGetIceConnection(mySmcConnection));
00678 }
00679 #endif
00680 }
00681
00682 void KApplication::commitData( QSessionManager& sm )
00683 {
00684 d->session_save = true;
00685 bool canceled = false;
00686
00687 foreach (KSessionManager *it, KSessionManager::sessionClients()) {
00688 if ( ( canceled = !it->commitData( sm ) ) )
00689 break;
00690 }
00691
00692 if ( canceled )
00693 sm.cancel();
00694
00695 if ( sm.allowsInteraction() ) {
00696 QWidgetList donelist, todolist;
00697 QWidget* w;
00698
00699 commitDataRestart:
00700 todolist = QApplication::topLevelWidgets();
00701
00702 for ( int i = 0; i < todolist.size(); ++i ) {
00703 w = todolist.at( i );
00704 if( !w )
00705 break;
00706
00707 if ( donelist.contains( w ) )
00708 continue;
00709
00710 if ( !w->isHidden() && !w->inherits( "KMainWindow" ) ) {
00711 QCloseEvent e;
00712 sendEvent( w, &e );
00713 if ( !e.isAccepted() )
00714 break;
00715
00716 donelist.append( w );
00717
00718
00719 goto commitDataRestart;
00720 }
00721 }
00722 }
00723
00724 if ( !d->bSessionManagement )
00725 sm.setRestartHint( QSessionManager::RestartNever );
00726 else
00727 sm.setRestartHint( QSessionManager::RestartIfRunning );
00728 d->session_save = false;
00729 }
00730
00731 #ifdef Q_WS_X11
00732 static void checkRestartVersion( QSessionManager& sm )
00733 {
00734 Display* dpy = QX11Info::display();
00735 Atom type;
00736 int format;
00737 unsigned long nitems, after;
00738 unsigned char* data;
00739 if( XGetWindowProperty( dpy, RootWindow( dpy, 0 ), XInternAtom( dpy, "KDE_SESSION_VERSION", False ),
00740 0, 1, False, AnyPropertyType, &type, &format, &nitems, &after, &data ) == Success ) {
00741 if( type == XA_INTEGER && format == 32 ) {
00742 int version = *( long* ) data;
00743 if( version == KDE_VERSION_MAJOR ) {
00744 XFree( data );
00745 return;
00746 }
00747 }
00748 XFree( data );
00749 }
00750 #define NUM_TO_STRING2( num ) #num
00751 #define NUM_TO_STRING( num ) NUM_TO_STRING2( num )
00752 QString wrapper = KStandardDirs::findExe( "kde" NUM_TO_STRING( KDE_VERSION_MAJOR ) );
00753 #undef NUM_TO_STRING
00754 #undef NUM_TO_STRING2
00755 QStringList restartCommand = sm.restartCommand();
00756 restartCommand.prepend( wrapper );
00757 sm.setRestartCommand( restartCommand );
00758 }
00759 #endif // Q_WS_X11
00760
00761 void KApplication::saveState( QSessionManager& sm )
00762 {
00763 d->session_save = true;
00764 #ifdef Q_WS_X11
00765 static bool firstTime = true;
00766 mySmcConnection = (SmcConn) sm.handle();
00767
00768 if ( !d->bSessionManagement ) {
00769 sm.setRestartHint( QSessionManager::RestartNever );
00770 d->session_save = false;
00771 return;
00772 }
00773 else
00774 sm.setRestartHint( QSessionManager::RestartIfRunning );
00775
00776 if ( firstTime ) {
00777 firstTime = false;
00778 d->session_save = false;
00779 return;
00780 }
00781
00782
00783
00784
00785
00786
00787
00788 if ( d->pSessionConfig ) {
00789 delete d->pSessionConfig;
00790 d->pSessionConfig = 0;
00791 }
00792
00793
00794 QStringList restartCommand = sm.restartCommand();
00795
00796 QByteArray multiHead = qgetenv("KDE_MULTIHEAD");
00797 if (multiHead.toLower() == "true") {
00798
00799
00800
00801
00802
00803
00804 QByteArray displayname = qgetenv("DISPLAY");
00805 if (! displayname.isNull()) {
00806
00807
00808 restartCommand.append(QLatin1String("-display"));
00809 restartCommand.append(QLatin1String(displayname));
00810 }
00811 sm.setRestartCommand( restartCommand );
00812 }
00813
00814 #ifdef Q_WS_X11
00815 checkRestartVersion( sm );
00816 #endif
00817
00818
00819 emit saveYourself();
00820 bool canceled = false;
00821 foreach(KSessionManager* it, KSessionManager::sessionClients()) {
00822 if(canceled) break;
00823 canceled = !it->saveState( sm );
00824 }
00825
00826
00827 if ( d->pSessionConfig ) {
00828 d->pSessionConfig->sync();
00829 QStringList discard;
00830 discard << QLatin1String("rm") << KStandardDirs::locateLocal("config", d->sessionConfigName());
00831 sm.setDiscardCommand( discard );
00832 } else {
00833 sm.setDiscardCommand( QStringList( QLatin1String("") ) );
00834 }
00835
00836 if ( canceled )
00837 sm.cancel();
00838 #else
00839
00840 #endif
00841 d->session_save = false;
00842 }
00843
00844 bool KApplication::sessionSaving() const
00845 {
00846 return d->session_save;
00847 }
00848
00849 void KApplicationPrivate::parseCommandLine( )
00850 {
00851 KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
00852
00853 #ifdef Q_WS_X11
00854 if (args && args->isSet("style"))
00855 {
00856 extern QString kde_overrideStyle;
00857 QString reqStyle(args->getOption("style").toLower());
00858 if (QStyleFactory::keys().contains(reqStyle, Qt::CaseInsensitive))
00859 kde_overrideStyle = reqStyle;
00860 else
00861 qWarning() << i18n("The style '%1' was not found", reqStyle);
00862 }
00863 #endif
00864
00865 if ( q->type() != KApplication::Tty ) {
00866 if (args && args->isSet("icon"))
00867 {
00868 q->setWindowIcon(KIcon(args->getOption("icon")));
00869 }
00870 else {
00871 q->setWindowIcon(KIcon(componentData.aboutData()->programIconName()));
00872 }
00873 }
00874
00875 if (!args)
00876 return;
00877
00878 if (args->isSet("config"))
00879 {
00880 QString config = args->getOption("config");
00881 componentData.setConfigName(config);
00882 }
00883
00884 bool nocrashhandler = (!qgetenv("KDE_DEBUG").isEmpty());
00885 if (!nocrashhandler && args->isSet("crashhandler"))
00886 {
00887
00888 KCrash::setCrashHandler(KCrash::defaultCrashHandler);
00889 }
00890
00891 KCrash::setApplicationName(args->appName());
00892
00893 #ifdef Q_WS_X11
00894 if ( args->isSet( "waitforwm" ) ) {
00895 Atom type;
00896 (void) q->desktop();
00897 int format;
00898 unsigned long length, after;
00899 unsigned char *data;
00900 while ( XGetWindowProperty( QX11Info::display(), QX11Info::appRootWindow(), atom_NetSupported,
00901 0, 1, false, AnyPropertyType, &type, &format,
00902 &length, &after, &data ) != Success || !length ) {
00903 if ( data )
00904 XFree( data );
00905 XEvent event;
00906 XWindowEvent( QX11Info::display(), QX11Info::appRootWindow(), PropertyChangeMask, &event );
00907 }
00908 if ( data )
00909 XFree( data );
00910 }
00911 #else
00912
00913 #endif
00914
00915 #ifndef Q_WS_WIN
00916 if (args->isSet("smkey"))
00917 {
00918 sessionKey = args->getOption("smkey");
00919 }
00920 #endif
00921 }
00922
00923 extern void kDebugCleanup();
00924
00925 KApplication::~KApplication()
00926 {
00927 #ifdef Q_WS_X11
00928 if ( d->oldXErrorHandler != NULL )
00929 XSetErrorHandler( d->oldXErrorHandler );
00930 if ( d->oldXIOErrorHandler != NULL )
00931 XSetIOErrorHandler( d->oldXIOErrorHandler );
00932 if ( d->oldIceIOErrorHandler != NULL )
00933 IceSetIOErrorHandler( d->oldIceIOErrorHandler );
00934 #endif
00935
00936 delete d;
00937 KApp = 0;
00938
00939 #ifdef Q_WS_X11
00940 mySmcConnection = 0;
00941 #else
00942
00943 #endif
00944 }
00945
00946
00947 #ifdef Q_WS_X11
00948 class KAppX11HackWidget: public QWidget
00949 {
00950 public:
00951 bool publicx11Event( XEvent * e) { return x11Event( e ); }
00952 };
00953 #endif
00954
00955
00956
00957 #ifdef Q_WS_X11
00958 bool KApplication::x11EventFilter( XEvent *_event )
00959 {
00960 switch ( _event->type ) {
00961 case ClientMessage:
00962 {
00963 #if KDE_IS_VERSION( 3, 90, 90 )
00964 #ifdef __GNUC__
00965 #warning This should be already in Qt, check.
00966 #endif
00967 #endif
00968
00969
00970
00971
00972
00973 if( _event->xclient.message_type == kde_xdnd_drop )
00974 {
00975 if( _event->xclient.data.l[ 1 ] == 1 << 24
00976 && _event->xclient.data.l[ 2 ] == 0
00977 && _event->xclient.data.l[ 4 ] == 0
00978 && _event->xclient.data.l[ 3 ] != 0 )
00979 {
00980 if( QX11Info::appUserTime() == 0
00981 || NET::timestampCompare( _event->xclient.data.l[ 3 ], QX11Info::appUserTime() ) > 0 )
00982 {
00983 QX11Info::setAppUserTime(_event->xclient.data.l[ 3 ]);
00984 }
00985 }
00986 else
00987 {
00988 if( QX11Info::appUserTime() == 0
00989 || NET::timestampCompare( _event->xclient.data.l[ 2 ], QX11Info::appUserTime() ) > 0 )
00990 {
00991 QX11Info::setAppUserTime(_event->xclient.data.l[ 2 ]);
00992 }
00993 }
00994 }
00995 }
00996 default: break;
00997 }
00998
00999 if (x11Filter) {
01000 foreach (const QWidget *w, *x11Filter) {
01001 if (((KAppX11HackWidget*) w)->publicx11Event(_event))
01002 return true;
01003 }
01004 }
01005
01006 return false;
01007 }
01008 #endif // Q_WS_X11
01009
01010 void KApplication::updateUserTimestamp( int time )
01011 {
01012 #if defined Q_WS_X11
01013 if( time == 0 )
01014 {
01015 Window w = XCreateSimpleWindow( QX11Info::display(), QX11Info::appRootWindow(), 0, 0, 1, 1, 0, 0, 0 );
01016 XSelectInput( QX11Info::display(), w, PropertyChangeMask );
01017 unsigned char data[ 1 ];
01018 XChangeProperty( QX11Info::display(), w, XA_ATOM, XA_ATOM, 8, PropModeAppend, data, 1 );
01019 XEvent ev;
01020 XWindowEvent( QX11Info::display(), w, PropertyChangeMask, &ev );
01021 time = ev.xproperty.time;
01022 XDestroyWindow( QX11Info::display(), w );
01023 }
01024 if( QX11Info::appUserTime() == 0
01025 || NET::timestampCompare( time, QX11Info::appUserTime()) > 0 )
01026 QX11Info::setAppUserTime(time);
01027 if( QX11Info::appTime() == 0
01028 || NET::timestampCompare( time, QX11Info::appTime()) > 0 )
01029 QX11Info::setAppTime(time);
01030 #endif
01031 }
01032
01033 unsigned long KApplication::userTimestamp() const
01034 {
01035 #if defined Q_WS_X11
01036 return QX11Info::appUserTime();
01037 #else
01038 return 0;
01039 #endif
01040 }
01041
01042 void KApplication::updateRemoteUserTimestamp( const QString& service, int time )
01043 {
01044 #if defined Q_WS_X11
01045 Q_ASSERT(service.contains('.'));
01046 if( time == 0 )
01047 time = QX11Info::appUserTime();
01048 QDBusInterface(service, QLatin1String("/MainApplication"),
01049 QString(QLatin1String("org.kde.KApplication")))
01050 .call(QLatin1String("updateUserTimestamp"), time);
01051 #endif
01052 }
01053
01054
01055 QString KApplication::tempSaveName( const QString& pFilename )
01056 {
01057 QString aFilename;
01058
01059 if( QDir::isRelativePath(pFilename) )
01060 {
01061 kWarning(101) << "Relative filename passed to KApplication::tempSaveName";
01062 aFilename = QFileInfo( QDir( QLatin1String(".") ), pFilename ).absoluteFilePath();
01063 }
01064 else
01065 aFilename = pFilename;
01066
01067 QDir aAutosaveDir( QDir::homePath() + QLatin1String("/autosave/") );
01068 if( !aAutosaveDir.exists() )
01069 {
01070 if( !aAutosaveDir.mkdir( aAutosaveDir.absolutePath() ) )
01071 {
01072
01073 aAutosaveDir.setPath( KGlobal::dirs()->saveLocation("tmp") );
01074 }
01075 }
01076
01077 aFilename.replace( '/', QLatin1String("\\!") )
01078 .prepend( QLatin1Char('#') )
01079 .append( QLatin1Char('#') )
01080 .prepend( QLatin1Char('/') ).prepend( aAutosaveDir.absolutePath() );
01081
01082 return aFilename;
01083 }
01084
01085
01086 QString KApplication::checkRecoverFile( const QString& pFilename,
01087 bool& bRecover )
01088 {
01089 QString aFilename;
01090
01091 if( QDir::isRelativePath(pFilename) )
01092 {
01093 kWarning(101) << "Relative filename passed to KApplication::tempSaveName";
01094 aFilename = QFileInfo( QDir( QLatin1String(".") ), pFilename ).absoluteFilePath();
01095 }
01096 else
01097 aFilename = pFilename;
01098
01099 QDir aAutosaveDir( QDir::homePath() + QLatin1String("/autosave/") );
01100 if( !aAutosaveDir.exists() )
01101 {
01102 if( !aAutosaveDir.mkdir( aAutosaveDir.absolutePath() ) )
01103 {
01104
01105 aAutosaveDir.setPath( KGlobal::dirs()->saveLocation("tmp") );
01106 }
01107 }
01108
01109 aFilename.replace( QLatin1String("/"), QLatin1String("\\!") )
01110 .prepend( QLatin1Char('#') )
01111 .append( QLatin1Char('#') )
01112 .prepend( QLatin1Char('/') )
01113 .prepend( aAutosaveDir.absolutePath() );
01114
01115 if( QFile( aFilename ).exists() )
01116 {
01117 bRecover = true;
01118 return aFilename;
01119 }
01120 else
01121 {
01122 bRecover = false;
01123 return pFilename;
01124 }
01125 }
01126
01127
01128 void KApplication::setTopWidget( QWidget *topWidget )
01129 {
01130 if( !topWidget )
01131 return;
01132
01133
01134 if ( !topWidget->inherits("KMainWindow") ) {
01135 topWidget->setWindowTitle(KGlobal::caption());
01136 }
01137
01138 #if defined Q_WS_X11
01139
01140
01141 KStartupInfo::setWindowStartupId( topWidget->winId(), startupId());
01142 #endif
01143 }
01144
01145 QByteArray KApplication::startupId() const
01146 {
01147 return d->startup_id;
01148 }
01149
01150 void KApplication::setStartupId( const QByteArray& startup_id )
01151 {
01152 if( startup_id == d->startup_id )
01153 return;
01154 #if defined Q_WS_X11
01155 KStartupInfo::handleAutoAppStartedSending();
01156 #endif
01157 if( startup_id.isEmpty())
01158 d->startup_id = "0";
01159 else
01160 {
01161 d->startup_id = startup_id;
01162 #if defined Q_WS_X11
01163 KStartupInfoId id;
01164 id.initId( startup_id );
01165 long timestamp = id.timestamp();
01166 if( timestamp != 0 )
01167 updateUserTimestamp( timestamp );
01168 #endif
01169 }
01170 }
01171
01172 void KApplication::clearStartupId()
01173 {
01174 d->startup_id = "0";
01175 }
01176
01177
01178
01179
01180 void KApplicationPrivate::preread_app_startup_id()
01181 {
01182 #if defined Q_WS_X11
01183 KStartupInfoId id = KStartupInfo::currentStartupIdEnv();
01184 KStartupInfo::resetStartupEnv();
01185 startup_id_tmp = new QByteArray( id.id());
01186 #endif
01187 }
01188
01189
01190
01191 void KApplicationPrivate::read_app_startup_id()
01192 {
01193 #if defined Q_WS_X11
01194 startup_id = *startup_id_tmp;
01195 delete startup_id_tmp;
01196 startup_id_tmp = NULL;
01197 #endif
01198 }
01199
01200
01201 void KApplicationPrivate::_k_slot_KToolInvocation_hook(QStringList& envs,QByteArray& startup_id)
01202 {
01203 #ifdef Q_WS_X11
01204 if (QX11Info::display()) {
01205 QByteArray dpystring(XDisplayString(QX11Info::display()));
01206 envs << QString::fromLatin1( QByteArray("DISPLAY=") + dpystring );
01207 } else {
01208 const QByteArray dpystring( qgetenv( "DISPLAY" ));
01209 if(!dpystring.isEmpty())
01210 envs << QString::fromLatin1( QByteArray("DISPLAY=") + dpystring );
01211 }
01212
01213 if(startup_id.isEmpty())
01214 startup_id = KStartupInfo::createNewStartupId();
01215 #else
01216 Q_UNUSED(envs);
01217 Q_UNUSED(startup_id);
01218 #endif
01219 }
01220
01221 void KApplication::setSynchronizeClipboard(bool synchronize)
01222 {
01223 KClipboardSynchronizer::self()->setSynchronizing(synchronize);
01224 KClipboardSynchronizer::self()->setReverseSynchronizing(synchronize);
01225 }
01226
01227 #include "kapplication.moc"
01228