File indexing completed on 2024-11-10 04:57:26
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"