1use crate::core::mouse;
2use crate::core::window::Id;
3use crate::core::{Point, Size};
4use crate::graphics::Compositor;
5use crate::program::{DefaultStyle, Program, State};
6
7use iced_futures::core::Element;
8use std::collections::BTreeMap;
9use std::sync::{Arc, Mutex};
10use winit::monitor::MonitorHandle;
11
12#[allow(missing_debug_implementations)]
13pub struct WindowManager<P, C>
14where
15 P: Program,
16 C: Compositor<Renderer = P::Renderer>,
17 P::Theme: DefaultStyle,
18{
19 pub(crate) aliases: BTreeMap<winit::window::WindowId, Id>,
20 entries: BTreeMap<Id, Window<P, C>>,
21}
22
23impl<P, C> WindowManager<P, C>
24where
25 P: Program,
26 C: Compositor<Renderer = P::Renderer>,
27 P::Theme: DefaultStyle,
28{
29 pub fn new() -> Self {
30 Self {
31 aliases: BTreeMap::new(),
32 entries: BTreeMap::new(),
33 }
34 }
35
36 pub fn insert(
37 &mut self,
38 id: Id,
39 window: Arc<dyn winit::window::Window>,
40 application: &P,
41 compositor: &mut C,
42 exit_on_close_request: bool,
43 resize_border: u32,
44 ) -> &mut Window<P, C> {
45 let state = State::new(application, id, window.as_ref());
46 let viewport_version = state.viewport_version();
47 let physical_size = state.physical_size();
48 let surface = compositor.create_surface(
49 window.clone(),
50 physical_size.width,
51 physical_size.height,
52 );
53 let renderer = compositor.create_renderer();
54
55 let _ = self.aliases.insert(window.id(), id);
56
57 let drag_resize_window_func = super::drag_resize::event_func(
58 window.as_ref(),
59 resize_border as f64 * window.scale_factor(),
60 );
61
62 let _ = self.entries.insert(
63 id,
64 Window {
65 raw: window,
66 state,
67 viewport_version,
68 exit_on_close_request,
69 drag_resize_window_func,
70 surface,
71 renderer,
72 mouse_interaction: mouse::Interaction::None,
73 prev_dnd_destination_rectangles_count: 0,
74 resize_enabled: false,
75 redraw_requested: false,
76 },
77 );
78
79 self.entries
80 .get_mut(&id)
81 .expect("Get window that was just inserted")
82 }
83
84 pub fn is_empty(&self) -> bool {
85 self.entries.is_empty()
86 }
87
88 pub fn first(&self) -> Option<&Window<P, C>> {
89 self.entries.first_key_value().map(|(_id, window)| window)
90 }
91
92 pub fn iter_mut(
93 &mut self,
94 ) -> impl Iterator<Item = (Id, &mut Window<P, C>)> {
95 self.entries.iter_mut().map(|(k, v)| (*k, v))
96 }
97
98 pub fn get(&self, id: Id) -> Option<&Window<P, C>> {
99 self.entries.get(&id)
100 }
101
102 pub fn get_mut(&mut self, id: Id) -> Option<&mut Window<P, C>> {
103 self.entries.get_mut(&id)
104 }
105
106 pub fn ids(&self) -> impl Iterator<Item = Id> + '_ {
107 self.entries.keys().cloned()
108 }
109
110 pub fn get_mut_alias(
111 &mut self,
112 id: winit::window::WindowId,
113 ) -> Option<(Id, &mut Window<P, C>)> {
114 let id = self.aliases.get(&id).copied()?;
115
116 Some((id, self.get_mut(id)?))
117 }
118
119 pub fn last_monitor(&self) -> Option<MonitorHandle> {
120 self.entries.values().last()?.raw.current_monitor()
121 }
122
123 pub fn remove(&mut self, id: Id) -> Option<Window<P, C>> {
124 let window = self.entries.remove(&id)?;
125 let _ = self.aliases.remove(&window.raw.id());
126
127 Some(window)
128 }
129}
130
131impl<P, C> Default for WindowManager<P, C>
132where
133 P: Program,
134 C: Compositor<Renderer = P::Renderer>,
135 P::Theme: DefaultStyle,
136{
137 fn default() -> Self {
138 Self::new()
139 }
140}
141
142pub(crate) enum Frame {
143 None,
144 Waiting,
145 Ready,
146}
147
148pub(crate) type ViewFn<M, T, R> = Arc<
149 Box<dyn Fn() -> Option<Element<'static, M, T, R>> + Send + Sync + 'static>,
150>;
151
152#[allow(missing_debug_implementations)]
153pub struct Window<P, C>
154where
155 P: Program,
156 C: Compositor<Renderer = P::Renderer>,
157 P::Theme: DefaultStyle,
158{
159 pub raw: Arc<dyn winit::window::Window>,
160 pub(crate) state: State<P>,
161 pub viewport_version: u64,
162 pub exit_on_close_request: bool,
163 pub drag_resize_window_func: Option<
164 Box<
165 dyn FnMut(
166 &dyn winit::window::Window,
167 &winit::event::WindowEvent,
168 ) -> bool,
169 >,
170 >,
171 pub prev_dnd_destination_rectangles_count: usize,
172 pub mouse_interaction: mouse::Interaction,
173 pub surface: C::Surface,
174 pub renderer: P::Renderer,
175 pub resize_enabled: bool,
176 pub(crate) redraw_requested: bool,
177}
178
179impl<P, C> Window<P, C>
180where
181 P: Program,
182 C: Compositor<Renderer = P::Renderer>,
183 P::Theme: DefaultStyle,
184{
185 pub fn position(&self) -> Option<Point> {
186 self.raw
187 .inner_position()
188 .ok()
189 .map(|position| position.to_logical(self.raw.scale_factor()))
190 .map(|position| Point {
191 x: position.x,
192 y: position.y,
193 })
194 }
195
196 pub fn size(&self) -> Size {
197 let size = self.raw.surface_size().to_logical(self.raw.scale_factor());
198
199 Size::new(size.width, size.height)
200 }
201
202 pub fn request_redraw(&mut self) {
203 if !self.redraw_requested {
204 self.redraw_requested = true;
205 self.raw.request_redraw();
206 }
207 }
208
209 }