summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDDoSolitary <DDoSolitary@gmail.com>2025-01-22 22:27:46 +0800
committerGitHub <noreply@github.com>2025-01-22 14:27:46 +0000
commitfda5626594c3f31bbab08e877a797a623c98c450 (patch)
treebc2f665ad5f61d91e9dc3e57b755b63140d7e14a /src
parentc90dbfab6f0f7f295b8b4b211223ea6e82a1021d (diff)
xwayland: fix sending large clipboard data (#9134)
Diffstat (limited to 'src')
-rw-r--r--src/xwayland/XWM.cpp55
-rw-r--r--src/xwayland/XWM.hpp1
2 files changed, 35 insertions, 21 deletions
diff --git a/src/xwayland/XWM.cpp b/src/xwayland/XWM.cpp
index 3486b286..71a7c44c 100644
--- a/src/xwayland/XWM.cpp
+++ b/src/xwayland/XWM.cpp
@@ -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");
@@ -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);
}
}
@@ -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];
@@ -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);
diff --git a/src/xwayland/XWM.hpp b/src/xwayland/XWM.hpp
index 0455c761..02ade80d 100644
--- a/src/xwayland/XWM.hpp
+++ b/src/xwayland/XWM.hpp
@@ -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;