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