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