summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/src/window.rs81
-rw-r--r--runtime/src/window/screenshot.rs108
2 files changed, 63 insertions, 126 deletions
diff --git a/runtime/src/window.rs b/runtime/src/window.rs
index 382f4518..183fab97 100644
--- a/runtime/src/window.rs
+++ b/runtime/src/window.rs
@@ -1,11 +1,8 @@
//! 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,
+ Direction, Event, Icon, Id, Level, Mode, Screenshot, Settings,
+ UserAttention,
};
use crate::core::{Point, Size};
use crate::futures::event;
@@ -35,10 +32,17 @@ pub enum Action {
/// Move the window with the left mouse button until the button is
/// released.
///
- /// There’s no guarantee that this will work unless the left mouse
+ /// There's no guarantee that this will work unless the left mouse
/// button was pressed immediately before this function is called.
Drag(Id),
+ /// Resize the window with the left mouse button until the button is
+ /// released.
+ ///
+ /// There's no guarantee that this will work unless the left mouse
+ /// button was pressed immediately before this function is called.
+ DragResize(Id, Direction),
+
/// Resize the window to the given logical dimensions.
Resize(Id, Size),
@@ -72,7 +76,7 @@ pub enum Action {
Move(Id, Point),
/// Change the [`Mode`] of the window.
- ChangeMode(Id, Mode),
+ SetMode(Id, Mode),
/// Get the current [`Mode`] of the window.
GetMode(Id, oneshot::Sender<Mode>),
@@ -115,7 +119,7 @@ pub enum Action {
GainFocus(Id),
/// Change the window [`Level`].
- ChangeLevel(Id, Level),
+ SetLevel(Id, Level),
/// Show the system menu at cursor position.
///
@@ -140,7 +144,7 @@ pub enum Action {
///
/// - **X11:** Has no universal guidelines for icon sizes, so you're at the whims of the WM. That
/// said, it's usually in the same ballpark as on Windows.
- ChangeIcon(Id, Icon),
+ SetIcon(Id, Icon),
/// Runs the closure with the native window handle of the window with the given [`Id`].
RunWithHandle(Id, Box<dyn FnOnce(WindowHandle<'_>) + Send>),
@@ -159,6 +163,18 @@ pub enum Action {
/// This enables mouse events for the window and stops mouse events
/// from being passed to whatever is underneath.
DisableMousePassthrough(Id),
+
+ /// Set the minimum inner window size.
+ SetMinSize(Id, Option<Size>),
+
+ /// Set the maximum inner window size.
+ SetMaxSize(Id, Option<Size>),
+
+ /// Set the window to be resizable or not.
+ SetResizable(Id, bool),
+
+ /// Set the window size increment.
+ SetResizeIncrements(Id, Option<Size>),
}
/// Subscribes to the frames of the window of the running application.
@@ -264,11 +280,40 @@ pub fn drag<T>(id: Id) -> Task<T> {
task::effect(crate::Action::Window(Action::Drag(id)))
}
+/// Begins resizing the window while the left mouse button is held.
+pub fn drag_resize<T>(id: Id, direction: Direction) -> Task<T> {
+ task::effect(crate::Action::Window(Action::DragResize(id, direction)))
+}
+
/// Resizes the window to the given logical dimensions.
pub fn resize<T>(id: Id, new_size: Size) -> Task<T> {
task::effect(crate::Action::Window(Action::Resize(id, new_size)))
}
+/// Set the window to be resizable or not.
+pub fn set_resizable<T>(id: Id, resizable: bool) -> Task<T> {
+ task::effect(crate::Action::Window(Action::SetResizable(id, resizable)))
+}
+
+/// Set the inner maximum size of the window.
+pub fn set_max_size<T>(id: Id, size: Option<Size>) -> Task<T> {
+ task::effect(crate::Action::Window(Action::SetMaxSize(id, size)))
+}
+
+/// Set the inner minimum size of the window.
+pub fn set_min_size<T>(id: Id, size: Option<Size>) -> Task<T> {
+ task::effect(crate::Action::Window(Action::SetMinSize(id, size)))
+}
+
+/// Set the window size increment.
+///
+/// This is usually used by apps such as terminal emulators that need "blocky" resizing.
+pub fn set_resize_increments<T>(id: Id, increments: Option<Size>) -> Task<T> {
+ task::effect(crate::Action::Window(Action::SetResizeIncrements(
+ id, increments,
+ )))
+}
+
/// Get the window's size in logical dimensions.
pub fn get_size(id: Id) -> Task<Size> {
task::oneshot(move |channel| {
@@ -319,11 +364,6 @@ pub fn move_to<T>(id: Id, position: Point) -> Task<T> {
task::effect(crate::Action::Window(Action::Move(id, position)))
}
-/// Changes the [`Mode`] of the window.
-pub fn change_mode<T>(id: Id, mode: Mode) -> Task<T> {
- task::effect(crate::Action::Window(Action::ChangeMode(id, mode)))
-}
-
/// Gets the current [`Mode`] of the window.
pub fn get_mode(id: Id) -> Task<Mode> {
task::oneshot(move |channel| {
@@ -331,6 +371,11 @@ pub fn get_mode(id: Id) -> Task<Mode> {
})
}
+/// Changes the [`Mode`] of the window.
+pub fn set_mode<T>(id: Id, mode: Mode) -> Task<T> {
+ task::effect(crate::Action::Window(Action::SetMode(id, mode)))
+}
+
/// Toggles the window to maximized or back.
pub fn toggle_maximize<T>(id: Id) -> Task<T> {
task::effect(crate::Action::Window(Action::ToggleMaximize(id)))
@@ -368,8 +413,8 @@ pub fn gain_focus<T>(id: Id) -> Task<T> {
}
/// Changes the window [`Level`].
-pub fn change_level<T>(id: Id, level: Level) -> Task<T> {
- task::effect(crate::Action::Window(Action::ChangeLevel(id, level)))
+pub fn set_level<T>(id: Id, level: Level) -> Task<T> {
+ task::effect(crate::Action::Window(Action::SetLevel(id, level)))
}
/// Show the [system menu] at cursor position.
@@ -388,8 +433,8 @@ pub fn get_raw_id<Message>(id: Id) -> Task<u64> {
}
/// Changes the [`Icon`] of the window.
-pub fn change_icon<T>(id: Id, icon: Icon) -> Task<T> {
- task::effect(crate::Action::Window(Action::ChangeIcon(id, icon)))
+pub fn set_icon<T>(id: Id, icon: Icon) -> Task<T> {
+ task::effect(crate::Action::Window(Action::SetIcon(id, icon)))
}
/// Runs the given callback with the native window handle for the window with the given id.
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,
-}