theme_detector/
gtk.rs

1// SPDX-FileCopyrightText: 2023 CELESTIFYX Team
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4use crate::{
5    constants::{
6        DE_GNOME,
7        DE_GNOME_CLASSIC,
8        DE_XFCE4,
9        DE_CINNAMON,
10        DE_MATE,
11        DE_BUDGIE,
12        DE_UNITY
13    },
14
15    properties::{
16        parse_prop_file_values,
17        get_config_dirs
18    },
19
20    settings::{
21        Variant,
22
23        get_xfconf,
24        get_xfconf_first_match,
25        get_gnome_setting
26    }
27};
28
29#[derive(Default)]
30pub struct GtkResult {
31    pub theme:       String,
32    pub icons:       String,
33    pub font:        String,
34    pub cursor:      String,
35    pub cursor_size: String,
36    pub wallpaper:   String
37}
38
39impl GtkResult {
40    fn all_set(&self) -> bool {
41        !self.theme.is_empty() && !self.icons.is_empty() && !self.font.is_empty()
42    }
43}
44
45fn detect_gtk_from_settings(de_name: &str) -> GtkResult {
46    let mut result: GtkResult = GtkResult::default();
47
48    if de_name.eq_ignore_ascii_case(DE_XFCE4) {
49        if let Some(theme) = get_xfconf("xsettings", "/Net/ThemeName").as_str() {
50            (&mut result).theme = theme.to_string();
51        }
52
53        if let Some(icons) = get_xfconf("xsettings", "/Net/IconThemeName").as_str() {
54            (&mut result).icons = icons.to_string();
55        }
56
57        if let Some(font) = get_xfconf("xsettings", "/Gtk/FontName").as_str() {
58            (&mut result).font = font.to_string();
59        }
60
61        if let Some(cursor) = get_xfconf("xsettings", "/Gtk/CursorThemeName").as_str() {
62            (&mut result).cursor = cursor.to_string();
63        }
64
65        if let Some(size) = get_xfconf("xsettings", "/Gtk/CursorThemeSize").as_int() {
66            (&mut result).cursor_size = size.to_string();
67        }
68
69        let wallpaper: Variant = get_xfconf_first_match("xfce4-desktop", "/backdrop/screen0", |prop: &str| {
70            prop.contains("/workspace0/last-image")
71        });
72
73        if let Some(wp) = wallpaper.as_str() {
74            (&mut result).wallpaper = wp.to_string();
75        }
76    } else if de_name.eq_ignore_ascii_case(DE_CINNAMON) {
77        if let Some(theme) = get_gnome_setting("/org/cinnamon/desktop/interface/gtk-theme", "org.cinnamon.desktop.interface", None, "gtk-theme").as_str() {
78            (&mut result).theme = theme.to_string();
79        }
80
81        if let Some(icons) = get_gnome_setting("/org/cinnamon/desktop/interface/icon-theme", "org.cinnamon.desktop.interface", None, "icon-theme").as_str() {
82            (&mut result).icons = icons.to_string();
83        }
84
85        if let Some(font) = get_gnome_setting("/org/cinnamon/desktop/interface/font-name", "org.cinnamon.desktop.interface", None, "font-name").as_str() {
86            (&mut result).font = font.to_string();
87        }
88
89        if let Some(cursor) = get_gnome_setting("/org/cinnamon/desktop/interface/cursor-theme", "org.cinnamon.desktop.interface", None, "cursor-theme").as_str() {
90            (&mut result).cursor = cursor.to_string();
91        }
92
93        if let Some(size) = get_gnome_setting("/org/cinnamon/desktop/interface/cursor-size", "org.cinnamon.desktop.interface", None, "cursor-size").as_int() {
94            (&mut result).cursor_size = size.to_string();
95        }
96
97        if let Some(wp) = get_gnome_setting("/org/cinnamon/desktop/background/picture-uri", "org.cinnamon.desktop.background", None, "picture-uri").as_str() {
98            (&mut result).wallpaper = wp.to_string();
99        }
100    } else if de_name.eq_ignore_ascii_case(DE_MATE) {
101        if let Some(theme) = get_gnome_setting("/org/mate/interface/gtk-theme", "org.mate.interface", None, "gtk-theme").as_str() {
102            (&mut result).theme = theme.to_string();
103        }
104
105        if let Some(icons) = get_gnome_setting("/org/mate/interface/icon-theme", "org.mate.interface", None, "icon-theme").as_str() {
106            (&mut result).icons = icons.to_string();
107        }
108
109        if let Some(font) = get_gnome_setting("/org/mate/interface/font-name", "org.mate.interface", None, "font-name").as_str() {
110            (&mut result).font = font.to_string();
111        }
112
113        if let Some(cursor) = get_gnome_setting("/org/mate/peripherals-mouse/cursor-theme", "org.mate.peripherals-mouse", None, "cursor-theme").as_str() {
114            (&mut result).cursor = cursor.to_string();
115        }
116
117        if let Some(size) = get_gnome_setting("/org/mate/peripherals-mouse/cursor-size", "org.mate.peripherals-mouse", None, "cursor-size").as_int() {
118            (&mut result).cursor_size = size.to_string();
119        }
120
121        if let Some(wp) = get_gnome_setting("/org/mate/desktop/background", "org.mate.background", None, "picture-filename").as_str() {
122            (&mut result).wallpaper = wp.to_string();
123        }
124    } else if de_name.eq_ignore_ascii_case(DE_GNOME) || de_name.eq_ignore_ascii_case(DE_GNOME_CLASSIC) || de_name.eq_ignore_ascii_case(DE_UNITY) || de_name.eq_ignore_ascii_case(DE_BUDGIE) {
125        if let Some(theme) = get_gnome_setting("/org/gnome/desktop/interface/gtk-theme", "org.gnome.desktop.interface", None, "gtk-theme").as_str() {
126            (&mut result).theme = theme.to_string();
127        }
128
129        if let Some(icons) = get_gnome_setting("/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", None, "icon-theme").as_str() {
130            (&mut result).icons = icons.to_string();
131        }
132
133        if let Some(font) = get_gnome_setting("/org/gnome/desktop/interface/font-name", "org.gnome.desktop.interface", None, "font-name").as_str() {
134            (&mut result).font = font.to_string();
135        }
136
137        if let Some(cursor) = get_gnome_setting("/org/gnome/desktop/interface/cursor-theme", "org.gnome.desktop.interface", None, "cursor-theme").as_str() {
138            (&mut result).cursor = cursor.to_string();
139        }
140
141        if let Some(size) = get_gnome_setting("/org/gnome/desktop/interface/cursor-size", "org.gnome.desktop.interface", None, "cursor-size").as_int() {
142            (&mut result).cursor_size = size.to_string();
143        }
144
145        if let Some(wp) = get_gnome_setting("/org/gnome/desktop/background/picture-uri", "org.gnome.desktop.background", None, "picture-uri").as_str() {
146            (&mut result).wallpaper = wp.to_string();
147        }
148    }
149
150    result
151}
152
153fn detect_gtk_from_config_file(filename: &str, result: &mut GtkResult) -> () {
154    let mut queries: Vec<(&str, String)> = vec![
155        ("gtk-theme-name =",        String::new()),
156        ("gtk-icon-theme-name =",   String::new()),
157        ("gtk-font-name =",         String::new()),
158        ("gtk-cursor-theme-name =", String::new()),
159        ("gtk-cursor-theme-size =", String::new())
160    ];
161
162    if parse_prop_file_values(filename, &mut queries) {
163        if result.theme.is_empty() && !queries[0].1.is_empty() {
164            result.theme = queries[0].1.clone();
165        }
166
167        if result.icons.is_empty() && !queries[1].1.is_empty() {
168            result.icons = queries[1].1.clone();
169        }
170
171        if result.font.is_empty() && !queries[2].1.is_empty() {
172            result.font = queries[2].1.clone();
173        }
174
175        if result.cursor.is_empty() && !queries[3].1.is_empty() {
176            result.cursor = queries[3].1.clone();
177        }
178
179        if result.cursor_size.is_empty() && !queries[4].1.is_empty() {
180            result.cursor_size = queries[4].1.clone();
181        }
182    }
183}
184
185fn detect_gtk_from_config_dir(config_dir: &str, version: &str, result: &mut GtkResult) -> () {
186    let files: [String; 4] = [
187        format!("{}gtk-{}.0/settings.ini", config_dir, version),
188        format!("{}gtk-{}.0/gtkrc",        config_dir, version),
189        format!("{}gtkrc-{}.0",            config_dir, version),
190        format!("{}.gtkrc-{}.0",           config_dir, version)
191    ];
192
193    for file in &files {
194        detect_gtk_from_config_file(file, result);
195
196        if result.all_set() {
197            return;
198        }
199    }
200}
201
202fn detect_gtk_impl(version: &str, de_name: Option<&str>) -> GtkResult {
203    let mut result: GtkResult = if let Some(de) = de_name {
204        detect_gtk_from_settings(de)
205    } else {
206        GtkResult::default()
207    };
208
209    if result.all_set() {
210        return result;
211    }
212
213    let config_dirs: Vec<String> = get_config_dirs();
214
215    for config_dir in &config_dirs {
216        detect_gtk_from_config_dir(config_dir, version, &mut result);
217
218        if result.all_set() {
219            break;
220        }
221    }
222
223    result
224}
225
226pub fn detect_gtk2(de_name: Option<&str>) -> GtkResult {
227    detect_gtk_impl("2", de_name)
228}
229
230pub fn detect_gtk3(de_name: Option<&str>) -> GtkResult {
231    detect_gtk_impl("3", de_name)
232}
233
234pub fn detect_gtk4(de_name: Option<&str>) -> GtkResult {
235    detect_gtk_impl("4", de_name)
236}