diff --git a/src/state.rs b/src/state.rs index 471582b3..d175d88a 100644 --- a/src/state.rs +++ b/src/state.rs @@ -5,6 +5,7 @@ use crate::{ config::{Config, OutputConfig}, input::gestures::GestureState, shell::{grabs::SeatMoveGrabState, CosmicSurface, SeatExt, Shell}, + utils::prelude::OutputExt, wayland::protocols::{ drm::WlDrmState, image_source::ImageSourceState, @@ -280,6 +281,7 @@ impl BackendData { .get::>() .unwrap() .borrow(); + let mode = Some(OutputMode { size: final_config.mode_size(), refresh: final_config.mode_refresh() as i32, @@ -295,6 +297,9 @@ impl BackendData { let location = Some(final_config.position.into()).filter(|x| *x != output.current_location()); output.change_current_state(mode, transform, scale.map(Scale::Fractional), location); + + output.set_adaptive_sync(final_config.vrr); + layer_map_for_output(output).arrange(); } diff --git a/src/utils/prelude.rs b/src/utils/prelude.rs index 2503fee1..052e5d7b 100644 --- a/src/utils/prelude.rs +++ b/src/utils/prelude.rs @@ -8,10 +8,16 @@ pub use crate::shell::{SeatExt, Shell, Workspace}; pub use crate::state::{Common, State}; pub use crate::wayland::handlers::xdg_shell::popup::update_reactive_popups; +use std::sync::atomic::{AtomicBool, Ordering}; + pub trait OutputExt { fn geometry(&self) -> Rectangle; + fn adaptive_sync(&self) -> bool; + fn set_adaptive_sync(&self, vrr: bool); } +struct Vrr(AtomicBool); + impl OutputExt for Output { fn geometry(&self) -> Rectangle { Rectangle::from_loc_and_size(self.current_location(), { @@ -27,4 +33,20 @@ impl OutputExt for Output { }) .as_global() } + + fn adaptive_sync(&self) -> bool { + self.user_data() + .get::() + .map(|vrr| vrr.0.load(Ordering::SeqCst)) + .unwrap_or(false) + } + fn set_adaptive_sync(&self, vrr: bool) { + let user_data = self.user_data(); + user_data.insert_if_missing_threadsafe(|| Vrr(AtomicBool::new(false))); + user_data + .get::() + .unwrap() + .0 + .store(vrr, Ordering::SeqCst); + } } diff --git a/src/wayland/handlers/output_configuration.rs b/src/wayland/handlers/output_configuration.rs index 5e3fc2cf..6523ca1d 100644 --- a/src/wayland/handlers/output_configuration.rs +++ b/src/wayland/handlers/output_configuration.rs @@ -55,6 +55,7 @@ impl State { scale, transform, position, + adaptive_sync, } = conf { match mode { @@ -76,6 +77,9 @@ impl State { if let Some(position) = position { current_config.position = (*position).into(); } + if let Some(vrr) = adaptive_sync { + current_config.vrr = *vrr; + } current_config.enabled = OutputState::Enabled; } else { current_config.enabled = OutputState::Disabled; diff --git a/src/wayland/protocols/output_configuration.rs b/src/wayland/protocols/output_configuration.rs index 071db38b..0f53badc 100644 --- a/src/wayland/protocols/output_configuration.rs +++ b/src/wayland/protocols/output_configuration.rs @@ -92,6 +92,7 @@ pub struct PendingOutputConfigurationInner { position: Option>, transform: Option, scale: Option, + adaptive_sync: Option, } pub type PendingOutputConfiguration = Mutex; @@ -102,6 +103,7 @@ pub enum OutputConfiguration { position: Option>, transform: Option, scale: Option, + adaptive_sync: Option, }, Disabled, } @@ -128,6 +130,7 @@ impl<'a> TryFrom<&'a mut PendingOutputConfigurationInner> for OutputConfiguratio position: pending.position, transform: pending.transform, scale: pending.scale, + adaptive_sync: pending.adaptive_sync, }) } } @@ -543,6 +546,29 @@ where } }); } + zwlr_output_configuration_head_v1::Request::SetAdaptiveSync { state } => { + let mut pending = data.lock().unwrap(); + if pending.adaptive_sync.is_some() { + obj.post_error( + zwlr_output_configuration_head_v1::Error::AlreadySet, + format!("{:?} already had adaptive sync configured", obj), + ); + return; + } + pending.adaptive_sync = Some(match state.into_result() { + Ok(state) => match state { + zwlr_output_head_v1::AdaptiveSyncState::Enabled => true, + _ => false, + }, + Err(err) => { + obj.post_error( + zwlr_output_configuration_head_v1::Error::InvalidAdaptiveSyncState, + format!("Invalid adaptive sync value: {:?}", err), + ); + return; + } + }); + } _ => {} } } @@ -565,7 +591,7 @@ where F: for<'a> Fn(&'a Client) -> bool + Send + Sync + 'static, { let global = dh.create_global::( - 3, + 4, OutputMngrGlobalData { filter: Box::new(client_filter), }, @@ -810,9 +836,16 @@ where instance .obj .scale(output.current_scale().fractional_scale()); + if instance.obj.version() >= zwlr_output_head_v1::EVT_ADAPTIVE_SYNC_SINCE { + instance.obj.adaptive_sync(if output.adaptive_sync() { + zwlr_output_head_v1::AdaptiveSyncState::Enabled + } else { + zwlr_output_head_v1::AdaptiveSyncState::Disabled + }); + } } - if mngr.obj.version() >= zwlr_output_head_v1::EVT_MAKE_SINCE { + if instance.obj.version() >= zwlr_output_head_v1::EVT_MAKE_SINCE { if physical.make != "Unknown" { instance.obj.make(physical.make.clone()); } @@ -845,3 +878,5 @@ macro_rules! delegate_output_configuration { }; } pub(crate) use delegate_output_configuration; + +use crate::utils::prelude::OutputExt;