65 struct Client { |
65 struct Client { |
66 char name[256]; |
66 char name[256]; |
67 int x, y, w, h; |
67 int x, y, w, h; |
68 int basew, baseh, incw, inch, maxw, maxh, minw, minh; |
68 int basew, baseh, incw, inch, maxw, maxh, minw, minh; |
69 int minax, maxax, minay, maxay; |
69 int minax, maxax, minay, maxay; |
70 int *tags; |
|
71 long flags; |
70 long flags; |
72 unsigned int border, oldborder; |
71 unsigned int border, oldborder; |
73 Bool isbanned, isfixed, isfloating, isurgent; |
72 Bool isbanned, isfixed, isfloating, isurgent; |
|
73 Bool *tags; |
74 Client *next; |
74 Client *next; |
75 Client *prev; |
75 Client *prev; |
76 Client *snext; |
76 Client *snext; |
77 Window win; |
77 Window win; |
78 }; |
78 }; |
108 const char *prop; |
108 const char *prop; |
109 const char *tag; |
109 const char *tag; |
110 Bool isfloating; |
110 Bool isfloating; |
111 } Rule; |
111 } Rule; |
112 |
112 |
|
113 typedef struct { |
|
114 const char name[MAXTAGLEN]; |
|
115 unsigned int view; |
|
116 } Tag; |
|
117 |
113 struct View { |
118 struct View { |
114 int id; |
|
115 int x, y, w, h, wax, way, wah, waw; |
119 int x, y, w, h, wax, way, wah, waw; |
116 double mwfact; |
120 double mwfact; |
117 Layout *layout; |
121 Layout *layout; |
118 Window barwin; |
122 Window barwin; |
119 }; |
123 }; |
120 |
124 |
121 /* function declarations */ |
125 /* function declarations */ |
|
126 void addtag(Client *c, const char *t); |
122 void applyrules(Client *c); |
127 void applyrules(Client *c); |
123 void arrange(void); |
128 void arrange(void); |
124 void attach(Client *c); |
129 void attach(Client *c); |
125 void attachstack(Client *c); |
130 void attachstack(Client *c); |
126 void ban(Client *c); |
131 void ban(Client *c); |
151 View *getview(Client *c); |
156 View *getview(Client *c); |
152 long getstate(Window w); |
157 long getstate(Window w); |
153 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); |
158 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); |
154 void grabbuttons(Client *c, Bool focused); |
159 void grabbuttons(Client *c, Bool focused); |
155 void grabkeys(void); |
160 void grabkeys(void); |
156 unsigned int idxoftag(const char *tag); |
161 unsigned int idxoftag(const char *t); |
157 void initfont(const char *fontstr); |
162 void initfont(const char *fontstr); |
158 Bool isoccupied(unsigned int t); |
163 Bool isoccupied(unsigned int t); |
159 Bool isprotodel(Client *c); |
164 Bool isprotodel(Client *c); |
160 Bool isurgent(unsigned int t); |
165 Bool isurgent(unsigned int t); |
161 Bool isvisible(Client *c); |
166 Bool isvisible(Client *c); |
206 /* variables */ |
211 /* variables */ |
207 char stext[256], buf[256]; |
212 char stext[256], buf[256]; |
208 int nviews = 1; |
213 int nviews = 1; |
209 View *selview; |
214 View *selview; |
210 int screen; |
215 int screen; |
211 int *seltags; |
|
212 int *prevtags; |
|
213 int (*xerrorxlib)(Display *, XErrorEvent *); |
216 int (*xerrorxlib)(Display *, XErrorEvent *); |
214 unsigned int bh, bpos; |
217 unsigned int bh, bpos; |
215 unsigned int blw = 0; |
218 unsigned int blw = 0; |
216 unsigned int numlockmask = 0; |
219 unsigned int numlockmask = 0; |
217 void (*handler[LASTEvent]) (XEvent *) = { |
220 void (*handler[LASTEvent]) (XEvent *) = { |
232 Bool isxinerama = False; |
235 Bool isxinerama = False; |
233 Bool domwfact = True; |
236 Bool domwfact = True; |
234 Bool dozoom = True; |
237 Bool dozoom = True; |
235 Bool otherwm, readin; |
238 Bool otherwm, readin; |
236 Bool running = True; |
239 Bool running = True; |
|
240 Bool *prevtags; |
|
241 Bool *seltags; |
237 Client *clients = NULL; |
242 Client *clients = NULL; |
238 Client *sel = NULL; |
243 Client *sel = NULL; |
239 Client *stack = NULL; |
244 Client *stack = NULL; |
240 Cursor cursor[CurLast]; |
245 Cursor cursor[CurLast]; |
241 Display *dpy; |
246 Display *dpy; |
246 /* configuration, allows nested code to access above variables */ |
251 /* configuration, allows nested code to access above variables */ |
247 #include "config.h" |
252 #include "config.h" |
248 |
253 |
249 /* function implementations */ |
254 /* function implementations */ |
250 void |
255 void |
|
256 addtag(Client *c, const char *t) { |
|
257 unsigned int i, tidx = idxoftag(t); |
|
258 |
|
259 for(i = 0; i < LENGTH(tags); i++) |
|
260 if(c->tags[i] && vtags[i] != vtags[tidx]) |
|
261 return; /* conflict */ |
|
262 c->tags[tidx] = True; |
|
263 } |
|
264 |
|
265 void |
251 applyrules(Client *c) { |
266 applyrules(Client *c) { |
252 unsigned int i; |
267 unsigned int i; |
253 Bool matched_tag = False; |
268 Bool matched = False; |
254 Rule *r; |
269 Rule *r; |
255 XClassHint ch = { 0 }; |
270 XClassHint ch = { 0 }; |
256 |
271 |
257 /* rule matching */ |
272 /* rule matching */ |
258 XGetClassHint(dpy, c->win, &ch); |
273 XGetClassHint(dpy, c->win, &ch); |
259 snprintf(buf, sizeof buf, "%s:%s:%s", |
|
260 ch.res_class ? ch.res_class : "", |
|
261 ch.res_name ? ch.res_name : "", c->name); |
|
262 for(i = 0; i < LENGTH(rules); i++) { |
274 for(i = 0; i < LENGTH(rules); i++) { |
263 r = &rules[i]; |
275 r = &rules[i]; |
264 if(strstr(c->name, r->prop) |
276 if(strstr(c->name, r->prop) |
265 || (ch.res_class && strstr(ch.res_class, r->prop)) |
277 || (ch.res_class && strstr(ch.res_class, r->prop)) |
266 || (ch.res_name && strstr(ch.res_name, r->prop))) |
278 || (ch.res_name && strstr(ch.res_name, r->prop))) |
267 { |
279 { |
268 c->isfloating = r->isfloating; |
280 c->isfloating = r->isfloating; |
269 if(r->tag) { |
281 if(r->tag) { |
270 matched_tag = True; |
282 addtag(c, r->tag); |
271 c->tags[idxoftag(r->tag)] = selview->id; |
283 matched = True; |
272 } |
284 } |
273 } |
285 } |
274 } |
286 } |
275 if(ch.res_class) |
287 if(ch.res_class) |
276 XFree(ch.res_class); |
288 XFree(ch.res_class); |
277 if(ch.res_name) |
289 if(ch.res_name) |
278 XFree(ch.res_name); |
290 XFree(ch.res_name); |
279 if(!matched_tag) |
291 if(!matched) |
280 memcpy(c->tags, seltags, sizeof initags); |
292 memcpy(c->tags, seltags, sizeof initags); |
281 } |
293 } |
282 |
294 |
283 |
295 |
284 |
296 |
530 |
542 |
531 dc.x = 0; |
543 dc.x = 0; |
532 for(c = stack; c && (!isvisible(c) || getview(c) != v); c = c->snext); |
544 for(c = stack; c && (!isvisible(c) || getview(c) != v); c = c->snext); |
533 for(i = 0; i < LENGTH(tags); i++) { |
545 for(i = 0; i < LENGTH(tags); i++) { |
534 dc.w = textw(tags[i]); |
546 dc.w = textw(tags[i]); |
535 if(seltags[i] && seltags[i] == v->id) { |
547 if(seltags[i]) { |
536 drawtext(v, tags[i], dc.sel, isurgent(i)); |
548 drawtext(v, tags[i], dc.sel, isurgent(i)); |
537 drawsquare(v, c && c->tags[i], isoccupied(i), isurgent(i), dc.sel); |
549 drawsquare(v, c && c->tags[i], isoccupied(i), isurgent(i), dc.sel); |
538 } |
550 } |
539 else { |
551 else { |
540 drawtext(v, tags[i], dc.norm, isurgent(i)); |
552 drawtext(v, tags[i], dc.norm, isurgent(i)); |
900 GrabModeAsync, GrabModeAsync); |
912 GrabModeAsync, GrabModeAsync); |
901 } |
913 } |
902 } |
914 } |
903 |
915 |
904 unsigned int |
916 unsigned int |
905 idxoftag(const char *tag) { |
917 idxoftag(const char *t) { |
906 unsigned int i; |
918 unsigned int i; |
907 |
919 |
908 for(i = 0; (i < LENGTH(tags)) && (tags[i] != tag); i++); |
920 for(i = 0; (i < LENGTH(tags)) && (tags[i] != t); i++); |
909 return (i < LENGTH(tags)) ? i : 0; |
921 return (i < LENGTH(tags)) ? i : 0; |
910 } |
922 } |
911 |
923 |
912 void |
924 void |
913 initfont(const char *fontstr) { |
925 initfont(const char *fontstr) { |
1557 memcpy(prevtags, initags, sizeof initags); |
1569 memcpy(prevtags, initags, sizeof initags); |
1558 |
1570 |
1559 for(i = 0; i < nviews; i++) { |
1571 for(i = 0; i < nviews; i++) { |
1560 /* init geometry */ |
1572 /* init geometry */ |
1561 v = &views[i]; |
1573 v = &views[i]; |
1562 v->id = i + 1; |
|
1563 |
1574 |
1564 if(nviews != 1 && isxinerama) { |
1575 if(nviews != 1 && isxinerama) { |
1565 |
1576 |
1566 #if defined(AIM_XINERAMA) |
1577 #if defined(AIM_XINERAMA) |
1567 v->w = DisplayWidth(dpy, screen) / 2; |
1578 v->w = DisplayWidth(dpy, screen) / 2; |
1748 return; |
1759 return; |
1749 i = idxoftag(arg); |
1760 i = idxoftag(arg); |
1750 sel->tags[i] = !sel->tags[i]; |
1761 sel->tags[i] = !sel->tags[i]; |
1751 for(j = 0; j < LENGTH(tags) && !sel->tags[j]; j++); |
1762 for(j = 0; j < LENGTH(tags) && !sel->tags[j]; j++); |
1752 if(j == LENGTH(tags)) |
1763 if(j == LENGTH(tags)) |
1753 sel->tags[i] = selview->id; /* at least one tag must be enabled */ |
1764 sel->tags[i] = True; /* at least one tag must be enabled */ |
1754 arrange(); |
1765 arrange(); |
1755 } |
1766 } |
1756 |
1767 |
1757 void |
1768 void |
1758 toggleview(const char *arg) { |
1769 toggleview(const char *arg) { |
1901 } |
1912 } |
1902 |
1913 |
1903 void |
1914 void |
1904 view(const char *arg) { |
1915 view(const char *arg) { |
1905 unsigned int i; |
1916 unsigned int i; |
1906 int tmp[LENGTH(tags)]; |
1917 Bool tmp[LENGTH(tags)]; |
1907 |
1918 |
1908 for(i = 0; i < LENGTH(tags); i++) |
1919 for(i = 0; i < LENGTH(tags); i++) |
1909 tmp[i] = (NULL == arg) ? selview->id : 0; |
1920 tmp[i] = (NULL == arg); |
1910 tmp[idxoftag(arg)] = selview->id; |
1921 tmp[idxoftag(arg)] = True; |
|
1922 |
1911 if(memcmp(seltags, tmp, sizeof initags) != 0) { |
1923 if(memcmp(seltags, tmp, sizeof initags) != 0) { |
1912 memcpy(prevtags, seltags, sizeof initags); |
1924 memcpy(prevtags, seltags, sizeof initags); |
1913 memcpy(seltags, tmp, sizeof initags); |
1925 memcpy(seltags, tmp, sizeof initags); |
1914 arrange(); |
1926 arrange(); |
1915 } |
1927 } |