summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb/qxcbdrag.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbdrag.cpp')
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp67
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)