Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] 🪟 Multi Window 🪟 .. redux! #1964

Merged
merged 75 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
529589d
Introduce `multi_window` from `pure`
derezzedex Apr 1, 2022
287306e
Introduce `multi_window` in `iced_winit`
derezzedex Apr 1, 2022
b896e41
Unify `Application` and `Program`
derezzedex Apr 1, 2022
12538d3
Use map of windows internally
derezzedex Jun 15, 2022
5919325
Internally wrap `Message` with a `Event` enum
derezzedex Jun 15, 2022
00d6baf
fix: temporalily remove the unsafe pointer `HWND`
derezzedex Jun 15, 2022
8fdd5ee
Synchronize window list with `windows` method
derezzedex Jun 15, 2022
ec56c06
Introduce opaque `window::Id` type
derezzedex Jun 21, 2022
64e2153
Fix `multi_window` example
derezzedex Jun 28, 2022
97914da
what is this
derezzedex Jul 12, 2022
8f53df5
fix: temporarily add `window::Id` to
derezzedex Jul 14, 2022
01bad4f
duplicate `pane_grid` example to `multi_window`
derezzedex Jul 14, 2022
2fe58e1
add `window::Id` to `view`
derezzedex Jul 21, 2022
3d901d5
create multi-windowed `pane_grid` example
derezzedex Jul 21, 2022
35331d0
Allow closing the window from user code
derezzedex Jul 26, 2022
dc86bd0
Introduce `close_requested` for `multi-window`
derezzedex Jul 27, 2022
7f35256
Split `Surface` and `Window`
derezzedex Sep 15, 2022
974cc6b
Introduce `multi_window` to `iced_glutin`
derezzedex Sep 19, 2022
0ad53a3
add `window::Id` to `Event` and `Action`
derezzedex Sep 19, 2022
0644076
implement `multi_window` for `iced_glutin`
derezzedex Sep 21, 2022
ce43514
copy `multi_window::Event` from `iced_winit`
derezzedex Sep 21, 2022
a386788
use `glutin/multi_window` branch
derezzedex Sep 28, 2022
1bc0c48
move window settings to `iced_native`
derezzedex Oct 20, 2022
f93fa02
introduce `window::spawn` and `window::close`
derezzedex Oct 20, 2022
aa7164f
update `glutin` to 0.30
derezzedex Oct 31, 2022
0553062
update `iced_glutin` to use new surface api
derezzedex Oct 31, 2022
ac20f35
update `glutin\multi_window` to new surface api
derezzedex Nov 2, 2022
5e4e410
remove `windows` method (use commands instead)
derezzedex Nov 3, 2022
942f1c9
merged in iced master
bungoboingo Jan 2, 2023
f43419d
Fixed issue with window ID on winit
bungoboingo Jan 3, 2023
1944e98
Fix multi-window example for Glutin on MacOS
bungoboingo Jan 3, 2023
ec41918
Implemented window title update functionality for multiwindow.
bungoboingo Jan 5, 2023
3e5d34f
Formatting
bungoboingo Jan 9, 2023
f78ccd9
Removed glutin's individual multi_window state since 0.30+ doesn't ha…
bungoboingo Jan 9, 2023
790fa3e
Added tracing to multi_window applications
bungoboingo Jan 13, 2023
70d487b
Merge remote-tracking branch 'origin/master' into feat/multi-window-s…
bungoboingo Jan 18, 2023
7e9a12a
New iced changes
bungoboingo Jan 18, 2023
0a64328
Added window::Id to multi_window application's scale_factor
bungoboingo Jan 19, 2023
367fea5
Redraw request events for multiwindow.
bungoboingo Feb 15, 2023
64e0e81
Widget operations for multi-window.
bungoboingo Feb 15, 2023
63fb608
Merge remote-tracking branch 'origin/master' into feat/multi-window-s…
bungoboingo Feb 15, 2023
3c095aa
Merged in iced master
bungoboingo Feb 15, 2023
8da0983
Fixed widget animations implementation
bungoboingo Feb 17, 2023
744cef5
Merge remote-tracking branch 'origin/master' into feat/multi-window-s…
bungoboingo Feb 17, 2023
2d42745
Iced master merge (again)
bungoboingo Feb 17, 2023
3aaf5d8
Fixed widget operations
bungoboingo Feb 17, 2023
9565b47
Merge remote-tracking branch 'origin/master' into feat/multi-window-s…
bungoboingo Feb 20, 2023
bd58d5f
Cargo fix
bungoboingo Feb 20, 2023
50b9c77
Fixed state syncing issue with MW.
bungoboingo Feb 22, 2023
a131f11
Merge remote-tracking branch 'origin/master' into feat/multi-window-s…
bungoboingo Feb 23, 2023
5129657
Merge remote-tracking branch 'iced-main/master' into feat/multi-windo…
bungoboingo Feb 28, 2023
e36daa6
Removed glutin MW support and reverted glutin changes back to Iced ma…
bungoboingo Feb 28, 2023
fa068b9
Merge remote-tracking branch 'origin/master' into feat/multi-window-s…
bungoboingo Mar 13, 2023
8ba1843
Code cleanup, clearer comments + removed some unnecessary dupe;
bungoboingo Mar 13, 2023
ce4b2c9
Added simpler MW example
bungoboingo Mar 14, 2023
41836dd
Added per-window theme support.
bungoboingo Mar 16, 2023
633f405
Merge remote-tracking branch 'origin/master' into feat/multi-window-s…
bungoboingo Jul 12, 2023
d53ccc8
refactored window storage;
bungoboingo Jul 13, 2023
83c7870
Moved `exit_on_close_request` to window settings. This now controls w…
bungoboingo Jul 24, 2023
e09b4e2
Merge branch 'master' into feat/multi-window-support
hecrj Nov 29, 2023
6dca076
Use `workspace` dependency for `raw-window-handle`
hecrj Nov 29, 2023
abe13b5
Move `multi-window` feature before the `advanced` one
hecrj Nov 29, 2023
9b34b2a
Run `cargo fmt`
hecrj Nov 29, 2023
7def3ee
Fix `clippy` lints
hecrj Nov 29, 2023
6740c2c
Fix broken intra-doc links
hecrj Nov 29, 2023
8c4e7d8
Fix `renderer` method in `iced_renderer::Compositor`
hecrj Nov 29, 2023
ac12d2d
Remove unnecessary unsafe `Send` marker in `iced_winit`
hecrj Nov 29, 2023
3b39ba7
Fix unused import in `multi_window::application`
hecrj Nov 29, 2023
d34bc4e
Refactor event loop <-> instance communication in `multi_window`
hecrj Nov 29, 2023
9f29aec
Move `Event` and `Control` types after `multi_window::run`
hecrj Nov 29, 2023
6740831
Use actual floats for logical coordinates
hecrj Nov 30, 2023
ea42af7
Use `AtomicU64` for `window::Id`
hecrj Dec 2, 2023
b152ecd
Separate `Compositor::new` from `Compositor::create_renderer`
hecrj Dec 2, 2023
31cccd8
Remove unnecessary re-exports in `iced_winit`
hecrj Dec 2, 2023
5c5e765
Refactor `Windows` abstraction into `WindowManager`
hecrj Dec 2, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/ISSUE_TEMPLATE/BUG-REPORT.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ body:
Before filing an issue...

