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.

237 lines
3.7 KiB

19 years ago
19 years ago
19 years ago
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. char *tags[TLast] = {
  24. [Tscratch] = "scratch",
  25. [Tdev] = "dev",
  26. [Twww] = "www",
  27. [Twork] = "work",
  28. };
  29. void (*arrange)(Arg *) = dotile;
  30. /* END CUSTOMIZE */
  31. /* extern */
  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. for(c = clients; c; c = c->next) {
  45. c->ismax = False;
  46. if(c->tags[tsel]) {
  47. resize(c, True, TopLeft);
  48. }
  49. else
  50. ban(c);
  51. }
  52. if(sel && !sel->tags[tsel]) {
  53. if((sel = getnext(clients, tsel))) {
  54. higher(sel);
  55. focus(sel);
  56. }
  57. }
  58. drawall();
  59. }
  60. void
  61. dotile(Arg *arg)
  62. {
  63. int n, i, w, h;
  64. Client *c;
  65. w = sw - mw;
  66. for(n = 0, c = clients; c; c = c->next)
  67. if(c->tags[tsel] && !c->isfloat)
  68. n++;
  69. if(n > 1)
  70. h = (sh - bh) / (n - 1);
  71. else
  72. h = sh - bh;
  73. for(i = 0, c = clients; c; c = c->next) {
  74. c->ismax = False;
  75. if(c->tags[tsel]) {
  76. if(c->isfloat) {
  77. higher(c);
  78. resize(c, True, TopLeft);
  79. continue;
  80. }
  81. if(n == 1) {
  82. c->x = sx;
  83. c->y = sy + bh;
  84. c->w = sw - 2 * c->border;
  85. c->h = sh - 2 * c->border - bh;
  86. }
  87. else if(i == 0) {
  88. c->x = sx;
  89. c->y = sy + bh;
  90. c->w = mw - 2 * c->border;
  91. c->h = sh - 2 * c->border - bh;
  92. }
  93. else if(h > bh) {
  94. c->x = sx + mw;
  95. c->y = sy + (i - 1) * h + bh;
  96. c->w = w - 2 * c->border;
  97. c->h = h - 2 * c->border;
  98. }
  99. else { /* fallback if h < bh */
  100. c->x = sx + mw;
  101. c->y = sy + bh;
  102. c->w = w - 2 * c->border;
  103. c->h = sh - 2 * c->border - bh;
  104. }
  105. resize(c, False, TopLeft);
  106. i++;
  107. }
  108. else
  109. ban(c);
  110. }
  111. if(!sel || (sel && !sel->tags[tsel])) {
  112. if((sel = getnext(clients, tsel))) {
  113. higher(sel);
  114. focus(sel);
  115. }
  116. }
  117. drawall();
  118. }
  119. Client *
  120. getnext(Client *c, unsigned int t)
  121. {
  122. for(; c && !c->tags[t]; c = c->next);
  123. return c;
  124. }
  125. Client *
  126. getprev(Client *c)
  127. {
  128. for(; c && !c->tags[tsel]; c = c->prev);
  129. return c;
  130. }
  131. void
  132. heretag(Arg *arg)
  133. {
  134. int i;
  135. Client *c;
  136. if(arg->i == tsel)
  137. return;
  138. if(!(c = getnext(clients, arg->i)))
  139. return;
  140. for(i = 0; i < TLast; i++)
  141. c->tags[i] = NULL;
  142. c->tags[tsel] = tags[tsel];
  143. pop(c);
  144. focus(c);
  145. }
  146. void
  147. replacetag(Arg *arg)
  148. {
  149. int i;
  150. if(!sel)
  151. return;
  152. for(i = 0; i < TLast; i++)
  153. sel->tags[i] = NULL;
  154. appendtag(arg);
  155. }
  156. void
  157. settags(Client *c)
  158. {
  159. char classinst[256];
  160. static unsigned int len = rule ? sizeof(rule) / sizeof(rule[0]) : 0;
  161. unsigned int i, j;
  162. regex_t regex;
  163. regmatch_t tmp;
  164. Bool matched = False;
  165. XClassHint ch;
  166. if(!len) {
  167. c->tags[tsel] = tags[tsel];
  168. return;
  169. }
  170. if(XGetClassHint(dpy, c->win, &ch)) {
  171. snprintf(classinst, sizeof(classinst), "%s:%s",
  172. ch.res_class ? ch.res_class : "",
  173. ch.res_name ? ch.res_name : "");
  174. for(i = 0; !matched && i < len; i++) {
  175. if(!regcomp(&regex, rule[i].pattern, 0)) {
  176. if(!regexec(&regex, classinst, 1, &tmp, 0)) {
  177. for(j = 0; j < TLast; j++) {
  178. if(rule[i].tags[j])
  179. matched = True;
  180. c->tags[j] = rule[i].tags[j];
  181. }
  182. c->isfloat = rule[i].isfloat;
  183. }
  184. regfree(&regex);
  185. }
  186. }
  187. if(ch.res_class)
  188. XFree(ch.res_class);
  189. if(ch.res_name)
  190. XFree(ch.res_name);
  191. }
  192. if(!matched)
  193. c->tags[tsel] = tags[tsel];
  194. }
  195. void
  196. togglemode(Arg *arg)
  197. {
  198. arrange = arrange == dofloat ? dotile : dofloat;
  199. arrange(NULL);
  200. }
  201. void
  202. view(Arg *arg)
  203. {
  204. tsel = arg->i;
  205. arrange(NULL);
  206. drawall();
  207. }