feat: dnd integration

This commit is contained in:
Ashley Wulber 2024-03-26 16:03:05 -04:00
parent c3e9e794b9
commit 228288dfdf
No known key found for this signature in database
GPG key ID: 5216D4F46A90A820
11 changed files with 589 additions and 14 deletions

102
src/dnd/mod.rs Normal file
View file

@ -0,0 +1,102 @@
use std::borrow::Cow;
use ::dnd::{DndAction, DndDestinationRectangle, Sender};
use dnd::DndSurface;
use mime::{AllowedMimeTypes, AsMimeTypes};
pub trait DndProvider {
/// Set up DnD operations for the Clipboard
fn init_dnd(
&self,
_tx: Box<dyn dnd::Sender<DndSurface> + Send + Sync + 'static>,
) {
}
/// Start a DnD operation on the given surface with some data
fn start_dnd<D: AsMimeTypes + Send + 'static>(
&self,
_internal: bool,
_source_surface: DndSurface,
_icon_surface: Option<DndSurface>,
_content: D,
_actions: DndAction,
) {
}
/// End the current DnD operation, if there is one
fn end_dnd(&self) {}
/// Register a surface for receiving DnD offers
/// Rectangles should be provided in order of decreasing priority.
/// This method can be called multiple time for a single surface if the
/// rectangles change.
fn register_dnd_destination(
&self,
_surface: DndSurface,
_rectangles: Vec<DndDestinationRectangle>,
) {
}
/// Set the final action after presenting the user with a choice
fn set_action(&self, _action: DndAction) {}
/// Peek at the contents of a DnD offer
fn peek_offer<D: AllowedMimeTypes + 'static>(
&self,
_mime_type: Cow<'static, str>,
) -> std::io::Result<D> {
Err(std::io::Error::new(
std::io::ErrorKind::Other,
"DnD not supported",
))
}
}
impl<C: DndProvider> DndProvider for crate::PlatformClipboard<C> {
fn init_dnd(
&self,
tx: Box<dyn Sender<DndSurface> + Send + Sync + 'static>,
) {
self.raw.init_dnd(tx);
}
fn start_dnd<D: AsMimeTypes + Send + 'static>(
&self,
internal: bool,
source_surface: DndSurface,
icon_surface: Option<DndSurface>,
content: D,
actions: DndAction,
) {
self.raw.start_dnd(
internal,
source_surface,
icon_surface,
content,
actions,
);
}
fn end_dnd(&self) {
self.raw.end_dnd();
}
fn register_dnd_destination(
&self,
surface: DndSurface,
rectangles: Vec<DndDestinationRectangle>,
) {
self.raw.register_dnd_destination(surface, rectangles);
}
fn set_action(&self, action: DndAction) {
self.raw.set_action(action);
}
fn peek_offer<D: AllowedMimeTypes + 'static>(
&self,
mime_type: Cow<'static, str>,
) -> std::io::Result<D> {
self.raw.peek_offer::<D>(mime_type)
}
}

View file

@ -48,6 +48,8 @@ mod platform;
#[path = "platform/dummy.rs"]
mod platform;
mod dnd;
use mime::ClipboardStoreData;
use raw_window_handle::HasDisplayHandle;
use std::error::Error;

View file

@ -1,10 +1,14 @@
use crate::{
dnd::DndProvider,
mime::{ClipboardLoadData, ClipboardStoreData},
ClipboardProvider,
};
use dnd::{DndAction, DndDestinationRectangle, DndSurface};
use mime::{AllowedMimeTypes, AsMimeTypes};
use raw_window_handle::{HasDisplayHandle, RawDisplayHandle};
use std::error::Error;
use std::{borrow::Cow, error::Error, sync::Arc};
use wayland::DndSender;
pub use clipboard_wayland as wayland;
pub use clipboard_x11 as x11;
@ -125,6 +129,78 @@ impl ClipboardProvider for Clipboard {
}
}
impl DndProvider for Clipboard {
fn init_dnd(
&self,
tx: Box<dyn dnd::Sender<DndSurface> + Send + Sync + 'static>,
) {
match self {
Clipboard::Wayland(c) => c.init_dnd(DndSender(Arc::new(tx))),
Clipboard::X11(_) => {}
}
}
fn start_dnd<D: AsMimeTypes + Send + 'static>(
&self,
internal: bool,
source_surface: DndSurface,
icon_surface: Option<DndSurface>,
content: D,
actions: DndAction,
) {
match self {
Clipboard::Wayland(c) => c.start_dnd(
internal,
source_surface,
icon_surface,
content,
actions,
),
Clipboard::X11(_) => {}
}
}
fn end_dnd(&self) {
match self {
Clipboard::Wayland(c) => c.end_dnd(),
Clipboard::X11(_) => {}
}
}
fn register_dnd_destination(
&self,
surface: DndSurface,
rectangles: Vec<DndDestinationRectangle>,
) {
match self {
Clipboard::Wayland(c) => {
c.register_dnd_destination(surface, rectangles)
}
Clipboard::X11(_) => {}
}
}
fn set_action(&self, action: DndAction) {
match self {
Clipboard::Wayland(c) => c.set_action(action),
Clipboard::X11(_) => {}
}
}
fn peek_offer<D: AllowedMimeTypes + 'static>(
&self,
mime_type: Cow<'static, str>,
) -> std::io::Result<D> {
match self {
Clipboard::Wayland(c) => c.peek_offer::<D>(mime_type),
Clipboard::X11(_) => Err(std::io::Error::new(
std::io::ErrorKind::Other,
"DnD not supported",
)),
}
}
}
pub unsafe fn connect<W: HasDisplayHandle>(
window: &W,
) -> Result<Clipboard, Box<dyn Error>> {