mirror of
https://github.com/YaLTeR/niri.git
synced 2024-09-11 20:37:25 +03:00
Implement draw-border-with-background window rule
This commit is contained in:
parent
c61361de3c
commit
db49deb7fd
@ -693,6 +693,9 @@ pub struct WindowRule {
|
||||
pub max_width: Option<u16>,
|
||||
#[knuffel(child, unwrap(argument))]
|
||||
pub max_height: Option<u16>,
|
||||
|
||||
#[knuffel(child, unwrap(argument))]
|
||||
pub draw_border_with_background: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(knuffel::Decode, Debug, Default, Clone)]
|
||||
|
@ -4,6 +4,7 @@ use std::rc::Rc;
|
||||
|
||||
use niri::layout::{LayoutElement, LayoutElementRenderElement};
|
||||
use niri::render_helpers::renderer::NiriRenderer;
|
||||
use niri::window::ResolvedWindowRules;
|
||||
use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement};
|
||||
use smithay::backend::renderer::element::{Id, Kind};
|
||||
use smithay::output::Output;
|
||||
@ -217,4 +218,9 @@ impl LayoutElement for TestWindow {
|
||||
}
|
||||
|
||||
fn refresh(&self) {}
|
||||
|
||||
fn rules(&self) -> &ResolvedWindowRules {
|
||||
static EMPTY: ResolvedWindowRules = ResolvedWindowRules::empty();
|
||||
&EMPTY
|
||||
}
|
||||
}
|
||||
|
@ -123,6 +123,9 @@ layout {
|
||||
// If you don't like that, you should uncomment `prefer-no-csd` below.
|
||||
// Niri will draw focus ring and border *around* windows that agree to omit their
|
||||
// client-side decorations.
|
||||
//
|
||||
// Alternatively, you can override it with a window rule called
|
||||
// `draw-border-with-background`.
|
||||
|
||||
// You can change how the focus ring looks.
|
||||
focus-ring {
|
||||
@ -393,6 +396,13 @@ animations {
|
||||
// if it is equal to min-height. Either set this equal to min-height,
|
||||
// or change the window height manually for this to apply.
|
||||
max-height 300
|
||||
|
||||
// Override whether the border and the focus ring draw with a background.
|
||||
// Set this to `true` to draw them as solid colored rectangles even for
|
||||
// windows which agreed to omit their client-side decorations.
|
||||
// Set this to `false` to draw them as borders around the window even for
|
||||
// windows which use client-side decorations.
|
||||
draw-border-with-background false
|
||||
}
|
||||
|
||||
// Here's a useful example. Work around WezTerm's initial configure bug
|
||||
|
@ -123,7 +123,7 @@ impl CompositorHandler for State {
|
||||
(rules, width, is_full_width, output)
|
||||
} else {
|
||||
error!("window map must happen after initial configure");
|
||||
(ResolvedWindowRules::default(), None, false, None)
|
||||
(ResolvedWindowRules::empty(), None, false, None)
|
||||
};
|
||||
|
||||
let parent = window
|
||||
|
@ -49,6 +49,7 @@ use self::workspace::{compute_working_area, Column, ColumnWidth, OutputId, Works
|
||||
use crate::niri_render_elements;
|
||||
use crate::render_helpers::renderer::NiriRenderer;
|
||||
use crate::utils::output_size;
|
||||
use crate::window::ResolvedWindowRules;
|
||||
|
||||
pub mod focus_ring;
|
||||
pub mod monitor;
|
||||
@ -121,6 +122,8 @@ pub trait LayoutElement {
|
||||
/// This *will* switch immediately after a [`LayoutElement::request_fullscreen()`] call.
|
||||
fn is_pending_fullscreen(&self) -> bool;
|
||||
|
||||
fn rules(&self) -> &ResolvedWindowRules;
|
||||
|
||||
/// Runs periodic clean-up tasks.
|
||||
fn refresh(&self);
|
||||
}
|
||||
@ -1905,6 +1908,11 @@ mod tests {
|
||||
}
|
||||
|
||||
fn refresh(&self) {}
|
||||
|
||||
fn rules(&self) -> &ResolvedWindowRules {
|
||||
static EMPTY: ResolvedWindowRules = ResolvedWindowRules::empty();
|
||||
&EMPTY
|
||||
}
|
||||
}
|
||||
|
||||
fn arbitrary_bbox() -> impl Strategy<Value = Rectangle<i32, Logical>> {
|
||||
|
@ -85,11 +85,22 @@ impl<W: LayoutElement> Tile<W> {
|
||||
}
|
||||
|
||||
pub fn advance_animations(&mut self, current_time: Duration, is_active: bool) {
|
||||
let draw_border_with_background = self
|
||||
.window
|
||||
.rules()
|
||||
.draw_border_with_background
|
||||
.unwrap_or_else(|| !self.window.has_ssd());
|
||||
self.border
|
||||
.update(self.window.size(), self.window.has_ssd());
|
||||
.update(self.window.size(), !draw_border_with_background);
|
||||
self.border.set_active(is_active);
|
||||
|
||||
self.focus_ring.update(self.tile_size(), self.has_ssd());
|
||||
let draw_focus_ring_with_background = if self.effective_border_width().is_some() {
|
||||
false
|
||||
} else {
|
||||
draw_border_with_background
|
||||
};
|
||||
self.focus_ring
|
||||
.update(self.tile_size(), !draw_focus_ring_with_background);
|
||||
self.focus_ring.set_active(is_active);
|
||||
|
||||
match &mut self.open_animation {
|
||||
@ -295,8 +306,15 @@ impl<W: LayoutElement> Tile<W> {
|
||||
size
|
||||
}
|
||||
|
||||
pub fn has_ssd(&self) -> bool {
|
||||
self.effective_border_width().is_some() || self.window.has_ssd()
|
||||
pub fn draw_border_with_background(&self) -> bool {
|
||||
if self.effective_border_width().is_some() {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.window
|
||||
.rules()
|
||||
.draw_border_with_background
|
||||
.unwrap_or_else(|| !self.window.has_ssd())
|
||||
}
|
||||
|
||||
fn render_inner<R: NiriRenderer>(
|
||||
|
@ -184,4 +184,8 @@ impl LayoutElement for Mapped {
|
||||
fn refresh(&self) {
|
||||
self.window.refresh();
|
||||
}
|
||||
|
||||
fn rules(&self) -> &ResolvedWindowRules {
|
||||
&self.rules
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ pub mod unmapped;
|
||||
pub use unmapped::{InitialConfigureState, Unmapped};
|
||||
|
||||
/// Rules fully resolved for a window.
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ResolvedWindowRules {
|
||||
/// Default width for this window.
|
||||
///
|
||||
@ -39,13 +39,32 @@ pub struct ResolvedWindowRules {
|
||||
pub max_width: Option<u16>,
|
||||
/// Extra bound on the maximum window height.
|
||||
pub max_height: Option<u16>,
|
||||
|
||||
/// Whether or not to draw the border with a solid background.
|
||||
///
|
||||
/// `None` means using the SSD heuristic.
|
||||
pub draw_border_with_background: Option<bool>,
|
||||
}
|
||||
|
||||
impl ResolvedWindowRules {
|
||||
pub const fn empty() -> Self {
|
||||
Self {
|
||||
default_width: None,
|
||||
open_on_output: None,
|
||||
open_maximized: None,
|
||||
open_fullscreen: None,
|
||||
min_width: None,
|
||||
min_height: None,
|
||||
max_width: None,
|
||||
max_height: None,
|
||||
draw_border_with_background: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute(rules: &[WindowRule], toplevel: &ToplevelSurface) -> Self {
|
||||
let _span = tracy_client::span!("ResolvedWindowRules::compute");
|
||||
|
||||
let mut resolved = ResolvedWindowRules::default();
|
||||
let mut resolved = ResolvedWindowRules::empty();
|
||||
|
||||
with_states(toplevel.wl_surface(), |states| {
|
||||
let role = states
|
||||
@ -100,6 +119,10 @@ impl ResolvedWindowRules {
|
||||
if let Some(x) = rule.max_height {
|
||||
resolved.max_height = Some(x);
|
||||
}
|
||||
|
||||
if let Some(x) = rule.draw_border_with_background {
|
||||
resolved.draw_border_with_background = Some(x);
|
||||
}
|
||||
}
|
||||
|
||||
resolved.open_on_output = open_on_output.map(|x| x.to_owned());
|
||||
|
Loading…
Reference in New Issue
Block a user