TDE core libraries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3600 lines
109KB

  1. /* This file is part of the KDE libraries
  2. Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
  3. Copyright (C) 1998, 1999, 2000 KDE Team
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public License
  13. along with this library; see the file COPYING.LIB. If not, write to
  14. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  15. Boston, MA 02110-1301, USA.
  16. */
  17. #include "config.h"
  18. #ifdef HAVE_XCOMPOSITE
  19. #define COMPOSITE
  20. #endif
  21. // #ifdef QTRANSLATOR_H
  22. // #error qtranslator.h was already included
  23. // #endif // QTRANSLATOR_H
  24. //
  25. // #ifdef TQTRANSLATOR_H
  26. // #error tqtranslator.h was already included
  27. // #endif // TQTRANSLATOR_H
  28. #undef QT_NO_TRANSLATION
  29. #undef TQT_NO_TRANSLATION
  30. #include <tqtranslator.h>
  31. #include "kapplication.h"
  32. #define QT_NO_TRANSLATION
  33. #define TQT_NO_TRANSLATION
  34. #include <tqdir.h>
  35. #include <tqptrcollection.h>
  36. #include <tqwidgetlist.h>
  37. #include <tqstrlist.h>
  38. #include <tqfile.h>
  39. #include <tqmessagebox.h>
  40. #include <tqtextstream.h>
  41. #include <tqregexp.h>
  42. #include <tqlineedit.h>
  43. #include <tqtextedit.h>
  44. #include <tqsessionmanager.h>
  45. #include <tqptrlist.h>
  46. #include <tqtimer.h>
  47. #include <tqstylesheet.h>
  48. #include <tqpixmapcache.h>
  49. #include <tqtooltip.h>
  50. #include <tqstylefactory.h>
  51. #include <tqmetaobject.h>
  52. #include <tqimage.h>
  53. #ifndef QT_NO_SQL
  54. #include <tqsqlpropertymap.h>
  55. #endif
  56. #include <kglobal.h>
  57. #include <kstandarddirs.h>
  58. #include <kdebug.h>
  59. #include <klocale.h>
  60. #include <kstyle.h>
  61. #include <kiconloader.h>
  62. #include <kclipboard.h>
  63. #include <kconfig.h>
  64. #include <ksimpleconfig.h>
  65. #include <kcmdlineargs.h>
  66. #include <kaboutdata.h>
  67. #include <kglobalsettings.h>
  68. #include <kcrash.h>
  69. #include <kdatastream.h>
  70. #include <klibloader.h>
  71. #include <kmimesourcefactory.h>
  72. #include <kstdaccel.h>
  73. #include <kaccel.h>
  74. #include "kcheckaccelerators.h"
  75. #include <tqptrdict.h>
  76. #include <kmacroexpander.h>
  77. #include <kshell.h>
  78. #include <kprotocolinfo.h>
  79. #include <kkeynative.h>
  80. #include <kmdcodec.h>
  81. #include <kglobalaccel.h>
  82. #if defined Q_WS_X11
  83. #include <kstartupinfo.h>
  84. #endif
  85. #include <dcopclient.h>
  86. #include <dcopref.h>
  87. #include <sys/types.h>
  88. #ifdef HAVE_SYS_STAT_H
  89. #include <sys/stat.h>
  90. #endif
  91. #include <sys/wait.h>
  92. #include <grp.h>
  93. #include <sys/types.h>
  94. #ifndef Q_WS_WIN
  95. #include "kwin.h"
  96. #endif
  97. #include <fcntl.h>
  98. #include <stdlib.h> // getenv(), srand(), rand()
  99. #include <signal.h>
  100. #include <unistd.h>
  101. #include <time.h>
  102. #include <sys/time.h>
  103. #include <errno.h>
  104. #include <string.h>
  105. #include <netdb.h>
  106. #if defined Q_WS_X11
  107. //#ifndef Q_WS_QWS //FIXME(E): NetWM should talk to QWS...
  108. #include <netwm.h>
  109. #endif
  110. #include "kprocctrl.h"
  111. #ifdef HAVE_PATHS_H
  112. #include <paths.h>
  113. #endif
  114. #ifdef Q_WS_X11
  115. #include <X11/Xlib.h>
  116. #ifdef COMPOSITE
  117. #include <X11/extensions/Xrender.h>
  118. #include <X11/extensions/Xcomposite.h>
  119. #include <dlfcn.h>
  120. #endif
  121. #include <X11/Xutil.h>
  122. #include <X11/Xatom.h>
  123. #include <X11/SM/SMlib.h>
  124. #include <fixx11h.h>
  125. #endif
  126. #include <pwd.h>
  127. #ifndef Q_WS_WIN
  128. #include <KDE-ICE/ICElib.h>
  129. #else
  130. typedef void* IceIOErrorHandler;
  131. #include <windows.h>
  132. //KDE4: remove
  133. #define Button1Mask (1<<8)
  134. #define Button2Mask (1<<9)
  135. #define Button3Mask (1<<10)
  136. #endif
  137. #ifdef Q_WS_X11
  138. #define DISPLAY "DISPLAY"
  139. #elif defined(Q_WS_QWS)
  140. #define DISPLAY "QWS_DISPLAY"
  141. #endif
  142. #if defined Q_WS_X11
  143. #include <kipc.h>
  144. #endif
  145. #ifdef Q_WS_MACX
  146. #include <Carbon/Carbon.h>
  147. #include <tqimage.h>
  148. #endif
  149. #include "kappdcopiface.h"
  150. // exported for kdm kfrontend
  151. KDE_EXPORT bool kde_have_kipc = true; // magic hook to disable kipc in kdm
  152. bool kde_kiosk_exception = false; // flag to disable kiosk restrictions
  153. bool kde_kiosk_admin = false;
  154. KApplication* KApplication::KApp = 0L;
  155. bool KApplication::loadedByKdeinit = false;
  156. DCOPClient *KApplication::s_DCOPClient = 0L;
  157. bool KApplication::s_dcopClientNeedsPostInit = false;
  158. #ifdef Q_WS_X11
  159. static Atom atom_DesktopWindow;
  160. static Atom atom_NetSupported;
  161. static Atom kde_xdnd_drop;
  162. #endif
  163. #ifdef Q_WS_X11
  164. static int composite_event, composite_error, composite_opcode;
  165. static bool x11_composite_error_generated;
  166. static int x11_error(Display *dpy, XErrorEvent *ev) {
  167. if (ev->request_code == composite_opcode && ev->minor_code == X_CompositeRedirectSubwindows)
  168. {
  169. x11_composite_error_generated = true;
  170. return 0;
  171. }
  172. }
  173. #endif
  174. // duplicated from patched Qt, so that there won't be unresolved symbols if Qt gets
  175. // replaced by unpatched one
  176. KDECORE_EXPORT bool qt_qclipboard_bailout_hack = false;
  177. template class TQPtrList<KSessionManaged>;
  178. #ifdef Q_WS_X11
  179. extern "C" {
  180. static int kde_xio_errhandler( Display * dpy )
  181. {
  182. return kapp->xioErrhandler( dpy );
  183. }
  184. static int kde_x_errhandler( Display *dpy, XErrorEvent *err )
  185. {
  186. return kapp->xErrhandler( dpy, err );
  187. }
  188. }
  189. extern "C" {
  190. static void kde_ice_ioerrorhandler( IceConn conn )
  191. {
  192. if(kapp)
  193. kapp->iceIOErrorHandler( conn );
  194. // else ignore the error for now
  195. }
  196. }
  197. #endif
  198. #ifdef Q_WS_WIN
  199. void KApplication_init_windows(bool GUIenabled);
  200. class QAssistantClient;
  201. #endif
  202. /*
  203. Private data to make keeping binary compatibility easier
  204. */
  205. class KApplicationPrivate
  206. {
  207. public:
  208. KApplicationPrivate()
  209. : actionRestrictions( false ),
  210. refCount( 1 ),
  211. oldIceIOErrorHandler( 0 ),
  212. checkAccelerators( 0 ),
  213. overrideStyle( TQString::null ),
  214. startup_id( "0" ),
  215. app_started_timer( NULL ),
  216. m_KAppDCOPInterface( 0L ),
  217. session_save( false )
  218. #ifdef Q_WS_X11
  219. ,oldXErrorHandler( NULL )
  220. ,oldXIOErrorHandler( NULL )
  221. #elif defined Q_WS_WIN
  222. ,qassistantclient( 0 )
  223. #endif
  224. {
  225. }
  226. ~KApplicationPrivate()
  227. {
  228. #ifdef Q_WS_WIN
  229. delete qassistantclient;
  230. #endif
  231. }
  232. bool actionRestrictions : 1;
  233. bool guiEnabled : 1;
  234. /**
  235. * This counter indicates when to exit the application.
  236. * It starts at 1, is decremented in KMainWindow when the last window is closed, but
  237. * is incremented by operations that should outlive the last window closed
  238. * (e.g. a file copy for a file manager, or 'compacting folders on exit' for a mail client).
  239. */
  240. int refCount;
  241. IceIOErrorHandler oldIceIOErrorHandler;
  242. KCheckAccelerators* checkAccelerators;
  243. TQString overrideStyle;
  244. TQString geometry_arg;
  245. TQCString startup_id;
  246. TQTimer* app_started_timer;
  247. KAppDCOPInterface *m_KAppDCOPInterface;
  248. bool session_save;
  249. #ifdef Q_WS_X11
  250. int (*oldXErrorHandler)(Display*,XErrorEvent*);
  251. int (*oldXIOErrorHandler)(Display*);
  252. #elif defined Q_WS_WIN
  253. QAssistantClient* qassistantclient;
  254. #endif
  255. class URLActionRule
  256. {
  257. public:
  258. #define checkExactMatch(s, b) \
  259. if (s.isEmpty()) b = true; \
  260. else if (s[s.length()-1] == '!') \
  261. { b = false; s.truncate(s.length()-1); } \
  262. else b = true;
  263. #define checkStartWildCard(s, b) \
  264. if (s.isEmpty()) b = true; \
  265. else if (s[0] == '*') \
  266. { b = true; s = s.mid(1); } \
  267. else b = false;
  268. #define checkEqual(s, b) \
  269. b = (s == "=");
  270. URLActionRule(const TQString &act,
  271. const TQString &bProt, const TQString &bHost, const TQString &bPath,
  272. const TQString &dProt, const TQString &dHost, const TQString &dPath,
  273. bool perm)
  274. : action(act),
  275. baseProt(bProt), baseHost(bHost), basePath(bPath),
  276. destProt(dProt), destHost(dHost), destPath(dPath),
  277. permission(perm)
  278. {
  279. checkExactMatch(baseProt, baseProtWildCard);
  280. checkStartWildCard(baseHost, baseHostWildCard);
  281. checkExactMatch(basePath, basePathWildCard);
  282. checkExactMatch(destProt, destProtWildCard);
  283. checkStartWildCard(destHost, destHostWildCard);
  284. checkExactMatch(destPath, destPathWildCard);
  285. checkEqual(destProt, destProtEqual);
  286. checkEqual(destHost, destHostEqual);
  287. }
  288. bool baseMatch(const KURL &url, const TQString &protClass)
  289. {
  290. if (baseProtWildCard)
  291. {
  292. if ( !baseProt.isEmpty() && !url.protocol().startsWith(baseProt) &&
  293. (protClass.isEmpty() || (protClass != baseProt)) )
  294. return false;
  295. }
  296. else
  297. {
  298. if ( (url.protocol() != baseProt) &&
  299. (protClass.isEmpty() || (protClass != baseProt)) )
  300. return false;
  301. }
  302. if (baseHostWildCard)
  303. {
  304. if (!baseHost.isEmpty() && !url.host().endsWith(baseHost))
  305. return false;
  306. }
  307. else
  308. {
  309. if (url.host() != baseHost)
  310. return false;
  311. }
  312. if (basePathWildCard)
  313. {
  314. if (!basePath.isEmpty() && !url.path().startsWith(basePath))
  315. return false;
  316. }
  317. else
  318. {
  319. if (url.path() != basePath)
  320. return false;
  321. }
  322. return true;
  323. }
  324. bool destMatch(const KURL &url, const TQString &protClass, const KURL &base, const TQString &baseClass)
  325. {
  326. if (destProtEqual)
  327. {
  328. if ( (url.protocol() != base.protocol()) &&
  329. (protClass.isEmpty() || baseClass.isEmpty() || protClass != baseClass) )
  330. return false;
  331. }
  332. else if (destProtWildCard)
  333. {
  334. if ( !destProt.isEmpty() && !url.protocol().startsWith(destProt) &&
  335. (protClass.isEmpty() || (protClass != destProt)) )
  336. return false;
  337. }
  338. else
  339. {
  340. if ( (url.protocol() != destProt) &&
  341. (protClass.isEmpty() || (protClass != destProt)) )
  342. return false;
  343. }
  344. if (destHostWildCard)
  345. {
  346. if (!destHost.isEmpty() && !url.host().endsWith(destHost))
  347. return false;
  348. }
  349. else if (destHostEqual)
  350. {
  351. if (url.host() != base.host())
  352. return false;
  353. }
  354. else
  355. {
  356. if (url.host() != destHost)
  357. return false;
  358. }
  359. if (destPathWildCard)
  360. {
  361. if (!destPath.isEmpty() && !url.path().startsWith(destPath))
  362. return false;
  363. }
  364. else
  365. {
  366. if (url.path() != destPath)
  367. return false;
  368. }
  369. return true;
  370. }
  371. TQString action;
  372. TQString baseProt;
  373. TQString baseHost;
  374. TQString basePath;
  375. TQString destProt;
  376. TQString destHost;
  377. TQString destPath;
  378. bool baseProtWildCard : 1;
  379. bool baseHostWildCard : 1;
  380. bool basePathWildCard : 1;
  381. bool destProtWildCard : 1;
  382. bool destHostWildCard : 1;
  383. bool destPathWildCard : 1;
  384. bool destProtEqual : 1;
  385. bool destHostEqual : 1;
  386. bool permission;
  387. };
  388. TQPtrList<URLActionRule> urlActionRestrictions;
  389. TQString sessionKey;
  390. TQString pSessionConfigFile;
  391. };
  392. static TQPtrList<TQWidget>*x11Filter = 0;
  393. static bool autoDcopRegistration = true;
  394. void KApplication::installX11EventFilter( TQWidget* filter )
  395. {
  396. if ( !filter )
  397. return;
  398. if (!x11Filter)
  399. x11Filter = new TQPtrList<TQWidget>;
  400. connect ( filter, TQT_SIGNAL( destroyed() ), this, TQT_SLOT( x11FilterDestroyed() ) );
  401. x11Filter->append( filter );
  402. }
  403. void KApplication::x11FilterDestroyed()
  404. {
  405. removeX11EventFilter( static_cast< const TQWidget* >( sender()));
  406. }
  407. void KApplication::removeX11EventFilter( const TQWidget* filter )
  408. {
  409. if ( !x11Filter || !filter )
  410. return;
  411. x11Filter->removeRef( filter );
  412. if ( x11Filter->isEmpty() ) {
  413. delete x11Filter;
  414. x11Filter = 0;
  415. }
  416. }
  417. // FIXME: remove this when we've get a better method of
  418. // customizing accelerator handling -- hopefully in Qt.
  419. // For now, this is set whenever an accelerator is overridden
  420. // in KAccelEventHandler so that the AccelOverride isn't sent twice. -- ellis, 19/10/02
  421. extern bool kde_g_bKillAccelOverride;
  422. bool KApplication::notify(TQObject *receiver, TQEvent *event)
  423. {
  424. TQEvent::Type t = event->type();
  425. if (kde_g_bKillAccelOverride)
  426. {
  427. kde_g_bKillAccelOverride = false;
  428. // Indicate that the accelerator has been overridden.
  429. if (t == TQEvent::AccelOverride)
  430. {
  431. TQT_TQKEYEVENT(event)->accept();
  432. return true;
  433. }
  434. else
  435. kdWarning(125) << "kde_g_bKillAccelOverride set, but received an event other than AccelOverride." << endl;
  436. }
  437. if ((t == TQEvent::AccelOverride) || (t == TQEvent::KeyPress))
  438. {
  439. static const KShortcut& _selectAll = KStdAccel::selectAll();
  440. TQLineEdit *edit = ::tqqt_cast<TQLineEdit *>(receiver);
  441. if (edit)
  442. {
  443. // We have a keypress for a lineedit...
  444. TQKeyEvent *kevent = TQT_TQKEYEVENT(event);
  445. KKey key(kevent);
  446. if (_selectAll.contains(key))
  447. {
  448. if (t == TQEvent::KeyPress)
  449. {
  450. edit->selectAll();
  451. return true;
  452. }
  453. else
  454. {
  455. kevent->accept();
  456. }
  457. }
  458. // Ctrl-U deletes from start of line.
  459. if (key == KKey(Qt::CTRL + Qt::Key_U))
  460. {
  461. if (t == TQEvent::KeyPress)
  462. {
  463. if (!edit->isReadOnly())
  464. {
  465. TQString t(edit->text());
  466. t = t.mid(edit->cursorPosition());
  467. edit->validateAndSet(t, 0, 0, 0);
  468. }
  469. return true;
  470. }
  471. else
  472. {
  473. kevent->accept();
  474. }
  475. }
  476. }
  477. TQTextEdit *medit = ::tqqt_cast<TQTextEdit *>(receiver);
  478. if (medit)
  479. {
  480. // We have a keypress for a multilineedit...
  481. TQKeyEvent *kevent = TQT_TQKEYEVENT(event);
  482. if (_selectAll.contains(KKey(kevent)))
  483. {
  484. if (t == TQEvent::KeyPress)
  485. {
  486. medit->selectAll();
  487. return true;
  488. }
  489. else
  490. {
  491. kevent->accept();
  492. }
  493. }
  494. }
  495. }
  496. if( t == TQEvent::Show && receiver->isWidgetType())
  497. {
  498. TQWidget* w = TQT_TQWIDGET( receiver );
  499. #if defined Q_WS_X11
  500. if( w->isTopLevel() && !startupId().isEmpty() && !TQT_TQSHOWEVENT(event)->spontaneous()) // TODO better done using window group leader?
  501. KStartupInfo::setWindowStartupId( w->winId(), startupId());
  502. #endif
  503. if( w->isTopLevel() && !w->testWFlags( WX11BypassWM ) && !w->isPopup() && !event->spontaneous())
  504. {
  505. if( d->app_started_timer == NULL )
  506. {
  507. d->app_started_timer = new TQTimer( this, "app_started_timer" );
  508. connect( d->app_started_timer, TQT_SIGNAL( timeout()), TQT_SLOT( checkAppStartedSlot()));
  509. }
  510. if( !d->app_started_timer->isActive())
  511. d->app_started_timer->start( 0, true );
  512. }
  513. if( w->isTopLevel() && ( w->icon() == NULL || w->icon()->isNull()))
  514. {
  515. // icon() cannot be null pixmap, it'll be the "unknown" icon - so check if there is this application icon
  516. static TQPixmap* ic = NULL;
  517. if( ic == NULL )
  518. ic = new TQPixmap( KGlobal::iconLoader()->loadIcon( iconName(),
  519. KIcon::NoGroup, 0, KIcon::DefaultState, NULL, true ));
  520. if( !ic->isNull())
  521. {
  522. w->setIcon( *ic );
  523. #if defined Q_WS_X11
  524. KWin::setIcons( w->winId(), *ic, miniIcon());
  525. #endif
  526. }
  527. }
  528. }
  529. return TQApplication::notify(receiver, event);
  530. }
  531. void KApplication::checkAppStartedSlot()
  532. {
  533. #if defined Q_WS_X11
  534. KStartupInfo::handleAutoAppStartedSending();
  535. #endif
  536. }
  537. // the help class for session management communication
  538. static TQPtrList<KSessionManaged>* sessionClients()
  539. {
  540. static TQPtrList<KSessionManaged>* session_clients = 0L;
  541. if ( !session_clients )
  542. session_clients = new TQPtrList<KSessionManaged>;
  543. return session_clients;
  544. }
  545. /*
  546. Auxiliary function to calculate a a session config name used for the
  547. instance specific config object.
  548. Syntax: "session/<appname>_<sessionId>"
  549. */
  550. TQString KApplication::sessionConfigName() const
  551. {
  552. TQString sessKey = sessionKey();
  553. if ( sessKey.isEmpty() && !d->sessionKey.isEmpty() )
  554. sessKey = d->sessionKey;
  555. return TQString("session/%1_%2_%3").arg(name()).arg(sessionId()).arg(sessKey);
  556. }
  557. #ifdef Q_WS_X11
  558. static SmcConn mySmcConnection = 0;
  559. static SmcConn tmpSmcConnection = 0;
  560. #else
  561. // FIXME(E): Implement for Qt Embedded
  562. // Possibly "steal" XFree86's libSM?
  563. #endif
  564. static TQTime* smModificationTime = 0;
  565. KApplication::KApplication( int& argc, char** argv, const TQCString& rAppName,
  566. bool allowStyles, bool GUIenabled ) :
  567. TQApplication( argc, argv, GUIenabled ), KInstance(rAppName),
  568. #ifdef Q_WS_X11
  569. display(0L),
  570. argb_visual(false),
  571. #endif
  572. d (new KApplicationPrivate())
  573. {
  574. aIconPixmap.pm.icon = 0L;
  575. aIconPixmap.pm.miniIcon = 0L;
  576. read_app_startup_id();
  577. if (!GUIenabled)
  578. allowStyles = false;
  579. useStyles = allowStyles;
  580. Q_ASSERT (!rAppName.isEmpty());
  581. setName(rAppName);
  582. installSigpipeHandler();
  583. KCmdLineArgs::initIgnore(argc, argv, rAppName.data());
  584. parseCommandLine( );
  585. init(GUIenabled);
  586. d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
  587. }
  588. KApplication::KApplication( bool allowStyles, bool GUIenabled ) :
  589. TQApplication( *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(), TRUE ), // Qt4 requires that there always be a GUI
  590. KInstance( KCmdLineArgs::about),
  591. #ifdef Q_WS_X11
  592. display(0L),
  593. argb_visual(false),
  594. #endif
  595. d (new KApplicationPrivate)
  596. {
  597. aIconPixmap.pm.icon = 0L;
  598. aIconPixmap.pm.miniIcon = 0L;
  599. read_app_startup_id();
  600. if (!GUIenabled)
  601. allowStyles = false;
  602. useStyles = allowStyles;
  603. setName( instanceName() );
  604. installSigpipeHandler();
  605. parseCommandLine( );
  606. init(GUIenabled);
  607. d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
  608. }
  609. #ifdef Q_WS_X11
  610. KApplication::KApplication( Display *dpy, bool allowStyles ) :
  611. TQApplication( dpy, *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(),
  612. getX11RGBAVisual(dpy), getX11RGBAColormap(dpy) ),
  613. KInstance( KCmdLineArgs::about), display(0L), d (new KApplicationPrivate)
  614. {
  615. aIconPixmap.pm.icon = 0L;
  616. aIconPixmap.pm.miniIcon = 0L;
  617. read_app_startup_id();
  618. useStyles = allowStyles;
  619. setName( instanceName() );
  620. installSigpipeHandler();
  621. parseCommandLine( );
  622. init( true );
  623. d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
  624. }
  625. KApplication::KApplication( Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap,
  626. bool allowStyles ) :
  627. TQApplication( dpy, *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(),
  628. visual?visual:getX11RGBAVisual(dpy), colormap?colormap:getX11RGBAColormap(dpy) ),
  629. KInstance( KCmdLineArgs::about), display(0L), d (new KApplicationPrivate)
  630. {
  631. if ((visual) && (colormap))
  632. getX11RGBAInformation(dpy);
  633. aIconPixmap.pm.icon = 0L;
  634. aIconPixmap.pm.miniIcon = 0L;
  635. read_app_startup_id();
  636. useStyles = allowStyles;
  637. setName( instanceName() );
  638. installSigpipeHandler();
  639. parseCommandLine( );
  640. init( true );
  641. d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
  642. }
  643. KApplication::KApplication( Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap,
  644. bool allowStyles, KInstance * _instance ) :
  645. TQApplication( dpy, *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(),
  646. visual?visual:getX11RGBAVisual(dpy), colormap?colormap:getX11RGBAColormap(dpy) ),
  647. KInstance( _instance ), display(0L), d (new KApplicationPrivate)
  648. {
  649. if ((visual) && (colormap))
  650. getX11RGBAInformation(dpy);
  651. aIconPixmap.pm.icon = 0L;
  652. aIconPixmap.pm.miniIcon = 0L;
  653. read_app_startup_id();
  654. useStyles = allowStyles;
  655. setName( instanceName() );
  656. installSigpipeHandler();
  657. parseCommandLine( );
  658. init( true );
  659. d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
  660. }
  661. #endif
  662. KApplication::KApplication( bool allowStyles, bool GUIenabled, KInstance* _instance ) :
  663. TQApplication( *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(),
  664. GUIenabled ),
  665. KInstance( _instance ),
  666. argb_visual(false),
  667. #ifdef Q_WS_X11
  668. display(0L),
  669. #endif
  670. d (new KApplicationPrivate)
  671. {
  672. aIconPixmap.pm.icon = 0L;
  673. aIconPixmap.pm.miniIcon = 0L;
  674. read_app_startup_id();
  675. if (!GUIenabled)
  676. allowStyles = false;
  677. useStyles = allowStyles;
  678. setName( instanceName() );
  679. installSigpipeHandler();
  680. parseCommandLine( );
  681. init(GUIenabled);
  682. d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
  683. }
  684. #ifdef Q_WS_X11
  685. KApplication::KApplication(Display *display, int& argc, char** argv, const TQCString& rAppName,
  686. bool allowStyles, bool GUIenabled ) :
  687. TQApplication( display ), KInstance(rAppName),
  688. display(0L),
  689. argb_visual(false),
  690. d (new KApplicationPrivate())
  691. {
  692. aIconPixmap.pm.icon = 0L;
  693. aIconPixmap.pm.miniIcon = 0L;
  694. read_app_startup_id();
  695. if (!GUIenabled)
  696. allowStyles = false;
  697. useStyles = allowStyles;
  698. Q_ASSERT (!rAppName.isEmpty());
  699. setName(rAppName);
  700. installSigpipeHandler();
  701. KCmdLineArgs::initIgnore(argc, argv, rAppName.data());
  702. parseCommandLine( );
  703. init(GUIenabled);
  704. d->m_KAppDCOPInterface = new KAppDCOPInterface(this);
  705. }
  706. #endif
  707. int KApplication::xioErrhandler( Display* dpy )
  708. {
  709. if(kapp)
  710. {
  711. emit shutDown();
  712. #ifdef Q_WS_X11
  713. d->oldXIOErrorHandler( dpy );
  714. #else
  715. Q_UNUSED(dpy);
  716. #endif
  717. }
  718. exit( 1 );
  719. return 0;
  720. }
  721. int KApplication::xErrhandler( Display* dpy, void* err_ )
  722. { // no idea how to make forward decl. for XErrorEvent
  723. #ifdef Q_WS_X11
  724. XErrorEvent* err = static_cast< XErrorEvent* >( err_ );
  725. if(kapp)
  726. {
  727. // add KDE specific stuff here
  728. d->oldXErrorHandler( dpy, err );
  729. }
  730. #endif
  731. return 0;
  732. }
  733. void KApplication::iceIOErrorHandler( _IceConn *conn )
  734. {
  735. emit shutDown();
  736. #ifdef Q_WS_X11
  737. if ( d->oldIceIOErrorHandler != NULL )
  738. (*d->oldIceIOErrorHandler)( conn );
  739. #endif
  740. exit( 1 );
  741. }
  742. class KDETranslator : public TQTranslator
  743. {
  744. public:
  745. KDETranslator(TQObject *parent) : TQTranslator(parent, "kdetranslator") {}
  746. virtual TQTranslatorMessage findMessage(const char* context,
  747. const char *sourceText,
  748. const char* message) const
  749. {
  750. TQTranslatorMessage res;
  751. res.setTranslation(KGlobal::locale()->translateQt(context, sourceText, message));
  752. return res;
  753. }
  754. };
  755. void KApplication::init(bool GUIenabled)
  756. {
  757. d->guiEnabled = GUIenabled;
  758. if ((getuid() != geteuid()) ||
  759. (getgid() != getegid()) )
  760. {
  761. // man permissions are not exploitable and better than
  762. // world writable directories
  763. struct group *man = getgrnam("man");
  764. if ( !man || man->gr_gid != getegid() ){
  765. fprintf(stderr, "The KDE libraries are not designed to run with suid privileges.\n");
  766. ::exit(127);
  767. }
  768. }
  769. KProcessController::ref();
  770. (void) KClipboardSynchronizer::self();
  771. TQApplication::setDesktopSettingsAware( false );
  772. KApp = this;
  773. #ifdef Q_WS_X11 //FIXME(E)
  774. // create all required atoms in _one_ roundtrip to the X server
  775. if ( GUIenabled ) {
  776. const int max = 20;
  777. Atom* atoms[max];
  778. char* names[max];
  779. Atom atoms_return[max];
  780. int n = 0;
  781. atoms[n] = &kipcCommAtom;
  782. names[n++] = (char *) "KIPC_COMM_ATOM";
  783. atoms[n] = &atom_DesktopWindow;
  784. names[n++] = (char *) "KDE_DESKTOP_WINDOW";
  785. atoms[n] = &atom_NetSupported;
  786. names[n++] = (char *) "_NET_SUPPORTED";
  787. atoms[n] = &kde_xdnd_drop;
  788. names[n++] = (char *) "XdndDrop";
  789. XInternAtoms( qt_xdisplay(), names, n, false, atoms_return );
  790. for (int i = 0; i < n; i++ )
  791. *atoms[i] = atoms_return[i];
  792. }
  793. #endif
  794. dcopAutoRegistration();
  795. dcopClientPostInit();
  796. smw = 0;
  797. // Initial KIPC event mask.
  798. #if defined Q_WS_X11
  799. kipcEventMask = (1 << KIPC::StyleChanged) | (1 << KIPC::PaletteChanged) |
  800. (1 << KIPC::FontChanged) | (1 << KIPC::BackgroundChanged) |
  801. (1 << KIPC::ToolbarStyleChanged) | (1 << KIPC::SettingsChanged) |
  802. (1 << KIPC::ClipboardConfigChanged) | (1 << KIPC::BlockShortcuts);
  803. #endif
  804. // Trigger creation of locale.
  805. (void) KGlobal::locale();
  806. KConfig* config = KGlobal::config();
  807. d->actionRestrictions = config->hasGroup("KDE Action Restrictions" ) && !kde_kiosk_exception;
  808. // For brain-dead configurations where the user's local config file is not writable.
  809. // * We use kdialog to warn the user, so we better not generate warnings from
  810. // kdialog itself.
  811. // * Don't warn if we run with a read-only $HOME
  812. TQCString readOnly = getenv("KDE_HOME_READONLY");
  813. if (readOnly.isEmpty() && (tqstrcmp(name(), "kdialog") != 0))
  814. {
  815. KConfigGroupSaver saver(config, "KDE Action Restrictions");
  816. if (config->readBoolEntry("warn_unwritable_config",true))
  817. config->checkConfigFilesWritable(true);
  818. }
  819. if (GUIenabled)
  820. {
  821. #ifdef Q_WS_X11
  822. // this is important since we fork() to launch the help (Matthias)
  823. fcntl(ConnectionNumber(qt_xdisplay()), F_SETFD, FD_CLOEXEC);
  824. // set up the fancy (=robust and error ignoring ) KDE xio error handlers (Matthias)
  825. d->oldXErrorHandler = XSetErrorHandler( kde_x_errhandler );
  826. d->oldXIOErrorHandler = XSetIOErrorHandler( kde_xio_errhandler );
  827. #endif
  828. connect( this, TQT_SIGNAL( aboutToQuit() ), this, TQT_SIGNAL( shutDown() ) );
  829. #ifdef Q_WS_X11 //FIXME(E)
  830. display = desktop()->x11Display();
  831. #endif
  832. {
  833. TQStringList plugins = KGlobal::dirs()->resourceDirs( "qtplugins" );
  834. TQStringList::Iterator it = plugins.begin();
  835. while (it != plugins.end()) {
  836. addLibraryPath( *it );
  837. ++it;
  838. }
  839. }
  840. kdisplaySetStyle();
  841. kdisplaySetFont();
  842. // kdisplaySetPalette(); done by kdisplaySetStyle
  843. propagateSettings(SETTINGS_QT);
  844. // Set default mime-source factory
  845. // XXX: This is a hack. Make our factory the default factory, but add the
  846. // previous default factory to the list of factories. Why? When the default
  847. // factory can't resolve something, it iterates in the list of factories.
  848. // But it TQWhatsThis only uses the default factory. So if there was already
  849. // a default factory (which happens when using an image library using uic),
  850. // we prefer KDE's factory and so we put that old default factory in the
  851. // list and use KDE as the default. This may speed up things as well.
  852. TQMimeSourceFactory* oldDefaultFactory = TQMimeSourceFactory::takeDefaultFactory();
  853. TQMimeSourceFactory::setDefaultFactory( mimeSourceFactory() );
  854. if ( oldDefaultFactory ) {
  855. TQMimeSourceFactory::addFactory( oldDefaultFactory );
  856. }
  857. d->checkAccelerators = new KCheckAccelerators( TQT_TQOBJECT(this) );
  858. }
  859. #ifdef Q_WS_MACX
  860. if (GUIenabled) {
  861. TQPixmap pixmap = KGlobal::iconLoader()->loadIcon( KCmdLineArgs::appName(),
  862. KIcon::NoGroup, KIcon::SizeLarge, KIcon::DefaultState, 0L, false );
  863. if (!pixmap.isNull()) {
  864. TQImage i = pixmap.convertToImage().convertDepth(32).smoothScale(40, 40);
  865. for(int y = 0; y < i.height(); y++) {
  866. uchar *l = i.scanLine(y);
  867. for(int x = 0; x < i.width(); x+=4)
  868. *(l+x) = 255;
  869. }
  870. CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
  871. CGDataProviderRef dp = CGDataProviderCreateWithData(NULL,
  872. i.bits(), i.numBytes(), NULL);
  873. CGImageRef ir = CGImageCreate(i.width(), i.height(), 8, 32, i.bytesPerLine(),
  874. cs, kCGImageAlphaNoneSkipFirst, dp,
  875. 0, 0, kCGRenderingIntentDefault);
  876. //cleanup
  877. SetApplicationDockTileImage(ir);
  878. CGImageRelease(ir);
  879. CGColorSpaceRelease(cs);
  880. CGDataProviderRelease(dp);
  881. }
  882. }
  883. #endif
  884. // save and restore the RTL setting, as installTranslator calls qt_detectRTLLanguage,
  885. // which makes it impossible to use the -reverse cmdline switch with KDE apps
  886. bool rtl = reverseLayout();
  887. installTranslator(new KDETranslator(TQT_TQOBJECT(this)));
  888. setReverseLayout( rtl );
  889. if (i18n( "_: Dear Translator! Translate this string to the string 'LTR' in "
  890. "left-to-right languages (as english) or to 'RTL' in right-to-left "
  891. "languages (such as Hebrew and Arabic) to get proper widget layout." ) == "RTL")
  892. setReverseLayout( !rtl );
  893. // install appdata resource type
  894. KGlobal::dirs()->addResourceType("appdata", KStandardDirs::kde_default("data")
  895. + TQString::tqfromLatin1(name()) + '/');
  896. pSessionConfig = 0L;
  897. bSessionManagement = true;
  898. #ifdef Q_WS_X11
  899. // register a communication window for desktop changes (Matthias)
  900. if (GUIenabled && kde_have_kipc )
  901. {
  902. smw = new TQWidget(0,0);
  903. long data = 1;
  904. XChangeProperty(qt_xdisplay(), smw->winId(),
  905. atom_DesktopWindow, atom_DesktopWindow,
  906. 32, PropModeReplace, (unsigned char *)&data, 1);
  907. }
  908. d->oldIceIOErrorHandler = IceSetIOErrorHandler( kde_ice_ioerrorhandler );
  909. #elif defined(Q_WS_WIN)
  910. KApplication_init_windows(GUIenabled);
  911. #else
  912. // FIXME(E): Implement for Qt Embedded
  913. #endif
  914. }
  915. static int my_system (const char *command) {
  916. int pid, status;
  917. pid = fork();
  918. if (pid == -1)
  919. return -1;
  920. if (pid == 0) {
  921. const char* shell = "/bin/sh";
  922. execl(shell, shell, "-c", command, (void *)0);
  923. ::_exit(127);
  924. }
  925. do {
  926. if (waitpid(pid, &status, 0) == -1) {
  927. if (errno != EINTR)
  928. return -1;
  929. } else
  930. return status;
  931. } while(1);
  932. }
  933. DCOPClient *KApplication::dcopClient()
  934. {
  935. if (s_DCOPClient)
  936. return s_DCOPClient;
  937. s_DCOPClient = new DCOPClient();
  938. KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
  939. if (args && args->isSet("dcopserver"))
  940. {
  941. s_DCOPClient->setServerAddress( args->getOption("dcopserver"));
  942. }
  943. if( kapp ) {
  944. connect(s_DCOPClient, TQT_SIGNAL(attachFailed(const TQString &)),
  945. kapp, TQT_SLOT(dcopFailure(const TQString &)));
  946. connect(s_DCOPClient, TQT_SIGNAL(blockUserInput(bool) ),
  947. kapp, TQT_SLOT(dcopBlockUserInput(bool)) );
  948. }
  949. else
  950. s_dcopClientNeedsPostInit = true;
  951. DCOPClient::setMainClient( s_DCOPClient );
  952. return s_DCOPClient;
  953. }
  954. void KApplication::dcopClientPostInit()
  955. {
  956. if( s_dcopClientNeedsPostInit )
  957. {
  958. s_dcopClientNeedsPostInit = false;
  959. connect(s_DCOPClient, TQT_SIGNAL(blockUserInput(bool) ),
  960. TQT_SLOT(dcopBlockUserInput(bool)) );
  961. s_DCOPClient->bindToApp(); // Make sure we get events from the DCOPClient.
  962. }
  963. }
  964. void KApplication::dcopAutoRegistration()
  965. {
  966. if (autoDcopRegistration)
  967. {
  968. ( void ) dcopClient();
  969. if( dcopClient()->appId().isEmpty())
  970. dcopClient()->registerAs(name());
  971. }
  972. }
  973. void KApplication::disableAutoDcopRegistration()
  974. {
  975. autoDcopRegistration = false;
  976. }
  977. KConfig* KApplication::sessionConfig()
  978. {
  979. if (pSessionConfig)
  980. return pSessionConfig;
  981. // create an instance specific config object
  982. pSessionConfig = new KConfig( sessionConfigName(), false, false);
  983. return pSessionConfig;
  984. }
  985. void KApplication::ref()
  986. {
  987. d->refCount++;
  988. //kdDebug() << "KApplication::ref() : refCount = " << d->refCount << endl;
  989. }
  990. void KApplication::deref()
  991. {
  992. d->refCount--;
  993. //kdDebug() << "KApplication::deref() : refCount = " << d->refCount << endl;
  994. if ( d->refCount <= 0 )
  995. quit();
  996. }
  997. KSessionManaged::KSessionManaged()
  998. {
  999. sessionClients()->remove( this );
  1000. sessionClients()->append( this );
  1001. }
  1002. KSessionManaged::~KSessionManaged()
  1003. {
  1004. sessionClients()->remove( this );
  1005. }
  1006. bool KSessionManaged::saveState(TQSessionManager&)
  1007. {
  1008. return true;
  1009. }
  1010. bool KSessionManaged::commitData(TQSessionManager&)
  1011. {
  1012. return true;
  1013. }
  1014. void KApplication::disableSessionManagement() {
  1015. bSessionManagement = false;
  1016. }
  1017. void KApplication::enableSessionManagement() {
  1018. bSessionManagement = true;
  1019. #ifdef Q_WS_X11
  1020. // Session management support in Qt/KDE is awfully broken.
  1021. // If konqueror disables session management right after its startup,
  1022. // and enables it later (preloading stuff), it won't be properly
  1023. // saved on session shutdown.
  1024. // I'm not actually sure why it doesn't work, but saveState()
  1025. // doesn't seem to be called on session shutdown, possibly
  1026. // because disabling session management after konqueror startup
  1027. // disabled it somehow. Forcing saveState() here for this application
  1028. // seems to fix it.
  1029. if( mySmcConnection ) {
  1030. SmcRequestSaveYourself( mySmcConnection, SmSaveLocal, False,
  1031. SmInteractStyleAny,
  1032. False, False );
  1033. // flush the request
  1034. IceFlush(SmcGetIceConnection(mySmcConnection));
  1035. }
  1036. #endif
  1037. }
  1038. bool KApplication::requestShutDown(
  1039. ShutdownConfirm confirm, ShutdownType sdtype, ShutdownMode sdmode )
  1040. {
  1041. #ifdef Q_WS_X11
  1042. TQApplication::syncX();
  1043. /* use ksmserver's dcop interface if necessary */
  1044. if ( confirm == ShutdownConfirmYes ||
  1045. sdtype != ShutdownTypeDefault ||
  1046. sdmode != ShutdownModeDefault )
  1047. {
  1048. TQByteArray data;
  1049. TQDataStream arg(data, IO_WriteOnly);
  1050. arg << (int)confirm << (int)sdtype << (int)sdmode;
  1051. return dcopClient()->send( "ksmserver", "ksmserver",
  1052. "logout(int,int,int)", data );
  1053. }
  1054. if ( mySmcConnection ) {
  1055. // we already have a connection to the session manager, use it.
  1056. SmcRequestSaveYourself( mySmcConnection, SmSaveBoth, True,
  1057. SmInteractStyleAny,
  1058. confirm == ShutdownConfirmNo, True );
  1059. // flush the request
  1060. IceFlush(SmcGetIceConnection(mySmcConnection));
  1061. return true;
  1062. }
  1063. // open a temporary connection, if possible
  1064. propagateSessionManager();
  1065. TQCString smEnv = ::getenv("SESSION_MANAGER");
  1066. if (smEnv.isEmpty())
  1067. return false;
  1068. if (! tmpSmcConnection) {
  1069. char cerror[256];
  1070. char* myId = 0;
  1071. char* prevId = 0;
  1072. SmcCallbacks cb;
  1073. tmpSmcConnection = SmcOpenConnection( 0, 0, 1, 0,
  1074. 0, &cb,
  1075. prevId,
  1076. &myId,
  1077. 255,
  1078. cerror );
  1079. ::free( myId ); // it was allocated by C
  1080. if (!tmpSmcConnection )
  1081. return false;
  1082. }
  1083. SmcRequestSaveYourself( tmpSmcConnection, SmSaveBoth, True,
  1084. SmInteractStyleAny, False, True );
  1085. // flush the request
  1086. IceFlush(SmcGetIceConnection(tmpSmcConnection));
  1087. return true;
  1088. #else
  1089. // FIXME(E): Implement for Qt Embedded
  1090. return false;
  1091. #endif
  1092. }
  1093. void KApplication::propagateSessionManager()
  1094. {
  1095. #ifdef Q_WS_X11
  1096. TQCString fName = TQFile::encodeName(locateLocal("socket", "KSMserver"));
  1097. TQCString display = ::getenv(DISPLAY);
  1098. // strip the screen number from the display
  1099. display.replace(TQRegExp("\\.[0-9]+$"), "");
  1100. int i;
  1101. while( (i = display.find(':')) >= 0)
  1102. display[i] = '_';
  1103. fName += "_"+display;
  1104. TQCString smEnv = ::getenv("SESSION_MANAGER");
  1105. bool check = smEnv.isEmpty();
  1106. if ( !check && smModificationTime ) {
  1107. TQFileInfo info( fName );
  1108. TQTime current = TQT_TQTIME_OBJECT(info.lastModified().time());
  1109. check = current > *smModificationTime;
  1110. }
  1111. if ( check ) {
  1112. delete smModificationTime;
  1113. TQFile f( fName );
  1114. if ( !f.open( IO_ReadOnly ) )
  1115. return;
  1116. TQFileInfo info ( f );
  1117. smModificationTime = new TQTime( TQT_TQTIME_OBJECT(info.lastModified().time()) );
  1118. TQTextStream t(&f);
  1119. t.setEncoding( TQTextStream::Latin1 );
  1120. TQString s = t.readLine();
  1121. f.close();
  1122. ::setenv( "SESSION_MANAGER", s.latin1(), true );
  1123. }
  1124. #endif
  1125. }
  1126. void KApplication::commitData( TQSessionManager& sm )
  1127. {
  1128. d->session_save = true;
  1129. bool canceled = false;
  1130. for (KSessionManaged* it = sessionClients()->first();
  1131. it && !canceled;
  1132. it = sessionClients()->next() ) {
  1133. canceled = !it->commitData( sm );
  1134. }
  1135. if ( canceled )
  1136. sm.cancel();
  1137. if ( sm.allowsInteraction() ) {
  1138. TQWidgetList done;
  1139. TQWidgetList *list = TQApplication::tqtopLevelWidgets();
  1140. bool canceled = false;
  1141. TQWidget* w = list->first();
  1142. while ( !canceled && w ) {
  1143. if ( !w->testWState( WState_ForceHide ) && !w->inherits("KMainWindow") ) {
  1144. TQCloseEvent e;
  1145. sendEvent( w, &e );
  1146. canceled = !e.isAccepted();
  1147. if ( !canceled )
  1148. done.append( w );
  1149. delete list; // one never knows...
  1150. list = TQApplication::tqtopLevelWidgets();
  1151. w = list->first();
  1152. } else {
  1153. w = list->next();
  1154. }
  1155. while ( w && done.containsRef( w ) )
  1156. w = list->next();
  1157. }
  1158. delete list;
  1159. }
  1160. if ( !bSessionManagement )
  1161. sm.setRestartHint( TQSessionManager::RestartNever );
  1162. else
  1163. sm.setRestartHint( TQSessionManager::RestartIfRunning );
  1164. d->session_save = false;
  1165. }
  1166. static void checkRestartVersion( TQSessionManager& sm )
  1167. {
  1168. Display* dpy = qt_xdisplay();
  1169. Atom type;
  1170. int format;
  1171. unsigned long nitems, after;
  1172. unsigned char* data;
  1173. if( XGetWindowProperty( dpy, RootWindow( dpy, 0 ), XInternAtom( dpy, "TDE_FULL_SESSION", False ),
  1174. 0, 1, False, AnyPropertyType, &type, &format, &nitems, &after, &data ) == Success ) {
  1175. if( data != NULL )
  1176. XFree( data );
  1177. if( type == XA_STRING && format == 8 ) { // session set, check if KDE_SESSION_VERSION is not set (meaning KDE3)
  1178. if( XGetWindowProperty( dpy, RootWindow( dpy, 0 ), XInternAtom( dpy, "KDE_SESSION_VERSION", False ),
  1179. 0, 1, False, AnyPropertyType, &type, &format, &nitems, &after, &data ) == Success ) {
  1180. if( data != NULL )
  1181. XFree( data ); // KDE4 or newer
  1182. if( type == None )
  1183. return; // we run in our native session, no need to wrap
  1184. } else {
  1185. return; // we run in our native session, no need to wrap
  1186. }
  1187. }
  1188. }
  1189. TQString wrapper = KStandardDirs::findExe( "kde3" );
  1190. TQStringList restartCommand = sm.restartCommand();
  1191. restartCommand.prepend( wrapper );
  1192. sm.setRestartCommand( restartCommand );
  1193. }
  1194. void KApplication::saveState( TQSessionManager& sm )
  1195. {
  1196. d->session_save = true;
  1197. #ifdef Q_WS_X11
  1198. static bool firstTime = true;
  1199. mySmcConnection = (SmcConn) sm.handle();
  1200. if ( !bSessionManagement ) {
  1201. sm.setRestartHint( TQSessionManager::RestartNever );
  1202. d->session_save = false;
  1203. return;
  1204. }
  1205. else
  1206. sm.setRestartHint( TQSessionManager::RestartIfRunning );
  1207. if ( firstTime ) {
  1208. firstTime = false;
  1209. d->session_save = false;
  1210. return; // no need to save the state.
  1211. }
  1212. // remove former session config if still existing, we want a new
  1213. // and fresh one. Note that we do not delete the config file here,
  1214. // this is done by the session manager when it executes the
  1215. // discard commands. In fact it would be harmful to remove the
  1216. // file here, as the session might be stored under a different
  1217. // name, meaning the user still might need it eventually.
  1218. if ( pSessionConfig ) {
  1219. delete pSessionConfig;
  1220. pSessionConfig = 0;
  1221. }
  1222. // tell the session manager about our new lifecycle
  1223. TQStringList restartCommand = sm.restartCommand();
  1224. TQCString multiHead = getenv("KDE_MULTIHEAD");
  1225. if (multiHead.lower() == "true") {
  1226. // if multihead is enabled, we save our -display argument so that
  1227. // we are restored onto the correct head... one problem with this
  1228. // is that the display is hard coded, which means we cannot restore
  1229. // to a different display (ie. if we are in a university lab and try,
  1230. // try to restore a multihead session, our apps could be started on
  1231. // someone else's display instead of our own)
  1232. TQCString displayname = getenv(DISPLAY);
  1233. if (! displayname.isNull()) {
  1234. // only store the command if we actually have a DISPLAY
  1235. // environment variable
  1236. restartCommand.append("-display");
  1237. restartCommand.append(displayname);
  1238. }
  1239. sm.setRestartCommand( restartCommand );
  1240. }
  1241. checkRestartVersion( sm );
  1242. // finally: do session management
  1243. emit saveYourself(); // for compatibility
  1244. bool canceled = false;
  1245. for (KSessionManaged* it = sessionClients()->first();
  1246. it && !canceled;
  1247. it = sessionClients()->next() ) {
  1248. canceled = !it->saveState( sm );
  1249. }
  1250. // if we created a new session config object, register a proper discard command
  1251. if ( pSessionConfig ) {
  1252. pSessionConfig->sync();
  1253. TQStringList discard;
  1254. discard << "rm" << locateLocal("config", sessionConfigName());
  1255. sm.setDiscardCommand( discard );
  1256. } else {
  1257. sm.setDiscardCommand( TQStringList("") );
  1258. }
  1259. if ( canceled )
  1260. sm.cancel();
  1261. #else
  1262. // FIXME(E): Implement for Qt Embedded
  1263. #endif
  1264. d->session_save = false;
  1265. }
  1266. bool KApplication::sessionSaving() const
  1267. {
  1268. return d->session_save;
  1269. }
  1270. void KApplication::startKdeinit()
  1271. {
  1272. #ifndef Q_WS_WIN //TODO
  1273. KInstance inst( "startkdeinitlock" );
  1274. KLockFile lock( locateLocal( "tmp", "startkdeinitlock", &inst ));
  1275. if( lock.lock( KLockFile::LockNoBlock ) != KLockFile::LockOK ) {
  1276. lock.lock();
  1277. DCOPClient cl;
  1278. if( cl.attach())
  1279. return; // whoever held the lock has already started dcopserver
  1280. }
  1281. // Try to launch kdeinit.
  1282. TQString srv = KStandardDirs::findExe(TQString::tqfromLatin1("kdeinit"));
  1283. if (srv.isEmpty())
  1284. srv = KStandardDirs::findExe(TQString::tqfromLatin1("kdeinit"), KGlobal::dirs()->kfsstnd_defaultbindir());
  1285. if (srv.isEmpty())
  1286. return;
  1287. if (kapp && (Tty != kapp->type()))
  1288. setOverrideCursor( tqwaitCursor );
  1289. my_system(TQFile::encodeName(srv)+" --suicide"+" --new-startup");
  1290. if (kapp && (Tty != kapp->type()))
  1291. restoreOverrideCursor();
  1292. #endif
  1293. }
  1294. void KApplication::dcopFailure(const TQString &msg)
  1295. {
  1296. static int failureCount = 0;
  1297. failureCount++;
  1298. if (failureCount == 1)
  1299. {
  1300. startKdeinit();
  1301. return;
  1302. }
  1303. if (failureCount == 2)
  1304. {
  1305. #ifdef Q_WS_WIN
  1306. KGlobal::config()->setGroup("General");
  1307. if (KGlobal::config()->readBoolEntry("ignoreDCOPFailures", false))
  1308. return;
  1309. #endif
  1310. TQString msgStr(i18n("There was an error setting up inter-process "
  1311. "communications for KDE. The message returned "
  1312. "by the system was:\n\n"));
  1313. msgStr += msg;
  1314. msgStr += i18n("\n\nPlease check that the \"dcopserver\" program is running!");
  1315. if (Tty != kapp->type())
  1316. {
  1317. TQMessageBox::critical
  1318. (
  1319. kapp->mainWidget(),
  1320. i18n("DCOP communications error (%1)").arg(kapp->caption()),
  1321. msgStr,
  1322. i18n("&OK")
  1323. );
  1324. }
  1325. else
  1326. {
  1327. fprintf(stderr, "%s\n", msgStr.local8Bit().data());
  1328. }
  1329. return;
  1330. }
  1331. }
  1332. static const KCmdLineOptions qt_options[] =
  1333. {
  1334. //FIXME: Check if other options are specific to Qt/X11
  1335. #ifdef Q_WS_X11
  1336. { "display <displayname>", I18N_NOOP("Use the X-server display 'displayname'"), 0},
  1337. #else
  1338. { "display <displayname>", I18N_NOOP("Use the QWS display 'displayname'"), 0},
  1339. #endif
  1340. { "session <sessionId>", I18N_NOOP("Restore the application for the given 'sessionId'"), 0},
  1341. { "cmap", I18N_NOOP("Causes the application to install a private color\nmap on an 8-bit display"), 0},
  1342. { "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},
  1343. { "nograb", I18N_NOOP("tells Qt to never grab the mouse or the keyboard"), 0},
  1344. { "dograb", I18N_NOOP("running under a debugger can cause an implicit\n-nograb, use -dograb to override"), 0},
  1345. { "sync", I18N_NOOP("switches to synchronous mode for debugging"), 0},
  1346. { "fn", 0, 0},
  1347. { "font <fontname>", I18N_NOOP("defines the application font"), 0},
  1348. { "bg", 0, 0},
  1349. { "background <color>", I18N_NOOP("sets the default background color and an\napplication palette (light and dark shades are\ncalculated)"), 0},
  1350. { "fg", 0, 0},
  1351. { "foreground <color>", I18N_NOOP("sets the default foreground color"), 0},
  1352. { "btn", 0, 0},
  1353. { "button <color>", I18N_NOOP("sets the default button color"), 0},
  1354. { "name <name>", I18N_NOOP("sets the application name"), 0},
  1355. { "title <title>", I18N_NOOP("sets the application title (caption)"), 0},
  1356. #ifdef Q_WS_X11
  1357. { "visual TrueColor", I18N_NOOP("forces the application to use a TrueColor visual on\nan 8-bit display"), 0},
  1358. { "inputstyle <inputstyle>", I18N_NOOP("sets XIM (X Input Method) input style. Possible\nvalues are onthespot, overthespot, offthespot and\nroot"), 0 },
  1359. { "im <XIM server>", I18N_NOOP("set XIM server"),0},
  1360. { "noxim", I18N_NOOP("disable XIM"), 0 },
  1361. #endif
  1362. #ifdef Q_WS_QWS
  1363. { "qws", I18N_NOOP("forces the application to run as QWS Server"), 0},
  1364. #endif
  1365. { "reverse", I18N_NOOP("mirrors the whole layout of widgets"), 0},
  1366. KCmdLineLastOption
  1367. };
  1368. static const KCmdLineOptions kde_options[] =
  1369. {
  1370. { "caption <caption>", I18N_NOOP("Use 'caption' as name in the titlebar"), 0},
  1371. { "icon <icon>", I18N_NOOP("Use 'icon' as the application icon"), 0},
  1372. { "miniicon <icon>", I18N_NOOP("Use 'icon' as the icon in the titlebar"), 0},
  1373. { "config <filename>", I18N_NOOP("Use alternative configuration file"), 0},
  1374. { "dcopserver <server>", I18N_NOOP("Use the DCOP Server specified by 'server'"), 0},
  1375. { "nocrashhandler", I18N_NOOP("Disable crash handler, to get core dumps"), 0},
  1376. { "waitforwm", I18N_NOOP("Waits for a WM_NET compatible windowmanager"), 0},
  1377. { "style <style>", I18N_NOOP("sets the application GUI style"), 0},
  1378. { "geometry <geometry>", I18N_NOOP("sets the client geometry of the main widget - see man X for the argument format"), 0},
  1379. { "smkey <sessionKey>", 0, 0}, // this option is obsolete and exists only to allow smooth upgrades from sessions
  1380. // saved under Qt 3.0.x -- Qt 3.1.x includes the session key now automatically in
  1381. // the session id (Simon)
  1382. KCmdLineLastOption
  1383. };
  1384. void
  1385. KApplication::addCmdLineOptions()
  1386. {
  1387. KCmdLineArgs::addCmdLineOptions(qt_options, "Qt", "qt");
  1388. KCmdLineArgs::addCmdLineOptions(kde_options, "KDE", "kde");
  1389. }
  1390. void KApplication::parseCommandLine( )
  1391. {
  1392. KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
  1393. if ( !args ) return;
  1394. if (args->isSet("config"))
  1395. {
  1396. TQString config = TQString::fromLocal8Bit(args->getOption("config"));
  1397. setConfigName(config);
  1398. }
  1399. if (args->isSet("style"))
  1400. {
  1401. TQStringList plugins = KGlobal::dirs()->resourceDirs( "qtplugins" );
  1402. TQStringList::Iterator itp = plugins.begin();
  1403. while (itp != plugins.end()) {
  1404. addLibraryPath( *itp );
  1405. ++itp;
  1406. }
  1407. TQStringList styles = TQStyleFactory::keys();
  1408. TQString reqStyle(args->getOption("style").lower());
  1409. TQStringList list = libraryPaths();
  1410. TQStringList::Iterator it = list.begin();
  1411. while( it != list.end() ) {
  1412. ++it;
  1413. }
  1414. for (TQStringList::ConstIterator it = styles.begin(); it != styles.end(); ++it) {
  1415. if ((*it).lower() == reqStyle)
  1416. {
  1417. d->overrideStyle = *it;
  1418. break;
  1419. }
  1420. }
  1421. if (d->overrideStyle.isEmpty())
  1422. fprintf(stderr, "%s", TQString(i18n("The style %1 was not found\n").arg(reqStyle)).local8Bit().data());
  1423. }
  1424. if (args->isSet("caption"))
  1425. {
  1426. aCaption = TQString::fromLocal8Bit(args->getOption("caption"));
  1427. }
  1428. if (args->isSet("miniicon"))
  1429. {
  1430. const char *tmp = args->getOption("miniicon");
  1431. if (!aIconPixmap.pm.miniIcon) {
  1432. aIconPixmap.pm.miniIcon = new TQPixmap;
  1433. }
  1434. *aIconPixmap.pm.miniIcon = SmallIcon(tmp);
  1435. aMiniIconName = tmp;
  1436. }
  1437. if (args->isSet("icon"))
  1438. {
  1439. const char *tmp = args->getOption("icon");
  1440. if (!aIconPixmap.pm.icon) {
  1441. aIconPixmap.pm.icon = new TQPixmap;
  1442. }
  1443. *aIconPixmap.pm.icon = DesktopIcon( tmp );
  1444. aIconName = tmp;
  1445. if (!aIconPixmap.pm.miniIcon) {
  1446. aIconPixmap.pm.miniIcon = new TQPixmap;
  1447. }
  1448. if (aIconPixmap.pm.miniIcon->isNull())
  1449. {
  1450. *aIconPixmap.pm.miniIcon = SmallIcon( tmp );
  1451. aMiniIconName = tmp;
  1452. }
  1453. }
  1454. bool nocrashhandler = (getenv("KDE_DEBUG") != NULL);
  1455. if (!nocrashhandler && args->isSet("crashhandler"))
  1456. {
  1457. // set default crash handler / set emergency save function to nothing
  1458. KCrash::setCrashHandler(KCrash::defaultCrashHandler);
  1459. KCrash::setEmergencySaveFunction(NULL);
  1460. KCrash::setApplicationName(TQString(args->appName()));
  1461. }
  1462. #ifdef Q_WS_X11
  1463. if ( args->isSet( "waitforwm" ) ) {
  1464. Atom type;
  1465. (void) desktop(); // trigger desktop creation, we need PropertyNotify events for the root window
  1466. int format;
  1467. unsigned long length, after;
  1468. unsigned char *data;
  1469. while ( XGetWindowProperty( qt_xdisplay(), qt_xrootwin(), atom_NetSupported,
  1470. 0, 1, false, AnyPropertyType, &type, &format,
  1471. &length, &after, &data ) != Success || !length ) {
  1472. if ( data )
  1473. XFree( data );
  1474. XEvent event;
  1475. XWindowEvent( qt_xdisplay(), qt_xrootwin(), PropertyChangeMask, &event );
  1476. }
  1477. if ( data )
  1478. XFree( data );
  1479. }
  1480. #else
  1481. // FIXME(E): Implement for Qt Embedded
  1482. #endif
  1483. if (args->isSet("geometry"))
  1484. {
  1485. d->geometry_arg = args->getOption("geometry");
  1486. }
  1487. if (args->isSet("smkey"))
  1488. {
  1489. d->sessionKey = args->getOption("smkey");
  1490. }
  1491. }
  1492. TQString KApplication::geometryArgument() const
  1493. {
  1494. return d->geometry_arg;
  1495. }
  1496. TQPixmap KApplication::icon() const
  1497. {
  1498. if( !aIconPixmap.pm.icon) {
  1499. aIconPixmap.pm.icon = new TQPixmap;
  1500. }
  1501. if( aIconPixmap.pm.icon->isNull()) {
  1502. *aIconPixmap.pm.icon = DesktopIcon( instanceName() );
  1503. }
  1504. return *aIconPixmap.pm.icon;
  1505. }
  1506. TQString KApplication::iconName() const
  1507. {
  1508. return aIconName.isNull() ? (TQString)instanceName() : aIconName;
  1509. }
  1510. TQPixmap KApplication::miniIcon() const
  1511. {
  1512. if (!aIconPixmap.pm.miniIcon) {
  1513. aIconPixmap.pm.miniIcon = new TQPixmap;
  1514. }
  1515. if (aIconPixmap.pm.miniIcon->isNull()) {
  1516. *aIconPixmap.pm.miniIcon = SmallIcon( instanceName() );
  1517. }
  1518. return *aIconPixmap.pm.miniIcon;
  1519. }
  1520. TQString KApplication::miniIconName() const
  1521. {
  1522. return aMiniIconName.isNull() ? (TQString)instanceName() : aMiniIconName;
  1523. }
  1524. extern void kDebugCleanup();
  1525. KApplication::~KApplication()
  1526. {
  1527. delete aIconPixmap.pm.miniIcon;
  1528. aIconPixmap.pm.miniIcon = 0L;
  1529. delete aIconPixmap.pm.icon;
  1530. aIconPixmap.pm.icon = 0L;
  1531. delete d->m_KAppDCOPInterface;
  1532. // First call the static deleters and then call KLibLoader::cleanup()
  1533. // The static deleters may delete libraries for which they need KLibLoader.
  1534. // KLibLoader will take care of the remaining ones.
  1535. KGlobal::deleteStaticDeleters();
  1536. KLibLoader::cleanUp();
  1537. delete smw;
  1538. // close down IPC
  1539. delete s_DCOPClient;
  1540. s_DCOPClient = 0L;
  1541. KProcessController::deref();
  1542. #ifdef Q_WS_X11
  1543. if ( d->oldXErrorHandler != NULL )
  1544. XSetErrorHandler( d->oldXErrorHandler );
  1545. if ( d->oldXIOErrorHandler != NULL )
  1546. XSetIOErrorHandler( d->oldXIOErrorHandler );
  1547. if ( d->oldIceIOErrorHandler != NULL )
  1548. IceSetIOErrorHandler( d->oldIceIOErrorHandler );
  1549. #endif
  1550. delete d;
  1551. KApp = 0;
  1552. #ifdef Q_WS_X11
  1553. mySmcConnection = 0;
  1554. delete smModificationTime;
  1555. smModificationTime = 0;
  1556. // close the temporary smc connection
  1557. if (tmpSmcConnection) {
  1558. SmcCloseConnection( tmpSmcConnection, 0, 0 );
  1559. tmpSmcConnection = 0;
  1560. }
  1561. #else
  1562. // FIXME(E): Implement for Qt Embedded
  1563. #endif
  1564. }
  1565. #ifdef Q_WS_X11
  1566. class KAppX11HackWidget: public QWidget
  1567. {
  1568. public:
  1569. bool publicx11Event( XEvent * e) { return x11Event( e ); }
  1570. };
  1571. #endif
  1572. #if defined(Q_WS_X11) && defined(COMPOSITE)
  1573. bool KApplication::isCompositionManagerAvailable() {
  1574. bool have_manager = false;
  1575. const char *home;
  1576. struct passwd *p;
  1577. p = getpwuid(getuid());
  1578. if (p)
  1579. home = p->pw_dir;
  1580. else
  1581. home = getenv("HOME");
  1582. char *filename;
  1583. const char *configfile = "/.kompmgr.available";
  1584. int n = strlen(home)+strlen(configfile)+1;
  1585. filename = (char*)malloc(n*sizeof(char));
  1586. memset(filename,0,n);
  1587. strcat(filename, home);
  1588. strcat(filename, configfile);
  1589. // Now that we did all that by way of introduction...read the file!
  1590. FILE *pFile;
  1591. char buffer[255];
  1592. pFile = fopen(filename, "r");
  1593. int kompmgrpid = 0;
  1594. if (pFile) {
  1595. have_manager = true;
  1596. fclose(pFile);
  1597. }
  1598. free(filename);
  1599. filename = NULL;
  1600. return have_manager;
  1601. }
  1602. bool KApplication::detectCompositionManagerAvailable(bool force_available, bool available) {
  1603. bool compositing_manager_available;
  1604. if (force_available) {
  1605. compositing_manager_available = available;
  1606. }
  1607. else {
  1608. // See if compositing has been enabled
  1609. KCmdLineArgs *qtargs = KCmdLineArgs::parsedArgs("qt");
  1610. char *displayname = 0;
  1611. if ( qtargs->isSet("display"))
  1612. displayname = qtargs->getOption( "display" ).data();
  1613. Display *dpy = XOpenDisplay( displayname );
  1614. x11_composite_error_generated = false;
  1615. compositing_manager_available = false;
  1616. XSetErrorHandler(x11_error);
  1617. if (!XQueryExtension (dpy, COMPOSITE_NAME, &composite_opcode, &composite_event, &composite_error)) {
  1618. XSetErrorHandler(NULL);
  1619. compositing_manager_available = false;
  1620. }
  1621. else {
  1622. Window root_window = XDefaultRootWindow(dpy);
  1623. XCompositeRedirectSubwindows(dpy, root_window, CompositeRedirectManual);
  1624. XSync(dpy, false);
  1625. if (x11_composite_error_generated == true) {
  1626. compositing_manager_available = true;
  1627. }
  1628. else {
  1629. XCompositeUnredirectSubwindows(dpy, root_window, CompositeRedirectManual);
  1630. compositing_manager_available = false;
  1631. }
  1632. XSetErrorHandler(NULL);
  1633. XCloseDisplay(dpy);
  1634. }
  1635. }
  1636. const char *home;
  1637. struct passwd *p;
  1638. p = getpwuid(getuid());
  1639. if (p)
  1640. home = p->pw_dir;
  1641. else
  1642. home = getenv("HOME");
  1643. char *filename;
  1644. const char *configfile = "/.kompmgr.available";
  1645. int n = strlen(home)+strlen(configfile)+1;
  1646. filename = (char*)malloc(n*sizeof(char));
  1647. memset(filename,0,n);
  1648. strcat(filename, home);
  1649. strcat(filename, configfile);
  1650. /* now that we did all that by way of introduction...create or remove the file! */
  1651. if (compositing_manager_available) {
  1652. FILE *pFile;
  1653. char buffer[255];
  1654. sprintf(buffer, "available");
  1655. pFile = fopen(filename, "w");
  1656. if (pFile) {
  1657. fwrite(buffer,1,strlen(buffer), pFile);
  1658. fclose(pFile);
  1659. }
  1660. }
  1661. else {
  1662. unlink(filename);
  1663. }
  1664. free(filename);
  1665. filename = NULL;
  1666. return compositing_manager_available;
  1667. }
  1668. Display* KApplication::openX11RGBADisplay() {
  1669. KCmdLineArgs *qtargs = KCmdLineArgs::parsedArgs("qt");
  1670. char *display = 0;
  1671. if ( qtargs->isSet("display"))
  1672. display = qtargs->getOption( "display" ).data();
  1673. Display *dpy = XOpenDisplay( display );
  1674. if ( !dpy ) {
  1675. kdError() << "cannot connect to X server " << display << endl;
  1676. exit( 1 );
  1677. }
  1678. return dpy;
  1679. }
  1680. Qt::HANDLE KApplication::getX11RGBAVisual(Display *dpy) {
  1681. getX11RGBAInformation(dpy);
  1682. if (KApplication::isCompositionManagerAvailable() == true) {
  1683. return argb_x11_visual;
  1684. }
  1685. else {
  1686. return NULL;
  1687. }
  1688. }
  1689. Qt::HANDLE KApplication::getX11RGBAColormap(Display *dpy) {
  1690. getX11RGBAInformation(dpy);
  1691. if (KApplication::isCompositionManagerAvailable() == true) {
  1692. return argb_x11_colormap;
  1693. }
  1694. else {
  1695. return NULL;
  1696. }
  1697. }
  1698. bool KApplication::isX11CompositionAvailable() {
  1699. return (argb_visual & isCompositionManagerAvailable());
  1700. }
  1701. void KApplication::getX11RGBAInformation(Display *dpy) {
  1702. if ( !dpy ) {
  1703. argb_visual = false;
  1704. return;
  1705. }
  1706. int screen = DefaultScreen( dpy );
  1707. Colormap colormap = 0;
  1708. Visual *visual = 0;
  1709. int event_base, error_base;
  1710. if ( XRenderQueryExtension( dpy, &event_base, &error_base ) ) {
  1711. int nvi;
  1712. XVisualInfo templ;
  1713. templ.screen = screen;
  1714. templ.depth = 32;
  1715. templ.c_class = TrueColor;
  1716. XVisualInfo *xvi = XGetVisualInfo( dpy, VisualScreenMask | VisualDepthMask
  1717. | VisualClassMask, &templ, &nvi );
  1718. for ( int i = 0; i < nvi; i++ ) {
  1719. XRenderPictFormat *format = XRenderFindVisualFormat( dpy, xvi[i].visual );
  1720. if ( format->type == PictTypeDirect && format->direct.alphaMask ) {
  1721. visual = xvi[i].visual;
  1722. colormap = XCreateColormap( dpy, RootWindow( dpy, screen ), visual, AllocNone );
  1723. kdDebug() << "found visual with alpha support" << endl;
  1724. argb_visual = true;
  1725. break;
  1726. }
  1727. }
  1728. }
  1729. if( argb_visual ) {
  1730. argb_x11_visual = Qt::HANDLE( visual );
  1731. argb_x11_colormap = Qt::HANDLE( colormap );
  1732. argb_visual = true;
  1733. return;
  1734. }
  1735. argb_visual = false;
  1736. return;
  1737. }
  1738. #else
  1739. void KApplication::getX11RGBAInformation(Display *dpy) {
  1740. }
  1741. bool KApplication::isCompositionManagerAvailable() {
  1742. return false;
  1743. }
  1744. bool KApplication::detectCompositionManagerAvailable(bool force_available) {
  1745. const char *home;
  1746. struct passwd *p;
  1747. p = getpwuid(getuid());
  1748. if (p)
  1749. home = p->pw_dir;
  1750. else
  1751. home = getenv("HOME");
  1752. char *filename;
  1753. const char *configfile = "/.kompmgr.available";
  1754. int n = strlen(home)+strlen(configfile)+1;
  1755. filename = (char*)malloc(n*sizeof(char));
  1756. memset(filename,0,n);
  1757. strcat(filename, home);
  1758. strcat(filename, configfile);
  1759. /* now that we did all that by way of introduction...remove the file! */
  1760. unlink(filename);
  1761. free(filename);
  1762. filename = NULL;
  1763. return false;
  1764. }
  1765. Display* KApplication::openX11RGBADisplay() {
  1766. return 0;
  1767. }
  1768. Qt::HANDLE KApplication::getX11RGBAVisual(char *display) {
  1769. return 0;
  1770. }
  1771. Qt::HANDLE KApplication::getX11RGBAColormap(char *display) {
  1772. return 0;
  1773. }
  1774. bool KApplication::isX11CompositionAvailable() {
  1775. return false;
  1776. }
  1777. KApplication KApplication::KARGBApplication( bool allowStyles ) {
  1778. return KApplication::KApplication(allowStyles, true);
  1779. }
  1780. #endif
  1781. static bool kapp_block_user_input = false;
  1782. void KApplication::dcopBlockUserInput( bool b )
  1783. {
  1784. kapp_block_user_input = b;
  1785. }
  1786. #ifdef Q_WS_X11
  1787. bool KApplication::x11EventFilter( XEvent *_event )
  1788. {
  1789. switch ( _event->type ) {
  1790. case ClientMessage:
  1791. {
  1792. #if KDE_IS_VERSION( 3, 90, 90 )
  1793. #warning This should be already in Qt, check.
  1794. #endif
  1795. // Workaround for focus stealing prevention not working when dragging e.g. text from KWrite
  1796. // to KDesktop -> the dialog asking for filename doesn't get activated. This is because
  1797. // Qt-3.2.x doesn't have concept of qt_x_user_time at all, and Qt-3.3.0b1 passes the timestamp
  1798. // in the XdndDrop message in incorrect field (and doesn't update qt_x_user_time either).
  1799. // Patch already sent, future Qt version should have this fixed.
  1800. if( _event->xclient.message_type == kde_xdnd_drop )
  1801. { // if the message is XdndDrop
  1802. if( _event->xclient.data.l[ 1 ] == 1 << 24 // and it's broken the way it's in Qt-3.2.x
  1803. && _event->xclient.data.l[ 2 ] == 0
  1804. && _event->xclient.data.l[ 4 ] == 0
  1805. && _event->xclient.data.l[ 3 ] != 0 )
  1806. {
  1807. if( GET_QT_X_USER_TIME() == 0
  1808. || NET::timestampCompare( _event->xclient.data.l[ 3 ], GET_QT_X_USER_TIME() ) > 0 )
  1809. { // and the timestamp looks reasonable
  1810. SET_QT_X_USER_TIME(_event->xclient.data.l[ 3 ]); // update our qt_x_user_time from it
  1811. }
  1812. }
  1813. else // normal DND, only needed until Qt updates qt_x_user_time from XdndDrop
  1814. {
  1815. if( GET_QT_X_USER_TIME() == 0
  1816. || NET::timestampCompare( _event->xclient.data.l[ 2 ], GET_QT_X_USER_TIME() ) > 0 )
  1817. { // the timestamp looks reasonable
  1818. SET_QT_X_USER_TIME(_event->xclient.data.l[ 2 ]); // update our qt_x_user_time from it
  1819. }
  1820. }
  1821. }
  1822. }
  1823. default: break;
  1824. }
  1825. if ( kapp_block_user_input ) {
  1826. switch ( _event->type ) {
  1827. case ButtonPress:
  1828. case ButtonRelease:
  1829. case XKeyPress:
  1830. case XKeyRelease:
  1831. case MotionNotify:
  1832. case EnterNotify:
  1833. case LeaveNotify:
  1834. return true;
  1835. default:
  1836. break;
  1837. }
  1838. }
  1839. if (x11Filter) {
  1840. for (TQWidget *w=x11Filter->first(); w; w=x11Filter->next()) {
  1841. if (((KAppX11HackWidget*) w)->publicx11Event(_event))
  1842. return true;
  1843. }
  1844. }
  1845. if ((_event->type == ClientMessage) &&
  1846. (_event->xclient.message_type == kipcCommAtom))
  1847. {
  1848. XClientMessageEvent *cme = (XClientMessageEvent *) _event;
  1849. int id = cme->data.l[0];
  1850. int arg = cme->data.l[1];
  1851. if ((id < 32) && (kipcEventMask & (1 << id)))
  1852. {
  1853. switch (id)
  1854. {
  1855. case KIPC::StyleChanged:
  1856. KGlobal::config()->reparseConfiguration();
  1857. kdisplaySetStyle();
  1858. break;
  1859. case KIPC::ToolbarStyleChanged:
  1860. KGlobal::config()->reparseConfiguration();
  1861. if (useStyles)
  1862. emit toolbarAppearanceChanged(arg);
  1863. break;
  1864. case KIPC::PaletteChanged:
  1865. KGlobal::config()->reparseConfiguration();
  1866. kdisplaySetPalette();
  1867. break;
  1868. case KIPC::FontChanged:
  1869. KGlobal::config()->reparseConfiguration();
  1870. KGlobalSettings::rereadFontSettings();
  1871. kdisplaySetFont();
  1872. break;
  1873. case KIPC::BackgroundChanged:
  1874. emit backgroundChanged(arg);
  1875. break;
  1876. case KIPC::SettingsChanged:
  1877. KGlobal::config()->reparseConfiguration();
  1878. if (arg == SETTINGS_PATHS)
  1879. KGlobalSettings::rereadPathSettings();
  1880. else if (arg == SETTINGS_MOUSE)
  1881. KGlobalSettings::rereadMouseSettings();
  1882. propagateSettings((SettingsCategory)arg);
  1883. break;
  1884. case KIPC::IconChanged:
  1885. TQPixmapCache::clear();
  1886. KGlobal::config()->reparseConfiguration();
  1887. KGlobal::instance()->newIconLoader();
  1888. emit updateIconLoaders();
  1889. emit iconChanged(arg);
  1890. break;
  1891. case KIPC::ClipboardConfigChanged:
  1892. KClipboardSynchronizer::newConfiguration(arg);
  1893. break;
  1894. case KIPC::BlockShortcuts:
  1895. KGlobalAccel::blockShortcuts(arg);
  1896. emit kipcMessage(id, arg); // some apps may do additional things
  1897. break;
  1898. }
  1899. }
  1900. else if (id >= 32)
  1901. {
  1902. emit kipcMessage(id, arg);
  1903. }
  1904. return true;
  1905. }
  1906. return false;
  1907. }
  1908. #endif // Q_WS_X11
  1909. void KApplication::updateUserTimestamp( unsigned long time )
  1910. {
  1911. #if defined Q_WS_X11
  1912. if( time == 0 )
  1913. { // get current X timestamp
  1914. Window w = XCreateSimpleWindow( qt_xdisplay(), qt_xrootwin(), 0, 0, 1, 1, 0, 0, 0 );
  1915. XSelectInput( qt_xdisplay(), w, PropertyChangeMask );
  1916. unsigned char data[ 1 ];
  1917. XChangeProperty( qt_xdisplay(), w, XA_ATOM, XA_ATOM, 8, PropModeAppend, data, 1 );
  1918. XEvent ev;
  1919. XWindowEvent( qt_xdisplay(), w, PropertyChangeMask, &ev );
  1920. time = ev.xproperty.time;
  1921. XDestroyWindow( qt_xdisplay(), w );
  1922. }
  1923. if( GET_QT_X_USER_TIME() == 0
  1924. || NET::timestampCompare( time, GET_QT_X_USER_TIME() ) > 0 ) // check time > qt_x_user_time
  1925. SET_QT_X_USER_TIME(time);
  1926. #endif
  1927. }
  1928. unsigned long KApplication::userTimestamp() const
  1929. {
  1930. #if defined Q_WS_X11
  1931. return GET_QT_X_USER_TIME();
  1932. #else
  1933. return 0;
  1934. #endif
  1935. }
  1936. void KApplication::updateRemoteUserTimestamp( const TQCString& dcopId, unsigned long time )
  1937. {
  1938. #if defined Q_WS_X11
  1939. if( time == 0 )
  1940. time = GET_QT_X_USER_TIME();
  1941. DCOPRef( dcopId, "MainApplication-Interface" ).call( "updateUserTimestamp", time );
  1942. #endif
  1943. }
  1944. void KApplication::invokeEditSlot( const char *slot )
  1945. {
  1946. TQObject *object = TQT_TQOBJECT(tqfocusWidget());
  1947. if( !object )
  1948. return;
  1949. TQMetaObject *meta = object->tqmetaObject();
  1950. int idx = meta->findSlot( slot + 1, true );
  1951. if( idx < 0 )
  1952. return;
  1953. object->qt_invoke( idx, 0 );
  1954. }
  1955. void KApplication::addKipcEventMask(int id)
  1956. {
  1957. if (id >= 32)
  1958. {
  1959. kdDebug(101) << "Cannot use KIPC event mask for message IDs >= 32\n";
  1960. return;
  1961. }
  1962. kipcEventMask |= (1 << id);
  1963. }
  1964. void KApplication::removeKipcEventMask(int id)
  1965. {
  1966. if (id >= 32)
  1967. {
  1968. kdDebug(101) << "Cannot use KIPC event mask for message IDs >= 32\n";
  1969. return;
  1970. }
  1971. kipcEventMask &= ~(1 << id);
  1972. }
  1973. void KApplication::enableStyles()
  1974. {
  1975. if (!useStyles)
  1976. {
  1977. useStyles = true;
  1978. applyGUIStyle();
  1979. }
  1980. }
  1981. void KApplication::disableStyles()
  1982. {
  1983. useStyles = false;
  1984. }
  1985. void KApplication::applyGUIStyle()
  1986. {
  1987. if ( !useStyles ) return;
  1988. KConfigGroup pConfig (KGlobal::config(), "General");
  1989. TQString defaultStyle = KStyle::defaultStyle();
  1990. TQString styleStr = pConfig.readEntry("widgetStyle", defaultStyle);
  1991. if (d->overrideStyle.isEmpty()) {
  1992. // ### add check whether we already use the correct style to return then
  1993. // (workaround for Qt misbehavior to avoid double style initialization)
  1994. TQStyle* sp = TQStyleFactory::create( styleStr );
  1995. // If there is no default style available, try falling back any available style
  1996. if ( !sp && styleStr != defaultStyle)
  1997. sp = TQStyleFactory::create( defaultStyle );
  1998. if ( !sp )
  1999. sp = TQStyleFactory::create( *(TQStyleFactory::keys().begin()) );
  2000. setStyle(sp);
  2001. }
  2002. else
  2003. setStyle(d->overrideStyle);
  2004. // Reread palette from config file.
  2005. kdisplaySetPalette();
  2006. }
  2007. TQString KApplication::caption() const
  2008. {
  2009. // Caption set from command line ?
  2010. if( !aCaption.isNull() )
  2011. return aCaption;
  2012. else
  2013. // We have some about data ?
  2014. if ( KGlobal::instance()->aboutData() )
  2015. return KGlobal::instance()->aboutData()->programName();
  2016. else
  2017. // Last resort : application name
  2018. return name();
  2019. }
  2020. //
  2021. // 1999-09-20: Espen Sand
  2022. // An attempt to simplify consistent captions.
  2023. //
  2024. TQString KApplication::makeStdCaption( const TQString &userCaption,
  2025. bool withAppName, bool modified ) const
  2026. {
  2027. TQString s = userCaption.isEmpty() ? caption() : userCaption;
  2028. // If the document is modified, add '[modified]'.
  2029. if (modified)
  2030. s += TQString::fromUtf8(" [") + i18n("modified") + TQString::fromUtf8("]");
  2031. if ( !userCaption.isEmpty() ) {
  2032. // Add the application name if:
  2033. // User asked for it, it's not a duplication and the app name (caption()) is not empty
  2034. if ( withAppName && !caption().isNull() && !userCaption.endsWith(caption()) )
  2035. s += TQString::fromUtf8(" - ") + caption();
  2036. }
  2037. return s;
  2038. }
  2039. TQPalette KApplication::createApplicationPalette()
  2040. {
  2041. KConfig *config = KGlobal::config();
  2042. KConfigGroupSaver saver( config, "General" );
  2043. return createApplicationPalette( config, KGlobalSettings::contrast() );
  2044. }
  2045. TQPalette KApplication::createApplicationPalette( KConfig *config, int contrast_ )
  2046. {
  2047. TQColor kde34Background( 239, 239, 239 );
  2048. TQColor kde34Blue( 103,141,178 );
  2049. TQColor kde34Button;
  2050. if ( TQPixmap::defaultDepth() > 8 )
  2051. kde34Button.setRgb( 221, 223, 228 );
  2052. else
  2053. kde34Button.setRgb( 220, 220, 220 );
  2054. TQColor kde34Link( 0, 0, 238 );
  2055. TQColor kde34VisitedLink( 82, 24, 139 );
  2056. TQColor background = config->readColorEntry( "background", &kde34Background );
  2057. TQColor foreground = config->readColorEntry( "foreground", tqblackptr );
  2058. TQColor button = config->readColorEntry( "buttonBackground", &kde34Button );
  2059. TQColor buttonText = config->readColorEntry( "buttonForeground", tqblackptr );
  2060. TQColor highlight = config->readColorEntry( "selectBackground", &kde34Blue );
  2061. TQColor highlightedText = config->readColorEntry( "selectForeground", tqwhiteptr );
  2062. TQColor base = config->readColorEntry( "windowBackground", tqwhiteptr );
  2063. TQColor baseText = config->readColorEntry( "windowForeground", tqblackptr );
  2064. TQColor link = config->readColorEntry( "linkColor", &kde34Link );
  2065. TQColor visitedLink = config->readColorEntry( "visitedLinkColor", &kde34VisitedLink );
  2066. int highlightVal, lowlightVal;
  2067. highlightVal = 100 + (2*contrast_+4)*16/10;
  2068. lowlightVal = 100 + (2*contrast_+4)*10;
  2069. TQColor disfg = foreground;
  2070. int h, s, v;
  2071. disfg.hsv( &h, &s, &v );
  2072. if (v > 128)
  2073. // dark bg, light fg - need a darker disabled fg
  2074. disfg = disfg.dark(lowlightVal);
  2075. else if (disfg != Qt::black)
  2076. // light bg, dark fg - need a lighter disabled fg - but only if !black
  2077. disfg = disfg.light(highlightVal);
  2078. else
  2079. // black fg - use darkgray disabled fg
  2080. disfg = Qt::darkGray;
  2081. TQColorGroup disabledgrp(disfg, background,
  2082. background.light(highlightVal),
  2083. background.dark(lowlightVal),
  2084. background.dark(120),
  2085. background.dark(120), base);
  2086. TQColorGroup colgrp(foreground, background, background.light(highlightVal),
  2087. background.dark(lowlightVal),
  2088. background.dark(120),
  2089. baseText, base);
  2090. int inlowlightVal = lowlightVal-25;
  2091. if(inlowlightVal < 120)
  2092. inlowlightVal = 120;
  2093. colgrp.setColor(TQColorGroup::Highlight, highlight);
  2094. colgrp.setColor(TQColorGroup::HighlightedText, highlightedText);
  2095. colgrp.setColor(TQColorGroup::Button, button);
  2096. colgrp.setColor(TQColorGroup::ButtonText, buttonText);
  2097. colgrp.setColor(TQColorGroup::Midlight, background.light(110));
  2098. colgrp.setColor(TQColorGroup::Link, link);
  2099. colgrp.setColor(TQColorGroup::LinkVisited, visitedLink);
  2100. disabledgrp.setColor(TQColorGroup::Button, button);
  2101. TQColor disbtntext = buttonText;
  2102. disbtntext.hsv( &h, &s, &v );
  2103. if (v > 128)
  2104. // dark button, light buttonText - need a darker disabled buttonText
  2105. disbtntext = disbtntext.dark(lowlightVal);
  2106. else if (disbtntext != Qt::black)
  2107. // light buttonText, dark button - need a lighter disabled buttonText - but only if !black
  2108. disbtntext = disbtntext.light(highlightVal);
  2109. else
  2110. // black button - use darkgray disabled buttonText
  2111. disbtntext = Qt::darkGray;
  2112. disabledgrp.setColor(TQColorGroup::ButtonText, disbtntext);
  2113. disabledgrp.setColor(TQColorGroup::Midlight, background.light(110));
  2114. disabledgrp.setColor(TQColorGroup::Highlight, highlight.dark(120));
  2115. disabledgrp.setColor(TQColorGroup::Link, link);
  2116. disabledgrp.setColor(TQColorGroup::LinkVisited, visitedLink);
  2117. return TQPalette(colgrp, disabledgrp, colgrp);
  2118. }
  2119. void KApplication::kdisplaySetPalette()
  2120. {
  2121. #ifdef Q_WS_MACX
  2122. //Can I have this on other platforms, please!? --Sam
  2123. {
  2124. KConfig *config = KGlobal::config();
  2125. KConfigGroupSaver saver( config, "General" );
  2126. bool do_not_set_palette = FALSE;
  2127. if(config->readBoolEntry("nopaletteChange", &do_not_set_palette))
  2128. return;
  2129. }
  2130. #endif
  2131. TQApplication::tqsetPalette( createApplicationPalette(), true);
  2132. emit kdisplayPaletteChanged();
  2133. emit appearanceChanged();
  2134. }
  2135. void KApplication::kdisplaySetFont()
  2136. {
  2137. TQApplication::tqsetFont(KGlobalSettings::generalFont(), true);
  2138. TQApplication::tqsetFont(KGlobalSettings::menuFont(), true, TQMENUBAR_OBJECT_NAME_STRING);
  2139. TQApplication::tqsetFont(KGlobalSettings::menuFont(), true, TQPOPUPMENU_OBJECT_NAME_STRING);
  2140. TQApplication::tqsetFont(KGlobalSettings::menuFont(), true, "KPopupTitle");
  2141. // "patch" standard TQStyleSheet to follow our fonts
  2142. TQStyleSheet* sheet = TQStyleSheet::defaultSheet();
  2143. sheet->item ("pre")->setFontFamily (KGlobalSettings::fixedFont().family());
  2144. sheet->item ("code")->setFontFamily (KGlobalSettings::fixedFont().family());
  2145. sheet->item ("tt")->setFontFamily (KGlobalSettings::fixedFont().family());
  2146. emit kdisplayFontChanged();
  2147. emit appearanceChanged();
  2148. }
  2149. void KApplication::kdisplaySetStyle()
  2150. {
  2151. if (useStyles)
  2152. {
  2153. applyGUIStyle();
  2154. emit kdisplayStyleChanged();
  2155. emit appearanceChanged();
  2156. }
  2157. }
  2158. void KApplication::propagateSettings(SettingsCategory arg)
  2159. {
  2160. KConfigBase* config = KGlobal::config();
  2161. KConfigGroupSaver saver( config, "KDE" );
  2162. #ifdef QT_HAVE_MAX_IMAGE_SIZE
  2163. TQSize maxImageSize(4096, 4096);
  2164. maxImageSize = config->readSizeEntry("MaxImageSize", &maxImageSize);
  2165. TQImage::setMaxImageSize(maxImageSize);
  2166. #endif
  2167. int num = config->readNumEntry("CursorBlinkRate", TQApplication::cursorFlashTime());
  2168. if ((num != 0) && (num < 200))
  2169. num = 200;
  2170. if (num > 2000)
  2171. num = 2000;
  2172. TQApplication::setCursorFlashTime(num);
  2173. num = config->readNumEntry("DoubleClickInterval", TQApplication::doubleClickInterval());
  2174. TQApplication::setDoubleClickInterval(num);
  2175. num = config->readNumEntry("StartDragTime", TQApplication::startDragTime());
  2176. TQApplication::setStartDragTime(num);
  2177. num = config->readNumEntry("StartDragDist", TQApplication::startDragDistance());
  2178. TQApplication::setStartDragDistance(num);
  2179. num = config->readNumEntry("WheelScrollLines", TQApplication::wheelScrollLines());
  2180. TQApplication::setWheelScrollLines(num);
  2181. bool b = config->readBoolEntry("EffectAnimateMenu", false);
  2182. TQApplication::setEffectEnabled( Qt::UI_AnimateMenu, b);
  2183. b = config->readBoolEntry("EffectFadeMenu", false);
  2184. TQApplication::setEffectEnabled( Qt::UI_FadeMenu, b);
  2185. b = config->readBoolEntry("EffectAnimateCombo", false);
  2186. TQApplication::setEffectEnabled( Qt::UI_AnimateCombo, b);
  2187. b = config->readBoolEntry("EffectAnimateTooltip", false);
  2188. TQApplication::setEffectEnabled( Qt::UI_AnimateTooltip, b);
  2189. b = config->readBoolEntry("EffectFadeTooltip", false);
  2190. TQApplication::setEffectEnabled( Qt::UI_FadeTooltip, b);
  2191. b = !config->readBoolEntry("EffectNoTooltip", false);
  2192. TQToolTip::setGloballyEnabled( b );
  2193. emit settingsChanged(arg);
  2194. }
  2195. void KApplication::installKDEPropertyMap()
  2196. {
  2197. #ifndef QT_NO_SQL
  2198. static bool installed = false;
  2199. if (installed) return;
  2200. installed = true;
  2201. /**
  2202. * If you are adding a widget that was missing please
  2203. * make sure to also add it to KConfigDialogManager's retrieveSettings()
  2204. * function.
  2205. * Thanks.
  2206. */
  2207. // TQSqlPropertyMap takes ownership of the new default map.
  2208. TQSqlPropertyMap *kdeMap = new TQSqlPropertyMap;
  2209. kdeMap->insert( "KColorButton", "color" );
  2210. kdeMap->insert( "KComboBox", "currentItem" );
  2211. kdeMap->insert( "KDatePicker", "date" );
  2212. kdeMap->insert( "KDateWidget", "date" );
  2213. kdeMap->insert( "KDateTimeWidget", "dateTime" );
  2214. kdeMap->insert( "KEditListBox", "items" );
  2215. kdeMap->insert( "KFontCombo", "family" );
  2216. kdeMap->insert( "KFontRequester", "font" );
  2217. kdeMap->insert( "KFontChooser", "font" );
  2218. kdeMap->insert( "KHistoryCombo", "currentItem" );
  2219. kdeMap->insert( "KListBox", "currentItem" );
  2220. kdeMap->insert( "KLineEdit", "text" );
  2221. kdeMap->insert( "KRestrictedLine", "text" );
  2222. kdeMap->insert( "KSqueezedTextLabel", "text" );
  2223. kdeMap->insert( "KTextBrowser", "source" );
  2224. kdeMap->insert( "KTextEdit", "text" );
  2225. kdeMap->insert( "KURLRequester", "url" );
  2226. kdeMap->insert( "KPasswordEdit", "password" );
  2227. kdeMap->insert( "KIntNumInput", "value" );
  2228. kdeMap->insert( "KIntSpinBox", "value" );
  2229. kdeMap->insert( "KDoubleNumInput", "value" );
  2230. // Temp til fixed in QT then enable ifdef with the correct version num
  2231. kdeMap->insert( TQGROUPBOX_OBJECT_NAME_STRING, "checked" );
  2232. kdeMap->insert( TQTABWIDGET_OBJECT_NAME_STRING, "currentPage" );
  2233. TQSqlPropertyMap::installDefaultMap( kdeMap );
  2234. #endif
  2235. }
  2236. void KApplication::invokeHelp( const TQString& anchor,
  2237. const TQString& _appname) const
  2238. {
  2239. return invokeHelp( anchor, _appname, "" );
  2240. }
  2241. #ifndef Q_WS_WIN
  2242. // for win32 we're using simple help tools like Qt Assistant,
  2243. // see kapplication_win.cpp
  2244. void KApplication::invokeHelp( const TQString& anchor,
  2245. const TQString& _appname,
  2246. const TQCString& startup_id ) const
  2247. {
  2248. TQString url;
  2249. TQString appname;
  2250. if (_appname.isEmpty())
  2251. appname = name();
  2252. else
  2253. appname = _appname;
  2254. if (!anchor.isEmpty())
  2255. url = TQString("help:/%1?anchor=%2").arg(appname).arg(anchor);
  2256. else
  2257. url = TQString("help:/%1/index.html").arg(appname);
  2258. TQString error;
  2259. if ( !dcopClient()->isApplicationRegistered("khelpcenter") )
  2260. {
  2261. if (startServiceByDesktopName("khelpcenter", url, &error, 0, 0, startup_id, false))
  2262. {
  2263. if (Tty != kapp->type())
  2264. TQMessageBox::critical(kapp->mainWidget(), i18n("Could not Launch Help Center"),
  2265. i18n("Could not launch the KDE Help Center:\n\n%1").arg(error), i18n("&OK"));
  2266. else
  2267. kdWarning() << "Could not launch help:\n" << error << endl;
  2268. return;
  2269. }
  2270. }
  2271. else
  2272. DCOPRef( "khelpcenter", "KHelpCenterIface" ).send( "openUrl", url, startup_id );
  2273. }
  2274. #endif
  2275. void KApplication::invokeHTMLHelp( const TQString& _filename, const TQString& topic ) const
  2276. {
  2277. kdWarning() << "invoking HTML help is deprecated! use docbook and invokeHelp!\n";
  2278. TQString filename;
  2279. if( _filename.isEmpty() )
  2280. filename = TQString(name()) + "/index.html";
  2281. else
  2282. filename = _filename;
  2283. TQString url;
  2284. if (!topic.isEmpty())
  2285. url = TQString("help:/%1#%2").arg(filename).arg(topic);
  2286. else
  2287. url = TQString("help:/%1").arg(filename);
  2288. TQString error;
  2289. if ( !dcopClient()->isApplicationRegistered("khelpcenter") )
  2290. {
  2291. if (startServiceByDesktopName("khelpcenter", url, &error, 0, 0, "", false))
  2292. {
  2293. if (Tty != kapp->type())
  2294. TQMessageBox::critical(kapp->mainWidget(), i18n("Could not Launch Help Center"),
  2295. i18n("Could not launch the KDE Help Center:\n\n%1").arg(error), i18n("&OK"));
  2296. else
  2297. kdWarning() << "Could not launch help:\n" << error << endl;
  2298. return;
  2299. }
  2300. }
  2301. else
  2302. DCOPRef( "khelpcenter", "KHelpCenterIface" ).send( "openUrl", url );
  2303. }
  2304. void KApplication::invokeMailer(const TQString &address, const TQString &subject)
  2305. {
  2306. return invokeMailer(address,subject,"");
  2307. }
  2308. void KApplication::invokeMailer(const TQString &address, const TQString &subject, const TQCString& startup_id)
  2309. {
  2310. invokeMailer(address, TQString::null, TQString::null, subject, TQString::null, TQString::null,
  2311. TQStringList(), startup_id );
  2312. }
  2313. void KApplication::invokeMailer(const KURL &mailtoURL)
  2314. {
  2315. return invokeMailer( mailtoURL, "" );
  2316. }
  2317. void KApplication::invokeMailer(const KURL &mailtoURL, const TQCString& startup_id )
  2318. {
  2319. return invokeMailer( mailtoURL, startup_id, false);
  2320. }
  2321. void KApplication::invokeMailer(const KURL &mailtoURL, const TQCString& startup_id, bool allowAttachments )
  2322. {
  2323. TQString address = KURL::decode_string(mailtoURL.path()), subject, cc, bcc, body;
  2324. TQStringList queries = TQStringList::split('&', mailtoURL.query().mid(1));
  2325. TQStringList attachURLs;
  2326. for (TQStringList::Iterator it = queries.begin(); it != queries.end(); ++it)
  2327. {
  2328. TQString q = (*it).lower();
  2329. if (q.startsWith("subject="))
  2330. subject = KURL::decode_string((*it).mid(8));
  2331. else
  2332. if (q.startsWith("cc="))
  2333. cc = cc.isEmpty()? KURL::decode_string((*it).mid(3)): cc + ',' + KURL::decode_string((*it).mid(3));
  2334. else
  2335. if (q.startsWith("bcc="))
  2336. bcc = bcc.isEmpty()? KURL::decode_string((*it).mid(4)): bcc + ',' + KURL::decode_string((*it).mid(4));
  2337. else
  2338. if (q.startsWith("body="))
  2339. body = KURL::decode_string((*it).mid(5));
  2340. else
  2341. if (allowAttachments && q.startsWith("attach="))
  2342. attachURLs.push_back(KURL::decode_string((*it).mid(7)));
  2343. else
  2344. if (allowAttachments && q.startsWith("attachment="))
  2345. attachURLs.push_back(KURL::decode_string((*it).mid(11)));
  2346. else
  2347. if (q.startsWith("to="))
  2348. address = address.isEmpty()? KURL::decode_string((*it).mid(3)): address + ',' + KURL::decode_string((*it).mid(3));
  2349. }
  2350. invokeMailer( address, cc, bcc, subject, body, TQString::null, attachURLs, startup_id );
  2351. }
  2352. void KApplication::invokeMailer(const TQString &to, const TQString &cc, const TQString &bcc,
  2353. const TQString &subject, const TQString &body,
  2354. const TQString & messageFile, const TQStringList &attachURLs)
  2355. {
  2356. return invokeMailer(to,cc,bcc,subject,body,messageFile,attachURLs,"");
  2357. }
  2358. #ifndef Q_WS_WIN
  2359. // on win32, for invoking browser we're using win32 API
  2360. // see kapplication_win.cpp
  2361. static TQStringList splitEmailAddressList( const TQString & aStr )
  2362. {
  2363. // This is a copy of KPIM::splitEmailAddrList().
  2364. // Features:
  2365. // - always ignores quoted characters
  2366. // - ignores everything (including parentheses and commas)
  2367. // inside quoted strings
  2368. // - supports nested comments
  2369. // - ignores everything (including double quotes and commas)
  2370. // inside comments
  2371. TQStringList list;
  2372. if (aStr.isEmpty())
  2373. return list;
  2374. TQString addr;
  2375. uint addrstart = 0;
  2376. int commentlevel = 0;
  2377. bool insidequote = false;
  2378. for (uint index=0; index<aStr.length(); index++) {
  2379. // the following conversion to latin1 is o.k. because
  2380. // we can safely ignore all non-latin1 characters
  2381. switch (aStr[index].latin1()) {
  2382. case '"' : // start or end of quoted string
  2383. if (commentlevel == 0)
  2384. insidequote = !insidequote;
  2385. break;
  2386. case '(' : // start of comment
  2387. if (!insidequote)
  2388. commentlevel++;
  2389. break;
  2390. case ')' : // end of comment
  2391. if (!insidequote) {
  2392. if (commentlevel > 0)
  2393. commentlevel--;
  2394. else {
  2395. //kdDebug() << "Error in address splitting: Unmatched ')'"
  2396. // << endl;
  2397. return list;
  2398. }
  2399. }
  2400. break;
  2401. case '\\' : // quoted character
  2402. index++; // ignore the quoted character
  2403. break;
  2404. case ',' :
  2405. if (!insidequote && (commentlevel == 0)) {
  2406. addr = aStr.mid(addrstart, index-addrstart);
  2407. if (!addr.isEmpty())
  2408. list += addr.simplifyWhiteSpace();
  2409. addrstart = index+1;
  2410. }
  2411. break;
  2412. }
  2413. }
  2414. // append the last address to the list
  2415. if (!insidequote && (commentlevel == 0)) {
  2416. addr = aStr.mid(addrstart, aStr.length()-addrstart);
  2417. if (!addr.isEmpty())
  2418. list += addr.simplifyWhiteSpace();
  2419. }
  2420. //else
  2421. // kdDebug() << "Error in address splitting: "
  2422. // << "Unexpected end of address list"
  2423. // << endl;
  2424. return list;
  2425. }
  2426. void KApplication::invokeMailer(const TQString &_to, const TQString &_cc, const TQString &_bcc,
  2427. const TQString &subject, const TQString &body,
  2428. const TQString & /*messageFile TODO*/, const TQStringList &attachURLs,
  2429. const TQCString& startup_id )
  2430. {
  2431. KConfig config("emaildefaults");
  2432. config.setGroup("Defaults");
  2433. TQString group = config.readEntry("Profile","Default");
  2434. config.setGroup( TQString("PROFILE_%1").arg(group) );
  2435. TQString command = config.readPathEntry("EmailClient");
  2436. TQString to, cc, bcc;
  2437. if (command.isEmpty() || command == TQString::tqfromLatin1("kmail")
  2438. || command.endsWith("/kmail"))
  2439. {
  2440. command = TQString::tqfromLatin1("kmail --composer -s %s -c %c -b %b --body %B --attach %A -- %t");
  2441. if ( !_to.isEmpty() )
  2442. {
  2443. // put the whole address lists into RFC2047 encoded blobs; technically
  2444. // this isn't correct, but KMail understands it nonetheless
  2445. to = TQString( "=?utf8?b?%1?=" )
  2446. .arg( QString(KCodecs::base64Encode( _to.utf8(), false )) );
  2447. }
  2448. if ( !_cc.isEmpty() )
  2449. cc = TQString( "=?utf8?b?%1?=" )
  2450. .arg( QString(KCodecs::base64Encode( _cc.utf8(), false )) );
  2451. if ( !_bcc.isEmpty() )
  2452. bcc = TQString( "=?utf8?b?%1?=" )
  2453. .arg( QString(KCodecs::base64Encode( _bcc.utf8(), false )) );
  2454. } else {
  2455. to = _to;
  2456. cc = _cc;
  2457. bcc = _bcc;
  2458. if( !command.contains( '%' ))
  2459. command += " %u";
  2460. }
  2461. if (config.readBoolEntry("TerminalClient", false))
  2462. {
  2463. KConfigGroup confGroup( KGlobal::config(), "General" );
  2464. TQString preferredTerminal = confGroup.readPathEntry("TerminalApplication", "konsole");
  2465. command = preferredTerminal + " -e " + command;
  2466. }
  2467. TQStringList cmdTokens = KShell::splitArgs(command);
  2468. TQString cmd = cmdTokens[0];
  2469. cmdTokens.remove(cmdTokens.begin());
  2470. KURL url;
  2471. TQStringList qry;
  2472. if (!to.isEmpty())
  2473. {
  2474. TQStringList tos = splitEmailAddressList( to );
  2475. url.setPath( tos.first() );
  2476. tos.remove( tos.begin() );
  2477. for (TQStringList::ConstIterator it = tos.begin(); it != tos.end(); ++it)
  2478. qry.append( "to=" + KURL::encode_string( *it ) );
  2479. }
  2480. const TQStringList ccs = splitEmailAddressList( cc );
  2481. for (TQStringList::ConstIterator it = ccs.begin(); it != ccs.end(); ++it)
  2482. qry.append( "cc=" + KURL::encode_string( *it ) );
  2483. const TQStringList bccs = splitEmailAddressList( bcc );
  2484. for (TQStringList::ConstIterator it = bccs.begin(); it != bccs.end(); ++it)
  2485. qry.append( "bcc=" + KURL::encode_string( *it ) );
  2486. for (TQStringList::ConstIterator it = attachURLs.begin(); it != attachURLs.end(); ++it)
  2487. qry.append( "attach=" + KURL::encode_string( *it ) );
  2488. if (!subject.isEmpty())
  2489. qry.append( "subject=" + KURL::encode_string( subject ) );
  2490. if (!body.isEmpty())
  2491. qry.append( "body=" + KURL::encode_string( body ) );
  2492. url.setQuery( qry.join( "&" ) );
  2493. if ( ! (to.isEmpty() && qry.isEmpty()) )
  2494. url.setProtocol("mailto");
  2495. TQMap<TQChar, TQString> keyMap;
  2496. keyMap.insert('t', to);
  2497. keyMap.insert('s', subject);
  2498. keyMap.insert('c', cc);
  2499. keyMap.insert('b', bcc);
  2500. keyMap.insert('B', body);
  2501. keyMap.insert('u', url.url());
  2502. TQString attachlist = attachURLs.join(",");
  2503. attachlist.prepend('\'');
  2504. attachlist.append('\'');
  2505. keyMap.insert('A', attachlist);
  2506. for (TQStringList::Iterator it = cmdTokens.begin(); it != cmdTokens.end(); )
  2507. {
  2508. if (*it == "%A")
  2509. {
  2510. if (it == cmdTokens.begin()) // better safe than sorry ...
  2511. continue;
  2512. TQStringList::ConstIterator urlit = attachURLs.begin();
  2513. TQStringList::ConstIterator urlend = attachURLs.end();
  2514. if ( urlit != urlend )
  2515. {
  2516. TQStringList::Iterator previt = it;
  2517. --previt;
  2518. *it = *urlit;
  2519. ++it;
  2520. while ( ++urlit != urlend )
  2521. {
  2522. cmdTokens.insert( it, *previt );
  2523. cmdTokens.insert( it, *urlit );
  2524. }
  2525. } else {
  2526. --it;
  2527. it = cmdTokens.remove( cmdTokens.remove( it ) );
  2528. }
  2529. } else {
  2530. *it = KMacroExpander::expandMacros(*it, keyMap);
  2531. ++it;
  2532. }
  2533. }
  2534. TQString error;
  2535. // TODO this should check if cmd has a .desktop file, and use data from it, together
  2536. // with sending more ASN data
  2537. if (kdeinitExec(cmd, cmdTokens, &error, NULL, startup_id ))
  2538. if (Tty != kapp->type())
  2539. TQMessageBox::critical(kapp->mainWidget(), i18n("Could not Launch Mail Client"),
  2540. i18n("Could not launch the mail client:\n\n%1").arg(error), i18n("&OK"));
  2541. else
  2542. kdWarning() << "Could not launch mail client:\n" << error << endl;
  2543. }
  2544. #endif
  2545. void KApplication::invokeBrowser( const TQString &url )
  2546. {
  2547. return invokeBrowser( url, "" );
  2548. }
  2549. #ifndef Q_WS_WIN
  2550. // on win32, for invoking browser we're using win32 API
  2551. // see kapplication_win.cpp
  2552. void KApplication::invokeBrowser( const TQString &url, const TQCString& startup_id )
  2553. {
  2554. TQString error;
  2555. if (startServiceByDesktopName("kfmclient", url, &error, 0, 0, startup_id, false))
  2556. {
  2557. if (Tty != kapp->type())
  2558. TQMessageBox::critical(kapp->mainWidget(), i18n("Could not Launch Browser"),
  2559. i18n("Could not launch the browser:\n\n%1").arg(error), i18n("&OK"));
  2560. else
  2561. kdWarning() << "Could not launch browser:\n" << error << endl;
  2562. return;
  2563. }
  2564. }
  2565. #endif
  2566. void KApplication::cut()
  2567. {
  2568. invokeEditSlot( TQT_SLOT( cut() ) );
  2569. }
  2570. void KApplication::copy()
  2571. {
  2572. invokeEditSlot( TQT_SLOT( copy() ) );
  2573. }
  2574. void KApplication::paste()
  2575. {
  2576. invokeEditSlot( TQT_SLOT( paste() ) );
  2577. }
  2578. void KApplication::clear()
  2579. {
  2580. invokeEditSlot( TQT_SLOT( clear() ) );
  2581. }
  2582. void KApplication::selectAll()
  2583. {
  2584. invokeEditSlot( TQT_SLOT( selectAll() ) );
  2585. }
  2586. void KApplication::broadcastKeyCode(unsigned int keyCode)
  2587. {
  2588. emit coreFakeKeyPress(keyCode);
  2589. }
  2590. TQCString
  2591. KApplication::launcher()
  2592. {
  2593. return "klauncher";
  2594. }
  2595. static int
  2596. startServiceInternal( const TQCString &function,
  2597. const TQString& _name, const TQStringList &URLs,
  2598. TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait )
  2599. {
  2600. struct serviceResult
  2601. {
  2602. int result;
  2603. TQCString dcopName;
  2604. TQString error;
  2605. pid_t pid;
  2606. };
  2607. // Register app as able to send DCOP messages
  2608. DCOPClient *dcopClient;
  2609. if (kapp)
  2610. dcopClient = kapp->dcopClient();
  2611. else
  2612. dcopClient = new DCOPClient;
  2613. if (!dcopClient->isAttached())
  2614. {
  2615. if (!dcopClient->attach())
  2616. {
  2617. if (error)
  2618. *error = i18n("Could not register with DCOP.\n");
  2619. if (!kapp)
  2620. delete dcopClient;
  2621. return -1;
  2622. }
  2623. }
  2624. TQByteArray params;
  2625. TQDataStream stream(params, IO_WriteOnly);
  2626. stream << _name << URLs;
  2627. TQCString replyType;
  2628. TQByteArray replyData;
  2629. TQCString _launcher = KApplication::launcher();
  2630. TQValueList<TQCString> envs;
  2631. #ifdef Q_WS_X11
  2632. if (qt_xdisplay()) {
  2633. TQCString dpystring(XDisplayString(qt_xdisplay()));
  2634. envs.append( TQCString("DISPLAY=") + dpystring );
  2635. } else if( getenv( "DISPLAY" )) {
  2636. TQCString dpystring( getenv( "DISPLAY" ));
  2637. envs.append( TQCString("DISPLAY=") + dpystring );
  2638. }
  2639. #endif
  2640. stream << envs;
  2641. #if defined Q_WS_X11
  2642. // make sure there is id, so that user timestamp exists
  2643. stream << ( startup_id.isEmpty() ? KStartupInfo::createNewStartupId() : startup_id );
  2644. #endif
  2645. if( function.left( 12 ) != "kdeinit_exec" )
  2646. stream << noWait;
  2647. if (!dcopClient->call(_launcher, _launcher,
  2648. function, params, replyType, replyData))
  2649. {
  2650. if (error)
  2651. *error = i18n("KLauncher could not be reached via DCOP.\n");
  2652. if (!kapp)
  2653. delete dcopClient;
  2654. return -1;
  2655. }
  2656. if (!kapp)
  2657. delete dcopClient;
  2658. if (noWait)
  2659. return 0;
  2660. TQDataStream stream2(replyData, IO_ReadOnly);
  2661. serviceResult result;
  2662. stream2 >> result.result >> result.dcopName >> result.error >> result.pid;
  2663. if (dcopService)
  2664. *dcopService = result.dcopName;
  2665. if (error)
  2666. *error = result.error;
  2667. if (pid)
  2668. *pid = result.pid;
  2669. return result.result;
  2670. }
  2671. int
  2672. KApplication::startServiceByName( const TQString& _name, const TQString &URL,
  2673. TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait )
  2674. {
  2675. TQStringList URLs;
  2676. if (!URL.isEmpty())
  2677. URLs.append(URL);
  2678. return startServiceInternal(
  2679. "start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)",
  2680. _name, URLs, error, dcopService, pid, startup_id, noWait);
  2681. }
  2682. int
  2683. KApplication::startServiceByName( const TQString& _name, const TQStringList &URLs,
  2684. TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait )
  2685. {
  2686. return startServiceInternal(
  2687. "start_service_by_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)",
  2688. _name, URLs, error, dcopService, pid, startup_id, noWait);
  2689. }
  2690. int
  2691. KApplication::startServiceByDesktopPath( const TQString& _name, const TQString &URL,
  2692. TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait )
  2693. {
  2694. TQStringList URLs;
  2695. if (!URL.isEmpty())
  2696. URLs.append(URL);
  2697. return startServiceInternal(
  2698. "start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)",
  2699. _name, URLs, error, dcopService, pid, startup_id, noWait);
  2700. }
  2701. int
  2702. KApplication::startServiceByDesktopPath( const TQString& _name, const TQStringList &URLs,
  2703. TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait )
  2704. {
  2705. return startServiceInternal(
  2706. "start_service_by_desktop_path(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)",
  2707. _name, URLs, error, dcopService, pid, startup_id, noWait);
  2708. }
  2709. int
  2710. KApplication::startServiceByDesktopName( const TQString& _name, const TQString &URL,
  2711. TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait )
  2712. {
  2713. TQStringList URLs;
  2714. if (!URL.isEmpty())
  2715. URLs.append(URL);
  2716. return startServiceInternal(
  2717. "start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)",
  2718. _name, URLs, error, dcopService, pid, startup_id, noWait);
  2719. }
  2720. int
  2721. KApplication::startServiceByDesktopName( const TQString& _name, const TQStringList &URLs,
  2722. TQString *error, TQCString *dcopService, int *pid, const TQCString& startup_id, bool noWait )
  2723. {
  2724. return startServiceInternal(
  2725. "start_service_by_desktop_name(TQString,TQStringList,TQValueList<TQCString>,TQCString,bool)",
  2726. _name, URLs, error, dcopService, pid, startup_id, noWait);
  2727. }
  2728. int
  2729. KApplication::kdeinitExec( const TQString& name, const TQStringList &args,
  2730. TQString *error, int *pid )
  2731. {
  2732. return kdeinitExec( name, args, error, pid, "" );
  2733. }
  2734. int
  2735. KApplication::kdeinitExec( const TQString& name, const TQStringList &args,
  2736. TQString *error, int *pid, const TQCString& startup_id )
  2737. {
  2738. return startServiceInternal("kdeinit_exec(TQString,TQStringList,TQValueList<TQCString>,TQCString)",
  2739. name, args, error, 0, pid, startup_id, false);
  2740. }
  2741. int
  2742. KApplication::kdeinitExecWait( const TQString& name, const TQStringList &args,
  2743. TQString *error, int *pid )
  2744. {
  2745. return kdeinitExecWait( name, args, error, pid, "" );
  2746. }
  2747. int
  2748. KApplication::kdeinitExecWait( const TQString& name, const TQStringList &args,
  2749. TQString *error, int *pid, const TQCString& startup_id )
  2750. {
  2751. return startServiceInternal("kdeinit_exec_wait(TQString,TQStringList,TQValueList<TQCString>,TQCString)",
  2752. name, args, error, 0, pid, startup_id, false);
  2753. }
  2754. TQString KApplication::tempSaveName( const TQString& pFilename ) const
  2755. {
  2756. TQString aFilename;
  2757. if( TQDir::isRelativePath(pFilename) )
  2758. {
  2759. kdWarning(101) << "Relative filename passed to KApplication::tempSaveName" << endl;
  2760. aFilename = TQFileInfo( TQDir( "." ), pFilename ).absFilePath();
  2761. }
  2762. else
  2763. aFilename = pFilename;
  2764. TQDir aAutosaveDir( TQDir::homeDirPath() + "/autosave/" );
  2765. if( !aAutosaveDir.exists() )
  2766. {
  2767. if( !aAutosaveDir.mkdir( aAutosaveDir.absPath() ) )
  2768. {
  2769. // Last chance: use temp dir
  2770. aAutosaveDir.setPath( KGlobal::dirs()->saveLocation("tmp") );
  2771. }
  2772. }
  2773. aFilename.replace( "/", "\\!" ).prepend( "#" ).append( "#" ).prepend( "/" ).prepend( aAutosaveDir.absPath() );
  2774. return aFilename;
  2775. }
  2776. TQString KApplication::checkRecoverFile( const TQString& pFilename,
  2777. bool& bRecover ) const
  2778. {
  2779. TQString aFilename;
  2780. if( TQDir::isRelativePath(pFilename) )
  2781. {
  2782. kdWarning(101) << "Relative filename passed to KApplication::tempSaveName" << endl;
  2783. aFilename = TQFileInfo( TQDir( "." ), pFilename ).absFilePath();
  2784. }
  2785. else
  2786. aFilename = pFilename;
  2787. TQDir aAutosaveDir( TQDir::homeDirPath() + "/autosave/" );
  2788. if( !aAutosaveDir.exists() )
  2789. {
  2790. if( !aAutosaveDir.mkdir( aAutosaveDir.absPath() ) )
  2791. {
  2792. // Last chance: use temp dir
  2793. aAutosaveDir.setPath( KGlobal::dirs()->saveLocation("tmp") );
  2794. }
  2795. }
  2796. aFilename.replace( "/", "\\!" ).prepend( "#" ).append( "#" ).prepend( "/" ).prepend( aAutosaveDir.absPath() );
  2797. if( TQFile( aFilename ).exists() )
  2798. {
  2799. bRecover = true;
  2800. return aFilename;
  2801. }
  2802. else
  2803. {
  2804. bRecover = false;
  2805. return pFilename;
  2806. }
  2807. }
  2808. bool checkAccess(const TQString& pathname, int mode)
  2809. {
  2810. int accessOK = access( TQFile::encodeName(pathname), mode );
  2811. if ( accessOK == 0 )
  2812. return true; // OK, I can really access the file
  2813. // else
  2814. // if we want to write the file would be created. Check, if the
  2815. // user may write to the directory to create the file.
  2816. if ( (mode & W_OK) == 0 )
  2817. return false; // Check for write access is not part of mode => bail out
  2818. if (!access( TQFile::encodeName(pathname), F_OK)) // if it already exists
  2819. return false;
  2820. //strip the filename (everything until '/' from the end
  2821. TQString dirName(pathname);
  2822. int pos = dirName.findRev('/');
  2823. if ( pos == -1 )
  2824. return false; // No path in argument. This is evil, we won't allow this
  2825. else if ( pos == 0 ) // don't turn e.g. /root into an empty string
  2826. pos = 1;
  2827. dirName.truncate(pos); // strip everything starting from the last '/'
  2828. accessOK = access( TQFile::encodeName(dirName), W_OK );
  2829. // -?- Can I write to the accessed diretory
  2830. if ( accessOK == 0 )
  2831. return true; // Yes
  2832. else
  2833. return false; // No
  2834. }
  2835. void KApplication::setTopWidget( TQWidget *topWidget )
  2836. {
  2837. if( !topWidget )
  2838. return;
  2839. // set the specified caption
  2840. if ( !topWidget->inherits("KMainWindow") ) { // KMainWindow does this already for us
  2841. topWidget->setCaption( caption() );
  2842. }
  2843. // set the specified icons
  2844. topWidget->setIcon( icon() ); //standard X11
  2845. #if defined Q_WS_X11
  2846. //#ifdef Q_WS_X11 // FIXME(E): Implement for Qt/Embedded
  2847. KWin::setIcons(topWidget->winId(), icon(), miniIcon() ); // NET_WM hints for KWin
  2848. // set the app startup notification window property
  2849. KStartupInfo::setWindowStartupId( topWidget->winId(), startupId());
  2850. #endif
  2851. }
  2852. TQCString KApplication::startupId() const
  2853. {
  2854. return d->startup_id;
  2855. }
  2856. void KApplication::setStartupId( const TQCString& startup_id )
  2857. {
  2858. if( startup_id == d->startup_id )
  2859. return;
  2860. #if defined Q_WS_X11
  2861. KStartupInfo::handleAutoAppStartedSending(); // finish old startup notification if needed
  2862. #endif
  2863. if( startup_id.isEmpty())
  2864. d->startup_id = "0";
  2865. else
  2866. {
  2867. d->startup_id = startup_id;
  2868. #if defined Q_WS_X11
  2869. KStartupInfoId id;
  2870. id.initId( startup_id );
  2871. long timestamp = id.timestamp();
  2872. if( timestamp != 0 )
  2873. updateUserTimestamp( timestamp );
  2874. #endif
  2875. }
  2876. }
  2877. // read the startup notification env variable, save it and unset it in order
  2878. // not to propagate it to processes started from this app
  2879. void KApplication::read_app_startup_id()
  2880. {
  2881. #if defined Q_WS_X11
  2882. KStartupInfoId id = KStartupInfo::currentStartupIdEnv();
  2883. KStartupInfo::resetStartupEnv();
  2884. d->startup_id = id.id();
  2885. #endif
  2886. }
  2887. int KApplication::random()
  2888. {
  2889. static bool init = false;
  2890. if (!init)
  2891. {
  2892. unsigned int seed;
  2893. init = true;
  2894. int fd = open("/dev/urandom", O_RDONLY);
  2895. if (fd < 0 || ::read(fd, &seed, sizeof(seed)) != sizeof(seed))
  2896. {
  2897. // No /dev/urandom... try something else.
  2898. srand(getpid());
  2899. seed = rand()+time(0);
  2900. }
  2901. if (fd >= 0) close(fd);
  2902. srand(seed);
  2903. }
  2904. return rand();
  2905. }
  2906. TQString KApplication::randomString(int length)
  2907. {
  2908. if (length <=0 ) return TQString::null;
  2909. TQString str; str.setLength( length );
  2910. int i = 0;
  2911. while (length--)
  2912. {
  2913. int r=random() % 62;
  2914. r+=48;
  2915. if (r>57) r+=7;
  2916. if (r>90) r+=6;
  2917. str[i++] = char(r);
  2918. // so what if I work backwards?
  2919. }
  2920. return str;
  2921. }
  2922. bool KApplication::authorize(const TQString &genericAction)
  2923. {
  2924. if (!d->actionRestrictions)
  2925. return true;
  2926. KConfig *config = KGlobal::config();
  2927. KConfigGroupSaver saver( config, "KDE Action Restrictions" );
  2928. return config->readBoolEntry(genericAction, true);
  2929. }
  2930. bool KApplication::authorizeKAction(const char *action)
  2931. {
  2932. if (!d->actionRestrictions || !action)
  2933. return true;
  2934. static const TQString &action_prefix = KGlobal::staticQString( "action/" );
  2935. return authorize(action_prefix + action);
  2936. }
  2937. bool KApplication::authorizeControlModule(const TQString &menuId)
  2938. {
  2939. if (menuId.isEmpty() || kde_kiosk_exception)
  2940. return true;
  2941. KConfig *config = KGlobal::config();
  2942. KConfigGroupSaver saver( config, "KDE Control Module Restrictions" );
  2943. return config->readBoolEntry(menuId, true);
  2944. }
  2945. TQStringList KApplication::authorizeControlModules(const TQStringList &menuIds)
  2946. {
  2947. KConfig *config = KGlobal::config();
  2948. KConfigGroupSaver saver( config, "KDE Control Module Restrictions" );
  2949. TQStringList result;
  2950. for(TQStringList::ConstIterator it = menuIds.begin();
  2951. it != menuIds.end(); ++it)
  2952. {
  2953. if (config->readBoolEntry(*it, true))
  2954. result.append(*it);
  2955. }
  2956. return result;
  2957. }
  2958. void KApplication::initUrlActionRestrictions()
  2959. {
  2960. d->urlActionRestrictions.setAutoDelete(true);
  2961. d->urlActionRestrictions.clear();
  2962. d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
  2963. ("open", TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, true));
  2964. d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
  2965. ("list", TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, true));
  2966. // TEST:
  2967. // d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
  2968. // ("list", TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, false));
  2969. // d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
  2970. // ("list", TQString::null, TQString::null, TQString::null, "file", TQString::null, TQDir::homeDirPath(), true));
  2971. d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
  2972. ("link", TQString::null, TQString::null, TQString::null, ":internet", TQString::null, TQString::null, true));
  2973. d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
  2974. ("redirect", TQString::null, TQString::null, TQString::null, ":internet", TQString::null, TQString::null, true));
  2975. // We allow redirections to file: but not from internet protocols, redirecting to file:
  2976. // is very popular among io-slaves and we don't want to break them
  2977. d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
  2978. ("redirect", TQString::null, TQString::null, TQString::null, "file", TQString::null, TQString::null, true));
  2979. d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
  2980. ("redirect", ":internet", TQString::null, TQString::null, "file", TQString::null, TQString::null, false));
  2981. // local protocols may redirect everywhere
  2982. d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
  2983. ("redirect", ":local", TQString::null, TQString::null, TQString::null, TQString::null, TQString::null, true));
  2984. // Anyone may redirect to about:
  2985. d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
  2986. ("redirect", TQString::null, TQString::null, TQString::null, "about", TQString::null, TQString::null, true));
  2987. // Anyone may redirect to itself, cq. within it's own group
  2988. d->urlActionRestrictions.append( new KApplicationPrivate::URLActionRule
  2989. ("redirect", TQString::null, TQString::null, TQString::null, "=", TQString::null, TQString::null, true));
  2990. KConfig *config = KGlobal::config();
  2991. KConfigGroupSaver saver( config, "KDE URL Restrictions" );
  2992. int count = config->readNumEntry("rule_count");
  2993. TQString keyFormat = TQString("rule_%1");
  2994. for(int i = 1; i <= count; i++)
  2995. {
  2996. TQString key = keyFormat.arg(i);
  2997. TQStringList rule = config->readListEntry(key);
  2998. if (rule.count() != 8)
  2999. continue;
  3000. TQString action = rule[0];
  3001. TQString refProt = rule[1];
  3002. TQString refHost = rule[2];
  3003. TQString refPath = rule[3];
  3004. TQString urlProt = rule[4];
  3005. TQString urlHost = rule[5];
  3006. TQString urlPath = rule[6];
  3007. TQString strEnabled = rule[7].lower();
  3008. bool bEnabled = (strEnabled == "true");
  3009. if (refPath.startsWith("$HOME"))
  3010. refPath.replace(0, 5, TQDir::homeDirPath());
  3011. else if (refPath.startsWith("~"))
  3012. refPath.replace(0, 1, TQDir::homeDirPath());
  3013. if (urlPath.startsWith("$HOME"))
  3014. urlPath.replace(0, 5, TQDir::homeDirPath());
  3015. else if (urlPath.startsWith("~"))
  3016. urlPath.replace(0, 1, TQDir::homeDirPath());
  3017. if (refPath.startsWith("$TMP"))
  3018. refPath.replace(0, 4, KGlobal::dirs()->saveLocation("tmp"));
  3019. if (urlPath.startsWith("$TMP"))
  3020. urlPath.replace(0, 4, KGlobal::dirs()->saveLocation("tmp"));
  3021. d->urlActionRestrictions.append(new KApplicationPrivate::URLActionRule
  3022. ( action, refProt, refHost, refPath, urlProt, urlHost, urlPath, bEnabled));
  3023. }
  3024. }
  3025. void KApplication::allowURLAction(const TQString &action, const KURL &_baseURL, const KURL &_destURL)
  3026. {
  3027. if (authorizeURLAction(action, _baseURL, _destURL))
  3028. return;
  3029. d->urlActionRestrictions.append(new KApplicationPrivate::URLActionRule
  3030. ( action, _baseURL.protocol(), _baseURL.host(), _baseURL.path(-1),
  3031. _destURL.protocol(), _destURL.host(), _destURL.path(-1), true));
  3032. }
  3033. bool KApplication::authorizeURLAction(const TQString &action, const KURL &_baseURL, const KURL &_destURL)
  3034. {
  3035. if (_destURL.isEmpty())
  3036. return true;
  3037. bool result = false;
  3038. if (d->urlActionRestrictions.isEmpty())
  3039. initUrlActionRestrictions();
  3040. KURL baseURL(_baseURL);
  3041. baseURL.setPath(TQDir::cleanDirPath(baseURL.path()));
  3042. TQString baseClass = KProtocolInfo::protocolClass(baseURL.protocol());
  3043. KURL destURL(_destURL);
  3044. destURL.setPath(TQDir::cleanDirPath(destURL.path()));
  3045. TQString destClass = KProtocolInfo::protocolClass(destURL.protocol());
  3046. for(KApplicationPrivate::URLActionRule *rule = d->urlActionRestrictions.first();
  3047. rule; rule = d->urlActionRestrictions.next())
  3048. {
  3049. if ((result != rule->permission) && // No need to check if it doesn't make a difference
  3050. (action == rule->action) &&
  3051. rule->baseMatch(baseURL, baseClass) &&
  3052. rule->destMatch(destURL, destClass, baseURL, baseClass))
  3053. {
  3054. result = rule->permission;
  3055. }
  3056. }
  3057. return result;
  3058. }
  3059. uint KApplication::keyboardModifiers()
  3060. {
  3061. #ifdef Q_WS_X11
  3062. Window root;
  3063. Window child;
  3064. int root_x, root_y, win_x, win_y;
  3065. uint keybstate;
  3066. XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child,
  3067. &root_x, &root_y, &win_x, &win_y, &keybstate );
  3068. return keybstate & 0x00ff;
  3069. #elif defined W_WS_MACX
  3070. return GetCurrentEventKeyModifiers() & 0x00ff;
  3071. #else
  3072. //TODO for win32
  3073. return 0;
  3074. #endif
  3075. }
  3076. uint KApplication::mouseState()
  3077. {
  3078. uint mousestate;
  3079. #ifdef Q_WS_X11
  3080. Window root;
  3081. Window child;
  3082. int root_x, root_y, win_x, win_y;
  3083. XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child,
  3084. &root_x, &root_y, &win_x, &win_y, &mousestate );
  3085. #elif defined(Q_WS_WIN)
  3086. const bool mousebtn_swapped = GetSystemMetrics(SM_SWAPBUTTON);
  3087. if (GetAsyncKeyState(VK_LBUTTON))
  3088. mousestate |= (mousebtn_swapped ? Button3Mask : Button1Mask);
  3089. if (GetAsyncKeyState(VK_MBUTTON))
  3090. mousestate |= Button2Mask;
  3091. if (GetAsyncKeyState(VK_RBUTTON))
  3092. mousestate |= (mousebtn_swapped ? Button1Mask : Button3Mask);
  3093. #elif defined(Q_WS_MACX)
  3094. mousestate = GetCurrentEventButtonState();
  3095. #else
  3096. //TODO: other platforms
  3097. #endif
  3098. return mousestate & 0xff00;
  3099. }
  3100. TQ_ButtonState KApplication::keyboardMouseState()
  3101. {
  3102. int ret = 0;
  3103. #ifdef Q_WS_X11
  3104. Window root;
  3105. Window child;
  3106. int root_x, root_y, win_x, win_y;
  3107. uint state;
  3108. XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child,
  3109. &root_x, &root_y, &win_x, &win_y, &state );
  3110. // transform the same way like Qt's qt_x11_translateButtonState()
  3111. if( state & Button1Mask )
  3112. ret |= TQ_LeftButton;
  3113. if( state & Button2Mask )
  3114. ret |= TQ_MidButton;
  3115. if( state & Button3Mask )
  3116. ret |= TQ_RightButton;
  3117. if( state & ShiftMask )
  3118. ret |= TQ_ShiftButton;
  3119. if( state & ControlMask )
  3120. ret |= TQ_ControlButton;
  3121. if( state & KKeyNative::modX( KKey::ALT ))
  3122. ret |= TQ_AltButton;
  3123. if( state & KKeyNative::modX( KKey::WIN ))
  3124. ret |= TQ_MetaButton;
  3125. #elif defined(Q_WS_WIN)
  3126. const bool mousebtn_swapped = GetSystemMetrics(SM_SWAPBUTTON);
  3127. if (GetAsyncKeyState(VK_LBUTTON))
  3128. ret |= (mousebtn_swapped ? RightButton : LeftButton);
  3129. if (GetAsyncKeyState(VK_MBUTTON))
  3130. ret |= TQ_MidButton;
  3131. if (GetAsyncKeyState(VK_RBUTTON))
  3132. ret |= (mousebtn_swapped ? TQ_LeftButton : TQ_RightButton);
  3133. if (GetAsyncKeyState(VK_SHIFT))
  3134. ret |= TQ_ShiftButton;
  3135. if (GetAsyncKeyState(VK_CONTROL))
  3136. ret |= TQ_ControlButton;
  3137. if (GetAsyncKeyState(VK_MENU))
  3138. ret |= TQ_AltButton;
  3139. if (GetAsyncKeyState(VK_LWIN) || GetAsyncKeyState(VK_RWIN))
  3140. ret |= TQ_MetaButton;
  3141. #else
  3142. //TODO: other platforms
  3143. #endif
  3144. return static_cast< ButtonState >( ret );
  3145. }
  3146. void KApplication::installSigpipeHandler()
  3147. {
  3148. #ifdef Q_OS_UNIX
  3149. struct sigaction act;
  3150. act.sa_handler = SIG_IGN;
  3151. sigemptyset( &act.sa_mask );
  3152. act.sa_flags = 0;
  3153. sigaction( SIGPIPE, &act, 0 );
  3154. #endif
  3155. }
  3156. void KApplication::sigpipeHandler(int)
  3157. {
  3158. int saved_errno = errno;
  3159. // Using kdDebug from a signal handler is not a good idea.
  3160. #ifndef NDEBUG
  3161. char msg[1000];
  3162. sprintf(msg, "*** SIGPIPE *** (ignored, pid = %ld)\n", (long) getpid());
  3163. write(2, msg, strlen(msg));
  3164. #endif
  3165. // Do nothing.
  3166. errno = saved_errno;
  3167. }
  3168. bool KApplication::guiEnabled()
  3169. {
  3170. return kapp && kapp->d->guiEnabled;
  3171. }
  3172. void KApplication::virtual_hook( int id, void* data )
  3173. { KInstance::virtual_hook( id, data ); }
  3174. void KSessionManaged::virtual_hook( int, void* )
  3175. { /*BASE::virtual_hook( id, data );*/ }
  3176. #include "kapplication.moc"