1
0
Fork 0
forked from wry/wry

head-management: add non-desktop-info-v1 extension

This commit is contained in:
Julian Orth 2025-07-13 11:14:37 +02:00
parent 81a7c973d0
commit b76aade265
17 changed files with 164 additions and 5 deletions

View file

@ -104,6 +104,7 @@ pub struct MonitorInfo {
pub width_mm: i32,
pub height_mm: i32,
pub non_desktop: bool,
pub non_desktop_effective: bool,
pub vrr_capable: bool,
pub transfer_functions: Vec<BackendTransferFunction>,
pub color_spaces: Vec<BackendColorSpace>,

View file

@ -727,7 +727,7 @@ impl MetalConnector {
match &event {
ConnectorEvent::Connected(ty) => match state {
FrontState::Disconnected => {
let non_desktop = ty.non_desktop;
let non_desktop = ty.non_desktop_effective;
self.on_change.send_event(event);
set_state(FrontState::Connected { non_desktop });
}
@ -1915,7 +1915,8 @@ impl MetalBackend {
output_id: dd.output_id.clone(),
width_mm: dd.mm_width as _,
height_mm: dd.mm_height as _,
non_desktop: dd.non_desktop_effective,
non_desktop: dd.non_desktop,
non_desktop_effective: dd.non_desktop_effective,
vrr_capable: dd.vrr_capable,
transfer_functions,
color_spaces,

View file

@ -597,6 +597,7 @@ impl XBackend {
width_mm: output.width.get(),
height_mm: output.height.get(),
non_desktop: false,
non_desktop_effective: false,
vrr_capable: false,
transfer_functions: vec![],
color_spaces: vec![],

View file

@ -651,6 +651,8 @@ fn create_dummy_output(state: &Rc<State>) {
in_compositor_space: false,
mode: Default::default(),
monitor_info: None,
inherent_non_desktop: false,
override_non_desktop: None,
};
let connector_data = Rc::new(ConnectorData {
id,

View file

@ -77,6 +77,8 @@ pub struct HeadState {
pub transform: Transform,
pub scale: Scale,
pub monitor_info: Option<RcEq<MonitorInfo>>,
pub inherent_non_desktop: bool,
pub override_non_desktop: Option<bool>,
}
impl HeadState {
@ -92,6 +94,9 @@ impl HeadState {
if mi.non_desktop {
return;
}
if self.override_non_desktop == Some(true) {
return;
}
self.in_compositor_space = true;
self.wl_output = wl_output;
}
@ -206,6 +211,7 @@ impl HeadManagers {
let state = &mut *self.state.borrow_mut();
state.connected = true;
state.monitor_info = Some(RcEq(output.monitor_info.clone()));
state.inherent_non_desktop = output.monitor_info.non_desktop;
state.update_in_compositor_space(output.node.as_ref().map(|n| n.global.name));
if let Some(n) = &output.node {
state.position = n.global.pos.get().position();
@ -239,6 +245,10 @@ impl HeadManagers {
ext.send_wl_output(state);
head.session.schedule_done();
}
if let Some(ext) = &head.ext.non_desktop_info_v1 {
ext.send_state(state);
head.session.schedule_done();
}
}
}
@ -337,4 +347,16 @@ impl HeadManagers {
}
}
}
pub fn handle_non_desktop_override_changed(&self, overrd: Option<bool>) {
let state = &mut *self.state.borrow_mut();
state.override_non_desktop = overrd;
for head in self.managers.lock().values() {
skip_in_transaction!(head);
if let Some(ext) = &head.ext.non_desktop_info_v1 {
ext.send_state(state);
head.session.schedule_done();
}
}
}
}

View file

@ -398,4 +398,5 @@ declare_extensions! {
mode_info_v1: ModeInfoV1,
mode_setter_v1: ModeSetterV1,
physical_display_info_v1: PhysicalDisplayInfoV1,
non_desktop_info_v1: NonDesktopInfoV1,
}

View file

@ -7,4 +7,5 @@ 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;
pub(super) mod jay_head_ext_non_desktop_info_v1;
pub(super) mod jay_head_ext_physical_display_info_v1;

View file

@ -0,0 +1,78 @@
use {
crate::{
ifs::head_management::HeadState,
wire::{
jay_head_ext_non_desktop_info_v1::{
EffectiveDesktop, EffectiveNonDesktop, InherentDesktop, InherentNonDesktop,
JayHeadExtNonDesktopInfoV1RequestHandler, OverrideDesktop, OverrideNonDesktop,
Reset,
},
jay_head_manager_ext_non_desktop_info_v1::JayHeadManagerExtNonDesktopInfoV1RequestHandler,
},
},
std::rc::Rc,
};
impl_non_desktop_info_v1! {
version = 1,
after_announce = after_announce,
after_transaction = after_transaction,
}
impl HeadName {
fn after_announce(&self, shared: &HeadState) {
self.send_state(shared);
}
fn after_transaction(&self, shared: &HeadState, tran: &HeadState) {
if shared.override_non_desktop == tran.override_non_desktop {
match (&shared.monitor_info, &tran.monitor_info) {
(Some(s), Some(t)) if s.non_desktop == t.non_desktop => return,
(None, None) => return,
_ => {}
}
}
self.send_state(shared);
}
pub(in super::super) fn send_state(&self, state: &HeadState) {
self.client.event(Reset { self_id: self.id });
let mut inherent_non_desktop = None;
if let Some(monitor_info) = &state.monitor_info {
inherent_non_desktop = Some(monitor_info.non_desktop);
if monitor_info.non_desktop {
self.client.event(InherentNonDesktop { self_id: self.id });
} else {
self.client.event(InherentDesktop { self_id: self.id });
}
}
if let Some(overrd) = state.override_non_desktop {
if overrd {
self.client.event(OverrideNonDesktop { self_id: self.id });
} else {
self.client.event(OverrideDesktop { self_id: self.id });
}
}
if let Some(nd) = state.override_non_desktop.or(inherent_non_desktop) {
if nd {
self.client.event(EffectiveNonDesktop { self_id: self.id });
} else {
self.client.event(EffectiveDesktop { self_id: self.id });
}
}
}
}
impl JayHeadManagerExtNonDesktopInfoV1RequestHandler for MgrName {
type Error = ErrorName;
mgr_common_req!();
}
impl JayHeadExtNonDesktopInfoV1RequestHandler for HeadName {
type Error = ErrorName;
head_common_req!();
}
error!();

View file

@ -50,7 +50,7 @@ impl HeadName {
self.send_model(&mi.output_id.model);
self.send_serial_number(&mi.output_id.serial_number);
self.send_physical_size(mi.width_mm, mi.height_mm);
if mi.non_desktop {
if mi.non_desktop_effective {
self.send_non_desktop();
}
if mi.vrr_capable {

View file

@ -383,6 +383,7 @@ impl JayHeadManagerSessionV1RequestHandler for JayHeadManagerSessionV1 {
COMPOSITOR_SPACE_INFO_TRANSFORM = 1 << 4,
COMPOSITOR_SPACE_INFO_SCALE = 1 << 5,
MODE_INFO = 1 << 6,
NON_DESKTOP_INFO = 1 << 7,
COMPOSITOR_SPACE_INFO_ENABLED = 1 << 13,
}
for head in self.heads.lock().values() {
@ -454,6 +455,11 @@ impl JayHeadManagerSessionV1RequestHandler for JayHeadManagerSessionV1 {
{
i.send_mode(state);
}
if to_send.contains(NON_DESKTOP_INFO)
&& let Some(i) = &head.ext.non_desktop_info_v1
{
i.send_state(state);
}
}
slf.schedule_transaction_result(req.result, None)?;
Ok(())

View file

@ -56,7 +56,7 @@ impl WpDrmLeaseDeviceV1Global {
}
for c in dev.connectors.lock().keys() {
if let Some(o) = client.state.outputs.get(c)
&& o.monitor_info.non_desktop
&& o.monitor_info.non_desktop_effective
{
obj.create_connector(&o);
}

View file

@ -135,6 +135,7 @@ impl TestBackend {
width_mm: 80,
height_mm: 60,
non_desktop: false,
non_desktop_effective: false,
vrr_capable: false,
transfer_functions: vec![],
color_spaces: vec![],

View file

@ -47,6 +47,7 @@ async fn test(run: Rc<TestRun>) -> TestResult {
width_mm: 0,
height_mm: 0,
non_desktop: false,
non_desktop_effective: false,
vrr_capable: false,
transfer_functions: vec![],
color_spaces: vec![],

View file

@ -449,6 +449,10 @@ impl ConnectorData {
if old.active != s.active {
self.head_managers.handle_active_change(s.active);
}
if old.non_desktop_override != s.non_desktop_override {
self.head_managers
.handle_non_desktop_override_changed(s.non_desktop_override);
}
if let Some(output) = state.outputs.get(&self.connector.id())
&& let Some(node) = &output.node
{

View file

@ -57,6 +57,8 @@ pub fn handle(state: &Rc<State>, connector: &Rc<dyn Connector>) {
in_compositor_space: false,
mode: Default::default(),
monitor_info: None,
inherent_non_desktop: false,
override_non_desktop: backend_state.non_desktop_override,
};
let data = Rc::new(ConnectorData {
id,
@ -132,7 +134,7 @@ impl ConnectorHandler {
self.data.connected.set(true);
self.data.set_state(&self.state, info.state);
let name = self.state.globals.name();
if info.non_desktop {
if info.non_desktop_effective {
self.handle_non_desktop_connected(info).await;
} else {
self.handle_desktop_connected(info, name).await;