From af9e353f5003cb323a46340acf1939123147a041 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 7 Jan 2025 13:56:58 -0800 Subject: [PATCH] dnd_source: Add suppport for surface offset The `drag_icon` callback is passed the offset of the cursor within the widget at the start of the drag, and can return an offset the drag surface should be placed relative to the cursor. --- iced | 2 +- src/widget/dnd_source.rs | 17 +++++++++++------ src/widget/text_input/input.rs | 3 ++- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/iced b/iced index 2cc6865c908..9ad04dadde7 160000 --- a/iced +++ b/iced @@ -1 +1 @@ -Subproject commit 2cc6865c908d025e43d7fc937f6b67defd51ea18 +Subproject commit 9ad04dadde75ac4b445602fc6f31e05d7b7003c3 diff --git a/src/widget/dnd_source.rs b/src/widget/dnd_source.rs index 38b921ee154..d57e099ba3f 100644 --- a/src/widget/dnd_source.rs +++ b/src/widget/dnd_source.rs @@ -32,7 +32,7 @@ pub struct DndSource<'a, Message, D> { container: Element<'a, Message>, window: Option, drag_content: Option D>>, - drag_icon: Option (Element<'static, ()>, tree::State)>>, + drag_icon: Option (Element<'static, ()>, tree::State, Vector)>>, on_start: Option, on_cancelled: Option, on_finish: Option, @@ -90,7 +90,7 @@ impl< #[must_use] pub fn drag_icon( mut self, - f: impl Fn() -> (Element<'static, ()>, tree::State) + 'static, + f: impl Fn(Vector) -> (Element<'static, ()>, tree::State, Vector) + 'static, ) -> Self { self.drag_icon = Some(Box::new(f)); self @@ -102,7 +102,7 @@ impl< self } - pub fn start_dnd(&self, clipboard: &mut dyn Clipboard, bounds: Rectangle) { + pub fn start_dnd(&self, clipboard: &mut dyn Clipboard, bounds: Rectangle, offset: Vector) { let Some(content) = self.drag_content.as_ref().map(|f| f()) else { return; }; @@ -116,13 +116,14 @@ impl< Some(iced_core::clipboard::DndSource::Widget(self.id.clone())) }, self.drag_icon.as_ref().map(|f| { - let (icon, state) = f(); - ( + let (icon, state, offset) = f(offset); + iced_core::clipboard::IconSurface::new( container(icon) .width(Length::Fixed(bounds.width)) .height(Length::Fixed(bounds.height)) .into(), state, + offset, ) }), Box::new(content), @@ -262,7 +263,11 @@ impl< if let Some(on_start) = self.on_start.as_ref() { shell.publish(on_start.clone()) } - self.start_dnd(clipboard, state.cached_bounds); + let offset = Vector::new( + left_pressed_position.x - layout.bounds().x, + left_pressed_position.y - layout.bounds().y, + ); + self.start_dnd(clipboard, state.cached_bounds, offset); state.is_dragging = true; state.left_pressed_position = None; } diff --git a/src/widget/text_input/input.rs b/src/widget/text_input/input.rs index 80bd8b54094..0ff27127a73 100644 --- a/src/widget/text_input/input.rs +++ b/src/widget/text_input/input.rs @@ -1350,12 +1350,13 @@ where clipboard, false, id.map(|id| iced_core::clipboard::DndSource::Widget(id)), - Some(( + Some(iced_core::clipboard::IconSurface::new( Element::from( TextInput::<'static, ()>::new("", input_text.clone()) .dnd_icon(true), ), iced_core::widget::tree::State::new(state_clone), + Vector::ZERO, )), Box::new(TextInputString(input_text)), DndAction::Move,