From 1f18b461359edb5f36b3378d1b88c4c1cab6a06b Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Thu, 25 Apr 2024 18:39:29 +0200 Subject: [PATCH] cli: allow overriding non-desktop setting --- src/backend.rs | 3 +++ src/backends/metal/video.rs | 43 +++++++++++++++++++++++++++++++------ src/cli/randr.rs | 27 ++++++++++++++++++++++- src/ifs/jay_randr.rs | 13 +++++++++++ wire/jay_randr.txt | 5 +++++ 5 files changed, 84 insertions(+), 7 deletions(-) diff --git a/src/backend.rs b/src/backend.rs index a6a122e9..406d3ab6 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -91,6 +91,9 @@ pub trait Connector { None } fn set_mode(&self, mode: Mode); + fn set_non_desktop_override(&self, non_desktop: Option) { + let _ = non_desktop; + } } #[derive(Debug)] diff --git a/src/backends/metal/video.rs b/src/backends/metal/video.rs index 6f9991ad..6b7637c7 100644 --- a/src/backends/metal/video.rs +++ b/src/backends/metal/video.rs @@ -173,6 +173,7 @@ pub struct ConnectorDisplayData { pub mode: Option, pub refresh: u32, pub non_desktop: bool, + pub non_desktop_effective: bool, pub monitor_manufacturer: String, pub monitor_name: String, @@ -209,6 +210,7 @@ pub struct MetalConnector { pub next_buffer: NumCell, pub enabled: Cell, + pub non_desktop_override: Cell>, pub can_present: Cell, pub has_damage: Cell, @@ -907,7 +909,7 @@ impl Connector for MetalConnector { fn set_mode(&self, be_mode: Mode) { let mut dd = self.display.borrow_mut(); - if dd.non_desktop { + if dd.non_desktop_effective { return; } let Some(mode) = dd.modes.iter().find(|m| m.to_backend() == be_mode) else { @@ -945,6 +947,25 @@ impl Connector for MetalConnector { log::warn!("Could not restore the previous mode: {}", ErrorFmt(e)); }; } + + fn set_non_desktop_override(&self, non_desktop: Option) { + if self.non_desktop_override.replace(non_desktop) == non_desktop { + return; + } + let mut dd = self.display.borrow_mut(); + let non_desktop_effective = non_desktop.unwrap_or(dd.non_desktop); + if dd.non_desktop_effective == non_desktop_effective { + return; + } + dd.non_desktop_effective = non_desktop_effective; + drop(dd); + if let Some(dev) = self.backend.device_holder.drm_devices.get(&self.dev.devnum) { + if let Err(e) = self.backend.handle_drm_change_(&dev, true) { + dev.unprocessed_change.set(true); + log::error!("Could not override non-desktop setting: {}", ErrorFmt(e)); + } + } + } } pub struct MetalCrtc { @@ -1052,7 +1073,7 @@ fn create_connector( connector: DrmConnector, dev: &Rc, ) -> Result<(Rc, ConnectorFutures), DrmError> { - let display = create_connector_display_data(connector, dev)?; + let display = create_connector_display_data(connector, dev, None)?; let slf = Rc::new(MetalConnector { id: connector, master: dev.master.clone(), @@ -1063,6 +1084,7 @@ fn create_connector( buffers: Default::default(), next_buffer: Default::default(), enabled: Cell::new(true), + non_desktop_override: Default::default(), can_present: Cell::new(true), has_damage: Cell::new(true), primary_plane: Default::default(), @@ -1100,6 +1122,7 @@ fn create_connector( fn create_connector_display_data( connector: DrmConnector, dev: &Rc, + non_desktop_override: Option, ) -> Result { let info = dev.master.get_connector_info(connector, true)?; let mut crtcs = AHashMap::new(); @@ -1186,13 +1209,15 @@ fn create_connector_display_data( } let props = collect_properties(&dev.master, connector)?; let connector_type = ConnectorType::from_drm(info.connector_type); + let non_desktop = props.get("non-desktop")?.value.get() != 0; Ok(ConnectorDisplayData { crtc_id: props.get("CRTC_ID")?.map(|v| DrmCrtc(v as _)), crtcs, modes: info.modes, mode, refresh, - non_desktop: props.get("non-desktop")?.value.get() != 0, + non_desktop, + non_desktop_effective: non_desktop_override.unwrap_or(non_desktop), monitor_manufacturer: manufacturer, monitor_name: name, monitor_serial_number: serial_number, @@ -1486,7 +1511,8 @@ impl MetalBackend { } let mut preserve = Preserve::default(); for c in dev.connectors.lock().values() { - let mut dd = match create_connector_display_data(c.id, &dev.dev) { + let dd = create_connector_display_data(c.id, &dev.dev, c.non_desktop_override.get()); + let mut dd = match dd { Ok(d) => d, Err(e) => { log::error!( @@ -1509,6 +1535,7 @@ impl MetalBackend { if !c.enabled.get() || old.connection != ConnectorStatus::Connected || !old.is_same_monitor(&dd) + || c.primary_plane.is_none() != old.non_desktop_effective { c.on_change.send_event(ConnectorEvent::Disconnected); c.connect_sent.set(false); @@ -1562,7 +1589,7 @@ impl MetalBackend { initial_mode: dd.mode.clone().unwrap().to_backend(), width_mm: dd.mm_width as _, height_mm: dd.mm_height as _, - non_desktop: dd.non_desktop, + non_desktop: dd.non_desktop_effective, })); connector.connect_sent.set(true); connector.send_hardware_cursor(); @@ -1857,6 +1884,8 @@ impl MetalBackend { if preserve.connectors.contains(&connector.id) { continue; } + connector.buffers.set(None); + connector.cursor_buffers.set(None); connector.primary_plane.set(None); connector.cursor_plane.set(None); connector.cursor_enabled.set(false); @@ -2528,5 +2557,7 @@ fn modes_equal(a: &DrmModeInfo, b: &DrmModeInfo) -> bool { } fn should_ignore(connector: &MetalConnector, dd: &ConnectorDisplayData) -> bool { - !connector.enabled.get() || dd.connection != ConnectorStatus::Connected || dd.non_desktop + !connector.enabled.get() + || dd.connection != ConnectorStatus::Connected + || dd.non_desktop_effective } diff --git a/src/cli/randr.rs b/src/cli/randr.rs index 63db0fba..f627bd83 100644 --- a/src/cli/randr.rs +++ b/src/cli/randr.rs @@ -6,7 +6,7 @@ use { utils::transform_ext::TransformExt, wire::{jay_compositor, jay_randr, JayRandrId}, }, - clap::{Args, Subcommand}, + clap::{Args, Subcommand, ValueEnum}, isnt::std_1::vec::IsntVecExt, jay_config::video::Transform, std::{ @@ -115,6 +115,21 @@ pub enum OutputCommand { Enable, /// Disable the output. Disable, + /// Override the display's non-desktop setting. + NonDesktop(NonDesktopArgs), +} + +#[derive(ValueEnum, Debug, Clone)] +pub enum NonDesktopType { + Default, + False, + True, +} + +#[derive(Args, Debug, Clone)] +pub struct NonDesktopArgs { + /// Whether this output is a non-desktop output. + pub setting: NonDesktopType, } #[derive(Args, Debug, Clone)] @@ -374,6 +389,16 @@ impl Randr { enabled: enable as _, }); } + OutputCommand::NonDesktop(a) => { + self.handle_error(randr, move |msg| { + eprintln!("Could not change the non-desktop setting: {}", msg); + }); + tc.send(jay_randr::SetNonDesktop { + self_id: randr, + output: &args.output, + non_desktop: a.setting as _, + }); + } } tc.round_trip().await; } diff --git a/src/ifs/jay_randr.rs b/src/ifs/jay_randr.rs index 5c70fd88..e6c975fa 100644 --- a/src/ifs/jay_randr.rs +++ b/src/ifs/jay_randr.rs @@ -284,6 +284,19 @@ impl JayRandrRequestHandler for JayRandr { c.connector.set_enabled(req.enabled != 0); Ok(()) } + + fn set_non_desktop(&self, req: SetNonDesktop<'_>, _slf: &Rc) -> Result<(), Self::Error> { + let Some(c) = self.get_connector(req.output) else { + return Ok(()); + }; + let non_desktop = match req.non_desktop { + 0 => None, + 1 => Some(false), + _ => Some(true), + }; + c.connector.set_non_desktop_override(non_desktop); + Ok(()) + } } object_base! { diff --git a/wire/jay_randr.txt b/wire/jay_randr.txt index 0792f380..96ab32ed 100644 --- a/wire/jay_randr.txt +++ b/wire/jay_randr.txt @@ -50,6 +50,11 @@ request set_enabled { enabled: u32, } +request set_non_desktop { + output: str, + non_desktop: u32, +} + # events event global {