File indexing completed on 2024-12-22 05:09:20

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 "datasource.h"
0007 #include "wayland_pointer_p.h"
0008 // Qt
0009 #include <QMimeType>
0010 // Wayland
0011 #include <wayland-client-protocol.h>
0012 
0013 namespace KWayland
0014 {
0015 namespace Client
0016 {
0017 class Q_DECL_HIDDEN DataSource::Private
0018 {
0019 public:
0020     explicit Private(DataSource *q);
0021     void setup(wl_data_source *s);
0022 
0023     WaylandPointer<wl_data_source, wl_data_source_destroy> source;
0024     DataDeviceManager::DnDAction selectedAction = DataDeviceManager::DnDAction::None;
0025 
0026 private:
0027     void setAction(DataDeviceManager::DnDAction action);
0028     static void targetCallback(void *data, wl_data_source *dataSource, const char *mimeType);
0029     static void sendCallback(void *data, wl_data_source *dataSource, const char *mimeType, int32_t fd);
0030     static void cancelledCallback(void *data, wl_data_source *dataSource);
0031     static void dndDropPerformedCallback(void *data, wl_data_source *wl_data_source);
0032     static void dndFinishedCallback(void *data, wl_data_source *wl_data_source);
0033     static void actionCallback(void *data, wl_data_source *wl_data_source, uint32_t dnd_action);
0034 
0035     static const struct wl_data_source_listener s_listener;
0036 
0037     DataSource *q;
0038 };
0039 
0040 const wl_data_source_listener DataSource::Private::s_listener =
0041     {targetCallback, sendCallback, cancelledCallback, dndDropPerformedCallback, dndFinishedCallback, actionCallback};
0042 
0043 DataSource::Private::Private(DataSource *q)
0044     : q(q)
0045 {
0046 }
0047 
0048 void DataSource::Private::targetCallback(void *data, wl_data_source *dataSource, const char *mimeType)
0049 {
0050     auto d = reinterpret_cast<DataSource::Private *>(data);
0051     Q_ASSERT(d->source == dataSource);
0052     Q_EMIT d->q->targetAccepts(QString::fromUtf8(mimeType));
0053 }
0054 
0055 void DataSource::Private::sendCallback(void *data, wl_data_source *dataSource, const char *mimeType, int32_t fd)
0056 {
0057     auto d = reinterpret_cast<DataSource::Private *>(data);
0058     Q_ASSERT(d->source == dataSource);
0059     Q_EMIT d->q->sendDataRequested(QString::fromUtf8(mimeType), fd);
0060 }
0061 
0062 void DataSource::Private::cancelledCallback(void *data, wl_data_source *dataSource)
0063 {
0064     auto d = reinterpret_cast<DataSource::Private *>(data);
0065     Q_ASSERT(d->source == dataSource);
0066     Q_EMIT d->q->cancelled();
0067 }
0068 
0069 void DataSource::Private::dndDropPerformedCallback(void *data, wl_data_source *wl_data_source)
0070 {
0071     Q_UNUSED(wl_data_source)
0072     auto d = reinterpret_cast<DataSource::Private *>(data);
0073     Q_EMIT d->q->dragAndDropPerformed();
0074 }
0075 
0076 void DataSource::Private::dndFinishedCallback(void *data, wl_data_source *wl_data_source)
0077 {
0078     Q_UNUSED(wl_data_source)
0079     auto d = reinterpret_cast<DataSource::Private *>(data);
0080     Q_EMIT d->q->dragAndDropFinished();
0081 }
0082 
0083 void DataSource::Private::actionCallback(void *data, wl_data_source *wl_data_source, uint32_t dnd_action)
0084 {
0085     Q_UNUSED(wl_data_source)
0086     auto d = reinterpret_cast<Private *>(data);
0087     switch (dnd_action) {
0088     case WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY:
0089         d->setAction(DataDeviceManager::DnDAction::Copy);
0090         break;
0091     case WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE:
0092         d->setAction(DataDeviceManager::DnDAction::Move);
0093         break;
0094     case WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK:
0095         d->setAction(DataDeviceManager::DnDAction::Ask);
0096         break;
0097     case WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE:
0098         d->setAction(DataDeviceManager::DnDAction::None);
0099         break;
0100     default:
0101         Q_UNREACHABLE();
0102     }
0103 }
0104 
0105 void DataSource::Private::setAction(DataDeviceManager::DnDAction action)
0106 {
0107     if (action == selectedAction) {
0108         return;
0109     }
0110     selectedAction = action;
0111     Q_EMIT q->selectedDragAndDropActionChanged();
0112 }
0113 
0114 void DataSource::Private::setup(wl_data_source *s)
0115 {
0116     Q_ASSERT(!source.isValid());
0117     Q_ASSERT(s);
0118     source.setup(s);
0119     wl_data_source_add_listener(s, &s_listener, this);
0120 }
0121 
0122 DataSource::DataSource(QObject *parent)
0123     : QObject(parent)
0124     , d(new Private(this))
0125 {
0126 }
0127 
0128 DataSource::~DataSource()
0129 {
0130     release();
0131 }
0132 
0133 void DataSource::release()
0134 {
0135     d->source.release();
0136 }
0137 
0138 void DataSource::destroy()
0139 {
0140     d->source.destroy();
0141 }
0142 
0143 bool DataSource::isValid() const
0144 {
0145     return d->source.isValid();
0146 }
0147 
0148 void DataSource::setup(wl_data_source *dataSource)
0149 {
0150     d->setup(dataSource);
0151 }
0152 
0153 void DataSource::offer(const QString &mimeType)
0154 {
0155     wl_data_source_offer(d->source, mimeType.toUtf8().constData());
0156 }
0157 
0158 void DataSource::offer(const QMimeType &mimeType)
0159 {
0160     if (!mimeType.isValid()) {
0161         return;
0162     }
0163     offer(mimeType.name());
0164 }
0165 
0166 DataSource::operator wl_data_source *() const
0167 {
0168     return d->source;
0169 }
0170 
0171 DataSource::operator wl_data_source *()
0172 {
0173     return d->source;
0174 }
0175 
0176 void DataSource::setDragAndDropActions(DataDeviceManager::DnDActions actions)
0177 {
0178     uint32_t wlActions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
0179     if (actions.testFlag(DataDeviceManager::DnDAction::Copy)) {
0180         wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
0181     }
0182     if (actions.testFlag(DataDeviceManager::DnDAction::Move)) {
0183         wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
0184     }
0185     if (actions.testFlag(DataDeviceManager::DnDAction::Ask)) {
0186         wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
0187     }
0188     wl_data_source_set_actions(d->source, wlActions);
0189 }
0190 
0191 DataDeviceManager::DnDAction DataSource::selectedDragAndDropAction() const
0192 {
0193     return d->selectedAction;
0194 }
0195 
0196 }
0197 }
0198 
0199 #include "moc_datasource.cpp"