Skip to content

Commit

Permalink
Define a IconSurface<E> for drag and drop instead of tuple, box dyn
Browse files Browse the repository at this point in the history
This makes it easier to add a field, and makes the handling of
upcasting/downcasting a more organized.
  • Loading branch information
ids1024 committed Jan 3, 2025
1 parent b48a5f3 commit b58c55d
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 28 deletions.
44 changes: 37 additions & 7 deletions core/src/clipboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,39 @@ use mime::{self, AllowedMimeTypes, AsMimeTypes, ClipboardStoreData};

use crate::{widget::tree::State, window, Element};

#[derive(Debug)]
pub struct IconSurface<E> {
pub element: E,
pub state: State,
}

pub type DynIconSurface = IconSurface<Box<dyn Any>>;

impl<T: 'static, R: 'static> IconSurface<Element<'static, (), T, R>> {
pub fn new(element: Element<'static, (), T, R>, state: State) -> Self {
Self { element, state }
}

fn upcast(self) -> DynIconSurface {
IconSurface {
element: Box::new(self.element),
state: self.state,
}
}
}

impl DynIconSurface {
/// Downcast `element` to concrete type `Element<(), T, R>`
///
/// Panics if type doesn't match
pub fn downcast<T: 'static, R: 'static>(self) -> IconSurface<Element<'static, (), T, R>> {
IconSurface {
element: *self.element.downcast().expect("drag-and-drop icon surface has invalid element type"),
state: self.state,
}
}
}

/// A buffer for short-term storage and transfer within and between
/// applications.
pub trait Clipboard {
Expand Down Expand Up @@ -53,7 +86,7 @@ pub trait Clipboard {
&mut self,
_internal: bool,
_source_surface: Option<DndSource>,
_icon_surface: Option<Box<dyn Any>>,
_icon_surface: Option<DynIconSurface>,
_content: Box<dyn AsMimeTypes + Send + 'static>,
_actions: DndAction,
) {
Expand Down Expand Up @@ -86,21 +119,18 @@ pub enum Kind {

/// Starts a DnD operation.
/// icon surface is a tuple of the icon element and optionally the icon element state.
pub fn start_dnd<T: 'static, R: 'static, M: 'static>(
pub fn start_dnd<T: 'static, R: 'static>(
clipboard: &mut dyn Clipboard,
internal: bool,
source_surface: Option<DndSource>,
icon_surface: Option<(Element<'static, M, T, R>, State)>,
icon_surface: Option<IconSurface<Element<'static, (), T, R>>>,
content: Box<dyn AsMimeTypes + Send + 'static>,
actions: DndAction,
) {
clipboard.start_dnd(
internal,
source_surface,
icon_surface.map(|i| {
let i: Box<dyn Any> = Box::new(i);
i
}),
icon_surface.map(IconSurface::upcast),
content,
actions,
);
Expand Down
6 changes: 3 additions & 3 deletions winit/src/clipboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use std::sync::Mutex;
use std::{any::Any, borrow::Cow};

use crate::core::clipboard::DndSource;
use crate::core::clipboard::{DndSource, DynIconSurface};
use crate::core::clipboard::Kind;
use std::sync::Arc;
use winit::dpi::LogicalSize;
Expand All @@ -26,7 +26,7 @@ pub struct Clipboard {
pub(crate) struct StartDnd {
pub(crate) internal: bool,
pub(crate) source_surface: Option<DndSource>,
pub(crate) icon_surface: Option<Box<dyn Any>>,
pub(crate) icon_surface: Option<DynIconSurface>,
pub(crate) content: Box<dyn mime::AsMimeTypes + Send + 'static>,
pub(crate) actions: DndAction,
}
Expand Down Expand Up @@ -261,7 +261,7 @@ impl crate::core::Clipboard for Clipboard {
&mut self,
internal: bool,
source_surface: Option<DndSource>,
icon_surface: Option<Box<dyn Any>>,
icon_surface: Option<DynIconSurface>,
content: Box<dyn mime::AsMimeTypes + Send + 'static>,
actions: DndAction,
) {
Expand Down
26 changes: 8 additions & 18 deletions winit/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -888,17 +888,7 @@ async fn run_instance<'a, P, C>(
let state = &window.state;
let icon_surface = icon_surface
.map(|i| {
let e = i.downcast::<(
core::Element<
'static,
(),
P::Theme,
P::Renderer,
>,
core::widget::tree::State,
)>()
.unwrap();
let (mut e, widget_state) = *e;
let mut icon_surface = i.downcast::<P::Theme, P::Renderer>();

let mut renderer = compositor.create_renderer();

Expand All @@ -913,16 +903,16 @@ async fn run_instance<'a, P, C>(
);

let mut tree = core::widget::Tree {
id: e.as_widget().id(),
tag: e.as_widget().tag(),
state: widget_state,
children: e.as_widget().children(),
id: icon_surface.element.as_widget().id(),
tag: icon_surface.element.as_widget().tag(),
state: icon_surface.state,
children: icon_surface.element.as_widget().children(),
};

let size = e
let size = icon_surface.element
.as_widget()
.layout(&mut tree, &renderer, &lim);
e.as_widget_mut().diff(&mut tree);
icon_surface.element.as_widget_mut().diff(&mut tree);

let size = lim.resolve(
Length::Shrink,
Expand All @@ -935,7 +925,7 @@ async fn run_instance<'a, P, C>(
);

let mut ui = UserInterface::build(
e,
icon_surface.element,
size,
user_interface::Cache::default(),
&mut renderer,
Expand Down

0 comments on commit b58c55d

Please sign in to comment.