File indexing completed on 2024-11-10 04:57:38

0001 /*
0002     SPDX-FileCopyrightText: 2023 David Redondo <kde@david-redondo.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "xdgtopleveldrag_v1.h"
0008 #include "dataoffer.h"
0009 #include "datasource.h"
0010 #include "datasource_p.h"
0011 #include "display.h"
0012 #include "surface.h"
0013 #include "utils/resource.h"
0014 #include "xdgshell.h"
0015 
0016 #include <qwayland-server-xdg-toplevel-drag-v1.h>
0017 
0018 #include <QPointer>
0019 
0020 #include <memory>
0021 
0022 namespace KWin
0023 {
0024 constexpr int version = 1;
0025 
0026 class XdgToplevelDragV1InterfacePrivate : public QtWaylandServer::xdg_toplevel_drag_v1
0027 {
0028 public:
0029     XdgToplevelDragV1InterfacePrivate(wl_resource *resource, XdgToplevelDragV1Interface *q)
0030         : xdg_toplevel_drag_v1(resource)
0031         , q(q)
0032     {
0033     }
0034     XdgToplevelDragV1Interface *q;
0035     QPointer<DataSourceInterface> dataSource;
0036     QPointer<XdgToplevelInterface> toplevel;
0037     QPoint pos;
0038 
0039 private:
0040     void xdg_toplevel_drag_v1_attach(Resource *resource, wl_resource *toplevelResource, int32_t x_offset, int32_t y_offset) override
0041     {
0042         if (toplevel) {
0043             wl_resource_post_error(resource->handle, error_toplevel_attached, "Valid toplevel already attached");
0044             return;
0045         }
0046         toplevel = XdgToplevelInterface::get(toplevelResource);
0047         QObject::connect(toplevel, &XdgToplevelInterface::resetOccurred, q, [this] {
0048             toplevel = nullptr;
0049         });
0050         pos = QPoint(x_offset, y_offset);
0051         Q_EMIT q->toplevelChanged();
0052     }
0053 
0054     void xdg_toplevel_drag_v1_destroy_resource(Resource *resource) override
0055     {
0056         delete q;
0057     }
0058     void xdg_toplevel_drag_v1_destroy(Resource *resource) override
0059     {
0060         if (!dataSource || dataSource->isDndCancelled() || dataSource->isDropPerformed()) {
0061             wl_resource_destroy(resource->handle);
0062             return;
0063         }
0064         wl_resource_post_error(resource->handle, error_ongoing_drag, "Drag has not ended");
0065     }
0066 };
0067 
0068 XdgToplevelDragV1Interface::XdgToplevelDragV1Interface(wl_resource *resource, DataSourceInterface *dataSource)
0069     : d(std::make_unique<XdgToplevelDragV1InterfacePrivate>(resource, this))
0070 {
0071     d->dataSource = dataSource;
0072     DataSourceInterfacePrivate::get(dataSource)->xdgToplevelDrag = this;
0073 }
0074 
0075 XdgToplevelDragV1Interface::~XdgToplevelDragV1Interface()
0076 {
0077     if (d->dataSource) {
0078         DataSourceInterfacePrivate::get(d->dataSource)->xdgToplevelDrag = nullptr;
0079     }
0080 }
0081 
0082 XdgToplevelInterface *XdgToplevelDragV1Interface::toplevel() const
0083 {
0084     return d->toplevel;
0085 }
0086 
0087 QPoint XdgToplevelDragV1Interface::offset() const
0088 {
0089     return d->pos;
0090 }
0091 
0092 class XdgToplevelDragManagerV1InterfacePrivate : public QtWaylandServer::xdg_toplevel_drag_manager_v1
0093 {
0094 public:
0095     XdgToplevelDragManagerV1InterfacePrivate(XdgToplevelDragManagerV1Interface *q, Display *display)
0096         : xdg_toplevel_drag_manager_v1(*display, version)
0097         , q(q)
0098     {
0099     }
0100 
0101 protected:
0102     void xdg_toplevel_drag_manager_v1_destroy(Resource *resource) override
0103     {
0104         wl_resource_destroy(resource->handle);
0105     }
0106 
0107     void xdg_toplevel_drag_manager_v1_get_xdg_toplevel_drag(Resource *resource, uint32_t id, wl_resource *data_source) override
0108     {
0109         auto dataSource = DataSourceInterface::get(data_source);
0110 
0111         wl_resource *xdg_toplevel_drag = wl_resource_create(resource->client(), &xdg_toplevel_drag_v1_interface, resource->version(), id);
0112         if (!xdg_toplevel_drag) {
0113             wl_resource_post_no_memory(resource->handle);
0114             return;
0115         }
0116         new XdgToplevelDragV1Interface(xdg_toplevel_drag, dataSource);
0117     }
0118 
0119     XdgToplevelDragManagerV1Interface *q;
0120 };
0121 
0122 XdgToplevelDragManagerV1Interface::XdgToplevelDragManagerV1Interface(Display *display, QObject *parent)
0123     : QObject(parent)
0124     , d(std::make_unique<XdgToplevelDragManagerV1InterfacePrivate>(this, display))
0125 {
0126 }
0127 
0128 XdgToplevelDragManagerV1Interface::~XdgToplevelDragManagerV1Interface() = default;
0129 }
0130 
0131 #include "moc_xdgtopleveldrag_v1.cpp"