1use crate::access_winit_window::AccessWinitWindow;
2use aeth_event::{Pub, Sub, new_pubsub};
3use indexed_bitmap::IndexedBitmap;
4use std::cell::RefCell;
5use std::collections::HashMap;
6use std::rc::{Rc, Weak};
7use winit::event::WindowEvent;
8use winit::window::{Window as WinitWindow, WindowId};
9
10pub(crate) struct WindowInner {
11 window: Box<dyn WinitWindow>,
12 window_event_pub: Pub<WindowEvent>,
13 win_id: WindowId,
14 slot_id: Rc<RefCell<usize>>,
15}
16
17impl WindowInner {
18 pub(crate) fn window_event_pub(&self) -> Pub<WindowEvent> {
19 self.window_event_pub.clone()
20 }
21}
22
23pub(crate) struct Windows {
24 windows: Vec<WindowInner>,
25 lookup: HashMap<WindowId, Rc<RefCell<usize>>>,
26 refreshing: IndexedBitmap,
27}
28
29impl Windows {
30 pub(crate) fn new() -> Self {
31 Self {
32 windows: Vec::new(),
33 lookup: HashMap::new(),
34 refreshing: IndexedBitmap::new(),
35 }
36 }
37
38 fn unlink(&mut self, id: usize) {
39 let evicted_id = self.windows[id].win_id;
40 self.lookup.remove(&evicted_id);
41 self.refreshing.bitset(id, false);
42 }
43
44 pub(crate) fn evict(&mut self, id: usize) {
45 assert!(self.windows.len() > 0);
48 self.unlink(id);
49 let last_id = self.windows.len() - 1;
50 if id < last_id {
51 let win_id = self.windows[last_id].win_id;
52 let slot_id = self.windows[last_id].slot_id.clone();
53 let last_refreshing = self.refreshing.bitget(last_id);
54 self.unlink(last_id);
55 self.windows.swap(id, last_id);
56 *slot_id.borrow_mut() = id;
57 self.refreshing.bitset(id, last_refreshing);
58 self.lookup.insert(win_id, slot_id);
59 }
60 self.windows.pop();
63 if self.windows.len() * 2 < self.windows.capacity() {
64 self.windows.shrink_to_fit();
65 self.refreshing.shrink_to(self.windows.capacity());
66 }
67 }
68
69 fn set_refreshing(&mut self, id: usize, enable: bool) {
70 self.refreshing.bitset(id, enable);
71 }
72
73 fn broadcast_refresh_option(&self) -> Option<()> {
74 let mut id = self.refreshing.lowest_one()?;
75 loop {
76 self.windows[id].window.request_redraw();
77 id = self.refreshing.next_one(id)?;
78 }
79 }
80
81 pub(crate) fn broadcast_refresh(&self) {
82 self.broadcast_refresh_option();
83 }
84
85 pub(crate) fn allocate(rc: &Rc<RefCell<Self>>, window: Box<dyn WinitWindow>) -> Window {
86 let mut this = rc.borrow_mut();
87 let win_id = window.id();
88 let slot_id = this.windows.len();
89 let slot_id = Rc::new(RefCell::new(slot_id));
90 let (window_event_pub, window_event_sub) = new_pubsub();
91 this.windows.push(WindowInner {
92 window,
93 window_event_pub,
94 win_id,
95 slot_id: slot_id.clone(),
96 });
97 this.lookup.insert(win_id, slot_id.clone());
98 Window {
99 windows: Rc::downgrade(rc),
100 window_event_sub,
101 slot_id: slot_id,
102 }
103 }
104
105 pub(crate) fn find_inner_by_window_id(
106 &mut self,
107 window_id: WindowId,
108 ) -> Option<&mut WindowInner> {
109 let slot_id = *self.lookup.get(&window_id)?.borrow();
110 Some(&mut self.windows[slot_id])
111 }
112}
113
114pub struct Window {
137 windows: Weak<RefCell<Windows>>,
138 window_event_sub: Sub<WindowEvent>,
139 slot_id: Rc<RefCell<usize>>,
140}
141
142impl Drop for Window {
143 fn drop(&mut self) {
144 self.drop_option();
145 }
146}
147
148impl Window {
149 fn id(&self) -> usize {
150 *self.slot_id.borrow()
151 }
152
153 fn drop_option(&mut self) -> Option<()> {
154 let rc = self.windows.upgrade()?;
155 rc.borrow_mut().evict(self.id());
156 Some(())
157 }
158
159 fn must_upgrade_windows(&self) -> Rc<RefCell<Windows>> {
160 self.windows
161 .upgrade()
162 .expect("Windows dropped, maybe not inside valid window subsystem context")
163 }
164
165 pub fn set_refreshing(&mut self, enable: bool) {
173 let rc = self.must_upgrade_windows();
174 let mut windows = rc.borrow_mut();
175 windows.set_refreshing(self.id(), enable);
176 }
177
178 pub fn is_refreshing(&self) -> bool {
180 let rc = self.must_upgrade_windows();
181 let windows = rc.borrow_mut();
182 windows.refreshing.bitget(self.id())
183 }
184
185 pub fn window_event_sub(&self) -> Sub<WindowEvent> {
188 self.window_event_sub.clone()
189 }
190}
191
192impl AccessWinitWindow for Window {
193 fn map_winit_window<F, T>(&self, f: F) -> T
194 where
195 F: FnOnce(&Box<dyn WinitWindow>) -> T,
196 {
197 let rc = self.must_upgrade_windows();
198 let windows = rc.borrow();
199 let window = &windows.windows[self.id()].window;
200 f(window)
201 }
202
203 fn map_winit_window_mut<F, T>(&mut self, f: F) -> T
204 where
205 F: FnOnce(&mut Box<dyn WinitWindow>) -> T,
206 {
207 let rc = self.must_upgrade_windows();
215 let mut windows = rc.borrow_mut();
216 let window = &mut windows.windows[self.id()].window;
217 f(window)
218 }
219}