leenfetch_core/modules/linux/desktop/
de.rs1use std::env;
2use std::process::Command;
3
4pub fn get_de(show_version: bool, wm: Option<&str>) -> Option<String> {
5 let mut de = detect_de_env().or_else(detect_de_fallback)?;
6
7 if let Some(wm_name) = wm {
9 if de.eq_ignore_ascii_case(wm_name) {
10 return None;
11 }
12 }
13
14 normalize_de_name(&mut de);
15
16 if show_version {
18 if let Some(ver) = get_de_version(&de) {
19 de = format!("{} {}", de, ver);
20 }
21 }
22
23 if env::var_os("WAYLAND_DISPLAY").is_some() {
25 de.push_str(" (Wayland)");
26 }
27
28 Some(de)
29}
30
31fn detect_de_env() -> Option<String> {
33 if let Some(val) = env::var_os("DESKTOP_SESSION") {
34 let val_str = val.to_string_lossy();
35 return Some(if val_str.contains("regolith") {
36 "Regolith".into()
37 } else {
38 val_str.into()
39 });
40 }
41
42 if let Some(val) = env::var_os("XDG_CURRENT_DESKTOP") {
43 let val_str = val
44 .to_string_lossy()
45 .replace("X-", "")
46 .replace("Budgie:GNOME", "Budgie");
47 return Some(val_str);
48 }
49
50 None
51}
52
53fn detect_de_fallback() -> Option<String> {
55 if env::var_os("GNOME_DESKTOP_SESSION_ID").is_some() {
56 return Some("GNOME".into());
57 }
58 if env::var_os("MATE_DESKTOP_SESSION_ID").is_some() {
59 return Some("MATE".into());
60 }
61 if env::var_os("TDE_FULL_SESSION").is_some() {
62 return Some("Trinity".into());
63 }
64
65 if env::var_os("DISPLAY").is_some() && is_installed("xprop") {
67 let output = run_command("xprop", &["-root"])?;
68 if output.contains("KDE_SESSION_VERSION") {
69 return Some("KDE".into());
70 }
71 if output.contains("_MUFFIN") {
72 return Some("Cinnamon".into());
73 }
74 if output.contains("xfce") {
75 return Some("Xfce".into());
76 }
77 }
78
79 None
80}
81
82fn normalize_de_name(de: &mut String) {
84 let lower = de.to_lowercase();
85 *de = match lower.as_str() {
86 s if s.contains("xfce4") => "Xfce4",
87 s if s.contains("xfce5") => "Xfce5",
88 s if s.contains("xfce") => "Xfce",
89 s if s.contains("mate") => "MATE",
90 s if s.contains("gnome") => "GNOME",
91 s if s.contains("muffin") => "Cinnamon",
92 s if s.contains("budgie") => "Budgie",
93 s if s.contains("lxqt") => "LXQt",
94 s if s.contains("plasma") || s.contains("kde") => "Plasma",
95 s if s.contains("unity") => "Unity",
96 _ => de.as_str(),
97 }
98 .to_string();
99}
100
101fn is_installed(cmd: &str) -> bool {
102 Command::new("which")
103 .arg(cmd)
104 .output()
105 .map(|o| o.status.success())
106 .unwrap_or(false)
107}
108
109fn run_command(cmd: &str, args: &[&str]) -> Option<String> {
110 Command::new(cmd)
111 .args(args)
112 .output()
113 .ok()
114 .filter(|o| o.status.success())
115 .map(|o| String::from_utf8_lossy(&o.stdout).to_string())
116}
117
118fn get_de_version(de: &str) -> Option<String> {
119 match de {
120 "Plasma" => parse_version("plasmashell", &["--version"]),
121 "MATE" => parse_version("mate-session", &["--version"]),
122 "Xfce" | "Xfce4" => parse_version("xfce4-session", &["--version"]),
123 "GNOME" => parse_version("gnome-shell", &["--version"]),
124 "Cinnamon" => parse_version("cinnamon", &["--version"]),
125 "Budgie" => parse_version("budgie-desktop", &["--version"]),
126 "LXQt" => parse_version("lxqt-session", &["--version"]),
127 "Lumina" => parse_version("lumina-desktop", &["--version"]),
128 "Trinity" => parse_version("tde-config", &["--version"]),
129 "Unity" => parse_version("unity", &["--version"]),
130 _ => None,
131 }
132}
133
134fn parse_version(cmd: &str, args: &[&str]) -> Option<String> {
135 run_command(cmd, args).and_then(|out| {
136 out.lines().rev().find_map(|line| {
137 line.split_whitespace()
138 .find(|s| {
139 s.chars()
140 .next()
141 .map(|c| c.is_ascii_digit())
142 .unwrap_or(false)
143 })
144 .map(|s| s.to_string())
145 })
146 })
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152 use crate::test_utils::EnvLock;
153
154 fn clear_env() -> EnvLock {
155 let vars = [
156 "DESKTOP_SESSION",
157 "XDG_CURRENT_DESKTOP",
158 "GNOME_DESKTOP_SESSION_ID",
159 "MATE_DESKTOP_SESSION_ID",
160 "TDE_FULL_SESSION",
161 "WAYLAND_DISPLAY",
162 "DISPLAY",
163 ];
164 let env_lock = EnvLock::acquire(&vars);
165 for var in vars {
166 env_lock.remove_var(var);
167 }
168 env_lock
169 }
170
171 #[test]
220 fn excludes_wm_that_matches_de() {
221 let env_lock = clear_env();
222 env_lock.set_var("DESKTOP_SESSION", "sway");
223 let result = get_de(false, Some("sway"));
224 assert_eq!(result, None);
225 drop(env_lock);
226 }
227
228 #[test]
238 fn normalize_de_variants() {
239 let mut de = "xfce".to_string();
240 normalize_de_name(&mut de);
241 assert_eq!(de, "Xfce");
242
243 let mut de = "Xfce4".to_string();
244 normalize_de_name(&mut de);
245 assert_eq!(de, "Xfce4");
246
247 let mut de = "mate".to_string();
248 normalize_de_name(&mut de);
249 assert_eq!(de, "MATE");
250
251 let mut de = "gnome".to_string();
252 normalize_de_name(&mut de);
253 assert_eq!(de, "GNOME");
254
255 let mut de = "lxqt".to_string();
256 normalize_de_name(&mut de);
257 assert_eq!(de, "LXQt");
258
259 let mut de = "plasma-kde".to_string();
260 normalize_de_name(&mut de);
261 assert_eq!(de, "Plasma");
262 }
263}