| 1 | /* |
| 2 | SPDX-FileCopyrightText: 2003 Lubos Lunak <l.lunak@kde.org> |
| 3 | |
| 4 | SPDX-License-Identifier: MIT |
| 5 | */ |
| 6 | |
| 7 | #ifndef KSELECTIONOWNER_H |
| 8 | #define KSELECTIONOWNER_H |
| 9 | |
| 10 | #include <QObject> |
| 11 | #include <kwindowsystem_export.h> |
| 12 | |
| 13 | #include <xcb/xcb.h> |
| 14 | #include <xcb/xproto.h> |
| 15 | |
| 16 | /*! |
| 17 | \class KSelectionOwner |
| 18 | \inmodule KWindowSystem |
| 19 | |
| 20 | \brief ICCCM manager selection owner. |
| 21 | |
| 22 | This class implements claiming and owning manager selections, as described |
| 23 | in the ICCCM, section 2.8. The selection atom is passed to the constructor, |
| 24 | claim() attempts to claim ownership of the selection, release() gives up |
| 25 | the selection ownership. Signal lostOwnership() is emitted when the selection |
| 26 | is claimed by another owner. |
| 27 | |
| 28 | This class is only useful on the xcb platform. On other platforms the code is only |
| 29 | functional if the constructor overloads taking an xcb_connection_t are used. In case |
| 30 | you inherit from this class ensure that you don't use xcb and/or XLib without verifying |
| 31 | the platform. |
| 32 | */ |
| 33 | class KWINDOWSYSTEM_EXPORT KSelectionOwner : public QObject |
| 34 | { |
| 35 | Q_OBJECT |
| 36 | public: |
| 37 | /*! |
| 38 | * This constructor initializes the object, but doesn't perform any |
| 39 | * operation on the selection. |
| 40 | * |
| 41 | * \a selection atom representing the manager selection |
| 42 | * |
| 43 | * \a screen X screen, or -1 for default |
| 44 | * |
| 45 | * \a parent parent object, or nullptr if there is none |
| 46 | */ |
| 47 | explicit KSelectionOwner(xcb_atom_t selection, int screen = -1, QObject *parent = nullptr); |
| 48 | |
| 49 | /*! |
| 50 | * \overload |
| 51 | * This constructor accepts the selection name and creates the appropriate atom |
| 52 | * for it automatically. |
| 53 | * |
| 54 | * \a selection name of the manager selection |
| 55 | * |
| 56 | * \a screen X screen, or -1 for default |
| 57 | * |
| 58 | * \a parent parent object, or nullptr if there is none |
| 59 | */ |
| 60 | explicit KSelectionOwner(const char *selection, int screen = -1, QObject *parent = nullptr); |
| 61 | /*! |
| 62 | * \overload |
| 63 | * This constructor accepts the xcb_connection_t and root window and doesn't depend on |
| 64 | * running on the xcb platform. Otherwise this constructor behaves like the similar one |
| 65 | * without the xcb_connection_t. |
| 66 | * |
| 67 | * \a selection atom representing the manager selection |
| 68 | * |
| 69 | * \a c the xcb connection this KSelectionWatcher should use |
| 70 | * |
| 71 | * \a root the root window this KSelectionWatcher should use |
| 72 | * |
| 73 | * \a parent parent object, or nullptr if there is none |
| 74 | * |
| 75 | * \since 5.8 |
| 76 | **/ |
| 77 | explicit KSelectionOwner(xcb_atom_t selection, xcb_connection_t *c, xcb_window_t root, QObject *parent = nullptr); |
| 78 | |
| 79 | /*! |
| 80 | * \overload |
| 81 | * This constructor accepts the xcb_connection_t and root window and doesn't depend on |
| 82 | * running on the xcb platform. Otherwise this constructor behaves like the similar one |
| 83 | * without the xcb_connection_t. |
| 84 | * |
| 85 | * \a selection name of the manager selection |
| 86 | * |
| 87 | * \a c the xcb connection this KSelectionWatcher should use |
| 88 | * |
| 89 | * \a root the root window this KSelectionWatcher should use |
| 90 | * |
| 91 | * \a parent parent object, or nullptr if there is none |
| 92 | * |
| 93 | * \since 5.8 |
| 94 | **/ |
| 95 | explicit KSelectionOwner(const char *selection, xcb_connection_t *c, xcb_window_t root, QObject *parent = nullptr); |
| 96 | |
| 97 | /*! |
| 98 | * Destructor. Calls release(). |
| 99 | */ |
| 100 | ~KSelectionOwner() override; |
| 101 | |
| 102 | /*! |
| 103 | * Try to claim ownership of the manager selection using the current X timestamp. |
| 104 | * |
| 105 | * This function returns immediately, but it may take up to one second for the claim |
| 106 | * to succeed or fail, at which point either the claimedOwnership() or |
| 107 | * failedToClaimOwnership() signal is emitted. The claim will not be completed until |
| 108 | * the caller has returned to the event loop. |
| 109 | * |
| 110 | * If \a force is false, and the selection is already owned, the selection is not claimed, |
| 111 | * and failedToClaimOwnership() is emitted. If \a force is true and the selection is |
| 112 | * owned by another client, the client will be given one second to relinquish ownership |
| 113 | * of the selection. If \a force_kill is true, and the previous owner fails to disown |
| 114 | * the selection in time, it will be forcibly killed. |
| 115 | */ |
| 116 | void claim(bool force, bool force_kill = true); |
| 117 | |
| 118 | /*! |
| 119 | * If the selection is owned, the ownership is given up. |
| 120 | */ |
| 121 | void release(); |
| 122 | |
| 123 | /*! |
| 124 | * If the selection is owned, returns the window used internally |
| 125 | * for owning the selection. |
| 126 | */ |
| 127 | xcb_window_t ownerWindow() const; // None if not owning the selection |
| 128 | |
| 129 | bool filterEvent(void *ev_P); // internal |
| 130 | |
| 131 | void timerEvent(QTimerEvent *event) override; |
| 132 | |
| 133 | Q_SIGNALS: |
| 134 | /*! |
| 135 | * This signal is emitted if the selection was owned and the ownership |
| 136 | * has been lost due to another client claiming it, this signal is emitted. |
| 137 | * IMPORTANT: It's not safe to delete the instance in a slot connected |
| 138 | * to this signal. |
| 139 | */ |
| 140 | void lostOwnership(); |
| 141 | |
| 142 | /*! |
| 143 | * This signal is emitted when claim() was successful in claiming |
| 144 | * ownership of the selection. |
| 145 | */ |
| 146 | void claimedOwnership(); |
| 147 | |
| 148 | /*! |
| 149 | * This signal is emitted when claim() failed to claim ownership |
| 150 | * of the selection. |
| 151 | */ |
| 152 | void failedToClaimOwnership(); |
| 153 | |
| 154 | protected: |
| 155 | /* |
| 156 | * Called for every X event received on the window used for owning |
| 157 | * the selection. If true is returned, the event is filtered out. |
| 158 | */ |
| 159 | // virtual bool handleMessage( XEvent* ev ); // removed for KF5, please shout if you need this |
| 160 | /*! |
| 161 | * Called when a SelectionRequest event is received. A reply should |
| 162 | * be sent using the selection handling mechanism described in the ICCCM |
| 163 | * section 2. |
| 164 | * |
| 165 | * \a target requested target type |
| 166 | * |
| 167 | * \a property property to use for the reply data |
| 168 | * |
| 169 | * \a requestor requestor window |
| 170 | */ |
| 171 | virtual bool genericReply(xcb_atom_t target, xcb_atom_t property, xcb_window_t requestor); |
| 172 | /*! |
| 173 | * Called to announce the supported targets, as described in the ICCCM |
| 174 | * section 2.6. The default implementation announces the required targets |
| 175 | * MULTIPLE, TIMESTAMP and TARGETS. |
| 176 | */ |
| 177 | virtual void replyTargets(xcb_atom_t property, xcb_window_t requestor); |
| 178 | /*! |
| 179 | * Called to create atoms needed for claiming the selection and |
| 180 | * communication using the selection handling mechanism. The default |
| 181 | * implementation must be called if reimplemented. This method |
| 182 | * may be called repeatedly. |
| 183 | */ |
| 184 | virtual void getAtoms(); |
| 185 | /*! |
| 186 | * Sets extra data to be sent in the message sent to root window |
| 187 | * after successfully claiming a selection. These extra data |
| 188 | * are in data.l[3] and data.l[4] fields of the XClientMessage. |
| 189 | */ |
| 190 | void setData(uint32_t , uint32_t ); |
| 191 | |
| 192 | private: |
| 193 | void filter_selection_request(void *ev_P); |
| 194 | bool handle_selection(xcb_atom_t target_P, xcb_atom_t property_P, xcb_window_t requestor_P); |
| 195 | |
| 196 | class Private; |
| 197 | Private *const d; |
| 198 | }; |
| 199 | |
| 200 | #endif |
| 201 | |