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 )
129 if( !tdeApp->getDisplay())
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 tdeApp->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( tdeApp->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( tdeApp->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 tdeApp->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.
const char * name(StdAction id)
static int currentDesktop()
Convenience function to access the current desktop.
TQString description(StdAccel id)
kndbgstream & endl(kndbgstream &s)
Does nothing.
static void setOnDesktop(WId win, int desktop)
Moves window win to desktop desktop.