Skip to content

Commit

Permalink
xwayland: fix sending large clipboard data (#9134)
Browse files Browse the repository at this point in the history
  • Loading branch information
DDoSolitary authored Jan 22, 2025
1 parent c90dbfa commit fda5626
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 21 deletions.
55 changes: 34 additions & 21 deletions src/xwayland/XWM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,11 @@ void CXWM::setClipboardToWayland(SXSelection& sel) {
g_pSeatManager->setCurrentSelection(sel.dataSource);
}

static int writeDataSource(int fd, uint32_t mask, void* data) {
auto selection = (SXSelection*)data;
return selection->onWrite();
}

void CXWM::getTransferData(SXSelection& sel) {
Debug::log(LOG, "[xwm] getTransferData");

Expand All @@ -1179,26 +1184,9 @@ void CXWM::getTransferData(SXSelection& sel) {
sel.transfer.reset();
return;
} else {
char* property = (char*)xcb_get_property_value(sel.transfer->propertyReply);
int remainder = xcb_get_property_value_length(sel.transfer->propertyReply) - sel.transfer->propertyStart;

ssize_t len = write(sel.transfer->wlFD, property + sel.transfer->propertyStart, remainder);
if (len == -1) {
Debug::log(ERR, "[xwm] write died in transfer get");
close(sel.transfer->wlFD);
sel.transfer.reset();
return;
}

if (len < remainder) {
sel.transfer->propertyStart += len;
Debug::log(ERR, "[xwm] wl client read partially: len {}", len);
return;
} else {
Debug::log(LOG, "[xwm] cb transfer to wl client complete, read {} bytes", len);
close(sel.transfer->wlFD);
sel.transfer.reset();
}
sel.onWrite();
if (sel.transfer)
sel.transfer->eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, sel.transfer->wlFD, WL_EVENT_WRITABLE, ::writeDataSource, &sel);
}
}

Expand Down Expand Up @@ -1370,7 +1358,8 @@ bool SXSelection::sendData(xcb_selection_request_event_t* e, std::string mime) {
fcntl(p[0], F_SETFD, FD_CLOEXEC);
fcntl(p[0], F_SETFL, O_NONBLOCK);
fcntl(p[1], F_SETFD, FD_CLOEXEC);
fcntl(p[1], F_SETFL, O_NONBLOCK);
// the wayland client might not expect a non-blocking fd
// fcntl(p[1], F_SETFL, O_NONBLOCK);

transfer->wlFD = p[0];

Expand All @@ -1383,6 +1372,30 @@ bool SXSelection::sendData(xcb_selection_request_event_t* e, std::string mime) {
return true;
}

int SXSelection::onWrite() {
char* property = (char*)xcb_get_property_value(transfer->propertyReply);
int remainder = xcb_get_property_value_length(transfer->propertyReply) - transfer->propertyStart;

ssize_t len = write(transfer->wlFD, property + transfer->propertyStart, remainder);
if (len == -1) {
Debug::log(ERR, "[xwm] write died in transfer get");
close(transfer->wlFD);
transfer.reset();
return 0;
}

if (len < remainder) {
transfer->propertyStart += len;
Debug::log(LOG, "[xwm] wl client read partially: len {}", len);
} else {
Debug::log(LOG, "[xwm] cb transfer to wl client complete, read {} bytes", len);
close(transfer->wlFD);
transfer.reset();
}

return 1;
}

SXTransfer::~SXTransfer() {
if (wlFD)
close(wlFD);
Expand Down
1 change: 1 addition & 0 deletions src/xwayland/XWM.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ struct SXSelection {
void onKeyboardFocus();
bool sendData(xcb_selection_request_event_t* e, std::string mime);
int onRead(int fd, uint32_t mask);
int onWrite();

struct {
CHyprSignalListener setSelection;
Expand Down

0 comments on commit fda5626

Please sign in to comment.