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.

222 lines
3.5 KiB

19 years ago
  1. /*
  2. * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
  3. * See LICENSE file for license details.
  4. */
  5. #include "dwm.h"
  6. #include <regex.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <sys/types.h>
  10. #include <X11/Xutil.h>
  11. /* static */
  12. typedef struct {
  13. const char *pattern;
  14. char *tags[TLast];
  15. Bool isfloat;
  16. } Rule;
  17. /* CUSTOMIZE */
  18. static Rule rule[] = {
  19. /* class instance tags isfloat */
  20. { "Firefox.*", { [Twww] = "www" }, False },
  21. { "Gimp.*", { 0 }, True},
  22. };
  23. /* extern */
  24. /* CUSTOMIZE */
  25. char *tags[TLast] = {
  26. [Tscratch] = "scratch",
  27. [Tdev] = "dev",
  28. [Twww] = "www",
  29. [Twork] = "work",
  30. };
  31. void (*arrange)(Arg *) = dotile;
  32. void
  33. appendtag(Arg *arg)
  34. {
  35. if(!sel)
  36. return;
  37. sel->tags[arg->i] = tags[arg->i];
  38. arrange(NULL);
  39. }
  40. void
  41. dofloat(Arg *arg)
  42. {
  43. Client *c;
  44. arrange = dofloat;
  45. for(c = clients; c; c = c->next) {
  46. setgeom(c);
  47. if(c->tags[tsel]) {
  48. resize(c, True, TopLeft);
  49. }
  50. else
  51. ban(c);
  52. }
  53. if(sel && !sel->tags[tsel]) {
  54. if((sel = getnext(clients, tsel))) {
  55. higher(sel);
  56. focus(sel);
  57. }
  58. }
  59. drawall();
  60. }
  61. void
  62. dotile(Arg *arg)
  63. {
  64. Client *c;
  65. int n, i, w, h;
  66. w = sw - mw;
  67. arrange = dotile;
  68. for(n = 0, c = clients; c; c = c->next)
  69. if(c->tags[tsel] && !c->isfloat)
  70. n++;
  71. if(n > 1)
  72. h = (sh - bh) / (n - 1);
  73. else
  74. h = sh - bh;
  75. for(i = 0, c = clients; c; c = c->next) {
  76. setgeom(c);
  77. if(c->tags[tsel]) {
  78. if(c->isfloat) {
  79. higher(c);
  80. resize(c, True, TopLeft);
  81. continue;
  82. }
  83. if(n == 1) {
  84. *c->x = sx;
  85. *c->y = sy + bh;
  86. *c->w = sw - 2 * c->border;
  87. *c->h = sh - 2 * c->border - bh;
  88. }
  89. else if(i == 0) {
  90. *c->x = sx;
  91. *c->y = sy + bh;
  92. *c->w = mw - 2 * c->border;
  93. *c->h = sh - 2 * c->border - bh;
  94. }
  95. else if(h > bh) {
  96. *c->x = sx + mw;
  97. *c->y = sy + (i - 1) * h + bh;
  98. *c->w = w - 2 * c->border;
  99. *c->h = h - 2 * c->border;
  100. }
  101. else { /* fallback if h < bh */
  102. *c->x = sx + mw;
  103. *c->y = sy + bh;
  104. *c->w = w - 2 * c->border;
  105. *c->h = sh - 2 * c->border - bh;
  106. }
  107. resize(c, False, TopLeft);
  108. i++;
  109. }
  110. else
  111. ban(c);
  112. }
  113. if(!sel || (sel && !sel->tags[tsel])) {
  114. if((sel = getnext(clients, tsel))) {
  115. higher(sel);
  116. focus(sel);
  117. }
  118. }
  119. drawall();
  120. }
  121. Client *
  122. getnext(Client *c, unsigned int t)
  123. {
  124. for(; c && !c->tags[t]; c = c->next);
  125. return c;
  126. }
  127. void
  128. heretag(Arg *arg)
  129. {
  130. int i;
  131. Client *c;
  132. if(arg->i == tsel)
  133. return;
  134. if(!(c = getnext(clients, arg->i)))
  135. return;
  136. for(i = 0; i < TLast; i++)
  137. c->tags[i] = NULL;
  138. c->tags[tsel] = tags[tsel];
  139. pop(c);
  140. focus(c);
  141. }
  142. void
  143. replacetag(Arg *arg)
  144. {
  145. int i;
  146. if(!sel)
  147. return;
  148. for(i = 0; i < TLast; i++)
  149. sel->tags[i] = NULL;
  150. appendtag(arg);
  151. }
  152. void
  153. settags(Client *c)
  154. {
  155. char classinst[256];
  156. static unsigned int len = rule ? sizeof(rule) / sizeof(rule[0]) : 0;
  157. unsigned int i, j;
  158. regex_t regex;
  159. regmatch_t tmp;
  160. Bool matched = False;
  161. XClassHint ch;
  162. if(!len) {
  163. c->tags[tsel] = tags[tsel];
  164. return;
  165. }
  166. if(XGetClassHint(dpy, c->win, &ch)) {
  167. snprintf(classinst, sizeof(classinst), "%s:%s",
  168. ch.res_class ? ch.res_class : "",
  169. ch.res_name ? ch.res_name : "");
  170. for(i = 0; !matched && i < len; i++) {
  171. if(!regcomp(&regex, rule[i].pattern, 0)) {
  172. if(!regexec(&regex, classinst, 1, &tmp, 0)) {
  173. for(j = 0; j < TLast; j++) {
  174. if(rule[i].tags[j])
  175. matched = True;
  176. c->tags[j] = rule[i].tags[j];
  177. }
  178. c->isfloat = rule[i].isfloat;
  179. }
  180. regfree(&regex);
  181. }
  182. }
  183. if(ch.res_class)
  184. XFree(ch.res_class);
  185. if(ch.res_name)
  186. XFree(ch.res_name);
  187. }
  188. if(!matched)
  189. c->tags[tsel] = tags[tsel];
  190. }
  191. void
  192. view(Arg *arg)
  193. {
  194. tsel = arg->i;
  195. arrange(NULL);
  196. drawall();
  197. }