1
0
Fork 0
forked from wry/wry
wry/src/ifs/wlr_output_manager/zwlr_output_configuration_head.rs
2025-07-17 08:57:24 +02:00

146 lines
4.8 KiB
Rust

use {
crate::{
backend::Mode,
client::{Client, ClientError},
fixed::Fixed,
ifs::wlr_output_manager::zwlr_output_head_v1::{
ADAPTIVE_SYNC_STATE_DISABLED, ADAPTIVE_SYNC_STATE_ENABLED, WlrOutputHeadId,
},
leaks::Tracker,
object::{Object, Version},
scale::Scale,
tree::VrrMode,
utils::transform_ext::TransformExt,
wire::{ZwlrOutputConfigurationHeadV1Id, zwlr_output_configuration_head_v1::*},
},
jay_config::video::Transform,
std::{cell::RefCell, rc::Rc},
thiserror::Error,
};
pub struct ZwlrOutputConfigurationHeadV1 {
pub(super) id: ZwlrOutputConfigurationHeadV1Id,
pub(super) head_id: WlrOutputHeadId,
pub(super) version: Version,
pub(super) client: Rc<Client>,
pub(super) config: RefCell<OutputConfig>,
pub(super) tracker: Tracker<Self>,
}
#[derive(Default, Copy, Clone)]
pub struct OutputConfig {
pub(super) transform: Option<Transform>,
pub(super) scale: Option<Scale>,
pub(super) vrr_mode: Option<&'static VrrMode>,
pub(super) pos: Option<(i32, i32)>,
pub(super) mode: Option<Mode>,
}
impl ZwlrOutputConfigurationHeadV1RequestHandler for ZwlrOutputConfigurationHeadV1 {
type Error = ZwlrOutputConfigurationHeadV1Error;
fn set_mode(&self, req: SetMode, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let config = &mut *self.config.borrow_mut();
if config.mode.is_some() {
return Err(ZwlrOutputConfigurationHeadV1Error::AlreadySet);
}
let mode = self.client.lookup(req.mode)?;
if self.head_id != mode.head_id {
return Err(ZwlrOutputConfigurationHeadV1Error::InvalidMode);
}
config.mode = Some(mode.mode);
Ok(())
}
fn set_custom_mode(&self, req: SetCustomMode, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let config = &mut *self.config.borrow_mut();
if config.mode.is_some() {
return Err(ZwlrOutputConfigurationHeadV1Error::AlreadySet);
}
config.mode = Some(Mode {
width: req.width,
height: req.height,
refresh_rate_millihz: req.refresh as u32,
});
Ok(())
}
fn set_position(&self, req: SetPosition, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let config = &mut *self.config.borrow_mut();
if config.pos.is_some() {
return Err(ZwlrOutputConfigurationHeadV1Error::AlreadySet);
}
config.pos = Some((req.x, req.y));
Ok(())
}
fn set_transform(&self, req: SetTransform, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let config = &mut *self.config.borrow_mut();
if config.transform.is_some() {
return Err(ZwlrOutputConfigurationHeadV1Error::AlreadySet);
}
let Some(transform) = Transform::from_wl(req.transform) else {
return Err(ZwlrOutputConfigurationHeadV1Error::InvalidTransform(
req.transform,
));
};
config.transform = Some(transform);
Ok(())
}
fn set_scale(&self, req: SetScale, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let config = &mut *self.config.borrow_mut();
if config.scale.is_some() {
return Err(ZwlrOutputConfigurationHeadV1Error::AlreadySet);
}
if req.scale <= 0 {
return Err(ZwlrOutputConfigurationHeadV1Error::InvalidScale(req.scale));
}
config.scale = Some(Scale::from_f64(req.scale.to_f64()));
Ok(())
}
fn set_adaptive_sync(&self, req: SetAdaptiveSync, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let config = &mut *self.config.borrow_mut();
if config.vrr_mode.is_some() {
return Err(ZwlrOutputConfigurationHeadV1Error::AlreadySet);
}
let state = match req.state {
ADAPTIVE_SYNC_STATE_DISABLED => VrrMode::NEVER,
ADAPTIVE_SYNC_STATE_ENABLED => VrrMode::ALWAYS,
_ => {
return Err(
ZwlrOutputConfigurationHeadV1Error::InvalidAdaptiveSyncState(req.state),
);
}
};
config.vrr_mode = Some(state);
Ok(())
}
}
object_base! {
self = ZwlrOutputConfigurationHeadV1;
version = self.version;
}
impl Object for ZwlrOutputConfigurationHeadV1 {}
simple_add_obj!(ZwlrOutputConfigurationHeadV1);
#[derive(Debug, Error)]
pub enum ZwlrOutputConfigurationHeadV1Error {
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("Property has already been set")]
AlreadySet,
#[error("Mode doesn't belong to head")]
InvalidMode,
#[error("Unknown transform {0}")]
InvalidTransform(i32),
#[error("Invalid scale {0}")]
InvalidScale(Fixed),
#[error("Invalid adaptive sync state {0}")]
InvalidAdaptiveSyncState(u32),
}
efrom!(ZwlrOutputConfigurationHeadV1Error, ClientError);