From e781a3ae035f1c8d1b7454fc90acdec6f3d7cc6a Mon Sep 17 00:00:00 2001 From: rfm Date: Mon, 19 Feb 2024 22:06:55 +0000 Subject: [PATCH] reduce x library traffic and memory footprint during large transfers --- Tools/xpbs.m | 51 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/Tools/xpbs.m b/Tools/xpbs.m index c1ac6660..fa3cc0a6 100644 --- a/Tools/xpbs.m +++ b/Tools/xpbs.m @@ -884,6 +884,7 @@ - (void) xSelectionClear - (NSMutableData*) getSelectionData: (XSelectionEvent*)xEvent type: (Atom*)type + size: (long)max { int status; unsigned char *data; @@ -896,6 +897,7 @@ - (NSMutableData*) getSelectionData: (XSelectionEvent*)xEvent unsigned long number_items; NSMutableData *md = nil; + if (max > long_length) long_length = max; /* * Read data from property identified in SelectionNotify event. */ @@ -995,54 +997,63 @@ - (void) xSelectionNotify: (XSelectionEvent*)xEvent } [self setWaitingForSelection: 0]; - md = [self getSelectionData: xEvent type: &actual_type]; + md = [self getSelectionData: xEvent type: &actual_type size: 0]; if (md != nil) { if (actual_type == XG_INCR) { XEvent event; - NSMutableData *imd = nil; BOOL wait = YES; unsigned count = 0; + int32_t size; // Need to delete the property to start transfer XDeleteProperty(xDisplay, xEvent->requestor, xEvent->property); - md = nil; + memcpy(&size, [md bytes], 4); + NSDebugMLLog(@"INCR", + @"Size for INCR chunks is %u bytes.", (unsigned)size); + [md setLength: 0]; while (wait) { XNextEvent(xDisplay, &event); - if (event.type == PropertyNotify) + if (event.type == PropertyNotify + && event.xproperty.state == PropertyNewValue) { - if (event.xproperty.state != PropertyNewValue) continue; - - imd = [self getSelectionData: xEvent type: &actual_type]; - - // delete the property to get the next transfer chunk - XDeleteProperty(xDisplay, xEvent->requestor, xEvent->property); + ENTER_POOL + NSMutableData *imd; + + imd = [self getSelectionData: xEvent + type: &actual_type + size: size]; + + /* Delete the property to get the next transfer chunk + * or clean up if the end of transfer was indicated by + * an empty chunk. + */ + XDeleteProperty(xDisplay, + xEvent->requestor, xEvent->property); if (imd != nil) { - NSDebugMLLog(@"Pbs", + NSDebugMLLog(@"INCR", @"Retrieved %lu bytes type '%s' from X selection.", - (unsigned long)[md length], + (unsigned long)[imd length], XGetAtomName(xDisplay, actual_type)); count++; - if (md == nil) - { - md = imd; - } - else - { - [md appendData: imd]; - } + [md appendData: imd]; } else { wait = NO; } + LEAVE_POOL } } + if ([md length] == 0) + { + md = nil; + } NSDebugMLLog(@"Pbs", @"Retrieved %lu bytes type '%s' in %u chunks from X selection.", (unsigned long)[md length], XGetAtomName(xDisplay, actual_type),