screen.rs (6436B)
1 use crate::geometry::Dim; 2 use crate::geometry::Edge; 3 use crate::geometry::Pos; 4 use crate::geometry::Region; 5 use crate::geometry::Strut; 6 use crate::window::Window; 7 8 use std::cell::Cell; 9 use std::cell::RefCell; 10 use std::collections::HashMap; 11 use std::sync::atomic::AtomicUsize; 12 use std::sync::atomic::Ordering; 13 use std::vec::Vec; 14 15 #[derive(Debug, Clone)] 16 pub struct Screen { 17 number: Cell<usize>, 18 full_region: Cell<Region>, 19 placeable_region: Cell<Region>, 20 windows: RefCell<HashMap<Window, Vec<Edge>>>, 21 struts: RefCell<HashMap<Edge, Vec<Strut>>>, 22 showing_struts: Cell<bool>, 23 } 24 25 impl std::cmp::PartialEq<Self> for Screen { 26 fn eq( 27 &self, 28 other: &Self, 29 ) -> bool { 30 self.number == other.number 31 } 32 } 33 34 impl Screen { 35 pub fn new( 36 region: Region, 37 number: usize, 38 ) -> Self { 39 Screen::init(Self { 40 number: Cell::new(number), 41 full_region: Cell::new(region), 42 placeable_region: Cell::new(region), 43 windows: RefCell::new(HashMap::new()), 44 struts: RefCell::new(HashMap::with_capacity(4)), 45 showing_struts: Cell::new(true), 46 }) 47 } 48 49 fn init(self) -> Self { 50 let mut struts = self.struts.borrow_mut(); 51 52 struts.insert(Edge::Left, Vec::with_capacity(1)); 53 struts.insert(Edge::Right, Vec::with_capacity(1)); 54 struts.insert(Edge::Top, Vec::with_capacity(1)); 55 struts.insert(Edge::Bottom, Vec::with_capacity(1)); 56 57 drop(struts); 58 self 59 } 60 61 #[inline] 62 pub fn showing_struts(&self) -> bool { 63 self.showing_struts.get() 64 } 65 66 #[inline] 67 pub fn number(&self) -> usize { 68 self.number.get() 69 } 70 71 #[inline] 72 pub fn set_number( 73 &self, 74 number: usize, 75 ) { 76 self.number.set(number) 77 } 78 79 #[inline] 80 pub fn show_and_yield_struts( 81 &self, 82 show: bool, 83 ) -> Vec<Window> { 84 self.showing_struts.set(show); 85 self.compute_placeable_region(); 86 87 self.windows.borrow().keys().cloned().collect() 88 } 89 90 #[inline] 91 pub fn full_region(&self) -> Region { 92 self.full_region.get() 93 } 94 95 #[inline] 96 pub fn placeable_region(&self) -> Region { 97 self.placeable_region.get() 98 } 99 100 #[inline] 101 pub fn contains_window( 102 &self, 103 window: Window, 104 ) -> bool { 105 self.windows.borrow().contains_key(&window) 106 } 107 108 #[inline] 109 pub fn compute_placeable_region(&self) { 110 let mut region = self.full_region.get(); 111 112 if self.showing_struts.get() { 113 let struts = self.struts.borrow(); 114 115 if let Some(strut) = struts.get(&Edge::Left).unwrap().last() { 116 region.pos.x += strut.width as i32; 117 region.dim.w -= strut.width as i32; 118 } 119 120 if let Some(strut) = struts.get(&Edge::Right).unwrap().last() { 121 region.dim.w -= strut.width as i32; 122 } 123 124 if let Some(strut) = struts.get(&Edge::Top).unwrap().last() { 125 region.pos.y += strut.width as i32; 126 region.dim.h -= strut.width as i32; 127 } 128 129 if let Some(strut) = struts.get(&Edge::Bottom).unwrap().last() { 130 region.dim.h -= strut.width as i32; 131 } 132 } 133 134 self.placeable_region.set(region); 135 } 136 137 #[inline] 138 pub fn add_strut( 139 &self, 140 edge: Edge, 141 window: Window, 142 width: u32, 143 ) { 144 let mut struts = self.struts.borrow_mut(); 145 let strut = struts.get_mut(&edge).unwrap(); 146 147 let index = strut.binary_search_by(|s| s.width.cmp(&width)); 148 strut.insert(index.unwrap_or_else(|e| e), Strut::new(window, width)); 149 150 self.windows 151 .borrow_mut() 152 .entry(window) 153 .or_insert(vec![edge]) 154 .push(edge); 155 } 156 157 #[inline] 158 pub fn add_struts( 159 &self, 160 struts: Vec<Option<Strut>>, 161 ) { 162 if let Some(left_strut) = struts[0] { 163 self.add_strut(Edge::Left, left_strut.window, left_strut.width); 164 } 165 166 if let Some(right_strut) = struts[1] { 167 self.add_strut(Edge::Right, right_strut.window, right_strut.width); 168 } 169 170 if let Some(top_strut) = struts[2] { 171 self.add_strut(Edge::Top, top_strut.window, top_strut.width); 172 } 173 174 if let Some(bottom_strut) = struts[3] { 175 self.add_strut(Edge::Bottom, bottom_strut.window, bottom_strut.width); 176 } 177 } 178 179 #[inline] 180 pub fn remove_window_strut( 181 &self, 182 window: Window, 183 ) { 184 self.struts.borrow_mut().iter_mut().for_each(|(_, struts)| { 185 // a window may have strut at multiple screen edges 186 struts.retain(|s| s.window != window); 187 }); 188 189 self.windows.borrow_mut().remove(&window); 190 } 191 192 #[inline] 193 pub fn update_strut( 194 &self, 195 edge: Edge, 196 window: Window, 197 width: u32, 198 ) { 199 self.remove_window_strut(window); 200 self.add_strut(edge, window, width); 201 } 202 203 #[inline] 204 pub fn max_strut_val( 205 &self, 206 edge: Edge, 207 ) -> Option<u32> { 208 self.struts 209 .borrow() 210 .get(&edge) 211 .unwrap() 212 .last() 213 .map(|strut| strut.width) 214 } 215 216 #[inline] 217 pub fn has_strut_window( 218 &self, 219 window: Window, 220 ) -> bool { 221 self.windows.borrow().contains_key(&window) 222 } 223 224 #[inline] 225 pub fn full_encompasses( 226 &self, 227 pos: Pos, 228 ) -> bool { 229 self.full_region.get().encompasses(pos) 230 } 231 232 #[inline] 233 pub fn placeable_encompasses( 234 &self, 235 pos: Pos, 236 ) -> bool { 237 self.placeable_region.get().encompasses(pos) 238 } 239 240 #[inline] 241 pub fn full_contains( 242 &self, 243 region: Region, 244 ) -> bool { 245 self.full_region.get().contains(region) 246 } 247 248 #[inline] 249 pub fn placeable_contains( 250 &self, 251 region: Region, 252 ) -> bool { 253 self.placeable_region.get().contains(region) 254 } 255 256 #[inline] 257 pub fn full_occludes( 258 &self, 259 region: Region, 260 ) -> bool { 261 self.full_region.get().occludes(region) 262 } 263 264 #[inline] 265 pub fn placeable_occludes( 266 &self, 267 region: Region, 268 ) -> bool { 269 self.placeable_region.get().occludes(region) 270 } 271 }