tag.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /*
  2. * wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
  3. * For license, see COPYING.
  4. */
  5. #include <X11/Xutil.h> /* IconicState / NormalState */
  6. #include "tag.h"
  7. #include "util.h"
  8. #include "infobar.h"
  9. #include "client.h"
  10. #include "config.h"
  11. #include "barwin.h"
  12. #include "ewmh.h"
  13. #include "layout.h"
  14. struct tag*
  15. tag_new(struct screen *s, char *name)
  16. {
  17. struct tag *t, *l;
  18. t = xcalloc(1, sizeof(struct tag));
  19. t->screen = s;
  20. t->flags = 0;
  21. t->id = 0;
  22. t->sel = NULL;
  23. t->prev = NULL;
  24. if((l = TAILQ_LAST(&s->tags, tsub)))
  25. t->id = l->id + 1;
  26. if(!strlen(name))
  27. xasprintf(&t->name, "%d", t->id + 1);
  28. else
  29. t->name = xstrdup(name);
  30. SLIST_INIT(&t->clients);
  31. TAILQ_INIT(&t->sets);
  32. TAILQ_INSERT_TAIL(&s->tags, t, next);
  33. return t;
  34. }
  35. void
  36. tag_screen(struct screen *s, struct tag *t)
  37. {
  38. if(t == s->seltag)
  39. t = t->prev;
  40. if(!t)
  41. t = TAILQ_FIRST(&s->tags);
  42. t->prev = s->seltag;
  43. s->seltag = t;
  44. clients_arrange_map();
  45. if(!SLIST_EMPTY(&t->clients) && !(W->flags & WMFS_SCAN))
  46. client_focus( client_tab_next(t->sel));
  47. if(t->flags & TAG_URGENT)
  48. t->flags ^= TAG_URGENT;
  49. infobar_elem_screen_update(s, ElemTag);
  50. ewmh_update_wmfs_props();
  51. }
  52. /* Set t to NULL to untag c from c->tag */
  53. void
  54. tag_client(struct tag *t, struct client *c)
  55. {
  56. /* Remove client from its previous tag */
  57. if(c->tag && !(c->flags & CLIENT_RULED))
  58. {
  59. if(c->tag == t)
  60. return;
  61. if(!(c->flags & (CLIENT_IGNORE_LAYOUT | CLIENT_FREE)))
  62. layout_split_arrange_closed(c);
  63. if(!(c->flags & CLIENT_REMOVEALL))
  64. {
  65. SLIST_REMOVE(&c->tag->clients, c, client, tnext);
  66. if(c->tag->sel == c || W->client == c)
  67. client_focus( client_tab_next( client_next(c)));
  68. }
  69. }
  70. c->flags &= ~CLIENT_RULED;
  71. /* Client remove */
  72. if(!t)
  73. return;
  74. c->prevtag = c->tag;
  75. c->tag = t;
  76. c->screen = t->screen;
  77. client_update_props(c, CPROP_LOC);
  78. SLIST_INSERT_HEAD(&t->clients, c, tnext);
  79. infobar_elem_screen_update(t->screen, ElemTag);
  80. if(c->flags & CLIENT_TABMASTER && c->prevtag)
  81. {
  82. struct client *cc;
  83. SLIST_FOREACH(cc, &c->prevtag->clients, tnext)
  84. if(cc->tabmaster == c)
  85. {
  86. cc->flags |= CLIENT_IGNORE_LAYOUT;
  87. tag_client(t, cc);
  88. }
  89. }
  90. layout_client(c);
  91. if(t != c->screen->seltag || c->flags & CLIENT_TABBED)
  92. client_unmap(c);
  93. }
  94. void
  95. uicb_tag_set(Uicb cmd)
  96. {
  97. int i = 0, n = ATOI(cmd);
  98. struct tag *t;
  99. TAILQ_FOREACH(t, &W->screen->tags, next)
  100. if(i++ == n)
  101. {
  102. tag_screen(W->screen, t);
  103. return;
  104. }
  105. }
  106. void
  107. uicb_tag_set_with_name(Uicb cmd)
  108. {
  109. struct tag *t;
  110. TAILQ_FOREACH(t, &W->screen->tags, next)
  111. if(!strcmp(cmd, t->name))
  112. {
  113. tag_screen(W->screen, t);
  114. return;
  115. }
  116. }
  117. void
  118. uicb_tag_next(Uicb cmd)
  119. {
  120. (void)cmd;
  121. struct tag *t;
  122. if((t = TAILQ_NEXT(W->screen->seltag, next)))
  123. tag_screen(W->screen, t);
  124. else if( /* CIRCULAR OPTION */ 1)
  125. tag_screen(W->screen, TAILQ_FIRST(&W->screen->tags));
  126. }
  127. void
  128. uicb_tag_prev(Uicb cmd)
  129. {
  130. (void)cmd;
  131. struct tag *t;
  132. if((t = TAILQ_PREV(W->screen->seltag, tsub, next)))
  133. tag_screen(W->screen, t);
  134. else if( /* CIRCULAR OPTION */ 1)
  135. tag_screen(W->screen, TAILQ_LAST(&W->screen->tags, tsub));
  136. }
  137. void
  138. uicb_tag_client(Uicb cmd)
  139. {
  140. struct tag *t;
  141. int id = ATOI(cmd);
  142. if((t = tag_gb_id(W->screen, id)))
  143. tag_client(t, W->client);
  144. }
  145. void
  146. uicb_tag_move_client_next(Uicb cmd)
  147. {
  148. (void)cmd;
  149. struct tag *t;
  150. if((t = TAILQ_NEXT(W->screen->seltag, next)))
  151. tag_client(t, W->client);
  152. else if( /* CIRCULAR OPTION */ 1)
  153. tag_client(TAILQ_FIRST(&W->screen->tags), W->client);
  154. }
  155. void
  156. uicb_tag_move_client_prev(Uicb cmd)
  157. {
  158. (void)cmd;
  159. struct tag *t;
  160. if((t = TAILQ_PREV(W->screen->seltag, tsub, next)))
  161. tag_client(t, W->client);
  162. else if( /* CIRCULAR OPTION */ 1)
  163. tag_client(TAILQ_LAST(&W->screen->tags, tsub), W->client);
  164. }
  165. void
  166. uicb_tag_click(Uicb cmd)
  167. {
  168. (void)cmd;
  169. struct tag *t;
  170. if((t = (struct tag*)W->last_clicked_barwin->ptr)
  171. && t->screen == W->screen)
  172. tag_screen(W->screen, t);
  173. }
  174. static void
  175. tag_remove(struct tag *t)
  176. {
  177. TAILQ_REMOVE(&t->screen->tags, t, next);
  178. free(t->name);
  179. layout_free_set(t);
  180. free(t);
  181. }
  182. void
  183. uicb_tag_new(Uicb cmd)
  184. {
  185. struct screen *s = W->screen;
  186. struct infobar *i;
  187. tag_new(s, (char*)cmd);
  188. s->flags |= SCREEN_TAG_UPDATE;
  189. SLIST_FOREACH(i, &s->infobars, next)
  190. infobar_elem_reinit(i);
  191. }
  192. void
  193. uicb_tag_del(Uicb cmd)
  194. {
  195. struct infobar *i;
  196. struct tag *t = W->screen->seltag;
  197. (void)cmd;
  198. if(SLIST_EMPTY(&t->clients)
  199. && TAILQ_NEXT(TAILQ_FIRST(&W->screen->tags), next))
  200. {
  201. tag_screen(W->screen, TAILQ_NEXT(t, next));
  202. tag_remove(t);
  203. W->screen->flags |= SCREEN_TAG_UPDATE;
  204. SLIST_FOREACH(i, &W->screen->infobars, next)
  205. infobar_elem_reinit(i);
  206. }
  207. }
  208. void
  209. tag_free(struct screen *s)
  210. {
  211. struct tag *t;
  212. TAILQ_FOREACH(t, &s->tags, next)
  213. tag_remove(t);
  214. }