From aaef75f9f30068d6eb9233c5547849038c15c722 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Sun, 13 Jul 2025 13:20:42 +0200 Subject: [PATCH] head-management: add vrr-state-v1 extension --- src/compositor.rs | 1 + src/ifs/head_management.rs | 21 +++++++ .../head_management/head_management_macros.rs | 1 + src/ifs/head_management/jay_head_ext.rs | 1 + .../jay_head_ext/jay_head_ext_vrr_state_v1.rs | 58 +++++++++++++++++++ src/state.rs | 3 + src/tasks/connector.rs | 1 + wire/jay_head_ext_vrr_state_v1.txt | 15 +++++ wire/jay_head_manager_ext_vrr_state_v1.txt | 7 +++ 9 files changed, 108 insertions(+) create mode 100644 src/ifs/head_management/jay_head_ext/jay_head_ext_vrr_state_v1.rs create mode 100644 wire/jay_head_ext_vrr_state_v1.txt create mode 100644 wire/jay_head_manager_ext_vrr_state_v1.txt diff --git a/src/compositor.rs b/src/compositor.rs index 4c23006c..d5f72de0 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -653,6 +653,7 @@ fn create_dummy_output(state: &Rc) { monitor_info: None, inherent_non_desktop: false, override_non_desktop: None, + vrr: false, }; let connector_data = Rc::new(ConnectorData { id, diff --git a/src/ifs/head_management.rs b/src/ifs/head_management.rs index 330f028b..d964a6cd 100644 --- a/src/ifs/head_management.rs +++ b/src/ifs/head_management.rs @@ -79,6 +79,7 @@ pub struct HeadState { pub monitor_info: Option>, pub inherent_non_desktop: bool, pub override_non_desktop: Option, + pub vrr: bool, } impl HeadState { @@ -249,6 +250,10 @@ impl HeadManagers { ext.send_state(state); head.session.schedule_done(); } + if let Some(ext) = &head.ext.vrr_state_v1 { + ext.send_state(state); + head.session.schedule_done(); + } } } @@ -275,6 +280,10 @@ impl HeadManagers { ext.send_info(state); head.session.schedule_done(); } + if let Some(ext) = &head.ext.vrr_state_v1 { + ext.send_state(state); + head.session.schedule_done(); + } } } @@ -359,4 +368,16 @@ impl HeadManagers { } } } + + pub fn handle_vrr_change(&self, vrr: bool) { + let state = &mut *self.state.borrow_mut(); + state.vrr = vrr; + for head in self.managers.lock().values() { + skip_in_transaction!(head); + if let Some(ext) = &head.ext.vrr_state_v1 { + ext.send_state(state); + head.session.schedule_done(); + } + } + } } diff --git a/src/ifs/head_management/head_management_macros.rs b/src/ifs/head_management/head_management_macros.rs index 6bafdee2..20160c2c 100644 --- a/src/ifs/head_management/head_management_macros.rs +++ b/src/ifs/head_management/head_management_macros.rs @@ -399,4 +399,5 @@ declare_extensions! { mode_setter_v1: ModeSetterV1, physical_display_info_v1: PhysicalDisplayInfoV1, non_desktop_info_v1: NonDesktopInfoV1, + vrr_state_v1: VrrStateV1, } diff --git a/src/ifs/head_management/jay_head_ext.rs b/src/ifs/head_management/jay_head_ext.rs index 2a43ac31..96d21fc7 100644 --- a/src/ifs/head_management/jay_head_ext.rs +++ b/src/ifs/head_management/jay_head_ext.rs @@ -9,3 +9,4 @@ pub(super) mod jay_head_ext_mode_info_v1; pub(super) mod jay_head_ext_mode_setter_v1; pub(super) mod jay_head_ext_non_desktop_info_v1; pub(super) mod jay_head_ext_physical_display_info_v1; +pub(super) mod jay_head_ext_vrr_state_v1; diff --git a/src/ifs/head_management/jay_head_ext/jay_head_ext_vrr_state_v1.rs b/src/ifs/head_management/jay_head_ext/jay_head_ext_vrr_state_v1.rs new file mode 100644 index 00000000..778dea23 --- /dev/null +++ b/src/ifs/head_management/jay_head_ext/jay_head_ext_vrr_state_v1.rs @@ -0,0 +1,58 @@ +use { + crate::{ + ifs::head_management::HeadState, + wire::{ + jay_head_ext_vrr_state_v1::{ + Capable, Enabled, JayHeadExtVrrStateV1RequestHandler, Reset, + }, + jay_head_manager_ext_vrr_state_v1::JayHeadManagerExtVrrStateV1RequestHandler, + }, + }, + std::rc::Rc, +}; + +impl_vrr_state_v1! { + version = 1, + after_announce = after_announce, + after_transaction = after_transaction, +} + +impl HeadName { + fn after_announce(&self, shared: &HeadState) { + self.send_state(shared); + } + + fn after_transaction(&self, shared: &HeadState, tran: &HeadState) { + let shared_capable = shared.monitor_info.as_ref().map(|m| m.vrr_capable); + let tran_capable = tran.monitor_info.as_ref().map(|m| m.vrr_capable); + if (shared.vrr, shared_capable) != (tran.vrr, tran_capable) { + self.send_state(shared); + } + } + + pub(in super::super) fn send_state(&self, state: &HeadState) { + self.client.event(Reset { self_id: self.id }); + if let Some(mi) = &state.monitor_info + && mi.vrr_capable + { + self.client.event(Capable { self_id: self.id }); + } + if state.vrr { + self.client.event(Enabled { self_id: self.id }); + } + } +} + +impl JayHeadManagerExtVrrStateV1RequestHandler for MgrName { + type Error = ErrorName; + + mgr_common_req!(); +} + +impl JayHeadExtVrrStateV1RequestHandler for HeadName { + type Error = ErrorName; + + head_common_req!(); +} + +error!(); diff --git a/src/state.rs b/src/state.rs index f54fe3e9..b30b0da1 100644 --- a/src/state.rs +++ b/src/state.rs @@ -453,6 +453,9 @@ impl ConnectorData { self.head_managers .handle_non_desktop_override_changed(s.non_desktop_override); } + if old.vrr != s.vrr { + self.head_managers.handle_vrr_change(s.vrr); + } if let Some(output) = state.outputs.get(&self.connector.id()) && let Some(node) = &output.node { diff --git a/src/tasks/connector.rs b/src/tasks/connector.rs index 5891835f..73f356eb 100644 --- a/src/tasks/connector.rs +++ b/src/tasks/connector.rs @@ -59,6 +59,7 @@ pub fn handle(state: &Rc, connector: &Rc) { monitor_info: None, inherent_non_desktop: false, override_non_desktop: backend_state.non_desktop_override, + vrr: backend_state.vrr, }; let data = Rc::new(ConnectorData { id, diff --git a/wire/jay_head_ext_vrr_state_v1.txt b/wire/jay_head_ext_vrr_state_v1.txt new file mode 100644 index 00000000..5ff3c63d --- /dev/null +++ b/wire/jay_head_ext_vrr_state_v1.txt @@ -0,0 +1,15 @@ +request destroy (destructor) { + +} + +event reset { + +} + +event capable { + +} + +event enabled { + +} diff --git a/wire/jay_head_manager_ext_vrr_state_v1.txt b/wire/jay_head_manager_ext_vrr_state_v1.txt new file mode 100644 index 00000000..5f7c21db --- /dev/null +++ b/wire/jay_head_manager_ext_vrr_state_v1.txt @@ -0,0 +1,7 @@ +request destroy (destructor) { + +} + +event head { + head: id(jay_head_ext_vrr_state_v1) (new), +}