diff --git a/src/compositor.rs b/src/compositor.rs index 3c307503..8ef2f6f9 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -647,6 +647,7 @@ fn create_dummy_output(state: &Rc) { wl_output: None, connector_enabled: true, in_compositor_space: false, + mode: Default::default(), monitor_info: None, }; let connector_data = Rc::new(ConnectorData { diff --git a/src/ifs/head_management.rs b/src/ifs/head_management.rs index db0396c7..920b3eb3 100644 --- a/src/ifs/head_management.rs +++ b/src/ifs/head_management.rs @@ -1,6 +1,6 @@ use { crate::{ - backend::{ConnectorId, MonitorInfo, transaction::BackendConnectorTransactionError}, + backend::{ConnectorId, Mode, MonitorInfo, transaction::BackendConnectorTransactionError}, client::ClientId, globals::GlobalName, ifs::head_management::{ @@ -71,6 +71,7 @@ pub struct HeadState { pub in_compositor_space: bool, pub position: (i32, i32), pub size: (i32, i32), + pub mode: Mode, pub transform: Transform, pub scale: Scale, pub monitor_info: Option>, @@ -92,10 +93,17 @@ impl HeadState { self.in_compositor_space = true; self.wl_output = wl_output; } + + fn update_size(&mut self) { + self.size = + OutputNode::calculate_extents_(self.mode, self.transform, self.scale, self.position) + .size(); + } } enum HeadOp { SetPosition(i32, i32), + SetScale(Scale), } #[derive(Copy, Clone, Debug, Eq, PartialEq, Default)] @@ -196,6 +204,7 @@ impl HeadManagers { if let Some(n) = &output.node { state.position = n.global.pos.get().position(); state.size = n.global.pos.get().size(); + state.mode = n.global.mode.get(); state.transform = n.global.persistent.transform.get(); } for head in self.managers.lock().values() { @@ -233,6 +242,7 @@ impl HeadManagers { let pos = node.global.pos.get(); state.position = pos.position(); state.size = pos.size(); + state.mode = node.global.mode.get(); for head in self.managers.lock().values() { skip_in_transaction!(head); if let Some(ext) = &head.ext.compositor_space_info_v1 { diff --git a/src/ifs/head_management/head_management_macros.rs b/src/ifs/head_management/head_management_macros.rs index 72dcd2f2..031c33a8 100644 --- a/src/ifs/head_management/head_management_macros.rs +++ b/src/ifs/head_management/head_management_macros.rs @@ -391,4 +391,5 @@ declare_extensions! { core_info_v1: CoreInfoV1, compositor_space_info_v1: CompositorSpaceInfoV1, compositor_space_positioner_v1: CompositorSpacePositionerV1, + compositor_space_scaler_v1: CompositorSpaceScalerV1, } diff --git a/src/ifs/head_management/jay_head_ext.rs b/src/ifs/head_management/jay_head_ext.rs index 544be3e6..fbea35cc 100644 --- a/src/ifs/head_management/jay_head_ext.rs +++ b/src/ifs/head_management/jay_head_ext.rs @@ -1,3 +1,4 @@ pub(super) mod jay_head_ext_compositor_space_info_v1; pub(super) mod jay_head_ext_compositor_space_positioner_v1; +pub(super) mod jay_head_ext_compositor_space_scaler_v1; pub(super) mod jay_head_ext_core_info_v1; diff --git a/src/ifs/head_management/jay_head_ext/jay_head_ext_compositor_space_scaler_v1.rs b/src/ifs/head_management/jay_head_ext/jay_head_ext_compositor_space_scaler_v1.rs new file mode 100644 index 00000000..6ac99aa9 --- /dev/null +++ b/src/ifs/head_management/jay_head_ext/jay_head_ext_compositor_space_scaler_v1.rs @@ -0,0 +1,62 @@ +use { + crate::{ + ifs::head_management::{HeadOp, HeadState}, + scale::Scale, + wire::{ + jay_head_ext_compositor_space_scaler_v1::{ + JayHeadExtCompositorSpaceScalerV1RequestHandler, Range, SetScale, + }, + jay_head_manager_ext_compositor_space_scaler_v1::JayHeadManagerExtCompositorSpaceScalerV1RequestHandler, + }, + }, + std::rc::Rc, +}; + +impl_compositor_space_scaler_v1! { + version = 1, + after_announce = after_announce, +} + +const MIN_SCALE: Scale = Scale::from_wl(60); +const MAX_SCALE: Scale = Scale::from_int(16); + +impl HeadName { + fn after_announce(&self, _shared: &HeadState) { + self.send_range(MIN_SCALE, MAX_SCALE); + } + + fn send_range(&self, min: Scale, max: Scale) { + self.client.event(Range { + self_id: self.id, + min: min.to_wl(), + max: max.to_wl(), + }); + } +} + +impl JayHeadManagerExtCompositorSpaceScalerV1RequestHandler for MgrName { + type Error = ErrorName; + + mgr_common_req!(); +} + +impl JayHeadExtCompositorSpaceScalerV1RequestHandler for HeadName { + type Error = ErrorName; + + head_common_req!(); + + fn set_scale(&self, req: SetScale, _slf: &Rc) -> Result<(), Self::Error> { + self.common.assert_in_transaction()?; + let scale = Scale::from_wl(req.scale); + if scale < MIN_SCALE || scale > MAX_SCALE { + return Err(JayHeadExtCompositorSpaceScalerV1Error::ScaleOutOfBounds); + } + self.common.push_op(HeadOp::SetScale(scale))?; + Ok(()) + } +} + +error! { + #[error("The scale is out of bounds")] + ScaleOutOfBounds, +} diff --git a/src/ifs/head_management/jay_head_manager_session_v1.rs b/src/ifs/head_management/jay_head_manager_session_v1.rs index df58a6a3..107bb6c3 100644 --- a/src/ifs/head_management/jay_head_manager_session_v1.rs +++ b/src/ifs/head_management/jay_head_manager_session_v1.rs @@ -395,6 +395,12 @@ impl JayHeadManagerSessionV1RequestHandler for JayHeadManagerSessionV1 { state.position = (x, y); to_send |= COMPOSITOR_SPACE_INFO_POS; } + HeadOp::SetScale(s) => { + state.scale = s; + state.update_size(); + to_send |= COMPOSITOR_SPACE_INFO_SCALE; + to_send |= COMPOSITOR_SPACE_INFO_SIZE; + } } } if to_send.contains(CORE_INFO) @@ -456,6 +462,7 @@ impl JayHeadManagerSessionV1RequestHandler for JayHeadManagerSessionV1 { && let Some(node) = &output.node { node.set_position(desired.position.0, desired.position.1); + node.set_preferred_scale(desired.scale); } else if let Some(mi) = &desired.monitor_info { let pos = &self.client.state.persistent_output_states; let pos = match pos.get(&mi.output_id) { @@ -475,6 +482,7 @@ impl JayHeadManagerSessionV1RequestHandler for JayHeadManagerSessionV1 { } }; pos.pos.set(desired.position); + pos.scale.set(desired.scale); } } slf.schedule_transaction_result(req.result, None)?; diff --git a/src/scale.rs b/src/scale.rs index b937faa4..63f06f81 100644 --- a/src/scale.rs +++ b/src/scale.rs @@ -15,7 +15,7 @@ impl Default for Scale { } impl Scale { - pub fn from_int(f: u32) -> Self { + pub const fn from_int(f: u32) -> Self { Self(f.saturating_mul(BASE)) } @@ -31,7 +31,7 @@ impl Scale { self.0.saturating_add(BASE - 1) / BASE } - pub fn from_wl(wl: u32) -> Self { + pub const fn from_wl(wl: u32) -> Self { Self(wl) } diff --git a/src/tasks/connector.rs b/src/tasks/connector.rs index 203f3049..49e07403 100644 --- a/src/tasks/connector.rs +++ b/src/tasks/connector.rs @@ -53,6 +53,7 @@ pub fn handle(state: &Rc, connector: &Rc) { wl_output: None, connector_enabled: backend_state.enabled, in_compositor_space: false, + mode: Default::default(), monitor_info: None, }; let data = Rc::new(ConnectorData { diff --git a/src/tree/output.rs b/src/tree/output.rs index cb06b12e..e20e6256 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -812,14 +812,22 @@ impl OutputNode { } fn calculate_extents(&self) -> Rect { - let mode = self.global.mode.get(); - let (width, height) = calculate_logical_size( - (mode.width, mode.height), + Self::calculate_extents_( + self.global.mode.get(), self.global.persistent.transform.get(), self.global.persistent.scale.get(), - ); - let pos = self.global.pos.get(); - pos.with_size(width, height).unwrap() + self.global.pos.get().position(), + ) + } + + pub fn calculate_extents_( + mode: Mode, + transform: Transform, + scale: Scale, + pos: (i32, i32), + ) -> Rect { + let (width, height) = calculate_logical_size((mode.width, mode.height), transform, scale); + Rect::new_sized(pos.0, pos.1, width, height).unwrap() } fn change_extents_(self: &Rc, rect: &Rect) { diff --git a/wire/jay_head_ext_compositor_space_scaler_v1.txt b/wire/jay_head_ext_compositor_space_scaler_v1.txt new file mode 100644 index 00000000..249a721e --- /dev/null +++ b/wire/jay_head_ext_compositor_space_scaler_v1.txt @@ -0,0 +1,12 @@ +request destroy (destructor) { + +} + +request set_scale { + scale: u32, +} + +event range { + min: u32, + max: u32, +} diff --git a/wire/jay_head_manager_ext_compositor_space_scaler_v1.txt b/wire/jay_head_manager_ext_compositor_space_scaler_v1.txt new file mode 100644 index 00000000..7c3b5ab4 --- /dev/null +++ b/wire/jay_head_manager_ext_compositor_space_scaler_v1.txt @@ -0,0 +1,7 @@ +request destroy (destructor) { + +} + +event head { + head: id(jay_head_ext_compositor_space_scaler_v1) (new), +}