feat: add per output max-bpc config and ipc action

List current max-bpc values in outputs.

fix: remove 16 bpc and change default behaviour

feat(ipc): add max_bpc and format to output

fix: bpc on output config change

docs: add bpc to Outputs

feat: use atomic commits for connector properties

fix: drm `value_type` breaking change

fix: minor changes based on PR review

Rename bpc to max-bpc.

Add max-bpc output action.

refactor: add set_connector_properties

Fix niri-config parse test.

fix: bail when outside valid max bpc range
This commit is contained in:
Michael Yang
2026-01-01 05:45:17 +11:00
committed by Ivan Molodetskikh
parent 9a6f31012d
commit c5253968b4
9 changed files with 274 additions and 56 deletions
+9 -1
View File
@@ -745,6 +745,7 @@ mod tests {
transform "flipped-90"
position x=10 y=20
mode "1920x1080@144"
max-bpc 10
variable-refresh-rate on-demand=true
background-color "rgba(25, 25, 102, 1.0)"
hot-corners {
@@ -857,7 +858,7 @@ mod tests {
window-open { off; }
window-close {
curve "cubic-bezier" 0.05 0.7 0.1 1
curve "cubic-bezier" 0.05 0.7 0.1 1
}
recent-windows-close {
@@ -1160,6 +1161,11 @@ mod tests {
y: 20,
},
),
max_bpc: Some(
MaxBpc(
_10,
),
),
mode: Some(
Mode {
custom: false,
@@ -1205,6 +1211,7 @@ mod tests {
scale: None,
transform: Normal,
position: None,
max_bpc: None,
mode: Some(
Mode {
custom: true,
@@ -1231,6 +1238,7 @@ mod tests {
scale: None,
transform: Normal,
position: None,
max_bpc: None,
mode: None,
modeline: Some(
Modeline {
+42
View File
@@ -59,6 +59,8 @@ pub struct Output {
pub transform: Transform,
#[knuffel(child)]
pub position: Option<Position>,
#[knuffel(child, unwrap(argument))]
pub max_bpc: Option<MaxBpc>,
#[knuffel(child)]
pub mode: Option<Mode>,
#[knuffel(child)]
@@ -101,6 +103,7 @@ impl Default for Output {
scale: None,
transform: Transform::Normal,
position: None,
max_bpc: None,
mode: None,
modeline: None,
variable_refresh_rate: None,
@@ -128,6 +131,9 @@ pub struct Position {
pub y: i32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct MaxBpc(pub niri_ipc::MaxBpc);
#[derive(knuffel::Decode, Debug, Clone, PartialEq, Default)]
pub struct Vrr {
#[knuffel(property, default = false)]
@@ -257,6 +263,42 @@ impl OutputName {
}
}
impl<S: ErrorSpan> knuffel::DecodeScalar<S> for MaxBpc {
fn type_check(
type_name: &Option<knuffel::span::Spanned<knuffel::ast::TypeName, S>>,
ctx: &mut Context<S>,
) {
if let Some(type_name) = &type_name {
ctx.emit_error(DecodeError::unexpected(
type_name,
"type name",
"no type name expected for this node",
));
}
}
fn raw_decode(
value: &knuffel::span::Spanned<knuffel::ast::Literal, S>,
ctx: &mut Context<S>,
) -> Result<Self, DecodeError<S>> {
match &**value {
knuffel::ast::Literal::Int(ref val) => match u8::try_from(val) {
Ok(v) => niri_ipc::MaxBpc::try_from(v)
.map(MaxBpc)
.map_err(|e| DecodeError::conversion(value, e)),
Err(e) => {
ctx.emit_error(DecodeError::conversion(value, e));
Ok(Self::default())
}
},
_ => {
ctx.emit_error(DecodeError::scalar_kind(knuffel::decode::Kind::Int, value));
Ok(Self::default())
}
}
}
}
impl<S: ErrorSpan> knuffel::Decode<S> for Mode {
fn decode_node(node: &SpannedNode<S>, ctx: &mut Context<S>) -> Result<Self, DecodeError<S>> {
if let Some(type_name) = &node.type_name {