summaryrefslogtreecommitdiffstats
path: root/winit/src/multi_window
diff options
context:
space:
mode:
Diffstat (limited to 'winit/src/multi_window')
-rw-r--r--winit/src/multi_window/state.rs4
-rw-r--r--winit/src/multi_window/window_manager.rs156
-rw-r--r--winit/src/multi_window/windows.rs201
3 files changed, 158 insertions, 203 deletions
diff --git a/winit/src/multi_window/state.rs b/winit/src/multi_window/state.rs
index e9a9f91a..03da5ad7 100644
--- a/winit/src/multi_window/state.rs
+++ b/winit/src/multi_window/state.rs
@@ -19,7 +19,7 @@ where
title: String,
scale_factor: f64,
viewport: Viewport,
- viewport_version: usize,
+ viewport_version: u64,
cursor_position: Option<winit::dpi::PhysicalPosition<f64>>,
modifiers: winit::event::ModifiersState,
theme: <A::Renderer as core::Renderer>::Theme,
@@ -86,7 +86,7 @@ where
/// Returns the version of the [`Viewport`] of the [`State`].
///
/// The version is incremented every time the [`Viewport`] changes.
- pub fn viewport_version(&self) -> usize {
+ pub fn viewport_version(&self) -> u64 {
self.viewport_version
}
diff --git a/winit/src/multi_window/window_manager.rs b/winit/src/multi_window/window_manager.rs
new file mode 100644
index 00000000..d54156e7
--- /dev/null
+++ b/winit/src/multi_window/window_manager.rs
@@ -0,0 +1,156 @@
+use crate::core::mouse;
+use crate::core::window::Id;
+use crate::core::{Point, Size};
+use crate::graphics::Compositor;
+use crate::multi_window::{Application, State};
+use crate::style::application::StyleSheet;
+
+use std::collections::BTreeMap;
+use winit::monitor::MonitorHandle;
+
+#[allow(missing_debug_implementations)]
+pub struct WindowManager<A: Application, C: Compositor>
+where
+ <A::Renderer as crate::core::Renderer>::Theme: StyleSheet,
+ C: Compositor<Renderer = A::Renderer>,
+{
+ aliases: BTreeMap<winit::window::WindowId, Id>,
+ entries: BTreeMap<Id, Window<A, C>>,
+}
+
+impl<A, C> WindowManager<A, C>
+where
+ A: Application,
+ C: Compositor<Renderer = A::Renderer>,
+ <A::Renderer as crate::core::Renderer>::Theme: StyleSheet,
+{
+ pub fn new() -> Self {
+ Self {
+ aliases: BTreeMap::new(),
+ entries: BTreeMap::new(),
+ }
+ }
+
+ pub fn insert(
+ &mut self,
+ id: Id,
+ window: winit::window::Window,
+ application: &A,
+ compositor: &mut C,
+ exit_on_close_request: bool,
+ ) -> &mut Window<A, C> {
+ let state = State::new(application, id, &window);
+ 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.create_renderer();
+
+ let _ = self.aliases.insert(window.id(), id);
+
+ let _ = self.entries.insert(
+ id,
+ Window {
+ raw: window,
+ state,
+ viewport_version,
+ exit_on_close_request,
+ surface,
+ renderer,
+ mouse_interaction: mouse::Interaction::Idle,
+ },
+ );
+
+ self.entries
+ .get_mut(&id)
+ .expect("Get window that was just inserted")
+ }
+
+ pub fn is_empty(&self) -> bool {
+ self.entries.is_empty()
+ }
+
+ pub fn iter_mut(
+ &mut self,
+ ) -> impl Iterator<Item = (Id, &mut Window<A, C>)> {
+ self.entries.iter_mut().map(|(k, v)| (*k, v))
+ }
+
+ pub fn get_mut(&mut self, id: Id) -> Option<&mut Window<A, C>> {
+ self.entries.get_mut(&id)
+ }
+
+ pub fn get_mut_alias(
+ &mut self,
+ id: winit::window::WindowId,
+ ) -> Option<(Id, &mut Window<A, C>)> {
+ let id = self.aliases.get(&id).copied()?;
+
+ Some((id, self.get_mut(id)?))
+ }
+
+ pub fn last_monitor(&self) -> Option<MonitorHandle> {
+ self.entries.values().last()?.raw.current_monitor()
+ }
+
+ pub fn remove(&mut self, id: Id) -> Option<Window<A, C>> {
+ let window = self.entries.remove(&id)?;
+ let _ = self.aliases.remove(&window.raw.id());
+
+ Some(window)
+ }
+}
+
+impl<A, C> Default for WindowManager<A, C>
+where
+ A: Application,
+ C: Compositor<Renderer = A::Renderer>,
+ <A::Renderer as crate::core::Renderer>::Theme: StyleSheet,
+{
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+#[allow(missing_debug_implementations)]
+pub struct Window<A, C>
+where
+ A: Application,
+ C: Compositor<Renderer = A::Renderer>,
+ <A::Renderer as crate::core::Renderer>::Theme: StyleSheet,
+{
+ pub raw: winit::window::Window,
+ pub state: State<A>,
+ pub viewport_version: u64,
+ pub exit_on_close_request: bool,
+ pub mouse_interaction: mouse::Interaction,
+ pub surface: C::Surface,
+ pub renderer: A::Renderer,
+}
+
+impl<A, C> Window<A, C>
+where
+ A: Application,
+ C: Compositor<Renderer = A::Renderer>,
+ <A::Renderer as crate::core::Renderer>::Theme: StyleSheet,
+{
+ pub fn position(&self) -> Option<Point> {
+ self.raw
+ .inner_position()
+ .ok()
+ .map(|position| position.to_logical(self.raw.scale_factor()))
+ .map(|position| Point {
+ x: position.x,
+ y: position.y,
+ })
+ }
+
+ pub fn size(&self) -> Size {
+ let size = self.raw.inner_size().to_logical(self.raw.scale_factor());
+
+ Size::new(size.width, size.height)
+ }
+}
diff --git a/winit/src/multi_window/windows.rs b/winit/src/multi_window/windows.rs
deleted file mode 100644
index 5a33b7b4..00000000
--- a/winit/src/multi_window/windows.rs
+++ /dev/null
@@ -1,201 +0,0 @@
-use crate::core::{window, Size};
-use crate::graphics::Compositor;
-use crate::multi_window::{Application, State};
-use crate::style::application::StyleSheet;
-
-use winit::monitor::MonitorHandle;
-
-use std::fmt::{Debug, Formatter};
-
-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 exit_on_close_requested: Vec<bool>,
- 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(winit::window::Window::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,
- exit_on_close_requested: bool,
- ) -> 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],
- exit_on_close_requested: vec![exit_on_close_requested],
- 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,
- exit_on_close_requested: bool,
- ) -> (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.create_renderer();
-
- self.ids.push(id);
- self.raw.push(window);
- self.states.push(state);
- self.exit_on_close_requested.push(exit_on_close_requested);
- 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(winit::window::Window::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.exit_on_close_requested.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
- }
-
- /// Returns the windows that need to be requested to closed, and also the windows that can be
- /// closed immediately.
- pub fn partition_close_requests(
- &self,
- ) -> (Vec<window::Id>, Vec<window::Id>) {
- self.exit_on_close_requested.iter().enumerate().fold(
- (vec![], vec![]),
- |(mut close_immediately, mut needs_request_closed), (i, close)| {
- let id = self.ids[i];
-
- if *close {
- close_immediately.push(id);
- } else {
- needs_request_closed.push(id);
- }
-
- (close_immediately, needs_request_closed)
- },
- )
- }
-}