View | Details | Raw Unified | Return to bug 58423
Collapse All | Expand All

(-)a/src/systemclipboard/waylandclipboard.cpp (+118 lines)
Lines 16-21 Link Here
16
#include <QPointer>
16
#include <QPointer>
17
#include <QThread>
17
#include <QThread>
18
#include <QTimer>
18
#include <QTimer>
19
#include <QQueue>
19
#include <QWaylandClientExtension>
20
#include <QWaylandClientExtension>
20
#include <QWindow>
21
#include <QWindow>
21
#include <QtWaylandClientVersion>
22
#include <QtWaylandClientVersion>
Lines 320-325 Link Here
320
321
321
Q_SIGNALS:
322
Q_SIGNALS:
322
    void cancelled();
323
    void cancelled();
324
    void dataSendingCompleted();
323
325
324
protected:
326
protected:
325
    void ext_data_control_source_v1_send(const QString &mime_type, int32_t fd) override;
327
    void ext_data_control_source_v1_send(const QString &mime_type, int32_t fd) override;
Lines 394-399 Link Here
394
        break;
396
        break;
395
    }
397
    }
396
    close(fd);
398
    close(fd);
399
400
    Q_EMIT dataSendingCompleted();
397
}
401
}
398
402
399
void DataControlSource::ext_data_control_source_v1_cancelled()
403
void DataControlSource::ext_data_control_source_v1_cancelled()
Lines 578-583 Link Here
578
    wl_display *m_display = nullptr;
582
    wl_display *m_display = nullptr;
579
};
583
};
580
584
585
class ClipboardProcessingQueue : public QObject
586
{
587
    Q_OBJECT
588
public:
589
    explicit ClipboardProcessingQueue(WaylandClipboard &wclip, QObject *parent = nullptr);
590
    ~ClipboardProcessingQueue();
591
592
    void addMimeData(QMimeData *data);
593
    void stop();
594
595
private Q_SLOTS:
596
    void processNext();
597
598
private:
599
    QThread m_th;
600
    QMutex m_mtx;
601
    QQueue<QMimeData*> m_queue;
602
    WaylandClipboard &m_wclip;
603
    bool m_stopped = false;
604
    bool m_processing = false;
605
    QEventLoop *m_waitLoop = nullptr;
606
};
607
608
ClipboardProcessingQueue::ClipboardProcessingQueue(WaylandClipboard &wclip, QObject *parent)
609
    : QObject(parent)
610
    , m_wclip(wclip)
611
{
612
    moveToThread(&m_th);
613
    m_th.start();
614
}
615
616
ClipboardProcessingQueue::~ClipboardProcessingQueue()
617
{
618
    if (m_th.isRunning()) {
619
        m_th.quit();
620
        m_th.wait();
621
    }
622
}
623
624
void ClipboardProcessingQueue::addMimeData(QMimeData *data)
625
{
626
    QMutexLocker locker(&m_mtx);
627
    m_queue.enqueue(data);
628
    if (!m_processing) {
629
        QMetaObject::invokeMethod(this, "processNext", Qt::QueuedConnection);
630
    }
631
}
632
633
void ClipboardProcessingQueue::stop()
634
{
635
    QMutexLocker locker(&m_mtx);
636
    m_stopped = true;
637
638
    if (m_waitLoop && m_waitLoop->isRunning()) {
639
        QMetaObject::invokeMethod(this, [this]{
640
            m_waitLoop->quit();
641
        }, Qt::QueuedConnection);
642
    }
643
}
644
645
void ClipboardProcessingQueue::processNext()
646
{
647
    if (m_stopped) {
648
        return;
649
    }
650
651
    QMimeData *mime = nullptr;
652
    {
653
        QMutexLocker locker(&m_mtx);
654
        if (m_queue.isEmpty() || m_processing) {
655
            return;
656
        }
657
        mime = m_queue.dequeue();
658
        m_processing = true;
659
    }
660
661
    if (mime) {
662
        auto &device = m_wclip.m_device;
663
        auto &manager = m_wclip.m_manager;
664
        auto source = std::make_unique<DataControlSource>(manager->create_data_source(), mime);
665
        source->moveToThread(m_wclip.m_thread.get());
666
667
        auto *sourcePtr = source.get();
668
        device->setSelection(std::move(source));
669
670
        QEventLoop loop;
671
        m_waitLoop = &loop;
672
        connect(sourcePtr, &DataControlSource::dataSendingCompleted, &loop, &QEventLoop::quit);
673
        connect(sourcePtr, &DataControlSource::cancelled, &loop, &QEventLoop::quit);
674
        QTimer::singleShot(5000, &loop, &QEventLoop::quit);
675
        loop.exec();
676
        m_waitLoop = nullptr;
677
    }
678
679
    {
680
        QMutexLocker locker(&m_mtx);
681
        m_processing = false;
682
    }
683
684
    QMetaObject::invokeMethod(this, "processNext", Qt::QueuedConnection);
685
}
686
581
WaylandClipboard::WaylandClipboard(QObject *parent)
687
WaylandClipboard::WaylandClipboard(QObject *parent)
582
    : KSystemClipboard(parent)
