State
@@ -25,11 +27,10 @@ where pub fn new( mut program: P, bounds: Size, - cursor_position: Point, renderer: &mut P::Renderer, debug: &mut Debug, ) -> Self { - let mut user_interface = build_user_interface( + let user_interface = build_user_interface( &mut program, Cache::default(), renderer, @@ -44,6 +45,7 @@ where cache, queued_events: Vec::new(), queued_messages: Vec::new(), + mouse_interaction: mouse::Interaction::Idle, } } @@ -71,6 +73,11 @@ where self.queued_events.is_empty() && self.queued_messages.is_empty() } + /// Returns the current [`mouse::Interaction`] of the [`State`]. + pub fn mouse_interaction(&self) -> mouse::Interaction { + self.mouse_interaction + } + /// Processes all the queued events and messages, rebuilding and redrawing /// the widgets of the linked [`Program`] if necessary. /// @@ -109,7 +116,8 @@ where if messages.is_empty() { debug.draw_started(); - user_interface.draw(renderer, cursor_position); + self.mouse_interaction = + user_interface.draw(renderer, cursor_position); debug.draw_finished(); self.cache = Some(user_interface.into_cache()); @@ -140,7 +148,8 @@ where ); debug.draw_started(); - user_interface.draw(renderer, cursor_position); + self.mouse_interaction = + user_interface.draw(renderer, cursor_position); debug.draw_finished(); self.cache = Some(user_interface.into_cache()); diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs index 2f76c084..d9338524 100644 --- a/native/src/user_interface.rs +++ b/native/src/user_interface.rs @@ -1,5 +1,6 @@ use crate::event::{self, Event}; use crate::layout; +use crate::mouse; use crate::overlay; use crate::renderer; use crate::{Clipboard, Element, Layout, Point, Rectangle, Size, Vector}; @@ -330,7 +331,11 @@ where /// // Flush rendering operations... /// } /// ``` - pub fn draw(&mut self, renderer: &mut Renderer, cursor_position: Point) { + pub fn draw( + &mut self, + renderer: &mut Renderer, + cursor_position: Point, + ) -> mouse::Interaction { // TODO: Move to shell level (?) renderer.clear(); @@ -346,6 +351,12 @@ where renderer, ); + let mouse_interaction = overlay.mouse_interaction( + Layout::new(&layer.layout), + &viewport, + cursor_position, + ); + let overlay_bounds = layer.layout.bounds(); renderer.with_layer( @@ -363,12 +374,12 @@ where self.overlay = Some(layer); - Some(overlay_bounds) + Some((overlay_bounds, mouse_interaction)) } else { None }; - if let Some(overlay_bounds) = overlay { + if let Some((overlay_bounds, overlay_interaction)) = overlay { let base_cursor = if overlay_bounds.contains(cursor_position) { Point::new(-1.0, -1.0) } else { @@ -382,6 +393,8 @@ where base_cursor, &viewport, ); + + overlay_interaction } else { self.root.widget.draw( renderer, @@ -390,6 +403,12 @@ where cursor_position, &viewport, ); + + self.root.widget.mouse_interaction( + Layout::new(&self.base.layout), + &viewport, + cursor_position, + ) } } diff --git a/native/src/widget.rs b/native/src/widget.rs index 9a494771..9999701e 100644 --- a/native/src/widget.rs +++ b/native/src/widget.rs @@ -80,6 +80,7 @@ pub use tooltip::Tooltip; use crate::event::{self, Event}; use crate::layout; +use crate::mouse; use crate::overlay; use crate::renderer; use crate::{Clipboard, Hasher, Layout, Length, Point, Rectangle}; @@ -175,6 +176,18 @@ where event::Status::Ignored } + /// Returns the current [`mouse::Interaction`] of the [`Widget`]. + /// + /// By default, it returns [`mouse::Interaction::Idle`]. + fn mouse_interaction( + &self, + _layout: Layout<'_>, + _viewport: &Rectangle, + _cursor_position: Point, + ) -> mouse::Interaction { + mouse::Interaction::Idle + } + /// Returns the overlay of the [`Widget`], if there is any. fn overlay( &mut self, diff --git a/winit/src/application.rs b/winit/src/application.rs index 70562627..9d787933 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -5,6 +5,7 @@ pub use state::State; use crate::clipboard::{self, Clipboard}; use crate::conversion; +use crate::mouse; use crate::{ Color, Command, Debug, Error, Executor, Mode, Proxy, Runtime, Settings, Size, Subscription, @@ -252,9 +253,7 @@ async fn run_instance( &mut debug, )); - // TODO - // let mut mouse_interaction = mouse::Interaction::default(); - + let mut mouse_interaction = mouse::Interaction::default(); let mut events = Vec::new(); let mut messages = Vec::new(); @@ -317,9 +316,18 @@ async fn run_instance( } debug.draw_started(); - user_interface.draw(&mut renderer, state.cursor_position()); + let new_mouse_interaction = + user_interface.draw(&mut renderer, state.cursor_position()); debug.draw_finished(); + if new_mouse_interaction != mouse_interaction { + window.set_cursor_icon(conversion::mouse_interaction( + new_mouse_interaction, + )); + + mouse_interaction = new_mouse_interaction; + } + window.request_redraw(); } event::Event::PlatformSpecific(event::PlatformSpecific::MacOS( @@ -356,7 +364,16 @@ async fn run_instance( debug.layout_finished(); debug.draw_started(); - user_interface.draw(&mut renderer, state.cursor_position()); + let new_mouse_interaction = user_interface + .draw(&mut renderer, state.cursor_position()); + + if new_mouse_interaction != mouse_interaction { + window.set_cursor_icon(conversion::mouse_interaction( + new_mouse_interaction, + )); + + mouse_interaction = new_mouse_interaction; + } debug.draw_finished(); compositor.configure_surface(