- If you are using `wgpu`, you need an environment that supports Vulkan, Metal, or DirectX 12. Please, make sure you can run [the `wgpu` examples].
- If you are using `glow`, you need support for OpenGL 2.1+. Please, make sure you can run [the `glow` examples].

If you have any issues running any of the examples, make sure your graphics drivers are up-to-date. If the issues persist, please report them to the authors of the libraries directly!

Expand Down
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ web-colors = ["iced_renderer/web-colors"]
webgl = ["iced_renderer/webgl"]
# Enables the syntax `highlighter` module
highlighter = ["iced_highlighter"]
# Enables experimental multi-window support.
multi-window = ["iced_winit/multi-window"]
# Enables the advanced module
advanced = []

Expand Down
8 changes: 2 additions & 6 deletions ECOSYSTEM.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ The widgets of a _graphical_ user interface produce some primitives that eventua
Currently, there are two different official renderers:

- [`iced_wgpu`] is powered by [`wgpu`] and supports Vulkan, DirectX 12, and Metal.
- [`iced_glow`] is powered by [`glow`] and supports OpenGL 2.1+ and OpenGL ES 2.0+.
- [`tiny-skia`] is used as a fallback software renderer when `wgpu` is not supported.

Additionally, the [`iced_graphics`] subcrate contains a bunch of backend-agnostic types that can be leveraged to build renderers. Both of the renderers rely on the graphical foundations provided by this crate.

