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(); }