Skip to main content

Mountain/IPC/WindServiceHandlers/NativeHost/
GetColorScheme.rs

1#![allow(non_snake_case, unused_variables, dead_code, unused_imports)]
2
3//! Wire method: `nativeHost:getColorScheme`.
4//! Returns `{ dark, highContrast }`. Dark-mode probe covers macOS
5//! `AppleInterfaceStyle`, Windows `AppsUseLightTheme`, and a Linux ladder
6//! (GTK color-scheme → GTK theme name → `KDE_COLOR_SCHEME` → xfconf).
7//! High-contrast probe is Windows `HighContrast/Flags` and the GNOME a11y
8//! `high-contrast` key; other OSes return false.
9
10use serde_json::{Value, json};
11
12pub async fn NativeGetColorScheme() -> Result<Value, String> {
13	let Dark = detect_dark_mode();
14
15	let HighContrast = {
16		#[cfg(target_os = "windows")]
17		{
18			std::process::Command::new("reg")
19				.args(["query", "HKCU\\Control Panel\\Accessibility\\HighContrast", "/v", "Flags"])
20				.output()
21				.ok()
22				.map(|O| {
23					let Output = String::from_utf8_lossy(&O.stdout);
24					Output.contains("0x1") || Output.contains("REG_DWORD    1")
25				})
26				.unwrap_or(false)
27		}
28
29		#[cfg(not(target_os = "windows"))]
30		{
31			#[cfg(target_os = "linux")]
32			{
33				std::process::Command::new("gsettings")
34					.args(["get", "org.gnome.desktop.a11y.interface", "high-contrast"])
35					.output()
36					.ok()
37					.map(|O| String::from_utf8_lossy(&O.stdout).trim() == "true")
38					.unwrap_or(false)
39			}
40
41			#[cfg(not(target_os = "linux"))]
42			{
43				false
44			}
45		}
46	};
47
48	Ok(json!({ "dark": Dark, "highContrast": HighContrast }))
49}
50
51fn detect_dark_mode() -> bool {
52	#[cfg(target_os = "macos")]
53	{
54		std::process::Command::new("defaults")
55			.args(["read", "-g", "AppleInterfaceStyle"])
56			.output()
57			.ok()
58			.map(|O| String::from_utf8_lossy(&O.stdout).trim().to_lowercase().contains("dark"))
59			.unwrap_or(false)
60	}
61
62	#[cfg(target_os = "windows")]
63	{
64		std::process::Command::new("reg")
65			.args([
66				"query",
67				"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
68				"/v",
69				"AppsUseLightTheme",
70			])
71			.output()
72			.ok()
73			.map(|O| {
74				let Output = String::from_utf8_lossy(&O.stdout);
75				Output.contains("0x0") || Output.contains("REG_DWORD    0")
76			})
77			.unwrap_or(false)
78	}
79
80	#[cfg(target_os = "linux")]
81	{
82		let GtkDark = std::process::Command::new("gsettings")
83			.args(["get", "org.gnome.desktop.interface", "color-scheme"])
84			.output()
85			.ok()
86			.map(|O| String::from_utf8_lossy(&O.stdout).contains("dark"))
87			.unwrap_or(false);
88
89		if GtkDark {
90			return true;
91		}
92
93		let GtkTheme = std::process::Command::new("gsettings")
94			.args(["get", "org.gnome.desktop.interface", "gtk-theme"])
95			.output()
96			.ok()
97			.map(|O| String::from_utf8_lossy(&O.stdout).to_lowercase().contains("dark"))
98			.unwrap_or(false);
99
100		if GtkTheme {
101			return true;
102		}
103
104		let KdeDark = std::env::var("KDE_COLOR_SCHEME")
105			.ok()
106			.map(|V| V.to_lowercase().contains("dark"))
107			.unwrap_or(false);
108
109		if KdeDark {
110			return true;
111		}
112
113		let XfceDark = std::process::Command::new("xfconf-query")
114			.args(["-c", "xsettings", "-p", "/Net/ThemeName"])
115			.output()
116			.ok()
117			.map(|O| String::from_utf8_lossy(&O.stdout).to_lowercase().contains("dark"))
118			.unwrap_or(false);
119
120		XfceDark
121	}
122
123	#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))]
124	{
125		false
126	}
127}