mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-22 02:01:55 +07:00
Parse CSS colors in {in,}active-color
This commit is contained in:
+93
-6
@@ -422,15 +422,11 @@ impl From<Border> for FocusRing {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Color {
|
||||
#[knuffel(argument)]
|
||||
pub r: u8,
|
||||
#[knuffel(argument)]
|
||||
pub g: u8,
|
||||
#[knuffel(argument)]
|
||||
pub b: u8,
|
||||
#[knuffel(argument)]
|
||||
pub a: u8,
|
||||
}
|
||||
|
||||
@@ -849,6 +845,97 @@ impl FromStr for Color {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(knuffel::Decode)]
|
||||
struct ColorRgba {
|
||||
#[knuffel(argument)]
|
||||
r: u8,
|
||||
#[knuffel(argument)]
|
||||
g: u8,
|
||||
#[knuffel(argument)]
|
||||
b: u8,
|
||||
#[knuffel(argument)]
|
||||
a: u8,
|
||||
}
|
||||
|
||||
impl From<ColorRgba> for Color {
|
||||
fn from(value: ColorRgba) -> Self {
|
||||
let ColorRgba { r, g, b, a } = value;
|
||||
Self { r, g, b, a }
|
||||
}
|
||||
}
|
||||
|
||||
// Manual impl to allow both one-argument string and 4-argument RGBA forms.
|
||||
impl<S> knuffel::Decode<S> for Color
|
||||
where
|
||||
S: knuffel::traits::ErrorSpan,
|
||||
{
|
||||
fn decode_node(
|
||||
node: &knuffel::ast::SpannedNode<S>,
|
||||
ctx: &mut knuffel::decode::Context<S>,
|
||||
) -> Result<Self, knuffel::errors::DecodeError<S>> {
|
||||
// Check for unexpected type name.
|
||||
if let Some(type_name) = &node.type_name {
|
||||
ctx.emit_error(knuffel::errors::DecodeError::unexpected(
|
||||
type_name,
|
||||
"type name",
|
||||
"no type name expected for this node",
|
||||
));
|
||||
}
|
||||
|
||||
// Get the first argument.
|
||||
let mut iter_args = node.arguments.iter();
|
||||
let val = iter_args.next().ok_or_else(|| {
|
||||
knuffel::errors::DecodeError::missing(node, "additional argument is required")
|
||||
})?;
|
||||
|
||||
// Check for unexpected type name.
|
||||
if let Some(typ) = &val.type_name {
|
||||
ctx.emit_error(knuffel::errors::DecodeError::TypeName {
|
||||
span: typ.span().clone(),
|
||||
found: Some((**typ).clone()),
|
||||
expected: knuffel::errors::ExpectedType::no_type(),
|
||||
rust_type: "str",
|
||||
});
|
||||
}
|
||||
|
||||
// Check the argument type.
|
||||
let rv = match *val.literal {
|
||||
// If it's a string, use FromStr.
|
||||
knuffel::ast::Literal::String(ref s) => Color::from_str(s)
|
||||
.map_err(|e| knuffel::errors::DecodeError::conversion(&val.literal, e)),
|
||||
// Otherwise, fall back to the 4-argument RGBA form.
|
||||
_ => return ColorRgba::decode_node(node, ctx).map(Color::from),
|
||||
}?;
|
||||
|
||||
// Check for unexpected following arguments.
|
||||
if let Some(val) = iter_args.next() {
|
||||
ctx.emit_error(knuffel::errors::DecodeError::unexpected(
|
||||
&val.literal,
|
||||
"argument",
|
||||
"unexpected argument",
|
||||
));
|
||||
}
|
||||
|
||||
// Check for unexpected properties and children.
|
||||
for name in node.properties.keys() {
|
||||
ctx.emit_error(knuffel::errors::DecodeError::unexpected(
|
||||
name,
|
||||
"property",
|
||||
format!("unexpected property `{}`", name.escape_default()),
|
||||
));
|
||||
}
|
||||
for child in node.children.as_ref().map(|lst| &lst[..]).unwrap_or(&[]) {
|
||||
ctx.emit_error(knuffel::errors::DecodeError::unexpected(
|
||||
child,
|
||||
"node",
|
||||
format!("unexpected node `{}`", child.node_name.escape_default()),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(rv)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Mode {
|
||||
type Err = miette::Error;
|
||||
|
||||
@@ -1025,7 +1112,7 @@ mod tests {
|
||||
|
||||
border {
|
||||
width 3
|
||||
inactive-color 255 200 100 0
|
||||
inactive-color "rgba(255, 200, 100, 0.0)"
|
||||
}
|
||||
|
||||
preset-column-widths {
|
||||
|
||||
@@ -113,18 +113,22 @@ layout {
|
||||
// How many logical pixels the ring extends out from the windows.
|
||||
width 4
|
||||
|
||||
// Color of the ring on the active monitor: red, green, blue, alpha.
|
||||
active-color 127 200 255 255
|
||||
// Colors can be set in a variety of ways:
|
||||
// - CSS named colors: "red"
|
||||
// - RGB hex: "#rgb", "#rgba", "#rrggbb", "#rrggbbaa"
|
||||
// - CSS-like notation: "rgb(255, 127, 0)", rgba(), hsl() and a few others.
|
||||
|
||||
// Color of the ring on inactive monitors: red, green, blue, alpha.
|
||||
inactive-color 80 80 80 255
|
||||
// Color of the ring on the active monitor.
|
||||
active-color "#7fc8ff"
|
||||
|
||||
// Color of the ring on inactive monitors.
|
||||
inactive-color "#505050"
|
||||
|
||||
// Additionally, there's a legacy RGBA syntax:
|
||||
// active-color 127 200 255 255
|
||||
|
||||
// You can also use gradients. They take precedence over solid colors.
|
||||
// Gradients are rendered the same as CSS linear-gradient(angle, from, to).
|
||||
// Colors can be set in a variety of ways here:
|
||||
// - CSS named colors: from="red"
|
||||
// - RGB hex: from="#rgb", from="#rgba", from="#rrggbb", from="#rrggbbaa"
|
||||
// - CSS-like notation: from="rgb(255, 127, 0)", rgba(), hsl() and a few others.
|
||||
// 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.
|
||||
@@ -145,8 +149,8 @@ layout {
|
||||
off
|
||||
|
||||
width 4
|
||||
active-color 255 200 127 255
|
||||
inactive-color 80 80 80 255
|
||||
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"
|
||||
|
||||
Reference in New Issue
Block a user