29 #define KSTARTUPINFO_ALL_DEBUG
30 #warning Extra KStartupInfo debug messages enabled.
44 #ifndef QT_CLEAN_NAMESPACE
45 #define QT_CLEAN_NAMESPACE
48 #include "kstartupinfo.h"
58 #include <kapplication.h>
61 #include <kwinmodule.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 KStartupInfo::Data
84 :
public KStartupInfoData
87 Data() : KStartupInfoData(), age(0) {}
88 Data(
const TQString& txt_P )
89 : KStartupInfoData( txt_P ), age( 0 ) {}
93 struct KStartupInfoPrivate
96 TQMap< KStartupInfoId, KStartupInfo::Data > startups;
98 TQMap< KStartupInfoId, KStartupInfo::Data > silent_startups;
100 TQMap< KStartupInfoId, KStartupInfo::Data > uninited_startups;
107 KStartupInfoPrivate(
int flags_P )
110 msgs( NET_STARTUP_MSG, NULL, false ),
115 KStartupInfo::KStartupInfo(
int flags_P, TQObject* parent_P,
const char* name_P )
116 : TQObject( parent_P, name_P ),
117 timeout( 60 ), d( NULL )
122 KStartupInfo::KStartupInfo(
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 KStartupInfo::init(
int flags_P )
137 d =
new KStartupInfoPrivate( 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 KStartupInfo::~KStartupInfo()
158 void KStartupInfo::got_message(
const TQString& msg_P )
161 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] 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 KStartupInfo::slot_window_added( WId w_P )
191 kapp->postEvent(
this,
new DelayedWindowEvent( w_P ));
194 void KStartupInfo::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 KStartupInfo::window_added( WId w_P )
205 KStartupInfoData data;
206 startup_t ret = check_startup_internal( w_P, &
id, &data );
210 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] new window match" <<
endl;
215 if( d->flags & CleanOnCantDetect )
216 clean_all_noncompliant();
221 void KStartupInfo::got_startup_info(
const TQString& msg_P,
bool update_P )
223 KStartupInfoId id( msg_P );
226 KStartupInfo::Data data( msg_P );
227 new_startup_info_internal(
id, data, update_P );
230 void KStartupInfo::new_startup_info_internal(
const KStartupInfoId& 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 ) <<
"[kdecore-kstartupinfo] 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 ) <<
"[kdecore-kstartupinfo] 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 ) <<
"[kdecore-kstartupinfo] 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 ) <<
"[kdecore-kstartupinfo] 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 ) <<
"[kdecore-kstartupinfo] adding" <<
endl;
290 d->startups.insert( id_P, data_P );
291 emit gotNewStartup( id_P, data_P );
295 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] adding silent" <<
endl;
296 d->silent_startups.insert( id_P, data_P );
298 d->cleanup->start( 1000 );
301 void KStartupInfo::got_remove_startup_info(
const TQString& msg_P )
303 KStartupInfoId id( msg_P );
304 KStartupInfoData 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 KStartupInfo::remove_startup_info_internal(
const KStartupInfoId& id_P )
320 if( d->startups.contains( id_P ))
322 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] 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 ) <<
"[kdecore-kstartupinfo] removing silent" <<
endl;
329 d->silent_startups.remove( id_P );
331 else if( d->uninited_startups.contains( id_P ))
333 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] removing uninited" <<
endl;
334 d->uninited_startups.remove( id_P );
339 void KStartupInfo::remove_startup_pids(
const KStartupInfoData& data_P )
343 for( TQMap< KStartupInfoId, 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 KStartupInfo::remove_startup_pids(
const KStartupInfoId& id_P,
357 const KStartupInfoData& 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 KStartupInfo::sendStartup(
const KStartupInfoId& id_P,
const KStartupInfoData& 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, qt_xscreen());
387 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] sending " << msg <<
endl;
388 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1,
false );
392 bool KStartupInfo::sendStartupX( Display* disp_P,
const KStartupInfoId& id_P,
393 const KStartupInfoData& 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 ) <<
"[kdecore-kstartupinfo] sending " << msg <<
endl;
403 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1,
false );
406 TQString KStartupInfo::check_required_startup_fields(
const TQString& msg,
const KStartupInfoData& 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 KStartupInfo::sendChange(
const KStartupInfoId& id_P,
const KStartupInfoData& data_P )
428 TQString msg = TQString::fromLatin1(
"change: %1 %2" )
429 .arg( id_P.to_text()).arg( data_P.to_text());
430 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] sending " << msg <<
endl;
431 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1,
false );
435 bool KStartupInfo::sendChangeX( Display* disp_P,
const KStartupInfoId& id_P,
436 const KStartupInfoData& 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 ) <<
"[kdecore-kstartupinfo] sending " << msg <<
endl;
445 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1,
false );
448 bool KStartupInfo::sendFinish(
const KStartupInfoId& id_P )
453 TQString msg = TQString::fromLatin1(
"remove: %1" ).arg( id_P.to_text());
454 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] sending " << msg <<
endl;
455 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1,
false );
459 bool KStartupInfo::sendFinishX( Display* disp_P,
const KStartupInfoId& id_P )
463 TQString msg = TQString::fromLatin1(
"remove: %1" ).arg( id_P.to_text());
464 #ifdef KSTARTUPINFO_ALL_DEBUG
465 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] sending " << msg <<
endl;
467 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1,
false );
470 bool KStartupInfo::sendFinish(
const KStartupInfoId& id_P,
const KStartupInfoData& data_P )
475 TQString msg = TQString::fromLatin1(
"remove: %1 %2" )
476 .arg( id_P.to_text()).arg( data_P.to_text());
477 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] sending " << msg <<
endl;
478 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1,
false );
482 bool KStartupInfo::sendFinishX( Display* disp_P,
const KStartupInfoId& id_P,
483 const KStartupInfoData& 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 ) <<
"[kdecore-kstartupinfo] sending " << msg <<
endl;
492 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1,
false );
495 void KStartupInfo::appStarted()
498 appStarted( kapp->startupId());
500 appStarted( KStartupInfo::currentStartupIdEnv().
id());
503 void KStartupInfo::appStarted(
const TQCString& startup_id )
506 id.initId( startup_id );
510 KStartupInfo::sendFinish(
id );
511 else if( getenv(
"DISPLAY" ) != NULL )
514 Display* disp = XOpenDisplay( NULL );
517 KStartupInfo::sendFinishX( disp,
id );
518 XCloseDisplay( disp );
524 void KStartupInfo::disableAutoAppStartedSending(
bool disable )
526 auto_app_started_sending = !disable;
529 void KStartupInfo::silenceStartup(
bool silence )
532 id.initId( kapp->startupId());
535 KStartupInfoData data;
536 data.setSilent( silence ? KStartupInfoData::Yes : KStartupInfoData::No );
537 sendChange(
id, data );
540 void KStartupInfo::handleAutoAppStartedSending()
542 if( auto_app_started_sending )
546 void KStartupInfo::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( qt_xdisplay(), NET::Supported );
555 if( i.isSupported( NET::WM2StartupId ))
557 KStartupInfo::setWindowStartupId( window->winId(), startup_id );
571 KStartupInfo::handleAutoAppStartedSending();
574 KStartupInfo::startup_t KStartupInfo::checkStartup( WId w_P, KStartupInfoId& id_O,
575 KStartupInfoData& data_O )
577 return check_startup_internal( w_P, &id_O, &data_O );
580 KStartupInfo::startup_t KStartupInfo::checkStartup( WId w_P, KStartupInfoId& id_O )
582 return check_startup_internal( w_P, &id_O, NULL );
585 KStartupInfo::startup_t KStartupInfo::checkStartup( WId w_P, KStartupInfoData& data_O )
587 return check_startup_internal( w_P, NULL, &data_O );
590 KStartupInfo::startup_t KStartupInfo::checkStartup( WId w_P )
592 return check_startup_internal( w_P, NULL, NULL );
595 KStartupInfo::startup_t KStartupInfo::check_startup_internal( WId w_P, KStartupInfoId* id_O,
596 KStartupInfoData* data_O )
600 if( d->startups.count() == 0 )
609 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] check_startup" <<
endl;
610 TQCString
id = windowStartupId( w_P );
613 if(
id.isEmpty() ||
id ==
"0" )
615 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] ignore" <<
endl;
618 return find_id(
id, id_O, data_O ) ? Match : NoMatch;
621 NETWinInfo info( qt_xdisplay(), w_P, qt_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( qt_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( qt_xdisplay(),
static_cast< Window
>( w_P ), &transient_for )
656 &&
static_cast< WId
>( transient_for ) != qt_xrootwin()
657 && transient_for != None )
660 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] check_startup:cantdetect" <<
endl;
664 bool KStartupInfo::find_id(
const TQCString& id_P, KStartupInfoId* id_O,
665 KStartupInfoData* data_O )
669 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] find_id:" << id_P <<
endl;
672 if( d->startups.contains(
id ))
677 *data_O = d->startups[ id ];
678 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] check_startup_id:match" <<
endl;
684 bool KStartupInfo::find_pid( pid_t pid_P,
const TQCString& hostname_P,
685 KStartupInfoId* id_O, KStartupInfoData* data_O )
689 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] find_pid:" << pid_P <<
endl;
690 for( TQMap< KStartupInfoId, 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 ) <<
"[kdecore-kstartupinfo] check_startup_pid:match" <<
endl;
709 bool KStartupInfo::find_wclass( TQCString res_name, TQCString res_class,
710 KStartupInfoId* id_O, KStartupInfoData* data_O )
714 res_name = res_name.lower();
715 res_class = res_class.lower();
716 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] find_wclass:" << res_name <<
":" << res_class <<
endl;
717 for( TQMap< KStartupInfoId, 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 ) <<
"[kdecore-kstartupinfo] 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( qt_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 KStartupInfo::windowStartupId( WId w_P )
764 if( net_startup_atom == None )
765 net_startup_atom = XInternAtom( qt_xdisplay(), NET_STARTUP_WINDOW, False );
766 if( utf8_string_atom == None )
767 utf8_string_atom = XInternAtom( qt_xdisplay(),
"UTF8_STRING", False );
768 TQCString ret = read_startup_id_property( w_P );
771 XWMHints* hints = XGetWMHints( qt_xdisplay(), w_P );
772 if( hints && ( hints->flags & WindowGroupHint ) != 0 )
773 ret = read_startup_id_property( hints->window_group );
783 void KStartupInfo::setWindowStartupId( WId w_P,
const TQCString& id_P )
788 if( net_startup_atom == None )
789 net_startup_atom = XInternAtom( qt_xdisplay(), NET_STARTUP_WINDOW, False );
790 if( utf8_string_atom == None )
791 utf8_string_atom = XInternAtom( qt_xdisplay(),
"UTF8_STRING", False );
792 XChangeProperty( qt_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 KStartupInfo::get_window_hostname( WId w_P )
803 if( XGetWMClientMachine( qt_xdisplay(), w_P, &tp ) != 0
804 && XTextPropertyToStringList( &tp, &hh, &cnt ) != 0 )
808 TQCString hostname = hh[ 0 ];
809 XFreeStringList( hh );
812 XFreeStringList( hh );
819 void KStartupInfo::setTimeout(
unsigned int secs_P )
823 TQTimer::singleShot( 0,
this, TQT_SLOT( startups_cleanup_no_age()));
826 void KStartupInfo::startups_cleanup_no_age()
828 startups_cleanup_internal(
false );
831 void KStartupInfo::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 KStartupInfo::startups_cleanup_internal(
bool age_P )
848 for( TQMap< KStartupInfoId, 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 KStartupInfoId&
key = it.key();
861 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] startups entry timeout:" <<
key.id() <<
endl;
862 remove_startup_info_internal( key );
867 for( TQMap< KStartupInfoId, 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 KStartupInfoId&
key = it.key();
880 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] silent entry timeout:" <<
key.id() <<
endl;
881 remove_startup_info_internal( key );
886 for( TQMap< KStartupInfoId, 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 KStartupInfoId&
key = it.key();
899 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] uninited entry timeout:" <<
key.id() <<
endl;
900 remove_startup_info_internal( key );
907 void KStartupInfo::clean_all_noncompliant()
911 for( TQMap< KStartupInfoId, Data >::Iterator it = d->startups.begin();
912 it != d->startups.end();
915 if( ( *it ).WMClass() !=
"0" )
920 const KStartupInfoId&
key = it.key();
922 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] entry cleaning:" <<
key.id() <<
endl;
923 remove_startup_info_internal( key );
927 TQCString KStartupInfo::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 ) <<
"[kdecore-kstartupinfo] creating: " <<
id <<
":" << tqAppName() <<
endl;
944 struct KStartupInfoIdPrivate
946 KStartupInfoIdPrivate() : id(
"" ) {}
950 const TQCString& KStartupInfoId::id()
const
956 TQString KStartupInfoId::to_text()
const
958 return TQString::fromLatin1(
" ID=\"%1\" " ).arg( escape_str(
id()));
961 KStartupInfoId::KStartupInfoId(
const TQString& txt_P )
963 d =
new KStartupInfoIdPrivate;
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 KStartupInfoId::initId(
const TQCString& id_P )
980 #ifdef KSTARTUPINFO_ALL_DEBUG
981 kdDebug( 172 ) <<
"[kdecore-kstartupinfo] 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 ) <<
"[kdecore-kstartupinfo] reusing: " << d->id <<
endl;
994 d->id = KStartupInfo::createNewStartupId();
997 bool KStartupInfoId::setupStartupEnv()
const
1001 unsetenv( NET_STARTUP_ENV );
1004 return setenv( NET_STARTUP_ENV,
id(),
true ) == 0;
1007 KStartupInfoId KStartupInfo::currentStartupIdEnv()
1009 const char* startup_env = getenv( NET_STARTUP_ENV );
1011 if( startup_env != NULL && *startup_env !=
'\0' )
1012 id.d->id = startup_env;
1018 void KStartupInfo::resetStartupEnv()
1020 unsetenv( NET_STARTUP_ENV );
1023 KStartupInfoId::KStartupInfoId()
1025 d =
new KStartupInfoIdPrivate;
1028 KStartupInfoId::~KStartupInfoId()
1033 KStartupInfoId::KStartupInfoId(
const KStartupInfoId& id_P )
1035 d =
new KStartupInfoIdPrivate( *id_P.d );
1038 KStartupInfoId& KStartupInfoId::operator=(
const KStartupInfoId& id_P )
1043 d =
new KStartupInfoIdPrivate( *id_P.d );
1047 bool KStartupInfoId::operator==(
const KStartupInfoId& id_P )
const
1049 return id() == id_P.id();
1052 bool KStartupInfoId::operator!=(
const KStartupInfoId& id_P )
const
1054 return !(*
this == id_P );
1058 bool KStartupInfoId::operator<(
const KStartupInfoId& id_P )
const
1060 return id() < id_P.id();
1063 bool KStartupInfoId::none()
const
1065 return d->id.isEmpty() || d->id ==
"0";
1068 unsigned long KStartupInfoId::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 KStartupInfoDataPrivate
1106 KStartupInfoDataPrivate() : desktop( 0 ), wmclass(
"" ), hostname(
"" ),
1107 silent( KStartupInfoData::Unknown ), timestamp( -1U ), screen( -1 ), xinerama( -1 ), launched_by( 0 ) {}
1113 TQValueList< pid_t > pids;
1116 KStartupInfoData::TriState silent;
1117 unsigned long timestamp;
1123 TQString KStartupInfoData::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 KStartupInfoData::KStartupInfoData(
const TQString& txt_P )
1160 d =
new KStartupInfoDataPrivate;
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 KStartupInfoData::KStartupInfoData(
const KStartupInfoData& data )
1214 d =
new KStartupInfoDataPrivate( *data.d );
1217 KStartupInfoData& KStartupInfoData::operator=(
const KStartupInfoData& data )
1222 d =
new KStartupInfoDataPrivate( *data.d );
1226 void KStartupInfoData::update(
const KStartupInfoData& 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 KStartupInfoData::KStartupInfoData()
1260 d =
new KStartupInfoDataPrivate;
1263 KStartupInfoData::~KStartupInfoData()
1268 void KStartupInfoData::setBin(
const TQString& bin_P )
1273 const TQString& KStartupInfoData::bin()
const
1278 void KStartupInfoData::setName(
const TQString& name_P )
1283 const TQString& KStartupInfoData::name()
const
1288 const TQString& KStartupInfoData::findName()
const
1290 if( !
name().isEmpty())
1295 void KStartupInfoData::setDescription(
const TQString& desc_P )
1297 d->description = desc_P;
1300 const TQString& KStartupInfoData::description()
const
1302 return d->description;
1305 const TQString& KStartupInfoData::findDescription()
const
1312 void KStartupInfoData::setIcon(
const TQString& icon_P )
1317 const TQString& KStartupInfoData::findIcon()
const
1319 if( !icon().isEmpty())
1324 const TQString& KStartupInfoData::icon()
const
1329 void KStartupInfoData::setDesktop(
int desktop_P )
1331 d->desktop = desktop_P;
1334 int KStartupInfoData::desktop()
const
1339 void KStartupInfoData::setWMClass(
const TQCString& wmclass_P )
1341 d->wmclass = wmclass_P;
1344 const TQCString KStartupInfoData::findWMClass()
const
1346 if( !WMClass().isEmpty() && WMClass() !=
"0" )
1348 return bin().utf8();
1351 const TQCString& KStartupInfoData::WMClass()
const
1356 void KStartupInfoData::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& KStartupInfoData::hostname()
const
1375 void KStartupInfoData::addPid( pid_t pid_P )
1377 if( !d->pids.contains( pid_P ))
1378 d->pids.append( pid_P );
1381 void KStartupInfoData::remove_pid( pid_t pid_P )
1383 d->pids.remove( pid_P );
1386 const TQValueList< pid_t >& KStartupInfoData::pids()
const
1391 bool KStartupInfoData::is_pid( pid_t pid_P )
const
1393 return d->pids.contains( pid_P );
1396 void KStartupInfoData::setSilent( TriState state_P )
1398 d->silent = state_P;
1401 KStartupInfoData::TriState KStartupInfoData::silent()
const
1406 void KStartupInfoData::setTimestamp(
unsigned long time )
1408 d->timestamp = time;
1411 unsigned long KStartupInfoData::timestamp()
const
1413 return d->timestamp;
1416 void KStartupInfoData::setScreen(
int screen )
1421 int KStartupInfoData::screen()
const
1426 void KStartupInfoData::setXinerama(
int xinerama )
1428 d->xinerama = xinerama;
1431 int KStartupInfoData::xinerama()
const
1436 void KStartupInfoData::setLaunchedBy( WId window )
1438 d->launched_by = window;
1441 WId KStartupInfoData::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 "kstartupinfo.moc"
static KApplication * kApplication()
Returns the current application object.
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.
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".
TQString description(StdAccel id)
const char * name(StdAction id)