Move drag logic to seat and introduce SeatInterface::startDrag
A dataDevice has a request to start a drag with multiple parameters. As kwayland's goal is to turn an event-driven API into a property cache API we store this data. This patch moves that storage to the Seat as properties of the active drag, rather than a property of the data device that happened to initialise it. This both helps keep a lot of other logic together, but also allows us to expose a public startDrag method that can be invoked from Kwin's internal surfaces or xwayland. Any properties in DataDevice now relate to data being dropped on the device.
This commit is contained in:
parent
ea65068fe0
commit
0aaed33c66
14 changed files with 119 additions and 183 deletions
|
@ -29,6 +29,11 @@ class KWAYLANDSERVER_EXPORT AbstractDataSource : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
virtual bool isAccepted() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void accept(const QString &mimeType)
|
||||
{
|
||||
Q_UNUSED(mimeType);
|
||||
|
|
|
@ -171,9 +171,6 @@ void TestDataDevice::testCreate()
|
|||
auto deviceInterface = dataDeviceCreatedSpy.first().first().value<DataDeviceInterface *>();
|
||||
QVERIFY(deviceInterface);
|
||||
QCOMPARE(deviceInterface->seat(), m_seatInterface);
|
||||
QVERIFY(!deviceInterface->dragSource());
|
||||
QVERIFY(!deviceInterface->origin());
|
||||
QVERIFY(!deviceInterface->icon());
|
||||
QVERIFY(!deviceInterface->selection());
|
||||
|
||||
// this will probably fail, we need to make a selection client side
|
||||
|
@ -269,9 +266,9 @@ void TestDataDevice::testDrag()
|
|||
dataDevice->startDrag(pointerButtonSerial, dataSource.data(), surface.data());
|
||||
QCOMPARE(dragStartedSpy.wait(500), success);
|
||||
QCOMPARE(!dragStartedSpy.isEmpty(), success);
|
||||
QCOMPARE(deviceInterface->dragSource(), success ? sourceInterface : nullptr);
|
||||
QCOMPARE(deviceInterface->origin(), success ? surfaceInterface : nullptr);
|
||||
QVERIFY(!deviceInterface->icon());
|
||||
QCOMPARE(m_seatInterface->dragSource(), success ? sourceInterface : nullptr);
|
||||
QCOMPARE(m_seatInterface->dragSurface(), success ? surfaceInterface : nullptr);
|
||||
QVERIFY(!m_seatInterface->dragIcon());
|
||||
}
|
||||
|
||||
void TestDataDevice::testDragInternally_data()
|
||||
|
@ -350,13 +347,13 @@ void TestDataDevice::testDragInternally()
|
|||
dataDevice->startDragInternally(pointerButtonSerial, surface.data(), iconSurface.data());
|
||||
QCOMPARE(dragStartedSpy.wait(500), success);
|
||||
QCOMPARE(!dragStartedSpy.isEmpty(), success);
|
||||
QVERIFY(!deviceInterface->dragSource());
|
||||
QCOMPARE(deviceInterface->origin(), success ? surfaceInterface : nullptr);
|
||||
QVERIFY(!m_seatInterface->dragSource());
|
||||
QCOMPARE(m_seatInterface->dragSurface(), success ? surfaceInterface : nullptr);
|
||||
|
||||
if (success) {
|
||||
QCOMPARE(deviceInterface->icon()->surface(), iconSurfaceInterface);
|
||||
QCOMPARE(m_seatInterface->dragIcon()->surface(), iconSurfaceInterface);
|
||||
} else {
|
||||
QCOMPARE(deviceInterface->icon(), nullptr);
|
||||
QCOMPARE(m_seatInterface->dragIcon(), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "../../src/server/datasource_interface.h"
|
||||
#include "../../src/server/display.h"
|
||||
#include "../../src/server/seat_interface.h"
|
||||
#include "../../src/server/seat_interface_p.h"
|
||||
#include "KWayland/Client/compositor.h"
|
||||
#include "KWayland/Client/connection_thread.h"
|
||||
#include "KWayland/Client/datadevice.h"
|
||||
|
@ -230,8 +231,8 @@ void TestDragAndDrop::testPointerDragAndDrop()
|
|||
QVERIFY(dragStartedSpy.wait());
|
||||
QCOMPARE(m_seatInterface->dragSurface(), serverSurface);
|
||||
QCOMPARE(m_seatInterface->dragSurfaceTransformation(), QMatrix4x4());
|
||||
QVERIFY(!m_seatInterface->dragSource()->icon());
|
||||
QCOMPARE(m_seatInterface->dragSource()->dragImplicitGrabSerial(), buttonPressSpy.first().first().value<quint32>());
|
||||
QVERIFY(!m_seatInterface->dragIcon());
|
||||
QCOMPARE(SeatInterfacePrivate::get(m_seatInterface)->drag.dragImplicitGrabSerial, buttonPressSpy.first().first().value<quint32>());
|
||||
QVERIFY(dragEnteredSpy.wait());
|
||||
QCOMPARE(dragEnteredSpy.count(), 1);
|
||||
QCOMPARE(dragEnteredSpy.first().first().value<quint32>(), m_display->serial());
|
||||
|
@ -333,8 +334,8 @@ void TestDragAndDrop::testTouchDragAndDrop()
|
|||
QVERIFY(dragStartedSpy.wait());
|
||||
QCOMPARE(m_seatInterface->dragSurface(), serverSurface);
|
||||
QCOMPARE(m_seatInterface->dragSurfaceTransformation(), QMatrix4x4());
|
||||
QVERIFY(!m_seatInterface->dragSource()->icon());
|
||||
QCOMPARE(m_seatInterface->dragSource()->dragImplicitGrabSerial(), tp->downSerial());
|
||||
QVERIFY(!m_seatInterface->dragIcon());
|
||||
QCOMPARE(SeatInterfacePrivate::get(m_seatInterface)->drag.dragImplicitGrabSerial, tp->downSerial());
|
||||
QVERIFY(dragEnteredSpy.wait());
|
||||
QCOMPARE(dragEnteredSpy.count(), 1);
|
||||
QCOMPARE(dragEnteredSpy.first().first().value<quint32>(), m_display->serial());
|
||||
|
@ -428,8 +429,8 @@ void TestDragAndDrop::testDragAndDropWithCancelByDestroyDataSource()
|
|||
QVERIFY(dragStartedSpy.wait());
|
||||
QCOMPARE(m_seatInterface->dragSurface(), serverSurface);
|
||||
QCOMPARE(m_seatInterface->dragSurfaceTransformation(), QMatrix4x4());
|
||||
QVERIFY(!m_seatInterface->dragSource()->icon());
|
||||
QCOMPARE(m_seatInterface->dragSource()->dragImplicitGrabSerial(), buttonPressSpy.first().first().value<quint32>());
|
||||
QVERIFY(!m_seatInterface->dragIcon());
|
||||
QCOMPARE(SeatInterfacePrivate::get(m_seatInterface)->drag.dragImplicitGrabSerial, buttonPressSpy.first().first().value<quint32>());
|
||||
QVERIFY(dragEnteredSpy.wait());
|
||||
QCOMPARE(dragEnteredSpy.count(), 1);
|
||||
QCOMPARE(dragEnteredSpy.first().first().value<quint32>(), m_display->serial());
|
||||
|
|
|
@ -39,8 +39,8 @@ void DragAndDropIconPrivate::commit()
|
|||
position += surface()->offset();
|
||||
}
|
||||
|
||||
DragAndDropIcon::DragAndDropIcon(SurfaceInterface *surface, QObject *parent)
|
||||
: QObject(parent)
|
||||
DragAndDropIcon::DragAndDropIcon(SurfaceInterface *surface)
|
||||
: QObject(surface)
|
||||
, d(new DragAndDropIconPrivate(surface))
|
||||
{
|
||||
}
|
||||
|
@ -71,11 +71,6 @@ DataDeviceInterfacePrivate::DataDeviceInterfacePrivate(SeatInterface *seat, Data
|
|||
{
|
||||
}
|
||||
|
||||
void DataDeviceInterfacePrivate::endDrag()
|
||||
{
|
||||
icon.reset();
|
||||
}
|
||||
|
||||
void DataDeviceInterfacePrivate::data_device_start_drag(Resource *resource,
|
||||
wl_resource *sourceResource,
|
||||
wl_resource *originResource,
|
||||
|
@ -109,22 +104,14 @@ void DataDeviceInterfacePrivate::data_device_start_drag(Resource *resource,
|
|||
return;
|
||||
}
|
||||
}
|
||||
// TODO: source is allowed to be null, handled client internally!
|
||||
source = dataSource;
|
||||
if (dataSource) {
|
||||
QObject::connect(dataSource, &AbstractDataSource::aboutToBeDestroyed, q, [this] {
|
||||
source = nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
DragAndDropIcon *dragIcon = nullptr;
|
||||
if (iconSurface) {
|
||||
icon.reset(new DragAndDropIcon(iconSurface));
|
||||
QObject::connect(iconSurface, &SurfaceInterface::aboutToBeDestroyed, icon.data(), [this] {
|
||||
icon.reset();
|
||||
});
|
||||
// drag icon lifespan is mapped to surface lifespan
|
||||
dragIcon = new DragAndDropIcon(iconSurface);
|
||||
}
|
||||
surface = focusSurface;
|
||||
drag.serial = serial;
|
||||
Q_EMIT q->dragStarted();
|
||||
Q_EMIT q->dragStarted(dataSource, focusSurface, serial, dragIcon);
|
||||
}
|
||||
|
||||
void DataDeviceInterfacePrivate::data_device_set_selection(Resource *resource, wl_resource *source, uint32_t serial)
|
||||
|
@ -198,21 +185,6 @@ SeatInterface *DataDeviceInterface::seat() const
|
|||
return d->seat;
|
||||
}
|
||||
|
||||
DataSourceInterface *DataDeviceInterface::dragSource() const
|
||||
{
|
||||
return d->source;
|
||||
}
|
||||
|
||||
DragAndDropIcon *DataDeviceInterface::icon() const
|
||||
{
|
||||
return d->icon.data();
|
||||
}
|
||||
|
||||
SurfaceInterface *DataDeviceInterface::origin() const
|
||||
{
|
||||
return d->proxyRemoteSurface ? d->proxyRemoteSurface.data() : d->surface;
|
||||
}
|
||||
|
||||
DataSourceInterface *DataDeviceInterface::selection() const
|
||||
{
|
||||
return d->selection;
|
||||
|
@ -267,23 +239,18 @@ void DataDeviceInterface::updateDragTarget(SurfaceInterface *surface, quint32 se
|
|||
}
|
||||
// don't update serial, we need it
|
||||
}
|
||||
auto dragSourceDevice = d->seat->dragSource();
|
||||
if (!surface || !dragSourceDevice) {
|
||||
if (auto s = dragSourceDevice->dragSource()) {
|
||||
auto dragSource = d->seat->dragSource();
|
||||
if (!surface || !dragSource) {
|
||||
if (auto s = dragSource) {
|
||||
s->dndAction(DataDeviceManagerInterface::DnDAction::None);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (d->proxyRemoteSurface && d->proxyRemoteSurface == surface) {
|
||||
// A proxy can not have the remote surface as target.
|
||||
// TODO: do this for all client's surfaces?
|
||||
return;
|
||||
|
||||
if (dragSource) {
|
||||
dragSource->accept(QString());
|
||||
}
|
||||
auto *source = dragSourceDevice->dragSource();
|
||||
if (source) {
|
||||
source->setAccepted(false);
|
||||
}
|
||||
DataOfferInterface *offer = d->createDataOffer(source);
|
||||
DataOfferInterface *offer = d->createDataOffer(dragSource);
|
||||
d->drag.surface = surface;
|
||||
if (d->seat->isDragPointer()) {
|
||||
d->drag.posConnection = connect(d->seat, &SeatInterface::pointerPosChanged, this, [this] {
|
||||
|
@ -314,35 +281,30 @@ void DataDeviceInterface::updateDragTarget(SurfaceInterface *surface, quint32 se
|
|||
d->send_enter(serial, surface->resource(), wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()), offer ? offer->resource() : nullptr);
|
||||
if (offer) {
|
||||
offer->sendSourceActions();
|
||||
auto matchOffers = [source, offer] {
|
||||
auto matchOffers = [dragSource, offer] {
|
||||
DataDeviceManagerInterface::DnDAction action{DataDeviceManagerInterface::DnDAction::None};
|
||||
if (source->supportedDragAndDropActions().testFlag(offer->preferredDragAndDropAction())) {
|
||||
if (dragSource->supportedDragAndDropActions().testFlag(offer->preferredDragAndDropAction())) {
|
||||
action = offer->preferredDragAndDropAction();
|
||||
} else {
|
||||
if (source->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Copy)
|
||||
if (dragSource->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Copy)
|
||||
&& offer->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Copy)) {
|
||||
action = DataDeviceManagerInterface::DnDAction::Copy;
|
||||
} else if (source->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Move)
|
||||
} else if (dragSource->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Move)
|
||||
&& offer->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Move)) {
|
||||
action = DataDeviceManagerInterface::DnDAction::Move;
|
||||
} else if (source->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Ask)
|
||||
} else if (dragSource->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Ask)
|
||||
&& offer->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Ask)) {
|
||||
action = DataDeviceManagerInterface::DnDAction::Ask;
|
||||
}
|
||||
}
|
||||
offer->dndAction(action);
|
||||
source->dndAction(action);
|
||||
dragSource->dndAction(action);
|
||||
};
|
||||
d->drag.targetActionConnection = connect(offer, &DataOfferInterface::dragAndDropActionsChanged, source, matchOffers);
|
||||
d->drag.sourceActionConnection = connect(source, &DataSourceInterface::supportedDragAndDropActionsChanged, source, matchOffers);
|
||||
d->drag.targetActionConnection = connect(offer, &DataOfferInterface::dragAndDropActionsChanged, dragSource, matchOffers);
|
||||
d->drag.sourceActionConnection = connect(dragSource, &AbstractDataSource::supportedDragAndDropActionsChanged, dragSource, matchOffers);
|
||||
}
|
||||
}
|
||||
|
||||
quint32 DataDeviceInterface::dragImplicitGrabSerial() const
|
||||
{
|
||||
return d->drag.serial;
|
||||
}
|
||||
|
||||
void DataDeviceInterface::updateProxy(SurfaceInterface *remote)
|
||||
{
|
||||
// TODO: connect destroy signal?
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
SurfaceInterface *surface() const;
|
||||
|
||||
private:
|
||||
explicit DragAndDropIcon(SurfaceInterface *surface, QObject *parent = nullptr);
|
||||
explicit DragAndDropIcon(SurfaceInterface *surface);
|
||||
friend class DataDeviceInterfacePrivate;
|
||||
QScopedPointer<DragAndDropIconPrivate> d;
|
||||
};
|
||||
|
@ -72,18 +72,6 @@ public:
|
|||
virtual ~DataDeviceInterface();
|
||||
|
||||
SeatInterface *seat() const;
|
||||
DataSourceInterface *dragSource() const;
|
||||
SurfaceInterface *origin() const;
|
||||
/**
|
||||
* Returns the additional icon attached to the cursor during a drag-and-drop operation.
|
||||
* This function returns @c null if no drag-and-drop icon has been attached.
|
||||
*/
|
||||
DragAndDropIcon *icon() const;
|
||||
|
||||
/**
|
||||
* @returns the serial of the implicit grab which started the drag
|
||||
*/
|
||||
quint32 dragImplicitGrabSerial() const;
|
||||
|
||||
DataSourceInterface *selection() const;
|
||||
|
||||
|
@ -105,16 +93,13 @@ public:
|
|||
* @param serial The serial to be used for enter/leave
|
||||
*/
|
||||
void updateDragTarget(SurfaceInterface *surface, quint32 serial);
|
||||
/**
|
||||
* Mark this DataDeviceInterface as being a proxy device for @p remote.
|
||||
*/
|
||||
void updateProxy(SurfaceInterface *remote);
|
||||
|
||||
wl_client *client();
|
||||
|
||||
Q_SIGNALS:
|
||||
void aboutToBeDestroyed();
|
||||
void dragStarted();
|
||||
void dragStarted(AbstractDataSource *source, SurfaceInterface *originSurface, quint32 serial, DragAndDropIcon *dragIcon);
|
||||
void selectionChanged(KWaylandServer::DataSourceInterface *);
|
||||
void selectionCleared();
|
||||
|
||||
|
|
|
@ -29,13 +29,9 @@ public:
|
|||
DataDeviceInterfacePrivate(SeatInterface *seat, DataDeviceInterface *_q, wl_resource *resource);
|
||||
|
||||
DataOfferInterface *createDataOffer(AbstractDataSource *source);
|
||||
void endDrag();
|
||||
|
||||
SeatInterface *seat;
|
||||
DataDeviceInterface *q;
|
||||
DataSourceInterface *source = nullptr;
|
||||
SurfaceInterface *surface = nullptr;
|
||||
QScopedPointer<DragAndDropIcon> icon;
|
||||
QPointer<DataSourceInterface> selection;
|
||||
QPointer<SurfaceInterface> proxyRemoteSurface;
|
||||
|
||||
|
|
|
@ -118,7 +118,9 @@ void DataSourceInterface::requestData(const QString &mimeType, qint32 fd)
|
|||
|
||||
void DataSourceInterface::cancel()
|
||||
{
|
||||
d->send_cancelled();
|
||||
if (wl_resource_get_version(resource()) >= WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) {
|
||||
d->send_cancelled();
|
||||
}
|
||||
}
|
||||
|
||||
QStringList DataSourceInterface::mimeTypes() const
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
|
||||
wl_client *client() const override;
|
||||
|
||||
bool isAccepted() const;
|
||||
bool isAccepted() const override;
|
||||
void setAccepted(bool accepted);
|
||||
|
||||
private:
|
||||
|
|
|
@ -171,42 +171,12 @@ void SeatInterfacePrivate::registerDataDevice(DataDeviceInterface *dataDevice)
|
|||
QObject::connect(dataDevice, &DataDeviceInterface::selectionCleared, q, [this, dataDevice] {
|
||||
updateSelection(dataDevice);
|
||||
});
|
||||
QObject::connect(dataDevice, &DataDeviceInterface::dragStarted, q, [this, dataDevice] {
|
||||
const auto dragSerial = dataDevice->dragImplicitGrabSerial();
|
||||
if (q->hasImplicitPointerGrab(dragSerial)) {
|
||||
drag.mode = Drag::Mode::Pointer;
|
||||
drag.transformation = globalPointer.focus.transformation;
|
||||
} else if (q->hasImplicitTouchGrab(dragSerial)) {
|
||||
drag.mode = Drag::Mode::Touch;
|
||||
// TODO: touch transformation
|
||||
} else {
|
||||
// no implicit grab, abort drag
|
||||
return;
|
||||
}
|
||||
auto *originSurface = dataDevice->origin();
|
||||
const bool proxied = originSurface->dataProxy();
|
||||
if (!proxied) {
|
||||
// origin surface
|
||||
drag.target = dataDevice;
|
||||
drag.surface = originSurface;
|
||||
// TODO: transformation needs to be either pointer or touch
|
||||
drag.transformation = globalPointer.focus.transformation;
|
||||
}
|
||||
drag.source = dataDevice;
|
||||
drag.destroyConnection = QObject::connect(dataDevice, &DataDeviceInterface::aboutToBeDestroyed, q, [this] {
|
||||
cancelDrag(display->nextSerial());
|
||||
});
|
||||
if (dataDevice->dragSource()) {
|
||||
drag.dragSourceDestroyConnection = QObject::connect(dataDevice->dragSource(), &AbstractDataSource::aboutToBeDestroyed, q, [this] {
|
||||
cancelDrag(display->nextSerial());
|
||||
});
|
||||
} else {
|
||||
drag.dragSourceDestroyConnection = QMetaObject::Connection();
|
||||
}
|
||||
dataDevice->updateDragTarget(proxied ? nullptr : originSurface, dataDevice->dragImplicitGrabSerial());
|
||||
Q_EMIT q->dragStarted();
|
||||
Q_EMIT q->dragSurfaceChanged();
|
||||
});
|
||||
QObject::connect(dataDevice,
|
||||
&DataDeviceInterface::dragStarted,
|
||||
q,
|
||||
[this](AbstractDataSource *source, SurfaceInterface *origin, quint32 serial, DragAndDropIcon *dragIcon) {
|
||||
q->startDrag(source, origin, serial, dragIcon);
|
||||
});
|
||||
// is the new DataDevice for the current keyoard focus?
|
||||
if (globalKeyboard.focus.surface) {
|
||||
// same client?
|
||||
|
@ -303,12 +273,10 @@ void SeatInterfacePrivate::cancelDrag(quint32 serial)
|
|||
|
||||
void SeatInterfacePrivate::endDrag(quint32 serial)
|
||||
{
|
||||
QObject::disconnect(drag.destroyConnection);
|
||||
QObject::disconnect(drag.dragSourceDestroyConnection);
|
||||
|
||||
DataDeviceInterface *dragTargetDevice = drag.target;
|
||||
DataDeviceInterface *dragSourceDevice = drag.source;
|
||||
DataSourceInterface *dragSource = dragSourceDevice ? dragSourceDevice->dragSource() : nullptr;
|
||||
AbstractDataSource *dragSource = drag.source;
|
||||
if (dragSource) {
|
||||
// TODO: Also check the current drag-and-drop action.
|
||||
if (dragTargetDevice && dragSource->isAccepted()) {
|
||||
|
@ -316,19 +284,13 @@ void SeatInterfacePrivate::endDrag(quint32 serial)
|
|||
dragTargetDevice->drop();
|
||||
dragSource->dropPerformed();
|
||||
} else {
|
||||
if (wl_resource_get_version(dragSource->resource()) >= WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) {
|
||||
dragSource->cancel();
|
||||
}
|
||||
dragSource->cancel();
|
||||
}
|
||||
}
|
||||
|
||||
if (dragTargetDevice) {
|
||||
dragTargetDevice->updateDragTarget(nullptr, serial);
|
||||
}
|
||||
if (dragSourceDevice) {
|
||||
auto devicePrivate = DataDeviceInterfacePrivate::get(dragSourceDevice);
|
||||
devicePrivate->endDrag();
|
||||
}
|
||||
|
||||
drag = Drag();
|
||||
Q_EMIT q->dragSurfaceChanged();
|
||||
|
@ -486,12 +448,10 @@ void SeatInterface::notifyPointerMotion(const QPointF &pos)
|
|||
return;
|
||||
}
|
||||
if (isDragPointer()) {
|
||||
const auto *originSurface = dragSource()->origin();
|
||||
const bool proxyRemoteFocused = originSurface->dataProxy() && originSurface == focusedSurface;
|
||||
if (!proxyRemoteFocused) {
|
||||
// handled by DataDevice
|
||||
// data device will handle it directly
|
||||
// for xwayland cases we still want to send pointer events
|
||||
if (!d->dataDevicesForSurface(focusedSurface).isEmpty())
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (focusedSurface->lockedPointer() && focusedSurface->lockedPointer()->isLocked()) {
|
||||
return;
|
||||
|
@ -743,7 +703,7 @@ void SeatInterface::notifyPointerButton(quint32 button, PointerButtonState state
|
|||
d->updatePointerButtonSerial(button, serial);
|
||||
d->updatePointerButtonState(button, SeatInterfacePrivate::Pointer::State::Released);
|
||||
if (d->drag.mode == SeatInterfacePrivate::Drag::Mode::Pointer) {
|
||||
if (d->drag.source->dragImplicitGrabSerial() != currentButtonSerial) {
|
||||
if (d->drag.dragImplicitGrabSerial != currentButtonSerial) {
|
||||
// not our drag button - ignore
|
||||
return;
|
||||
}
|
||||
|
@ -1100,7 +1060,7 @@ void SeatInterface::notifyTouchUp(qint32 id)
|
|||
}
|
||||
Q_ASSERT(d->globalTouch.ids.contains(id));
|
||||
const qint32 serial = d->display->nextSerial();
|
||||
if (d->drag.mode == SeatInterfacePrivate::Drag::Mode::Touch && d->drag.source->dragImplicitGrabSerial() == d->globalTouch.ids.value(id)) {
|
||||
if (d->drag.mode == SeatInterfacePrivate::Drag::Mode::Touch && d->drag.dragImplicitGrabSerial == d->globalTouch.ids.value(id)) {
|
||||
// the implicitly grabbing touch point has been upped
|
||||
d->endDrag(serial);
|
||||
}
|
||||
|
@ -1174,7 +1134,7 @@ SurfaceInterface *SeatInterface::dragSurface() const
|
|||
return d->drag.surface;
|
||||
}
|
||||
|
||||
DataDeviceInterface *SeatInterface::dragSource() const
|
||||
AbstractDataSource *SeatInterface::dragSource() const
|
||||
{
|
||||
return d->drag.source;
|
||||
}
|
||||
|
@ -1305,4 +1265,45 @@ void SeatInterface::setPrimarySelection(AbstractDataSource *selection)
|
|||
Q_EMIT primarySelectionChanged(selection);
|
||||
}
|
||||
|
||||
void SeatInterface::startDrag(AbstractDataSource *dragSource, SurfaceInterface *originSurface, int dragSerial, DragAndDropIcon *dragIcon)
|
||||
{
|
||||
if (hasImplicitPointerGrab(dragSerial)) {
|
||||
d->drag.mode = SeatInterfacePrivate::Drag::Mode::Pointer;
|
||||
d->drag.transformation = d->globalPointer.focus.transformation;
|
||||
} else if (hasImplicitTouchGrab(dragSerial)) {
|
||||
d->drag.mode = SeatInterfacePrivate::Drag::Mode::Touch;
|
||||
// TODO: touch transformation
|
||||
} else {
|
||||
// no implicit grab, abort drag
|
||||
return;
|
||||
}
|
||||
d->drag.dragImplicitGrabSerial = dragSerial;
|
||||
|
||||
// set initial drag target to ourself
|
||||
d->drag.surface = originSurface;
|
||||
// TODO: transformation needs to be either pointer or touch
|
||||
d->drag.transformation = d->globalPointer.focus.transformation;
|
||||
|
||||
d->drag.source = dragSource;
|
||||
if (dragSource) {
|
||||
d->drag.dragSourceDestroyConnection = QObject::connect(dragSource, &AbstractDataSource::aboutToBeDestroyed, this, [this] {
|
||||
d->cancelDrag(d->display->nextSerial());
|
||||
});
|
||||
}
|
||||
d->drag.dragIcon = dragIcon;
|
||||
|
||||
if (!d->dataDevicesForSurface(originSurface).isEmpty()) {
|
||||
d->drag.target = d->dataDevicesForSurface(originSurface)[0];
|
||||
}
|
||||
if (d->drag.target) {
|
||||
d->drag.target->updateDragTarget(originSurface, dragSerial);
|
||||
}
|
||||
Q_EMIT dragStarted();
|
||||
Q_EMIT dragSurfaceChanged();
|
||||
}
|
||||
|
||||
DragAndDropIcon *SeatInterface::dragIcon() const
|
||||
{
|
||||
return d->drag.dragIcon;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ struct wl_resource;
|
|||
namespace KWaylandServer
|
||||
{
|
||||
class AbstractDataSource;
|
||||
class DragAndDropIcon;
|
||||
class DataDeviceInterface;
|
||||
class Display;
|
||||
class KeyboardInterface;
|
||||
|
@ -208,7 +209,7 @@ public:
|
|||
* @returns The DataDeviceInterface which started the drag and drop operation.
|
||||
* @see isDrag
|
||||
*/
|
||||
DataDeviceInterface *dragSource() const;
|
||||
KWaylandServer::AbstractDataSource *dragSource() const;
|
||||
/**
|
||||
* Sets the current drag target to @p surface.
|
||||
*
|
||||
|
@ -618,6 +619,14 @@ public:
|
|||
KWaylandServer::AbstractDataSource *primarySelection() const;
|
||||
void setPrimarySelection(AbstractDataSource *selection);
|
||||
|
||||
void startDrag(AbstractDataSource *source, SurfaceInterface *sourceSurface, int dragSerial = -1, DragAndDropIcon *dragIcon = nullptr);
|
||||
|
||||
/**
|
||||
* Returns the additional icon attached to the cursor during a drag-and-drop operation.
|
||||
* This function returns @c null if no drag-and-drop is active or no icon has been attached.
|
||||
*/
|
||||
DragAndDropIcon *dragIcon() const;
|
||||
|
||||
static SeatInterface *get(wl_resource *native);
|
||||
|
||||
Q_SIGNALS:
|
||||
|
|
|
@ -25,11 +25,13 @@ class DataControlDeviceV1Interface;
|
|||
class TextInputV2Interface;
|
||||
class TextInputV3Interface;
|
||||
class PrimarySelectionDeviceV1Interface;
|
||||
class DragAndDropIcon;
|
||||
|
||||
class SeatInterfacePrivate : public QtWaylandServer::wl_seat
|
||||
{
|
||||
public:
|
||||
static SeatInterfacePrivate *get(SeatInterface *seat);
|
||||
// exported for unit tests
|
||||
KWAYLANDSERVER_EXPORT static SeatInterfacePrivate *get(SeatInterface *seat);
|
||||
SeatInterfacePrivate(SeatInterface *q, Display *display);
|
||||
|
||||
void sendCapabilities();
|
||||
|
@ -119,11 +121,12 @@ public:
|
|||
Touch,
|
||||
};
|
||||
Mode mode = Mode::None;
|
||||
DataDeviceInterface *source = nullptr;
|
||||
AbstractDataSource *source = nullptr;
|
||||
QPointer<SurfaceInterface> surface;
|
||||
QPointer<DataDeviceInterface> target;
|
||||
SurfaceInterface *surface = nullptr;
|
||||
QPointer<DragAndDropIcon> dragIcon;
|
||||
QMatrix4x4 transformation;
|
||||
QMetaObject::Connection destroyConnection;
|
||||
quint32 dragImplicitGrabSerial = -1;
|
||||
QMetaObject::Connection dragSourceDestroyConnection;
|
||||
};
|
||||
Drag drag;
|
||||
|
|
|
@ -936,16 +936,6 @@ bool SurfaceInterface::inhibitsIdle() const
|
|||
return !d->idleInhibitors.isEmpty();
|
||||
}
|
||||
|
||||
void SurfaceInterface::setDataProxy(SurfaceInterface *surface)
|
||||
{
|
||||
d->dataProxy = surface;
|
||||
}
|
||||
|
||||
SurfaceInterface *SurfaceInterface::dataProxy() const
|
||||
{
|
||||
return d->dataProxy;
|
||||
}
|
||||
|
||||
QPointF SurfaceInterface::mapToBuffer(const QPointF &point) const
|
||||
{
|
||||
return d->surfaceToBufferMatrix.map(point);
|
||||
|
|
|
@ -310,20 +310,6 @@ public:
|
|||
*/
|
||||
static SurfaceInterface *get(quint32 id, const ClientConnection *client);
|
||||
|
||||
/**
|
||||
* Set @p surface as a data proxy for this SurfaceInterface. This enables
|
||||
* the proxy to conduct drags on the surface's client behalf.
|
||||
*
|
||||
* Setting a data proxy is only allowed when the client owning this surface
|
||||
* has not created a data device itself.
|
||||
*/
|
||||
void setDataProxy(SurfaceInterface *surface);
|
||||
/**
|
||||
* Returns the data proxy of this SurfaceInterface or null if there
|
||||
* is none set.
|
||||
*/
|
||||
SurfaceInterface *dataProxy() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* This signal is emitted when the underlying wl_surface resource is about to be freed.
|
||||
|
|
|
@ -119,7 +119,6 @@ public:
|
|||
|
||||
QVector<IdleInhibitorV1Interface *> idleInhibitors;
|
||||
ViewportInterface *viewportExtension = nullptr;
|
||||
SurfaceInterface *dataProxy = nullptr;
|
||||
ClientConnection *client = nullptr;
|
||||
|
||||
protected:
|
||||
|
|
Loading…
Reference in a new issue