Skip to content

Commit

Permalink
WIP DPMS with wlr-output-power-management-unstable-v1 protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
ids1024 committed Aug 26, 2024
1 parent 8114116 commit c788cad
Show file tree
Hide file tree
Showing 10 changed files with 201 additions and 3 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ zbus = "4.4.0"
profiling = { version = "1.0" }
rustix = { version = "0.38.32", features = ["process"] }
smallvec = "1.13.2"
drm-ffi = "0.8.0"

[dependencies.id_tree]
branch = "feature/copy_clone"
Expand Down
14 changes: 14 additions & 0 deletions src/backend/kms/drm_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,3 +421,17 @@ pub fn set_max_bpc(dev: &impl ControlDevice, conn: connector::Handle, bpc: u32)
_ => unreachable!(),
})
}

pub fn set_dpms(dev: &impl ControlDevice, conn: connector::Handle, on: bool) -> Result<()> {
dev.set_property(
conn,
get_prop(dev, conn, "DPMS")?,
property::Value::UnsignedRange(if on {
drm_ffi::DRM_MODE_DPMS_ON.into()
} else {
drm_ffi::DRM_MODE_DPMS_OFF.into()
})
.into(),
)?;
Ok(())
}
2 changes: 1 addition & 1 deletion src/backend/kms/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use std::{
};

mod device;
mod drm_helpers;
pub(crate) mod drm_helpers;
pub mod render;
mod socket;
mod surface;
Expand Down
4 changes: 2 additions & 2 deletions src/backend/kms/surface/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ static NVIDIA_LOGO: &'static [u8] = include_bytes!("../../../../resources/icons/

