-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: support custom mime types #56
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We also have CHANGELOG
which is here, but no one cares about, even me.
src/worker.rs
Outdated
Store(Box<dyn AsMimeTypes + Send>, SelectionTarget), | ||
/// Store Data with the given Mime Types |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This broke formatting. Also, each doc comments ends with .
in the end.
src/worker.rs
Outdated
if state.data_device_manager_state.is_some() => | ||
{ | ||
if let Err(err) = state.load_selection(target, &mime_types) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That doesn't follow the old code, because it doesn't check primary selection clipboard, which may be absent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what you mean. I don't think the old code checked primary_selection_manager_state but I can add a check for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, the code I wrote is fool-proof and actually doesn't try to unwrap anything. I'm not even sure whether the first check is needed for data device, given that it's also checked, kind of.
Though, maybe won't hurt.
src/mime.rs
Outdated
@@ -1,50 +1,88 @@ | |||
use std::borrow::Cow; | |||
use thiserror::Error; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's used just for a single enum
in the entire crate, no need to be fancy.
src/lib.rs
Outdated
fn store_inner<T: AsMimeTypes + Send + 'static>(&self, data: T, target: SelectionTarget) { | ||
let request = worker::Command::Store(Box::new(data), target); | ||
let _ = self.request_sender.send(request); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All private functions go bellow the public ones.
src/lib.rs
Outdated
if let Ok(reply) = self.request_receiver.recv() { | ||
reply | ||
match reply { | ||
Ok((data, mime)) => T::try_from((data, mime)) | ||
.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err)), | ||
Err(err) => Err(err), | ||
} | ||
} else { | ||
// The clipboard thread is dead, however we shouldn't crash downstream, so | ||
// propogating an error. | ||
Err(std::io::Error::new(std::io::ErrorKind::Other, "clipboard is dead.")) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can probably rewrite this with match
+ .recv().map
, it's just ugly the way it's right now.
src/mime.rs
Outdated
fn discriminant(&self) -> u8 { | ||
unsafe { *(self as *const Self as *const u8) } | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No tricks like that please. You can do it safely e.g by slapping into Text
enum and doing discriminant there.
src/mime.rs
Outdated
allowed | ||
.iter() | ||
.find(|allowed| { | ||
offered_mime_types.iter().any(|offered| offered.as_str() == allowed.as_ref()) | ||
}) | ||
.cloned() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks kind of less efficient, but I guess you don't have that many mime types, so it's kind of ok?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ya, I guess it is algorithmically inefficient, but I assumed neither list would be long enough in practice to cause issues.
src/mime.rs
Outdated
/// Available mime types for this data | ||
fn available(&self) -> Cow<'static, [MimeType]>; | ||
|
||
/// Data as a specific mime_type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The description reads really weird.
src/lib.rs
Outdated
@@ -8,18 +8,22 @@ use std::ffi::c_void; | |||
use std::io::Result; | |||
use std::sync::mpsc::{self, Receiver}; | |||
|
|||
use mime::{AllowedMimeTypes, AsMimeTypes, MimeType}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
local crate exports go below the mod *;
this place is reserved for the outsiders.
😅 I'll edit the CHANGELOG and address the other comments, thanks. |
Would there be any interest in using the mimes crate? I'm hoping to add support for multiple mime types to window_clipboard and I think it could also probably use the mime crate. |
Never mind about the mime crate, I think this is OK. |
src/dnd/mod.rs
Outdated
pub fn end_dnd() {} | ||
|
||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New line in the end of file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, this file will be part of a separate PR for DnD. So I'll remove it.
src/lib.rs
Outdated
use state::SelectionTarget; | ||
use text::Text; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
below mod
src/lib.rs
Outdated
/// Load raw clipboard data. | ||
/// | ||
/// Loads content from a primary clipboard on a last observed seat. | ||
pub fn load_raw( | ||
&self, | ||
allowed: impl Into<Cow<'static, [MimeType]>>, | ||
) -> Result<(Vec<u8>, MimeType)> { | ||
self.load_inner(SelectionTarget::Clipboard, allowed) | ||
} | ||
|
||
/// Load raw primary clipboard data. | ||
/// | ||
/// Loads content from a primary clipboard on a last observed seat. | ||
pub fn load_primary_raw( | ||
&self, | ||
allowed: impl Into<Cow<'static, [MimeType]>>, | ||
) -> Result<(Vec<u8>, MimeType)> { | ||
self.load_inner(SelectionTarget::Primary, allowed) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the use case for raw
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found it useful to have an option without trait bounds on the return type, when passing around a boxed trait object clipboard. I still use the AllowedMimeTypes
trait, but not in the return type trait for the clipboard because Boxing it in a return type doesn't seem to be object safe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the trait were allowed to take an optional reference to self like below, the raw
methods could be avoided, but the api would probably need to include an argument Option<&(impl AllowedMimeTypes + 'static)>
. This way users could create their own type type implementing AllowedMimeTypes which just wraps the received raw data and the allowed mime types.
/// Describes the mime types which are accepted.
pub trait AllowedMimeTypes: TryFrom<(Vec<u8>, MimeType)> {
/// List allowed mime types for the type to convert from a byte slice.
///
/// Allowed mime types should be listed in order of decreasing preference,
/// most preferred first.
fn allowed(_self: Option<&self>) -> Cow<'static, [MimeType]>;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've refactored the methods a bit so they are just allowing a specific mime type to be requested instead.
src/mime.rs
Outdated
fn discriminant(&self) -> usize { | ||
match self { | ||
MimeType::Text(t) => *t as usize, | ||
MimeType::Other(_) => 3, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is error prone and should be removed all together.
src/mime.rs
Outdated
fn as_ref(&self) -> &str { | ||
match self { | ||
MimeType::Other(s) => s.as_ref(), | ||
m => ALLOWED_TEXT_MIME_TYPES[m.discriminant()], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use MimeType::Text(text)
and index with text
right away.
src/mime.rs
Outdated
} | ||
|
||
fallback | ||
pub fn find_allowed( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should likely be pub(crate)
now.
This adds support for loading and storing data that is not text. I've renamed some of the existing methods, so it's a breaking change, but I guess I could avoid renaming the methods so that isn't an issue. and make the methods for loading and storing custom types something like
store_custom
orload_custom
.