mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-22 02:01:55 +07:00
Implement gradient color interpolation option (#548)
* Added the better color averaging code (tested & functional) * rustfmt * Make Color f32 0..1, clarify premul/unpremul * Fix imports and test name * Premultiply gradient colors matching CSS * Fix indentation * fixup * Add gradient image --------- Co-authored-by: K's Thinkpad <K.T.Kraft@protonmail.com>
This commit is contained in:
committed by
GitHub
parent
0824737757
commit
3ace97660f
+214
-42
@@ -410,8 +410,8 @@ impl Default for FocusRing {
|
||||
Self {
|
||||
off: false,
|
||||
width: FloatOrInt(4.),
|
||||
active_color: Color::new(127, 200, 255, 255),
|
||||
inactive_color: Color::new(80, 80, 80, 255),
|
||||
active_color: Color::from_rgba8_unpremul(127, 200, 255, 255),
|
||||
inactive_color: Color::from_rgba8_unpremul(80, 80, 80, 255),
|
||||
active_gradient: None,
|
||||
inactive_gradient: None,
|
||||
}
|
||||
@@ -428,6 +428,8 @@ pub struct Gradient {
|
||||
pub angle: i16,
|
||||
#[knuffel(property, default)]
|
||||
pub relative_to: GradientRelativeTo,
|
||||
#[knuffel(property(name = "in"), str, default)]
|
||||
pub in_: GradientInterpolation,
|
||||
}
|
||||
|
||||
#[derive(knuffel::DecodeScalar, Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
@@ -437,6 +439,30 @@ pub enum GradientRelativeTo {
|
||||
WorkspaceView,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Copy, PartialEq)]
|
||||
pub struct GradientInterpolation {
|
||||
pub color_space: GradientColorSpace,
|
||||
pub hue_interpolation: HueInterpolation,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum GradientColorSpace {
|
||||
#[default]
|
||||
Srgb,
|
||||
SrgbLinear,
|
||||
Oklab,
|
||||
Oklch,
|
||||
}
|
||||
|
||||
#[derive(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)]
|
||||
@@ -458,8 +484,8 @@ impl Default for Border {
|
||||
Self {
|
||||
off: true,
|
||||
width: FloatOrInt(4.),
|
||||
active_color: Color::new(255, 200, 127, 255),
|
||||
inactive_color: Color::new(80, 80, 80, 255),
|
||||
active_color: Color::from_rgba8_unpremul(255, 200, 127, 255),
|
||||
inactive_color: Color::from_rgba8_unpremul(80, 80, 80, 255),
|
||||
active_gradient: None,
|
||||
inactive_gradient: None,
|
||||
}
|
||||
@@ -492,23 +518,49 @@ impl From<FocusRing> for Border {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
/// RGB color in [0, 1] with unpremultiplied alpha.
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
||||
pub struct Color {
|
||||
pub r: u8,
|
||||
pub g: u8,
|
||||
pub b: u8,
|
||||
pub a: u8,
|
||||
pub r: f32,
|
||||
pub g: f32,
|
||||
pub b: f32,
|
||||
pub a: f32,
|
||||
}
|
||||
|
||||
impl Color {
|
||||
pub const fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
|
||||
pub const fn new_unpremul(r: f32, g: f32, b: f32, a: f32) -> Self {
|
||||
Self { r, g, b, a }
|
||||
}
|
||||
|
||||
pub fn from_rgba8_unpremul(r: u8, g: u8, b: u8, a: u8) -> Self {
|
||||
Self::from_array_unpremul([r, g, b, a].map(|x| x as f32 / 255.))
|
||||
}
|
||||
|
||||
pub fn from_array_premul([r, g, b, a]: [f32; 4]) -> Self {
|
||||
let a = a.clamp(0., 1.);
|
||||
|
||||
if a == 0. {
|
||||
Self::new_unpremul(0., 0., 0., 0.)
|
||||
} else {
|
||||
Self {
|
||||
r: (r / a).clamp(0., 1.),
|
||||
g: (g / a).clamp(0., 1.),
|
||||
b: (b / a).clamp(0., 1.),
|
||||
a,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Color> for [f32; 4] {
|
||||
fn from(c: Color) -> Self {
|
||||
let [r, g, b, a] = [c.r, c.g, c.b, c.a].map(|x| x as f32 / 255.);
|
||||
pub fn from_array_unpremul([r, g, b, a]: [f32; 4]) -> Self {
|
||||
Self { r, g, b, a }
|
||||
}
|
||||
|
||||
pub fn to_array_unpremul(self) -> [f32; 4] {
|
||||
[self.r, self.g, self.b, self.a]
|
||||
}
|
||||
|
||||
pub fn to_array_premul(self) -> [f32; 4] {
|
||||
let [r, g, b, a] = [self.r, self.g, self.b, self.a];
|
||||
[r * a, g * a, b * a, a]
|
||||
}
|
||||
}
|
||||
@@ -1429,12 +1481,73 @@ impl CornerRadius {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for GradientInterpolation {
|
||||
type Err = miette::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut iter = s.split_whitespace();
|
||||
let in_part1 = iter.next();
|
||||
let in_part2 = iter.next();
|
||||
let in_part3 = iter.next();
|
||||
|
||||
let Some(in_part1) = in_part1 else {
|
||||
return Err(miette!("missing color space"));
|
||||
};
|
||||
|
||||
let color = match in_part1 {
|
||||
"srgb" => GradientColorSpace::Srgb,
|
||||
"srgb-linear" => GradientColorSpace::SrgbLinear,
|
||||
"oklab" => GradientColorSpace::Oklab,
|
||||
"oklch" => GradientColorSpace::Oklch,
|
||||
x => {
|
||||
return Err(miette!(
|
||||
"invalid color space {x}; can be srgb, srgb-linear, oklab or oklch"
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
let interpolation = if let Some(in_part2) = in_part2 {
|
||||
if color != GradientColorSpace::Oklch {
|
||||
return Err(miette!("only oklch color space can have hue interpolation"));
|
||||
}
|
||||
|
||||
if in_part3 != Some("hue") {
|
||||
return Err(miette!(
|
||||
"interpolation must end with \"hue\", like \"oklch shorter hue\""
|
||||
));
|
||||
} else if iter.next().is_some() {
|
||||
return Err(miette!("unexpected text after hue interpolation"));
|
||||
} else {
|
||||
match in_part2 {
|
||||
"shorter" => HueInterpolation::Shorter,
|
||||
"longer" => HueInterpolation::Longer,
|
||||
"increasing" => HueInterpolation::Increasing,
|
||||
"decreasing" => HueInterpolation::Decreasing,
|
||||
x => {
|
||||
return Err(miette!(
|
||||
"invalid hue interpolation {x}; \
|
||||
can be shorter, longer, increasing, decreasing"
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
HueInterpolation::default()
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
color_space: color,
|
||||
hue_interpolation: interpolation,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Color {
|
||||
type Err = miette::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let [r, g, b, a] = csscolorparser::parse(s).into_diagnostic()?.to_rgba8();
|
||||
Ok(Self { r, g, b, a })
|
||||
let color = csscolorparser::parse(s).into_diagnostic()?.to_array();
|
||||
Ok(Self::from_array_unpremul(color.map(|x| x as f32)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1453,7 +1566,7 @@ struct ColorRgba {
|
||||
impl From<ColorRgba> for Color {
|
||||
fn from(value: ColorRgba) -> Self {
|
||||
let ColorRgba { r, g, b, a } = value;
|
||||
Self { r, g, b, a }
|
||||
Self::from_array_unpremul([r, g, b, a].map(|x| x as f32 / 255.))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2771,41 +2884,25 @@ mod tests {
|
||||
focus_ring: FocusRing {
|
||||
off: false,
|
||||
width: FloatOrInt(5.),
|
||||
active_color: Color {
|
||||
r: 0,
|
||||
g: 100,
|
||||
b: 200,
|
||||
a: 255,
|
||||
},
|
||||
inactive_color: Color {
|
||||
r: 255,
|
||||
g: 200,
|
||||
b: 100,
|
||||
a: 0,
|
||||
},
|
||||
active_color: Color::from_rgba8_unpremul(0, 100, 200, 255),
|
||||
inactive_color: Color::from_rgba8_unpremul(255, 200, 100, 0),
|
||||
active_gradient: Some(Gradient {
|
||||
from: Color::new(10, 20, 30, 255),
|
||||
to: Color::new(0, 128, 255, 255),
|
||||
from: Color::from_rgba8_unpremul(10, 20, 30, 255),
|
||||
to: Color::from_rgba8_unpremul(0, 128, 255, 255),
|
||||
angle: 180,
|
||||
relative_to: GradientRelativeTo::WorkspaceView,
|
||||
in_: GradientInterpolation {
|
||||
color_space: GradientColorSpace::Srgb,
|
||||
hue_interpolation: HueInterpolation::Shorter,
|
||||
},
|
||||
}),
|
||||
inactive_gradient: None,
|
||||
},
|
||||
border: Border {
|
||||
off: false,
|
||||
width: FloatOrInt(3.),
|
||||
active_color: Color {
|
||||
r: 255,
|
||||
g: 200,
|
||||
b: 127,
|
||||
a: 255,
|
||||
},
|
||||
inactive_color: Color {
|
||||
r: 255,
|
||||
g: 200,
|
||||
b: 100,
|
||||
a: 0,
|
||||
},
|
||||
active_color: Color::from_rgba8_unpremul(255, 200, 127, 255),
|
||||
inactive_color: Color::from_rgba8_unpremul(255, 200, 100, 0),
|
||||
active_gradient: None,
|
||||
inactive_gradient: None,
|
||||
},
|
||||
@@ -3095,6 +3192,81 @@ mod tests {
|
||||
assert!("10% ".parse::<SizeChange>().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_gradient_interpolation() {
|
||||
assert_eq!(
|
||||
"srgb".parse::<GradientInterpolation>().unwrap(),
|
||||
GradientInterpolation {
|
||||
color_space: GradientColorSpace::Srgb,
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
"srgb-linear".parse::<GradientInterpolation>().unwrap(),
|
||||
GradientInterpolation {
|
||||
color_space: GradientColorSpace::SrgbLinear,
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
"oklab".parse::<GradientInterpolation>().unwrap(),
|
||||
GradientInterpolation {
|
||||
color_space: GradientColorSpace::Oklab,
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
"oklch".parse::<GradientInterpolation>().unwrap(),
|
||||
GradientInterpolation {
|
||||
color_space: GradientColorSpace::Oklch,
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
"oklch shorter hue"
|
||||
.parse::<GradientInterpolation>()
|
||||
.unwrap(),
|
||||
GradientInterpolation {
|
||||
color_space: GradientColorSpace::Oklch,
|
||||
hue_interpolation: HueInterpolation::Shorter,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
"oklch longer hue".parse::<GradientInterpolation>().unwrap(),
|
||||
GradientInterpolation {
|
||||
color_space: GradientColorSpace::Oklch,
|
||||
hue_interpolation: HueInterpolation::Longer,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
"oklch decreasing hue"
|
||||
.parse::<GradientInterpolation>()
|
||||
.unwrap(),
|
||||
GradientInterpolation {
|
||||
color_space: GradientColorSpace::Oklch,
|
||||
hue_interpolation: HueInterpolation::Decreasing,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
"oklch increasing hue"
|
||||
.parse::<GradientInterpolation>()
|
||||
.unwrap(),
|
||||
GradientInterpolation {
|
||||
color_space: GradientColorSpace::Oklch,
|
||||
hue_interpolation: HueInterpolation::Increasing,
|
||||
}
|
||||
);
|
||||
|
||||
assert!("".parse::<GradientInterpolation>().is_err());
|
||||
assert!("srgb shorter hue".parse::<GradientInterpolation>().is_err());
|
||||
assert!("oklch shorter".parse::<GradientInterpolation>().is_err());
|
||||
assert!("oklch shorter h".parse::<GradientInterpolation>().is_err());
|
||||
assert!("oklch a hue".parse::<GradientInterpolation>().is_err());
|
||||
assert!("oklch shorter hue a"
|
||||
.parse::<GradientInterpolation>()
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_iso_level3_shift() {
|
||||
assert_eq!(
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::time::Duration;
|
||||
|
||||
use niri::animation::ANIMATION_SLOWDOWN;
|
||||
use niri::render_helpers::border::BorderRenderElement;
|
||||
use niri_config::CornerRadius;
|
||||
use niri_config::{Color, CornerRadius, GradientInterpolation};
|
||||
use smithay::backend::renderer::element::RenderElement;
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
||||
@@ -64,8 +64,9 @@ impl TestCase for GradientAngle {
|
||||
[BorderRenderElement::new(
|
||||
area.size,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
[1., 0., 0., 1.],
|
||||
[0., 1., 0., 1.],
|
||||
GradientInterpolation::default(),
|
||||
Color::new_unpremul(1., 0., 0., 1.),
|
||||
Color::new_unpremul(0., 1., 0., 1.),
|
||||
self.angle - FRAC_PI_2,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
0.,
|
||||
|
||||
@@ -5,7 +5,7 @@ use std::time::Duration;
|
||||
use niri::animation::ANIMATION_SLOWDOWN;
|
||||
use niri::layout::focus_ring::FocusRing;
|
||||
use niri::render_helpers::border::BorderRenderElement;
|
||||
use niri_config::{Color, CornerRadius, FloatOrInt};
|
||||
use niri_config::{Color, CornerRadius, FloatOrInt, GradientInterpolation};
|
||||
use smithay::backend::renderer::element::RenderElement;
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
use smithay::utils::{Logical, Physical, Point, Rectangle, Size};
|
||||
@@ -23,7 +23,7 @@ impl GradientArea {
|
||||
let border = FocusRing::new(niri_config::FocusRing {
|
||||
off: false,
|
||||
width: FloatOrInt(1.),
|
||||
active_color: Color::new(255, 255, 255, 128),
|
||||
active_color: Color::from_rgba8_unpremul(255, 255, 255, 128),
|
||||
inactive_color: Color::default(),
|
||||
active_gradient: None,
|
||||
inactive_gradient: None,
|
||||
@@ -104,8 +104,9 @@ impl TestCase for GradientArea {
|
||||
[BorderRenderElement::new(
|
||||
area.size,
|
||||
g_area,
|
||||
[1., 0., 0., 1.],
|
||||
[0., 1., 0., 1.],
|
||||
GradientInterpolation::default(),
|
||||
Color::new_unpremul(1., 0., 0., 1.),
|
||||
Color::new_unpremul(0., 1., 0., 1.),
|
||||
FRAC_PI_4,
|
||||
Rectangle::from_loc_and_size((0, 0), rect_size).to_f64(),
|
||||
0.,
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
use niri::render_helpers::border::BorderRenderElement;
|
||||
use niri_config::{
|
||||
Color, CornerRadius, GradientColorSpace, GradientInterpolation, HueInterpolation,
|
||||
};
|
||||
use smithay::backend::renderer::element::RenderElement;
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
||||
|
||||
use super::TestCase;
|
||||
|
||||
pub struct GradientOklab {
|
||||
gradient_format: GradientInterpolation,
|
||||
}
|
||||
|
||||
impl GradientOklab {
|
||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
||||
Self {
|
||||
gradient_format: GradientInterpolation {
|
||||
color_space: GradientColorSpace::Oklab,
|
||||
hue_interpolation: HueInterpolation::Shorter,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TestCase for GradientOklab {
|
||||
fn render(
|
||||
&mut self,
|
||||
_renderer: &mut GlesRenderer,
|
||||
size: Size<i32, Physical>,
|
||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||
let (a, b) = (size.w / 6, size.h / 3);
|
||||
let size = (size.w - a * 2, size.h - b * 2);
|
||||
let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
|
||||
|
||||
[BorderRenderElement::new(
|
||||
area.size,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
self.gradient_format,
|
||||
Color::new_unpremul(1., 0., 0., 1.),
|
||||
Color::new_unpremul(0., 1., 0., 1.),
|
||||
0.,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
0.,
|
||||
CornerRadius::default(),
|
||||
1.,
|
||||
)
|
||||
.with_location(area.loc)]
|
||||
.into_iter()
|
||||
.map(|elem| Box::new(elem) as _)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
use niri::render_helpers::border::BorderRenderElement;
|
||||
use niri_config::{Color, CornerRadius, GradientColorSpace, GradientInterpolation};
|
||||
use smithay::backend::renderer::element::RenderElement;
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
||||
|
||||
use super::TestCase;
|
||||
|
||||
pub struct GradientOklabAlpha {
|
||||
gradient_format: GradientInterpolation,
|
||||
}
|
||||
|
||||
impl GradientOklabAlpha {
|
||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
||||
Self {
|
||||
gradient_format: GradientInterpolation {
|
||||
color_space: GradientColorSpace::Oklab,
|
||||
hue_interpolation: Default::default(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TestCase for GradientOklabAlpha {
|
||||
fn render(
|
||||
&mut self,
|
||||
_renderer: &mut GlesRenderer,
|
||||
size: Size<i32, Physical>,
|
||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||
let (a, b) = (size.w / 6, size.h / 3);
|
||||
let size = (size.w - a * 2, size.h - b * 2);
|
||||
let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
|
||||
|
||||
[BorderRenderElement::new(
|
||||
area.size,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
self.gradient_format,
|
||||
Color::new_unpremul(1., 0., 0., 1.),
|
||||
Color::new_unpremul(0., 1., 0., 0.),
|
||||
0.,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
0.,
|
||||
CornerRadius::default(),
|
||||
1.,
|
||||
)
|
||||
.with_location(area.loc)]
|
||||
.into_iter()
|
||||
.map(|elem| Box::new(elem) as _)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
use niri::render_helpers::border::BorderRenderElement;
|
||||
use niri_config::{
|
||||
Color, CornerRadius, GradientColorSpace, GradientInterpolation, HueInterpolation,
|
||||
};
|
||||
use smithay::backend::renderer::element::RenderElement;
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
||||
|
||||
use super::TestCase;
|
||||
|
||||
pub struct GradientOklchAlpha {
|
||||
gradient_format: GradientInterpolation,
|
||||
}
|
||||
|
||||
impl GradientOklchAlpha {
|
||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
||||
Self {
|
||||
gradient_format: GradientInterpolation {
|
||||
color_space: GradientColorSpace::Oklch,
|
||||
hue_interpolation: HueInterpolation::Longer,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TestCase for GradientOklchAlpha {
|
||||
fn render(
|
||||
&mut self,
|
||||
_renderer: &mut GlesRenderer,
|
||||
size: Size<i32, Physical>,
|
||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||
let (a, b) = (size.w / 6, size.h / 3);
|
||||
let size = (size.w - a * 2, size.h - b * 2);
|
||||
let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
|
||||
|
||||
[BorderRenderElement::new(
|
||||
area.size,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
self.gradient_format,
|
||||
Color::new_unpremul(1., 0., 0., 1.),
|
||||
Color::new_unpremul(0., 1., 0., 0.),
|
||||
0.,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
0.,
|
||||
CornerRadius::default(),
|
||||
1.,
|
||||
)
|
||||
.with_location(area.loc)]
|
||||
.into_iter()
|
||||
.map(|elem| Box::new(elem) as _)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
use niri::render_helpers::border::BorderRenderElement;
|
||||
use niri_config::{
|
||||
Color, CornerRadius, GradientColorSpace, GradientInterpolation, HueInterpolation,
|
||||
};
|
||||
use smithay::backend::renderer::element::RenderElement;
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
||||
|
||||
use super::TestCase;
|
||||
|
||||
pub struct GradientOklchDecreasing {
|
||||
gradient_format: GradientInterpolation,
|
||||
}
|
||||
|
||||
impl GradientOklchDecreasing {
|
||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
||||
Self {
|
||||
gradient_format: GradientInterpolation {
|
||||
color_space: GradientColorSpace::Oklch,
|
||||
hue_interpolation: HueInterpolation::Decreasing,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TestCase for GradientOklchDecreasing {
|
||||
fn render(
|
||||
&mut self,
|
||||
_renderer: &mut GlesRenderer,
|
||||
size: Size<i32, Physical>,
|
||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||
let (a, b) = (size.w / 6, size.h / 3);
|
||||
let size = (size.w - a * 2, size.h - b * 2);
|
||||
let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
|
||||
|
||||
[BorderRenderElement::new(
|
||||
area.size,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
self.gradient_format,
|
||||
Color::new_unpremul(1., 0., 0., 1.),
|
||||
Color::new_unpremul(0., 1., 0., 1.),
|
||||
0.,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
0.,
|
||||
CornerRadius::default(),
|
||||
1.,
|
||||
)
|
||||
.with_location(area.loc)]
|
||||
.into_iter()
|
||||
.map(|elem| Box::new(elem) as _)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
use niri::render_helpers::border::BorderRenderElement;
|
||||
use niri_config::{
|
||||
Color, CornerRadius, GradientColorSpace, GradientInterpolation, HueInterpolation,
|
||||
};
|
||||
use smithay::backend::renderer::element::RenderElement;
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
||||
|
||||
use super::TestCase;
|
||||
|
||||
pub struct GradientOklchIncreasing {
|
||||
gradient_format: GradientInterpolation,
|
||||
}
|
||||
|
||||
impl GradientOklchIncreasing {
|
||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
||||
Self {
|
||||
gradient_format: GradientInterpolation {
|
||||
color_space: GradientColorSpace::Oklch,
|
||||
hue_interpolation: HueInterpolation::Increasing,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TestCase for GradientOklchIncreasing {
|
||||
fn render(
|
||||
&mut self,
|
||||
_renderer: &mut GlesRenderer,
|
||||
size: Size<i32, Physical>,
|
||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||
let (a, b) = (size.w / 6, size.h / 3);
|
||||
let size = (size.w - a * 2, size.h - b * 2);
|
||||
let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
|
||||
|
||||
[BorderRenderElement::new(
|
||||
area.size,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
self.gradient_format,
|
||||
Color::new_unpremul(1., 0., 0., 1.),
|
||||
Color::new_unpremul(0., 1., 0., 1.),
|
||||
0.,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
0.,
|
||||
CornerRadius::default(),
|
||||
1.,
|
||||
)
|
||||
.with_location(area.loc)]
|
||||
.into_iter()
|
||||
.map(|elem| Box::new(elem) as _)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
use niri::render_helpers::border::BorderRenderElement;
|
||||
use niri_config::{
|
||||
Color, CornerRadius, GradientColorSpace, GradientInterpolation, HueInterpolation,
|
||||
};
|
||||
use smithay::backend::renderer::element::RenderElement;
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
||||
|
||||
use super::TestCase;
|
||||
|
||||
pub struct GradientOklchLonger {
|
||||
gradient_format: GradientInterpolation,
|
||||
}
|
||||
|
||||
impl GradientOklchLonger {
|
||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
||||
Self {
|
||||
gradient_format: GradientInterpolation {
|
||||
color_space: GradientColorSpace::Oklch,
|
||||
hue_interpolation: HueInterpolation::Longer,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TestCase for GradientOklchLonger {
|
||||
fn render(
|
||||
&mut self,
|
||||
_renderer: &mut GlesRenderer,
|
||||
size: Size<i32, Physical>,
|
||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||
let (a, b) = (size.w / 6, size.h / 3);
|
||||
let size = (size.w - a * 2, size.h - b * 2);
|
||||
let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
|
||||
|
||||
[BorderRenderElement::new(
|
||||
area.size,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
self.gradient_format,
|
||||
Color::new_unpremul(1., 0., 0., 1.),
|
||||
Color::new_unpremul(0., 1., 0., 1.),
|
||||
0.,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
0.,
|
||||
CornerRadius::default(),
|
||||
1.,
|
||||
)
|
||||
.with_location(area.loc)]
|
||||
.into_iter()
|
||||
.map(|elem| Box::new(elem) as _)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
use niri::render_helpers::border::BorderRenderElement;
|
||||
use niri_config::{
|
||||
Color, CornerRadius, GradientColorSpace, GradientInterpolation, HueInterpolation,
|
||||
};
|
||||
use smithay::backend::renderer::element::RenderElement;
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
||||
|
||||
use super::TestCase;
|
||||
|
||||
pub struct GradientOklchShorter {
|
||||
gradient_format: GradientInterpolation,
|
||||
}
|
||||
|
||||
impl GradientOklchShorter {
|
||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
||||
Self {
|
||||
gradient_format: GradientInterpolation {
|
||||
color_space: GradientColorSpace::Oklch,
|
||||
hue_interpolation: HueInterpolation::Shorter,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TestCase for GradientOklchShorter {
|
||||
fn render(
|
||||
&mut self,
|
||||
_renderer: &mut GlesRenderer,
|
||||
size: Size<i32, Physical>,
|
||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||
let (a, b) = (size.w / 6, size.h / 3);
|
||||
let size = (size.w - a * 2, size.h - b * 2);
|
||||
let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
|
||||
|
||||
[BorderRenderElement::new(
|
||||
area.size,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
self.gradient_format,
|
||||
Color::new_unpremul(1., 0., 0., 1.),
|
||||
Color::new_unpremul(0., 1., 0., 1.),
|
||||
0.,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
0.,
|
||||
CornerRadius::default(),
|
||||
1.,
|
||||
)
|
||||
.with_location(area.loc)]
|
||||
.into_iter()
|
||||
.map(|elem| Box::new(elem) as _)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
use niri::render_helpers::border::BorderRenderElement;
|
||||
use niri_config::{
|
||||
Color, CornerRadius, GradientColorSpace, GradientInterpolation, HueInterpolation,
|
||||
};
|
||||
use smithay::backend::renderer::element::RenderElement;
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
||||
|
||||
use super::TestCase;
|
||||
|
||||
pub struct GradientSrgb {
|
||||
gradient_format: GradientInterpolation,
|
||||
}
|
||||
|
||||
impl GradientSrgb {
|
||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
||||
Self {
|
||||
gradient_format: GradientInterpolation {
|
||||
color_space: GradientColorSpace::Srgb,
|
||||
hue_interpolation: HueInterpolation::Shorter,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TestCase for GradientSrgb {
|
||||
fn render(
|
||||
&mut self,
|
||||
_renderer: &mut GlesRenderer,
|
||||
size: Size<i32, Physical>,
|
||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||
let (a, b) = (size.w / 6, size.h / 3);
|
||||
let size = (size.w - a * 2, size.h - b * 2);
|
||||
let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
|
||||
|
||||
[BorderRenderElement::new(
|
||||
area.size,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
self.gradient_format,
|
||||
Color::new_unpremul(1., 0., 0., 1.),
|
||||
Color::new_unpremul(0., 1., 0., 1.),
|
||||
0.,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
0.,
|
||||
CornerRadius::default(),
|
||||
1.,
|
||||
)
|
||||
.with_location(area.loc)]
|
||||
.into_iter()
|
||||
.map(|elem| Box::new(elem) as _)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
use niri::render_helpers::border::BorderRenderElement;
|
||||
use niri_config::{Color, CornerRadius, GradientColorSpace, GradientInterpolation};
|
||||
use smithay::backend::renderer::element::RenderElement;
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
||||
|
||||
use super::TestCase;
|
||||
|
||||
pub struct GradientSrgbAlpha {
|
||||
gradient_format: GradientInterpolation,
|
||||
}
|
||||
|
||||
impl GradientSrgbAlpha {
|
||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
||||
Self {
|
||||
gradient_format: GradientInterpolation {
|
||||
color_space: GradientColorSpace::Srgb,
|
||||
hue_interpolation: Default::default(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TestCase for GradientSrgbAlpha {
|
||||
fn render(
|
||||
&mut self,
|
||||
_renderer: &mut GlesRenderer,
|
||||
size: Size<i32, Physical>,
|
||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||
let (a, b) = (size.w / 6, size.h / 3);
|
||||
let size = (size.w - a * 2, size.h - b * 2);
|
||||
let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
|
||||
|
||||
[BorderRenderElement::new(
|
||||
area.size,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
self.gradient_format,
|
||||
Color::new_unpremul(1., 0., 0., 1.),
|
||||
Color::new_unpremul(0., 1., 0., 0.),
|
||||
0.,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
0.,
|
||||
CornerRadius::default(),
|
||||
1.,
|
||||
)
|
||||
.with_location(area.loc)]
|
||||
.into_iter()
|
||||
.map(|elem| Box::new(elem) as _)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
use niri::render_helpers::border::BorderRenderElement;
|
||||
use niri_config::{
|
||||
Color, CornerRadius, GradientColorSpace, GradientInterpolation, HueInterpolation,
|
||||
};
|
||||
use smithay::backend::renderer::element::RenderElement;
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
||||
|
||||
use super::TestCase;
|
||||
|
||||
pub struct GradientSrgbLinear {
|
||||
gradient_format: GradientInterpolation,
|
||||
}
|
||||
|
||||
impl GradientSrgbLinear {
|
||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
||||
Self {
|
||||
gradient_format: GradientInterpolation {
|
||||
color_space: GradientColorSpace::SrgbLinear,
|
||||
hue_interpolation: HueInterpolation::Shorter,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TestCase for GradientSrgbLinear {
|
||||
fn render(
|
||||
&mut self,
|
||||
_renderer: &mut GlesRenderer,
|
||||
size: Size<i32, Physical>,
|
||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||
let (a, b) = (size.w / 6, size.h / 3);
|
||||
let size = (size.w - a * 2, size.h - b * 2);
|
||||
let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
|
||||
|
||||
[BorderRenderElement::new(
|
||||
area.size,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
self.gradient_format,
|
||||
Color::new_unpremul(1., 0., 0., 1.),
|
||||
Color::new_unpremul(0., 1., 0., 1.),
|
||||
0.,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
0.,
|
||||
CornerRadius::default(),
|
||||
1.,
|
||||
)
|
||||
.with_location(area.loc)]
|
||||
.into_iter()
|
||||
.map(|elem| Box::new(elem) as _)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
use niri::render_helpers::border::BorderRenderElement;
|
||||
use niri_config::{Color, CornerRadius, GradientColorSpace, GradientInterpolation};
|
||||
use smithay::backend::renderer::element::RenderElement;
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
use smithay::utils::{Logical, Physical, Rectangle, Size};
|
||||
|
||||
use super::TestCase;
|
||||
|
||||
pub struct GradientSrgbLinearAlpha {
|
||||
gradient_format: GradientInterpolation,
|
||||
}
|
||||
|
||||
impl GradientSrgbLinearAlpha {
|
||||
pub fn new(_size: Size<i32, Logical>) -> Self {
|
||||
Self {
|
||||
gradient_format: GradientInterpolation {
|
||||
color_space: GradientColorSpace::SrgbLinear,
|
||||
hue_interpolation: Default::default(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TestCase for GradientSrgbLinearAlpha {
|
||||
fn render(
|
||||
&mut self,
|
||||
_renderer: &mut GlesRenderer,
|
||||
size: Size<i32, Physical>,
|
||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||
let (a, b) = (size.w / 6, size.h / 3);
|
||||
let size = (size.w - a * 2, size.h - b * 2);
|
||||
let area = Rectangle::from_loc_and_size((a, b), size).to_f64();
|
||||
|
||||
[BorderRenderElement::new(
|
||||
area.size,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
self.gradient_format,
|
||||
Color::new_unpremul(1., 0., 0., 1.),
|
||||
Color::new_unpremul(0., 1., 0., 0.),
|
||||
0.,
|
||||
Rectangle::from_loc_and_size((0., 0.), area.size),
|
||||
0.,
|
||||
CornerRadius::default(),
|
||||
1.,
|
||||
)
|
||||
.with_location(area.loc)]
|
||||
.into_iter()
|
||||
.map(|elem| Box::new(elem) as _)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -50,8 +50,8 @@ impl Layout {
|
||||
border: niri_config::Border {
|
||||
off: false,
|
||||
width: FloatOrInt(4.),
|
||||
active_color: Color::new(255, 163, 72, 255),
|
||||
inactive_color: Color::new(50, 50, 50, 255),
|
||||
active_color: Color::from_rgba8_unpremul(255, 163, 72, 255),
|
||||
inactive_color: Color::from_rgba8_unpremul(50, 50, 50, 255),
|
||||
active_gradient: None,
|
||||
inactive_gradient: None,
|
||||
},
|
||||
|
||||
@@ -6,6 +6,17 @@ use smithay::utils::{Physical, Size};
|
||||
|
||||
pub mod gradient_angle;
|
||||
pub mod gradient_area;
|
||||
pub mod gradient_oklab;
|
||||
pub mod gradient_oklab_alpha;
|
||||
pub mod gradient_oklch_alpha;
|
||||
pub mod gradient_oklch_decreasing;
|
||||
pub mod gradient_oklch_increasing;
|
||||
pub mod gradient_oklch_longer;
|
||||
pub mod gradient_oklch_shorter;
|
||||
pub mod gradient_srgb;
|
||||
pub mod gradient_srgb_alpha;
|
||||
pub mod gradient_srgblinear;
|
||||
pub mod gradient_srgblinear_alpha;
|
||||
pub mod layout;
|
||||
pub mod tile;
|
||||
pub mod window;
|
||||
|
||||
@@ -72,7 +72,7 @@ impl Tile {
|
||||
border: niri_config::Border {
|
||||
off: false,
|
||||
width: FloatOrInt(32.),
|
||||
active_color: Color::new(255, 163, 72, 255),
|
||||
active_color: Color::from_rgba8_unpremul(255, 163, 72, 255),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
|
||||
@@ -5,8 +5,6 @@ use std::env;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use adw::prelude::{AdwApplicationWindowExt, NavigationPageExt};
|
||||
use cases::tile::Tile;
|
||||
use cases::window::Window;
|
||||
use gtk::prelude::{
|
||||
AdjustmentExt, ApplicationExt, ApplicationExtManual, BoxExt, GtkWindowExt, WidgetExt,
|
||||
};
|
||||
@@ -18,7 +16,20 @@ use tracing_subscriber::EnvFilter;
|
||||
|
||||
use crate::cases::gradient_angle::GradientAngle;
|
||||
use crate::cases::gradient_area::GradientArea;
|
||||
use crate::cases::gradient_oklab::GradientOklab;
|
||||
use crate::cases::gradient_oklab_alpha::GradientOklabAlpha;
|
||||
use crate::cases::gradient_oklch_alpha::GradientOklchAlpha;
|
||||
use crate::cases::gradient_oklch_decreasing::GradientOklchDecreasing;
|
||||
use crate::cases::gradient_oklch_increasing::GradientOklchIncreasing;
|
||||
use crate::cases::gradient_oklch_longer::GradientOklchLonger;
|
||||
use crate::cases::gradient_oklch_shorter::GradientOklchShorter;
|
||||
use crate::cases::gradient_srgb::GradientSrgb;
|
||||
use crate::cases::gradient_srgb_alpha::GradientSrgbAlpha;
|
||||
use crate::cases::gradient_srgblinear::GradientSrgbLinear;
|
||||
use crate::cases::gradient_srgblinear_alpha::GradientSrgbLinearAlpha;
|
||||
use crate::cases::layout::Layout;
|
||||
use crate::cases::tile::Tile;
|
||||
use crate::cases::window::Window;
|
||||
use crate::cases::TestCase;
|
||||
|
||||
mod cases;
|
||||
@@ -112,6 +123,17 @@ fn build_ui(app: &adw::Application) {
|
||||
|
||||
s.add(GradientAngle::new, "Gradient - Angle");
|
||||
s.add(GradientArea::new, "Gradient - Area");
|
||||
s.add(GradientSrgb::new, "Gradient - Srgb");
|
||||
s.add(GradientSrgbLinear::new, "Gradient - SrgbLinear");
|
||||
s.add(GradientOklab::new, "Gradient - Oklab");
|
||||
s.add(GradientOklchShorter::new, "Gradient - Oklch Shorter");
|
||||
s.add(GradientOklchLonger::new, "Gradient - Oklch Longer");
|
||||
s.add(GradientOklchIncreasing::new, "Gradient - Oklch Increasing");
|
||||
s.add(GradientOklchDecreasing::new, "Gradient - Oklch Decreasing");
|
||||
s.add(GradientSrgbAlpha::new, "Gradient - Srgb Alpha");
|
||||
s.add(GradientSrgbLinearAlpha::new, "Gradient - SrgbLinear Alpha");
|
||||
s.add(GradientOklabAlpha::new, "Gradient - Oklab Alpha");
|
||||
s.add(GradientOklchAlpha::new, "Gradient - Oklch Alpha");
|
||||
|
||||
let content_headerbar = adw::HeaderBar::new();
|
||||
|
||||
|
||||
@@ -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.
|
||||
// Changing the color space is also supported, check the wiki for more info.
|
||||
//
|
||||
// active-gradient from="#80c8ff" to="#bbddff" angle=45
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::iter::zip;
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use niri_config::{CornerRadius, Gradient, GradientRelativeTo};
|
||||
use niri_config::{CornerRadius, Gradient, GradientInterpolation, GradientRelativeTo};
|
||||
use smithay::backend::renderer::element::Kind;
|
||||
use smithay::utils::{Logical, Point, Rectangle, Size};
|
||||
|
||||
@@ -72,7 +72,7 @@ impl FocusRing {
|
||||
};
|
||||
|
||||
for buf in &mut self.buffers {
|
||||
buf.set_color(color.into());
|
||||
buf.set_color(color.to_array_premul());
|
||||
}
|
||||
|
||||
let radius = radius.fit_to(self.full_size.w as f32, self.full_size.h as f32);
|
||||
@@ -91,6 +91,7 @@ impl FocusRing {
|
||||
to: color,
|
||||
angle: 0,
|
||||
relative_to: GradientRelativeTo::Window,
|
||||
in_: GradientInterpolation::default(),
|
||||
});
|
||||
|
||||
let full_rect = Rectangle::from_loc_and_size((-width, -width), self.full_size);
|
||||
@@ -178,8 +179,9 @@ impl FocusRing {
|
||||
border.update(
|
||||
size,
|
||||
Rectangle::from_loc_and_size(gradient_area.loc - loc, gradient_area.size),
|
||||
gradient.from.into(),
|
||||
gradient.to.into(),
|
||||
gradient.in_,
|
||||
gradient.from,
|
||||
gradient.to,
|
||||
((gradient.angle as f32) - 90.).to_radians(),
|
||||
Rectangle::from_loc_and_size(full_rect.loc - loc, full_rect.size),
|
||||
rounded_corner_border_width,
|
||||
@@ -198,8 +200,9 @@ impl FocusRing {
|
||||
gradient_area.loc - self.locations[0],
|
||||
gradient_area.size,
|
||||
),
|
||||
gradient.from.into(),
|
||||
gradient.to.into(),
|
||||
gradient.in_,
|
||||
gradient.from,
|
||||
gradient.to,
|
||||
((gradient.angle as f32) - 90.).to_radians(),
|
||||
Rectangle::from_loc_and_size(full_rect.loc - self.locations[0], full_rect.size),
|
||||
rounded_corner_border_width,
|
||||
|
||||
+4
-3
@@ -1,7 +1,7 @@
|
||||
use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
|
||||
use niri_config::CornerRadius;
|
||||
use niri_config::{Color, CornerRadius, GradientInterpolation};
|
||||
use smithay::backend::allocator::Fourcc;
|
||||
use smithay::backend::renderer::element::{Element, Kind};
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
@@ -757,8 +757,9 @@ impl<W: LayoutElement> Tile<W> {
|
||||
return BorderRenderElement::new(
|
||||
geo.size,
|
||||
Rectangle::from_loc_and_size((0., 0.), geo.size),
|
||||
elem.color(),
|
||||
elem.color(),
|
||||
GradientInterpolation::default(),
|
||||
Color::from_array_premul(elem.color()),
|
||||
Color::from_array_premul(elem.color()),
|
||||
0.,
|
||||
Rectangle::from_loc_and_size((0., 0.), geo.size),
|
||||
0.,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use glam::{Mat3, Vec2};
|
||||
use niri_config::CornerRadius;
|
||||
use niri_config::{
|
||||
Color, CornerRadius, GradientColorSpace, GradientInterpolation, 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,8 +30,9 @@ pub struct BorderRenderElement {
|
||||
struct Parameters {
|
||||
size: Size<f64, Logical>,
|
||||
gradient_area: Rectangle<f64, Logical>,
|
||||
color_from: [f32; 4],
|
||||
color_to: [f32; 4],
|
||||
gradient_format: GradientInterpolation,
|
||||
color_from: Color,
|
||||
color_to: Color,
|
||||
angle: f32,
|
||||
geometry: Rectangle<f64, Logical>,
|
||||
border_width: f32,
|
||||
@@ -43,8 +46,9 @@ impl BorderRenderElement {
|
||||
pub fn new(
|
||||
size: Size<f64, Logical>,
|
||||
gradient_area: Rectangle<f64, Logical>,
|
||||
color_from: [f32; 4],
|
||||
color_to: [f32; 4],
|
||||
gradient_format: GradientInterpolation,
|
||||
color_from: Color,
|
||||
color_to: Color,
|
||||
angle: f32,
|
||||
geometry: Rectangle<f64, Logical>,
|
||||
border_width: f32,
|
||||
@@ -57,6 +61,7 @@ impl BorderRenderElement {
|
||||
params: Parameters {
|
||||
size,
|
||||
gradient_area,
|
||||
gradient_format,
|
||||
color_from,
|
||||
color_to,
|
||||
angle,
|
||||
@@ -77,6 +82,7 @@ impl BorderRenderElement {
|
||||
params: Parameters {
|
||||
size: Default::default(),
|
||||
gradient_area: Default::default(),
|
||||
gradient_format: GradientInterpolation::default(),
|
||||
color_from: Default::default(),
|
||||
color_to: Default::default(),
|
||||
angle: 0.,
|
||||
@@ -97,8 +103,9 @@ impl BorderRenderElement {
|
||||
&mut self,
|
||||
size: Size<f64, Logical>,
|
||||
gradient_area: Rectangle<f64, Logical>,
|
||||
color_from: [f32; 4],
|
||||
color_to: [f32; 4],
|
||||
gradient_format: GradientInterpolation,
|
||||
color_from: Color,
|
||||
color_to: Color,
|
||||
angle: f32,
|
||||
geometry: Rectangle<f64, Logical>,
|
||||
border_width: f32,
|
||||
@@ -108,6 +115,7 @@ impl BorderRenderElement {
|
||||
let params = Parameters {
|
||||
size,
|
||||
gradient_area,
|
||||
gradient_format,
|
||||
color_from,
|
||||
color_to,
|
||||
angle,
|
||||
@@ -128,6 +136,7 @@ impl BorderRenderElement {
|
||||
let Parameters {
|
||||
size,
|
||||
gradient_area,
|
||||
gradient_format,
|
||||
color_from,
|
||||
color_to,
|
||||
angle,
|
||||
@@ -162,13 +171,29 @@ 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::Oklch => 3.,
|
||||
};
|
||||
|
||||
let hue_interpolation = match gradient_format.hue_interpolation {
|
||||
HueInterpolation::Shorter => 0.,
|
||||
HueInterpolation::Longer => 1.,
|
||||
HueInterpolation::Increasing => 2.,
|
||||
HueInterpolation::Decreasing => 3.,
|
||||
};
|
||||
|
||||
self.inner.update(
|
||||
size,
|
||||
None,
|
||||
scale,
|
||||
vec
|
||||
|
||||
```kdl
|
||||
layout {
|
||||
border {
|
||||
active-gradient from="#f00f" to="#0f05" angle=45 in="oklch longer hue"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `struts`
|
||||
|
||||
Struts shrink the area occupied by windows, similarly to layer-shell panels.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a3e4db583ac849ec3bd6c2312a84a16eaad810ebb7599cad3762a7dfc66e865b
|
||||
size 23180
|
||||
Reference in New Issue
Block a user