diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2023-10-09 18:37:43 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2023-10-09 18:37:43 +0400 |
| commit | 189d1bd97b7aa241b5ad651145ca4d3ef483f505 (patch) | |
| tree | dc48204a57c51c6ec57de7d174d60b972b16e39c /src/backend | |
| parent | d91d5d674c5b456d25f2e865b28d99aa57f4db4f (diff) | |
| download | niri-189d1bd97b7aa241b5ad651145ca4d3ef483f505.tar.gz niri-189d1bd97b7aa241b5ad651145ca4d3ef483f505.tar.bz2 niri-189d1bd97b7aa241b5ad651145ca4d3ef483f505.zip | |
Add power-off-monitors bind
Implements https://github.com/YaLTeR/niri/issues/24
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/mod.rs | 7 | ||||
| -rw-r--r-- | src/backend/tty.rs | 48 |
2 files changed, 53 insertions, 2 deletions
diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 0c27abd6..64b1b5da 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -109,6 +109,13 @@ impl Backend { } } + pub fn set_monitors_active(&self, active: bool) { + match self { + Backend::Tty(tty) => tty.set_monitors_active(active), + Backend::Winit(_) => (), + } + } + pub fn tty(&mut self) -> &mut Tty { if let Self::Tty(v) = self { v diff --git a/src/backend/tty.rs b/src/backend/tty.rs index f6a40500..403f31ab 100644 --- a/src/backend/tty.rs +++ b/src/backend/tty.rs @@ -26,7 +26,7 @@ use smithay::output::{Mode, Output, OutputModeSource, PhysicalProperties, Subpix use smithay::reexports::calloop::timer::{Timer, TimeoutAction}; use smithay::reexports::calloop::{Dispatcher, LoopHandle, RegistrationToken}; use smithay::reexports::drm::control::{ - connector, crtc, Mode as DrmMode, ModeFlags, ModeTypeFlags, + connector, crtc, Mode as DrmMode, ModeFlags, ModeTypeFlags, Device, property, }; use smithay::reexports::input::Libinput; use smithay::reexports::nix::fcntl::OFlag; @@ -612,7 +612,12 @@ impl Tty { assert!(res.is_none(), "crtc must not have already existed"); niri.add_output(output.clone(), Some(refresh_interval(*mode))); - niri.queue_redraw(output); + + // Power on all monitors if necessary and queue a redraw on the new one. + niri.event_loop.insert_idle(move |state| { + state.niri.activate_monitors(&state.backend); + state.niri.queue_redraw(output); + }); Ok(()) } @@ -956,6 +961,45 @@ impl Tty { device.drm.is_active() } + + pub fn set_monitors_active(&self, active: bool) { + let Some(device) = &self.output_device else { + return; + }; + + for crtc in device.surfaces.keys() { + set_crtc_active(&device.drm, *crtc, active); + } + } +} + +fn find_drm_property(drm: &DrmDevice, crtc: crtc::Handle, name: &str) -> Option<property::Handle> { + let props = match drm.get_properties(crtc) { + Ok(props) => props, + Err(err) => { + warn!("error getting CRTC properties: {err:?}"); + return None; + } + }; + + let (handles, _) = props.as_props_and_values(); + handles.iter().find_map(|handle| { + let info = drm.get_property(*handle).ok()?; + let n = info.name().to_str().ok()?; + + (n == name).then_some(*handle) + }) +} + +fn set_crtc_active(drm: &DrmDevice, crtc: crtc::Handle, active: bool) { + let Some(prop) = find_drm_property(drm, crtc, "ACTIVE") else { + return; + }; + + let value = property::Value::Boolean(active); + if let Err(err) = drm.set_property(crtc, prop, value.into()) { + warn!("error setting CRTC property: {err:?}"); + } } fn refresh_interval(mode: DrmMode) -> Duration { |
