summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/src/overlay/nested.rs76
-rw-r--r--runtime/src/task.rs63
-rw-r--r--runtime/src/user_interface.rs10
-rw-r--r--runtime/src/window.rs6
-rw-r--r--runtime/src/window/screenshot.rs108
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,
-}