summaryrefslogtreecommitdiffstats
path: root/src/client/qwaylanddatadevice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/qwaylanddatadevice.cpp')
-rw-r--r--src/client/qwaylanddatadevice.cpp60
1 files changed, 49 insertions, 11 deletions
diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp
index a7014f7a1..e9d82100f 100644
--- a/src/client/qwaylanddatadevice.cpp
+++ b/src/client/qwaylanddatadevice.cpp
@@ -13,6 +13,8 @@
#include "qwaylandabstractdecoration_p.h"
#include "qwaylandsurface_p.h"
+#include <QtWaylandClient/private/qwayland-qt-toplevel-drag-v1.h>
+
#include <QtCore/QMimeData>
#include <QtGui/QGuiApplication>
#include <QtGui/private/qguiapplication_p.h>
@@ -27,6 +29,8 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
+using namespace Qt::StringLiterals;
+
QWaylandDataDevice::QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWaylandInputDevice *inputDevice)
: QObject(inputDevice)
, QtWayland::wl_data_device(manager->get_data_device(inputDevice->wl_seat()))
@@ -105,14 +109,47 @@ bool QWaylandDataDevice::startDrag(QMimeData *mimeData, Qt::DropActions supporte
drag->setResponse(response);
}
});
- connect(m_dragSource.data(), &QWaylandDataSource::dndDropped, this, [](bool accepted, Qt::DropAction action) {
- QPlatformDropQtResponse response(accepted, action);
- static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setDropResponse(response);
- });
- connect(m_dragSource.data(), &QWaylandDataSource::finished, this, []() {
+ connect(m_dragSource.data(), &QWaylandDataSource::dndDropped, this,
+ [this](bool accepted, Qt::DropAction action) {
+ QPlatformDropQtResponse response(accepted, action);
+ if (m_toplevelDrag) {
+ // If the widget was dropped but the drag not accepted it
+ // should be its own window in the future. To distinguish
+ // from canceling mid-drag the drag is accepted here as the
+ // we know if the widget is over a zone where it can be
+ // incorporated or not
+ response = { accepted, Qt::MoveAction };
+ }
+ static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())
+ ->setDropResponse(response);
+ });
+ connect(m_dragSource.data(), &QWaylandDataSource::finished, this, [this]() {
static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag();
+ if (m_toplevelDrag) {
+ m_toplevelDrag->destroy();
+ m_toplevelDrag = nullptr;
+ }
});
+ if (mimeData->hasFormat("application/x-qt-mainwindowdrag-window"_L1)
+ && m_display->xdgToplevelDragManager()) {
+ qintptr dockWindowPtr;
+ QPoint offset;
+ QDataStream windowStream(mimeData->data("application/x-qt-mainwindowdrag-window"_L1));
+ windowStream >> dockWindowPtr;
+ QWindow *dockWindow = reinterpret_cast<QWindow *>(dockWindowPtr);
+ QDataStream offsetStream(mimeData->data("application/x-qt-mainwindowdrag-position"_L1));
+ offsetStream >> offset;
+ if (auto waylandWindow = static_cast<QWaylandWindow *>(dockWindow->handle())) {
+ if (auto toplevel = waylandWindow->surfaceRole<xdg_toplevel>()) {
+ m_toplevelDrag = new QtWayland::qt_toplevel_drag_v1(
+ m_display->xdgToplevelDragManager()->get_qt_toplevel_drag(
+ m_dragSource->object()));
+ m_toplevelDrag->attach(toplevel, offset.x(), offset.y());
+ }
+ }
+ }
+
start_drag(m_dragSource->object(), origin->wlSurface(), icon->wlSurface(), m_display->currentInputDevice()->serial());
return true;
}
@@ -148,7 +185,6 @@ void QWaylandDataDevice::data_device_drop()
QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(m_dragWindow, dragData, m_dragPoint, supportedActions,
QGuiApplication::mouseButtons(),
QGuiApplication::keyboardModifiers());
-
if (drag) {
auto drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag());
drag->setDropResponse(response);
@@ -175,16 +211,14 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface,
QDrag *drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->currentDrag();
if (drag) {
dragData = drag->mimeData();
- supportedActions = drag->supportedActions();
} else if (m_dragOffer) {
dragData = m_dragOffer->mimeData();
supportedActions = m_dragOffer->supportedActions();
}
- const QPlatformDragQtResponse &response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions,
- QGuiApplication::mouseButtons(),
- QGuiApplication::keyboardModifiers());
-
+ const QPlatformDragQtResponse &response = QWindowSystemInterface::handleDrag(
+ m_dragWindow, dragData, m_dragPoint, supportedActions, QGuiApplication::mouseButtons(),
+ QGuiApplication::keyboardModifiers());
if (drag) {
static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
}
@@ -263,6 +297,10 @@ void QWaylandDataDevice::dragSourceCancelled()
{
static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag();
m_dragSource.reset();
+ if (m_toplevelDrag) {
+ m_toplevelDrag->destroy();
+ m_toplevelDrag = nullptr;
+ }
}
QPoint QWaylandDataDevice::calculateDragPosition(int x, int y, QWindow *wnd) const