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 2cc6865c..9ad04dad 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 38b921ee..d57e099b 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 80bd8b54..0ff27127 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,