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 | |
20 | typedef struct _XDisplay Display; |
21 | |
22 | struct xcb_connection_t; |
23 | |
24 | class KStartupInfoId; |
25 | class 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 | */ |
47 | class KWINDOWSYSTEM_EXPORT KStartupInfo : public QObject |
48 | { |
49 | Q_OBJECT |
50 | public: |
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; |
281 | Q_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 | |
303 | protected: |
304 | /** |
305 | * |
306 | */ |
307 | void customEvent(QEvent *e_P) override; |
308 | |
309 | private: |
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 | */ |
332 | class KWINDOWSYSTEM_EXPORT KStartupInfoId |
333 | { |
334 | public: |
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 | |
386 | private: |
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 | */ |
405 | class KWINDOWSYSTEM_EXPORT KStartupInfoData |
406 | { |
407 | public: |
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 | |
603 | private: |
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 | |