1
0
Fork 0
forked from wry/wry

head-management: add compositor-space-scaler-v1 extension

This commit is contained in:
Julian Orth 2025-07-12 09:24:45 +02:00
parent a12b259648
commit a8ed4785af
11 changed files with 120 additions and 9 deletions

View file

@ -647,6 +647,7 @@ fn create_dummy_output(state: &Rc<State>) {
wl_output: None,
connector_enabled: true,
in_compositor_space: false,
mode: Default::default(),
monitor_info: None,
};
let connector_data = Rc::new(ConnectorData {

View file

@ -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<RcEq<MonitorInfo>>,
@ -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 {

View file

@ -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,
}

View file

@ -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;

View file

@ -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<Self>) -> 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,
}

View file

@ -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)?;

View file

@ -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)
}

View file

@ -53,6 +53,7 @@ pub fn handle(state: &Rc<State>, connector: &Rc<dyn Connector>) {
wl_output: None,
connector_enabled: backend_state.enabled,
in_compositor_space: false,
mode: Default::default(),
monitor_info: None,
};
let data = Rc::new(ConnectorData {

View file

@ -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<Self>, rect: &Rect) {

View file

@ -0,0 +1,12 @@
request destroy (destructor) {
}
request set_scale {
scale: u32,
}
event range {
min: u32,
max: u32,
}

View file

@ -0,0 +1,7 @@
request destroy (destructor) {
}
event head {
head: id(jay_head_ext_compositor_space_scaler_v1) (new),
}