diff options
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbdrag.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbdrag.cpp | 67 |
1 files changed, 36 insertions, 31 deletions
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 4f0f57c375..53437f24ae 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -1,40 +1,32 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtGui module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL$ +** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -183,7 +175,7 @@ void QXcbDrag::startDrag() QStringList fmts = QXcbMime::formatsHelper(drag()->mimeData()); for (int i = 0; i < fmts.size(); ++i) { - QList<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), fmts.at(i)); + QVector<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), fmts.at(i)); for (int j = 0; j < atoms.size(); ++j) { if (!drag_types.contains(atoms.at(j))) drag_types.append(atoms.at(j)); @@ -242,9 +234,16 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md if (reply->map_state != XCB_MAP_STATE_VIEWABLE) return 0; + free(reply); + xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(xcb_connection(), w); xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(xcb_connection(), gcookie, 0); - if (reply && QRect(greply->x, greply->y, greply->width, greply->height).contains(pos)) { + if (!greply) + return 0; + + QRect windowRect(greply->x, greply->y, greply->width, greply->height); + free(greply); + if (windowRect.contains(pos)) { bool windowContainsMouse = !ignoreNonXdndAwareWindows; { xcb_get_property_cookie_t cookie = @@ -255,7 +254,7 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md bool isAware = reply && reply->type != XCB_NONE; free(reply); if (isAware) { - const QPoint relPos = pos - QPoint(greply->x, greply->y); + const QPoint relPos = pos - windowRect.topLeft(); // When ShapeInput and ShapeBounding are not set they return a single rectangle with the geometry of the window, this is why we // need to check both here so that in the case one is set and the other is not we still get the correct result. if (connection()->hasInputShape()) @@ -279,7 +278,7 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md xcb_window_t r = 0; for (uint i = nc; !r && i--;) - r = findRealWindow(pos - QPoint(greply->x, greply->y), c[i], md-1, ignoreNonXdndAwareWindows); + r = findRealWindow(pos - windowRect.topLeft(), c[i], md-1, ignoreNonXdndAwareWindows); free(reply); if (r) @@ -300,6 +299,11 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md void QXcbDrag::move(const QMouseEvent *me) { + // 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. + static const int dpr = int(qApp->devicePixelRatio()); QBasicDrag::move(me); QPoint globalPos = me->globalPos(); @@ -336,7 +340,7 @@ void QXcbDrag::move(const QMouseEvent *me) // qt_xdnd_current_screen = screen; xcb_window_t rootwin = current_screen->root(); xcb_translate_coordinates_reply_t *translate = - ::translateCoordinates(connection(), rootwin, rootwin, globalPos.x(), globalPos.y()); + ::translateCoordinates(connection(), rootwin, rootwin, globalPos.x() * dpr, globalPos.y() * dpr); if (!translate) return; @@ -401,7 +405,7 @@ void QXcbDrag::move(const QMouseEvent *me) int target_version = 1; if (proxy_target) { - xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, target, + xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, proxy_target, atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 1); xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0); if (!reply || reply->type == XCB_NONE) @@ -459,7 +463,7 @@ void QXcbDrag::move(const QMouseEvent *me) move.type = atom(QXcbAtom::XdndPosition); move.data.data32[0] = connection()->clipboard()->owner(); move.data.data32[1] = 0; // flags - move.data.data32[2] = (globalPos.x() << 16) + globalPos.y(); + move.data.data32[2] = (globalPos.x() * dpr << 16) + globalPos.y() * dpr; move.data.data32[3] = connection()->time(); move.data.data32[4] = toXdndAction(defaultAction(currentDrag()->supportedActions(), QGuiApplication::keyboardModifiers())); DEBUG() << "sending Xdnd position source=" << move.data.data32[0] << "target=" << move.window; @@ -705,7 +709,9 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t QPoint p((e->data.data32[2] & 0xffff0000) >> 16, e->data.data32[2] & 0x0000ffff); Q_ASSERT(w); QRect geometry = w->geometry(); + const int dpr = int(w->handle()->devicePixelRatio()); + p /= dpr; p -= geometry.topLeft(); if (!w || (w->type() == Qt::Desktop)) @@ -824,10 +830,12 @@ void QXcbDrag::handle_xdnd_status(const xcb_client_message_event_t *event) updateCursor(Qt::IgnoreAction); } + static const int dpr = int(qApp->devicePixelRatio()); + if ((event->data.data32[1] & 2) == 0) { QPoint p((event->data.data32[2] & 0xffff0000) >> 16, event->data.data32[2] & 0x0000ffff); QSize s((event->data.data32[3] & 0xffff0000) >> 16, event->data.data32[3] & 0x0000ffff); - source_sameanswer = QRect(p, s); + source_sameanswer = QRect(p / dpr, s / dpr); } else { source_sameanswer = QRect(); } @@ -1010,9 +1018,6 @@ void QXcbDrag::handleFinished(const xcb_client_message_event_t *event) // current_target = 0; // current_proxy_target = 0; - if (t.drag) - t.drag->deleteLater(); - // current_target = target; // current_proxy_target = proxy_target; // current_embedding_widget = embedding_widget; @@ -1211,7 +1216,7 @@ QVariant QXcbDropData::xdndObtainData(const QByteArray &format, QVariant::Type r return result; } - QList<xcb_atom_t> atoms = drag->xdnd_types; + QVector<xcb_atom_t> atoms = drag->xdnd_types; QByteArray encoding; xcb_atom_t a = mimeAtomForFormat(c, QLatin1String(format), requestedType, atoms, &encoding); if (a == XCB_NONE) |