infobar.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*
  2. * infobar.c
  3. * Copyright © 2008, 2009 Martin Duquesnoy <xorg62@gmail.com>
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are
  8. * met:
  9. *
  10. * * Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above
  13. * copyright notice, this list of conditions and the following disclaimer
  14. * in the documentation and/or other materials provided with the
  15. * distribution.
  16. * * Neither the name of the nor the names of its
  17. * contributors may be used to endorse or promote products derived from
  18. * this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. #include "wmfs.h"
  33. /** Init the Infobar
  34. */
  35. void
  36. infobar_init(void)
  37. {
  38. int sc, i, j;
  39. if(!infobar)
  40. infobar = emalloc(screen_count(), sizeof(InfoBar));
  41. for(sc = 0; sc < screen_count(); ++sc)
  42. {
  43. j = 0;
  44. infobar[sc].geo.height = INFOBARH;
  45. switch(tags[sc][seltag[sc]].barpos)
  46. {
  47. case IB_Hide:
  48. sgeo[sc].y = spgeo[sc].y + TBARH;
  49. sgeo[sc].height += INFOBARH;
  50. infobar[sc].geo.y = -(infobar[sc].geo.height) * 2;
  51. break;
  52. case IB_Bottom:
  53. sgeo[sc].y = TBARH;
  54. infobar[sc].geo.y = spgeo[sc].y + sgeo[sc].height + TBARH;
  55. break;
  56. default:
  57. case IB_Top:
  58. sgeo[sc].y = spgeo[sc].y + INFOBARH + TBARH;
  59. infobar[sc].geo.y = spgeo[sc].y;
  60. break;
  61. }
  62. /* Create infobar barwindow */
  63. infobar[sc].bar = barwin_create(ROOT, sgeo[sc].x - BORDH, infobar[sc].geo.y,
  64. sgeo[sc].width, infobar[sc].geo.height,
  65. conf.colors.bar, conf.colors.text, False, False, conf.border.bar);
  66. /* Create tags window */
  67. for(i = 1; i < conf.ntag[sc] + 1; ++i)
  68. {
  69. infobar[sc].tags[i] = barwin_create(infobar[sc].bar->win, j, 0,
  70. textw(tags[sc][i].name) + PAD,
  71. infobar[sc].geo.height,
  72. conf.colors.bar, conf.colors.text, False, False, conf.border.tag);
  73. j += textw(tags[sc][i].name) + PAD;
  74. barwin_map_subwin(infobar[sc].tags[i]);
  75. }
  76. /* Create layout switch barwindow */
  77. infobar[sc].layout_button = barwin_create(infobar[sc].bar->win, j + PAD / 2, 0,
  78. textw(tags[sc][seltag[sc]].layout.symbol) + PAD,
  79. infobar[sc].geo.height,
  80. conf.colors.layout_bg, conf.colors.layout_fg,
  81. False, False, conf.border.layout);
  82. /* Map/Refresh all */
  83. barwin_map(infobar[sc].bar);
  84. barwin_map_subwin(infobar[sc].bar);
  85. if(conf.border.layout)
  86. barwin_map_subwin(infobar[sc].layout_button);
  87. barwin_refresh_color(infobar[sc].bar);
  88. barwin_refresh(infobar[sc].bar);
  89. /* Default statustext is set here */
  90. for(i = 0; i < screen_count(); ++i)
  91. infobar[i].statustext = _strdup(WMFS_VERSION);
  92. infobar_draw(sc);
  93. }
  94. return;
  95. }
  96. /** Draw the Infobar
  97. *\param sc Screen number
  98. */
  99. void
  100. infobar_draw(int sc)
  101. {
  102. infobar_draw_taglist(sc);
  103. infobar_draw_layout(sc);
  104. barwin_refresh_color(infobar[sc].bar);
  105. infobar_draw_statustext(sc, infobar[sc].statustext);
  106. return;
  107. }
  108. /** Draw the layout button in the InfoBar
  109. *\param sc Screen number
  110. */
  111. void
  112. infobar_draw_layout(int sc)
  113. {
  114. barwin_resize(infobar[sc].layout_button, textw(tags[sc][seltag[sc]].layout.symbol) + PAD, infobar[sc].geo.height);
  115. barwin_refresh_color(infobar[sc].layout_button);
  116. if(tags[sc][seltag[sc]].layout.symbol)
  117. barwin_draw_text(infobar[sc].layout_button, PAD / 2, FHINFOBAR, tags[sc][seltag[sc]].layout.symbol);
  118. return;
  119. }
  120. /** Draw the taglist in the InfoBar
  121. *\param sc Screen number
  122. */
  123. void
  124. infobar_draw_taglist(int sc)
  125. {
  126. int i;
  127. Client *c;
  128. for(i = 1; i < conf.ntag[sc] + 1; ++i)
  129. {
  130. infobar[sc].tags[i]->bg = ((i == seltag[sc]) ? conf.colors.tagselbg : conf.colors.bar);
  131. infobar[sc].tags[i]->fg = ((i == seltag[sc]) ? conf.colors.tagselfg : conf.colors.text);
  132. barwin_refresh_color(infobar[sc].tags[i]);
  133. /* Colorize a tag if there are clients in this */
  134. for(c = clients; c; c = c->next)
  135. {
  136. if(c->screen == sc)
  137. {
  138. infobar[sc].tags[c->tag]->bg = ((c->tag == seltag[sc]) ? conf.colors.tagselbg : conf.colors.tag_occupied_bg);
  139. barwin_refresh_color(infobar[sc].tags[i]);
  140. }
  141. }
  142. if(tags[sc][i].name)
  143. barwin_draw_text(infobar[sc].tags[i], PAD / 2, FHINFOBAR, tags[sc][i].name);
  144. }
  145. return;
  146. }
  147. /** Draw text in the statustext and parse color format
  148. *\param sc Screen
  149. *\param str String
  150. */
  151. void
  152. infobar_draw_statustext(int sc, char *str)
  153. {
  154. char *buf = NULL;
  155. char *strwc = NULL;
  156. char col[8] = { 0 };
  157. int i, j, c, k = 0;
  158. char *lastst;
  159. /* If the str == the current statustext, return (not needed) */
  160. if(!str)
  161. return;
  162. barwin_refresh_color(infobar[sc].bar);
  163. /* save last status text address (for free at the end) */
  164. lastst = infobar[sc].statustext;
  165. infobar[sc].statustext = _strdup(str);
  166. strwc = _strdup(str);
  167. /* Count how many color block there is and make a string without color block (\#....\)*/
  168. for(i = j = c = 0; i < strlen(str); ++i, ++j)
  169. {
  170. if(str[i] == '\\' && str[i + 1] == '#' && str[i + 8] == '\\')
  171. {
  172. ++c;
  173. i += 8;
  174. --j;
  175. }
  176. else
  177. strwc[j] = str[i];
  178. }
  179. strwc[j] = '\0';
  180. /* Draw a first time the statustext for non colorized text */
  181. draw_text(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - textw(strwc),
  182. FHINFOBAR, infobar[sc].bar->fg, 0, strwc);
  183. /* Draw text with its color */
  184. if(c)
  185. {
  186. buf = _strdup(strwc);
  187. for(i = k; i < strlen(str); ++i, ++k)
  188. if(str[i] == '\\' && str[i + 1] == '#' && str[i + 8] == '\\')
  189. {
  190. /* Store current color in col[] */
  191. for(j = 0, ++i; str[i] != '\\'; col[j++] = str[i++]);
  192. buf += k;
  193. /* Draw a rectangle with the bar color to draw the text properly */
  194. draw_rectangle(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - textw(buf),
  195. 0, INFOBARH - (sgeo[sc].width - SHADH) - textw(buf),
  196. INFOBARH, conf.colors.bar);
  197. /* Draw text with its color */
  198. draw_text(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - textw(buf),
  199. FHINFOBAR, col, 0, buf);
  200. buf = _strdup(strwc);
  201. ++i;
  202. }
  203. free(buf);
  204. }
  205. barwin_refresh(infobar[sc].bar);
  206. free(lastst);
  207. free(strwc);
  208. return;
  209. }
  210. /** Destroy the InfoBar
  211. */
  212. void
  213. infobar_destroy(void)
  214. {
  215. int sc, i;
  216. for(sc = 0; sc < screen_count(); ++sc)
  217. {
  218. barwin_delete(infobar[sc].layout_button);
  219. barwin_delete_subwin(infobar[sc].layout_button);
  220. for(i = 1; i < conf.ntag[sc] + 1; ++i)
  221. {
  222. barwin_delete_subwin(infobar[sc].tags[i]);
  223. barwin_delete(infobar[sc].tags[i]);
  224. }
  225. barwin_delete_subwin(infobar[sc].bar);
  226. barwin_delete(infobar[sc].bar);
  227. }
  228. return;
  229. }
  230. /* Set the infobar position
  231. * \param pos Position of the bar
  232. */
  233. void
  234. infobar_set_position(int pos)
  235. {
  236. screen_get_sel();
  237. switch(pos)
  238. {
  239. case IB_Hide:
  240. sgeo[selscreen].y = spgeo[selscreen].y + TBARH;
  241. sgeo[selscreen].height = spgeo[selscreen].height - TBARH;
  242. infobar[selscreen].geo.y = -(infobar[selscreen].geo.height) * 2;
  243. break;
  244. case IB_Bottom:
  245. sgeo[selscreen].y = spgeo[selscreen].y + TBARH;
  246. sgeo[selscreen].height = spgeo[selscreen].height - INFOBARH - TBARH;
  247. infobar[selscreen].geo.y = spgeo[selscreen].y + sgeo[selscreen].height + TBARH;
  248. break;
  249. default:
  250. case IB_Top:
  251. sgeo[selscreen].y = spgeo[selscreen].y + INFOBARH + TBARH;
  252. sgeo[selscreen].height = spgeo[selscreen].height - INFOBARH - TBARH;
  253. infobar[selscreen].geo.y = spgeo[selscreen].y;
  254. break;
  255. }
  256. tags[selscreen][seltag[selscreen]].barpos = pos;
  257. barwin_move(infobar[selscreen].bar, sgeo[selscreen].x - BORDH, infobar[selscreen].geo.y);
  258. infobar_draw(selscreen);
  259. ewmh_set_workarea();
  260. arrange(selscreen, True);
  261. return;
  262. }
  263. /** Toggle the infobar position
  264. * \param cmd uicb_t type unused
  265. */
  266. void
  267. uicb_infobar_togglepos(uicb_t cmd)
  268. {
  269. screen_get_sel();
  270. infobar_set_position((tags[selscreen][seltag[selscreen]].barpos
  271. = (tags[selscreen][seltag[selscreen]].barpos < 2)
  272. ? tags[selscreen][seltag[selscreen]].barpos + 1
  273. : 0));
  274. return;
  275. }