aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/handlers/xdg_shell.rs15
-rw-r--r--src/layer/mapped.rs18
-rw-r--r--src/layer/mod.rs7
-rw-r--r--src/niri.rs75
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))
});