wzrd

An ICCCM & EWMH compliant X11 reparenting, dynamic window manager, written in Rust
git clone git://git.deurzen.net/wzrd
Log | Files | Refs | LICENSE

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 }