diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-12-13 10:28:25 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-12-30 20:12:37 +0300 |
| commit | aac54d0ea1a5c95aba698aed583ee3fa9670f18b (patch) | |
| tree | 9fc958b60bd2808afd82a4e58fd3cce40df1ff5d /src/layout/floating.rs | |
| parent | 4fe718581b4369ea8fae041c8896cf5b4ab45cb5 (diff) | |
| download | niri-aac54d0ea1a5c95aba698aed583ee3fa9670f18b.tar.gz niri-aac54d0ea1a5c95aba698aed583ee3fa9670f18b.tar.bz2 niri-aac54d0ea1a5c95aba698aed583ee3fa9670f18b.zip | |
Implement floating child stacking above parents
Diffstat (limited to 'src/layout/floating.rs')
| -rw-r--r-- | src/layout/floating.rs | 72 |
1 files changed, 66 insertions, 6 deletions
diff --git a/src/layout/floating.rs b/src/layout/floating.rs index 64446c61..342a8d3c 100644 --- a/src/layout/floating.rs +++ b/src/layout/floating.rs @@ -325,7 +325,7 @@ impl<W: LayoutElement> FloatingSpace<W> { fn add_tile_at( &mut self, - idx: usize, + mut idx: usize, mut tile: Tile<W>, pos: Option<Point<f64, Logical>>, activate: bool, @@ -353,6 +353,14 @@ impl<W: LayoutElement> FloatingSpace<W> { self.active_window_id = Some(win.id().clone()); } + // Make sure the tile isn't inserted below its parent. + for (i, tile_above) in self.tiles.iter().enumerate().take(idx) { + if win.is_child_of(tile_above.window()) { + idx = i; + break; + } + } + let mut pos = pos.unwrap_or_else(|| { let area_size = self.working_area.size.to_point(); let tile_size = tile.tile_size().to_point(); @@ -367,6 +375,8 @@ impl<W: LayoutElement> FloatingSpace<W> { let data = Data::new(self.working_area, &tile, pos); self.data.insert(idx, data); self.tiles.insert(idx, tile); + + self.bring_up_descendants_of(idx); } pub fn add_tile_above(&mut self, above: &W::Id, tile: Tile<W>) { @@ -382,6 +392,33 @@ impl<W: LayoutElement> FloatingSpace<W> { self.add_tile_at(idx, tile, Some(pos), activate); } + fn bring_up_descendants_of(&mut self, idx: usize) { + let tile = &self.tiles[idx]; + let win = tile.window(); + + // We always maintain the correct stacking order, so walking descendants back to front + // should give us all of them. + let mut descendants: Vec<usize> = Vec::new(); + for (i, tile_below) in self.tiles.iter().enumerate().skip(idx + 1).rev() { + let win_below = tile_below.window(); + if win_below.is_child_of(win) + || descendants + .iter() + .any(|idx| win_below.is_child_of(self.tiles[*idx].window())) + { + descendants.push(i); + } + } + + // Now, descendants is in back-to-front order, and repositioning them in the front-to-back + // order will preserve the subsequent indices and work out right. + let mut idx = idx; + for descendant_idx in descendants.into_iter().rev() { + self.raise_window(descendant_idx, idx); + idx += 1; + } + } + pub fn remove_active_tile(&mut self) -> Option<RemovedTile<W>> { let id = self.active_window_id.clone()?; Some(self.remove_tile(&id)) @@ -434,15 +471,22 @@ impl<W: LayoutElement> FloatingSpace<W> { return false; }; - let tile = self.tiles.remove(idx); - let data = self.data.remove(idx); - self.tiles.insert(0, tile); - self.data.insert(0, data); + self.raise_window(idx, 0); self.active_window_id = Some(id.clone()); + self.bring_up_descendants_of(0); true } + fn raise_window(&mut self, from_idx: usize, to_idx: usize) { + assert!(to_idx <= from_idx); + + let tile = self.tiles.remove(from_idx); + let data = self.data.remove(from_idx); + self.tiles.insert(to_idx, tile); + self.data.insert(to_idx, data); + } + pub fn start_close_animation_for_window( &mut self, renderer: &mut GlesRenderer, @@ -561,6 +605,15 @@ impl<W: LayoutElement> FloatingSpace<W> { win.request_size(win_size, animate, None); } + pub fn descendants_added(&mut self, id: &W::Id) -> bool { + let Some(idx) = self.idx_of(id) else { + return false; + }; + + self.bring_up_descendants_of(idx); + true + } + pub fn update_window(&mut self, id: &W::Id, serial: Option<Serial>) -> bool { let Some(tile_idx) = self.idx_of(id) else { return false; @@ -769,7 +822,7 @@ impl<W: LayoutElement> FloatingSpace<W> { assert!(self.scale.is_finite()); assert_eq!(self.tiles.len(), self.data.len()); - for (tile, data) in zip(&self.tiles, &self.data) { + for (i, (tile, data)) in zip(&self.tiles, &self.data).enumerate() { assert!(Rc::ptr_eq(&self.options, &tile.options)); assert_eq!(self.clock, tile.clock); assert_eq!(self.scale, tile.scale()); @@ -786,6 +839,13 @@ impl<W: LayoutElement> FloatingSpace<W> { data2.update(tile); data2.update_config(self.working_area); assert_eq!(data, &data2, "tile data must be up to date"); + + for tile_below in &self.tiles[i + 1..] { + assert!( + !tile_below.window().is_child_of(tile.window()), + "children must be stacked above parents" + ); + } } if let Some(id) = &self.active_window_id { |
