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"
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)