refactor: update smithay-clipboard
This commit is contained in:
parent
4e05e3c657
commit
5bfbaae180
9 changed files with 70 additions and 35 deletions
|
|
@ -99,8 +99,8 @@ pub trait Sender<T> {
|
||||||
pub trait RawSurface {
|
pub trait RawSurface {
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// returned pointer must be a valid pointer to the underlying surface, and it must
|
/// returned pointer must be a valid pointer to the underlying surface, and
|
||||||
/// remain valid for as long as `RawSurface` object is alive.
|
/// it must remain valid for as long as `RawSurface` object is alive.
|
||||||
unsafe fn get_ptr(&mut self) -> *mut c_void;
|
unsafe fn get_ptr(&mut self) -> *mut c_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,8 @@ impl<T: mime::AsMimeTypes> AsMimeTypes for DataWrapper<T> {
|
||||||
|
|
||||||
impl smithay_clipboard::dnd::RawSurface for DndSurface {
|
impl smithay_clipboard::dnd::RawSurface for DndSurface {
|
||||||
unsafe fn get_ptr(&mut self) -> *mut c_void {
|
unsafe fn get_ptr(&mut self) -> *mut c_void {
|
||||||
// XXX won't panic because this is only called once before it could be cloned
|
// XXX won't panic because this is only called once before it could be
|
||||||
|
// cloned
|
||||||
Arc::get_mut(&mut self.0).unwrap().get_ptr()
|
Arc::get_mut(&mut self.0).unwrap().get_ptr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,11 @@
|
||||||
extern crate objc;
|
extern crate objc;
|
||||||
|
|
||||||
use objc::runtime::{Class, Object};
|
use objc::runtime::{Class, Object};
|
||||||
use objc_foundation::{INSArray, INSObject, INSString};
|
use objc_foundation::{
|
||||||
use objc_foundation::{NSArray, NSDictionary, NSObject, NSString};
|
INSArray, INSObject, INSString, NSArray, NSDictionary, NSObject, NSString,
|
||||||
|
};
|
||||||
use objc_id::{Id, Owned};
|
use objc_id::{Id, Owned};
|
||||||
use std::error::Error;
|
use std::{error::Error, mem::transmute};
|
||||||
use std::mem::transmute;
|
|
||||||
|
|
||||||
pub struct Clipboard {
|
pub struct Clipboard {
|
||||||
pasteboard: Id<Object>,
|
pasteboard: Id<Object>,
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,23 @@ pub mod platform;
|
||||||
|
|
||||||
use std::{borrow::Cow, error, fmt};
|
use std::{borrow::Cow, error, fmt};
|
||||||
|
|
||||||
|
/// Raw data from the clipboard
|
||||||
|
pub struct ClipboardData(pub Vec<u8>, pub String);
|
||||||
|
|
||||||
|
impl AllowedMimeTypes for ClipboardData {
|
||||||
|
fn allowed() -> Cow<'static, [String]> {
|
||||||
|
Cow::Owned(vec![])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<(Vec<u8>, String)> for ClipboardData {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn try_from((data, mime): (Vec<u8>, String)) -> Result<Self, Self::Error> {
|
||||||
|
Ok(ClipboardData(data, mime))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Data that can be loaded from the clipboard.
|
/// Data that can be loaded from the clipboard.
|
||||||
pub struct ClipboardLoadData<T>(pub T);
|
pub struct ClipboardLoadData<T>(pub T);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ pub trait DndProvider {
|
||||||
/// Peek at the contents of a DnD offer
|
/// Peek at the contents of a DnD offer
|
||||||
fn peek_offer<D: AllowedMimeTypes + 'static>(
|
fn peek_offer<D: AllowedMimeTypes + 'static>(
|
||||||
&self,
|
&self,
|
||||||
_mime_type: Cow<'static, str>,
|
_mime_type: Option<Cow<'static, str>>,
|
||||||
) -> std::io::Result<D> {
|
) -> std::io::Result<D> {
|
||||||
Err(std::io::Error::new(
|
Err(std::io::Error::new(
|
||||||
std::io::ErrorKind::Other,
|
std::io::ErrorKind::Other,
|
||||||
|
|
@ -95,7 +95,7 @@ impl<C: DndProvider> DndProvider for crate::PlatformClipboard<C> {
|
||||||
|
|
||||||
fn peek_offer<D: AllowedMimeTypes + 'static>(
|
fn peek_offer<D: AllowedMimeTypes + 'static>(
|
||||||
&self,
|
&self,
|
||||||
mime_type: Cow<'static, str>,
|
mime_type: Option<Cow<'static, str>>,
|
||||||
) -> std::io::Result<D> {
|
) -> std::io::Result<D> {
|
||||||
self.raw.peek_offer::<D>(mime_type)
|
self.raw.peek_offer::<D>(mime_type)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,7 @@ impl DndProvider for Clipboard {
|
||||||
|
|
||||||
fn peek_offer<D: AllowedMimeTypes + 'static>(
|
fn peek_offer<D: AllowedMimeTypes + 'static>(
|
||||||
&self,
|
&self,
|
||||||
mime_type: Cow<'static, str>,
|
mime_type: Option<Cow<'static, str>>,
|
||||||
) -> std::io::Result<D> {
|
) -> std::io::Result<D> {
|
||||||
match self {
|
match self {
|
||||||
Clipboard::Wayland(c) => c.peek_offer::<D>(mime_type),
|
Clipboard::Wayland(c) => c.peek_offer::<D>(mime_type),
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ use std::{
|
||||||
use dnd::{
|
use dnd::{
|
||||||
DataWrapper, DndAction, DndDestinationRectangle, DndSurface, Sender,
|
DataWrapper, DndAction, DndDestinationRectangle, DndSurface, Sender,
|
||||||
};
|
};
|
||||||
|
use mime::ClipboardData;
|
||||||
use smithay_clipboard::dnd::Rectangle;
|
use smithay_clipboard::dnd::Rectangle;
|
||||||
pub use smithay_clipboard::mime::{AllowedMimeTypes, AsMimeTypes, MimeType};
|
pub use smithay_clipboard::mime::{AllowedMimeTypes, AsMimeTypes, MimeType};
|
||||||
|
|
||||||
|
|
@ -178,13 +179,13 @@ impl Clipboard {
|
||||||
.context
|
.context
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.load_primary_raw(
|
.load_primary_mime::<DataWrapper<ClipboardData>>(
|
||||||
allowed
|
allowed
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|s| MimeType::from(Cow::Owned(s)))
|
.map(|s| MimeType::from(Cow::Owned(s)))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
)
|
)
|
||||||
.map(|(d, m)| (d, m.to_string()))?)
|
.map(|d| (d.0 .0, d.0 .1.to_string()))?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_raw(
|
pub fn read_raw(
|
||||||
|
|
@ -195,13 +196,13 @@ impl Clipboard {
|
||||||
.context
|
.context
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.load_raw(
|
.load_mime::<DataWrapper<ClipboardData>>(
|
||||||
allowed
|
allowed
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|s| MimeType::from(Cow::Owned(s)))
|
.map(|s| MimeType::from(Cow::Owned(s)))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
)
|
)
|
||||||
.map(|(d, m)| (d, m.to_string()))?)
|
.map(|d| (d.0 .0, d.0 .1))?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_dnd(&self, tx: DndSender) {
|
pub fn init_dnd(&self, tx: DndSender) {
|
||||||
|
|
@ -257,13 +258,13 @@ impl Clipboard {
|
||||||
/// Peek at the contents of a DnD offer
|
/// Peek at the contents of a DnD offer
|
||||||
pub fn peek_offer<D: mime::AllowedMimeTypes + 'static>(
|
pub fn peek_offer<D: mime::AllowedMimeTypes + 'static>(
|
||||||
&self,
|
&self,
|
||||||
mime_type: Cow<'static, str>,
|
mime_type: Option<Cow<'static, str>>,
|
||||||
) -> std::io::Result<D> {
|
) -> std::io::Result<D> {
|
||||||
let d = self
|
let d = self
|
||||||
.context
|
.context
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.peek_offer::<DataWrapper<D>>(mime_type.into());
|
.peek_offer::<DataWrapper<D>>(mime_type.map(MimeType::from));
|
||||||
d.map(|d| d.0)
|
d.map(|d| d.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
use x11rb::errors::{ConnectError, ConnectionError, ReplyError};
|
use x11rb::{
|
||||||
use x11rb::protocol::xproto::Atom;
|
errors::{ConnectError, ConnectionError, ReplyError},
|
||||||
|
protocol::xproto::Atom,
|
||||||
|
};
|
||||||
|
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,23 @@ mod error;
|
||||||
|
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
|
|
||||||
use x11rb::connection::Connection as _;
|
use x11rb::{
|
||||||
use x11rb::errors::ConnectError;
|
connection::Connection as _,
|
||||||
use x11rb::protocol::xproto::{self, Atom, AtomEnum, EventMask, Window};
|
errors::ConnectError,
|
||||||
use x11rb::protocol::Event;
|
protocol::{
|
||||||
use x11rb::rust_connection::RustConnection as Connection;
|
xproto::{self, Atom, AtomEnum, EventMask, Window},
|
||||||
use x11rb::wrapper::ConnectionExt;
|
Event,
|
||||||
|
},
|
||||||
|
rust_connection::RustConnection as Connection,
|
||||||
|
wrapper::ConnectionExt,
|
||||||
|
};
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::{
|
||||||
use std::sync::{Arc, RwLock};
|
collections::HashMap,
|
||||||
use std::thread;
|
sync::{Arc, RwLock},
|
||||||
use std::time::{Duration, Instant};
|
thread,
|
||||||
|
time::{Duration, Instant},
|
||||||
|
};
|
||||||
|
|
||||||
const POLL_DURATION: std::time::Duration = Duration::from_micros(50);
|
const POLL_DURATION: std::time::Duration = Duration::from_micros(50);
|
||||||
|
|
||||||
|
|
@ -60,13 +66,16 @@ impl Clipboard {
|
||||||
self.read_selection(self.reader.atoms.clipboard)
|
self.read_selection(self.reader.atoms.clipboard)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Read the current PRIMARY [`Clipboard`] value.
|
/// Read the current PRIMARY [`Clipboard`] value.
|
||||||
pub fn read_primary(&self) -> Result<String, Error> {
|
pub fn read_primary(&self) -> Result<String, Error> {
|
||||||
self.read_selection(self.reader.atoms.primary)
|
self.read_selection(self.reader.atoms.primary)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_selection(&mut self, selection: Atom, contents: String) -> Result<(), Error> {
|
fn write_selection(
|
||||||
|
&mut self,
|
||||||
|
selection: Atom,
|
||||||
|
contents: String,
|
||||||
|
) -> Result<(), Error> {
|
||||||
let target = self.writer.atoms.utf8_string;
|
let target = self.writer.atoms.utf8_string;
|
||||||
|
|
||||||
self.selections
|
self.selections
|
||||||
|
|
@ -124,9 +133,13 @@ impl Clipboard {
|
||||||
selection,
|
selection,
|
||||||
target,
|
target,
|
||||||
property,
|
property,
|
||||||
x11rb::CURRENT_TIME, // FIXME ^
|
x11rb::CURRENT_TIME, /* FIXME ^
|
||||||
// Clients should not use CurrentTime for the time argument of a ConvertSelection request.
|
* Clients should not use CurrentTime for
|
||||||
// Instead, they should use the timestamp of the event that caused the request to be made.
|
* the time argument of a ConvertSelection
|
||||||
|
* request.
|
||||||
|
* Instead, they should use the timestamp
|
||||||
|
* of the event that caused the request to
|
||||||
|
* be made. */
|
||||||
)?;
|
)?;
|
||||||
let _ = self.reader.connection.flush()?;
|
let _ = self.reader.connection.flush()?;
|
||||||
|
|
||||||
|
|
@ -186,8 +199,9 @@ impl Clipboard {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Note that setting the property argument to None indicates that the
|
// Note that setting the property argument to None indicates
|
||||||
// conversion requested could not be made.
|
// that the conversion requested could
|
||||||
|
// not be made.
|
||||||
if event.property == AtomEnum::NONE.into() {
|
if event.property == AtomEnum::NONE.into() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue