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.
23 * \defgroup ui_callback
27 #include <X11/keysym.h>
35 #include "statusbar.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 */
54 /** Link a name to a mouse button symbol */
61 /** List of available UI bindable callbacks and functions */
62 const NameFuncLink UicbList
[] = {
64 {"spawn", uicb_spawn
},
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
},
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
},
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
},
91 {"tag_setmwfact", uicb_tag_setmwfact
},
92 {"tag_setnmaster", uicb_tag_setnmaster
},
93 {"tag_setncol", uicb_tag_setncol
},
95 {"screen_focusnext", uicb_screen_focusnext
},
96 {"screen_focusprev", uicb_screen_focusprev
},
97 {"client_movetoscreen", uicb_client_movetoscreen
},
101 {"togglebar", uicb_togglebar
},
103 {"reloadconfig", uicb_reloadconfig
},
104 {"setstatustext", uicb_setstatustext
},
106 {"client_movemouse", uicb_client_movemouse
},
107 {"client_resizemouse", uicb_client_resizemouse
},
111 /** List of keyname and corresponding X11 mask codes */
112 static const KeyMod KeyModList
[] =
114 {"Shift", ShiftMask
},
116 {"Control", ControlMask
},
125 /** List of button name and corresponding X11 mask codes */
126 static const MouseButton MouseButtonList
[] =
135 /** List of available layouts and link between name and functions */
136 static const NameFuncLink LayoutsList
[] =
138 {"tile", layout_tile
},
139 {"tileleft", layout_tileleft
},
141 {"floating", layout_floating
},
145 /** Lookup for a key mask from its name
146 * \param keyname Key name
147 * \return Key mask or 0 if not found
150 key_mask_lookup(const char *keyname
)
155 for(i
= 0; KeyModList
[i
].name
; i
++)
156 if(!a_strcmp(keyname
, KeyModList
[i
].name
))
157 return KeyModList
[i
].keysym
;
162 /** Lookup for a mouse button from its name
163 * \param button Mouse button name
164 * \return Mouse button or 0 if not found
167 mouse_button_lookup(const char *button
)
172 for(i
= 0; MouseButtonList
[i
].name
; i
++)
173 if(!a_strcmp(button
, MouseButtonList
[i
].name
))
174 return MouseButtonList
[i
].button
;
180 parse_mouse_bindings(cfg_t
* cfg
, const char *secname
, Bool handle_arg
)
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 */
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
);
199 b
->arg
= a_strdup(cfg_getstr(cfgsectmp
, "arg"));
203 /* switch to next elem or finalize the list */
204 if(i
< cfg_size(cfg
, secname
) - 1)
206 b
->next
= p_new(Button
, 1);
216 /** Parse configuration file and initialize some stuff
217 * \param disp Display ref
218 * \param scr Screen number
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
),
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
),
245 static cfg_opt_t statusbar_opts
[] =
247 CFG_STR((char *) "position", (char *) "top", CFGF_NONE
),
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
),
258 static cfg_opt_t tags_opts
[] =
260 CFG_SEC((char *) "tag", tag_opts
, CFGF_TITLE
| CFGF_MULTI
),
263 static cfg_opt_t layout_opts
[] =
265 CFG_STR((char *) "symbol", (char *) "???", CFGF_NONE
),
268 static cfg_opt_t layouts_opts
[] =
270 CFG_SEC((char *) "layout", layout_opts
, CFGF_TITLE
| CFGF_MULTI
),
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
),
289 static cfg_opt_t rules_opts
[] =
291 CFG_SEC((char *) "rule", rule_opts
, CFGF_MULTI
),
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
),
302 static cfg_opt_t keys_opts
[] =
304 CFG_SEC((char *) "key", key_opts
, CFGF_MULTI
),
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
),
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
),
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
;
349 confpath
= a_strdup(confpatharg
);
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
);
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");
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"));
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
;
424 awesomeconf
->statusbar
.dposition
= BarTop
;
426 awesomeconf
->statusbar
.position
= awesomeconf
->statusbar
.dposition
;
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
;
441 awesomeconf
->layouts
[i
].symbol
= a_strdup(cfg_getstr(cfgsectmp
, "symbol"));
444 if(!awesomeconf
->nlayouts
)
445 eprint("awesome: fatal: no default layout available\n");
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
))
458 rule
->isfloating
= cfg_getbool(cfgsectmp
, "float");
459 rule
->screen
= cfg_getint(cfgsectmp
, "screen");
460 if(rule
->screen
>= get_screen_count(awesomeconf
->display
))
463 if(j
< cfg_size(cfg_rules
, "rule") - 1)
465 rule
->next
= p_new(Rule
, 1);
473 awesomeconf
->rules
= NULL
;
475 compileregs(awesomeconf
->rules
);
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
))
490 if(k
== awesomeconf
->nlayouts
)
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
;
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
);
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);
550 awesomeconf
->keys
= NULL
;
552 /* Free! Like a river! */
558 get_numlockmask(Display
*disp
)
560 XModifierKeymap
*modmap
;
561 unsigned int mask
= 0;
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
))
571 XFreeModifiermap(modmap
);
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
583 initxcolor(Display
*disp
, int scr
, const char *colstr
)
586 if(!XAllocNamedColor(disp
, DefaultColormap(disp
, scr
), colstr
, &color
, &color
))
587 die("awesome: error, cannot allocate color '%s'\n", colstr
);
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
;
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
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
;
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
)
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
]);
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