Extend cursor availability to the shell level

This commit is contained in:
Héctor Ramón Jiménez 2023-06-08 20:35:40 +02:00
parent 57db196c3a
commit aba98e4965
No known key found for this signature in database
GPG key ID: 140CC052C94F138E
6 changed files with 73 additions and 49 deletions

View file

@ -1,12 +1,13 @@
use crate::{Point, Rectangle, Vector}; use crate::{Point, Rectangle, Vector};
/// The mouse cursor state. /// The mouse cursor state.
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq, Default)]
pub enum Cursor { pub enum Cursor {
/// The cursor has a defined position. /// The cursor has a defined position.
Available(Point), Available(Point),
/// The cursor is currently unavailable (i.e. out of bounds or busy). /// The cursor is currently unavailable (i.e. out of bounds or busy).
#[default]
Unavailable, Unavailable,
} }

View file

@ -6,6 +6,7 @@ use scene::Scene;
use iced_wgpu::graphics::Viewport; use iced_wgpu::graphics::Viewport;
use iced_wgpu::{wgpu, Backend, Renderer, Settings}; use iced_wgpu::{wgpu, Backend, Renderer, Settings};
use iced_winit::core::mouse;
use iced_winit::core::renderer; use iced_winit::core::renderer;
use iced_winit::core::{Color, Size}; use iced_winit::core::{Color, Size};
use iced_winit::runtime::program; use iced_winit::runtime::program;
@ -194,10 +195,10 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
// We update iced // We update iced
let _ = state.update( let _ = state.update(
viewport.logical_size(), viewport.logical_size(),
conversion::cursor_position( mouse::Cursor::Available(conversion::cursor_position(
cursor_position, cursor_position,
viewport.scale_factor(), viewport.scale_factor(),
), )),
&mut renderer, &mut renderer,
&Theme::Dark, &Theme::Dark,
&renderer::Style { text_color: Color::WHITE }, &renderer::Style { text_color: Color::WHITE },

View file

@ -1,7 +1,7 @@
use crate::core::event::{self, Event}; use crate::core::event::{self, Event};
use crate::core::mouse; use crate::core::mouse;
use crate::core::renderer; use crate::core::renderer;
use crate::core::{Clipboard, Point, Size}; use crate::core::{Clipboard, Size};
use crate::user_interface::{self, UserInterface}; use crate::user_interface::{self, UserInterface};
use crate::{Command, Debug, Program}; use crate::{Command, Debug, Program};
@ -88,7 +88,7 @@ where
pub fn update( pub fn update(
&mut self, &mut self,
bounds: Size, bounds: Size,
cursor_position: Point, cursor: mouse::Cursor,
renderer: &mut P::Renderer, renderer: &mut P::Renderer,
theme: &<P::Renderer as iced_core::Renderer>::Theme, theme: &<P::Renderer as iced_core::Renderer>::Theme,
style: &renderer::Style, style: &renderer::Style,
@ -108,7 +108,7 @@ where
let (_, event_statuses) = user_interface.update( let (_, event_statuses) = user_interface.update(
&self.queued_events, &self.queued_events,
cursor_position, cursor,
renderer, renderer,
clipboard, clipboard,
&mut messages, &mut messages,
@ -131,7 +131,7 @@ where
let command = if messages.is_empty() { let command = if messages.is_empty() {
debug.draw_started(); debug.draw_started();
self.mouse_interaction = self.mouse_interaction =
user_interface.draw(renderer, theme, style, cursor_position); user_interface.draw(renderer, theme, style, cursor);
debug.draw_finished(); debug.draw_finished();
self.cache = Some(user_interface.into_cache()); self.cache = Some(user_interface.into_cache());
@ -163,7 +163,7 @@ where
debug.draw_started(); debug.draw_started();
self.mouse_interaction = self.mouse_interaction =
user_interface.draw(renderer, theme, style, cursor_position); user_interface.draw(renderer, theme, style, cursor);
debug.draw_finished(); debug.draw_finished();
self.cache = Some(user_interface.into_cache()); self.cache = Some(user_interface.into_cache());

View file

@ -5,7 +5,7 @@ use crate::core::mouse;
use crate::core::renderer; use crate::core::renderer;
use crate::core::widget; use crate::core::widget;
use crate::core::window; use crate::core::window;
use crate::core::{Clipboard, Point, Rectangle, Size, Vector}; use crate::core::{Clipboard, Rectangle, Size, Vector};
use crate::core::{Element, Layout, Shell}; use crate::core::{Element, Layout, Shell};
/// A set of interactive graphical elements with a specific [`Layout`]. /// A set of interactive graphical elements with a specific [`Layout`].
@ -128,7 +128,9 @@ where
/// # pub fn view(&self) -> iced_core::Element<(), Renderer> { unimplemented!() } /// # pub fn view(&self) -> iced_core::Element<(), Renderer> { unimplemented!() }
/// # pub fn update(&mut self, _: ()) {} /// # pub fn update(&mut self, _: ()) {}
/// # } /// # }
/// use iced_runtime::core::{clipboard, Size, Point}; /// use iced_runtime::core::clipboard;
/// use iced_runtime::core::mouse;
/// use iced_runtime::core::Size;
/// use iced_runtime::user_interface::{self, UserInterface}; /// use iced_runtime::user_interface::{self, UserInterface};
/// use iced_wgpu::Renderer; /// use iced_wgpu::Renderer;
/// ///
@ -136,7 +138,7 @@ where
/// let mut cache = user_interface::Cache::new(); /// let mut cache = user_interface::Cache::new();
/// let mut renderer = Renderer::new(); /// let mut renderer = Renderer::new();
/// let mut window_size = Size::new(1024.0, 768.0); /// let mut window_size = Size::new(1024.0, 768.0);
/// let mut cursor_position = Point::default(); /// let mut cursor = mouse::Cursor::default();
/// let mut clipboard = clipboard::Null; /// let mut clipboard = clipboard::Null;
/// ///
/// // Initialize our event storage /// // Initialize our event storage
@ -156,7 +158,7 @@ where
/// // Update the user interface /// // Update the user interface
/// let (state, event_statuses) = user_interface.update( /// let (state, event_statuses) = user_interface.update(
/// &events, /// &events,
/// cursor_position, /// cursor,
/// &mut renderer, /// &mut renderer,
/// &mut clipboard, /// &mut clipboard,
/// &mut messages /// &mut messages
@ -173,7 +175,7 @@ where
pub fn update( pub fn update(
&mut self, &mut self,
events: &[Event], events: &[Event],
cursor_position: Point, cursor: mouse::Cursor,
renderer: &mut Renderer, renderer: &mut Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, messages: &mut Vec<Message>,
@ -203,7 +205,7 @@ where
let event_status = overlay.on_event( let event_status = overlay.on_event(
event, event,
Layout::new(&layout), Layout::new(&layout),
mouse::Cursor::Available(cursor_position), cursor,
renderer, renderer,
clipboard, clipboard,
&mut shell, &mut shell,
@ -255,19 +257,22 @@ where
let base_cursor = manual_overlay let base_cursor = manual_overlay
.as_ref() .as_ref()
.filter(|overlay| { .filter(|overlay| {
overlay.is_over(Layout::new(&layout), cursor_position) cursor
.position()
.map(|cursor_position| {
overlay
.is_over(Layout::new(&layout), cursor_position)
})
.unwrap_or_default()
}) })
.map(|_| mouse::Cursor::Unavailable) .map(|_| mouse::Cursor::Unavailable)
.unwrap_or(mouse::Cursor::Available(cursor_position)); .unwrap_or(cursor);
self.overlay = Some(layout); self.overlay = Some(layout);
(base_cursor, event_statuses) (base_cursor, event_statuses)
} else { } else {
( (cursor, vec![event::Status::Ignored; events.len()])
mouse::Cursor::Available(cursor_position),
vec![event::Status::Ignored; events.len()],
)
}; };
let _ = ManuallyDrop::into_inner(manual_overlay); let _ = ManuallyDrop::into_inner(manual_overlay);
@ -359,8 +364,9 @@ where
/// # pub fn update(&mut self, _: ()) {} /// # pub fn update(&mut self, _: ()) {}
/// # } /// # }
/// use iced_runtime::core::clipboard; /// use iced_runtime::core::clipboard;
/// use iced_runtime::core::mouse;
/// use iced_runtime::core::renderer; /// use iced_runtime::core::renderer;
/// use iced_runtime::core::{Element, Size, Point}; /// use iced_runtime::core::{Element, Size};
/// use iced_runtime::user_interface::{self, UserInterface}; /// use iced_runtime::user_interface::{self, UserInterface};
/// use iced_wgpu::{Renderer, Theme}; /// use iced_wgpu::{Renderer, Theme};
/// ///
@ -368,7 +374,7 @@ where
/// let mut cache = user_interface::Cache::new(); /// let mut cache = user_interface::Cache::new();
/// let mut renderer = Renderer::new(); /// let mut renderer = Renderer::new();
/// let mut window_size = Size::new(1024.0, 768.0); /// let mut window_size = Size::new(1024.0, 768.0);
/// let mut cursor_position = Point::default(); /// let mut cursor = mouse::Cursor::default();
/// let mut clipboard = clipboard::Null; /// let mut clipboard = clipboard::Null;
/// let mut events = Vec::new(); /// let mut events = Vec::new();
/// let mut messages = Vec::new(); /// let mut messages = Vec::new();
@ -387,14 +393,14 @@ where
/// // Update the user interface /// // Update the user interface
/// let event_statuses = user_interface.update( /// let event_statuses = user_interface.update(
/// &events, /// &events,
/// cursor_position, /// cursor,
/// &mut renderer, /// &mut renderer,
/// &mut clipboard, /// &mut clipboard,
/// &mut messages /// &mut messages
/// ); /// );
/// ///
/// // Draw the user interface /// // Draw the user interface
/// let mouse_cursor = user_interface.draw(&mut renderer, &theme, &renderer::Style::default(), cursor_position); /// let mouse_interaction = user_interface.draw(&mut renderer, &theme, &renderer::Style::default(), cursor);
/// ///
/// cache = user_interface.into_cache(); /// cache = user_interface.into_cache();
/// ///
@ -411,7 +417,7 @@ where
renderer: &mut Renderer, renderer: &mut Renderer,
theme: &Renderer::Theme, theme: &Renderer::Theme,
style: &renderer::Style, style: &renderer::Style,
cursor_position: Point, cursor: mouse::Cursor,
) -> mouse::Interaction { ) -> mouse::Interaction {
// TODO: Move to shell level (?) // TODO: Move to shell level (?)
renderer.clear(); renderer.clear();
@ -427,19 +433,24 @@ where
overlay.layout(renderer, self.bounds, Vector::ZERO) overlay.layout(renderer, self.bounds, Vector::ZERO)
}); });
let cursor = if overlay let cursor = if cursor
.is_over(Layout::new(&overlay_layout), cursor_position) .position()
.map(|cursor_position| {
overlay
.is_over(Layout::new(&overlay_layout), cursor_position)
})
.unwrap_or_default()
{ {
mouse::Cursor::Unavailable mouse::Cursor::Unavailable
} else { } else {
mouse::Cursor::Available(cursor_position) cursor
}; };
self.overlay = Some(overlay_layout); self.overlay = Some(overlay_layout);
cursor cursor
} else { } else {
mouse::Cursor::Available(cursor_position) cursor
}; };
self.root.as_widget().draw( self.root.as_widget().draw(
@ -480,7 +491,7 @@ where
.map(|overlay| { .map(|overlay| {
let overlay_interaction = overlay.mouse_interaction( let overlay_interaction = overlay.mouse_interaction(
Layout::new(layout), Layout::new(layout),
mouse::Cursor::Available(cursor_position), cursor,
&viewport, &viewport,
renderer, renderer,
); );
@ -493,11 +504,19 @@ where
theme, theme,
style, style,
Layout::new(layout), Layout::new(layout),
mouse::Cursor::Available(cursor_position), cursor,
); );
}); });
if overlay.is_over(Layout::new(layout), cursor_position) if cursor
.position()
.map(|cursor_position| {
overlay.is_over(
Layout::new(layout),
cursor_position,
)
})
.unwrap_or_default()
{ {
overlay_interaction overlay_interaction
} else { } else {

View file

@ -356,7 +356,7 @@ async fn run_instance<A, E, C>(
let (interface_state, statuses) = user_interface.update( let (interface_state, statuses) = user_interface.update(
&events, &events,
state.cursor_position(), state.cursor(),
&mut renderer, &mut renderer,
&mut clipboard, &mut clipboard,
&mut messages, &mut messages,
@ -422,7 +422,7 @@ async fn run_instance<A, E, C>(
let (interface_state, _) = user_interface.update( let (interface_state, _) = user_interface.update(
&[redraw_event.clone()], &[redraw_event.clone()],
state.cursor_position(), state.cursor(),
&mut renderer, &mut renderer,
&mut clipboard, &mut clipboard,
&mut messages, &mut messages,
@ -435,7 +435,7 @@ async fn run_instance<A, E, C>(
&renderer::Style { &renderer::Style {
text_color: state.text_color(), text_color: state.text_color(),
}, },
state.cursor_position(), state.cursor(),
); );
debug.draw_finished(); debug.draw_finished();
@ -508,7 +508,7 @@ async fn run_instance<A, E, C>(
&renderer::Style { &renderer::Style {
text_color: state.text_color(), text_color: state.text_color(),
}, },
state.cursor_position(), state.cursor(),
); );
if new_mouse_interaction != mouse_interaction { if new_mouse_interaction != mouse_interaction {

View file

@ -1,7 +1,8 @@
use crate::application::{self, StyleSheet as _}; use crate::application::{self, StyleSheet as _};
use crate::conversion; use crate::conversion;
use crate::core; use crate::core;
use crate::core::{Color, Point, Size}; use crate::core::mouse;
use crate::core::{Color, Size};
use crate::graphics::Viewport; use crate::graphics::Viewport;
use crate::runtime::Debug; use crate::runtime::Debug;
use crate::Application; use crate::Application;
@ -20,7 +21,7 @@ where
scale_factor: f64, scale_factor: f64,
viewport: Viewport, viewport: Viewport,
viewport_version: usize, viewport_version: usize,
cursor_position: winit::dpi::PhysicalPosition<f64>, cursor_position: Option<winit::dpi::PhysicalPosition<f64>>,
modifiers: winit::event::ModifiersState, modifiers: winit::event::ModifiersState,
theme: <A::Renderer as core::Renderer>::Theme, theme: <A::Renderer as core::Renderer>::Theme,
appearance: application::Appearance, appearance: application::Appearance,
@ -52,8 +53,7 @@ where
scale_factor, scale_factor,
viewport, viewport,
viewport_version: 0, viewport_version: 0,
// TODO: Encode cursor availability in the type-system cursor_position: None,
cursor_position: winit::dpi::PhysicalPosition::new(-1.0, -1.0),
modifiers: winit::event::ModifiersState::default(), modifiers: winit::event::ModifiersState::default(),
theme, theme,
appearance, appearance,
@ -89,11 +89,16 @@ where
} }
/// Returns the current cursor position of the [`State`]. /// Returns the current cursor position of the [`State`].
pub fn cursor_position(&self) -> Point { pub fn cursor(&self) -> mouse::Cursor {
conversion::cursor_position( self.cursor_position
self.cursor_position, .map(|cursor_position| {
self.viewport.scale_factor(), conversion::cursor_position(
) cursor_position,
self.viewport.scale_factor(),
)
})
.map(mouse::Cursor::Available)
.unwrap_or(mouse::Cursor::Unavailable)
} }
/// Returns the current keyboard modifiers of the [`State`]. /// Returns the current keyboard modifiers of the [`State`].
@ -153,12 +158,10 @@ where
| WindowEvent::Touch(Touch { | WindowEvent::Touch(Touch {
location: position, .. location: position, ..
}) => { }) => {
self.cursor_position = *position; self.cursor_position = Some(*position);
} }
WindowEvent::CursorLeft { .. } => { WindowEvent::CursorLeft { .. } => {
// TODO: Encode cursor availability in the type-system self.cursor_position = None;
self.cursor_position =
winit::dpi::PhysicalPosition::new(-1.0, -1.0);
} }
WindowEvent::ModifiersChanged(new_modifiers) => { WindowEvent::ModifiersChanged(new_modifiers) => {
self.modifiers = *new_modifiers; self.modifiers = *new_modifiers;