]> icculus.org git repositories - dana/obconf.git/blob - src/main.c
add the --config-file option, and use the OB_CONFIG_FILE property on root
[dana/obconf.git] / src / main.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3    main.c for ObConf, the configuration tool for Openbox
4    Copyright (c) 2003-2008   Dana Jansens
5    Copyright (c) 2003        Tim Riley
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    See the COPYING file for a copy of the GNU General Public License.
18 */
19
20 #include "main.h"
21 #include "archive.h"
22 #include "theme.h"
23 #include "appearance.h"
24 #include "windows.h"
25 #include "margins.h"
26 #include "mouse.h"
27 #include "desktops.h"
28 #include "dock.h"
29 #include "preview_update.h"
30 #include "gettext.h"
31
32 #include <gdk/gdkx.h>
33 #define SN_API_NOT_YET_FROZEN
34 #include <libsn/sn.h>
35 #undef SN_API_NOT_YET_FROZEN
36 #include <stdlib.h>
37
38 GtkWidget *mainwin = NULL;
39
40 GladeXML *glade;
41 xmlDocPtr doc;
42 xmlNodePtr root;
43 RrInstance *rrinst;
44 gchar *obc_config_file = NULL;
45
46 static gchar *obc_theme_install = NULL;
47 static gchar *obc_theme_archive = NULL;
48
49 void obconf_error(gchar *msg)
50 {
51     GtkWidget *d;
52
53     d = gtk_message_dialog_new(mainwin ? GTK_WINDOW(mainwin) : NULL,
54                                GTK_DIALOG_DESTROY_WITH_PARENT,
55                                GTK_MESSAGE_ERROR,
56                                GTK_BUTTONS_CLOSE,
57                                "%s", msg);
58     g_signal_connect_swapped(GTK_OBJECT(d), "response",
59                              G_CALLBACK(gtk_widget_destroy),
60                              GTK_OBJECT(d));
61     gtk_widget_show(d);
62 }
63
64 static void print_version()
65 {
66     g_print("ObConf %s\n", PACKAGE_VERSION);
67     g_print(_("Copyright (c)"));
68     g_print(" 2003-2008   Dana Jansens\n");
69     g_print(_("Copyright (c)"));
70     g_print(" 2003        Tim Riley\n");
71     g_print(_("Copyright (c)"));
72     g_print(" 2007        Javeed Shaikh\n\n");
73     g_print("This program comes with ABSOLUTELY NO WARRANTY.\n");
74     g_print("This is free software, and you are welcome to redistribute it\n");
75     g_print("under certain conditions. See the file COPYING for details.\n\n");
76
77     exit(EXIT_SUCCESS);
78 }
79
80 static void print_help()
81 {
82     g_print(_("Syntax: obconf [options] [ARCHIVE.obt]\n"));
83     g_print(_("\nOptions:\n"));
84     g_print(_("  --help                Display this help and exit\n"));
85     g_print(_("  --version             Display the version and exit\n"));
86     g_print(_("  --install ARCHIVE.obt Install the given theme archive and select it\n"));
87     g_print(_("  --archive THEME       Create a theme archive from the given theme directory\n"));
88     g_print(_("  --config-file FILE    Specify the path to the config file to use\n"));
89     g_print(_("\nPlease report bugs at %s\n\n"), PACKAGE_BUGREPORT);
90     
91     exit(EXIT_SUCCESS);
92 }
93
94 static void parse_args(int argc, char **argv)
95 {
96     int i;
97
98     for (i = 1; i < argc; ++i) {
99         if (!strcmp(argv[i], "--help"))
100             print_help();
101         if (!strcmp(argv[i], "--version"))
102             print_version();
103         else if (!strcmp(argv[i], "--install")) {
104             if (i == argc - 1) /* no args left */
105                 g_printerr(_("--install requires an argument\n"));
106             else
107                 obc_theme_install = argv[++i];
108         }
109         else if (!strcmp(argv[i], "--archive")) {
110             if (i == argc - 1) /* no args left */
111                 g_printerr(_("--archive requires an argument\n"));
112             else
113                 obc_theme_archive = argv[++i];
114         }
115         else if (!strcmp(argv[i], "--config-file")) {
116             if (i == argc - 1) /* no args left */
117                 g_printerr(_("--config-file requires an argument\n"));
118             else
119                 obc_config_file = argv[++i];
120         } else
121             obc_theme_install = argv[i];
122     }
123 }
124
125 static gboolean get_all(Window win, Atom prop, Atom type, gint size,
126                         guchar **data, guint *num)
127 {
128     gboolean ret = FALSE;
129     gint res;
130     guchar *xdata = NULL;
131     Atom ret_type;
132     gint ret_size;
133     gulong ret_items, bytes_left;
134
135     res = XGetWindowProperty(GDK_DISPLAY(), win, prop, 0l, G_MAXLONG,
136                              FALSE, type, &ret_type, &ret_size,
137                              &ret_items, &bytes_left, &xdata);
138     if (res == Success) {
139         if (ret_size == size && ret_items > 0) {
140             guint i;
141
142             *data = g_malloc(ret_items * (size / 8));
143             for (i = 0; i < ret_items; ++i)
144                 switch (size) {
145                 case 8:
146                     (*data)[i] = xdata[i];
147                     break;
148                 case 16:
149                     ((guint16*)*data)[i] = ((gushort*)xdata)[i];
150                     break;
151                 case 32:
152                     ((guint32*)*data)[i] = ((gulong*)xdata)[i];
153                     break;
154                 default:
155                     g_assert_not_reached(); /* unhandled size */
156                 }
157             *num = ret_items;
158             ret = TRUE;
159         }
160         XFree(xdata);
161     }
162     return ret;
163 }
164
165 static gboolean prop_get_string_utf8(Window win, Atom prop, gchar **ret)
166 {
167     gchar *raw;
168     gchar *str;
169     guint num;
170
171     if (get_all(win, prop,
172                 gdk_x11_get_xatom_by_name("UTF8_STRING"),
173                 8,(guchar**)&raw, &num))
174     {
175         str = g_strndup(raw, num); /* grab the first string from the list */
176         g_free(raw);
177         if (g_utf8_validate(str, -1, NULL)) {
178             *ret = str;
179             return TRUE;
180         }
181         g_free(str);
182     }
183     return FALSE;
184 }
185
186 int main(int argc, char **argv)
187 {
188     gchar *p;
189
190     bindtextdomain(PACKAGE_NAME, LOCALEDIR);
191     bind_textdomain_codeset(PACKAGE_NAME, "UTF-8");
192     textdomain(PACKAGE_NAME);
193
194     gtk_init(&argc, &argv);
195     parse_args(argc, argv);
196
197     if (obc_theme_archive) {
198         archive_create(obc_theme_archive);
199         return;
200     }
201
202     p = g_build_filename(GLADEDIR, "obconf.glade", NULL);
203     glade = glade_xml_new(p, NULL, NULL);
204     g_free(p);
205
206     if (!glade) {
207         obconf_error("Failed to load the obconf.glade interface file. You "
208                      "have probably failed to install ObConf properly.");
209         return 1;
210     }
211
212     parse_paths_startup();
213     rrinst = RrInstanceNew(GDK_DISPLAY(), gdk_x11_get_default_screen());
214
215     if (!obc_config_file) {
216         gchar *p;
217
218         if (prop_get_string_utf8(GDK_ROOT_WINDOW(),
219                                  gdk_x11_get_xatom_by_name("_OB_CONFIG_FILE"),
220                                  &p))
221         {
222             obc_config_file = g_filename_from_utf8(p, -1, NULL, NULL, NULL);
223             g_free(p);
224         }
225     }
226
227     xmlIndentTreeOutput = 1;
228     if (!parse_load_rc(obc_config_file, &doc, &root)) {
229         obconf_error("Failed to load an rc.xml. You have probably failed to "
230                      "install Openbox properly.");
231         return 1;
232     }
233
234     glade_xml_signal_autoconnect(glade);
235
236     {
237         gchar *s = g_strdup_printf
238             ("<span weight=\"bold\" size=\"xx-large\">ObConf %s</span>",
239              PACKAGE_VERSION);
240         gtk_label_set_markup(GTK_LABEL
241                              (glade_xml_get_widget(glade, "title_label")), s);
242         g_free(s);
243     }
244
245     theme_setup_tab();
246     appearance_setup_tab();
247     windows_setup_tab();
248     moveresize_setup_tab();
249     mouse_setup_tab();
250     desktops_setup_tab();
251     margins_setup_tab();
252     dock_setup_tab();
253
254     mainwin = get_widget("main_window");
255
256     if (obc_theme_install)
257         theme_install(obc_theme_install);
258     else
259         theme_load_all();
260
261     /* the main window is not shown here ! it is shown when the theme previews
262        are completed */
263     gtk_main();
264
265     preview_update_set_active_font(NULL);
266     preview_update_set_inactive_font(NULL);
267     preview_update_set_menu_header_font(NULL);
268     preview_update_set_menu_item_font(NULL);
269     preview_update_set_osd_font(NULL);
270     preview_update_set_title_layout(NULL);
271
272     RrInstanceFree(rrinst);
273     parse_paths_shutdown();
274
275     xmlFreeDoc(doc);
276     return 0;
277 }
278
279 gboolean on_main_window_delete_event(GtkWidget *w, GdkEvent *e, gpointer d)
280 {
281     gtk_main_quit();
282     return FALSE;
283 }
284
285 void on_close_clicked()
286 {
287     gtk_main_quit();
288 }
289
290 void obconf_show_main()
291 {
292     SnDisplay *sn_d;
293     SnLauncheeContext *sn_cx;
294
295     if (GTK_WIDGET_VISIBLE(mainwin)) return;
296
297     gtk_widget_show_all(mainwin);
298
299     sn_d = sn_display_new(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()),
300                           NULL, NULL);
301
302     sn_cx = sn_launchee_context_new_from_environment
303         (sn_d, gdk_screen_get_number(gdk_display_get_default_screen
304                                      (gdk_display_get_default())));
305
306     if (sn_cx)
307         sn_launchee_context_setup_window
308             (sn_cx, GDK_WINDOW_XWINDOW(GDK_WINDOW(mainwin->window)));
309
310     if (sn_cx)
311         sn_launchee_context_complete(sn_cx);
312
313     if (sn_cx)
314         sn_launchee_context_unref(sn_cx);
315     sn_display_unref(sn_d);
316 }