aboutsummaryrefslogtreecommitdiff
path: root/src/layout
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-02-21 21:27:44 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2024-02-21 22:15:21 +0400
commit48f0f6fb3ceb68fdb559ab38c8dcbb7b9ba3a13e (patch)
treed71dbc10132f38f59e4a72d1d8a509102f701f8c /src/layout
parent340bac0690972ee6f6badc8d386162320d70b7bd (diff)
downloadniri-48f0f6fb3ceb68fdb559ab38c8dcbb7b9ba3a13e.tar.gz
niri-48f0f6fb3ceb68fdb559ab38c8dcbb7b9ba3a13e.tar.bz2
niri-48f0f6fb3ceb68fdb559ab38c8dcbb7b9ba3a13e.zip
Implement gradient borders
Diffstat (limited to 'src/layout')
-rw-r--r--src/layout/focus_ring.rs101
-rw-r--r--src/layout/tile.rs22
-rw-r--r--src/layout/workspace.rs2
3 files changed, 97 insertions, 28 deletions
diff --git a/src/layout/focus_ring.rs b/src/layout/focus_ring.rs
index 0addd204..24013510 100644
--- a/src/layout/focus_ring.rs
+++ b/src/layout/focus_ring.rs
@@ -1,26 +1,41 @@
use std::iter::zip;
use arrayvec::ArrayVec;
-use niri_config;
+use niri_config::{self, GradientRelativeTo};
use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement};
use smithay::backend::renderer::element::Kind;
-use smithay::utils::{Logical, Point, Scale, Size};
+use smithay::utils::{Logical, Point, Rectangle, Scale, Size};
+
+use crate::niri_render_elements;
+use crate::render_helpers::gradient::GradientRenderElement;
+use crate::render_helpers::renderer::NiriRenderer;
#[derive(Debug)]
pub struct FocusRing {
buffers: [SolidColorBuffer; 4],
locations: [Point<i32, Logical>; 4],
+ sizes: [Size<i32, Logical>; 4],
+ full_size: Size<i32, Logical>,
+ is_active: bool,
is_border: bool,
config: niri_config::FocusRing,
}
-pub type FocusRingRenderElement = SolidColorRenderElement;
+niri_render_elements! {
+ FocusRingRenderElement => {
+ SolidColor = SolidColorRenderElement,
+ Gradient = GradientRenderElement,
+ }
+}
impl FocusRing {
pub fn new(config: niri_config::FocusRing) -> Self {
Self {
buffers: Default::default(),
locations: Default::default(),
+ sizes: Default::default(),
+ full_size: Default::default(),
+ is_active: false,
is_border: false,
config,
}
@@ -32,20 +47,25 @@ impl FocusRing {
pub fn update(&mut self, win_size: Size<i32, Logical>, is_border: bool) {
let width = i32::from(self.config.width);
+ self.full_size = win_size + Size::from((width * 2, width * 2));
if is_border {
- self.buffers[0].resize((win_size.w + width * 2, width));
- self.buffers[1].resize((win_size.w + width * 2, width));
- self.buffers[2].resize((width, win_size.h));
- self.buffers[3].resize((width, win_size.h));
+ self.sizes[0] = Size::from((win_size.w + width * 2, width));
+ self.sizes[1] = Size::from((win_size.w + width * 2, width));
+ self.sizes[2] = Size::from((width, win_size.h));
+ self.sizes[3] = Size::from((width, win_size.h));
+
+ for (buf, size) in zip(&mut self.buffers, self.sizes) {
+ buf.resize(size);
+ }
self.locations[0] = Point::from((-width, -width));
self.locations[1] = Point::from((-width, win_size.h));
self.locations[2] = Point::from((-width, 0));
self.locations[3] = Point::from((win_size.w, 0));
} else {
- let size = win_size + Size::from((width * 2, width * 2));
- self.buffers[0].resize(size);
+ self.sizes[0] = self.full_size;
+ self.buffers[0].resize(self.sizes[0]);
self.locations[0] = Point::from((-width, -width));
}
@@ -62,12 +82,16 @@ impl FocusRing {
for buf in &mut self.buffers {
buf.set_color(color);
}
+
+ self.is_active = is_active;
}
- pub fn render(
+ pub fn render<R: NiriRenderer>(
&self,
+ renderer: &mut R,
location: Point<i32, Logical>,
scale: Scale<f64>,
+ view_size: Size<i32, Logical>,
) -> impl Iterator<Item = FocusRingRenderElement> {
let mut rv = ArrayVec::<_, 4>::new();
@@ -75,23 +99,56 @@ impl FocusRing {
return rv.into_iter();
}
- let mut push = |buffer, location: Point<i32, Logical>| {
- let elem = SolidColorRenderElement::from_buffer(
- buffer,
- location.to_physical_precise_round(scale),
- scale,
- 1.,
- Kind::Unspecified,
- );
- rv.push(elem.into());
+ let gradient = if self.is_active {
+ self.config.active_gradient
+ } else {
+ self.config.inactive_gradient
+ };
+
+ let full_rect = Rectangle::from_loc_and_size(location + self.locations[0], self.full_size);
+ let view_rect = Rectangle::from_loc_and_size((0, 0), view_size);
+
+ let mut push = |buffer, location: Point<i32, Logical>, size: Size<i32, Logical>| {
+ let elem = gradient.and_then(|gradient| {
+ let gradient_area = match gradient.relative_to {
+ GradientRelativeTo::Window => full_rect,
+ GradientRelativeTo::WorkspaceView => view_rect,
+ };
+ GradientRenderElement::new(
+ renderer,
+ scale,
+ Rectangle::from_loc_and_size(location, size),
+ gradient_area,
+ gradient.from.into(),
+ gradient.to.into(),
+ ((gradient.angle as f32) - 90.).to_radians(),
+ )
+ .map(Into::into)
+ });
+
+ let elem = elem.unwrap_or_else(|| {
+ SolidColorRenderElement::from_buffer(
+ buffer,
+ location.to_physical_precise_round(scale),
+ scale,
+ 1.,
+ Kind::Unspecified,
+ )
+ .into()
+ });
+ rv.push(elem);
};
if self.is_border {
- for (buf, loc) in zip(&self.buffers, self.locations) {
- push(buf, location + loc);
+ for (buf, (loc, size)) in zip(&self.buffers, zip(self.locations, self.sizes)) {
+ push(buf, location + loc, size);
}
} else {
- push(&self.buffers[0], location + self.locations[0]);
+ push(
+ &self.buffers[0],
+ location + self.locations[0],
+ self.sizes[0],
+ );
}
rv.into_iter()
diff --git a/src/layout/tile.rs b/src/layout/tile.rs
index 28bcfb47..ca2779fe 100644
--- a/src/layout/tile.rs
+++ b/src/layout/tile.rs
@@ -7,7 +7,7 @@ use smithay::backend::renderer::element::utils::RescaleRenderElement;
use smithay::backend::renderer::element::{Element, Kind};
use smithay::utils::{Logical, Point, Rectangle, Scale, Size};
-use super::focus_ring::FocusRing;
+use super::focus_ring::{FocusRing, FocusRingRenderElement};
use super::{LayoutElement, LayoutElementRenderElement, Options};
use crate::animation::Animation;
use crate::niri_render_elements;
@@ -51,6 +51,7 @@ pub struct Tile<W: LayoutElement> {
niri_render_elements! {
TileRenderElement<R> => {
LayoutElement = LayoutElementRenderElement<R>,
+ FocusRing = FocusRingRenderElement,
SolidColor = SolidColorRenderElement,
Offscreen = RescaleRenderElement<OffscreenRenderElement>,
}
@@ -297,6 +298,7 @@ impl<W: LayoutElement> Tile<W> {
renderer: &mut R,
location: Point<i32, Logical>,
scale: Scale<f64>,
+ view_size: Size<i32, Logical>,
focus_ring: bool,
) -> impl Iterator<Item = TileRenderElement<R>> {
let rv = self
@@ -307,12 +309,21 @@ impl<W: LayoutElement> Tile<W> {
let elem = self.effective_border_width().map(|width| {
self.border
- .render(location + Point::from((width, width)), scale)
+ .render(
+ renderer,
+ location + Point::from((width, width)),
+ scale,
+ view_size,
+ )
.map(Into::into)
});
let rv = rv.chain(elem.into_iter().flatten());
- let elem = focus_ring.then(|| self.focus_ring.render(location, scale).map(Into::into));
+ let elem = focus_ring.then(|| {
+ self.focus_ring
+ .render(renderer, location, scale, view_size)
+ .map(Into::into)
+ });
let rv = rv.chain(elem.into_iter().flatten());
let elem = self.is_fullscreen.then(|| {
@@ -333,11 +344,12 @@ impl<W: LayoutElement> Tile<W> {
renderer: &mut R,
location: Point<i32, Logical>,
scale: Scale<f64>,
+ view_size: Size<i32, Logical>,
focus_ring: bool,
) -> impl Iterator<Item = TileRenderElement<R>> {
if let Some(anim) = &self.open_animation {
let renderer = renderer.as_gles_renderer();
- let elements = self.render_inner(renderer, location, scale, focus_ring);
+ let elements = self.render_inner(renderer, location, scale, view_size, focus_ring);
let elements = elements.collect::<Vec<TileRenderElement<_>>>();
let elem = OffscreenRenderElement::new(
@@ -365,7 +377,7 @@ impl<W: LayoutElement> Tile<W> {
} else {
self.window().set_offscreen_element_id(None);
- let elements = self.render_inner(renderer, location, scale, focus_ring);
+ let elements = self.render_inner(renderer, location, scale, view_size, focus_ring);
None.into_iter().chain(Some(elements).into_iter().flatten())
}
}
diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs
index 5e872340..b9016098 100644
--- a/src/layout/workspace.rs
+++ b/src/layout/workspace.rs
@@ -1188,7 +1188,7 @@ impl<W: LayoutElement> Workspace<W> {
first = false;
rv.extend(
- tile.render(renderer, tile_pos, output_scale, focus_ring)
+ tile.render(renderer, tile_pos, output_scale, self.view_size, focus_ring)
.map(Into::into),
);
}