Crate wayland_clipboard_listener

Crate wayland_clipboard_listener 

Source
Expand description

§General Induction

By default, this library uses the ext-data-control-v1 protocol. This is the standard protocol supported by modern compositors.

For legacy support, you can enable the wlr-data-control feature to use the older wlr-data-control-unstable-v1 protocol. This handles the clipboard on sway, hyperland or kde that implement the protocol. You can view the protocol in wlr-data-control-unstable-v1. Here we simply explain it.

This protocol involves there register: WlSeat, ZwlrDataControlManagerV1, ZwlrDataControlDeviceV1, and zwlrDataControlOfferV1, seat is used to create a device, and the device will handle the copy and paste,

when you want to use this protocol, you need to init these first, then enter the eventloop, you can view our code, part of init()

§Paste

Copy is mainly in the part of device dispatch and dataoffer one, there are two road to finished a copy event, this is decided by the time you send the receive request of ZwlrDataControlDeviceV1;

§Road 1
    1. First, the event enter to DataOffer event of zwlrDataControlOfferV1, it will send a zwlrDataControlOfferV1 object, this will include the data message of clipboard, if you send this time, you will not know the mimetype. In this time, the data includes the text selected and copied, here you can pass a file description to receive, and mimetype of TEXT, because at this time you do not know any mimetype of the data
    1. It will enter the event of zwlrDataControlOfferV1, there the mimetype be send, but before , you ignore the mimetype
    1. it enter the selection, follow the document of the protocol, you need to destroy the offer, if there is one,
    1. The main loop is end, then you need to run roundtrip, again, for the pipeline finished, then you will receive the text. Note, if in this routine, you need to check the mimetype in the end, because the data in pipeline maybe not text

§Road 2

it is similar with Road 1, but send receive request when receive selection event, this time you will receive mimetype. Here you can only receive the data which is by copy

§Copy

Paste with wlr-data-control-unstable-v1, need data provider alive, you can make an experiment, if you copy a text from firefox, and kill firefox, you will find, you cannot paste! It is amazing, doesn’t it? So the copy event need to keep alive if the data is still available. You will find that if you copy a text with wl-copy, it will always alive in htop, if you view the code, you will find it fork itself, and live in the backend, until you copy another text from other place, it will die.

Then the problem is, how to copy the data, and when to kill the progress?

Copy event involves ZwlrDataControlDeviceV1 and ZwlrDataControlSourceV1.

    1. if you want to send the data, you need to create a new ZwlrDataControlSourceV1, use the create_data_source function of zwlr_data_control_manager_v1, create a new one, and set the mimetype to it , use offer request. You can set multi times,
    1. start a never end loop of blocking_dispatch, but it is not never end loop, it should break when receive cancelled event of ZwlrDataControlSourceV1, this means another data is copied, the progress is not needed anymore
    • 2.1. In blocking_dispatches at the beginning, you will receive some signals of send, with mimetype and a file description, write the data to the fd, then copy will finished, data will be in clipboard
    • 2.2. when received cancelled, exit the progress

A simple example to create a clipboard listener is following:

use wayland_clipboard_listener::WlClipboardPasteStream;
use wayland_clipboard_listener::WlListenType;

fn main() {
    let mut stream = WlClipboardPasteStream::init(WlListenType::ListenOnCopy).unwrap();
    // Note: MIME type priority is ignored when WlListenType is ListenOnSelect
    // stream.set_priority(vec![
    //     "image/jpeg".into(),
    //     "text/plain;charset=utf-8".into(),
    // ]);
    for context in stream.paste_stream().flatten() {
        println!("{context:?}");
    }
}

For using the legacy wlr protocol (with the wlr-data-control feature):

use wayland_clipboard_listener::WlClipboardPasteStreamWlr;
use wayland_clipboard_listener::WlListenType;

fn main() {
    let mut stream = WlClipboardPasteStreamWlr::init(WlListenType::ListenOnCopy).unwrap();
    for context in stream.paste_stream().flatten() {
        println!("{context:?}");
    }
}

A simple example to create a wl-copy is following:

use wayland_clipboard_listener::{WlClipboardCopyStream, WlClipboardListenerError};
fn main() -> Result<(), WlClipboardListenerError> {
    let args = std::env::args();
    if args.len() != 2 {
        println!("You need to pass a string to it");
        return Ok(());
    }
    let context: &str = &args.last().unwrap();
    let mut stream = WlClipboardCopyStream::init()?;
    stream.copy_to_clipboard(context.as_bytes().to_vec(), vec!["TEXT"] ,false)?;
    Ok(())
}

Structs§

ClipBoardListenContext
context here describe two types of context
ClipBoardListenMessage
WlClipboardCopyStream
copy stream, it can used to make a wl-copy
WlClipboardListenerStream
Stream, provide a iter to listen to clipboard Note, the iter will loop very fast, you would better to use thread sleep or iter you self
WlClipboardPasteStream
Paste stream it is used to handle paste event

Enums§

WlClipboardListenerError
Error it describe three kind of error
WlListenType
listentype if ListenOnHover, it will be useful for translation apps, but in dispatch, we cannot know the mime_types, it can only handle text