#[derive(Debug)]
pub struct Surface {
pub(super) connector: connector::Handle,
pub(crate) connector: connector::Handle,
pub(super) crtc: crtc::Handle,
pub(super) output: Output,
pub(crate) output: Output,
known_nodes: HashSet<DrmNode>,

active: Arc<AtomicBool>,
Expand Down
2 changes: 2 additions & 0 deletions src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::{
drm::WlDrmState,
image_source::ImageSourceState,
output_configuration::OutputConfigurationState,
output_power::OutputPowerState,
screencopy::ScreencopyState,
toplevel_info::ToplevelInfoState,
toplevel_management::{ManagementCapabilities, ToplevelManagementState},
Expand Down Expand Up @@ -490,6 +491,7 @@ impl State {
let keyboard_shortcuts_inhibit_state = KeyboardShortcutsInhibitState::new::<Self>(dh);
let output_state = OutputManagerState::new_with_xdg_output::<Self>(dh);
let output_configuration_state = OutputConfigurationState::new(dh, client_is_privileged);
OutputPowerState::new::<Self, _>(dh, client_is_privileged);
let presentation_state = PresentationState::new::<Self>(dh, clock.id() as u32);
let primary_selection_state = PrimarySelectionState::new::<Self>(dh);
let image_source_state = ImageSourceState::new::<Self, _>(dh, client_is_privileged);
Expand Down
1 change: 1 addition & 0 deletions src/wayland/handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub mod keyboard_shortcuts_inhibit;
pub mod layer_shell;
pub mod output;
pub mod output_configuration;
pub mod output_power;
pub mod pointer_constraints;
pub mod pointer_gestures;
pub mod presentation;
Expand Down
27 changes: 27 additions & 0 deletions src/wayland/handlers/output_power.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-3.0-only

use smithay::{output::Output, reexports::wayland_server::protocol::wl_output::WlOutput};

use crate::{
backend::kms::drm_helpers,
state::{BackendData, State},
wayland::protocols::output_power::{delegate_output_power, OutputPowerHandler},
};

impl OutputPowerHandler for State {
fn set_dpms(&mut self, wl_output: &WlOutput, on: bool) {
if let Some(output) = Output::from_resource(wl_output) {
if let BackendData::Kms(ref mut kms_state) = &mut self.backend {
for (_, device) in &mut kms_state.drm_devices {
for (_, surface) in &mut device.surfaces {
if surface.output == output {
drm_helpers::set_dpms(&device.drm, surface.connector, on);
}
}
}
}
}
}
}

delegate_output_power!(State);
1 change: 1 addition & 0 deletions src/wayland/protocols/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pub mod drm;
pub mod image_source;
pub mod output_configuration;
pub mod output_power;
pub mod screencopy;
pub mod toplevel_info;
pub mod toplevel_management;
Expand Down
151 changes: 151 additions & 0 deletions src/wayland/protocols/output_power.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// SPDX-License-Identifier: GPL-3.0-only

use smithay::reexports::{
wayland_protocols_wlr::output_power_management::v1::server::{
zwlr_output_power_manager_v1::{self, ZwlrOutputPowerManagerV1},
zwlr_output_power_v1::{self, ZwlrOutputPowerV1},
},
wayland_server::{
backend::GlobalId, protocol::wl_output::WlOutput, Client, DataInit, Dispatch,
DisplayHandle, GlobalDispatch, New, Resource, Weak,
},
};
use wayland_backend::protocol::WEnum;

pub trait OutputPowerHandler {
fn set_dpms(&mut self, output: &WlOutput, on: bool);
}

pub struct OutputPowerState {
global: GlobalId,
}

impl OutputPowerState {
pub fn new<D, F>(dh: &DisplayHandle, client_filter: F) -> OutputPowerState
where
D: GlobalDispatch<ZwlrOutputPowerManagerV1, OutputPowerManagerGlobalData> + 'static,
F: for<'a> Fn(&'a Client) -> bool + Clone + Send + Sync + 'static,
{
let global = dh.create_global::<D, ZwlrOutputPowerManagerV1, _>(
1,
OutputPowerManagerGlobalData {
filter: Box::new(client_filter.clone()),
},
);

OutputPowerState { global }
}

pub fn send_dpms(&self, _on: bool) {
// TODO
}
}

pub struct OutputPowerManagerGlobalData {
filter: Box<dyn for<'a> Fn(&'a Client) -> bool + Send + Sync>,
}

pub struct OutputPowerData {
output: Weak<WlOutput>,
}

impl<D> GlobalDispatch<ZwlrOutputPowerManagerV1, OutputPowerManagerGlobalData, D>
for OutputPowerState
where
D: GlobalDispatch<ZwlrOutputPowerManagerV1, OutputPowerManagerGlobalData>
+ Dispatch<ZwlrOutputPowerManagerV1, ()>
+ 'static,
{
fn bind(
_state: &mut D,
_dh: &DisplayHandle,
_client: &Client,
resource: New<ZwlrOutputPowerManagerV1>,
_global_data: &OutputPowerManagerGlobalData,
data_init: &mut DataInit<'_, D>,
) {
data_init.init(resource, ());
}

fn can_view(client: Client, global_data: &OutputPowerManagerGlobalData) -> bool {
(global_data.filter)(&client)
}
}

impl<D> Dispatch<ZwlrOutputPowerManagerV1, (), D> for OutputPowerState
where
D: GlobalDispatch<ZwlrOutputPowerManagerV1, OutputPowerManagerGlobalData>
+ Dispatch<ZwlrOutputPowerManagerV1, ()>
+ Dispatch<ZwlrOutputPowerV1, OutputPowerData>
+ 'static,
{
fn request(
_state: &mut D,
_client: &Client,
_obj: &ZwlrOutputPowerManagerV1,
request: zwlr_output_power_manager_v1::Request,
_data: &(),
_dh: &DisplayHandle,
data_init: &mut DataInit<'_, D>,
) {
match request {
zwlr_output_power_manager_v1::Request::GetOutputPower { id, output } => {
data_init.init(
id,
OutputPowerData {
output: output.downgrade(),
},
);
}
zwlr_output_power_manager_v1::Request::Destroy => {}
_ => unreachable!(),
}
}
}

impl<D> Dispatch<ZwlrOutputPowerV1, OutputPowerData, D> for OutputPowerState
where
D: Dispatch<ZwlrOutputPowerV1, OutputPowerData> + OutputPowerHandler + 'static,
{
fn request(
state: &mut D,
_client: &Client,
_obj: &ZwlrOutputPowerV1,
request: zwlr_output_power_v1::Request,
data: &OutputPowerData,
_dh: &DisplayHandle,
_data_init: &mut DataInit<'_, D>,
) {
match request {
zwlr_output_power_v1::Request::SetMode { mode } => {
if let Ok(output) = data.output.upgrade() {
let on = match mode {
WEnum::Value(zwlr_output_power_v1::Mode::On) => true,
WEnum::Value(zwlr_output_power_v1::Mode::Off) => false,
_ => {
return;
}
};
state.set_dpms(&output, on);
}
}
zwlr_output_power_v1::Request::Destroy => {}
_ => unreachable!(),
}
}
}

macro_rules! delegate_output_power {
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
smithay::reexports::wayland_protocols_wlr::output_power_management::v1::server::zwlr_output_power_manager_v1::ZwlrOutputPowerManagerV1: $crate::wayland::protocols::output_power::OutputPowerManagerGlobalData
] => $crate::wayland::protocols::output_power::OutputPowerState);
smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
smithay::reexports::wayland_protocols_wlr::output_power_management::v1::server::zwlr_output_power_manager_v1::ZwlrOutputPowerManagerV1: ()
] => $crate::wayland::protocols::output_power::OutputPowerState);
smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
smithay::reexports::wayland_protocols_wlr::output_power_management::v1::server::zwlr_output_power_v1::ZwlrOutputPowerV1: $crate::wayland::protocols::output_power::OutputPowerData
] => $crate::wayland::protocols::output_power::OutputPowerState);
};
}
pub(crate) use delegate_output_power;

0 comments on commit c788cad

Please sign in to comment.