1
0
Fork 0
forked from wry/wry

head-management: add mode-setter-v1 extension

This commit is contained in:
Julian Orth 2025-07-12 09:33:44 +02:00
parent c25ddc8b5b
commit 7e69a80dbc
7 changed files with 128 additions and 0 deletions

View file

@ -108,6 +108,7 @@ enum HeadOp {
SetConnectorEnabled(bool),
SetTransform(Transform),
SetScale(Scale),
SetMode(usize),
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
@ -222,6 +223,10 @@ impl HeadManagers {
ext.send_mode(state);
head.session.schedule_done();
}
if let Some(ext) = &head.ext.mode_setter_v1 {
ext.send_modes(state);
head.session.schedule_done();
}
if let Some(ext) = &head.ext.compositor_space_info_v1 {
ext.send_inside_outside(state);
head.session.schedule_done();

View file

@ -396,4 +396,5 @@ declare_extensions! {
compositor_space_enabler_v1: CompositorSpaceEnablerV1,
connector_info_v1: ConnectorInfoV1,
mode_info_v1: ModeInfoV1,
mode_setter_v1: ModeSetterV1,
}

View file

@ -6,3 +6,4 @@ pub(super) mod jay_head_ext_compositor_space_transformer_v1;
pub(super) mod jay_head_ext_connector_info_v1;
pub(super) mod jay_head_ext_core_info_v1;
pub(super) mod jay_head_ext_mode_info_v1;
pub(super) mod jay_head_ext_mode_setter_v1;

View file

@ -0,0 +1,90 @@
use {
crate::{
backend::CONCAP_MODE_SETTING,
ifs::head_management::{HeadCommon, HeadOp, HeadState},
state::ConnectorData,
wire::{
jay_head_ext_mode_setter_v1::{
JayHeadExtModeSetterV1RequestHandler, Mode, Reset, SetMode,
},
jay_head_manager_ext_mode_setter_v1::JayHeadManagerExtModeSetterV1RequestHandler,
},
},
std::rc::Rc,
};
impl_mode_setter_v1! {
version = 1,
filter = filter,
after_announce = after_announce,
after_transaction = after_transaction,
}
impl MgrName {
fn filter(&self, connector: &ConnectorData, _common: &Rc<HeadCommon>) -> bool {
connector.connector.caps().contains(CONCAP_MODE_SETTING)
}
}
impl HeadName {
fn after_announce(&self, shared: &HeadState) {
self.send_modes(shared);
}
fn after_transaction(&self, shared: &HeadState, tran: &HeadState) {
match (&shared.monitor_info, &tran.monitor_info) {
(Some(s), Some(t)) if s != t => {}
_ => return,
}
self.send_modes(shared);
}
pub(in super::super) fn send_modes(&self, state: &HeadState) {
self.client.event(Reset { self_id: self.id });
if let Some(mi) = &state.monitor_info {
for mode in &mi.modes {
self.client.event(Mode {
self_id: self.id,
width: mode.width,
height: mode.height,
refresh_mhz: mode.refresh_rate_millihz,
})
}
}
}
}
impl JayHeadManagerExtModeSetterV1RequestHandler for MgrName {
type Error = ErrorName;
mgr_common_req!();
}
impl JayHeadExtModeSetterV1RequestHandler for HeadName {
type Error = ErrorName;
head_common_req!();
fn set_mode(&self, req: SetMode, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.common.assert_in_transaction()?;
let num_modes = self
.common
.snapshot_state
.borrow()
.monitor_info
.as_deref()
.map(|i| i.modes.len())
.unwrap_or(0);
let idx = req.idx as usize;
if idx >= num_modes {
return Err(JayHeadExtModeSetterV1Error::ModeOutOfBounds);
}
self.common.push_op(HeadOp::SetMode(idx))?;
Ok(())
}
}
error! {
#[error("The mode is out of bounds")]
ModeOutOfBounds,
}

View file

@ -264,6 +264,7 @@ impl JayHeadManagerSessionV1 {
let old = connector.state.get();
let mut new = old;
new.enabled = desired.connector_enabled;
new.mode = desired.mode;
if old == new {
continue;
}
@ -414,6 +415,12 @@ impl JayHeadManagerSessionV1RequestHandler for JayHeadManagerSessionV1 {
to_send |= COMPOSITOR_SPACE_INFO_SCALE;
to_send |= COMPOSITOR_SPACE_INFO_SIZE;
}
HeadOp::SetMode(i) => {
state.mode = snapshot.monitor_info.as_deref().unwrap().modes[i];
state.update_size();
to_send |= MODE_INFO;
to_send |= COMPOSITOR_SPACE_INFO_SIZE;
}
}
}
if to_send.contains(CORE_INFO)

View file

@ -0,0 +1,17 @@
request destroy (destructor) {
}
request set_mode {
idx: u32,
}
event reset {
}
event mode {
width: i32,
height: i32,
refresh_mhz: u32,
}

View file

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