Changeset View
Changeset View
Standalone View
Standalone View
xwl/selection.cpp
Show First 20 Lines • Show All 77 Lines • ▼ Show 20 Line(s) | |||||
78 | } | 78 | } | ||
79 | 79 | | |||
80 | Selection::Selection(xcb_atom_t atom, QObject *parent) | 80 | Selection::Selection(xcb_atom_t atom, QObject *parent) | ||
81 | : QObject(parent), | 81 | : QObject(parent), | ||
82 | m_atom(atom) | 82 | m_atom(atom) | ||
83 | { | 83 | { | ||
84 | auto *xcbConn = kwinApp()->x11Connection(); | 84 | auto *xcbConn = kwinApp()->x11Connection(); | ||
85 | m_window = xcb_generate_id(kwinApp()->x11Connection()); | 85 | m_window = xcb_generate_id(kwinApp()->x11Connection()); | ||
86 | m_requestorWindow = m_window; | ||||
86 | xcb_flush(xcbConn); | 87 | xcb_flush(xcbConn); | ||
87 | } | 88 | } | ||
88 | 89 | | |||
89 | bool Selection::handleXfixesNotify(xcb_xfixes_selection_notify_event_t *event) | 90 | bool Selection::handleXfixesNotify(xcb_xfixes_selection_notify_event_t *event) | ||
90 | { | 91 | { | ||
91 | if (event->window != m_window) { | 92 | if (event->window != m_window) { | ||
92 | return false; | 93 | return false; | ||
93 | } | 94 | } | ||
Show All 10 Lines | 103 | if (event->owner == m_window && m_wlSrc) { | |||
104 | // grab the actual timestamp here to answer TIMESTAMP requests | 105 | // grab the actual timestamp here to answer TIMESTAMP requests | ||
105 | // correctly | 106 | // correctly | ||
106 | m_wlSrc->setTimestamp(event->timestamp); | 107 | m_wlSrc->setTimestamp(event->timestamp); | ||
107 | m_timestamp = event->timestamp; | 108 | m_timestamp = event->timestamp; | ||
108 | return true; | 109 | return true; | ||
109 | } | 110 | } | ||
110 | 111 | | |||
111 | // Being here means some other X window has claimed the selection. | 112 | // Being here means some other X window has claimed the selection. | ||
112 | delete m_xSrc; | | |||
113 | m_xSrc = nullptr; | | |||
114 | const auto *ac = workspace()->activeClient(); | | |||
115 | if (!ac || !ac->inherits("KWin::Client")) { | | |||
116 | // selections are only allowed to be acquired when Xwayland has focus | | |||
117 | // TODO: can we make this stronger (window id comparision)? | | |||
118 | return true; | | |||
119 | } | | |||
120 | doHandleXfixesNotify(event); | 113 | doHandleXfixesNotify(event); | ||
121 | return true; | 114 | return true; | ||
122 | } | 115 | } | ||
123 | 116 | | |||
124 | bool Selection::filterEvent(xcb_generic_event_t *event) | 117 | bool Selection::filterEvent(xcb_generic_event_t *event) | ||
125 | { | 118 | { | ||
126 | switch (event->response_type & XCB_EVENT_RESPONSE_TYPE_MASK) { | 119 | switch (event->response_type & XCB_EVENT_RESPONSE_TYPE_MASK) { | ||
127 | case XCB_SELECTION_NOTIFY: | 120 | case XCB_SELECTION_NOTIFY: | ||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Line(s) | |||||
195 | } | 188 | } | ||
196 | 189 | | |||
197 | void Selection::createX11Source(xcb_xfixes_selection_notify_event_t *event) | 190 | void Selection::createX11Source(xcb_xfixes_selection_notify_event_t *event) | ||
198 | { | 191 | { | ||
199 | delete m_wlSrc; | 192 | delete m_wlSrc; | ||
200 | delete m_xSrc; | 193 | delete m_xSrc; | ||
201 | m_wlSrc = nullptr; | 194 | m_wlSrc = nullptr; | ||
202 | m_xSrc = nullptr; | 195 | m_xSrc = nullptr; | ||
203 | if (event->owner == XCB_WINDOW_NONE) { | 196 | if (!event || event->owner == XCB_WINDOW_NONE) { | ||
204 | return; | 197 | return; | ||
205 | } | 198 | } | ||
206 | m_xSrc = new X11Source(this, event); | 199 | m_xSrc = new X11Source(this, event); | ||
207 | 200 | | |||
208 | connect(m_xSrc, &X11Source::offersChanged, this, &Selection::x11OffersChanged); | 201 | connect(m_xSrc, &X11Source::offersChanged, this, &Selection::x11OffersChanged); | ||
209 | connect(m_xSrc, &X11Source::transferReady, this, &Selection::startTransferToWayland); | 202 | connect(m_xSrc, &X11Source::transferReady, this, &Selection::startTransferToWayland); | ||
210 | } | 203 | } | ||
211 | 204 | | |||
Show All 10 Lines | 213 | } else { | |||
222 | xcb_set_selection_owner(xcbConn, | 215 | xcb_set_selection_owner(xcbConn, | ||
223 | XCB_WINDOW_NONE, | 216 | XCB_WINDOW_NONE, | ||
224 | m_atom, | 217 | m_atom, | ||
225 | m_timestamp); | 218 | m_timestamp); | ||
226 | } | 219 | } | ||
227 | xcb_flush(xcbConn); | 220 | xcb_flush(xcbConn); | ||
228 | } | 221 | } | ||
229 | 222 | | |||
223 | void Selection::overwriteRequestorWindow(xcb_window_t window) | ||||
224 | { | ||||
225 | Q_ASSERT(m_xSrc); | ||||
226 | if (window == XCB_WINDOW_NONE) { | ||||
227 | // reset | ||||
228 | window = m_window; | ||||
229 | } | ||||
230 | m_requestorWindow = window; | ||||
231 | m_xSrc->setRequestor(window); | ||||
232 | } | ||||
233 | | ||||
230 | bool Selection::handleSelRequest(xcb_selection_request_event_t *event) | 234 | bool Selection::handleSelRequest(xcb_selection_request_event_t *event) | ||
231 | { | 235 | { | ||
232 | if (event->selection != m_atom) { | 236 | if (event->selection != m_atom) { | ||
233 | return false; | 237 | return false; | ||
234 | } | 238 | } | ||
235 | 239 | | |||
236 | if (qobject_cast<Client *>(workspace()->activeClient()) == nullptr) { | 240 | if (qobject_cast<Client *>(workspace()->activeClient()) == nullptr) { | ||
237 | // Receiving Wayland selection not allowed when no Xwayland surface active | 241 | // Receiving Wayland selection not allowed when no Xwayland surface active | ||
Show All 40 Lines | 279 | for (auto *transfer : m_wlToXTransfers) { | |||
278 | } | 282 | } | ||
279 | } | 283 | } | ||
280 | return false; | 284 | return false; | ||
281 | } | 285 | } | ||
282 | 286 | | |||
283 | void Selection::startTransferToWayland(xcb_atom_t target, qint32 fd) | 287 | void Selection::startTransferToWayland(xcb_atom_t target, qint32 fd) | ||
284 | { | 288 | { | ||
285 | // create new x to wl data transfer object | 289 | // create new x to wl data transfer object | ||
286 | auto *transfer = new TransferXtoWl(m_atom, target, fd, m_xSrc->timestamp(), m_window, this); | 290 | auto *transfer = new TransferXtoWl(m_atom, target, fd, m_xSrc->timestamp(), m_requestorWindow, this); | ||
287 | m_xToWlTransfers << transfer; | 291 | m_xToWlTransfers << transfer; | ||
288 | 292 | | |||
289 | connect(transfer, &TransferXtoWl::finished, this, [this, transfer]() { | 293 | connect(transfer, &TransferXtoWl::finished, this, [this, transfer]() { | ||
290 | Q_EMIT transferFinished(transfer->timestamp()); | 294 | Q_EMIT transferFinished(transfer->timestamp()); | ||
291 | delete transfer; | 295 | delete transfer; | ||
292 | m_xToWlTransfers.removeOne(transfer); | 296 | m_xToWlTransfers.removeOne(transfer); | ||
293 | endTimeoutTransfersTimer(); | 297 | endTimeoutTransfersTimer(); | ||
294 | }); | 298 | }); | ||
▲ Show 20 Lines • Show All 64 Lines • Show Last 20 Lines |