Introduce AbstractDropHandler

This abstract class represents an object that receives drag and drop
events.
This roughly maps to some of DataDevice's receiving methods, but by
being abstract
also allows us to use the same code from xwayland in a manner
transparent to all
code paths.

Preivous xwayland support with "proxy surfaces" have been removed.

--
In future it will be extended to have the mouse move events, so that we
can
avoid spying on the seat both in dataDevice and kwin's internal filter
This commit is contained in:
David Redondo 2021-09-03 14:43:06 +02:00 committed by David Edmundson
parent 0aaed33c66
commit efbe1c9664
8 changed files with 75 additions and 20 deletions

View file

@ -1,5 +1,6 @@
set(SERVER_LIB_SRCS
abstract_data_source.cpp
abstract_drop_handler.cpp
appmenu_interface.cpp
blur_interface.cpp
clientbuffer.cpp
@ -319,6 +320,7 @@ install(TARGETS KWaylandServer EXPORT KWaylandServerTargets ${KF5_INSTALL_TARGET
set(SERVER_LIB_HEADERS
${CMAKE_CURRENT_BINARY_DIR}/KWaylandServer/kwaylandserver_export.h
abstract_data_source.h
abstract_drop_handler.h
appmenu_interface.h
blur_interface.h
clientbuffer.h

View file

@ -0,0 +1,17 @@
/*
SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org>
SPDX-FileCopyrightText: 2021 David Redondo <kde@david-redondo.de>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "abstract_drop_handler.h"
namespace KWaylandServer
{
AbstractDropHandler::AbstractDropHandler(QObject *parent)
: QObject(parent)
{
}
}

View file

@ -0,0 +1,26 @@
/*
SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org>
SPDX-FileCopyrightText: 2021 David Redondo <kde@david-redondo.de>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#pragma once
#include <KWaylandServer/kwaylandserver_export.h>
#include <QObject>
namespace KWaylandServer
{
class SurfaceInterface;
class KWAYLANDSERVER_EXPORT AbstractDropHandler : public QObject
{
Q_OBJECT
public:
AbstractDropHandler(QObject *parent = nullptr);
virtual void updateDragTarget(SurfaceInterface *surface, quint32 serial) = 0;
virtual void drop() = 0;
};
}

View file

@ -91,10 +91,6 @@ void DataDeviceInterfacePrivate::data_device_start_drag(Resource *resource,
dataSource = DataSourceInterface::get(sourceResource);
}
if (proxyRemoteSurface) {
// origin is a proxy surface
focusSurface = proxyRemoteSurface.data();
}
const bool pointerGrab = seat->hasImplicitPointerGrab(serial) && seat->focusedPointerSurface() == focusSurface;
if (!pointerGrab) {
// Client doesn't have pointer grab.
@ -171,7 +167,7 @@ void DataDeviceInterfacePrivate::data_device_destroy_resource(QtWaylandServer::w
}
DataDeviceInterface::DataDeviceInterface(SeatInterface *seat, wl_resource *resource)
: QObject(nullptr)
: AbstractDropHandler(nullptr)
, d(new DataDeviceInterfacePrivate(seat, this, resource))
{
SeatInterfacePrivate *seatPrivate = SeatInterfacePrivate::get(seat);

View file

@ -11,6 +11,8 @@
#include <KWaylandServer/kwaylandserver_export.h>
#include "abstract_drop_handler.h"
struct wl_client;
struct wl_resource;
@ -65,7 +67,7 @@ private:
* @see SeatInterface
* @see DataSourceInterface
*/
class KWAYLANDSERVER_EXPORT DataDeviceInterface : public QObject
class KWAYLANDSERVER_EXPORT DataDeviceInterface : public AbstractDropHandler
{
Q_OBJECT
public:
@ -80,7 +82,7 @@ public:
/**
* The event is sent when a drag-and-drop operation is ended because the implicit grab is removed.
*/
void drop();
void drop() override;
/**
* Updates the SurfaceInterface to which drag motion events are sent.
*
@ -92,7 +94,7 @@ public:
* @param surface The SurfaceInterface which gets motion events
* @param serial The serial to be used for enter/leave
*/
void updateDragTarget(SurfaceInterface *surface, quint32 serial);
void updateDragTarget(SurfaceInterface *surface, quint32 serial) override;
void updateProxy(SurfaceInterface *remote);
wl_client *client();

View file

@ -189,6 +189,15 @@ void SeatInterfacePrivate::registerDataDevice(DataDeviceInterface *dataDevice)
}
}
KWaylandServer::AbstractDropHandler *SeatInterface::dropHandlerForSurface(SurfaceInterface *surface) const
{
auto list = d->dataDevicesForSurface(surface);
if (list.isEmpty()) {
return nullptr;
};
return list.first();
}
void SeatInterfacePrivate::registerDataControlDevice(DataControlDeviceV1Interface *dataDevice)
{
Q_ASSERT(dataDevice->seat() == q);
@ -275,7 +284,7 @@ void SeatInterfacePrivate::endDrag(quint32 serial)
{
QObject::disconnect(drag.dragSourceDestroyConnection);
DataDeviceInterface *dragTargetDevice = drag.target;
AbstractDropHandler *dragTargetDevice = drag.target.data();
AbstractDataSource *dragSource = drag.source;
if (dragSource) {
// TODO: Also check the current drag-and-drop action.
@ -487,7 +496,10 @@ void SeatInterface::setTimestamp(quint32 time)
Q_EMIT timestampChanged(time);
}
void SeatInterface::setDragTarget(SurfaceInterface *surface, const QPointF &globalPosition, const QMatrix4x4 &inputTransformation)
void SeatInterface::setDragTarget(AbstractDropHandler *dropTarget,
SurfaceInterface *surface,
const QPointF &globalPosition,
const QMatrix4x4 &inputTransformation)
{
if (surface == d->drag.surface) {
// no change
@ -501,10 +513,7 @@ void SeatInterface::setDragTarget(SurfaceInterface *surface, const QPointF &glob
// TODO: technically we can have mulitple data devices
// and we should send the drag to all of them, but that seems overly complicated
// in practice so far the only case for mulitple data devices is for clipboard overriding
d->drag.target = nullptr;
if (d->dataDevicesForSurface(surface).size() > 0) {
d->drag.target = d->dataDevicesForSurface(surface).first();
}
d->drag.target = dropTarget;
if (d->drag.mode == SeatInterfacePrivate::Drag::Mode::Pointer) {
notifyPointerMotion(globalPosition);
@ -523,13 +532,13 @@ void SeatInterface::setDragTarget(SurfaceInterface *surface, const QPointF &glob
return;
}
void SeatInterface::setDragTarget(SurfaceInterface *surface, const QMatrix4x4 &inputTransformation)
void SeatInterface::setDragTarget(AbstractDropHandler *target, SurfaceInterface *surface, const QMatrix4x4 &inputTransformation)
{
if (d->drag.mode == SeatInterfacePrivate::Drag::Mode::Pointer) {
setDragTarget(surface, pointerPos(), inputTransformation);
setDragTarget(target, surface, pointerPos(), inputTransformation);
} else {
Q_ASSERT(d->drag.mode == SeatInterfacePrivate::Drag::Mode::Touch);
setDragTarget(surface, d->globalTouch.focus.firstTouchPos, inputTransformation);
setDragTarget(target, surface, d->globalTouch.focus.firstTouchPos, inputTransformation);
}
}

View file

@ -18,6 +18,7 @@ struct wl_resource;
namespace KWaylandServer
{
class AbstractDataSource;
class AbstractDropHandler;
class DragAndDropIcon;
class DataDeviceInterface;
class Display;
@ -216,16 +217,18 @@ public:
* Sends a drag leave event to the current target and an enter event to @p surface.
* The enter position is derived from @p globalPosition and transformed by @p inputTransformation.
*/
void setDragTarget(SurfaceInterface *surface, const QPointF &globalPosition, const QMatrix4x4 &inputTransformation);
void setDragTarget(AbstractDropHandler *dropTarget, SurfaceInterface *surface, const QPointF &globalPosition, const QMatrix4x4 &inputTransformation);
/**
* Sets the current drag target to @p surface.
*
* Sends a drag leave event to the current target and an enter event to @p surface.
* The enter position is derived from current global position and transformed by @p inputTransformation.
*/
void setDragTarget(SurfaceInterface *surface, const QMatrix4x4 &inputTransformation = QMatrix4x4());
void setDragTarget(AbstractDropHandler *dropTarget, SurfaceInterface *surface, const QMatrix4x4 &inputTransformation = QMatrix4x4());
///@}
AbstractDropHandler *dropHandlerForSurface(SurfaceInterface *surface) const;
/**
* @name Pointer related methods
*/

View file

@ -123,7 +123,7 @@ public:
Mode mode = Mode::None;
AbstractDataSource *source = nullptr;
QPointer<SurfaceInterface> surface;
QPointer<DataDeviceInterface> target;
QPointer<AbstractDropHandler> target;
QPointer<DragAndDropIcon> dragIcon;
QMatrix4x4 transformation;
quint32 dragImplicitGrabSerial = -1;