From 67b4c7dbddab0b47d1a28a2bbc884f3a6f58a863 Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Wed, 30 Aug 2023 16:28:51 +0200 Subject: [PATCH 1/7] feat(renderer): define default icon color By default, this is the same as the text color for best visibility. --- core/src/renderer.rs | 3 +++ style/src/application.rs | 3 +++ style/src/button.rs | 3 +++ style/src/container.rs | 3 +++ style/src/theme.rs | 2 ++ style/src/theme/palette.rs | 10 ++++++++-- widget/src/button.rs | 1 + widget/src/container.rs | 3 +++ widget/src/pane_grid/title_bar.rs | 1 + widget/src/scrollable.rs | 12 ++++++------ widget/src/svg.rs | 16 ++++++++++++++-- widget/src/text_input/text_input.rs | 8 ++++++-- widget/src/text_input/text_input_wayland.rs | 8 ++++++-- widget/src/tooltip.rs | 1 + 14 files changed, 60 insertions(+), 14 deletions(-) diff --git a/core/src/renderer.rs b/core/src/renderer.rs index f6acc01937..e2649fa6fe 100644 --- a/core/src/renderer.rs +++ b/core/src/renderer.rs @@ -63,6 +63,8 @@ pub struct Quad { /// The styling attributes of a [`Renderer`]. #[derive(Debug, Clone, Copy, PartialEq)] pub struct Style { + /// The color to apply to symbolic icons. + pub icon_color: Color, /// The text color pub text_color: Color, /// The scale factor @@ -72,6 +74,7 @@ pub struct Style { impl Default for Style { fn default() -> Self { Style { + icon_color: Color::BLACK, text_color: Color::BLACK, scale_factor: 1.0, } diff --git a/style/src/application.rs b/style/src/application.rs index e9a1f4ff45..673178b801 100644 --- a/style/src/application.rs +++ b/style/src/application.rs @@ -18,6 +18,9 @@ pub struct Appearance { /// The background [`Color`] of the application. pub background_color: Color, + /// The default icon [`Color`] of the application. + pub icon_color: Color, + /// The default text [`Color`] of the application. pub text_color: Color, } diff --git a/style/src/button.rs b/style/src/button.rs index f46b34a183..f95b52947f 100644 --- a/style/src/button.rs +++ b/style/src/button.rs @@ -14,6 +14,8 @@ pub struct Appearance { pub border_width: f32, /// The border [`Color`] of the button. pub border_color: Color, + /// The icon [`Color`] of the button. + pub icon_color: Color, /// The text [`Color`] of the button. pub text_color: Color, } @@ -26,6 +28,7 @@ impl std::default::Default for Appearance { border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, + icon_color: Color::BLACK, text_color: Color::BLACK, } } diff --git a/style/src/container.rs b/style/src/container.rs index ec543ae4db..e31d9dcc7d 100644 --- a/style/src/container.rs +++ b/style/src/container.rs @@ -4,6 +4,8 @@ use iced_core::{Background, BorderRadius, Color}; /// The appearance of a container. #[derive(Debug, Clone, Copy)] pub struct Appearance { + /// The icon [`Color`] of the container. + pub icon_color: Option, /// The text [`Color`] of the container. pub text_color: Option, /// The [`Background`] of the container. @@ -19,6 +21,7 @@ pub struct Appearance { impl std::default::Default for Appearance { fn default() -> Self { Self { + icon_color: None, text_color: None, background: None, border_radius: 0.0.into(), diff --git a/style/src/theme.rs b/style/src/theme.rs index 644971814a..7d9555d71d 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -98,6 +98,7 @@ impl application::StyleSheet for Theme { match style { Application::Default => application::Appearance { background_color: palette.background.base.color, + icon_color: palette.background.base.icon, text_color: palette.background.base.text, }, Application::Custom(custom) => custom.appearance(self), @@ -381,6 +382,7 @@ impl container::StyleSheet for Theme { let palette = self.extended_palette(); container::Appearance { + icon_color: None, text_color: None, background: Some(palette.background.weak.color.into()), border_radius: 2.0.into(), diff --git a/style/src/theme/palette.rs b/style/src/theme/palette.rs index aaeb799df4..6c98d98ad5 100644 --- a/style/src/theme/palette.rs +++ b/style/src/theme/palette.rs @@ -117,12 +117,15 @@ impl Extended { } } -/// A pair of background and text colors. +/// Recommended background, icon, and text [`Color`]. #[derive(Debug, Clone, Copy, PartialEq)] pub struct Pair { /// The background color. pub color: Color, + /// The icon color, which defaults to the text color. + pub icon: Color, + /// The text color. /// /// It's guaranteed to be readable on top of the background [`color`]. @@ -134,9 +137,12 @@ pub struct Pair { impl Pair { /// Creates a new [`Pair`] from a background [`Color`] and some text [`Color`]. pub fn new(color: Color, text: Color) -> Self { + let text = readable(color, text); + Self { color, - text: readable(color, text), + icon: text, + text, } } } diff --git a/widget/src/button.rs b/widget/src/button.rs index d39847c832..ab58ec0a77 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -316,6 +316,7 @@ where renderer, theme, &renderer::Style { + icon_color: styling.icon_color, text_color: styling.text_color, scale_factor: renderer_style.scale_factor, }, diff --git a/widget/src/container.rs b/widget/src/container.rs index c9f27bab12..f44e66a6d0 100644 --- a/widget/src/container.rs +++ b/widget/src/container.rs @@ -253,6 +253,9 @@ where renderer, theme, &renderer::Style { + icon_color: style + .icon_color + .unwrap_or(renderer_style.text_color), text_color: style .text_color .unwrap_or(renderer_style.text_color), diff --git a/widget/src/pane_grid/title_bar.rs b/widget/src/pane_grid/title_bar.rs index 22114dac0b..da1cc29c0d 100644 --- a/widget/src/pane_grid/title_bar.rs +++ b/widget/src/pane_grid/title_bar.rs @@ -133,6 +133,7 @@ where let bounds = layout.bounds(); let style = theme.appearance(&self.style); let inherited_style = renderer::Style { + icon_color: style.icon_color.unwrap_or(inherited_style.icon_color), text_color: style.text_color.unwrap_or(inherited_style.text_color), scale_factor: inherited_style.scale_factor, }; diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs index a223cdf68d..11fc50d1e8 100644 --- a/widget/src/scrollable.rs +++ b/widget/src/scrollable.rs @@ -748,7 +748,7 @@ pub fn update( match event { touch::Event::FingerPressed { .. } => { let Some(cursor_position) = cursor.position() else { - return event::Status::Ignored + return event::Status::Ignored; }; state.scroll_area_touched_at = Some(cursor_position); @@ -758,7 +758,7 @@ pub fn update( state.scroll_area_touched_at { let Some(cursor_position) = cursor.position() else { - return event::Status::Ignored + return event::Status::Ignored; }; let delta = Vector::new( @@ -803,7 +803,7 @@ pub fn update( | Event::Touch(touch::Event::FingerMoved { .. }) => { if let Some(scrollbar) = scrollbars.y { let Some(cursor_position) = cursor.position() else { - return event::Status::Ignored + return event::Status::Ignored; }; state.scroll_y_to( @@ -833,7 +833,7 @@ pub fn update( Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) => { let Some(cursor_position) = cursor.position() else { - return event::Status::Ignored + return event::Status::Ignored; }; if let (Some(scroller_grabbed_at), Some(scrollbar)) = @@ -877,7 +877,7 @@ pub fn update( Event::Mouse(mouse::Event::CursorMoved { .. }) | Event::Touch(touch::Event::FingerMoved { .. }) => { let Some(cursor_position) = cursor.position() else { - return event::Status::Ignored + return event::Status::Ignored; }; if let Some(scrollbar) = scrollbars.x { @@ -908,7 +908,7 @@ pub fn update( Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) => { let Some(cursor_position) = cursor.position() else { - return event::Status::Ignored + return event::Status::Ignored; }; if let (Some(scroller_grabbed_at), Some(scrollbar)) = diff --git a/widget/src/svg.rs b/widget/src/svg.rs index 3fb280b9f7..c0d59c2140 100644 --- a/widget/src/svg.rs +++ b/widget/src/svg.rs @@ -39,6 +39,7 @@ where width: Length, height: Length, content_fit: ContentFit, + symbolic: bool, style: ::Style, _phantom_data: std::marker::PhantomData<&'a ()>, } @@ -62,6 +63,7 @@ where width: Length::Fill, height: Length::Shrink, content_fit: ContentFit::Contain, + symbolic: false, style: Default::default(), _phantom_data: std::marker::PhantomData, } @@ -99,6 +101,13 @@ where } } + /// Symbolic icons inherit their color from the renderer if a color is not defined. + #[must_use] + pub fn symbolic(mut self, symbolic: bool) -> Self { + self.symbolic = symbolic; + self + } + /// Sets the style variant of this [`Svg`]. #[must_use] pub fn style( @@ -196,7 +205,7 @@ where _state: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, - _style: &renderer::Style, + style: &renderer::Style, layout: Layout<'_>, _cursor: mouse::Cursor, _viewport: &Rectangle, @@ -219,7 +228,10 @@ where ..bounds }; - let appearance = theme.appearance(&self.style); + let mut appearance = theme.appearance(&self.style); + if self.symbolic && appearance.color.is_none() { + appearance.color = Some(style.icon_color); + } renderer.draw( self.handle.clone(), diff --git a/widget/src/text_input/text_input.rs b/widget/src/text_input/text_input.rs index 7605abfe22..cb5b965d98 100644 --- a/widget/src/text_input/text_input.rs +++ b/widget/src/text_input/text_input.rs @@ -668,7 +668,9 @@ where let state = state(); if let Some(focus) = &mut state.is_focused { - let Some(on_input) = on_input else { return event::Status::Ignored }; + let Some(on_input) = on_input else { + return event::Status::Ignored; + }; if state.is_pasting.is_none() && !state.keyboard_modifiers.command() @@ -691,7 +693,9 @@ where let state = state(); if let Some(focus) = &mut state.is_focused { - let Some(on_input) = on_input else { return event::Status::Ignored }; + let Some(on_input) = on_input else { + return event::Status::Ignored; + }; let modifiers = state.keyboard_modifiers; focus.updated_at = Instant::now(); diff --git a/widget/src/text_input/text_input_wayland.rs b/widget/src/text_input/text_input_wayland.rs index b041185fd0..e8cef9f2de 100644 --- a/widget/src/text_input/text_input_wayland.rs +++ b/widget/src/text_input/text_input_wayland.rs @@ -890,7 +890,9 @@ where let state = state(); if let Some(focus) = &mut state.is_focused { - let Some(on_input) = on_input else { return event::Status::Ignored }; + let Some(on_input) = on_input else { + return event::Status::Ignored; + }; if state.is_pasting.is_none() && !state.keyboard_modifiers.command() @@ -913,7 +915,9 @@ where let state = state(); if let Some(focus) = &mut state.is_focused { - let Some(on_input) = on_input else { return event::Status::Ignored }; + let Some(on_input) = on_input else { + return event::Status::Ignored; + }; let modifiers = state.keyboard_modifiers; focus.updated_at = Instant::now(); diff --git a/widget/src/tooltip.rs b/widget/src/tooltip.rs index ea07a3c2c0..efb4b24d15 100644 --- a/widget/src/tooltip.rs +++ b/widget/src/tooltip.rs @@ -420,6 +420,7 @@ where container::draw_background(renderer, &style, layout.bounds()); let defaults = renderer::Style { + icon_color: inherited_style.icon_color, text_color: style.text_color.unwrap_or(inherited_style.text_color), scale_factor: inherited_style.scale_factor, }; From c979c34b3d156e715c8209bdbc4e2175443ecad6 Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Wed, 30 Aug 2023 16:29:56 +0200 Subject: [PATCH 2/7] feat(winit): support icon color appearance Changes required to support the icon_color renderer setting. --- winit/src/application.rs | 2 ++ winit/src/application/state.rs | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/winit/src/application.rs b/winit/src/application.rs index d393dab94f..2c13b0b0c8 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -517,6 +517,7 @@ async fn run_instance( &mut renderer, state.theme(), &renderer::Style { + icon_color: state.icon_color(), text_color: state.text_color(), scale_factor: state.scale_factor(), }, @@ -682,6 +683,7 @@ async fn run_instance( &mut renderer, state.theme(), &renderer::Style { + icon_color: state.icon_color(), text_color: state.text_color(), scale_factor: state.scale_factor(), }, diff --git a/winit/src/application/state.rs b/winit/src/application/state.rs index e3295e605d..f590efc555 100644 --- a/winit/src/application/state.rs +++ b/winit/src/application/state.rs @@ -121,6 +121,11 @@ where self.appearance.background_color } + /// Returns the current icon [`Color`] of the [`State`]. + pub fn icon_color(&self) -> Color { + self.appearance.icon_color + } + /// Returns the current text [`Color`] of the [`State`]. pub fn text_color(&self) -> Color { self.appearance.text_color From 97a3fbfd7b3fd03111371e776b988a88efd2518f Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Wed, 30 Aug 2023 16:30:07 +0200 Subject: [PATCH 3/7] feat(sctk): support icon color appearance Changes required to support the icon_color renderer setting. --- sctk/src/application.rs | 23 ++++++++++++++++------- sctk/src/event_loop/mod.rs | 7 +------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/sctk/src/application.rs b/sctk/src/application.rs index 34d1c70f2e..cab42bdc17 100644 --- a/sctk/src/application.rs +++ b/sctk/src/application.rs @@ -631,7 +631,7 @@ where configure.new_size.1 as f64, ); } - + } } LayerSurfaceEventVariant::ScaleFactorChanged(sf, viewport) => { @@ -854,6 +854,7 @@ where &mut renderer, state.theme(), &Style { + icon_color: state.icon_color(), text_color: state.text_color(), scale_factor: state.scale_factor(), }, @@ -1012,10 +1013,11 @@ where has_events || !native_events.is_empty(); let (interface_state, statuses) = { - let Some(user_interface) = interfaces - .get_mut(&surface_id.inner()) else { - continue; - }; + let Some(user_interface) = + interfaces.get_mut(&surface_id.inner()) + else { + continue; + }; user_interface.update( native_events.as_slice(), cursor_position, @@ -1141,8 +1143,9 @@ where Instant::now(), ), ); - let Some(user_interface) = interfaces - .get_mut(&surface_id.inner()) else { + let Some(user_interface) = + interfaces.get_mut(&surface_id.inner()) + else { continue; }; let (interface_state, _) = user_interface.update( @@ -1306,6 +1309,7 @@ where &mut renderer, state.theme(), &Style { + icon_color: state.icon_color(), text_color: state.text_color(), scale_factor: state.scale_factor(), }, @@ -1725,6 +1729,11 @@ where self.appearance.background_color } + /// Returns the current icon [`Color`] of the [`State`]. + pub fn icon_color(&self) -> Color { + self.appearance.icon_color + } + /// Returns the current text [`Color`] of the [`State`]. pub fn text_color(&self) -> Color { self.appearance.text_color diff --git a/sctk/src/event_loop/mod.rs b/sctk/src/event_loop/mod.rs index 144406a24d..88c8752baf 100644 --- a/sctk/src/event_loop/mod.rs +++ b/sctk/src/event_loop/mod.rs @@ -43,11 +43,7 @@ use sctk::{ }, registry::RegistryState, seat::SeatState, - shell::{ - wlr_layer::LayerShell, - xdg::XdgShell, - WaylandSurface, - }, + shell::{wlr_layer::LayerShell, xdg::XdgShell, WaylandSurface}, shm::Shm, }; #[cfg(feature = "a11y")] @@ -680,7 +676,6 @@ where let wl_surface = layer_surface.surface.wl_surface(); if let Some(mut prev_configure) = layer_surface.last_configure.clone() { - prev_configure.new_size = (width.unwrap_or(prev_configure.new_size.0), width.unwrap_or(prev_configure.new_size.1)); sticky_exit_callback( IcedSctkEvent::SctkEvent(SctkEvent::LayerSurfaceEvent { variant: LayerSurfaceEventVariant::Configure(prev_configure, wl_surface.clone(), false), id: wl_surface.clone()}), From ab80fe81ae12dbcffe781287610d165189389c60 Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Thu, 31 Aug 2023 02:08:12 +0200 Subject: [PATCH 4/7] fix(button): inherit icon color if set to none --- style/src/button.rs | 4 ++-- widget/src/button.rs | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/style/src/button.rs b/style/src/button.rs index f95b52947f..04ea0ddbce 100644 --- a/style/src/button.rs +++ b/style/src/button.rs @@ -15,7 +15,7 @@ pub struct Appearance { /// The border [`Color`] of the button. pub border_color: Color, /// The icon [`Color`] of the button. - pub icon_color: Color, + pub icon_color: Option, /// The text [`Color`] of the button. pub text_color: Color, } @@ -28,7 +28,7 @@ impl std::default::Default for Appearance { border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, - icon_color: Color::BLACK, + icon_color: None, text_color: Color::BLACK, } } diff --git a/widget/src/button.rs b/widget/src/button.rs index ab58ec0a77..c069d7ff0a 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -316,7 +316,9 @@ where renderer, theme, &renderer::Style { - icon_color: styling.icon_color, + icon_color: styling + .icon_color + .unwrap_or(renderer_style.icon_color), text_color: styling.text_color, scale_factor: renderer_style.scale_factor, }, From 8b2389f144966a5f9b60ab778c1073748fee5e70 Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Fri, 1 Sep 2023 08:45:41 +0200 Subject: [PATCH 5/7] chore: error if neither winit or wayland feature is set --- Cargo.toml | 1 - src/lib.rs | 7 +++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 7d876472b8..6596e8e059 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,6 @@ keywords = ["gui", "ui", "graphics", "interface", "widgets"] categories = ["gui"] [features] -default = ["winit", "a11y"] # Enable the `wgpu` GPU-accelerated renderer backend wgpu = ["iced_renderer/wgpu"] # Enables the `Image` widget diff --git a/src/lib.rs b/src/lib.rs index 706081a785..09fc0e3d81 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -165,6 +165,13 @@ #![allow(clippy::inherent_to_string, clippy::type_complexity)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![cfg_attr(docsrs, feature(doc_cfg))] + +#[cfg(all(not(feature = "wayland"), not(feature = "winit")))] +compile_error!("must define `wayland` or `winit` feature"); + +#[cfg(all(feature = "wayland", feature = "winit"))] +compile_error!("cannot use `wayland` feature with `winit"); + pub use iced_futures::futures; use iced_widget::graphics; use iced_widget::renderer; From 497edfca17acd71d9fcfd6497259fec62b0c6d41 Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Thu, 7 Sep 2023 16:52:53 +0200 Subject: [PATCH 6/7] fix(widget): container inherited wrong icon color from renderer --- widget/src/container.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widget/src/container.rs b/widget/src/container.rs index f44e66a6d0..6ab9530ebc 100644 --- a/widget/src/container.rs +++ b/widget/src/container.rs @@ -255,7 +255,7 @@ where &renderer::Style { icon_color: style .icon_color - .unwrap_or(renderer_style.text_color), + .unwrap_or(renderer_style.icon_color), text_color: style .text_color .unwrap_or(renderer_style.text_color), From c7b345ec511c5fb2591f07a33ec5822ccc59db60 Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Tue, 12 Sep 2023 17:53:44 +0200 Subject: [PATCH 7/7] feat(mouse-area): added on_drag method --- widget/src/mouse_area.rs | 42 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/widget/src/mouse_area.rs b/widget/src/mouse_area.rs index 18efcebd03..785e545db3 100644 --- a/widget/src/mouse_area.rs +++ b/widget/src/mouse_area.rs @@ -1,6 +1,7 @@ //! A container for capturing mouse events. use iced_renderer::core::widget::OperationOutputWrapper; +use iced_renderer::core::Point; use crate::core::event::{self, Event}; use crate::core::layout; @@ -17,6 +18,7 @@ use crate::core::{ #[allow(missing_debug_implementations)] pub struct MouseArea<'a, Message, Renderer> { content: Element<'a, Message, Renderer>, + on_drag: Option, on_press: Option, on_release: Option, on_right_press: Option, @@ -26,6 +28,13 @@ pub struct MouseArea<'a, Message, Renderer> { } impl<'a, Message, Renderer> MouseArea<'a, Message, Renderer> { + /// The message to emit when a drag is initiated. + #[must_use] + pub fn on_drag(mut self, message: Message) -> Self { + self.on_drag = Some(message); + self + } + /// The message to emit on a left button press. #[must_use] pub fn on_press(mut self, message: Message) -> Self { @@ -73,6 +82,7 @@ impl<'a, Message, Renderer> MouseArea<'a, Message, Renderer> { #[derive(Default)] struct State { // TODO: Support on_mouse_enter and on_mouse_exit + drag_initiated: Option, } impl<'a, Message, Renderer> MouseArea<'a, Message, Renderer> { @@ -80,6 +90,7 @@ impl<'a, Message, Renderer> MouseArea<'a, Message, Renderer> { pub fn new(content: impl Into>) -> Self { MouseArea { content: content.into(), + on_drag: None, on_press: None, on_release: None, on_right_press: None, @@ -167,7 +178,14 @@ where return event::Status::Captured; } - update(self, &event, layout, cursor, shell) + update( + self, + &event, + layout, + cursor, + shell, + tree.state.downcast_mut::(), + ) } fn mouse_interaction( @@ -243,6 +261,7 @@ fn update( layout: Layout<'_>, cursor: mouse::Cursor, shell: &mut Shell<'_, Message>, + state: &mut State, ) -> event::Status { if !cursor.is_over(layout.bounds()) { return event::Status::Ignored; @@ -252,6 +271,7 @@ fn update( if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) = event { + state.drag_initiated = cursor.position(); shell.publish(message.clone()); return event::Status::Captured; @@ -262,6 +282,7 @@ fn update( if let Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) | Event::Touch(touch::Event::FingerLifted { .. }) = event { + state.drag_initiated = None; shell.publish(message.clone()); return event::Status::Captured; @@ -311,5 +332,24 @@ fn update( } } + if state.drag_initiated.is_none() && widget.on_drag.is_some() { + if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) + | Event::Touch(touch::Event::FingerPressed { .. }) = event + { + state.drag_initiated = cursor.position(); + } + } else if let Some((message, drag_source)) = + widget.on_drag.as_ref().zip(state.drag_initiated) + { + if let Some(position) = cursor.position() { + if position.distance(drag_source) > 1.0 { + state.drag_initiated = None; + shell.publish(message.clone()); + + return event::Status::Captured; + } + } + } + event::Status::Ignored }