Commit | Line | Data |
---|---|---|
0cd84ed6 | 1 | /* |
3a7d812e | 2 | * lxappearance.c |
0cd84ed6 HJYP |
3 | * |
4 | * Copyright 2010 PCMan <pcman.tw@gmail.com> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program; if not, write to the Free Software | |
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | |
19 | * MA 02110-1301, USA. | |
20 | */ | |
21 | ||
22 | #ifdef HAVE_CONFIG_H | |
23 | #include <config.h> | |
24 | #endif | |
25 | ||
3a7d812e | 26 | #include "lxappearance.h" |
15c155a6 | 27 | |
0cd84ed6 HJYP |
28 | #include <gtk/gtk.h> |
29 | #include <glib/gi18n.h> | |
fb28c6fe | 30 | #include <glib/gstdio.h> |
15c155a6 HJYP |
31 | |
32 | #include <X11/X.h> | |
33 | #include <X11/Xatom.h> | |
34 | #include <X11/Xlib.h> | |
35 | #include <gdk/gdkx.h> | |
ae63f687 | 36 | #include <string.h> |
15c155a6 | 37 | |
c847cfdc | 38 | #if ENABLE_DBUS |
924e9daf | 39 | #include <dbus/dbus.h> |
c847cfdc | 40 | #endif |
924e9daf | 41 | |
0cd84ed6 | 42 | #include "widget-theme.h" |
71ce58a7 | 43 | #include "color-scheme.h" |
0cd84ed6 HJYP |
44 | #include "icon-theme.h" |
45 | #include "cursor-theme.h" | |
2d9128f0 | 46 | #include "font.h" |
e597424e | 47 | #include "other.h" |
756f0a66 | 48 | #include "plugin.h" |
0cd84ed6 | 49 | |
15c155a6 HJYP |
50 | LXAppearance app = {0}; |
51 | ||
52 | Atom lxsession_atom = 0; | |
ae63f687 | 53 | static const char* lxsession_name = NULL; |
15c155a6 | 54 | |
924e9daf JL |
55 | /* Dbus functions Copy from lxsession-logout |
56 | TODO Create a library fro this ? | |
57 | */ | |
58 | ||
59 | static gboolean check_lxde_dbus() | |
60 | { | |
c847cfdc | 61 | #if ENABLE_DBUS |
924e9daf JL |
62 | DBusError error; |
63 | dbus_error_init(&error); | |
64 | DBusConnection * connection = dbus_bus_get(DBUS_BUS_SESSION, &error); | |
65 | if (connection == NULL) | |
66 | { | |
67 | g_warning(G_STRLOC ": Failed to connect to the session message bus: %s", error.message); | |
68 | dbus_error_free(&error); | |
69 | return FALSE; | |
70 | } | |
71 | ||
a50b8ed7 | 72 | dbus_bool_t ret = dbus_bus_name_has_owner(connection,"org.lxde.SessionManager",NULL); |
924e9daf | 73 | |
a50b8ed7 | 74 | if (ret == TRUE) |
924e9daf JL |
75 | { |
76 | return TRUE; | |
77 | } | |
78 | else | |
79 | { | |
80 | return FALSE; | |
81 | } | |
c847cfdc JL |
82 | #else |
83 | return FALSE; | |
84 | #endif | |
924e9daf JL |
85 | } |
86 | ||
15c155a6 HJYP |
87 | static void check_lxsession() |
88 | { | |
073c0729 | 89 | lxsession_atom = XInternAtom( GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), "_LXSESSION", True ); |
15c155a6 HJYP |
90 | if( lxsession_atom != None ) |
91 | { | |
073c0729 JL |
92 | XGrabServer( GDK_DISPLAY_XDISPLAY(gdk_display_get_default()) ); |
93 | if( XGetSelectionOwner( GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), lxsession_atom ) ) | |
ae63f687 | 94 | { |
15c155a6 | 95 | app.use_lxsession = TRUE; |
ae63f687 HJYP |
96 | lxsession_name = g_getenv("DESKTOP_SESSION"); |
97 | } | |
073c0729 | 98 | XUngrabServer( GDK_DISPLAY_XDISPLAY(gdk_display_get_default()) ); |
15c155a6 | 99 | } |
924e9daf JL |
100 | |
101 | /* Check Lxsession also with dbus */ | |
102 | if (check_lxde_dbus()) | |
103 | { | |
104 | app.use_lxsession = TRUE; | |
105 | lxsession_name = g_getenv("DESKTOP_SESSION"); | |
106 | } | |
107 | ||
15c155a6 HJYP |
108 | } |
109 | ||
0cd84ed6 HJYP |
110 | static GOptionEntry option_entries[] = |
111 | { | |
112 | { NULL } | |
113 | }; | |
114 | ||
fb28c6fe AG |
115 | static gboolean verify_cursor_theme(GKeyFile *kf, const char *cursor_theme, |
116 | const char *test) | |
117 | { | |
118 | char *fpath; | |
119 | gboolean ret; | |
120 | ||
121 | /* get the inherited theme name. */ | |
122 | fpath = g_build_filename(g_get_home_dir(), ".icons", cursor_theme, | |
123 | "index.theme", NULL); | |
124 | ret = g_key_file_load_from_file(kf, fpath, 0, NULL); | |
125 | g_free(fpath); | |
126 | ||
127 | fpath = g_build_filename("icons", cursor_theme, "index.theme", NULL); | |
128 | if (!ret) | |
129 | ret = g_key_file_load_from_data_dirs(kf, fpath, NULL, 0, NULL); | |
130 | g_free(fpath); | |
131 | ||
132 | if (ret) | |
133 | { | |
134 | fpath = g_key_file_get_string(kf, "Icon Theme", "Inherits", NULL); | |
135 | if (fpath == NULL) /* end of chain, success */ | |
136 | return TRUE; | |
137 | if (strcmp(fpath, test) == 0) /* recursion */ | |
138 | ret = FALSE; | |
139 | else if (!verify_cursor_theme(kf, fpath, test)) /* recursion */ | |
140 | ret = FALSE; | |
141 | else /* check recursion against this one too */ | |
142 | ret = verify_cursor_theme(kf, fpath, cursor_theme); | |
143 | g_free(fpath); | |
144 | } | |
145 | return ret; | |
146 | } | |
147 | ||
ae63f687 HJYP |
148 | static void save_cursor_theme_name() |
149 | { | |
150 | char* dir_path; | |
fb28c6fe AG |
151 | GKeyFile* kf; |
152 | ||
153 | if (app.cursor_theme == NULL || strcmp(app.cursor_theme, "default") == 0) | |
ae63f687 HJYP |
154 | return; |
155 | ||
156 | dir_path = g_build_filename(g_get_home_dir(), ".icons/default", NULL); | |
fb28c6fe AG |
157 | kf = g_key_file_new(); |
158 | /* test if cursor theme isn't recursed and don't use it otherwise */ | |
159 | if (!verify_cursor_theme(kf, app.cursor_theme, "default")) | |
160 | { | |
161 | g_free(app.cursor_theme); | |
162 | app.cursor_theme = NULL; /* FIXME: replace with "default"? */ | |
163 | /* FIXME: show an error message */ | |
164 | } | |
165 | /* SF bug #614: ~/.icons/default may be symlink so remove symlink */ | |
166 | else if (g_file_test(dir_path, G_FILE_TEST_IS_SYMLINK) && | |
167 | g_unlink(dir_path) != 0) | |
168 | { | |
169 | /* FIXME: show an error message */ | |
170 | } | |
171 | else if (0 == g_mkdir_with_parents(dir_path, 0700)) | |
ae63f687 HJYP |
172 | { |
173 | char* index_theme = g_build_filename(dir_path, "index.theme", NULL); | |
174 | char* content = g_strdup_printf( | |
fb28c6fe AG |
175 | "# This file is written by LXAppearance. Do not edit.\n" |
176 | "[Icon Theme]\n" | |
177 | "Name=Default\n" | |
178 | "Comment=Default Cursor Theme\n" | |
179 | "Inherits=%s\n", app.cursor_theme); | |
ae63f687 HJYP |
180 | g_file_set_contents(index_theme, content, -1, NULL); |
181 | g_free(content); | |
182 | g_free(index_theme); | |
183 | } | |
fb28c6fe | 184 | g_key_file_free(kf); |
ae63f687 HJYP |
185 | g_free(dir_path); |
186 | ||
187 | /* | |
188 | dir_path = g_build_filename(g_get_home_dir(), ".Xdefaults", NULL); | |
189 | Xcursor.theme: name | |
190 | Xcursor.size: [size] | |
191 | g_file_set_contents(dir_path, "", -1, NULL); | |
192 | g_free(dir_path); | |
193 | */ | |
194 | } | |
195 | ||
196 | static void reload_all_programs() | |
15c155a6 | 197 | { |
b4438824 JL |
198 | #if GTK_CHECK_VERSION(3, 0, 0) |
199 | ||
200 | /* TODO Port this to something else than gdk_event_send_clientmessage_toall */ | |
201 | ||
202 | #else | |
ae63f687 HJYP |
203 | GdkEventClient event; |
204 | event.type = GDK_CLIENT_EVENT; | |
205 | event.send_event = TRUE; | |
206 | event.window = NULL; | |
15c155a6 | 207 | |
ae63f687 HJYP |
208 | if( app.use_lxsession ) |
209 | { | |
210 | event.message_type = gdk_atom_intern_static_string("_LXSESSION"); | |
211 | event.data.b[0] = 0; /* LXS_RELOAD */ | |
212 | } | |
213 | else | |
214 | { | |
215 | /* if( icon_only ) | |
216 | event.message_type = gdk_atom_intern("_GTK_LOAD_ICONTHEMES", FALSE); | |
217 | */ | |
218 | event.message_type = gdk_atom_intern("_GTK_READ_RCFILES", FALSE); | |
219 | } | |
220 | event.data_format = 8; | |
221 | gdk_event_send_clientmessage_toall((GdkEvent *)&event); | |
b4438824 | 222 | #endif |
ae63f687 HJYP |
223 | } |
224 | ||
225 | static void lxappearance_save_gtkrc() | |
226 | { | |
227 | static const char* tb_styles[]={ | |
228 | "GTK_TOOLBAR_ICONS", | |
229 | "GTK_TOOLBAR_TEXT", | |
230 | "GTK_TOOLBAR_BOTH", | |
231 | "GTK_TOOLBAR_BOTH_HORIZ" | |
232 | }; | |
233 | static const char* tb_icon_sizes[]={ | |
234 | "GTK_ICON_SIZE_INVALID", | |
235 | "GTK_ICON_SIZE_MENU", | |
236 | "GTK_ICON_SIZE_SMALL_TOOLBAR", | |
237 | "GTK_ICON_SIZE_LARGE_TOOLBAR", | |
238 | "GTK_ICON_SIZE_BUTTON", | |
239 | "GTK_ICON_SIZE_DND", | |
240 | "GTK_ICON_SIZE_DIALOG" | |
241 | }; | |
242 | ||
3518acea | 243 | char* file_path = g_build_filename(g_get_home_dir(), ".gtkrc-2.0", NULL); |
c92e9c11 | 244 | GString* content = g_string_sized_new(512); |
79ec4790 | 245 | g_string_append(content, |
ae63f687 | 246 | "# DO NOT EDIT! This file will be overwritten by LXAppearance.\n" |
79ec4790 | 247 | "# Any customization should be done in ~/.gtkrc-2.0.mine instead.\n\n"); |
ec6b7b65 AG |
248 | |
249 | /* include ~/.gtkrc-2.0.mine first to be able to apply changes done | |
250 | by LXAppearance if the same settings exist in that file */ | |
251 | g_string_append_printf(content, | |
252 | "include \"%s/.gtkrc-2.0.mine\"\n", | |
253 | g_get_home_dir()); | |
254 | ||
79ec4790 HJYP |
255 | if(app.widget_theme) |
256 | g_string_append_printf(content, | |
257 | "gtk-theme-name=\"%s\"\n", app.widget_theme); | |
258 | if(app.icon_theme) | |
259 | g_string_append_printf(content, | |
260 | "gtk-icon-theme-name=\"%s\"\n", app.icon_theme); | |
261 | if(app.default_font) | |
262 | g_string_append_printf(content, | |
263 | "gtk-font-name=\"%s\"\n", app.default_font); | |
264 | if(app.cursor_theme) | |
265 | g_string_append_printf(content, | |
266 | "gtk-cursor-theme-name=\"%s\"\n", app.cursor_theme); | |
267 | save_cursor_theme_name(); | |
268 | ||
269 | g_string_append_printf(content, | |
270 | "gtk-cursor-theme-size=%d\n" | |
ae63f687 HJYP |
271 | "gtk-toolbar-style=%s\n" |
272 | "gtk-toolbar-icon-size=%s\n" | |
36827f45 HJYP |
273 | "gtk-button-images=%d\n" |
274 | "gtk-menu-images=%d\n" | |
9bb12c12 | 275 | #if GTK_CHECK_VERSION(2, 14, 0) |
36827f45 | 276 | "gtk-enable-event-sounds=%d\n" |
79ec4790 | 277 | "gtk-enable-input-feedback-sounds=%d\n" |
9bb12c12 | 278 | #endif |
2d9128f0 JL |
279 | "gtk-xft-antialias=%d\n" |
280 | "gtk-xft-hinting=%d\n" | |
281 | ||
79ec4790 | 282 | , app.cursor_theme_size, |
ae63f687 HJYP |
283 | tb_styles[app.toolbar_style], |
284 | tb_icon_sizes[app.toolbar_icon_size], | |
36827f45 HJYP |
285 | app.button_images ? 1 : 0, |
286 | app.menu_images ? 1 : 0, | |
9bb12c12 | 287 | #if GTK_CHECK_VERSION(2, 14, 0) |
36827f45 | 288 | app.enable_event_sound ? 1 : 0, |
2d9128f0 | 289 | app.enable_input_feedback ? 1 : 0, |
9bb12c12 | 290 | #endif |
2d9128f0 JL |
291 | app.enable_antialising ? 1 : 0, |
292 | app.enable_hinting ? 1 : 0 | |
c92e9c11 HJYP |
293 | ); |
294 | ||
2d9128f0 JL |
295 | if(app.hinting_style) |
296 | g_string_append_printf(content, | |
b8648654 | 297 | "gtk-xft-hintstyle=\"%s\"\n", app.hinting_style); |
2d9128f0 JL |
298 | |
299 | if(app.font_rgba) | |
300 | g_string_append_printf(content, | |
b8648654 | 301 | "gtk-xft-rgba=\"%s\"\n", app.font_rgba); |
2d9128f0 | 302 | |
afcecf68 AG |
303 | if(app.modules && app.modules[0]) |
304 | g_string_append_printf(content, "gtk-modules=\"%s\"\n", app.modules); | |
305 | ||
eee70cc4 AG |
306 | #if 0 |
307 | /* unfortunately we cannot set colors without XSETTINGS daemon, | |
308 | themes will override any custom settings in .gtkrc-2.0 file */ | |
309 | /* FIXME: we should support other xsettings daemons too */ | |
c92e9c11 HJYP |
310 | if(app.color_scheme) |
311 | { | |
312 | char* escaped = g_strescape(app.color_scheme, NULL); | |
313 | g_string_append_printf(content, | |
203587a3 | 314 | "gtk-color-scheme=\"%s\"\n", |
c92e9c11 HJYP |
315 | escaped); |
316 | g_free(escaped); | |
317 | } | |
eee70cc4 | 318 | #endif |
c92e9c11 | 319 | |
c92e9c11 | 320 | g_file_set_contents(file_path, content->str, content->len, NULL); |
c26fee92 | 321 | |
924e9daf JL |
322 | /* Save also in GTK3 folder |
323 | Content shold be different from the gtk2 one | |
324 | */ | |
b3957344 | 325 | GKeyFile *content_gtk3 = g_key_file_new(); |
924e9daf | 326 | char* file_path_gtk3 = g_build_filename(g_get_user_config_dir(), "gtk-3.0", NULL); |
b3957344 | 327 | char* file_path_settings = g_build_filename(file_path_gtk3, "settings.ini", NULL); |
c26fee92 JL |
328 | |
329 | if (!g_file_test(file_path_gtk3, G_FILE_TEST_IS_DIR)) | |
330 | { | |
331 | g_mkdir_with_parents(file_path_gtk3, 0755); | |
332 | } | |
333 | ||
b3957344 AG |
334 | g_key_file_load_from_file(content_gtk3, file_path_settings, /* ignoring errors */ |
335 | G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, NULL); | |
924e9daf JL |
336 | |
337 | if(app.widget_theme) | |
b3957344 AG |
338 | g_key_file_set_string(content_gtk3, "Settings", |
339 | "gtk-theme-name", app.widget_theme); | |
924e9daf | 340 | if(app.icon_theme) |
b3957344 AG |
341 | g_key_file_set_string(content_gtk3, "Settings", |
342 | "gtk-icon-theme-name", app.icon_theme); | |
924e9daf | 343 | if(app.default_font) |
b3957344 AG |
344 | g_key_file_set_string(content_gtk3, "Settings", |
345 | "gtk-font-name", app.default_font); | |
924e9daf | 346 | if(app.cursor_theme) |
b3957344 AG |
347 | g_key_file_set_string(content_gtk3, "Settings", |
348 | "gtk-cursor-theme-name", app.cursor_theme); | |
924e9daf JL |
349 | save_cursor_theme_name(); |
350 | ||
b3957344 AG |
351 | g_key_file_set_integer(content_gtk3, "Settings", |
352 | "gtk-cursor-theme-size", app.cursor_theme_size); | |
353 | g_key_file_set_string(content_gtk3, "Settings", | |
354 | "gtk-toolbar-style", tb_styles[app.toolbar_style]); | |
355 | g_key_file_set_string(content_gtk3, "Settings", | |
356 | "gtk-toolbar-icon-size", tb_icon_sizes[app.toolbar_icon_size]); | |
3dca6a19 AG |
357 | g_key_file_set_integer(content_gtk3, "Settings", |
358 | "gtk-button-images", app.button_images ? 1 : 0); | |
359 | g_key_file_set_integer(content_gtk3, "Settings", | |
360 | "gtk-menu-images", app.menu_images ? 1 : 0); | |
924e9daf | 361 | #if GTK_CHECK_VERSION(2, 14, 0) |
3dca6a19 AG |
362 | g_key_file_set_integer(content_gtk3, "Settings", |
363 | "gtk-enable-event-sounds", app.enable_event_sound ? 1 : 0); | |
364 | g_key_file_set_integer(content_gtk3, "Settings", | |
365 | "gtk-enable-input-feedback-sounds", app.enable_input_feedback ? 1 : 0); | |
924e9daf | 366 | #endif |
3dca6a19 AG |
367 | g_key_file_set_integer(content_gtk3, "Settings", |
368 | "gtk-xft-antialias", app.enable_antialising ? 1 : 0); | |
369 | g_key_file_set_integer(content_gtk3, "Settings", | |
370 | "gtk-xft-hinting", app.enable_hinting ? 1 : 0); | |
924e9daf JL |
371 | |
372 | if(app.hinting_style) | |
b3957344 AG |
373 | g_key_file_set_string(content_gtk3, "Settings", |
374 | "gtk-xft-hintstyle", app.hinting_style); | |
924e9daf JL |
375 | |
376 | if(app.font_rgba) | |
b3957344 AG |
377 | g_key_file_set_string(content_gtk3, "Settings", |
378 | "gtk-xft-rgba", app.font_rgba); | |
924e9daf | 379 | |
afcecf68 AG |
380 | if(app.modules && app.modules[0]) |
381 | g_key_file_set_string(content_gtk3, "Settings", "gtk-modules", app.modules); | |
382 | else | |
383 | g_key_file_remove_key(content_gtk3, "Settings", "gtk-modules", NULL); | |
384 | ||
eee70cc4 AG |
385 | #if 0 |
386 | /* unfortunately we cannot set colors without XSETTINGS daemon, | |
387 | themes will override any custom settings in .gtkrc-2.0 file */ | |
388 | /* FIXME: we should support other xsettings daemons too */ | |
924e9daf JL |
389 | if(app.color_scheme) |
390 | { | |
391 | char* escaped = g_strescape(app.color_scheme, NULL); | |
392 | g_string_append_printf(content_gtk3, | |
393 | "gtk-color-scheme=%s\n", | |
394 | escaped); | |
395 | g_free(escaped); | |
396 | } | |
eee70cc4 | 397 | #endif |
924e9daf | 398 | |
b3957344 AG |
399 | #if GLIB_CHECK_VERSION(2, 40, 0) |
400 | g_key_file_save_to_file(content_gtk3, file_path_settings, NULL); | |
401 | #else | |
402 | char *contents; | |
403 | gsize s; | |
404 | ||
405 | contents = g_key_file_to_data(content_gtk3, &s, NULL); | |
406 | if (contents) | |
407 | g_file_set_contents(file_path_settings, contents, s, NULL); | |
408 | g_free(contents); | |
409 | #endif | |
c26fee92 | 410 | |
b3957344 AG |
411 | g_free(file_path_gtk3); |
412 | g_free(file_path_settings); | |
c92e9c11 | 413 | g_string_free(content, TRUE); |
b3957344 | 414 | g_key_file_free(content_gtk3); |
ae63f687 | 415 | g_free(file_path); |
15c155a6 HJYP |
416 | } |
417 | ||
418 | static void lxappearance_save_lxsession() | |
419 | { | |
ae63f687 HJYP |
420 | char* rel_path = g_strconcat("lxsession/", lxsession_name, "/desktop.conf", NULL); |
421 | char* user_config_file = g_build_filename(g_get_user_config_dir(), rel_path, NULL); | |
422 | char* buf; | |
8a35b255 | 423 | gsize len; |
ae63f687 HJYP |
424 | GKeyFile* kf = g_key_file_new(); |
425 | ||
426 | if(!g_key_file_load_from_file(kf, user_config_file, G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS, NULL)) | |
427 | { | |
428 | /* the user config file doesn't exist, create its parent dir */ | |
429 | len = strlen(user_config_file) - strlen("/desktop.conf"); | |
430 | user_config_file[len] = '\0'; | |
431 | g_debug("user_config_file = %s", user_config_file); | |
432 | g_mkdir_with_parents(user_config_file, 0700); | |
433 | user_config_file[len] = '/'; | |
434 | ||
df6716ee HJYP |
435 | g_key_file_load_from_dirs(kf, rel_path, (const char**)g_get_system_config_dirs(), NULL, |
436 | G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS, NULL); | |
ae63f687 HJYP |
437 | } |
438 | ||
439 | g_free(rel_path); | |
15c155a6 | 440 | |
ae63f687 HJYP |
441 | g_key_file_set_string( kf, "GTK", "sNet/ThemeName", app.widget_theme ); |
442 | g_key_file_set_string( kf, "GTK", "sGtk/FontName", app.default_font ); | |
443 | ||
c92e9c11 | 444 | g_key_file_set_string( kf, "GTK", "sGtk/ColorScheme", app.color_scheme ? app.color_scheme : "" ); |
71ce58a7 | 445 | |
ae63f687 HJYP |
446 | g_key_file_set_string( kf, "GTK", "sNet/IconThemeName", app.icon_theme ); |
447 | ||
448 | g_key_file_set_string( kf, "GTK", "sGtk/CursorThemeName", app.cursor_theme ); | |
449 | g_key_file_set_integer( kf, "GTK", "iGtk/CursorThemeSize", app.cursor_theme_size ); | |
450 | save_cursor_theme_name(); | |
451 | ||
452 | g_key_file_set_integer( kf, "GTK", "iGtk/ToolbarStyle", app.toolbar_style ); | |
453 | g_key_file_set_integer( kf, "GTK", "iGtk/ToolbarIconSize", app.toolbar_icon_size ); | |
454 | ||
9bb12c12 HJYP |
455 | g_key_file_set_integer( kf, "GTK", "iGtk/ToolbarStyle", app.toolbar_style ); |
456 | g_key_file_set_integer( kf, "GTK", "iGtk/ToolbarIconSize", app.toolbar_icon_size ); | |
457 | ||
6b54b65a HJYP |
458 | g_key_file_set_integer( kf, "GTK", "iGtk/ButtonImages", app.button_images ); |
459 | g_key_file_set_integer( kf, "GTK", "iGtk/MenuImages", app.menu_images ); | |
460 | ||
461 | #if GTK_CHECK_VERSION(2, 14, 0) | |
9bb12c12 HJYP |
462 | /* "Net/SoundThemeName\0" "gtk-sound-theme-name\0" */ |
463 | g_key_file_set_integer( kf, "GTK", "iNet/EnableEventSounds", app.enable_event_sound); | |
464 | g_key_file_set_integer( kf, "GTK", "iNet/EnableInputFeedbackSounds", app.enable_input_feedback); | |
465 | #endif | |
2d9128f0 JL |
466 | g_key_file_set_integer( kf, "GTK", "iXft/Antialias", app.enable_antialising); |
467 | g_key_file_set_integer( kf, "GTK", "iXft/Hinting", app.enable_hinting); | |
b8648654 JL |
468 | g_key_file_set_string( kf, "GTK", "sXft/HintStyle", app.hinting_style); |
469 | g_key_file_set_string( kf, "GTK", "sXft/RGBA", app.font_rgba); | |
9bb12c12 | 470 | |
ae63f687 HJYP |
471 | buf = g_key_file_to_data( kf, &len, NULL ); |
472 | g_key_file_free(kf); | |
473 | ||
474 | g_file_set_contents(user_config_file, buf, len, NULL); | |
475 | g_free(buf); | |
476 | g_free(user_config_file); | |
15c155a6 HJYP |
477 | } |
478 | ||
479 | static void on_dlg_response(GtkDialog* dlg, int res, gpointer user_data) | |
480 | { | |
481 | switch(res) | |
482 | { | |
483 | case GTK_RESPONSE_APPLY: | |
484 | ||
485 | if(app.use_lxsession) | |
486 | lxappearance_save_lxsession(); | |
b5134e4c | 487 | lxappearance_save_gtkrc(); |
15c155a6 | 488 | |
ae63f687 HJYP |
489 | reload_all_programs(); |
490 | ||
15c155a6 | 491 | app.changed = FALSE; |
df6716ee | 492 | gtk_dialog_set_response_sensitive(GTK_DIALOG(app.dlg), GTK_RESPONSE_APPLY, FALSE); |
15c155a6 HJYP |
493 | break; |
494 | case 1: /* about dialog */ | |
495 | { | |
496 | GtkBuilder* b = gtk_builder_new(); | |
497 | if(gtk_builder_add_from_file(b, PACKAGE_UI_DIR "/about.ui", NULL)) | |
498 | { | |
499 | GtkWidget* dlg = GTK_WIDGET(gtk_builder_get_object(b, "dlg")); | |
df6716ee | 500 | gtk_dialog_run(GTK_DIALOG(dlg)); |
15c155a6 HJYP |
501 | gtk_widget_destroy(dlg); |
502 | } | |
503 | g_object_unref(b); | |
504 | } | |
505 | break; | |
506 | default: | |
507 | gtk_main_quit(); | |
508 | } | |
509 | } | |
510 | ||
511 | static void settings_init() | |
512 | { | |
e597424e HJYP |
513 | GtkSettings* settings = gtk_settings_get_default(); |
514 | g_object_get(settings, | |
515 | "gtk-theme-name", &app.widget_theme, | |
ae63f687 | 516 | "gtk-font-name", &app.default_font, |
e597424e HJYP |
517 | "gtk-icon-theme-name", &app.icon_theme, |
518 | "gtk-cursor-theme-name", &app.cursor_theme, | |
4e409096 | 519 | "gtk-cursor-theme-size", &app.cursor_theme_size, |
e597424e HJYP |
520 | "gtk-toolbar-style", &app.toolbar_style, |
521 | "gtk-toolbar-icon-size", &app.toolbar_icon_size, | |
6b54b65a HJYP |
522 | "gtk-button-images", &app.button_images, |
523 | "gtk-menu-images", &app.menu_images, | |
9bb12c12 HJYP |
524 | #if GTK_CHECK_VERSION(2, 14, 0) |
525 | "gtk-enable-event-sounds", &app.enable_event_sound, | |
526 | "gtk-enable-input-feedback-sounds", &app.enable_input_feedback, | |
527 | #endif | |
2d9128f0 JL |
528 | "gtk-xft-antialias", &app.enable_antialising, |
529 | "gtk-xft-hinting", &app.enable_hinting, | |
530 | "gtk-xft-hintstyle", &app.hinting_style, | |
531 | "gtk-xft-rgba", &app.font_rgba, | |
afcecf68 | 532 | "gtk-modules", &app.modules, |
e597424e | 533 | NULL); |
15c155a6 | 534 | /* try to figure out cursor theme used. */ |
15c155a6 HJYP |
535 | if(!app.cursor_theme || g_strcmp0(app.cursor_theme, "default") == 0) |
536 | { | |
537 | /* get the real theme name from default. */ | |
538 | GKeyFile* kf = g_key_file_new(); | |
539 | char* fpath = g_build_filename(g_get_home_dir(), ".icons/default/index.theme", NULL); | |
540 | gboolean ret = g_key_file_load_from_file(kf, fpath, 0, NULL); | |
541 | g_free(fpath); | |
542 | ||
543 | if(!ret) | |
544 | ret = g_key_file_load_from_data_dirs(kf, "icons/default/index.theme", NULL, 0, NULL); | |
545 | ||
546 | if(ret) | |
547 | { | |
e597424e | 548 | g_free(app.cursor_theme); |
15c155a6 HJYP |
549 | app.cursor_theme = g_key_file_get_string(kf, "Icon Theme", "Inherits", NULL); |
550 | g_debug("cursor theme name: %s", app.cursor_theme); | |
551 | } | |
552 | g_key_file_free(kf); | |
553 | } | |
c92e9c11 HJYP |
554 | |
555 | app.color_scheme_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | |
556 | /* try to load custom color scheme if available */ | |
557 | if(app.use_lxsession) | |
558 | { | |
559 | char* rel_path = g_strconcat("lxsession/", lxsession_name, "/desktop.conf", NULL); | |
560 | char* user_config_file = g_build_filename(g_get_user_config_dir(), rel_path, NULL); | |
561 | GKeyFile* kf = g_key_file_new(); | |
562 | if(g_key_file_load_from_file(kf, user_config_file, 0, NULL)) | |
563 | app.color_scheme = g_key_file_get_string(kf, "GTK", "sGtk/ColorScheme", NULL); | |
df6716ee | 564 | else if(g_key_file_load_from_dirs(kf, rel_path, (const char**)g_get_system_config_dirs(), NULL, 0, NULL)) |
c92e9c11 HJYP |
565 | app.color_scheme = g_key_file_get_string(kf, "GTK", "sGtk/ColorScheme", NULL); |
566 | g_key_file_free(kf); | |
567 | g_free(rel_path); | |
568 | g_free(user_config_file); | |
569 | ||
570 | if(app.color_scheme) | |
571 | { | |
572 | if(*app.color_scheme) | |
573 | color_scheme_str_to_hash(app.color_scheme_hash, app.color_scheme); | |
574 | else | |
575 | { | |
576 | g_free(app.color_scheme); | |
577 | app.color_scheme = NULL; | |
578 | } | |
579 | } | |
580 | } | |
eee70cc4 AG |
581 | #if 0 |
582 | /* unfortunately we cannot set colors without XSETTINGS daemon, | |
583 | themes will override any custom settings in .gtkrc-2.0 file */ | |
584 | /* FIXME: we should support other xsettings daemons too */ | |
c92e9c11 HJYP |
585 | else |
586 | { | |
587 | char* gtkrc_file = g_build_filename(g_get_home_dir(), ".gtkrc-2.0", NULL); | |
588 | gtkrc_file_get_color_scheme(gtkrc_file, app.color_scheme_hash); | |
589 | g_free(gtkrc_file); | |
590 | if(g_hash_table_size(app.color_scheme_hash) > 0) | |
591 | app.color_scheme = color_scheme_hash_to_str(app.color_scheme_hash); | |
592 | } | |
eee70cc4 | 593 | #endif |
15c155a6 HJYP |
594 | } |
595 | ||
0cd84ed6 HJYP |
596 | int main(int argc, char** argv) |
597 | { | |
598 | GError* err = NULL; | |
599 | GtkBuilder* b; | |
0cd84ed6 HJYP |
600 | |
601 | /* gettext support */ | |
602 | #ifdef ENABLE_NLS | |
603 | bindtextdomain ( GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR ); | |
604 | bind_textdomain_codeset ( GETTEXT_PACKAGE, "UTF-8" ); | |
605 | textdomain ( GETTEXT_PACKAGE ); | |
606 | #endif | |
607 | ||
fd9f7e8d | 608 | #if !GLIB_CHECK_VERSION(2, 32, 0) |
ff19d42c | 609 | g_thread_init(NULL); |
fd9f7e8d | 610 | #endif |
0cd84ed6 HJYP |
611 | /* initialize GTK+ and parse the command line arguments */ |
612 | if( G_UNLIKELY( ! gtk_init_with_args( &argc, &argv, "", option_entries, GETTEXT_PACKAGE, &err ) ) ) | |
613 | { | |
614 | g_print( "Error: %s\n", err->message ); | |
615 | return 1; | |
616 | } | |
617 | ||
1123e741 HJYP |
618 | app.abi_version = LXAPPEARANCE_ABI_VERSION; |
619 | ||
15c155a6 HJYP |
620 | /* check if we're under LXSession */ |
621 | check_lxsession(); | |
622 | ||
0cd84ed6 HJYP |
623 | /* create GUI here */ |
624 | b = gtk_builder_new(); | |
625 | if(!gtk_builder_add_from_file(b, PACKAGE_UI_DIR "/lxappearance.ui", NULL)) | |
626 | return 1; | |
627 | ||
6b54b65a HJYP |
628 | /* NOTE: GUI must be created prior to loading settings from GtkSettings object. |
629 | * Some properties of GtkSettings class are installed by some other gtk classes. | |
630 | * For example, "gtk-menu-images" property is actually installed by initialization | |
631 | * of GtkImageMenuItem class. If we load the GUI first, then when the menu items | |
632 | * are created, this property gets correctly registered. So later it can be read. */ | |
633 | ||
634 | /* load config values */ | |
635 | settings_init(); | |
636 | ||
e597424e HJYP |
637 | app.dlg = GTK_WIDGET(gtk_builder_get_object(b, "dlg")); |
638 | ||
0cd84ed6 | 639 | widget_theme_init(b); |
71ce58a7 | 640 | color_scheme_init(b); |
0cd84ed6 HJYP |
641 | icon_theme_init(b); |
642 | cursor_theme_init(b); | |
2d9128f0 | 643 | font_init(b); |
e597424e | 644 | other_init(b); |
756f0a66 HJYP |
645 | /* the page for window manager plugins */ |
646 | app.wm_page = GTK_WIDGET(gtk_builder_get_object(b, "wm_page")); | |
647 | ||
ff19d42c HJYP |
648 | plugins_init(b); |
649 | ||
15c155a6 | 650 | g_signal_connect(app.dlg, "response", G_CALLBACK(on_dlg_response), NULL); |
0cd84ed6 | 651 | |
15c155a6 | 652 | gtk_window_present(GTK_WINDOW(app.dlg)); |
0cd84ed6 HJYP |
653 | g_object_unref(b); |
654 | ||
655 | gtk_main(); | |
656 | ||
756f0a66 HJYP |
657 | plugins_finalize(); |
658 | ||
0cd84ed6 HJYP |
659 | return 0; |
660 | } | |
15c155a6 HJYP |
661 | |
662 | void lxappearance_changed() | |
663 | { | |
664 | if(!app.changed) | |
665 | { | |
666 | app.changed = TRUE; | |
df6716ee | 667 | gtk_dialog_set_response_sensitive(GTK_DIALOG(app.dlg), GTK_RESPONSE_APPLY, TRUE); |
15c155a6 HJYP |
668 | } |
669 | } | |
2d9128f0 JL |
670 | |
671 | void on_check_button_toggled(GtkToggleButton* btn, gpointer user_data) | |
672 | { | |
673 | gboolean* val = (gboolean*)user_data; | |
674 | gboolean new_val = gtk_toggle_button_get_active(btn); | |
675 | if(new_val != *val) | |
676 | { | |
677 | *val = new_val; | |
678 | lxappearance_changed(); | |
679 | } | |
680 | } |