From b9c5a938c0b578249cac7491592547042f5aa4d2 Mon Sep 17 00:00:00 2001
From: Alexander Volkov <a.volkov@rusbitech.ru>
Date: Tue, 3 Mar 2015 18:46:57 +0300
Subject: [PATCH] xcb: Always send dnd events to the proxy window if it exists

The standard http://www.newplanetsoftware.com/xdnd/ says:
"The only place where the proxy window should be used is when
checking XdndAware and in the calls to XSendEvent()".

Change-Id: I62e504ba52ec7ec2a941c53a84889bb3eb4b4cc1
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
---
 src/plugins/platforms/xcb/qxcbdrag.cpp | 17 ++++++++++++-----
 src/plugins/platforms/xcb/qxcbdrag.h   |  2 +-
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index a3e646ed7a7..de23c59a637 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -444,7 +444,7 @@ void QXcbDrag::move(const QPoint &globalPos)
 
             DEBUG() << "sending Xdnd enter source=" << enter.data.data32[0];
             if (w)
-                handleEnter(w, &enter);
+                handleEnter(w, &enter, current_proxy_target);
             else if (target)
                 xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&enter);
             waiting_for_status = false;
@@ -665,7 +665,7 @@ static bool checkEmbedded(QWidget* w, const XEvent* xe)
 #endif
 
 
-void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event)
+void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event, xcb_window_t proxy)
 {
     Q_UNUSED(window);
     DEBUG() << "handleEnter" << window;
@@ -677,6 +677,9 @@ void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_eve
         return;
 
     xdnd_dragsource = event->data.data32[0];
+    if (!proxy)
+        proxy = xdndProxy(connection(), xdnd_dragsource);
+    current_proxy_target = proxy ? proxy : xdnd_dragsource;
 
     if (event->data.data32[1] & 1) {
         // get the types from XdndTypeList
@@ -775,7 +778,7 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message
     if (xdnd_dragsource == connection()->clipboard()->owner())
         handle_xdnd_status(&response);
     else
-        Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xdnd_dragsource,
+        Q_XCB_CALL(xcb_send_event(xcb_connection(), false, current_proxy_target,
                                   XCB_EVENT_MASK_NO_EVENT, (const char *)&response));
 }
 
@@ -967,7 +970,7 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e
     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());
-    Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xdnd_dragsource,
+    Q_XCB_CALL(xcb_send_event(xcb_connection(), false, current_proxy_target,
                               XCB_EVENT_MASK_NO_EVENT, (char *)&finished));
 
     xdnd_dragsource = 0;
@@ -1132,7 +1135,11 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event
         }
     }
 
-    xcb_send_event(xcb_connection(), false, event->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&notify);
+    xcb_window_t proxy_target = xdndProxy(connection(), event->requestor);
+    if (!proxy_target)
+        proxy_target = event->requestor;
+
+    xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&notify);
 }
 
 
diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h
index 699d402ea61..9584c04238b 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.h
+++ b/src/plugins/platforms/xcb/qxcbdrag.h
@@ -76,7 +76,7 @@ public:
     void drop(const QPoint &globalPos) Q_DECL_OVERRIDE;
     void endDrag() Q_DECL_OVERRIDE;
 
-    void handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event);
+    void handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event, xcb_window_t proxy = 0);
     void handlePosition(QPlatformWindow *w, const xcb_client_message_event_t *event);
     void handleLeave(QPlatformWindow *w, const xcb_client_message_event_t *event);
     void handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event);
-- 
GitLab