00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #if 0
00029 #define KSTARTUPINFO_ALL_DEBUG
00030 #warning Extra TDEStartupInfo debug messages enabled.
00031 #endif
00032
00033 #include <tqwidget.h>
00034
00035 #include "config.h"
00036 #ifdef Q_WS_X11
00037
00038 #include <tqglobal.h>
00039 #ifdef HAVE_CONFIG_H
00040 #include <config.h>
00041 #endif
00042
00043
00044 #ifndef QT_CLEAN_NAMESPACE
00045 #define QT_CLEAN_NAMESPACE
00046 #endif
00047
00048 #include "tdestartupinfo.h"
00049
00050 #include <unistd.h>
00051 #include <sys/time.h>
00052 #include <stdlib.h>
00053 #include <tqtimer.h>
00054 #ifdef Q_WS_X11
00055 #include <netwm.h>
00056 #endif
00057 #include <kdebug.h>
00058 #include <tdeapplication.h>
00059 #include <signal.h>
00060 #ifdef Q_WS_X11
00061 #include <twinmodule.h>
00062 #include <kxmessages.h>
00063 #include <twin.h>
00064 #endif
00065
00066 static const char* const NET_STARTUP_MSG = "_NET_STARTUP_INFO";
00067 static const char* const NET_STARTUP_WINDOW = "_NET_STARTUP_ID";
00068
00069
00070 static const char* const NET_STARTUP_ENV = "DESKTOP_STARTUP_ID";
00071
00072 static bool auto_app_started_sending = true;
00073
00074 static long get_num( const TQString& item_P );
00075 static unsigned long get_unum( const TQString& item_P );
00076 static TQString get_str( const TQString& item_P );
00077 static TQCString get_cstr( const TQString& item_P );
00078 static TQStringList get_fields( const TQString& txt_P );
00079 static TQString escape_str( const TQString& str_P );
00080
00081 static Atom utf8_string_atom = None;
00082
00083 class TDEStartupInfo::Data
00084 : public TDEStartupInfoData
00085 {
00086 public:
00087 Data() : TDEStartupInfoData(), age(0) {}
00088 Data( const TQString& txt_P )
00089 : TDEStartupInfoData( txt_P ), age( 0 ) {}
00090 unsigned int age;
00091 };
00092
00093 struct TDEStartupInfoPrivate
00094 {
00095 public:
00096 TQMap< TDEStartupInfoId, TDEStartupInfo::Data > startups;
00097
00098 TQMap< TDEStartupInfoId, TDEStartupInfo::Data > silent_startups;
00099
00100 TQMap< TDEStartupInfoId, TDEStartupInfo::Data > uninited_startups;
00101 #ifdef Q_WS_X11
00102 KWinModule* wm_module;
00103 KXMessages msgs;
00104 #endif
00105 TQTimer* cleanup;
00106 int flags;
00107 TDEStartupInfoPrivate( int flags_P )
00108 :
00109 #ifdef Q_WS_X11
00110 msgs( NET_STARTUP_MSG, NULL, false ),
00111 #endif
00112 flags( flags_P ) {}
00113 };
00114
00115 TDEStartupInfo::TDEStartupInfo( int flags_P, TQObject* parent_P, const char* name_P )
00116 : TQObject( parent_P, name_P ),
00117 timeout( 60 ), d( NULL )
00118 {
00119 init( flags_P );
00120 }
00121
00122 TDEStartupInfo::TDEStartupInfo( bool clean_on_cantdetect_P, TQObject* parent_P, const char* name_P )
00123 : TQObject( parent_P, name_P ),
00124 timeout( 60 ), d( NULL )
00125 {
00126 init( clean_on_cantdetect_P ? CleanOnCantDetect : 0 );
00127 }
00128
00129 void TDEStartupInfo::init( int flags_P )
00130 {
00131
00132 if( !TDEApplication::kApplication())
00133 return;
00134 if( !TDEApplication::kApplication()->getDisplay())
00135 return;
00136
00137 d = new TDEStartupInfoPrivate( flags_P );
00138 #ifdef Q_WS_X11
00139 if( !( d->flags & DisableKWinModule ))
00140 {
00141 d->wm_module = new KWinModule( this );
00142 connect( d->wm_module, TQT_SIGNAL( windowAdded( WId )), TQT_SLOT( slot_window_added( WId )));
00143 connect( d->wm_module, TQT_SIGNAL( systemTrayWindowAdded( WId )), TQT_SLOT( slot_window_added( WId )));
00144 }
00145 else
00146 d->wm_module = NULL;
00147 connect( &d->msgs, TQT_SIGNAL( gotMessage( const TQString& )), TQT_SLOT( got_message( const TQString& )));
00148 #endif
00149 d->cleanup = new TQTimer( this, "cleanup" );
00150 connect( d->cleanup, TQT_SIGNAL( timeout()), TQT_SLOT( startups_cleanup()));
00151 }
00152
00153 TDEStartupInfo::~TDEStartupInfo()
00154 {
00155 delete d;
00156 }
00157
00158 void TDEStartupInfo::got_message( const TQString& msg_P )
00159 {
00160
00161 kdDebug( 172 ) << "[tdecore-tdestartupinfo] got:" << msg_P << endl;
00162 TQString msg = msg_P.stripWhiteSpace();
00163 if( msg.startsWith( "new:" ))
00164 got_startup_info( msg.mid( 4 ), false );
00165 else if( msg.startsWith( "change:" ))
00166 got_startup_info( msg.mid( 7 ), true );
00167 else if( msg.startsWith( "remove:" ))
00168 got_remove_startup_info( msg.mid( 7 ));
00169 }
00170
00171
00172
00173
00174
00175
00176
00177 namespace
00178 {
00179 class DelayedWindowEvent
00180 : public TQCustomEvent
00181 {
00182 public:
00183 DelayedWindowEvent( WId w_P )
00184 : TQCustomEvent( TQEvent::User + 15 ), w( w_P ) {}
00185 Window w;
00186 };
00187 }
00188
00189 void TDEStartupInfo::slot_window_added( WId w_P )
00190 {
00191 kapp->postEvent( this, new DelayedWindowEvent( w_P ));
00192 }
00193
00194 void TDEStartupInfo::customEvent( TQCustomEvent* e_P )
00195 {
00196 if( e_P->type() == TQEvent::User + 15 )
00197 window_added( static_cast< DelayedWindowEvent* >( e_P )->w );
00198 else
00199 TQObject::customEvent( e_P );
00200 }
00201
00202 void TDEStartupInfo::window_added( WId w_P )
00203 {
00204 TDEStartupInfoId id;
00205 TDEStartupInfoData data;
00206 startup_t ret = check_startup_internal( w_P, &id, &data );
00207 switch( ret )
00208 {
00209 case Match:
00210 kdDebug( 172 ) << "[tdecore-tdestartupinfo] new window match" << endl;
00211 break;
00212 case NoMatch:
00213 break;
00214 case CantDetect:
00215 if( d->flags & CleanOnCantDetect )
00216 clean_all_noncompliant();
00217 break;
00218 }
00219 }
00220
00221 void TDEStartupInfo::got_startup_info( const TQString& msg_P, bool update_P )
00222 {
00223 TDEStartupInfoId id( msg_P );
00224 if( id.none())
00225 return;
00226 TDEStartupInfo::Data data( msg_P );
00227 new_startup_info_internal( id, data, update_P );
00228 }
00229
00230 void TDEStartupInfo::new_startup_info_internal( const TDEStartupInfoId& id_P,
00231 Data& data_P, bool update_P )
00232 {
00233 if( d == NULL )
00234 return;
00235 if( id_P.none())
00236 return;
00237 if( d->startups.contains( id_P ))
00238 {
00239 d->startups[ id_P ].update( data_P );
00240 d->startups[ id_P ].age = 0;
00241 kdDebug( 172 ) << "[tdecore-tdestartupinfo] updating" << endl;
00242 if( d->startups[ id_P ].silent() == Data::Yes
00243 && !( d->flags & AnnounceSilenceChanges ))
00244 {
00245 d->silent_startups[ id_P ] = d->startups[ id_P ];
00246 d->startups.remove( id_P );
00247 emit gotRemoveStartup( id_P, d->silent_startups[ id_P ] );
00248 return;
00249 }
00250 emit gotStartupChange( id_P, d->startups[ id_P ] );
00251 return;
00252 }
00253 if( d->silent_startups.contains( id_P ))
00254 {
00255 d->silent_startups[ id_P ].update( data_P );
00256 d->silent_startups[ id_P ].age = 0;
00257 kdDebug( 172 ) << "[tdecore-tdestartupinfo] updating silenced" << endl;
00258 if( d->silent_startups[ id_P ].silent() != Data::Yes )
00259 {
00260 d->startups[ id_P ] = d->silent_startups[ id_P ];
00261 d->silent_startups.remove( id_P );
00262 emit gotNewStartup( id_P, d->startups[ id_P ] );
00263 return;
00264 }
00265 emit gotStartupChange( id_P, d->silent_startups[ id_P ] );
00266 return;
00267 }
00268 if( d->uninited_startups.contains( id_P ))
00269 {
00270 d->uninited_startups[ id_P ].update( data_P );
00271 kdDebug( 172 ) << "[tdecore-tdestartupinfo] updating uninited" << endl;
00272 if( !update_P )
00273 {
00274 d->startups[ id_P ] = d->uninited_startups[ id_P ];
00275 d->uninited_startups.remove( id_P );
00276 emit gotNewStartup( id_P, d->startups[ id_P ] );
00277 return;
00278 }
00279
00280 return;
00281 }
00282 if( update_P )
00283 {
00284 kdDebug( 172 ) << "[tdecore-tdestartupinfo] adding uninited" << endl;
00285 d->uninited_startups.insert( id_P, data_P );
00286 }
00287 else if( data_P.silent() != Data::Yes || d->flags & AnnounceSilenceChanges )
00288 {
00289 kdDebug( 172 ) << "[tdecore-tdestartupinfo] adding" << endl;
00290 d->startups.insert( id_P, data_P );
00291 emit gotNewStartup( id_P, data_P );
00292 }
00293 else
00294 {
00295 kdDebug( 172 ) << "[tdecore-tdestartupinfo] adding silent" << endl;
00296 d->silent_startups.insert( id_P, data_P );
00297 }
00298 d->cleanup->start( 1000 );
00299 }
00300
00301 void TDEStartupInfo::got_remove_startup_info( const TQString& msg_P )
00302 {
00303 TDEStartupInfoId id( msg_P );
00304 TDEStartupInfoData data( msg_P );
00305 if( data.pids().count() > 0 )
00306 {
00307 if( !id.none())
00308 remove_startup_pids( id, data );
00309 else
00310 remove_startup_pids( data );
00311 return;
00312 }
00313 remove_startup_info_internal( id );
00314 }
00315
00316 void TDEStartupInfo::remove_startup_info_internal( const TDEStartupInfoId& id_P )
00317 {
00318 if( d == NULL )
00319 return;
00320 if( d->startups.contains( id_P ))
00321 {
00322 kdDebug( 172 ) << "[tdecore-tdestartupinfo] removing" << endl;
00323 emit gotRemoveStartup( id_P, d->startups[ id_P ]);
00324 d->startups.remove( id_P );
00325 }
00326 else if( d->silent_startups.contains( id_P ))
00327 {
00328 kdDebug( 172 ) << "[tdecore-tdestartupinfo] removing silent" << endl;
00329 d->silent_startups.remove( id_P );
00330 }
00331 else if( d->uninited_startups.contains( id_P ))
00332 {
00333 kdDebug( 172 ) << "[tdecore-tdestartupinfo] removing uninited" << endl;
00334 d->uninited_startups.remove( id_P );
00335 }
00336 return;
00337 }
00338
00339 void TDEStartupInfo::remove_startup_pids( const TDEStartupInfoData& data_P )
00340 {
00341 if( d == NULL )
00342 return;
00343 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->startups.begin();
00344 it != d->startups.end();
00345 ++it )
00346 {
00347 if( ( *it ).hostname() != data_P.hostname())
00348 continue;
00349 if( !( *it ).is_pid( data_P.pids().first()))
00350 continue;
00351 remove_startup_pids( it.key(), data_P );
00352 break;
00353 }
00354 }
00355
00356 void TDEStartupInfo::remove_startup_pids( const TDEStartupInfoId& id_P,
00357 const TDEStartupInfoData& data_P )
00358 {
00359 if( d == NULL )
00360 return;
00361 kdFatal( data_P.pids().count() == 0, 172 );
00362 Data* data = NULL;
00363 if( d->startups.contains( id_P ))
00364 data = &d->startups[ id_P ];
00365 else if( d->silent_startups.contains( id_P ))
00366 data = &d->silent_startups[ id_P ];
00367 else if( d->uninited_startups.contains( id_P ))
00368 data = &d->uninited_startups[ id_P ];
00369 else
00370 return;
00371 for( TQValueList< pid_t >::ConstIterator it2 = data_P.pids().begin();
00372 it2 != data_P.pids().end();
00373 ++it2 )
00374 data->remove_pid( *it2 );
00375 if( data->pids().count() == 0 )
00376 remove_startup_info_internal( id_P );
00377 }
00378
00379 bool TDEStartupInfo::sendStartup( const TDEStartupInfoId& id_P, const TDEStartupInfoData& data_P )
00380 {
00381 if( id_P.none())
00382 return false;
00383 KXMessages msgs;
00384 TQString msg = TQString::fromLatin1( "new: %1 %2" )
00385 .arg( id_P.to_text()).arg( data_P.to_text());
00386 msg = check_required_startup_fields( msg, data_P, tqt_xscreen());
00387 kdDebug( 172 ) << "[tdecore-tdestartupinfo] sending " << msg << endl;
00388 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1, false );
00389 return true;
00390 }
00391
00392 bool TDEStartupInfo::sendStartupX( Display* disp_P, const TDEStartupInfoId& id_P,
00393 const TDEStartupInfoData& data_P )
00394 {
00395 if( id_P.none())
00396 return false;
00397 TQString msg = TQString::fromLatin1( "new: %1 %2" )
00398 .arg( id_P.to_text()).arg( data_P.to_text());
00399 msg = check_required_startup_fields( msg, data_P, DefaultScreen( disp_P ));
00400 #ifdef KSTARTUPINFO_ALL_DEBUG
00401 kdDebug( 172 ) << "[tdecore-tdestartupinfo] sending " << msg << endl;
00402 #endif
00403 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1, false );
00404 }
00405
00406 TQString TDEStartupInfo::check_required_startup_fields( const TQString& msg, const TDEStartupInfoData& data_P,
00407 int screen )
00408 {
00409 TQString ret = msg;
00410 if( data_P.name().isEmpty())
00411 {
00412
00413 TQString name = data_P.bin();
00414 if( name.isEmpty())
00415 name = "UNKNOWN";
00416 ret += TQString( " NAME=\"%1\"" ).arg( escape_str( name ));
00417 }
00418 if( data_P.screen() == -1 )
00419 ret += TQString( " SCREEN=%1" ).arg( screen );
00420 return ret;
00421 }
00422
00423 bool TDEStartupInfo::sendChange( const TDEStartupInfoId& id_P, const TDEStartupInfoData& data_P )
00424 {
00425 if( id_P.none())
00426 return false;
00427 KXMessages msgs;
00428 TQString msg = TQString::fromLatin1( "change: %1 %2" )
00429 .arg( id_P.to_text()).arg( data_P.to_text());
00430 kdDebug( 172 ) << "[tdecore-tdestartupinfo] sending " << msg << endl;
00431 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1, false );
00432 return true;
00433 }
00434
00435 bool TDEStartupInfo::sendChangeX( Display* disp_P, const TDEStartupInfoId& id_P,
00436 const TDEStartupInfoData& data_P )
00437 {
00438 if( id_P.none())
00439 return false;
00440 TQString msg = TQString::fromLatin1( "change: %1 %2" )
00441 .arg( id_P.to_text()).arg( data_P.to_text());
00442 #ifdef KSTARTUPINFO_ALL_DEBUG
00443 kdDebug( 172 ) << "[tdecore-tdestartupinfo] sending " << msg << endl;
00444 #endif
00445 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1, false );
00446 }
00447
00448 bool TDEStartupInfo::sendFinish( const TDEStartupInfoId& id_P )
00449 {
00450 if( id_P.none())
00451 return false;
00452 KXMessages msgs;
00453 TQString msg = TQString::fromLatin1( "remove: %1" ).arg( id_P.to_text());
00454 kdDebug( 172 ) << "[tdecore-tdestartupinfo] sending " << msg << endl;
00455 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1, false );
00456 return true;
00457 }
00458
00459 bool TDEStartupInfo::sendFinishX( Display* disp_P, const TDEStartupInfoId& id_P )
00460 {
00461 if( id_P.none())
00462 return false;
00463 TQString msg = TQString::fromLatin1( "remove: %1" ).arg( id_P.to_text());
00464 #ifdef KSTARTUPINFO_ALL_DEBUG
00465 kdDebug( 172 ) << "[tdecore-tdestartupinfo] sending " << msg << endl;
00466 #endif
00467 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1, false );
00468 }
00469
00470 bool TDEStartupInfo::sendFinish( const TDEStartupInfoId& id_P, const TDEStartupInfoData& data_P )
00471 {
00472
00473
00474 KXMessages msgs;
00475 TQString msg = TQString::fromLatin1( "remove: %1 %2" )
00476 .arg( id_P.to_text()).arg( data_P.to_text());
00477 kdDebug( 172 ) << "[tdecore-tdestartupinfo] sending " << msg << endl;
00478 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1, false );
00479 return true;
00480 }
00481
00482 bool TDEStartupInfo::sendFinishX( Display* disp_P, const TDEStartupInfoId& id_P,
00483 const TDEStartupInfoData& data_P )
00484 {
00485
00486
00487 TQString msg = TQString::fromLatin1( "remove: %1 %2" )
00488 .arg( id_P.to_text()).arg( data_P.to_text());
00489 #ifdef KSTARTUPINFO_ALL_DEBUG
00490 kdDebug( 172 ) << "[tdecore-tdestartupinfo] sending " << msg << endl;
00491 #endif
00492 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1, false );
00493 }
00494
00495 void TDEStartupInfo::appStarted()
00496 {
00497 if( kapp != NULL )
00498 appStarted( kapp->startupId());
00499 else
00500 appStarted( TDEStartupInfo::currentStartupIdEnv().id());
00501 }
00502
00503 void TDEStartupInfo::appStarted( const TQCString& startup_id )
00504 {
00505 TDEStartupInfoId id;
00506 id.initId( startup_id );
00507 if( id.none())
00508 return;
00509 if( kapp != NULL )
00510 TDEStartupInfo::sendFinish( id );
00511 else if( getenv( "DISPLAY" ) != NULL )
00512 {
00513 #ifdef Q_WS_X11
00514 Display* disp = XOpenDisplay( NULL );
00515 if( disp != NULL )
00516 {
00517 TDEStartupInfo::sendFinishX( disp, id );
00518 XCloseDisplay( disp );
00519 }
00520 #endif
00521 }
00522 }
00523
00524 void TDEStartupInfo::disableAutoAppStartedSending( bool disable )
00525 {
00526 auto_app_started_sending = !disable;
00527 }
00528
00529 void TDEStartupInfo::silenceStartup( bool silence )
00530 {
00531 TDEStartupInfoId id;
00532 id.initId( kapp->startupId());
00533 if( id.none())
00534 return;
00535 TDEStartupInfoData data;
00536 data.setSilent( silence ? TDEStartupInfoData::Yes : TDEStartupInfoData::No );
00537 sendChange( id, data );
00538 }
00539
00540 void TDEStartupInfo::handleAutoAppStartedSending()
00541 {
00542 if( auto_app_started_sending )
00543 appStarted();
00544 }
00545
00546 void TDEStartupInfo::setNewStartupId( TQWidget* window, const TQCString& startup_id )
00547 {
00548 bool activate = true;
00549 kapp->setStartupId( startup_id );
00550 if( window != NULL )
00551 {
00552 if( !startup_id.isEmpty() && startup_id != "0" )
00553 {
00554 NETRootInfo i( tqt_xdisplay(), NET::Supported );
00555 if( i.isSupported( NET::WM2StartupId ))
00556 {
00557 TDEStartupInfo::setWindowStartupId( window->winId(), startup_id );
00558 activate = false;
00559 }
00560 }
00561 if( activate )
00562 {
00563 KWin::setOnDesktop( window->winId(), KWin::currentDesktop());
00564
00565
00566
00567
00568 KWin::forceActiveWindow( window->winId());
00569 }
00570 }
00571 TDEStartupInfo::handleAutoAppStartedSending();
00572 }
00573
00574 TDEStartupInfo::startup_t TDEStartupInfo::checkStartup( WId w_P, TDEStartupInfoId& id_O,
00575 TDEStartupInfoData& data_O )
00576 {
00577 return check_startup_internal( w_P, &id_O, &data_O );
00578 }
00579
00580 TDEStartupInfo::startup_t TDEStartupInfo::checkStartup( WId w_P, TDEStartupInfoId& id_O )
00581 {
00582 return check_startup_internal( w_P, &id_O, NULL );
00583 }
00584
00585 TDEStartupInfo::startup_t TDEStartupInfo::checkStartup( WId w_P, TDEStartupInfoData& data_O )
00586 {
00587 return check_startup_internal( w_P, NULL, &data_O );
00588 }
00589
00590 TDEStartupInfo::startup_t TDEStartupInfo::checkStartup( WId w_P )
00591 {
00592 return check_startup_internal( w_P, NULL, NULL );
00593 }
00594
00595 TDEStartupInfo::startup_t TDEStartupInfo::check_startup_internal( WId w_P, TDEStartupInfoId* id_O,
00596 TDEStartupInfoData* data_O )
00597 {
00598 if( d == NULL )
00599 return NoMatch;
00600 if( d->startups.count() == 0 )
00601 return NoMatch;
00602
00603
00604
00605
00606
00607
00608
00609 kdDebug( 172 ) << "[tdecore-tdestartupinfo] check_startup" << endl;
00610 TQCString id = windowStartupId( w_P );
00611 if( !id.isNull())
00612 {
00613 if( id.isEmpty() || id == "0" )
00614 {
00615 kdDebug( 172 ) << "[tdecore-tdestartupinfo] ignore" << endl;
00616 return NoMatch;
00617 }
00618 return find_id( id, id_O, data_O ) ? Match : NoMatch;
00619 }
00620 #ifdef Q_WS_X11
00621 NETWinInfo info( tqt_xdisplay(), w_P, tqt_xrootwin(),
00622 NET::WMWindowType | NET::WMPid | NET::WMState );
00623 pid_t pid = info.pid();
00624 if( pid > 0 )
00625 {
00626 TQCString hostname = get_window_hostname( w_P );
00627 if( !hostname.isEmpty()
00628 && find_pid( pid, hostname, id_O, data_O ))
00629 return Match;
00630
00631 }
00632 XClassHint hint;
00633 if( XGetClassHint( tqt_xdisplay(), w_P, &hint ) != 0 )
00634 {
00635 TQCString res_name = hint.res_name;
00636 TQCString res_class = hint.res_class;
00637 XFree( hint.res_name );
00638 XFree( hint.res_class );
00639 if( find_wclass( res_name, res_class, id_O, data_O ))
00640 return Match;
00641 }
00642
00643 NET::WindowType type = info.windowType( NET::NormalMask | NET::DesktopMask
00644 | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
00645 | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
00646 if( type != NET::Normal
00647 && type != NET::Override
00648 && type != NET::Unknown
00649 && type != NET::Dialog
00650 && type != NET::Utility )
00651
00652 return NoMatch;
00653
00654 Window transient_for;
00655 if( XGetTransientForHint( tqt_xdisplay(), static_cast< Window >( w_P ), &transient_for )
00656 && static_cast< WId >( transient_for ) != tqt_xrootwin()
00657 && transient_for != None )
00658 return NoMatch;
00659 #endif
00660 kdDebug( 172 ) << "[tdecore-tdestartupinfo] check_startup:cantdetect" << endl;
00661 return CantDetect;
00662 }
00663
00664 bool TDEStartupInfo::find_id( const TQCString& id_P, TDEStartupInfoId* id_O,
00665 TDEStartupInfoData* data_O )
00666 {
00667 if( d == NULL )
00668 return false;
00669 kdDebug( 172 ) << "[tdecore-tdestartupinfo] find_id:" << id_P << endl;
00670 TDEStartupInfoId id;
00671 id.initId( id_P );
00672 if( d->startups.contains( id ))
00673 {
00674 if( id_O != NULL )
00675 *id_O = id;
00676 if( data_O != NULL )
00677 *data_O = d->startups[ id ];
00678 kdDebug( 172 ) << "[tdecore-tdestartupinfo] check_startup_id:match" << endl;
00679 return true;
00680 }
00681 return false;
00682 }
00683
00684 bool TDEStartupInfo::find_pid( pid_t pid_P, const TQCString& hostname_P,
00685 TDEStartupInfoId* id_O, TDEStartupInfoData* data_O )
00686 {
00687 if( d == NULL )
00688 return false;
00689 kdDebug( 172 ) << "[tdecore-tdestartupinfo] find_pid:" << pid_P << endl;
00690 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->startups.begin();
00691 it != d->startups.end();
00692 ++it )
00693 {
00694 if( ( *it ).is_pid( pid_P ) && ( *it ).hostname() == hostname_P )
00695 {
00696 if( id_O != NULL )
00697 *id_O = it.key();
00698 if( data_O != NULL )
00699 *data_O = *it;
00700
00701 remove_startup_info_internal( it.key());
00702 kdDebug( 172 ) << "[tdecore-tdestartupinfo] check_startup_pid:match" << endl;
00703 return true;
00704 }
00705 }
00706 return false;
00707 }
00708
00709 bool TDEStartupInfo::find_wclass( TQCString res_name, TQCString res_class,
00710 TDEStartupInfoId* id_O, TDEStartupInfoData* data_O )
00711 {
00712 if( d == NULL )
00713 return false;
00714 res_name = res_name.lower();
00715 res_class = res_class.lower();
00716 kdDebug( 172 ) << "[tdecore-tdestartupinfo] find_wclass:" << res_name << ":" << res_class << endl;
00717 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->startups.begin();
00718 it != d->startups.end();
00719 ++it )
00720 {
00721 const TQCString wmclass = ( *it ).findWMClass();
00722 if( wmclass.lower() == res_name || wmclass.lower() == res_class )
00723 {
00724 if( id_O != NULL )
00725 *id_O = it.key();
00726 if( data_O != NULL )
00727 *data_O = *it;
00728
00729 remove_startup_info_internal( it.key());
00730 kdDebug( 172 ) << "[tdecore-tdestartupinfo] check_startup_wclass:match" << endl;
00731 return true;
00732 }
00733 }
00734 return false;
00735 }
00736
00737 #ifdef Q_WS_X11
00738 static Atom net_startup_atom = None;
00739
00740 static TQCString read_startup_id_property( WId w_P )
00741 {
00742 TQCString ret;
00743 unsigned char *name_ret;
00744 Atom type_ret;
00745 int format_ret;
00746 unsigned long nitems_ret = 0, after_ret = 0;
00747 if( XGetWindowProperty( tqt_xdisplay(), w_P, net_startup_atom, 0l, 4096,
00748 False, utf8_string_atom, &type_ret, &format_ret, &nitems_ret, &after_ret, &name_ret )
00749 == Success )
00750 {
00751 if( type_ret == utf8_string_atom && format_ret == 8 && name_ret != NULL )
00752 ret = reinterpret_cast< char* >( name_ret );
00753 if ( name_ret != NULL )
00754 XFree( name_ret );
00755 }
00756 return ret;
00757 }
00758
00759 #endif
00760
00761 TQCString TDEStartupInfo::windowStartupId( WId w_P )
00762 {
00763 #ifdef Q_WS_X11
00764 if( net_startup_atom == None )
00765 net_startup_atom = XInternAtom( tqt_xdisplay(), NET_STARTUP_WINDOW, False );
00766 if( utf8_string_atom == None )
00767 utf8_string_atom = XInternAtom( tqt_xdisplay(), "UTF8_STRING", False );
00768 TQCString ret = read_startup_id_property( w_P );
00769 if( ret.isEmpty())
00770 {
00771 XWMHints* hints = XGetWMHints( tqt_xdisplay(), w_P );
00772 if( hints && ( hints->flags & WindowGroupHint ) != 0 )
00773 ret = read_startup_id_property( hints->window_group );
00774 if( hints )
00775 XFree( hints );
00776 }
00777 return ret;
00778 #else
00779 return TQCString();
00780 #endif
00781 }
00782
00783 void TDEStartupInfo::setWindowStartupId( WId w_P, const TQCString& id_P )
00784 {
00785 #ifdef Q_WS_X11
00786 if( id_P.isNull())
00787 return;
00788 if( net_startup_atom == None )
00789 net_startup_atom = XInternAtom( tqt_xdisplay(), NET_STARTUP_WINDOW, False );
00790 if( utf8_string_atom == None )
00791 utf8_string_atom = XInternAtom( tqt_xdisplay(), "UTF8_STRING", False );
00792 XChangeProperty( tqt_xdisplay(), w_P, net_startup_atom, utf8_string_atom, 8,
00793 PropModeReplace, reinterpret_cast< unsigned char* >( const_cast<TQCString&>(id_P).data()), id_P.length());
00794 #endif
00795 }
00796
00797 TQCString TDEStartupInfo::get_window_hostname( WId w_P )
00798 {
00799 #ifdef Q_WS_X11
00800 XTextProperty tp;
00801 char** hh;
00802 int cnt;
00803 if( XGetWMClientMachine( tqt_xdisplay(), w_P, &tp ) != 0
00804 && XTextPropertyToStringList( &tp, &hh, &cnt ) != 0 )
00805 {
00806 if( cnt == 1 )
00807 {
00808 TQCString hostname = hh[ 0 ];
00809 XFreeStringList( hh );
00810 return hostname;
00811 }
00812 XFreeStringList( hh );
00813 }
00814 #endif
00815
00816 return TQCString();
00817 }
00818
00819 void TDEStartupInfo::setTimeout( unsigned int secs_P )
00820 {
00821 timeout = secs_P;
00822
00823 TQTimer::singleShot( 0, this, TQT_SLOT( startups_cleanup_no_age()));
00824 }
00825
00826 void TDEStartupInfo::startups_cleanup_no_age()
00827 {
00828 startups_cleanup_internal( false );
00829 }
00830
00831 void TDEStartupInfo::startups_cleanup()
00832 {
00833 if( d == NULL )
00834 return;
00835 if( d->startups.count() == 0 && d->silent_startups.count() == 0
00836 && d->uninited_startups.count() == 0 )
00837 {
00838 d->cleanup->stop();
00839 return;
00840 }
00841 startups_cleanup_internal( true );
00842 }
00843
00844 void TDEStartupInfo::startups_cleanup_internal( bool age_P )
00845 {
00846 if( d == NULL )
00847 return;
00848 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->startups.begin();
00849 it != d->startups.end();
00850 )
00851 {
00852 if( age_P )
00853 ( *it ).age++;
00854 unsigned int tout = timeout;
00855 if( ( *it ).silent() == Data::Yes )
00856 tout *= 20;
00857 if( ( *it ).age >= tout )
00858 {
00859 const TDEStartupInfoId& key = it.key();
00860 ++it;
00861 kdDebug( 172 ) << "[tdecore-tdestartupinfo] startups entry timeout:" << key.id() << endl;
00862 remove_startup_info_internal( key );
00863 }
00864 else
00865 ++it;
00866 }
00867 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->silent_startups.begin();
00868 it != d->silent_startups.end();
00869 )
00870 {
00871 if( age_P )
00872 ( *it ).age++;
00873 unsigned int tout = timeout;
00874 if( ( *it ).silent() == Data::Yes )
00875 tout *= 20;
00876 if( ( *it ).age >= tout )
00877 {
00878 const TDEStartupInfoId& key = it.key();
00879 ++it;
00880 kdDebug( 172 ) << "[tdecore-tdestartupinfo] silent entry timeout:" << key.id() << endl;
00881 remove_startup_info_internal( key );
00882 }
00883 else
00884 ++it;
00885 }
00886 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->uninited_startups.begin();
00887 it != d->uninited_startups.end();
00888 )
00889 {
00890 if( age_P )
00891 ( *it ).age++;
00892 unsigned int tout = timeout;
00893 if( ( *it ).silent() == Data::Yes )
00894 tout *= 20;
00895 if( ( *it ).age >= tout )
00896 {
00897 const TDEStartupInfoId& key = it.key();
00898 ++it;
00899 kdDebug( 172 ) << "[tdecore-tdestartupinfo] uninited entry timeout:" << key.id() << endl;
00900 remove_startup_info_internal( key );
00901 }
00902 else
00903 ++it;
00904 }
00905 }
00906
00907 void TDEStartupInfo::clean_all_noncompliant()
00908 {
00909 if( d == NULL )
00910 return;
00911 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->startups.begin();
00912 it != d->startups.end();
00913 )
00914 {
00915 if( ( *it ).WMClass() != "0" )
00916 {
00917 ++it;
00918 continue;
00919 }
00920 const TDEStartupInfoId& key = it.key();
00921 ++it;
00922 kdDebug( 172 ) << "[tdecore-tdestartupinfo] entry cleaning:" << key.id() << endl;
00923 remove_startup_info_internal( key );
00924 }
00925 }
00926
00927 TQCString TDEStartupInfo::createNewStartupId()
00928 {
00929
00930
00931 struct timeval tm;
00932 gettimeofday( &tm, NULL );
00933 char hostname[ 256 ];
00934 hostname[ 0 ] = '\0';
00935 if (!gethostname( hostname, 255 ))
00936 hostname[sizeof(hostname)-1] = '\0';
00937 TQCString id = TQString(TQString( "%1;%2;%3;%4_TIME%5" ).arg( hostname ).arg( tm.tv_sec )
00938 .arg( tm.tv_usec ).arg( getpid()).arg( GET_QT_X_USER_TIME() )).utf8();
00939 kdDebug( 172 ) << "[tdecore-tdestartupinfo] creating: " << id << ":" << tqAppName() << endl;
00940 return id;
00941 }
00942
00943
00944 struct TDEStartupInfoIdPrivate
00945 {
00946 TDEStartupInfoIdPrivate() : id( "" ) {}
00947 TQCString id;
00948 };
00949
00950 const TQCString& TDEStartupInfoId::id() const
00951 {
00952 return d->id;
00953 }
00954
00955
00956 TQString TDEStartupInfoId::to_text() const
00957 {
00958 return TQString::fromLatin1( " ID=\"%1\" " ).arg( escape_str( id()));
00959 }
00960
00961 TDEStartupInfoId::TDEStartupInfoId( const TQString& txt_P )
00962 {
00963 d = new TDEStartupInfoIdPrivate;
00964 TQStringList items = get_fields( txt_P );
00965 const TQString id_str = TQString::fromLatin1( "ID=" );
00966 for( TQStringList::Iterator it = items.begin();
00967 it != items.end();
00968 ++it )
00969 {
00970 if( ( *it ).startsWith( id_str ))
00971 d->id = get_cstr( *it );
00972 }
00973 }
00974
00975 void TDEStartupInfoId::initId( const TQCString& id_P )
00976 {
00977 if( !id_P.isEmpty())
00978 {
00979 d->id = id_P;
00980 #ifdef KSTARTUPINFO_ALL_DEBUG
00981 kdDebug( 172 ) << "[tdecore-tdestartupinfo] using: " << d->id << endl;
00982 #endif
00983 return;
00984 }
00985 const char* startup_env = getenv( NET_STARTUP_ENV );
00986 if( startup_env != NULL && *startup_env != '\0' )
00987 {
00988 d->id = startup_env;
00989 #ifdef KSTARTUPINFO_ALL_DEBUG
00990 kdDebug( 172 ) << "[tdecore-tdestartupinfo] reusing: " << d->id << endl;
00991 #endif
00992 return;
00993 }
00994 d->id = TDEStartupInfo::createNewStartupId();
00995 }
00996
00997 bool TDEStartupInfoId::setupStartupEnv() const
00998 {
00999 if( id().isEmpty())
01000 {
01001 unsetenv( NET_STARTUP_ENV );
01002 return false;
01003 }
01004 return setenv( NET_STARTUP_ENV, id(), true ) == 0;
01005 }
01006
01007 TDEStartupInfoId TDEStartupInfo::currentStartupIdEnv()
01008 {
01009 const char* startup_env = getenv( NET_STARTUP_ENV );
01010 TDEStartupInfoId id;
01011 if( startup_env != NULL && *startup_env != '\0' )
01012 id.d->id = startup_env;
01013 else
01014 id.d->id = "0";
01015 return id;
01016 }
01017
01018 void TDEStartupInfo::resetStartupEnv()
01019 {
01020 unsetenv( NET_STARTUP_ENV );
01021 }
01022
01023 TDEStartupInfoId::TDEStartupInfoId()
01024 {
01025 d = new TDEStartupInfoIdPrivate;
01026 }
01027
01028 TDEStartupInfoId::~TDEStartupInfoId()
01029 {
01030 delete d;
01031 }
01032
01033 TDEStartupInfoId::TDEStartupInfoId( const TDEStartupInfoId& id_P )
01034 {
01035 d = new TDEStartupInfoIdPrivate( *id_P.d );
01036 }
01037
01038 TDEStartupInfoId& TDEStartupInfoId::operator=( const TDEStartupInfoId& id_P )
01039 {
01040 if( &id_P == this )
01041 return *this;
01042 delete d;
01043 d = new TDEStartupInfoIdPrivate( *id_P.d );
01044 return *this;
01045 }
01046
01047 bool TDEStartupInfoId::operator==( const TDEStartupInfoId& id_P ) const
01048 {
01049 return id() == id_P.id();
01050 }
01051
01052 bool TDEStartupInfoId::operator!=( const TDEStartupInfoId& id_P ) const
01053 {
01054 return !(*this == id_P );
01055 }
01056
01057
01058 bool TDEStartupInfoId::operator<( const TDEStartupInfoId& id_P ) const
01059 {
01060 return id() < id_P.id();
01061 }
01062
01063 bool TDEStartupInfoId::none() const
01064 {
01065 return d->id.isEmpty() || d->id == "0";
01066 }
01067
01068 unsigned long TDEStartupInfoId::timestamp() const
01069 {
01070 if( none())
01071 return 0;
01072 int pos = d->id.findRev( "_TIME" );
01073 if( pos >= 0 )
01074 {
01075 bool ok;
01076 unsigned long time = d->id.mid( pos + 5 ).toULong( &ok );
01077 if( !ok && d->id[ pos + 5 ] == '-' )
01078 time = d->id.mid( pos + 5 ).toLong( &ok );
01079 if( ok )
01080 return time;
01081 }
01082
01083
01084
01085
01086 int pos1 = d->id.findRev( '/' );
01087 if( pos1 > 0 )
01088 {
01089 int pos2 = d->id.findRev( '/', pos1 - 1 );
01090 if( pos2 >= 0 )
01091 {
01092 bool ok;
01093 unsigned long time = d->id.mid( pos2 + 1, pos1 - pos2 - 1 ).toULong( &ok );
01094 if( !ok && d->id[ pos2 + 1 ] == '-' )
01095 time = d->id.mid( pos2 + 1, pos1 - pos2 - 1 ).toLong( &ok );
01096 if( ok )
01097 return time;
01098 }
01099 }
01100
01101 return 0;
01102 }
01103
01104 struct TDEStartupInfoDataPrivate
01105 {
01106 TDEStartupInfoDataPrivate() : desktop( 0 ), wmclass( "" ), hostname( "" ),
01107 silent( TDEStartupInfoData::Unknown ), timestamp( -1U ), screen( -1 ), xinerama( -1 ), launched_by( 0 ) {}
01108 TQString bin;
01109 TQString name;
01110 TQString description;
01111 TQString icon;
01112 int desktop;
01113 TQValueList< pid_t > pids;
01114 TQCString wmclass;
01115 TQCString hostname;
01116 TDEStartupInfoData::TriState silent;
01117 unsigned long timestamp;
01118 int screen;
01119 int xinerama;
01120 WId launched_by;
01121 };
01122
01123 TQString TDEStartupInfoData::to_text() const
01124 {
01125 TQString ret = "";
01126 if( !d->bin.isEmpty())
01127 ret += TQString::fromLatin1( " BIN=\"%1\"" ).arg( escape_str( d->bin ));
01128 if( !d->name.isEmpty())
01129 ret += TQString::fromLatin1( " NAME=\"%1\"" ).arg( escape_str( d->name ));
01130 if( !d->description.isEmpty())
01131 ret += TQString::fromLatin1( " DESCRIPTION=\"%1\"" ).arg( escape_str( d->description ));
01132 if( !d->icon.isEmpty())
01133 ret += TQString::fromLatin1( " ICON=%1" ).arg( d->icon );
01134 if( d->desktop != 0 )
01135 ret += TQString::fromLatin1( " DESKTOP=%1" )
01136 .arg( d->desktop == NET::OnAllDesktops ? NET::OnAllDesktops : d->desktop - 1 );
01137 if( !d->wmclass.isEmpty())
01138 ret += TQString::fromLatin1( " WMCLASS=\"%1\"" ).arg( QString(d->wmclass) );
01139 if( !d->hostname.isEmpty())
01140 ret += TQString::fromLatin1( " HOSTNAME=%1" ).arg( QString(d->hostname) );
01141 for( TQValueList< pid_t >::ConstIterator it = d->pids.begin();
01142 it != d->pids.end();
01143 ++it )
01144 ret += TQString::fromLatin1( " PID=%1" ).arg( *it );
01145 if( d->silent != Unknown )
01146 ret += TQString::fromLatin1( " SILENT=%1" ).arg( d->silent == Yes ? 1 : 0 );
01147 if( d->timestamp != -1U )
01148 ret += TQString::fromLatin1( " TIMESTAMP=%1" ).arg( d->timestamp );
01149 if( d->screen != -1 )
01150 ret += TQString::fromLatin1( " SCREEN=%1" ).arg( d->screen );
01151 if( d->xinerama != -1 )
01152 ret += TQString::fromLatin1( " XINERAMA=%1" ).arg( d->xinerama );
01153 if( d->launched_by != 0 )
01154 ret += TQString::fromLatin1( " LAUNCHED_BY=%1" ).arg( d->launched_by );
01155 return ret;
01156 }
01157
01158 TDEStartupInfoData::TDEStartupInfoData( const TQString& txt_P )
01159 {
01160 d = new TDEStartupInfoDataPrivate;
01161 TQStringList items = get_fields( txt_P );
01162 const TQString bin_str = TQString::fromLatin1( "BIN=" );
01163 const TQString name_str = TQString::fromLatin1( "NAME=" );
01164 const TQString description_str = TQString::fromLatin1( "DESCRIPTION=" );
01165 const TQString icon_str = TQString::fromLatin1( "ICON=" );
01166 const TQString desktop_str = TQString::fromLatin1( "DESKTOP=" );
01167 const TQString wmclass_str = TQString::fromLatin1( "WMCLASS=" );
01168 const TQString hostname_str = TQString::fromLatin1( "HOSTNAME=" );
01169 const TQString pid_str = TQString::fromLatin1( "PID=" );
01170 const TQString silent_str = TQString::fromLatin1( "SILENT=" );
01171 const TQString timestamp_str = TQString::fromLatin1( "TIMESTAMP=" );
01172 const TQString screen_str = TQString::fromLatin1( "SCREEN=" );
01173 const TQString xinerama_str = TQString::fromLatin1( "XINERAMA=" );
01174 const TQString launched_by_str = TQString::fromLatin1( "LAUNCHED_BY=" );
01175 for( TQStringList::Iterator it = items.begin();
01176 it != items.end();
01177 ++it )
01178 {
01179 if( ( *it ).startsWith( bin_str ))
01180 d->bin = get_str( *it );
01181 else if( ( *it ).startsWith( name_str ))
01182 d->name = get_str( *it );
01183 else if( ( *it ).startsWith( description_str ))
01184 d->description = get_str( *it );
01185 else if( ( *it ).startsWith( icon_str ))
01186 d->icon = get_str( *it );
01187 else if( ( *it ).startsWith( desktop_str ))
01188 {
01189 d->desktop = get_num( *it );
01190 if( d->desktop != NET::OnAllDesktops )
01191 ++d->desktop;
01192 }
01193 else if( ( *it ).startsWith( wmclass_str ))
01194 d->wmclass = get_cstr( *it );
01195 else if( ( *it ).startsWith( hostname_str ))
01196 d->hostname = get_cstr( *it );
01197 else if( ( *it ).startsWith( pid_str ))
01198 addPid( get_num( *it ));
01199 else if( ( *it ).startsWith( silent_str ))
01200 d->silent = get_num( *it ) != 0 ? Yes : No;
01201 else if( ( *it ).startsWith( timestamp_str ))
01202 d->timestamp = get_unum( *it );
01203 else if( ( *it ).startsWith( screen_str ))
01204 d->screen = get_num( *it );
01205 else if( ( *it ).startsWith( xinerama_str ))
01206 d->xinerama = get_num( *it );
01207 else if( ( *it ).startsWith( launched_by_str ))
01208 d->launched_by = get_num( *it );
01209 }
01210 }
01211
01212 TDEStartupInfoData::TDEStartupInfoData( const TDEStartupInfoData& data )
01213 {
01214 d = new TDEStartupInfoDataPrivate( *data.d );
01215 }
01216
01217 TDEStartupInfoData& TDEStartupInfoData::operator=( const TDEStartupInfoData& data )
01218 {
01219 if( &data == this )
01220 return *this;
01221 delete d;
01222 d = new TDEStartupInfoDataPrivate( *data.d );
01223 return *this;
01224 }
01225
01226 void TDEStartupInfoData::update( const TDEStartupInfoData& data_P )
01227 {
01228 if( !data_P.bin().isEmpty())
01229 d->bin = data_P.bin();
01230 if( !data_P.name().isEmpty() && name().isEmpty())
01231 d->name = data_P.name();
01232 if( !data_P.description().isEmpty() && description().isEmpty())
01233 d->description = data_P.description();
01234 if( !data_P.icon().isEmpty() && icon().isEmpty())
01235 d->icon = data_P.icon();
01236 if( data_P.desktop() != 0 && desktop() == 0 )
01237 d->desktop = data_P.desktop();
01238 if( !data_P.d->wmclass.isEmpty())
01239 d->wmclass = data_P.d->wmclass;
01240 if( !data_P.d->hostname.isEmpty())
01241 d->hostname = data_P.d->hostname;
01242 for( TQValueList< pid_t >::ConstIterator it = data_P.d->pids.begin();
01243 it != data_P.d->pids.end();
01244 ++it )
01245 addPid( *it );
01246 if( data_P.silent() != Unknown )
01247 d->silent = data_P.silent();
01248 if( data_P.timestamp() != -1U && timestamp() == -1U )
01249 d->timestamp = data_P.timestamp();
01250 if( data_P.screen() != -1 )
01251 d->screen = data_P.screen();
01252 if( data_P.xinerama() != -1 && xinerama() != -1 )
01253 d->xinerama = data_P.xinerama();
01254 if( data_P.launchedBy() != 0 && launchedBy() != 0 )
01255 d->launched_by = data_P.launchedBy();
01256 }
01257
01258 TDEStartupInfoData::TDEStartupInfoData()
01259 {
01260 d = new TDEStartupInfoDataPrivate;
01261 }
01262
01263 TDEStartupInfoData::~TDEStartupInfoData()
01264 {
01265 delete d;
01266 }
01267
01268 void TDEStartupInfoData::setBin( const TQString& bin_P )
01269 {
01270 d->bin = bin_P;
01271 }
01272
01273 const TQString& TDEStartupInfoData::bin() const
01274 {
01275 return d->bin;
01276 }
01277
01278 void TDEStartupInfoData::setName( const TQString& name_P )
01279 {
01280 d->name = name_P;
01281 }
01282
01283 const TQString& TDEStartupInfoData::name() const
01284 {
01285 return d->name;
01286 }
01287
01288 const TQString& TDEStartupInfoData::findName() const
01289 {
01290 if( !name().isEmpty())
01291 return name();
01292 return bin();
01293 }
01294
01295 void TDEStartupInfoData::setDescription( const TQString& desc_P )
01296 {
01297 d->description = desc_P;
01298 }
01299
01300 const TQString& TDEStartupInfoData::description() const
01301 {
01302 return d->description;
01303 }
01304
01305 const TQString& TDEStartupInfoData::findDescription() const
01306 {
01307 if( !description().isEmpty())
01308 return description();
01309 return name();
01310 }
01311
01312 void TDEStartupInfoData::setIcon( const TQString& icon_P )
01313 {
01314 d->icon = icon_P;
01315 }
01316
01317 const TQString& TDEStartupInfoData::findIcon() const
01318 {
01319 if( !icon().isEmpty())
01320 return icon();
01321 return bin();
01322 }
01323
01324 const TQString& TDEStartupInfoData::icon() const
01325 {
01326 return d->icon;
01327 }
01328
01329 void TDEStartupInfoData::setDesktop( int desktop_P )
01330 {
01331 d->desktop = desktop_P;
01332 }
01333
01334 int TDEStartupInfoData::desktop() const
01335 {
01336 return d->desktop;
01337 }
01338
01339 void TDEStartupInfoData::setWMClass( const TQCString& wmclass_P )
01340 {
01341 d->wmclass = wmclass_P;
01342 }
01343
01344 const TQCString TDEStartupInfoData::findWMClass() const
01345 {
01346 if( !WMClass().isEmpty() && WMClass() != "0" )
01347 return WMClass();
01348 return bin().utf8();
01349 }
01350
01351 const TQCString& TDEStartupInfoData::WMClass() const
01352 {
01353 return d->wmclass;
01354 }
01355
01356 void TDEStartupInfoData::setHostname( const TQCString& hostname_P )
01357 {
01358 if( !hostname_P.isNull())
01359 d->hostname = hostname_P;
01360 else
01361 {
01362 char tmp[ 256 ];
01363 tmp[ 0 ] = '\0';
01364 if (!gethostname( tmp, 255 ))
01365 tmp[sizeof(tmp)-1] = '\0';
01366 d->hostname = tmp;
01367 }
01368 }
01369
01370 const TQCString& TDEStartupInfoData::hostname() const
01371 {
01372 return d->hostname;
01373 }
01374
01375 void TDEStartupInfoData::addPid( pid_t pid_P )
01376 {
01377 if( !d->pids.contains( pid_P ))
01378 d->pids.append( pid_P );
01379 }
01380
01381 void TDEStartupInfoData::remove_pid( pid_t pid_P )
01382 {
01383 d->pids.remove( pid_P );
01384 }
01385
01386 const TQValueList< pid_t >& TDEStartupInfoData::pids() const
01387 {
01388 return d->pids;
01389 }
01390
01391 bool TDEStartupInfoData::is_pid( pid_t pid_P ) const
01392 {
01393 return d->pids.contains( pid_P );
01394 }
01395
01396 void TDEStartupInfoData::setSilent( TriState state_P )
01397 {
01398 d->silent = state_P;
01399 }
01400
01401 TDEStartupInfoData::TriState TDEStartupInfoData::silent() const
01402 {
01403 return d->silent;
01404 }
01405
01406 void TDEStartupInfoData::setTimestamp( unsigned long time )
01407 {
01408 d->timestamp = time;
01409 }
01410
01411 unsigned long TDEStartupInfoData::timestamp() const
01412 {
01413 return d->timestamp;
01414 }
01415
01416 void TDEStartupInfoData::setScreen( int screen )
01417 {
01418 d->screen = screen;
01419 }
01420
01421 int TDEStartupInfoData::screen() const
01422 {
01423 return d->screen;
01424 }
01425
01426 void TDEStartupInfoData::setXinerama( int xinerama )
01427 {
01428 d->xinerama = xinerama;
01429 }
01430
01431 int TDEStartupInfoData::xinerama() const
01432 {
01433 return d->xinerama;
01434 }
01435
01436 void TDEStartupInfoData::setLaunchedBy( WId window )
01437 {
01438 d->launched_by = window;
01439 }
01440
01441 WId TDEStartupInfoData::launchedBy() const
01442 {
01443 return d->launched_by;
01444 }
01445
01446 static
01447 long get_num( const TQString& item_P )
01448 {
01449 unsigned int pos = item_P.find( '=' );
01450 return item_P.mid( pos + 1 ).toLong();
01451 }
01452
01453 static
01454 unsigned long get_unum( const TQString& item_P )
01455 {
01456 unsigned int pos = item_P.find( '=' );
01457 return item_P.mid( pos + 1 ).toULong();
01458 }
01459
01460 static
01461 TQString get_str( const TQString& item_P )
01462 {
01463 unsigned int pos = item_P.find( '=' );
01464 if( item_P.length() > pos + 2 && item_P[ pos + 1 ] == (QChar)'\"' )
01465 {
01466 int pos2 = item_P.left( pos + 2 ).find( '\"' );
01467 if( pos2 < 0 )
01468 return TQString::null;
01469 return item_P.mid( pos + 2, pos2 - 2 - pos );
01470 }
01471 return item_P.mid( pos + 1 );
01472 }
01473
01474 static
01475 TQCString get_cstr( const TQString& item_P )
01476 {
01477 return get_str( item_P ).utf8();
01478 }
01479
01480 static
01481 TQStringList get_fields( const TQString& txt_P )
01482 {
01483 TQString txt = txt_P.simplifyWhiteSpace();
01484 TQStringList ret;
01485 TQString item = "";
01486 bool in = false;
01487 bool escape = false;
01488 for( unsigned int pos = 0;
01489 pos < txt.length();
01490 ++pos )
01491 {
01492 if( escape )
01493 {
01494 item += txt[ pos ];
01495 escape = false;
01496 }
01497 else if( txt[ pos ] == '\\' )
01498 escape = true;
01499 else if( txt[ pos ] == '\"' )
01500 in = !in;
01501 else if( txt[ pos ] == ' ' && !in )
01502 {
01503 ret.append( item );
01504 item = "";
01505 }
01506 else
01507 item += txt[ pos ];
01508 }
01509 ret.append( item );
01510 return ret;
01511 }
01512
01513 static TQString escape_str( const TQString& str_P )
01514 {
01515 TQString ret = "";
01516 for( unsigned int pos = 0;
01517 pos < str_P.length();
01518 ++pos )
01519 {
01520 if( str_P[ pos ] == (QChar)'\\'
01521 || str_P[ pos ] == (QChar)'"' )
01522 ret += '\\';
01523 ret += str_P[ pos ];
01524 }
01525 return ret;
01526 }
01527
01528 #include "tdestartupinfo.moc"
01529 #endif