tdeapplication.cpp
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org) 00003 Copyright (C) 1998, 1999, 2000 KDE Team 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include "config.h" 00022 00023 #ifdef HAVE_XCOMPOSITE 00024 #define COMPOSITE 00025 #endif 00026 00027 // #ifdef QTRANSLATOR_H 00028 // #error qtranslator.h was already included 00029 // #endif // QTRANSLATOR_H 00030 // 00031 // #ifdef TQTRANSLATOR_H 00032 // #error tqtranslator.h was already included 00033 // #endif // TQTRANSLATOR_H 00034 00035 #undef QT_NO_TRANSLATION 00036 #undef TQT_NO_TRANSLATION 00037 #include <tqtranslator.h> 00038 00039 // FIXME 00040 // FOR BINARY COMPATIBILITY ONLY 00041 // REMOVE WHEN PRACTICAL! 00042 #define TDEAPPLICATION_BINARY_COMPAT_HACK 1 00043 #include "tdeapplication.h" 00044 #undef TDEAPPLICATION_BINARY_COMPAT_HACK 00045 00046 #define QT_NO_TRANSLATION 00047 #define TQT_NO_TRANSLATION 00048 #include <tqdir.h> 00049 #include <tqptrcollection.h> 00050 #include <tqwidgetlist.h> 00051 #include <tqstrlist.h> 00052 #include <tqfile.h> 00053 #include <tqmessagebox.h> 00054 #include <tqtextstream.h> 00055 #include <tqregexp.h> 00056 #include <tqlineedit.h> 00057 #include <tqtextedit.h> 00058 #include <tqsessionmanager.h> 00059 #include <tqptrlist.h> 00060 #include <tqtimer.h> 00061 #include <tqstylesheet.h> 00062 #include <tqpixmapcache.h> 00063 #include <tqtooltip.h> 00064 #include <tqstylefactory.h> 00065 #include <tqmetaobject.h> 00066 #include <tqimage.h> 00067 #ifndef QT_NO_SQL 00068 #include <tqsqlpropertymap.h> 00069 #endif 00070 00071 #include <tdeglobal.h> 00072 #include <kstandarddirs.h> 00073 #include <kdebug.h> 00074 #include <tdelocale.h> 00075 #include <tdestyle.h> 00076 #include <kiconloader.h> 00077 #include <kclipboard.h> 00078 #include <tdeconfig.h> 00079 #include <ksimpleconfig.h> 00080 #include <tdecmdlineargs.h> 00081 #include <tdeaboutdata.h> 00082 #include <tdeglobalsettings.h> 00083 #include <kcrash.h> 00084 #include <kdatastream.h> 00085 #include <klibloader.h> 00086 #include <kmimesourcefactory.h> 00087 #include <tdestdaccel.h> 00088 #include <tdeaccel.h> 00089 #include "kcheckaccelerators.h" 00090 #include <tqptrdict.h> 00091 #include <kmacroexpander.h> 00092 #include <kshell.h> 00093 #include <kprotocolinfo.h> 00094 #include <kkeynative.h> 00095 #include <kmdcodec.h> 00096 #include <kglobalaccel.h> 00097 00098 #if defined Q_WS_X11 00099 #include <tdestartupinfo.h> 00100 #endif 00101 00102 #include <dcopclient.h> 00103 #include <dcopref.h> 00104 00105 #include <sys/types.h> 00106 #ifdef HAVE_SYS_STAT_H 00107 #include <sys/stat.h> 00108 #endif 00109 #include <sys/wait.h> 00110 #include <grp.h> 00111 #include <sys/types.h> 00112 00113 #ifndef Q_WS_WIN 00114 #include "twin.h" 00115 #endif 00116 00117 #include <fcntl.h> 00118 #include <stdlib.h> // getenv(), srand(), rand() 00119 #include <signal.h> 00120 #include <unistd.h> 00121 #include <time.h> 00122 #include <sys/time.h> 00123 #include <errno.h> 00124 #include <string.h> 00125 #include <netdb.h> 00126 #if defined Q_WS_X11 00127 //#ifndef Q_WS_QWS //FIXME(E): NetWM should talk to QWS... 00128 #include <netwm.h> 00129 #endif 00130 00131 #include "kprocctrl.h" 00132 00133 #ifdef HAVE_PATHS_H 00134 #include <paths.h> 00135 #endif 00136 00137 #ifdef Q_WS_X11 00138 #include <X11/Xlib.h> 00139 #ifdef COMPOSITE 00140 #include <X11/extensions/Xrender.h> 00141 #include <X11/extensions/Xcomposite.h> 00142 #include <dlfcn.h> 00143 #endif 00144 #include <X11/Xutil.h> 00145 #include <X11/Xatom.h> 00146 #include <X11/SM/SMlib.h> 00147 #include <fixx11h.h> 00148 #endif 00149 00150 #include <pwd.h> 00151 00152 #ifndef Q_WS_WIN 00153 #include <KDE-ICE/ICElib.h> 00154 #else 00155 typedef void* IceIOErrorHandler; 00156 #include <windows.h> 00157 //KDE4: remove 00158 #define Button1Mask (1<<8) 00159 #define Button2Mask (1<<9) 00160 #define Button3Mask (1<<10) 00161 #endif 00162 00163 #ifdef Q_WS_X11 00164 #define DISPLAY "DISPLAY" 00165 #elif defined(Q_WS_QWS) 00166 #define DISPLAY "QWS_DISPLAY" 00167 #endif 00168 00169 #if defined Q_WS_X11 00170 #include <kipc.h> 00171 #endif 00172 00173 #ifdef Q_WS_MACX 00174 #include <Carbon/Carbon.h> 00175 #include <tqimage.h> 00176 #endif 00177 00178 #if defined Q_WS_X11 00179 #include <sys/ioctl.h> 00180 #ifdef __linux__ 00181 #include <linux/vt.h> 00182 #endif 00183 extern "C" { 00184 extern int getfd(const char *fnam); 00185 } 00186 #endif 00187 00188 #include "kappdcopiface.h" 00189 00190 // exported for tdm kfrontend 00191 KDE_EXPORT bool kde_have_kipc = true; // magic hook to disable kipc in tdm 00192 bool kde_kiosk_exception = false; // flag to disable kiosk restrictions 00193 bool kde_kiosk_admin = false; 00194 00195 TDEApplication* TDEApplication::KApp = 0L; 00196 bool TDEApplication::loadedByKdeinit = false; 00197 DCOPClient *TDEApplication::s_DCOPClient = 0L; 00198 bool TDEApplication::s_dcopClientNeedsPostInit = false; 00199 00200 #ifdef Q_WS_X11 00201 static Atom atom_DesktopWindow; 00202 static Atom atom_NetSupported; 00203 #endif 00204 00205 #if defined(Q_WS_X11) && defined(COMPOSITE) 00206 static int composite_event, composite_error, composite_opcode; 00207 static bool x11_composite_error_generated; 00208 static int x11_error(Display *dpy, XErrorEvent *ev) { 00209 if (ev->request_code == composite_opcode && ev->minor_code == X_CompositeRedirectSubwindows) 00210 { 00211 x11_composite_error_generated = true; 00212 return 0; 00213 } 00214 return 1; 00215 } 00216 #endif 00217 00218 // duplicated from patched Qt, so that there won't be unresolved symbols if Qt gets 00219 // replaced by unpatched one 00220 TDECORE_EXPORT bool tqt_qclipboard_bailout_hack = false; 00221 00222 template class TQPtrList<KSessionManaged>; 00223 00224 #ifdef Q_WS_X11 00225 extern "C" { 00226 static int kde_xio_errhandler( Display * dpy ) 00227 { 00228 return kapp->xioErrhandler( dpy ); 00229 } 00230 00231 static int kde_x_errhandler( Display *dpy, XErrorEvent *err ) 00232 { 00233 return kapp->xErrhandler( dpy, err ); 00234 } 00235 00236 } 00237 00238 extern "C" { 00239 static void kde_ice_ioerrorhandler( IceConn conn ) 00240 { 00241 if(kapp) 00242 kapp->iceIOErrorHandler( conn ); 00243 // else ignore the error for now 00244 } 00245 } 00246 #endif 00247 00248 #ifdef Q_WS_WIN 00249 void TDEApplication_init_windows(bool GUIenabled); 00250 00251 class QAssistantClient; 00252 #endif 00253 00254 #ifdef Q_WS_X11 00255 // -------------------------------------------------------------------------------------- 00256 // Get the VT number X is running on 00257 // (code taken from GDM, daemon/getvt.c, GPLv2+) 00258 // -------------------------------------------------------------------------------------- 00259 int get_x_vtnum(Display *dpy) 00260 { 00261 Atom prop; 00262 Atom actualtype; 00263 int actualformat; 00264 unsigned long nitems; 00265 unsigned long bytes_after; 00266 unsigned char *buf; 00267 int num; 00268 00269 prop = XInternAtom (dpy, "XFree86_VT", False); 00270 if (prop == None) 00271 return -1; 00272 00273 if (XGetWindowProperty (dpy, DefaultRootWindow (dpy), prop, 0, 1, 00274 False, AnyPropertyType, &actualtype, &actualformat, 00275 &nitems, &bytes_after, &buf)) { 00276 return -1; 00277 } 00278 00279 if (nitems != 1) { 00280 XFree (buf); 00281 return -1; 00282 } 00283 00284 switch (actualtype) { 00285 case XA_CARDINAL: 00286 case XA_INTEGER: 00287 case XA_WINDOW: 00288 switch (actualformat) { 00289 case 8: 00290 num = (*(uint8_t *)(void *)buf); 00291 break; 00292 case 16: 00293 num = (*(uint16_t *)(void *)buf); 00294 break; 00295 case 32: 00296 num = (*(uint32_t *)(void *)buf); 00297 break; 00298 default: 00299 XFree (buf); 00300 return -1; 00301 } 00302 break; 00303 default: 00304 XFree (buf); 00305 return -1; 00306 } 00307 00308 XFree (buf); 00309 00310 return num; 00311 } 00312 // -------------------------------------------------------------------------------------- 00313 #endif // Q_WS_X11 00314 00315 /* 00316 Private data to make keeping binary compatibility easier 00317 */ 00318 class TDEApplicationPrivate 00319 { 00320 public: 00321 TDEApplicationPrivate() 00322 : actionRestrictions( false ), 00323 refCount( 1 ), 00324 oldIceIOErrorHandler( 0 ), 00325 checkAccelerators( 0 ), 00326 overrideStyle( TQString::null ), 00327 startup_id( "0" ), 00328 app_started_timer( NULL ), 00329 m_KAppDCOPInterface( 0L ), 00330 session_save( false ) 00331 #ifdef Q_WS_X11 00332 ,oldXErrorHandler( NULL ) 00333 ,oldXIOErrorHandler( NULL ) 00334 #elif defined Q_WS_WIN 00335 ,qassistantclient( 0 ) 00336 #endif 00337 { 00338 } 00339 00340 ~TDEApplicationPrivate() 00341 { 00342 #ifdef Q_WS_WIN 00343 delete qassistantclient; 00344 #endif 00345 } 00346 00347 00348 bool actionRestrictions : 1; 00349 bool guiEnabled : 1; 00356 int refCount; 00357 IceIOErrorHandler oldIceIOErrorHandler; 00358 KCheckAccelerators* checkAccelerators; 00359 TQString overrideStyle; 00360 TQString geometry_arg; 00361 TQCString startup_id; 00362 TQTimer* app_started_timer; 00363 KAppDCOPInterface *m_KAppDCOPInterface; 00364 bool session_save; 00365 #ifdef Q_WS_X11 00366 int (*oldXErrorHandler)(Display*,XErrorEvent*); 00367 int (*oldXIOErrorHandler)(Display*); 00368 #elif defined Q_WS_WIN 00369 QAssistantClient* qassistantclient; 00370 #endif 00371 00372 class URLActionRule 00373 { 00374 public: 00375 #define checkExactMatch(s, b) \ 00376 if (s.isEmpty()) b = true; \ 00377 else if (s[s.length()-1] == '!') \ 00378 { b = false; s.truncate(s.length()-1); } \ 00379 else b = true; 00380 #define checkStartWildCard(s, b) \ 00381 if (s.isEmpty()) b = true; \ 00382 else if (s[0] == '*') \ 00383 { b = true; s = s.mid(1); } \ 00384 else b = false; 00385 #define checkEqual(s, b) \ 00386 b = (s == "="); 00387 00388 URLActionRule(const TQString &act, 00389 const TQString &bProt, const TQString &bHost, const TQString &bPath, 00390 const TQString &dProt, const TQString &dHost, const TQString &dPath, 00391 bool perm) 00392 : action(act), 00393 baseProt(bProt), baseHost(bHost), basePath(bPath), 00394 destProt(dProt), destHost(dHost), destPath(dPath), 00395 permission(perm) 00396 { 00397 checkExactMatch(baseProt, baseProtWildCard); 00398 checkStartWildCard(baseHost, baseHostWildCard); 00399 checkExactMatch(basePath, basePathWildCard); 00400 checkExactMatch(destProt, destProtWildCard); 00401 checkStartWildCard(destHost, destHostWildCard); 00402 checkExactMatch(destPath, destPathWildCard); 00403 checkEqual(destProt, destProtEqual); 00404 checkEqual(destHost, destHostEqual); 00405 } 00406 00407 bool baseMatch(const KURL &url, const TQString &protClass) 00408 { 00409 if (baseProtWildCard) 00410 { 00411 if ( !baseProt.isEmpty() && !url.protocol().startsWith(baseProt) && 00412 (protClass.isEmpty() || (protClass != baseProt)) ) 00413 return false; 00414 } 00415 else 00416 { 00417 if ( (url.protocol() != baseProt) && 00418 (protClass.isEmpty() || (protClass != baseProt)) ) 00419 return false; 00420 } 00421 if (baseHostWildCard) 00422 { 00423 if (!baseHost.isEmpty() && !url.host().endsWith(baseHost)) 00424 return false; 00425 } 00426 else 00427 { 00428 if (url.host() != baseHost) 00429 return false; 00430 } 00431 if (basePathWildCard) 00432 { 00433 if (!basePath.isEmpty() && !url.path().startsWith(basePath)) 00434 return false; 00435 } 00436 else 00437 { 00438 if (url.path() != basePath) 00439 return false; 00440 } 00441 return true; 00442 } 00443 00444 bool destMatch(const KURL &url, const TQString &protClass, const KURL &base, const TQString &baseClass) 00445 { 00446 if (destProtEqual) 00447 { 00448 if ( (url.protocol() != base.protocol()) && 00449 (protClass.isEmpty() || baseClass.isEmpty() || protClass != baseClass) ) 00450 return false; 00451 } 00452 else if (destProtWildCard) 00453 { 00454 if ( !destProt.isEmpty() && !url.protocol().startsWith(destProt) && 00455 (protClass.isEmpty() || (protClass != destProt)) ) 00456 return false; 00457 } 00458 else 00459 { 00460 if ( (url.protocol() != destProt) && 00461 (protClass.isEmpty() || (protClass != destProt)) ) 00462 return false; 00463 } 00464 if (destHostWildCard) 00465 { 00466 if (!destHost.isEmpty() && !url.host().endsWith(destHost)) 00467 return false; 00468 } 00469 else if (destHostEqual) 00470 { 00471 if (url.host() != base.host()) 00472 return false; 00473 } 00474 else 00475 { 00476 if (url.host() != destHost) 00477 return false; 00478 } 00479 if (destPathWildCard) 00480 { 00481 if (!destPath.isEmpty() && !url.path().startsWith(destPath)) 00482 return false; 00483 } 00484 else 00485 { 00486 if (url.path() != destPath) 00487 return false; 00488 } 00489 return true; 00490 } 00491 00492 TQString action; 00493 TQString baseProt; 00494 TQString baseHost; 00495 TQString basePath; 00496 TQString destProt; 00497 TQString destHost; 00498 TQString destPath; 00499 bool baseProtWildCard : 1; 00500 bool baseHostWildCard : 1; 00501 bool basePathWildCard : 1; 00502 bool destProtWildCard : 1; 00503 bool destHostWildCard : 1; 00504 bool destPathWildCard : 1; 00505 bool destProtEqual : 1; 00506 bool destHostEqual : 1; 00507 bool permission; 00508 }; 00509 TQPtrList<URLActionRule> urlActionRestrictions; 00510 00511 TQString sessionKey; 00512 TQString pSessionConfigFile; 00513 }; 00514 00515 00516 static TQPtrList<TQWidget>*x11Filter = 0; 00517 static bool autoDcopRegistration = true; 00518 00519 void TDEApplication::installX11EventFilter( TQWidget* filter ) 00520 { 00521 if ( !filter ) 00522 return; 00523 if (!x11Filter) 00524 x11Filter = new TQPtrList<TQWidget>; 00525 connect ( filter, TQT_SIGNAL( destroyed() ), this, TQT_SLOT( x11FilterDestroyed() ) ); 00526 x11Filter->append( filter ); 00527 } 00528 00529 void TDEApplication::x11FilterDestroyed() 00530 { 00531 removeX11EventFilter( static_cast< const TQWidget* >( sender())); 00532 } 00533 00534 void TDEApplication::removeX11EventFilter( const TQWidget* filter ) 00535 { 00536 if ( !x11Filter || !filter ) 00537 return; 00538 x11Filter->removeRef( filter ); 00539 if ( x11Filter->isEmpty() ) { 00540 delete x11Filter; 00541 x11Filter = 0; 00542 } 00543 } 00544 00545 // FIXME: remove this when we've get a better method of 00546 // customizing accelerator handling -- hopefully in Qt. 00547 // For now, this is set whenever an accelerator is overridden 00548 // in TDEAccelEventHandler so that the AccelOverride isn't sent twice. -- ellis, 19/10/02 00549 extern bool kde_g_bKillAccelOverride; 00550 00551 bool TDEApplication::notify(TQObject *receiver, TQEvent *event) 00552 { 00553 TQEvent::Type t = event->type(); 00554 if (kde_g_bKillAccelOverride) 00555 { 00556 kde_g_bKillAccelOverride = false; 00557 // Indicate that the accelerator has been overridden. 00558 if (t == TQEvent::AccelOverride) 00559 { 00560 TQT_TQKEYEVENT(event)->accept(); 00561 return true; 00562 } 00563 else 00564 kdWarning(125) << "kde_g_bKillAccelOverride set, but received an event other than AccelOverride." << endl; 00565 } 00566 00567 if ((t == TQEvent::AccelOverride) || (t == TQEvent::KeyPress)) 00568 { 00569 static const TDEShortcut& _selectAll = TDEStdAccel::selectAll(); 00570 TQLineEdit *edit = ::tqqt_cast<TQLineEdit *>(receiver); 00571 if (edit) 00572 { 00573 // We have a keypress for a lineedit... 00574 TQKeyEvent *kevent = TQT_TQKEYEVENT(event); 00575 KKey key(kevent); 00576 if (_selectAll.contains(key)) 00577 { 00578 if (t == TQEvent::KeyPress) 00579 { 00580 edit->selectAll(); 00581 return true; 00582 } 00583 else 00584 { 00585 kevent->accept(); 00586 } 00587 } 00588 // Ctrl-U deletes from start of line. 00589 if (key == KKey(Qt::CTRL + Qt::Key_U)) 00590 { 00591 if (t == TQEvent::KeyPress) 00592 { 00593 if (!edit->isReadOnly()) 00594 { 00595 TQString t(edit->text()); 00596 t = t.mid(edit->cursorPosition()); 00597 edit->validateAndSet(t, 0, 0, 0); 00598 } 00599 return true; 00600 } 00601 else 00602 { 00603 kevent->accept(); 00604 } 00605 00606 } 00607 } 00608 TQTextEdit *medit = ::tqqt_cast<TQTextEdit *>(receiver); 00609 if (medit) 00610 { 00611 // We have a keypress for a multilineedit... 00612 TQKeyEvent *kevent = TQT_TQKEYEVENT(event); 00613 if (_selectAll.contains(KKey(kevent))) 00614 { 00615 if (t == TQEvent::KeyPress) 00616 { 00617 medit->selectAll(); 00618 return true; 00619 } 00620 else 00621 { 00622 kevent->accept(); 00623 } 00624 } 00625 } 00626 } 00627 if( t == TQEvent::Show && receiver->isWidgetType()) 00628 { 00629 TQWidget* w = TQT_TQWIDGET( receiver ); 00630 #if defined Q_WS_X11 00631 if( w->isTopLevel() && !startupId().isEmpty() && !TQT_TQSHOWEVENT(event)->spontaneous()) // TODO better done using window group leader? 00632 TDEStartupInfo::setWindowStartupId( w->winId(), startupId()); 00633 #endif 00634 if( w->isTopLevel() && !w->testWFlags( WX11BypassWM ) && !w->isPopup() && !event->spontaneous()) 00635 { 00636 if( d->app_started_timer == NULL ) 00637 { 00638 d->app_started_timer = new TQTimer( this, "app_started_timer" ); 00639 connect( d->app_started_timer, TQT_SIGNAL( timeout()), TQT_SLOT( checkAppStartedSlot())); 00640 } 00641 if( !d->app_started_timer->isActive()) 00642 d->app_started_timer->start( 0, true ); 00643 } 00644 if( w->isTopLevel() && ( w->icon() == NULL || w->icon()->isNull())) 00645 { 00646 // icon() cannot be null pixmap, it'll be the "unknown" icon - so check if there is this application icon 00647 static TQPixmap* ic = NULL; 00648 if( ic == NULL ) 00649 ic = new TQPixmap( TDEGlobal::iconLoader()->loadIcon( iconName(), 00650 TDEIcon::NoGroup, 0, TDEIcon::DefaultState, NULL, true )); 00651 if( !ic->isNull()) 00652 { 00653 w->setIcon( *ic ); 00654 #if defined Q_WS_X11 00655 KWin::setIcons( w->winId(), *ic, miniIcon()); 00656 #endif 00657 } 00658 } 00659 } 00660 return TQApplication::notify(receiver, event); 00661 } 00662 00663 void TDEApplication::checkAppStartedSlot() 00664 { 00665 #if defined Q_WS_X11 00666 TDEStartupInfo::handleAutoAppStartedSending(); 00667 #endif 00668 } 00669 00670 // the help class for session management communication 00671 static TQPtrList<KSessionManaged>* sessionClients() 00672 { 00673 static TQPtrList<KSessionManaged>* session_clients = 0L; 00674 if ( !session_clients ) 00675 session_clients = new TQPtrList<KSessionManaged>; 00676 return session_clients; 00677 } 00678 00679 /* 00680 Auxiliary function to calculate a a session config name used for the 00681 instance specific config object. 00682 Syntax: "session/<appname>_<sessionId>" 00683 */ 00684 TQString TDEApplication::sessionConfigName() const 00685 { 00686 TQString sessKey = sessionKey(); 00687 if ( sessKey.isEmpty() && !d->sessionKey.isEmpty() ) 00688 sessKey = d->sessionKey; 00689 return TQString("session/%1_%2_%3").arg(name()).arg(sessionId()).arg(sessKey); 00690 } 00691 00692 #ifdef Q_WS_X11 00693 static SmcConn mySmcConnection = 0; 00694 static SmcConn tmpSmcConnection = 0; 00695 #else 00696 // FIXME(E): Implement for Qt Embedded 00697 // Possibly "steal" XFree86's libSM? 00698 #endif 00699 static TQTime* smModificationTime = 0; 00700 00701 TDEApplication::TDEApplication( int& argc, char** argv, const TQCString& rAppName, 00702 bool allowStyles, bool GUIenabled, bool SMenabled ) : 00703 TQApplication( argc, argv, GUIenabled, SMenabled ), TDEInstance(rAppName), 00704 #ifdef Q_WS_X11 00705 display(0L), 00706 argb_visual(false), 00707 #endif 00708 d (new TDEApplicationPrivate()) 00709 { 00710 aIconPixmap.pm.icon = 0L; 00711 aIconPixmap.pm.miniIcon = 0L; 00712 read_app_startup_id(); 00713 if (!GUIenabled) 00714 allowStyles = false; 00715 useStyles = allowStyles; 00716 Q_ASSERT (!rAppName.isEmpty()); 00717 setName(rAppName); 00718 00719 installSigpipeHandler(); 00720 TDECmdLineArgs::initIgnore(argc, argv, rAppName.data()); 00721 parseCommandLine( ); 00722 init(GUIenabled); 00723 d->m_KAppDCOPInterface = new KAppDCOPInterface(this); 00724 } 00725 00726 // FIXME 00727 // FOR BINARY COMPATIBILITY ONLY 00728 // REMOVE WHEN PRACTICAL! 00729 TDEApplication::TDEApplication( int& argc, char** argv, const TQCString& rAppName, 00730 bool allowStyles, bool GUIenabled ) : 00731 TQApplication( argc, argv, GUIenabled ), TDEInstance(rAppName), 00732 #ifdef Q_WS_X11 00733 display(0L), 00734 argb_visual(false), 00735 #endif 00736 d (new TDEApplicationPrivate()) 00737 { 00738 aIconPixmap.pm.icon = 0L; 00739 aIconPixmap.pm.miniIcon = 0L; 00740 read_app_startup_id(); 00741 if (!GUIenabled) 00742 allowStyles = false; 00743 useStyles = allowStyles; 00744 Q_ASSERT (!rAppName.isEmpty()); 00745 setName(rAppName); 00746 00747 installSigpipeHandler(); 00748 TDECmdLineArgs::initIgnore(argc, argv, rAppName.data()); 00749 parseCommandLine( ); 00750 init(GUIenabled); 00751 d->m_KAppDCOPInterface = new KAppDCOPInterface(this); 00752 } 00753 00754 TDEApplication::TDEApplication( bool allowStyles, bool GUIenabled, bool SMenabled ) : 00755 // TQApplication( *TDECmdLineArgs::tqt_argc(), *TDECmdLineArgs::tqt_argv(), TRUE ), // Qt4 requires that there always be a GUI 00756 TQApplication( *TDECmdLineArgs::tqt_argc(), *TDECmdLineArgs::tqt_argv(), GUIenabled, SMenabled ), // We need to be able to run command line apps 00757 TDEInstance( TDECmdLineArgs::about), 00758 #ifdef Q_WS_X11 00759 display(0L), 00760 argb_visual(false), 00761 #endif 00762 d (new TDEApplicationPrivate) 00763 { 00764 aIconPixmap.pm.icon = 0L; 00765 aIconPixmap.pm.miniIcon = 0L; 00766 read_app_startup_id(); 00767 if (!GUIenabled) 00768 allowStyles = false; 00769 useStyles = allowStyles; 00770 setName( instanceName() ); 00771 00772 installSigpipeHandler(); 00773 parseCommandLine( ); 00774 init(GUIenabled); 00775 d->m_KAppDCOPInterface = new KAppDCOPInterface(this); 00776 } 00777 00778 // FIXME 00779 // FOR BINARY COMPATIBILITY ONLY 00780 // REMOVE WHEN PRACTICAL! 00781 TDEApplication::TDEApplication( bool allowStyles, bool GUIenabled ) : 00782 // TQApplication( *TDECmdLineArgs::tqt_argc(), *TDECmdLineArgs::tqt_argv(), TRUE ), // Qt4 requires that there always be a GUI 00783 TQApplication( *TDECmdLineArgs::tqt_argc(), *TDECmdLineArgs::tqt_argv(), GUIenabled ), // We need to be able to run command line apps 00784 TDEInstance( TDECmdLineArgs::about), 00785 #ifdef Q_WS_X11 00786 display(0L), 00787 argb_visual(false), 00788 #endif 00789 d (new TDEApplicationPrivate) 00790 { 00791 aIconPixmap.pm.icon = 0L; 00792 aIconPixmap.pm.miniIcon = 0L; 00793 read_app_startup_id(); 00794 if (!GUIenabled) 00795 allowStyles = false; 00796 useStyles = allowStyles; 00797 setName( instanceName() ); 00798 00799 installSigpipeHandler(); 00800 parseCommandLine( ); 00801 init(GUIenabled); 00802 d->m_KAppDCOPInterface = new KAppDCOPInterface(this); 00803 } 00804 00805 #ifdef Q_WS_X11 00806 TDEApplication::TDEApplication( Display *dpy, bool allowStyles ) : 00807 TQApplication( dpy, *TDECmdLineArgs::tqt_argc(), *TDECmdLineArgs::tqt_argv(), 00808 getX11RGBAVisual(dpy), getX11RGBAColormap(dpy) ), 00809 TDEInstance( TDECmdLineArgs::about), display(0L), d (new TDEApplicationPrivate) 00810 { 00811 aIconPixmap.pm.icon = 0L; 00812 aIconPixmap.pm.miniIcon = 0L; 00813 read_app_startup_id(); 00814 useStyles = allowStyles; 00815 setName( instanceName() ); 00816 installSigpipeHandler(); 00817 parseCommandLine( ); 00818 init( true ); 00819 d->m_KAppDCOPInterface = new KAppDCOPInterface(this); 00820 } 00821 00822 TDEApplication::TDEApplication( Display *dpy, bool disable_argb, Qt::HANDLE visual, Qt::HANDLE colormap, bool allowStyles ) : 00823 TQApplication( dpy, *TDECmdLineArgs::tqt_argc(), *TDECmdLineArgs::tqt_argv(), 00824 disable_argb?visual:getX11RGBAVisual(dpy), disable_argb?colormap:getX11RGBAColormap(dpy) ), 00825 TDEInstance( TDECmdLineArgs::about), display(0L), d (new TDEApplicationPrivate) 00826 { 00827 aIconPixmap.pm.icon = 0L; 00828 aIconPixmap.pm.miniIcon = 0L; 00829 read_app_startup_id(); 00830 useStyles = allowStyles; 00831 if (disable_argb) argb_visual = false; 00832 setName( instanceName() ); 00833 installSigpipeHandler(); 00834 parseCommandLine( ); 00835 init( true ); 00836 d->m_KAppDCOPInterface = new KAppDCOPInterface(this); 00837 } 00838 00839 TDEApplication::TDEApplication( Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap, 00840 bool allowStyles ) : 00841 TQApplication( dpy, *TDECmdLineArgs::tqt_argc(), *TDECmdLineArgs::tqt_argv(), 00842 visual?visual:getX11RGBAVisual(dpy), colormap?colormap:getX11RGBAColormap(dpy) ), 00843 TDEInstance( TDECmdLineArgs::about), display(0L), d (new TDEApplicationPrivate) 00844 { 00845 if ((visual) && (colormap)) 00846 getX11RGBAInformation(dpy); 00847 aIconPixmap.pm.icon = 0L; 00848 aIconPixmap.pm.miniIcon = 0L; 00849 read_app_startup_id(); 00850 useStyles = allowStyles; 00851 setName( instanceName() ); 00852 installSigpipeHandler(); 00853 parseCommandLine( ); 00854 init( true ); 00855 d->m_KAppDCOPInterface = new KAppDCOPInterface(this); 00856 } 00857 00858 TDEApplication::TDEApplication( Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap, 00859 bool allowStyles, TDEInstance * _instance ) : 00860 TQApplication( dpy, *TDECmdLineArgs::tqt_argc(), *TDECmdLineArgs::tqt_argv(), 00861 visual?visual:getX11RGBAVisual(dpy), colormap?colormap:getX11RGBAColormap(dpy) ), 00862 TDEInstance( _instance ), display(0L), d (new TDEApplicationPrivate) 00863 { 00864 if ((visual) && (colormap)) 00865 getX11RGBAInformation(dpy); 00866 aIconPixmap.pm.icon = 0L; 00867 aIconPixmap.pm.miniIcon = 0L; 00868 read_app_startup_id(); 00869 useStyles = allowStyles; 00870 setName( instanceName() ); 00871 installSigpipeHandler(); 00872 parseCommandLine( ); 00873 init( true ); 00874 d->m_KAppDCOPInterface = new KAppDCOPInterface(this); 00875 } 00876 #endif 00877 00878 TDEApplication::TDEApplication( bool allowStyles, bool GUIenabled, TDEInstance* _instance ) : 00879 TQApplication( *TDECmdLineArgs::tqt_argc(), *TDECmdLineArgs::tqt_argv(), 00880 GUIenabled ), 00881 TDEInstance( _instance ), 00882 #ifdef Q_WS_X11 00883 display(0L), 00884 #endif 00885 argb_visual(false), 00886 d (new TDEApplicationPrivate) 00887 { 00888 aIconPixmap.pm.icon = 0L; 00889 aIconPixmap.pm.miniIcon = 0L; 00890 read_app_startup_id(); 00891 if (!GUIenabled) 00892 allowStyles = false; 00893 useStyles = allowStyles; 00894 setName( instanceName() ); 00895 00896 installSigpipeHandler(); 00897 parseCommandLine( ); 00898 init(GUIenabled); 00899 d->m_KAppDCOPInterface = new KAppDCOPInterface(this); 00900 } 00901 00902 #ifdef Q_WS_X11 00903 TDEApplication::TDEApplication(Display *display, int& argc, char** argv, const TQCString& rAppName, 00904 bool allowStyles, bool GUIenabled ) : 00905 TQApplication( display ), TDEInstance(rAppName), 00906 display(0L), 00907 argb_visual(false), 00908 d (new TDEApplicationPrivate()) 00909 { 00910 aIconPixmap.pm.icon = 0L; 00911 aIconPixmap.pm.miniIcon = 0L; 00912 read_app_startup_id(); 00913 if (!GUIenabled) 00914 allowStyles = false; 00915 useStyles = allowStyles; 00916 00917 Q_ASSERT (!rAppName.isEmpty()); 00918 setName(rAppName); 00919 00920 installSigpipeHandler(); 00921 TDECmdLineArgs::initIgnore(argc, argv, rAppName.data()); 00922 parseCommandLine( ); 00923 init(GUIenabled); 00924 d->m_KAppDCOPInterface = new KAppDCOPInterface(this); 00925 } 00926 #endif 00927 00928 int TDEApplication::xioErrhandler( Display* dpy ) 00929 { 00930 if(kapp) 00931 { 00932 emit shutDown(); 00933 #ifdef Q_WS_X11 00934 d->oldXIOErrorHandler( dpy ); 00935 #else 00936 Q_UNUSED(dpy); 00937 #endif 00938 } 00939 exit( 1 ); 00940 return 0; 00941 } 00942 00943 int TDEApplication::xErrhandler( Display* dpy, void* err_ ) 00944 { // no idea how to make forward decl. for XErrorEvent 00945 #ifdef Q_WS_X11 00946 XErrorEvent* err = static_cast< XErrorEvent* >( err_ ); 00947 if(kapp) 00948 { 00949 // add KDE specific stuff here 00950 d->oldXErrorHandler( dpy, err ); 00951 } 00952 #endif 00953 return 0; 00954 } 00955 00956 void TDEApplication::iceIOErrorHandler( _IceConn *conn ) 00957 { 00958 emit shutDown(); 00959 00960 #ifdef Q_WS_X11 00961 if ( d->oldIceIOErrorHandler != NULL ) 00962 (*d->oldIceIOErrorHandler)( conn ); 00963 #endif 00964 exit( 1 ); 00965 } 00966 00967 class KDETranslator : public TQTranslator 00968 { 00969 public: 00970 KDETranslator(TQObject *parent) : TQTranslator(parent, "kdetranslator") {} 00971 virtual TQTranslatorMessage findMessage(const char* context, 00972 const char *sourceText, 00973 const char* message) const 00974 { 00975 TQTranslatorMessage res; 00976 res.setTranslation(TDEGlobal::locale()->translateQt(context, sourceText, message)); 00977 return res; 00978 } 00979 }; 00980 00981 void TDEApplication::init(bool GUIenabled) 00982 { 00983 d->guiEnabled = GUIenabled; 00984 if ((getuid() != geteuid()) || 00985 (getgid() != getegid()) ) 00986 { 00987 // man permissions are not exploitable and better than 00988 // world writable directories 00989 struct group *man = getgrnam("man"); 00990 if ( !man || man->gr_gid != getegid() ){ 00991 fprintf(stderr, "The TDE libraries are not designed to run with suid privileges.\n"); 00992 ::exit(127); 00993 } 00994 } 00995 00996 TDEProcessController::ref(); 00997 00998 (void) TDEClipboardSynchronizer::self(); 00999 01000 TQApplication::setDesktopSettingsAware( false ); 01001 01002 KApp = this; 01003 01004 01005 #ifdef Q_WS_X11 //FIXME(E) 01006 // create all required atoms in _one_ roundtrip to the X server 01007 if ( GUIenabled ) { 01008 const int max = 20; 01009 Atom* atoms[max]; 01010 char* names[max]; 01011 Atom atoms_return[max]; 01012 int n = 0; 01013 01014 atoms[n] = &kipcCommAtom; 01015 names[n++] = (char *) "KIPC_COMM_ATOM"; 01016 01017 atoms[n] = &atom_DesktopWindow; 01018 names[n++] = (char *) "KDE_DESKTOP_WINDOW"; 01019 01020 atoms[n] = &atom_NetSupported; 01021 names[n++] = (char *) "_NET_SUPPORTED"; 01022 01023 XInternAtoms( tqt_xdisplay(), names, n, false, atoms_return ); 01024 01025 for (int i = 0; i < n; i++ ) 01026 *atoms[i] = atoms_return[i]; 01027 } 01028 #endif 01029 01030 dcopAutoRegistration(); 01031 dcopClientPostInit(); 01032 01033 smw = 0; 01034 01035 // Initial KIPC event mask. 01036 #if defined Q_WS_X11 01037 kipcEventMask = (1 << KIPC::StyleChanged) | (1 << KIPC::PaletteChanged) | 01038 (1 << KIPC::FontChanged) | (1 << KIPC::BackgroundChanged) | 01039 (1 << KIPC::ToolbarStyleChanged) | (1 << KIPC::SettingsChanged) | 01040 (1 << KIPC::ClipboardConfigChanged) | (1 << KIPC::BlockShortcuts); 01041 #endif 01042 01043 // Trigger creation of locale. 01044 (void) TDEGlobal::locale(); 01045 01046 TDEConfig* config = TDEGlobal::config(); 01047 d->actionRestrictions = config->hasGroup("KDE Action Restrictions" ) && !kde_kiosk_exception; 01048 // For brain-dead configurations where the user's local config file is not writable. 01049 // * We use kdialog to warn the user, so we better not generate warnings from 01050 // kdialog itself. 01051 // * Don't warn if we run with a read-only $HOME 01052 TQCString readOnly = getenv("TDE_HOME_READONLY"); 01053 if (readOnly.isEmpty() && (tqstrcmp(name(), "kdialog") != 0)) 01054 { 01055 TDEConfigGroupSaver saver(config, "KDE Action Restrictions"); 01056 if (config->readBoolEntry("warn_unwritable_config",true)) 01057 config->checkConfigFilesWritable(true); 01058 } 01059 01060 if (GUIenabled) 01061 { 01062 #ifdef Q_WS_X11 01063 // this is important since we fork() to launch the help (Matthias) 01064 fcntl(ConnectionNumber(tqt_xdisplay()), F_SETFD, FD_CLOEXEC); 01065 // set up the fancy (=robust and error ignoring ) KDE xio error handlers (Matthias) 01066 d->oldXErrorHandler = XSetErrorHandler( kde_x_errhandler ); 01067 d->oldXIOErrorHandler = XSetIOErrorHandler( kde_xio_errhandler ); 01068 #endif 01069 01070 connect( this, TQT_SIGNAL( aboutToQuit() ), this, TQT_SIGNAL( shutDown() ) ); 01071 01072 #ifdef Q_WS_X11 //FIXME(E) 01073 display = desktop()->x11Display(); 01074 #endif 01075 01076 { 01077 TQStringList plugins = TDEGlobal::dirs()->resourceDirs( "qtplugins" ); 01078 TQStringList::Iterator it = plugins.begin(); 01079 while (it != plugins.end()) { 01080 addLibraryPath( *it ); 01081 ++it; 01082 } 01083 01084 } 01085 tdedisplaySetStyle(); 01086 tdedisplaySetFont(); 01087 // tdedisplaySetPalette(); done by tdedisplaySetStyle 01088 propagateSettings(SETTINGS_QT); 01089 01090 // Set default mime-source factory 01091 // XXX: This is a hack. Make our factory the default factory, but add the 01092 // previous default factory to the list of factories. Why? When the default 01093 // factory can't resolve something, it iterates in the list of factories. 01094 // But it TQWhatsThis only uses the default factory. So if there was already 01095 // a default factory (which happens when using an image library using uic), 01096 // we prefer KDE's factory and so we put that old default factory in the 01097 // list and use KDE as the default. This may speed up things as well. 01098 TQMimeSourceFactory* oldDefaultFactory = TQMimeSourceFactory::takeDefaultFactory(); 01099 TQMimeSourceFactory::setDefaultFactory( mimeSourceFactory() ); 01100 if ( oldDefaultFactory ) { 01101 TQMimeSourceFactory::addFactory( oldDefaultFactory ); 01102 } 01103 01104 d->checkAccelerators = new KCheckAccelerators( TQT_TQOBJECT(this) ); 01105 } 01106 01107 #ifdef Q_WS_MACX 01108 if (GUIenabled) { 01109 TQPixmap pixmap = TDEGlobal::iconLoader()->loadIcon( TDECmdLineArgs::appName(), 01110 TDEIcon::NoGroup, TDEIcon::SizeLarge, TDEIcon::DefaultState, 0L, false ); 01111 if (!pixmap.isNull()) { 01112 TQImage i = pixmap.convertToImage().convertDepth(32).smoothScale(40, 40); 01113 for(int y = 0; y < i.height(); y++) { 01114 uchar *l = i.scanLine(y); 01115 for(int x = 0; x < i.width(); x+=4) 01116 *(l+x) = 255; 01117 } 01118 CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); 01119 CGDataProviderRef dp = CGDataProviderCreateWithData(NULL, 01120 i.bits(), i.numBytes(), NULL); 01121 CGImageRef ir = CGImageCreate(i.width(), i.height(), 8, 32, i.bytesPerLine(), 01122 cs, kCGImageAlphaNoneSkipFirst, dp, 01123 0, 0, kCGRenderingIntentDefault); 01124 //cleanup 01125 SetApplicationDockTileImage(ir); 01126 CGImageRelease(ir); 01127 CGColorSpaceRelease(cs); 01128 CGDataProviderRelease(dp); 01129 } 01130 } 01131 #endif 01132 01133 01134 // save and restore the RTL setting, as installTranslator calls qt_detectRTLLanguage, 01135 // which makes it impossible to use the -reverse cmdline switch with KDE apps 01136 bool rtl = reverseLayout(); 01137 installTranslator(new KDETranslator(TQT_TQOBJECT(this))); 01138 setReverseLayout( rtl ); 01139 if (i18n( "_: Dear Translator! Translate this string to the string 'LTR' in " 01140 "left-to-right languages (as english) or to 'RTL' in right-to-left " 01141 "languages (such as Hebrew and Arabic) to get proper widget layout." ) == "RTL") 01142 setReverseLayout( !rtl ); 01143 01144 // install appdata resource type 01145 TDEGlobal::dirs()->addResourceType("appdata", TDEStandardDirs::kde_default("data") 01146 + TQString::fromLatin1(name()) + '/'); 01147 pSessionConfig = 0L; 01148 bSessionManagement = true; 01149 01150 #ifdef Q_WS_X11 01151 // register a communication window for desktop changes (Matthias) 01152 if (GUIenabled && kde_have_kipc ) 01153 { 01154 smw = new TQWidget(0,0); 01155 long data = 1; 01156 XChangeProperty(tqt_xdisplay(), smw->winId(), 01157 atom_DesktopWindow, atom_DesktopWindow, 01158 32, PropModeReplace, (unsigned char *)&data, 1); 01159 } 01160 d->oldIceIOErrorHandler = IceSetIOErrorHandler( kde_ice_ioerrorhandler ); 01161 #elif defined(Q_WS_WIN) 01162 TDEApplication_init_windows(GUIenabled); 01163 #else 01164 // FIXME(E): Implement for Qt Embedded 01165 #endif 01166 } 01167 01168 static int my_system (const char *command) { 01169 int pid, status; 01170 01171 pid = fork(); 01172 if (pid == -1) 01173 return -1; 01174 if (pid == 0) { 01175 const char* shell = "/bin/sh"; 01176 execl(shell, shell, "-c", command, (void *)0); 01177 ::_exit(127); 01178 } 01179 do { 01180 if (waitpid(pid, &status, 0) == -1) { 01181 if (errno != EINTR) 01182 return -1; 01183 } else 01184 return status; 01185 } while(1); 01186 } 01187 01188 01189 DCOPClient *TDEApplication::dcopClient() 01190 { 01191 if (s_DCOPClient) 01192 return s_DCOPClient; 01193 01194 s_DCOPClient = new DCOPClient(); 01195 TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs("tde"); 01196 if (args && args->isSet("dcopserver")) 01197 { 01198 s_DCOPClient->setServerAddress( args->getOption("dcopserver")); 01199 } 01200 if( kapp ) { 01201 connect(s_DCOPClient, TQT_SIGNAL(attachFailed(const TQString &)), 01202 kapp, TQT_SLOT(dcopFailure(const TQString &))); 01203 connect(s_DCOPClient, TQT_SIGNAL(blockUserInput(bool) ), 01204 kapp, TQT_SLOT(dcopBlockUserInput(bool)) ); 01205 } 01206 else 01207 s_dcopClientNeedsPostInit = true; 01208 01209 DCOPClient::setMainClient( s_DCOPClient ); 01210 return s_DCOPClient; 01211 } 01212 01213 void TDEApplication::dcopClientPostInit() 01214 { 01215 if( s_dcopClientNeedsPostInit ) 01216 { 01217 s_dcopClientNeedsPostInit = false; 01218 connect(s_DCOPClient, TQT_SIGNAL(blockUserInput(bool) ), 01219 TQT_SLOT(dcopBlockUserInput(bool)) ); 01220 s_DCOPClient->bindToApp(); // Make sure we get events from the DCOPClient. 01221 } 01222 } 01223 01224 void TDEApplication::dcopAutoRegistration() 01225 { 01226 if (autoDcopRegistration) 01227 { 01228 ( void ) dcopClient(); 01229 if( dcopClient()->appId().isEmpty()) 01230 dcopClient()->registerAs(name()); 01231 } 01232 } 01233 01234 void TDEApplication::disableAutoDcopRegistration() 01235 { 01236 autoDcopRegistration = false; 01237 } 01238 01239 TDEConfig* TDEApplication::sessionConfig() 01240 { 01241 if (pSessionConfig) 01242 return pSessionConfig; 01243 01244 // create an instance specific config object 01245 pSessionConfig = new TDEConfig( sessionConfigName(), false, false); 01246 return pSessionConfig; 01247 } 01248 01249 void TDEApplication::ref() 01250 { 01251 d->refCount++; 01252 //kdDebug() << "[tdecore-tdeapplication] TDEApplication::ref() : refCount = " << d->refCount << endl; 01253 } 01254 01255 void TDEApplication::deref() 01256 { 01257 d->refCount--; 01258 //kdDebug() << "[tdecore-tdeapplication] TDEApplication::deref() : refCount = " << d->refCount << endl; 01259 if ( d->refCount <= 0 ) 01260 quit(); 01261 } 01262 01263 KSessionManaged::KSessionManaged() 01264 { 01265 sessionClients()->remove( this ); 01266 sessionClients()->append( this ); 01267 } 01268 01269 KSessionManaged::~KSessionManaged() 01270 { 01271 sessionClients()->remove( this ); 01272 } 01273 01274 bool KSessionManaged::saveState(TQSessionManager&) 01275 { 01276 return true; 01277 } 01278 01279 bool KSessionManaged::commitData(TQSessionManager&) 01280 { 01281 return true; 01282 } 01283 01284 01285 void TDEApplication::disableSessionManagement() { 01286 bSessionManagement = false; 01287 } 01288 01289 void TDEApplication::enableSessionManagement() { 01290 bSessionManagement = true; 01291 #ifdef Q_WS_X11 01292 // Session management support in Qt/TDE is awfully broken. 01293 // If konqueror disables session management right after its startup, 01294 // and enables it later (preloading stuff), it won't be properly 01295 // saved on session shutdown. 01296 // I'm not actually sure why it doesn't work, but saveState() 01297 // doesn't seem to be called on session shutdown, possibly 01298 // because disabling session management after konqueror startup 01299 // disabled it somehow. Forcing saveState() here for this application 01300 // seems to fix it. 01301 if( mySmcConnection ) { 01302 SmcRequestSaveYourself( mySmcConnection, SmSaveLocal, False, 01303 SmInteractStyleAny, 01304 False, False ); 01305 01306 // flush the request 01307 IceFlush(SmcGetIceConnection(mySmcConnection)); 01308 } 01309 #endif 01310 } 01311 01312 01313 bool TDEApplication::requestShutDown( 01314 ShutdownConfirm confirm, ShutdownType sdtype, ShutdownMode sdmode ) 01315 { 01316 #ifdef Q_WS_X11 01317 TQApplication::syncX(); 01318 /* use ksmserver's dcop interface if necessary */ 01319 if ( confirm == ShutdownConfirmYes || 01320 sdtype != ShutdownTypeDefault || 01321 sdmode != ShutdownModeDefault ) 01322 { 01323 TQByteArray data; 01324 TQDataStream arg(data, IO_WriteOnly); 01325 arg << (int)confirm << (int)sdtype << (int)sdmode; 01326 return dcopClient()->send( "ksmserver", "ksmserver", 01327 "logout(int,int,int)", data ); 01328 } 01329 01330 if ( mySmcConnection ) { 01331 // we already have a connection to the session manager, use it. 01332 SmcRequestSaveYourself( mySmcConnection, SmSaveBoth, True, 01333 SmInteractStyleAny, 01334 confirm == ShutdownConfirmNo, True ); 01335 01336 // flush the request 01337 IceFlush(SmcGetIceConnection(mySmcConnection)); 01338 return true; 01339 } 01340 01341 // open a temporary connection, if possible 01342 01343 propagateSessionManager(); 01344 TQCString smEnv = ::getenv("SESSION_MANAGER"); 01345 if (smEnv.isEmpty()) 01346 return false; 01347 01348 if (! tmpSmcConnection) { 01349 char cerror[256]; 01350 char* myId = 0; 01351 char* prevId = 0; 01352 SmcCallbacks cb; 01353 tmpSmcConnection = SmcOpenConnection( 0, 0, 1, 0, 01354 0, &cb, 01355 prevId, 01356 &myId, 01357 255, 01358 cerror ); 01359 ::free( myId ); // it was allocated by C 01360 if (!tmpSmcConnection ) 01361 return false; 01362 } 01363 01364 SmcRequestSaveYourself( tmpSmcConnection, SmSaveBoth, True, 01365 SmInteractStyleAny, False, True ); 01366 01367 // flush the request 01368 IceFlush(SmcGetIceConnection(tmpSmcConnection)); 01369 return true; 01370 #else 01371 // FIXME(E): Implement for Qt Embedded 01372 return false; 01373 #endif 01374 } 01375 01376 void TDEApplication::propagateSessionManager() 01377 { 01378 #ifdef Q_WS_X11 01379 TQCString fName = TQFile::encodeName(locateLocal("socket", "KSMserver")); 01380 TQCString display = ::getenv(DISPLAY); 01381 // strip the screen number from the display 01382 display.replace(TQRegExp("\\.[0-9]+$"), ""); 01383 int i; 01384 while( (i = display.find(':')) >= 0) 01385 display[i] = '_'; 01386 01387 fName += "_"+display; 01388 TQCString smEnv = ::getenv("SESSION_MANAGER"); 01389 bool check = smEnv.isEmpty(); 01390 if ( !check && smModificationTime ) { 01391 TQFileInfo info( fName ); 01392 TQTime current = TQT_TQTIME_OBJECT(info.lastModified().time()); 01393 check = current > *smModificationTime; 01394 } 01395 if ( check ) { 01396 delete smModificationTime; 01397 TQFile f( fName ); 01398 if ( !f.open( IO_ReadOnly ) ) 01399 return; 01400 TQFileInfo info ( f ); 01401 smModificationTime = new TQTime( TQT_TQTIME_OBJECT(info.lastModified().time()) ); 01402 TQTextStream t(&f); 01403 t.setEncoding( TQTextStream::Latin1 ); 01404 TQString s = t.readLine(); 01405 f.close(); 01406 ::setenv( "SESSION_MANAGER", s.latin1(), true ); 01407 } 01408 #endif 01409 } 01410 01411 void TDEApplication::commitData( TQSessionManager& sm ) 01412 { 01413 d->session_save = true; 01414 bool canceled = false; 01415 for (KSessionManaged* it = sessionClients()->first(); 01416 it && !canceled; 01417 it = sessionClients()->next() ) { 01418 canceled = !it->commitData( sm ); 01419 } 01420 if ( canceled ) 01421 sm.cancel(); 01422 01423 if ( sm.allowsInteraction() ) { 01424 TQWidgetList done; 01425 TQWidgetList *list = TQApplication::topLevelWidgets(); 01426 bool canceled = false; 01427 TQWidget* w = list->first(); 01428 while ( !canceled && w ) { 01429 if ( !w->testWState( WState_ForceHide ) && !w->inherits("TDEMainWindow") ) { 01430 TQCloseEvent e; 01431 sendEvent( w, &e ); 01432 canceled = !e.isAccepted(); 01433 if ( !canceled ) 01434 done.append( w ); 01435 delete list; // one never knows... 01436 list = TQApplication::topLevelWidgets(); 01437 w = list->first(); 01438 } else { 01439 w = list->next(); 01440 } 01441 while ( w && done.containsRef( w ) ) 01442 w = list->next(); 01443 } 01444 delete list; 01445 } 01446 01447 01448 if ( !bSessionManagement ) 01449 sm.setRestartHint( TQSessionManager::RestartNever ); 01450 else 01451 sm.setRestartHint( TQSessionManager::RestartIfRunning ); 01452 d->session_save = false; 01453 } 01454 01455 static void checkRestartVersion( TQSessionManager& sm ) 01456 { 01457 Display* dpy = tqt_xdisplay(); 01458 Atom type; 01459 int format; 01460 unsigned long nitems, after; 01461 unsigned char* data; 01462 if( XGetWindowProperty( dpy, RootWindow( dpy, 0 ), XInternAtom( dpy, "TDE_FULL_SESSION", False ), 01463 0, 1, False, AnyPropertyType, &type, &format, &nitems, &after, &data ) == Success ) { 01464 if( data != NULL ) 01465 XFree( data ); 01466 if( type == XA_STRING && format == 8 ) { // session set, check if TDE_SESSION_VERSION is not set (meaning KDE3) 01467 if( XGetWindowProperty( dpy, RootWindow( dpy, 0 ), XInternAtom( dpy, "TDE_SESSION_VERSION", False ), 01468 0, 1, False, AnyPropertyType, &type, &format, &nitems, &after, &data ) == Success ) { 01469 if( data != NULL ) 01470 XFree( data ); // KDE4 or newer 01471 if( type == None ) 01472 return; // we run in our native session, no need to wrap 01473 } else { 01474 return; // we run in our native session, no need to wrap 01475 } 01476 } 01477 } 01478 TQString wrapper = TDEStandardDirs::findExe( "trinity" ); 01479 TQStringList restartCommand = sm.restartCommand(); 01480 restartCommand.prepend( wrapper ); 01481 sm.setRestartCommand( restartCommand ); 01482 } 01483 01484 void TDEApplication::saveState( TQSessionManager& sm ) 01485 { 01486 d->session_save = true; 01487 #ifdef Q_WS_X11 01488 static bool firstTime = true; 01489 mySmcConnection = (SmcConn) sm.handle(); 01490 01491 if ( !bSessionManagement ) { 01492 sm.setRestartHint( TQSessionManager::RestartNever ); 01493 d->session_save = false; 01494 return; 01495 } 01496 else 01497 sm.setRestartHint( TQSessionManager::RestartIfRunning ); 01498 01499 if ( firstTime ) { 01500 firstTime = false; 01501 d->session_save = false; 01502 return; // no need to save the state. 01503 } 01504 01505 // remove former session config if still existing, we want a new 01506 // and fresh one. Note that we do not delete the config file here, 01507 // this is done by the session manager when it executes the 01508 // discard commands. In fact it would be harmful to remove the 01509 // file here, as the session might be stored under a different 01510 // name, meaning the user still might need it eventually. 01511 if ( pSessionConfig ) { 01512 delete pSessionConfig; 01513 pSessionConfig = 0; 01514 } 01515 01516 // tell the session manager about our new lifecycle 01517 TQStringList restartCommand = sm.restartCommand(); 01518 01519 TQCString multiHead = getenv("TDE_MULTIHEAD"); 01520 if (multiHead.lower() == "true") { 01521 // if multihead is enabled, we save our -display argument so that 01522 // we are restored onto the correct head... one problem with this 01523 // is that the display is hard coded, which means we cannot restore 01524 // to a different display (ie. if we are in a university lab and try, 01525 // try to restore a multihead session, our apps could be started on 01526 // someone else's display instead of our own) 01527 TQCString displayname = getenv(DISPLAY); 01528 if (! displayname.isNull()) { 01529 // only store the command if we actually have a DISPLAY 01530 // environment variable 01531 restartCommand.append("-display"); 01532 restartCommand.append(displayname); 01533 } 01534 sm.setRestartCommand( restartCommand ); 01535 } 01536 01537 checkRestartVersion( sm ); 01538 01539 // finally: do session management 01540 emit saveYourself(); // for compatibility 01541 bool canceled = false; 01542 for (KSessionManaged* it = sessionClients()->first(); 01543 it && !canceled; 01544 it = sessionClients()->next() ) { 01545 canceled = !it->saveState( sm ); 01546 } 01547 01548 // if we created a new session config object, register a proper discard command 01549 if ( pSessionConfig ) { 01550 pSessionConfig->sync(); 01551 TQStringList discard; 01552 discard << "rm" << locateLocal("config", sessionConfigName()); 01553 sm.setDiscardCommand( discard ); 01554 } else { 01555 sm.setDiscardCommand( TQStringList("") ); 01556 } 01557 01558 if ( canceled ) 01559 sm.cancel(); 01560 #else 01561 // FIXME(E): Implement for Qt Embedded 01562 #endif 01563 d->session_save = false; 01564 } 01565 01566 bool TDEApplication::sessionSaving() const 01567 { 01568 return d->session_save; 01569 } 01570 01571 void TDEApplication::startKdeinit() 01572 { 01573 #ifndef Q_WS_WIN //TODO 01574 TDEInstance inst( "starttdeinitlock" ); 01575 TDELockFile lock( locateLocal( "tmp", "starttdeinitlock", &inst )); 01576 if( lock.lock( TDELockFile::LockNoBlock ) != TDELockFile::LockOK ) { 01577 lock.lock(); 01578 DCOPClient cl; 01579 if( cl.attach()) 01580 return; // whoever held the lock has already started dcopserver 01581 } 01582 // Try to launch tdeinit. 01583 TQString srv = TDEStandardDirs::findExe(TQString::fromLatin1("tdeinit")); 01584 if (srv.isEmpty()) 01585 srv = TDEStandardDirs::findExe(TQString::fromLatin1("tdeinit"), TDEGlobal::dirs()->kfsstnd_defaultbindir()); 01586 if (srv.isEmpty()) 01587 return; 01588 if (kapp && (Tty != kapp->type())) 01589 setOverrideCursor( tqwaitCursor ); 01590 my_system(TQFile::encodeName(srv)+" --suicide"+" --new-startup"); 01591 if (kapp && (Tty != kapp->type())) 01592 restoreOverrideCursor(); 01593 #endif 01594 } 01595 01596 void TDEApplication::dcopFailure(const TQString &msg) 01597 { 01598 static int failureCount = 0; 01599 failureCount++; 01600 if (failureCount == 1) 01601 { 01602 startKdeinit(); 01603 return; 01604 } 01605 if (failureCount == 2) 01606 { 01607 #ifdef Q_WS_WIN 01608 TDEGlobal::config()->setGroup("General"); 01609 if (TDEGlobal::config()->readBoolEntry("ignoreDCOPFailures", false)) 01610 return; 01611 #endif 01612 TQString msgStr(i18n("There was an error setting up inter-process " 01613 "communications for TDE. The message returned " 01614 "by the system was:\n\n")); 01615 msgStr += msg; 01616 msgStr += i18n("\n\nPlease check that the \"dcopserver\" program is running!"); 01617 01618 if (Tty != kapp->type()) 01619 { 01620 TQMessageBox::critical 01621 ( 01622 kapp->mainWidget(), 01623 i18n("DCOP communications error (%1)").arg(kapp->caption()), 01624 msgStr, 01625 i18n("&OK") 01626 ); 01627 } 01628 else 01629 { 01630 fprintf(stderr, "%s\n", msgStr.local8Bit().data()); 01631 } 01632 01633 return; 01634 } 01635 } 01636 01637 static const TDECmdLineOptions qt_options[] = 01638 { 01639 //FIXME: Check if other options are specific to Qt/X11 01640 #ifdef Q_WS_X11 01641 { "display <displayname>", I18N_NOOP("Use the X-server display 'displayname'"), 0}, 01642 #else 01643 { "display <displayname>", I18N_NOOP("Use the QWS display 'displayname'"), 0}, 01644 #endif 01645 { "session <sessionId>", I18N_NOOP("Restore the application for the given 'sessionId'"), 0}, 01646 { "cmap", I18N_NOOP("Causes the application to install a private color\nmap on an 8-bit display"), 0}, 01647 { "ncols <count>", I18N_NOOP("Limits the number of colors allocated in the color\ncube on an 8-bit display, if the application is\nusing the TQApplication::ManyColor color\nspecification"), 0}, 01648 { "nograb", I18N_NOOP("tells TQt to never grab the mouse or the keyboard"), 0}, 01649 { "dograb", I18N_NOOP("running under a debugger can cause an implicit\n-nograb, use -dograb to override"), 0}, 01650 { "sync", I18N_NOOP("switches to synchronous mode for debugging"), 0}, 01651 { "fn", 0, 0}, 01652 { "font <fontname>", I18N_NOOP("defines the application font"), 0}, 01653 { "bg", 0, 0}, 01654 { "background <color>", I18N_NOOP("sets the default background color and an\napplication palette (light and dark shades are\ncalculated)"), 0}, 01655 { "fg", 0, 0}, 01656 { "foreground <color>", I18N_NOOP("sets the default foreground color"), 0}, 01657 { "btn", 0, 0}, 01658 { "button <color>", I18N_NOOP("sets the default button color"), 0}, 01659 { "name <name>", I18N_NOOP("sets the application name"), 0}, 01660 { "title <title>", I18N_NOOP("sets the application title (caption)"), 0}, 01661 #ifdef Q_WS_X11 01662 { "visual TrueColor", I18N_NOOP("forces the application to use a TrueColor visual on\nan 8-bit display"), 0}, 01663 { "inputstyle <inputstyle>", I18N_NOOP("sets XIM (X Input Method) input style. Possible\nvalues are onthespot, overthespot, offthespot and\nroot"), 0 }, 01664 { "im <XIM server>", I18N_NOOP("set XIM server"),0}, 01665 { "noxim", I18N_NOOP("disable XIM"), 0 }, 01666 #endif 01667 #ifdef Q_WS_QWS 01668 { "qws", I18N_NOOP("forces the application to run as QWS Server"), 0}, 01669 #endif 01670 { "reverse", I18N_NOOP("mirrors the whole layout of widgets"), 0}, 01671 TDECmdLineLastOption 01672 }; 01673 01674 static const TDECmdLineOptions kde_options[] = 01675 { 01676 { "caption <caption>", I18N_NOOP("Use 'caption' as name in the titlebar"), 0}, 01677 { "icon <icon>", I18N_NOOP("Use 'icon' as the application icon"), 0}, 01678 { "miniicon <icon>", I18N_NOOP("Use 'icon' as the icon in the titlebar"), 0}, 01679 { "config <filename>", I18N_NOOP("Use alternative configuration file"), 0}, 01680 { "dcopserver <server>", I18N_NOOP("Use the DCOP Server specified by 'server'"), 0}, 01681 { "nocrashhandler", I18N_NOOP("Disable crash handler, to get core dumps"), 0}, 01682 { "waitforwm", I18N_NOOP("Waits for a WM_NET compatible windowmanager"), 0}, 01683 { "style <style>", I18N_NOOP("sets the application GUI style"), 0}, 01684 { "geometry <geometry>", I18N_NOOP("sets the client geometry of the main widget - see man X for the argument format"), 0}, 01685 { "smkey <sessionKey>", 0, 0}, // this option is obsolete and exists only to allow smooth upgrades from sessions 01686 // saved under Qt 3.0.x -- Qt 3.1.x includes the session key now automatically in 01687 // the session id (Simon) 01688 TDECmdLineLastOption 01689 }; 01690 01691 void 01692 TDEApplication::addCmdLineOptions() 01693 { 01694 TDECmdLineArgs::addCmdLineOptions(qt_options, "Qt", "qt"); 01695 TDECmdLineArgs::addCmdLineOptions(kde_options, "TDE", "tde"); 01696 } 01697 01698 void TDEApplication::parseCommandLine( ) 01699 { 01700 TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs("tde"); 01701 01702 if ( !args ) return; 01703 01704 if (args->isSet("config")) 01705 { 01706 TQString config = TQString::fromLocal8Bit(args->getOption("config")); 01707 setConfigName(config); 01708 } 01709 01710 if (args->isSet("style")) 01711 { 01712 01713 TQStringList plugins = TDEGlobal::dirs()->resourceDirs( "qtplugins" ); 01714 TQStringList::Iterator itp = plugins.begin(); 01715 while (itp != plugins.end()) { 01716 addLibraryPath( *itp ); 01717 ++itp; 01718 } 01719 01720 TQStringList styles = TQStyleFactory::keys(); 01721 TQString reqStyle(args->getOption("style").lower()); 01722 01723 TQStringList list = libraryPaths(); 01724 TQStringList::Iterator it = list.begin(); 01725 while( it != list.end() ) { 01726 ++it; 01727 } 01728 01729 for (TQStringList::ConstIterator it = styles.begin(); it != styles.end(); ++it) { 01730 if ((*it).lower() == reqStyle) 01731 { 01732 d->overrideStyle = *it; 01733 break; 01734 } 01735 } 01736 01737 if (d->overrideStyle.isEmpty()) 01738 fprintf(stderr, "%s", TQString(i18n("The style %1 was not found\n").arg(reqStyle)).local8Bit().data()); 01739 } 01740 01741 if (args->isSet("caption")) 01742 { 01743 aCaption = TQString::fromLocal8Bit(args->getOption("caption")); 01744 } 01745 01746 if (args->isSet("miniicon")) 01747 { 01748 const char *tmp = args->getOption("miniicon"); 01749 if (!aIconPixmap.pm.miniIcon) { 01750 aIconPixmap.pm.miniIcon = new TQPixmap; 01751 } 01752 *aIconPixmap.pm.miniIcon = SmallIcon(tmp); 01753 aMiniIconName = tmp; 01754 } 01755 01756 if (args->isSet("icon")) 01757 { 01758 const char *tmp = args->getOption("icon"); 01759 if (!aIconPixmap.pm.icon) { 01760 aIconPixmap.pm.icon = new TQPixmap; 01761 } 01762 *aIconPixmap.pm.icon = DesktopIcon( tmp ); 01763 aIconName = tmp; 01764 if (!aIconPixmap.pm.miniIcon) { 01765 aIconPixmap.pm.miniIcon = new TQPixmap; 01766 } 01767 if (aIconPixmap.pm.miniIcon->isNull()) 01768 { 01769 *aIconPixmap.pm.miniIcon = SmallIcon( tmp ); 01770 aMiniIconName = tmp; 01771 } 01772 } 01773 01774 bool nocrashhandler = (getenv("TDE_DEBUG") != NULL); 01775 if (!nocrashhandler && args->isSet("crashhandler")) 01776 { 01777 // set default crash handler / set emergency save function to nothing 01778 TDECrash::setCrashHandler(TDECrash::defaultCrashHandler); 01779 TDECrash::setEmergencySaveFunction(NULL); 01780 01781 TDECrash::setApplicationName(TQString(args->appName())); 01782 } 01783 01784 #ifdef Q_WS_X11 01785 if ( args->isSet( "waitforwm" ) ) { 01786 Atom type; 01787 (void) desktop(); // trigger desktop creation, we need PropertyNotify events for the root window 01788 int format; 01789 unsigned long length, after; 01790 unsigned char *data; 01791 while ( XGetWindowProperty( tqt_xdisplay(), tqt_xrootwin(), atom_NetSupported, 01792 0, 1, false, AnyPropertyType, &type, &format, 01793 &length, &after, &data ) != Success || !length ) { 01794 if ( data ) 01795 XFree( data ); 01796 XEvent event; 01797 XWindowEvent( tqt_xdisplay(), tqt_xrootwin(), PropertyChangeMask, &event ); 01798 } 01799 if ( data ) 01800 XFree( data ); 01801 } 01802 #else 01803 // FIXME(E): Implement for Qt Embedded 01804 #endif 01805 01806 if (args->isSet("geometry")) 01807 { 01808 d->geometry_arg = args->getOption("geometry"); 01809 } 01810 01811 if (args->isSet("smkey")) 01812 { 01813 d->sessionKey = args->getOption("smkey"); 01814 } 01815 01816 } 01817 01818 TQString TDEApplication::geometryArgument() const 01819 { 01820 return d->geometry_arg; 01821 } 01822 01823 TQPixmap TDEApplication::icon() const 01824 { 01825 if( !aIconPixmap.pm.icon) { 01826 aIconPixmap.pm.icon = new TQPixmap; 01827 } 01828 if( aIconPixmap.pm.icon->isNull()) { 01829 *aIconPixmap.pm.icon = DesktopIcon( instanceName() ); 01830 } 01831 return *aIconPixmap.pm.icon; 01832 } 01833 01834 TQString TDEApplication::iconName() const 01835 { 01836 return aIconName.isNull() ? (TQString)instanceName() : aIconName; 01837 } 01838 01839 TQPixmap TDEApplication::miniIcon() const 01840 { 01841 if (!aIconPixmap.pm.miniIcon) { 01842 aIconPixmap.pm.miniIcon = new TQPixmap; 01843 } 01844 if (aIconPixmap.pm.miniIcon->isNull()) { 01845 *aIconPixmap.pm.miniIcon = SmallIcon( instanceName() ); 01846 } 01847 return *aIconPixmap.pm.miniIcon; 01848 } 01849 01850 TQString TDEApplication::miniIconName() const 01851 { 01852 return aMiniIconName.isNull() ? (TQString)instanceName() : aMiniIconName; 01853 } 01854 01855 extern void kDebugCleanup(); 01856 01857 TDEApplication::~TDEApplication() 01858 { 01859 delete aIconPixmap.pm.miniIcon; 01860 aIconPixmap.pm.miniIcon = 0L; 01861 delete aIconPixmap.pm.icon; 01862 aIconPixmap.pm.icon = 0L; 01863 delete d->m_KAppDCOPInterface; 01864 01865 // First call the static deleters and then call KLibLoader::cleanup() 01866 // The static deleters may delete libraries for which they need KLibLoader. 01867 // KLibLoader will take care of the remaining ones. 01868 TDEGlobal::deleteStaticDeleters(); 01869 KLibLoader::cleanUp(); 01870 01871 delete smw; 01872 01873 // close down IPC 01874 delete s_DCOPClient; 01875 s_DCOPClient = 0L; 01876 01877 TDEProcessController::deref(); 01878 01879 #ifdef Q_WS_X11 01880 if ( d->oldXErrorHandler != NULL ) 01881 XSetErrorHandler( d->oldXErrorHandler ); 01882 if ( d->oldXIOErrorHandler != NULL ) 01883 XSetIOErrorHandler( d->oldXIOErrorHandler ); 01884 if ( d->oldIceIOErrorHandler != NULL ) 01885 IceSetIOErrorHandler( d->oldIceIOErrorHandler ); 01886 #endif 01887 01888 delete d; 01889 KApp = 0; 01890 01891 #ifdef Q_WS_X11 01892 mySmcConnection = 0; 01893 delete smModificationTime; 01894 smModificationTime = 0; 01895 01896 // close the temporary smc connection 01897 if (tmpSmcConnection) { 01898 SmcCloseConnection( tmpSmcConnection, 0, 0 ); 01899 tmpSmcConnection = 0; 01900 } 01901 #else 01902 // FIXME(E): Implement for Qt Embedded 01903 #endif 01904 } 01905 01906 01907 #ifdef Q_WS_X11 01908 class KAppX11HackWidget: public TQWidget 01909 { 01910 public: 01911 bool publicx11Event( XEvent * e) { return x11Event( e ); } 01912 }; 01913 #endif 01914 01915 #if defined(Q_WS_X11) && defined(COMPOSITE) 01916 bool TDEApplication::isCompositionManagerAvailable() { 01917 bool have_manager = false; 01918 01919 char *filename; 01920 const char *pidfile = "compton-tde.available"; 01921 char uidstr[sizeof(uid_t)*8+1]; 01922 sprintf(uidstr, "%d", getuid()); 01923 int n = strlen(P_tmpdir)+strlen(uidstr)+strlen(pidfile)+3; 01924 filename = (char*)malloc(n*sizeof(char)+1); 01925 memset(filename,0,n); 01926 strcat(filename, P_tmpdir); 01927 strcat(filename, "/."); 01928 strcat(filename, uidstr); 01929 strcat(filename, "-"); 01930 strcat(filename, pidfile); 01931 01932 // Now that we did all that by way of introduction...read the file! 01933 FILE *pFile; 01934 pFile = fopen(filename, "r"); 01935 if (pFile) { 01936 have_manager = true; 01937 fclose(pFile); 01938 } 01939 01940 free(filename); 01941 filename = NULL; 01942 01943 return have_manager; 01944 } 01945 01946 bool TDEApplication::detectCompositionManagerAvailable(bool force_available, bool available) { 01947 bool compositing_manager_available; 01948 if (force_available) { 01949 compositing_manager_available = available; 01950 } 01951 else { 01952 // See if compositing has been enabled 01953 TDECmdLineArgs *qtargs = TDECmdLineArgs::parsedArgs("qt"); 01954 char *displayname = 0; 01955 if ( qtargs->isSet("display")) 01956 displayname = qtargs->getOption( "display" ).data(); 01957 01958 Display *dpy = XOpenDisplay( displayname ); 01959 01960 x11_composite_error_generated = false; 01961 compositing_manager_available = false; 01962 XSetErrorHandler(x11_error); 01963 if (!XQueryExtension (dpy, COMPOSITE_NAME, &composite_opcode, &composite_event, &composite_error)) { 01964 XSetErrorHandler(NULL); 01965 compositing_manager_available = false; 01966 } 01967 else { 01968 if (available) { // FIXME This variable does double duty to avoid breaking the ABI for R14.0. In reality it should be called perform_deep_check 01969 Window root_window = XDefaultRootWindow(dpy); 01970 XCompositeRedirectSubwindows(dpy, root_window, CompositeRedirectManual); 01971 XSync(dpy, false); 01972 if (x11_composite_error_generated == true) { 01973 compositing_manager_available = true; 01974 } 01975 else { 01976 XCompositeUnredirectSubwindows(dpy, root_window, CompositeRedirectManual); 01977 compositing_manager_available = false; 01978 } 01979 XSetErrorHandler(NULL); 01980 XCloseDisplay(dpy); 01981 } 01982 else { 01983 compositing_manager_available = true; 01984 } 01985 } 01986 } 01987 01988 char *filename; 01989 const char *pidfile = "compton-tde.available"; 01990 char uidstr[sizeof(uid_t)*8+1]; 01991 sprintf(uidstr, "%d", getuid()); 01992 int n = strlen(P_tmpdir)+strlen(uidstr)+strlen(pidfile)+3; 01993 filename = (char*)malloc(n*sizeof(char)+1); 01994 memset(filename,0,n); 01995 strcat(filename, P_tmpdir); 01996 strcat(filename, "/."); 01997 strcat(filename, uidstr); 01998 strcat(filename, "-"); 01999 strcat(filename, pidfile); 02000 02001 /* now that we did all that by way of introduction...create or remove the file! */ 02002 if (compositing_manager_available) { 02003 FILE *pFile; 02004 char buffer[255]; 02005 sprintf(buffer, "available"); 02006 pFile = fopen(filename, "w"); 02007 if (pFile) { 02008 fwrite(buffer,1,strlen(buffer), pFile); 02009 fclose(pFile); 02010 } 02011 } 02012 else { 02013 unlink(filename); 02014 } 02015 02016 free(filename); 02017 filename = NULL; 02018 02019 return compositing_manager_available; 02020 } 02021 02022 Display* TDEApplication::openX11RGBADisplay() { 02023 TDECmdLineArgs *qtargs = TDECmdLineArgs::parsedArgs("qt"); 02024 char *display = 0; 02025 if ( qtargs->isSet("display")) 02026 display = qtargs->getOption( "display" ).data(); 02027 02028 Display *dpy = XOpenDisplay( display ); 02029 if ( !dpy ) { 02030 kdError() << "cannot connect to X server " << display << endl; 02031 exit( 1 ); 02032 } 02033 02034 return dpy; 02035 } 02036 02037 Qt::HANDLE TDEApplication::getX11RGBAVisual(Display *dpy) { 02038 getX11RGBAInformation(dpy); 02039 if (TDEApplication::isCompositionManagerAvailable() == true) { 02040 return argb_x11_visual; 02041 } 02042 else { 02043 return (Qt::HANDLE)NULL; 02044 } 02045 } 02046 02047 Qt::HANDLE TDEApplication::getX11RGBAColormap(Display *dpy) { 02048 getX11RGBAInformation(dpy); 02049 if (TDEApplication::isCompositionManagerAvailable() == true) { 02050 return argb_x11_colormap; 02051 } 02052 else { 02053 return (Qt::HANDLE)NULL; 02054 } 02055 } 02056 02057 bool TDEApplication::isX11CompositionAvailable() { 02058 return (argb_visual & isCompositionManagerAvailable()); 02059 } 02060 02061 void TDEApplication::getX11RGBAInformation(Display *dpy) { 02062 if ( !dpy ) { 02063 argb_visual = false; 02064 return; 02065 } 02066 02067 int screen = DefaultScreen( dpy ); 02068 Colormap colormap = 0; 02069 Visual *visual = 0; 02070 int event_base, error_base; 02071 02072 if ( XRenderQueryExtension( dpy, &event_base, &error_base ) ) { 02073 int nvi; 02074 XVisualInfo templ; 02075 templ.screen = screen; 02076 templ.depth = 32; 02077 templ.c_class = TrueColor; 02078 XVisualInfo *xvi = XGetVisualInfo( dpy, VisualScreenMask | VisualDepthMask 02079 | VisualClassMask, &templ, &nvi ); 02080 02081 for ( int i = 0; i < nvi; i++ ) { 02082 XRenderPictFormat *format = XRenderFindVisualFormat( dpy, xvi[i].visual ); 02083 if ( format->type == PictTypeDirect && format->direct.alphaMask ) { 02084 visual = xvi[i].visual; 02085 colormap = XCreateColormap( dpy, RootWindow( dpy, screen ), visual, AllocNone ); 02086 kdDebug() << "[tdecore-tdeapplication] Found visual with alpha support" << endl; 02087 argb_visual = true; 02088 break; 02089 } 02090 } 02091 } 02092 02093 if( argb_visual ) { 02094 argb_x11_visual = Qt::HANDLE( visual ); 02095 argb_x11_colormap = Qt::HANDLE( colormap ); 02096 argb_visual = true; 02097 return; 02098 } 02099 argb_visual = false; 02100 return; 02101 } 02102 #else 02103 void TDEApplication::getX11RGBAInformation(Display *dpy) { 02104 } 02105 02106 bool TDEApplication::isCompositionManagerAvailable() { 02107 return false; 02108 } 02109 02110 bool TDEApplication::detectCompositionManagerAvailable(bool force_available, bool available) { 02111 char *filename; 02112 const char *pidfile = "compton-tde.available"; 02113 char uidstr[sizeof(uid_t)*8+1]; 02114 sprintf(uidstr, "%d", getuid()); 02115 int n = strlen(P_tmpdir)+strlen(uidstr)+strlen(pidfile)+3; 02116 filename = (char*)malloc(n*sizeof(char)+1); 02117 memset(filename,0,n); 02118 strcat(filename, P_tmpdir); 02119 strcat(filename, "/."); 02120 strcat(filename, uidstr); 02121 strcat(filename, "-"); 02122 strcat(filename, pidfile); 02123 02124 /* now that we did all that by way of introduction...create or remove the file! */ 02125 if (force_available) { 02126 FILE *pFile; 02127 char buffer[255]; 02128 sprintf(buffer, "available"); 02129 pFile = fopen(filename, "w"); 02130 if (pFile) { 02131 fwrite(buffer,1,strlen(buffer), pFile); 02132 fclose(pFile); 02133 } 02134 } 02135 else { 02136 unlink(filename); 02137 } 02138 02139 free(filename); 02140 filename = NULL; 02141 02142 return false; 02143 } 02144 02145 Display* TDEApplication::openX11RGBADisplay() { 02146 return 0; 02147 } 02148 02149 Qt::HANDLE TDEApplication::getX11RGBAVisual(Display *dpy) { 02150 return 0; 02151 } 02152 02153 Qt::HANDLE TDEApplication::getX11RGBAColormap(Display *dpy) { 02154 return 0; 02155 } 02156 02157 bool TDEApplication::isX11CompositionAvailable() { 02158 return false; 02159 } 02160 #endif 02161 02162 static bool kapp_block_user_input = false; 02163 02164 void TDEApplication::dcopBlockUserInput( bool b ) 02165 { 02166 kapp_block_user_input = b; 02167 } 02168 02169 #ifdef Q_WS_X11 02170 bool TDEApplication::x11EventFilter( XEvent *_event ) 02171 { 02172 if ( kapp_block_user_input ) { 02173 switch ( _event->type ) { 02174 case ButtonPress: 02175 case ButtonRelease: 02176 case XKeyPress: 02177 case XKeyRelease: 02178 case MotionNotify: 02179 case EnterNotify: 02180 case LeaveNotify: 02181 return true; 02182 default: 02183 break; 02184 } 02185 } 02186 02187 if (x11Filter) { 02188 for (TQWidget *w=x11Filter->first(); w; w=x11Filter->next()) { 02189 if (((KAppX11HackWidget*) w)->publicx11Event(_event)) 02190 return true; 02191 } 02192 } 02193 02194 if ((_event->type == ClientMessage) && 02195 (_event->xclient.message_type == kipcCommAtom)) 02196 { 02197 XClientMessageEvent *cme = (XClientMessageEvent *) _event; 02198 02199 int id = cme->data.l[0]; 02200 int arg = cme->data.l[1]; 02201 if ((id < 32) && (kipcEventMask & (1 << id))) 02202 { 02203 switch (id) 02204 { 02205 case KIPC::StyleChanged: 02206 TDEGlobal::config()->reparseConfiguration(); 02207 tdedisplaySetStyle(); 02208 break; 02209 02210 case KIPC::ToolbarStyleChanged: 02211 TDEGlobal::config()->reparseConfiguration(); 02212 if (useStyles) 02213 emit toolbarAppearanceChanged(arg); 02214 break; 02215 02216 case KIPC::PaletteChanged: 02217 TDEGlobal::config()->reparseConfiguration(); 02218 tdedisplaySetPalette(); 02219 break; 02220 02221 case KIPC::FontChanged: 02222 TDEGlobal::config()->reparseConfiguration(); 02223 TDEGlobalSettings::rereadFontSettings(); 02224 tdedisplaySetFont(); 02225 break; 02226 02227 case KIPC::BackgroundChanged: 02228 emit backgroundChanged(arg); 02229 break; 02230 02231 case KIPC::SettingsChanged: 02232 TDEGlobal::config()->reparseConfiguration(); 02233 if (arg == SETTINGS_PATHS) 02234 TDEGlobalSettings::rereadPathSettings(); 02235 else if (arg == SETTINGS_MOUSE) 02236 TDEGlobalSettings::rereadMouseSettings(); 02237 propagateSettings((SettingsCategory)arg); 02238 break; 02239 02240 case KIPC::IconChanged: 02241 TQPixmapCache::clear(); 02242 TDEGlobal::config()->reparseConfiguration(); 02243 TDEGlobal::instance()->newIconLoader(); 02244 emit updateIconLoaders(); 02245 emit iconChanged(arg); 02246 break; 02247 02248 case KIPC::ClipboardConfigChanged: 02249 TDEClipboardSynchronizer::newConfiguration(arg); 02250 break; 02251 02252 case KIPC::BlockShortcuts: 02253 TDEGlobalAccel::blockShortcuts(arg); 02254 emit kipcMessage(id, arg); // some apps may do additional things 02255 break; 02256 } 02257 } 02258 else if (id >= 32) 02259 { 02260 emit kipcMessage(id, arg); 02261 } 02262 return true; 02263 } 02264 return false; 02265 } 02266 #endif // Q_WS_X11 02267 02268 void TDEApplication::updateUserTimestamp( unsigned long time ) 02269 { 02270 #if defined Q_WS_X11 02271 Display *display = tqt_xdisplay(); 02272 if (!display) { 02273 return; 02274 } 02275 if( time == 0 ) 02276 { // get current X timestamp 02277 Window w = XCreateSimpleWindow( display, tqt_xrootwin(), 0, 0, 1, 1, 0, 0, 0 ); 02278 XSelectInput( tqt_xdisplay(), w, PropertyChangeMask ); 02279 unsigned char data[ 1 ]; 02280 XChangeProperty( display, w, XA_ATOM, XA_ATOM, 8, PropModeAppend, data, 1 ); 02281 XEvent ev; 02282 XWindowEvent( display, w, PropertyChangeMask, &ev ); 02283 time = ev.xproperty.time; 02284 XDestroyWindow( display, w ); 02285 } 02286 if( GET_QT_X_USER_TIME() == 0 02287 || NET::timestampCompare( time, GET_QT_X_USER_TIME() ) > 0 ) // check time > tqt_x_user_time 02288 SET_QT_X_USER_TIME(time); 02289 #endif 02290 } 02291 02292 unsigned long TDEApplication::userTimestamp() const 02293 { 02294 #if defined Q_WS_X11 02295 return GET_QT_X_USER_TIME(); 02296 #else 02297 return 0; 02298 #endif 02299 } 02300 02301 void TDEApplication::updateRemoteUserTimestamp( const TQCString& dcopId, unsigned long time ) 02302 { 02303 #if defined Q_WS_X11 02304 if( time == 0 ) 02305 time = GET_QT_X_USER_TIME(); 02306 DCOPRef( dcopId, "MainApplication-Interface" ).call( "updateUserTimestamp", time ); 02307 #endif 02308 } 02309 02310 void TDEApplication::invokeEditSlot( const char *slot ) 02311 { 02312 TQObject *object = TQT_TQOBJECT(focusWidget()); 02313 if( !object ) 02314 return; 02315 02316 TQMetaObject *meta = object->metaObject(); 02317 02318 int idx = meta->findSlot( slot + 1, true ); 02319 if( idx < 0 ) 02320 return; 02321 02322 object->tqt_invoke( idx, 0 ); 02323 } 02324 02325 void TDEApplication::addKipcEventMask(int id) 02326 { 02327 if (id >= 32) 02328 { 02329 kdDebug(101) << "[tdecore-tdeapplication] Cannot use KIPC event mask for message IDs >= 32\n"; 02330 return; 02331 } 02332 kipcEventMask |= (1 << id); 02333 } 02334 02335 void TDEApplication::removeKipcEventMask(int id) 02336 { 02337 if (id >= 32) 02338 { 02339 kdDebug(101) << "[tdecore-tdeapplication] Cannot use KIPC event mask for message IDs >= 32\n"; 02340 return; 02341 } 02342 kipcEventMask &= ~(1 << id); 02343 } 02344 02345 void TDEApplication::enableStyles() 02346 { 02347 if (!useStyles) 02348 { 02349 useStyles = true; 02350 applyGUIStyle(); 02351 } 02352 } 02353 02354 void TDEApplication::disableStyles() 02355 { 02356 useStyles = false; 02357 } 02358 02359 void TDEApplication::applyGUIStyle() 02360 { 02361 if ( !useStyles ) return; 02362 02363 TDEConfigGroup pConfig (TDEGlobal::config(), "General"); 02364 TQString defaultStyle = TDEStyle::defaultStyle(); 02365 TQString styleStr = pConfig.readEntry("widgetStyle", defaultStyle); 02366 02367 if (d->overrideStyle.isEmpty()) { 02368 // ### add check whether we already use the correct style to return then 02369 // (workaround for Qt misbehavior to avoid double style initialization) 02370 02371 TQStyle* sp = TQStyleFactory::create( styleStr ); 02372 02373 // If there is no default style available, try falling back any available style 02374 if ( !sp && styleStr != defaultStyle) 02375 sp = TQStyleFactory::create( defaultStyle ); 02376 if ( !sp ) 02377 sp = TQStyleFactory::create( *(TQStyleFactory::keys().begin()) ); 02378 setStyle(sp); 02379 } 02380 else 02381 setStyle(d->overrideStyle); 02382 // Reread palette from config file. 02383 tdedisplaySetPalette(); 02384 } 02385 02386 TQString TDEApplication::caption() const 02387 { 02388 // Caption set from command line ? 02389 if( !aCaption.isNull() ) 02390 return aCaption; 02391 else 02392 // We have some about data ? 02393 if ( TDEGlobal::instance()->aboutData() ) 02394 return TDEGlobal::instance()->aboutData()->programName(); 02395 else 02396 // Last resort : application name 02397 return name(); 02398 } 02399 02400 02401 // 02402 // 1999-09-20: Espen Sand 02403 // An attempt to simplify consistent captions. 02404 // 02405 TQString TDEApplication::makeStdCaption( const TQString &userCaption, 02406 bool withAppName, bool modified ) const 02407 { 02408 TQString s = userCaption.isEmpty() ? caption() : userCaption; 02409 02410 // If the document is modified, add '[modified]'. 02411 if (modified) 02412 s += TQString::fromUtf8(" [") + i18n("modified") + TQString::fromUtf8("]"); 02413 02414 if ( !userCaption.isEmpty() ) { 02415 // Add the application name if: 02416 // User asked for it, it's not a duplication and the app name (caption()) is not empty 02417 if ( withAppName && !caption().isNull() && !userCaption.endsWith(caption()) ) 02418 s += TQString::fromUtf8(" - ") + caption(); 02419 } 02420 02421 return s; 02422 } 02423 02424 TQPalette TDEApplication::createApplicationPalette() 02425 { 02426 TDEConfig *config = TDEGlobal::config(); 02427 TDEConfigGroupSaver saver( config, "General" ); 02428 return createApplicationPalette( config, TDEGlobalSettings::contrast() ); 02429 } 02430 02431 TQPalette TDEApplication::createApplicationPalette( TDEConfig *config, int contrast_ ) 02432 { 02433 TQColor trinity4Background( 239, 239, 239 ); 02434 TQColor trinity4Blue( 103,141,178 ); 02435 02436 TQColor trinity4Button; 02437 if ( TQPixmap::defaultDepth() > 8 ) 02438 trinity4Button.setRgb( 221, 223, 228 ); 02439 else 02440 trinity4Button.setRgb( 220, 220, 220 ); 02441 02442 TQColor trinity4Link( 0, 0, 238 ); 02443 TQColor trinity4VisitedLink( 82, 24, 139 ); 02444 02445 TQColor background = config->readColorEntry( "background", &trinity4Background ); 02446 TQColor foreground = config->readColorEntry( "foreground", tqblackptr ); 02447 TQColor button = config->readColorEntry( "buttonBackground", &trinity4Button ); 02448 TQColor buttonText = config->readColorEntry( "buttonForeground", tqblackptr ); 02449 TQColor highlight = config->readColorEntry( "selectBackground", &trinity4Blue ); 02450 TQColor highlightedText = config->readColorEntry( "selectForeground", tqwhiteptr ); 02451 TQColor base = config->readColorEntry( "windowBackground", tqwhiteptr ); 02452 TQColor baseText = config->readColorEntry( "windowForeground", tqblackptr ); 02453 TQColor link = config->readColorEntry( "linkColor", &trinity4Link ); 02454 TQColor visitedLink = config->readColorEntry( "visitedLinkColor", &trinity4VisitedLink ); 02455 02456 int highlightVal, lowlightVal; 02457 highlightVal = 100 + (2*contrast_+4)*16/10; 02458 lowlightVal = 100 + (2*contrast_+4)*10; 02459 02460 TQColor disfg = foreground; 02461 02462 int h, s, v; 02463 disfg.hsv( &h, &s, &v ); 02464 if (v > 128) 02465 // dark bg, light fg - need a darker disabled fg 02466 disfg = disfg.dark(lowlightVal); 02467 else if (disfg != Qt::black) 02468 // light bg, dark fg - need a lighter disabled fg - but only if !black 02469 disfg = disfg.light(highlightVal); 02470 else 02471 // black fg - use darkgray disabled fg 02472 disfg = Qt::darkGray; 02473 02474 02475 TQColorGroup disabledgrp(disfg, background, 02476 background.light(highlightVal), 02477 background.dark(lowlightVal), 02478 background.dark(120), 02479 background.dark(120), base); 02480 02481 TQColorGroup colgrp(foreground, background, background.light(highlightVal), 02482 background.dark(lowlightVal), 02483 background.dark(120), 02484 baseText, base); 02485 02486 int inlowlightVal = lowlightVal-25; 02487 if(inlowlightVal < 120) 02488 inlowlightVal = 120; 02489 02490 colgrp.setColor(TQColorGroup::Highlight, highlight); 02491 colgrp.setColor(TQColorGroup::HighlightedText, highlightedText); 02492 colgrp.setColor(TQColorGroup::Button, button); 02493 colgrp.setColor(TQColorGroup::ButtonText, buttonText); 02494 colgrp.setColor(TQColorGroup::Midlight, background.light(110)); 02495 colgrp.setColor(TQColorGroup::Link, link); 02496 colgrp.setColor(TQColorGroup::LinkVisited, visitedLink); 02497 02498 disabledgrp.setColor(TQColorGroup::Button, button); 02499 02500 TQColor disbtntext = buttonText; 02501 disbtntext.hsv( &h, &s, &v ); 02502 if (v > 128) 02503 // dark button, light buttonText - need a darker disabled buttonText 02504 disbtntext = disbtntext.dark(lowlightVal); 02505 else if (disbtntext != Qt::black) 02506 // light buttonText, dark button - need a lighter disabled buttonText - but only if !black 02507 disbtntext = disbtntext.light(highlightVal); 02508 else 02509 // black button - use darkgray disabled buttonText 02510 disbtntext = Qt::darkGray; 02511 02512 disabledgrp.setColor(TQColorGroup::ButtonText, disbtntext); 02513 disabledgrp.setColor(TQColorGroup::Midlight, background.light(110)); 02514 disabledgrp.setColor(TQColorGroup::Highlight, highlight.dark(120)); 02515 disabledgrp.setColor(TQColorGroup::Link, link); 02516 disabledgrp.setColor(TQColorGroup::LinkVisited, visitedLink); 02517 02518 return TQPalette(colgrp, disabledgrp, colgrp); 02519 } 02520 02521 02522 void TDEApplication::tdedisplaySetPalette() 02523 { 02524 #ifdef Q_WS_MACX 02525 //Can I have this on other platforms, please!? --Sam 02526 { 02527 TDEConfig *config = TDEGlobal::config(); 02528 TDEConfigGroupSaver saver( config, "General" ); 02529 bool do_not_set_palette = FALSE; 02530 if(config->readBoolEntry("nopaletteChange", &do_not_set_palette)) 02531 return; 02532 } 02533 #endif 02534 TQApplication::setPalette( createApplicationPalette(), true); 02535 emit tdedisplayPaletteChanged(); 02536 emit appearanceChanged(); 02537 } 02538 02539 02540 void TDEApplication::tdedisplaySetFont() 02541 { 02542 TQApplication::setFont(TDEGlobalSettings::generalFont(), true); 02543 TQApplication::setFont(TDEGlobalSettings::menuFont(), true, TQMENUBAR_OBJECT_NAME_STRING); 02544 TQApplication::setFont(TDEGlobalSettings::menuFont(), true, TQPOPUPMENU_OBJECT_NAME_STRING); 02545 TQApplication::setFont(TDEGlobalSettings::menuFont(), true, "TDEPopupTitle"); 02546 02547 // "patch" standard TQStyleSheet to follow our fonts 02548 TQStyleSheet* sheet = TQStyleSheet::defaultSheet(); 02549 sheet->item ("pre")->setFontFamily (TDEGlobalSettings::fixedFont().family()); 02550 sheet->item ("code")->setFontFamily (TDEGlobalSettings::fixedFont().family()); 02551 sheet->item ("tt")->setFontFamily (TDEGlobalSettings::fixedFont().family()); 02552 02553 emit tdedisplayFontChanged(); 02554 emit appearanceChanged(); 02555 } 02556 02557 02558 void TDEApplication::tdedisplaySetStyle() 02559 { 02560 if (useStyles) 02561 { 02562 applyGUIStyle(); 02563 emit tdedisplayStyleChanged(); 02564 emit appearanceChanged(); 02565 } 02566 } 02567 02568 02569 void TDEApplication::propagateSettings(SettingsCategory arg) 02570 { 02571 TDEConfigBase* config = TDEGlobal::config(); 02572 TDEConfigGroupSaver saver( config, "KDE" ); 02573 02574 #ifdef QT_HAVE_MAX_IMAGE_SIZE 02575 TQSize maxImageSize(4096, 4096); 02576 maxImageSize = config->readSizeEntry("MaxImageSize", &maxImageSize); 02577 TQImage::setMaxImageSize(maxImageSize); 02578 #endif 02579 02580 int num = config->readNumEntry("CursorBlinkRate", TQApplication::cursorFlashTime()); 02581 if ((num != 0) && (num < 200)) 02582 num = 200; 02583 if (num > 2000) 02584 num = 2000; 02585 TQApplication::setCursorFlashTime(num); 02586 num = config->readNumEntry("DoubleClickInterval", TQApplication::doubleClickInterval()); 02587 TQApplication::setDoubleClickInterval(num); 02588 num = config->readNumEntry("StartDragTime", TQApplication::startDragTime()); 02589 TQApplication::setStartDragTime(num); 02590 num = config->readNumEntry("StartDragDist", TQApplication::startDragDistance()); 02591 TQApplication::setStartDragDistance(num); 02592 num = config->readNumEntry("WheelScrollLines", TQApplication::wheelScrollLines()); 02593 TQApplication::setWheelScrollLines(num); 02594 02595 bool b = config->readBoolEntry("EffectAnimateMenu", false); 02596 TQApplication::setEffectEnabled( Qt::UI_AnimateMenu, b); 02597 b = config->readBoolEntry("EffectFadeMenu", false); 02598 TQApplication::setEffectEnabled( Qt::UI_FadeMenu, b); 02599 b = config->readBoolEntry("EffectAnimateCombo", false); 02600 TQApplication::setEffectEnabled( Qt::UI_AnimateCombo, b); 02601 b = config->readBoolEntry("EffectAnimateTooltip", false); 02602 TQApplication::setEffectEnabled( Qt::UI_AnimateTooltip, b); 02603 b = config->readBoolEntry("EffectFadeTooltip", false); 02604 TQApplication::setEffectEnabled( Qt::UI_FadeTooltip, b); 02605 b = !config->readBoolEntry("EffectNoTooltip", false); 02606 TQToolTip::setGloballyEnabled( b ); 02607 02608 emit settingsChanged(arg); 02609 } 02610 02611 void TDEApplication::installKDEPropertyMap() 02612 { 02613 #ifndef QT_NO_SQL 02614 static bool installed = false; 02615 if (installed) return; 02616 installed = true; 02623 // TQSqlPropertyMap takes ownership of the new default map. 02624 TQSqlPropertyMap *kdeMap = new TQSqlPropertyMap; 02625 kdeMap->insert( "KColorButton", "color" ); 02626 kdeMap->insert( "KComboBox", "currentItem" ); 02627 kdeMap->insert( "KDatePicker", "date" ); 02628 kdeMap->insert( "KDateWidget", "date" ); 02629 kdeMap->insert( "KDateTimeWidget", "dateTime" ); 02630 kdeMap->insert( "KEditListBox", "items" ); 02631 kdeMap->insert( "TDEFontCombo", "family" ); 02632 kdeMap->insert( "TDEFontRequester", "font" ); 02633 kdeMap->insert( "TDEFontChooser", "font" ); 02634 kdeMap->insert( "KHistoryCombo", "currentItem" ); 02635 kdeMap->insert( "TDEListBox", "currentItem" ); 02636 kdeMap->insert( "KLineEdit", "text" ); 02637 kdeMap->insert( "KRestrictedLine", "text" ); 02638 kdeMap->insert( "KSqueezedTextLabel", "text" ); 02639 kdeMap->insert( "KTextBrowser", "source" ); 02640 kdeMap->insert( "KTextEdit", "text" ); 02641 kdeMap->insert( "KURLRequester", "url" ); 02642 kdeMap->insert( "KPasswordEdit", "password" ); 02643 kdeMap->insert( "KIntNumInput", "value" ); 02644 kdeMap->insert( "KIntSpinBox", "value" ); 02645 kdeMap->insert( "KDoubleNumInput", "value" ); 02646 // Temp til fixed in QT then enable ifdef with the correct version num 02647 kdeMap->insert( TQGROUPBOX_OBJECT_NAME_STRING, "checked" ); 02648 kdeMap->insert( TQTABWIDGET_OBJECT_NAME_STRING, "currentPage" ); 02649 TQSqlPropertyMap::installDefaultMap( kdeMap ); 02650 #endif 02651 } 02652 02653 void TDEApplication::invokeHelp( const TQString& anchor, 02654 const TQString& _appname) const 02655 { 02656 return invokeHelp( anchor, _appname, "" ); 02657 } 02658 02659 #ifndef Q_WS_WIN 02660 // for win32 we're using simple help tools like Qt Assistant, 02661 // see kapplication_win.cpp 02662 void TDEApplication::invokeHelp( const TQString& anchor, 02663 const TQString& _appname, 02664 const TQCString& startup_id ) const 02665 { 02666 TQString url; 02667 TQString appname; 02668 if (_appname.isEmpty()) 02669 appname = name(); 02670 else 02671 appname = _appname; 02672 02673 if (!anchor.isEmpty()) 02674 url = TQString("help:/%1?anchor=%2").arg(appname).arg(anchor); 02675 else 02676 url = TQString("help:/%1/index.html").arg(appname); 02677 02678 TQString error; 02679 if ( !dcopClient()->isApplicationRegistered("khelpcenter") ) 02680 { 02681 if (startServiceByDesktopName("khelpcenter", url, &error, 0, 0, startup_id, false)) 02682 { 02683 if (Tty != kapp->type()) 02684 TQMessageBox::critical(kapp->mainWidget(), i18n("Could not Launch Help Center"), 02685 i18n("Could not launch the TDE Help Center:\n\n%1").arg(error), i18n("&OK")); 02686 else 02687 kdWarning() << "Could not launch help:\n" << error << endl; 02688 return; 02689 } 02690 } 02691 else 02692 DCOPRef( "khelpcenter", "KHelpCenterIface" ).send( "openUrl", url, startup_id ); 02693 } 02694 #endif 02695 02696 void TDEApplication::invokeHTMLHelp( const TQString& _filename, const TQString& topic ) const 02697 { 02698 kdWarning() << "invoking HTML help is deprecated! use docbook and invokeHelp!\n"; 02699 02700 TQString filename; 02701 02702 if( _filename.isEmpty() ) 02703 filename = TQString(name()) + "/index.html"; 02704 else 02705 filename = _filename; 02706 02707 TQString url; 02708 if (!topic.isEmpty()) 02709 url = TQString("help:/%1#%2").arg(filename).arg(topic); 02710 else 02711 url = TQString("help:/%1").arg(filename); 02712 02713 TQString error; 02714 if ( !dcopClient()->isApplicationRegistered("khelpcenter") ) 02715 { 02716 if (startServiceByDesktopName("khelpcenter", url, &error, 0, 0, "", false)) 02717 { 02718 if (Tty != kapp->type()) 02719 TQMessageBox::critical(kapp->mainWidget(), i18n("Could not Launch Help Center"), 02720 i18n("Could not launch the TDE Help Center:\n\n%1").arg(error), i18n("&OK")); 02721 else 02722 kdWarning() << "Could not launch help:\n" << error << endl; 02723 return; 02724 } 02725 } 02726 else 02727 DCOPRef( "khelpcenter", "KHelpCenterIface" ).send( "openUrl", url ); 02728 } 02729 02730 02731 void TDEApplication::invokeMailer(const TQString &address, const TQString &subject) 02732 { 02733 return invokeMailer(address,subject,""); 02734 } 02735 02736 void TDEApplication::invokeMailer(const TQString &address, const TQString &subject, const TQCString& startup_id) 02737 { 02738 invokeMailer(address, TQString::null, TQString::null, subject, TQString::null, TQString::null, 02739 TQStringList(), startup_id ); 02740 } 02741 02742 void TDEApplication::invokeMailer(const KURL &mailtoURL) 02743 { 02744 return invokeMailer( mailtoURL, "" ); 02745 } 02746 02747 void TDEApplication::invokeMailer(const KURL &mailtoURL, const TQCString& startup_id ) 02748 { 02749 return invokeMailer( mailtoURL, startup_id, false); 02750 } 02751 02752 void TDEApplication::invokeMailer(const KURL &mailtoURL, const TQCString& startup_id, bool allowAttachments ) 02753 { 02754 TQString address = KURL::decode_string(mailtoURL.path()), subject, cc, bcc, body; 02755 TQStringList queries = TQStringList::split('&', mailtoURL.query().mid(1)); 02756 TQStringList attachURLs; 02757 for (TQStringList::Iterator it = queries.begin(); it != queries.end(); ++it) 02758 { 02759 TQString q = (*it).lower(); 02760 if (q.startsWith("subject=")) 02761 subject = KURL::decode_string((*it).mid(8)); 02762 else 02763 if (q.startsWith("cc=")) 02764 cc = cc.isEmpty()? KURL::decode_string((*it).mid(3)): cc + ',' + KURL::decode_string((*it).mid(3)); 02765 else 02766 if (q.startsWith("bcc=")) 02767 bcc = bcc.isEmpty()? KURL::decode_string((*it).mid(4)): bcc + ',' + KURL::decode_string((*it).mid(4)); 02768 else 02769 if (q.startsWith("body=")) 02770 body = KURL::decode_string((*it).mid(5)); 02771 else 02772 if (allowAttachments && q.startsWith("attach=")) 02773 attachURLs.push_back(KURL::decode_string((*it).mid(7))); 02774 else 02775 if (allowAttachments && q.startsWith("attachment=")) 02776 attachURLs.push_back(KURL::decode_string((*it).mid(11))); 02777 else 02778 if (q.startsWith("to=")) 02779 address = address.isEmpty()? KURL::decode_string((*it).mid(3)): address + ',' + KURL::decode_string((*it).mid(3)); 02780 } 02781 02782 invokeMailer( address, cc, bcc, subject, body, TQString::null, attachURLs, startup_id ); 02783 } 02784 02785 void TDEApplication::invokeMailer(const TQString &to, const TQString &cc, const TQString &bcc, 02786 const TQString &subject, const TQString &body, 02787 const TQString & messageFile, const TQStringList &attachURLs) 02788 { 02789 return invokeMailer(to,cc,bcc,subject,body,messageFile,attachURLs,""); 02790 } 02791 02792 #ifndef Q_WS_WIN 02793 // on win32, for invoking browser we're using win32 API 02794 // see kapplication_win.cpp 02795 02796 static TQStringList splitEmailAddressList( const TQString & aStr ) 02797 { 02798 // This is a copy of KPIM::splitEmailAddrList(). 02799 // Features: 02800 // - always ignores quoted characters 02801 // - ignores everything (including parentheses and commas) 02802 // inside quoted strings 02803 // - supports nested comments 02804 // - ignores everything (including double quotes and commas) 02805 // inside comments 02806 02807 TQStringList list; 02808 02809 if (aStr.isEmpty()) 02810 return list; 02811 02812 TQString addr; 02813 uint addrstart = 0; 02814 int commentlevel = 0; 02815 bool insidequote = false; 02816 02817 for (uint index=0; index<aStr.length(); index++) { 02818 // the following conversion to latin1 is o.k. because 02819 // we can safely ignore all non-latin1 characters 02820 switch (aStr[index].latin1()) { 02821 case '"' : // start or end of quoted string 02822 if (commentlevel == 0) 02823 insidequote = !insidequote; 02824 break; 02825 case '(' : // start of comment 02826 if (!insidequote) 02827 commentlevel++; 02828 break; 02829 case ')' : // end of comment 02830 if (!insidequote) { 02831 if (commentlevel > 0) 02832 commentlevel--; 02833 else { 02834 //kdDebug() << "[tdecore-tdeapplication] Error in address splitting: Unmatched ')'" 02835 // << endl; 02836 return list; 02837 } 02838 } 02839 break; 02840 case '\\' : // quoted character 02841 index++; // ignore the quoted character 02842 break; 02843 case ',' : 02844 if (!insidequote && (commentlevel == 0)) { 02845 addr = aStr.mid(addrstart, index-addrstart); 02846 if (!addr.isEmpty()) 02847 list += addr.simplifyWhiteSpace(); 02848 addrstart = index+1; 02849 } 02850 break; 02851 } 02852 } 02853 // append the last address to the list 02854 if (!insidequote && (commentlevel == 0)) { 02855 addr = aStr.mid(addrstart, aStr.length()-addrstart); 02856 if (!addr.isEmpty()) 02857 list += addr.simplifyWhiteSpace(); 02858 } 02859 //else 02860 // kdDebug() << "[tdecore-tdeapplication] Error in address splitting: " 02861 // << "Unexpected end of address list" 02862 // << endl; 02863 02864 return list; 02865 } 02866 02867 void TDEApplication::invokeMailer(const TQString &_to, const TQString &_cc, const TQString &_bcc, 02868 const TQString &subject, const TQString &body, 02869 const TQString & /*messageFile TODO*/, const TQStringList &attachURLs, 02870 const TQCString& startup_id ) 02871 { 02872 TDEConfig config("emaildefaults"); 02873 02874 config.setGroup("Defaults"); 02875 TQString group = config.readEntry("Profile","Default"); 02876 02877 config.setGroup( TQString("PROFILE_%1").arg(group) ); 02878 TQString command = config.readPathEntry("EmailClient"); 02879 02880 TQString to, cc, bcc; 02881 if (command.isEmpty() || command == TQString::fromLatin1("kmail") 02882 || command.endsWith("/kmail")) 02883 { 02884 command = TQString::fromLatin1("kmail --composer -s %s -c %c -b %b --body %B --attach %A -- %t"); 02885 if ( !_to.isEmpty() ) 02886 { 02887 // put the whole address lists into RFC2047 encoded blobs; technically 02888 // this isn't correct, but KMail understands it nonetheless 02889 to = TQString( "=?utf8?b?%1?=" ) 02890 .arg( TQString(KCodecs::base64Encode( _to.utf8(), false )) ); 02891 } 02892 if ( !_cc.isEmpty() ) 02893 cc = TQString( "=?utf8?b?%1?=" ) 02894 .arg( TQString(KCodecs::base64Encode( _cc.utf8(), false )) ); 02895 if ( !_bcc.isEmpty() ) 02896 bcc = TQString( "=?utf8?b?%1?=" ) 02897 .arg( TQString(KCodecs::base64Encode( _bcc.utf8(), false )) ); 02898 } else { 02899 to = _to; 02900 cc = _cc; 02901 bcc = _bcc; 02902 if( !command.contains( '%' )) 02903 command += " %u"; 02904 } 02905 02906 if (config.readBoolEntry("TerminalClient", false)) 02907 { 02908 TDEConfigGroup confGroup( TDEGlobal::config(), "General" ); 02909 TQString preferredTerminal = confGroup.readPathEntry("TerminalApplication", "konsole"); 02910 command = preferredTerminal + " -e " + command; 02911 } 02912 02913 TQStringList cmdTokens = KShell::splitArgs(command); 02914 TQString cmd = cmdTokens[0]; 02915 cmdTokens.remove(cmdTokens.begin()); 02916 02917 KURL url; 02918 TQStringList qry; 02919 if (!to.isEmpty()) 02920 { 02921 TQStringList tos = splitEmailAddressList( to ); 02922 url.setPath( tos.first() ); 02923 tos.remove( tos.begin() ); 02924 for (TQStringList::ConstIterator it = tos.begin(); it != tos.end(); ++it) 02925 qry.append( "to=" + KURL::encode_string( *it ) ); 02926 } 02927 const TQStringList ccs = splitEmailAddressList( cc ); 02928 for (TQStringList::ConstIterator it = ccs.begin(); it != ccs.end(); ++it) 02929 qry.append( "cc=" + KURL::encode_string( *it ) ); 02930 const TQStringList bccs = splitEmailAddressList( bcc ); 02931 for (TQStringList::ConstIterator it = bccs.begin(); it != bccs.end(); ++it) 02932 qry.append( "bcc=" + KURL::encode_string( *it ) ); 02933 for (TQStringList::ConstIterator it = attachURLs.begin(); it != attachURLs.end(); ++it) 02934 qry.append( "attach=" + KURL::encode_string( *it ) ); 02935 if (!subject.isEmpty()) 02936 qry.append( "subject=" + KURL::encode_string( subject ) ); 02937 if (!body.isEmpty()) 02938 qry.append( "body=" + KURL::encode_string( body ) ); 02939 url.setQuery( qry.join( "&" ) ); 02940 if ( ! (to.isEmpty() && qry.isEmpty()) ) 02941 url.setProtocol("mailto"); 02942 02943 TQMap<TQChar, TQString> keyMap; 02944 keyMap.insert('t', to); 02945 keyMap.insert('s', subject); 02946 keyMap.insert('c', cc); 02947 keyMap.insert('b', bcc); 02948 keyMap.insert('B', body); 02949 keyMap.insert('u', url.url()); 02950 02951 TQString attachlist = attachURLs.join(","); 02952 attachlist.prepend('\''); 02953 attachlist.append('\''); 02954 keyMap.insert('A', attachlist); 02955 02956 for (TQStringList::Iterator it = cmdTokens.begin(); it != cmdTokens.end(); ) 02957 { 02958 if (*it == "%A") 02959 { 02960 if (it == cmdTokens.begin()) // better safe than sorry ... 02961 continue; 02962 TQStringList::ConstIterator urlit = attachURLs.begin(); 02963 TQStringList::ConstIterator urlend = attachURLs.end(); 02964 if ( urlit != urlend ) 02965 { 02966 TQStringList::Iterator previt = it; 02967 --previt; 02968 *it = *urlit; 02969 ++it; 02970 while ( ++urlit != urlend ) 02971 { 02972 cmdTokens.insert( it, *previt ); 02973 cmdTokens.insert( it, *urlit ); 02974 } 02975 } else { 02976 --it; 02977 it = cmdTokens.remove( cmdTokens.remove( it ) ); 02978 } 02979 } else { 02980 *it = KMacroExpander::expandMacros(*it, keyMap); 02981 ++it; 02982 } 02983 } 02984 02985 TQString error; 02986 // TODO this should check if cmd has a .desktop file, and use data from it, together 02987 // with sending more ASN data 02988 if (tdeinitExec(cmd, cmdTokens, &error, NULL, startup_id )) { 02989 if (Tty != kapp->type()) { 02990 TQMessageBox::critical(kapp->mainWidget(), i18n("Could not Launch Mail Client"), 02991 i18n("Could not launch the mail client:\n\n%1").arg(error), i18n("&OK")); 02992 } 02993 else { 02994 kdWarning() << "Could not launch mail client:\n" << error << endl; 02995 } 02996 } 02997 } 02998 #endif 02999 03000 void TDEApplication::invokeBrowser( const TQString &url ) 03001 { 03002 return invokeBrowser( url, "" ); 03003 } 03004 03005 #ifndef Q_WS_WIN 03006 // on win32, for invoking browser we're using win32 API 03007 // see kapplication_win.cpp 03008 void TDEApplication::invokeBrowser( const TQString &url, const TQCString& startup_id ) 03009 { 03010 TQString error; 03011 03012 if (startServiceByDesktopName("kfmclient", url, &error, 0, 0, startup_id, false)) 03013 { 03014 if (Tty != kapp->type()) 03015 TQMessageBox::critical(kapp->mainWidget(), i18n("Could not Launch Browser"), 03016 i18n("Could not launch the browser:\n\n%1").arg(error), i18n("&OK")); 03017 else 03018 kdWarning() << "Could not launch browser:\n" << error << endl; 03019 return; 03020 } 03021 } 03022 #endif 03023 03024 void TDEApplication::cut() 03025 { 03026 invokeEditSlot( TQT_SLOT( cut() ) ); 03027 } 03028 03029 void TDEApplication::copy() 03030 { 03031 invokeEditSlot( TQT_SLOT( copy() ) ); 03032 } 03033 03034 void TDEApplication::paste() 03035 { 03036 invokeEditSlot( TQT_SLOT( paste() ) ); 03037 } 03038 03039 void TDEApplication::clear() 03040 { 03041 invokeEditSlot( TQT_SLOT( clear() ) ); 03042 } 03043 03044 void TDEApplication::selectAll() 03045 { 03046 invokeEditSlot( TQT_SLOT( selectAll() ) ); 03047 } 03048 03049 void TDEApplication::broadcastKeyCode(unsigned int keyCode) 03050 { 03051 emit coreFakeKeyPress(keyCode); 03052 } 03053 03054 TQCString 03055 TDEApplication::launcher() 03056 { 03057 return "tdelauncher"; 03058 } 03059 03060 static int 03061 startServiceInternal( const TQCString &function, 03062 const TQString& _name, const TQStringList &URLs, 03063 TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait ) 03064 { 03065 struct serviceResult 03066 { 03067 int result; 03068 TQCString dcopName; 03069 TQString error; 03070 pid_t pid; 03071 }; 03072 03073 // Register app as able to send DCOP messages 03074 DCOPClient *dcopClient; 03075 if (kapp) 03076 dcopClient = kapp->dcopClient(); 03077 else 03078 dcopClient = new DCOPClient; 03079 03080 if (!dcopClient->isAttached()) 03081 { 03082 if (!dcopClient->attach()) 03083 { 03084 if (error) 03085 *error = i18n("Could not register with DCOP.\n"); 03086 if (!kapp) 03087 delete dcopClient; 03088 03089 return -1; 03090 } 03091 } 03092 TQByteArray params; 03093 TQDataStream stream(params, IO_WriteOnly); 03094 stream << _name << URLs; 03095 TQCString replyType; 03096 TQByteArray replyData; 03097 TQCString _launcher = TDEApplication::launcher(); 03098 TQValueList<TQCString> envs; 03099 #ifdef Q_WS_X11 03100 if (tqt_xdisplay()) { 03101 TQCString dpystring(XDisplayString(tqt_xdisplay())); 03102 envs.append( TQCString("DISPLAY=") + dpystring ); 03103 } else if( getenv( "DISPLAY" )) { 03104 TQCString dpystring( getenv( "DISPLAY" )); 03105 envs.append( TQCString("DISPLAY=") + dpystring ); 03106 } 03107 #endif 03108 stream << envs; 03109 #if defined Q_WS_X11 03110 // make sure there is id, so that user timestamp exists 03111 stream << ( startup_id.isEmpty() ? TDEStartupInfo::createNewStartupId() : startup_id ); 03112 #endif 03113 if( function.left( 12 ) != "tdeinit_exec" ) 03114 stream << noWait; 03115 03116 if (!dcopClient->call(_launcher, _launcher, 03117 function, params, replyType, replyData)) 03118 { 03119 if (error) 03120 *error = i18n("TDELauncher could not be reached via DCOP.\n"); 03121 if (!kapp) 03122 delete dcopClient; 03123 return -1; 03124 } 03125 if (!kapp) 03126 delete dcopClient; 03127 03128 if (noWait) 03129 return 0; 03130 03131 TQDataStream stream2(replyData, IO_ReadOnly); 03132 serviceResult result; 03133 stream2 >> result.result >> result.dcopName >> result.error >> result.pid; 03134 if (dcopService) 03135 *dcopService = result.dcopName; 03136 if (error) 03137 *error = result.error; 03138 if (pid) 03139 *pid = result.pid; 03140 return result.result; 03141 } 03142 03143 int 03144 TDEApplication::startServiceByName( const TQString& _name, const TQString &URL, 03145 TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait ) 03146 { 03147 TQStringList URLs; 03148 if (!URL.isEmpty()) 03149 URLs.append(URL); 03150 return startServiceInternal( 03151 "start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)", 03152 _name, URLs, error, dcopService, pid, startup_id, noWait); 03153 } 03154 03155 int 03156 TDEApplication::startServiceByName( const TQString& _name, const TQStringList &URLs, 03157 TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait ) 03158 { 03159 return startServiceInternal( 03160 "start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)", 03161 _name, URLs, error, dcopService, pid, startup_id, noWait); 03162 } 03163 03164 int 03165 TDEApplication::startServiceByDesktopPath( const TQString& _name, const TQString &URL, 03166 TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait ) 03167 { 03168 TQStringList URLs; 03169 if (!URL.isEmpty()) 03170 URLs.append(URL); 03171 return startServiceInternal( 03172 "start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)", 03173 _name, URLs, error, dcopService, pid, startup_id, noWait); 03174 } 03175 03176 int 03177 TDEApplication::startServiceByDesktopPath( const TQString& _name, const TQStringList &URLs, 03178 TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait ) 03179 { 03180 return startServiceInternal( 03181 "start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)", 03182 _name, URLs, error, dcopService, pid, startup_id, noWait); 03183 } 03184 03185 int 03186 TDEApplication::startServiceByDesktopName( const TQString& _name, const TQString &URL, 03187 TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait ) 03188 { 03189 TQStringList URLs; 03190 if (!URL.isEmpty()) 03191 URLs.append(URL); 03192 return startServiceInternal( 03193 "start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)", 03194 _name, URLs, error, dcopService, pid, startup_id, noWait); 03195 } 03196 03197 int 03198 TDEApplication::startServiceByDesktopName( const TQString& _name, const TQStringList &URLs, 03199 TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait ) 03200 { 03201 return startServiceInternal( 03202 "start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)", 03203 _name, URLs, error, dcopService, pid, startup_id, noWait); 03204 } 03205 03206 int 03207 TDEApplication::tdeinitExec( const TQString& name, const TQStringList &args, 03208 TQString *error, int *pid ) 03209 { 03210 return tdeinitExec( name, args, error, pid, "" ); 03211 } 03212 03213 int 03214 TDEApplication::tdeinitExec( const TQString& name, const TQStringList &args, 03215 TQString *error, int *pid, const TQCString& startup_id ) 03216 { 03217 return startServiceInternal("tdeinit_exec(TQString,TQStringList,TQValueList<TQCString>,TQCString)", 03218 name, args, error, 0, pid, startup_id, false); 03219 } 03220 03221 int 03222 TDEApplication::tdeinitExecWait( const TQString& name, const TQStringList &args, 03223 TQString *error, int *pid ) 03224 { 03225 return tdeinitExecWait( name, args, error, pid, "" ); 03226 } 03227 03228 int 03229 TDEApplication::tdeinitExecWait( const TQString& name, const TQStringList &args, 03230 TQString *error, int *pid, const TQCString& startup_id ) 03231 { 03232 return startServiceInternal("tdeinit_exec_wait(TQString,TQStringList,TQValueList<TQCString>,TQCString)", 03233 name, args, error, 0, pid, startup_id, false); 03234 } 03235 03236 TQString TDEApplication::tempSaveName( const TQString& pFilename ) const 03237 { 03238 TQString aFilename; 03239 03240 if( TQDir::isRelativePath(pFilename) ) 03241 { 03242 kdWarning(101) << "Relative filename passed to TDEApplication::tempSaveName" << endl; 03243 aFilename = TQFileInfo( TQDir( "." ), pFilename ).absFilePath(); 03244 } 03245 else 03246 aFilename = pFilename; 03247 03248 TQDir aAutosaveDir( TQDir::homeDirPath() + "/autosave/" ); 03249 if( !aAutosaveDir.exists() ) 03250 { 03251 if( !aAutosaveDir.mkdir( aAutosaveDir.absPath() ) ) 03252 { 03253 // Last chance: use temp dir 03254 aAutosaveDir.setPath( TDEGlobal::dirs()->saveLocation("tmp") ); 03255 } 03256 } 03257 03258 aFilename.replace( "/", "\\!" ).prepend( "#" ).append( "#" ).prepend( "/" ).prepend( aAutosaveDir.absPath() ); 03259 03260 return aFilename; 03261 } 03262 03263 03264 TQString TDEApplication::checkRecoverFile( const TQString& pFilename, 03265 bool& bRecover ) const 03266 { 03267 TQString aFilename; 03268 03269 if( TQDir::isRelativePath(pFilename) ) 03270 { 03271 kdWarning(101) << "Relative filename passed to TDEApplication::tempSaveName" << endl; 03272 aFilename = TQFileInfo( TQDir( "." ), pFilename ).absFilePath(); 03273 } 03274 else 03275 aFilename = pFilename; 03276 03277 TQDir aAutosaveDir( TQDir::homeDirPath() + "/autosave/" ); 03278 if( !aAutosaveDir.exists() ) 03279 { 03280 if( !aAutosaveDir.mkdir( aAutosaveDir.absPath() ) ) 03281 { 03282 // Last chance: use temp dir 03283 aAutosaveDir.setPath( TDEGlobal::dirs()->saveLocation("tmp") ); 03284 } 03285 } 03286 03287 aFilename.replace( "/", "\\!" ).prepend( "#" ).append( "#" ).prepend( "/" ).prepend( aAutosaveDir.absPath() ); 03288 03289 if( TQFile( aFilename ).exists() ) 03290 { 03291 bRecover = true; 03292 return aFilename; 03293 } 03294 else 03295 { 03296 bRecover = false; 03297 return pFilename; 03298 } 03299 } 03300 03301 03302 bool checkAccess(const TQString& pathname, int mode) 03303 { 03304 int accessOK = access( TQFile::encodeName(pathname), mode ); 03305 if ( accessOK == 0 ) 03306 return true; // OK, I can really access the file 03307 03308 // else 03309 // if we want to write the file would be created. Check, if the 03310 // user may write to the directory to create the file. 03311 if ( (mode & W_OK) == 0 ) 03312 return false; // Check for write access is not part of mode => bail out 03313 03314 03315 if (!access( TQFile::encodeName(pathname), F_OK)) // if it already exists 03316 return false; 03317 03318 //strip the filename (everything until '/' from the end 03319 TQString dirName(pathname); 03320 int pos = dirName.findRev('/'); 03321 if ( pos == -1 ) 03322 return false; // No path in argument. This is evil, we won't allow this 03323 else if ( pos == 0 ) // don't turn e.g. /root into an empty string 03324 pos = 1; 03325 03326 dirName.truncate(pos); // strip everything starting from the last '/' 03327 03328 accessOK = access( TQFile::encodeName(dirName), W_OK ); 03329 // -?- Can I write to the accessed diretory 03330 if ( accessOK == 0 ) 03331 return true; // Yes 03332 else 03333 return false; // No 03334 } 03335 03336 void TDEApplication::setTopWidget( TQWidget *topWidget ) 03337 { 03338 if( !topWidget ) 03339 return; 03340 03341 // set the specified caption 03342 if ( !topWidget->inherits("TDEMainWindow") ) { // TDEMainWindow does this already for us 03343 topWidget->setCaption( caption() ); 03344 } 03345 03346 // set the specified icons 03347 topWidget->setIcon( icon() ); //standard X11 03348 #if defined Q_WS_X11 03349 //#ifdef Q_WS_X11 // FIXME(E): Implement for Qt/Embedded 03350 KWin::setIcons(topWidget->winId(), icon(), miniIcon() ); // NET_WM hints for KWin 03351 03352 // set the app startup notification window property 03353 TDEStartupInfo::setWindowStartupId( topWidget->winId(), startupId()); 03354 #endif 03355 } 03356 03357 TQCString TDEApplication::startupId() const 03358 { 03359 return d->startup_id; 03360 } 03361 03362 void TDEApplication::setStartupId( const TQCString& startup_id ) 03363 { 03364 if( startup_id == d->startup_id ) 03365 return; 03366 #if defined Q_WS_X11 03367 TDEStartupInfo::handleAutoAppStartedSending(); // finish old startup notification if needed 03368 #endif 03369 if( startup_id.isEmpty()) 03370 d->startup_id = "0"; 03371 else 03372 { 03373 d->startup_id = startup_id; 03374 #if defined Q_WS_X11 03375 TDEStartupInfoId id; 03376 id.initId( startup_id ); 03377 long timestamp = id.timestamp(); 03378 if( timestamp != 0 ) 03379 updateUserTimestamp( timestamp ); 03380 #endif 03381 } 03382 } 03383 03384 // read the startup notification env variable, save it and unset it in order 03385 // not to propagate it to processes started from this app 03386 void TDEApplication::read_app_startup_id() 03387 { 03388 #if defined Q_WS_X11 03389 TDEStartupInfoId id = TDEStartupInfo::currentStartupIdEnv(); 03390 TDEStartupInfo::resetStartupEnv(); 03391 d->startup_id = id.id(); 03392 #endif 03393 } 03394 03395 int TDEApplication::random() 03396 { 03397 static bool init = false; 03398 if (!init) 03399 { 03400 unsigned int seed; 03401 init = true; 03402 int fd = open("/dev/urandom", O_RDONLY); 03403 if (fd < 0 || ::read(fd, &seed, sizeof(seed)) != sizeof(seed)) 03404 { 03405 // No /dev/urandom... try something else. 03406 srand(getpid()); 03407 seed = rand()+time(0); 03408 } 03409 if (fd >= 0) close(fd); 03410 srand(seed); 03411 } 03412 return rand(); 03413 } 03414 03415 TQString TDEApplication::randomString(int length) 03416 { 03417 if (length <=0 ) return TQString::null; 03418 03419 TQString str; str.setLength( length ); 03420 int i = 0; 03421 while (length--) 03422 { 03423 int r=random() % 62; 03424 r+=48; 03425 if (r>57) r+=7; 03426 if (r>90) r+=6; 03427 str[i++] = char(r); 03428 // so what if I work backwards? 03429 } 03430 return str; 03431 } 03432 03433 bool TDEApplication::authorize(const TQString &genericAction) 03434 { 03435 if (!d->actionRestrictions) 03436 return true; 03437 03438 TDEConfig *config = TDEGlobal::config(); 03439 TDEConfigGroupSaver saver( config, "KDE Action Restrictions" ); 03440 return config->readBoolEntry(genericAction, true); 03441 } 03442 03443 bool TDEApplication::authorizeTDEAction(const char *action) 03444 { 03445 if (!d->actionRestrictions || !action) 03446 return true; 03447 03448 static const TQString &action_prefix = TDEGlobal::staticQString( "action/" ); 03449 03450 return authorize(action_prefix + action); 03451 } 03452 03453 bool TDEApplication::authorizeControlModule(const TQString &menuId) 03454 { 03455 if (menuId.isEmpty() || kde_kiosk_exception) 03456 return true; 03457 TDEConfig *config = TDEGlobal::config(); 03458 TDEConfigGroupSaver saver( config, "TDE Control Module Restrictions" ); 03459 return config->readBoolEntry(menuId, true); 03460 } 03461 03462 TQStringList TDEApplication::authorizeControlModules(const TQStringList &menuIds) 03463 { 03464 TDEConfig *config = TDEGlobal::config(); 03465 TDEConfigGroupSaver saver( config, "TDE Control Module Restrictions" ); 03466 TQStringList result; 03467 for(TQStringList::ConstIterator it = menuIds.begin(); 03468 it != menuIds.end(); ++it) 03469 { 03470 if (config->readBoolEntry(*it, true)) 03471 result.append(*it); 03472 } 03473 return result; 03474 } 03475 03476 void TDEApplication::initUrlActionRestrictions() 03477 { 03478 d->urlActionRestrictions.setAutoDelete(true); 03479 d->urlActionRestrictions.clear(); 03480 d->urlActionRestrictions.append( new TDEApplicationPrivate::URLActionRule 03481 ("open", TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, true)); 03482 d->urlActionRestrictions.append( new TDEApplicationPrivate::URLActionRule 03483 ("list", TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, true)); 03484 // TEST: 03485 // d->urlActionRestrictions.append( new TDEApplicationPrivate::URLActionRule 03486 // ("list", TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, false)); 03487 // d->urlActionRestrictions.append( new TDEApplicationPrivate::URLActionRule 03488 // ("list", TQString::null, TQString::null, TQString::null, "file", TQString::null, TQDir::homeDirPath(), true)); 03489 d->urlActionRestrictions.append( new TDEApplicationPrivate::URLActionRule 03490 ("link", TQString::null, TQString::null, TQString::null, ":internet", TQString::null, TQString::null, true)); 03491 d->urlActionRestrictions.append( new TDEApplicationPrivate::URLActionRule 03492 ("redirect", TQString::null, TQString::null, TQString::null, ":internet", TQString::null, TQString::null, true)); 03493 03494 // We allow redirections to file: but not from internet protocols, redirecting to file: 03495 // is very popular among io-slaves and we don't want to break them 03496 d->urlActionRestrictions.append( new TDEApplicationPrivate::URLActionRule 03497 ("redirect", TQString::null, TQString::null, TQString::null, "file", TQString::null, TQString::null, true)); 03498 d->urlActionRestrictions.append( new TDEApplicationPrivate::URLActionRule 03499 ("redirect", ":internet", TQString::null, TQString::null, "file", TQString::null, TQString::null, false)); 03500 03501 // local protocols may redirect everywhere 03502 d->urlActionRestrictions.append( new TDEApplicationPrivate::URLActionRule 03503 ("redirect", ":local", TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, true)); 03504 03505 // Anyone may redirect to about: 03506 d->urlActionRestrictions.append( new TDEApplicationPrivate::URLActionRule 03507 ("redirect", TQString::null, TQString::null, TQString::null, "about", TQString::null, TQString::null, true)); 03508 03509 // Anyone may redirect to itself, cq. within it's own group 03510 d->urlActionRestrictions.append( new TDEApplicationPrivate::URLActionRule 03511 ("redirect", TQString::null, TQString::null, TQString::null, "=", TQString::null, TQString::null, true)); 03512 03513 TDEConfig *config = TDEGlobal::config(); 03514 TDEConfigGroupSaver saver( config, "KDE URL Restrictions" ); 03515 int count = config->readNumEntry("rule_count"); 03516 TQString keyFormat = TQString("rule_%1"); 03517 for(int i = 1; i <= count; i++) 03518 { 03519 TQString key = keyFormat.arg(i); 03520 TQStringList rule = config->readListEntry(key); 03521 if (rule.count() != 8) 03522 continue; 03523 TQString action = rule[0]; 03524 TQString refProt = rule[1]; 03525 TQString refHost = rule[2]; 03526 TQString refPath = rule[3]; 03527 TQString urlProt = rule[4]; 03528 TQString urlHost = rule[5]; 03529 TQString urlPath = rule[6]; 03530 TQString strEnabled = rule[7].lower(); 03531 03532 bool bEnabled = (strEnabled == "true"); 03533 03534 if (refPath.startsWith("$HOME")) 03535 refPath.replace(0, 5, TQDir::homeDirPath()); 03536 else if (refPath.startsWith("~")) 03537 refPath.replace(0, 1, TQDir::homeDirPath()); 03538 if (urlPath.startsWith("$HOME")) 03539 urlPath.replace(0, 5, TQDir::homeDirPath()); 03540 else if (urlPath.startsWith("~")) 03541 urlPath.replace(0, 1, TQDir::homeDirPath()); 03542 03543 if (refPath.startsWith("$TMP")) 03544 refPath.replace(0, 4, TDEGlobal::dirs()->saveLocation("tmp")); 03545 if (urlPath.startsWith("$TMP")) 03546 urlPath.replace(0, 4, TDEGlobal::dirs()->saveLocation("tmp")); 03547 03548 d->urlActionRestrictions.append(new TDEApplicationPrivate::URLActionRule 03549 ( action, refProt, refHost, refPath, urlProt, urlHost, urlPath, bEnabled)); 03550 } 03551 } 03552 03553 void TDEApplication::allowURLAction(const TQString &action, const KURL &_baseURL, const KURL &_destURL) 03554 { 03555 if (authorizeURLAction(action, _baseURL, _destURL)) 03556 return; 03557 03558 d->urlActionRestrictions.append(new TDEApplicationPrivate::URLActionRule 03559 ( action, _baseURL.protocol(), _baseURL.host(), _baseURL.path(-1), 03560 _destURL.protocol(), _destURL.host(), _destURL.path(-1), true)); 03561 } 03562 03563 bool TDEApplication::authorizeURLAction(const TQString &action, const KURL &_baseURL, const KURL &_destURL) 03564 { 03565 if (_destURL.isEmpty()) 03566 return true; 03567 03568 bool result = false; 03569 if (d->urlActionRestrictions.isEmpty()) 03570 initUrlActionRestrictions(); 03571 03572 KURL baseURL(_baseURL); 03573 baseURL.setPath(TQDir::cleanDirPath(baseURL.path())); 03574 TQString baseClass = KProtocolInfo::protocolClass(baseURL.protocol()); 03575 KURL destURL(_destURL); 03576 destURL.setPath(TQDir::cleanDirPath(destURL.path())); 03577 TQString destClass = KProtocolInfo::protocolClass(destURL.protocol()); 03578 03579 for(TDEApplicationPrivate::URLActionRule *rule = d->urlActionRestrictions.first(); 03580 rule; rule = d->urlActionRestrictions.next()) 03581 { 03582 if ((result != rule->permission) && // No need to check if it doesn't make a difference 03583 (action == rule->action) && 03584 rule->baseMatch(baseURL, baseClass) && 03585 rule->destMatch(destURL, destClass, baseURL, baseClass)) 03586 { 03587 result = rule->permission; 03588 } 03589 } 03590 return result; 03591 } 03592 03593 03594 uint TDEApplication::keyboardModifiers() 03595 { 03596 #ifdef Q_WS_X11 03597 Window root; 03598 Window child; 03599 int root_x, root_y, win_x, win_y; 03600 uint keybstate; 03601 XQueryPointer( tqt_xdisplay(), tqt_xrootwin(), &root, &child, 03602 &root_x, &root_y, &win_x, &win_y, &keybstate ); 03603 return keybstate & 0x00ff; 03604 #elif defined W_WS_MACX 03605 return GetCurrentEventKeyModifiers() & 0x00ff; 03606 #else 03607 //TODO for win32 03608 return 0; 03609 #endif 03610 } 03611 03612 uint TDEApplication::mouseState() 03613 { 03614 uint mousestate; 03615 #ifdef Q_WS_X11 03616 Window root; 03617 Window child; 03618 int root_x, root_y, win_x, win_y; 03619 XQueryPointer( tqt_xdisplay(), tqt_xrootwin(), &root, &child, 03620 &root_x, &root_y, &win_x, &win_y, &mousestate ); 03621 #elif defined(Q_WS_WIN) 03622 const bool mousebtn_swapped = GetSystemMetrics(SM_SWAPBUTTON); 03623 if (GetAsyncKeyState(VK_LBUTTON)) 03624 mousestate |= (mousebtn_swapped ? Button3Mask : Button1Mask); 03625 if (GetAsyncKeyState(VK_MBUTTON)) 03626 mousestate |= Button2Mask; 03627 if (GetAsyncKeyState(VK_RBUTTON)) 03628 mousestate |= (mousebtn_swapped ? Button1Mask : Button3Mask); 03629 #elif defined(Q_WS_MACX) 03630 mousestate = GetCurrentEventButtonState(); 03631 #else 03632 //TODO: other platforms 03633 #endif 03634 return mousestate & 0xff00; 03635 } 03636 03637 TQ_ButtonState TDEApplication::keyboardMouseState() 03638 { 03639 int ret = 0; 03640 #ifdef Q_WS_X11 03641 Window root; 03642 Window child; 03643 int root_x, root_y, win_x, win_y; 03644 uint state; 03645 XQueryPointer( tqt_xdisplay(), tqt_xrootwin(), &root, &child, 03646 &root_x, &root_y, &win_x, &win_y, &state ); 03647 // transform the same way like Qt's qt_x11_translateButtonState() 03648 if( state & Button1Mask ) 03649 ret |= TQ_LeftButton; 03650 if( state & Button2Mask ) 03651 ret |= TQ_MidButton; 03652 if( state & Button3Mask ) 03653 ret |= TQ_RightButton; 03654 if( state & ShiftMask ) 03655 ret |= TQ_ShiftButton; 03656 if( state & ControlMask ) 03657 ret |= TQ_ControlButton; 03658 if( state & KKeyNative::modX( KKey::ALT )) 03659 ret |= TQ_AltButton; 03660 if( state & KKeyNative::modX( KKey::WIN )) 03661 ret |= TQ_MetaButton; 03662 #elif defined(Q_WS_WIN) 03663 const bool mousebtn_swapped = GetSystemMetrics(SM_SWAPBUTTON); 03664 if (GetAsyncKeyState(VK_LBUTTON)) 03665 ret |= (mousebtn_swapped ? RightButton : LeftButton); 03666 if (GetAsyncKeyState(VK_MBUTTON)) 03667 ret |= TQ_MidButton; 03668 if (GetAsyncKeyState(VK_RBUTTON)) 03669 ret |= (mousebtn_swapped ? TQ_LeftButton : TQ_RightButton); 03670 if (GetAsyncKeyState(VK_SHIFT)) 03671 ret |= TQ_ShiftButton; 03672 if (GetAsyncKeyState(VK_CONTROL)) 03673 ret |= TQ_ControlButton; 03674 if (GetAsyncKeyState(VK_MENU)) 03675 ret |= TQ_AltButton; 03676 if (GetAsyncKeyState(VK_LWIN) || GetAsyncKeyState(VK_RWIN)) 03677 ret |= TQ_MetaButton; 03678 #else 03679 //TODO: other platforms 03680 #endif 03681 return static_cast< ButtonState >( ret ); 03682 } 03683 03684 #if defined Q_WS_X11 03685 int TDEApplication::currentX11VT() 03686 { 03687 return get_x_vtnum(TQPaintDevice::x11AppDisplay()); 03688 } 03689 #else // Q_WS_X11 03690 int TDEApplication::currentX11VT() 03691 { 03692 return -1; 03693 } 03694 #endif // Q_WS_X11 03695 03696 void TDEApplication::installSigpipeHandler() 03697 { 03698 #ifdef Q_OS_UNIX 03699 struct sigaction act; 03700 act.sa_handler = SIG_IGN; 03701 sigemptyset( &act.sa_mask ); 03702 act.sa_flags = 0; 03703 sigaction( SIGPIPE, &act, 0 ); 03704 #endif 03705 } 03706 03707 void TDEApplication::sigpipeHandler(int) 03708 { 03709 int saved_errno = errno; 03710 // Using kdDebug from a signal handler is not a good idea. 03711 #ifndef NDEBUG 03712 char msg[1000]; 03713 sprintf(msg, "*** SIGPIPE *** (ignored, pid = %ld)\n", (long) getpid()); 03714 if (write(2, msg, strlen(msg)) < 0) { 03715 // ERROR 03716 } 03717 #endif 03718 03719 // Do nothing. 03720 errno = saved_errno; 03721 } 03722 03723 bool TDEApplication::guiEnabled() 03724 { 03725 return kapp && kapp->d->guiEnabled; 03726 } 03727 03728 void TDEApplication::virtual_hook( int id, void* data ) 03729 { TDEInstance::virtual_hook( id, data ); } 03730 03731 void KSessionManaged::virtual_hook( int, void* ) 03732 { /*BASE::virtual_hook( id, data );*/ } 03733 03734 #include "tdeapplication.moc"