|
3 | 3 | // SPDX-License-Identifier: GPL-3.0-or-later
|
4 | 4 |
|
5 | 5 | #include "waylandcopyclient.h"
|
6 |
| -#include "readpipedatatask.h" |
7 | 6 |
|
8 | 7 | #include <QEventLoop>
|
9 | 8 | #include <QMimeData>
|
|
22 | 21 | #include <DWayland/Client/datacontroloffer.h>
|
23 | 22 |
|
24 | 23 | #include <unistd.h>
|
| 24 | +#include <mutex> |
| 25 | + |
| 26 | +static std::mutex PIPELINE_GUARD; |
| 27 | + |
| 28 | +constexpr int BYTE_MAX = 1024 * 4; |
25 | 29 |
|
26 | 30 | static const QString ApplicationXQtImageLiteral QStringLiteral("application/x-qt-image");
|
27 | 31 |
|
@@ -140,6 +144,7 @@ WaylandCopyClient::WaylandCopyClient(QObject *parent)
|
140 | 144 | , m_mimeData(new DMimeData())
|
141 | 145 | , m_seat(nullptr)
|
142 | 146 | , m_curOffer(0)
|
| 147 | + , m_pipeIsForcedClosed(false) |
143 | 148 | {
|
144 | 149 |
|
145 | 150 | }
|
@@ -167,6 +172,7 @@ void WaylandCopyClient::init()
|
167 | 172 | m_connectionThread->start();
|
168 | 173 | m_connectionThreadObject->initConnection();
|
169 | 174 | connect(this, &WaylandCopyClient::dataCopied, this, &WaylandCopyClient::onDataCopied);
|
| 175 | + connect(this, &WaylandCopyClient::dataReady, this, &WaylandCopyClient::taskDataReady); |
170 | 176 | }
|
171 | 177 |
|
172 | 178 | void WaylandCopyClient::setupRegistry(Registry *registry)
|
@@ -217,13 +223,89 @@ void WaylandCopyClient::onDataOffered(KWayland::Client::DataControlOfferV1* offe
|
217 | 223 | // NOTE: no thread, this should be block
|
218 | 224 | void WaylandCopyClient::execTask(const QStringList &mimeTypes, DataControlOfferV1 *offer)
|
219 | 225 | {
|
| 226 | + m_pipeIsForcedClosed = false; |
220 | 227 | for (const QString &mimeType : mimeTypes) {
|
221 |
| - ReadPipeDataTask *task = new ReadPipeDataTask(m_connectionThreadObject, offer, mimeType, this); |
222 |
| - connect(this, &WaylandCopyClient::dataOfferedNew, task, &ReadPipeDataTask::forceClosePipeLine); |
223 |
| - connect(task, &ReadPipeDataTask::dataReady, this, &WaylandCopyClient::taskDataReady); |
| 228 | + onDataOfferedTask(offer, mimeType); |
| 229 | + } |
| 230 | +} |
224 | 231 |
|
225 |
| - task->run(); |
| 232 | +void WaylandCopyClient::onDataOfferedTask(DataControlOfferV1 *offer, const QString &mimeType) |
| 233 | +{ |
| 234 | + if (!m_connectionThreadObject || !offer || mimeType.isEmpty()) { |
| 235 | + return; |
226 | 236 | }
|
| 237 | + int pipeFds[2]; |
| 238 | + |
| 239 | + if (pipe(pipeFds) != 0) { |
| 240 | + qWarning() << "Create pipe failed."; |
| 241 | + |
| 242 | + // 避免返回数据量少 |
| 243 | + Q_EMIT dataReady((qint64)offer, mimeType, QByteArray()); |
| 244 | + return; |
| 245 | + } |
| 246 | + |
| 247 | + // 根据mime类取数据,写入pipe中 |
| 248 | + offer->receive(mimeType, pipeFds[1]); |
| 249 | + m_connectionThreadObject->roundtrip(); |
| 250 | + close(pipeFds[1]); |
| 251 | + |
| 252 | + // force to close the piepline |
| 253 | + connect(this, &WaylandCopyClient::dataOfferedNew, this, [pipeFds, this] { |
| 254 | + std::lock_guard<std::mutex> guard(PIPELINE_GUARD); |
| 255 | + m_pipeIsForcedClosed = true; |
| 256 | + close(pipeFds[0]); |
| 257 | + }); |
| 258 | + |
| 259 | + qint64 offerId = (qint64)offer; |
| 260 | + |
| 261 | + // FIXME: in QtConcurrent run , when signal is emit, sometimes it cannot be recepted |
| 262 | + // So sometimes copy will not succcessed |
| 263 | + QtConcurrent::run([this, pipeFds, mimeType, offerId] { |
| 264 | + QByteArray data; |
| 265 | + bool is_successed = readData(pipeFds[0], data); |
| 266 | + std::lock_guard<std::mutex> guard(PIPELINE_GUARD); |
| 267 | + if (m_pipeIsForcedClosed) { |
| 268 | + qDebug() << "pipeline is block here;" << "mimetype is: " << mimeType; |
| 269 | + m_pipeIsForcedClosed = false; |
| 270 | + return; |
| 271 | + } |
| 272 | + |
| 273 | + if (!is_successed) { |
| 274 | + qDebug() << "Cannot open pipeline"; |
| 275 | + return; |
| 276 | + } |
| 277 | + |
| 278 | + Q_EMIT dataReady(offerId, mimeType, data); |
| 279 | + m_pipeIsForcedClosed = false; |
| 280 | + close(pipeFds[0]); |
| 281 | + }); |
| 282 | + |
| 283 | +} |
| 284 | + |
| 285 | +bool WaylandCopyClient::readData(int fd, QByteArray &data) |
| 286 | +{ |
| 287 | + QFile readPipe; |
| 288 | + if (!readPipe.open(fd, QIODevice::ReadOnly)) { |
| 289 | + return false; |
| 290 | + } |
| 291 | + |
| 292 | + if (!readPipe.isReadable()) { |
| 293 | + qWarning() << "Pipe is not readable"; |
| 294 | + readPipe.close(); |
| 295 | + return false; |
| 296 | + } |
| 297 | + |
| 298 | + int retCount = BYTE_MAX; |
| 299 | + do { |
| 300 | + QByteArray bytes = readPipe.read(BYTE_MAX); |
| 301 | + retCount = bytes.count(); |
| 302 | + if (!bytes.isEmpty()) |
| 303 | + data.append(bytes); |
| 304 | + } while (retCount == BYTE_MAX); |
| 305 | + |
| 306 | + readPipe.close(); |
| 307 | + |
| 308 | + return true; |
227 | 309 | }
|
228 | 310 |
|
229 | 311 | void WaylandCopyClient::taskDataReady(qint64 offer, const QString &mimeType, const QByteArray &data)
|
|
0 commit comments