Expand All @@ -54,10 +54,7 @@ The widgets of a graphical user _interface_ are interactive. __Shells__ gather a

Normally, a shell will be responsible of creating a window and managing the lifecycle of a user interface, implementing a runtime of [The Elm Architecture].

As of now, there are two official shells:

- [`iced_winit`] implements a shell runtime on top of [`winit`].
- [`iced_glutin`] is similar to [`iced_winit`], but it also deals with [OpenGL context creation].
As of now, there is one official shell: [`iced_winit`] implements a shell runtime on top of [`winit`].

## The web target
The Web platform provides all the abstractions necessary to draw widgets and gather users interactions.
Expand Down Expand Up @@ -91,5 +88,4 @@ Finally, [`iced`] unifies everything into a simple abstraction to create cross-p
[`winit`]: https://github.com/rust-windowing/winit
[`glutin`]: https://github.com/rust-windowing/glutin
[`dodrio`]: https://github.com/fitzgen/dodrio
[OpenGL context creation]: https://www.khronos.org/opengl/wiki/Creating_an_OpenGL_Context
[The Elm Architecture]: https://guide.elm-lang.org/architecture/
3 changes: 3 additions & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
2 changes: 1 addition & 1 deletion core/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
58 changes: 42 additions & 16 deletions core/src/point.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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)
}
}

Expand All @@ -46,32 +54,50 @@ 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,
}
}
}

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,
}
}
}

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)
}
}
2 changes: 1 addition & 1 deletion core/src/widget/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>],
Expand Down
6 changes: 6 additions & 0 deletions core/src/window.rs
Original file line number Diff line number Diff line change
@@ -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;
22 changes: 18 additions & 4 deletions core/src/window/event.rs
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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.
Expand Down
21 changes: 21 additions & 0 deletions core/src/window/id.rs
Original file line number Diff line number Diff line change
@@ -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))
}
}
6 changes: 4 additions & 2 deletions winit/src/position.rs → core/src/window/position.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::Point;

/// The position of a window in a given screen.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Position {
/// The platform-specific default position for a new window.
Default,
Expand All @@ -12,7 +14,7 @@ pub enum Position {
/// 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(i32, i32),
Specific(Point),
}

impl Default for Position {
Expand Down
73 changes: 46 additions & 27 deletions src/window/settings.rs → core/src/window/settings.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,47 @@
use crate::window::{Icon, Level, Position};
//! 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;

pub use iced_winit::settings::PlatformSpecific;
#[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 size of the window.
pub size: (u32, u32),
/// 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<(u32, u32)>,
pub min_size: Option<Size>,

/// The maximum size of the window.
pub max_size: Option<(u32, u32)>,
pub max_size: Option<Size>,

/// Whether the window should be visible or not.
pub visible: bool,
Expand All @@ -37,12 +63,22 @@ pub struct Settings {

/// 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() -> Settings {
Settings {
size: (1024, 768),
fn default() -> Self {
Self {
size: Size::new(1024.0, 768.0),
position: Position::default(),
min_size: None,
max_size: None,
Expand All @@ -52,25 +88,8 @@ impl Default for Settings {
transparent: false,
level: Level::default(),
icon: None,
exit_on_close_request: true,
platform_specific: PlatformSpecific::default(),
}
}
}

impl From<Settings> for iced_winit::settings::Window {
fn from(settings: Settings) -> Self {
Self {
size: settings.size,
position: iced_winit::Position::from(settings.position),
min_size: settings.min_size,
max_size: settings.max_size,
visible: settings.visible,
resizable: settings.resizable,
decorations: settings.decorations,
transparent: settings.transparent,
level: settings.level,
icon: settings.icon.map(Icon::into),
platform_specific: settings.platform_specific,
}
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading
Loading