diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/handlers/xdg_shell.rs | 15 | ||||
| -rw-r--r-- | src/layer/mapped.rs | 18 | ||||
| -rw-r--r-- | src/layer/mod.rs | 7 | ||||
| -rw-r--r-- | src/niri.rs | 75 |
4 files changed, 94 insertions, 21 deletions
diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs index 4dfce86d..bf61e37e 100644 --- a/src/handlers/xdg_shell.rs +++ b/src/handlers/xdg_shell.rs @@ -319,10 +319,17 @@ impl XdgShellHandler for State { // FIXME: somewhere here we probably need to check is_overview_open to match the logic // in update_keyboard_focus(). - if layers - .layer_for_surface(&root, WindowSurfaceType::TOPLEVEL) - .is_none() - { + if let Some(layer) = layers.layer_for_surface(&root, WindowSurfaceType::TOPLEVEL) { + // This is a grab for a layer surface. + + if let Some(mapped) = self.niri.mapped_layer_surfaces.get(layer) { + if mapped.place_within_backdrop() { + trace!("ignoring popup grab for a layer surface within overview backdrop"); + let _ = PopupManager::dismiss_popup(&root, &popup); + return; + } + } + } else { // This is a grab for a regular window; check that there's no layer surface with a // higher input priority. diff --git a/src/layer/mapped.rs b/src/layer/mapped.rs index 5e62d033..78cfadbf 100644 --- a/src/layer/mapped.rs +++ b/src/layer/mapped.rs @@ -6,6 +6,7 @@ use smithay::backend::renderer::element::surface::{ use smithay::backend::renderer::element::Kind; use smithay::desktop::{LayerSurface, PopupManager}; use smithay::utils::{Logical, Point, Scale, Size}; +use smithay::wayland::shell::wlr_layer::{ExclusiveZone, Layer}; use super::ResolvedLayerRules; use crate::layout::shadow::Shadow; @@ -96,6 +97,23 @@ impl MappedLayer { true } + pub fn place_within_backdrop(&self) -> bool { + if !self.rules.place_within_backdrop { + return false; + } + + if self.surface.layer() != Layer::Background { + return false; + } + + let state = self.surface.cached_state(); + if state.exclusive_zone != ExclusiveZone::DontCare { + return false; + } + + true + } + pub fn render<R: NiriRenderer>( &self, renderer: &mut R, diff --git a/src/layer/mod.rs b/src/layer/mod.rs index 36e7ee67..3b27737c 100644 --- a/src/layer/mod.rs +++ b/src/layer/mod.rs @@ -19,6 +19,9 @@ pub struct ResolvedLayerRules { /// Corner radius to assume this layer surface has. pub geometry_corner_radius: Option<CornerRadius>, + + /// Whether to place this layer surface within the overview backdrop. + pub place_within_backdrop: bool, } impl ResolvedLayerRules { @@ -37,6 +40,7 @@ impl ResolvedLayerRules { inactive_color: None, }, geometry_corner_radius: None, + place_within_backdrop: false, } } @@ -73,6 +77,9 @@ impl ResolvedLayerRules { if let Some(x) = rule.geometry_corner_radius { resolved.geometry_corner_radius = Some(x); } + if let Some(x) = rule.place_within_backdrop { + resolved.place_within_backdrop = x; + } resolved.shadow.merge_with(&rule.shadow); } diff --git a/src/niri.rs b/src/niri.rs index be553293..4aa353d1 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -992,9 +992,19 @@ impl State { // Clean up on-demand layer surface focus if necessary. if let Some(surface) = &self.niri.layer_shell_on_demand_focus { // Still alive and has on-demand interactivity. - let good = surface.alive() + let mut good = surface.alive() && surface.cached_state().keyboard_interactivity == wlr_layer::KeyboardInteractivity::OnDemand; + + // Check if it moved to the overview backdrop. + if let Some(mapped) = self.niri.mapped_layer_surfaces.get(surface) { + if mapped.place_within_backdrop() { + good = false; + } + } else { + good = false; + } + if !good { self.niri.layer_shell_on_demand_focus = None; } @@ -1042,6 +1052,11 @@ impl State { return None; } + let mapped = self.niri.mapped_layer_surfaces.get(surface)?; + if mapped.place_within_backdrop() { + return None; + } + let surface = surface.wl_surface().clone(); Some(KeyboardFocus::LayerShell { surface }) }) @@ -1513,11 +1528,10 @@ impl State { resized_outputs.push(output.clone()); } - let mut background_color = config + let background_color = config .map(|c| c.background_color) .unwrap_or(DEFAULT_BACKGROUND_COLOR) .to_array_unpremul(); - background_color[3] = 1.; let background_color = Color32F::from(background_color); let mut backdrop_color = config @@ -2710,11 +2724,10 @@ impl Niri { .map(|c| ipc_transform_to_smithay(c.transform)) .unwrap_or(Transform::Normal); - let mut background_color = c + let background_color = c .map(|c| c.background_color) .unwrap_or(DEFAULT_BACKGROUND_COLOR) .to_array_unpremul(); - background_color[3] = 1.; let mut backdrop_color = c .and_then(|c| c.backdrop_color) @@ -2991,6 +3004,11 @@ impl Niri { .layers_on(layer) .rev() .find_map(|layer_surface| { + let mapped = self.mapped_layer_surfaces.get(layer_surface)?; + if mapped.place_within_backdrop() { + return None; + } + let mut layer_pos_within_output = layers.layer_geometry(layer_surface).unwrap().loc.to_f64(); @@ -3141,6 +3159,11 @@ impl Niri { .layers_on(layer) .rev() .find_map(|layer_surface| { + let mapped = self.mapped_layer_surfaces.get(layer_surface)?; + if mapped.place_within_backdrop() { + return None; + } + let mut layer_pos_within_output = layers.layer_geometry(layer_surface).unwrap().loc.to_f64(); @@ -4021,19 +4044,27 @@ impl Niri { // Get layer-shell elements. let layer_map = layer_map_for_output(output); - let mut extend_from_layer = |elements: &mut SplitElements<LayerSurfaceRenderElement<R>>, - layer| { - self.render_layer(renderer, target, output_scale, &layer_map, layer, elements); - }; + let mut extend_from_layer = + |elements: &mut SplitElements<LayerSurfaceRenderElement<R>>, layer, for_backdrop| { + self.render_layer( + renderer, + target, + output_scale, + &layer_map, + layer, + elements, + for_backdrop, + ); + }; // The overlay layer elements go next. let mut layer_elems = SplitElements::default(); - extend_from_layer(&mut layer_elems, Layer::Overlay); + extend_from_layer(&mut layer_elems, Layer::Overlay, false); elements.extend(layer_elems.into_iter().map(OutputRenderElements::from)); // Collect the top layer elements. let mut layer_elems = SplitElements::default(); - extend_from_layer(&mut layer_elems, Layer::Top); + extend_from_layer(&mut layer_elems, Layer::Top, false); let top_layer = layer_elems; // When rendering above the top layer, we put the regular monitor elements first. @@ -4041,8 +4072,8 @@ impl Niri { if mon.render_above_top_layer() { // Collect all other layer-shell elements. let mut layer_elems = SplitElements::default(); - extend_from_layer(&mut layer_elems, Layer::Bottom); - extend_from_layer(&mut layer_elems, Layer::Background); + extend_from_layer(&mut layer_elems, Layer::Bottom, false); + extend_from_layer(&mut layer_elems, Layer::Background, false); elements.extend( int_move_elements @@ -4062,8 +4093,7 @@ impl Niri { ); elements.extend(top_layer.into_iter().map(OutputRenderElements::from)); - elements.extend(layer_elems.popups.drain(..).map(OutputRenderElements::from)); - elements.extend(layer_elems.normal.drain(..).map(OutputRenderElements::from)); + elements.extend(layer_elems.into_iter().map(OutputRenderElements::from)); elements.push(OutputRenderElements::from(background)); @@ -4090,8 +4120,8 @@ impl Niri { for (ws_geo, ws_elements) in monitor_elements { // Collect all other layer-shell elements. let mut layer_elems = SplitElements::default(); - extend_from_layer(&mut layer_elems, Layer::Bottom); - extend_from_layer(&mut layer_elems, Layer::Background); + extend_from_layer(&mut layer_elems, Layer::Bottom, false); + extend_from_layer(&mut layer_elems, Layer::Background, false); elements.extend( layer_elems @@ -4126,6 +4156,10 @@ impl Niri { } // Then the backdrop. + let mut layer_elems = SplitElements::default(); + extend_from_layer(&mut layer_elems, Layer::Background, true); + elements.extend(layer_elems.into_iter().map(OutputRenderElements::from)); + elements.push(backdrop); if self.debug_draw_opaque_regions { @@ -4135,6 +4169,7 @@ impl Niri { elements } + #[allow(clippy::too_many_arguments)] fn render_layer<R: NiriRenderer>( &self, renderer: &mut R, @@ -4143,10 +4178,16 @@ impl Niri { layer_map: &LayerMap, layer: Layer, elements: &mut SplitElements<LayerSurfaceRenderElement<R>>, + for_backdrop: bool, ) { // LayerMap returns layers in reverse stacking order. let iter = layer_map.layers_on(layer).rev().filter_map(|surface| { let mapped = self.mapped_layer_surfaces.get(surface)?; + + if for_backdrop != mapped.place_within_backdrop() { + return None; + } + let geo = layer_map.layer_geometry(surface)?; Some((mapped, geo)) }); |
