Commit 5c459f657de6
tarball5 files changed+58-48
@@ -852,6 +852,23 @@ impl Layout {
852852
visible: vis(window),853853
})854854
.collect();855
+ let floating = self.floating_on(o, out, vis);856
+ let fullscreen = self.fullscreen_in(vis);857
+ let over = fullscreen.map_or_else(Vec::new, |f| self.above_fullscreen(f, &floating));858
+ Arrangement {859
+ tiled,860
+ floating,861
+ fullscreen,862
+ over,863
+ }864
+ }865
+866
+ fn floating_on(867
+ &self,868
+ o: OutputId,869
+ out: &Output,870
+ vis: &dyn Fn(WindowId) -> bool,871
+ ) -> Vec<(WindowId, Rect)> {855872
let mut floating: Vec<(WindowId, Rect)> = out856873
.floating857874
.iter()@@ -868,31 +885,37 @@ impl Layout {
868885
floating.push((sp.windows[i], centre_in(out.usable(), r.w, r.h)));869886
}870887
}888
+ floating889
+ }890
+891
+ fn fullscreen_in(&self, vis: &dyn Fn(WindowId) -> bool) -> Option<WindowId> {871892
let is_fullscreen = |w: WindowId| self.windows[w].fullscreen && vis(w);872
- let fullscreen = self873
- .history893
+ self.history874894
.iter()875895
.rev()876896
.copied()877897
.find(|&w| is_fullscreen(w))878
- .or_else(|| self.windows.keys().find(|&w| is_fullscreen(w)));879
- let over = fullscreen880
- .map(|f| {881
- floating882
- .iter()883
- .map(|&(w, _)| w)884
- .filter(|&w| {885
- w != f && (self.descends(w, f) || self.windows[w].scratchpad.is_some())886
- })887
- .collect()888
- })889
- .unwrap_or_default();890
- Arrangement {891
- tiled,892
- floating,893
- fullscreen,894
- over,895
- }898
+ .or_else(|| self.windows.keys().find(|&w| is_fullscreen(w)))899
+ }900
+901
+ fn above_fullscreen(&self, f: WindowId, floating: &[(WindowId, Rect)]) -> Vec<WindowId> {902
+ floating903
+ .iter()904
+ .map(|&(w, _)| w)905
+ .filter(|&w| w != f && (self.descends(w, f) || self.windows[w].scratchpad.is_some()))906
+ .collect()907
+ }908
+909
+ /// The fullscreen window of the output under (x, y), with the floating910
+ /// transients that stay above it. Cheaper than arranging the output.911
+ pub fn fullscreen_at(&self, x: f64, y: f64) -> Option<(WindowId, Vec<WindowId>)> {912
+ let (o, out) = self913
+ .outputs914
+ .iter()915
+ .find(|(_, out)| out.area.contains(x, y))?;916
+ let vis = self.vis_on(o);917
+ let f = self.fullscreen_in(&vis)?;918
+ Some((f, self.above_fullscreen(f, &self.floating_on(o, out, &vis))))896919
}897920
898921
/// Records that `w` is a transient of `parent`.@@ -275,7 +275,8 @@ fn focus_under_pointer(state: &mut State) {
275275
}276276
277277
fn window_at(state: &State, pos: Point<f64, Logical>) -> Option<WindowId> {278
- if let Some((root, ..)) = state.window_popup_under(pos) {278
+ let fullscreen = state.wm.layout.fullscreen_at(pos.x, pos.y);279
+ if let Some((root, ..)) = state.window_popup_under(pos, fullscreen.as_ref()) {279280
return state.window_id(&root);280281
}281282
let (w, _) = state.wm.space.element_under(pos)?;@@ -165,25 +165,21 @@ impl State {
165165
pub fn placed(166166
root: &WlSurface,167167
geometry_at: Point<i32, Logical>,168
-) -> Vec<(WlSurface, Point<i32, Logical>)> {169
- offsets(root)170
- .into_iter()171
- .map(|(popup, at)| (popup, geometry_at + at))172
- .collect()168
+) -> impl Iterator<Item = (WlSurface, Point<i32, Logical>)> + use<> {169
+ offsets(root).map(move |(popup, at)| (popup, geometry_at + at))173170
}174171
175
-fn offsets(root: &WlSurface) -> Vec<(WlSurface, Point<i32, Logical>)> {172
+fn offsets(root: &WlSurface) -> impl Iterator<Item = (WlSurface, Point<i32, Logical>)> + use<> {176173
PopupManager::popups_for_surface(root)177174
.map(|(popup, at)| (popup.wl_surface().clone(), at - popup.geometry().loc))178
- .collect()179175
}180176
181177
/// The surface of `popups` under `pos`, with its origin.182178
pub fn hit(183
- popups: Vec<(WlSurface, Point<i32, Logical>)>,179
+ mut popups: impl Iterator<Item = (WlSurface, Point<i32, Logical>)>,184180
pos: Point<f64, Logical>,185181
) -> Option<(WlSurface, Point<f64, Logical>)> {186
- popups.into_iter().find_map(|(popup, at)| {182
+ popups.find_map(|(popup, at)| {187183
let (s, p) =188184
under_from_surface_tree(&popup, pos - at.to_f64(), (0, 0), WindowSurfaceType::ALL)?;189185
Some((s, (p + at).to_f64()))@@ -217,28 +213,18 @@ pub fn elements(
217213
}218214
219215
impl State {220
- /// The window covering the output under `pos` while it is fullscreen.221
- pub fn fullscreen_at(&self, pos: Point<f64, Logical>) -> Option<WindowId> {222
- self.wm.layout.outputs().find_map(|(o, out)| {223
- let a = out.area;224
- a.contains(pos.x, pos.y)225
- .then(|| self.wm.layout.arrange(o).fullscreen)226
- .flatten()227
- })228
- }229
-230216
/// The popup of a window under `pos`, frontmost window first, with the231217
/// window's root surface. A fullscreen window hides the popups of the232
- /// windows below it.218
+ /// windows below it, except those of the transients kept above it.233219
pub fn window_popup_under(234220
&self,235221
pos: Point<f64, Logical>,222
+ fullscreen: Option<&(WindowId, Vec<WindowId>)>,236223
) -> Option<(WlSurface, WlSurface, Point<f64, Logical>)> {237
- let fullscreen = self.fullscreen_at(pos);238224
self.wm.space.elements().rev().find_map(|window| {239225
let root = crate::wm::root(window).filter(|_| window.toplevel().is_some())?;240226
let id = self.window_id(&root)?;241
- if fullscreen.is_some_and(|f| f != id) {227
+ if fullscreen.is_some_and(|(f, over)| *f != id && !over.contains(&id)) {242228
return None;243229
}244230
let (_, rect, _) = self.wm.get(id)?.placed?;@@ -137,7 +137,7 @@ pub fn build(
137137
}138138
let covering = arr.fullscreen.filter(|_| fullscreen_at_rest);139139
for &(id, r, _, _) in tiled.iter().chain(&above).rev() {140
- if covering.is_some_and(|f| f != id) {140
+ if covering.is_some_and(|f| f != id) && !arr.over.contains(&id) {141141
continue;142142
}143143
let Some(root) = windows.get(id).and_then(|s| s.window.toplevel()) else {@@ -560,8 +560,8 @@ impl State {
560560
return Some(other((s, (p + geo.loc).to_f64())));561561
}562562
}563
- let fullscreen = self.fullscreen_at(pos).is_some();564
- let above: &[Layer] = if fullscreen {563
+ let fullscreen = self.wm.layout.fullscreen_at(pos.x, pos.y);564
+ let above: &[Layer] = if fullscreen.is_some() {565565
&[Layer::Overlay]566566
} else {567567
&[Layer::Overlay, Layer::Top]@@ -569,11 +569,11 @@ impl State {
569569
let layer = |layers| self.layer_under(pos, layers).map(|(_, s, p)| (s, p));570570
layer(above)571571
.or_else(|| {572
- self.window_popup_under(pos)572
+ self.window_popup_under(pos, fullscreen.as_ref())573573
.map(|(_, surface, origin)| (surface, origin))574574
})575575
.or_else(|| {576
- if fullscreen {576
+ if fullscreen.is_some() {577577
return None;578578
}579579
self.lower_popup_under(pos)