diff options
author | Urs Fleisch <ufleisch@users.sourceforge.net> | 2016-02-26 17:46:09 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@theqtcompany.com> | 2016-04-25 05:47:46 +0000 |
commit | 269fdbdd2bedda5f5eacb751224d3a3fc3eed5bc (patch) | |
tree | c62bfe13bcde2521042337302b4dea60047d0b87 /src/plugins/platforms | |
parent | 072f5b513e486e884ea7fa4a1cac9aedf3846374 (diff) |
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>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbdrag.cpp | 55 |
1 files changed, 44 insertions, 11 deletions
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index f5cc87394b..f1428d0a96 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -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; |