summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar bungoboingo <shankern@protonmail.com>2023-01-05 15:26:28 -0800
committerLibravatar bungoboingo <shankern@protonmail.com>2023-01-09 11:28:07 -0800
commitec41918ec40bddaba81235372f1566da59fd09f2 (patch)
treefb530943ccf14dfec3820bf65f71a9572fd3d8be
parent1944e98f82b7efd5b268e04ba5ced065e55a218e (diff)
downloadiced-ec41918ec40bddaba81235372f1566da59fd09f2.tar.gz
iced-ec41918ec40bddaba81235372f1566da59fd09f2.tar.bz2
iced-ec41918ec40bddaba81235372f1566da59fd09f2.zip
Implemented window title update functionality for multiwindow.
Diffstat (limited to '')
-rw-r--r--examples/multi_window/Cargo.toml2
-rw-r--r--examples/multi_window/src/main.rs10
-rw-r--r--glutin/src/application.rs33
-rw-r--r--glutin/src/multi_window.rs156
-rw-r--r--glutin/src/multi_window/state.rs14
-rw-r--r--native/src/window.rs4
-rw-r--r--native/src/window/action.rs8
-rw-r--r--native/src/window/icon.rs6
-rw-r--r--native/src/window/id.rs13
-rw-r--r--src/multi_window/application.rs8
-rw-r--r--winit/src/application.rs2
-rw-r--r--winit/src/multi_window.rs190
-rw-r--r--winit/src/multi_window/state.rs14
-rw-r--r--winit/src/window.rs37
14 files changed, 262 insertions, 235 deletions
diff --git a/examples/multi_window/Cargo.toml b/examples/multi_window/Cargo.toml
index 6de895d7..62198595 100644
--- a/examples/multi_window/Cargo.toml
+++ b/examples/multi_window/Cargo.toml
@@ -10,4 +10,4 @@ publish = false
iced = { path = "../..", features = ["debug", "multi_window"] }
env_logger = "0.10.0"
iced_native = { path = "../../native" }
-iced_lazy = { path = "../../lazy" } \ No newline at end of file
+iced_lazy = { path = "../../lazy" }
diff --git a/examples/multi_window/src/main.rs b/examples/multi_window/src/main.rs
index 9fe6b481..b9f0514c 100644
--- a/examples/multi_window/src/main.rs
+++ b/examples/multi_window/src/main.rs
@@ -26,6 +26,7 @@ struct Example {
_focused: window::Id,
}
+#[derive(Debug)]
struct Window {
title: String,
panes: pane_grid::State<Pane>,
@@ -80,8 +81,11 @@ impl Application for Example {
)
}
- fn title(&self) -> String {
- String::from("Multi windowed pane grid - Iced")
+ fn title(&self, window: window::Id) -> String {
+ self.windows
+ .get(&window)
+ .map(|w| w.title.clone())
+ .unwrap_or(String::from("New Window"))
}
fn update(&mut self, message: Message) -> Command<Message> {
@@ -262,7 +266,6 @@ impl Application for Example {
&window.title,
WindowMessage::TitleChanged,
),
- button(text("Apply")).style(theme::Button::Primary),
button(text("Close"))
.on_press(WindowMessage::CloseWindow)
.style(theme::Button::Destructive),
@@ -389,6 +392,7 @@ impl std::fmt::Display for SelectableWindow {
}
}
+#[derive(Debug)]
struct Pane {
id: usize,
pub axis: pane_grid::Axis,
diff --git a/glutin/src/application.rs b/glutin/src/application.rs
index 45ff37f0..f43a47b9 100644
--- a/glutin/src/application.rs
+++ b/glutin/src/application.rs
@@ -245,18 +245,7 @@ where
)
})?;
- let (width, height) = window.inner_size().into();
- let surface_attributes =
- SurfaceAttributesBuilder::<WindowSurface>::new()
- .with_srgb(Some(true))
- .build(
- window_handle,
- NonZeroU32::new(width).unwrap_or(ONE),
- NonZeroU32::new(height).unwrap_or(ONE),
- );
-
- let surface = display
- .create_window_surface(configuration.as_ref(), &surface_attributes)
+ let surface = gl_surface(&display, configuration.as_ref(), &window)
.map_err(|error| {
Error::GraphicsCreationFailed(
iced_graphics::Error::BackendError(format!(
@@ -616,3 +605,23 @@ async fn run_instance<A, E, C>(
// Manually drop the user interface
drop(ManuallyDrop::into_inner(user_interface));
}
+
+#[allow(unsafe_code)]
+/// Creates a new [`glutin::Surface<WindowSurface>`].
+pub fn gl_surface(
+ display: &Display,
+ gl_config: &Config,
+ window: &winit::window::Window,
+) -> Result<Surface<WindowSurface>, glutin::error::Error> {
+ let (width, height) = window.inner_size().into();
+
+ let surface_attributes = SurfaceAttributesBuilder::<WindowSurface>::new()
+ .with_srgb(Some(true))
+ .build(
+ window.raw_window_handle(),
+ NonZeroU32::new(width).unwrap_or(ONE),
+ NonZeroU32::new(height).unwrap_or(ONE),
+ );
+
+ unsafe { display.create_window_surface(gl_config, &surface_attributes) }
+}
diff --git a/glutin/src/multi_window.rs b/glutin/src/multi_window.rs
index 35eeeb36..e79ec77d 100644
--- a/glutin/src/multi_window.rs
+++ b/glutin/src/multi_window.rs
@@ -12,7 +12,6 @@ use iced_winit::conversion;
use iced_winit::futures;
use iced_winit::futures::channel::mpsc;
use iced_winit::renderer;
-use iced_winit::settings;
use iced_winit::user_interface;
use iced_winit::window;
use iced_winit::winit;
@@ -26,11 +25,12 @@ use glutin::context::{
NotCurrentGlContextSurfaceAccessor, PossiblyCurrentGlContext,
};
use glutin::display::{Display, DisplayApiPreference, GlDisplay};
-use glutin::surface::{
- GlSurface, Surface, SurfaceAttributesBuilder, SwapInterval, WindowSurface,
-};
+use glutin::surface::{GlSurface, SwapInterval};
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
+use crate::application::gl_surface;
+use iced_native::window::Action;
+use iced_winit::multi_window::Event;
use std::collections::HashMap;
use std::ffi::CString;
use std::mem::ManuallyDrop;
@@ -76,7 +76,7 @@ where
};
let builder = settings.window.into_builder(
- &application.title(),
+ &application.title(window::Id::MAIN),
event_loop.primary_monitor(),
settings.id,
);
@@ -239,7 +239,14 @@ where
)
})?;
- let surface = gl_surface(&display, configuration.as_ref(), &window);
+ let surface = gl_surface(&display, configuration.as_ref(), &window)
+ .map_err(|error| {
+ Error::GraphicsCreationFailed(
+ iced_graphics::Error::BackendError(format!(
+ "failed to create surface: {error}"
+ )),
+ )
+ })?;
(display, window, configuration.0, surface, context)
};
@@ -301,14 +308,13 @@ where
event: winit::event::WindowEvent::Resized(*new_inner_size),
window_id,
}),
- winit::event::Event::UserEvent(Event::NewWindow(id, settings)) => {
- // TODO(derezzedex)
+ winit::event::Event::UserEvent(Event::NewWindow {
+ id,
+ settings,
+ title,
+ }) => {
let window = settings
- .into_builder(
- "fix window title",
- event_loop.primary_monitor(),
- None,
- )
+ .into_builder(&title, event_loop.primary_monitor(), None)
.build(event_loop)
.expect("Failed to build window");
@@ -372,9 +378,11 @@ async fn run_instance<A, E, C>(
let mut interfaces = ManuallyDrop::new(HashMap::new());
for (&id, window) in windows.keys().zip(windows.values()) {
- let surface = gl_surface(&display, &configuration, &window);
- let current_context = context.make_current(&surface).expect("Make current.");
- let state = State::new(&application, &window);
+ let surface = gl_surface(&display, &configuration, &window)
+ .expect("Create surface.");
+ let current_context =
+ context.make_current(&surface).expect("Make current.");
+ let state = State::new(&application, id, &window);
let physical_size = state.physical_size();
surface.resize(
@@ -392,7 +400,9 @@ async fn run_instance<A, E, C>(
id,
);
- context = current_context.make_not_current().expect("Make not current.");
+ context = current_context
+ .make_not_current()
+ .expect("Make not current.");
let _ = states.insert(id, state);
let _ = surfaces.insert(id, surface);
@@ -431,7 +441,7 @@ async fn run_instance<A, E, C>(
let (filtered, remaining): (Vec<_>, Vec<_>) =
events.iter().cloned().partition(
|(window_id, _event): &(
- Option<crate::window::Id>,
+ Option<window::Id>,
iced_native::event::Event,
)| {
*window_id == Some(id) || *window_id == None
@@ -503,7 +513,11 @@ async fn run_instance<A, E, C>(
);
// Update window
- state.synchronize(&application, &windows);
+ state.synchronize(
+ &application,
+ id,
+ windows.get(&id).expect("No window found with ID."),
+ );
let should_exit = application.should_exit();
@@ -563,7 +577,7 @@ async fn run_instance<A, E, C>(
event::Event::UserEvent(event) => match event {
Event::Application(message) => messages.push(message),
Event::WindowCreated(id, window) => {
- let state = State::new(&application, &window);
+ let state = State::new(&application, id, &window);
let user_interface = multi_window::build_user_interface(
&application,
user_interface::Cache::default(),
@@ -573,26 +587,8 @@ async fn run_instance<A, E, C>(
id,
);
- let window_handle = window.raw_window_handle();
- let (width, height) = window.inner_size().into();
- let surface_attributes =
- SurfaceAttributesBuilder::<WindowSurface>::new()
- .with_srgb(Some(true))
- .build(
- window_handle,
- NonZeroU32::new(width).unwrap_or(ONE),
- NonZeroU32::new(height).unwrap_or(ONE),
- );
-
- #[allow(unsafe_code)]
- let surface = unsafe {
- display
- .create_window_surface(
- &configuration,
- &surface_attributes,
- )
- .expect("failed to create surface")
- };
+ let surface = gl_surface(&display, &configuration, &window)
+ .expect("Create surface.");
let _ = states.insert(id, state);
let _ = interfaces.insert(id, user_interface);
@@ -624,7 +620,7 @@ async fn run_instance<A, E, C>(
break 'main;
}
}
- Event::NewWindow(_, _) => unreachable!(),
+ Event::NewWindow { .. } => unreachable!(),
},
event::Event::RedrawRequested(id) => {
let state = window_ids
@@ -687,9 +683,10 @@ async fn run_instance<A, E, C>(
NonZeroU32::new(physical_size.height).unwrap_or(ONE),
);
- if let Err(error) =
- surface.set_swap_interval(&current_context, SwapInterval::Wait(ONE))
- {
+ if let Err(_) = surface.set_swap_interval(
+ &current_context,
+ SwapInterval::Wait(ONE),
+ ) {
log::error!("Could not set swap interval for surface attached to window id: {:?}", id);
}
@@ -706,9 +703,13 @@ async fn run_instance<A, E, C>(
&debug.overlay(),
);
- surface.swap_buffers(&current_context).expect("Swap buffers");
+ surface
+ .swap_buffers(&current_context)
+ .expect("Swap buffers");
- context = current_context.make_not_current().expect("Make not current.");
+ context = current_context
+ .make_not_current()
+ .expect("Make not current.");
debug.render_finished();
// TODO: Handle animations!
// Maybe we can use `ControlFlow::WaitUntil` for this.
@@ -751,11 +752,10 @@ async fn run_instance<A, E, C>(
));
}
} else {
- // TODO(derezzedex): log error
+ log::error!("Window state not found for id: {:?}", window_id);
}
} else {
- // TODO(derezzedex): log error
- // println!("{:?}: {:?}", window_id, window_event);
+ log::error!("Window not found for id: {:?}", window_id);
}
}
_ => {}
@@ -766,25 +766,6 @@ async fn run_instance<A, E, C>(
// drop(ManuallyDrop::into_inner(user_interface));
}
-/// TODO(derezzedex):
-// This is the an wrapper around the `Application::Message` associate type
-// to allows the `shell` to create internal messages, while still having
-// the current user specified custom messages.
-#[derive(Debug)]
-pub enum Event<Message> {
- /// An [`Application`] generated message
- Application(Message),
-
- /// TODO(derezzedex)
- // Create a wrapper variant of `window::Event` type instead
- // (maybe we should also allow users to listen/react to those internal messages?)
- NewWindow(window::Id, settings::Window),
- /// TODO(derezzedex)
- CloseWindow(window::Id),
- /// TODO(derezzedex)
- WindowCreated(window::Id, winit::window::Window),
-}
-
/// Updates an [`Application`] by feeding it the provided messages, spawning any
/// resulting [`Command`], and tracking its [`Subscription`].
pub fn update<A: Application, E: Executor>(
@@ -872,7 +853,11 @@ pub fn run_command<A, E>(
command::Action::Window(id, action) => match action {
window::Action::Spawn { settings } => {
proxy
- .send_event(Event::NewWindow(id, settings.into()))
+ .send_event(Event::NewWindow {
+ id,
+ settings: settings.into(),
+ title: application.title(id),
+ })
.expect("Send message to event loop");
}
window::Action::Close => {
@@ -934,6 +919,16 @@ pub fn run_command<A, E>(
let window = windows.get(&id).expect("No window found!");
window.set_decorations(!window.is_decorated());
}
+ Action::RequestUserAttention(attention_type) => {
+ let window = windows.get(&id).expect("No window found!");
+ window.request_user_attention(
+ attention_type.map(conversion::user_attention),
+ );
+ }
+ Action::GainFocus => {
+ let window = windows.get(&id).expect("No window found!");
+ window.focus_window();
+ }
},
command::Action::System(action) => match action {
system::Action::QueryInformation(_tag) => {
@@ -1031,26 +1026,3 @@ where
interfaces
}
-
-#[allow(unsafe_code)]
-fn gl_surface(
- display: &Display,
- gl_config: &Config,
- window: &winit::window::Window,
-) -> Surface<WindowSurface> {
- let (width, height) = window.inner_size().into();
-
- let surface_attributes = SurfaceAttributesBuilder::<WindowSurface>::new()
- .with_srgb(Some(true))
- .build(
- window.raw_window_handle(),
- NonZeroU32::new(width).unwrap_or(ONE),
- NonZeroU32::new(height).unwrap_or(ONE),
- );
-
- unsafe {
- display
- .create_window_surface(gl_config, &surface_attributes)
- .expect("failed to create surface")
- }
-}
diff --git a/glutin/src/multi_window/state.rs b/glutin/src/multi_window/state.rs
index e7e82876..04ec5083 100644
--- a/glutin/src/multi_window/state.rs
+++ b/glutin/src/multi_window/state.rs
@@ -8,7 +8,6 @@ use iced_winit::winit;
use winit::event::{Touch, WindowEvent};
use winit::window::Window;
-use std::collections::HashMap;
use std::marker::PhantomData;
/// The state of a windowed [`Application`].
@@ -33,8 +32,8 @@ where
<A::Renderer as crate::Renderer>::Theme: application::StyleSheet,
{
/// Creates a new [`State`] for the provided [`Application`] and window.
- pub fn new(application: &A, window: &Window) -> Self {
- let title = application.title();
+ pub fn new(application: &A, window_id: window::Id, window: &Window) -> Self {
+ let title = application.title(window_id);
let scale_factor = application.scale_factor();
let theme = application.theme();
let appearance = theme.appearance(&application.style());
@@ -67,7 +66,7 @@ where
&self.viewport
}
- /// TODO(derezzedex)
+ /// Returns whether or not the current [`Viewport`] has changed.
pub fn viewport_changed(&self) -> bool {
self.viewport_changed
}
@@ -187,12 +186,11 @@ where
pub fn synchronize(
&mut self,
application: &A,
- windows: &HashMap<window::Id, Window>,
+ window_id: window::Id,
+ window: &Window,
) {
- let window = windows.values().next().expect("No window found");
-
// Update window title
- let new_title = application.title();
+ let new_title = application.title(window_id);
if self.title != new_title {
window.set_title(&new_title);
diff --git a/native/src/window.rs b/native/src/window.rs
index 1c03fcdf..96a5fe61 100644
--- a/native/src/window.rs
+++ b/native/src/window.rs
@@ -4,6 +4,8 @@ mod event;
mod icon;
mod id;
mod mode;
+mod position;
+mod settings;
mod user_attention;
pub use action::Action;
@@ -11,6 +13,6 @@ pub use event::Event;
pub use icon::Icon;
pub use id::Id;
pub use mode::Mode;
-pub use user_attention::UserAttention;
pub use position::Position;
pub use settings::Settings;
+pub use user_attention::UserAttention;
diff --git a/native/src/window/action.rs b/native/src/window/action.rs
index 0587f25c..929663ec 100644
--- a/native/src/window/action.rs
+++ b/native/src/window/action.rs
@@ -1,4 +1,4 @@
-use crate::window::{self, Mode, UserAttention};
+use crate::window;
use iced_futures::MaybeSend;
use std::fmt;
@@ -13,9 +13,9 @@ pub enum Action<T> {
/// There’s no guarantee that this will work unless the left mouse
/// button was pressed immediately before this function is called.
Drag,
- /// TODO(derezzedex)
+ /// Spawns a new window with the provided [`window::Settings`].
Spawn {
- /// TODO(derezzedex)
+ /// The settings of the [`Window`].
settings: window::Settings,
},
/// Resize the window.
@@ -62,7 +62,7 @@ pub enum Action<T> {
/// - **macOS:** `None` has no effect.
/// - **X11:** Requests for user attention must be manually cleared.
/// - **Wayland:** Requires `xdg_activation_v1` protocol, `None` has no effect.
- RequestUserAttention(Option<UserAttention>),
+ RequestUserAttention(Option<window::UserAttention>),
/// Brings the window to the front and sets input focus. Has no effect if the window is
/// already in focus, minimized, or not visible.
///
diff --git a/native/src/window/icon.rs b/native/src/window/icon.rs
index e89baf03..08a6acfd 100644
--- a/native/src/window/icon.rs
+++ b/native/src/window/icon.rs
@@ -3,10 +3,10 @@
/// The icon of a window.
#[derive(Debug, Clone)]
pub struct Icon {
- /// TODO(derezzedex)
+ /// The __rgba__ color data of the window [`Icon`].
pub rgba: Vec<u8>,
- /// TODO(derezzedex)
+ /// The width of the window [`Icon`].
pub width: u32,
- /// TODO(derezzedex)
+ /// The height of the window [`Icon`].
pub height: u32,
}
diff --git a/native/src/window/id.rs b/native/src/window/id.rs
index 5060e162..fa9761f5 100644
--- a/native/src/window/id.rs
+++ b/native/src/window/id.rs
@@ -1,15 +1,18 @@
use std::collections::hash_map::DefaultHasher;
+use std::fmt::{Display, Formatter};
use std::hash::{Hash, Hasher};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
-/// TODO(derezzedex)
+/// The ID of the window.
+///
+/// This is not necessarily the same as the window ID fetched from `winit::window::Window`.
pub struct Id(u64);
impl Id {
/// TODO(derezzedex): maybe change `u64` to an enum `Type::{Single, Multi(u64)}`
pub const MAIN: Self = Id(0);
- /// TODO(derezzedex)
+ /// Creates a new unique window ID.
pub fn new(id: impl Hash) -> Id {
let mut hasher = DefaultHasher::new();
id.hash(&mut hasher);
@@ -17,3 +20,9 @@ impl Id {
Id(hasher.finish())
}
}
+
+impl Display for Id {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ write!(f, "Id({})", self.0)
+ }
+}
diff --git a/src/multi_window/application.rs b/src/multi_window/application.rs
index 7d559397..dc1ac5b0 100644
--- a/src/multi_window/application.rs
+++ b/src/multi_window/application.rs
@@ -44,7 +44,7 @@ pub trait Application: Sized {
///
/// This title can be dynamic! The runtime will automatically update the
/// title of your application when necessary.
- fn title(&self) -> String;
+ fn title(&self, window: window::Id) -> String;
/// Handles a __message__ and updates the state of the [`Application`].
///
@@ -110,7 +110,7 @@ pub trait Application: Sized {
false
}
- /// TODO(derezzedex)
+ /// Requests that the [`window`] be closed.
fn close_requested(&self, window: window::Id) -> Self::Message;
/// Runs the [`Application`].
@@ -163,8 +163,8 @@ where
(Instance(app), command)
}
- fn title(&self) -> String {
- self.0.title()
+ fn title(&self, window: window::Id) -> String {
+ self.0.title(window)
}
fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
diff --git a/winit/src/application.rs b/winit/src/application.rs
index 910f3d94..eef6833c 100644
--- a/winit/src/application.rs
+++ b/winit/src/application.rs
@@ -675,7 +675,7 @@ pub fn run_command<A, E>(
window::Action::Drag => {
let _res = window.drag_window();
}
- window::Action::Spawn { .. } | window::Action::Close => {
+ window::Action::Spawn { .. } => {
log::info!(
"This is only available on `multi_window::Application`"
)
diff --git a/winit/src/multi_window.rs b/winit/src/multi_window.rs
index 43455148..6a2bdca9 100644
--- a/winit/src/multi_window.rs
+++ b/winit/src/multi_window.rs
@@ -22,6 +22,7 @@ use iced_native::user_interface::{self, UserInterface};
pub use iced_native::application::{Appearance, StyleSheet};
+use iced_native::window::Action;
use std::collections::HashMap;
use std::mem::ManuallyDrop;
@@ -36,7 +37,14 @@ pub enum Event<Message> {
/// TODO(derezzedex)
// Create a wrapper variant of `window::Event` type instead
// (maybe we should also allow users to listen/react to those internal messages?)
- NewWindow(window::Id, settings::Window),
+ NewWindow {
+ /// The [window::Id] of the newly spawned [`Window`].
+ id: window::Id,
+ /// The [settings::Window] of the newly spawned [`Window`].
+ settings: settings::Window,
+ /// The title of the newly spawned [`Window`].
+ title: String,
+ },
/// TODO(derezzedex)
CloseWindow(window::Id),
/// TODO(derezzedex)
@@ -95,11 +103,11 @@ where
/// load state from a file, perform an initial HTTP request, etc.
fn new(flags: Self::Flags) -> (Self, Command<Self::Message>);
- /// Returns the current title of the [`Application`].
+ /// Returns the current title of the current [`Application`] window.
///
/// This title can be dynamic! The runtime will automatically update the
/// title of your application when necessary.
- fn title(&self) -> String;
+ fn title(&self, window_id: window::Id) -> String;
/// Returns the current [`Theme`] of the [`Application`].
fn theme(&self) -> <Self::Renderer as crate::Renderer>::Theme;
@@ -144,7 +152,7 @@ where
false
}
- /// TODO(derezzedex)
+ /// Requests that the [`window`] be closed.
fn close_requested(&self, window: window::Id) -> Self::Message;
}
@@ -184,7 +192,7 @@ where
};
let builder = settings.window.into_builder(
- &application.title(),
+ &application.title(window::Id::MAIN),
event_loop.primary_monitor(),
settings.id,
);
@@ -253,14 +261,13 @@ where
event: winit::event::WindowEvent::Resized(*new_inner_size),
window_id,
}),
- winit::event::Event::UserEvent(Event::NewWindow(id, settings)) => {
- // TODO(derezzedex)
+ winit::event::Event::UserEvent(Event::NewWindow {
+ id,
+ settings,
+ title,
+ }) => {
let window = settings
- .into_builder(
- "fix window title",
- event_loop.primary_monitor(),
- None,
- )
+ .into_builder(&title, event_loop.primary_monitor(), None)
.build(event_loop)
.expect("Failed to build window");
@@ -320,10 +327,7 @@ async fn run_instance<A, E, C>(
for (&id, window) in windows.keys().zip(windows.values()) {
let mut surface = compositor.create_surface(window);
- println!("Creating surface for window: {:?}", window);
-
- let state = State::new(&application, window);
-
+ let state = State::new(&application, id, window);
let physical_size = state.physical_size();
compositor.configure_surface(
@@ -457,7 +461,11 @@ async fn run_instance<A, E, C>(
);
// Update window
- state.synchronize(&application, &windows);
+ state.synchronize(
+ &application,
+ id,
+ windows.get(&id).expect("No window found with ID."),
+ );
let should_exit = application.should_exit();
@@ -516,72 +524,85 @@ async fn run_instance<A, E, C>(
),
));
}
- event::Event::UserEvent(event) => {
- match event {
- Event::Application(message) => {
- messages.push(message);
- }
- Event::WindowCreated(id, window) => {
- let mut surface = compositor.create_surface(&window);
-
- let state = State::new(&application, &window);
+ event::Event::UserEvent(event) => match event {
+ Event::Application(message) => {
+ messages.push(message);
+ }
+ Event::WindowCreated(id, window) => {
+ let mut surface = compositor.create_surface(&window);
- let physical_size = state.physical_size();
+ let state = State::new(&application, id, &window);
- compositor.configure_surface(
- &mut surface,
- physical_size.width,
- physical_size.height,
- );
+ let physical_size = state.physical_size();
- let user_interface = build_user_interface(
- &application,
- user_interface::Cache::default(),
- &mut renderer,
- state.logical_size(),
- &mut debug,
- id,
- );
+ compositor.configure_surface(
+ &mut surface,
+ physical_size.width,
+ physical_size.height,
+ );
- let _ = states.insert(id, state);
- let _ = surfaces.insert(id, surface);
- let _ = interfaces.insert(id, user_interface);
- let _ = window_ids.insert(window.id(), id);
- let _ = windows.insert(id, window);
- }
- Event::CloseWindow(id) => {
- println!("Closing window {:?}. Total: {}", id, windows.len());
+ let user_interface = build_user_interface(
+ &application,
+ user_interface::Cache::default(),
+ &mut renderer,
+ state.logical_size(),
+ &mut debug,
+ id,
+ );
- if let Some(window) = windows.get(&id) {
- if window_ids.remove(&window.id()).is_none() {
- log::error!("Failed to remove window with id {:?} from window_ids.", window.id());
- }
- } else {
- log::error!("Could not find window with id {:?} in windows.", id);
- }
- if states.remove(&id).is_none() {
- log::error!("Failed to remove window {:?} from states.", id);
- }
- if interfaces.remove(&id).is_none() {
- log::error!("Failed to remove window {:?} from interfaces.", id);
- }
- if windows.remove(&id).is_none() {
- log::error!("Failed to remove window {:?} from windows.", id);
- }
- if surfaces.remove(&id).is_none() {
- log::error!("Failed to remove window {:?} from surfaces.", id);
+ let _ = states.insert(id, state);
+ let _ = surfaces.insert(id, surface);
+ let _ = interfaces.insert(id, user_interface);
+ let _ = window_ids.insert(window.id(), id);
+ let _ = windows.insert(id, window);
+ }
+ Event::CloseWindow(id) => {
+ if let Some(window) = windows.get(&id) {
+ if window_ids.remove(&window.id()).is_none() {
+ log::error!("Failed to remove window with id {:?} from window_ids.", window.id());
}
+ } else {
+ log::error!(
+ "Could not find window with id {:?} in windows.",
+ id
+ );
+ }
+ if states.remove(&id).is_none() {
+ log::error!(
+ "Failed to remove window {:?} from states.",
+ id
+ );
+ }
+ if interfaces.remove(&id).is_none() {
+ log::error!(
+ "Failed to remove window {:?} from interfaces.",
+ id
+ );
+ }
+ if windows.remove(&id).is_none() {
+ log::error!(
+ "Failed to remove window {:?} from windows.",
+ id
+ );
+ }
+ if surfaces.remove(&id).is_none() {
+ log::error!(
+ "Failed to remove window {:?} from surfaces.",
+ id
+ );
+ }
- if windows.is_empty() {
- log::info!("All windows are closed. Terminating program.");
- break 'main;
- } else {
- log::info!("Remaining windows: {:?}", windows.len());
- }
+ if windows.is_empty() {
+ log::info!(
+ "All windows are closed. Terminating program."
+ );
+ break 'main;
+ } else {
+ log::info!("Remaining windows: {:?}", windows.len());
}
- Event::NewWindow(_, _) => unreachable!(),
}
- }
+ Event::NewWindow { .. } => unreachable!(),
+ },
event::Event::RedrawRequested(id) => {
let state = window_ids
.get(&id)
@@ -716,11 +737,10 @@ async fn run_instance<A, E, C>(
));
}
} else {
- // TODO(derezzedex): log error
+ log::error!("No window state found for id: {:?}", window_id);
}
} else {
- // TODO(derezzedex): log error
- // println!("{:?}: {:?}", window_id, window_event);
+ log::error!("No window found with id: {:?}", window_id);
}
}
_ => {}
@@ -864,7 +884,11 @@ pub fn run_command<A, E>(
command::Action::Window(id, action) => match action {
window::Action::Spawn { settings } => {
proxy
- .send_event(Event::NewWindow(id, settings.into()))
+ .send_event(Event::NewWindow {
+ id,
+ settings: settings.into(),
+ title: application.title(id),
+ })
.expect("Send message to event loop");
}
window::Action::Close => {
@@ -926,6 +950,16 @@ pub fn run_command<A, E>(
let window = windows.get(&id).expect("No window found!");
window.set_decorations(!window.is_decorated());
}
+ window::Action::RequestUserAttention(attention_type) => {
+ let window = windows.get(&id).expect("No window found!");
+ window.request_user_attention(
+ attention_type.map(conversion::user_attention),
+ );
+ }
+ Action::GainFocus => {
+ let window = windows.get(&id).expect("No window found!");
+ window.focus_window();
+ }
},
command::Action::System(action) => match action {
system::Action::QueryInformation(_tag) => {
diff --git a/winit/src/multi_window/state.rs b/winit/src/multi_window/state.rs
index eebdcdf1..7a598b98 100644
--- a/winit/src/multi_window/state.rs
+++ b/winit/src/multi_window/state.rs
@@ -4,7 +4,6 @@ use crate::multi_window::Application;
use crate::window;
use crate::{Color, Debug, Point, Size, Viewport};
-use std::collections::HashMap;
use std::marker::PhantomData;
use winit::event::{Touch, WindowEvent};
use winit::window::Window;
@@ -31,8 +30,8 @@ where
<A::Renderer as crate::Renderer>::Theme: application::StyleSheet,
{
/// Creates a new [`State`] for the provided [`Application`] and window.
- pub fn new(application: &A, window: &Window) -> Self {
- let title = application.title();
+ pub fn new(application: &A, window_id: window::Id, window: &Window) -> Self {
+ let title = application.title(window_id);
let scale_factor = application.scale_factor();
let theme = application.theme();
let appearance = theme.appearance(&application.style());
@@ -65,7 +64,7 @@ where
&self.viewport
}
- /// TODO(derezzedex)
+ /// Returns whether or not the viewport changed.
pub fn viewport_changed(&self) -> bool {
self.viewport_changed
}
@@ -184,12 +183,11 @@ where
pub fn synchronize(
&mut self,
application: &A,
- windows: &HashMap<window::Id, Window>,
+ window_id: window::Id,
+ window: &Window,
) {
- let window = windows.values().next().expect("No window found");
-
// Update window title
- let new_title = application.title();
+ let new_title = application.title(window_id);
if self.title != new_title {
window.set_title(&new_title);
diff --git a/winit/src/window.rs b/winit/src/window.rs
index fba863ef..5a8ff6df 100644
--- a/winit/src/window.rs
+++ b/winit/src/window.rs
@@ -2,19 +2,19 @@
use crate::command::{self, Command};
use iced_native::window;
-pub use window::{Id, Event, Mode, UserAttention};
+pub use window::{Event, Id, Mode, UserAttention};
-/// Closes the current window and exits the application.
-pub fn close<Message>() -> Command<Message> {
- Command::single(command::Action::Window(window::Action::Close))
+/// Closes the window.
+pub fn close<Message>(id: window::Id) -> Command<Message> {
+ Command::single(command::Action::Window(id, window::Action::Close))
}
/// Begins dragging the window while the left mouse button is held.
-pub fn drag<Message>() -> Command<Message> {
- Command::single(command::Action::Window(window::Action::Drag))
+pub fn drag<Message>(id: window::Id) -> Command<Message> {
+ Command::single(command::Action::Window(id, window::Action::Drag))
}
-/// TODO(derezzedex)
+/// Spawns a new window.
pub fn spawn<Message>(
id: window::Id,
settings: window::Settings,
@@ -25,11 +25,6 @@ pub fn spawn<Message>(
))
}
-/// TODO(derezzedex)
-pub fn close<Message>(id: window::Id) -> Command<Message> {
- Command::single(command::Action::Window(id, window::Action::Close))
-}
-
/// Resizes the window to the given logical dimensions.
pub fn resize<Message>(
id: window::Id,
@@ -43,13 +38,19 @@ pub fn resize<Message>(
}
/// Sets the window to maximized or back.
-pub fn maximize<Message>(value: bool) -> Command<Message> {
- Command::single(command::Action::Window(window::Action::Maximize(value)))
+pub fn maximize<Message>(id: window::Id, value: bool) -> Command<Message> {
+ Command::single(command::Action::Window(
+ id,
+ window::Action::Maximize(value),
+ ))
}
/// Set the window to minimized or back.
-pub fn minimize<Message>(value: bool) -> Command<Message> {
- Command::single(command::Action::Window(window::Action::Minimize(value)))
+pub fn minimize<Message>(id: window::Id, value: bool) -> Command<Message> {
+ Command::single(command::Action::Window(
+ id,
+ window::Action::Minimize(value),
+ ))
}
/// Moves a window to the given logical coordinates.
@@ -63,8 +64,8 @@ pub fn set_mode<Message>(id: window::Id, mode: Mode) -> Command<Message> {
}
/// Sets the window to maximized or back.
-pub fn toggle_maximize<Message>() -> Command<Message> {
- Command::single(command::Action::Window(window::Action::ToggleMaximize))
+pub fn toggle_maximize<Message>(id: window::Id) -> Command<Message> {
+ Command::single(command::Action::Window(id, window::Action::ToggleMaximize))
}
/// Fetches the current [`Mode`] of the window.