File indexing completed on 2024-07-14 03:57:44

0001 /*
0002     SPDX-FileCopyrightText: 2001-2003 Lubos Lunak <l.lunak@kde.org>
0003 
0004     SPDX-License-Identifier: MIT
0005 */
0006 
0007 #ifndef KSTARTUPINFO_H
0008 #define KSTARTUPINFO_H
0009 
0010 #include <kwindowsystem_export.h>
0011 
0012 #include <QChildEvent>
0013 #include <QObject>
0014 #include <QString>
0015 #include <QWidgetList> // for WId
0016 #include <QWindow>
0017 
0018 #include <sys/types.h>
0019 
0020 typedef struct _XDisplay Display;
0021 
0022 struct xcb_connection_t;
0023 
0024 class KStartupInfoId;
0025 class KStartupInfoData;
0026 
0027 /**
0028  * Class for manipulating the application startup notification.
0029  *
0030  * This class can be used to send information about started application,
0031  * change the information and receive this information. For detailed
0032  * description, see kdelibs/kdecore/README.kstartupinfo.
0033  *
0034  * You usually don't need to use this class for sending the notification
0035  * information, as KDE libraries should do this when an application is
0036  * started (e.g. KRun class).
0037  *
0038  * For receiving the startup notification info, create an instance and connect
0039  * to its slots. It will automatically detect started applications and when
0040  * they are ready.
0041  *
0042  * @see KStartupInfoId
0043  * @see KStartupInfoData
0044  *
0045  * @author Lubos Lunak <l.lunak@kde.org>
0046  */
0047 class KWINDOWSYSTEM_EXPORT KStartupInfo : public QObject
0048 {
0049     Q_OBJECT
0050 public:
0051     /**
0052      * Manual notification that the application has started.
0053      * If you do not map a (toplevel) window, then startup
0054      * notification will not disappear for the application
0055      * until a timeout. You can use this as an alternative
0056      * method in this case.
0057      */
0058     static void appStarted();
0059 
0060     /**
0061      * Sends explicit notification that the startup notification
0062      * with id startup_id should end.
0063      */
0064     static void appStarted(const QByteArray &startup_id);
0065 
0066     /**
0067      * Sets a new value for the application startup notification window property for newly
0068      * created toplevel windows.
0069      * @param startup_id the startup notification identifier
0070      * @see KStartupInfo::setNewStartupId
0071      */
0072     static void setStartupId(const QByteArray &startup_id);
0073 
0074     /**
0075      * Use this function if the application got a request with startup
0076      * notification from outside (for example, when KUniqueApplication::newInstance()
0077      * is called, or e.g.\ when khelpcenter opens new URL in its window).
0078      * The window can be either an already existing and visible window,
0079      * or a new one, before being shown. Note that this function is usually
0080      * needed only when a window is reused.
0081      */
0082     static void setNewStartupId(QWindow *window, const QByteArray &startup_id);
0083 
0084     /**
0085      * Creates and returns new startup id. The id includes properly setup
0086      * user timestamp.
0087      *
0088      * On the X11 platform the current timestamp will be fetched from the
0089      * X-Server. If the caller has an adaquat timestamp (e.g. from a QMouseEvent)
0090      * it should prefer using createNewStartupIdForTimestamp to not trigger a
0091      * roundtrip to the X-Server
0092      *
0093      * @see createNewStartupIdForTimestamp
0094      */
0095     static QByteArray createNewStartupId();
0096     /**
0097      * Creates and returns new startup id with @p timestamp as user timestamp part.
0098      *
0099      * @param timestamp The timestamp for the startup id.
0100      * @see createNewStartupId
0101      * @since 5.5
0102      **/
0103     static QByteArray createNewStartupIdForTimestamp(quint32 timestamp);
0104     /**
0105      *
0106      */
0107     enum {
0108         CleanOnCantDetect = 1 << 0,
0109         DisableKWinModule = 1 << 1,
0110         AnnounceSilenceChanges = 1 << 2,
0111     };
0112 
0113     /**
0114      * Creates an instance that will receive the startup notifications.
0115      * The various flags passed may be
0116      * @li CleanOnCantDetect - when a new unknown window appears, all startup
0117      *     notifications for applications that are not compliant with
0118      *     the startup protocol are removed
0119      * @li DisableKWinModule - KWinModule, which is normally used to detect
0120      *     new windows, is disabled. With this flag, checkStartup() must be
0121      *     called in order to check newly mapped windows.
0122      * @li AnnounceSilenceChanges - normally, startup notifications are
0123      *     "removed" when they're silenced, and "recreated" when they're resumed.
0124      *     With this flag, the change is normally announced with gotStartupChange().
0125      *
0126      * @param flags OR-ed combination of flags
0127      * @param parent the parent of this QObject (can be @c nullptr for no parent)
0128      *
0129      */
0130     explicit KStartupInfo(int flags, QObject *parent = nullptr);
0131 
0132     ~KStartupInfo() override;
0133     /**
0134      * Sends given notification data about started application
0135      * with the given startup identification. If no notification for this identification
0136      * exists yet, it is created, otherwise it's updated. Note that the name field
0137      * in data is required.
0138      *
0139      * @param id the id of the application
0140      * @param data the application's data
0141      * @return true if successful, false otherwise
0142      * @see KStartupInfoId
0143      * @see KStartupInfoData
0144      */
0145     static bool sendStartup(const KStartupInfoId &id, const KStartupInfoData &data);
0146 
0147     /**
0148      * Like sendStartup , uses @p conn instead of QX11Info::connection() for sending the info.
0149      * @param conn the xcb connection of the application. Note that the name field
0150      * in data is required.
0151      * @param screen The x11 screen the connection belongs to
0152      * @param id the id of the application
0153      * @param data the application's data
0154      * @return true if successful, false otherwise
0155      * @since 5.18
0156      */
0157     static bool sendStartupXcb(xcb_connection_t *conn, int screen, const KStartupInfoId &id, const KStartupInfoData &data);
0158 
0159     /**
0160      * Sends given notification data about started application
0161      * with the given startup identification. This is used for updating the notification
0162      * info, if no notification for this identification exists, it's ignored.
0163      * @param id the id of the application
0164      * @param data the application's data
0165      * @return true if successful, false otherwise
0166      * @see KStartupInfoId
0167      * @see KStartupInfoData
0168      */
0169     static bool sendChange(const KStartupInfoId &id, const KStartupInfoData &data);
0170 
0171     /**
0172      * Like sendChange , uses @p conn instead of QX11Info::connection() for sending the info.
0173      * @param conn the xcb connection of the application.
0174      * @param screen The x11 screen the connection belongs to
0175      * @param id the id of the application
0176      * @param data the application's data
0177      * @return true if successful, false otherwise
0178      * @since 5.18
0179      */
0180     static bool sendChangeXcb(xcb_connection_t *conn, int screen, const KStartupInfoId &id, const KStartupInfoData &data);
0181 
0182     /**
0183      * Ends startup notification with the given identification.
0184      * @param id the id of the application
0185      * @return true if successful, false otherwise
0186      */
0187     static bool sendFinish(const KStartupInfoId &id);
0188 
0189     /**
0190      * Like sendFinish , uses @p conn instead of QX11Info::connection() for sending the info.
0191      * @param conn the xcb connection of the application.
0192      * @param screen The x11 screen the connection belongs to
0193      * @param id the id of the application
0194      * @return true if successful, false otherwise
0195      * @since 5.18
0196      */
0197     static bool sendFinishXcb(xcb_connection_t *conn, int screen, const KStartupInfoId &id);
0198 
0199     /**
0200      * Ends startup notification with the given identification and the given data
0201      * (e.g.\ PIDs of processes for this startup notification that exited).
0202      * @param id the id of the application
0203      * @param data the application's data
0204      * @return true if successful, false otherwise
0205      */
0206     static bool sendFinish(const KStartupInfoId &id, const KStartupInfoData &data);
0207 
0208     /**
0209      * Like sendFinish , uses @p conn instead of QX11Info::connection() for sending the info.
0210      * @param conn the xcb connection of the application.
0211      * @param screen The x11 screen the connection belongs to
0212      * @param id the id of the application
0213      * @param data the application's data
0214      * @return true if successful, false otherwise
0215      * @since 5.18
0216      */
0217     static bool sendFinishXcb(xcb_connection_t *conn, int screen, const KStartupInfoId &id, const KStartupInfoData &data);
0218 
0219     /**
0220      * Unsets the startup notification environment variable.
0221      */
0222     static void resetStartupEnv();
0223     /**
0224      * @li NoMatch    - the window doesn't match any existing startup notification
0225      * @li Match      - the window matches an existing startup notification
0226      * @li CantDetect - unable to detect if the window matches any existing
0227      *          startup notification
0228      */
0229     enum startup_t { NoMatch, Match, CantDetect };
0230     /**
0231      * Checks if the given windows matches any existing startup notification.
0232      * @param w the window id to check
0233      * @return the result of the operation
0234      */
0235     startup_t checkStartup(WId w);
0236     /**
0237      * Checks if the given windows matches any existing startup notification, and
0238      * if yes, returns the identification in id.
0239      * @param w the window id to check
0240      * @param id if found, the id of the startup notification will be written here
0241      * @return the result of the operation
0242      */
0243     startup_t checkStartup(WId w, KStartupInfoId &id);
0244     /**
0245      * Checks if the given windows matches any existing startup notification, and
0246      * if yes, returns the notification data in data.
0247      * @param w the window id to check
0248      * @param data if found, the data of the startup notification will be written here
0249      * @return the result of the operation
0250      */
0251     startup_t checkStartup(WId w, KStartupInfoData &data);
0252     /**
0253      * Checks if the given windows matches any existing startup notification, and
0254      * if yes, returns the identification in id and notification data in data.
0255      * @param w the window id to check
0256      * @param id if found, the id of the startup notification will be written here
0257      * @param data if found, the data of the startup notification will be written here
0258      * @return the result of the operation
0259      */
0260     startup_t checkStartup(WId w, KStartupInfoId &id, KStartupInfoData &data);
0261     /**
0262      * Sets the timeout for notifications, after this timeout a notification is removed.
0263      * @param secs the new timeout in seconds
0264      */
0265     void setTimeout(unsigned int secs);
0266     /**
0267      * Returns startup notification identification of the given window.
0268      * @param w the id of the window
0269      * @return the startup notification id. Can be null if not found.
0270      */
0271     static QByteArray windowStartupId(WId w);
0272     /**
0273      * @internal
0274      */
0275     class Data;
0276 
0277     /**
0278      * @internal
0279      */
0280     class Private;
0281 Q_SIGNALS:
0282     /**
0283      * Emitted when a new startup notification is created (i.e.\ a new application is
0284      * being started).
0285      * @param id the notification identification
0286      * @param data the notification data
0287      */
0288     void gotNewStartup(const KStartupInfoId &id, const KStartupInfoData &data);
0289     /**
0290      * Emitted when a startup notification changes.
0291      * @param id the notification identification
0292      * @param data the notification data
0293      */
0294     void gotStartupChange(const KStartupInfoId &id, const KStartupInfoData &data);
0295     /**
0296      * Emitted when a startup notification is removed (either because it was detected
0297      * that the application is ready or because of a timeout).
0298      * @param id the notification identification
0299      * @param data the notification data
0300      */
0301     void gotRemoveStartup(const KStartupInfoId &id, const KStartupInfoData &data);
0302 
0303 protected:
0304     /**
0305      *
0306      */
0307     void customEvent(QEvent *e_P) override;
0308 
0309 private:
0310     Q_PRIVATE_SLOT(d, void startups_cleanup())
0311     Q_PRIVATE_SLOT(d, void startups_cleanup_no_age())
0312     Q_PRIVATE_SLOT(d, void got_message(const QString &msg))
0313     Q_PRIVATE_SLOT(d, void window_added(WId w))
0314     Q_PRIVATE_SLOT(d, void slot_window_added(WId w))
0315 
0316     Private *const d;
0317 
0318     Q_DISABLE_COPY(KStartupInfo)
0319 };
0320 
0321 /**
0322  * Class representing an identification of application startup notification.
0323  *
0324  * Every existing notification about a starting application has its own unique
0325  * identification, that's used to identify and manipulate the notification.
0326  *
0327  * @see KStartupInfo
0328  * @see KStartupInfoData
0329  *
0330  * @author Lubos Lunak <l.lunak@kde.org>
0331  */
0332 class KWINDOWSYSTEM_EXPORT KStartupInfoId
0333 {
0334 public:
0335     /**
0336      * Overloaded operator.
0337      * @return true if the notification identifications are the same
0338      */
0339     bool operator==(const KStartupInfoId &id) const;
0340     /**
0341      * Overloaded operator.
0342      * @return true if the notification identifications are different
0343      */
0344     bool operator!=(const KStartupInfoId &id) const;
0345     /**
0346      * Checks whether the identifier is valid.
0347      * @return true if this object doesn't represent a valid notification identification
0348      */
0349     bool isNull() const;
0350 
0351     /**
0352      * Initializes this object with the given identification ( which may be also "0"
0353      * for no notification ), or if "" is given, tries to read it from the startup
0354      * notification environment variable, and if it's not set, creates a new one.
0355      * @param id the new identification, "0" for no notification or "" to read
0356      *           the environment variable
0357      */
0358     void initId(const QByteArray &id = "");
0359     /**
0360      * Returns the notification identifier as string.
0361      * @return the identification string for the notification
0362      */
0363     const QByteArray &id() const;
0364     /**
0365      * Return the user timestamp for the startup notification, or 0 if no timestamp
0366      * is set.
0367      */
0368     unsigned long timestamp() const;
0369     /**
0370      * Sets the startup notification environment variable to this identification.
0371      * @return true if successful, false otherwise
0372      */
0373     bool setupStartupEnv() const;
0374     /**
0375      * Creates an empty identification
0376      */
0377     KStartupInfoId();
0378     /**
0379      * Copy constructor.
0380      */
0381     KStartupInfoId(const KStartupInfoId &data);
0382     ~KStartupInfoId();
0383     KStartupInfoId &operator=(const KStartupInfoId &data);
0384     bool operator<(const KStartupInfoId &id) const;
0385 
0386 private:
0387     explicit KStartupInfoId(const QString &txt);
0388     friend class KStartupInfo;
0389     friend class KStartupInfo::Private;
0390     struct Private;
0391     Private *const d;
0392 };
0393 
0394 /**
0395  * Class representing data about an application startup notification.
0396  *
0397  * Such data include the icon of the starting application, the desktop on which
0398  * the application should start, the binary name of the application, etc.
0399  *
0400  * @see KStartupInfo
0401  * @see KStartupInfoId
0402  *
0403  * @author Lubos Lunak <l.lunak@kde.org>
0404  */
0405 class KWINDOWSYSTEM_EXPORT KStartupInfoData
0406 {
0407 public:
0408     /**
0409      * Sets the binary name of the application (e.g.\ 'kcontrol').
0410      * @param bin the new binary name of the application
0411      */
0412     void setBin(const QString &bin);
0413     /**
0414      * Returns the binary name of the starting application
0415      * @return the new binary name of the application
0416      */
0417     const QString &bin() const;
0418     /**
0419      * Sets the name for the notification (e.g.\ 'Control Center').
0420      */
0421     void setName(const QString &name);
0422     /**
0423      * Returns the name of the startup notification. If it's not available,
0424      * it tries to use other information (binary name).
0425      * @return the name of the startup notification
0426      */
0427     const QString &findName() const;
0428     /**
0429      * Returns the name of the startup notification, or empty if not available.
0430      * @return the name of the startup notification, or an empty string
0431      *         if not set.
0432      */
0433     const QString &name() const;
0434     /**
0435      * Sets the description for the notification (e.g.\ 'Launching Control Center').
0436      * I.e. name() describes what is being started, while description() is
0437      * the actual action performed by the starting.
0438      */
0439     void setDescription(const QString &descr);
0440     /**
0441      * Returns the description of the startup notification. If it's not available,
0442      * it returns name().
0443      * @return the description of the startup notification
0444      */
0445     const QString &findDescription() const;
0446     /**
0447      * Returns the name of the startup notification, or empty if not available.
0448      * @return the name of the startup notification, or an empty string
0449      *         if not set.
0450      */
0451     const QString &description() const;
0452     /**
0453      * Sets the icon for the startup notification (e.g.\ 'kcontrol').
0454      * @param icon the name of the icon
0455      */
0456     void setIcon(const QString &icon);
0457     /**
0458      * Returns the icon of the startup notification, and if it's not available,
0459      * tries to get it from the binary name.
0460      * @return the name of the startup notification's icon, or the name of
0461      *         the binary if not set
0462      */
0463     const QString &findIcon() const;
0464     /**
0465      * Returns the icon of the startup notification, or empty if not available.
0466      * @return the name of the icon, or an empty string if not set.
0467      */
0468     const QString &icon() const;
0469     /**
0470      * Sets the desktop for the startup notification (i.e.\ the desktop on which
0471      * the starting application should appear ).
0472      * @param desktop the desktop for the startup notification
0473      */
0474     void setDesktop(int desktop);
0475     /**
0476      * Returns the desktop for the startup notification.
0477      * @return the desktop for the startup notification
0478      */
0479     int desktop() const;
0480     /**
0481      * Sets a WM_CLASS value for the startup notification, it may be used for increasing
0482      * the chance that the windows created by the starting application will be
0483      * detected correctly.
0484      * @param wmclass the WM_CLASS value for the startup notification
0485      */
0486     void setWMClass(const QByteArray &wmclass);
0487     /**
0488      * Returns the WM_CLASS value for the startup notification, or binary name if not
0489      * available.
0490      * @return the WM_CLASS value for the startup notification, or the binary name
0491      *         if not set
0492      */
0493     const QByteArray findWMClass() const;
0494     /**
0495      * Returns the WM_CLASS value for the startup notification, or empty if not available.
0496      * @return the WM_CLASS value for the startup notification, or empty
0497      *         if not set
0498      */
0499     QByteArray WMClass() const;
0500     /**
0501      * Adds a PID to the list of processes that belong to the startup notification. It
0502      * may be used to increase the chance that the windows created by the starting
0503      * application will be detected correctly, and also for detecting if the application
0504      * has quit without creating any window.
0505      * @param pid the PID to add
0506      */
0507     void addPid(pid_t pid);
0508     /**
0509      * Returns all PIDs for the startup notification.
0510      * @return the list of all PIDs
0511      */
0512     QList<pid_t> pids() const;
0513     /**
0514      * Checks whether the given @p pid is in the list of PIDs for startup
0515      * notification.
0516      * @return true if the given @p pid is in the list of PIDs for the startup notification
0517      */
0518     bool is_pid(pid_t pid) const;
0519     /**
0520      * Sets the hostname on which the application is starting. It's necessary to set
0521      * it if PIDs are set.
0522      * @param hostname the application's hostname. If it's a null string, the current hostname is used
0523      */
0524     void setHostname(const QByteArray &hostname = QByteArray());
0525     /**
0526      * Returns the hostname for the startup notification.
0527      * @return the hostname
0528      */
0529     QByteArray hostname() const;
0530 
0531     /**
0532      *
0533      */
0534     enum TriState { Yes, No, Unknown };
0535 
0536     /**
0537      * Sets whether the visual feedback for this startup notification
0538      * should be silenced (temporarily suspended).
0539      */
0540     void setSilent(TriState state);
0541 
0542     /**
0543      * Return the silence status for the startup notification.
0544      * @return KStartupInfoData::Yes if visual feedback is silenced
0545      */
0546     TriState silent() const;
0547 
0548     /**
0549      * The X11 screen on which the startup notification is happening, -1 if unknown.
0550      */
0551     int screen() const;
0552 
0553     /**
0554      * Sets the X11 screen on which the startup notification should happen.
0555      * This is usually not necessary to set, as it's set by default to QX11Info::screen().
0556      */
0557     void setScreen(int screen);
0558 
0559     /**
0560      * The Xinerama screen for the startup notification, -1 if unknown.
0561      */
0562     int xinerama() const;
0563 
0564     /**
0565      * Sets the Xinerama screen for the startup notification ( i.e. the screeen on which
0566      * the starting application should appear ).
0567      * @param xinerama the Xinerama screen for the startup notification
0568      */
0569     void setXinerama(int xinerama);
0570 
0571     /**
0572      * The .desktop file used to initiate this startup notification, or empty. This information
0573      * should be used only to identify the application, not to read any additional information.
0574      * @since 4.5
0575      **/
0576     QString applicationId() const;
0577 
0578     /**
0579      * Sets the .desktop file that was used to initiate the startup notification.
0580      * @since 4.5
0581      */
0582     void setApplicationId(const QString &desktop);
0583 
0584     /**
0585      * Updates the notification data from the given data. Some data, such as the desktop
0586      * or the name, won't be rewritten if already set.
0587      * @param data the data to update
0588      */
0589     void update(const KStartupInfoData &data);
0590 
0591     /**
0592      * Constructor. Initializes all the data to their default empty values.
0593      */
0594     KStartupInfoData();
0595 
0596     /**
0597      * Copy constructor.
0598      */
0599     KStartupInfoData(const KStartupInfoData &data);
0600     ~KStartupInfoData();
0601     KStartupInfoData &operator=(const KStartupInfoData &data);
0602 
0603 private:
0604     explicit KStartupInfoData(const QString &txt);
0605     friend class KStartupInfo;
0606     friend class KStartupInfo::Data;
0607     friend class KStartupInfo::Private;
0608     struct Private;
0609     Private *const d;
0610 };
0611 
0612 #endif