diff options
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/mod.rs | 9 | ||||
| -rw-r--r-- | src/backend/tty.rs | 77 | ||||
| -rw-r--r-- | src/backend/winit.rs | 29 |
3 files changed, 106 insertions, 9 deletions
diff --git a/src/backend/mod.rs b/src/backend/mod.rs index a273f769..595b8513 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -1,4 +1,6 @@ +use std::cell::RefCell; use std::collections::HashMap; +use std::rc::Rc; use std::sync::{Arc, Mutex}; use std::time::Duration; @@ -110,6 +112,13 @@ impl Backend { } } + pub fn ipc_outputs(&self) -> Rc<RefCell<HashMap<String, niri_ipc::Output>>> { + match self { + Backend::Tty(tty) => tty.ipc_outputs(), + Backend::Winit(winit) => winit.ipc_outputs(), + } + } + #[cfg_attr(not(feature = "dbus"), allow(unused))] pub fn enabled_outputs(&self) -> Arc<Mutex<HashMap<String, Output>>> { match self { diff --git a/src/backend/tty.rs b/src/backend/tty.rs index 0dacf9b7..f86851cb 100644 --- a/src/backend/tty.rs +++ b/src/backend/tty.rs @@ -74,6 +74,7 @@ pub struct Tty { // The allocator for the primary GPU. It is only `Some()` if we have a device corresponding to // the primary GPU. primary_allocator: Option<DmabufAllocator<GbmAllocator<DrmDeviceFd>>>, + ipc_outputs: Rc<RefCell<HashMap<String, niri_ipc::Output>>>, enabled_outputs: Arc<Mutex<HashMap<String, Output>>>, } @@ -221,6 +222,7 @@ impl Tty { devices: HashMap::new(), dmabuf_global: None, primary_allocator: None, + ipc_outputs: Rc::new(RefCell::new(HashMap::new())), enabled_outputs: Arc::new(Mutex::new(HashMap::new())), } } @@ -367,6 +369,8 @@ impl Tty { warn!("error adding device: {err:?}"); } } + + self.refresh_ipc_outputs(); } } } @@ -512,6 +516,8 @@ impl Tty { _ => (), } } + + self.refresh_ipc_outputs(); } fn device_removed(&mut self, device_id: dev_t, niri: &mut Niri) { @@ -576,6 +582,8 @@ impl Tty { self.gpu_manager.as_mut().remove_node(&device.render_node); niri.event_loop.remove(device.token); + + self.refresh_ipc_outputs(); } fn connector_connected( @@ -608,16 +616,7 @@ impl Tty { let device = self.devices.get_mut(&node).context("missing device")?; - // FIXME: print modes here until we have a better way to list all modes. for m in connector.modes() { - let wl_mode = Mode::from(*m); - debug!( - "mode: {}x{}@{:.3}", - m.size().0, - m.size().1, - wl_mode.refresh as f64 / 1000., - ); - trace!("{m:?}"); } @@ -1157,6 +1156,64 @@ impl Tty { } } + fn refresh_ipc_outputs(&self) { + let _span = tracy_client::span!("Tty::refresh_ipc_outputs"); + + let mut ipc_outputs = HashMap::new(); + + for device in self.devices.values() { + for (connector, crtc) in device.drm_scanner.crtcs() { + let connector_name = format!( + "{}-{}", + connector.interface().as_str(), + connector.interface_id(), + ); + + let physical_size = connector.size(); + + let (make, model) = EdidInfo::for_connector(&device.drm, connector.handle()) + .map(|info| (info.manufacturer, info.model)) + .unwrap_or_else(|| ("Unknown".into(), "Unknown".into())); + + let modes = connector + .modes() + .iter() + .map(|m| niri_ipc::Mode { + width: m.size().0, + height: m.size().1, + refresh_rate: Mode::from(*m).refresh as u32, + }) + .collect(); + + let mut output = niri_ipc::Output { + name: connector_name.clone(), + make, + model, + physical_size, + modes, + current_mode: None, + }; + + if let Some(surface) = device.surfaces.get(&crtc) { + let current = surface.compositor.pending_mode(); + if let Some(current) = connector.modes().iter().position(|m| *m == current) { + output.current_mode = Some(current); + } else { + error!("connector mode list missing current mode"); + } + } + + ipc_outputs.insert(connector_name, output); + } + } + + self.ipc_outputs.replace(ipc_outputs); + } + + pub fn ipc_outputs(&self) -> Rc<RefCell<HashMap<String, niri_ipc::Output>>> { + self.ipc_outputs.clone() + } + pub fn enabled_outputs(&self) -> Arc<Mutex<HashMap<String, Output>>> { self.enabled_outputs.clone() } @@ -1305,6 +1362,8 @@ impl Tty { warn!("error connecting connector: {err:?}"); } } + + self.refresh_ipc_outputs(); } } diff --git a/src/backend/winit.rs b/src/backend/winit.rs index 9b31d2c5..3c4b9ad3 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -28,6 +28,7 @@ pub struct Winit { output: Output, backend: WinitGraphicsBackend<GlesRenderer>, damage_tracker: OutputDamageTracker, + ipc_outputs: Rc<RefCell<HashMap<String, niri_ipc::Output>>>, enabled_outputs: Arc<Mutex<HashMap<String, Output>>>, } @@ -56,6 +57,23 @@ impl Winit { output.change_current_state(Some(mode), Some(Transform::Flipped180), None, None); output.set_preferred(mode); + let physical_properties = output.physical_properties(); + let ipc_outputs = Rc::new(RefCell::new(HashMap::from([( + "winit".to_owned(), + niri_ipc::Output { + name: output.name(), + make: physical_properties.make, + model: physical_properties.model, + physical_size: None, + modes: vec![niri_ipc::Mode { + width: backend.window_size().w.clamp(0, u16::MAX as i32) as u16, + height: backend.window_size().h.clamp(0, u16::MAX as i32) as u16, + refresh_rate: 60_000, + }], + current_mode: Some(0), + }, + )]))); + let enabled_outputs = Arc::new(Mutex::new(HashMap::from([( "winit".to_owned(), output.clone(), @@ -76,6 +94,12 @@ impl Winit { None, None, ); + + let mut ipc_outputs = winit.ipc_outputs.borrow_mut(); + let mode = &mut ipc_outputs.get_mut("winit").unwrap().modes[0]; + mode.width = size.w.clamp(0, u16::MAX as i32) as u16; + mode.height = size.h.clamp(0, u16::MAX as i32) as u16; + state.niri.output_resized(winit.output.clone()); } WinitEvent::Input(event) => state.process_input_event(event), @@ -95,6 +119,7 @@ impl Winit { output, backend, damage_tracker, + ipc_outputs, enabled_outputs, } } @@ -198,6 +223,10 @@ impl Winit { } } + pub fn ipc_outputs(&self) -> Rc<RefCell<HashMap<String, niri_ipc::Output>>> { + self.ipc_outputs.clone() + } + pub fn enabled_outputs(&self) -> Arc<Mutex<HashMap<String, Output>>> { self.enabled_outputs.clone() } |
