• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • kdeui
  • kernel
kstartupinfo.cpp
Go to the documentation of this file.
1/****************************************************************************
2
3 Copyright (C) 2001-2003 Lubos Lunak <l.lunak@kde.org>
4
5Permission is hereby granted, free of charge, to any person obtaining a
6copy of this software and associated documentation files (the "Software"),
7to deal in the Software without restriction, including without limitation
8the rights to use, copy, modify, merge, publish, distribute, sublicense,
9and/or sell copies of the Software, and to permit persons to whom the
10Software is furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21DEALINGS IN THE SOFTWARE.
22
23****************************************************************************/
24
25// kDebug() can't be turned off in kdeinit
26#if 0
27#define KSTARTUPINFO_ALL_DEBUG
28#ifdef __GNUC__
29#warning Extra KStartupInfo debug messages enabled.
30#endif
31#endif
32
33#include "kstartupinfo.h"
34
35#include <QtGui/QWidget>
36#include <QtCore/QBool>
37
38#include <config.h>
39
40// need to resolve INT32(qglobal.h)<>INT32(Xlibint.h) conflict
41#ifndef QT_CLEAN_NAMESPACE
42#define QT_CLEAN_NAMESPACE
43#endif
44
45#include <unistd.h>
46#include <sys/time.h>
47#include <stdlib.h>
48#include <QtCore/QTimer>
49#include <QtGui/QActionEvent>
50#ifdef Q_WS_X11
51#include <qx11info_x11.h>
52#include <netwm.h>
53#endif
54#include <kdebug.h>
55#include <kapplication.h>
56#include <signal.h>
57#include <kstandarddirs.h>
58#ifdef Q_WS_X11
59#include <kwindowsystem.h>
60#include <kxmessages.h>
61#endif
62
63static const char* const NET_STARTUP_MSG = "_NET_STARTUP_INFO";
64static const char* const NET_STARTUP_WINDOW = "_NET_STARTUP_ID";
65// DESKTOP_STARTUP_ID is used also in kinit/wrapper.c ,
66// kdesu in both kdelibs and kdebase and who knows where else
67static const char* const NET_STARTUP_ENV = "DESKTOP_STARTUP_ID";
68
69static bool auto_app_started_sending = true;
70
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 );
77
78#ifdef Q_WS_X11
79static Atom utf8_string_atom = None;
80#endif
81
82class KStartupInfo::Data
83 : public KStartupInfoData
84 {
85 public:
86 Data() : age(0) {} // just because it's in a QMap
87 Data( const QString& txt_P )
88 : KStartupInfoData( txt_P ), age( 0 ) {}
89 unsigned int age;
90 };
91
92struct KStartupInfoId::Private
93 {
94 Private() : id( "" ) {}
95
96 QString to_text() const;
97
98 QByteArray id; // id
99 };
100
101struct KStartupInfoData::Private
102 {
103 Private() : desktop( 0 ), wmclass( "" ), hostname( "" ),
104 silent( KStartupInfoData::Unknown ), timestamp( ~0U ), screen( -1 ), xinerama( -1 ), launched_by( 0 ) {}
105
106 QString to_text() const;
107 void remove_pid( pid_t pid );
108
109 QString bin;
110 QString name;
111 QString description;
112 QString icon;
113 int desktop;
114 QList< pid_t > pids;
115 QByteArray wmclass;
116 QByteArray hostname;
117 KStartupInfoData::TriState silent;
118 unsigned long timestamp;
119 int screen;
120 int xinerama;
121 WId launched_by;
122 QString application_id;
123 };
124
125class KStartupInfo::Private
126 {
127 public:
128 // private slots
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 );
134
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 );
138 void new_startup_info_internal( const KStartupInfoId& id_P,
139 Data& data_P, bool update_only_P );
140 void remove_startup_info_internal( const KStartupInfoId& id_P );
141 void remove_startup_pids( const KStartupInfoId& id, const KStartupInfoData& data );
142 void remove_startup_pids( const KStartupInfoData& data );
143 startup_t check_startup_internal( WId w, KStartupInfoId* id, KStartupInfoData* data );
144 bool find_id( const QByteArray& id_P, KStartupInfoId* id_O,
145 KStartupInfoData* data_O );
146 bool find_pid( pid_t pid_P, const QByteArray& hostname, KStartupInfoId* id_O,
147 KStartupInfoData* data_O );
148 bool find_wclass( const QByteArray &res_name_P, const QByteArray &res_class_P,
149 KStartupInfoId* id_O, KStartupInfoData* data_O );
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,
154 const KStartupInfoData& data, int screen );
155
156
157 KStartupInfo *q;
158 unsigned int timeout;
159 QMap< KStartupInfoId, KStartupInfo::Data > startups;
160 // contains silenced ASN's only if !AnnounceSilencedChanges
161 QMap< KStartupInfoId, KStartupInfo::Data > silent_startups;
162 // contains ASN's that had change: but no new: yet
163 QMap< KStartupInfoId, KStartupInfo::Data > uninited_startups;
164#ifdef Q_WS_X11
165 KXMessages msgs;
166#endif
167 QTimer* cleanup;
168 int flags;
169
170 Private( int flags_P, KStartupInfo *q )
171 : q( q ),
172 timeout( 60 ),
173#ifdef Q_WS_X11
174 msgs( NET_STARTUP_MSG, NULL, false ),
175#endif
176 flags( flags_P )
177 {
178 }
179
180 void createConnections()
181 {
182#ifdef Q_WS_X11
183 // d == NULL means "disabled"
184 if( !KApplication::kApplication())
185 return;
186 if( !QX11Info::display())
187 return;
188
189 if( !( flags & DisableKWinModule )) {
190 QObject::connect( KWindowSystem::self(), SIGNAL(windowAdded(WId)), q, SLOT(slot_window_added(WId)));
191#ifdef __GNUC__
192#warning "systemTrayWindowAdded signal was remove from KWindowSystem class"
193#endif
194 //QObject::connect( KWindowSystem::self(), SIGNAL(systemTrayWindowAdded(WId)), q, SLOT(slot_window_added(WId)));
195 }
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()));
199#endif
200 }
201 };
202
203KStartupInfo::KStartupInfo( int flags_P, QObject* parent_P )
204 : QObject( parent_P ),
205 d(new Private(flags_P, this))
206 {
207 d->createConnections();
208 }
209
210KStartupInfo::KStartupInfo( bool clean_on_cantdetect_P, QObject* parent_P )
211 : QObject( parent_P ),
212 d(new Private(clean_on_cantdetect_P ? CleanOnCantDetect : 0, this))
213 {
214 d->createConnections();
215 }
216
217
218KStartupInfo::~KStartupInfo()
219 {
220 delete d;
221 }
222
223void KStartupInfo::Private::got_message( const QString& msg_P )
224 {
225#ifdef Q_WS_X11
226// TODO do something with SCREEN= ?
227 kDebug( 172 ) << "got:" << msg_P;
228 QString msg = msg_P.trimmed();
229 if( msg.startsWith( QLatin1String("new:") )) // must match length below
230 got_startup_info( msg.mid( 4 ), false );
231 else if( msg.startsWith( QLatin1String("change:") )) // must match length below
232 got_startup_info( msg.mid( 7 ), true );
233 else if( msg.startsWith( QLatin1String("remove:") )) // must match length below
234 got_remove_startup_info( msg.mid( 7 ));
235#endif
236 }
237
238// if the application stops responding for a while, KWindowSystem may get
239// the information about the already mapped window before KXMessages
240// actually gets the info about the started application (depends
241// on their order in X11 event filter in KApplication)
242// simply delay info from KWindowSystem a bit
243// SELI???
244namespace
245{
246class DelayedWindowEvent
247 : public QEvent
248 {
249 public:
250 DelayedWindowEvent( WId w_P )
251 : QEvent( uniqueType() ), w( w_P ) {}
252#ifdef Q_WS_X11
253 Window w;
254#else
255 WId w;
256#endif
257 static Type uniqueType() { return Type(QEvent::User+15); }
258 };
259}
260
261void KStartupInfo::Private::slot_window_added( WId w_P )
262 {
263 qApp->postEvent( q, new DelayedWindowEvent( w_P ));
264 }
265
266void KStartupInfo::customEvent( QEvent* e_P )
267 {
268#ifdef Q_WS_X11
269 if( e_P->type() == DelayedWindowEvent::uniqueType() )
270 d->window_added( static_cast< DelayedWindowEvent* >( e_P )->w );
271 else
272#endif
273 QObject::customEvent( e_P );
274 }
275
276void KStartupInfo::Private::window_added( WId w_P )
277 {
278 KStartupInfoId id;
279 KStartupInfoData data;
280 startup_t ret = check_startup_internal( w_P, &id, &data );
281 switch( ret )
282 {
283 case Match:
284 kDebug( 172 ) << "new window match";
285 break;
286 case NoMatch:
287 break; // nothing
288 case CantDetect:
289 if( flags & CleanOnCantDetect )
290 clean_all_noncompliant();
291 break;
292 }
293 }
294
295void KStartupInfo::Private::got_startup_info( const QString& msg_P, bool update_P )
296 {
297 KStartupInfoId id( msg_P );
298 if( id.none())
299 return;
300 KStartupInfo::Data data( msg_P );
301 new_startup_info_internal( id, data, update_P );
302 }
303
304void KStartupInfo::Private::new_startup_info_internal( const KStartupInfoId& id_P,
305 KStartupInfo::Data& data_P, bool update_P )
306 {
307 if( id_P.none())
308 return;
309 if( startups.contains( id_P ))
310 { // already reported, update
311 startups[ id_P ].update( data_P );
312 startups[ id_P ].age = 0; // CHECKME
313 kDebug( 172 ) << "updating";
314 if( startups[ id_P ].silent() == KStartupInfo::Data::Yes
315 && !( flags & AnnounceSilenceChanges ))
316 {
317 silent_startups[ id_P ] = startups[ id_P ];
318 startups.remove( id_P );
319 emit q->gotRemoveStartup( id_P, silent_startups[ id_P ] );
320 return;
321 }
322 emit q->gotStartupChange( id_P, startups[ id_P ] );
323 return;
324 }
325 if( silent_startups.contains( id_P ))
326 { // already reported, update
327 silent_startups[ id_P ].update( data_P );
328 silent_startups[ id_P ].age = 0; // CHECKME
329 kDebug( 172 ) << "updating silenced";
330 if( silent_startups[ id_P ].silent() != Data::Yes )
331 {
332 startups[ id_P ] = silent_startups[ id_P ];
333 silent_startups.remove( id_P );
334 q->emit gotNewStartup( id_P, startups[ id_P ] );
335 return;
336 }
337 emit q->gotStartupChange( id_P, silent_startups[ id_P ] );
338 return;
339 }
340 if( uninited_startups.contains( id_P ))
341 {
342 uninited_startups[ id_P ].update( data_P );
343 kDebug( 172 ) << "updating uninited";
344 if( !update_P ) // uninited finally got new:
345 {
346 startups[ id_P ] = uninited_startups[ id_P ];
347 uninited_startups.remove( id_P );
348 emit q->gotNewStartup( id_P, startups[ id_P ] );
349 return;
350 }
351 // no change announce, it's still uninited
352 return;
353 }
354 if( update_P ) // change: without any new: first
355 {
356 kDebug( 172 ) << "adding uninited";
357 uninited_startups.insert( id_P, data_P );
358 }
359 else if( data_P.silent() != Data::Yes || flags & AnnounceSilenceChanges )
360 {
361 kDebug( 172 ) << "adding";
362 startups.insert( id_P, data_P );
363 emit q->gotNewStartup( id_P, data_P );
364 }
365 else // new silenced, and silent shouldn't be announced
366 {
367 kDebug( 172 ) << "adding silent";
368 silent_startups.insert( id_P, data_P );
369 }
370 cleanup->start( 1000 ); // 1 sec
371 }
372
373void KStartupInfo::Private::got_remove_startup_info( const QString& msg_P )
374 {
375 KStartupInfoId id( msg_P );
376 KStartupInfoData data( msg_P );
377 if( data.pids().count() > 0 )
378 {
379 if( !id.none())
380 remove_startup_pids( id, data );
381 else
382 remove_startup_pids( data );
383 return;
384 }
385 remove_startup_info_internal( id );
386 }
387
388void KStartupInfo::Private::remove_startup_info_internal( const KStartupInfoId& id_P )
389 {
390 if( startups.contains( id_P ))
391 {
392 kDebug( 172 ) << "removing";
393 emit q->gotRemoveStartup( id_P, startups[ id_P ]);
394 startups.remove( id_P );
395 }
396 else if( silent_startups.contains( id_P ))
397 {
398 kDebug( 172 ) << "removing silent";
399 silent_startups.remove( id_P );
400 }
401 else if( uninited_startups.contains( id_P ))
402 {
403 kDebug( 172 ) << "removing uninited";
404 uninited_startups.remove( id_P );
405 }
406 return;
407 }
408
409void KStartupInfo::Private::remove_startup_pids( const KStartupInfoData& data_P )
410 { // first find the matching info
411 for( QMap< KStartupInfoId, KStartupInfo::Data >::Iterator it = startups.begin();
412 it != startups.end();
413 ++it )
414 {
415 if( ( *it ).hostname() != data_P.hostname())
416 continue;
417 if( !( *it ).is_pid( data_P.pids().first()))
418 continue; // not the matching info
419 remove_startup_pids( it.key(), data_P );
420 break;
421 }
422 }
423
424void KStartupInfo::Private::remove_startup_pids( const KStartupInfoId& id_P,
425 const KStartupInfoData& data_P )
426 {
427 kFatal( data_P.pids().count() == 0, 172 );
428 Data* data = NULL;
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 ];
435 else
436 return;
437 for( QList< pid_t >::ConstIterator it2 = data_P.pids().constBegin();
438 it2 != data_P.pids().constEnd();
439 ++it2 )
440 data->d->remove_pid( *it2 ); // remove all pids from the info
441 if( data->pids().count() == 0 ) // all pids removed -> remove info
442 remove_startup_info_internal( id_P );
443 }
444
445bool KStartupInfo::sendStartup( const KStartupInfoId& id_P, const KStartupInfoData& data_P )
446 {
447 if( id_P.none())
448 return false;
449#ifdef Q_WS_X11
450 KXMessages msgs;
451 QString msg = QString::fromLatin1( "new: %1 %2" )
452 .arg( id_P.d->to_text()).arg( data_P.d->to_text());
453 QX11Info inf;
454 msg = Private::check_required_startup_fields( msg, data_P, inf.screen());
455 kDebug( 172 ) << "sending " << msg;
456 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1, false );
457#endif
458 return true;
459 }
460
461bool KStartupInfo::sendStartupX( Display* disp_P, const KStartupInfoId& id_P,
462 const KStartupInfoData& data_P )
463 {
464 if( id_P.none())
465 return false;
466#ifdef Q_WS_X11
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;
472#endif
473 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1, false );
474#else
475 return true;
476#endif
477 }
478
479QString KStartupInfo::Private::check_required_startup_fields( const QString& msg, const KStartupInfoData& data_P,
480 int screen )
481 {
482 QString ret = msg;
483 if( data_P.name().isEmpty())
484 {
485// kWarning( 172 ) << "NAME not specified in initial startup message";
486 QString name = data_P.bin();
487 if( name.isEmpty())
488 name = "UNKNOWN";
489 ret += QString( " NAME=\"%1\"" ).arg( escape_str( name ));
490 }
491 if( data_P.screen() == -1 ) // add automatically if needed
492 ret += QString( " SCREEN=%1" ).arg( screen );
493 return ret;
494 }
495
496bool KStartupInfo::sendChange( const KStartupInfoId& id_P, const KStartupInfoData& data_P )
497 {
498 if( id_P.none())
499 return false;
500#ifdef Q_WS_X11
501 KXMessages msgs;
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;
505 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1, false );
506#endif
507 return true;
508 }
509
510bool KStartupInfo::sendChangeX( Display* disp_P, const KStartupInfoId& id_P,
511 const KStartupInfoData& data_P )
512 {
513 if( id_P.none())
514 return false;
515#ifdef Q_WS_X11
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;
520#endif
521 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1, false );
522#else
523 return true;
524#endif
525 }
526
527bool KStartupInfo::sendFinish( const KStartupInfoId& id_P )
528 {
529 if( id_P.none())
530 return false;
531#ifdef Q_WS_X11
532 KXMessages msgs;
533 QString msg = QString::fromLatin1( "remove: %1" ).arg( id_P.d->to_text());
534 kDebug( 172 ) << "sending " << msg;
535 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1, false );
536#endif
537 return true;
538 }
539
540bool KStartupInfo::sendFinishX( Display* disp_P, const KStartupInfoId& id_P )
541 {
542 if( id_P.none())
543 return false;
544#ifdef Q_WS_X11
545 QString msg = QString::fromLatin1( "remove: %1" ).arg( id_P.d->to_text());
546#ifdef KSTARTUPINFO_ALL_DEBUG
547 kDebug( 172 ) << "sending " << msg;
548#endif
549 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1, false );
550#else
551 return true;
552#endif
553 }
554
555bool KStartupInfo::sendFinish( const KStartupInfoId& id_P, const KStartupInfoData& data_P )
556 {
557// if( id_P.none()) // id may be none, the pids and hostname matter then
558// return false;
559#ifdef Q_WS_X11
560 KXMessages msgs;
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;
564 msgs.broadcastMessage( NET_STARTUP_MSG, msg, -1, false );
565#endif
566 return true;
567 }
568
569bool KStartupInfo::sendFinishX( Display* disp_P, const KStartupInfoId& id_P,
570 const KStartupInfoData& data_P )
571 {
572// if( id_P.none()) // id may be none, the pids and hostname matter then
573// return false;
574#ifdef Q_WS_X11
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;
579#endif
580 return KXMessages::broadcastMessageX( disp_P, NET_STARTUP_MSG, msg, -1, false );
581#else
582 return true;
583#endif
584 }
585
586void KStartupInfo::appStarted()
587 {
588 if( kapp != NULL ) // KApplication constructor unsets the env. variable
589 {
590 appStarted( kapp->startupId());
591 kapp->clearStartupId(); // reset the id, no longer valid (must use clearStartupId() to avoid infinite loop)
592 }
593 else
594 {
595 appStarted( currentStartupIdEnv().id());
596 resetStartupEnv();
597 }
598 }
599
600void KStartupInfo::appStarted( const QByteArray& startup_id )
601 {
602 KStartupInfoId id;
603 id.initId( startup_id );
604 if( id.none())
605 return;
606 if( kapp != NULL )
607 KStartupInfo::sendFinish( id );
608 else if( !qgetenv( "DISPLAY" ).isEmpty() ) // don't rely on QX11Info::display()
609 {
610#ifdef Q_WS_X11
611 Display* disp = XOpenDisplay( NULL );
612 if( disp != NULL )
613 {
614 KStartupInfo::sendFinishX( disp, id );
615 XCloseDisplay( disp );
616 }
617#endif
618 }
619 }
620
621void KStartupInfo::disableAutoAppStartedSending( bool disable )
622 {
623 auto_app_started_sending = !disable;
624 }
625
626void KStartupInfo::silenceStartup( bool silence )
627 {
628 KStartupInfoId id;
629 id.initId( kapp->startupId());
630 if( id.none())
631 return;
632 KStartupInfoData data;
633 data.setSilent( silence ? KStartupInfoData::Yes : KStartupInfoData::No );
634 sendChange( id, data );
635 }
636
637void KStartupInfo::handleAutoAppStartedSending()
638 {
639 if( auto_app_started_sending )
640 appStarted();
641 }
642
643void KStartupInfo::setNewStartupId( QWidget* window, const QByteArray& startup_id )
644 {
645 bool activate = true;
646 kapp->setStartupId( startup_id );
647#ifdef Q_WS_X11
648 if( window != NULL )
649 {
650 if( !startup_id.isEmpty() && startup_id != "0" )
651 {
652 NETRootInfo i( QX11Info::display(), NET::Supported );
653 if( i.isSupported( NET::WM2StartupId ))
654 {
655 KStartupInfo::setWindowStartupId( window->winId(), startup_id );
656 activate = false; // WM will take care of it
657 }
658 }
659 if( activate )
660 {
661 KWindowSystem::setOnDesktop( window->winId(), KWindowSystem::currentDesktop());
662 // This is not very nice, but there's no way how to get any
663 // usable timestamp without ASN, so force activating the window.
664 // And even with ASN, it's not possible to get the timestamp here,
665 // so if the WM doesn't have support for ASN, it can't be used either.
666 KWindowSystem::forceActiveWindow( window->winId());
667 }
668 }
669#endif
670 KStartupInfo::handleAutoAppStartedSending();
671 }
672
673KStartupInfo::startup_t KStartupInfo::checkStartup( WId w_P, KStartupInfoId& id_O,
674 KStartupInfoData& data_O )
675 {
676 return d->check_startup_internal( w_P, &id_O, &data_O );
677 }
678
679KStartupInfo::startup_t KStartupInfo::checkStartup( WId w_P, KStartupInfoId& id_O )
680 {
681 return d->check_startup_internal( w_P, &id_O, NULL );
682 }
683
684KStartupInfo::startup_t KStartupInfo::checkStartup( WId w_P, KStartupInfoData& data_O )
685 {
686 return d->check_startup_internal( w_P, NULL, &data_O );
687 }
688
689KStartupInfo::startup_t KStartupInfo::checkStartup( WId w_P )
690 {
691 return d->check_startup_internal( w_P, NULL, NULL );
692 }
693
694KStartupInfo::startup_t KStartupInfo::Private::check_startup_internal( WId w_P, KStartupInfoId* id_O,
695 KStartupInfoData* data_O )
696 {
697 if( startups.count() == 0 )
698 return NoMatch; // no startups
699 // Strategy:
700 //
701 // Is this a compliant app ?
702 // - Yes - test for match
703 // - No - Is this a NET_WM compliant app ?
704 // - Yes - test for pid match
705 // - No - test for WM_CLASS match
706 kDebug( 172 ) << "check_startup";
707 QByteArray id = windowStartupId( w_P );
708 if( !id.isNull())
709 {
710 if( id.isEmpty() || id == "0" ) // means ignore this window
711 {
712 kDebug( 172 ) << "ignore";
713 return NoMatch;
714 }
715 return find_id( id, id_O, data_O ) ? Match : NoMatch;
716 }
717#ifdef Q_WS_X11
718 NETWinInfo info( QX11Info::display(), w_P, QX11Info::appRootWindow(),
719 NET::WMWindowType | NET::WMPid | NET::WMState );
720 pid_t pid = info.pid();
721 if( pid > 0 )
722 {
723 QByteArray hostname = get_window_hostname( w_P );
724 if( !hostname.isEmpty()
725 && find_pid( pid, hostname, id_O, data_O ))
726 return Match;
727 // try XClass matching , this PID stuff sucks :(
728 }
729 XClassHint hint;
730 if( XGetClassHint( QX11Info::display(), w_P, &hint ) != 0 )
731 { // We managed to read the class hint
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 ))
737 return Match;
738 }
739 // ignore NET::Tool and other special window types, if they can't be matched
740 NET::WindowType type = info.windowType( NET::NormalMask | NET::DesktopMask
741 | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
742 | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
743 if( type != NET::Normal
744 && type != NET::Override
745 && type != NET::Unknown
746 && type != NET::Dialog
747 && type != NET::Utility )
748// && type != NET::Dock ) why did I put this here?
749 return NoMatch;
750 // lets see if this is a transient
751 Window transient_for;
752 if( XGetTransientForHint( QX11Info::display(), static_cast< Window >( w_P ), &transient_for )
753 && static_cast< WId >( transient_for ) != QX11Info::appRootWindow()
754 && transient_for != None )
755 return NoMatch;
756#endif
757 kDebug( 172 ) << "check_startup:cantdetect";
758 return CantDetect;
759 }
760
761bool KStartupInfo::Private::find_id( const QByteArray& id_P, KStartupInfoId* id_O,
762 KStartupInfoData* data_O )
763 {
764 kDebug( 172 ) << "find_id:" << id_P;
765 KStartupInfoId id;
766 id.initId( id_P );
767 if( startups.contains( id ))
768 {
769 if( id_O != NULL )
770 *id_O = id;
771 if( data_O != NULL )
772 *data_O = startups[ id ];
773 kDebug( 172 ) << "check_startup_id:match";
774 return true;
775 }
776 return false;
777 }
778
779bool KStartupInfo::Private::find_pid( pid_t pid_P, const QByteArray& hostname_P,
780 KStartupInfoId* id_O, KStartupInfoData* data_O )
781 {
782 kDebug( 172 ) << "find_pid:" << pid_P;
783 for( QMap< KStartupInfoId, KStartupInfo::Data >::Iterator it = startups.begin();
784 it != startups.end();
785 ++it )
786 {
787 if( ( *it ).is_pid( pid_P ) && ( *it ).hostname() == hostname_P )
788 { // Found it !
789 if( id_O != NULL )
790 *id_O = it.key();
791 if( data_O != NULL )
792 *data_O = *it;
793 // non-compliant, remove on first match
794 remove_startup_info_internal( it.key());
795 kDebug( 172 ) << "check_startup_pid:match";
796 return true;
797 }
798 }
799 return false;
800 }
801
802bool KStartupInfo::Private::find_wclass( const QByteArray &_res_name, const QByteArray &_res_class,
803 KStartupInfoId* id_O, KStartupInfoData* data_O )
804 {
805 QByteArray res_name = _res_name.toLower();
806 QByteArray res_class = _res_class.toLower();
807 kDebug( 172 ) << "find_wclass:" << res_name << ":" << res_class;
808 for( QMap< KStartupInfoId, Data >::Iterator it = startups.begin();
809 it != startups.end();
810 ++it )
811 {
812 const QByteArray wmclass = ( *it ).findWMClass();
813 if( wmclass.toLower() == res_name || wmclass.toLower() == res_class )
814 { // Found it !
815 if( id_O != NULL )
816 *id_O = it.key();
817 if( data_O != NULL )
818 *data_O = *it;
819 // non-compliant, remove on first match
820 remove_startup_info_internal( it.key());
821 kDebug( 172 ) << "check_startup_wclass:match";
822 return true;
823 }
824 }
825 return false;
826 }
827
828#ifdef Q_WS_X11
829static Atom net_startup_atom = None;
830
831static QByteArray read_startup_id_property( WId w_P )
832 {
833 QByteArray ret;
834 unsigned char *name_ret;
835 Atom type_ret;
836 int format_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 )
840 == Success )
841 {
842 if( type_ret == utf8_string_atom && format_ret == 8 && name_ret != NULL )
843 ret = reinterpret_cast< char* >( name_ret );
844 if ( name_ret != NULL )
845 XFree( name_ret );
846 }
847 return ret;
848 }
849
850#endif
851
852QByteArray KStartupInfo::windowStartupId( WId w_P )
853 {
854#ifdef Q_WS_X11
855 if( net_startup_atom == None )
856 net_startup_atom = XInternAtom( QX11Info::display(), NET_STARTUP_WINDOW, False );
857 if( utf8_string_atom == None )
858 utf8_string_atom = XInternAtom( QX11Info::display(), "UTF8_STRING", False );
859 QByteArray ret = read_startup_id_property( w_P );
860 if( ret.isEmpty())
861 { // retry with window group leader, as the spec says
862 XWMHints* hints = XGetWMHints( QX11Info::display(), w_P );
863 if( hints && ( hints->flags & WindowGroupHint ) != 0 )
864 ret = read_startup_id_property( hints->window_group );
865 if( hints )
866 XFree( hints );
867 }
868 return ret;
869#else
870 return QByteArray();
871#endif
872 }
873
874void KStartupInfo::setWindowStartupId( WId w_P, const QByteArray& id_P )
875 {
876#ifdef Q_WS_X11
877 if( id_P.isNull())
878 return;
879 if( net_startup_atom == None )
880 net_startup_atom = XInternAtom( QX11Info::display(), NET_STARTUP_WINDOW, False );
881 if( utf8_string_atom == None )
882 utf8_string_atom = XInternAtom( QX11Info::display(), "UTF8_STRING", False );
883 XChangeProperty( QX11Info::display(), w_P, net_startup_atom, utf8_string_atom, 8,
884 PropModeReplace, reinterpret_cast< const unsigned char* >( id_P.data()), id_P.length());
885#endif
886 }
887
888QByteArray KStartupInfo::Private::get_window_hostname( WId w_P )
889 {
890#ifdef Q_WS_X11
891 XTextProperty tp;
892 char** hh;
893 int cnt;
894 if( XGetWMClientMachine( QX11Info::display(), w_P, &tp ) != 0
895 && XTextPropertyToStringList( &tp, &hh, &cnt ) != 0 )
896 {
897 if( cnt == 1 )
898 {
899 QByteArray hostname = hh[ 0 ];
900 XFreeStringList( hh );
901 return hostname;
902 }
903 XFreeStringList( hh );
904 }
905#endif
906 // no hostname
907 return QByteArray();
908 }
909
910void KStartupInfo::setTimeout( unsigned int secs_P )
911 {
912 d->timeout = secs_P;
913 // schedule removing entries that are older than the new timeout
914 QTimer::singleShot( 0, this, SLOT(startups_cleanup_no_age()));
915 }
916
917void KStartupInfo::Private::startups_cleanup_no_age()
918 {
919 startups_cleanup_internal( false );
920 }
921
922void KStartupInfo::Private::startups_cleanup()
923 {
924 if( startups.count() == 0 && silent_startups.count() == 0
925 && uninited_startups.count() == 0 )
926 {
927 cleanup->stop();
928 return;
929 }
930 startups_cleanup_internal( true );
931 }
932
933void KStartupInfo::Private::startups_cleanup_internal( bool age_P )
934 {
935 for( QMap< KStartupInfoId, KStartupInfo::Data >::Iterator it = startups.begin();
936 it != startups.end();
937 )
938 {
939 if( age_P )
940 ( *it ).age++;
941 unsigned int tout = timeout;
942 if( ( *it ).silent() == Data::Yes ) // TODO
943 tout *= 20;
944 if( ( *it ).age >= tout )
945 {
946 const KStartupInfoId& key = it.key();
947 ++it;
948 kDebug( 172 ) << "entry timeout:" << key.id();
949 remove_startup_info_internal( key );
950 }
951 else
952 ++it;
953 }
954 for( QMap< KStartupInfoId, KStartupInfo::Data >::Iterator it = silent_startups.begin();
955 it != silent_startups.end();
956 )
957 {
958 if( age_P )
959 ( *it ).age++;
960 unsigned int tout = timeout;
961 if( ( *it ).silent() == Data::Yes ) // TODO
962 tout *= 20;
963 if( ( *it ).age >= tout )
964 {
965 const KStartupInfoId& key = it.key();
966 ++it;
967 kDebug( 172 ) << "entry timeout:" << key.id();
968 remove_startup_info_internal( key );
969 }
970 else
971 ++it;
972 }
973 for( QMap< KStartupInfoId, KStartupInfo::Data >::Iterator it = uninited_startups.begin();
974 it != uninited_startups.end();
975 )
976 {
977 if( age_P )
978 ( *it ).age++;
979 unsigned int tout = timeout;
980 if( ( *it ).silent() == Data::Yes ) // TODO
981 tout *= 20;
982 if( ( *it ).age >= tout )
983 {
984 const KStartupInfoId& key = it.key();
985 ++it;
986 kDebug( 172 ) << "entry timeout:" << key.id();
987 remove_startup_info_internal( key );
988 }
989 else
990 ++it;
991 }
992 }
993
994void KStartupInfo::Private::clean_all_noncompliant()
995 {
996 for( QMap< KStartupInfoId, KStartupInfo::Data >::Iterator it = startups.begin();
997 it != startups.end();
998 )
999 {
1000 if( ( *it ).WMClass() != "0" )
1001 {
1002 ++it;
1003 continue;
1004 }
1005 const KStartupInfoId& key = it.key();
1006 ++it;
1007 kDebug( 172 ) << "entry cleaning:" << key.id();
1008 remove_startup_info_internal( key );
1009 }
1010 }
1011
1012QByteArray KStartupInfo::createNewStartupId()
1013 {
1014 // Assign a unique id, use hostname+time+pid, that should be 200% unique.
1015 // Also append the user timestamp (for focus stealing prevention).
1016 struct timeval tm;
1017 gettimeofday( &tm, NULL );
1018 char hostname[ 256 ];
1019 hostname[ 0 ] = '\0';
1020 if (!gethostname( hostname, 255 ))
1021 hostname[sizeof(hostname)-1] = '\0';
1022#ifdef Q_WS_X11
1023 unsigned long qt_x_user_time = QX11Info::appUserTime();
1024#else
1025 unsigned long qt_x_user_time = 0;
1026#endif
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") /* e.g. kdeinit */);
1030 return id;
1031 }
1032
1033
1034const QByteArray& KStartupInfoId::id() const
1035 {
1036 return d->id;
1037 }
1038
1039
1040QString KStartupInfoId::Private::to_text() const
1041 {
1042 return QString::fromLatin1( " ID=\"%1\" " ).arg( escape_str( id));
1043 }
1044
1045KStartupInfoId::KStartupInfoId( const QString& txt_P ) : d(new Private)
1046 {
1047 const QStringList items = get_fields( txt_P );
1048 const QString id_str = QLatin1String( "ID=" );
1049 for( QStringList::ConstIterator it = items.begin();
1050 it != items.end();
1051 ++it )
1052 {
1053 if( ( *it ).startsWith( id_str ))
1054 d->id = get_cstr( *it );
1055 }
1056 }
1057
1058void KStartupInfoId::initId( const QByteArray& id_P )
1059 {
1060 if( !id_P.isEmpty())
1061 {
1062 d->id = id_P;
1063#ifdef KSTARTUPINFO_ALL_DEBUG
1064 kDebug( 172 ) << "using: " << d->id;
1065#endif
1066 return;
1067 }
1068 const QByteArray startup_env = qgetenv( NET_STARTUP_ENV );
1069 if( !startup_env.isEmpty() )
1070 { // already has id
1071 d->id = startup_env;
1072#ifdef KSTARTUPINFO_ALL_DEBUG
1073 kDebug( 172 ) << "reusing: " << d->id;
1074#endif
1075 return;
1076 }
1077 d->id = KStartupInfo::createNewStartupId();
1078 }
1079
1080bool KStartupInfoId::setupStartupEnv() const
1081 {
1082 if( none())
1083 {
1084 unsetenv( NET_STARTUP_ENV );
1085 return false;
1086 }
1087 return setenv( NET_STARTUP_ENV, id(), true ) == 0;
1088 }
1089
1090KStartupInfoId KStartupInfo::currentStartupIdEnv()
1091 {
1092 const QByteArray startup_env = qgetenv( NET_STARTUP_ENV );
1093 KStartupInfoId id;
1094 if( !startup_env.isEmpty() )
1095 id.d->id = startup_env;
1096 else
1097 id.d->id = "0";
1098 return id;
1099 }
1100
1101void KStartupInfo::resetStartupEnv()
1102 {
1103 unsetenv( NET_STARTUP_ENV );
1104 }
1105
1106KStartupInfoId::KStartupInfoId() : d(new Private)
1107 {
1108 }
1109
1110KStartupInfoId::~KStartupInfoId()
1111 {
1112 delete d;
1113 }
1114
1115KStartupInfoId::KStartupInfoId( const KStartupInfoId& id_P ) : d(new Private(*id_P.d))
1116 {
1117 }
1118
1119KStartupInfoId& KStartupInfoId::operator=( const KStartupInfoId& id_P )
1120 {
1121 if( &id_P == this )
1122 return *this;
1123 *d = *id_P.d;
1124 return *this;
1125 }
1126
1127bool KStartupInfoId::operator==( const KStartupInfoId& id_P ) const
1128 {
1129 return id() == id_P.id();
1130 }
1131
1132bool KStartupInfoId::operator!=( const KStartupInfoId& id_P ) const
1133 {
1134 return !(*this == id_P );
1135 }
1136
1137// needed for QMap
1138bool KStartupInfoId::operator<( const KStartupInfoId& id_P ) const
1139 {
1140 return id() < id_P.id();
1141 }
1142
1143// KDE5 TODO: rename to isNull ?
1144bool KStartupInfoId::none() const
1145 {
1146 return d->id.isEmpty() || d->id == "0";
1147 }
1148
1149unsigned long KStartupInfoId::timestamp() const
1150 {
1151 if( none())
1152 return 0;
1153 int pos = d->id.lastIndexOf( "_TIME" );
1154 if( pos >= 0 )
1155 {
1156 bool ok;
1157 unsigned long time = QString( d->id.mid( pos + 5 ) ).toULong( &ok );
1158 if( !ok && d->id[ pos + 5 ] == '-' ) // try if it's as a negative signed number perhaps
1159 time = QString( d->id.mid( pos + 5 ) ).toLong( &ok );
1160 if( ok )
1161 return time;
1162 }
1163 // libstartup-notification style :
1164 // qsnprintf (s, len, "%s/%s/%lu/%d-%d-%s",
1165 // canonicalized_launcher, canonicalized_launchee, (unsigned long) timestamp,
1166 // (int) getpid (), (int) sequence_number, hostbuf);
1167 int pos1 = d->id.lastIndexOf( '/' );
1168 if( pos1 > 0 )
1169 {
1170 int pos2 = d->id.lastIndexOf( '/', pos1 - 1 );
1171 if( pos2 >= 0 )
1172 {
1173 bool ok;
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 );
1177 if( ok )
1178 return time;
1179 }
1180 }
1181 // bah ... old KStartupInfo or a problem
1182 return 0;
1183 }
1184
1185QString KStartupInfoData::Private::to_text() const
1186 {
1187 QString ret;
1188 if( !bin.isEmpty())
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 );
1196 if( desktop != 0 )
1197 ret += QString::fromLatin1( " DESKTOP=%1" )
1198#ifdef Q_WS_X11
1199 .arg( desktop == NET::OnAllDesktops ? NET::OnAllDesktops : desktop - 1 ); // spec counts from 0
1200#else
1201 .arg( 0 ); // spec counts from 0
1202#endif
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 ) );
1207 for( QList< pid_t >::ConstIterator it = pids.begin();
1208 it != pids.end();
1209 ++it )
1210 ret += QString::fromLatin1( " PID=%1" ).arg( *it );
1211 if( silent != KStartupInfoData::Unknown )
1212 ret += QString::fromLatin1( " SILENT=%1" ).arg( silent == KStartupInfoData::Yes ? 1 : 0 );
1213 if( timestamp != ~0U )
1214 ret += QString::fromLatin1( " TIMESTAMP=%1" ).arg( timestamp );
1215 if( screen != -1 )
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 );
1223 return ret;
1224 }
1225
1226KStartupInfoData::KStartupInfoData( const QString& txt_P ) : d(new Private)
1227 {
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=" ); // SELI nonstd
1236 const QString pid_str = QString::fromLatin1( "PID=" ); // SELI nonstd
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();
1244 it != items.end();
1245 ++it )
1246 {
1247 if( ( *it ).startsWith( bin_str ))
1248 d->bin = get_str( *it );
1249 else if( ( *it ).startsWith( name_str ))
1250 d->name = get_str( *it );
1251 else if( ( *it ).startsWith( description_str ))
1252 d->description = get_str( *it );
1253 else if( ( *it ).startsWith( icon_str ))
1254 d->icon = get_str( *it );
1255 else if( ( *it ).startsWith( desktop_str ))
1256 {
1257 d->desktop = get_num( *it );
1258#ifdef Q_WS_X11
1259 if( d->desktop != NET::OnAllDesktops )
1260#endif
1261 ++d->desktop; // spec counts from 0
1262 }
1263 else if( ( *it ).startsWith( wmclass_str ))
1264 d->wmclass = get_cstr( *it );
1265 else if( ( *it ).startsWith( hostname_str ))
1266 d->hostname = get_cstr( *it );
1267 else if( ( *it ).startsWith( pid_str ))
1268 addPid( get_num( *it ));
1269 else if( ( *it ).startsWith( silent_str ))
1270 d->silent = get_num( *it ) != 0 ? Yes : No;
1271 else if( ( *it ).startsWith( timestamp_str ))
1272 d->timestamp = get_unum( *it );
1273 else if( ( *it ).startsWith( screen_str ))
1274 d->screen = get_num( *it );
1275 else if( ( *it ).startsWith( xinerama_str ))
1276 d->xinerama = get_num( *it );
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 );
1281 }
1282 }
1283
1284KStartupInfoData::KStartupInfoData( const KStartupInfoData& data ) : d(new Private(*data.d))
1285{
1286}
1287
1288KStartupInfoData& KStartupInfoData::operator=( const KStartupInfoData& data )
1289{
1290 if( &data == this )
1291 return *this;
1292 *d = *data.d;
1293 return *this;
1294}
1295
1296void KStartupInfoData::update( const KStartupInfoData& data_P )
1297 {
1298 if( !data_P.bin().isEmpty())
1299 d->bin = data_P.bin();
1300 if( !data_P.name().isEmpty() && name().isEmpty()) // don't overwrite
1301 d->name = data_P.name();
1302 if( !data_P.description().isEmpty() && description().isEmpty()) // don't overwrite
1303 d->description = data_P.description();
1304 if( !data_P.icon().isEmpty() && icon().isEmpty()) // don't overwrite
1305 d->icon = data_P.icon();
1306 if( data_P.desktop() != 0 && desktop() == 0 ) // don't overwrite
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;
1312 for( QList< pid_t >::ConstIterator it = data_P.d->pids.constBegin();
1313 it != data_P.d->pids.constEnd();
1314 ++it )
1315 addPid( *it );
1316 if( data_P.silent() != Unknown )
1317 d->silent = data_P.silent();
1318 if( data_P.timestamp() != ~0U && timestamp() == ~0U ) // don't overwrite
1319 d->timestamp = data_P.timestamp();
1320 if( data_P.screen() != -1 )
1321 d->screen = data_P.screen();
1322 if( data_P.xinerama() != -1 && xinerama() != -1 ) // don't overwrite
1323 d->xinerama = data_P.xinerama();
1324 if( data_P.launchedBy() != 0 && launchedBy() != 0 ) // don't overwrite
1325 d->launched_by = data_P.launchedBy();
1326 if( !data_P.applicationId().isEmpty() && applicationId().isEmpty()) // don't overwrite
1327 d->application_id = data_P.applicationId();
1328 }
1329
1330KStartupInfoData::KStartupInfoData() : d(new Private)
1331{
1332}
1333
1334KStartupInfoData::~KStartupInfoData()
1335{
1336 delete d;
1337}
1338
1339void KStartupInfoData::setBin( const QString& bin_P )
1340 {
1341 d->bin = bin_P;
1342 }
1343
1344const QString& KStartupInfoData::bin() const
1345 {
1346 return d->bin;
1347 }
1348
1349void KStartupInfoData::setName( const QString& name_P )
1350 {
1351 d->name = name_P;
1352 }
1353
1354const QString& KStartupInfoData::name() const
1355 {
1356 return d->name;
1357 }
1358
1359const QString& KStartupInfoData::findName() const
1360 {
1361 if( !name().isEmpty())
1362 return name();
1363 return bin();
1364 }
1365
1366void KStartupInfoData::setDescription( const QString& desc_P )
1367 {
1368 d->description = desc_P;
1369 }
1370
1371const QString& KStartupInfoData::description() const
1372 {
1373 return d->description;
1374 }
1375
1376const QString& KStartupInfoData::findDescription() const
1377 {
1378 if( !description().isEmpty())
1379 return description();
1380 return name();
1381 }
1382
1383void KStartupInfoData::setIcon( const QString& icon_P )
1384 {
1385 d->icon = icon_P;
1386 }
1387
1388const QString& KStartupInfoData::findIcon() const
1389 {
1390 if( !icon().isEmpty())
1391 return icon();
1392 return bin();
1393 }
1394
1395const QString& KStartupInfoData::icon() const
1396 {
1397 return d->icon;
1398 }
1399
1400void KStartupInfoData::setDesktop( int desktop_P )
1401 {
1402 d->desktop = desktop_P;
1403 }
1404
1405int KStartupInfoData::desktop() const
1406 {
1407 return d->desktop;
1408 }
1409
1410void KStartupInfoData::setWMClass( const QByteArray& wmclass_P )
1411 {
1412 d->wmclass = wmclass_P;
1413 }
1414
1415const QByteArray KStartupInfoData::findWMClass() const
1416 {
1417 if( !WMClass().isEmpty() && WMClass() != "0" )
1418 return WMClass();
1419 return bin().toUtf8();
1420 }
1421
1422QByteArray KStartupInfoData::WMClass() const
1423 {
1424 return d->wmclass;
1425 }
1426
1427void KStartupInfoData::setHostname( const QByteArray& hostname_P )
1428 {
1429 if( !hostname_P.isNull())
1430 d->hostname = hostname_P;
1431 else
1432 {
1433 char tmp[ 256 ];
1434 tmp[ 0 ] = '\0';
1435 if (!gethostname( tmp, 255 ))
1436 tmp[sizeof(tmp)-1] = '\0';
1437 d->hostname = tmp;
1438 }
1439 }
1440
1441QByteArray KStartupInfoData::hostname() const
1442 {
1443 return d->hostname;
1444 }
1445
1446void KStartupInfoData::addPid( pid_t pid_P )
1447 {
1448 if( !d->pids.contains( pid_P ))
1449 d->pids.append( pid_P );
1450 }
1451
1452void KStartupInfoData::Private::remove_pid( pid_t pid_P )
1453 {
1454 pids.removeAll( pid_P );
1455 }
1456
1457QList< pid_t > KStartupInfoData::pids() const
1458 {
1459 return d->pids;
1460 }
1461
1462bool KStartupInfoData::is_pid( pid_t pid_P ) const
1463 {
1464 return d->pids.contains( pid_P );
1465 }
1466
1467void KStartupInfoData::setSilent( TriState state_P )
1468 {
1469 d->silent = state_P;
1470 }
1471
1472KStartupInfoData::TriState KStartupInfoData::silent() const
1473 {
1474 return d->silent;
1475 }
1476
1477void KStartupInfoData::setTimestamp( unsigned long time )
1478 {
1479 d->timestamp = time;
1480 }
1481
1482unsigned long KStartupInfoData::timestamp() const
1483 {
1484 return d->timestamp;
1485 }
1486
1487void KStartupInfoData::setScreen( int _screen )
1488 {
1489 d->screen = _screen;
1490 }
1491
1492int KStartupInfoData::screen() const
1493 {
1494 return d->screen;
1495 }
1496
1497void KStartupInfoData::setXinerama( int xinerama )
1498 {
1499 d->xinerama = xinerama;
1500 }
1501
1502int KStartupInfoData::xinerama() const
1503 {
1504 return d->xinerama;
1505 }
1506
1507void KStartupInfoData::setLaunchedBy( WId window )
1508 {
1509 d->launched_by = window;
1510 }
1511
1512WId KStartupInfoData::launchedBy() const
1513 {
1514 return d->launched_by;
1515 }
1516
1517void KStartupInfoData::setApplicationId( const QString& desktop )
1518 {
1519 if( desktop.startsWith( '/' ))
1520 {
1521 d->application_id = desktop;
1522 return;
1523 }
1524 // the spec requires this is always a full path, in order for everyone to be able to find it
1525 QString desk = KStandardDirs::locate( "apps", desktop );
1526 if( desk.isEmpty())
1527 desk = KStandardDirs::locate( "services", desktop );
1528 if( desk.isEmpty())
1529 return;
1530 d->application_id = desk;
1531 }
1532
1533QString KStartupInfoData::applicationId() const
1534 {
1535 return d->application_id;
1536 }
1537
1538static
1539long get_num( const QString& item_P )
1540 {
1541 unsigned int pos = item_P.indexOf( QLatin1Char('=') );
1542 return item_P.mid( pos + 1 ).toLong();
1543 }
1544
1545static
1546unsigned long get_unum( const QString& item_P )
1547 {
1548 unsigned int pos = item_P.indexOf( QLatin1Char('=') );
1549 return item_P.mid( pos + 1 ).toULong();
1550 }
1551
1552static
1553QString get_str( const QString& item_P )
1554 {
1555 int pos = item_P.indexOf( QLatin1Char('=') );
1556 if( item_P.length() > pos + 2 && item_P.at( pos + 1 ) == QLatin1Char('\"') )
1557 {
1558 int pos2 = item_P.left( pos + 2 ).indexOf( QLatin1Char('\"') );
1559 if( pos2 < 0 )
1560 return QString(); // 01234
1561 return item_P.mid( pos + 2, pos2 - 2 - pos ); // A="C"
1562 }
1563 return item_P.mid( pos + 1 );
1564 }
1565
1566static
1567QByteArray get_cstr( const QString& item_P )
1568 {
1569 return get_str( item_P ).toUtf8();
1570 }
1571
1572static
1573QStringList get_fields( const QString& txt_P )
1574 {
1575 QString txt = txt_P.simplified();
1576 QStringList ret;
1577 QString item = "";
1578 bool in = false;
1579 bool escape = false;
1580 for( int pos = 0;
1581 pos < txt.length();
1582 ++pos )
1583 {
1584 if( escape )
1585 {
1586 item += txt[ pos ];
1587 escape = false;
1588 }
1589 else if( txt[ pos ] == '\\' )
1590 escape = true;
1591 else if( txt[ pos ] == '\"' )
1592 in = !in;
1593 else if( txt[ pos ] == ' ' && !in )
1594 {
1595 ret.append( item );
1596 item = "";
1597 }
1598 else
1599 item += txt[ pos ];
1600 }
1601 ret.append( item );
1602 return ret;
1603 }
1604
1605static QString escape_str( const QString& str_P )
1606 {
1607 QString ret = "";
1608 for( int pos = 0;
1609 pos < str_P.length();
1610 ++pos )
1611 {
1612 if( str_P[ pos ] == '\\'
1613 || str_P[ pos ] == '"' )
1614 ret += '\\';
1615 ret += str_P[ pos ];
1616 }
1617 return ret;
1618 }
1619
1620#include "kstartupinfo.moc"
KApplication::kApplication
static KApplication * kApplication()
Returns the current application object.
Definition: kapplication.cpp:603
KStandardDirs::locate
static QString locate(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
KStartupInfoData
Class representing data about an application startup notification.
Definition: kstartupinfo.h:440
KStartupInfoData::findDescription
const QString & findDescription() const
Returns the description of the startup notification.
Definition: kstartupinfo.cpp:1376
KStartupInfoData::TriState
TriState
Definition: kstartupinfo.h:568
KStartupInfoData::No
@ No
Definition: kstartupinfo.h:568
KStartupInfoData::Yes
@ Yes
Definition: kstartupinfo.h:568
KStartupInfoData::Unknown
@ Unknown
Definition: kstartupinfo.h:568
KStartupInfoData::description
const QString & description() const
Returns the name of the startup notification, or empty if not available.
Definition: kstartupinfo.cpp:1371
KStartupInfoData::WMClass
QByteArray WMClass() const
Returns the WM_CLASS value for the startup notification, or empty if not available.
Definition: kstartupinfo.cpp:1422
KStartupInfoData::update
void update(const KStartupInfoData &data)
Updates the notification data from the given data.
Definition: kstartupinfo.cpp:1296
KStartupInfoData::setHostname
void setHostname(const QByteArray &hostname=QByteArray())
Sets the hostname on which the application is starting.
Definition: kstartupinfo.cpp:1427
KStartupInfoData::silent
TriState silent() const
Return the silence status for the startup notification.
Definition: kstartupinfo.cpp:1472
KStartupInfoData::timestamp
unsigned long timestamp() const
Definition: kstartupinfo.cpp:1482
KStartupInfoData::setDesktop
void setDesktop(int desktop)
Sets the desktop for the startup notification ( i.e.
Definition: kstartupinfo.cpp:1400
KStartupInfoData::applicationId
QString applicationId() const
The .desktop file used to initiate this startup notification, or empty.
Definition: kstartupinfo.cpp:1533
KStartupInfoData::operator=
KStartupInfoData & operator=(const KStartupInfoData &data)
Definition: kstartupinfo.cpp:1288
KStartupInfoData::findIcon
const QString & findIcon() const
Returns the icon of the startup notification, and if it's not available, tries to get it from the bin...
Definition: kstartupinfo.cpp:1388
KStartupInfoData::pids
QList< pid_t > pids() const
Returns all PIDs for the startup notification.
Definition: kstartupinfo.cpp:1457
KStartupInfoData::name
const QString & name() const
Returns the name of the startup notification, or empty if not available.
Definition: kstartupinfo.cpp:1354
KStartupInfoData::bin
const QString & bin() const
Returns the binary name of the starting application.
Definition: kstartupinfo.cpp:1344
KStartupInfoData::addPid
void addPid(pid_t pid)
Adds a PID to the list of processes that belong to the startup notification.
Definition: kstartupinfo.cpp:1446
KStartupInfoData::setName
void setName(const QString &name)
Sets the name for the notification (e.g.
Definition: kstartupinfo.cpp:1349
KStartupInfoData::~KStartupInfoData
~KStartupInfoData()
Definition: kstartupinfo.cpp:1334
KStartupInfoData::launchedBy
WId launchedBy() const
The toplevel window of the application that caused this startup notification, 0 if unknown.
Definition: kstartupinfo.cpp:1512
KStartupInfoData::setXinerama
void setXinerama(int xinerama)
Sets the Xinerama screen for the startup notification ( i.e.
Definition: kstartupinfo.cpp:1497
KStartupInfoData::setLaunchedBy
void setLaunchedBy(WId window)
Sets the toplevel window of the application that caused this startup notification.
Definition: kstartupinfo.cpp:1507
KStartupInfoData::screen
int screen() const
The X11 screen on which the startup notification is happening, -1 if unknown.
Definition: kstartupinfo.cpp:1492
KStartupInfoData::setWMClass
void setWMClass(const QByteArray &wmclass)
Sets a WM_CLASS value for the startup notification, it may be used for increasing the chance that the...
Definition: kstartupinfo.cpp:1410
KStartupInfoData::setIcon
void setIcon(const QString &icon)
Sets the icon for the startup notification ( e.g.
Definition: kstartupinfo.cpp:1383
KStartupInfoData::xinerama
int xinerama() const
The Xinerama screen for the startup notification, -1 if unknown.
Definition: kstartupinfo.cpp:1502
KStartupInfoData::setTimestamp
void setTimestamp(unsigned long time)
Definition: kstartupinfo.cpp:1477
KStartupInfoData::setBin
void setBin(const QString &bin)
Sets the binary name of the application ( e.g.
Definition: kstartupinfo.cpp:1339
KStartupInfoData::KStartupInfoData
KStartupInfoData()
Constructor.
Definition: kstartupinfo.cpp:1330
KStartupInfoData::setDescription
void setDescription(const QString &descr)
Sets the description for the notification (e.g.
Definition: kstartupinfo.cpp:1366
KStartupInfoData::icon
const QString & icon() const
Returns the icon of the startup notification, or empty if not available.
Definition: kstartupinfo.cpp:1395
KStartupInfoData::findWMClass
const QByteArray findWMClass() const
Returns the WM_CLASS value for the startup notification, or binary name if not available.
Definition: kstartupinfo.cpp:1415
KStartupInfoData::setSilent
void setSilent(TriState state)
Sets whether the visual feedback for this startup notification should be silenced (temporarily suspen...
Definition: kstartupinfo.cpp:1467
KStartupInfoData::is_pid
bool is_pid(pid_t pid) const
Checks whether the given pid is in the list of PIDs for starup notification.
Definition: kstartupinfo.cpp:1462
KStartupInfoData::hostname
QByteArray hostname() const
Returns the hostname for the startup notification.
Definition: kstartupinfo.cpp:1441
KStartupInfoData::desktop
int desktop() const
Returns the desktop for the startup notification.
Definition: kstartupinfo.cpp:1405
KStartupInfoData::setApplicationId
void setApplicationId(const QString &desktop)
Sets the .desktop file that was used to initiate the startup notification.
Definition: kstartupinfo.cpp:1517
KStartupInfoData::setScreen
void setScreen(int screen)
Sets the X11 screen on which the startup notification should happen.
Definition: kstartupinfo.cpp:1487
KStartupInfoData::findName
const QString & findName() const
Returns the name of the startup notification.
Definition: kstartupinfo.cpp:1359
KStartupInfoId
Class representing an identification of application startup notification.
Definition: kstartupinfo.h:369
KStartupInfoId::initId
void initId(const QByteArray &id="")
Initializes this object with the given identification ( which may be also "0" for no notification ),...
Definition: kstartupinfo.cpp:1058
KStartupInfoId::setupStartupEnv
bool setupStartupEnv() const
Sets the startup notification environment variable to this identification.
Definition: kstartupinfo.cpp:1080
KStartupInfoId::timestamp
unsigned long timestamp() const
Return the user timestamp for the startup notification, or 0 if no timestamp is set.
Definition: kstartupinfo.cpp:1149
KStartupInfoId::KStartupInfoId
KStartupInfoId()
Creates an empty identification.
Definition: kstartupinfo.cpp:1106
KStartupInfoId::none
bool none() const
Checks whether the identifier is valid.
Definition: kstartupinfo.cpp:1144
KStartupInfoId::operator!=
bool operator!=(const KStartupInfoId &id) const
Overloaded operator.
Definition: kstartupinfo.cpp:1132
KStartupInfoId::operator<
bool operator<(const KStartupInfoId &id) const
Definition: kstartupinfo.cpp:1138
KStartupInfoId::operator=
KStartupInfoId & operator=(const KStartupInfoId &data)
Definition: kstartupinfo.cpp:1119
KStartupInfoId::operator==
bool operator==(const KStartupInfoId &id) const
Overloaded operator.
Definition: kstartupinfo.cpp:1127
KStartupInfoId::~KStartupInfoId
~KStartupInfoId()
Definition: kstartupinfo.cpp:1110
KStartupInfoId::id
const QByteArray & id() const
Returns the notification identifier as string.
Definition: kstartupinfo.cpp:1034
KStartupInfo
Class for manipulating the application startup notification.
Definition: kstartupinfo.h:66
KStartupInfo::setTimeout
void setTimeout(unsigned int secs)
Sets the timeout for notifications, after this timeout a notification is removed.
Definition: kstartupinfo.cpp:910
KStartupInfo::disableAutoAppStartedSending
static void disableAutoAppStartedSending(bool disable=true)
By default, the startup notification is ended for the application after it shows its first toplevel w...
Definition: kstartupinfo.cpp:621
KStartupInfo::startup_t
startup_t
Definition: kstartupinfo.h:255
KStartupInfo::appStarted
static void appStarted()
Manual notification that the application has started.
Definition: kstartupinfo.cpp:586
KStartupInfo::setNewStartupId
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...
Definition: kstartupinfo.cpp:643
KStartupInfo::sendStartupX
static bool sendStartupX(Display *dpy, const KStartupInfoId &id, const KStartupInfoData &data)
Like sendStartup , uses dpy instead of qt_x11display() for sending the info.
Definition: kstartupinfo.cpp:461
KStartupInfo::sendStartup
static bool sendStartup(const KStartupInfoId &id, const KStartupInfoData &data)
Sends given notification data about started application with the given startup identification.
Definition: kstartupinfo.cpp:445
KStartupInfo::checkStartup
startup_t checkStartup(WId w)
Checks if the given windows matches any existing startup notification.
Definition: kstartupinfo.cpp:689
KStartupInfo::windowStartupId
static QByteArray windowStartupId(WId w)
Returns startup notification identification of the given window.
Definition: kstartupinfo.cpp:852
KStartupInfo::sendChange
static bool sendChange(const KStartupInfoId &id, const KStartupInfoData &data)
Sends given notification data about started application with the given startup identification.
Definition: kstartupinfo.cpp:496
KStartupInfo::handleAutoAppStartedSending
static void handleAutoAppStartedSending()
Definition: kstartupinfo.cpp:637
KStartupInfo::setWindowStartupId
static void setWindowStartupId(WId window, const QByteArray &id)
Sets the startup notification window property on the given window.
Definition: kstartupinfo.cpp:874
KStartupInfo::sendChangeX
static bool sendChangeX(Display *dpy, const KStartupInfoId &id, const KStartupInfoData &data)
Like sendChange , uses dpy instead of qt_x11display() for sending the info.
Definition: kstartupinfo.cpp:510
KStartupInfo::resetStartupEnv
static void resetStartupEnv()
Unsets the startup notification environment variable.
Definition: kstartupinfo.cpp:1101
KStartupInfo::DisableKWinModule
@ DisableKWinModule
Definition: kstartupinfo.h:123
KStartupInfo::sendFinishX
static bool sendFinishX(Display *dpy, const KStartupInfoId &id)
Like sendFinish , uses dpy instead of qt_x11display() for sending the info.
Definition: kstartupinfo.cpp:540
KStartupInfo::gotRemoveStartup
void gotRemoveStartup(const KStartupInfoId &id, const KStartupInfoData &data)
Emitted when a startup notification is removed (either because it was detected that the application i...
KStartupInfo::gotStartupChange
void gotStartupChange(const KStartupInfoId &id, const KStartupInfoData &data)
Emitted when a startup notification changes.
KStartupInfo::gotNewStartup
void gotNewStartup(const KStartupInfoId &id, const KStartupInfoData &data)
Emitted when a new startup notification is created (i.e.
KStartupInfo::~KStartupInfo
virtual ~KStartupInfo()
Definition: kstartupinfo.cpp:218
KStartupInfo::currentStartupIdEnv
static KStartupInfoId currentStartupIdEnv()
Returns the current startup notification identification for the current startup notification environm...
Definition: kstartupinfo.cpp:1090
KStartupInfo::sendFinish
static bool sendFinish(const KStartupInfoId &id)
Ends startup notification with the given identification.
Definition: kstartupinfo.cpp:527
KStartupInfo::customEvent
virtual void customEvent(QEvent *e_P)
Definition: kstartupinfo.cpp:266
KStartupInfo::KStartupInfo
KStartupInfo(int flags, QObject *parent=0)
Creates an instance that will receive the startup notifications.
Definition: kstartupinfo.cpp:203
KStartupInfo::silenceStartup
static void silenceStartup(bool silence)
If your application shows temporarily some window during its startup, for example a dialog,...
Definition: kstartupinfo.cpp:626
KStartupInfo::createNewStartupId
static QByteArray createNewStartupId()
Creates and returns new startup id.
Definition: kstartupinfo.cpp:1012
KWindowSystem::setOnDesktop
static void setOnDesktop(WId win, int desktop)
Moves window win to desktop desktop.
Definition: kwindowsystem_mac.cpp:406
KWindowSystem::currentDesktop
static int currentDesktop()
Returns the current virtual desktop.
Definition: kwindowsystem_mac.cpp:384
KWindowSystem::forceActiveWindow
static void forceActiveWindow(WId win, long time=0)
Sets window win to be the active window.
Definition: kwindowsystem_mac.cpp:366
KWindowSystem::self
static KWindowSystem * self()
Access to the singleton instance.
Definition: kwindowsystem_mac.cpp:308
KXMessages
Sending string messages to other applications using the X Client Messages.
Definition: kxmessages.h:48
KXMessages::broadcastMessage
void broadcastMessage(const char *msg_type, const QString &message, int screen, bool obsolete)
Broadcasts the given message with the given message type.
Definition: kxmessages.cpp:96
KXMessages::broadcastMessageX
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.
Definition: kxmessages.cpp:125
NETRootInfo
Common API for root window properties/protocols.
Definition: netwm.h:58
NETRootInfo::isSupported
bool isSupported(NET::Property property) const
Returns true if the given property is supported by the window manager.
Definition: netwm.cpp:2640
NETWinInfo
Common API for application window properties/protocols.
Definition: netwm.h:829
NET::DialogMask
@ DialogMask
Definition: netwm_def.h:390
NET::MenuMask
@ MenuMask
Definition: netwm_def.h:389
NET::SplashMask
@ SplashMask
Definition: netwm_def.h:394
NET::UtilityMask
@ UtilityMask
Definition: netwm_def.h:393
NET::OverrideMask
@ OverrideMask
Definition: netwm_def.h:391
NET::ToolbarMask
@ ToolbarMask
Definition: netwm_def.h:388
NET::DockMask
@ DockMask
Definition: netwm_def.h:387
NET::NormalMask
@ NormalMask
Definition: netwm_def.h:385
NET::DesktopMask
@ DesktopMask
Definition: netwm_def.h:386
NET::TopMenuMask
@ TopMenuMask
Definition: netwm_def.h:392
NET::WindowType
WindowType
Window type.
Definition: netwm_def.h:305
NET::Override
@ Override
Definition: netwm_def.h:340
NET::Normal
@ Normal
indicates that this is a normal, top-level window
Definition: netwm_def.h:313
NET::Unknown
@ Unknown
indicates that the window did not define a window type.
Definition: netwm_def.h:309
NET::Dialog
@ Dialog
indicates that this is a dialog window
Definition: netwm_def.h:336
NET::Utility
@ Utility
indicates a utility window
Definition: netwm_def.h:349
NET::OnAllDesktops
@ OnAllDesktops
Definition: netwm_def.h:704
NET::WM2StartupId
@ WM2StartupId
Definition: netwm_def.h:677
NET::Supported
@ Supported
Definition: netwm_def.h:614
NET::WMWindowType
@ WMWindowType
Definition: netwm_def.h:634
NET::WMState
@ WMState
Definition: netwm_def.h:635
NET::WMPid
@ WMPid
Definition: netwm_def.h:639
QList< pid_t >
QMap< KStartupInfoId, KStartupInfo::Data >
QObject
QWidget
kDebug
#define kDebug
kapplication.h
kapp
#define kapp
Definition: kapplication.h:56
Atom
unsigned long Atom
Definition: kapplication.h:40
kdebug.h
timeout
int timeout
kstandarddirs.h
get_str
static QString get_str(const QString &item_P)
Definition: kstartupinfo.cpp:1553
NET_STARTUP_MSG
static const char *const NET_STARTUP_MSG
Definition: kstartupinfo.cpp:63
get_fields
static QStringList get_fields(const QString &txt_P)
Definition: kstartupinfo.cpp:1573
utf8_string_atom
static Atom utf8_string_atom
Definition: kstartupinfo.cpp:79
read_startup_id_property
static QByteArray read_startup_id_property(WId w_P)
Definition: kstartupinfo.cpp:831
get_cstr
static QByteArray get_cstr(const QString &item_P)
Definition: kstartupinfo.cpp:1567
get_num
static long get_num(const QString &item_P)
Definition: kstartupinfo.cpp:1539
net_startup_atom
static Atom net_startup_atom
Definition: kstartupinfo.cpp:829
NET_STARTUP_WINDOW
static const char *const NET_STARTUP_WINDOW
Definition: kstartupinfo.cpp:64
NET_STARTUP_ENV
static const char *const NET_STARTUP_ENV
Definition: kstartupinfo.cpp:67
escape_str
static QString escape_str(const QString &str_P)
Definition: kstartupinfo.cpp:1605
auto_app_started_sending
static bool auto_app_started_sending
Definition: kstartupinfo.cpp:69
get_unum
static unsigned long get_unum(const QString &item_P)
Definition: kstartupinfo.cpp:1546
kstartupinfo.h
kwindowsystem.h
kxmessages.h
Type
Type
KStandardAction::name
const char * name(StandardAction id)
This will return the internal name of a given standard action.
Definition: kstandardaction.cpp:223
KStandardGuiItem::No
@ No
Definition: kstandardguiitem.h:50
KStandardGuiItem::Yes
@ Yes
Definition: kstandardguiitem.h:50
Window
Window
None
None
netwm.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal