refactored window storage;
new helper window events (Destroyed, Created); clippy + fmt;
This commit is contained in:
parent
633f405f3f
commit
d53ccc857d
56 changed files with 1508 additions and 1819 deletions
|
|
@ -1,33 +1,50 @@
|
|||
use crate::application::{self, StyleSheet as _};
|
||||
use crate::conversion;
|
||||
use crate::core;
|
||||
use crate::core::{mouse, window};
|
||||
use crate::core::{Color, Size};
|
||||
use crate::graphics::Viewport;
|
||||
use crate::multi_window::Application;
|
||||
use crate::window;
|
||||
use crate::{Color, Debug, Point, Size, Viewport};
|
||||
use crate::style::application;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use iced_style::application::StyleSheet;
|
||||
use winit::event::{Touch, WindowEvent};
|
||||
use winit::window::Window;
|
||||
|
||||
/// The state of a multi-windowed [`Application`].
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct State<A: Application>
|
||||
where
|
||||
<A::Renderer as crate::Renderer>::Theme: application::StyleSheet,
|
||||
<A::Renderer as core::Renderer>::Theme: application::StyleSheet,
|
||||
{
|
||||
title: String,
|
||||
scale_factor: f64,
|
||||
viewport: Viewport,
|
||||
viewport_changed: bool,
|
||||
cursor_position: winit::dpi::PhysicalPosition<f64>,
|
||||
viewport_version: usize,
|
||||
cursor_position: Option<winit::dpi::PhysicalPosition<f64>>,
|
||||
modifiers: winit::event::ModifiersState,
|
||||
theme: <A::Renderer as crate::Renderer>::Theme,
|
||||
theme: <A::Renderer as core::Renderer>::Theme,
|
||||
appearance: application::Appearance,
|
||||
application: PhantomData<A>,
|
||||
}
|
||||
|
||||
impl<A: Application> Debug for State<A>
|
||||
where
|
||||
<A::Renderer as core::Renderer>::Theme: application::StyleSheet,
|
||||
{
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("multi_window::State")
|
||||
.field("title", &self.title)
|
||||
.field("scale_factor", &self.scale_factor)
|
||||
.field("viewport", &self.viewport)
|
||||
.field("viewport_version", &self.viewport_version)
|
||||
.field("cursor_position", &self.cursor_position)
|
||||
.field("appearance", &self.appearance)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Application> State<A>
|
||||
where
|
||||
<A::Renderer as crate::Renderer>::Theme: application::StyleSheet,
|
||||
<A::Renderer as core::Renderer>::Theme: application::StyleSheet,
|
||||
{
|
||||
/// Creates a new [`State`] for the provided [`Application`]'s `window`.
|
||||
pub fn new(
|
||||
|
|
@ -53,13 +70,11 @@ where
|
|||
title,
|
||||
scale_factor,
|
||||
viewport,
|
||||
viewport_changed: false,
|
||||
// TODO: Encode cursor availability in the type-system
|
||||
cursor_position: winit::dpi::PhysicalPosition::new(-1.0, -1.0),
|
||||
viewport_version: 0,
|
||||
cursor_position: None,
|
||||
modifiers: winit::event::ModifiersState::default(),
|
||||
theme,
|
||||
appearance,
|
||||
application: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -68,9 +83,11 @@ where
|
|||
&self.viewport
|
||||
}
|
||||
|
||||
/// Returns whether or not the viewport changed.
|
||||
pub fn viewport_changed(&self) -> bool {
|
||||
self.viewport_changed
|
||||
/// Returns the version of the [`Viewport`] of the [`State`].
|
||||
///
|
||||
/// The version is incremented every time the [`Viewport`] changes.
|
||||
pub fn viewport_version(&self) -> usize {
|
||||
self.viewport_version
|
||||
}
|
||||
|
||||
/// Returns the physical [`Size`] of the [`Viewport`] of the [`State`].
|
||||
|
|
@ -89,11 +106,16 @@ where
|
|||
}
|
||||
|
||||
/// Returns the current cursor position of the [`State`].
|
||||
pub fn cursor_position(&self) -> Point {
|
||||
conversion::cursor_position(
|
||||
self.cursor_position,
|
||||
self.viewport.scale_factor(),
|
||||
)
|
||||
pub fn cursor(&self) -> mouse::Cursor {
|
||||
self.cursor_position
|
||||
.map(|cursor_position| {
|
||||
conversion::cursor_position(
|
||||
cursor_position,
|
||||
self.viewport.scale_factor(),
|
||||
)
|
||||
})
|
||||
.map(mouse::Cursor::Available)
|
||||
.unwrap_or(mouse::Cursor::Unavailable)
|
||||
}
|
||||
|
||||
/// Returns the current keyboard modifiers of the [`State`].
|
||||
|
|
@ -102,7 +124,7 @@ where
|
|||
}
|
||||
|
||||
/// Returns the current theme of the [`State`].
|
||||
pub fn theme(&self) -> &<A::Renderer as crate::Renderer>::Theme {
|
||||
pub fn theme(&self) -> &<A::Renderer as core::Renderer>::Theme {
|
||||
&self.theme
|
||||
}
|
||||
|
||||
|
|
@ -121,7 +143,7 @@ where
|
|||
&mut self,
|
||||
window: &Window,
|
||||
event: &WindowEvent<'_>,
|
||||
_debug: &mut Debug,
|
||||
_debug: &mut crate::runtime::Debug,
|
||||
) {
|
||||
match event {
|
||||
WindowEvent::Resized(new_size) => {
|
||||
|
|
@ -132,7 +154,7 @@ where
|
|||
window.scale_factor() * self.scale_factor,
|
||||
);
|
||||
|
||||
self.viewport_changed = true;
|
||||
self.viewport_version = self.viewport_version.wrapping_add(1);
|
||||
}
|
||||
WindowEvent::ScaleFactorChanged {
|
||||
scale_factor: new_scale_factor,
|
||||
|
|
@ -146,18 +168,16 @@ where
|
|||
new_scale_factor * self.scale_factor,
|
||||
);
|
||||
|
||||
self.viewport_changed = true;
|
||||
self.viewport_version = self.viewport_version.wrapping_add(1);
|
||||
}
|
||||
WindowEvent::CursorMoved { position, .. }
|
||||
| WindowEvent::Touch(Touch {
|
||||
location: position, ..
|
||||
}) => {
|
||||
self.cursor_position = *position;
|
||||
self.cursor_position = Some(*position);
|
||||
}
|
||||
WindowEvent::CursorLeft { .. } => {
|
||||
// TODO: Encode cursor availability in the type-system
|
||||
self.cursor_position =
|
||||
winit::dpi::PhysicalPosition::new(-1.0, -1.0);
|
||||
self.cursor_position = None;
|
||||
}
|
||||
WindowEvent::ModifiersChanged(new_modifiers) => {
|
||||
self.modifiers = *new_modifiers;
|
||||
|
|
@ -197,16 +217,20 @@ where
|
|||
self.title = new_title;
|
||||
}
|
||||
|
||||
// Update scale factor
|
||||
// Update scale factor and size
|
||||
let new_scale_factor = application.scale_factor(window_id);
|
||||
let new_size = window.inner_size();
|
||||
let current_size = self.viewport.physical_size();
|
||||
|
||||
if self.scale_factor != new_scale_factor {
|
||||
let size = window.inner_size();
|
||||
|
||||
if self.scale_factor != new_scale_factor
|
||||
|| (current_size.width, current_size.height)
|
||||
!= (new_size.width, new_size.height)
|
||||
{
|
||||
self.viewport = Viewport::with_physical_size(
|
||||
Size::new(size.width, size.height),
|
||||
Size::new(new_size.width, new_size.height),
|
||||
window.scale_factor() * new_scale_factor,
|
||||
);
|
||||
self.viewport_version = self.viewport_version.wrapping_add(1);
|
||||
|
||||
self.scale_factor = new_scale_factor;
|
||||
}
|
||||
|
|
|
|||
170
winit/src/multi_window/windows.rs
Normal file
170
winit/src/multi_window/windows.rs
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
use crate::core::{window, Size};
|
||||
use crate::multi_window::{Application, State};
|
||||
use iced_graphics::Compositor;
|
||||
use iced_style::application::StyleSheet;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use winit::monitor::MonitorHandle;
|
||||
|
||||
pub struct Windows<A: Application, C: Compositor>
|
||||
where
|
||||
<A::Renderer as crate::core::Renderer>::Theme: StyleSheet,
|
||||
C: Compositor<Renderer = A::Renderer>,
|
||||
{
|
||||
pub ids: Vec<window::Id>,
|
||||
pub raw: Vec<winit::window::Window>,
|
||||
pub states: Vec<State<A>>,
|
||||
pub viewport_versions: Vec<usize>,
|
||||
pub surfaces: Vec<C::Surface>,
|
||||
pub renderers: Vec<A::Renderer>,
|
||||
pub pending_destroy: Vec<(window::Id, winit::window::WindowId)>,
|
||||
}
|
||||
|
||||
impl<A: Application, C: Compositor> Debug for Windows<A, C>
|
||||
where
|
||||
<A::Renderer as crate::core::Renderer>::Theme: StyleSheet,
|
||||
C: Compositor<Renderer = A::Renderer>,
|
||||
{
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Windows")
|
||||
.field("ids", &self.ids)
|
||||
.field(
|
||||
"raw",
|
||||
&self
|
||||
.raw
|
||||
.iter()
|
||||
.map(|raw| raw.id())
|
||||
.collect::<Vec<winit::window::WindowId>>(),
|
||||
)
|
||||
.field("states", &self.states)
|
||||
.field("viewport_versions", &self.viewport_versions)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Application, C: Compositor> Windows<A, C>
|
||||
where
|
||||
<A::Renderer as crate::core::Renderer>::Theme: StyleSheet,
|
||||
C: Compositor<Renderer = A::Renderer>,
|
||||
{
|
||||
/// Creates a new [`Windows`] with a single `window::Id::MAIN` window.
|
||||
pub fn new(
|
||||
application: &A,
|
||||
compositor: &mut C,
|
||||
renderer: A::Renderer,
|
||||
main: winit::window::Window,
|
||||
) -> Self {
|
||||
let state = State::new(application, window::Id::MAIN, &main);
|
||||
let viewport_version = state.viewport_version();
|
||||
let physical_size = state.physical_size();
|
||||
let surface = compositor.create_surface(
|
||||
&main,
|
||||
physical_size.width,
|
||||
physical_size.height,
|
||||
);
|
||||
|
||||
Self {
|
||||
ids: vec![window::Id::MAIN],
|
||||
raw: vec![main],
|
||||
states: vec![state],
|
||||
viewport_versions: vec![viewport_version],
|
||||
surfaces: vec![surface],
|
||||
renderers: vec![renderer],
|
||||
pending_destroy: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a new window to [`Windows`]. Returns the size of the newly created window in logical
|
||||
/// pixels & the index of the window within [`Windows`].
|
||||
pub fn add(
|
||||
&mut self,
|
||||
application: &A,
|
||||
compositor: &mut C,
|
||||
id: window::Id,
|
||||
window: winit::window::Window,
|
||||
) -> (Size, usize) {
|
||||
let state = State::new(application, id, &window);
|
||||
let window_size = state.logical_size();
|
||||
let viewport_version = state.viewport_version();
|
||||
let physical_size = state.physical_size();
|
||||
let surface = compositor.create_surface(
|
||||
&window,
|
||||
physical_size.width,
|
||||
physical_size.height,
|
||||
);
|
||||
let renderer = compositor.renderer();
|
||||
|
||||
self.ids.push(id);
|
||||
self.raw.push(window);
|
||||
self.states.push(state);
|
||||
self.viewport_versions.push(viewport_version);
|
||||
self.surfaces.push(surface);
|
||||
self.renderers.push(renderer);
|
||||
|
||||
(window_size, self.ids.len() - 1)
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.ids.is_empty()
|
||||
}
|
||||
|
||||
pub fn main(&self) -> &winit::window::Window {
|
||||
&self.raw[0]
|
||||
}
|
||||
|
||||
pub fn index_from_raw(&self, id: winit::window::WindowId) -> usize {
|
||||
self.raw
|
||||
.iter()
|
||||
.position(|window| window.id() == id)
|
||||
.expect("No raw window in multi_window::Windows")
|
||||
}
|
||||
|
||||
pub fn index_from_id(&self, id: window::Id) -> usize {
|
||||
self.ids
|
||||
.iter()
|
||||
.position(|window_id| *window_id == id)
|
||||
.expect("No window in multi_window::Windows")
|
||||
}
|
||||
|
||||
pub fn last_monitor(&self) -> Option<MonitorHandle> {
|
||||
self.raw.last().and_then(|w| w.current_monitor())
|
||||
}
|
||||
|
||||
pub fn last(&self) -> usize {
|
||||
self.ids.len() - 1
|
||||
}
|
||||
|
||||
pub fn with_raw(&self, id: window::Id) -> &winit::window::Window {
|
||||
let i = self.index_from_id(id);
|
||||
&self.raw[i]
|
||||
}
|
||||
|
||||
/// Deletes the window with `id` from [`Windows`]. Returns the index that the window had.
|
||||
pub fn delete(&mut self, id: window::Id) -> usize {
|
||||
let i = self.index_from_id(id);
|
||||
|
||||
let id = self.ids.remove(i);
|
||||
let window = self.raw.remove(i);
|
||||
let _ = self.states.remove(i);
|
||||
let _ = self.viewport_versions.remove(i);
|
||||
let _ = self.surfaces.remove(i);
|
||||
|
||||
self.pending_destroy.push((id, window.id()));
|
||||
|
||||
i
|
||||
}
|
||||
|
||||
/// Gets the winit `window` that is pending to be destroyed if it exists.
|
||||
pub fn get_pending_destroy(
|
||||
&mut self,
|
||||
window: winit::window::WindowId,
|
||||
) -> window::Id {
|
||||
let i = self
|
||||
.pending_destroy
|
||||
.iter()
|
||||
.position(|(_, window_id)| window == *window_id)
|
||||
.unwrap();
|
||||
|
||||
let (id, _) = self.pending_destroy.remove(i);
|
||||
id
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue