mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-21 02:01:55 +07:00
Add layer matcher to layer-rule
This commit is contained in:
@@ -3,10 +3,10 @@ use smithay::desktop::{layer_map_for_output, LayerSurface, PopupKind, WindowSurf
|
||||
use smithay::output::Output;
|
||||
use smithay::reexports::wayland_server::protocol::wl_output::WlOutput;
|
||||
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
|
||||
use smithay::wayland::compositor::{get_parent, with_states};
|
||||
use smithay::wayland::compositor::{add_pre_commit_hook, get_parent, with_states, HookId};
|
||||
use smithay::wayland::shell::wlr_layer::{
|
||||
self, Layer, LayerSurface as WlrLayerSurface, LayerSurfaceData, WlrLayerShellHandler,
|
||||
WlrLayerShellState,
|
||||
self, Layer, LayerSurface as WlrLayerSurface, LayerSurfaceCachedState, LayerSurfaceData,
|
||||
WlrLayerShellHandler, WlrLayerShellState,
|
||||
};
|
||||
use smithay::wayland::shell::xdg::PopupSurface;
|
||||
|
||||
@@ -126,8 +126,10 @@ impl State {
|
||||
let output_size = output_size(&output);
|
||||
let scale = output.current_scale().fractional_scale();
|
||||
|
||||
let hook = add_mapped_layer_pre_commit_hook(layer);
|
||||
let mapped = MappedLayer::new(
|
||||
layer.clone(),
|
||||
hook,
|
||||
rules,
|
||||
output_size,
|
||||
scale,
|
||||
@@ -142,6 +144,21 @@ impl State {
|
||||
if prev.is_some() {
|
||||
error!("MappedLayer was present for an unmapped surface");
|
||||
}
|
||||
} else {
|
||||
// The surface remains mapped.
|
||||
if let Some(mapped) = self.niri.mapped_layer_surfaces.get_mut(layer) {
|
||||
// Check if the layer changed.
|
||||
if mapped.take_recompute_rules_on_commit() {
|
||||
let config = self.niri.config.borrow();
|
||||
if mapped
|
||||
.recompute_layer_rules(&config.layer_rules, self.niri.is_at_startup)
|
||||
{
|
||||
mapped.update_config(&config);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error!("MappedLayer missing for a mapped surface");
|
||||
}
|
||||
}
|
||||
|
||||
// Give focus to newly mapped on-demand surfaces. Some launchers like lxqt-runner rely
|
||||
@@ -204,3 +221,23 @@ impl State {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn add_mapped_layer_pre_commit_hook(layer: &LayerSurface) -> HookId {
|
||||
add_pre_commit_hook::<State, _>(layer.wl_surface(), move |state, _dh, surface| {
|
||||
let layer_changed = with_states(surface, |states| {
|
||||
let mut guard = states.cached_state.get::<LayerSurfaceCachedState>();
|
||||
let pending_layer = guard.pending().layer;
|
||||
let current_layer = guard.current().layer;
|
||||
pending_layer != current_layer
|
||||
});
|
||||
|
||||
if layer_changed {
|
||||
for mapped in state.niri.mapped_layer_surfaces.values_mut() {
|
||||
if mapped.surface().wl_surface() == surface {
|
||||
mapped.set_recompute_rules_on_commit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ use smithay::backend::renderer::element::surface::WaylandSurfaceRenderElement;
|
||||
use smithay::backend::renderer::element::Kind;
|
||||
use smithay::desktop::{LayerSurface, PopupManager};
|
||||
use smithay::utils::{Logical, Point, Scale, Size};
|
||||
use smithay::wayland::compositor::{remove_pre_commit_hook, HookId};
|
||||
use smithay::wayland::shell::wlr_layer::{ExclusiveZone, Layer};
|
||||
|
||||
use super::ResolvedLayerRules;
|
||||
@@ -22,9 +23,17 @@ pub struct MappedLayer {
|
||||
/// The surface itself.
|
||||
surface: LayerSurface,
|
||||
|
||||
/// Pre-commit hook that we have on all mapped layer surfaces.
|
||||
pre_commit_hook: HookId,
|
||||
|
||||
/// Up-to-date rules.
|
||||
rules: ResolvedLayerRules,
|
||||
|
||||
/// Whether to recompute layer rules on the next commit.
|
||||
///
|
||||
/// Set in the pre-commit hook when the layer changes; consumed in the commit handler.
|
||||
recompute_rules_on_commit: bool,
|
||||
|
||||
/// Buffer to draw instead of the surface when it should be blocked out.
|
||||
block_out_buffer: SolidColorBuffer,
|
||||
|
||||
@@ -52,6 +61,7 @@ niri_render_elements! {
|
||||
impl MappedLayer {
|
||||
pub fn new(
|
||||
surface: LayerSurface,
|
||||
pre_commit_hook: HookId,
|
||||
rules: ResolvedLayerRules,
|
||||
view_size: Size<f64, Logical>,
|
||||
scale: f64,
|
||||
@@ -65,7 +75,9 @@ impl MappedLayer {
|
||||
|
||||
Self {
|
||||
surface,
|
||||
pre_commit_hook,
|
||||
rules,
|
||||
recompute_rules_on_commit: false,
|
||||
block_out_buffer: SolidColorBuffer::new((0., 0.), [0., 0., 0., 1.]),
|
||||
view_size,
|
||||
scale,
|
||||
@@ -128,6 +140,14 @@ impl MappedLayer {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn set_recompute_rules_on_commit(&mut self) {
|
||||
self.recompute_rules_on_commit = true;
|
||||
}
|
||||
|
||||
pub fn take_recompute_rules_on_commit(&mut self) -> bool {
|
||||
std::mem::take(&mut self.recompute_rules_on_commit)
|
||||
}
|
||||
|
||||
pub fn place_within_backdrop(&self) -> bool {
|
||||
if !self.rules.place_within_backdrop {
|
||||
return false;
|
||||
@@ -232,3 +252,9 @@ impl MappedLayer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for MappedLayer {
|
||||
fn drop(&mut self) {
|
||||
remove_pre_commit_hook(self.surface.wl_surface(), self.pre_commit_hook.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ use niri_config::layer_rule::{LayerRule, Match};
|
||||
use niri_config::utils::MergeWith as _;
|
||||
use niri_config::{BlockOutFrom, CornerRadius, ShadowRule};
|
||||
use smithay::desktop::LayerSurface;
|
||||
use smithay::wayland::shell::wlr_layer::Layer;
|
||||
|
||||
pub mod mapped;
|
||||
pub use mapped::MappedLayer;
|
||||
@@ -83,5 +84,17 @@ fn surface_matches(surface: &LayerSurface, m: &Match) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(layer) = m.layer {
|
||||
let surface_layer = match surface.layer() {
|
||||
Layer::Background => niri_ipc::Layer::Background,
|
||||
Layer::Bottom => niri_ipc::Layer::Bottom,
|
||||
Layer::Top => niri_ipc::Layer::Top,
|
||||
Layer::Overlay => niri_ipc::Layer::Overlay,
|
||||
};
|
||||
if layer != surface_layer {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user