use std::{env, fmt};
use anyhow::Result;
use clap::ValueEnum;
use log::debug;
use crate::Scene;
mod niri;
pub trait SceneReader {
fn scene(&self) -> Result<Scene>;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum Compositor {
Niri,
Sway,
Hyprland,
Mango,
}
impl Compositor {
const fn env_var(self) -> &'static str {
match self {
Self::Niri => "NIRI_SOCKET",
Self::Sway => "SWAYSOCK",
Self::Hyprland => "HYPRLAND_INSTANCE_SIGNATURE",
Self::Mango => "MANGO_INSTANCE_SIGNATURE",
}
}
#[must_use]
pub fn detect() -> Option<Self> {
for backend in Self::value_variants() {
if env::var_os(backend.env_var()).is_some() {
debug!("env {} matched {backend}", backend.env_var());
return Some(*backend);
}
}
env::var("XDG_CURRENT_DESKTOP").ok().and_then(|desktop| {
desktop
.split(':')
.find_map(|name| Self::from_str(name, true).ok())
})
}
pub fn connect(self) -> Result<Box<dyn SceneReader>> {
match self {
Self::Niri => Ok(Box::new(niri::Niri::connect()?)),
other => unimplemented!("the `{other}` compositor is not implemented yet"),
}
}
}
impl fmt::Display for Compositor {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(self.to_possible_value().unwrap().get_name())
}
}