#![deny(missing_docs)]
use core::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub enum DesktopEnvironment {
Cinnamon,
Cosmic,
CosmicEpoch,
Dde,
Ede,
Endless,
Enlightenment,
Gnome,
Hyprland,
Kde,
Lxde,
Lxqt,
MacOs,
Mate,
Old,
Pantheon,
Razor,
Rox,
Sway,
Tde,
Unity,
Windows,
Xfce,
}
impl DesktopEnvironment {
pub fn detect() -> Option<Self> {
Self::detect_impl()
}
pub const fn gtk(self) -> bool {
use DesktopEnvironment::*;
matches!(
self,
Cinnamon | Cosmic | Dde | Gnome | Lxde | Mate | Pantheon | Unity | Xfce
)
}
pub const fn qt(self) -> bool {
use DesktopEnvironment::*;
matches!(self, Kde | Lxqt | Razor | Tde)
}
#[cfg(target_os = "macos")]
fn detect_impl() -> Option<Self> {
Some(DesktopEnvironment::MacOs)
}
#[cfg(target_os = "windows")]
fn detect_impl() -> Option<Self> {
Some(DesktopEnvironment::Windows)
}
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
fn detect_impl() -> Option<Self> {
std::env::var("XDG_CURRENT_DESKTOP")
.ok()
.as_deref()
.and_then(Self::from_xdg_current_desktop)
}
pub fn from_freedesktop(name: &str) -> Option<Self> {
match name {
"COSMIC" => Some(DesktopEnvironment::CosmicEpoch),
"GNOME" => Some(DesktopEnvironment::Gnome),
"GNOME-Classic" => Some(DesktopEnvironment::Gnome),
"GNOME-Flashback" => Some(DesktopEnvironment::Gnome),
"KDE" => Some(DesktopEnvironment::Kde),
"LXDE" => Some(DesktopEnvironment::Lxde),
"LXQt" => Some(DesktopEnvironment::Lxqt),
"MATE" => Some(DesktopEnvironment::Mate),
"Razor" => Some(DesktopEnvironment::Razor),
"ROX" => Some(DesktopEnvironment::Rox),
"TDE" => Some(DesktopEnvironment::Tde),
"Unity" => Some(DesktopEnvironment::Unity),
"XFCE" => Some(DesktopEnvironment::Xfce),
"EDE" => Some(DesktopEnvironment::Ede),
"Cinnamon" => Some(DesktopEnvironment::Cinnamon),
"Pantheon" => Some(DesktopEnvironment::Pantheon),
"DDE" => Some(DesktopEnvironment::Dde),
"Endless" => Some(DesktopEnvironment::Endless),
"Old" => Some(DesktopEnvironment::Old),
_ => None,
}
}
pub fn from_xdg_name(name: &str) -> Option<Self> {
if let Some(de) = Self::from_freedesktop(name) {
return Some(de);
}
match name {
"ENLIGHTENMENT" => Some(DesktopEnvironment::Enlightenment),
"Hyprland" => Some(DesktopEnvironment::Hyprland),
"SWAY" | "sway" => Some(DesktopEnvironment::Sway),
"X-Cinnamon" => Some(DesktopEnvironment::Cinnamon),
_ => None,
}
}
pub fn from_xdg_current_desktop(xdg_current_desktop: &str) -> Option<Self> {
let mut resolved: Option<DesktopEnvironment> = None;
for part in xdg_current_desktop.split(':') {
let de = match Self::from_xdg_name(part) {
Some(de) => de,
None => {
continue;
}
};
match resolved {
None => {
resolved = Some(de)
}
Some(prev) => {
if de != prev {
return None;
}
}
}
}
resolved
}
}
impl fmt::Display for DesktopEnvironment {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Cinnamon => write!(f, "Cinnamon"),
Self::Cosmic => write!(f, "COSMIC"),
Self::CosmicEpoch => write!(f, "COSMIC Epoch"),
Self::Dde => write!(f, "Deepin"),
Self::Ede => write!(f, "EDE"),
Self::Endless => write!(f, "Endless"),
Self::Enlightenment => write!(f, "Enlightenment"),
Self::Gnome => write!(f, "GNOME"),
Self::Hyprland => write!(f, "Hyprland"),
Self::Kde => write!(f, "KDE Plasma"),
Self::Lxde => write!(f, "LXDE"),
Self::Lxqt => write!(f, "LXQt"),
Self::MacOs => write!(f, "macOS"),
Self::Mate => write!(f, "MATE"),
Self::Old => write!(f, "Old"),
Self::Pantheon => write!(f, "Pantheon"),
Self::Razor => write!(f, "Razor"),
Self::Rox => write!(f, "ROX"),
Self::Sway => write!(f, "Sway"),
Self::Tde => write!(f, "TDE"),
Self::Unity => write!(f, "Unity"),
Self::Windows => write!(f, "Windows"),
Self::Xfce => write!(f, "Xfce"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn linux_tests() {
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("Cinnamon"),
Some(DesktopEnvironment::Cinnamon)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("ENLIGHTENMENT"),
Some(DesktopEnvironment::Enlightenment)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("GNOME"),
Some(DesktopEnvironment::Gnome)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("KDE"),
Some(DesktopEnvironment::Kde)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("LXDE"),
Some(DesktopEnvironment::Lxde)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("LXQt"),
Some(DesktopEnvironment::Lxqt)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("MATE"),
Some(DesktopEnvironment::Mate)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("Unity"),
Some(DesktopEnvironment::Unity)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("X-Cinnamon"),
Some(DesktopEnvironment::Cinnamon)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("XFCE"),
Some(DesktopEnvironment::Xfce)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("TDE"),
Some(DesktopEnvironment::Tde)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("DDE"),
Some(DesktopEnvironment::Dde)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("Pantheon"),
Some(DesktopEnvironment::Pantheon)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("SWAY"),
Some(DesktopEnvironment::Sway)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("Hyprland"),
Some(DesktopEnvironment::Hyprland)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("COSMIC"),
Some(DesktopEnvironment::CosmicEpoch)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("ubuntu:GNOME"),
Some(DesktopEnvironment::Gnome)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("ubuntu:KDE"),
Some(DesktopEnvironment::Kde)
);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("pop:GNOME"),
Some(DesktopEnvironment::Gnome)
);
assert_eq!(DesktopEnvironment::from_xdg_current_desktop("KDE:GNOME"), None);
assert_eq!(DesktopEnvironment::from_xdg_current_desktop("ubuntu:KDE:GNOME"), None);
assert_eq!(
DesktopEnvironment::from_xdg_current_desktop("GNOME:GNOME"),
Some(DesktopEnvironment::Gnome)
);
assert_eq!(DesktopEnvironment::from_xdg_current_desktop(""), None);
assert_eq!(DesktopEnvironment::from_xdg_current_desktop("foo"), None);
}
}