43 //#ifdef XINERAMA |
43 //#ifdef XINERAMA |
44 #include <X11/extensions/Xinerama.h> |
44 #include <X11/extensions/Xinerama.h> |
45 //#endif |
45 //#endif |
46 |
46 |
47 /* macros */ |
47 /* macros */ |
48 #define BUTTONMASK (ButtonPressMask | ButtonReleaseMask) |
48 #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) |
49 #define CLEANMASK(mask) (mask & ~(numlockmask | LockMask)) |
49 #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask)) |
50 #define LENGTH(x) (sizeof x / sizeof x[0]) |
50 #define LENGTH(x) (sizeof x / sizeof x[0]) |
51 #define MAXTAGLEN 16 |
51 #define MAXTAGLEN 16 |
52 #define MOUSEMASK (BUTTONMASK | PointerMotionMask) |
52 #define MOUSEMASK (BUTTONMASK|PointerMotionMask) |
53 |
53 |
54 |
54 |
55 /* enums */ |
55 /* enums */ |
56 enum { BarTop, BarBot, BarOff }; /* bar position */ |
56 enum { BarTop, BarBot, BarOff }; /* bar position */ |
57 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ |
57 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ |
58 enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ |
58 enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ |
59 enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */ |
59 enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */ |
60 enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */ |
60 enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */ |
61 |
61 |
62 /* typedefs */ |
62 /* typedefs */ |
63 typedef struct Monitor Monitor; |
63 typedef struct View View; |
64 typedef struct Client Client; |
64 typedef struct Client Client; |
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; |
70 long flags; |
71 long flags; |
71 unsigned int border, oldborder; |
72 unsigned int border, oldborder; |
72 Bool isbanned, isfixed, isfloating, isurgent; |
73 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 Monitor *monitor; |
|
79 }; |
78 }; |
80 |
79 |
81 typedef struct { |
80 typedef struct { |
82 int x, y, w, h; |
81 int x, y, w, h; |
83 unsigned long norm[ColLast]; |
82 unsigned long norm[ColLast]; |
141 void configurenotify(XEvent *e); |
137 void configurenotify(XEvent *e); |
142 void configurerequest(XEvent *e); |
138 void configurerequest(XEvent *e); |
143 void destroynotify(XEvent *e); |
139 void destroynotify(XEvent *e); |
144 void detach(Client *c); |
140 void detach(Client *c); |
145 void detachstack(Client *c); |
141 void detachstack(Client *c); |
146 void drawbar(Monitor *m); |
142 void drawbar(View *v); |
147 void drawsquare(Monitor *m, Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); |
143 void drawsquare(View *v, Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); |
148 void drawtext(Monitor *m, const char *text, unsigned long col[ColLast], Bool invert); |
144 void drawtext(View *v, const char *text, unsigned long col[ColLast], Bool invert); |
149 void *emallocz(unsigned int size); |
145 void *emallocz(unsigned int size); |
150 void enternotify(XEvent *e); |
146 void enternotify(XEvent *e); |
151 void eprint(const char *errstr, ...); |
147 void eprint(const char *errstr, ...); |
152 void expose(XEvent *e); |
148 void expose(XEvent *e); |
153 void floating(Monitor *m); /* default floating layout */ |
149 void floating(View *v); /* default floating layout */ |
154 void focus(Client *c); |
150 void focus(Client *c); |
155 void focusin(XEvent *e); |
151 void focusin(XEvent *e); |
156 void focusnext(const char *arg); |
152 void focusnext(const char *arg); |
157 void focusprev(const char *arg); |
153 void focusprev(const char *arg); |
158 Client *getclient(Window w); |
154 Client *getclient(Window w); |
159 unsigned long getcolor(const char *colstr); |
155 unsigned long getcolor(const char *colstr); |
160 Monitor *getmonitor(Window barwin); |
156 View *getviewbar(Window barwin); |
|
157 View *getview(Client *c); |
161 long getstate(Window w); |
158 long getstate(Window w); |
162 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); |
159 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); |
163 void grabbuttons(Client *c, Bool focused); |
160 void grabbuttons(Client *c, Bool focused); |
164 void grabkeys(void); |
161 void grabkeys(void); |
165 unsigned int idxoftag(const char *tag); |
162 unsigned int idxoftag(const char *tag); |
166 void initfont(const char *fontstr); |
163 void initfont(const char *fontstr); |
167 Bool isoccupied(Monitor *monitor, unsigned int t); |
164 Bool isoccupied(unsigned int t); |
168 Bool isprotodel(Client *c); |
165 Bool isprotodel(Client *c); |
169 Bool isurgent(Monitor *monitor, unsigned int t); |
166 Bool isurgent(unsigned int t); |
170 Bool isvisible(Client *c, Monitor *m); |
167 Bool isvisible(Client *c); |
171 void keypress(XEvent *e); |
168 void keypress(XEvent *e); |
172 void killclient(const char *arg); |
169 void killclient(const char *arg); |
173 void manage(Window w, XWindowAttributes *wa); |
170 void manage(Window w, XWindowAttributes *wa); |
174 void mappingnotify(XEvent *e); |
171 void mappingnotify(XEvent *e); |
175 void maprequest(XEvent *e); |
172 void maprequest(XEvent *e); |
176 Monitor *monitorat(void); |
173 View *viewat(void); |
177 void movemouse(Client *c); |
174 void movemouse(Client *c); |
178 Client *nexttiled(Client *c, Monitor *monitor); |
175 Client *nexttiled(Client *c, View *v); |
179 void propertynotify(XEvent *e); |
176 void propertynotify(XEvent *e); |
180 void quit(const char *arg); |
177 void quit(const char *arg); |
181 void reapply(const char *arg); |
178 void reapply(const char *arg); |
182 void resize(Client *c, int x, int y, int w, int h, Bool sizehints); |
179 void resize(Client *c, int x, int y, int w, int h, Bool sizehints); |
183 void resizemouse(Client *c); |
180 void resizemouse(Client *c); |
184 void restack(Monitor *m); |
181 void restack(View *v); |
185 void run(void); |
182 void run(void); |
186 void scan(void); |
183 void scan(void); |
187 void setclientstate(Client *c, long state); |
184 void setclientstate(Client *c, long state); |
188 void setlayout(const char *arg); |
185 void setlayout(const char *arg); |
189 void setmwfact(const char *arg); |
186 void setmwfact(const char *arg); |
190 void setup(void); |
187 void setup(void); |
191 void spawn(const char *arg); |
188 void spawn(const char *arg); |
192 void tag(const char *arg); |
189 void tag(const char *arg); |
193 unsigned int textnw(const char *text, unsigned int len); |
190 unsigned int textnw(const char *text, unsigned int len); |
194 unsigned int textw(const char *text); |
191 unsigned int textw(const char *text); |
195 void tile(Monitor *m); |
192 void tile(View *v); |
196 void togglebar(const char *arg); |
193 void togglebar(const char *arg); |
197 void togglefloating(const char *arg); |
194 void togglefloating(const char *arg); |
198 void toggletag(const char *arg); |
195 void toggletag(const char *arg); |
199 void toggleview(const char *arg); |
196 void toggleview(const char *arg); |
200 void unban(Client *c); |
197 void unban(Client *c); |
201 void unmanage(Client *c); |
198 void unmanage(Client *c); |
202 void unmapnotify(XEvent *e); |
199 void unmapnotify(XEvent *e); |
203 void updatebarpos(Monitor *m); |
200 void updatebarpos(View *v); |
204 void updatesizehints(Client *c); |
201 void updatesizehints(Client *c); |
205 void updatetitle(Client *c); |
202 void updatetitle(Client *c); |
206 void updatewmhints(Client *c); |
203 void updatewmhints(Client *c); |
207 void view(const char *arg); |
204 void view(const char *arg); |
208 void viewprevtag(const char *arg); /* views previous selected tags */ |
205 void viewprevtag(const char *arg); /* views previous selected tags */ |
209 int xerror(Display *dpy, XErrorEvent *ee); |
206 int xerror(Display *dpy, XErrorEvent *ee); |
210 int xerrordummy(Display *dsply, XErrorEvent *ee); |
207 int xerrordummy(Display *dpy, XErrorEvent *ee); |
211 int xerrorstart(Display *dsply, XErrorEvent *ee); |
208 int xerrorstart(Display *dpy, XErrorEvent *ee); |
212 void zoom(const char *arg); |
209 void zoom(const char *arg); |
213 void movetomonitor(const char *arg); |
210 void selectview(const char *arg); |
214 void selectmonitor(const char *arg); |
|
215 |
211 |
216 /* variables */ |
212 /* variables */ |
217 char stext[256]; |
213 char stext[256]; |
218 int mcount = 1; |
214 int nviews = 1; |
219 Monitor *selmonitor; |
215 View *selview; |
220 int screen; |
216 int screen; |
|
217 int *seltags; |
|
218 int *prevtags; |
221 int (*xerrorxlib)(Display *, XErrorEvent *); |
219 int (*xerrorxlib)(Display *, XErrorEvent *); |
222 unsigned int bh, bpos; |
220 unsigned int bh, bpos; |
223 unsigned int blw = 0; |
221 unsigned int blw = 0; |
224 unsigned int numlockmask = 0; |
222 unsigned int numlockmask = 0; |
225 void (*handler[LASTEvent]) (XEvent *) = { |
223 void (*handler[LASTEvent]) (XEvent *) = { |
247 Client *stack = NULL; |
245 Client *stack = NULL; |
248 Cursor cursor[CurLast]; |
246 Cursor cursor[CurLast]; |
249 Display *dpy; |
247 Display *dpy; |
250 DC dc = {0}; |
248 DC dc = {0}; |
251 Regs *regs = NULL; |
249 Regs *regs = NULL; |
252 Monitor *monitors; |
250 View *views; |
253 Window root; |
251 Window root; |
254 |
252 |
255 /* configuration, allows nested code to access above variables */ |
253 /* configuration, allows nested code to access above variables */ |
256 #include "config.h" |
254 #include "config.h" |
257 |
|
258 //Bool prevtags[LENGTH(tags)]; |
|
259 |
255 |
260 /* function implementations */ |
256 /* function implementations */ |
261 void |
257 void |
262 applyrules(Client *c) { |
258 applyrules(Client *c) { |
263 static char buf[512]; |
259 static char buf[512]; |
264 unsigned int i, j; |
260 unsigned int i, j; |
265 regmatch_t tmp; |
261 regmatch_t tmp; |
266 Bool matched_tag = False; |
262 Bool matched_tag = False; |
267 Bool matched_monitor = False; |
|
268 XClassHint ch = { 0 }; |
263 XClassHint ch = { 0 }; |
269 |
264 |
270 /* rule matching */ |
265 /* rule matching */ |
271 XGetClassHint(dpy, c->win, &ch); |
266 XGetClassHint(dpy, c->win, &ch); |
272 snprintf(buf, sizeof buf, "%s:%s:%s", |
267 snprintf(buf, sizeof buf, "%s:%s:%s", |
273 ch.res_class ? ch.res_class : "", |
268 ch.res_class ? ch.res_class : "", |
274 ch.res_name ? ch.res_name : "", c->name); |
269 ch.res_name ? ch.res_name : "", c->name); |
275 for(i = 0; i < LENGTH(rules); i++) |
270 for(i = 0; i < LENGTH(rules); i++) |
276 if(regs[i].propregex && !regexec(regs[i].propregex, buf, 1, &tmp, 0)) { |
271 if(regs[i].propregex && !regexec(regs[i].propregex, buf, 1, &tmp, 0)) { |
277 if (rules[i].monitor >= 0 && rules[i].monitor < mcount) { |
|
278 matched_monitor = True; |
|
279 c->monitor = &monitors[rules[i].monitor]; |
|
280 } |
|
281 |
|
282 c->isfloating = rules[i].isfloating; |
272 c->isfloating = rules[i].isfloating; |
283 for(j = 0; regs[i].tagregex && j < LENGTH(tags); j++) { |
273 for(j = 0; regs[i].tagregex && j < LENGTH(tags); j++) { |
284 if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) { |
274 if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) { |
285 matched_tag = True; |
275 matched_tag = True; |
286 c->tags[j] = True; |
276 c->tags[j] = selview->id; |
287 } |
277 } |
288 } |
278 } |
289 } |
279 } |
290 if(ch.res_class) |
280 if(ch.res_class) |
291 XFree(ch.res_class); |
281 XFree(ch.res_class); |
292 if(ch.res_name) |
282 if(ch.res_name) |
293 XFree(ch.res_name); |
283 XFree(ch.res_name); |
294 if(!matched_tag) |
284 if(!matched_tag) |
295 memcpy(c->tags, monitorat()->seltags, sizeof initags); |
285 memcpy(c->tags, seltags, sizeof initags); |
296 if (!matched_monitor) |
286 } |
297 c->monitor = monitorat(); |
287 |
298 } |
288 |
299 |
289 |
300 void |
290 void |
301 arrange(Monitor *m) { |
291 arrange(void) { |
302 unsigned int i; |
292 unsigned int i; |
303 Client *c; |
293 Client *c; |
304 |
294 |
305 for(c = clients; c; c = c->next) |
295 for(c = clients; c; c = c->next) |
306 if(isvisible(c, c->monitor)) |
296 if(isvisible(c)) |
307 unban(c); |
297 unban(c); |
308 else |
298 else |
309 ban(c); |
299 ban(c); |
310 |
300 |
311 if(m) |
301 for(i = 0; i < nviews; i++) { |
312 m->layout->arrange(m); |
302 views[i].layout->arrange(&views[i]); |
313 else |
303 restack(&views[i]); |
314 for(i = 0; i < mcount; i++) |
304 } |
315 monitors[i].layout->arrange(&monitors[i]); |
|
316 focus(NULL); |
305 focus(NULL); |
317 restack(m); |
|
318 } |
306 } |
319 |
307 |
320 void |
308 void |
321 attach(Client *c) { |
309 attach(Client *c) { |
322 if(clients) |
310 if(clients) |
477 } |
465 } |
478 |
466 |
479 void |
467 void |
480 configurenotify(XEvent *e) { |
468 configurenotify(XEvent *e) { |
481 XConfigureEvent *ev = &e->xconfigure; |
469 XConfigureEvent *ev = &e->xconfigure; |
482 Monitor *m = selmonitor; |
470 View *v = selview; |
483 |
471 |
484 if(ev->window == root && (ev->width != m->sw || ev->height != m->sh)) { |
472 if(ev->window == root && (ev->width != v->w || ev->height != v->h)) { |
485 /* TODO -- update Xinerama dimensions here */ |
473 /* TODO -- update Xinerama dimensions here */ |
486 m->sw = ev->width; |
474 v->w = ev->width; |
487 m->sh = ev->height; |
475 v->h = ev->height; |
488 XFreePixmap(dpy, dc.drawable); |
476 XFreePixmap(dpy, dc.drawable); |
489 dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(root, screen), bh, DefaultDepth(dpy, screen)); |
477 dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(root, screen), bh, DefaultDepth(dpy, screen)); |
490 XResizeWindow(dpy, m->barwin, m->sw, bh); |
478 XResizeWindow(dpy, v->barwin, v->w, bh); |
491 updatebarpos(m); |
479 updatebarpos(v); |
492 arrange(m); |
480 arrange(); |
493 } |
481 } |
494 } |
482 } |
495 |
483 |
496 void |
484 void |
497 configurerequest(XEvent *e) { |
485 configurerequest(XEvent *e) { |
498 Client *c; |
486 Client *c; |
499 XConfigureRequestEvent *ev = &e->xconfigurerequest; |
487 XConfigureRequestEvent *ev = &e->xconfigurerequest; |
500 XWindowChanges wc; |
488 XWindowChanges wc; |
501 |
489 |
502 if((c = getclient(ev->window))) { |
490 if((c = getclient(ev->window))) { |
503 Monitor *m = c->monitor; |
491 View *v = getview(c); |
504 if(ev->value_mask & CWBorderWidth) |
492 if(ev->value_mask & CWBorderWidth) |
505 c->border = ev->border_width; |
493 c->border = ev->border_width; |
506 if(c->isfixed || c->isfloating || (floating == m->layout->arrange)) { |
494 if(c->isfixed || c->isfloating || (floating == v->layout->arrange)) { |
507 if(ev->value_mask & CWX) |
495 if(ev->value_mask & CWX) |
508 c->x = m->sx+ev->x; |
496 c->x = v->x + ev->x; |
509 if(ev->value_mask & CWY) |
497 if(ev->value_mask & CWY) |
510 c->y = m->sy+ev->y; |
498 c->y = v->y + ev->y; |
511 if(ev->value_mask & CWWidth) |
499 if(ev->value_mask & CWWidth) |
512 c->w = ev->width; |
500 c->w = ev->width; |
513 if(ev->value_mask & CWHeight) |
501 if(ev->value_mask & CWHeight) |
514 c->h = ev->height; |
502 c->h = ev->height; |
515 if((c->x - m->sx + c->w) > m->sw && c->isfloating) |
503 if((c->x - v->x + c->w) > v->w && c->isfloating) |
516 c->x = m->sx + (m->sw / 2 - c->w / 2); /* center in x direction */ |
504 c->x = v->x + (v->w / 2 - c->w / 2); /* center in x direction */ |
517 if((c->y - m->sy + c->h) > m->sh && c->isfloating) |
505 if((c->y - v->y + c->h) > v->h && c->isfloating) |
518 c->y = m->sy + (m->sh / 2 - c->h / 2); /* center in y direction */ |
506 c->y = v->y + (v->h / 2 - c->h / 2); /* center in y direction */ |
519 if((ev->value_mask & (CWX | CWY)) |
507 if((ev->value_mask & (CWX|CWY)) |
520 && !(ev->value_mask & (CWWidth | CWHeight))) |
508 && !(ev->value_mask & (CWWidth|CWHeight))) |
521 configure(c); |
509 configure(c); |
522 if(isvisible(c, monitorat())) |
510 if(isvisible(c)) |
523 XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); |
511 XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); |
524 } |
512 } |
525 else |
513 else |
526 configure(c); |
514 configure(c); |
527 } |
515 } |
565 for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext); |
553 for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext); |
566 *tc = c->snext; |
554 *tc = c->snext; |
567 } |
555 } |
568 |
556 |
569 void |
557 void |
570 drawbar(Monitor *m) { |
558 drawbar(View *v) { |
571 int j, x; |
559 int i, x; |
572 Client *c; |
560 Client *c; |
573 |
561 |
574 dc.x = 0; |
562 dc.x = 0; |
575 for(c = stack; c && !isvisible(c, m); c = c->snext); |
563 for(c = stack; c && !isvisible(c); c = c->snext); |
576 for(j = 0; j < LENGTH(tags); j++) { |
564 for(i = 0; i < LENGTH(tags); i++) { |
577 dc.w = textw(tags[j]); |
565 dc.w = textw(tags[i]); |
578 if(m->seltags[j]) { |
566 if(seltags[i]) { |
579 drawtext(m, tags[j], dc.sel, isurgent(m, j)); |
567 drawtext(v, tags[i], dc.sel, isurgent(i)); |
580 drawsquare(m, c && c->tags[j] && c->monitor == m, |
568 drawsquare(v, c && c->tags[i], isoccupied(i), isurgent(i), dc.sel); |
581 isoccupied(m, j), isurgent(m, j), dc.sel); |
|
582 } |
569 } |
583 else { |
570 else { |
584 drawtext(m, tags[j], dc.norm, isurgent(m, j)); |
571 drawtext(v, tags[i], dc.norm, isurgent(i)); |
585 drawsquare(m, c && c->tags[j] && c->monitor == m, |
572 drawsquare(v, c && c->tags[i], isoccupied(i), isurgent(i), dc.norm); |
586 isoccupied(m, j), isurgent(m, j), dc.norm); |
|
587 } |
573 } |
588 dc.x += dc.w; |
574 dc.x += dc.w; |
589 } |
575 } |
590 dc.w = blw; |
576 dc.w = blw; |
591 drawtext(m, m->layout->symbol, dc.norm, False); |
577 drawtext(v, v->layout->symbol, dc.norm, False); |
592 x = dc.x + dc.w; |
578 x = dc.x + dc.w; |
593 if(m == selmonitor) { |
579 if(v == selview) { |
594 dc.w = textw(stext); |
580 dc.w = textw(stext); |
595 dc.x = m->sw - dc.w; |
581 dc.x = v->w - dc.w; |
596 if(dc.x < x) { |
582 if(dc.x < x) { |
597 dc.x = x; |
583 dc.x = x; |
598 dc.w = m->sw - x; |
584 dc.w = v->w - x; |
599 } |
585 } |
600 drawtext(m, stext, dc.norm, False); |
586 drawtext(v, stext, dc.norm, False); |
601 } |
587 } |
602 else |
588 else |
603 dc.x = m->sw; |
589 dc.x = v->w; |
604 if((dc.w = dc.x - x) > bh) { |
590 if((dc.w = dc.x - x) > bh) { |
605 dc.x = x; |
591 dc.x = x; |
606 if(c) { |
592 if(c) { |
607 drawtext(m, c->name, dc.sel, False); |
593 drawtext(v, c->name, dc.sel, False); |
608 drawsquare(m, False, c->isfloating, False, dc.sel); |
594 drawsquare(v, False, c->isfloating, False, dc.sel); |
609 } |
595 } |
610 else |
596 else |
611 drawtext(m, NULL, dc.norm, False); |
597 drawtext(v, NULL, dc.norm, False); |
612 } |
598 } |
613 XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->sw, bh, 0, 0); |
599 XCopyArea(dpy, dc.drawable, v->barwin, dc.gc, 0, 0, v->w, bh, 0, 0); |
614 XSync(dpy, False); |
600 XSync(dpy, False); |
615 } |
601 } |
616 |
602 |
617 void |
603 void |
618 drawsquare(Monitor *m, Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { |
604 drawsquare(View *v, Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { |
619 int x; |
605 int x; |
620 XGCValues gcv; |
606 XGCValues gcv; |
621 XRectangle r = { dc.x, dc.y, dc.w, dc.h }; |
607 XRectangle r = { dc.x, dc.y, dc.w, dc.h }; |
622 |
608 |
623 gcv.foreground = col[invert ? ColBG : ColFG]; |
609 gcv.foreground = col[invert ? ColBG : ColFG]; |
874 XUngrabButton(dpy, AnyButton, AnyModifier, c->win); |
872 XUngrabButton(dpy, AnyButton, AnyModifier, c->win); |
875 |
873 |
876 if(focused) { |
874 if(focused) { |
877 XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK, |
875 XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK, |
878 GrabModeAsync, GrabModeSync, None, None); |
876 GrabModeAsync, GrabModeSync, None, None); |
879 XGrabButton(dpy, Button1, MODKEY | LockMask, c->win, False, BUTTONMASK, |
877 XGrabButton(dpy, Button1, MODKEY|LockMask, c->win, False, BUTTONMASK, |
880 GrabModeAsync, GrabModeSync, None, None); |
878 GrabModeAsync, GrabModeSync, None, None); |
881 XGrabButton(dpy, Button1, MODKEY | numlockmask, c->win, False, BUTTONMASK, |
879 XGrabButton(dpy, Button1, MODKEY|numlockmask, c->win, False, BUTTONMASK, |
882 GrabModeAsync, GrabModeSync, None, None); |
880 GrabModeAsync, GrabModeSync, None, None); |
883 XGrabButton(dpy, Button1, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, |
881 XGrabButton(dpy, Button1, MODKEY|numlockmask|LockMask, c->win, False, BUTTONMASK, |
884 GrabModeAsync, GrabModeSync, None, None); |
882 GrabModeAsync, GrabModeSync, None, None); |
885 |
883 |
886 XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK, |
884 XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK, |
887 GrabModeAsync, GrabModeSync, None, None); |
885 GrabModeAsync, GrabModeSync, None, None); |
888 XGrabButton(dpy, Button2, MODKEY | LockMask, c->win, False, BUTTONMASK, |
886 XGrabButton(dpy, Button2, MODKEY|LockMask, c->win, False, BUTTONMASK, |
889 GrabModeAsync, GrabModeSync, None, None); |
887 GrabModeAsync, GrabModeSync, None, None); |
890 XGrabButton(dpy, Button2, MODKEY | numlockmask, c->win, False, BUTTONMASK, |
888 XGrabButton(dpy, Button2, MODKEY|numlockmask, c->win, False, BUTTONMASK, |
891 GrabModeAsync, GrabModeSync, None, None); |
889 GrabModeAsync, GrabModeSync, None, None); |
892 XGrabButton(dpy, Button2, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, |
890 XGrabButton(dpy, Button2, MODKEY|numlockmask|LockMask, c->win, False, BUTTONMASK, |
893 GrabModeAsync, GrabModeSync, None, None); |
891 GrabModeAsync, GrabModeSync, None, None); |
894 |
892 |
895 XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK, |
893 XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK, |
896 GrabModeAsync, GrabModeSync, None, None); |
894 GrabModeAsync, GrabModeSync, None, None); |
897 XGrabButton(dpy, Button3, MODKEY | LockMask, c->win, False, BUTTONMASK, |
895 XGrabButton(dpy, Button3, MODKEY|LockMask, c->win, False, BUTTONMASK, |
898 GrabModeAsync, GrabModeSync, None, None); |
896 GrabModeAsync, GrabModeSync, None, None); |
899 XGrabButton(dpy, Button3, MODKEY | numlockmask, c->win, False, BUTTONMASK, |
897 XGrabButton(dpy, Button3, MODKEY|numlockmask, c->win, False, BUTTONMASK, |
900 GrabModeAsync, GrabModeSync, None, None); |
898 GrabModeAsync, GrabModeSync, None, None); |
901 XGrabButton(dpy, Button3, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, |
899 XGrabButton(dpy, Button3, MODKEY|numlockmask|LockMask, c->win, False, BUTTONMASK, |
902 GrabModeAsync, GrabModeSync, None, None); |
900 GrabModeAsync, GrabModeSync, None, None); |
903 } |
901 } |
904 else |
902 else |
905 XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK, |
903 XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK, |
906 GrabModeAsync, GrabModeSync, None, None); |
904 GrabModeAsync, GrabModeSync, None, None); |
924 XUngrabKey(dpy, AnyKey, AnyModifier, root); |
922 XUngrabKey(dpy, AnyKey, AnyModifier, root); |
925 for(i = 0; i < LENGTH(keys); i++) { |
923 for(i = 0; i < LENGTH(keys); i++) { |
926 code = XKeysymToKeycode(dpy, keys[i].keysym); |
924 code = XKeysymToKeycode(dpy, keys[i].keysym); |
927 XGrabKey(dpy, code, keys[i].mod, root, True, |
925 XGrabKey(dpy, code, keys[i].mod, root, True, |
928 GrabModeAsync, GrabModeAsync); |
926 GrabModeAsync, GrabModeAsync); |
929 XGrabKey(dpy, code, keys[i].mod | LockMask, root, True, |
927 XGrabKey(dpy, code, keys[i].mod|LockMask, root, True, |
930 GrabModeAsync, GrabModeAsync); |
928 GrabModeAsync, GrabModeAsync); |
931 XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True, |
929 XGrabKey(dpy, code, keys[i].mod|numlockmask, root, True, |
932 GrabModeAsync, GrabModeAsync); |
930 GrabModeAsync, GrabModeAsync); |
933 XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True, |
931 XGrabKey(dpy, code, keys[i].mod|numlockmask|LockMask, root, True, |
934 GrabModeAsync, GrabModeAsync); |
932 GrabModeAsync, GrabModeAsync); |
935 } |
933 } |
936 } |
934 } |
937 |
935 |
938 unsigned int |
936 unsigned int |
1069 } |
1065 } |
1070 |
1066 |
1071 void |
1067 void |
1072 manage(Window w, XWindowAttributes *wa) { |
1068 manage(Window w, XWindowAttributes *wa) { |
1073 Client *c, *t = NULL; |
1069 Client *c, *t = NULL; |
1074 Monitor *m; |
1070 View *v; |
1075 Status rettrans; |
1071 Status rettrans; |
1076 Window trans; |
1072 Window trans; |
1077 XWindowChanges wc; |
1073 XWindowChanges wc; |
1078 |
1074 |
1079 c = emallocz(sizeof(Client)); |
1075 c = emallocz(sizeof(Client)); |
1080 c->tags = emallocz(sizeof initags); |
1076 c->tags = emallocz(sizeof initags); |
1081 c->win = w; |
1077 c->win = w; |
1082 |
1078 |
1083 applyrules(c); |
1079 applyrules(c); |
1084 |
1080 |
1085 m = c->monitor; |
1081 v = getview(c); |
1086 |
1082 |
1087 c->x = wa->x + m->sx; |
1083 c->x = wa->x + v->x; |
1088 c->y = wa->y + m->sy; |
1084 c->y = wa->y + v->y; |
1089 c->w = wa->width; |
1085 c->w = wa->width; |
1090 c->h = wa->height; |
1086 c->h = wa->height; |
1091 c->oldborder = wa->border_width; |
1087 c->oldborder = wa->border_width; |
1092 |
1088 |
1093 if(c->w == m->sw && c->h == m->sh) { |
1089 if(c->w == v->w && c->h == v->h) { |
1094 c->x = m->sx; |
1090 c->x = v->x; |
1095 c->y = m->sy; |
1091 c->y = v->y; |
1096 c->border = wa->border_width; |
1092 c->border = wa->border_width; |
1097 } |
1093 } |
1098 else { |
1094 else { |
1099 if(c->x + c->w + 2 * c->border > m->wax + m->waw) |
1095 if(c->x + c->w + 2 * c->border > v->wax + v->waw) |
1100 c->x = m->wax + m->waw - c->w - 2 * c->border; |
1096 c->x = v->wax + v->waw - c->w - 2 * c->border; |
1101 if(c->y + c->h + 2 * c->border > m->way + m->wah) |
1097 if(c->y + c->h + 2 * c->border > v->way + v->wah) |
1102 c->y = m->way + m->wah - c->h - 2 * c->border; |
1098 c->y = v->way + v->wah - c->h - 2 * c->border; |
1103 if(c->x < m->wax) |
1099 if(c->x < v->wax) |
1104 c->x = m->wax; |
1100 c->x = v->wax; |
1105 if(c->y < m->way) |
1101 if(c->y < v->way) |
1106 c->y = m->way; |
1102 c->y = v->way; |
1107 c->border = BORDERPX; |
1103 c->border = BORDERPX; |
1108 } |
1104 } |
1109 wc.border_width = c->border; |
1105 wc.border_width = c->border; |
1110 XConfigureWindow(dpy, w, CWBorderWidth, &wc); |
1106 XConfigureWindow(dpy, w, CWBorderWidth, &wc); |
1111 XSetWindowBorder(dpy, w, dc.norm[ColBorder]); |
1107 XSetWindowBorder(dpy, w, dc.norm[ColBorder]); |
1112 configure(c); /* propagates border_width, if size doesn't change */ |
1108 configure(c); /* propagates border_width, if size doesn't change */ |
1113 updatesizehints(c); |
1109 updatesizehints(c); |
1114 XSelectInput(dpy, w, EnterWindowMask | FocusChangeMask | PropertyChangeMask | StructureNotifyMask); |
1110 XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); |
1115 grabbuttons(c, False); |
1111 grabbuttons(c, False); |
1116 updatetitle(c); |
1112 updatetitle(c); |
1117 if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success)) |
1113 if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success)) |
1118 for(t = clients; t && t->win != trans; t = t->next); |
1114 for(t = clients; t && t->win != trans; t = t->next); |
1119 if(t) |
1115 if(t) |
1149 return; |
1145 return; |
1150 if(!getclient(ev->window)) |
1146 if(!getclient(ev->window)) |
1151 manage(ev->window, &wa); |
1147 manage(ev->window, &wa); |
1152 } |
1148 } |
1153 |
1149 |
1154 Monitor * |
1150 View * |
1155 monitorat() { |
1151 viewat() { |
1156 int i, x, y; |
1152 int i, x, y; |
1157 Window win; |
1153 Window win; |
1158 unsigned int mask; |
1154 unsigned int mask; |
1159 |
1155 |
1160 XQueryPointer(dpy, root, &win, &win, &x, &y, &i, &i, &mask); |
1156 XQueryPointer(dpy, root, &win, &win, &x, &y, &i, &i, &mask); |
1161 for(i = 0; i < mcount; i++) { |
1157 for(i = 0; i < nviews; i++) { |
1162 if((x >= monitors[i].sx && x < monitors[i].sx + monitors[i].sw) |
1158 if((x >= views[i].x && x < views[i].x + views[i].w) |
1163 && (y >= monitors[i].sy && y < monitors[i].sy + monitors[i].sh)) { |
1159 && (y >= views[i].y && y < views[i].y + views[i].h)) { |
1164 return &monitors[i]; |
1160 return &views[i]; |
1165 } |
1161 } |
1166 } |
1162 } |
1167 return NULL; |
1163 return NULL; |
1168 } |
1164 } |
1169 |
1165 |
1170 void |
1166 void |
1171 movemouse(Client *c) { |
1167 movemouse(Client *c) { |
1172 int x1, y1, ocx, ocy, di, nx, ny; |
1168 int x1, y1, ocx, ocy, di, nx, ny; |
1173 unsigned int dui; |
1169 unsigned int dui; |
1174 Monitor *m; |
1170 View *v; |
1175 Window dummy; |
1171 Window dummy; |
1176 XEvent ev; |
1172 XEvent ev; |
1177 |
1173 |
1178 ocx = nx = c->x; |
1174 ocx = nx = c->x; |
1179 ocy = ny = c->y; |
1175 ocy = ny = c->y; |
1180 m = c->monitor; |
1176 v = getview(c); |
1181 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |
1177 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |
1182 None, cursor[CurMove], CurrentTime) != GrabSuccess) |
1178 None, cursor[CurMove], CurrentTime) != GrabSuccess) |
1183 return; |
1179 return; |
1184 XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui); |
1180 XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui); |
1185 for(;;) { |
1181 for(;;) { |
1186 XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev); |
1182 XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); |
1187 switch (ev.type) { |
1183 switch (ev.type) { |
1188 case ButtonRelease: |
1184 case ButtonRelease: |
1189 XUngrabPointer(dpy, CurrentTime); |
1185 XUngrabPointer(dpy, CurrentTime); |
1190 return; |
1186 return; |
1191 case ConfigureRequest: |
1187 case ConfigureRequest: |
1195 break; |
1191 break; |
1196 case MotionNotify: |
1192 case MotionNotify: |
1197 XSync(dpy, False); |
1193 XSync(dpy, False); |
1198 nx = ocx + (ev.xmotion.x - x1); |
1194 nx = ocx + (ev.xmotion.x - x1); |
1199 ny = ocy + (ev.xmotion.y - y1); |
1195 ny = ocy + (ev.xmotion.y - y1); |
1200 if(abs(m->wax - nx) < SNAP) |
1196 if(abs(v->wax - nx) < SNAP) |
1201 nx = m->wax; |
1197 nx = v->wax; |
1202 else if(abs((m->wax + m->waw) - (nx + c->w + 2 * c->border)) < SNAP) |
1198 else if(abs((v->wax + v->waw) - (nx + c->w + 2 * c->border)) < SNAP) |
1203 nx = m->wax + m->waw - c->w - 2 * c->border; |
1199 nx = v->wax + v->waw - c->w - 2 * c->border; |
1204 if(abs(m->way - ny) < SNAP) |
1200 if(abs(v->way - ny) < SNAP) |
1205 ny = m->way; |
1201 ny = v->way; |
1206 else if(abs((m->way + m->wah) - (ny + c->h + 2 * c->border)) < SNAP) |
1202 else if(abs((v->way + v->wah) - (ny + c->h + 2 * c->border)) < SNAP) |
1207 ny = m->way + m->wah - c->h - 2 * c->border; |
1203 ny = v->way + v->wah - c->h - 2 * c->border; |
1208 if(!c->isfloating && (m->layout->arrange != floating) && (abs(nx - c->x) > SNAP || abs(ny - c->y) > SNAP)) |
1204 if(!c->isfloating && (v->layout->arrange != floating) && (abs(nx - c->x) > SNAP || abs(ny - c->y) > SNAP)) |
1209 togglefloating(NULL); |
1205 togglefloating(NULL); |
1210 if((m->layout->arrange == floating) || c->isfloating) |
1206 if((v->layout->arrange == floating) || c->isfloating) |
1211 resize(c, nx, ny, c->w, c->h, False); |
1207 resize(c, nx, ny, c->w, c->h, False); |
1212 break; |
1208 break; |
1213 } |
1209 } |
1214 } |
1210 } |
1215 } |
1211 } |
1216 |
1212 |
1217 Client * |
1213 Client * |
1218 nexttiled(Client *c, Monitor *monitor) { |
1214 nexttiled(Client *c, View *v) { |
1219 for(; c && (c->isfloating || !isvisible(c, monitor)); c = c->next); |
1215 for(; c && (c->isfloating || getview(c) != v || !isvisible(c)); c = c->next); |
1220 return c; |
1216 return c; |
1221 } |
1217 } |
1222 |
1218 |
1223 void |
1219 void |
1224 propertynotify(XEvent *e) { |
1220 propertynotify(XEvent *e) { |
1313 if(c->maxh > 0 && h > c->maxh) |
1309 if(c->maxh > 0 && h > c->maxh) |
1314 h = c->maxh; |
1310 h = c->maxh; |
1315 } |
1311 } |
1316 if(w <= 0 || h <= 0) |
1312 if(w <= 0 || h <= 0) |
1317 return; |
1313 return; |
1318 if(x > m->sw) |
1314 if(x > v->x + v->w) |
1319 x = m->sw - w - 2 * c->border; |
1315 x = v->w - w - 2 * c->border; |
1320 if(y > m->sh) |
1316 if(y > v->y + v->h) |
1321 y = m->sh - h - 2 * c->border; |
1317 y = v->h - h - 2 * c->border; |
1322 if(x + w + 2 * c->border < m->sx) |
1318 if(x + w + 2 * c->border < v->x) |
1323 x = m->sx; |
1319 x = v->x; |
1324 if(y + h + 2 * c->border < m->sy) |
1320 if(y + h + 2 * c->border < v->y) |
1325 y = m->sy; |
1321 y = v->y; |
1326 fprintf(stderr, "resize %d %d %d %d (%d %d %d %d)\n", x, y , w, h, m->sx, m->sy, m->sw, m->sh); |
|
1327 if(c->x != x || c->y != y || c->w != w || c->h != h) { |
1322 if(c->x != x || c->y != y || c->w != w || c->h != h) { |
1328 c->x = wc.x = x; |
1323 c->x = wc.x = x; |
1329 c->y = wc.y = y; |
1324 c->y = wc.y = y; |
1330 c->w = wc.width = w; |
1325 c->w = wc.width = w; |
1331 c->h = wc.height = h; |
1326 c->h = wc.height = h; |
1332 wc.border_width = c->border; |
1327 wc.border_width = c->border; |
1333 XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc); |
1328 XConfigureWindow(dpy, c->win, |
|
1329 CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); |
1334 configure(c); |
1330 configure(c); |
1335 XSync(dpy, False); |
1331 XSync(dpy, False); |
1336 } |
1332 } |
1337 } |
1333 } |
1338 |
1334 |
1339 void |
1335 void |
1340 resizemouse(Client *c) { |
1336 resizemouse(Client *c) { |
1341 int ocx, ocy; |
1337 int ocx, ocy; |
1342 int nw, nh; |
1338 int nw, nh; |
1343 Monitor *m; |
1339 View *v; |
1344 XEvent ev; |
1340 XEvent ev; |
1345 |
1341 |
1346 ocx = c->x; |
1342 ocx = c->x; |
1347 ocy = c->y; |
1343 ocy = c->y; |
1348 m = c->monitor; |
1344 v = getview(c); |
1349 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |
1345 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |
1350 None, cursor[CurResize], CurrentTime) != GrabSuccess) |
1346 None, cursor[CurResize], CurrentTime) != GrabSuccess) |
1351 return; |
1347 return; |
1352 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1); |
1348 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1); |
1353 for(;;) { |
1349 for(;;) { |
1354 XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev); |
1350 XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask , &ev); |
1355 switch(ev.type) { |
1351 switch(ev.type) { |
1356 case ButtonRelease: |
1352 case ButtonRelease: |
1357 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, |
1353 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, |
1358 c->w + c->border - 1, c->h + c->border - 1); |
1354 c->w + c->border - 1, c->h + c->border - 1); |
1359 XUngrabPointer(dpy, CurrentTime); |
1355 XUngrabPointer(dpy, CurrentTime); |
1368 XSync(dpy, False); |
1364 XSync(dpy, False); |
1369 if((nw = ev.xmotion.x - ocx - 2 * c->border + 1) <= 0) |
1365 if((nw = ev.xmotion.x - ocx - 2 * c->border + 1) <= 0) |
1370 nw = 1; |
1366 nw = 1; |
1371 if((nh = ev.xmotion.y - ocy - 2 * c->border + 1) <= 0) |
1367 if((nh = ev.xmotion.y - ocy - 2 * c->border + 1) <= 0) |
1372 nh = 1; |
1368 nh = 1; |
1373 if(!c->isfloating && (m->layout->arrange != floating) && (abs(nw - c->w) > SNAP || abs(nh - c->h) > SNAP)) |
1369 if(!c->isfloating && (v->layout->arrange != floating) && (abs(nw - c->w) > SNAP || abs(nh - c->h) > SNAP)) |
1374 togglefloating(NULL); |
1370 togglefloating(NULL); |
1375 if((m->layout->arrange == floating) || c->isfloating) |
1371 if((v->layout->arrange == floating) || c->isfloating) |
1376 resize(c, c->x, c->y, nw, nh, True); |
1372 resize(c, c->x, c->y, nw, nh, True); |
1377 break; |
1373 break; |
1378 } |
1374 } |
1379 } |
1375 } |
1380 } |
1376 } |
1381 |
1377 |
1382 void |
1378 void |
1383 restack(Monitor *m) { |
1379 restack(View *v) { |
1384 Client *c; |
1380 Client *c; |
1385 XEvent ev; |
1381 XEvent ev; |
1386 XWindowChanges wc; |
1382 XWindowChanges wc; |
1387 |
1383 |
1388 drawbar(m); |
1384 drawbar(v); |
1389 if(!sel) |
1385 if(!sel) |
1390 return; |
1386 return; |
1391 if(sel->isfloating || (m->layout->arrange == floating)) |
1387 if(sel->isfloating || (v->layout->arrange == floating)) |
1392 XRaiseWindow(dpy, sel->win); |
1388 XRaiseWindow(dpy, sel->win); |
1393 if(m->layout->arrange != floating) { |
1389 if(v->layout->arrange != floating) { |
1394 wc.stack_mode = Below; |
1390 wc.stack_mode = Below; |
1395 wc.sibling = m->barwin; |
1391 wc.sibling = v->barwin; |
1396 if(!sel->isfloating) { |
1392 if(!sel->isfloating) { |
1397 XConfigureWindow(dpy, sel->win, CWSibling | CWStackMode, &wc); |
1393 XConfigureWindow(dpy, sel->win, CWSibling|CWStackMode, &wc); |
1398 wc.sibling = sel->win; |
1394 wc.sibling = sel->win; |
1399 } |
1395 } |
1400 for(c = nexttiled(clients, m); c; c = nexttiled(c->next, m)) { |
1396 for(c = nexttiled(clients, v); c; c = nexttiled(c->next, v)) { |
1401 if(c == sel) |
1397 if(c == sel) |
1402 continue; |
1398 continue; |
1403 XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc); |
1399 XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); |
1404 wc.sibling = c->win; |
1400 wc.sibling = c->win; |
1405 } |
1401 } |
1406 } |
1402 } |
1407 XSync(dpy, False); |
1403 XSync(dpy, False); |
1408 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
1404 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
1597 for(blw = i = 0; i < LENGTH(layouts); i++) { |
1596 for(blw = i = 0; i < LENGTH(layouts); i++) { |
1598 i = textw(layouts[i].symbol); |
1597 i = textw(layouts[i].symbol); |
1599 if(i > blw) |
1598 if(i > blw) |
1600 blw = i; |
1599 blw = i; |
1601 } |
1600 } |
1602 for(i = 0; i < mcount; i++) { |
1601 |
|
1602 seltags = emallocz(sizeof initags); |
|
1603 prevtags = emallocz(sizeof initags); |
|
1604 memcpy(seltags, initags, sizeof initags); |
|
1605 memcpy(prevtags, initags, sizeof initags); |
|
1606 |
|
1607 for(i = 0; i < nviews; i++) { |
1603 /* init geometry */ |
1608 /* init geometry */ |
1604 m = &monitors[i]; |
1609 v = &views[i]; |
1605 |
1610 v->id = i + 1; |
1606 if(mcount != 1 && isxinerama) { |
1611 |
1607 m->sx = info[i].x_org; |
1612 if(nviews != 1 && isxinerama) { |
1608 m->sy = info[i].y_org; |
1613 |
1609 m->sw = info[i].width; |
1614 #if defined(AIM_XINERAMA) |
1610 m->sh = info[i].height; |
1615 v->w = DisplayWidth(dpy, screen) / 2; |
1611 fprintf(stderr, "monitor[%d]: %d,%d,%d,%d\n", i, m->sx, m->sy, m->sw, m->sh); |
1616 v->x = (i == 0) ? 0 : v->w; |
|
1617 v->y = 0; |
|
1618 v->h = DisplayHeight(dpy, screen); |
|
1619 #else |
|
1620 v->x = info[i].x_org; |
|
1621 v->y = info[i].y_org; |
|
1622 v->w = info[i].width; |
|
1623 v->h = info[i].height; |
|
1624 #endif |
1612 } |
1625 } |
1613 else { |
1626 else { |
1614 m->sx = 0; |
1627 v->x = 0; |
1615 m->sy = 0; |
1628 v->y = 0; |
1616 m->sw = DisplayWidth(dpy, screen); |
1629 v->w = DisplayWidth(dpy, screen); |
1617 m->sh = DisplayHeight(dpy, screen); |
1630 v->h = DisplayHeight(dpy, screen); |
1618 } |
1631 } |
1619 |
|
1620 m->seltags = emallocz(sizeof initags); |
|
1621 m->prevtags = emallocz(sizeof initags); |
|
1622 |
|
1623 memcpy(m->seltags, initags, sizeof initags); |
|
1624 memcpy(m->prevtags, initags, sizeof initags); |
|
1625 |
1632 |
1626 /* init layouts */ |
1633 /* init layouts */ |
1627 m->mwfact = MWFACT; |
1634 v->mwfact = MWFACT; |
1628 m->layout = &layouts[0]; |
1635 v->layout = &layouts[0]; |
1629 |
1636 |
1630 // TODO: bpos per screen? |
1637 // TODO: bpos per screen? |
1631 bpos = BARPOS; |
1638 bpos = BARPOS; |
1632 wa.override_redirect = 1; |
1639 wa.override_redirect = 1; |
1633 wa.background_pixmap = ParentRelative; |
1640 wa.background_pixmap = ParentRelative; |
1634 wa.event_mask = ButtonPressMask | ExposureMask; |
1641 wa.event_mask = ButtonPressMask|ExposureMask; |
1635 |
1642 |
1636 /* init bars */ |
1643 /* init bars */ |
1637 m->barwin = XCreateWindow(dpy, root, m->sx, m->sy, m->sw, bh, 0, |
1644 v->barwin = XCreateWindow(dpy, root, v->x, v->y, v->w, bh, 0, |
1638 DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen), |
1645 DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen), |
1639 CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); |
1646 CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); |
1640 XDefineCursor(dpy, m->barwin, cursor[CurNormal]); |
1647 XDefineCursor(dpy, v->barwin, cursor[CurNormal]); |
1641 updatebarpos(m); |
1648 updatebarpos(v); |
1642 XMapRaised(dpy, m->barwin); |
1649 XMapRaised(dpy, v->barwin); |
1643 strcpy(stext, "dwm-"VERSION); |
1650 strcpy(stext, "dwm-"VERSION); |
1644 |
1651 |
1645 /* EWMH support per monitor */ |
1652 /* EWMH support per view */ |
1646 XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, |
1653 XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, |
1647 PropModeReplace, (unsigned char *) netatom, NetLast); |
1654 PropModeReplace, (unsigned char *) netatom, NetLast); |
1648 |
1655 |
1649 /* select for events */ |
1656 /* select for events */ |
1650 wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask |
1657 wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask |
1651 | EnterWindowMask | LeaveWindowMask | StructureNotifyMask; |
1658 |EnterWindowMask|LeaveWindowMask|StructureNotifyMask; |
1652 XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); |
1659 XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); |
1653 XSelectInput(dpy, root, wa.event_mask); |
1660 XSelectInput(dpy, root, wa.event_mask); |
1654 |
1661 |
1655 drawbar(m); |
1662 drawbar(v); |
1656 } |
1663 } |
1657 if(info) |
1664 if(info) |
1658 XFree(info); |
1665 XFree(info); |
1659 |
1666 |
1660 /* grab keys */ |
1667 /* grab keys */ |
1661 grabkeys(); |
1668 grabkeys(); |
1662 |
1669 |
1663 /* init tags */ |
1670 /* init tags */ |
1664 compileregs(); |
1671 compileregs(); |
1665 |
1672 |
1666 selmonitor = monitorat(); |
1673 selview = &views[0]; |
1667 fprintf(stderr, "selmonitor == %d\n", selmonitor - monitors); |
|
1668 } |
1674 } |
1669 |
1675 |
1670 void |
1676 void |
1671 spawn(const char *arg) { |
1677 spawn(const char *arg) { |
1672 static char *shell = NULL; |
1678 static char *shell = NULL; |
1718 textw(const char *text) { |
1724 textw(const char *text) { |
1719 return textnw(text, strlen(text)) + dc.font.height; |
1725 return textnw(text, strlen(text)) + dc.font.height; |
1720 } |
1726 } |
1721 |
1727 |
1722 void |
1728 void |
1723 tile(Monitor *m) { |
1729 tile(View *v) { |
1724 unsigned int i, n, nx, ny, nw, nh, mw, th; |
1730 unsigned int i, n, nx, ny, nw, nh, mw, th; |
1725 Client *c, *mc; |
1731 Client *c, *mc; |
1726 |
1732 |
1727 domwfact = dozoom = True; |
1733 domwfact = dozoom = True; |
1728 nx = m->wax; |
1734 nx = v->wax; |
1729 ny = m->way; |
1735 ny = v->way; |
1730 nw = 0; |
1736 nw = 0; |
1731 for(n = 0, c = nexttiled(clients, m); c; c = nexttiled(c->next, m)) |
1737 for(n = 0, c = nexttiled(clients, v); c; c = nexttiled(c->next, v)) |
1732 n++; |
1738 n++; |
1733 |
1739 |
1734 /* window geoms */ |
1740 /* window geoms */ |
1735 mw = (n == 1) ? m->waw : m->mwfact * m->waw; |
1741 mw = (n == 1) ? v->waw : v->mwfact * v->waw; |
1736 th = (n > 1) ? m->wah / (n - 1) : 0; |
1742 th = (n > 1) ? v->wah / (n - 1) : 0; |
1737 if(n > 1 && th < bh) |
1743 if(n > 1 && th < bh) |
1738 th = m->wah; |
1744 th = v->wah; |
1739 |
1745 |
1740 for(i = 0, c = mc = nexttiled(clients, m); c; c = nexttiled(c->next, m)) { |
1746 for(i = 0, c = mc = nexttiled(clients, v); c; c = nexttiled(c->next, v)) { |
1741 if(i == 0) { /* master */ |
1747 if(i == 0) { /* master */ |
1742 nx = m->wax; |
1748 nx = v->wax; |
1743 ny = m->way; |
1749 ny = v->way; |
1744 nw = mw - 2 * c->border; |
1750 nw = mw - 2 * c->border; |
1745 nh = m->wah - 2 * c->border; |
1751 nh = v->wah - 2 * c->border; |
1746 } |
1752 } |
1747 else { /* tile window */ |
1753 else { /* tile window */ |
1748 if(i == 1) { |
1754 if(i == 1) { |
1749 ny = m->way; |
1755 ny = v->way; |
1750 nx += mc->w + 2 * mc->border; |
1756 nx += mc->w + 2 * mc->border; |
1751 nw = m->waw - mw - 2 * c->border; |
1757 nw = v->waw - mw - 2 * c->border; |
1752 } |
1758 } |
1753 if(i + 1 == n) /* remainder */ |
1759 if(i + 1 == n) /* remainder */ |
1754 nh = (m->way + m->wah) - ny - 2 * c->border; |
1760 nh = (v->way + v->wah) - ny - 2 * c->border; |
1755 else |
1761 else |
1756 nh = th - 2 * c->border; |
1762 nh = th - 2 * c->border; |
1757 } |
1763 } |
1758 fprintf(stderr, "tile %d %d %d %d\n", nx, ny, nw, nh); |
1764 fprintf(stderr, "tile %d %d %d %d\n", nx, ny, nw, nh); |
1759 resize(c, nx, ny, nw, nh, RESIZEHINTS); |
1765 resize(c, nx, ny, nw, nh, RESIZEHINTS); |
1760 if((RESIZEHINTS) && ((c->h < bh) || (c->h > nh) || (c->w < bh) || (c->w > nw))) |
1766 if((RESIZEHINTS) && ((c->h < bh) || (c->h > nh) || (c->w < bh) || (c->w > nw))) |
1761 /* client doesn't accept size constraints */ |
1767 /* client doesn't accept size constraints */ |
1762 resize(c, nx, ny, nw, nh, False); |
1768 resize(c, nx, ny, nw, nh, False); |
1763 if(n > 1 && th != m->wah) |
1769 if(n > 1 && th != v->wah) |
1764 ny = c->y + c->h + 2 * c->border; |
1770 ny = c->y + c->h + 2 * c->border; |
1765 i++; |
1771 i++; |
1766 } |
1772 } |
1767 } |
1773 } |
1768 |
1774 |
1966 ee->request_code, ee->error_code); |
1970 ee->request_code, ee->error_code); |
1967 return xerrorxlib(dpy, ee); /* may call exit */ |
1971 return xerrorxlib(dpy, ee); /* may call exit */ |
1968 } |
1972 } |
1969 |
1973 |
1970 int |
1974 int |
1971 xerrordummy(Display *dsply, XErrorEvent *ee) { |
1975 xerrordummy(Display *dpy, XErrorEvent *ee) { |
1972 return 0; |
1976 return 0; |
1973 } |
1977 } |
1974 |
1978 |
1975 /* Startup Error handler to check if another window manager |
1979 /* Startup Error handler to check if another window manager |
1976 * is already running. */ |
1980 * is already running. */ |
1977 int |
1981 int |
1978 xerrorstart(Display *dsply, XErrorEvent *ee) { |
1982 xerrorstart(Display *dpy, XErrorEvent *ee) { |
1979 otherwm = True; |
1983 otherwm = True; |
1980 return -1; |
1984 return -1; |
1981 } |
1985 } |
1982 |
1986 |
1983 void |
1987 void |
1984 view(const char *arg) { |
1988 view(const char *arg) { |
1985 unsigned int i; |
1989 unsigned int i; |
1986 Bool tmp[LENGTH(tags)]; |
1990 int tmp[LENGTH(tags)]; |
1987 Monitor *m = monitorat(); |
|
1988 |
1991 |
1989 for(i = 0; i < LENGTH(tags); i++) |
1992 for(i = 0; i < LENGTH(tags); i++) |
1990 tmp[i] = (NULL == arg); |
1993 tmp[i] = (NULL == arg) ? selview->id : 0; |
1991 tmp[idxoftag(arg)] = True; |
1994 tmp[idxoftag(arg)] = selview->id; |
1992 if(memcmp(m->seltags, tmp, sizeof initags) != 0) { |
1995 if(memcmp(seltags, tmp, sizeof initags) != 0) { |
1993 memcpy(m->prevtags, m->seltags, sizeof initags); |
1996 memcpy(prevtags, seltags, sizeof initags); |
1994 memcpy(m->seltags, tmp, sizeof initags); |
1997 memcpy(seltags, tmp, sizeof initags); |
1995 arrange(m); |
1998 arrange(); |
1996 } |
1999 } |
1997 } |
2000 } |
1998 |
2001 |
1999 void |
2002 void |
2000 viewprevtag(const char *arg) { |
2003 viewprevtag(const char *arg) { |
2001 static Bool tmp[LENGTH(tags)]; |
2004 static Bool tmp[LENGTH(tags)]; |
2002 |
2005 |
2003 Monitor *m = monitorat(); |
2006 memcpy(tmp, seltags, sizeof initags); |
2004 |
2007 memcpy(seltags, prevtags, sizeof initags); |
2005 memcpy(tmp, m->seltags, sizeof initags); |
2008 memcpy(prevtags, tmp, sizeof initags); |
2006 memcpy(m->seltags, m->prevtags, sizeof initags); |
2009 arrange(); |
2007 memcpy(m->prevtags, tmp, sizeof initags); |
|
2008 arrange(m); |
|
2009 } |
2010 } |
2010 |
2011 |
2011 void |
2012 void |
2012 zoom(const char *arg) { |
2013 zoom(const char *arg) { |
2013 Client *c = sel; |
2014 Client *c = sel; |
2014 |
2015 |
2015 if(!sel || !dozoom || sel->isfloating) |
2016 if(!sel || !dozoom || sel->isfloating) |
2016 return; |
2017 return; |
2017 if(c == nexttiled(clients, c->monitor)) |
2018 if(c == nexttiled(clients, getview(c))) |
2018 if(!(c = nexttiled(c->next, c->monitor))) |
2019 if(!(c = nexttiled(c->next, getview(c)))) |
2019 return; |
2020 return; |
2020 detach(c); |
2021 detach(c); |
2021 attach(c); |
2022 attach(c); |
2022 focus(c); |
2023 focus(c); |
2023 arrange(c->monitor); |
2024 arrange(); |
2024 } |
2025 } |
2025 |
2026 |
2026 void |
2027 void |
2027 movetomonitor(const char *arg) { |
2028 selectview(const char *arg) { |
2028 int i; |
2029 int i; |
2029 |
2030 View *v; |
2030 if (sel) |
2031 |
|
2032 if(!arg) |
2031 return; |
2033 return; |
2032 if(arg) |
2034 if(arg) |
2033 i = atoi(arg); |
2035 i = atoi(arg); |
2034 else { |
2036 v = &views[i % nviews]; |
2035 for(i = 0; &monitors[i] != sel->monitor && i < mcount; i++); |
2037 XWarpPointer(dpy, None, root, 0, 0, 0, 0, v->wax+v->waw/2, v->way+v->wah/2); |
2036 i++; |
|
2037 } |
|
2038 sel->monitor = &monitors[i % mcount]; |
|
2039 |
|
2040 memcpy(sel->tags, sel->monitor->seltags, sizeof initags); |
|
2041 resize(sel, sel->monitor->wax, sel->monitor->way, sel->w, sel->h, True); |
|
2042 arrange(sel->monitor); |
|
2043 } |
|
2044 |
|
2045 void |
|
2046 selectmonitor(const char *arg) { |
|
2047 int i; |
|
2048 Monitor *m; |
|
2049 |
|
2050 if(arg) |
|
2051 i = atoi(arg); |
|
2052 else { |
|
2053 for(i = 0; &monitors[i] != sel->monitor && i < mcount; i++); |
|
2054 i++; |
|
2055 } |
|
2056 m = &monitors[i % mcount]; |
|
2057 XWarpPointer(dpy, None, root, 0, 0, 0, 0, m->wax+m->waw/2, m->way+m->wah/2); |
|
2058 focus(NULL); |
2038 focus(NULL); |
2059 } |
2039 } |
2060 |
2040 |
2061 |
2041 |
2062 int |
2042 int |
2063 main(int argc, char *argv[]) { |
2043 main(int argc, char *argv[]) { |
2064 fprintf(stderr, "%u\n", sizeof("jsjsjsjsjssjsj")); |
|
2065 if(argc == 2 && !strcmp("-v", argv[1])) |
2044 if(argc == 2 && !strcmp("-v", argv[1])) |
2066 eprint("dwm-"VERSION", © 2006-2008 dwm engineers, see LICENSE for details\n"); |
2045 eprint("dwm-"VERSION", © 2006-2008 dwm engineers, see LICENSE for details\n"); |
2067 else if(argc != 1) |
2046 else if(argc != 1) |
2068 eprint("usage: dwm [-v]\n"); |
2047 eprint("usage: dwm [-v]\n"); |
2069 |
2048 |