config.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /*
  2. * wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
  3. * For license, see COPYING.
  4. */
  5. #include "config.h"
  6. #include "wmfs.h"
  7. #include "parse.h"
  8. #include "tag.h"
  9. #include "screen.h"
  10. #include "infobar.h"
  11. #include "util.h"
  12. #include "status.h"
  13. #define ISTRDUP(t, s) \
  14. do { \
  15. if((tmp = s)) \
  16. t = xstrdup(tmp); \
  17. } while(/* CONSTCOND */ 0);
  18. static void
  19. config_mouse_section(struct mbhead *mousebinds, struct conf_sec **sec)
  20. {
  21. struct mousebind *m;
  22. int i = 0;
  23. char *p;
  24. SLIST_INIT(mousebinds);
  25. for(; sec[i]; ++i)
  26. {
  27. m = xcalloc(1, sizeof(struct mousebind));
  28. m->button = fetch_opt_first(sec[i], "1", "button").num;
  29. m->func = uicb_name_func(fetch_opt_first(sec[i], "", "func").str);
  30. if((p = fetch_opt_first(sec[i], "", "cmd").str))
  31. m->cmd = xstrdup(p);
  32. m->use_area = false;
  33. SLIST_INSERT_HEAD(mousebinds, m, next);
  34. SLIST_INSERT_HEAD(&W->h.mousebind, m, globnext);
  35. }
  36. }
  37. static void
  38. config_theme(void)
  39. {
  40. struct theme *t, *p = NULL;
  41. size_t i, n;
  42. struct conf_sec *sec, **ks;
  43. char *tmp;
  44. /* [themes] */
  45. sec = fetch_section_first(NULL, "themes");
  46. ks = fetch_section(sec, "theme");
  47. /* No theme section? Make one with default value anyway. */
  48. if(!(n = fetch_section_count(ks)))
  49. ++n;
  50. SLIST_INIT(&W->h.theme);
  51. /* [theme]*/
  52. for(i = 0; i < n; ++i)
  53. {
  54. t = (struct theme*)xcalloc(1, sizeof(struct theme));
  55. t->name = fetch_opt_first(ks[i], "default", "name").str;
  56. wmfs_init_font(fetch_opt_first(ks[i], "fixed", "font").str, t);
  57. /* bars */
  58. t->bars.fg = color_atoh(fetch_opt_first(ks[i], "#CCCCCC", "bars_fg").str);
  59. t->bars.bg = color_atoh(fetch_opt_first(ks[i], "#222222", "bars_bg").str);
  60. t->bars_width = fetch_opt_first(ks[i], "12", "bars_width").num;
  61. /*
  62. * Elements
  63. */
  64. t->tags_n.fg = color_atoh(fetch_opt_first(ks[i], "#CCCCCC", "tags_normal_fg").str);
  65. t->tags_n.bg = color_atoh(fetch_opt_first(ks[i], "#222222", "tags_normal_bg").str);
  66. t->tags_s.fg = color_atoh(fetch_opt_first(ks[i], "#222222", "tags_sel_fg").str);
  67. t->tags_s.bg = color_atoh(fetch_opt_first(ks[i], "#CCCCCC", "tags_sel_bg").str);
  68. t->tags_o.fg = color_atoh(fetch_opt_first(ks[i], "#CCCCCC", "tags_occupied_fg").str);
  69. t->tags_o.bg = color_atoh(fetch_opt_first(ks[i], "#444444", "tags_occupied_bg").str);
  70. t->tags_u.fg = color_atoh(fetch_opt_first(ks[i], "#444444", "tags_urgent_fg").str);
  71. t->tags_u.bg = color_atoh(fetch_opt_first(ks[i], "#CC4444", "tags_urgent_bg").str);
  72. t->tags_border_col = color_atoh(fetch_opt_first(ks[i], "#888888", "tags_border_color").str);
  73. t->tags_border_width = fetch_opt_first(ks[i], "0", "tags_border_width").num;
  74. /* status line */
  75. t->tags_n_sl = status_new_ctx(NULL, t);
  76. t->tags_s_sl = status_new_ctx(NULL, t);
  77. t->tags_o_sl = status_new_ctx(NULL, t);
  78. t->tags_u_sl = status_new_ctx(NULL, t);
  79. ISTRDUP(t->tags_n_sl.status, fetch_opt_first(ks[i], "", "tags_normal_statusline").str);
  80. ISTRDUP(t->tags_s_sl.status, fetch_opt_first(ks[i], "", "tags_sel_statusline").str);
  81. ISTRDUP(t->tags_o_sl.status, fetch_opt_first(ks[i], "", "tags_occupied_statusline").str);
  82. ISTRDUP(t->tags_u_sl.status, fetch_opt_first(ks[i], "", "tags_urgent_statusline").str);
  83. if(t->tags_n_sl.status)
  84. status_parse(&t->tags_n_sl);
  85. if(t->tags_s_sl.status)
  86. status_parse(&t->tags_s_sl);
  87. if(t->tags_o_sl.status)
  88. status_parse(&t->tags_o_sl);
  89. if(t->tags_u_sl.status)
  90. status_parse(&t->tags_u_sl);
  91. /* Client / frame */
  92. t->client_n.fg = color_atoh(fetch_opt_first(ks[i], "#CCCCCC", "client_normal_fg").str);
  93. t->client_n.bg = color_atoh(fetch_opt_first(ks[i], "#222222", "client_normal_bg").str);
  94. t->client_s.fg = color_atoh(fetch_opt_first(ks[i], "#222222", "client_sel_fg").str);
  95. t->client_s.bg = color_atoh(fetch_opt_first(ks[i], "#CCCCCC", "client_sel_bg").str);
  96. t->frame_bg = color_atoh(fetch_opt_first(ks[i], "#555555", "frame_bg").str);
  97. t->client_titlebar_width = fetch_opt_first(ks[i], "12", "client_titlebar_width").num;
  98. t->client_border_width = fetch_opt_first(ks[i], "1", "client_border_width").num;
  99. /* status line */
  100. t->client_n_sl = status_new_ctx(NULL, t);
  101. t->client_s_sl = status_new_ctx(NULL, t);
  102. t->client_f_sl = status_new_ctx(NULL, t);
  103. ISTRDUP(t->client_n_sl.status, fetch_opt_first(ks[i], "", "client_normal_statusline").str);
  104. ISTRDUP(t->client_s_sl.status, fetch_opt_first(ks[i], "", "client_sel_statusline").str);
  105. ISTRDUP(t->client_f_sl.status, fetch_opt_first(ks[i], "", "client_free_statusline").str);
  106. if(t->client_n_sl.status)
  107. status_parse(&t->client_n_sl);
  108. if(t->client_s_sl.status)
  109. status_parse(&t->client_s_sl);
  110. if(t->client_f_sl.status)
  111. status_parse(&t->client_f_sl);
  112. SLIST_INSERT_TAIL(&W->h.theme, t, next, p);
  113. p = t;
  114. }
  115. free(ks);
  116. }
  117. static void
  118. config_bars(void)
  119. {
  120. struct screen *s;
  121. struct theme *t;
  122. size_t i, n;
  123. struct conf_sec *sec, **ks;
  124. int screenid;
  125. char *name, *elem;
  126. enum barpos pos = BarTop;
  127. /* [bars] */
  128. sec = fetch_section_first(NULL, "bars");
  129. ks = fetch_section(sec, "bar");
  130. n = fetch_section_count(ks);
  131. /* [bar] */
  132. for(i = 0; i < n; ++i)
  133. {
  134. name = fetch_opt_first(ks[i], "default", "name").str;
  135. elem = fetch_opt_first(ks[i], "", "elements").str;
  136. screenid = fetch_opt_first(ks[i], "-1", "screen").num;
  137. t = name_to_theme(fetch_opt_first(ks[i], "default", "theme").str);
  138. pos = fetch_opt_first(ks[i], "0", "position").num;
  139. SLIST_FOREACH(s, &W->h.screen, next)
  140. if(screenid == s->id || screenid == -1)
  141. infobar_new(s, name, t, pos, elem);
  142. }
  143. free(ks);
  144. }
  145. static void
  146. config_tag(void)
  147. {
  148. struct screen *s;
  149. struct tag *t;
  150. size_t i, n;
  151. struct conf_sec *sec, **ks, **mb;
  152. char *name, *tmp;
  153. int screenid;
  154. /* [tags] */
  155. sec = fetch_section_first(NULL, "tags");
  156. ks = fetch_section(sec, "tag");
  157. n = fetch_section_count(ks);
  158. if (fetch_opt_first(sec, "1", "circular").boolean)
  159. W->flags |= WMFS_TAGCIRC;
  160. /* [mouse] */
  161. if((mb = fetch_section(sec, "mouse")))
  162. {
  163. config_mouse_section(&W->tmp_head.tag, mb);
  164. free(mb);
  165. }
  166. /* [tag] */
  167. for(i = 0; i < n; ++i)
  168. {
  169. name = fetch_opt_first(ks[i], "tag", "name").str;
  170. screenid = fetch_opt_first(ks[i], "-1", "screen").num;
  171. SLIST_FOREACH(s, &W->h.screen, next)
  172. if(screenid == s->id || screenid == -1)
  173. {
  174. t = tag_new(s, name);
  175. t->statusctx = status_new_ctx(NULL, NULL);
  176. ISTRDUP(t->statusctx.status, fetch_opt_first(ks[i], "", "statusline").str);
  177. if(t->statusctx.status)
  178. status_parse(&t->statusctx);
  179. }
  180. }
  181. /* If no tag at all on a screen, add one anyway */
  182. SLIST_FOREACH(s, &W->h.screen, next)
  183. if(TAILQ_EMPTY(&s->tags))
  184. tag_new(s, "tag");
  185. free(ks);
  186. }
  187. static void
  188. config_client(void)
  189. {
  190. struct conf_sec *sec, **mb;
  191. char *tmp;
  192. /* [client] */
  193. sec = fetch_section_first(NULL, "client");
  194. W->padding = fetch_opt_first(sec, "0", "padding").num;
  195. W->client_mod = modkey_keysym(fetch_opt_first(sec, "Super", "key_modifier").str);
  196. if(fetch_opt_first(sec, "0", "autofocus").boolean)
  197. W->flags |= WMFS_AUTOFOCUS;
  198. /* Get theme */
  199. tmp = fetch_opt_first(sec, "default", "theme").str;
  200. W->ctheme = name_to_theme(tmp);
  201. /* Get focus configuration */
  202. W->cfocus = 0;
  203. tmp = fetch_opt_first(sec, "enter", "focus").str;
  204. if(strstr(tmp, "enter"))
  205. W->cfocus |= CFOCUS_ENTER;
  206. if(strstr(tmp, "click"))
  207. W->cfocus |= CFOCUS_CLICK;
  208. /* [mouse] */
  209. /* for client frame AND titlebar */
  210. if((mb = fetch_section(sec, "mouse")))
  211. {
  212. config_mouse_section(&W->tmp_head.client, mb);
  213. free(mb);
  214. }
  215. }
  216. static void
  217. config_rule(void)
  218. {
  219. int i, n;
  220. struct conf_sec *sec, **ks;
  221. struct rule *r;
  222. char *tn, *tmp;
  223. /* [rules] */
  224. sec = fetch_section_first(NULL, "rules");
  225. ks = fetch_section(sec, "rule");
  226. n = fetch_section_count(ks);
  227. SLIST_INIT(&W->h.rule);
  228. /* [rule] */
  229. for(i = 0; i < n; ++i)
  230. {
  231. r = (struct rule*)xcalloc(1, sizeof(struct rule));
  232. ISTRDUP(r->class, fetch_opt_first(ks[i], "", "class").str);
  233. ISTRDUP(r->instance, fetch_opt_first(ks[i], "", "instance").str);
  234. ISTRDUP(r->role, fetch_opt_first(ks[i], "", "role").str);
  235. ISTRDUP(r->name , fetch_opt_first(ks[i], "", "name").str);
  236. r->screen = fetch_opt_first(ks[i], "-1", "screen").num;
  237. r->tag = fetch_opt_first(ks[i], "-1", "tag").num;
  238. FLAGAPPLY(r->flags, fetch_opt_first(ks[i], "false", "free").boolean, RULE_FREE);
  239. FLAGAPPLY(r->flags, fetch_opt_first(ks[i], "false", "tab").boolean, RULE_TAB);
  240. FLAGAPPLY(r->flags, fetch_opt_first(ks[i], "false", "ignore_tag").boolean, RULE_IGNORE_TAG);
  241. if((tn = fetch_opt_first(ks[i], "", "theme").str))
  242. r->theme = name_to_theme(tn);
  243. else
  244. r->theme = W->ctheme;
  245. SLIST_INSERT_HEAD(&W->h.rule, r, next);
  246. }
  247. free(ks);
  248. }
  249. static void
  250. config_launcher(void)
  251. {
  252. struct conf_sec *sec, **ks;
  253. struct launcher *l;
  254. int n, i;
  255. /* [launchers] */
  256. sec = fetch_section_first(NULL, "launchers");
  257. ks = fetch_section(sec, "launcher");
  258. n = fetch_section_count(ks);
  259. SLIST_INIT(&W->h.launcher);
  260. /* [launcher] */
  261. for(i = 0; i < n; ++i)
  262. {
  263. l = xcalloc(1, sizeof(struct launcher));
  264. l->name = xstrdup(fetch_opt_first(ks[i], "default", "name").str);
  265. l->prompt = xstrdup(fetch_opt_first(ks[i], ":", "prompt").str);
  266. l->command = xstrdup(fetch_opt_first(ks[i], "spawn", "command").str);
  267. if((l->width = fetch_opt_first(ks[i], "150", "width").num) <= 0)
  268. l->width = 150;
  269. SLIST_INSERT_HEAD(&W->h.launcher, l, next);
  270. }
  271. free(ks);
  272. }
  273. static void
  274. config_keybind(void)
  275. {
  276. int i, n;
  277. size_t j;
  278. struct conf_sec *sec, **ks;
  279. struct opt_type *opt;
  280. char *cmd;
  281. struct keybind *k;
  282. /* [keys] */
  283. sec = fetch_section_first(NULL, "keys");
  284. ks = fetch_section(sec, "key");
  285. n = fetch_section_count(ks);
  286. SLIST_INIT(&W->h.keybind);
  287. /* [key] */
  288. for(i = 0; i < n; ++i)
  289. {
  290. k = (struct keybind*)xcalloc(1, sizeof(struct keybind));
  291. /* mod = {} */
  292. opt = fetch_opt(ks[i], "", "mod");
  293. for(j = k->mod = 0; j < fetch_opt_count(opt); ++j)
  294. k->mod |= modkey_keysym(opt[j].str);
  295. free(opt);
  296. /* key = */
  297. k->keysym = XStringToKeysym(fetch_opt_first(ks[i], "None", "key").str);
  298. /* func = */
  299. if(!(k->func = uicb_name_func(fetch_opt_first(ks[i], "", "func").str)))
  300. {
  301. warnxl("configuration: Unknown Function \"%s\".",
  302. fetch_opt_first(ks[i], "", "func").str);
  303. k->func = uicb_spawn;
  304. }
  305. /* cmd = */
  306. if((cmd = fetch_opt_first(ks[i], "", "cmd").str))
  307. k->cmd = xstrdup(cmd);
  308. SLIST_INSERT_HEAD(&W->h.keybind, k, next);
  309. }
  310. wmfs_grab_keys();
  311. free(ks);
  312. }
  313. void
  314. config_init(void)
  315. {
  316. if(get_conf(W->confpath) == -1)
  317. {
  318. warnl("parsing configuration file (%s) failed.", W->confpath);
  319. sprintf(W->confpath, "%s/"CONFIG_DEFAULT_PATH, getenv("HOME"));
  320. if(get_conf(W->confpath) == -1)
  321. {
  322. warnxl("parsing default configuration file (%s) failed.", W->confpath);
  323. sprintf(W->confpath, "%s/wmfs/wmfsrc", XDG_CONFIG_DIR);
  324. if(get_conf(W->confpath) == -1)
  325. errxl(1, "parsing system configuration file (%s) failed.", W->confpath);
  326. }
  327. }
  328. config_theme();
  329. config_keybind();
  330. config_tag();
  331. config_client();
  332. config_bars();
  333. config_rule();
  334. config_launcher();
  335. free_conf();
  336. }