29 #define KSTARTUPINFO_ALL_DEBUG
30 #warning Extra TDEStartupInfo debug messages enabled.
44 #ifndef QT_CLEAN_NAMESPACE
45 #define QT_CLEAN_NAMESPACE
48 #include "tdestartupinfo.h"
58 #include <tdeapplication.h>
61 #include <twinmodule.h>
62 #include <kxmessages.h>
66 static const char*
const NET_STARTUP_MSG =
"_NET_STARTUP_INFO";
67 static const char*
const NET_STARTUP_WINDOW =
"_NET_STARTUP_ID";
70 static const char*
const NET_STARTUP_ENV =
"DESKTOP_STARTUP_ID";
72 static bool auto_app_started_sending =
true;
74 static long get_num(
const TQString& item_P );
75 static unsigned long get_unum(
const TQString& item_P );
76 static TQString get_str(
const TQString& item_P );
77 static TQCString get_cstr(
const TQString& item_P );
78 static TQStringList get_fields(
const TQString& txt_P );
79 static TQString escape_str(
const TQString& str_P );
81 static Atom utf8_string_atom = None;
83 class TDEStartupInfo::Data
84 :
public TDEStartupInfoData
87 Data() : TDEStartupInfoData(), age(0) {}
88 Data(
const TQString& txt_P )
89 : TDEStartupInfoData( txt_P ), age( 0 ) {}
93 struct TDEStartupInfoPrivate
96 TQMap< TDEStartupInfoId, TDEStartupInfo::Data > startups;
98 TQMap< TDEStartupInfoId, TDEStartupInfo::Data > silent_startups;
100 TQMap< TDEStartupInfoId, TDEStartupInfo::Data > uninited_startups;
107 TDEStartupInfoPrivate(
int flags_P )
110 msgs( NET_STARTUP_MSG, NULL, false ),
115 TDEStartupInfo::TDEStartupInfo(
int flags_P, TQObject* parent_P,
const char* name_P )
116 : TQObject( parent_P, name_P ),
117 timeout( 60 ), d( NULL )
122 TDEStartupInfo::TDEStartupInfo(
bool clean_on_cantdetect_P, TQObject* parent_P,
const char* name_P )
123 : TQObject( parent_P, name_P ),
124 timeout( 60 ), d( NULL )
126 init( clean_on_cantdetect_P ? CleanOnCantDetect : 0 );
129 void TDEStartupInfo::init(
int flags_P )
137 d =
new TDEStartupInfoPrivate( flags_P );
139 if( !( d->flags & DisableKWinModule ))
142 connect( d->wm_module, TQT_SIGNAL( windowAdded( WId )), TQT_SLOT( slot_window_added( WId )));
143 connect( d->wm_module, TQT_SIGNAL( systemTrayWindowAdded( WId )), TQT_SLOT( slot_window_added( WId )));
147 connect( &d->msgs, TQT_SIGNAL( gotMessage(
const TQString& )), TQT_SLOT( got_message(
const TQString& )));
149 d->cleanup =
new TQTimer(
this,
"cleanup" );
150 connect( d->cleanup, TQT_SIGNAL( timeout()), TQT_SLOT( startups_cleanup()));
153 TDEStartupInfo::~TDEStartupInfo()
158 void TDEStartupInfo::got_message(
const TQString& msg_P )
161 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] got:" << msg_P <<
endl;
162 TQString msg = msg_P.stripWhiteSpace();
163 if( msg.startsWith(
"new:" ))
164 got_startup_info( msg.mid( 4 ), false );
165 else if( msg.startsWith(
"change:" ))
166 got_startup_info( msg.mid( 7 ), true );
167 else if( msg.startsWith(
"remove:" ))
168 got_remove_startup_info( msg.mid( 7 ));
179 class DelayedWindowEvent
180 :
public TQCustomEvent
183 DelayedWindowEvent( WId w_P )
184 : TQCustomEvent( TQEvent::User + 15 ), w( w_P ) {}
189 void TDEStartupInfo::slot_window_added( WId w_P )
191 kapp->postEvent(
this,
new DelayedWindowEvent( w_P ));
194 void TDEStartupInfo::customEvent( TQCustomEvent* e_P )
196 if( e_P->type() == TQEvent::User + 15 )
197 window_added( static_cast< DelayedWindowEvent* >( e_P )->w );
199 TQObject::customEvent( e_P );
202 void TDEStartupInfo::window_added( WId w_P )
205 TDEStartupInfoData data;
206 startup_t ret = check_startup_internal( w_P, &
id, &data );
210 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] new window match" <<
endl;
215 if( d->flags & CleanOnCantDetect )
216 clean_all_noncompliant();
221 void TDEStartupInfo::got_startup_info(
const TQString& msg_P,
bool update_P )
223 TDEStartupInfoId id( msg_P );
226 TDEStartupInfo::Data data( msg_P );
227 new_startup_info_internal(
id, data, update_P );
230 void TDEStartupInfo::new_startup_info_internal(
const TDEStartupInfoId& id_P,
231 Data& data_P,
bool update_P )
237 if( d->startups.contains( id_P ))
239 d->startups[ id_P ].update( data_P );
240 d->startups[ id_P ].age = 0;
241 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] updating" <<
endl;
242 if( d->startups[ id_P ].silent() == Data::Yes
243 && !( d->flags & AnnounceSilenceChanges ))
245 d->silent_startups[ id_P ] = d->startups[ id_P ];
246 d->startups.remove( id_P );
247 emit gotRemoveStartup( id_P, d->silent_startups[ id_P ] );
250 emit gotStartupChange( id_P, d->startups[ id_P ] );
253 if( d->silent_startups.contains( id_P ))
255 d->silent_startups[ id_P ].update( data_P );
256 d->silent_startups[ id_P ].age = 0;
257 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] updating silenced" <<
endl;
258 if( d->silent_startups[ id_P ].silent() != Data::Yes )
260 d->startups[ id_P ] = d->silent_startups[ id_P ];
261 d->silent_startups.remove( id_P );
262 emit gotNewStartup( id_P, d->startups[ id_P ] );
265 emit gotStartupChange( id_P, d->silent_startups[ id_P ] );
268 if( d->uninited_startups.contains( id_P ))
270 d->uninited_startups[ id_P ].update( data_P );
271 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] updating uninited" <<
endl;
274 d->startups[ id_P ] = d->uninited_startups[ id_P ];
275 d->uninited_startups.remove( id_P );
276 emit gotNewStartup( id_P, d->startups[ id_P ] );
284 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] adding uninited" <<
endl;
285 d->uninited_startups.insert( id_P, data_P );
287 else if( data_P.silent() != Data::Yes || d->flags & AnnounceSilenceChanges )
289 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] adding" <<
endl;
290 d->startups.insert( id_P, data_P );
291 emit gotNewStartup( id_P, data_P );
295 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] adding silent" <<
endl;
296 d->silent_startups.insert( id_P, data_P );
298 d->cleanup->start( 1000 );
301 void TDEStartupInfo::got_remove_startup_info(
const TQString& msg_P )
303 TDEStartupInfoId id( msg_P );
304 TDEStartupInfoData data( msg_P );
305 if( data.pids().count() > 0 )
308 remove_startup_pids(
id, data );
310 remove_startup_pids( data );
313 remove_startup_info_internal(
id );
316 void TDEStartupInfo::remove_startup_info_internal(
const TDEStartupInfoId& id_P )
320 if( d->startups.contains( id_P ))
322 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] removing" <<
endl;
323 emit gotRemoveStartup( id_P, d->startups[ id_P ]);
324 d->startups.remove( id_P );
326 else if( d->silent_startups.contains( id_P ))
328 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] removing silent" <<
endl;
329 d->silent_startups.remove( id_P );
331 else if( d->uninited_startups.contains( id_P ))
333 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] removing uninited" <<
endl;
334 d->uninited_startups.remove( id_P );
339 void TDEStartupInfo::remove_startup_pids(
const TDEStartupInfoData& data_P )
343 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->startups.begin();
344 it != d->startups.end();
347 if( ( *it ).hostname() != data_P.hostname())
349 if( !( *it ).is_pid( data_P.pids().first()))
351 remove_startup_pids( it.key(), data_P );
356 void TDEStartupInfo::remove_startup_pids(
const TDEStartupInfoId& id_P,
357 const TDEStartupInfoData& data_P )
361 kdFatal( data_P.pids().count() == 0, 172 );
363 if( d->startups.contains( id_P ))
364 data = &d->startups[ id_P ];
365 else if( d->silent_startups.contains( id_P ))
366 data = &d->silent_startups[ id_P ];
367 else if( d->uninited_startups.contains( id_P ))
368 data = &d->uninited_startups[ id_P ];
371 for( TQValueList< pid_t >::ConstIterator it2 = data_P.pids().begin();
372 it2 != data_P.pids().end();
374 data->remove_pid( *it2 );
375 if( data->pids().count() == 0 )
376 remove_startup_info_internal( id_P );
379 bool TDEStartupInfo::sendStartup(
const TDEStartupInfoId& id_P,
const TDEStartupInfoData& data_P )
384 TQString msg = TQString::fromLatin1(
"new: %1 %2" )
385 .arg( id_P.to_text()).arg( data_P.to_text());
386 msg = check_required_startup_fields( msg, data_P, tqt_xscreen());
387 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] sending " << msg <<
endl;
388 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1,
false );
392 bool TDEStartupInfo::sendStartupX( Display* disp_P,
const TDEStartupInfoId& id_P,
393 const TDEStartupInfoData& data_P )
397 TQString msg = TQString::fromLatin1(
"new: %1 %2" )
398 .arg( id_P.to_text()).arg( data_P.to_text());
399 msg = check_required_startup_fields( msg, data_P, DefaultScreen( disp_P ));
400 #ifdef KSTARTUPINFO_ALL_DEBUG
401 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] sending " << msg <<
endl;
403 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1,
false );
406 TQString TDEStartupInfo::check_required_startup_fields(
const TQString& msg,
const TDEStartupInfoData& data_P,
410 if( data_P.name().isEmpty())
413 TQString
name = data_P.bin();
416 ret += TQString(
" NAME=\"%1\"" ).arg( escape_str( name ));
418 if( data_P.screen() == -1 )
419 ret += TQString(
" SCREEN=%1" ).arg( screen );
423 bool TDEStartupInfo::sendChange(
const TDEStartupInfoId& id_P,
const TDEStartupInfoData& data_P )
428 TQString msg = TQString::fromLatin1(
"change: %1 %2" )
429 .arg( id_P.to_text()).arg( data_P.to_text());
430 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] sending " << msg <<
endl;
431 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1,
false );
435 bool TDEStartupInfo::sendChangeX( Display* disp_P,
const TDEStartupInfoId& id_P,
436 const TDEStartupInfoData& data_P )
440 TQString msg = TQString::fromLatin1(
"change: %1 %2" )
441 .arg( id_P.to_text()).arg( data_P.to_text());
442 #ifdef KSTARTUPINFO_ALL_DEBUG
443 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] sending " << msg <<
endl;
445 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1,
false );
448 bool TDEStartupInfo::sendFinish(
const TDEStartupInfoId& id_P )
453 TQString msg = TQString::fromLatin1(
"remove: %1" ).arg( id_P.to_text());
454 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] sending " << msg <<
endl;
455 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1,
false );
459 bool TDEStartupInfo::sendFinishX( Display* disp_P,
const TDEStartupInfoId& id_P )
463 TQString msg = TQString::fromLatin1(
"remove: %1" ).arg( id_P.to_text());
464 #ifdef KSTARTUPINFO_ALL_DEBUG
465 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] sending " << msg <<
endl;
467 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1,
false );
470 bool TDEStartupInfo::sendFinish(
const TDEStartupInfoId& id_P,
const TDEStartupInfoData& data_P )
475 TQString msg = TQString::fromLatin1(
"remove: %1 %2" )
476 .arg( id_P.to_text()).arg( data_P.to_text());
477 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] sending " << msg <<
endl;
478 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1,
false );
482 bool TDEStartupInfo::sendFinishX( Display* disp_P,
const TDEStartupInfoId& id_P,
483 const TDEStartupInfoData& data_P )
487 TQString msg = TQString::fromLatin1(
"remove: %1 %2" )
488 .arg( id_P.to_text()).arg( data_P.to_text());
489 #ifdef KSTARTUPINFO_ALL_DEBUG
490 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] sending " << msg <<
endl;
492 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1,
false );
495 void TDEStartupInfo::appStarted()
498 appStarted( kapp->startupId());
500 appStarted( TDEStartupInfo::currentStartupIdEnv().
id());
503 void TDEStartupInfo::appStarted(
const TQCString& startup_id )
506 id.initId( startup_id );
510 TDEStartupInfo::sendFinish(
id );
511 else if( getenv(
"DISPLAY" ) != NULL )
514 Display* disp = XOpenDisplay( NULL );
517 TDEStartupInfo::sendFinishX( disp,
id );
518 XCloseDisplay( disp );
524 void TDEStartupInfo::disableAutoAppStartedSending(
bool disable )
526 auto_app_started_sending = !disable;
529 void TDEStartupInfo::silenceStartup(
bool silence )
532 id.initId( kapp->startupId());
535 TDEStartupInfoData data;
536 data.setSilent( silence ? TDEStartupInfoData::Yes : TDEStartupInfoData::No );
537 sendChange(
id, data );
540 void TDEStartupInfo::handleAutoAppStartedSending()
542 if( auto_app_started_sending )
546 void TDEStartupInfo::setNewStartupId( TQWidget* window,
const TQCString& startup_id )
548 bool activate =
true;
549 kapp->setStartupId( startup_id );
552 if( !startup_id.isEmpty() && startup_id !=
"0" )
554 NETRootInfo i( tqt_xdisplay(), NET::Supported );
555 if( i.isSupported( NET::WM2StartupId ))
557 TDEStartupInfo::setWindowStartupId( window->winId(), startup_id );
571 TDEStartupInfo::handleAutoAppStartedSending();
574 TDEStartupInfo::startup_t TDEStartupInfo::checkStartup( WId w_P, TDEStartupInfoId& id_O,
575 TDEStartupInfoData& data_O )
577 return check_startup_internal( w_P, &id_O, &data_O );
580 TDEStartupInfo::startup_t TDEStartupInfo::checkStartup( WId w_P, TDEStartupInfoId& id_O )
582 return check_startup_internal( w_P, &id_O, NULL );
585 TDEStartupInfo::startup_t TDEStartupInfo::checkStartup( WId w_P, TDEStartupInfoData& data_O )
587 return check_startup_internal( w_P, NULL, &data_O );
590 TDEStartupInfo::startup_t TDEStartupInfo::checkStartup( WId w_P )
592 return check_startup_internal( w_P, NULL, NULL );
595 TDEStartupInfo::startup_t TDEStartupInfo::check_startup_internal( WId w_P, TDEStartupInfoId* id_O,
596 TDEStartupInfoData* data_O )
600 if( d->startups.count() == 0 )
609 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] check_startup" <<
endl;
610 TQCString
id = windowStartupId( w_P );
613 if(
id.isEmpty() ||
id ==
"0" )
615 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] ignore" <<
endl;
618 return find_id(
id, id_O, data_O ) ? Match : NoMatch;
621 NETWinInfo info( tqt_xdisplay(), w_P, tqt_xrootwin(),
622 NET::WMWindowType | NET::WMPid | NET::WMState );
623 pid_t pid = info.pid();
626 TQCString hostname = get_window_hostname( w_P );
627 if( !hostname.isEmpty()
628 && find_pid( pid, hostname, id_O, data_O ))
633 if( XGetClassHint( tqt_xdisplay(), w_P, &hint ) != 0 )
635 TQCString res_name = hint.res_name;
636 TQCString res_class = hint.res_class;
637 XFree( hint.res_name );
638 XFree( hint.res_class );
639 if( find_wclass( res_name, res_class, id_O, data_O ))
643 NET::WindowType type = info.windowType( NET::NormalMask | NET::DesktopMask
644 | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
645 | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
646 if( type != NET::Normal
648 && type != NET::Unknown
649 && type != NET::Dialog
654 Window transient_for;
655 if( XGetTransientForHint( tqt_xdisplay(), static_cast< Window >( w_P ), &transient_for )
656 && static_cast< WId >( transient_for ) != tqt_xrootwin()
657 && transient_for != None )
660 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] check_startup:cantdetect" <<
endl;
664 bool TDEStartupInfo::find_id(
const TQCString& id_P, TDEStartupInfoId* id_O,
665 TDEStartupInfoData* data_O )
669 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] find_id:" << id_P <<
endl;
672 if( d->startups.contains(
id ))
677 *data_O = d->startups[ id ];
678 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] check_startup_id:match" <<
endl;
684 bool TDEStartupInfo::find_pid( pid_t pid_P,
const TQCString& hostname_P,
685 TDEStartupInfoId* id_O, TDEStartupInfoData* data_O )
689 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] find_pid:" << pid_P <<
endl;
690 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->startups.begin();
691 it != d->startups.end();
694 if( ( *it ).is_pid( pid_P ) && ( *it ).hostname() == hostname_P )
701 remove_startup_info_internal( it.key());
702 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] check_startup_pid:match" <<
endl;
709 bool TDEStartupInfo::find_wclass( TQCString res_name, TQCString res_class,
710 TDEStartupInfoId* id_O, TDEStartupInfoData* data_O )
714 res_name = res_name.lower();
715 res_class = res_class.lower();
716 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] find_wclass:" << res_name <<
":" << res_class <<
endl;
717 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->startups.begin();
718 it != d->startups.end();
721 const TQCString wmclass = ( *it ).findWMClass();
722 if( wmclass.lower() == res_name || wmclass.lower() == res_class )
729 remove_startup_info_internal( it.key());
730 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] check_startup_wclass:match" <<
endl;
738 static Atom net_startup_atom = None;
740 static TQCString read_startup_id_property( WId w_P )
743 unsigned char *name_ret;
746 unsigned long nitems_ret = 0, after_ret = 0;
747 if( XGetWindowProperty( tqt_xdisplay(), w_P, net_startup_atom, 0l, 4096,
748 False, utf8_string_atom, &type_ret, &format_ret, &nitems_ret, &after_ret, &name_ret )
751 if( type_ret == utf8_string_atom && format_ret == 8 && name_ret != NULL )
752 ret =
reinterpret_cast< char*
>( name_ret );
753 if ( name_ret != NULL )
761 TQCString TDEStartupInfo::windowStartupId( WId w_P )
764 if( net_startup_atom == None )
765 net_startup_atom = XInternAtom( tqt_xdisplay(), NET_STARTUP_WINDOW, False );
766 if( utf8_string_atom == None )
767 utf8_string_atom = XInternAtom( tqt_xdisplay(),
"UTF8_STRING", False );
768 TQCString ret = read_startup_id_property( w_P );
771 XWMHints* hints = XGetWMHints( tqt_xdisplay(), w_P );
772 if( hints && ( hints->flags & WindowGroupHint ) != 0 )
773 ret = read_startup_id_property( hints->window_group );
783 void TDEStartupInfo::setWindowStartupId( WId w_P,
const TQCString& id_P )
788 if( net_startup_atom == None )
789 net_startup_atom = XInternAtom( tqt_xdisplay(), NET_STARTUP_WINDOW, False );
790 if( utf8_string_atom == None )
791 utf8_string_atom = XInternAtom( tqt_xdisplay(),
"UTF8_STRING", False );
792 XChangeProperty( tqt_xdisplay(), w_P, net_startup_atom, utf8_string_atom, 8,
793 PropModeReplace, reinterpret_cast< unsigned char* >( const_cast<TQCString&>(id_P).data()), id_P.length());
797 TQCString TDEStartupInfo::get_window_hostname( WId w_P )
803 if( XGetWMClientMachine( tqt_xdisplay(), w_P, &tp ) != 0
804 && XTextPropertyToStringList( &tp, &hh, &cnt ) != 0 )
808 TQCString hostname = hh[ 0 ];
809 XFreeStringList( hh );
812 XFreeStringList( hh );
819 void TDEStartupInfo::setTimeout(
unsigned int secs_P )
823 TQTimer::singleShot( 0,
this, TQT_SLOT( startups_cleanup_no_age()));
826 void TDEStartupInfo::startups_cleanup_no_age()
828 startups_cleanup_internal(
false );
831 void TDEStartupInfo::startups_cleanup()
835 if( d->startups.count() == 0 && d->silent_startups.count() == 0
836 && d->uninited_startups.count() == 0 )
841 startups_cleanup_internal(
true );
844 void TDEStartupInfo::startups_cleanup_internal(
bool age_P )
848 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->startups.begin();
849 it != d->startups.end();
854 unsigned int tout = timeout;
855 if( ( *it ).silent() == Data::Yes )
857 if( ( *it ).age >= tout )
859 const TDEStartupInfoId&
key = it.key();
861 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] startups entry timeout:" << key.id() <<
endl;
862 remove_startup_info_internal( key );
867 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->silent_startups.begin();
868 it != d->silent_startups.end();
873 unsigned int tout = timeout;
874 if( ( *it ).silent() == Data::Yes )
876 if( ( *it ).age >= tout )
878 const TDEStartupInfoId& key = it.key();
880 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] silent entry timeout:" << key.id() <<
endl;
881 remove_startup_info_internal( key );
886 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->uninited_startups.begin();
887 it != d->uninited_startups.end();
892 unsigned int tout = timeout;
893 if( ( *it ).silent() == Data::Yes )
895 if( ( *it ).age >= tout )
897 const TDEStartupInfoId& key = it.key();
899 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] uninited entry timeout:" << key.id() <<
endl;
900 remove_startup_info_internal( key );
907 void TDEStartupInfo::clean_all_noncompliant()
911 for( TQMap< TDEStartupInfoId, Data >::Iterator it = d->startups.begin();
912 it != d->startups.end();
915 if( ( *it ).WMClass() !=
"0" )
920 const TDEStartupInfoId& key = it.key();
922 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] entry cleaning:" << key.id() <<
endl;
923 remove_startup_info_internal( key );
927 TQCString TDEStartupInfo::createNewStartupId()
932 gettimeofday( &tm, NULL );
933 char hostname[ 256 ];
934 hostname[ 0 ] =
'\0';
935 if (!gethostname( hostname, 255 ))
936 hostname[
sizeof(hostname)-1] =
'\0';
937 TQCString
id = TQString(TQString(
"%1;%2;%3;%4_TIME%5" ).arg( hostname ).arg( tm.tv_sec )
938 .arg( tm.tv_usec ).arg( getpid()).arg( GET_QT_X_USER_TIME() )).utf8();
939 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] creating: " <<
id <<
":" << tqAppName() <<
endl;
944 struct TDEStartupInfoIdPrivate
946 TDEStartupInfoIdPrivate() : id(
"" ) {}
950 const TQCString& TDEStartupInfoId::id()
const
956 TQString TDEStartupInfoId::to_text()
const
958 return TQString::fromLatin1(
" ID=\"%1\" " ).arg( escape_str(
id()));
961 TDEStartupInfoId::TDEStartupInfoId(
const TQString& txt_P )
963 d =
new TDEStartupInfoIdPrivate;
964 TQStringList items = get_fields( txt_P );
965 const TQString id_str = TQString::fromLatin1(
"ID=" );
966 for( TQStringList::Iterator it = items.begin();
970 if( ( *it ).startsWith( id_str ))
971 d->id = get_cstr( *it );
975 void TDEStartupInfoId::initId(
const TQCString& id_P )
980 #ifdef KSTARTUPINFO_ALL_DEBUG
981 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] using: " << d->id <<
endl;
985 const char* startup_env = getenv( NET_STARTUP_ENV );
986 if( startup_env != NULL && *startup_env !=
'\0' )
989 #ifdef KSTARTUPINFO_ALL_DEBUG
990 kdDebug( 172 ) <<
"[tdecore-tdestartupinfo] reusing: " << d->id <<
endl;
994 d->id = TDEStartupInfo::createNewStartupId();
997 bool TDEStartupInfoId::setupStartupEnv()
const
1001 unsetenv( NET_STARTUP_ENV );
1004 return setenv( NET_STARTUP_ENV,
id(),
true ) == 0;
1007 TDEStartupInfoId TDEStartupInfo::currentStartupIdEnv()
1009 const char* startup_env = getenv( NET_STARTUP_ENV );
1010 TDEStartupInfoId id;
1011 if( startup_env != NULL && *startup_env !=
'\0' )
1012 id.d->id = startup_env;
1018 void TDEStartupInfo::resetStartupEnv()
1020 unsetenv( NET_STARTUP_ENV );
1023 TDEStartupInfoId::TDEStartupInfoId()
1025 d =
new TDEStartupInfoIdPrivate;
1028 TDEStartupInfoId::~TDEStartupInfoId()
1033 TDEStartupInfoId::TDEStartupInfoId(
const TDEStartupInfoId& id_P )
1035 d =
new TDEStartupInfoIdPrivate( *id_P.d );
1038 TDEStartupInfoId& TDEStartupInfoId::operator=(
const TDEStartupInfoId& id_P )
1043 d =
new TDEStartupInfoIdPrivate( *id_P.d );
1047 bool TDEStartupInfoId::operator==(
const TDEStartupInfoId& id_P )
const
1049 return id() == id_P.id();
1052 bool TDEStartupInfoId::operator!=(
const TDEStartupInfoId& id_P )
const
1054 return !(*
this == id_P );
1058 bool TDEStartupInfoId::operator<(
const TDEStartupInfoId& id_P )
const
1060 return id() < id_P.id();
1063 bool TDEStartupInfoId::none()
const
1065 return d->id.isEmpty() || d->id ==
"0";
1068 unsigned long TDEStartupInfoId::timestamp()
const
1072 int pos = d->id.findRev(
"_TIME" );
1076 unsigned long time = d->id.mid( pos + 5 ).toULong( &ok );
1077 if( !ok && d->id[ pos + 5 ] ==
'-' )
1078 time = d->id.mid( pos + 5 ).toLong( &ok );
1086 int pos1 = d->id.findRev(
'/' );
1089 int pos2 = d->id.findRev(
'/', pos1 - 1 );
1093 unsigned long time = d->id.mid( pos2 + 1, pos1 - pos2 - 1 ).toULong( &ok );
1094 if( !ok && d->id[ pos2 + 1 ] ==
'-' )
1095 time = d->id.mid( pos2 + 1, pos1 - pos2 - 1 ).toLong( &ok );
1104 struct TDEStartupInfoDataPrivate
1106 TDEStartupInfoDataPrivate() : desktop( 0 ), wmclass(
"" ), hostname(
"" ),
1107 silent( TDEStartupInfoData::Unknown ), timestamp( -1U ), screen( -1 ), xinerama( -1 ), launched_by( 0 ) {}
1113 TQValueList< pid_t > pids;
1116 TDEStartupInfoData::TriState silent;
1117 unsigned long timestamp;
1123 TQString TDEStartupInfoData::to_text()
const
1126 if( !d->bin.isEmpty())
1127 ret += TQString::fromLatin1(
" BIN=\"%1\"" ).arg( escape_str( d->bin ));
1128 if( !d->name.isEmpty())
1129 ret += TQString::fromLatin1(
" NAME=\"%1\"" ).arg( escape_str( d->name ));
1130 if( !d->description.isEmpty())
1131 ret += TQString::fromLatin1(
" DESCRIPTION=\"%1\"" ).arg( escape_str( d->description ));
1132 if( !d->icon.isEmpty())
1133 ret += TQString::fromLatin1(
" ICON=%1" ).arg( d->icon );
1134 if( d->desktop != 0 )
1135 ret += TQString::fromLatin1(
" DESKTOP=%1" )
1136 .arg( d->desktop == NET::OnAllDesktops ? NET::OnAllDesktops : d->desktop - 1 );
1137 if( !d->wmclass.isEmpty())
1138 ret += TQString::fromLatin1(
" WMCLASS=\"%1\"" ).arg( QString(d->wmclass) );
1139 if( !d->hostname.isEmpty())
1140 ret += TQString::fromLatin1(
" HOSTNAME=%1" ).arg( QString(d->hostname) );
1141 for( TQValueList< pid_t >::ConstIterator it = d->pids.begin();
1142 it != d->pids.end();
1144 ret += TQString::fromLatin1(
" PID=%1" ).arg( *it );
1145 if( d->silent != Unknown )
1146 ret += TQString::fromLatin1(
" SILENT=%1" ).arg( d->silent == Yes ? 1 : 0 );
1147 if( d->timestamp != -1U )
1148 ret += TQString::fromLatin1(
" TIMESTAMP=%1" ).arg( d->timestamp );
1149 if( d->screen != -1 )
1150 ret += TQString::fromLatin1(
" SCREEN=%1" ).arg( d->screen );
1151 if( d->xinerama != -1 )
1152 ret += TQString::fromLatin1(
" XINERAMA=%1" ).arg( d->xinerama );
1153 if( d->launched_by != 0 )
1154 ret += TQString::fromLatin1(
" LAUNCHED_BY=%1" ).arg( d->launched_by );
1158 TDEStartupInfoData::TDEStartupInfoData(
const TQString& txt_P )
1160 d =
new TDEStartupInfoDataPrivate;
1161 TQStringList items = get_fields( txt_P );
1162 const TQString bin_str = TQString::fromLatin1(
"BIN=" );
1163 const TQString name_str = TQString::fromLatin1(
"NAME=" );
1164 const TQString description_str = TQString::fromLatin1(
"DESCRIPTION=" );
1165 const TQString icon_str = TQString::fromLatin1(
"ICON=" );
1166 const TQString desktop_str = TQString::fromLatin1(
"DESKTOP=" );
1167 const TQString wmclass_str = TQString::fromLatin1(
"WMCLASS=" );
1168 const TQString hostname_str = TQString::fromLatin1(
"HOSTNAME=" );
1169 const TQString pid_str = TQString::fromLatin1(
"PID=" );
1170 const TQString silent_str = TQString::fromLatin1(
"SILENT=" );
1171 const TQString timestamp_str = TQString::fromLatin1(
"TIMESTAMP=" );
1172 const TQString screen_str = TQString::fromLatin1(
"SCREEN=" );
1173 const TQString xinerama_str = TQString::fromLatin1(
"XINERAMA=" );
1174 const TQString launched_by_str = TQString::fromLatin1(
"LAUNCHED_BY=" );
1175 for( TQStringList::Iterator it = items.begin();
1179 if( ( *it ).startsWith( bin_str ))
1180 d->bin = get_str( *it );
1181 else if( ( *it ).startsWith( name_str ))
1182 d->name = get_str( *it );
1183 else if( ( *it ).startsWith( description_str ))
1184 d->description = get_str( *it );
1185 else if( ( *it ).startsWith( icon_str ))
1186 d->icon = get_str( *it );
1187 else if( ( *it ).startsWith( desktop_str ))
1189 d->desktop = get_num( *it );
1190 if( d->desktop != NET::OnAllDesktops )
1193 else if( ( *it ).startsWith( wmclass_str ))
1194 d->wmclass = get_cstr( *it );
1195 else if( ( *it ).startsWith( hostname_str ))
1196 d->hostname = get_cstr( *it );
1197 else if( ( *it ).startsWith( pid_str ))
1198 addPid( get_num( *it ));
1199 else if( ( *it ).startsWith( silent_str ))
1200 d->silent = get_num( *it ) != 0 ? Yes : No;
1201 else if( ( *it ).startsWith( timestamp_str ))
1202 d->timestamp = get_unum( *it );
1203 else if( ( *it ).startsWith( screen_str ))
1204 d->screen = get_num( *it );
1205 else if( ( *it ).startsWith( xinerama_str ))
1206 d->xinerama = get_num( *it );
1207 else if( ( *it ).startsWith( launched_by_str ))
1208 d->launched_by = get_num( *it );
1212 TDEStartupInfoData::TDEStartupInfoData(
const TDEStartupInfoData& data )
1214 d =
new TDEStartupInfoDataPrivate( *data.d );
1217 TDEStartupInfoData& TDEStartupInfoData::operator=(
const TDEStartupInfoData& data )
1222 d =
new TDEStartupInfoDataPrivate( *data.d );
1226 void TDEStartupInfoData::update(
const TDEStartupInfoData& data_P )
1228 if( !data_P.bin().isEmpty())
1229 d->bin = data_P.bin();
1230 if( !data_P.name().isEmpty() && name().isEmpty())
1231 d->name = data_P.name();
1232 if( !data_P.description().isEmpty() &&
description().isEmpty())
1233 d->description = data_P.description();
1234 if( !data_P.icon().isEmpty() && icon().isEmpty())
1235 d->icon = data_P.icon();
1236 if( data_P.desktop() != 0 && desktop() == 0 )
1237 d->desktop = data_P.desktop();
1238 if( !data_P.d->wmclass.isEmpty())
1239 d->wmclass = data_P.d->wmclass;
1240 if( !data_P.d->hostname.isEmpty())
1241 d->hostname = data_P.d->hostname;
1242 for( TQValueList< pid_t >::ConstIterator it = data_P.d->pids.begin();
1243 it != data_P.d->pids.end();
1246 if( data_P.silent() != Unknown )
1247 d->silent = data_P.silent();
1248 if( data_P.timestamp() != -1U && timestamp() == -1U )
1249 d->timestamp = data_P.timestamp();
1250 if( data_P.screen() != -1 )
1251 d->screen = data_P.screen();
1252 if( data_P.xinerama() != -1 && xinerama() != -1 )
1253 d->xinerama = data_P.xinerama();
1254 if( data_P.launchedBy() != 0 && launchedBy() != 0 )
1255 d->launched_by = data_P.launchedBy();
1258 TDEStartupInfoData::TDEStartupInfoData()
1260 d =
new TDEStartupInfoDataPrivate;
1263 TDEStartupInfoData::~TDEStartupInfoData()
1268 void TDEStartupInfoData::setBin(
const TQString& bin_P )
1273 const TQString& TDEStartupInfoData::bin()
const
1278 void TDEStartupInfoData::setName(
const TQString& name_P )
1283 const TQString& TDEStartupInfoData::name()
const
1288 const TQString& TDEStartupInfoData::findName()
const
1290 if( !name().isEmpty())
1295 void TDEStartupInfoData::setDescription(
const TQString& desc_P )
1297 d->description = desc_P;
1300 const TQString& TDEStartupInfoData::description()
const
1302 return d->description;
1305 const TQString& TDEStartupInfoData::findDescription()
const
1312 void TDEStartupInfoData::setIcon(
const TQString& icon_P )
1317 const TQString& TDEStartupInfoData::findIcon()
const
1319 if( !icon().isEmpty())
1324 const TQString& TDEStartupInfoData::icon()
const
1329 void TDEStartupInfoData::setDesktop(
int desktop_P )
1331 d->desktop = desktop_P;
1334 int TDEStartupInfoData::desktop()
const
1339 void TDEStartupInfoData::setWMClass(
const TQCString& wmclass_P )
1341 d->wmclass = wmclass_P;
1344 const TQCString TDEStartupInfoData::findWMClass()
const
1346 if( !WMClass().isEmpty() && WMClass() !=
"0" )
1348 return bin().utf8();
1351 const TQCString& TDEStartupInfoData::WMClass()
const
1356 void TDEStartupInfoData::setHostname(
const TQCString& hostname_P )
1358 if( !hostname_P.isNull())
1359 d->hostname = hostname_P;
1364 if (!gethostname( tmp, 255 ))
1365 tmp[
sizeof(tmp)-1] =
'\0';
1370 const TQCString& TDEStartupInfoData::hostname()
const
1375 void TDEStartupInfoData::addPid( pid_t pid_P )
1377 if( !d->pids.contains( pid_P ))
1378 d->pids.append( pid_P );
1381 void TDEStartupInfoData::remove_pid( pid_t pid_P )
1383 d->pids.remove( pid_P );
1386 const TQValueList< pid_t >& TDEStartupInfoData::pids()
const
1391 bool TDEStartupInfoData::is_pid( pid_t pid_P )
const
1393 return d->pids.contains( pid_P );
1396 void TDEStartupInfoData::setSilent( TriState state_P )
1398 d->silent = state_P;
1401 TDEStartupInfoData::TriState TDEStartupInfoData::silent()
const
1406 void TDEStartupInfoData::setTimestamp(
unsigned long time )
1408 d->timestamp = time;
1411 unsigned long TDEStartupInfoData::timestamp()
const
1413 return d->timestamp;
1416 void TDEStartupInfoData::setScreen(
int screen )
1421 int TDEStartupInfoData::screen()
const
1426 void TDEStartupInfoData::setXinerama(
int xinerama )
1428 d->xinerama = xinerama;
1431 int TDEStartupInfoData::xinerama()
const
1436 void TDEStartupInfoData::setLaunchedBy( WId window )
1438 d->launched_by = window;
1441 WId TDEStartupInfoData::launchedBy()
const
1443 return d->launched_by;
1447 long get_num(
const TQString& item_P )
1449 unsigned int pos = item_P.find(
'=' );
1450 return item_P.mid( pos + 1 ).toLong();
1454 unsigned long get_unum(
const TQString& item_P )
1456 unsigned int pos = item_P.find(
'=' );
1457 return item_P.mid( pos + 1 ).toULong();
1461 TQString get_str(
const TQString& item_P )
1463 unsigned int pos = item_P.find(
'=' );
1464 if( item_P.length() > pos + 2 && item_P[ pos + 1 ] == (QChar)
'\"' )
1466 int pos2 = item_P.left( pos + 2 ).find(
'\"' );
1468 return TQString::null;
1469 return item_P.mid( pos + 2, pos2 - 2 - pos );
1471 return item_P.mid( pos + 1 );
1475 TQCString get_cstr(
const TQString& item_P )
1477 return get_str( item_P ).utf8();
1481 TQStringList get_fields(
const TQString& txt_P )
1483 TQString txt = txt_P.simplifyWhiteSpace();
1487 bool escape =
false;
1488 for(
unsigned int pos = 0;
1497 else if( txt[ pos ] ==
'\\' )
1499 else if( txt[ pos ] ==
'\"' )
1501 else if( txt[ pos ] ==
' ' && !in )
1513 static TQString escape_str(
const TQString& str_P )
1516 for(
unsigned int pos = 0;
1517 pos < str_P.length();
1520 if( str_P[ pos ] == (QChar)
'\\'
1521 || str_P[ pos ] == (QChar)
'"' )
1523 ret += str_P[ pos ];
1528 #include "tdestartupinfo.moc"
TQString description(StdAccel id)
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.
static TDEApplication * kApplication()
Returns the current application object.
kndbgstream & endl(kndbgstream &s)
Does nothing.
static void setOnDesktop(WId win, int desktop)
Moves window win to desktop desktop.