xcb: Fix drag and drop to applications like Emacs and Chromium.

Drops without matching time stamp do not work. I have fixed the issue by
reanimating the findXdndAwareParent() function (adapted to XCB) and
using it to find a matching transaction if all else fails.

Task-number: QTBUG-45812
Change-Id: Ibca15bbab02ccf2f25280418e9edf36972ebf9a0
Reviewed-by: Błażej Szczygieł <spaz16@wp.pl>
Reviewed-by: Dmitry Shachnev <mitya57@gmail.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@theqtcompany.com>
This commit is contained in:
Urs Fleisch 2016-02-26 17:46:09 +01:00 committed by Shawn Rutledge
parent 072f5b513e
commit 269fdbdd2b

View File

@ -1072,6 +1072,40 @@ void QXcbDrag::cancel()
send_leave();
}
// find an ancestor with XdndAware on it
static xcb_window_t findXdndAwareParent(QXcbConnection *c, xcb_window_t window)
{
xcb_window_t target = 0;
forever {
// check if window has XdndAware
xcb_get_property_cookie_t gpCookie = Q_XCB_CALL(
xcb_get_property(c->xcb_connection(), false, window,
c->atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0));
xcb_get_property_reply_t *gpReply = xcb_get_property_reply(
c->xcb_connection(), gpCookie, 0);
bool aware = gpReply && gpReply->type != XCB_NONE;
free(gpReply);
if (aware) {
target = window;
break;
}
// try window's parent
xcb_query_tree_cookie_t qtCookie = Q_XCB_CALL(
xcb_query_tree_unchecked(c->xcb_connection(), window));
xcb_query_tree_reply_t *qtReply = xcb_query_tree_reply(
c->xcb_connection(), qtCookie, NULL);
if (!qtReply)
break;
xcb_window_t root = qtReply->root;
xcb_window_t parent = qtReply->parent;
free(qtReply);
if (window == root)
break;
window = parent;
}
return target;
}
void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event)
{
@ -1099,17 +1133,16 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event
// xcb_convert_selection() that we sent the XdndDrop event to.
at = findTransactionByWindow(event->requestor);
}
// if (at == -1 && event->time == XCB_CURRENT_TIME) {
// // previous Qt versions always requested the data on a child of the target window
// // using CurrentTime... but it could be asking for either drop data or the current drag's data
// Window target = findXdndAwareParent(event->requestor);
// if (target) {
// if (current_target && current_target == target)
// at = -2;
// else
// at = findXdndDropTransactionByWindow(target);
// }
// }
if (at == -1 && event->time == XCB_CURRENT_TIME) {
xcb_window_t target = findXdndAwareParent(connection(), event->requestor);
if (target) {
if (current_target == target)
at = -2;
else
at = findTransactionByWindow(target);
}
}
}
QDrag *transactionDrag = 0;