Merge branch 'master' into beacon

This commit is contained in:
Héctor Ramón Jiménez 2025-03-04 19:11:37 +01:00
commit 8bd5de72ea
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
371 changed files with 33138 additions and 12950 deletions

View file

@ -0,0 +1,27 @@
/// The cardinal directions relative to the center of a window.
#[derive(Debug, Clone, Copy)]
pub enum Direction {
/// Points to the top edge of a window.
North,
/// Points to the bottom edge of a window.
South,
/// Points to the right edge of a window.
East,
/// Points to the left edge of a window.
West,
/// Points to the top-right corner of a window.
NorthEast,
/// Points to the top-left corner of a window.
NorthWest,
/// Points to the bottom-right corner of a window.
SouthEast,
/// Points to the bottom-left corner of a window.
SouthWest,
}

View file

@ -9,8 +9,8 @@ pub enum Event {
/// A window was opened.
Opened {
/// The position of the opened window. This is relative to the top-left corner of the desktop
/// the window is on, including virtual desktops. Refers to window's "inner" position,
/// or the client area, in logical pixels.
/// the window is on, including virtual desktops. Refers to window's "outer" position,
/// or the window area, in logical pixels.
///
/// **Note**: Not available in Wayland.
position: Option<Point>,
@ -23,20 +23,10 @@ pub enum Event {
Closed,
/// A window was moved.
Moved {
/// The new logical x location of the window
x: i32,
/// The new logical y location of the window
y: i32,
},
Moved(Point),
/// A window was resized.
Resized {
/// The new logical width of the window
width: u32,
/// The new logical height of the window
height: u32,
},
Resized(Size),
/// A window redraw was requested.
///
@ -56,17 +46,29 @@ pub enum Event {
///
/// When the user hovers multiple files at once, this event will be emitted
/// for each file separately.
///
/// ## Platform-specific
///
/// - **Wayland:** Not implemented.
FileHovered(PathBuf),
/// A file has been dropped into the window.
///
/// When the user drops multiple files at once, this event will be emitted
/// for each file separately.
///
/// ## Platform-specific
///
/// - **Wayland:** Not implemented.
FileDropped(PathBuf),
/// A file was hovered, but has exited the window.
///
/// There will be a single `FilesHoveredLeft` event triggered even if
/// multiple files were hovered.
///
/// ## Platform-specific
///
/// - **Wayland:** Not implemented.
FilesHoveredLeft,
}

View file

@ -1,10 +1,8 @@
use std::fmt;
use std::hash::Hash;
use std::sync::atomic::{self, AtomicU64};
/// The id of the window.
///
/// Internally Iced reserves `window::Id::MAIN` for the first window spawned.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Id(u64);
@ -12,11 +10,14 @@ pub struct Id(u64);
static COUNT: AtomicU64 = AtomicU64::new(1);
impl Id {
/// The reserved window [`Id`] for the first window in an Iced application.
pub const MAIN: Self = Id(0);
/// Creates a new unique window [`Id`].
pub fn unique() -> Id {
Id(COUNT.fetch_add(1, atomic::Ordering::Relaxed))
}
}
impl fmt::Display for Id {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}

View file

@ -8,6 +8,15 @@ pub enum RedrawRequest {
/// Redraw at the given time.
At(Instant),
/// No redraw is needed.
Wait,
}
impl From<Instant> for RedrawRequest {
fn from(time: Instant) -> Self {
Self::At(time)
}
}
#[cfg(test)]
@ -34,5 +43,8 @@ mod tests {
assert!(RedrawRequest::At(now) <= RedrawRequest::At(now));
assert!(RedrawRequest::At(now) <= RedrawRequest::At(later));
assert!(RedrawRequest::At(later) >= RedrawRequest::At(now));
assert!(RedrawRequest::Wait > RedrawRequest::NextFrame);
assert!(RedrawRequest::Wait > RedrawRequest::At(later));
}
}

View file

@ -0,0 +1,108 @@
//! Take screenshots of a window.
use crate::{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,
}

View file

@ -24,16 +24,23 @@ mod platform;
#[path = "settings/other.rs"]
mod platform;
use crate::window::{Icon, Level, Position};
use crate::Size;
use crate::window::{Icon, Level, Position};
pub use platform::PlatformSpecific;
/// The window settings of an application.
#[derive(Debug, Clone)]
pub struct Settings {
/// The initial logical dimensions of the window.
pub size: Size,
/// Whether the window should start maximized.
pub maximized: bool,
/// Whether the window should start fullscreen.
pub fullscreen: bool,
/// The initial position of the window.
pub position: Position,
@ -79,6 +86,8 @@ impl Default for Settings {
fn default() -> Self {
Self {
size: Size::new(1024.0, 768.0),
maximized: false,
fullscreen: false,
position: Position::default(),
min_size: None,
max_size: None,

View file

@ -8,4 +8,10 @@ pub struct PlatformSpecific {
/// As a best practice, it is suggested to select an application id that match
/// the basename of the applications .desktop file.
pub application_id: String,
/// Whether bypass the window manager mapping for x11 windows
///
/// This flag is particularly useful for creating UI elements that need precise
/// positioning and immediate display without window manager interference.
pub override_redirect: bool,
}

View file

@ -1,25 +1,27 @@
//! Platform specific settings for Windows.
use raw_window_handle::RawWindowHandle;
/// The platform specific window settings of an application.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PlatformSpecific {
/// Parent window
pub parent: Option<RawWindowHandle>,
/// Drag and drop support
pub drag_and_drop: bool,
/// Whether show or hide the window icon in the taskbar.
pub skip_taskbar: bool,
/// Shows or hides the background drop shadow for undecorated windows.
///
/// The shadow is hidden by default.
/// Enabling the shadow causes a thin 1px line to appear on the top of the window.
pub undecorated_shadow: bool,
}
impl Default for PlatformSpecific {
fn default() -> Self {
Self {
parent: None,
drag_and_drop: true,
skip_taskbar: false,
undecorated_shadow: false,
}
}
}