fix refresh of colborders
[awesome.git] / config.c
blob0ffc96613e9784084af4a149c1c0714ed7b12d90
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 "tab.h"
37 #include "layouts/tile.h"
38 #include "layouts/floating.h"
39 #include "layouts/max.h"
41 #define AWESOME_CONFIG_FILE ".awesomerc"
43 static XColor initxcolor(Display *, int, const char *);
44 static unsigned int get_numlockmask(Display *);
46 /** Link a name to a key symbol */
47 typedef struct
49 const char *name;
50 KeySym keysym;
51 } KeyMod;
53 /** List of available UI bindable callbacks and functions */
54 const NameFuncLink UicbList[] = {
55 /* util.c */
56 {"spawn", uicb_spawn},
57 {"exec", uicb_exec},
58 /* client.c */
59 {"killclient", uicb_killclient},
60 {"moveresize", uicb_moveresize},
61 {"settrans", uicb_settrans},
62 {"setborder", uicb_setborder},
63 {"swapnext", uicb_swapnext},
64 {"swapprev", uicb_swapprev},
65 /* tag.c */
66 {"tag", uicb_tag},
67 {"togglefloating", uicb_togglefloating},
68 {"toggleview", uicb_toggleview},
69 {"toggletag", uicb_toggletag},
70 {"view", uicb_view},
71 {"view_tag_prev_selected", uicb_tag_prev_selected},
72 {"view_tag_previous", uicb_tag_viewprev},
73 {"view_tag_next", uicb_tag_viewnext},
74 /* layout.c */
75 {"setlayout", uicb_setlayout},
76 {"focusnext", uicb_focusnext},
77 {"focusprev", uicb_focusprev},
78 {"togglemax", uicb_togglemax},
79 {"toggleverticalmax", uicb_toggleverticalmax},
80 {"togglehorizontalmax", uicb_togglehorizontalmax},
81 {"zoom", uicb_zoom},
82 /* layouts/tile.c */
83 {"setmwfact", uicb_setmwfact},
84 {"setnmaster", uicb_setnmaster},
85 {"setncol", uicb_setncol},
86 /* screen.c */
87 {"focusnextscreen", uicb_focusnextscreen},
88 {"focusprevscreen", uicb_focusprevscreen},
89 {"movetoscreen", uicb_movetoscreen},
90 /* awesome.c */
91 {"quit", uicb_quit},
92 /* statusbar.c */
93 {"togglebar", uicb_togglebar},
94 {"setstatustext", uicb_setstatustext},
95 /* tab.c */
96 {"tab", uicb_tab},
97 {"untab", uicb_untab},
98 {"viewnexttab", uicb_viewnexttab},
99 {"viewprevtab", uicb_viewprevtab},
100 {NULL, NULL}
103 /** List of keyname and corresponding X11 mask codes */
104 static const KeyMod KeyModList[] =
106 {"Shift", ShiftMask},
107 {"Lock", LockMask},
108 {"Control", ControlMask},
109 {"Mod1", Mod1Mask},
110 {"Mod2", Mod2Mask},
111 {"Mod3", Mod3Mask},
112 {"Mod4", Mod4Mask},
113 {"Mod5", Mod5Mask},
114 {"None", 0}
117 /** List of available layouts and link between name and functions */
118 static const NameFuncLink LayoutsList[] =
120 {"tile", layout_tile},
121 {"tileleft", layout_tileleft},
122 {"max", layout_max},
123 {"floating", layout_floating},
124 {NULL, NULL}
127 /** Lookup for a key mask from its name
128 * \param keyname Key name
129 * \return Key mask or 0 if not found
131 static KeySym
132 key_mask_lookup(const char *keyname)
134 int i;
136 if(keyname)
137 for(i = 0; KeyModList[i].name; i++)
138 if(!a_strcmp(keyname, KeyModList[i].name))
139 return KeyModList[i].keysym;
141 return 0;
144 /** Parse configuration file and initialize some stuff
145 * \param disp Display ref
146 * \param scr Screen number
148 void
149 parse_config(Display * disp, int scr,const char *confpatharg, awesome_config *awesomeconf)
151 static cfg_opt_t general_opts[] =
153 CFG_INT((char *) "border", 1, CFGF_NONE),
154 CFG_INT((char *) "snap", 8, CFGF_NONE),
155 CFG_BOOL((char *) "resize_hints", cfg_false, CFGF_NONE),
156 CFG_INT((char *) "opacity_unfocused", 100, CFGF_NONE),
157 CFG_BOOL((char *) "focus_move_pointer", cfg_false, CFGF_NONE),
158 CFG_BOOL((char *) "allow_lower_floats", cfg_false, CFGF_NONE),
159 CFG_STR((char *) "font", (char *) "mono-12", CFGF_NONE),
160 CFG_END()
162 static cfg_opt_t colors_opts[] =
164 CFG_STR((char *) "normal_border", (char *) "#111111", CFGF_NONE),
165 CFG_STR((char *) "normal_bg", (char *) "#111111", CFGF_NONE),
166 CFG_STR((char *) "normal_fg", (char *) "#eeeeee", CFGF_NONE),
167 CFG_STR((char *) "focus_border", (char *) "#6666ff", CFGF_NONE),
168 CFG_STR((char *) "focus_bg", (char *) "#6666ff", CFGF_NONE),
169 CFG_STR((char *) "focus_fg", (char *) "#ffffff", CFGF_NONE),
170 CFG_STR((char *) "tab_border", (char *) "#ff0000", CFGF_NONE),
171 CFG_END()
173 static cfg_opt_t statusbar_opts[] =
175 CFG_STR((char *) "position", (char *) "top", CFGF_NONE),
176 CFG_END()
178 static cfg_opt_t tag_opts[] =
180 CFG_STR((char *) "layout", (char *) "tile", CFGF_NONE),
181 CFG_END()
183 static cfg_opt_t tags_opts[] =
185 CFG_SEC((char *) "tag", tag_opts, CFGF_TITLE | CFGF_MULTI),
186 CFG_END()
188 static cfg_opt_t layout_opts[] =
190 CFG_STR((char *) "symbol", (char *) "???", CFGF_NONE),
191 CFG_END()
193 static cfg_opt_t layouts_opts[] =
195 CFG_SEC((char *) "layout", layout_opts, CFGF_TITLE | CFGF_MULTI),
196 CFG_FLOAT((char *) "mwfact", 0.5, CFGF_NONE),
197 CFG_INT((char *) "nmaster", 1, CFGF_NONE),
198 CFG_INT((char *) "ncol", 1, CFGF_NONE),
199 CFG_END()
201 static cfg_opt_t rule_opts[] =
203 CFG_STR((char *) "name", (char *) "", CFGF_NONE),
204 CFG_STR((char *) "tags", (char *) "", CFGF_NONE),
205 CFG_BOOL((char *) "float", cfg_false, CFGF_NONE),
206 CFG_END()
208 static cfg_opt_t rules_opts[] =
210 CFG_SEC((char *) "rule", rule_opts, CFGF_MULTI),
211 CFG_END()
213 static cfg_opt_t key_opts[] =
215 CFG_STR_LIST((char *) "modkey", (char *) "{Mod4}", CFGF_NONE),
216 CFG_STR((char *) "key", (char *) "None", CFGF_NONE),
217 CFG_STR((char *) "command", (char *) "", CFGF_NONE),
218 CFG_STR((char *) "arg", NULL, CFGF_NONE),
219 CFG_END()
221 static cfg_opt_t keys_opts[] =
223 CFG_STR((char *) "modkey", (char *) "Mod4", CFGF_NONE),
224 CFG_SEC((char *) "key", key_opts, CFGF_MULTI),
225 CFG_END()
227 static cfg_opt_t opts[] =
229 CFG_SEC((char *) "general", general_opts, CFGF_NONE),
230 CFG_SEC((char *) "colors", colors_opts, CFGF_NONE),
231 CFG_SEC((char *) "statusbar", statusbar_opts, CFGF_NONE),
232 CFG_SEC((char *) "tags", tags_opts, CFGF_NONE),
233 CFG_SEC((char *) "layouts", layouts_opts, CFGF_NONE),
234 CFG_SEC((char *) "rules", rules_opts, CFGF_NONE),
235 CFG_SEC((char *) "keys", keys_opts, CFGF_NONE),
236 CFG_END()
238 cfg_t *cfg, *cfg_general, *cfg_colors, *cfg_statusbar,
239 *cfg_tags, *cfg_layouts, *cfg_rules, *cfg_keys, *cfgsectmp;
240 int i = 0;
241 unsigned int j = 0;
242 int k = 0;
243 const char *tmp, *homedir;
244 char *confpath;
245 KeySym tmp_key;
246 ssize_t confpath_len;
248 if(confpatharg)
249 confpath = a_strdup(confpatharg);
250 else
252 homedir = getenv("HOME");
253 confpath_len = a_strlen(homedir) + a_strlen(AWESOME_CONFIG_FILE) + 2;
254 confpath = p_new(char, confpath_len);
255 a_strcpy(confpath, confpath_len, homedir);
256 a_strcat(confpath, confpath_len, "/");
257 a_strcat(confpath, confpath_len, AWESOME_CONFIG_FILE);
260 a_strcpy(awesomeconf->statustext, sizeof(awesomeconf->statustext), "awesome-" VERSION);
262 /* store display */
263 awesomeconf->display = disp;
265 /* set screen */
266 awesomeconf->screen = scr;
267 awesomeconf->phys_screen = get_phys_screen(disp, scr);
269 cfg = cfg_init(opts, CFGF_NONE);
271 if(cfg_parse(cfg, confpath) == CFG_PARSE_ERROR)
272 fprintf(stderr, "awesome: error parsing configuration file\n");
274 cfg_general = cfg_getsec(cfg, "general");
275 cfg_colors = cfg_getsec(cfg, "colors");
276 cfg_statusbar = cfg_getsec(cfg, "statusbar");
277 cfg_tags = cfg_getsec(cfg, "tags");
278 cfg_layouts = cfg_getsec(cfg, "layouts");
279 cfg_rules = cfg_getsec(cfg, "rules");
280 cfg_keys = cfg_getsec(cfg, "keys");
282 /* General section */
284 awesomeconf->borderpx = cfg_getint(cfg_general, "border");
285 awesomeconf->snap = cfg_getint(cfg_general, "snap");
286 awesomeconf->resize_hints = cfg_getbool(cfg_general, "resize_hints");
287 awesomeconf->opacity_unfocused = cfg_getint(cfg_general, "opacity_unfocused");
288 awesomeconf->focus_move_pointer = cfg_getbool(cfg_general, "focus_move_pointer");
289 awesomeconf->allow_lower_floats = cfg_getbool(cfg_general, "allow_lower_floats");
290 awesomeconf->font = XftFontOpenName(disp, awesomeconf->phys_screen, cfg_getstr(cfg_general, "font"));
291 if(!awesomeconf->font)
292 eprint("awesome: cannot init font\n");
294 /* Colors */
295 awesomeconf->colors_normal[ColBorder] = initxcolor(disp, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "normal_border"));
296 awesomeconf->colors_normal[ColBG] = initxcolor(disp, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "normal_bg"));
297 awesomeconf->colors_normal[ColFG] = initxcolor(disp, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "normal_fg"));
298 awesomeconf->colors_selected[ColBorder] = initxcolor(disp, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "focus_border"));
299 awesomeconf->colors_selected[ColBG] = initxcolor(disp, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "focus_bg"));
300 awesomeconf->colors_selected[ColFG] = initxcolor(disp, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "focus_fg"));
301 awesomeconf->colors_tab[ColBorder] = initxcolor(disp, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "tab_border"));
303 /* Statusbar */
304 tmp = cfg_getstr(cfg_statusbar, "position");
306 if(tmp && !a_strncmp(tmp, "off", 6))
307 awesomeconf->statusbar_default_position = BarOff;
308 else if(tmp && !a_strncmp(tmp, "bottom", 6))
309 awesomeconf->statusbar_default_position = BarBot;
310 else
311 awesomeconf->statusbar_default_position = BarTop;
313 awesomeconf->statusbar.position = awesomeconf->statusbar_default_position;
315 /* Layouts */
317 awesomeconf->nlayouts = cfg_size(cfg_layouts, "layout");
318 awesomeconf->layouts = p_new(Layout, awesomeconf->nlayouts);
319 for(i = 0; i < awesomeconf->nlayouts; i++)
321 cfgsectmp = cfg_getnsec(cfg_layouts, "layout", i);
322 awesomeconf->layouts[i].arrange = name_func_lookup(cfg_title(cfgsectmp), LayoutsList);
323 if(!awesomeconf->layouts[i].arrange)
325 fprintf(stderr, "awesome: unknown layout #%d in configuration file\n", i);
326 awesomeconf->layouts[i].symbol = NULL;
327 continue;
329 awesomeconf->layouts[i].symbol = a_strdup(cfg_getstr(cfgsectmp, "symbol"));
332 awesomeconf->mwfact = cfg_getfloat(cfg_layouts, "mwfact");
333 awesomeconf->nmaster = cfg_getint(cfg_layouts, "nmaster");
334 awesomeconf->ncol = cfg_getint(cfg_layouts, "ncol");
336 if(!awesomeconf->nlayouts)
337 eprint("awesome: fatal: no default layout available\n");
339 /* Rules */
341 awesomeconf->nrules = cfg_size(cfg_rules, "rule");
342 awesomeconf->rules = p_new(Rule, awesomeconf->nrules);
343 for(i = 0; i < awesomeconf->nrules; i++)
345 cfgsectmp = cfg_getnsec(cfg_rules, "rule", i);
346 awesomeconf->rules[i].prop = a_strdup(cfg_getstr(cfgsectmp, "name"));
347 awesomeconf->rules[i].tags = a_strdup(cfg_getstr(cfgsectmp, "tags"));
348 if(!a_strlen(awesomeconf->rules[i].tags))
349 awesomeconf->rules[i].tags = NULL;
350 awesomeconf->rules[i].isfloating = cfg_getbool(cfgsectmp, "float");
353 compileregs(awesomeconf->rules, awesomeconf->nrules);
355 /* Tags */
357 awesomeconf->ntags = cfg_size(cfg_tags, "tag");
358 awesomeconf->tags = p_new(Tag, awesomeconf->ntags);
359 for(i = 0; i < awesomeconf->ntags; i++)
361 cfgsectmp = cfg_getnsec(cfg_tags, "tag", i);
362 awesomeconf->tags[i].name = a_strdup(cfg_title(cfgsectmp));
363 awesomeconf->tags[i].selected = False;
364 awesomeconf->tags[i].was_selected = False;
365 tmp = cfg_getstr(cfgsectmp, "layout");
366 for(k = 0; k < awesomeconf->nlayouts; k++)
367 if(awesomeconf->layouts[k].arrange == name_func_lookup(tmp, LayoutsList))
368 break;
369 if(k == awesomeconf->nlayouts)
370 k = 0;
371 awesomeconf->tags[i].layout = &awesomeconf->layouts[k];
375 if(!awesomeconf->ntags)
376 eprint("awesome: fatal: no tags found in configuration file\n");
378 /* select first tag by default */
379 awesomeconf->current_layout = awesomeconf->tags[0].layout;
380 awesomeconf->tags[0].selected = True;
381 awesomeconf->tags[0].was_selected = True;
383 /* Keys */
384 tmp_key = key_mask_lookup(cfg_getstr(cfg_keys, "modkey"));
385 awesomeconf->modkey = tmp_key ? tmp_key : Mod4Mask;
386 awesomeconf->numlockmask = get_numlockmask(disp);
388 awesomeconf->nkeys = cfg_size(cfg_keys, "key");
389 awesomeconf->keys = p_new(Key, awesomeconf->nkeys);
390 for(i = 0; i < awesomeconf->nkeys; i++)
392 cfgsectmp = cfg_getnsec(cfg_keys, "key", i);
393 for(j = 0; j < cfg_size(cfgsectmp, "modkey"); j++)
394 awesomeconf->keys[i].mod |= key_mask_lookup(cfg_getnstr(cfgsectmp, "modkey", j));
395 awesomeconf->keys[i].keysym = XStringToKeysym(cfg_getstr(cfgsectmp, "key"));
396 awesomeconf->keys[i].func = name_func_lookup(cfg_getstr(cfgsectmp, "command"), UicbList);
397 awesomeconf->keys[i].arg = a_strdup(cfg_getstr(cfgsectmp, "arg"));
400 /* Free! Like a river! */
401 cfg_free(cfg);
402 p_delete(&confpath);
405 static unsigned int
406 get_numlockmask(Display *disp)
408 XModifierKeymap *modmap;
409 unsigned int mask = 0;
410 int i, j;
412 modmap = XGetModifierMapping(disp);
413 for(i = 0; i < 8; i++)
414 for(j = 0; j < modmap->max_keypermod; j++)
416 if(modmap->modifiermap[i * modmap->max_keypermod + j]
417 == XKeysymToKeycode(disp, XK_Num_Lock))
418 mask = (1 << i);
421 XFreeModifiermap(modmap);
423 return mask;
426 /** Initialize color from X side
427 * \param colorstr Color code
428 * \param disp Display ref
429 * \param scr Screen number
430 * \return XColor pixel
432 static XColor
433 initxcolor(Display *disp, int scr, const char *colstr)
435 XColor color;
436 if(!XAllocNamedColor(disp, DefaultColormap(disp, scr), colstr, &color, &color))
437 die("awesome: error, cannot allocate color '%s'\n", colstr);
438 return color;
440 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99