File indexing completed on 2024-12-22 05:09:19
0001 /* 0002 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 #include "dataoffer.h" 0007 #include "datadevice.h" 0008 #include "wayland_pointer_p.h" 0009 // Qt 0010 #include <QMimeDatabase> 0011 #include <QMimeType> 0012 // Wayland 0013 #include <wayland-client-protocol.h> 0014 0015 namespace KWayland 0016 { 0017 namespace Client 0018 { 0019 class Q_DECL_HIDDEN DataOffer::Private 0020 { 0021 public: 0022 Private(wl_data_offer *offer, DataOffer *q); 0023 WaylandPointer<wl_data_offer, wl_data_offer_destroy> dataOffer; 0024 QList<QMimeType> mimeTypes; 0025 DataDeviceManager::DnDActions sourceActions = DataDeviceManager::DnDAction::None; 0026 DataDeviceManager::DnDAction selectedAction = DataDeviceManager::DnDAction::None; 0027 0028 private: 0029 void offer(const QString &mimeType); 0030 void setAction(DataDeviceManager::DnDAction action); 0031 static void offerCallback(void *data, wl_data_offer *dataOffer, const char *mimeType); 0032 static void sourceActionsCallback(void *data, wl_data_offer *wl_data_offer, uint32_t source_actions); 0033 static void actionCallback(void *data, wl_data_offer *wl_data_offer, uint32_t dnd_action); 0034 DataOffer *q; 0035 0036 static const struct wl_data_offer_listener s_listener; 0037 }; 0038 0039 #ifndef K_DOXYGEN 0040 const struct wl_data_offer_listener DataOffer::Private::s_listener = {offerCallback, sourceActionsCallback, actionCallback}; 0041 #endif 0042 0043 DataOffer::Private::Private(wl_data_offer *offer, DataOffer *q) 0044 : q(q) 0045 { 0046 dataOffer.setup(offer); 0047 wl_data_offer_add_listener(offer, &s_listener, this); 0048 } 0049 0050 void DataOffer::Private::offerCallback(void *data, wl_data_offer *dataOffer, const char *mimeType) 0051 { 0052 auto d = reinterpret_cast<Private *>(data); 0053 Q_ASSERT(d->dataOffer == dataOffer); 0054 d->offer(QString::fromUtf8(mimeType)); 0055 } 0056 0057 void DataOffer::Private::offer(const QString &mimeType) 0058 { 0059 QMimeDatabase db; 0060 const auto &m = db.mimeTypeForName(mimeType); 0061 if (m.isValid()) { 0062 mimeTypes << m; 0063 Q_EMIT q->mimeTypeOffered(m.name()); 0064 } 0065 } 0066 0067 void DataOffer::Private::sourceActionsCallback(void *data, wl_data_offer *wl_data_offer, uint32_t source_actions) 0068 { 0069 Q_UNUSED(wl_data_offer) 0070 DataDeviceManager::DnDActions actions; 0071 if (source_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) { 0072 actions |= DataDeviceManager::DnDAction::Copy; 0073 } 0074 if (source_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) { 0075 actions |= DataDeviceManager::DnDAction::Move; 0076 } 0077 if (source_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) { 0078 actions |= DataDeviceManager::DnDAction::Ask; 0079 } 0080 auto d = reinterpret_cast<Private *>(data); 0081 if (d->sourceActions != actions) { 0082 d->sourceActions = actions; 0083 Q_EMIT d->q->sourceDragAndDropActionsChanged(); 0084 } 0085 } 0086 0087 void DataOffer::Private::actionCallback(void *data, wl_data_offer *wl_data_offer, uint32_t dnd_action) 0088 { 0089 Q_UNUSED(wl_data_offer) 0090 auto d = reinterpret_cast<Private *>(data); 0091 switch (dnd_action) { 0092 case WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY: 0093 d->setAction(DataDeviceManager::DnDAction::Copy); 0094 break; 0095 case WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE: 0096 d->setAction(DataDeviceManager::DnDAction::Move); 0097 break; 0098 case WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK: 0099 d->setAction(DataDeviceManager::DnDAction::Ask); 0100 break; 0101 case WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE: 0102 d->setAction(DataDeviceManager::DnDAction::None); 0103 break; 0104 default: 0105 Q_UNREACHABLE(); 0106 } 0107 } 0108 0109 void DataOffer::Private::setAction(DataDeviceManager::DnDAction action) 0110 { 0111 if (action == selectedAction) { 0112 return; 0113 } 0114 selectedAction = action; 0115 Q_EMIT q->selectedDragAndDropActionChanged(); 0116 } 0117 0118 DataOffer::DataOffer(DataDevice *parent, wl_data_offer *dataOffer) 0119 : QObject(parent) 0120 , d(new Private(dataOffer, this)) 0121 { 0122 } 0123 0124 DataOffer::~DataOffer() 0125 { 0126 release(); 0127 } 0128 0129 void DataOffer::release() 0130 { 0131 d->dataOffer.release(); 0132 } 0133 0134 void DataOffer::destroy() 0135 { 0136 d->dataOffer.destroy(); 0137 } 0138 0139 bool DataOffer::isValid() const 0140 { 0141 return d->dataOffer.isValid(); 0142 } 0143 0144 QList<QMimeType> DataOffer::offeredMimeTypes() const 0145 { 0146 return d->mimeTypes; 0147 } 0148 0149 void DataOffer::accept(const QMimeType &mimeType, quint32 serial) 0150 { 0151 accept(mimeType.name(), serial); 0152 } 0153 0154 void DataOffer::accept(const QString &mimeType, quint32 serial) 0155 { 0156 wl_data_offer_accept(d->dataOffer, serial, mimeType.toUtf8().constData()); 0157 } 0158 0159 void DataOffer::receive(const QMimeType &mimeType, qint32 fd) 0160 { 0161 receive(mimeType.name(), fd); 0162 } 0163 0164 void DataOffer::receive(const QString &mimeType, qint32 fd) 0165 { 0166 Q_ASSERT(isValid()); 0167 wl_data_offer_receive(d->dataOffer, mimeType.toUtf8().constData(), fd); 0168 } 0169 0170 DataOffer::operator wl_data_offer *() 0171 { 0172 return d->dataOffer; 0173 } 0174 0175 DataOffer::operator wl_data_offer *() const 0176 { 0177 return d->dataOffer; 0178 } 0179 0180 void DataOffer::dragAndDropFinished() 0181 { 0182 Q_ASSERT(isValid()); 0183 if (wl_proxy_get_version(d->dataOffer) < WL_DATA_OFFER_FINISH_SINCE_VERSION) { 0184 return; 0185 } 0186 wl_data_offer_finish(d->dataOffer); 0187 } 0188 0189 DataDeviceManager::DnDActions DataOffer::sourceDragAndDropActions() const 0190 { 0191 return d->sourceActions; 0192 } 0193 0194 void DataOffer::setDragAndDropActions(DataDeviceManager::DnDActions supported, DataDeviceManager::DnDAction preferred) 0195 { 0196 if (wl_proxy_get_version(d->dataOffer) < WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION) { 0197 return; 0198 } 0199 auto toWayland = [](DataDeviceManager::DnDAction action) { 0200 switch (action) { 0201 case DataDeviceManager::DnDAction::Copy: 0202 return WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; 0203 case DataDeviceManager::DnDAction::Move: 0204 return WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; 0205 case DataDeviceManager::DnDAction::Ask: 0206 return WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK; 0207 case DataDeviceManager::DnDAction::None: 0208 return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; 0209 default: 0210 Q_UNREACHABLE(); 0211 } 0212 }; 0213 uint32_t wlSupported = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; 0214 if (supported.testFlag(DataDeviceManager::DnDAction::Copy)) { 0215 wlSupported |= toWayland(DataDeviceManager::DnDAction::Copy); 0216 } 0217 if (supported.testFlag(DataDeviceManager::DnDAction::Move)) { 0218 wlSupported |= toWayland(DataDeviceManager::DnDAction::Move); 0219 } 0220 if (supported.testFlag(DataDeviceManager::DnDAction::Ask)) { 0221 wlSupported |= toWayland(DataDeviceManager::DnDAction::Ask); 0222 } 0223 wl_data_offer_set_actions(d->dataOffer, wlSupported, toWayland(preferred)); 0224 } 0225 0226 DataDeviceManager::DnDAction DataOffer::selectedDragAndDropAction() const 0227 { 0228 return d->selectedAction; 0229 } 0230 0231 } 0232 } 0233 0234 #include "moc_dataoffer.cpp"