Skip to content

get or set can fail with a large (>200MB) image on linux X11 with Mint 22.2 #212

@XavierF-C

Description

@XavierF-C

Hello, I have found two cases where the clipboard did not work on linux X11 with Mint 22.2 Cinnamon.

For the first case (I do not have an easily reproducible example), when I try to paste a large compressed image from GIMP (~27MB, ~9216x6912 pixels), the set operation can fail with: Unknown error while interacting with the clipboard: Maximum request length exceeded. When this error occurs, it is in the context of a multithreaded rust program.

For the second case, i have a reproducible example. When I run this program with linux X11, i get the following error for the get operation: The image or the text that was about to be transferred to/from the clipboard could not be converted to the appropriate format.

// Cargo.toml
// [dependencies]
// arboard = { version="3.6.1", features=["wayland-data-control"] }
fn main() {
    let clipboard = arboard::Clipboard::new();
    let mut clipboard = match clipboard {
        Ok(clipboard) => clipboard,
        Err(err) => {
            println!("Failed to initialize clipboard: {}", err);
            return;
        }
    };

    let number_mbs = 513; // Above 512 MB, get fails on Linux Mint 22.2 Cinnamon in release mode.
    let approximate_bytes = 1024 * 1024 * number_mbs;
    let size = (approximate_bytes as f64 / 4.0).sqrt() as usize;
    println!("Image width/height: {}", size);
    let mut huge_image_bytes = vec![0; 4 * size * size];
    let bytes = huge_image_bytes.len();
    for i in 0..huge_image_bytes.len() / 4 {
        huge_image_bytes[i * 4] = 101;
        huge_image_bytes[(i * 4) + 1] = 121;
        huge_image_bytes[(i * 4) + 2] = 141;
        huge_image_bytes[(i * 4) + 3] = 127;
    }
    let size = (huge_image_bytes.len() as f64 / 4.0).sqrt() as usize;
    let image_data = arboard::ImageData {
        width: size,
        height: size,
        bytes: huge_image_bytes.into(),
    };

    let start =  std::time::SystemTime::now();
    let since_the_epoch = start.duration_since(std::time::UNIX_EPOCH).unwrap_or_default();
    let start_ms = since_the_epoch.as_millis();
    match clipboard.set_image(image_data) {
        Ok(_) => {},
        Err(err) => {
            println!("Failed to set image into clipboard: {}", err);
        },
    };
    let end =  std::time::SystemTime::now();
    let since_the_epoch = end.duration_since(std::time::UNIX_EPOCH).unwrap_or_default();
    let end_ms = since_the_epoch.as_millis();
    let time = end_ms - start_ms;
    println!("Took {} ms to store {} bytes", time, bytes);

    let cliboard_get = clipboard.get();
    let start =  std::time::SystemTime::now();
    let since_the_epoch = start.duration_since(std::time::UNIX_EPOCH).unwrap_or_default();
    let start_ms = since_the_epoch.as_millis();
    match cliboard_get.image() {
        Ok(image) => {
            let end =  std::time::SystemTime::now();
            let since_the_epoch = end.duration_since(std::time::UNIX_EPOCH).unwrap_or_default();
            let end_ms = since_the_epoch.as_millis();
            let time = end_ms - start_ms;
            println!("Took {} ms to load {} bytes", time, image.bytes.len());

            match clipboard.set_image(image) {
                Ok(_) => {},
                Err(err) => {
                    println!("Failed to set text into clipboard: {}", err);
                },
            };
            println!("Fine to set image again");
        },
        Err(err) => println!("Error or not some image: {}", err),
    }

    std::thread::sleep(std::time::Duration::from_secs(5));
}

Thanks in advance.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions