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.

Pick-to: 6.4 6.3 6.2 5.15
Change-Id: I3a9d657c63dbca43e33262f49484861e60f59b58
Reviewed-by: Liang Qi <liang.qi@qt.io>
This commit is contained in:
Liang Qi 2022-08-09 11:28:06 +02:00
parent 64cd43d394
commit 7bc63f345f

View File

@ -980,21 +980,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()) {
if (!dropData)
dropData = currentDrag()->mimeData();
supported_drop_actions = Qt::DropActions(l[4]);
} else {
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();
@ -1003,7 +1012,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;
@ -1013,7 +1027,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;
@ -1217,6 +1231,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;