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