Generic clipboard storage#11407
Generic clipboard storage#11407eira-fransham merged 22 commits intoslint-ui:feature/drag-and-dropfrom
Conversation
LeonMatthes
left a comment
There was a problem hiding this comment.
Just some initial thoughts.
In summary, I think we should try to limit the API surface of this where possible.
Maybe we can just use strings for mime types for now? That's probably what they need to end up as in Slint code anyhow.
5335fcd to
a734ee0
Compare
This moves the `clipboard` module from a `mod.rs` to a separately-named file. It also heavily simplifies the `PlatformClipboard` trait to just have a `set` and `get` method.
|
Since there's still a bit of confusing, I decided to write up what I think a minimal API would be that (1) is easy to use for people who want to read/write to the clipboard and create/consume dnd data in the future pub trait Platform {
...
fn set_clipboard_text(&self, _text: &str, _clipboard: Clipboard) {
self.set_clipboard_data(MimeData::default().with_plain_text(_text), _clipboard);
}
fn clipboard_text(&self, _clipboard: Clipboard) -> Option<String> {
self.clipboard_data(_clipboard).and_then(|data| data.fetch_as_plain_text())
}
fn set_clipboard_data(&self, _data: MimeData, _clipboard: Clipboard) {}
fn clipboard_data(&self, _clipboard: Clipboard) -> Option<&MimeData> {
None
}
...
}
enum MimeDataEntry {
Bytes(Box<[u8]>),
Provider(Box<dyn Fn() -> Box<[u8]> + Send + Sync>),
}
#[derive(Default, Clone)]
pub struct MimeData {
entries: std::collections::HashMap<String, alloc::sync::Arc<MimeDataEntry>>,
}
impl MimeData {
pub fn with_bytes(self, mime_type: impl Into<String>, data: impl Into<Box<[u8]>>) -> Self {
todo!();
self
}
pub fn with_provider(
self,
mime_type: impl Into<String>,
provider: impl Fn() -> Box<[u8]> + Send + Sync + 'static,
) -> Self {
todo!();
self
}
pub fn with_plain_text(self, text: impl Into<String>) -> Self {
self.with_bytes("text/plain", text.into().into_bytes().into_boxed_slice())
}
pub fn mime_types(&self) -> impl Iterator<Item = &str> {
self.entries.keys().map(|s| s.as_str())
}
pub fn fetch_bytes(&self, mime_type: &str) -> Option<Box<[u8]>> {
self.entries.get(mime_type).map(|entry| match &**entry {
MimeDataEntry::Bytes(bytes) => bytes.clone(),
MimeDataEntry::Provider(provider) => provider(),
})
}
pub fn fetch_as_plain_text(&self) -> Option<String> {
self.fetch_bytes("text/plain;charset=utf-8")
.or_else(|| self.fetch_bytes("text/plain"))
.and_then(|bytes| String::from_utf8(bytes.to_vec()).ok())
}
}This is minimal. But we can extend it in the future to support async retrieval, add more convenience functions, as well as the ability to store an Names also subject to discussion, but I think this captures the core of what I feel is a minimal API that captures what I feel we need. |
|
@tronical Just to serialise the discussion we had on Mattermost so it's visible on this PR later:
Is there anything else that I missed? |
584ddbb
into
slint-ui:feature/drag-and-drop
Closes #11399 (that issue also explains the research and design decisions).
This is an initial implementation of an API for the clipboard that can support arbitrary MIME types. For now, the functionality is unchanged - only strings can be stored/retrieved from the clipboard. Actually handling multiple types is left for future work.