Merge pull request #1964 from bungoboingo/feat/multi-window-support
[Feature] 🪟 Multi Window 🪟 .. redux!
This commit is contained in:
commit
fc285d3e46
59 changed files with 3020 additions and 761 deletions
|
|
@ -23,5 +23,8 @@ palette.optional = true
|
|||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
instant.workspace = true
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
raw-window-handle.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
approx = "0.5"
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ pub enum Event {
|
|||
Mouse(mouse::Event),
|
||||
|
||||
/// A window event
|
||||
Window(window::Event),
|
||||
Window(window::Id, window::Event),
|
||||
|
||||
/// A touch event
|
||||
Touch(touch::Event),
|
||||
|
|
|
|||
|
|
@ -1,26 +1,34 @@
|
|||
use crate::Vector;
|
||||
|
||||
use num_traits::{Float, Num};
|
||||
use std::fmt;
|
||||
|
||||
/// A 2D point.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
||||
pub struct Point {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub struct Point<T = f32> {
|
||||
/// The X coordinate.
|
||||
pub x: f32,
|
||||
pub x: T,
|
||||
|
||||
/// The Y coordinate.
|
||||
pub y: f32,
|
||||
pub y: T,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
/// The origin (i.e. a [`Point`] at (0, 0)).
|
||||
pub const ORIGIN: Point = Point::new(0.0, 0.0);
|
||||
pub const ORIGIN: Self = Self::new(0.0, 0.0);
|
||||
}
|
||||
|
||||
impl<T: Num> Point<T> {
|
||||
/// Creates a new [`Point`] with the given coordinates.
|
||||
pub const fn new(x: f32, y: f32) -> Self {
|
||||
pub const fn new(x: T, y: T) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
|
||||
/// Computes the distance to another [`Point`].
|
||||
pub fn distance(&self, to: Point) -> f32 {
|
||||
pub fn distance(&self, to: Self) -> T
|
||||
where
|
||||
T: Float,
|
||||
{
|
||||
let a = self.x - to.x;
|
||||
let b = self.y - to.y;
|
||||
|
||||
|
|
@ -34,9 +42,9 @@ impl From<[f32; 2]> for Point {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<[u16; 2]> for Point {
|
||||
impl From<[u16; 2]> for Point<u16> {
|
||||
fn from([x, y]: [u16; 2]) -> Self {
|
||||
Point::new(x.into(), y.into())
|
||||
Point::new(x, y)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -46,10 +54,13 @@ impl From<Point> for [f32; 2] {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::ops::Add<Vector> for Point {
|
||||
impl<T> std::ops::Add<Vector<T>> for Point<T>
|
||||
where
|
||||
T: std::ops::Add<Output = T>,
|
||||
{
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, vector: Vector) -> Self {
|
||||
fn add(self, vector: Vector<T>) -> Self {
|
||||
Self {
|
||||
x: self.x + vector.x,
|
||||
y: self.y + vector.y,
|
||||
|
|
@ -57,10 +68,13 @@ impl std::ops::Add<Vector> for Point {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::ops::Sub<Vector> for Point {
|
||||
impl<T> std::ops::Sub<Vector<T>> for Point<T>
|
||||
where
|
||||
T: std::ops::Sub<Output = T>,
|
||||
{
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, vector: Vector) -> Self {
|
||||
fn sub(self, vector: Vector<T>) -> Self {
|
||||
Self {
|
||||
x: self.x - vector.x,
|
||||
y: self.y - vector.y,
|
||||
|
|
@ -68,10 +82,22 @@ impl std::ops::Sub<Vector> for Point {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::ops::Sub<Point> for Point {
|
||||
type Output = Vector;
|
||||
impl<T> std::ops::Sub<Point<T>> for Point<T>
|
||||
where
|
||||
T: std::ops::Sub<Output = T>,
|
||||
{
|
||||
type Output = Vector<T>;
|
||||
|
||||
fn sub(self, point: Point) -> Vector {
|
||||
fn sub(self, point: Self) -> Vector<T> {
|
||||
Vector::new(self.x - point.x, self.y - point.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Display for Point<T>
|
||||
where
|
||||
T: fmt::Display,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Point {{ x: {}, y: {} }}", self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ impl Tree {
|
|||
}
|
||||
}
|
||||
|
||||
/// Reconciliates the children of the tree with the provided list of widgets.
|
||||
/// Reconciles the children of the tree with the provided list of widgets.
|
||||
pub fn diff_children<'a, Message, Renderer>(
|
||||
&mut self,
|
||||
new_children: &[impl Borrow<dyn Widget<Message, Renderer> + 'a>],
|
||||
|
|
|
|||
|
|
@ -1,15 +1,21 @@
|
|||
//! Build window-based GUI applications.
|
||||
pub mod icon;
|
||||
pub mod settings;
|
||||
|
||||
mod event;
|
||||
mod id;
|
||||
mod level;
|
||||
mod mode;
|
||||
mod position;
|
||||
mod redraw_request;
|
||||
mod user_attention;
|
||||
|
||||
pub use event::Event;
|
||||
pub use icon::Icon;
|
||||
pub use id::Id;
|
||||
pub use level::Level;
|
||||
pub use mode::Mode;
|
||||
pub use position::Position;
|
||||
pub use redraw_request::RedrawRequest;
|
||||
pub use settings::Settings;
|
||||
pub use user_attention::UserAttention;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,27 @@
|
|||
use crate::time::Instant;
|
||||
use crate::{Point, Size};
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// A window-related event.
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
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.
|
||||
///
|
||||
/// **Note**: Not available in Wayland.
|
||||
position: Option<Point>,
|
||||
/// The size of the created window. This is its "inner" size, or the size of the
|
||||
/// client area, in logical pixels.
|
||||
size: Size,
|
||||
},
|
||||
|
||||
/// A window was closed.
|
||||
Closed,
|
||||
|
||||
/// A window was moved.
|
||||
Moved {
|
||||
/// The new logical x location of the window
|
||||
|
|
@ -27,9 +44,6 @@ pub enum Event {
|
|||
RedrawRequested(Instant),
|
||||
|
||||
/// The user has requested for the window to close.
|
||||
///
|
||||
/// Usually, you will want to terminate the execution whenever this event
|
||||
/// occurs.
|
||||
CloseRequested,
|
||||
|
||||
/// A window was focused.
|
||||
|
|
|
|||
21
core/src/window/id.rs
Normal file
21
core/src/window/id.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
use std::hash::Hash;
|
||||
|
||||
use std::sync::atomic::{self, AtomicU64};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
/// The id of the window.
|
||||
///
|
||||
/// Internally Iced reserves `window::Id::MAIN` for the first window spawned.
|
||||
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))
|
||||
}
|
||||
}
|
||||
24
core/src/window/position.rs
Normal file
24
core/src/window/position.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
use crate::Point;
|
||||
|
||||
/// The position of a window in a given screen.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum Position {
|
||||
/// The platform-specific default position for a new window.
|
||||
Default,
|
||||
/// The window is completely centered on the screen.
|
||||
Centered,
|
||||
/// The window is positioned with specific coordinates: `(X, Y)`.
|
||||
///
|
||||
/// When the decorations of the window are enabled, Windows 10 will add some
|
||||
/// invisible padding to the window. This padding gets included in the
|
||||
/// position. So if you have decorations enabled and want the window to be
|
||||
/// at (0, 0) you would have to set the position to
|
||||
/// `(PADDING_X, PADDING_Y)`.
|
||||
Specific(Point),
|
||||
}
|
||||
|
||||
impl Default for Position {
|
||||
fn default() -> Self {
|
||||
Self::Default
|
||||
}
|
||||
}
|
||||
95
core/src/window/settings.rs
Normal file
95
core/src/window/settings.rs
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
//! Configure your windows.
|
||||
#[cfg(target_os = "windows")]
|
||||
#[path = "settings/windows.rs"]
|
||||
mod platform;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[path = "settings/macos.rs"]
|
||||
mod platform;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[path = "settings/linux.rs"]
|
||||
mod platform;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[path = "settings/wasm.rs"]
|
||||
mod platform;
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "windows",
|
||||
target_os = "macos",
|
||||
target_os = "linux",
|
||||
target_arch = "wasm32"
|
||||
)))]
|
||||
#[path = "settings/other.rs"]
|
||||
mod platform;
|
||||
|
||||
use crate::window::{Icon, Level, Position};
|
||||
use crate::Size;
|
||||
|
||||
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,
|
||||
|
||||
/// The initial position of the window.
|
||||
pub position: Position,
|
||||
|
||||
/// The minimum size of the window.
|
||||
pub min_size: Option<Size>,
|
||||
|
||||
/// The maximum size of the window.
|
||||
pub max_size: Option<Size>,
|
||||
|
||||
/// Whether the window should be visible or not.
|
||||
pub visible: bool,
|
||||
|
||||
/// Whether the window should be resizable or not.
|
||||
pub resizable: bool,
|
||||
|
||||
/// Whether the window should have a border, a title bar, etc. or not.
|
||||
pub decorations: bool,
|
||||
|
||||
/// Whether the window should be transparent.
|
||||
pub transparent: bool,
|
||||
|
||||
/// The window [`Level`].
|
||||
pub level: Level,
|
||||
|
||||
/// The icon of the window.
|
||||
pub icon: Option<Icon>,
|
||||
|
||||
/// Platform specific settings.
|
||||
pub platform_specific: PlatformSpecific,
|
||||
|
||||
/// Whether the window will close when the user requests it, e.g. when a user presses the
|
||||
/// close button.
|
||||
///
|
||||
/// This can be useful if you want to have some behavior that executes before the window is
|
||||
/// actually destroyed. If you disable this, you must manually close the window with the
|
||||
/// `window::close` command.
|
||||
///
|
||||
/// By default this is enabled.
|
||||
pub exit_on_close_request: bool,
|
||||
}
|
||||
|
||||
impl Default for Settings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
size: Size::new(1024.0, 768.0),
|
||||
position: Position::default(),
|
||||
min_size: None,
|
||||
max_size: None,
|
||||
visible: true,
|
||||
resizable: true,
|
||||
decorations: true,
|
||||
transparent: false,
|
||||
level: Level::default(),
|
||||
icon: None,
|
||||
exit_on_close_request: true,
|
||||
platform_specific: PlatformSpecific::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
11
core/src/window/settings/linux.rs
Normal file
11
core/src/window/settings/linux.rs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
//! Platform specific settings for Linux.
|
||||
|
||||
/// The platform specific window settings of an application.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||
pub struct PlatformSpecific {
|
||||
/// Sets the application id of the window.
|
||||
///
|
||||
/// As a best practice, it is suggested to select an application id that match
|
||||
/// the basename of the application’s .desktop file.
|
||||
pub application_id: String,
|
||||
}
|
||||
12
core/src/window/settings/macos.rs
Normal file
12
core/src/window/settings/macos.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
//! Platform specific settings for macOS.
|
||||
|
||||
/// The platform specific window settings of an application.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub struct PlatformSpecific {
|
||||
/// Hides the window title.
|
||||
pub title_hidden: bool,
|
||||
/// Makes the titlebar transparent and allows the content to appear behind it.
|
||||
pub titlebar_transparent: bool,
|
||||
/// Makes the window content appear behind the titlebar.
|
||||
pub fullsize_content_view: bool,
|
||||
}
|
||||
3
core/src/window/settings/other.rs
Normal file
3
core/src/window/settings/other.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
/// The platform specific window settings of an application.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub struct PlatformSpecific;
|
||||
11
core/src/window/settings/wasm.rs
Normal file
11
core/src/window/settings/wasm.rs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
//! Platform specific settings for WebAssembly.
|
||||
|
||||
/// The platform specific window settings of an application.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||
pub struct PlatformSpecific {
|
||||
/// The identifier of a DOM element that will be replaced with the
|
||||
/// application.
|
||||
///
|
||||
/// If set to `None`, the application will be appended to the HTML body.
|
||||
pub target: Option<String>,
|
||||
}
|
||||
21
core/src/window/settings/windows.rs
Normal file
21
core/src/window/settings/windows.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
//! 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,
|
||||
}
|
||||
|
||||
impl Default for PlatformSpecific {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
parent: None,
|
||||
drag_and_drop: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue