tag.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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;
  18. XSetWindowAttributes at =
  19. {
  20. .background_pixel = THEME_DEFAULT->frame_bg,
  21. .override_redirect = true,
  22. .background_pixmap = ParentRelative,
  23. .event_mask = BARWIN_MASK
  24. };
  25. t = xcalloc(1, sizeof(struct tag));
  26. t->screen = s;
  27. t->name = xstrdup(name);
  28. t->flags = 0;
  29. t->sel = NULL;
  30. /* Frame window */
  31. t->frame = XCreateWindow(W->dpy, W->root,
  32. s->ugeo.x, s->ugeo.y,
  33. s->ugeo.w, s->ugeo.h,
  34. 0, CopyFromParent,
  35. InputOutput,
  36. CopyFromParent,
  37. (CWOverrideRedirect | CWBackPixmap
  38. | CWBackPixel | CWEventMask),
  39. &at);
  40. SLIST_INIT(&t->clients);
  41. TAILQ_INSERT_TAIL(&s->tags, t, next);
  42. return t;
  43. }
  44. void
  45. tag_screen(struct screen *s, struct tag *t)
  46. {
  47. struct client *c;
  48. /* Unmap previous tag's frame */
  49. WIN_STATE(s->seltag->frame, Unmap);
  50. SLIST_FOREACH(c, &s->seltag->clients, tnext)
  51. ewmh_set_wm_state(c->win, IconicState);
  52. /*
  53. * Map selected tag's frame, only if there is
  54. * clients in t
  55. */
  56. if(!SLIST_EMPTY(&t->clients))
  57. {
  58. WIN_STATE(t->frame, Map);
  59. SLIST_FOREACH(c, &t->clients, tnext)
  60. ewmh_set_wm_state(c->win, NormalState);
  61. client_focus(t->sel);
  62. }
  63. s->seltag = t;
  64. infobar_elem_screen_update(s, ElemTag);
  65. }
  66. /* Set t to NULL to untag c from c->tag */
  67. void
  68. tag_client(struct tag *t, struct client *c)
  69. {
  70. /* Remove client from its previous tag */
  71. if(c->tag)
  72. {
  73. if(c->tag == t)
  74. return;
  75. layout_split_arrange_closed(c);
  76. SLIST_REMOVE(&c->tag->clients, c, client, tnext);
  77. if(c->tag->sel == c || W->client == c)
  78. client_focus(client_next(c));
  79. }
  80. /*
  81. * Case of client removing: umap frame if empty
  82. */
  83. if(!t)
  84. {
  85. /* Unmap frame if tag is now empty */
  86. if(SLIST_EMPTY(&c->tag->clients))
  87. WIN_STATE(c->tag->frame, Unmap);
  88. return;
  89. }
  90. /* Reparent client win in frame win */
  91. XReparentWindow(W->dpy, c->win, t->frame, 0, 0);
  92. /* Map frame if tag was empty */
  93. if(SLIST_EMPTY(&t->clients))
  94. WIN_STATE(t->frame, Map);
  95. c->tag = t;
  96. layout_split_integrate(c, t->sel);
  97. /* Insert in new tag list */
  98. SLIST_INSERT_HEAD(&t->clients, c, tnext);
  99. }
  100. void
  101. uicb_tag_set(Uicb cmd)
  102. {
  103. int i = 0, n = ATOI(cmd);
  104. struct tag *t;
  105. TAILQ_FOREACH(t, &W->screen->tags, next)
  106. if(++i == n)
  107. {
  108. tag_screen(W->screen, t);
  109. return;
  110. }
  111. }
  112. void
  113. uicb_tag_set_with_name(Uicb cmd)
  114. {
  115. struct tag *t;
  116. TAILQ_FOREACH(t, &W->screen->tags, next)
  117. if(!strcmp(cmd, t->name))
  118. {
  119. tag_screen(W->screen, t);
  120. return;
  121. }
  122. }
  123. void
  124. uicb_tag_next(Uicb cmd)
  125. {
  126. (void)cmd;
  127. struct tag *t;
  128. if((t = TAILQ_NEXT(W->screen->seltag, next)))
  129. tag_screen(W->screen, t);
  130. else if( /* CIRCULAR OPTION */ 1)
  131. tag_screen(W->screen, TAILQ_FIRST(&W->screen->tags));
  132. }
  133. void
  134. uicb_tag_prev(Uicb cmd)
  135. {
  136. (void)cmd;
  137. struct tag *t;
  138. if((t = TAILQ_PREV(W->screen->seltag, tsub, next)))
  139. tag_screen(W->screen, t);
  140. else if( /* CIRCULAR OPTION */ 1)
  141. tag_screen(W->screen, TAILQ_LAST(&W->screen->tags, tsub));
  142. }
  143. static void
  144. tag_remove(struct tag *t)
  145. {
  146. free(t->name);
  147. XDestroyWindow(W->dpy, t->frame);
  148. free(t);
  149. }
  150. void
  151. tag_free(struct screen *s)
  152. {
  153. struct tag *t;
  154. TAILQ_FOREACH(t, &s->tags, next)
  155. {
  156. TAILQ_REMOVE(&s->tags, t, next);
  157. tag_remove(t);
  158. }
  159. }