29 #define KSTARTUPINFO_ALL_DEBUG
30 #warning Extra TDEStartupInfo debug messages enabled.
43 #include "tdestartupinfo.h"
53 #include <tdeapplication.h>
56 #include <twinmodule.h>
57 #include <kxmessages.h>
61 static const char*
const NET_STARTUP_MSG =
"_NET_STARTUP_INFO";
62 static const char*
const NET_STARTUP_WINDOW =
"_NET_STARTUP_ID";
65 static const char*
const NET_STARTUP_ENV =
"DESKTOP_STARTUP_ID";
67 static bool auto_app_started_sending =
true;
69 static long get_num(
const TQString& item_P );
70 static unsigned long get_unum(
const TQString& item_P );
71 static TQString get_str(
const TQString& item_P );
72 static TQCString get_cstr(
const TQString& item_P );
73 static TQStringList get_fields(
const TQString& txt_P );
74 static TQString escape_str(
const TQString& str_P );
76 static Atom utf8_string_atom = None;
78 class TDEStartupInfo::Data
79 :
public TDEStartupInfoData
82 Data() : TDEStartupInfoData(), age(0) {}
83 Data(
const TQString& txt_P )
84 : TDEStartupInfoData( txt_P ), age( 0 ) {}
88 struct TDEStartupInfoPrivate
91 TQMap< TDEStartupInfoId, TDEStartupInfo::Data > startups;
93 TQMap< TDEStartupInfoId, TDEStartupInfo::Data > silent_startups;
95 TQMap< TDEStartupInfoId, TDEStartupInfo::Data > uninited_startups;
102 TDEStartupInfoPrivate(
int flags_P )
105 msgs( NET_STARTUP_MSG, NULL, false ),
110 TDEStartupInfo::TDEStartupInfo(
int flags_P, TQObject* parent_P,
const char* name_P )
111 : TQObject( parent_P, name_P ),
112 timeout( 60 ), d( NULL )
117 TDEStartupInfo::TDEStartupInfo(
bool clean_on_cantdetect_P, TQObject* parent_P,
const char* name_P )
118 : TQObject( parent_P, name_P ),
119 timeout( 60 ), d( NULL )
121 init( clean_on_cantdetect_P ? CleanOnCantDetect : 0 );
124 void TDEStartupInfo::init(
int flags_P )
132 d =
new TDEStartupInfoPrivate( flags_P );
134 if( !( d->flags & DisableKWinModule ))
137 connect( d->wm_module, TQ_SIGNAL( windowAdded( WId )), TQ_SLOT( slot_window_added( WId )));
138 connect( d->wm_module, TQ_SIGNAL( systemTrayWindowAdded( WId )), TQ_SLOT( slot_window_added( WId )));
142 connect( &d->msgs, TQ_SIGNAL( gotMessage(
const TQString& )), TQ_SLOT( got_message(
const TQString& )));
144 d->cleanup =
new TQTimer(
this,
"cleanup" );
145 connect( d->cleanup, TQ_SIGNAL( timeout()), TQ_SLOT( startups_cleanup()));
148 TDEStartupInfo::~TDEStartupInfo()
153 void TDEStartupInfo::got_message(
const TQString& msg_P )
156 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] got:" << msg_P <<
endl;
157 TQString msg = msg_P.stripWhiteSpace();
158 if( msg.startsWith(
"new:" ))
159 got_startup_info( msg.mid( 4 ),
false );
160 else if( msg.startsWith(
"change:" ))
161 got_startup_info( msg.mid( 7 ),
true );
162 else if( msg.startsWith(
"remove:" ))
163 got_remove_startup_info( msg.mid( 7 ));
174 class DelayedWindowEvent
175 :
public TQCustomEvent
178 DelayedWindowEvent( WId w_P )
179 : TQCustomEvent( TQEvent::User + 15 ), w( w_P ) {}
184 void TDEStartupInfo::slot_window_added( WId w_P )
186 kapp->postEvent(
this,
new DelayedWindowEvent( w_P ));
189 void TDEStartupInfo::customEvent( TQCustomEvent* e_P )
191 if( e_P->type() == TQEvent::User + 15 )
192 window_added(
static_cast< DelayedWindowEvent*
>( e_P )->w );
194 TQObject::customEvent( e_P );
197 void TDEStartupInfo::window_added( WId w_P )
200 TDEStartupInfoData data;
201 startup_t ret = check_startup_internal( w_P, &
id, &data );
205 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] new window match" <<
endl;
210 if( d->flags & CleanOnCantDetect )
211 clean_all_noncompliant();
216 void TDEStartupInfo::got_startup_info(
const TQString& msg_P,
bool update_P )
218 TDEStartupInfoId id( msg_P );
221 TDEStartupInfo::Data data( msg_P );
222 new_startup_info_internal(
id, data, update_P );
225 void TDEStartupInfo::new_startup_info_internal(
const TDEStartupInfoId& id_P,
226 Data& data_P,
bool update_P )
232 if( d->startups.contains( id_P ))
234 d->startups[ id_P ].update( data_P );
235 d->startups[ id_P ].age = 0;
236 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] updating" <<
endl;
237 if( d->startups[ id_P ].silent() == Data::Yes
238 && !( d->flags & AnnounceSilenceChanges ))
240 d->silent_startups[ id_P ] = d->startups[ id_P ];
241 d->startups.remove( id_P );
242 emit gotRemoveStartup( id_P, d->silent_startups[ id_P ] );
245 emit gotStartupChange( id_P, d->startups[ id_P ] );
248 if( d->silent_startups.contains( id_P ))
250 d->silent_startups[ id_P ].update( data_P );
251 d->silent_startups[ id_P ].age = 0;
252 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] updating silenced" <<
endl;
253 if( d->silent_startups[ id_P ].silent() != Data::Yes )
255 d->startups[ id_P ] = d->silent_startups[ id_P ];
256 d->silent_startups.remove( id_P );
257 emit gotNewStartup( id_P, d->startups[ id_P ] );
260 emit gotStartupChange( id_P, d->silent_startups[ id_P ] );
263 if( d->uninited_startups.contains( id_P ))
265 d->uninited_startups[ id_P ].update( data_P );
266 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] updating uninited" <<
endl;
269 d->startups[ id_P ] = d->uninited_startups[ id_P ];
270 d->uninited_startups.remove( id_P );
271 emit gotNewStartup( id_P, d->startups[ id_P ] );
279 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] adding uninited" <<
endl;
280 d->uninited_startups.insert( id_P, data_P );
282 else if( data_P.silent() != Data::Yes || d->flags & AnnounceSilenceChanges )
284 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] adding" <<
endl;
285 d->startups.insert( id_P, data_P );
286 emit gotNewStartup( id_P, data_P );
290 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] adding silent" <<
endl;
291 d->silent_startups.insert( id_P, data_P );
293 d->cleanup->start( 1000 );
296 void TDEStartupInfo::got_remove_startup_info(
const TQString& msg_P )
298 TDEStartupInfoId id( msg_P );
299 TDEStartupInfoData data( msg_P );
300 if( data.pids().count() > 0 )
303 remove_startup_pids(
id, data );
305 remove_startup_pids( data );
308 remove_startup_info_internal(
id );
311 void TDEStartupInfo::remove_startup_info_internal(
const TDEStartupInfoId& id_P )
315 if( d->startups.contains( id_P ))
317 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] removing" <<
endl;
318 emit gotRemoveStartup( id_P, d->startups[ id_P ]);
319 d->startups.remove( id_P );
321 else if( d->silent_startups.contains( id_P ))
323 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] removing silent" <<
endl;
324 d->silent_startups.remove( id_P );
326 else if( d->uninited_startups.contains( id_P ))
328 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] removing uninited" <<
endl;
329 d->uninited_startups.remove( id_P );
334 void TDEStartupInfo::remove_startup_pids(
const TDEStartupInfoData& data_P )
338 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->startups.begin();
339 it != d->startups.end();
342 if( ( *it ).hostname() != data_P.hostname())
344 if( !( *it ).is_pid( data_P.pids().first()))
346 remove_startup_pids( it.key(), data_P );
351 void TDEStartupInfo::remove_startup_pids(
const TDEStartupInfoId& id_P,
352 const TDEStartupInfoData& data_P )
356 kdFatal( data_P.pids().count() == 0, 172 );
358 if( d->startups.contains( id_P ))
359 data = &d->startups[ id_P ];
360 else if( d->silent_startups.contains( id_P ))
361 data = &d->silent_startups[ id_P ];
362 else if( d->uninited_startups.contains( id_P ))
363 data = &d->uninited_startups[ id_P ];
366 for( TQValueList< pid_t >::ConstIterator it2 = data_P.pids().begin();
367 it2 != data_P.pids().end();
369 data->remove_pid( *it2 );
370 if( data->pids().count() == 0 )
371 remove_startup_info_internal( id_P );
374 bool TDEStartupInfo::sendStartup(
const TDEStartupInfoId& id_P,
const TDEStartupInfoData& data_P )
379 TQString msg = TQString::fromLatin1(
"new: %1 %2" )
380 .arg( id_P.to_text()).arg( data_P.to_text());
381 msg = check_required_startup_fields( msg, data_P, tqt_xscreen());
382 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] sending " << msg <<
endl;
383 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1,
false );
387 bool TDEStartupInfo::sendStartupX( Display* disp_P,
const TDEStartupInfoId& id_P,
388 const TDEStartupInfoData& data_P )
392 TQString msg = TQString::fromLatin1(
"new: %1 %2" )
393 .arg( id_P.to_text()).arg( data_P.to_text());
394 msg = check_required_startup_fields( msg, data_P, DefaultScreen( disp_P ));
395 #ifdef KSTARTUPINFO_ALL_DEBUG
396 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] sending " << msg <<
endl;
398 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1,
false );
401 TQString TDEStartupInfo::check_required_startup_fields(
const TQString& msg,
const TDEStartupInfoData& data_P,
405 if( data_P.name().isEmpty())
408 TQString
name = data_P.bin();
411 ret += TQString(
" NAME=\"%1\"" ).arg( escape_str( name ));
413 if( data_P.screen() == -1 )
414 ret += TQString(
" SCREEN=%1" ).arg( screen );
418 bool TDEStartupInfo::sendChange(
const TDEStartupInfoId& id_P,
const TDEStartupInfoData& data_P )
423 TQString msg = TQString::fromLatin1(
"change: %1 %2" )
424 .arg( id_P.to_text()).arg( data_P.to_text());
425 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] sending " << msg <<
endl;
426 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1,
false );
430 bool TDEStartupInfo::sendChangeX( Display* disp_P,
const TDEStartupInfoId& id_P,
431 const TDEStartupInfoData& data_P )
435 TQString msg = TQString::fromLatin1(
"change: %1 %2" )
436 .arg( id_P.to_text()).arg( data_P.to_text());
437 #ifdef KSTARTUPINFO_ALL_DEBUG
438 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] sending " << msg <<
endl;
440 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1,
false );
443 bool TDEStartupInfo::sendFinish(
const TDEStartupInfoId& id_P )
448 TQString msg = TQString::fromLatin1(
"remove: %1" ).arg( id_P.to_text());
449 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] sending " << msg <<
endl;
450 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1,
false );
454 bool TDEStartupInfo::sendFinishX( Display* disp_P,
const TDEStartupInfoId& id_P )
458 TQString msg = TQString::fromLatin1(
"remove: %1" ).arg( id_P.to_text());
459 #ifdef KSTARTUPINFO_ALL_DEBUG
460 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] sending " << msg <<
endl;
462 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1,
false );
465 bool TDEStartupInfo::sendFinish(
const TDEStartupInfoId& id_P,
const TDEStartupInfoData& data_P )
470 TQString msg = TQString::fromLatin1(
"remove: %1 %2" )
471 .arg( id_P.to_text()).arg( data_P.to_text());
472 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] sending " << msg <<
endl;
473 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1,
false );
477 bool TDEStartupInfo::sendFinishX( Display* disp_P,
const TDEStartupInfoId& id_P,
478 const TDEStartupInfoData& data_P )
482 TQString msg = TQString::fromLatin1(
"remove: %1 %2" )
483 .arg( id_P.to_text()).arg( data_P.to_text());
484 #ifdef KSTARTUPINFO_ALL_DEBUG
485 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] sending " << msg <<
endl;
487 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1,
false );
490 void TDEStartupInfo::appStarted()
493 appStarted( kapp->startupId());
495 appStarted( TDEStartupInfo::currentStartupIdEnv().
id());
498 void TDEStartupInfo::appStarted(
const TQCString& startup_id )
501 id.initId( startup_id );
505 TDEStartupInfo::sendFinish(
id );
506 else if( getenv(
"DISPLAY" ) != NULL )
509 Display* disp = XOpenDisplay( NULL );
512 TDEStartupInfo::sendFinishX( disp,
id );
513 XCloseDisplay( disp );
519 void TDEStartupInfo::disableAutoAppStartedSending(
bool disable )
521 auto_app_started_sending = !disable;
524 void TDEStartupInfo::silenceStartup(
bool silence )
527 id.initId( kapp->startupId());
530 TDEStartupInfoData data;
531 data.setSilent( silence ? TDEStartupInfoData::Yes : TDEStartupInfoData::No );
532 sendChange(
id, data );
535 void TDEStartupInfo::handleAutoAppStartedSending()
537 if( auto_app_started_sending )
541 void TDEStartupInfo::setNewStartupId( TQWidget* window,
const TQCString& startup_id )
543 bool activate =
true;
544 kapp->setStartupId( startup_id );
547 if( !startup_id.isEmpty() && startup_id !=
"0" )
549 NETRootInfo i( tqt_xdisplay(), NET::Supported );
550 if( i.isSupported( NET::WM2StartupId ))
552 TDEStartupInfo::setWindowStartupId( window->winId(), startup_id );
566 TDEStartupInfo::handleAutoAppStartedSending();
569 TDEStartupInfo::startup_t TDEStartupInfo::checkStartup( WId w_P, TDEStartupInfoId& id_O,
570 TDEStartupInfoData& data_O )
572 return check_startup_internal( w_P, &id_O, &data_O );
575 TDEStartupInfo::startup_t TDEStartupInfo::checkStartup( WId w_P, TDEStartupInfoId& id_O )
577 return check_startup_internal( w_P, &id_O, NULL );
580 TDEStartupInfo::startup_t TDEStartupInfo::checkStartup( WId w_P, TDEStartupInfoData& data_O )
582 return check_startup_internal( w_P, NULL, &data_O );
585 TDEStartupInfo::startup_t TDEStartupInfo::checkStartup( WId w_P )
587 return check_startup_internal( w_P, NULL, NULL );
590 TDEStartupInfo::startup_t TDEStartupInfo::check_startup_internal( WId w_P, TDEStartupInfoId* id_O,
591 TDEStartupInfoData* data_O )
595 if( d->startups.count() == 0 )
604 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] check_startup" <<
endl;
605 TQCString
id = windowStartupId( w_P );
608 if(
id.isEmpty() ||
id ==
"0" )
610 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] ignore" <<
endl;
613 return find_id(
id, id_O, data_O ) ? Match : NoMatch;
616 NETWinInfo info( tqt_xdisplay(), w_P, tqt_xrootwin(),
617 NET::WMWindowType | NET::WMPid | NET::WMState );
618 pid_t pid = info.pid();
621 TQCString hostname = get_window_hostname( w_P );
622 if( !hostname.isEmpty()
623 && find_pid( pid, hostname, id_O, data_O ))
628 if( XGetClassHint( tqt_xdisplay(), w_P, &hint ) != 0 )
630 TQCString res_name = hint.res_name;
631 TQCString res_class = hint.res_class;
632 XFree( hint.res_name );
633 XFree( hint.res_class );
634 if( find_wclass( res_name, res_class, id_O, data_O ))
638 NET::WindowType type = info.windowType( NET::NormalMask | NET::DesktopMask
639 | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
640 | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
641 if( type != NET::Normal
643 && type != NET::Unknown
644 && type != NET::Dialog
649 Window transient_for;
650 if( XGetTransientForHint( tqt_xdisplay(),
static_cast< Window
>( w_P ), &transient_for )
651 &&
static_cast< WId
>( transient_for ) != tqt_xrootwin()
652 && transient_for != None )
655 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] check_startup:cantdetect" <<
endl;
659 bool TDEStartupInfo::find_id(
const TQCString& id_P, TDEStartupInfoId* id_O,
660 TDEStartupInfoData* data_O )
664 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] find_id:" << id_P <<
endl;
667 if( d->startups.contains(
id ))
672 *data_O = d->startups[ id ];
673 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] check_startup_id:match" <<
endl;
679 bool TDEStartupInfo::find_pid( pid_t pid_P,
const TQCString& hostname_P,
680 TDEStartupInfoId* id_O, TDEStartupInfoData* data_O )
684 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] find_pid:" << pid_P <<
endl;
685 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->startups.begin();
686 it != d->startups.end();
689 if( ( *it ).is_pid( pid_P ) && ( *it ).hostname() == hostname_P )
696 remove_startup_info_internal( it.key());
697 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] check_startup_pid:match" <<
endl;
704 bool TDEStartupInfo::find_wclass( TQCString res_name, TQCString res_class,
705 TDEStartupInfoId* id_O, TDEStartupInfoData* data_O )
709 res_name = res_name.lower();
710 res_class = res_class.lower();
711 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] find_wclass:" << res_name <<
":" << res_class <<
endl;
712 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->startups.begin();
713 it != d->startups.end();
716 const TQCString wmclass = ( *it ).findWMClass();
717 if( wmclass.lower() == res_name || wmclass.lower() == res_class )
724 remove_startup_info_internal( it.key());
725 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] check_startup_wclass:match" <<
endl;
733 static Atom net_startup_atom = None;
735 static TQCString read_startup_id_property( WId w_P )
738 unsigned char *name_ret;
741 unsigned long nitems_ret = 0, after_ret = 0;
742 if( XGetWindowProperty( tqt_xdisplay(), w_P, net_startup_atom, 0l, 4096,
743 False, utf8_string_atom, &type_ret, &format_ret, &nitems_ret, &after_ret, &name_ret )
746 if( type_ret == utf8_string_atom && format_ret == 8 && name_ret != NULL )
747 ret =
reinterpret_cast< char*
>( name_ret );
748 if ( name_ret != NULL )
756 TQCString TDEStartupInfo::windowStartupId( WId w_P )
759 if( net_startup_atom == None )
760 net_startup_atom = XInternAtom( tqt_xdisplay(), NET_STARTUP_WINDOW, False );
761 if( utf8_string_atom == None )
762 utf8_string_atom = XInternAtom( tqt_xdisplay(),
"UTF8_STRING", False );
763 TQCString ret = read_startup_id_property( w_P );
766 XWMHints* hints = XGetWMHints( tqt_xdisplay(), w_P );
767 if( hints && ( hints->flags & WindowGroupHint ) != 0 )
768 ret = read_startup_id_property( hints->window_group );
778 void TDEStartupInfo::setWindowStartupId( WId w_P,
const TQCString& id_P )
783 if( net_startup_atom == None )
784 net_startup_atom = XInternAtom( tqt_xdisplay(), NET_STARTUP_WINDOW, False );
785 if( utf8_string_atom == None )
786 utf8_string_atom = XInternAtom( tqt_xdisplay(),
"UTF8_STRING", False );
787 XChangeProperty( tqt_xdisplay(), w_P, net_startup_atom, utf8_string_atom, 8,
788 PropModeReplace,
reinterpret_cast< unsigned char*
>(
const_cast<TQCString&
>(id_P).data()), id_P.length());
792 TQCString TDEStartupInfo::get_window_hostname( WId w_P )
798 if( XGetWMClientMachine( tqt_xdisplay(), w_P, &tp ) != 0
799 && XTextPropertyToStringList( &tp, &hh, &cnt ) != 0 )
803 TQCString hostname = hh[ 0 ];
804 XFreeStringList( hh );
807 XFreeStringList( hh );
814 void TDEStartupInfo::setTimeout(
unsigned int secs_P )
818 TQTimer::singleShot( 0,
this, TQ_SLOT( startups_cleanup_no_age()));
821 void TDEStartupInfo::startups_cleanup_no_age()
823 startups_cleanup_internal(
false );
826 void TDEStartupInfo::startups_cleanup()
830 if( d->startups.count() == 0 && d->silent_startups.count() == 0
831 && d->uninited_startups.count() == 0 )
836 startups_cleanup_internal(
true );
839 void TDEStartupInfo::startups_cleanup_internal(
bool age_P )
843 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->startups.begin();
844 it != d->startups.end();
849 unsigned int tout = timeout;
850 if( ( *it ).silent() == Data::Yes )
852 if( ( *it ).age >= tout )
854 const TDEStartupInfoId&
key = it.key();
856 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] startups entry timeout:" <<
key.id() <<
endl;
857 remove_startup_info_internal( key );
862 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->silent_startups.begin();
863 it != d->silent_startups.end();
868 unsigned int tout = timeout;
869 if( ( *it ).silent() == Data::Yes )
871 if( ( *it ).age >= tout )
873 const TDEStartupInfoId&
key = it.key();
875 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] silent entry timeout:" <<
key.id() <<
endl;
876 remove_startup_info_internal( key );
881 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->uninited_startups.begin();
882 it != d->uninited_startups.end();
887 unsigned int tout = timeout;
888 if( ( *it ).silent() == Data::Yes )
890 if( ( *it ).age >= tout )
892 const TDEStartupInfoId&
key = it.key();
894 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] uninited entry timeout:" <<
key.id() <<
endl;
895 remove_startup_info_internal( key );
902 void TDEStartupInfo::clean_all_noncompliant()
906 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->startups.begin();
907 it != d->startups.end();
910 if( ( *it ).WMClass() !=
"0" )
915 const TDEStartupInfoId&
key = it.key();
917 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] entry cleaning:" <<
key.id() <<
endl;
918 remove_startup_info_internal( key );
922 TQCString TDEStartupInfo::createNewStartupId()
927 gettimeofday( &tm, NULL );
928 char hostname[ 256 ];
929 hostname[ 0 ] =
'\0';
930 if (!gethostname( hostname, 255 ))
931 hostname[
sizeof(hostname)-1] =
'\0';
932 TQCString
id = TQString(TQString(
"%1;%2;%3;%4_TIME%5" ).arg( hostname ).arg( tm.tv_sec )
933 .arg( tm.tv_usec ).arg( getpid()).arg( get_tqt_x_user_time() )).utf8();
934 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] creating: " <<
id <<
":" << tqAppName() <<
endl;
939 struct TDEStartupInfoIdPrivate
941 TDEStartupInfoIdPrivate() : id(
"" ) {}
945 const TQCString& TDEStartupInfoId::id()
const
951 TQString TDEStartupInfoId::to_text()
const
953 return TQString::fromLatin1(
" ID=\"%1\" " ).arg( escape_str(
id()));
956 TDEStartupInfoId::TDEStartupInfoId(
const TQString& txt_P )
958 d =
new TDEStartupInfoIdPrivate;
959 TQStringList items = get_fields( txt_P );
960 const TQString id_str = TQString::fromLatin1(
"ID=" );
961 for( TQStringList::Iterator it = items.begin();
965 if( ( *it ).startsWith( id_str ))
966 d->id = get_cstr( *it );
970 void TDEStartupInfoId::initId(
const TQCString& id_P )
975 #ifdef KSTARTUPINFO_ALL_DEBUG
976 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] using: " << d->id <<
endl;
980 const char* startup_env = getenv( NET_STARTUP_ENV );
981 if( startup_env != NULL && *startup_env !=
'\0' )
984 #ifdef KSTARTUPINFO_ALL_DEBUG
985 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] reusing: " << d->id <<
endl;
989 d->id = TDEStartupInfo::createNewStartupId();
992 bool TDEStartupInfoId::setupStartupEnv()
const
996 unsetenv( NET_STARTUP_ENV );
999 return setenv( NET_STARTUP_ENV,
id(),
true ) == 0;
1002 TDEStartupInfoId TDEStartupInfo::currentStartupIdEnv()
1004 const char* startup_env = getenv( NET_STARTUP_ENV );
1005 TDEStartupInfoId id;
1006 if( startup_env != NULL && *startup_env !=
'\0' )
1007 id.d->id = startup_env;
1013 void TDEStartupInfo::resetStartupEnv()
1015 unsetenv( NET_STARTUP_ENV );
1018 TDEStartupInfoId::TDEStartupInfoId()
1020 d =
new TDEStartupInfoIdPrivate;
1023 TDEStartupInfoId::~TDEStartupInfoId()
1028 TDEStartupInfoId::TDEStartupInfoId(
const TDEStartupInfoId& id_P )
1030 d =
new TDEStartupInfoIdPrivate( *id_P.d );
1033 TDEStartupInfoId& TDEStartupInfoId::operator=(
const TDEStartupInfoId& id_P )
1038 d =
new TDEStartupInfoIdPrivate( *id_P.d );
1042 bool TDEStartupInfoId::operator==(
const TDEStartupInfoId& id_P )
const
1044 return id() == id_P.id();
1047 bool TDEStartupInfoId::operator!=(
const TDEStartupInfoId& id_P )
const
1049 return !(*
this == id_P );
1053 bool TDEStartupInfoId::operator<(
const TDEStartupInfoId& id_P )
const
1055 return id() < id_P.id();
1058 bool TDEStartupInfoId::none()
const
1060 return d->id.isEmpty() || d->id ==
"0";
1063 unsigned long TDEStartupInfoId::timestamp()
const
1067 int pos = d->id.findRev(
"_TIME" );
1071 unsigned long time = d->id.mid( pos + 5 ).toULong( &ok );
1072 if( !ok && d->id[ pos + 5 ] ==
'-' )
1073 time = d->id.mid( pos + 5 ).toLong( &ok );
1081 int pos1 = d->id.findRev(
'/' );
1084 int pos2 = d->id.findRev(
'/', pos1 - 1 );
1088 unsigned long time = d->id.mid( pos2 + 1, pos1 - pos2 - 1 ).toULong( &ok );
1089 if( !ok && d->id[ pos2 + 1 ] ==
'-' )
1090 time = d->id.mid( pos2 + 1, pos1 - pos2 - 1 ).toLong( &ok );
1099 struct TDEStartupInfoDataPrivate
1101 TDEStartupInfoDataPrivate() : desktop( 0 ), wmclass(
"" ), hostname(
"" ),
1102 silent( TDEStartupInfoData::Unknown ), timestamp( -1U ), screen( -1 ), xinerama( -1 ), launched_by( 0 ) {}
1108 TQValueList< pid_t > pids;
1111 TDEStartupInfoData::TriState silent;
1112 unsigned long timestamp;
1118 TQString TDEStartupInfoData::to_text()
const
1121 if( !d->bin.isEmpty())
1122 ret += TQString::fromLatin1(
" BIN=\"%1\"" ).arg( escape_str( d->bin ));
1123 if( !d->name.isEmpty())
1124 ret += TQString::fromLatin1(
" NAME=\"%1\"" ).arg( escape_str( d->name ));
1125 if( !d->description.isEmpty())
1126 ret += TQString::fromLatin1(
" DESCRIPTION=\"%1\"" ).arg( escape_str( d->description ));
1127 if( !d->icon.isEmpty())
1128 ret += TQString::fromLatin1(
" ICON=%1" ).arg( d->icon );
1129 if( d->desktop != 0 )
1130 ret += TQString::fromLatin1(
" DESKTOP=%1" )
1131 .arg( d->desktop == NET::OnAllDesktops ? NET::OnAllDesktops : d->desktop - 1 );
1132 if( !d->wmclass.isEmpty())
1133 ret += TQString::fromLatin1(
" WMCLASS=\"%1\"" ).arg( TQString(d->wmclass) );
1134 if( !d->hostname.isEmpty())
1135 ret += TQString::fromLatin1(
" HOSTNAME=%1" ).arg( TQString(d->hostname) );
1136 for( TQValueList< pid_t >::ConstIterator it = d->pids.begin();
1137 it != d->pids.end();
1139 ret += TQString::fromLatin1(
" PID=%1" ).arg( *it );
1140 if( d->silent != Unknown )
1141 ret += TQString::fromLatin1(
" SILENT=%1" ).arg( d->silent == Yes ? 1 : 0 );
1142 if( d->timestamp != -1U )
1143 ret += TQString::fromLatin1(
" TIMESTAMP=%1" ).arg( d->timestamp );
1144 if( d->screen != -1 )
1145 ret += TQString::fromLatin1(
" SCREEN=%1" ).arg( d->screen );
1146 if( d->xinerama != -1 )
1147 ret += TQString::fromLatin1(
" XINERAMA=%1" ).arg( d->xinerama );
1148 if( d->launched_by != 0 )
1149 ret += TQString::fromLatin1(
" LAUNCHED_BY=%1" ).arg( d->launched_by );
1153 TDEStartupInfoData::TDEStartupInfoData(
const TQString& txt_P )
1155 d =
new TDEStartupInfoDataPrivate;
1156 TQStringList items = get_fields( txt_P );
1157 const TQString bin_str = TQString::fromLatin1(
"BIN=" );
1158 const TQString name_str = TQString::fromLatin1(
"NAME=" );
1159 const TQString description_str = TQString::fromLatin1(
"DESCRIPTION=" );
1160 const TQString icon_str = TQString::fromLatin1(
"ICON=" );
1161 const TQString desktop_str = TQString::fromLatin1(
"DESKTOP=" );
1162 const TQString wmclass_str = TQString::fromLatin1(
"WMCLASS=" );
1163 const TQString hostname_str = TQString::fromLatin1(
"HOSTNAME=" );
1164 const TQString pid_str = TQString::fromLatin1(
"PID=" );
1165 const TQString silent_str = TQString::fromLatin1(
"SILENT=" );
1166 const TQString timestamp_str = TQString::fromLatin1(
"TIMESTAMP=" );
1167 const TQString screen_str = TQString::fromLatin1(
"SCREEN=" );
1168 const TQString xinerama_str = TQString::fromLatin1(
"XINERAMA=" );
1169 const TQString launched_by_str = TQString::fromLatin1(
"LAUNCHED_BY=" );
1170 for( TQStringList::Iterator it = items.begin();
1174 if( ( *it ).startsWith( bin_str ))
1175 d->bin = get_str( *it );
1176 else if( ( *it ).startsWith( name_str ))
1177 d->name = get_str( *it );
1178 else if( ( *it ).startsWith( description_str ))
1179 d->description = get_str( *it );
1180 else if( ( *it ).startsWith( icon_str ))
1181 d->icon = get_str( *it );
1182 else if( ( *it ).startsWith( desktop_str ))
1184 d->desktop = get_num( *it );
1185 if( d->desktop != NET::OnAllDesktops )
1188 else if( ( *it ).startsWith( wmclass_str ))
1189 d->wmclass = get_cstr( *it );
1190 else if( ( *it ).startsWith( hostname_str ))
1191 d->hostname = get_cstr( *it );
1192 else if( ( *it ).startsWith( pid_str ))
1193 addPid( get_num( *it ));
1194 else if( ( *it ).startsWith( silent_str ))
1195 d->silent = get_num( *it ) != 0 ? Yes : No;
1196 else if( ( *it ).startsWith( timestamp_str ))
1197 d->timestamp = get_unum( *it );
1198 else if( ( *it ).startsWith( screen_str ))
1199 d->screen = get_num( *it );
1200 else if( ( *it ).startsWith( xinerama_str ))
1201 d->xinerama = get_num( *it );
1202 else if( ( *it ).startsWith( launched_by_str ))
1203 d->launched_by = get_num( *it );
1207 TDEStartupInfoData::TDEStartupInfoData(
const TDEStartupInfoData& data )
1209 d =
new TDEStartupInfoDataPrivate( *data.d );
1212 TDEStartupInfoData& TDEStartupInfoData::operator=(
const TDEStartupInfoData& data )
1217 d =
new TDEStartupInfoDataPrivate( *data.d );
1221 void TDEStartupInfoData::update(
const TDEStartupInfoData& data_P )
1223 if( !data_P.bin().isEmpty())
1224 d->bin = data_P.bin();
1225 if( !data_P.name().isEmpty() &&
name().isEmpty())
1226 d->name = data_P.name();
1227 if( !data_P.description().isEmpty() &&
description().isEmpty())
1228 d->description = data_P.description();
1229 if( !data_P.icon().isEmpty() && icon().isEmpty())
1230 d->icon = data_P.icon();
1231 if( data_P.desktop() != 0 && desktop() == 0 )
1232 d->desktop = data_P.desktop();
1233 if( !data_P.d->wmclass.isEmpty())
1234 d->wmclass = data_P.d->wmclass;
1235 if( !data_P.d->hostname.isEmpty())
1236 d->hostname = data_P.d->hostname;
1237 for( TQValueList< pid_t >::ConstIterator it = data_P.d->pids.begin();
1238 it != data_P.d->pids.end();
1241 if( data_P.silent() != Unknown )
1242 d->silent = data_P.silent();
1243 if( data_P.timestamp() != -1U && timestamp() == -1U )
1244 d->timestamp = data_P.timestamp();
1245 if( data_P.screen() != -1 )
1246 d->screen = data_P.screen();
1247 if( data_P.xinerama() != -1 && xinerama() != -1 )
1248 d->xinerama = data_P.xinerama();
1249 if( data_P.launchedBy() != 0 && launchedBy() != 0 )
1250 d->launched_by = data_P.launchedBy();
1253 TDEStartupInfoData::TDEStartupInfoData()
1255 d =
new TDEStartupInfoDataPrivate;
1258 TDEStartupInfoData::~TDEStartupInfoData()
1263 void TDEStartupInfoData::setBin(
const TQString& bin_P )
1268 const TQString& TDEStartupInfoData::bin()
const
1273 void TDEStartupInfoData::setName(
const TQString& name_P )
1278 const TQString& TDEStartupInfoData::name()
const
1283 const TQString& TDEStartupInfoData::findName()
const
1285 if( !
name().isEmpty())
1290 void TDEStartupInfoData::setDescription(
const TQString& desc_P )
1292 d->description = desc_P;
1295 const TQString& TDEStartupInfoData::description()
const
1297 return d->description;
1300 const TQString& TDEStartupInfoData::findDescription()
const
1307 void TDEStartupInfoData::setIcon(
const TQString& icon_P )
1312 const TQString& TDEStartupInfoData::findIcon()
const
1314 if( !icon().isEmpty())
1319 const TQString& TDEStartupInfoData::icon()
const
1324 void TDEStartupInfoData::setDesktop(
int desktop_P )
1326 d->desktop = desktop_P;
1329 int TDEStartupInfoData::desktop()
const
1334 void TDEStartupInfoData::setWMClass(
const TQCString& wmclass_P )
1336 d->wmclass = wmclass_P;
1339 const TQCString TDEStartupInfoData::findWMClass()
const
1341 if( !WMClass().isEmpty() && WMClass() !=
"0" )
1343 return bin().utf8();
1346 const TQCString& TDEStartupInfoData::WMClass()
const
1351 void TDEStartupInfoData::setHostname(
const TQCString& hostname_P )
1353 if( !hostname_P.isNull())
1354 d->hostname = hostname_P;
1359 if (!gethostname( tmp, 255 ))
1360 tmp[
sizeof(tmp)-1] =
'\0';
1365 const TQCString& TDEStartupInfoData::hostname()
const
1370 void TDEStartupInfoData::addPid( pid_t pid_P )
1372 if( !d->pids.contains( pid_P ))
1373 d->pids.append( pid_P );
1376 void TDEStartupInfoData::remove_pid( pid_t pid_P )
1378 d->pids.remove( pid_P );
1381 const TQValueList< pid_t >& TDEStartupInfoData::pids()
const
1386 bool TDEStartupInfoData::is_pid( pid_t pid_P )
const
1388 return d->pids.contains( pid_P );
1391 void TDEStartupInfoData::setSilent( TriState state_P )
1393 d->silent = state_P;
1396 TDEStartupInfoData::TriState TDEStartupInfoData::silent()
const
1401 void TDEStartupInfoData::setTimestamp(
unsigned long time )
1403 d->timestamp = time;
1406 unsigned long TDEStartupInfoData::timestamp()
const
1408 return d->timestamp;
1411 void TDEStartupInfoData::setScreen(
int screen )
1416 int TDEStartupInfoData::screen()
const
1421 void TDEStartupInfoData::setXinerama(
int xinerama )
1423 d->xinerama = xinerama;
1426 int TDEStartupInfoData::xinerama()
const
1431 void TDEStartupInfoData::setLaunchedBy( WId window )
1433 d->launched_by = window;
1436 WId TDEStartupInfoData::launchedBy()
const
1438 return d->launched_by;
1442 long get_num(
const TQString& item_P )
1444 unsigned int pos = item_P.find(
'=' );
1445 return item_P.mid( pos + 1 ).toLong();
1449 unsigned long get_unum(
const TQString& item_P )
1451 unsigned int pos = item_P.find(
'=' );
1452 return item_P.mid( pos + 1 ).toULong();
1456 TQString get_str(
const TQString& item_P )
1458 unsigned int pos = item_P.find(
'=' );
1459 if( item_P.length() > pos + 2 && item_P[ pos + 1 ] == (TQChar)
'\"' )
1461 int pos2 = item_P.left( pos + 2 ).find(
'\"' );
1463 return TQString::null;
1464 return item_P.mid( pos + 2, pos2 - 2 - pos );
1466 return item_P.mid( pos + 1 );
1470 TQCString get_cstr(
const TQString& item_P )
1472 return get_str( item_P ).utf8();
1476 TQStringList get_fields(
const TQString& txt_P )
1478 TQString txt = txt_P.simplifyWhiteSpace();
1482 bool escape =
false;
1483 for(
unsigned int pos = 0;
1492 else if( txt[ pos ] ==
'\\' )
1494 else if( txt[ pos ] ==
'\"' )
1496 else if( txt[ pos ] ==
' ' && !in )
1508 static TQString escape_str(
const TQString& str_P )
1511 for(
unsigned int pos = 0;
1512 pos < str_P.length();
1515 if( str_P[ pos ] == (TQChar)
'\\'
1516 || str_P[ pos ] == (TQChar)
'"' )
1518 ret += str_P[ pos ];
1523 #include "tdestartupinfo.moc"
The class KWinModule provides information about the state of the window manager as required by window...
static void forceActiveWindow(WId win, long time=0)
Sets window win to be the active window.
static void setOnDesktop(WId win, int desktop)
Moves window win to desktop desktop.
static int currentDesktop()
Convenience function to access the current desktop.
static TDEApplication * kApplication()
Returns the current application object.
kdbgstream kdFatal(int area=0)
Returns a fatal error stream.
kdbgstream kdDebug(int area=0)
Returns a debug stream.
kdbgstream & endl(kdbgstream &s)
Prints an "\n".
const char * name(StdAction id)
TQString description(StdAccel id)