rename screen uicb correctly
[awesome.git] / config.c
blob60ef3e745cc4dfd0a91a4b5978477873afc07f2e
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 "rules.h"
35 #include "statusbar.h"
36 #include "layout.h"
37 #include "mouse.h"
38 #include "layouts/tile.h"
39 #include "layouts/floating.h"
40 #include "layouts/max.h"
42 #define AWESOME_CONFIG_FILE ".awesomerc"
44 static XColor initxcolor(Display *, int, const char *);
45 static unsigned int get_numlockmask(Display *);
47 /** Link a name to a key symbol */
48 typedef struct
50 const char *name;
51 KeySym keysym;
52 } KeyMod;
54 /** Link a name to a mouse button symbol */
55 typedef struct
57 const char *name;
58 unsigned int button;
59 } MouseButton;
61 /** List of available UI bindable callbacks and functions */
62 const NameFuncLink UicbList[] = {
63 /* util.c */
64 {"spawn", uicb_spawn},
65 {"exec", uicb_exec},
66 /* client.c */
67 {"client_kill", uicb_client_kill},
68 {"client_moveresize", uicb_client_moveresize},
69 {"client_settrans", uicb_client_settrans},
70 {"setborder", uicb_setborder},
71 {"client_swapnext", uicb_client_swapnext},
72 {"client_swapprev", uicb_client_swapprev},
73 /* tag.c */
74 {"client_tag", uicb_client_tag},
75 {"client_togglefloating", uicb_client_togglefloating},
76 {"tag_toggleview", uicb_tag_toggleview},
77 {"client_toggletag", uicb_client_toggletag},
78 {"tag_view", uicb_tag_view},
79 {"tag_view_prev_selected", uicb_tag_prev_selected},
80 {"tag_view_prev", uicb_tag_viewprev},
81 {"tag_view_next", uicb_tag_viewnext},
82 /* layout.c */
83 {"setlayout", uicb_setlayout},
84 {"client_focusnext", uicb_client_focusnext},
85 {"client_focusprev", uicb_client_focusprev},
86 {"client_togglemax", uicb_client_togglemax},
87 {"client_toggleverticalmax", uicb_client_toggleverticalmax},
88 {"client_togglehorizontalmax", uicb_client_togglehorizontalmax},
89 {"client_zoom", uicb_client_zoom},
90 /* layouts/tile.c */
91 {"tag_setmwfact", uicb_tag_setmwfact},
92 {"tag_setnmaster", uicb_tag_setnmaster},
93 {"tag_setncol", uicb_tag_setncol},
94 /* screen.c */
95 {"screen_focusnext", uicb_screen_focusnext},
96 {"screen_focusprev", uicb_screen_focusprev},
97 {"client_movetoscreen", uicb_client_movetoscreen},
98 /* awesome.c */
99 {"quit", uicb_quit},
100 /* statusbar.c */
101 {"togglebar", uicb_togglebar},
102 /* config.c */
103 {"reloadconfig", uicb_reloadconfig},
104 {"setstatustext", uicb_setstatustext},
105 /* mouse.c */
106 {"client_movemouse", uicb_client_movemouse},
107 {"client_resizemouse", uicb_client_resizemouse},
108 {NULL, NULL}
111 /** List of keyname and corresponding X11 mask codes */
112 static const KeyMod KeyModList[] =
114 {"Shift", ShiftMask},
115 {"Lock", LockMask},
116 {"Control", ControlMask},
117 {"Mod1", Mod1Mask},
118 {"Mod2", Mod2Mask},
119 {"Mod3", Mod3Mask},
120 {"Mod4", Mod4Mask},
121 {"Mod5", Mod5Mask},
122 {NULL, NoSymbol}
125 /** List of button name and corresponding X11 mask codes */
126 static const MouseButton MouseButtonList[] =
128 {"1", Button1},
129 {"2", Button2},
130 {"3", Button3},
131 {"4", Button4},
132 {"5", Button5},
133 {NULL, 0}
135 /** List of available layouts and link between name and functions */
136 static const NameFuncLink LayoutsList[] =
138 {"tile", layout_tile},
139 {"tileleft", layout_tileleft},
140 {"max", layout_max},
141 {"floating", layout_floating},
142 {NULL, NULL}
145 /** Lookup for a key mask from its name
146 * \param keyname Key name
147 * \return Key mask or 0 if not found
149 static KeySym
150 key_mask_lookup(const char *keyname)
152 int i;
154 if(keyname)
155 for(i = 0; KeyModList[i].name; i++)
156 if(!a_strcmp(keyname, KeyModList[i].name))
157 return KeyModList[i].keysym;
159 return NoSymbol;
162 /** Lookup for a mouse button from its name
163 * \param button Mouse button name
164 * \return Mouse button or 0 if not found
166 static unsigned int
167 mouse_button_lookup(const char *button)
169 int i;
171 if(button)
172 for(i = 0; MouseButtonList[i].name; i++)
173 if(!a_strcmp(button, MouseButtonList[i].name))
174 return MouseButtonList[i].button;
176 return 0;
179 static Button *
180 parse_mouse_bindings(cfg_t * cfg, const char *secname, Bool handle_arg)
182 unsigned int i, j;
183 cfg_t *cfgsectmp;
184 Button *b = NULL, *head = NULL;
186 /* Mouse: layout click bindings */
187 for(i = 0; i < cfg_size(cfg, secname); i++)
189 /* init first elem */
190 if(i == 0)
191 head = b = p_new(Button, 1);
193 cfgsectmp = cfg_getnsec(cfg, secname, i);
194 for(j = 0; j < cfg_size(cfgsectmp, "modkey"); j++)
195 b->mod |= key_mask_lookup(cfg_getnstr(cfgsectmp, "modkey", j));
196 b->button = mouse_button_lookup(cfg_getstr(cfgsectmp, "button"));
197 b->func = name_func_lookup(cfg_getstr(cfgsectmp, "command"), UicbList);
198 if(handle_arg)
199 b->arg = a_strdup(cfg_getstr(cfgsectmp, "arg"));
200 else
201 b->arg = NULL;
203 /* switch to next elem or finalize the list */
204 if(i < cfg_size(cfg, secname) - 1)
206 b->next = p_new(Button, 1);
207 b = b->next;
209 else
210 b->next = NULL;
213 return head;
216 /** Parse configuration file and initialize some stuff
217 * \param disp Display ref
218 * \param scr Screen number
220 void
221 parse_config(const char *confpatharg, awesome_config *awesomeconf)
223 static cfg_opt_t general_opts[] =
225 CFG_INT((char *) "border", 1, CFGF_NONE),
226 CFG_INT((char *) "snap", 8, CFGF_NONE),
227 CFG_BOOL((char *) "resize_hints", cfg_false, CFGF_NONE),
228 CFG_INT((char *) "opacity_unfocused", 100, CFGF_NONE),
229 CFG_BOOL((char *) "focus_move_pointer", cfg_false, CFGF_NONE),
230 CFG_BOOL((char *) "allow_lower_floats", cfg_false, CFGF_NONE),
231 CFG_STR((char *) "font", (char *) "mono-12", CFGF_NONE),
232 CFG_END()
234 static cfg_opt_t colors_opts[] =
236 CFG_STR((char *) "normal_border", (char *) "#111111", CFGF_NONE),
237 CFG_STR((char *) "normal_bg", (char *) "#111111", CFGF_NONE),
238 CFG_STR((char *) "normal_fg", (char *) "#eeeeee", CFGF_NONE),
239 CFG_STR((char *) "focus_border", (char *) "#6666ff", CFGF_NONE),
240 CFG_STR((char *) "focus_bg", (char *) "#6666ff", CFGF_NONE),
241 CFG_STR((char *) "focus_fg", (char *) "#ffffff", CFGF_NONE),
242 CFG_STR((char *) "tab_border", (char *) "#ff0000", CFGF_NONE),
243 CFG_END()
245 static cfg_opt_t statusbar_opts[] =
247 CFG_STR((char *) "position", (char *) "top", CFGF_NONE),
248 CFG_END()
250 static cfg_opt_t tag_opts[] =
252 CFG_STR((char *) "layout", (char *) "tile", CFGF_NONE),
253 CFG_FLOAT((char *) "mwfact", 0.5, CFGF_NONE),
254 CFG_INT((char *) "nmaster", 1, CFGF_NONE),
255 CFG_INT((char *) "ncol", 1, CFGF_NONE),
256 CFG_END()
258 static cfg_opt_t tags_opts[] =
260 CFG_SEC((char *) "tag", tag_opts, CFGF_TITLE | CFGF_MULTI),
261 CFG_END()
263 static cfg_opt_t layout_opts[] =
265 CFG_STR((char *) "symbol", (char *) "???", CFGF_NONE),
266 CFG_END()
268 static cfg_opt_t layouts_opts[] =
270 CFG_SEC((char *) "layout", layout_opts, CFGF_TITLE | CFGF_MULTI),
271 CFG_END()
273 static cfg_opt_t screen_opts[] =
275 CFG_SEC((char *) "general", general_opts, CFGF_NONE),
276 CFG_SEC((char *) "statusbar", statusbar_opts, CFGF_NONE),
277 CFG_SEC((char *) "tags", tags_opts, CFGF_NONE),
278 CFG_SEC((char *) "colors", colors_opts, CFGF_NONE),
279 CFG_SEC((char *) "layouts", layouts_opts, CFGF_NONE),
281 static cfg_opt_t rule_opts[] =
283 CFG_STR((char *) "name", (char *) "", CFGF_NONE),
284 CFG_STR((char *) "tags", (char *) "", CFGF_NONE),
285 CFG_BOOL((char *) "float", cfg_false, CFGF_NONE),
286 CFG_INT((char *) "screen", RULE_NOSCREEN, CFGF_NONE),
287 CFG_END()
289 static cfg_opt_t rules_opts[] =
291 CFG_SEC((char *) "rule", rule_opts, CFGF_MULTI),
292 CFG_END()
294 static cfg_opt_t key_opts[] =
296 CFG_STR_LIST((char *) "modkey", (char *) "{Mod4}", CFGF_NONE),
297 CFG_STR((char *) "key", (char *) "None", CFGF_NONE),
298 CFG_STR((char *) "command", (char *) "", CFGF_NONE),
299 CFG_STR((char *) "arg", NULL, CFGF_NONE),
300 CFG_END()
302 static cfg_opt_t keys_opts[] =
304 CFG_SEC((char *) "key", key_opts, CFGF_MULTI),
305 CFG_END()
307 static cfg_opt_t mouse_tag_opts[] =
309 CFG_STR_LIST((char *) "modkey", (char *) "{}", CFGF_NONE),
310 CFG_STR((char *) "button", (char *) "None", CFGF_NONE),
311 CFG_STR((char *) "command", (char *) "", CFGF_NONE),
313 static cfg_opt_t mouse_generic_opts[] =
315 CFG_STR_LIST((char *) "modkey", (char *) "{}", CFGF_NONE),
316 CFG_STR((char *) "button", (char *) "None", CFGF_NONE),
317 CFG_STR((char *) "command", (char *) "", CFGF_NONE),
318 CFG_STR((char *) "arg", NULL, CFGF_NONE),
320 static cfg_opt_t mouse_opts[] =
322 CFG_STR((char *) "modkey", (char *) "Mod4", CFGF_NONE),
323 CFG_SEC((char *) "tag", mouse_tag_opts, CFGF_MULTI),
324 CFG_SEC((char *) "layout", mouse_generic_opts, CFGF_MULTI),
325 CFG_SEC((char *) "title", mouse_generic_opts, CFGF_MULTI),
326 CFG_SEC((char *) "root", mouse_generic_opts, CFGF_MULTI),
327 CFG_SEC((char *) "client", mouse_generic_opts, CFGF_MULTI),
328 CFG_END()
330 static cfg_opt_t opts[] =
332 CFG_SEC((char *) "screen", screen_opts, CFGF_TITLE | CFGF_MULTI),
333 CFG_SEC((char *) "rules", rules_opts, CFGF_NONE),
334 CFG_SEC((char *) "keys", keys_opts, CFGF_NONE),
335 CFG_SEC((char *) "mouse", mouse_opts, CFGF_NONE),
336 CFG_END()
338 cfg_t *cfg, *cfg_general, *cfg_colors, *cfg_screen, *cfg_statusbar,
339 *cfg_tags, *cfg_layouts, *cfg_rules, *cfg_keys, *cfg_mouse, *cfgsectmp;
340 int i = 0, k = 0, ret;
341 unsigned int j = 0, l = 0;
342 const char *tmp, *homedir;
343 char *confpath, buf[2];
344 ssize_t confpath_len;
345 Key *key = NULL;
346 Rule *rule = NULL;
348 if(confpatharg)
349 confpath = a_strdup(confpatharg);
350 else
352 homedir = getenv("HOME");
353 confpath_len = a_strlen(homedir) + a_strlen(AWESOME_CONFIG_FILE) + 2;
354 confpath = p_new(char, confpath_len);
355 a_strcpy(confpath, confpath_len, homedir);
356 a_strcat(confpath, confpath_len, "/");
357 a_strcat(confpath, confpath_len, AWESOME_CONFIG_FILE);
360 awesomeconf->configpath = a_strdup(confpath);
362 a_strcpy(awesomeconf->statustext, sizeof(awesomeconf->statustext), "awesome-" VERSION " (" RELEASE ")");
364 awesomeconf->phys_screen = get_phys_screen(awesomeconf->display, awesomeconf->screen);
366 cfg = cfg_init(opts, CFGF_NONE);
368 ret = cfg_parse(cfg, confpath);
369 if(ret == CFG_FILE_ERROR)
370 perror("awesome: parsing configuration file failed");
371 else if(ret == CFG_PARSE_ERROR)
372 cfg_error(cfg, "awesome: parsing configuration file %s failed.\n", confpath);
374 /* get the right screen section */
375 snprintf(buf, sizeof(buf), "%d", awesomeconf->screen);
376 cfg_screen = cfg_gettsec(cfg, "screen", buf);
377 if(!cfg_screen)
378 cfg_screen = cfg_getsec(cfg, "screen");
380 /* get screen specific sections */
381 cfg_statusbar = cfg_getsec(cfg_screen, "statusbar");
382 cfg_tags = cfg_getsec(cfg_screen, "tags");
383 cfg_colors = cfg_getsec(cfg_screen, "colors");
384 cfg_general = cfg_getsec(cfg_screen, "general");
385 cfg_layouts = cfg_getsec(cfg_screen, "layouts");
387 /* get general sections */
388 cfg_rules = cfg_getsec(cfg, "rules");
389 cfg_keys = cfg_getsec(cfg, "keys");
390 cfg_mouse = cfg_getsec(cfg, "mouse");
392 /* General section */
394 awesomeconf->borderpx = cfg_getint(cfg_general, "border");
395 awesomeconf->snap = cfg_getint(cfg_general, "snap");
396 awesomeconf->resize_hints = cfg_getbool(cfg_general, "resize_hints");
397 awesomeconf->opacity_unfocused = cfg_getint(cfg_general, "opacity_unfocused");
398 awesomeconf->focus_move_pointer = cfg_getbool(cfg_general, "focus_move_pointer");
399 awesomeconf->allow_lower_floats = cfg_getbool(cfg_general, "allow_lower_floats");
400 awesomeconf->font = XftFontOpenName(awesomeconf->display, awesomeconf->phys_screen, cfg_getstr(cfg_general, "font"));
401 if(!awesomeconf->font)
402 eprint("awesome: cannot init font\n");
404 /* Colors */
405 awesomeconf->colors_normal[ColBorder] = initxcolor(awesomeconf->display, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "normal_border"));
406 awesomeconf->colors_normal[ColBG] = initxcolor(awesomeconf->display, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "normal_bg"));
407 awesomeconf->colors_normal[ColFG] = initxcolor(awesomeconf->display, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "normal_fg"));
408 awesomeconf->colors_selected[ColBorder] = initxcolor(awesomeconf->display, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "focus_border"));
409 awesomeconf->colors_selected[ColBG] = initxcolor(awesomeconf->display, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "focus_bg"));
410 awesomeconf->colors_selected[ColFG] = initxcolor(awesomeconf->display, awesomeconf->phys_screen, cfg_getstr(cfg_colors, "focus_fg"));
412 /* Statusbar */
413 tmp = cfg_getstr(cfg_statusbar, "position");
415 if(tmp && !a_strncmp(tmp, "off", 6))
416 awesomeconf->statusbar.dposition = BarOff;
417 else if(tmp && !a_strncmp(tmp, "bottom", 6))
418 awesomeconf->statusbar.dposition = BarBot;
419 else if(tmp && !a_strncmp(tmp, "right", 5))
420 awesomeconf->statusbar.dposition = BarRight;
421 else if(tmp && !a_strncmp(tmp, "left", 4))
422 awesomeconf->statusbar.dposition = BarLeft;
423 else
424 awesomeconf->statusbar.dposition = BarTop;
426 awesomeconf->statusbar.position = awesomeconf->statusbar.dposition;
428 /* Layouts */
429 awesomeconf->nlayouts = cfg_size(cfg_layouts, "layout");
430 awesomeconf->layouts = p_new(Layout, awesomeconf->nlayouts);
431 for(i = 0; i < awesomeconf->nlayouts; i++)
433 cfgsectmp = cfg_getnsec(cfg_layouts, "layout", i);
434 awesomeconf->layouts[i].arrange = name_func_lookup(cfg_title(cfgsectmp), LayoutsList);
435 if(!awesomeconf->layouts[i].arrange)
437 fprintf(stderr, "awesome: unknown layout #%d in configuration file\n", i);
438 awesomeconf->layouts[i].symbol = NULL;
439 continue;
441 awesomeconf->layouts[i].symbol = a_strdup(cfg_getstr(cfgsectmp, "symbol"));
444 if(!awesomeconf->nlayouts)
445 eprint("awesome: fatal: no default layout available\n");
447 /* Rules */
448 if(cfg_size(cfg_rules, "rule"))
450 awesomeconf->rules = rule = p_new(Rule, 1);
451 for(j = 0; j < cfg_size(cfg_rules, "rule"); j++)
453 cfgsectmp = cfg_getnsec(cfg_rules, "rule", j);
454 rule->prop = a_strdup(cfg_getstr(cfgsectmp, "name"));
455 rule->tags = a_strdup(cfg_getstr(cfgsectmp, "tags"));
456 if(!a_strlen(rule->tags))
457 rule->tags = NULL;
458 rule->isfloating = cfg_getbool(cfgsectmp, "float");
459 rule->screen = cfg_getint(cfgsectmp, "screen");
460 if(rule->screen >= get_screen_count(awesomeconf->display))
461 rule->screen = 0;
463 if(j < cfg_size(cfg_rules, "rule") - 1)
465 rule->next = p_new(Rule, 1);
466 rule = rule->next;
468 else
469 rule->next = NULL;
472 else
473 awesomeconf->rules = NULL;
475 compileregs(awesomeconf->rules);
477 /* Tags */
478 awesomeconf->ntags = cfg_size(cfg_tags, "tag");
479 awesomeconf->tags = p_new(Tag, awesomeconf->ntags);
480 for(i = 0; i < awesomeconf->ntags; i++)
482 cfgsectmp = cfg_getnsec(cfg_tags, "tag", i);
483 awesomeconf->tags[i].name = a_strdup(cfg_title(cfgsectmp));
484 awesomeconf->tags[i].selected = False;
485 awesomeconf->tags[i].was_selected = False;
486 tmp = cfg_getstr(cfgsectmp, "layout");
487 for(k = 0; k < awesomeconf->nlayouts; k++)
488 if(awesomeconf->layouts[k].arrange == name_func_lookup(tmp, LayoutsList))
489 break;
490 if(k == awesomeconf->nlayouts)
491 k = 0;
492 awesomeconf->tags[i].layout = &awesomeconf->layouts[k];
493 awesomeconf->tags[i].mwfact = cfg_getfloat(cfgsectmp, "mwfact");
494 awesomeconf->tags[i].nmaster = cfg_getint(cfgsectmp, "nmaster");
495 awesomeconf->tags[i].ncol = cfg_getint(cfgsectmp, "ncol");
499 if(!awesomeconf->ntags)
500 eprint("awesome: fatal: no tags found in configuration file\n");
502 /* select first tag by default */
503 awesomeconf->tags[0].selected = True;
504 awesomeconf->tags[0].was_selected = True;
506 /* Mouse */
507 if(!(awesomeconf->modkey = key_mask_lookup(cfg_getstr(cfg_mouse, "modkey"))))
508 awesomeconf->modkey = Mod4Mask;
510 /* Mouse: tags click bindings */
511 awesomeconf->buttons.tag = parse_mouse_bindings(cfg_mouse, "tag", False);
513 /* Mouse: layout click bindings */
514 awesomeconf->buttons.layout = parse_mouse_bindings(cfg_mouse, "layout", True);
516 /* Mouse: title click bindings */
517 awesomeconf->buttons.title = parse_mouse_bindings(cfg_mouse, "title", True);
519 /* Mouse: root window click bindings */
520 awesomeconf->buttons.root = parse_mouse_bindings(cfg_mouse, "root", True);
522 /* Mouse: client windows click bindings */
523 awesomeconf->buttons.client = parse_mouse_bindings(cfg_mouse, "client", True);
525 /* Keys */
526 awesomeconf->numlockmask = get_numlockmask(awesomeconf->display);
528 if(cfg_size(cfg_keys, "key"))
530 awesomeconf->keys = key = p_new(Key, 1);
531 for(j = 0; j < cfg_size(cfg_keys, "key"); j++)
533 cfgsectmp = cfg_getnsec(cfg_keys, "key", j);
534 for(l = 0; l < cfg_size(cfgsectmp, "modkey"); l++)
535 key->mod |= key_mask_lookup(cfg_getnstr(cfgsectmp, "modkey", l));
536 key->keysym = XStringToKeysym(cfg_getstr(cfgsectmp, "key"));
537 key->func = name_func_lookup(cfg_getstr(cfgsectmp, "command"), UicbList);
538 key->arg = a_strdup(cfg_getstr(cfgsectmp, "arg"));
540 if(j < cfg_size(cfg_keys, "key") - 1)
542 key->next = p_new(Key, 1);
543 key = key->next;
545 else
546 key->next = NULL;
549 else
550 awesomeconf->keys = NULL;
552 /* Free! Like a river! */
553 cfg_free(cfg);
554 p_delete(&confpath);
557 static unsigned int
558 get_numlockmask(Display *disp)
560 XModifierKeymap *modmap;
561 unsigned int mask = 0;
562 int i, j;
564 modmap = XGetModifierMapping(disp);
565 for(i = 0; i < 8; i++)
566 for(j = 0; j < modmap->max_keypermod; j++)
567 if(modmap->modifiermap[i * modmap->max_keypermod + j]
568 == XKeysymToKeycode(disp, XK_Num_Lock))
569 mask = (1 << i);
571 XFreeModifiermap(modmap);
573 return mask;
576 /** Initialize color from X side
577 * \param colorstr Color code
578 * \param disp Display ref
579 * \param scr Screen number
580 * \return XColor pixel
582 static XColor
583 initxcolor(Display *disp, int scr, const char *colstr)
585 XColor color;
586 if(!XAllocNamedColor(disp, DefaultColormap(disp, scr), colstr, &color, &color))
587 die("awesome: error, cannot allocate color '%s'\n", colstr);
588 return color;
591 void
592 uicb_reloadconfig(awesome_config *awesomeconf,
593 const char *arg __attribute__ ((unused)))
595 int i, j, tag, screen, screen_count = get_screen_count(awesomeconf->display);
596 awesome_config *awesomeconf_first = &awesomeconf[-awesomeconf->screen];
597 int *old_ntags, old_c_ntags, new_c_ntags, **mapping;
598 char ***savetagnames;
599 Client ***savetagclientsel;
600 char *configpath = a_strdup(awesomeconf_first->configpath);
601 Bool ***savetagselected;
602 Bool *old_c_tags;
603 Client *c, *clients;
605 /* Save tag information */
606 savetagnames = p_new(char **, screen_count);
607 savetagclientsel = p_new(Client **, screen_count);
608 savetagselected = p_new(Bool **, screen_count);
609 clients = *awesomeconf_first->clients;
610 for (screen = 0; screen < screen_count; screen ++)
612 savetagnames[screen] = p_new(char *, awesomeconf_first[screen].ntags);
613 savetagclientsel[screen] = p_new(Client *, awesomeconf_first[screen].ntags);
614 savetagselected[screen] = p_new(Bool *, awesomeconf_first[screen].ntags);
615 for (tag = 0; tag < awesomeconf_first[screen].ntags; tag++)
617 savetagnames[screen][tag] = a_strdup(awesomeconf_first[screen].tags[tag].name);
618 savetagclientsel[screen][tag] = awesomeconf_first[screen].tags[tag].client_sel;
619 savetagselected[screen][tag] = p_new(Bool, 2);
620 savetagselected[screen][tag][0] = awesomeconf_first[screen].tags[tag].selected;
621 savetagselected[screen][tag][1] = awesomeconf_first[screen].tags[tag].was_selected;
624 old_ntags = p_new(int, screen_count);
625 for (screen = 0; screen < screen_count; screen ++)
626 old_ntags[screen] = awesomeconf_first[screen].ntags;
628 mapping = p_new(int*, screen_count);
629 for(screen = 0; screen < screen_count; screen++)
631 /* Cleanup screens and reload their config. */
632 cleanup_screen(&awesomeconf_first[screen]);
633 setup_screen(&awesomeconf_first[screen], configpath);
635 /* Compute a mapping of tags between the old and new config, based on
636 * tag names. */
637 mapping[screen] = p_new(int, awesomeconf_first[screen].ntags);
638 for (i = 0; i < awesomeconf_first[screen].ntags; i ++)
640 mapping[screen][i] = -1;
641 for (j = 0; j < old_ntags[screen]; j ++)
642 if (!a_strcmp(savetagnames[screen][j], awesomeconf_first[screen].tags[i].name))
644 mapping[screen][i] = j;
645 break;
649 /* Reinitialize the tags' client lists and selected client. */
650 *awesomeconf_first[screen].clients = clients;
651 for (tag = 0; tag < awesomeconf_first[screen].ntags; tag++)
652 if (mapping[screen][tag] >= 0)
654 awesomeconf_first[screen].tags[tag].client_sel = savetagclientsel[screen][mapping[screen][tag]];
655 awesomeconf_first[screen].tags[tag].selected = savetagselected[screen][mapping[screen][tag]][0];
656 awesomeconf_first[screen].tags[tag].was_selected = savetagselected[screen][mapping[screen][tag]][1];
658 drawstatusbar(&awesomeconf_first[screen]);
661 /* Reinitialize the 'tags' array of each client.
662 * Clients are assigned to the tags of the same name as in the previous
663 * awesomerc, or to tag #1 otherwise. */
664 for (c = *awesomeconf_first->clients; c; c = c->next)
666 old_c_ntags = old_ntags[c->screen];
667 new_c_ntags = awesomeconf_first[c->screen].ntags;
669 old_c_tags = c->tags;
670 c->tags = p_new(Bool, new_c_ntags);
671 for (i = 0; i < new_c_ntags; i ++)
672 if (mapping[c->screen][i] >= 0)
673 c->tags[i] = old_c_tags[mapping[c->screen][i]];
674 p_delete(&old_c_tags);
676 for (i = 0; i < new_c_ntags && c->tags[i] == 0; i++) {}
677 if (i == new_c_ntags)
678 c->tags[0] = 1;
680 saveprops(c, awesomeconf_first[c->screen].ntags);
683 /* Cleanup after ourselves */
684 for(screen = 0; screen < screen_count; screen++)
686 for(i = 0; i < old_ntags[screen]; i++)
688 p_delete(&savetagnames[screen][i]);
689 p_delete(&savetagselected[screen][i]);
691 p_delete(&savetagselected[screen]);
692 p_delete(&savetagnames[screen]);
693 p_delete(&mapping[screen]);
694 p_delete(&savetagclientsel[screen]);
696 p_delete(&mapping);
697 p_delete(&savetagselected);
698 p_delete(&savetagnames);
699 p_delete(&old_ntags);
700 p_delete(&savetagclientsel);
701 p_delete(&configpath);
702 for (screen = 0; screen < screen_count; screen ++)
703 arrange(&awesomeconf_first[screen]);
706 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99