tag.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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. /* extern */
  36. void
  37. compileregs(void) {
  38. unsigned int i;
  39. regex_t *reg;
  40. if(regs)
  41. return;
  42. nrules = sizeof rule / sizeof rule[0];
  43. regs = emallocz(nrules * sizeof(Regs));
  44. for(i = 0; i < nrules; i++) {
  45. if(rule[i].prop) {
  46. reg = emallocz(sizeof(regex_t));
  47. if(regcomp(reg, rule[i].prop, REG_EXTENDED))
  48. free(reg);
  49. else
  50. regs[i].propregex = reg;
  51. }
  52. if(rule[i].tags) {
  53. reg = emallocz(sizeof(regex_t));
  54. if(regcomp(reg, rule[i].tags, REG_EXTENDED))
  55. free(reg);
  56. else
  57. regs[i].tagregex = reg;
  58. }
  59. }
  60. }
  61. Bool
  62. isvisible(Client *c) {
  63. unsigned int i;
  64. for(i = 0; i < ntags; i++)
  65. if(c->tags[i] && seltag[i])
  66. return True;
  67. return False;
  68. }
  69. void
  70. settags(Client *c, Client *trans) {
  71. unsigned int i, j;
  72. regmatch_t tmp;
  73. Bool matched = trans != NULL;
  74. XClassHint ch = { 0 };
  75. XTextProperty name;
  76. if(matched) {
  77. for(i = 0; i < ntags; i++)
  78. c->tags[i] = trans->tags[i];
  79. }
  80. else {
  81. /* check if window has set a property */
  82. name.nitems = 0;
  83. XGetTextProperty(dpy, c->win, &name, dwmconfig);
  84. if(name.nitems && name.encoding == XA_STRING) {
  85. strncpy(prop, (char *)name.value, sizeof prop - 1);
  86. prop[sizeof prop - 1] = '\0';
  87. XFree(name.value);
  88. for(i = 0; i < ntags && i < sizeof prop - 1 && prop[i] != '\0'; i++)
  89. if((c->tags[i] = prop[i] == '1'))
  90. matched = True;
  91. if(i < sizeof prop - 1 && prop[i] != '\0')
  92. c->isfloating = prop[i] == '1';
  93. }
  94. }
  95. if(!matched) {
  96. /* rule matching */
  97. XGetClassHint(dpy, c->win, &ch);
  98. snprintf(prop, sizeof prop, "%s:%s:%s",
  99. ch.res_class ? ch.res_class : "",
  100. ch.res_name ? ch.res_name : "", c->name);
  101. for(i = 0; i < nrules; i++)
  102. if(regs[i].propregex && !regexec(regs[i].propregex, prop, 1, &tmp, 0)) {
  103. c->isfloating = rule[i].isfloating;
  104. for(j = 0; regs[i].tagregex && j < ntags; j++) {
  105. if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) {
  106. matched = True;
  107. c->tags[j] = True;
  108. }
  109. }
  110. }
  111. if(ch.res_class)
  112. XFree(ch.res_class);
  113. if(ch.res_name)
  114. XFree(ch.res_name);
  115. }
  116. if(!matched)
  117. for(i = 0; i < ntags; i++)
  118. c->tags[i] = seltag[i];
  119. persistconfig(c);
  120. }
  121. void
  122. tag(const char *arg) {
  123. int i;
  124. if(!sel)
  125. return;
  126. for(i = 0; i < ntags; i++)
  127. sel->tags[i] = arg == NULL;
  128. i = arg ? atoi(arg) : 0;
  129. if(i >= 0 && i < ntags)
  130. sel->tags[i] = True;
  131. if(sel)
  132. persistconfig(sel);
  133. arrange();
  134. }
  135. void
  136. togglefloating(const char *arg) {
  137. if(!sel || isfloating())
  138. return;
  139. sel->isfloating = !sel->isfloating;
  140. if(sel->isfloating)
  141. resize(sel, sel->x, sel->y, sel->w, sel->h, True);
  142. arrange();
  143. }
  144. void
  145. toggletag(const char *arg) {
  146. int i, j;
  147. if(!sel)
  148. return;
  149. i = arg ? atoi(arg) : 0;
  150. sel->tags[i] = !sel->tags[i];
  151. for(j = 0; j < ntags && !sel->tags[j]; j++);
  152. if(j == ntags)
  153. sel->tags[i] = True;
  154. if(sel)
  155. persistconfig(sel);
  156. arrange();
  157. }
  158. void
  159. toggleview(const char *arg) {
  160. int i, j;
  161. i = arg ? atoi(arg) : 0;
  162. seltag[i] = !seltag[i];
  163. for(j = 0; j < ntags && !seltag[j]; j++);
  164. if(j == ntags)
  165. seltag[i] = True; /* cannot toggle last view */
  166. arrange();
  167. }
  168. void
  169. view(const char *arg) {
  170. int i;
  171. for(i = 0; i < ntags; i++)
  172. seltag[i] = arg == NULL;
  173. i = arg ? atoi(arg) : 0;
  174. if(i >= 0 && i < ntags)
  175. seltag[i] = True;
  176. arrange();
  177. }