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