void DataDeviceManager::setCurrentSelectionSource(DataSource *source)
{
    if (m_current_selection_source
            && m_current_selection_source->time() > source->time()) {
        qDebug() << "Trying to set older selection";
        return;
    }

    m_compositorOwnsSelection = false;

    finishReadFromClient();

    m_current_selection_source = source;
    source->setManager(this);

    // When retained selection is enabled, the compositor will query all the data from the client.
    // This makes it possible to
    //    1. supply the selection after the offering client is gone
    //    2. make it possible for the compositor to participate in copy-paste
    // The downside is decreased performance, therefore this mode has to be enabled
    // explicitly in the compositors.
    if (m_compositor->wantsRetainedSelection()) {
        m_retainedData.clear();
        m_retainedReadIndex = 0;
        retain();
    }
}
void DataDeviceManager::retain()
{
    QList<QString> offers = m_current_selection_source->mimeTypes();
    finishReadFromClient();
    if (m_retainedReadIndex >= offers.count()) {
        QWaylandCompositorPrivate::get(m_compositor)->feedRetainedSelectionData(&m_retainedData);
        return;
    }
    QString mimeType = offers.at(m_retainedReadIndex);
    m_retainedReadBuf.clear();
    int fd[2];
    if (pipe(fd) == -1) {
        qWarning("Clipboard: Failed to create pipe");
        return;
    }
    fcntl(fd[0], F_SETFL, fcntl(fd[0], F_GETFL, 0) | O_NONBLOCK);
    m_current_selection_source->send(mimeType, fd[1]);
    m_retainedReadNotifier = new QSocketNotifier(fd[0], QSocketNotifier::Read, this);
    connect(m_retainedReadNotifier, SIGNAL(activated(int)), SLOT(readFromClient(int)));
}
void DataDeviceManager::readFromClient(int fd)
{
    static char buf[4096];
    int obsCount = m_obsoleteRetainedReadNotifiers.count();
    for (int i = 0; i < obsCount; ++i) {
        QSocketNotifier *sn = m_obsoleteRetainedReadNotifiers.at(i);
        if (sn->socket() == fd) {
            // Read and drop the data, stopping to read and closing the handle
            // is not yet safe because that could kill the client with SIGPIPE
            // when it still tries to write.
            int n;
            do {
                n = QT_READ(fd, buf, sizeof buf);
            } while (n > 0);
            if (n != -1 || (errno != EAGAIN && errno != EWOULDBLOCK)) {
                m_obsoleteRetainedReadNotifiers.removeAt(i);
                delete sn;
                close(fd);
            }
            return;
        }
    }
    int n = QT_READ(fd, buf, sizeof buf);
    if (n <= 0) {
        if (n != -1 || (errno != EAGAIN && errno != EWOULDBLOCK)) {
            finishReadFromClient(true);
            QList<QByteArray> offers = m_current_selection_source->offerList();
            QString mimeType = QString::fromLatin1(offers.at(m_retainedReadIndex));
            m_retainedData.setData(mimeType, m_retainedReadBuf);
            ++m_retainedReadIndex;
            retain();
        }
    } else {
        m_retainedReadBuf.append(buf, n);
    }
}
void DataDeviceManager::sourceDestroyed(DataSource *source)
{
    Q_UNUSED(source);
    if (m_current_selection_source == source)
        finishReadFromClient();
}