688
    : KSystemClipboard(parent)
583
    , m_manager(new DataControlDeviceManager)
689
    , m_manager(new DataControlDeviceManager)
Lines 623-631 Link Here
623
            connect(m_device.get(), &DataControlDevice::primarySelectionChanged, this, [this]() {
729
            connect(m_device.get(), &DataControlDevice::primarySelectionChanged, this, [this]() {
624
                Q_EMIT changed(QClipboard::Selection);
730
                Q_EMIT changed(QClipboard::Selection);
625
            });
731
            });
732
733
            m_dataQueue.reset(new ClipboardProcessingQueue(*this));
626
            m_thread->start();
734
            m_thread->start();
627
735
628
        } else {
736
        } else {
737
            m_dataQueue.reset();
629
            m_device.reset();
738
            m_device.reset();
630
            m_thread->wait();
739
            m_thread->wait();
631
            m_thread.reset();
740
            m_thread.reset();
Lines 637-642 Link Here
637
746
638
WaylandClipboard::~WaylandClipboard()
747
WaylandClipboard::~WaylandClipboard()
639
{
748
{
749
    if (m_dataQueue) {
750
        m_dataQueue->stop();
751
    }
640
    if (m_thread && m_thread->isRunning()) {
752
    if (m_thread && m_thread->isRunning()) {
641
        m_thread->syncQueue();
753
        m_thread->syncQueue();
642
        m_thread->wait();
754
        m_thread->wait();
Lines 664-669 Link Here
664
        return;
776
        return;
665
    }
777
    }
666
778
779
    // Use only for clipboard insertion and if mime data contains an image
780
    if (mode == QClipboard::Clipboard && mime->hasImage()) {
781
        m_dataQueue->addMimeData(mime);
782
        return;
783
    }
784
667
    auto source = std::make_unique<DataControlSource>(m_manager->create_data_source(), mime);
785
    auto source = std::make_unique<DataControlSource>(m_manager->create_data_source(), mime);
668
    source->moveToThread(m_thread.get());
786
    source->moveToThread(m_thread.get());
669
    if (mode == QClipboard::Clipboard) {
787
    if (mode == QClipboard::Clipboard) {
(-)a/src/systemclipboard/waylandclipboard_p.h (+4 lines)
Lines 14-19 Link Here
14
class DataControlDevice;
14
class DataControlDevice;
15
class DataControlDeviceManager;
15
class DataControlDeviceManager;
16
class ClipboardThread;
16
class ClipboardThread;
17
class ClipboardProcessingQueue;
17
18
18
class WaylandClipboard : public KSystemClipboard
19
class WaylandClipboard : public KSystemClipboard
19
{
20
{
Lines 32-37 Link Here
32
    std::unique_ptr<ClipboardThread> m_thread;
33
    std::unique_ptr<ClipboardThread> m_thread;
33
    std::unique_ptr<DataControlDeviceManager> m_manager;
34
    std::unique_ptr<DataControlDeviceManager> m_manager;
34
    std::unique_ptr<DataControlDevice> m_device;
35
    std::unique_ptr<DataControlDevice> m_device;
36
    std::unique_ptr<ClipboardProcessingQueue> m_dataQueue;
37
38
    friend ClipboardProcessingQueue;
35
};
39
};
36
40
37
#endif
41
#endif

Return to bug 58423