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