File indexing completed on 2024-05-19 05:32:33

0001 /*
0002     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
0003     SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006 */
0007 #include "datasource.h"
0008 #include "clientconnection.h"
0009 #include "datadevicemanager.h"
0010 #include "datasource_p.h"
0011 #include "utils/resource.h"
0012 // Qt
0013 #include <QStringList>
0014 // Wayland
0015 #include <qwayland-server-wayland.h>
0016 // system
0017 #include <unistd.h>
0018 
0019 namespace KWin
0020 {
0021 DataSourceInterfacePrivate::DataSourceInterfacePrivate(DataSourceInterface *_q, ::wl_resource *resource)
0022     : QtWaylandServer::wl_data_source(resource)
0023     , q(_q)
0024 {
0025 }
0026 
0027 void DataSourceInterfacePrivate::data_source_destroy_resource(Resource *resource)
0028 {
0029     Q_EMIT q->aboutToBeDestroyed();
0030     delete q;
0031 }
0032 
0033 void DataSourceInterfacePrivate::data_source_offer(QtWaylandServer::wl_data_source::Resource *resource, const QString &mime_type)
0034 {
0035     mimeTypes << mime_type;
0036     Q_EMIT q->mimeTypeOffered(mime_type);
0037 }
0038 
0039 void DataSourceInterfacePrivate::data_source_destroy(QtWaylandServer::wl_data_source::Resource *resource)
0040 {
0041     wl_resource_destroy(resource->handle);
0042 }
0043 
0044 void DataSourceInterfacePrivate::offer(const QString &mimeType)
0045 {
0046     mimeTypes << mimeType;
0047     Q_EMIT q->mimeTypeOffered(mimeType);
0048 }
0049 
0050 void DataSourceInterfacePrivate::data_source_set_actions(Resource *resource, uint32_t dnd_actions)
0051 {
0052     // verify that the no other actions are sent
0053     if (dnd_actions
0054         & ~(QtWaylandServer::wl_data_device_manager::dnd_action_copy | QtWaylandServer::wl_data_device_manager::dnd_action_move
0055             | QtWaylandServer::wl_data_device_manager::dnd_action_ask)) {
0056         wl_resource_post_error(resource->handle, error_invalid_action_mask, "Invalid action mask");
0057         return;
0058     }
0059     DataDeviceManagerInterface::DnDActions supportedActions;
0060     if (dnd_actions & QtWaylandServer::wl_data_device_manager::dnd_action_copy) {
0061         supportedActions |= DataDeviceManagerInterface::DnDAction::Copy;
0062     }
0063     if (dnd_actions & QtWaylandServer::wl_data_device_manager::dnd_action_move) {
0064         supportedActions |= DataDeviceManagerInterface::DnDAction::Move;
0065     }
0066     if (dnd_actions & QtWaylandServer::wl_data_device_manager::dnd_action_ask) {
0067         supportedActions |= DataDeviceManagerInterface::DnDAction::Ask;
0068     }
0069     if (supportedDnDActions != supportedActions) {
0070         supportedDnDActions = supportedActions;
0071         Q_EMIT q->supportedDragAndDropActionsChanged();
0072     }
0073 }
0074 
0075 DataSourceInterfacePrivate *DataSourceInterfacePrivate::get(DataSourceInterface *dataSource)
0076 {
0077     return dataSource->d.get();
0078 }
0079 
0080 DataSourceInterface::DataSourceInterface(wl_resource *resource)
0081     : d(new DataSourceInterfacePrivate(this, resource))
0082 {
0083     if (d->resource()->version() < WL_DATA_SOURCE_ACTION_SINCE_VERSION) {
0084         d->supportedDnDActions = DataDeviceManagerInterface::DnDAction::Copy;
0085     }
0086 }
0087 
0088 DataSourceInterface::~DataSourceInterface() = default;
0089 
0090 void DataSourceInterface::accept(const QString &mimeType)
0091 {
0092     d->send_target(mimeType);
0093     d->isAccepted = !mimeType.isNull();
0094 }
0095 
0096 void DataSourceInterface::requestData(const QString &mimeType, qint32 fd)
0097 {
0098     d->send_send(mimeType, int32_t(fd));
0099     close(fd);
0100 }
0101 
0102 void DataSourceInterface::cancel()
0103 {
0104     d->send_cancelled();
0105 }
0106 
0107 QStringList DataSourceInterface::mimeTypes() const
0108 {
0109     return d->mimeTypes;
0110 }
0111 
0112 DataSourceInterface *DataSourceInterface::get(wl_resource *native)
0113 {
0114     if (auto sourcePrivate = resource_cast<DataSourceInterfacePrivate *>(native)) {
0115         return sourcePrivate->q;
0116     }
0117     return nullptr;
0118 }
0119 
0120 DataDeviceManagerInterface::DnDActions DataSourceInterface::supportedDragAndDropActions() const
0121 {
0122     return d->supportedDnDActions;
0123 }
0124 
0125 DataDeviceManagerInterface::DnDAction DataSourceInterface::selectedDndAction() const
0126 {
0127     return d->selectedDndAction;
0128 }
0129 
0130 void DataSourceInterface::dropPerformed()
0131 {
0132     d->dropPerformed = true;
0133     if (d->resource()->version() < WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION) {
0134         return;
0135     }
0136     d->send_dnd_drop_performed();
0137 }
0138 
0139 void DataSourceInterface::dndFinished()
0140 {
0141     if (d->resource()->version() < WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) {
0142         return;
0143     }
0144     d->send_dnd_finished();
0145 }
0146 
0147 bool DataSourceInterface::isDropPerformed() const
0148 {
0149     return d->dropPerformed;
0150 }
0151 
0152 void DataSourceInterface::dndAction(DataDeviceManagerInterface::DnDAction action)
0153 {
0154     d->selectedDndAction = action;
0155 
0156     if (d->resource()->version() < WL_DATA_SOURCE_ACTION_SINCE_VERSION) {
0157         return;
0158     }
0159     uint32_t wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_none;
0160     if (action == DataDeviceManagerInterface::DnDAction::Copy) {
0161         wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_copy;
0162     } else if (action == DataDeviceManagerInterface::DnDAction::Move) {
0163         wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_move;
0164     } else if (action == DataDeviceManagerInterface::DnDAction::Ask) {
0165         wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_ask;
0166     }
0167     d->send_action(wlAction);
0168 }
0169 
0170 void DataSourceInterface::dndCancelled()
0171 {
0172     d->isCanceled = true;
0173     // for v3 or less, cancel should not be called after a failed drag operation
0174     if (wl_resource_get_version(resource()) < 3) {
0175         return;
0176     }
0177     d->send_cancelled();
0178 }
0179 
0180 bool DataSourceInterface::isDndCancelled() const
0181 {
0182     return d->isCanceled;
0183 }
0184 
0185 wl_resource *DataSourceInterface::resource() const
0186 {
0187     return d->resource()->handle;
0188 }
0189 
0190 wl_client *DataSourceInterface::client() const
0191 {
0192     return d->resource()->client();
0193 }
0194 
0195 bool DataSourceInterface::isAccepted() const
0196 {
0197     return d->isAccepted;
0198 }
0199 
0200 void DataSourceInterface::setAccepted(bool accepted)
0201 {
0202     d->isAccepted = accepted;
0203 }
0204 
0205 XdgToplevelDragV1Interface *DataSourceInterface::xdgToplevelDrag() const
0206 {
0207     return d->xdgToplevelDrag;
0208 }
0209 
0210 }
0211 
0212 #include "moc_datasource.cpp"