diff --git a/src/cli.rs b/src/cli.rs index e3d8d74a..0b715bbb 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -3,6 +3,7 @@ mod color; mod color_management; mod config; mod damage_tracking; +mod dpms; mod duration; mod generate; mod idle; @@ -85,6 +86,8 @@ pub enum Cmd { Screenshot(ScreenshotArgs), /// Inspect/modify the idle (screensaver) settings. Idle(IdleArgs), + /// Turn monitors on or off. + Dpms(DpmsArgs), /// Run a privileged program. RunPrivileged(RunPrivilegedArgs), /// Run a program with a connection tag. @@ -131,6 +134,19 @@ pub struct IdleArgs { pub command: Option, } +#[derive(Args, Debug)] +pub struct DpmsArgs { + /// Whether monitors should be on or off. + #[clap(value_enum)] + pub state: DpmsState, +} + +#[derive(ValueEnum, Debug, Copy, Clone, Eq, PartialEq)] +pub enum DpmsState { + On, + Off, +} + #[derive(Args, Debug)] pub struct RunPrivilegedArgs { /// The program to run @@ -250,6 +266,7 @@ pub fn main() { Cmd::SetLogLevel(a) => set_log_level::main(cli.global, a), Cmd::Screenshot(a) => screenshot::main(cli.global, a), Cmd::Idle(a) => idle::main(cli.global, a), + Cmd::Dpms(a) => dpms::main(cli.global, a), Cmd::Unlock => unlock::main(cli.global), Cmd::RunPrivileged(a) => run_privileged::main(cli.global, a), Cmd::RunTagged(a) => run_tagged::main(cli.global, a), diff --git a/src/cli/dpms.rs b/src/cli/dpms.rs new file mode 100644 index 00000000..ec8fe577 --- /dev/null +++ b/src/cli/dpms.rs @@ -0,0 +1,23 @@ +use { + crate::{ + cli::{DpmsArgs, DpmsState, GlobalArgs}, + tools::tool_client::{ToolClient, with_tool_client}, + wire::jay_compositor::SetDpms, + }, + std::rc::Rc, +}; + +pub fn main(global: GlobalArgs, args: DpmsArgs) { + with_tool_client(global.log_level, |tc| async move { + run(tc, args).await; + }); +} + +async fn run(tc: Rc, args: DpmsArgs) { + let comp = tc.jay_compositor().await; + tc.send(SetDpms { + self_id: comp, + active: (args.state == DpmsState::On) as u32, + }); + tc.round_trip().await; +} diff --git a/src/ifs/jay_compositor.rs b/src/ifs/jay_compositor.rs index 4373125e..4abf04c3 100644 --- a/src/ifs/jay_compositor.rs +++ b/src/ifs/jay_compositor.rs @@ -1,5 +1,6 @@ use { crate::{ + backend::transaction::BackendConnectorTransactionError, client::{CAP_JAY_COMPOSITOR, Client, ClientCaps, ClientError, ClientId}, compositor::LogLevel, globals::{Global, GlobalName}, @@ -78,7 +79,7 @@ global_base!(JayCompositorGlobal, JayCompositor, JayCompositorError); impl Global for JayCompositorGlobal { fn version(&self) -> u32 { - 30 + 31 } fn required_caps(&self) -> ClientCaps { @@ -542,6 +543,14 @@ impl JayCompositorRequestHandler for JayCompositor { }); Ok(()) } + + fn set_dpms(&self, req: SetDpms, _slf: &Rc) -> Result<(), Self::Error> { + self.client + .state + .set_connectors_active(req.active != 0) + .map_err(JayCompositorError::SetDpms)?; + Ok(()) + } } object_base! { @@ -559,5 +568,7 @@ pub enum JayCompositorError { ClientError(Box), #[error("Unknown log level {0}")] UnknownLogLevel(u32), + #[error("Could not set DPMS state")] + SetDpms(#[source] BackendConnectorTransactionError), } efrom!(JayCompositorError, ClientError); diff --git a/src/state.rs b/src/state.rs index 4ae761a0..9349bbc7 100644 --- a/src/state.rs +++ b/src/state.rs @@ -7,7 +7,8 @@ use { Backend, BackendConnectorState, BackendConnectorStateSerials, BackendDrmDevice, BackendEvent, Connector, ConnectorId, ConnectorIds, DrmDeviceId, DrmDeviceIds, HardwareCursorUpdate, InputDevice, InputDeviceGroupIds, InputDeviceId, InputDeviceIds, - MonitorInfo, transaction::BackendConnectorTransactionError, + MonitorInfo, + transaction::{BackendConnectorTransactionError, ConnectorTransaction}, }, backends::dummy::DummyBackend, cli::RunArgs, @@ -1404,6 +1405,21 @@ impl State { } } + pub fn set_connectors_active( + self: &Rc, + active: bool, + ) -> Result<(), BackendConnectorTransactionError> { + let mut tran = ConnectorTransaction::new(self); + for connector in self.connectors.lock().values() { + let mut state = connector.state.borrow().clone(); + state.active = active; + tran.add(&connector.connector, state)?; + } + tran.prepare()?.apply()?.commit(); + self.set_backend_idle(!active); + Ok(()) + } + pub fn root_visible(&self) -> bool { !self.idle.backend_idle.get() } diff --git a/src/tasks/idle.rs b/src/tasks/idle.rs index 5561a263..228f2a33 100644 --- a/src/tasks/idle.rs +++ b/src/tasks/idle.rs @@ -1,6 +1,6 @@ use { crate::{ - backend::transaction::{BackendConnectorTransactionError, ConnectorTransaction}, + backend::transaction::BackendConnectorTransactionError, state::State, utils::{ errorfmt::ErrorFmt, @@ -136,15 +136,7 @@ impl Idle { } fn try_set_idle(&self, idle: bool) -> Result<(), BackendConnectorTransactionError> { - let mut tran = ConnectorTransaction::new(&self.state); - for connector in self.state.connectors.lock().values() { - let mut state = connector.state.borrow().clone(); - state.active = !idle; - tran.add(&connector.connector, state)?; - } - tran.prepare()?.apply()?.commit(); - self.state.set_backend_idle(idle); - Ok(()) + self.state.set_connectors_active(!idle) } } diff --git a/src/tools/tool_client.rs b/src/tools/tool_client.rs index 3cb77655..b62ce0b7 100644 --- a/src/tools/tool_client.rs +++ b/src/tools/tool_client.rs @@ -330,7 +330,7 @@ impl ToolClient { self_id: s.registry, name: s.jay_compositor.0, interface: JayCompositor.name(), - version: s.jay_compositor.1.min(30), + version: s.jay_compositor.1.min(31), id: id.into(), }); self.jay_compositor.set(Some(id)); diff --git a/wire/jay_compositor.txt b/wire/jay_compositor.txt index 019f9ea3..f22805d1 100644 --- a/wire/jay_compositor.txt +++ b/wire/jay_compositor.txt @@ -135,6 +135,10 @@ request get_pid (since = 27) { } +request set_dpms (since = 31) { + active: u32, +} + # events event client_id {