From 3c12482df08f3bb4b4bc2f2184985790f78d3351 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Mon, 22 Jun 2015 12:26:18 +0200 Subject: Fix highdpi drag-n-drop for X11 Task-number: QTBUG-46615 Change-Id: Iad548e62a580d6fbd15b7a826116a53ce23b4b8b Reviewed-by: Lars Knoll --- src/plugins/platforms/xcb/qxcbdrag.cpp | 50 ++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 24 deletions(-) (limited to 'src/plugins/platforms/xcb/qxcbdrag.cpp') diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index ebbd879922..a3e646ed7a 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -51,6 +51,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -71,6 +72,11 @@ QT_BEGIN_NAMESPACE const int xdnd_version = 5; +static inline xcb_window_t xcb_window(QPlatformWindow *w) +{ + return static_cast(w)->xcb_window(); +} + static inline xcb_window_t xcb_window(QWindow *w) { return static_cast(w->handle())->xcb_window(); @@ -296,14 +302,8 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md return 0; } -void QXcbDrag::move(const QMouseEvent *me) +void QXcbDrag::move(const QPoint &globalPos) { - // The mouse event is in the coordinate system of the window that started the drag. - // We do not know which window that was at this point, so we just use the device pixel ratio - // of the QGuiApplication. This will break once we support screens with different DPR. Fixing - // this properly requires some redesign of the drag and drop architecture. - QBasicDrag::move(me); - QPoint globalPos = me->globalPos(); if (source_sameanswer.contains(globalPos) && source_sameanswer.isValid()) return; @@ -317,6 +317,8 @@ void QXcbDrag::move(const QMouseEvent *me) } } + QBasicDrag::moveShapedPixmapWindow(QHighDpiScaling::mapPositionFromNative(globalPos, screen)); + if (screen != current_screen) { // ### need to recreate the shaped pixmap window? // int screen = QCursor::x11Screen(); @@ -442,7 +444,7 @@ void QXcbDrag::move(const QMouseEvent *me) DEBUG() << "sending Xdnd enter source=" << enter.data.data32[0]; if (w) - handleEnter(w->window(), &enter); + handleEnter(w, &enter); else if (target) xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&enter); waiting_for_status = false; @@ -470,15 +472,15 @@ void QXcbDrag::move(const QMouseEvent *me) source_time = connection()->time(); if (w) - handle_xdnd_position(w->window(), &move); + handle_xdnd_position(w, &move); else xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&move); } } -void QXcbDrag::drop(const QMouseEvent *event) +void QXcbDrag::drop(const QPoint &globalPos) { - QBasicDrag::drop(event); + QBasicDrag::drop(globalPos); if (!current_target) return; @@ -504,7 +506,7 @@ void QXcbDrag::drop(const QMouseEvent *event) connection()->time(), current_target, current_proxy_target, - (w ? w->window() : 0), + w, // current_embeddig_widget, currentDrag(), QTime::currentTime() @@ -517,7 +519,7 @@ void QXcbDrag::drop(const QMouseEvent *event) } if (w) { - handleDrop(w->window(), &drop); + handleDrop(w, &drop); } else { xcb_send_event(xcb_connection(), false, current_proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&drop); } @@ -663,7 +665,7 @@ static bool checkEmbedded(QWidget* w, const XEvent* xe) #endif -void QXcbDrag::handleEnter(QWindow *window, const xcb_client_message_event_t *event) +void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event) { Q_UNUSED(window); DEBUG() << "handleEnter" << window; @@ -704,14 +706,14 @@ void QXcbDrag::handleEnter(QWindow *window, const xcb_client_message_event_t *ev DEBUG() << " " << connection()->atomName(xdnd_types.at(i)); } -void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *e) +void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message_event_t *e) { QPoint p((e->data.data32[2] & 0xffff0000) >> 16, e->data.data32[2] & 0x0000ffff); Q_ASSERT(w); QRect geometry = w->geometry(); p -= geometry.topLeft(); - if (!w || (w->type() == Qt::Desktop)) + if (!w || !w->window() || (w->window()->type() == Qt::Desktop)) return; if (e->data.data32[0] != xdnd_dragsource) { @@ -720,7 +722,7 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t } currentPosition = p; - currentWindow = w; + currentWindow = w->window(); // timestamp from the source if (e->data.data32[3] != XCB_NONE) { @@ -737,7 +739,7 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t supported_actions = Qt::DropActions(toDropAction(e->data.data32[4])); } - QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag(w,dropData,p,supported_actions); + QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag(w->window(),dropData,p,supported_actions); QRect answerRect(p + geometry.topLeft(), QSize(1,1)); answerRect = qt_response.answerRect().translated(geometry.topLeft()).intersected(geometry); @@ -793,7 +795,7 @@ namespace }; } -void QXcbDrag::handlePosition(QWindow * w, const xcb_client_message_event_t *event) +void QXcbDrag::handlePosition(QPlatformWindow * w, const xcb_client_message_event_t *event) { xcb_client_message_event_t *lastEvent = const_cast(event); xcb_generic_event_t *nextEvent; @@ -856,10 +858,10 @@ void QXcbDrag::handleStatus(const xcb_client_message_event_t *event) DEBUG("xdndHandleStatus end"); } -void QXcbDrag::handleLeave(QWindow *w, const xcb_client_message_event_t *event) +void QXcbDrag::handleLeave(QPlatformWindow *w, const xcb_client_message_event_t *event) { DEBUG("xdnd leave"); - if (!currentWindow || w != currentWindow.data()) + if (!currentWindow || w != currentWindow.data()->handle()) return; // sanity // ### @@ -874,7 +876,7 @@ void QXcbDrag::handleLeave(QWindow *w, const xcb_client_message_event_t *event) DEBUG("xdnd drag leave from unexpected source (%x not %x", event->data.data32[0], xdnd_dragsource); } - QWindowSystemInterface::handleDrag(w,0,QPoint(),Qt::IgnoreAction); + QWindowSystemInterface::handleDrag(w->window(),0,QPoint(),Qt::IgnoreAction); xdnd_dragsource = 0; xdnd_types.clear(); @@ -904,7 +906,7 @@ void QXcbDrag::send_leave() w = 0; if (w) - handleLeave(w->window(), (const xcb_client_message_event_t *)&leave); + handleLeave(w, (const xcb_client_message_event_t *)&leave); else xcb_send_event(xcb_connection(), false,current_proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&leave); @@ -915,7 +917,7 @@ void QXcbDrag::send_leave() waiting_for_status = false; } -void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event) +void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event) { DEBUG("xdndHandleDrop"); if (!currentWindow) { -- cgit v1.2.3