1/*
2 SPDX-FileCopyrightText: 2001-2003 Lubos Lunak <l.lunak@kde.org>
3
4 SPDX-License-Identifier: MIT
5*/
6
7#ifndef KSTARTUPINFO_H
8#define KSTARTUPINFO_H
9
10#include <kwindowsystem_export.h>
11
12#include <QChildEvent>
13#include <QObject>
14#include <QString>
15#include <QWidgetList> // for WId
16#include <QWindow>
17
18#include <sys/types.h>
19
20typedef struct _XDisplay Display;
21
22struct xcb_connection_t;
23
24class KStartupInfoId;
25class KStartupInfoData;
26
27/**
28 * Class for manipulating the application startup notification.
29 *
30 * This class can be used to send information about started application,
31 * change the information and receive this information. For detailed
32 * description, see kdelibs/kdecore/README.kstartupinfo.
33 *
34 * You usually don't need to use this class for sending the notification
35 * information, as KDE libraries should do this when an application is
36 * started (e.g. KRun class).
37 *
38 * For receiving the startup notification info, create an instance and connect
39 * to its slots. It will automatically detect started applications and when
40 * they are ready.
41 *
42 * @see KStartupInfoId
43 * @see KStartupInfoData
44 *
45 * @author Lubos Lunak <l.lunak@kde.org>
46 */
47class KWINDOWSYSTEM_EXPORT KStartupInfo : public QObject
48{
49 Q_OBJECT
50public:
51 /**
52 * Manual notification that the application has started.
53 * If you do not map a (toplevel) window, then startup
54 * notification will not disappear for the application
55 * until a timeout. You can use this as an alternative
56 * method in this case.
57 */
58 static void appStarted();
59
60 /**
61 * Sends explicit notification that the startup notification
62 * with id startup_id should end.
63 */
64 static void appStarted(const QByteArray &startup_id);
65
66 /**
67 * Sets a new value for the application startup notification window property for newly
68 * created toplevel windows.
69 * @param startup_id the startup notification identifier
70 * @see KStartupInfo::setNewStartupId
71 */
72 static void setStartupId(const QByteArray &startup_id);
73
74 /**
75 * Use this function if the application got a request with startup
76 * notification from outside (for example, when KUniqueApplication::newInstance()
77 * is called, or e.g.\ when khelpcenter opens new URL in its window).
78 * The window can be either an already existing and visible window,
79 * or a new one, before being shown. Note that this function is usually
80 * needed only when a window is reused.
81 */
82 static void setNewStartupId(QWindow *window, const QByteArray &startup_id);
83
84 /**
85 * Creates and returns new startup id. The id includes properly setup
86 * user timestamp.
87 *
88 * On the X11 platform the current timestamp will be fetched from the
89 * X-Server. If the caller has an adaquat timestamp (e.g. from a QMouseEvent)
90 * it should prefer using createNewStartupIdForTimestamp to not trigger a
91 * roundtrip to the X-Server
92 *
93 * @see createNewStartupIdForTimestamp
94 */
95 static QByteArray createNewStartupId();
96 /**
97 * Creates and returns new startup id with @p timestamp as user timestamp part.
98 *
99 * @param timestamp The timestamp for the startup id.
100 * @see createNewStartupId
101 * @since 5.5
102 **/
103 static QByteArray createNewStartupIdForTimestamp(quint32 timestamp);
104 /**
105 *
106 */
107 enum {
108 CleanOnCantDetect = 1 << 0,
109 DisableKWinModule = 1 << 1,
110 AnnounceSilenceChanges = 1 << 2,
111 };
112
113 /**
114 * Creates an instance that will receive the startup notifications.
115 * The various flags passed may be
116 * @li CleanOnCantDetect - when a new unknown window appears, all startup
117 * notifications for applications that are not compliant with
118 * the startup protocol are removed
119 * @li DisableKWinModule - KWinModule, which is normally used to detect
120 * new windows, is disabled. With this flag, checkStartup() must be
121 * called in order to check newly mapped windows.
122 * @li AnnounceSilenceChanges - normally, startup notifications are
123 * "removed" when they're silenced, and "recreated" when they're resumed.
124 * With this flag, the change is normally announced with gotStartupChange().
125 *
126 * @param flags OR-ed combination of flags
127 * @param parent the parent of this QObject (can be @c nullptr for no parent)
128 *
129 */
130 explicit KStartupInfo(int flags, QObject *parent = nullptr);
131
132 ~KStartupInfo() override;
133 /**
134 * Sends given notification data about started application
135 * with the given startup identification. If no notification for this identification
136 * exists yet, it is created, otherwise it's updated. Note that the name field
137 * in data is required.
138 *
139 * @param id the id of the application
140 * @param data the application's data
141 * @return true if successful, false otherwise
142 * @see KStartupInfoId
143 * @see KStartupInfoData
144 */
145 static bool sendStartup(const KStartupInfoId &id, const KStartupInfoData &data);
146
147 /**
148 * Like sendStartup , uses @p conn instead of QX11Info::connection() for sending the info.
149 * @param conn the xcb connection of the application. Note that the name field
150 * in data is required.
151 * @param screen The x11 screen the connection belongs to
152 * @param id the id of the application
153 * @param data the application's data
154 * @return true if successful, false otherwise
155 * @since 5.18
156 */
157 static bool sendStartupXcb(xcb_connection_t *conn, int screen, const KStartupInfoId &id, const KStartupInfoData &data);
158
159 /**
160 * Sends given notification data about started application
161 * with the given startup identification. This is used for updating the notification
162 * info, if no notification for this identification exists, it's ignored.
163 * @param id the id of the application
164 * @param data the application's data
165 * @return true if successful, false otherwise
166 * @see KStartupInfoId
167 * @see KStartupInfoData
168 */
169 static bool sendChange(const KStartupInfoId &id, const KStartupInfoData &data);
170
171 /**
172 * Like sendChange , uses @p conn instead of QX11Info::connection() for sending the info.
173 * @param conn the xcb connection of the application.
174 * @param screen The x11 screen the connection belongs to
175 * @param id the id of the application
176 * @param data the application's data
177 * @return true if successful, false otherwise
178 * @since 5.18
179 */
180 static bool sendChangeXcb(xcb_connection_t *conn, int screen, const KStartupInfoId &id, const KStartupInfoData &data);
181
182 /**
183 * Ends startup notification with the given identification.
184 * @param id the id of the application
185 * @return true if successful, false otherwise
186 */
187 static bool sendFinish(const KStartupInfoId &id);
188
189 /**
190 * Like sendFinish , uses @p conn instead of QX11Info::connection() for sending the info.
191 * @param conn the xcb connection of the application.
192 * @param screen The x11 screen the connection belongs to
193 * @param id the id of the application
194 * @return true if successful, false otherwise
195 * @since 5.18
196 */
197 static bool sendFinishXcb(xcb_connection_t *conn, int screen, const KStartupInfoId &id);
198
199 /**
200 * Ends startup notification with the given identification and the given data
201 * (e.g.\ PIDs of processes for this startup notification that exited).
202 * @param id the id of the application
203 * @param data the application's data
204 * @return true if successful, false otherwise
205 */
206 static bool sendFinish(const KStartupInfoId &id, const KStartupInfoData &data);
207
208 /**
209 * Like sendFinish , uses @p conn instead of QX11Info::connection() for sending the info.
210 * @param conn the xcb connection of the application.
211 * @param screen The x11 screen the connection belongs to
212 * @param id the id of the application
213 * @param data the application's data
214 * @return true if successful, false otherwise
215 * @since 5.18
216 */
217 static bool sendFinishXcb(xcb_connection_t *conn, int screen, const KStartupInfoId &id, const KStartupInfoData &data);
218
219 /**
220 * Unsets the startup notification environment variable.
221 */
222 static void resetStartupEnv();
223 /**
224 * @li NoMatch - the window doesn't match any existing startup notification
225 * @li Match - the window matches an existing startup notification
226 * @li CantDetect - unable to detect if the window matches any existing
227 * startup notification
228 */
229 enum startup_t { NoMatch, Match, CantDetect };
230 /**
231 * Checks if the given windows matches any existing startup notification.
232 * @param w the window id to check
233 * @return the result of the operation
234 */
235 startup_t checkStartup(WId w);
236 /**
237 * Checks if the given windows matches any existing startup notification, and
238 * if yes, returns the identification in id.
239 * @param w the window id to check
240 * @param id if found, the id of the startup notification will be written here
241 * @return the result of the operation
242 */
243 startup_t checkStartup(WId w, KStartupInfoId &id);
244 /**
245 * Checks if the given windows matches any existing startup notification, and
246 * if yes, returns the notification data in data.
247 * @param w the window id to check
248 * @param data if found, the data of the startup notification will be written here
249 * @return the result of the operation
250 */
251 startup_t checkStartup(WId w, KStartupInfoData &data);
252 /**
253 * Checks if the given windows matches any existing startup notification, and
254 * if yes, returns the identification in id and notification data in data.
255 * @param w the window id to check
256 * @param id if found, the id of the startup notification will be written here
257 * @param data if found, the data of the startup notification will be written here
258 * @return the result of the operation
259 */
260 startup_t checkStartup(WId w, KStartupInfoId &id, KStartupInfoData &data);
261 /**
262 * Sets the timeout for notifications, after this timeout a notification is removed.
263 * @param secs the new timeout in seconds
264 */
265 void setTimeout(unsigned int secs);
266 /**
267 * Returns startup notification identification of the given window.
268 * @param w the id of the window
269 * @return the startup notification id. Can be null if not found.
270 */
271 static QByteArray windowStartupId(WId w);
272 /**
273 * @internal
274 */
275 class Data;
276
277 /**
278 * @internal
279 */
280 class Private;
281Q_SIGNALS:
282 /**
283 * Emitted when a new startup notification is created (i.e.\ a new application is
284 * being started).
285 * @param id the notification identification
286 * @param data the notification data
287 */
288 void gotNewStartup(const KStartupInfoId &id, const KStartupInfoData &data);
289 /**
290 * Emitted when a startup notification changes.
291 * @param id the notification identification
292 * @param data the notification data
293 */
294 void gotStartupChange(const KStartupInfoId &id, const KStartupInfoData &data);
295 /**
296 * Emitted when a startup notification is removed (either because it was detected
297 * that the application is ready or because of a timeout).
298 * @param id the notification identification
299 * @param data the notification data
300 */
301 void gotRemoveStartup(const KStartupInfoId &id, const KStartupInfoData &data);
302
303protected:
304 /**
305 *
306 */
307 void customEvent(QEvent *e_P) override;
308
309private:
310 Q_PRIVATE_SLOT(d, void startups_cleanup())
311 Q_PRIVATE_SLOT(d, void startups_cleanup_no_age())
312 Q_PRIVATE_SLOT(d, void got_message(const QString &msg))
313 Q_PRIVATE_SLOT(d, void window_added(WId w))
314 Q_PRIVATE_SLOT(d, void slot_window_added(WId w))
315
316 Private *const d;
317
318 Q_DISABLE_COPY(KStartupInfo)
319};
320
321/**
322 * Class representing an identification of application startup notification.
323 *
324 * Every existing notification about a starting application has its own unique
325 * identification, that's used to identify and manipulate the notification.
326 *
327 * @see KStartupInfo
328 * @see KStartupInfoData
329 *
330 * @author Lubos Lunak <l.lunak@kde.org>
331 */
332class KWINDOWSYSTEM_EXPORT KStartupInfoId
333{
334public:
335 /**
336 * Overloaded operator.
337 * @return true if the notification identifications are the same
338 */
339 bool operator==(const KStartupInfoId &id) const;
340 /**
341 * Overloaded operator.
342 * @return true if the notification identifications are different
343 */
344 bool operator!=(const KStartupInfoId &id) const;
345 /**
346 * Checks whether the identifier is valid.
347 * @return true if this object doesn't represent a valid notification identification
348 */
349 bool isNull() const;
350
351 /**
352 * Initializes this object with the given identification ( which may be also "0"
353 * for no notification ), or if "" is given, tries to read it from the startup
354 * notification environment variable, and if it's not set, creates a new one.
355 * @param id the new identification, "0" for no notification or "" to read
356 * the environment variable
357 */
358 void initId(const QByteArray &id = "");
359 /**
360 * Returns the notification identifier as string.
361 * @return the identification string for the notification
362 */
363 const QByteArray &id() const;
364 /**
365 * Return the user timestamp for the startup notification, or 0 if no timestamp
366 * is set.
367 */
368 unsigned long timestamp() const;
369 /**
370 * Sets the startup notification environment variable to this identification.
371 * @return true if successful, false otherwise
372 */
373 bool setupStartupEnv() const;
374 /**
375 * Creates an empty identification
376 */
377 KStartupInfoId();
378 /**
379 * Copy constructor.
380 */
381 KStartupInfoId(const KStartupInfoId &data);
382 ~KStartupInfoId();
383 KStartupInfoId &operator=(const KStartupInfoId &data);
384 bool operator<(const KStartupInfoId &id) const;
385
386private:
387 explicit KStartupInfoId(const QString &txt);
388 friend class KStartupInfo;
389 friend class KStartupInfo::Private;
390 struct Private;
391 Private *const d;
392};
393
394/**
395 * Class representing data about an application startup notification.
396 *
397 * Such data include the icon of the starting application, the desktop on which
398 * the application should start, the binary name of the application, etc.
399 *
400 * @see KStartupInfo
401 * @see KStartupInfoId
402 *
403 * @author Lubos Lunak <l.lunak@kde.org>
404 */
405class KWINDOWSYSTEM_EXPORT KStartupInfoData
406{
407public:
408 /**
409 * Sets the binary name of the application (e.g.\ 'kcontrol').
410 * @param bin the new binary name of the application
411 */
412 void setBin(const QString &bin);
413 /**
414 * Returns the binary name of the starting application
415 * @return the new binary name of the application
416 */
417 const QString &bin() const;
418 /**
419 * Sets the name for the notification (e.g.\ 'Control Center').
420 */
421 void setName(const QString &name);
422 /**
423 * Returns the name of the startup notification. If it's not available,
424 * it tries to use other information (binary name).
425 * @return the name of the startup notification
426 */
427 const QString &findName() const;
428 /**
429 * Returns the name of the startup notification, or empty if not available.
430 * @return the name of the startup notification, or an empty string
431 * if not set.
432 */
433 const QString &name() const;
434 /**
435 * Sets the description for the notification (e.g.\ 'Launching Control Center').
436 * I.e. name() describes what is being started, while description() is
437 * the actual action performed by the starting.
438 */
439 void setDescription(const QString &descr);
440 /**
441 * Returns the description of the startup notification. If it's not available,
442 * it returns name().
443 * @return the description of the startup notification
444 */
445 const QString &findDescription() const;
446 /**
447 * Returns the name of the startup notification, or empty if not available.
448 * @return the name of the startup notification, or an empty string
449 * if not set.
450 */
451 const QString &description() const;
452 /**
453 * Sets the icon for the startup notification (e.g.\ 'kcontrol').
454 * @param icon the name of the icon
455 */
456 void setIcon(const QString &icon);
457 /**
458 * Returns the icon of the startup notification, and if it's not available,
459 * tries to get it from the binary name.
460 * @return the name of the startup notification's icon, or the name of
461 * the binary if not set
462 */
463 const QString &findIcon() const;
464 /**
465 * Returns the icon of the startup notification, or empty if not available.
466 * @return the name of the icon, or an empty string if not set.
467 */
468 const QString &icon() const;
469 /**
470 * Sets the desktop for the startup notification (i.e.\ the desktop on which
471 * the starting application should appear ).
472 * @param desktop the desktop for the startup notification
473 */
474 void setDesktop(int desktop);
475 /**
476 * Returns the desktop for the startup notification.
477 * @return the desktop for the startup notification
478 */
479 int desktop() const;
480 /**
481 * Sets a WM_CLASS value for the startup notification, it may be used for increasing
482 * the chance that the windows created by the starting application will be
483 * detected correctly.
484 * @param wmclass the WM_CLASS value for the startup notification
485 */
486 void setWMClass(const QByteArray &wmclass);
487 /**
488 * Returns the WM_CLASS value for the startup notification, or binary name if not
489 * available.
490 * @return the WM_CLASS value for the startup notification, or the binary name
491 * if not set
492 */
493 const QByteArray findWMClass() const;
494 /**
495 * Returns the WM_CLASS value for the startup notification, or empty if not available.
496 * @return the WM_CLASS value for the startup notification, or empty
497 * if not set
498 */
499 QByteArray WMClass() const;
500 /**
501 * Adds a PID to the list of processes that belong to the startup notification. It
502 * may be used to increase the chance that the windows created by the starting
503 * application will be detected correctly, and also for detecting if the application
504 * has quit without creating any window.
505 * @param pid the PID to add
506 */
507 void addPid(pid_t pid);
508 /**
509 * Returns all PIDs for the startup notification.
510 * @return the list of all PIDs
511 */
512 QList<pid_t> pids() const;
513 /**
514 * Checks whether the given @p pid is in the list of PIDs for startup
515 * notification.
516 * @return true if the given @p pid is in the list of PIDs for the startup notification
517 */
518 bool is_pid(pid_t pid) const;
519 /**
520 * Sets the hostname on which the application is starting. It's necessary to set
521 * it if PIDs are set.
522 * @param hostname the application's hostname. If it's a null string, the current hostname is used
523 */
524 void setHostname(const QByteArray &hostname = QByteArray());
525 /**
526 * Returns the hostname for the startup notification.
527 * @return the hostname
528 */
529 QByteArray hostname() const;
530
531 /**
532 *
533 */
534 enum TriState { Yes, No, Unknown };
535
536 /**
537 * Sets whether the visual feedback for this startup notification
538 * should be silenced (temporarily suspended).
539 */
540 void setSilent(TriState state);
541
542 /**
543 * Return the silence status for the startup notification.
544 * @return KStartupInfoData::Yes if visual feedback is silenced
545 */
546 TriState silent() const;
547
548 /**
549 * The X11 screen on which the startup notification is happening, -1 if unknown.
550 */
551 int screen() const;
552
553 /**
554 * Sets the X11 screen on which the startup notification should happen.
555 * This is usually not necessary to set, as it's set by default to QX11Info::screen().
556 */
557 void setScreen(int screen);
558
559 /**
560 * The Xinerama screen for the startup notification, -1 if unknown.
561 */
562 int xinerama() const;
563
564 /**
565 * Sets the Xinerama screen for the startup notification ( i.e. the screeen on which
566 * the starting application should appear ).
567 * @param xinerama the Xinerama screen for the startup notification
568 */
569 void setXinerama(int xinerama);
570
571 /**
572 * The .desktop file used to initiate this startup notification, or empty. This information
573 * should be used only to identify the application, not to read any additional information.
574 * @since 4.5
575 **/
576 QString applicationId() const;
577
578 /**
579 * Sets the .desktop file that was used to initiate the startup notification.
580 * @since 4.5
581 */
582 void setApplicationId(const QString &desktop);
583
584 /**
585 * Updates the notification data from the given data. Some data, such as the desktop
586 * or the name, won't be rewritten if already set.
587 * @param data the data to update
588 */
589 void update(const KStartupInfoData &data);
590
591 /**
592 * Constructor. Initializes all the data to their default empty values.
593 */
594 KStartupInfoData();
595
596 /**
597 * Copy constructor.
598 */
599 KStartupInfoData(const KStartupInfoData &data);
600 ~KStartupInfoData();
601 KStartupInfoData &operator=(const KStartupInfoData &data);
602
603private:
604 explicit KStartupInfoData(const QString &txt);
605 friend class KStartupInfo;
606 friend class KStartupInfo::Data;
607 friend class KStartupInfo::Private;
608 struct Private;
609 Private *const d;
610};
611
612#endif
613

source code of kwindowsystem/src/kstartupinfo.h