/* SPDX-FileCopyrightText: 2001-2003 Lubos Lunak SPDX-License-Identifier: MIT */ #ifndef KSTARTUPINFO_H #define KSTARTUPINFO_H #include #include #include #include #include // for WId #include #include typedef struct _XDisplay Display; struct xcb_connection_t; class KStartupInfoId; class KStartupInfoData; /** * Class for manipulating the application startup notification. * * This class can be used to send information about started application, * change the information and receive this information. For detailed * description, see kdelibs/kdecore/README.kstartupinfo. * * You usually don't need to use this class for sending the notification * information, as KDE libraries should do this when an application is * started (e.g. KRun class). * * For receiving the startup notification info, create an instance and connect * to its slots. It will automatically detect started applications and when * they are ready. * * @see KStartupInfoId * @see KStartupInfoData * * @author Lubos Lunak */ class KWINDOWSYSTEM_EXPORT KStartupInfo : public QObject { Q_OBJECT public: /** * Manual notification that the application has started. * If you do not map a (toplevel) window, then startup * notification will not disappear for the application * until a timeout. You can use this as an alternative * method in this case. */ static void appStarted(); /** * Sends explicit notification that the startup notification * with id startup_id should end. */ static void appStarted(const QByteArray &startup_id); /** * Sets a new value for the application startup notification window property for newly * created toplevel windows. * @param startup_id the startup notification identifier * @see KStartupInfo::setNewStartupId */ static void setStartupId(const QByteArray &startup_id); /** * Use this function if the application got a request with startup * notification from outside (for example, when KUniqueApplication::newInstance() * is called, or e.g.\ when khelpcenter opens new URL in its window). * The window can be either an already existing and visible window, * or a new one, before being shown. Note that this function is usually * needed only when a window is reused. */ static void setNewStartupId(QWindow *window, const QByteArray &startup_id); /** * Creates and returns new startup id. The id includes properly setup * user timestamp. * * On the X11 platform the current timestamp will be fetched from the * X-Server. If the caller has an adaquat timestamp (e.g. from a QMouseEvent) * it should prefer using createNewStartupIdForTimestamp to not trigger a * roundtrip to the X-Server * * @see createNewStartupIdForTimestamp */ static QByteArray createNewStartupId(); /** * Creates and returns new startup id with @p timestamp as user timestamp part. * * @param timestamp The timestamp for the startup id. * @see createNewStartupId * @since 5.5 **/ static QByteArray createNewStartupIdForTimestamp(quint32 timestamp); /** * */ enum { CleanOnCantDetect = 1 << 0, DisableKWinModule = 1 << 1, AnnounceSilenceChanges = 1 << 2, }; /** * Creates an instance that will receive the startup notifications. * The various flags passed may be * @li CleanOnCantDetect - when a new unknown window appears, all startup * notifications for applications that are not compliant with * the startup protocol are removed * @li DisableKWinModule - KWinModule, which is normally used to detect * new windows, is disabled. With this flag, checkStartup() must be * called in order to check newly mapped windows. * @li AnnounceSilenceChanges - normally, startup notifications are * "removed" when they're silenced, and "recreated" when they're resumed. * With this flag, the change is normally announced with gotStartupChange(). * * @param flags OR-ed combination of flags * @param parent the parent of this QObject (can be @c nullptr for no parent) * */ explicit KStartupInfo(int flags, QObject *parent = nullptr); ~KStartupInfo() override; /** * Sends given notification data about started application * with the given startup identification. If no notification for this identification * exists yet, it is created, otherwise it's updated. Note that the name field * in data is required. * * @param id the id of the application * @param data the application's data * @return true if successful, false otherwise * @see KStartupInfoId * @see KStartupInfoData */ static bool sendStartup(const KStartupInfoId &id, const KStartupInfoData &data); /** * Like sendStartup , uses @p conn instead of QX11Info::connection() for sending the info. * @param conn the xcb connection of the application. Note that the name field * in data is required. * @param screen The x11 screen the connection belongs to * @param id the id of the application * @param data the application's data * @return true if successful, false otherwise * @since 5.18 */ static bool sendStartupXcb(xcb_connection_t *conn, int screen, const KStartupInfoId &id, const KStartupInfoData &data); /** * Sends given notification data about started application * with the given startup identification. This is used for updating the notification * info, if no notification for this identification exists, it's ignored. * @param id the id of the application * @param data the application's data * @return true if successful, false otherwise * @see KStartupInfoId * @see KStartupInfoData */ static bool sendChange(const KStartupInfoId &id, const KStartupInfoData &data); /** * Like sendChange , uses @p conn instead of QX11Info::connection() for sending the info. * @param conn the xcb connection of the application. * @param screen The x11 screen the connection belongs to * @param id the id of the application * @param data the application's data * @return true if successful, false otherwise * @since 5.18 */ static bool sendChangeXcb(xcb_connection_t *conn, int screen, const KStartupInfoId &id, const KStartupInfoData &data); /** * Ends startup notification with the given identification. * @param id the id of the application * @return true if successful, false otherwise */ static bool sendFinish(const KStartupInfoId &id); /** * Like sendFinish , uses @p conn instead of QX11Info::connection() for sending the info. * @param conn the xcb connection of the application. * @param screen The x11 screen the connection belongs to * @param id the id of the application * @return true if successful, false otherwise * @since 5.18 */ static bool sendFinishXcb(xcb_connection_t *conn, int screen, const KStartupInfoId &id); /** * Ends startup notification with the given identification and the given data * (e.g.\ PIDs of processes for this startup notification that exited). * @param id the id of the application * @param data the application's data * @return true if successful, false otherwise */ static bool sendFinish(const KStartupInfoId &id, const KStartupInfoData &data); /** * Like sendFinish , uses @p conn instead of QX11Info::connection() for sending the info. * @param conn the xcb connection of the application. * @param screen The x11 screen the connection belongs to * @param id the id of the application * @param data the application's data * @return true if successful, false otherwise * @since 5.18 */ static bool sendFinishXcb(xcb_connection_t *conn, int screen, const KStartupInfoId &id, const KStartupInfoData &data); /** * Unsets the startup notification environment variable. */ static void resetStartupEnv(); /** * @li NoMatch - the window doesn't match any existing startup notification * @li Match - the window matches an existing startup notification * @li CantDetect - unable to detect if the window matches any existing * startup notification */ enum startup_t { NoMatch, Match, CantDetect }; /** * Checks if the given windows matches any existing startup notification. * @param w the window id to check * @return the result of the operation */ startup_t checkStartup(WId w); /** * Checks if the given windows matches any existing startup notification, and * if yes, returns the identification in id. * @param w the window id to check * @param id if found, the id of the startup notification will be written here * @return the result of the operation */ startup_t checkStartup(WId w, KStartupInfoId &id); /** * Checks if the given windows matches any existing startup notification, and * if yes, returns the notification data in data. * @param w the window id to check * @param data if found, the data of the startup notification will be written here * @return the result of the operation */ startup_t checkStartup(WId w, KStartupInfoData &data); /** * Checks if the given windows matches any existing startup notification, and * if yes, returns the identification in id and notification data in data. * @param w the window id to check * @param id if found, the id of the startup notification will be written here * @param data if found, the data of the startup notification will be written here * @return the result of the operation */ startup_t checkStartup(WId w, KStartupInfoId &id, KStartupInfoData &data); /** * Sets the timeout for notifications, after this timeout a notification is removed. * @param secs the new timeout in seconds */ void setTimeout(unsigned int secs); /** * Returns startup notification identification of the given window. * @param w the id of the window * @return the startup notification id. Can be null if not found. */ static QByteArray windowStartupId(WId w); /** * @internal */ class Data; /** * @internal */ class Private; Q_SIGNALS: /** * Emitted when a new startup notification is created (i.e.\ a new application is * being started). * @param id the notification identification * @param data the notification data */ void gotNewStartup(const KStartupInfoId &id, const KStartupInfoData &data); /** * Emitted when a startup notification changes. * @param id the notification identification * @param data the notification data */ void gotStartupChange(const KStartupInfoId &id, const KStartupInfoData &data); /** * Emitted when a startup notification is removed (either because it was detected * that the application is ready or because of a timeout). * @param id the notification identification * @param data the notification data */ void gotRemoveStartup(const KStartupInfoId &id, const KStartupInfoData &data); protected: /** * */ void customEvent(QEvent *e_P) override; private: Q_PRIVATE_SLOT(d, void startups_cleanup()) Q_PRIVATE_SLOT(d, void startups_cleanup_no_age()) Q_PRIVATE_SLOT(d, void got_message(const QString &msg)) Q_PRIVATE_SLOT(d, void window_added(WId w)) Q_PRIVATE_SLOT(d, void slot_window_added(WId w)) Private *const d; Q_DISABLE_COPY(KStartupInfo) }; /** * Class representing an identification of application startup notification. * * Every existing notification about a starting application has its own unique * identification, that's used to identify and manipulate the notification. * * @see KStartupInfo * @see KStartupInfoData * * @author Lubos Lunak */ class KWINDOWSYSTEM_EXPORT KStartupInfoId { public: /** * Overloaded operator. * @return true if the notification identifications are the same */ bool operator==(const KStartupInfoId &id) const; /** * Overloaded operator. * @return true if the notification identifications are different */ bool operator!=(const KStartupInfoId &id) const; /** * Checks whether the identifier is valid. * @return true if this object doesn't represent a valid notification identification */ bool isNull() const; /** * Initializes this object with the given identification ( which may be also "0" * for no notification ), or if "" is given, tries to read it from the startup * notification environment variable, and if it's not set, creates a new one. * @param id the new identification, "0" for no notification or "" to read * the environment variable */ void initId(const QByteArray &id = ""); /** * Returns the notification identifier as string. * @return the identification string for the notification */ const QByteArray &id() const; /** * Return the user timestamp for the startup notification, or 0 if no timestamp * is set. */ unsigned long timestamp() const; /** * Sets the startup notification environment variable to this identification. * @return true if successful, false otherwise */ bool setupStartupEnv() const; /** * Creates an empty identification */ KStartupInfoId(); /** * Copy constructor. */ KStartupInfoId(const KStartupInfoId &data); ~KStartupInfoId(); KStartupInfoId &operator=(const KStartupInfoId &data); bool operator<(const KStartupInfoId &id) const; private: explicit KStartupInfoId(const QString &txt); friend class KStartupInfo; friend class KStartupInfo::Private; struct Private; Private *const d; }; /** * Class representing data about an application startup notification. * * Such data include the icon of the starting application, the desktop on which * the application should start, the binary name of the application, etc. * * @see KStartupInfo * @see KStartupInfoId * * @author Lubos Lunak */ class KWINDOWSYSTEM_EXPORT KStartupInfoData { public: /** * Sets the binary name of the application (e.g.\ 'kcontrol'). * @param bin the new binary name of the application */ void setBin(const QString &bin); /** * Returns the binary name of the starting application * @return the new binary name of the application */ const QString &bin() const; /** * Sets the name for the notification (e.g.\ 'Control Center'). */ void setName(const QString &name); /** * Returns the name of the startup notification. If it's not available, * it tries to use other information (binary name). * @return the name of the startup notification */ const QString &findName() const; /** * Returns the name of the startup notification, or empty if not available. * @return the name of the startup notification, or an empty string * if not set. */ const QString &name() const; /** * Sets the description for the notification (e.g.\ 'Launching Control Center'). * I.e. name() describes what is being started, while description() is * the actual action performed by the starting. */ void setDescription(const QString &descr); /** * Returns the description of the startup notification. If it's not available, * it returns name(). * @return the description of the startup notification */ const QString &findDescription() const; /** * Returns the name of the startup notification, or empty if not available. * @return the name of the startup notification, or an empty string * if not set. */ const QString &description() const; /** * Sets the icon for the startup notification (e.g.\ 'kcontrol'). * @param icon the name of the icon */ void setIcon(const QString &icon); /** * Returns the icon of the startup notification, and if it's not available, * tries to get it from the binary name. * @return the name of the startup notification's icon, or the name of * the binary if not set */ const QString &findIcon() const; /** * Returns the icon of the startup notification, or empty if not available. * @return the name of the icon, or an empty string if not set. */ const QString &icon() const; /** * Sets the desktop for the startup notification (i.e.\ the desktop on which * the starting application should appear ). * @param desktop the desktop for the startup notification */ void setDesktop(int desktop); /** * Returns the desktop for the startup notification. * @return the desktop for the startup notification */ int desktop() const; /** * Sets a WM_CLASS value for the startup notification, it may be used for increasing * the chance that the windows created by the starting application will be * detected correctly. * @param wmclass the WM_CLASS value for the startup notification */ void setWMClass(const QByteArray &wmclass); /** * Returns the WM_CLASS value for the startup notification, or binary name if not * available. * @return the WM_CLASS value for the startup notification, or the binary name * if not set */ const QByteArray findWMClass() const; /** * Returns the WM_CLASS value for the startup notification, or empty if not available. * @return the WM_CLASS value for the startup notification, or empty * if not set */ QByteArray WMClass() const; /** * Adds a PID to the list of processes that belong to the startup notification. It * may be used to increase the chance that the windows created by the starting * application will be detected correctly, and also for detecting if the application * has quit without creating any window. * @param pid the PID to add */ void addPid(pid_t pid); /** * Returns all PIDs for the startup notification. * @return the list of all PIDs */ QList pids() const; /** * Checks whether the given @p pid is in the list of PIDs for startup * notification. * @return true if the given @p pid is in the list of PIDs for the startup notification */ bool is_pid(pid_t pid) const; /** * Sets the hostname on which the application is starting. It's necessary to set * it if PIDs are set. * @param hostname the application's hostname. If it's a null string, the current hostname is used */ void setHostname(const QByteArray &hostname = QByteArray()); /** * Returns the hostname for the startup notification. * @return the hostname */ QByteArray hostname() const; /** * */ enum TriState { Yes, No, Unknown }; /** * Sets whether the visual feedback for this startup notification * should be silenced (temporarily suspended). */ void setSilent(TriState state); /** * Return the silence status for the startup notification. * @return KStartupInfoData::Yes if visual feedback is silenced */ TriState silent() const; /** * The X11 screen on which the startup notification is happening, -1 if unknown. */ int screen() const; /** * Sets the X11 screen on which the startup notification should happen. * This is usually not necessary to set, as it's set by default to QX11Info::screen(). */ void setScreen(int screen); /** * The Xinerama screen for the startup notification, -1 if unknown. */ int xinerama() const; /** * Sets the Xinerama screen for the startup notification ( i.e. the screeen on which * the starting application should appear ). * @param xinerama the Xinerama screen for the startup notification */ void setXinerama(int xinerama); /** * The .desktop file used to initiate this startup notification, or empty. This information * should be used only to identify the application, not to read any additional information. * @since 4.5 **/ QString applicationId() const; /** * Sets the .desktop file that was used to initiate the startup notification. * @since 4.5 */ void setApplicationId(const QString &desktop); /** * Updates the notification data from the given data. Some data, such as the desktop * or the name, won't be rewritten if already set. * @param data the data to update */ void update(const KStartupInfoData &data); /** * Constructor. Initializes all the data to their default empty values. */ KStartupInfoData(); /** * Copy constructor. */ KStartupInfoData(const KStartupInfoData &data); ~KStartupInfoData(); KStartupInfoData &operator=(const KStartupInfoData &data); private: explicit KStartupInfoData(const QString &txt); friend class KStartupInfo; friend class KStartupInfo::Data; friend class KStartupInfo::Private; struct Private; Private *const d; }; #endif