diff --git a/core/src/clipboard.rs b/core/src/clipboard.rs index 1ea53145e6..160ca46f07 100644 --- a/core/src/clipboard.rs +++ b/core/src/clipboard.rs @@ -7,6 +7,39 @@ use mime::{self, AllowedMimeTypes, AsMimeTypes, ClipboardStoreData}; use crate::{widget::tree::State, window, Element}; +#[derive(Debug)] +pub struct IconSurface { + pub element: E, + pub state: State, +} + +pub type DynIconSurface = IconSurface>; + +impl IconSurface> { + 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(self) -> IconSurface> { + 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 { @@ -53,7 +86,7 @@ pub trait Clipboard { &mut self, _internal: bool, _source_surface: Option, - _icon_surface: Option>, + _icon_surface: Option, _content: Box, _actions: DndAction, ) { @@ -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( +pub fn start_dnd( clipboard: &mut dyn Clipboard, internal: bool, source_surface: Option, - icon_surface: Option<(Element<'static, M, T, R>, State)>, + icon_surface: Option>>, content: Box, actions: DndAction, ) { clipboard.start_dnd( internal, source_surface, - icon_surface.map(|i| { - let i: Box = Box::new(i); - i - }), + icon_surface.map(IconSurface::upcast), content, actions, ); diff --git a/winit/src/clipboard.rs b/winit/src/clipboard.rs index 26381d2554..097e65ca1e 100644 --- a/winit/src/clipboard.rs +++ b/winit/src/clipboard.rs @@ -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; @@ -26,7 +26,7 @@ pub struct Clipboard { pub(crate) struct StartDnd { pub(crate) internal: bool, pub(crate) source_surface: Option, - pub(crate) icon_surface: Option>, + pub(crate) icon_surface: Option, pub(crate) content: Box, pub(crate) actions: DndAction, } @@ -261,7 +261,7 @@ impl crate::core::Clipboard for Clipboard { &mut self, internal: bool, source_surface: Option, - icon_surface: Option>, + icon_surface: Option, content: Box, actions: DndAction, ) { diff --git a/winit/src/program.rs b/winit/src/program.rs index 28254304e9..c9de2e2bd5 100644 --- a/winit/src/program.rs +++ b/winit/src/program.rs @@ -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::(); let mut renderer = compositor.create_renderer(); @@ -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, @@ -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,