xwayland/xwm: handle INCR clipboard transfer chunks correctly (#13125)
Handle XCB_PROPERTY_NEW_VALUE events for incremental selection transfers. Previously only DELETE was handled, causing INCR transfers to fail after the first chunk.
This commit is contained in:
parent
c92fb5e85f
commit
b8fc0def97
1 changed files with 29 additions and 8 deletions
|
|
@ -33,6 +33,8 @@ static int onX11Event(int fd, uint32_t mask, void* data) {
|
||||||
return g_pXWayland->m_wm->onEvent(fd, mask);
|
return g_pXWayland->m_wm->onEvent(fd, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int writeDataSource(int fd, uint32_t mask, void* data);
|
||||||
|
|
||||||
struct SFreeDeleter {
|
struct SFreeDeleter {
|
||||||
void operator()(void* ptr) const {
|
void operator()(void* ptr) const {
|
||||||
std::free(ptr); // NOLINT(cppcoreguidelines-no-malloc)
|
std::free(ptr); // NOLINT(cppcoreguidelines-no-malloc)
|
||||||
|
|
@ -648,19 +650,33 @@ void CXWM::handleSelectionNotify(xcb_selection_notify_event_t* e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CXWM::handleSelectionPropertyNotify(xcb_property_notify_event_t* e) {
|
bool CXWM::handleSelectionPropertyNotify(xcb_property_notify_event_t* e) {
|
||||||
if (e->state != XCB_PROPERTY_DELETE)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (auto* sel : {&m_clipboard, &m_primarySelection, &m_dndSelection}) {
|
for (auto* sel : {&m_clipboard, &m_primarySelection, &m_dndSelection}) {
|
||||||
auto it = std::ranges::find_if(sel->transfers, [e](const auto& t) { return t->incomingWindow == e->window; });
|
auto it = std::ranges::find_if(sel->transfers, [e](const auto& t) { return t->incomingWindow == e->window; });
|
||||||
if (it != sel->transfers.end()) {
|
if (it == sel->transfers.end())
|
||||||
if (!(*it)->getIncomingSelectionProp(true)) {
|
continue;
|
||||||
sel->transfers.erase(it);
|
|
||||||
return false;
|
auto& transfer = *it;
|
||||||
|
|
||||||
|
if (e->state == XCB_PROPERTY_NEW_VALUE) {
|
||||||
|
if (!transfer->incremental) {
|
||||||
|
getTransferData(*sel);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!transfer->getIncomingSelectionProp(true) || xcb_get_property_value_length(transfer->propertyReply) == 0) {
|
||||||
|
sel->transfers.erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = sel->onWrite();
|
||||||
|
|
||||||
|
if (result == 1 && !transfer->eventSource) {
|
||||||
|
transfer->eventSource = wl_event_loop_add_fd(g_pCompositor->m_wlEventLoop, transfer->wlFD.get(), WL_EVENT_WRITABLE, ::writeDataSource, sel);
|
||||||
|
}
|
||||||
|
} else if (e->state == XCB_PROPERTY_DELETE) {
|
||||||
getTransferData(*sel);
|
getTransferData(*sel);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1620,6 +1636,11 @@ int SXSelection::onWrite() {
|
||||||
free(transfer->propertyReply); // NOLINT(cppcoreguidelines-no-malloc)
|
free(transfer->propertyReply); // NOLINT(cppcoreguidelines-no-malloc)
|
||||||
transfer->propertyReply = nullptr;
|
transfer->propertyReply = nullptr;
|
||||||
transfer->propertyStart = 0;
|
transfer->propertyStart = 0;
|
||||||
|
if (transfer->eventSource) {
|
||||||
|
wl_event_source_remove(transfer->eventSource);
|
||||||
|
transfer->eventSource = nullptr;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue