This commit is contained in:
Kiko 2024-07-06 20:19:38 +05:30 committed by GitHub
commit a9240744a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 147 additions and 9 deletions

View File

@ -422,6 +422,8 @@ pub struct Gradient {
pub angle: i16,
#[knuffel(property, default)]
pub relative_to: GradientRelativeTo,
#[knuffel(child)]
pub _in: GradientInterpolation,
}
#[derive(knuffel::DecodeScalar, Debug, Default, Clone, Copy, PartialEq, Eq)]
@ -431,6 +433,32 @@ pub enum GradientRelativeTo {
WorkspaceView,
}
#[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)]
pub struct GradientInterpolation {
#[knuffel(property, default)]
pub color_space: GradientColorSpace,
#[knuffel(property, default)]
pub hue_interpol: HueInterpolation
}
#[derive(knuffel::DecodeScalar, Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum GradientColorSpace {
#[default]
Srgb,
SrgbLinear,
Oklab,
XyzD50,
}
#[derive(knuffel::DecodeScalar, Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum HueInterpolation {
#[default]
Shorter,
Longer,
Increasing,
Decreasing,
}
#[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)]
pub struct Border {
#[knuffel(child)]

View File

@ -153,6 +153,7 @@ layout {
// The angle is the same as in linear-gradient, and is optional,
// defaulting to 180 (top-to-bottom gradient).
// You can use any CSS linear-gradient tool on the web to set these up.
// for gradient types visit the wiki
//
// active-gradient from="#80c8ff" to="#bbddff" angle=45

View File

@ -1,7 +1,7 @@
use std::iter::zip;
use arrayvec::ArrayVec;
use niri_config::{CornerRadius, Gradient, GradientRelativeTo};
use niri_config::{CornerRadius, Gradient, GradientRelativeTo, GradientInterpolation, GradientColorSpace, HueInterpolation};
use smithay::backend::renderer::element::Kind;
use smithay::utils::{Logical, Point, Rectangle, Size};
@ -91,6 +91,10 @@ impl FocusRing {
to: color,
angle: 0,
relative_to: GradientRelativeTo::Window,
_in: GradientInterpolation {
color_space: GradientColorSpace::Srgb,
hue_interpol: HueInterpolation::Shorter
}
});
let full_rect = Rectangle::from_loc_and_size((-width, -width), self.full_size);
@ -99,6 +103,9 @@ impl FocusRing {
GradientRelativeTo::WorkspaceView => view_rect,
};
let gradient_format = gradient._in;
let rounded_corner_border_width = if self.is_border {
// HACK: increase the border width used for the inner rounded corners a tiny bit to
// reduce background bleed.
@ -178,6 +185,7 @@ impl FocusRing {
border.update(
size,
Rectangle::from_loc_and_size(gradient_area.loc - loc, gradient_area.size),
gradient_format,
gradient.from.into(),
gradient.to.into(),
((gradient.angle as f32) - 90.).to_radians(),
@ -198,6 +206,7 @@ impl FocusRing {
gradient_area.loc - self.locations[0],
gradient_area.size,
),
gradient_format,
gradient.from.into(),
gradient.to.into(),
((gradient.angle as f32) - 90.).to_radians(),

View File

@ -1,7 +1,7 @@
use std::rc::Rc;
use std::time::Duration;
use niri_config::CornerRadius;
use niri_config::{CornerRadius, GradientInterpolation, GradientColorSpace, HueInterpolation};
use smithay::backend::allocator::Fourcc;
use smithay::backend::renderer::element::{Element, Kind};
use smithay::backend::renderer::gles::GlesRenderer;
@ -757,6 +757,10 @@ impl<W: LayoutElement> Tile<W> {
return BorderRenderElement::new(
geo.size,
Rectangle::from_loc_and_size((0., 0.), geo.size),
GradientInterpolation{
color_space: GradientColorSpace::Srgb,
hue_interpol: HueInterpolation::Shorter
},
elem.color(),
elem.color(),
0.,

View File

@ -1,7 +1,7 @@
use std::collections::HashMap;
use glam::{Mat3, Vec2};
use niri_config::CornerRadius;
use niri_config::{CornerRadius, GradientInterpolation, GradientColorSpace, HueInterpolation};
use smithay::backend::renderer::element::{Element, Id, Kind, RenderElement, UnderlyingStorage};
use smithay::backend::renderer::gles::{GlesError, GlesFrame, GlesRenderer, Uniform};
use smithay::backend::renderer::utils::{CommitCounter, DamageSet, OpaqueRegions};
@ -28,6 +28,7 @@ pub struct BorderRenderElement {
struct Parameters {
size: Size<f64, Logical>,
gradient_area: Rectangle<f64, Logical>,
gradient_format: GradientInterpolation,
color_from: [f32; 4],
color_to: [f32; 4],
angle: f32,
@ -43,6 +44,7 @@ impl BorderRenderElement {
pub fn new(
size: Size<f64, Logical>,
gradient_area: Rectangle<f64, Logical>,
gradient_format: GradientInterpolation,
color_from: [f32; 4],
color_to: [f32; 4],
angle: f32,
@ -57,6 +59,7 @@ impl BorderRenderElement {
params: Parameters {
size,
gradient_area,
gradient_format,
color_from,
color_to,
angle,
@ -77,6 +80,10 @@ impl BorderRenderElement {
params: Parameters {
size: Default::default(),
gradient_area: Default::default(),
gradient_format: GradientInterpolation {
color_space: GradientColorSpace::Srgb,
hue_interpol: HueInterpolation::Shorter
},
color_from: Default::default(),
color_to: Default::default(),
angle: 0.,
@ -97,6 +104,7 @@ impl BorderRenderElement {
&mut self,
size: Size<f64, Logical>,
gradient_area: Rectangle<f64, Logical>,
gradient_format: GradientInterpolation,
color_from: [f32; 4],
color_to: [f32; 4],
angle: f32,
@ -108,6 +116,7 @@ impl BorderRenderElement {
let params = Parameters {
size,
gradient_area,
gradient_format,
color_from,
color_to,
angle,
@ -128,6 +137,7 @@ impl BorderRenderElement {
let Parameters {
size,
gradient_area,
gradient_format,
color_from,
color_to,
angle,
@ -162,11 +172,27 @@ impl BorderRenderElement {
let input_to_geo =
Mat3::from_scale(area_size) * Mat3::from_translation(-geo_loc / area_size);
let colorspace = match gradient_format.color_space {
GradientColorSpace::Srgb => 0.,
GradientColorSpace::SrgbLinear => 1.,
GradientColorSpace::Oklab => 2.,
GradientColorSpace::XyzD50 => 3.
};
let hue_interpolation = match gradient_format.hue_interpol {
HueInterpolation::Shorter => 0.,
HueInterpolation::Longer => 1.,
HueInterpolation::Increasing => 2.,
HueInterpolation::Decreasing => 3.
};
self.inner.update(
size,
None,
scale,
vec![
Uniform::new("colorspace", colorspace),
Uniform::new("hue_interpolation", hue_interpolation),
Uniform::new("color_from", color_from),
Uniform::new("color_to", color_to),
Uniform::new("grad_offset", grad_offset.to_array()),

View File

@ -10,6 +10,8 @@ uniform float niri_scale;
uniform vec2 niri_size;
varying vec2 niri_v_coords;
uniform float colorspace;
uniform float hue_interpolation;
uniform vec4 color_from;
uniform vec4 color_to;
uniform vec2 grad_offset;
@ -21,6 +23,53 @@ uniform vec2 geo_size;
uniform vec4 outer_radius;
uniform float border_width;
vec4 srgb_to_linear(vec4 color) {
return vec4(
(color.rgb / color.aaa) * (color.rgb / color.aaa),
color.a
);
}
vec4 linear_to_srgb(vec4 color) {
return vec4(
sqrt(color.r) * color.a,
sqrt(color.g) * color.a,
sqrt(color.b) * color.a,
color.a
);
}
vec4 color_mix(vec4 color1, vec4 color2, float color_ratio) {
if (colorspace == 0.0) // srgb
return mix(color1, color2, color_ratio);
vec4 color_out;
color1 = srgb_to_linear(color1);
color2 = srgb_to_linear(color2);
if (colorspace == 1.0) { // srgb-linear
color_out = mix(
color1,
color2,
color_ratio
);
} else if (colorspace == 2.0) { // oklab
color1 = xyz_to_oklab(linear_to_xyz(color1));
color2 = xyz_to_oklab(linear_to_xyz(color2));
color_out =
} else {
color_out = vec4(
255.0,
0.0,
0.0,
1.0
);
}
return linear_to_srgb(color_out);
}
vec4 gradient_color(vec2 coords) {
coords = coords + grad_offset;
@ -33,7 +82,7 @@ vec4 gradient_color(vec2 coords) {
frac += 1.0;
frac = clamp(frac, 0.0, 1.0);
return mix(color_from, color_to, frac);
return color_mix(color_from, color_to, frac);
}
float rounding_alpha(vec2 coords, vec2 size, vec4 corner_radius) {

View File

@ -34,6 +34,8 @@ impl Shaders {
renderer,
include_str!("border.frag"),
&[
UniformName::new("colorspace", UniformType::_1f),
UniformName::new("hue_interpolation", UniformType::_1f),
UniformName::new("color_from", UniformType::_4f),
UniformName::new("color_to", UniformType::_4f),
UniformName::new("grad_offset", UniformType::_2f),
@ -66,7 +68,10 @@ impl Shaders {
})
.ok();
let resize = compile_resize_program(renderer, include_str!("resize.frag"))
let resize = compile_resize_program(
renderer,
include_str!("resize.frag")
)
.map_err(|err| {
warn!("error compiling resize shader: {err:?}");
})

View File

@ -2,7 +2,7 @@ use std::cell::{Cell, RefCell};
use std::cmp::{max, min};
use std::time::Duration;
use niri_config::{CornerRadius, WindowRule};
use niri_config::{CornerRadius, GradientColorSpace, GradientInterpolation, HueInterpolation, WindowRule};
use smithay::backend::renderer::element::surface::render_elements_from_surface_tree;
use smithay::backend::renderer::element::{Id, Kind};
use smithay::backend::renderer::gles::GlesRenderer;
@ -289,6 +289,10 @@ impl Mapped {
return BorderRenderElement::new(
geo.size,
Rectangle::from_loc_and_size((0., 0.), geo.size),
GradientInterpolation{
color_space: GradientColorSpace::Srgb,
hue_interpol: HueInterpolation::Shorter
},
elem.color(),
elem.color(),
0.,

View File

@ -32,7 +32,7 @@ layout {
active-color "#ffc87f"
inactive-color "#505050"
// active-gradient from="#ffbb66" to="#ffc880" angle=45 relative-to="workspace-view"
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" gradient-type="linear"
}
struts {
@ -169,7 +169,7 @@ layout {
inactive-color "#505050"
// active-gradient from="#ffbb66" to="#ffc880" angle=45 relative-to="workspace-view"
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" gradient-type="linear"
}
}
```
@ -209,7 +209,7 @@ There's also a *deprecated* syntax for setting colors with four numbers represen
Similarly to colors, you can set `active-gradient` and `inactive-gradient`, which will take precedence.
Gradients are rendered the same as CSS [`linear-gradient(angle, from, to)`](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient).
Gradients can be rendered the same as CSS [`linear-gradient(angle, from, to)`](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient).
The angle works the same as in `linear-gradient`, and is optional, defaulting to `180` (top-to-bottom gradient).
You can use any CSS linear-gradient tool on the web to set these up, like [this one](https://www.css-gradient.com/).
@ -221,6 +221,18 @@ layout {
}
```
Gradients can be rendered with different kinds of color interpolation, this doesen't mean that the arguments the gradient takes
are any different. Except for an optional `gradient-type` argument which can currently be:
`gradient-type="css-linear"`(Default),
`gradient-type="linear"`,
`gradient-type="Oklab"`(Unimplemented),
`gradient-type="Lch"`
Gradients can be colored relative to windows individually (the default), or to the whole view of the workspace.
To do that, set `relative-to="workspace-view"`.
Here's a visual example: