From 50a265d6fb4402d25a005a07ef730d78da8ebbdc Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Tue, 9 Aug 2022 11:28:06 +0200 Subject: xcb: fix D&D in same xembed client This is kind of porting missing parts QX11Data::xdndHandleDrop() in src/gui/kernel/qdnd_x11.cpp in Qt 4. Change-Id: I3a9d657c63dbca43e33262f49484861e60f59b58 Reviewed-by: Liang Qi (cherry picked from commit 7bc63f345f9ab296979a75c6f4547ef038fd8b37) Reviewed-by: Qt Cherry-pick Bot --- src/plugins/platforms/xcb/qxcbdrag.cpp | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 9fef320078..bd86f6239d 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -1016,21 +1016,30 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e Qt::DropActions supported_drop_actions; QMimeData *dropData = nullptr; + // this could be a same-application drop, just proxied due to + // some XEMBEDding, so try to find the real QMimeData used + // based on the timestamp for this drop. + int at = findTransactionByTime(target_time); + if (at != -1) { + qCDebug(lcQpaXDnd) << "found one transaction via findTransactionByTime()"; + dropData = transactions.at(at).drag->mimeData(); + // Can't use the source QMimeData if we need the image conversion code from xdndObtainData + if (dropData && dropData->hasImage()) + dropData = 0; + } + // if we can't find it, then use the data in the drag manager if (currentDrag()) { - dropData = currentDrag()->mimeData(); + if (!dropData) + dropData = currentDrag()->mimeData(); supported_drop_actions = Qt::DropActions(l[4]); } else { - dropData = m_dropData; + if (!dropData) + dropData = m_dropData; supported_drop_actions = accepted_drop_action | toDropActions(drop_actions); } if (!dropData) return; - // ### - // int at = findXdndDropTransactionByTime(target_time); - // if (at != -1) - // dropData = QDragManager::dragPrivate(X11->dndDropTransactions.at(at).object)->data; - // if we can't find it, then use the data in the drag manager auto buttons = currentDrag() ? b : connection()->queryMouseButtons(); auto modifiers = currentDrag() ? mods : connection()->queryKeyboardModifiers(); @@ -1039,7 +1048,12 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e currentWindow.data(), dropData, currentPosition, supported_drop_actions, buttons, modifiers); - setExecutedDropAction(response.acceptedAction()); + Qt::DropAction acceptedAaction = response.acceptedAction(); + if (!response.isAccepted()) { + // Ignore a failed drag + acceptedAaction = Qt::IgnoreAction; + } + setExecutedDropAction(acceptedAaction); xcb_client_message_event_t finished = {}; finished.response_type = XCB_CLIENT_MESSAGE; @@ -1049,7 +1063,7 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e finished.type = atom(QXcbAtom::XdndFinished); finished.data.data32[0] = currentWindow ? xcb_window(currentWindow.data()) : XCB_NONE; finished.data.data32[1] = response.isAccepted(); // flags - finished.data.data32[2] = toXdndAction(response.acceptedAction()); + finished.data.data32[2] = toXdndAction(acceptedAaction); qCDebug(lcQpaXDnd) << "sending XdndFinished to source:" << xdnd_dragsource; @@ -1253,6 +1267,7 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event bool QXcbDrag::dndEnable(QXcbWindow *w, bool on) { + qCDebug(lcQpaXDnd) << "dndEnable" << w << on; // Windows announce that they support the XDND protocol by creating a window property XdndAware. if (on) { QXcbWindow *window = nullptr; -- cgit v1.2.3