diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/src/overlay/nested.rs | 76 | ||||
-rw-r--r-- | runtime/src/task.rs | 63 | ||||
-rw-r--r-- | runtime/src/user_interface.rs | 10 | ||||
-rw-r--r-- | runtime/src/window.rs | 6 | ||||
-rw-r--r-- | runtime/src/window/screenshot.rs | 108 |
5 files changed, 84 insertions, 179 deletions
diff --git a/runtime/src/overlay/nested.rs b/runtime/src/overlay/nested.rs index da3e6929..342ad70c 100644 --- a/runtime/src/overlay/nested.rs +++ b/runtime/src/overlay/nested.rs @@ -158,7 +158,7 @@ where } /// Processes a runtime [`Event`]. - pub fn on_event( + pub fn update( &mut self, event: Event, layout: Layout<'_>, @@ -166,7 +166,7 @@ where renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, - ) -> event::Status { + ) { fn recurse<Message, Theme, Renderer>( element: &mut overlay::Element<'_, Message, Theme, Renderer>, layout: Layout<'_>, @@ -175,31 +175,30 @@ where renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, - ) -> (event::Status, bool) + ) -> bool where Renderer: renderer::Renderer, { let mut layouts = layout.children(); if let Some(layout) = layouts.next() { - let (nested_status, nested_is_over) = - if let Some((mut nested, nested_layout)) = - element.overlay(layout, renderer).zip(layouts.next()) - { - recurse( - &mut nested, - nested_layout, - event.clone(), - cursor, - renderer, - clipboard, - shell, - ) - } else { - (event::Status::Ignored, false) - }; + let nested_is_over = if let Some((mut nested, nested_layout)) = + element.overlay(layout, renderer).zip(layouts.next()) + { + recurse( + &mut nested, + nested_layout, + event.clone(), + cursor, + renderer, + clipboard, + shell, + ) + } else { + false + }; - if matches!(nested_status, event::Status::Ignored) { + if shell.event_status() == event::Status::Ignored { let is_over = nested_is_over || cursor .position() @@ -212,30 +211,29 @@ where }) .unwrap_or_default(); - ( - element.on_event( - event, - layout, - if nested_is_over { - mouse::Cursor::Unavailable - } else { - cursor - }, - renderer, - clipboard, - shell, - ), - is_over, - ) + element.update( + event, + layout, + if nested_is_over { + mouse::Cursor::Unavailable + } else { + cursor + }, + renderer, + clipboard, + shell, + ); + + is_over } else { - (nested_status, nested_is_over) + nested_is_over } } else { - (event::Status::Ignored, false) + false } } - let (status, _) = recurse( + let _ = recurse( &mut self.overlay, layout, event, @@ -244,8 +242,6 @@ where clipboard, shell, ); - - status } /// Returns the current [`mouse::Interaction`] of the [`Nested`] overlay. diff --git a/runtime/src/task.rs b/runtime/src/task.rs index 4554c74b..22cfb63e 100644 --- a/runtime/src/task.rs +++ b/runtime/src/task.rs @@ -9,6 +9,7 @@ use crate::futures::{boxed_stream, BoxStream, MaybeSend}; use crate::Action; use std::future::Future; +use std::sync::Arc; /// A set of concurrent actions to be performed by the iced runtime. /// @@ -183,16 +184,16 @@ impl<T> Task<T> { ( Self(Some(boxed_stream(stream))), Handle { - raw: Some(handle), - abort_on_drop: false, + internal: InternalHandle::Manual(handle), }, ) } None => ( Self(None), Handle { - raw: None, - abort_on_drop: false, + internal: InternalHandle::Manual( + stream::AbortHandle::new_pair().0, + ), }, ), } @@ -220,44 +221,64 @@ impl<T> Task<T> { /// A handle to a [`Task`] that can be used for aborting it. #[derive(Debug, Clone)] pub struct Handle { - raw: Option<stream::AbortHandle>, - abort_on_drop: bool, + internal: InternalHandle, +} + +#[derive(Debug, Clone)] +enum InternalHandle { + Manual(stream::AbortHandle), + AbortOnDrop(Arc<stream::AbortHandle>), +} + +impl InternalHandle { + pub fn as_ref(&self) -> &stream::AbortHandle { + match self { + InternalHandle::Manual(handle) => handle, + InternalHandle::AbortOnDrop(handle) => handle.as_ref(), + } + } } impl Handle { /// Aborts the [`Task`] of this [`Handle`]. pub fn abort(&self) { - if let Some(handle) = &self.raw { - handle.abort(); - } + self.internal.as_ref().abort(); } /// Returns a new [`Handle`] that will call [`Handle::abort`] whenever - /// it is dropped. + /// all of its instances are dropped. + /// + /// If a [`Handle`] is cloned, [`Handle::abort`] will only be called + /// once all of the clones are dropped. /// /// This can be really useful if you do not want to worry about calling /// [`Handle::abort`] yourself. - pub fn abort_on_drop(mut self) -> Self { - Self { - raw: self.raw.take(), - abort_on_drop: true, + pub fn abort_on_drop(self) -> Self { + match &self.internal { + InternalHandle::Manual(handle) => Self { + internal: InternalHandle::AbortOnDrop(Arc::new(handle.clone())), + }, + InternalHandle::AbortOnDrop(_) => self, } } /// Returns `true` if the [`Task`] of this [`Handle`] has been aborted. pub fn is_aborted(&self) -> bool { - if let Some(handle) = &self.raw { - handle.is_aborted() - } else { - true - } + self.internal.as_ref().is_aborted() } } impl Drop for Handle { fn drop(&mut self) { - if self.abort_on_drop { - self.abort(); + if let InternalHandle::AbortOnDrop(handle) = &mut self.internal { + let handle = std::mem::replace( + handle, + Arc::new(stream::AbortHandle::new_pair().0), + ); + + if let Some(handle) = Arc::into_inner(handle) { + handle.abort(); + } } } } diff --git a/runtime/src/user_interface.rs b/runtime/src/user_interface.rs index 8dfc97a7..b2826f71 100644 --- a/runtime/src/user_interface.rs +++ b/runtime/src/user_interface.rs @@ -210,7 +210,7 @@ where for event in events.iter().cloned() { let mut shell = Shell::new(messages); - let event_status = overlay.on_event( + overlay.update( event, Layout::new(&layout), cursor, @@ -219,7 +219,7 @@ where &mut shell, ); - event_statuses.push(event_status); + event_statuses.push(shell.event_status()); match (redraw_request, shell.redraw_request()) { (None, Some(at)) => { @@ -308,7 +308,7 @@ where let mut shell = Shell::new(messages); - let event_status = self.root.as_widget_mut().on_event( + self.root.as_widget_mut().update( &mut self.state, event, Layout::new(&self.base), @@ -319,7 +319,7 @@ where &viewport, ); - if matches!(event_status, event::Status::Captured) { + if shell.event_status() == event::Status::Captured { self.overlay = None; } @@ -347,7 +347,7 @@ where outdated = true; } - event_status.merge(overlay_status) + shell.event_status().merge(overlay_status) }) .collect(); diff --git a/runtime/src/window.rs b/runtime/src/window.rs index 382f4518..0ebdba2f 100644 --- a/runtime/src/window.rs +++ b/runtime/src/window.rs @@ -1,11 +1,7 @@ //! Build window-based GUI applications. -pub mod screenshot; - -pub use screenshot::Screenshot; - use crate::core::time::Instant; use crate::core::window::{ - Event, Icon, Id, Level, Mode, Settings, UserAttention, + Event, Icon, Id, Level, Mode, Screenshot, Settings, UserAttention, }; use crate::core::{Point, Size}; use crate::futures::event; diff --git a/runtime/src/window/screenshot.rs b/runtime/src/window/screenshot.rs deleted file mode 100644 index d9adbc01..00000000 --- a/runtime/src/window/screenshot.rs +++ /dev/null @@ -1,108 +0,0 @@ -//! Take screenshots of a window. -use crate::core::{Rectangle, Size}; - -use bytes::Bytes; -use std::fmt::{Debug, Formatter}; - -/// Data of a screenshot, captured with `window::screenshot()`. -/// -/// The `bytes` of this screenshot will always be ordered as `RGBA` in the `sRGB` color space. -#[derive(Clone)] -pub struct Screenshot { - /// The bytes of the [`Screenshot`]. - pub bytes: Bytes, - /// The size of the [`Screenshot`] in physical pixels. - pub size: Size<u32>, - /// The scale factor of the [`Screenshot`]. This can be useful when converting between widget - /// bounds (which are in logical pixels) to crop screenshots. - pub scale_factor: f64, -} - -impl Debug for Screenshot { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!( - f, - "Screenshot: {{ \n bytes: {}\n scale: {}\n size: {:?} }}", - self.bytes.len(), - self.scale_factor, - self.size - ) - } -} - -impl Screenshot { - /// Creates a new [`Screenshot`]. - pub fn new( - bytes: impl Into<Bytes>, - size: Size<u32>, - scale_factor: f64, - ) -> Self { - Self { - bytes: bytes.into(), - size, - scale_factor, - } - } - - /// Crops a [`Screenshot`] to the provided `region`. This will always be relative to the - /// top-left corner of the [`Screenshot`]. - pub fn crop(&self, region: Rectangle<u32>) -> Result<Self, CropError> { - if region.width == 0 || region.height == 0 { - return Err(CropError::Zero); - } - - if region.x + region.width > self.size.width - || region.y + region.height > self.size.height - { - return Err(CropError::OutOfBounds); - } - - // Image is always RGBA8 = 4 bytes per pixel - const PIXEL_SIZE: usize = 4; - - let bytes_per_row = self.size.width as usize * PIXEL_SIZE; - let row_range = region.y as usize..(region.y + region.height) as usize; - let column_range = region.x as usize * PIXEL_SIZE - ..(region.x + region.width) as usize * PIXEL_SIZE; - - let chopped = self.bytes.chunks(bytes_per_row).enumerate().fold( - vec![], - |mut acc, (row, bytes)| { - if row_range.contains(&row) { - acc.extend(&bytes[column_range.clone()]); - } - - acc - }, - ); - - Ok(Self { - bytes: Bytes::from(chopped), - size: Size::new(region.width, region.height), - scale_factor: self.scale_factor, - }) - } -} - -impl AsRef<[u8]> for Screenshot { - fn as_ref(&self) -> &[u8] { - &self.bytes - } -} - -impl From<Screenshot> for Bytes { - fn from(screenshot: Screenshot) -> Self { - screenshot.bytes - } -} - -#[derive(Debug, thiserror::Error)] -/// Errors that can occur when cropping a [`Screenshot`]. -pub enum CropError { - #[error("The cropped region is out of bounds.")] - /// The cropped region's size is out of bounds. - OutOfBounds, - #[error("The cropped region is not visible.")] - /// The cropped region's size is zero. - Zero, -} |