You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
4.0 KiB

18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
  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 rule / sizeof rule[0];
  51. regs = emallocz(nrules * sizeof(Regs));
  52. for(i = 0; i < nrules; i++) {
  53. if(rule[i].prop) {
  54. reg = emallocz(sizeof(regex_t));
  55. if(regcomp(reg, rule[i].prop, REG_EXTENDED))
  56. free(reg);
  57. else
  58. regs[i].propregex = reg;
  59. }
  60. if(rule[i].tags) {
  61. reg = emallocz(sizeof(regex_t));
  62. if(regcomp(reg, rule[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] && seltag[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 = rule[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] = seltag[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. seltag[i] = !seltag[i];
  171. for(j = 0; j < ntags && !seltag[j]; j++);
  172. if(j == ntags)
  173. seltag[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. seltag[i] = arg == NULL;
  181. i = idxoftag(arg);
  182. if(i >= 0 && i < ntags)
  183. seltag[i] = True;
  184. arrange();
  185. }