27#define KSTARTUPINFO_ALL_DEBUG
29#warning Extra KStartupInfo debug messages enabled.
35#include <QtGui/QWidget>
36#include <QtCore/QBool>
41#ifndef QT_CLEAN_NAMESPACE
42#define QT_CLEAN_NAMESPACE
48#include <QtCore/QTimer>
49#include <QtGui/QActionEvent>
51#include <qx11info_x11.h>
71static long get_num(
const QString& item_P );
72static unsigned long get_unum(
const QString& item_P );
73static QString
get_str(
const QString& item_P );
74static QByteArray
get_cstr(
const QString& item_P );
75static QStringList
get_fields(
const QString& txt_P );
76static QString
escape_str(
const QString& str_P );
82class KStartupInfo::Data
87 Data(
const QString& txt_P )
92struct KStartupInfoId::Private
94 Private() : id(
"" ) {}
96 QString to_text()
const;
101struct KStartupInfoData::Private
103 Private() : desktop( 0 ), wmclass(
"" ), hostname(
"" ),
106 QString to_text()
const;
107 void remove_pid( pid_t pid );
118 unsigned long timestamp;
122 QString application_id;
125class KStartupInfo::Private
129 void startups_cleanup();
130 void startups_cleanup_no_age();
131 void got_message(
const QString& msg );
132 void window_added( WId w );
133 void slot_window_added( WId w );
135 void init(
int flags );
136 void got_startup_info(
const QString& msg_P,
bool update_only_P );
137 void got_remove_startup_info(
const QString& msg_P );
139 Data& data_P,
bool update_only_P );
146 bool find_pid( pid_t pid_P,
const QByteArray& hostname,
KStartupInfoId* id_O,
148 bool find_wclass(
const QByteArray &res_name_P,
const QByteArray &res_class_P,
150 static QByteArray get_window_hostname( WId w_P );
151 void startups_cleanup_internal(
bool age_P );
152 void clean_all_noncompliant();
153 static QString check_required_startup_fields(
const QString& msg,
180 void createConnections()
186 if( !QX11Info::display())
190 QObject::connect(
KWindowSystem::self(), SIGNAL(windowAdded(WId)), q, SLOT(slot_window_added(WId)));
192#warning "systemTrayWindowAdded signal was remove from KWindowSystem class"
196 QObject::connect( &msgs, SIGNAL(gotMessage(QString)), q, SLOT(got_message(QString)));
197 cleanup =
new QTimer( q );
198 QObject::connect( cleanup, SIGNAL(
timeout()), q, SLOT(startups_cleanup()));
205 d(new Private(flags_P, this))
207 d->createConnections();
212 d(new Private(clean_on_cantdetect_P ? CleanOnCantDetect : 0, this))
214 d->createConnections();
223void KStartupInfo::Private::got_message(
const QString& msg_P )
227 kDebug( 172 ) <<
"got:" << msg_P;
228 QString msg = msg_P.trimmed();
229 if( msg.startsWith( QLatin1String(
"new:") ))
230 got_startup_info( msg.mid( 4 ),
false );
231 else if( msg.startsWith( QLatin1String(
"change:") ))
232 got_startup_info( msg.mid( 7 ),
true );
233 else if( msg.startsWith( QLatin1String(
"remove:") ))
234 got_remove_startup_info( msg.mid( 7 ));
246class DelayedWindowEvent
250 DelayedWindowEvent( WId w_P )
251 : QEvent( uniqueType() ), w( w_P ) {}
257 static Type uniqueType() {
return Type(QEvent::User+15); }
261void KStartupInfo::Private::slot_window_added( WId w_P )
263 qApp->postEvent( q,
new DelayedWindowEvent( w_P ));
269 if( e_P->type() == DelayedWindowEvent::uniqueType() )
270 d->window_added(
static_cast< DelayedWindowEvent*
>( e_P )->w );
273 QObject::customEvent( e_P );
276void KStartupInfo::Private::window_added( WId w_P )
280 startup_t ret = check_startup_internal( w_P, &
id, &data );
284 kDebug( 172 ) <<
"new window match";
289 if( flags & CleanOnCantDetect )
290 clean_all_noncompliant();
295void KStartupInfo::Private::got_startup_info(
const QString& msg_P,
bool update_P )
300 KStartupInfo::Data data( msg_P );
301 new_startup_info_internal(
id, data, update_P );
304void KStartupInfo::Private::new_startup_info_internal(
const KStartupInfoId& id_P,
305 KStartupInfo::Data& data_P,
bool update_P )
309 if( startups.contains( id_P ))
311 startups[ id_P ].update( data_P );
312 startups[ id_P ].age = 0;
313 kDebug( 172 ) <<
"updating";
315 && !( flags & AnnounceSilenceChanges ))
317 silent_startups[ id_P ] = startups[ id_P ];
318 startups.remove( id_P );
325 if( silent_startups.contains( id_P ))
327 silent_startups[ id_P ].update( data_P );
328 silent_startups[ id_P ].age = 0;
329 kDebug( 172 ) <<
"updating silenced";
330 if( silent_startups[ id_P ].silent() != Data::Yes )
332 startups[ id_P ] = silent_startups[ id_P ];
333 silent_startups.remove( id_P );
334 q->emit gotNewStartup( id_P, startups[ id_P ] );
340 if( uninited_startups.contains( id_P ))
342 uninited_startups[ id_P ].update( data_P );
343 kDebug( 172 ) <<
"updating uninited";
346 startups[ id_P ] = uninited_startups[ id_P ];
347 uninited_startups.remove( id_P );
356 kDebug( 172 ) <<
"adding uninited";
357 uninited_startups.insert( id_P, data_P );
359 else if( data_P.silent() != Data::Yes || flags & AnnounceSilenceChanges )
361 kDebug( 172 ) <<
"adding";
362 startups.insert( id_P, data_P );
367 kDebug( 172 ) <<
"adding silent";
368 silent_startups.insert( id_P, data_P );
370 cleanup->start( 1000 );
373void KStartupInfo::Private::got_remove_startup_info(
const QString& msg_P )
377 if( data.
pids().count() > 0 )
380 remove_startup_pids(
id, data );
382 remove_startup_pids( data );
385 remove_startup_info_internal(
id );
388void KStartupInfo::Private::remove_startup_info_internal(
const KStartupInfoId& id_P )
390 if( startups.contains( id_P ))
392 kDebug( 172 ) <<
"removing";
394 startups.remove( id_P );
396 else if( silent_startups.contains( id_P ))
398 kDebug( 172 ) <<
"removing silent";
399 silent_startups.remove( id_P );
401 else if( uninited_startups.contains( id_P ))
403 kDebug( 172 ) <<
"removing uninited";
404 uninited_startups.remove( id_P );
409void KStartupInfo::Private::remove_startup_pids(
const KStartupInfoData& data_P )
412 it != startups.end();
415 if( ( *it ).hostname() != data_P.
hostname())
417 if( !( *it ).is_pid( data_P.
pids().first()))
419 remove_startup_pids( it.key(), data_P );
424void KStartupInfo::Private::remove_startup_pids(
const KStartupInfoId& id_P,
427 kFatal( data_P.
pids().count() == 0, 172 );
429 if( startups.contains( id_P ))
430 data = &startups[ id_P ];
431 else if( silent_startups.contains( id_P ))
432 data = &silent_startups[ id_P ];
433 else if( uninited_startups.contains( id_P ))
434 data = &uninited_startups[ id_P ];
438 it2 != data_P.
pids().constEnd();
440 data->d->remove_pid( *it2 );
441 if( data->pids().count() == 0 )
442 remove_startup_info_internal( id_P );
451 QString msg = QString::fromLatin1(
"new: %1 %2" )
452 .arg( id_P.d->to_text()).arg( data_P.d->to_text());
454 msg = Private::check_required_startup_fields( msg, data_P, inf.
screen());
455 kDebug( 172 ) <<
"sending " << msg;
467 QString msg = QString::fromLatin1(
"new: %1 %2" )
468 .arg( id_P.d->to_text()).arg( data_P.d->to_text());
469 msg = Private::check_required_startup_fields( msg, data_P, DefaultScreen( disp_P ));
470#ifdef KSTARTUPINFO_ALL_DEBUG
471 kDebug( 172 ) <<
"sending " << msg;
479QString KStartupInfo::Private::check_required_startup_fields(
const QString& msg,
const KStartupInfoData& data_P,
483 if( data_P.
name().isEmpty())
486 QString name = data_P.
bin();
489 ret += QString(
" NAME=\"%1\"" ).arg(
escape_str( name ));
491 if( data_P.
screen() == -1 )
492 ret += QString(
" SCREEN=%1" ).arg( screen );
502 QString msg = QString::fromLatin1(
"change: %1 %2" )
503 .arg( id_P.d->to_text()).arg( data_P.d->to_text());
504 kDebug( 172 ) <<
"sending " << msg;
516 QString msg = QString::fromLatin1(
"change: %1 %2" )
517 .arg( id_P.d->to_text()).arg( data_P.d->to_text());
518#ifdef KSTARTUPINFO_ALL_DEBUG
519 kDebug( 172 ) <<
"sending " << msg;
533 QString msg = QString::fromLatin1(
"remove: %1" ).arg( id_P.d->to_text());
534 kDebug( 172 ) <<
"sending " << msg;
545 QString msg = QString::fromLatin1(
"remove: %1" ).arg( id_P.d->to_text());
546#ifdef KSTARTUPINFO_ALL_DEBUG
547 kDebug( 172 ) <<
"sending " << msg;
561 QString msg = QString::fromLatin1(
"remove: %1 %2" )
562 .arg( id_P.d->to_text()).arg( data_P.d->to_text());
563 kDebug( 172 ) <<
"sending " << msg;
575 QString msg = QString::fromLatin1(
"remove: %1 %2" )
576 .arg( id_P.d->to_text()).arg( data_P.d->to_text());
577#ifdef KSTARTUPINFO_ALL_DEBUG
578 kDebug( 172 ) <<
"sending " << msg;
591 kapp->clearStartupId();
608 else if( !qgetenv(
"DISPLAY" ).isEmpty() )
611 Display* disp = XOpenDisplay( NULL );
615 XCloseDisplay( disp );
645 bool activate =
true;
646 kapp->setStartupId( startup_id );
650 if( !startup_id.isEmpty() && startup_id !=
"0" )
676 return d->check_startup_internal( w_P, &id_O, &data_O );
681 return d->check_startup_internal( w_P, &id_O, NULL );
686 return d->check_startup_internal( w_P, NULL, &data_O );
691 return d->check_startup_internal( w_P, NULL, NULL );
697 if( startups.count() == 0 )
706 kDebug( 172 ) <<
"check_startup";
707 QByteArray
id = windowStartupId( w_P );
710 if(
id.isEmpty() ||
id ==
"0" )
712 kDebug( 172 ) <<
"ignore";
715 return find_id(
id, id_O, data_O ) ? Match : NoMatch;
718 NETWinInfo info( QX11Info::display(), w_P, QX11Info::appRootWindow(),
720 pid_t pid = info.pid();
723 QByteArray hostname = get_window_hostname( w_P );
724 if( !hostname.isEmpty()
725 && find_pid( pid, hostname, id_O, data_O ))
730 if( XGetClassHint( QX11Info::display(), w_P, &hint ) != 0 )
732 QByteArray res_name = hint.res_name;
733 QByteArray res_class = hint.res_class;
734 XFree( hint.res_name );
735 XFree( hint.res_class );
736 if( find_wclass( res_name, res_class, id_O, data_O ))
752 if( XGetTransientForHint( QX11Info::display(),
static_cast< Window >( w_P ), &transient_for )
753 &&
static_cast< WId
>( transient_for ) != QX11Info::appRootWindow()
754 && transient_for != None )
757 kDebug( 172 ) <<
"check_startup:cantdetect";
761bool KStartupInfo::Private::find_id(
const QByteArray& id_P,
KStartupInfoId* id_O,
764 kDebug( 172 ) <<
"find_id:" << id_P;
767 if( startups.contains(
id ))
772 *data_O = startups[ id ];
773 kDebug( 172 ) <<
"check_startup_id:match";
779bool KStartupInfo::Private::find_pid( pid_t pid_P,
const QByteArray& hostname_P,
782 kDebug( 172 ) <<
"find_pid:" << pid_P;
784 it != startups.end();
787 if( ( *it ).is_pid( pid_P ) && ( *it ).hostname() == hostname_P )
794 remove_startup_info_internal( it.key());
795 kDebug( 172 ) <<
"check_startup_pid:match";
802bool KStartupInfo::Private::find_wclass(
const QByteArray &_res_name,
const QByteArray &_res_class,
805 QByteArray res_name = _res_name.toLower();
806 QByteArray res_class = _res_class.toLower();
807 kDebug( 172 ) <<
"find_wclass:" << res_name <<
":" << res_class;
809 it != startups.end();
812 const QByteArray wmclass = ( *it ).findWMClass();
813 if( wmclass.toLower() == res_name || wmclass.toLower() == res_class )
820 remove_startup_info_internal( it.key());
821 kDebug( 172 ) <<
"check_startup_wclass:match";
834 unsigned char *name_ret;
837 unsigned long nitems_ret = 0, after_ret = 0;
838 if( XGetWindowProperty( QX11Info::display(), w_P,
net_startup_atom, 0l, 4096,
839 False,
utf8_string_atom, &type_ret, &format_ret, &nitems_ret, &after_ret, &name_ret )
843 ret =
reinterpret_cast< char*
>( name_ret );
844 if ( name_ret != NULL )
858 utf8_string_atom = XInternAtom( QX11Info::display(),
"UTF8_STRING", False );
862 XWMHints* hints = XGetWMHints( QX11Info::display(), w_P );
863 if( hints && ( hints->flags & WindowGroupHint ) != 0 )
882 utf8_string_atom = XInternAtom( QX11Info::display(),
"UTF8_STRING", False );
884 PropModeReplace,
reinterpret_cast< const unsigned char*
>( id_P.data()), id_P.length());
888QByteArray KStartupInfo::Private::get_window_hostname( WId w_P )
894 if( XGetWMClientMachine( QX11Info::display(), w_P, &tp ) != 0
895 && XTextPropertyToStringList( &tp, &hh, &cnt ) != 0 )
899 QByteArray hostname = hh[ 0 ];
900 XFreeStringList( hh );
903 XFreeStringList( hh );
914 QTimer::singleShot( 0,
this, SLOT(startups_cleanup_no_age()));
917void KStartupInfo::Private::startups_cleanup_no_age()
919 startups_cleanup_internal(
false );
922void KStartupInfo::Private::startups_cleanup()
924 if( startups.count() == 0 && silent_startups.count() == 0
925 && uninited_startups.count() == 0 )
930 startups_cleanup_internal(
true );
933void KStartupInfo::Private::startups_cleanup_internal(
bool age_P )
936 it != startups.end();
942 if( ( *it ).silent() == Data::Yes )
944 if( ( *it ).age >= tout )
948 kDebug( 172 ) <<
"entry timeout:" << key.
id();
949 remove_startup_info_internal( key );
955 it != silent_startups.end();
961 if( ( *it ).silent() == Data::Yes )
963 if( ( *it ).age >= tout )
967 kDebug( 172 ) <<
"entry timeout:" << key.
id();
968 remove_startup_info_internal( key );
974 it != uninited_startups.end();
980 if( ( *it ).silent() == Data::Yes )
982 if( ( *it ).age >= tout )
986 kDebug( 172 ) <<
"entry timeout:" << key.
id();
987 remove_startup_info_internal( key );
994void KStartupInfo::Private::clean_all_noncompliant()
997 it != startups.end();
1000 if( ( *it ).WMClass() !=
"0" )
1007 kDebug( 172 ) <<
"entry cleaning:" << key.
id();
1008 remove_startup_info_internal( key );
1017 gettimeofday( &tm, NULL );
1018 char hostname[ 256 ];
1019 hostname[ 0 ] =
'\0';
1020 if (!gethostname( hostname, 255 ))
1021 hostname[
sizeof(hostname)-1] =
'\0';
1023 unsigned long qt_x_user_time = QX11Info::appUserTime();
1025 unsigned long qt_x_user_time = 0;
1027 QByteArray
id = QString::fromLatin1(
"%1;%2;%3;%4_TIME%5" ).arg( hostname ).arg( tm.tv_sec )
1028 .arg( tm.tv_usec ).arg( getpid()).arg( qt_x_user_time ).toUtf8();
1029 kDebug( 172 ) <<
"creating: " <<
id <<
":" << (qApp ? qAppName() : QString(
"unnamed app") );
1040QString KStartupInfoId::Private::to_text()
const
1042 return QString::fromLatin1(
" ID=\"%1\" " ).arg(
escape_str(
id));
1047 const QStringList items =
get_fields( txt_P );
1048 const QString id_str = QLatin1String(
"ID=" );
1049 for( QStringList::ConstIterator it = items.begin();
1053 if( ( *it ).startsWith( id_str ))
1060 if( !id_P.isEmpty())
1063#ifdef KSTARTUPINFO_ALL_DEBUG
1064 kDebug( 172 ) <<
"using: " << d->id;
1069 if( !startup_env.isEmpty() )
1071 d->id = startup_env;
1072#ifdef KSTARTUPINFO_ALL_DEBUG
1073 kDebug( 172 ) <<
"reusing: " << d->id;
1094 if( !startup_env.isEmpty() )
1095 id.d->id = startup_env;
1129 return id() == id_P.
id();
1134 return !(*
this == id_P );
1140 return id() < id_P.
id();
1146 return d->id.isEmpty() || d->id ==
"0";
1153 int pos = d->id.lastIndexOf(
"_TIME" );
1157 unsigned long time = QString( d->id.mid( pos + 5 ) ).toULong( &ok );
1158 if( !ok && d->id[ pos + 5 ] ==
'-' )
1159 time = QString( d->id.mid( pos + 5 ) ).toLong( &ok );
1167 int pos1 = d->id.lastIndexOf(
'/' );
1170 int pos2 = d->id.lastIndexOf(
'/', pos1 - 1 );
1174 unsigned long time = QString( d->id.mid( pos2 + 1, pos1 - pos2 - 1 ) ).toULong( &ok );
1175 if( !ok && d->id[ pos2 + 1 ] ==
'-' )
1176 time = QString( d->id.mid( pos2 + 1, pos1 - pos2 - 1 ) ).toLong( &ok );
1185QString KStartupInfoData::Private::to_text()
const
1189 ret += QString::fromLatin1(
" BIN=\"%1\"" ).arg(
escape_str( bin ));
1190 if( !name.isEmpty())
1191 ret += QString::fromLatin1(
" NAME=\"%1\"" ).arg(
escape_str( name ));
1192 if( !description.isEmpty())
1193 ret += QString::fromLatin1(
" DESCRIPTION=\"%1\"" ).arg(
escape_str( description ));
1194 if( !icon.isEmpty())
1195 ret += QString::fromLatin1(
" ICON=\"%1\"" ).arg( icon );
1197 ret += QString::fromLatin1(
" DESKTOP=%1" )
1203 if( !wmclass.isEmpty())
1204 ret += QString::fromLatin1(
" WMCLASS=\"%1\"" ).arg( QString( wmclass ) );
1205 if( !hostname.isEmpty())
1206 ret += QString::fromLatin1(
" HOSTNAME=%1" ).arg( QString( hostname ) );
1210 ret += QString::fromLatin1(
" PID=%1" ).arg( *it );
1213 if( timestamp != ~0U )
1214 ret += QString::fromLatin1(
" TIMESTAMP=%1" ).arg( timestamp );
1216 ret += QString::fromLatin1(
" SCREEN=%1" ).arg( screen );
1217 if( xinerama != -1 )
1218 ret += QString::fromLatin1(
" XINERAMA=%1" ).arg( xinerama );
1219 if( launched_by != 0 )
1220 ret += QString::fromLatin1(
" LAUNCHED_BY=%1" ).arg( (qptrdiff)launched_by );
1221 if( !application_id.isEmpty())
1222 ret += QString::fromLatin1(
" APPLICATION_ID=\"%1\"" ).arg( application_id );
1228 const QStringList items =
get_fields( txt_P );
1229 const QString bin_str = QString::fromLatin1(
"BIN=" );
1230 const QString name_str = QString::fromLatin1(
"NAME=" );
1231 const QString description_str = QString::fromLatin1(
"DESCRIPTION=" );
1232 const QString icon_str = QString::fromLatin1(
"ICON=" );
1233 const QString desktop_str = QString::fromLatin1(
"DESKTOP=" );
1234 const QString wmclass_str = QString::fromLatin1(
"WMCLASS=" );
1235 const QString hostname_str = QString::fromLatin1(
"HOSTNAME=" );
1236 const QString pid_str = QString::fromLatin1(
"PID=" );
1237 const QString silent_str = QString::fromLatin1(
"SILENT=" );
1238 const QString timestamp_str = QString::fromLatin1(
"TIMESTAMP=" );
1239 const QString screen_str = QString::fromLatin1(
"SCREEN=" );
1240 const QString xinerama_str = QString::fromLatin1(
"XINERAMA=" );
1241 const QString launched_by_str = QString::fromLatin1(
"LAUNCHED_BY=" );
1242 const QString application_id_str = QString::fromLatin1(
"APPLICATION_ID=" );
1243 for( QStringList::ConstIterator it = items.begin();
1247 if( ( *it ).startsWith( bin_str ))
1249 else if( ( *it ).startsWith( name_str ))
1251 else if( ( *it ).startsWith( description_str ))
1252 d->description =
get_str( *it );
1253 else if( ( *it ).startsWith( icon_str ))
1255 else if( ( *it ).startsWith( desktop_str ))
1263 else if( ( *it ).startsWith( wmclass_str ))
1265 else if( ( *it ).startsWith( hostname_str ))
1267 else if( ( *it ).startsWith( pid_str ))
1269 else if( ( *it ).startsWith( silent_str ))
1271 else if( ( *it ).startsWith( timestamp_str ))
1273 else if( ( *it ).startsWith( screen_str ))
1275 else if( ( *it ).startsWith( xinerama_str ))
1277 else if( ( *it ).startsWith( launched_by_str ))
1278 d->launched_by = ( WId )
get_num( *it );
1279 else if( ( *it ).startsWith( application_id_str ))
1280 d->application_id =
get_str( *it );
1298 if( !data_P.
bin().isEmpty())
1299 d->bin = data_P.
bin();
1300 if( !data_P.
name().isEmpty() && name().isEmpty())
1301 d->name = data_P.
name();
1304 if( !data_P.
icon().isEmpty() &&
icon().isEmpty())
1305 d->icon = data_P.
icon();
1307 d->desktop = data_P.
desktop();
1308 if( !data_P.d->wmclass.isEmpty())
1309 d->wmclass = data_P.d->wmclass;
1310 if( !data_P.d->hostname.isEmpty())
1311 d->hostname = data_P.d->hostname;
1313 it != data_P.d->pids.constEnd();
1317 d->silent = data_P.
silent();
1320 if( data_P.
screen() != -1 )
1321 d->screen = data_P.
screen();
1361 if( !name().isEmpty())
1368 d->description = desc_P;
1373 return d->description;
1390 if( !
icon().isEmpty())
1402 d->desktop = desktop_P;
1412 d->wmclass = wmclass_P;
1419 return bin().toUtf8();
1429 if( !hostname_P.isNull())
1430 d->hostname = hostname_P;
1435 if (!gethostname( tmp, 255 ))
1436 tmp[
sizeof(tmp)-1] =
'\0';
1448 if( !d->pids.contains( pid_P ))
1449 d->pids.append( pid_P );
1452void KStartupInfoData::Private::remove_pid( pid_t pid_P )
1454 pids.removeAll( pid_P );
1464 return d->pids.contains( pid_P );
1469 d->silent = state_P;
1479 d->timestamp = time;
1484 return d->timestamp;
1489 d->screen = _screen;
1499 d->xinerama = xinerama;
1509 d->launched_by = window;
1514 return d->launched_by;
1519 if( desktop.startsWith(
'/' ))
1521 d->application_id = desktop;
1530 d->application_id = desk;
1535 return d->application_id;
1541 unsigned int pos = item_P.indexOf( QLatin1Char(
'=') );
1542 return item_P.mid( pos + 1 ).toLong();
1548 unsigned int pos = item_P.indexOf( QLatin1Char(
'=') );
1549 return item_P.mid( pos + 1 ).toULong();
1555 int pos = item_P.indexOf( QLatin1Char(
'=') );
1556 if( item_P.length() > pos + 2 && item_P.at( pos + 1 ) == QLatin1Char(
'\"') )
1558 int pos2 = item_P.left( pos + 2 ).indexOf( QLatin1Char(
'\"') );
1561 return item_P.mid( pos + 2, pos2 - 2 - pos );
1563 return item_P.mid( pos + 1 );
1569 return get_str( item_P ).toUtf8();
1575 QString txt = txt_P.simplified();
1579 bool escape =
false;
1589 else if( txt[ pos ] ==
'\\' )
1591 else if( txt[ pos ] ==
'\"' )
1593 else if( txt[ pos ] ==
' ' && !in )
1609 pos < str_P.length();
1612 if( str_P[ pos ] ==
'\\'
1613 || str_P[ pos ] ==
'"' )
1615 ret += str_P[ pos ];
1620#include "kstartupinfo.moc"
static KApplication * kApplication()
Returns the current application object.
static QString locate(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
Class representing data about an application startup notification.
const QString & findDescription() const
Returns the description of the startup notification.
const QString & description() const
Returns the name of the startup notification, or empty if not available.
QByteArray WMClass() const
Returns the WM_CLASS value for the startup notification, or empty if not available.
void update(const KStartupInfoData &data)
Updates the notification data from the given data.
void setHostname(const QByteArray &hostname=QByteArray())
Sets the hostname on which the application is starting.
TriState silent() const
Return the silence status for the startup notification.
unsigned long timestamp() const
void setDesktop(int desktop)
Sets the desktop for the startup notification ( i.e.
QString applicationId() const
The .desktop file used to initiate this startup notification, or empty.
KStartupInfoData & operator=(const KStartupInfoData &data)
const QString & findIcon() const
Returns the icon of the startup notification, and if it's not available, tries to get it from the bin...
QList< pid_t > pids() const
Returns all PIDs for the startup notification.
const QString & name() const
Returns the name of the startup notification, or empty if not available.
const QString & bin() const
Returns the binary name of the starting application.
void addPid(pid_t pid)
Adds a PID to the list of processes that belong to the startup notification.
void setName(const QString &name)
Sets the name for the notification (e.g.
WId launchedBy() const
The toplevel window of the application that caused this startup notification, 0 if unknown.
void setXinerama(int xinerama)
Sets the Xinerama screen for the startup notification ( i.e.
void setLaunchedBy(WId window)
Sets the toplevel window of the application that caused this startup notification.
int screen() const
The X11 screen on which the startup notification is happening, -1 if unknown.
void setWMClass(const QByteArray &wmclass)
Sets a WM_CLASS value for the startup notification, it may be used for increasing the chance that the...
void setIcon(const QString &icon)
Sets the icon for the startup notification ( e.g.
int xinerama() const
The Xinerama screen for the startup notification, -1 if unknown.
void setTimestamp(unsigned long time)
void setBin(const QString &bin)
Sets the binary name of the application ( e.g.
KStartupInfoData()
Constructor.
void setDescription(const QString &descr)
Sets the description for the notification (e.g.
const QString & icon() const
Returns the icon of the startup notification, or empty if not available.
const QByteArray findWMClass() const
Returns the WM_CLASS value for the startup notification, or binary name if not available.
void setSilent(TriState state)
Sets whether the visual feedback for this startup notification should be silenced (temporarily suspen...
bool is_pid(pid_t pid) const
Checks whether the given pid is in the list of PIDs for starup notification.
QByteArray hostname() const
Returns the hostname for the startup notification.
int desktop() const
Returns the desktop for the startup notification.
void setApplicationId(const QString &desktop)
Sets the .desktop file that was used to initiate the startup notification.
void setScreen(int screen)
Sets the X11 screen on which the startup notification should happen.
const QString & findName() const
Returns the name of the startup notification.
Class representing an identification of application startup notification.
void initId(const QByteArray &id="")
Initializes this object with the given identification ( which may be also "0" for no notification ),...
bool setupStartupEnv() const
Sets the startup notification environment variable to this identification.
unsigned long timestamp() const
Return the user timestamp for the startup notification, or 0 if no timestamp is set.
KStartupInfoId()
Creates an empty identification.
bool none() const
Checks whether the identifier is valid.
bool operator!=(const KStartupInfoId &id) const
Overloaded operator.
bool operator<(const KStartupInfoId &id) const
KStartupInfoId & operator=(const KStartupInfoId &data)
bool operator==(const KStartupInfoId &id) const
Overloaded operator.
const QByteArray & id() const
Returns the notification identifier as string.
Class for manipulating the application startup notification.
void setTimeout(unsigned int secs)
Sets the timeout for notifications, after this timeout a notification is removed.
static void disableAutoAppStartedSending(bool disable=true)
By default, the startup notification is ended for the application after it shows its first toplevel w...
static void appStarted()
Manual notification that the application has started.
static void setNewStartupId(QWidget *window, const QByteArray &startup_id)
Use this function if the application got a request with startup notification from outside (for exampl...
static bool sendStartupX(Display *dpy, const KStartupInfoId &id, const KStartupInfoData &data)
Like sendStartup , uses dpy instead of qt_x11display() for sending the info.
static bool sendStartup(const KStartupInfoId &id, const KStartupInfoData &data)
Sends given notification data about started application with the given startup identification.
startup_t checkStartup(WId w)
Checks if the given windows matches any existing startup notification.
static QByteArray windowStartupId(WId w)
Returns startup notification identification of the given window.
static bool sendChange(const KStartupInfoId &id, const KStartupInfoData &data)
Sends given notification data about started application with the given startup identification.
static void handleAutoAppStartedSending()
static void setWindowStartupId(WId window, const QByteArray &id)
Sets the startup notification window property on the given window.
static bool sendChangeX(Display *dpy, const KStartupInfoId &id, const KStartupInfoData &data)
Like sendChange , uses dpy instead of qt_x11display() for sending the info.
static void resetStartupEnv()
Unsets the startup notification environment variable.
static bool sendFinishX(Display *dpy, const KStartupInfoId &id)
Like sendFinish , uses dpy instead of qt_x11display() for sending the info.
void gotRemoveStartup(const KStartupInfoId &id, const KStartupInfoData &data)
Emitted when a startup notification is removed (either because it was detected that the application i...
void gotStartupChange(const KStartupInfoId &id, const KStartupInfoData &data)
Emitted when a startup notification changes.
void gotNewStartup(const KStartupInfoId &id, const KStartupInfoData &data)
Emitted when a new startup notification is created (i.e.
static KStartupInfoId currentStartupIdEnv()
Returns the current startup notification identification for the current startup notification environm...
static bool sendFinish(const KStartupInfoId &id)
Ends startup notification with the given identification.
virtual void customEvent(QEvent *e_P)
KStartupInfo(int flags, QObject *parent=0)
Creates an instance that will receive the startup notifications.
static void silenceStartup(bool silence)
If your application shows temporarily some window during its startup, for example a dialog,...
static QByteArray createNewStartupId()
Creates and returns new startup id.
static void setOnDesktop(WId win, int desktop)
Moves window win to desktop desktop.
static int currentDesktop()
Returns the current virtual desktop.
static void forceActiveWindow(WId win, long time=0)
Sets window win to be the active window.
static KWindowSystem * self()
Access to the singleton instance.
Sending string messages to other applications using the X Client Messages.
void broadcastMessage(const char *msg_type, const QString &message, int screen, bool obsolete)
Broadcasts the given message with the given message type.
static bool broadcastMessageX(Display *disp, const char *msg_type, const QString &message, int screen, bool obsolete)
Broadcasts the given message with the given message type.
Common API for root window properties/protocols.
bool isSupported(NET::Property property) const
Returns true if the given property is supported by the window manager.
Common API for application window properties/protocols.
@ Normal
indicates that this is a normal, top-level window
@ Unknown
indicates that the window did not define a window type.
@ Dialog
indicates that this is a dialog window
@ Utility
indicates a utility window
static QString get_str(const QString &item_P)
static const char *const NET_STARTUP_MSG
static QStringList get_fields(const QString &txt_P)
static Atom utf8_string_atom
static QByteArray read_startup_id_property(WId w_P)
static QByteArray get_cstr(const QString &item_P)
static long get_num(const QString &item_P)
static Atom net_startup_atom
static const char *const NET_STARTUP_WINDOW
static const char *const NET_STARTUP_ENV
static QString escape_str(const QString &str_P)
static bool auto_app_started_sending
static unsigned long get_unum(const QString &item_P)
const char * name(StandardAction id)
This will return the internal name of a given standard action.