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

KDEUI

  • sources
  • kde-4.14
  • kdelibs
  • 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 
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11 
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14 
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 DEALINGS 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 
63 static const char* const NET_STARTUP_MSG = "_NET_STARTUP_INFO";
64 static 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
67 static const char* const NET_STARTUP_ENV = "DESKTOP_STARTUP_ID";
68 
69 static bool auto_app_started_sending = true;
70 
71 static long get_num( const QString& item_P );
72 static unsigned long get_unum( const QString& item_P );
73 static QString get_str( const QString& item_P );
74 static QByteArray get_cstr( const QString& item_P );
75 static QStringList get_fields( const QString& txt_P );
76 static QString escape_str( const QString& str_P );
77 
78 #ifdef Q_WS_X11
79 static Atom utf8_string_atom = None;
80 #endif
81 
82 class 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 
92 struct KStartupInfoId::Private
93  {
94  Private() : id( "" ) {}
95 
96  QString to_text() const;
97 
98  QByteArray id; // id
99  };
100 
101 struct 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 
125 class 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 
203 KStartupInfo::KStartupInfo( int flags_P, QObject* parent_P )
204  : QObject( parent_P ),
205  d(new Private(flags_P, this))
206  {
207  d->createConnections();
208  }
209 
210 KStartupInfo::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 
218 KStartupInfo::~KStartupInfo()
219  {
220  delete d;
221  }
222 
223 void 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???
244 namespace
245 {
246 class 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 
261 void KStartupInfo::Private::slot_window_added( WId w_P )
262  {
263  qApp->postEvent( q, new DelayedWindowEvent( w_P ));
264  }
265 
266 void 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 
276 void 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 
295 void 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 
304 void 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 
373 void 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 
388 void 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 
409 void 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 
424 void 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 
445 bool 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 
461 bool 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 
479 QString 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 
496 bool 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 
510 bool 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 
527 bool 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 
540 bool 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 
555 bool 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 
569 bool 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 
586 void 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 
600 void 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 
621 void KStartupInfo::disableAutoAppStartedSending( bool disable )
622  {
623  auto_app_started_sending = !disable;
624  }
625 
626 void 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 
637 void KStartupInfo::handleAutoAppStartedSending()
638  {
639  if( auto_app_started_sending )
640  appStarted();
641  }
642 
643 void 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 
673 KStartupInfo::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 
679 KStartupInfo::startup_t KStartupInfo::checkStartup( WId w_P, KStartupInfoId& id_O )
680  {
681  return d->check_startup_internal( w_P, &id_O, NULL );
682  }
683 
684 KStartupInfo::startup_t KStartupInfo::checkStartup( WId w_P, KStartupInfoData& data_O )
685  {
686  return d->check_startup_internal( w_P, NULL, &data_O );
687  }
688 
689 KStartupInfo::startup_t KStartupInfo::checkStartup( WId w_P )
690  {
691  return d->check_startup_internal( w_P, NULL, NULL );
692  }
693 
694 KStartupInfo::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 
761 bool 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 
779 bool 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 
802 bool 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
829 static Atom net_startup_atom = None;
830 
831 static 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 
852 QByteArray 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 
874 void 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 
888 QByteArray 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 
910 void 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 
917 void KStartupInfo::Private::startups_cleanup_no_age()
918  {
919  startups_cleanup_internal( false );
920  }
921 
922 void 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 
933 void 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 
994 void 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 
1012 QByteArray 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 
1034 const QByteArray& KStartupInfoId::id() const
1035  {
1036  return d->id;
1037  }
1038 
1039 
1040 QString KStartupInfoId::Private::to_text() const
1041  {
1042  return QString::fromLatin1( " ID=\"%1\" " ).arg( escape_str( id));
1043  }
1044 
1045 KStartupInfoId::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 
1058 void 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 
1080 bool 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 
1090 KStartupInfoId 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 
1101 void KStartupInfo::resetStartupEnv()
1102  {
1103  unsetenv( NET_STARTUP_ENV );
1104  }
1105 
1106 KStartupInfoId::KStartupInfoId() : d(new Private)
1107  {
1108  }
1109 
1110 KStartupInfoId::~KStartupInfoId()
1111  {
1112  delete d;
1113  }
1114 
1115 KStartupInfoId::KStartupInfoId( const KStartupInfoId& id_P ) : d(new Private(*id_P.d))
1116  {
1117  }
1118 
1119 KStartupInfoId& 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 
1127 bool KStartupInfoId::operator==( const KStartupInfoId& id_P ) const
1128  {
1129  return id() == id_P.id();
1130  }
1131 
1132 bool KStartupInfoId::operator!=( const KStartupInfoId& id_P ) const
1133  {
1134  return !(*this == id_P );
1135  }
1136 
1137 // needed for QMap
1138 bool KStartupInfoId::operator<( const KStartupInfoId& id_P ) const
1139  {
1140  return id() < id_P.id();
1141  }
1142 
1143 // KDE5 TODO: rename to isNull ?
1144 bool KStartupInfoId::none() const
1145  {
1146  return d->id.isEmpty() || d->id == "0";
1147  }
1148 
1149 unsigned 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 
1185 QString 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 
1226 KStartupInfoData::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 
1284 KStartupInfoData::KStartupInfoData( const KStartupInfoData& data ) : d(new Private(*data.d))
1285 {
1286 }
1287 
1288 KStartupInfoData& KStartupInfoData::operator=( const KStartupInfoData& data )
1289 {
1290  if( &data == this )
1291  return *this;
1292  *d = *data.d;
1293  return *this;
1294 }
1295 
1296 void 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 
1330 KStartupInfoData::KStartupInfoData() : d(new Private)
1331 {
1332 }
1333 
1334 KStartupInfoData::~KStartupInfoData()
1335 {
1336  delete d;
1337 }
1338 
1339 void KStartupInfoData::setBin( const QString& bin_P )
1340  {
1341  d->bin = bin_P;
1342  }
1343 
1344 const QString& KStartupInfoData::bin() const
1345  {
1346  return d->bin;
1347  }
1348 
1349 void KStartupInfoData::setName( const QString& name_P )
1350  {
1351  d->name = name_P;
1352  }
1353 
1354 const QString& KStartupInfoData::name() const
1355  {
1356  return d->name;
1357  }
1358 
1359 const QString& KStartupInfoData::findName() const
1360  {
1361  if( !name().isEmpty())
1362  return name();
1363  return bin();
1364  }
1365 
1366 void KStartupInfoData::setDescription( const QString& desc_P )
1367  {
1368  d->description = desc_P;
1369  }
1370 
1371 const QString& KStartupInfoData::description() const
1372  {
1373  return d->description;
1374  }
1375 
1376 const QString& KStartupInfoData::findDescription() const
1377  {
1378  if( !description().isEmpty())
1379  return description();
1380  return name();
1381  }
1382 
1383 void KStartupInfoData::setIcon( const QString& icon_P )
1384  {
1385  d->icon = icon_P;
1386  }
1387 
1388 const QString& KStartupInfoData::findIcon() const
1389  {
1390  if( !icon().isEmpty())
1391  return icon();
1392  return bin();
1393  }
1394 
1395 const QString& KStartupInfoData::icon() const
1396  {
1397  return d->icon;
1398  }
1399 
1400 void KStartupInfoData::setDesktop( int desktop_P )
1401  {
1402  d->desktop = desktop_P;
1403  }
1404 
1405 int KStartupInfoData::desktop() const
1406  {
1407  return d->desktop;
1408  }
1409 
1410 void KStartupInfoData::setWMClass( const QByteArray& wmclass_P )
1411  {
1412  d->wmclass = wmclass_P;
1413  }
1414 
1415 const QByteArray KStartupInfoData::findWMClass() const
1416  {
1417  if( !WMClass().isEmpty() && WMClass() != "0" )
1418  return WMClass();
1419  return bin().toUtf8();
1420  }
1421 
1422 QByteArray KStartupInfoData::WMClass() const
1423  {
1424  return d->wmclass;
1425  }
1426 
1427 void 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 
1441 QByteArray KStartupInfoData::hostname() const
1442  {
1443  return d->hostname;
1444  }
1445 
1446 void KStartupInfoData::addPid( pid_t pid_P )
1447  {
1448  if( !d->pids.contains( pid_P ))
1449  d->pids.append( pid_P );
1450  }
1451 
1452 void KStartupInfoData::Private::remove_pid( pid_t pid_P )
1453  {
1454  pids.removeAll( pid_P );
1455  }
1456 
1457 QList< pid_t > KStartupInfoData::pids() const
1458  {
1459  return d->pids;
1460  }
1461 
1462 bool KStartupInfoData::is_pid( pid_t pid_P ) const
1463  {
1464  return d->pids.contains( pid_P );
1465  }
1466 
1467 void KStartupInfoData::setSilent( TriState state_P )
1468  {
1469  d->silent = state_P;
1470  }
1471 
1472 KStartupInfoData::TriState KStartupInfoData::silent() const
1473  {
1474  return d->silent;
1475  }
1476 
1477 void KStartupInfoData::setTimestamp( unsigned long time )
1478  {
1479  d->timestamp = time;
1480  }
1481 
1482 unsigned long KStartupInfoData::timestamp() const
1483  {
1484  return d->timestamp;
1485  }
1486 
1487 void KStartupInfoData::setScreen( int _screen )
1488  {
1489  d->screen = _screen;
1490  }
1491 
1492 int KStartupInfoData::screen() const
1493  {
1494  return d->screen;
1495  }
1496 
1497 void KStartupInfoData::setXinerama( int xinerama )
1498  {
1499  d->xinerama = xinerama;
1500  }
1501 
1502 int KStartupInfoData::xinerama() const
1503  {
1504  return d->xinerama;
1505  }
1506 
1507 void KStartupInfoData::setLaunchedBy( WId window )
1508  {
1509  d->launched_by = window;
1510  }
1511 
1512 WId KStartupInfoData::launchedBy() const
1513  {
1514  return d->launched_by;
1515  }
1516 
1517 void 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 
1533 QString KStartupInfoData::applicationId() const
1534  {
1535  return d->application_id;
1536  }
1537 
1538 static
1539 long 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 
1545 static
1546 unsigned 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 
1552 static
1553 QString 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 
1566 static
1567 QByteArray get_cstr( const QString& item_P )
1568  {
1569  return get_str( item_P ).toUtf8();
1570  }
1571 
1572 static
1573 QStringList 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 
1605 static 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"
Atom
unsigned long Atom
Definition: kapplication.h:29
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
KStartupInfo::resetStartupEnv
static void resetStartupEnv()
Unsets the startup notification environment variable.
Definition: kstartupinfo.cpp:1101
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
QString::toULong
ulong toULong(bool *ok, int base) const
kapp
#define kapp
Definition: kapplication.h:56
QString::indexOf
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QEvent
NET::Normal
indicates that this is a normal, top-level window
Definition: netwm_def.h:313
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
QWidget
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::~KStartupInfo
virtual ~KStartupInfo()
Definition: kstartupinfo.cpp:218
NET::SplashMask
Definition: netwm_def.h:394
QEvent::type
Type type() const
KStartupInfoData::description
const QString & description() const
Returns the name of the startup notification, or empty if not available.
Definition: kstartupinfo.cpp:1371
KStartupInfo::DisableKWinModule
Definition: kstartupinfo.h:123
KStartupInfo::startup_t
startup_t
Definition: kstartupinfo.h:255
Type
Type
KStartupInfoData::findDescription
const QString & findDescription() const
Returns the description of the startup notification.
Definition: kstartupinfo.cpp:1376
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
kdebug.h
KStartupInfo
Class for manipulating the application startup notification.
Definition: kstartupinfo.h:64
kapplication.h
QByteArray::toLower
QByteArray toLower() const
NET::DesktopMask
Definition: netwm_def.h:386
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
Sending string messages to other applications using the X Client Messages.
Definition: kxmessages.h:46
QByteArray
NET::UtilityMask
Definition: netwm_def.h:393
KWindowSystem::setOnDesktop
static void setOnDesktop(WId win, int desktop)
Moves window win to desktop desktop.
Definition: kwindowsystem_mac.cpp:406
KStartupInfo::handleAutoAppStartedSending
static void handleAutoAppStartedSending()
Definition: kstartupinfo.cpp:637
KStartupInfoData::update
void update(const KStartupInfoData &data)
Updates the notification data from the given data.
Definition: kstartupinfo.cpp:1296
timeout
int timeout
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
QX11Info::appRootWindow
Qt::HANDLE appRootWindow(int screen)
QX11Info::display
Display * display()
get_str
static QString get_str(const QString &item_P)
Definition: kstartupinfo.cpp:1553
KStandardDirs::locate
static QString locate(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
KStartupInfo::setTimeout
void setTimeout(unsigned int secs)
Sets the timeout for notifications, after this timeout a notification is removed. ...
Definition: kstartupinfo.cpp:910
QMap< KStartupInfoId, KStartupInfo::Data >
QX11Info::screen
int screen() const
QByteArray::isNull
bool isNull() const
QByteArray::isEmpty
bool isEmpty() const
KStartupInfo::KStartupInfo
KStartupInfo(int flags, QObject *parent=0)
Creates an instance that will receive the startup notifications.
Definition: kstartupinfo.cpp:203
QString::simplified
QString simplified() const
NET::Supported
Definition: netwm_def.h:614
KStandardAction::name
const char * name(StandardAction id)
This will return the internal name of a given standard action.
Definition: kstandardaction.cpp:223
NET::WM2StartupId
Definition: netwm_def.h:677
NET::NormalMask
Definition: netwm_def.h:385
KStartupInfoId
Class representing an identification of application startup notification.
Definition: kstartupinfo.h:368
KStartupInfoData::WMClass
QByteArray WMClass() const
Returns the WM_CLASS value for the startup notification, or empty if not available.
Definition: kstartupinfo.cpp:1422
NET::Unknown
indicates that the window did not define a window type.
Definition: netwm_def.h:309
kstartupinfo.h
QByteArray::length
int length() const
KWindowSystem::forceActiveWindow
static void forceActiveWindow(WId win, long time=0)
Sets window win to be the active window.
Definition: kwindowsystem_mac.cpp:366
KStartupInfoData::setBin
void setBin(const QString &bin)
Sets the binary name of the application ( e.g.
Definition: kstartupinfo.cpp:1339
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
KStartupInfoData::TriState
TriState
Definition: kstartupinfo.h:568
KStartupInfoId::operator=
KStartupInfoId & operator=(const KStartupInfoId &data)
Definition: kstartupinfo.cpp:1119
NET::WMPid
Definition: netwm_def.h:639
NETRootInfo
Common API for root window properties/protocols.
Definition: netwm.h:58
KStartupInfoData::setName
void setName(const QString &name)
Sets the name for the notification (e.g.
Definition: kstartupinfo.cpp:1349
KStartupInfoData::setTimestamp
void setTimestamp(unsigned long time)
Definition: kstartupinfo.cpp:1477
KApplication::kApplication
static KApplication * kApplication()
Returns the current application object.
Definition: kapplication.cpp:603
KStartupInfo::checkStartup
startup_t checkStartup(WId w)
Checks if the given windows matches any existing startup notification.
Definition: kstartupinfo.cpp:689
KStartupInfoData::setXinerama
void setXinerama(int xinerama)
Sets the Xinerama screen for the startup notification ( i.e.
Definition: kstartupinfo.cpp:1497
get_cstr
static QByteArray get_cstr(const QString &item_P)
Definition: kstartupinfo.cpp:1567
kxmessages.h
NET_STARTUP_MSG
static const char *const NET_STARTUP_MSG
Definition: kstartupinfo.cpp:63
KStartupInfo::setWindowStartupId
static void setWindowStartupId(WId window, const QByteArray &id)
Sets the startup notification window property on the given window.
Definition: kstartupinfo.cpp:874
NET_STARTUP_WINDOW
static const char *const NET_STARTUP_WINDOW
Definition: kstartupinfo.cpp:64
NET::DialogMask
Definition: netwm_def.h:390
KStandardGuiItem::No
Definition: kstandardguiitem.h:50
NET_STARTUP_ENV
static const char *const NET_STARTUP_ENV
Definition: kstartupinfo.cpp:67
None
utf8_string_atom
static Atom utf8_string_atom
Definition: kstartupinfo.cpp:79
KStartupInfoData::desktop
int desktop() const
Returns the desktop for the startup notification.
Definition: kstartupinfo.cpp:1405
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
KWindowSystem::currentDesktop
static int currentDesktop()
Returns the current virtual desktop.
Definition: kwindowsystem_mac.cpp:384
KStartupInfoData::applicationId
QString applicationId() const
The .desktop file used to initiate this startup notification, or empty.
Definition: kstartupinfo.cpp:1533
read_startup_id_property
static QByteArray read_startup_id_property(WId w_P)
Definition: kstartupinfo.cpp:831
QList::count
int count(const T &value) const
KStartupInfoId::operator!=
bool operator!=(const KStartupInfoId &id) const
Overloaded operator.
Definition: kstartupinfo.cpp:1132
QList::append
void append(const T &value)
KStartupInfoData::setDescription
void setDescription(const QString &descr)
Sets the description for the notification (e.g.
Definition: kstartupinfo.cpp:1366
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
netwm.h
KStartupInfoData::hostname
QByteArray hostname() const
Returns the hostname for the startup notification.
Definition: kstartupinfo.cpp:1441
QTimer
NET::ToolbarMask
Definition: netwm_def.h:388
NET::Override
Definition: netwm_def.h:340
KStartupInfoData
Class representing data about an application startup notification.
Definition: kstartupinfo.h:439
get_fields
static QStringList get_fields(const QString &txt_P)
Definition: kstartupinfo.cpp:1573
NET::WindowType
WindowType
Window type.
Definition: netwm_def.h:305
KStartupInfoData::setIcon
void setIcon(const QString &icon)
Sets the icon for the startup notification ( e.g.
Definition: kstartupinfo.cpp:1383
QObject
QX11Info::appUserTime
unsigned long appUserTime()
KStartupInfoData::screen
int screen() const
The X11 screen on which the startup notification is happening, -1 if unknown.
Definition: kstartupinfo.cpp:1492
KStartupInfoData::name
const QString & name() const
Returns the name of the startup notification, or empty if not available.
Definition: kstartupinfo.cpp:1354
QString::isEmpty
bool isEmpty() const
KStartupInfoData::setSilent
void setSilent(TriState state)
Sets whether the visual feedback for this startup notification should be silenced (temporarily suspen...
Definition: kstartupinfo.cpp:1467
QString::trimmed
QString trimmed() const
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
KStartupInfoData::xinerama
int xinerama() const
The Xinerama screen for the startup notification, -1 if unknown.
Definition: kstartupinfo.cpp:1502
QWidget::winId
WId winId() const
KStartupInfoData::setHostname
void setHostname(const QByteArray &hostname=QByteArray())
Sets the hostname on which the application is starting.
Definition: kstartupinfo.cpp:1427
QList::first
T & first()
QString
QList< pid_t >
KStartupInfoId::operator<
bool operator<(const KStartupInfoId &id) const
Definition: kstartupinfo.cpp:1138
KStartupInfoData::Yes
Definition: kstartupinfo.h:568
get_unum
static unsigned long get_unum(const QString &item_P)
Definition: kstartupinfo.cpp:1546
KStartupInfoId::none
bool none() const
Checks whether the identifier is valid.
Definition: kstartupinfo.cpp:1144
QMap::begin
iterator begin()
QStringList
KStartupInfoData::findName
const QString & findName() const
Returns the name of the startup notification.
Definition: kstartupinfo.cpp:1359
NETRootInfo::isSupported
bool isSupported(NET::Property property) const
Returns true if the given property is supported by the window manager.
Definition: netwm.cpp:2640
KStartupInfoData::setApplicationId
void setApplicationId(const QString &desktop)
Sets the .desktop file that was used to initiate the startup notification.
Definition: kstartupinfo.cpp:1517
KStartupInfoData::pids
QList< pid_t > pids() const
Returns all PIDs for the startup notification.
Definition: kstartupinfo.cpp:1457
KStartupInfo::windowStartupId
static QByteArray windowStartupId(WId w)
Returns startup notification identification of the given window.
Definition: kstartupinfo.cpp:852
QList::end
iterator end()
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
escape_str
static QString escape_str(const QString &str_P)
Definition: kstartupinfo.cpp:1605
NET::WMWindowType
Definition: netwm_def.h:634
QLatin1Char
KStartupInfoId::~KStartupInfoId
~KStartupInfoId()
Definition: kstartupinfo.cpp:1110
KStartupInfo::sendFinish
static bool sendFinish(const KStartupInfoId &id)
Ends startup notification with the given identification.
Definition: kstartupinfo.cpp:527
KStartupInfoId::setupStartupEnv
bool setupStartupEnv() const
Sets the startup notification environment variable to this identification.
Definition: kstartupinfo.cpp:1080
KStandardGuiItem::ok
KGuiItem ok()
Returns the 'Ok' gui item.
Definition: kstandardguiitem.cpp:107
KWindowSystem::self
static KWindowSystem * self()
Access to the singleton instance.
Definition: kwindowsystem_mac.cpp:308
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
QString::toLong
long toLong(bool *ok, int base) const
QObject::customEvent
virtual void customEvent(QEvent *event)
KStartupInfoId::id
const QByteArray & id() const
Returns the notification identifier as string.
Definition: kstartupinfo.cpp:1034
KStartupInfoData::launchedBy
WId launchedBy() const
The toplevel window of the application that caused this startup notification, 0 if unknown...
Definition: kstartupinfo.cpp:1512
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
QString::mid
QString mid(int position, int n) const
KStartupInfo::currentStartupIdEnv
static KStartupInfoId currentStartupIdEnv()
Returns the current startup notification identification for the current startup notification environm...
Definition: kstartupinfo.cpp:1090
KStartupInfoData::setScreen
void setScreen(int screen)
Sets the X11 screen on which the startup notification should happen.
Definition: kstartupinfo.cpp:1487
KStartupInfoData::bin
const QString & bin() const
Returns the binary name of the starting application.
Definition: kstartupinfo.cpp:1344
KStartupInfo::appStarted
static void appStarted()
Manual notification that the application has started.
Definition: kstartupinfo.cpp:586
KStartupInfoData::operator=
KStartupInfoData & operator=(const KStartupInfoData &data)
Definition: kstartupinfo.cpp:1288
KStartupInfo::createNewStartupId
static QByteArray createNewStartupId()
Creates and returns new startup id.
Definition: kstartupinfo.cpp:1012
QLatin1String
Window
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
KStandardGuiItem::Yes
Definition: kstandardguiitem.h:50
KStartupInfoId::operator==
bool operator==(const KStartupInfoId &id) const
Overloaded operator.
Definition: kstartupinfo.cpp:1127
kstandarddirs.h
NET::DockMask
Definition: netwm_def.h:387
QString::at
const QChar at(int position) const
QList::ConstIterator
typedef ConstIterator
NET::Dialog
indicates that this is a dialog window
Definition: netwm_def.h:336
QString::length
int length() const
kwindowsystem.h
get_num
static long get_num(const QString &item_P)
Definition: kstartupinfo.cpp:1539
QByteArray::data
char * data()
QString::left
QString left(int n) const
QString::fromLatin1
QString fromLatin1(const char *str, int size)
NET::OverrideMask
Definition: netwm_def.h:391
NET::TopMenuMask
Definition: netwm_def.h:392
NETWinInfo
Common API for application window properties/protocols.
Definition: netwm.h:829
KStartupInfo::customEvent
virtual void customEvent(QEvent *e_P)
Definition: kstartupinfo.cpp:266
auto_app_started_sending
static bool auto_app_started_sending
Definition: kstartupinfo.cpp:69
KStartupInfoData::Unknown
Definition: kstartupinfo.h:568
NET::Utility
indicates a utility window
Definition: netwm_def.h:349
QList::constEnd
const_iterator constEnd() const
QList::constBegin
const_iterator constBegin() const
KStartupInfoData::icon
const QString & icon() const
Returns the icon of the startup notification, or empty if not available.
Definition: kstartupinfo.cpp:1395
KStartupInfoData::timestamp
unsigned long timestamp() const
Definition: kstartupinfo.cpp:1482
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
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KStartupInfoData::setDesktop
void setDesktop(int desktop)
Sets the desktop for the startup notification ( i.e.
Definition: kstartupinfo.cpp:1400
NET::MenuMask
Definition: netwm_def.h:389
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::KStartupInfoId
KStartupInfoId()
Creates an empty identification.
Definition: kstartupinfo.cpp:1106
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
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
kFatal
static QDebug kFatal(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
QList::begin
iterator begin()
NET::WMState
Definition: netwm_def.h:635
KStartupInfoData::silent
TriState silent() const
Return the silence status for the startup notification.
Definition: kstartupinfo.cpp:1472
KStartupInfoData::No
Definition: kstartupinfo.h:568
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
NET::OnAllDesktops
Definition: netwm_def.h:704
KStartupInfoData::~KStartupInfoData
~KStartupInfoData()
Definition: kstartupinfo.cpp:1334
KStartupInfoData::setLaunchedBy
void setLaunchedBy(WId window)
Sets the toplevel window of the application that caused this startup notification.
Definition: kstartupinfo.cpp:1507
QX11Info
QTimer::singleShot
singleShot
KStartupInfoData::KStartupInfoData
KStartupInfoData()
Constructor.
Definition: kstartupinfo.cpp:1330
net_startup_atom
static Atom net_startup_atom
Definition: kstartupinfo.cpp:829
QString::toUtf8
QByteArray toUtf8() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:24:00 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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

Search



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