tag.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /* See LICENSE file for copyright and license details. */
  2. #include "dwm.h"
  3. #include <regex.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <X11/Xatom.h>
  8. #include <X11/Xutil.h>
  9. /* static */
  10. typedef struct {
  11. const char *prop;
  12. const char *tags;
  13. Bool isfloating;
  14. } Rule;
  15. typedef struct {
  16. regex_t *propregex;
  17. regex_t *tagregex;
  18. } Regs;
  19. TAGS
  20. RULES
  21. static Regs *regs = NULL;
  22. static unsigned int nrules = 0;
  23. static char prop[512];
  24. static void
  25. persistconfig(Client *c) {
  26. unsigned int i;
  27. for(i = 0; i < ntags && i < sizeof prop - 1; i++)
  28. prop[i] = c->tags[i] ? '1' : '0';
  29. if(i < sizeof prop - 1)
  30. prop[i++] = c->isfloating ? '1' : '0';
  31. prop[i] = '\0';
  32. XChangeProperty(dpy, c->win, dwmconfig, XA_STRING, 8,
  33. PropModeReplace, (unsigned char *)prop, i);
  34. }
  35. static unsigned int
  36. idxoftag(const char *tag) {
  37. unsigned int i;
  38. for(i = 0; i < ntags; i++)
  39. if(tags[i] == tag)
  40. return i;
  41. return 0;
  42. }
  43. /* extern */
  44. void
  45. compileregs(void) {
  46. unsigned int i;
  47. regex_t *reg;
  48. if(regs)
  49. return;
  50. nrules = sizeof rules / sizeof rules[0];
  51. regs = emallocz(nrules * sizeof(Regs));
  52. for(i = 0; i < nrules; i++) {
  53. if(rules[i].prop) {
  54. reg = emallocz(sizeof(regex_t));
  55. if(regcomp(reg, rules[i].prop, REG_EXTENDED))
  56. free(reg);
  57. else
  58. regs[i].propregex = reg;
  59. }
  60. if(rules[i].tags) {
  61. reg = emallocz(sizeof(regex_t));
  62. if(regcomp(reg, rules[i].tags, REG_EXTENDED))
  63. free(reg);
  64. else
  65. regs[i].tagregex = reg;
  66. }
  67. }
  68. }
  69. Bool
  70. isvisible(Client *c) {
  71. unsigned int i;
  72. for(i = 0; i < ntags; i++)
  73. if(c->tags[i] && seltags[i])
  74. return True;
  75. return False;
  76. }
  77. void
  78. settags(Client *c, Client *trans) {
  79. unsigned int i, j;
  80. regmatch_t tmp;
  81. Bool matched = trans != NULL;
  82. XClassHint ch = { 0 };
  83. XTextProperty name;
  84. if(matched) {
  85. for(i = 0; i < ntags; i++)
  86. c->tags[i] = trans->tags[i];
  87. }
  88. else {
  89. /* check if window has set a property */
  90. name.nitems = 0;
  91. XGetTextProperty(dpy, c->win, &name, dwmconfig);
  92. if(name.nitems && name.encoding == XA_STRING) {
  93. strncpy(prop, (char *)name.value, sizeof prop - 1);
  94. prop[sizeof prop - 1] = '\0';
  95. XFree(name.value);
  96. for(i = 0; i < ntags && i < sizeof prop - 1 && prop[i] != '\0'; i++)
  97. if((c->tags[i] = prop[i] == '1'))
  98. matched = True;
  99. if(i < sizeof prop - 1 && prop[i] != '\0')
  100. c->isfloating = prop[i] == '1';
  101. }
  102. }
  103. if(!matched) {
  104. /* rule matching */
  105. XGetClassHint(dpy, c->win, &ch);
  106. snprintf(prop, sizeof prop, "%s:%s:%s",
  107. ch.res_class ? ch.res_class : "",
  108. ch.res_name ? ch.res_name : "", c->name);
  109. for(i = 0; i < nrules; i++)
  110. if(regs[i].propregex && !regexec(regs[i].propregex, prop, 1, &tmp, 0)) {
  111. c->isfloating = rules[i].isfloating;
  112. for(j = 0; regs[i].tagregex && j < ntags; j++) {
  113. if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) {
  114. matched = True;
  115. c->tags[j] = True;
  116. }
  117. }
  118. }
  119. if(ch.res_class)
  120. XFree(ch.res_class);
  121. if(ch.res_name)
  122. XFree(ch.res_name);
  123. }
  124. if(!matched)
  125. for(i = 0; i < ntags; i++)
  126. c->tags[i] = seltags[i];
  127. persistconfig(c);
  128. }
  129. void
  130. tag(const char *arg) {
  131. unsigned int i;
  132. if(!sel)
  133. return;
  134. for(i = 0; i < ntags; i++)
  135. sel->tags[i] = arg == NULL;
  136. i = idxoftag(arg);
  137. if(i >= 0 && i < ntags)
  138. sel->tags[i] = True;
  139. persistconfig(sel);
  140. arrange();
  141. }
  142. void
  143. togglefloating(const char *arg) {
  144. if(!sel || isfloating())
  145. return;
  146. sel->isfloating = !sel->isfloating;
  147. if(sel->isfloating) {
  148. resize(sel, sel->x, sel->y, sel->w, sel->h, True);
  149. persistconfig(sel);
  150. }
  151. arrange();
  152. }
  153. void
  154. toggletag(const char *arg) {
  155. unsigned int i, j;
  156. if(!sel)
  157. return;
  158. i = idxoftag(arg);
  159. sel->tags[i] = !sel->tags[i];
  160. for(j = 0; j < ntags && !sel->tags[j]; j++);
  161. if(j == ntags)
  162. sel->tags[i] = True;
  163. persistconfig(sel);
  164. arrange();
  165. }
  166. void
  167. toggleview(const char *arg) {
  168. unsigned int i, j;
  169. i = idxoftag(arg);
  170. seltags[i] = !seltags[i];
  171. for(j = 0; j < ntags && !seltags[j]; j++);
  172. if(j == ntags)
  173. seltags[i] = True; /* cannot toggle last view */
  174. arrange();
  175. }
  176. void
  177. view(const char *arg) {
  178. unsigned int i;
  179. for(i = 0; i < ntags; i++)
  180. seltags[i] = arg == NULL;
  181. i = idxoftag(arg);
  182. if(i >= 0 && i < ntags)
  183. seltags[i] = True;
  184. arrange();
  185. }