add coding style stuff
[awesome.git] / config.c
blobb117065057c0cdbbc2685e98f701124e7a4436a7
1 /*
2 * config.c - configuration management
4 * Copyright © 2007 Julien Danjou <julien@danjou.info>
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.
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.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 /**
23 * \defgroup ui_callback
26 #include <confuse.h>
27 #include <X11/keysym.h>
29 #include "util.h"
30 #include "awesome.h"
31 #include "screen.h"
32 #include "draw.h"
33 #include "tag.h"
34 #include "statusbar.h"
35 #include "layout.h"
36 #include "layouts/tile.h"
37 #include "layouts/floating.h"
38 #include "layouts/max.h"
40 #define AWESOME_CONFIG_FILE ".awesomerc"
42 static XColor initxcolor(Display *, int, const char *);
43 static unsigned int get_numlockmask(Display *);
45 /** Link a name to a key symbol */
46 typedef struct
48 const char *name;
49 KeySym keysym;
50 } KeyMod;
52 /** List of available UI bindable callbacks and functions */
53 const NameFuncLink UicbList[] = {
54 /* util.c */
55 {"spawn", uicb_spawn},
56 {"exec", uicb_exec},
57 /* client.c */
58 {"killclient", uicb_killclient},
59 {"moveresize", uicb_moveresize},
60 {"settrans", uicb_settrans},
61 {"setborder", uicb_setborder},
62 {"swapnext", uicb_swapnext},
63 {"swapprev", uicb_swapprev},
64 /* tag.c */
65 {"tag", uicb_tag},
66 {"togglefloating", uicb_togglefloating},
67 {"toggleview", uicb_toggleview},
68 {"toggletag", uicb_toggletag},
69 {"view", uicb_view},
70 {"view_tag_prev_selected", uicb_tag_prev_selected},
71 {"view_tag_previous", uicb_tag_viewprev},
72 {"view_tag_next", uicb_tag_viewnext},
73 /* layout.c */
74 {"setlayout", uicb_setlayout},
75 {"focusnext", uicb_focusnext},
76 {"focusprev", uicb_focusprev},
77 {"togglemax", uicb_togglemax},
78 {"toggleverticalmax", uicb_toggleverticalmax},
79 {"togglehorizontalmax", uicb_togglehorizontalmax},
80 {"zoom", uicb_zoom},
81 /* layouts/tile.c */
82 {"setmwfact", uicb_setmwfact},
83 {"setnmaster", uicb_setnmaster},
84 {"setncol", uicb_setncol},
85 /* screen.c */
86 {"focusnextscreen", uicb_focusnextscreen},
87 {"focusprevscreen", uicb_focusprevscreen},
88 {"movetoscreen", uicb_movetoscreen},
89 /* awesome.c */
90 {"quit", uicb_quit},
91 /* statusbar.c */
92 {"togglebar", uicb_togglebar},
93 {"setstatustext", uicb_setstatustext},
94 {NULL, NULL}
97 /** List of keyname and corresponding X11 mask codes */
98 static const KeyMod KeyModList[] =
100 {"Shift", ShiftMask},
101 {"Lock", LockMask},
102 {"Control", ControlMask},
103 {"Mod1", Mod1Mask},
104 {"Mod2", Mod2Mask},
105 {"Mod3", Mod3Mask},
106 {"Mod4", Mod4Mask},
107 {"Mod5", Mod5Mask},
108 {"None", 0}
111 /** List of available layouts and link between name and functions */
112 static const NameFuncLink LayoutsList[] =
114 {"tile", layout_tile},
115 {"tileleft", layout_tileleft},
116 {"max", layout_max},
117 {"floating", layout_floating},
118 {NULL, NULL}
121 /** Lookup for a key mask from its name
122 * \param keyname Key name
123 * \return Key mask or 0 if not found
125 static KeySym
126 key_mask_lookup(const char *keyname)
128 int i;
130 if(keyname)
131 for(i = 0; KeyModList[i].name; i++)
132 if(!a_strcmp(keyname, KeyModList[i].name))
133 return KeyModList[i].keysym;
135 return 0;
138 /** Parse configuration file and initialize some stuff
139 * \param disp Display ref
140 * \param scr Screen number
142 void
143 parse_config(Display * disp, int scr,const char *confpatharg, awesome_config *awesomeconf)
145 static cfg_opt_t general_opts[] =
147 CFG_INT((char *) "border", 1, CFGF_NONE),
148 CFG_INT((char *) "snap", 8, CFGF_NONE),
149 CFG_BOOL((char *) "resize_hints", cfg_false, CFGF_NONE),
150 CFG_INT((char *) "opacity_unfocused", 100, CFGF_NONE),
151 CFG_BOOL((char *) "focus_move_pointer", cfg_false, CFGF_NONE),
152 CFG_BOOL((char *) "allow_lower_floats", cfg_false, CFGF_NONE),
153 CFG_STR((char *) "font", (char *) "mono-12", CFGF_NONE),
154 CFG_END()
156 static cfg_opt_t colors_opts[] =
158 CFG_STR((char *) "normal_border", (char *) "#111111", CFGF_NONE),
159 CFG_STR((char *) "normal_bg", (char *) "#111111", CFGF_NONE),
160 CFG_STR((char *) "normal_fg", (char *) "#eeeeee", CFGF_NONE),
161 CFG_STR((char *) "focus_border", (char *) "#6666ff", CFGF_NONE),
162 CFG_STR((char *) "focus_bg", (char *) "#6666ff", CFGF_NONE),
163 CFG_STR((char *) "focus_fg", (char *) "#ffffff", CFGF_NONE),
164 CFG_END()
166 static cfg_opt_t statusbar_opts[] =
168 CFG_STR((char *) "position", (char *) "top", CFGF_NONE),
169 CFG_END()
171 static cfg_opt_t tag_opts[] =
173 CFG_STR((char *) "layout", (char *) "tile", CFGF_NONE),
174 CFG_END()
176 static cfg_opt_t tags_opts[] =
178 CFG_SEC((char *) "tag", tag_opts, CFGF_TITLE | CFGF_MULTI),
179 CFG_END()
181 static cfg_opt_t layout_opts[] =
183 CFG_STR((char *) "symbol", (char *) "???", CFGF_NONE),
184 CFG_END()
186 static cfg_opt_t layouts_opts[] =
188 CFG_SEC((char *) "layout", layout_opts, CFGF_TITLE | CFGF_MULTI),
189 CFG_FLOAT((char *) "mwfact", 0.5, CFGF_NONE),
190 CFG_INT((char *) "nmaster", 1, CFGF_NONE),
191 CFG_INT((char *) "ncol", 1, CFGF_NONE),
192 CFG_END()
194 static cfg_opt_t rule_opts[] =
196 CFG_STR((char *) "name", (char *) "", CFGF_NONE),
197 CFG_STR((char *) "tags", (char *) "", CFGF_NONE),
198 CFG_BOOL((char *) "float", cfg_false, CFGF_NONE),
199 CFG_END()
201 static cfg_opt_t rules_opts[] =
203 CFG_SEC((char *) "rule", rule_opts, CFGF_MULTI),
204 CFG_END()
206 static cfg_opt_t key_opts[] =
208 CFG_STR_LIST((char *) "modkey", (char *) "{Mod4}", CFGF_NONE),
209 CFG_STR((char *) "key", (char *) "None", CFGF_NONE),
210 CFG_STR((char *) "command", (char *) "", CFGF_NONE),
211 CFG_STR((char *) "arg", NULL, CFGF_NONE),
212 CFG_END()
214 static cfg_opt_t keys_opts[] =
216 CFG_STR((char *) "modkey", (char *) "Mod4", CFGF_NONE),
217 CFG_SEC((char *) "key", key_opts, CFGF_MULTI),
218 CFG_END()
220 static cfg_opt_t opts[] =
222 CFG_SEC((char *) "general", general_opts, CFGF_NONE),
223 CFG_SEC((char *) "colors", colors_opts, CFGF_NONE),
224 CFG_SEC((char *) "statusbar", statusbar_opts, CFGF_NONE),
225 CFG_SEC((char *) "tags", tags_opts, CFGF_NONE),
226 CFG_SEC((char *) "layouts", layouts_opts, CFGF_NONE),
227 CFG_SEC((char *) "rules", rules_opts, CFGF_NONE),
228 CFG_SEC((char *) "keys", keys_opts, CFGF_NONE),
229 CFG_END()
231 cfg_t *cfg, *cfg_general, *cfg_colors, *cfg_statusbar,
232 *cfg_tags, *cfg_layouts, *cfg_rules, *cfg_keys, *cfgsectmp;
233 int i = 0;
234 unsigned int j = 0;
235 int k = 0;
236 const char *tmp, *homedir;
237 char *confpath;
238 KeySym tmp_key;
239 ssize_t confpath_len;
241 if(confpatharg)
242 confpath = a_strdup(confpatharg);
243 else
245 homedir = getenv("HOME");
246 confpath_len = a_strlen(homedir) + a_strlen(AWESOME_CONFIG_FILE) + 2;
247 confpath = p_new(char, confpath_len);
248 a_strcpy(confpath, confpath_len, homedir);
249 a_strcat(confpath, confpath_len, "/");
250 a_strcat(confpath, confpath_len, AWESOME_CONFIG_FILE);
253 a_strcpy(awesomeconf->statustext, sizeof(awesomeconf->statustext), "awesome-" VERSION);
255 /* store display */
256 awesomeconf->display = disp;
258 /* set screen */
259 awesomeconf->screen = scr;
260 awesomeconf->phys_screen = get_phys_screen(disp, scr);
262 cfg = cfg_init(opts, CFGF_NONE);
264 if(cfg_parse(cfg, confpath) == CFG_PARSE_ERROR)
265 fprintf(stderr, "awesome: error parsing configuration file\n");
267 cfg_general = cfg_getsec(cfg, "general");
268 cfg_colors = cfg_getsec(cfg, "colors");
269 cfg_statusbar = cfg_getsec(cfg, "statusbar");
270 cfg_tags = cfg_getsec(cfg, "tags");
271 cfg_layouts = cfg_getsec(cfg, "layouts");
272 cfg_rules = cfg_getsec(cfg, "rules");
273 cfg_keys = cfg_getsec(cfg, "keys");
275 /* General section */
277 awesomeconf->borderpx = cfg_getint(cfg_general, "border");
278 awesomeconf->snap = cfg_getint(cfg_general, "snap");
279 awesomeconf->resize_hints = cfg_getbool(cfg_general, "resize_hints");
280 awesomeconf->opacity_unfocused = cfg_getint(cfg_general, "opacity_unfocused");
281 awesomeconf->focus_move_pointer = cfg_getbool(cfg_general, "focus_move_pointer");
282 awesomeconf->allow_lower_floats = cfg_getbool(cfg_general, "allow_lower_floats");
283 awesomeconf->font = XftFontOpenName(disp, awesomeconf->phys_screen, cfg_getstr(cfg_general, "font"));
284 if(!awesomeconf->font)
285 eprint("awesome: cannot init font\n");
287 /* Colors */
288 awesomeconf->colors_normal[ColBorder] = initxcolor(disp, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "normal_border"));
289 awesomeconf->colors_normal[ColBG] = initxcolor(disp, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "normal_bg"));
290 awesomeconf->colors_normal[ColFG] = initxcolor(disp, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "normal_fg"));
291 awesomeconf->colors_selected[ColBorder] = initxcolor(disp, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "focus_border"));
292 awesomeconf->colors_selected[ColBG] = initxcolor(disp, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "focus_bg"));
293 awesomeconf->colors_selected[ColFG] = initxcolor(disp, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "focus_fg"));
295 /* Statusbar */
296 tmp = cfg_getstr(cfg_statusbar, "position");
298 if(tmp && !a_strncmp(tmp, "off", 6))
299 awesomeconf->statusbar_default_position = BarOff;
300 else if(tmp && !a_strncmp(tmp, "bottom", 6))
301 awesomeconf->statusbar_default_position = BarBot;
302 else
303 awesomeconf->statusbar_default_position = BarTop;
305 awesomeconf->statusbar.position = awesomeconf->statusbar_default_position;
307 /* Layouts */
309 awesomeconf->nlayouts = cfg_size(cfg_layouts, "layout");
310 awesomeconf->layouts = p_new(Layout, awesomeconf->nlayouts);
311 for(i = 0; i < awesomeconf->nlayouts; i++)
313 cfgsectmp = cfg_getnsec(cfg_layouts, "layout", i);
314 awesomeconf->layouts[i].arrange = name_func_lookup(cfg_title(cfgsectmp), LayoutsList);
315 if(!awesomeconf->layouts[i].arrange)
317 fprintf(stderr, "awesome: unknown layout #%d in configuration file\n", i);
318 awesomeconf->layouts[i].symbol = NULL;
319 continue;
321 awesomeconf->layouts[i].symbol = a_strdup(cfg_getstr(cfgsectmp, "symbol"));
324 awesomeconf->mwfact = cfg_getfloat(cfg_layouts, "mwfact");
325 awesomeconf->nmaster = cfg_getint(cfg_layouts, "nmaster");
326 awesomeconf->ncol = cfg_getint(cfg_layouts, "ncol");
328 if(!awesomeconf->nlayouts)
329 eprint("awesome: fatal: no default layout available\n");
331 /* Rules */
333 awesomeconf->nrules = cfg_size(cfg_rules, "rule");
334 awesomeconf->rules = p_new(Rule, awesomeconf->nrules);
335 for(i = 0; i < awesomeconf->nrules; i++)
337 cfgsectmp = cfg_getnsec(cfg_rules, "rule", i);
338 awesomeconf->rules[i].prop = a_strdup(cfg_getstr(cfgsectmp, "name"));
339 awesomeconf->rules[i].tags = a_strdup(cfg_getstr(cfgsectmp, "tags"));
340 if(!a_strlen(awesomeconf->rules[i].tags))
341 awesomeconf->rules[i].tags = NULL;
342 awesomeconf->rules[i].isfloating = cfg_getbool(cfgsectmp, "float");
345 compileregs(awesomeconf->rules, awesomeconf->nrules);
347 /* Tags */
349 awesomeconf->ntags = cfg_size(cfg_tags, "tag");
350 awesomeconf->tags = p_new(Tag, awesomeconf->ntags);
351 for(i = 0; i < awesomeconf->ntags; i++)
353 cfgsectmp = cfg_getnsec(cfg_tags, "tag", i);
354 awesomeconf->tags[i].name = a_strdup(cfg_title(cfgsectmp));
355 awesomeconf->tags[i].selected = False;
356 awesomeconf->tags[i].was_selected = False;
357 tmp = cfg_getstr(cfgsectmp, "layout");
358 for(k = 0; k < awesomeconf->nlayouts; k++)
359 if(awesomeconf->layouts[k].arrange == name_func_lookup(tmp, LayoutsList))
360 break;
361 if(k == awesomeconf->nlayouts)
362 k = 0;
363 awesomeconf->tags[i].layout = &awesomeconf->layouts[k];
367 if(!awesomeconf->ntags)
368 eprint("awesome: fatal: no tags found in configuration file\n");
370 /* select first tag by default */
371 awesomeconf->current_layout = awesomeconf->tags[0].layout;
372 awesomeconf->tags[0].selected = True;
373 awesomeconf->tags[0].was_selected = True;
375 /* Keys */
376 tmp_key = key_mask_lookup(cfg_getstr(cfg_keys, "modkey"));
377 awesomeconf->modkey = tmp_key ? tmp_key : Mod4Mask;
378 awesomeconf->numlockmask = get_numlockmask(disp);
380 awesomeconf->nkeys = cfg_size(cfg_keys, "key");
381 awesomeconf->keys = p_new(Key, awesomeconf->nkeys);
382 for(i = 0; i < awesomeconf->nkeys; i++)
384 cfgsectmp = cfg_getnsec(cfg_keys, "key", i);
385 for(j = 0; j < cfg_size(cfgsectmp, "modkey"); j++)
386 awesomeconf->keys[i].mod |= key_mask_lookup(cfg_getnstr(cfgsectmp, "modkey", j));
387 awesomeconf->keys[i].keysym = XStringToKeysym(cfg_getstr(cfgsectmp, "key"));
388 awesomeconf->keys[i].func = name_func_lookup(cfg_getstr(cfgsectmp, "command"), UicbList);
389 awesomeconf->keys[i].arg = a_strdup(cfg_getstr(cfgsectmp, "arg"));
392 /* Free! Like a river! */
393 cfg_free(cfg);
394 p_delete(&confpath);
397 static unsigned int
398 get_numlockmask(Display *disp)
400 XModifierKeymap *modmap;
401 unsigned int mask = 0;
402 int i, j;
404 modmap = XGetModifierMapping(disp);
405 for(i = 0; i < 8; i++)
406 for(j = 0; j < modmap->max_keypermod; j++)
408 if(modmap->modifiermap[i * modmap->max_keypermod + j]
409 == XKeysymToKeycode(disp, XK_Num_Lock))
410 mask = (1 << i);
413 XFreeModifiermap(modmap);
415 return mask;
418 /** Initialize color from X side
419 * \param colorstr Color code
420 * \param disp Display ref
421 * \param scr Screen number
422 * \return XColor pixel
424 static XColor
425 initxcolor(Display *disp, int scr, const char *colstr)
427 XColor color;
428 if(!XAllocNamedColor(disp, DefaultColormap(disp, scr), colstr, &color, &color))
429 die("awesome: error, cannot allocate color '%s'\n", colstr);
430 return color;
432 // vim: filetype=c:expandtab:shiftwidth=6:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99