diff options
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/mod.rs | 18 | ||||
| -rw-r--r-- | src/backend/tty.rs | 36 | ||||
| -rw-r--r-- | src/backend/winit.rs | 6 |
3 files changed, 52 insertions, 8 deletions
diff --git a/src/backend/mod.rs b/src/backend/mod.rs index ccdda34d..c5662184 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -9,6 +9,7 @@ use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; use crate::input::CompositorMod; use crate::niri::Niri; +use crate::utils::id::IdCounter; pub mod tty; pub use tty::Tty; @@ -31,7 +32,22 @@ pub enum RenderResult { Skipped, } -pub type IpcOutputMap = HashMap<String, niri_ipc::Output>; +pub type IpcOutputMap = HashMap<OutputId, niri_ipc::Output>; + +static OUTPUT_ID_COUNTER: IdCounter = IdCounter::new(); + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct OutputId(u32); + +impl OutputId { + fn next() -> OutputId { + OutputId(OUTPUT_ID_COUNTER.next()) + } + + pub fn get(self) -> u32 { + self.0 + } +} impl Backend { pub fn init(&mut self, niri: &mut Niri) { diff --git a/src/backend/tty.rs b/src/backend/tty.rs index 54fc97c1..cb04c717 100644 --- a/src/backend/tty.rs +++ b/src/backend/tty.rs @@ -57,6 +57,7 @@ use wayland_protocols::wp::linux_dmabuf::zv1::server::zwp_linux_dmabuf_feedback_ use wayland_protocols::wp::presentation_time::server::wp_presentation_feedback; use super::{IpcOutputMap, RenderResult}; +use crate::backend::OutputId; use crate::frame_clock::FrameClock; use crate::niri::{Niri, RedrawState, State}; use crate::render_helpers::debug::draw_damage; @@ -118,6 +119,7 @@ pub struct OutputDevice { render_node: DrmNode, drm_scanner: DrmScanner, surfaces: HashMap<crtc::Handle, Surface>, + output_ids: HashMap<crtc::Handle, OutputId>, // SAFETY: drop after all the objects used with them are dropped. // See https://github.com/Smithay/smithay/issues/1102. drm: DrmDevice, @@ -575,6 +577,7 @@ impl Tty { gbm, drm_scanner: DrmScanner::new(), surfaces: HashMap::new(), + output_ids: HashMap::new(), drm_lease_state, active_leases: Vec::new(), non_desktop_connectors: HashSet::new(), @@ -599,6 +602,7 @@ impl Tty { return; }; + let mut removed = Vec::new(); for event in device.drm_scanner.scan_connectors(&device.drm) { match event { DrmScanEvent::Connected { @@ -611,11 +615,27 @@ impl Tty { } DrmScanEvent::Disconnected { crtc: Some(crtc), .. - } => self.connector_disconnected(niri, node, crtc), + } => { + self.connector_disconnected(niri, node, crtc); + removed.push(crtc); + } _ => (), } } + // FIXME: this is better done in connector_disconnected(), but currently we call that to + // turn off outputs temporarily, too. So we can't do this there. + let Some(device) = self.devices.get_mut(&node) else { + error!("device disappeared"); + return; + }; + + for crtc in removed { + if device.output_ids.remove(&crtc).is_none() { + error!("output ID missing for disconnected crtc: {crtc:?}"); + } + } + self.refresh_ipc_outputs(niri); } @@ -724,6 +744,10 @@ impl Tty { return Ok(()); } + // This should be unique per CRTC connection, however currently we can call + // connector_connected() multiple times for turning the output off and on. + device.output_ids.entry(crtc).or_insert_with(OutputId::next); + let config = self .config .borrow() @@ -1464,7 +1488,7 @@ impl Tty { for (node, device) in &self.devices { for (connector, crtc) in device.drm_scanner.crtcs() { - let connector_name = format!( + let name = format!( "{}-{}", connector.interface().as_str(), connector.interface_id(), @@ -1527,7 +1551,7 @@ impl Tty { .map(logical_output); let ipc_output = niri_ipc::Output { - name: connector_name.clone(), + name, make, model, physical_size, @@ -1538,7 +1562,11 @@ impl Tty { logical, }; - ipc_outputs.insert(connector_name, ipc_output); + let id = device.output_ids.get(&crtc).copied().unwrap_or_else(|| { + error!("output ID missing for crtc: {crtc:?}"); + OutputId::next() + }); + ipc_outputs.insert(id, ipc_output); } } diff --git a/src/backend/winit.rs b/src/backend/winit.rs index 677cb10c..61744e5e 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -17,7 +17,7 @@ use smithay::reexports::wayland_protocols::wp::presentation_time::server::wp_pre use smithay::reexports::winit::dpi::LogicalSize; use smithay::reexports::winit::window::Window; -use super::{IpcOutputMap, RenderResult}; +use super::{IpcOutputMap, OutputId, RenderResult}; use crate::niri::{Niri, RedrawState, State}; use crate::render_helpers::debug::draw_damage; use crate::render_helpers::{resources, shaders, RenderTarget}; @@ -61,7 +61,7 @@ impl Winit { let physical_properties = output.physical_properties(); let ipc_outputs = Arc::new(Mutex::new(HashMap::from([( - "winit".to_owned(), + OutputId::next(), niri_ipc::Output { name: output.name(), make: physical_properties.make, @@ -98,7 +98,7 @@ impl Winit { { let mut ipc_outputs = winit.ipc_outputs.lock().unwrap(); - let output = ipc_outputs.get_mut("winit").unwrap(); + let output = ipc_outputs.values_mut().next().unwrap(); let mode = &mut output.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; |
