diff --git a/src/backend.rs b/src/backend.rs index 7b5b6b73..39fe5a58 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -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, pub color_spaces: Vec, diff --git a/src/backends/metal/video.rs b/src/backends/metal/video.rs index bd8e10f4..ecf24277 100644 --- a/src/backends/metal/video.rs +++ b/src/backends/metal/video.rs @@ -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, diff --git a/src/backends/x.rs b/src/backends/x.rs index d35cacbb..29e4969d 100644 --- a/src/backends/x.rs +++ b/src/backends/x.rs @@ -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![], diff --git a/src/compositor.rs b/src/compositor.rs index 7967ed46..4c23006c 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -651,6 +651,8 @@ fn create_dummy_output(state: &Rc) { 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, diff --git a/src/ifs/head_management.rs b/src/ifs/head_management.rs index 2ee688ce..330f028b 100644 --- a/src/ifs/head_management.rs +++ b/src/ifs/head_management.rs @@ -77,6 +77,8 @@ pub struct HeadState { pub transform: Transform, pub scale: Scale, pub monitor_info: Option>, + pub inherent_non_desktop: bool, + pub override_non_desktop: Option, } 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) { + 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(); + } + } + } } diff --git a/src/ifs/head_management/head_management_macros.rs b/src/ifs/head_management/head_management_macros.rs index 30a78cd5..6bafdee2 100644 --- a/src/ifs/head_management/head_management_macros.rs +++ b/src/ifs/head_management/head_management_macros.rs @@ -398,4 +398,5 @@ declare_extensions! { mode_info_v1: ModeInfoV1, mode_setter_v1: ModeSetterV1, physical_display_info_v1: PhysicalDisplayInfoV1, + non_desktop_info_v1: NonDesktopInfoV1, } diff --git a/src/ifs/head_management/jay_head_ext.rs b/src/ifs/head_management/jay_head_ext.rs index ac41e1c7..2a43ac31 100644 --- a/src/ifs/head_management/jay_head_ext.rs +++ b/src/ifs/head_management/jay_head_ext.rs @@ -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; diff --git a/src/ifs/head_management/jay_head_ext/jay_head_ext_non_desktop_info_v1.rs b/src/ifs/head_management/jay_head_ext/jay_head_ext_non_desktop_info_v1.rs new file mode 100644 index 00000000..7c4d5dbd --- /dev/null +++ b/src/ifs/head_management/jay_head_ext/jay_head_ext_non_desktop_info_v1.rs @@ -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!(); diff --git a/src/ifs/head_management/jay_head_ext/jay_head_ext_physical_display_info_v1.rs b/src/ifs/head_management/jay_head_ext/jay_head_ext_physical_display_info_v1.rs index f927259f..0c1fff34 100644 --- a/src/ifs/head_management/jay_head_ext/jay_head_ext_physical_display_info_v1.rs +++ b/src/ifs/head_management/jay_head_ext/jay_head_ext_physical_display_info_v1.rs @@ -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 { 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 ecd51f3b..b9f24195 100644 --- a/src/ifs/head_management/jay_head_manager_session_v1.rs +++ b/src/ifs/head_management/jay_head_manager_session_v1.rs @@ -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(()) diff --git a/src/ifs/wp_drm_lease_device_v1.rs b/src/ifs/wp_drm_lease_device_v1.rs index 315610d5..fba54909 100644 --- a/src/ifs/wp_drm_lease_device_v1.rs +++ b/src/ifs/wp_drm_lease_device_v1.rs @@ -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); } diff --git a/src/it/test_backend.rs b/src/it/test_backend.rs index e755f151..161cc532 100644 --- a/src/it/test_backend.rs +++ b/src/it/test_backend.rs @@ -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![], diff --git a/src/it/tests/t0034_workspace_restoration.rs b/src/it/tests/t0034_workspace_restoration.rs index 97e63050..9adf3192 100644 --- a/src/it/tests/t0034_workspace_restoration.rs +++ b/src/it/tests/t0034_workspace_restoration.rs @@ -47,6 +47,7 @@ async fn test(run: Rc) -> TestResult { width_mm: 0, height_mm: 0, non_desktop: false, + non_desktop_effective: false, vrr_capable: false, transfer_functions: vec![], color_spaces: vec![], diff --git a/src/state.rs b/src/state.rs index 1e79ca79..f54fe3e9 100644 --- a/src/state.rs +++ b/src/state.rs @@ -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 { diff --git a/src/tasks/connector.rs b/src/tasks/connector.rs index b453da99..5891835f 100644 --- a/src/tasks/connector.rs +++ b/src/tasks/connector.rs @@ -57,6 +57,8 @@ pub fn handle(state: &Rc, connector: &Rc) { 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; diff --git a/wire/jay_head_ext_non_desktop_info_v1.txt b/wire/jay_head_ext_non_desktop_info_v1.txt new file mode 100644 index 00000000..8cb9d98a --- /dev/null +++ b/wire/jay_head_ext_non_desktop_info_v1.txt @@ -0,0 +1,31 @@ +request destroy (destructor) { + +} + +event reset { + +} + +event inherent_desktop { + +} + +event inherent_non_desktop { + +} + +event override_desktop { + +} + +event override_non_desktop { + +} + +event effective_desktop { + +} + +event effective_non_desktop { + +} diff --git a/wire/jay_head_manager_ext_non_desktop_info_v1.txt b/wire/jay_head_manager_ext_non_desktop_info_v1.txt new file mode 100644 index 00000000..f1f9d8d3 --- /dev/null +++ b/wire/jay_head_manager_ext_non_desktop_info_v1.txt @@ -0,0 +1,7 @@ +request destroy (destructor) { + +} + +event head { + head: id(jay_head_ext_non_desktop_info_v1) (new), +}