dwm.c
changeset 1093 5170cc8c078e
parent 1092 2c20bc278e5e
child 1094 0083ffeb95ee
equal deleted inserted replaced
1092:2c20bc278e5e 1093:5170cc8c078e
   142 void configurenotify(XEvent *e);
   142 void configurenotify(XEvent *e);
   143 void configurerequest(XEvent *e);
   143 void configurerequest(XEvent *e);
   144 void destroynotify(XEvent *e);
   144 void destroynotify(XEvent *e);
   145 void detach(Client *c);
   145 void detach(Client *c);
   146 void detachstack(Client *c);
   146 void detachstack(Client *c);
   147 void drawbar(void);
   147 void drawbar(Monitor *m);
   148 void drawsquare(Monitor *, Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
   148 void drawsquare(Monitor *m, Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
   149 void drawtext(Monitor *, const char *text, unsigned long col[ColLast], Bool invert);
   149 void drawtext(Monitor *m, const char *text, unsigned long col[ColLast], Bool invert);
   150 void *emallocz(unsigned int size);
   150 void *emallocz(unsigned int size);
   151 void enternotify(XEvent *e);
   151 void enternotify(XEvent *e);
   152 void eprint(const char *errstr, ...);
   152 void eprint(const char *errstr, ...);
   153 void expose(XEvent *e);
   153 void expose(XEvent *e);
   154 void floating(Monitor *m); /* default floating layout */
   154 void floating(Monitor *m); /* default floating layout */
   156 void focusin(XEvent *e);
   156 void focusin(XEvent *e);
   157 void focusnext(const char *arg);
   157 void focusnext(const char *arg);
   158 void focusprev(const char *arg);
   158 void focusprev(const char *arg);
   159 Client *getclient(Window w);
   159 Client *getclient(Window w);
   160 unsigned long getcolor(const char *colstr);
   160 unsigned long getcolor(const char *colstr);
       
   161 Monitor *getmonitor(Window barwin);
   161 long getstate(Window w);
   162 long getstate(Window w);
   162 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   163 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   163 void grabbuttons(Client *c, Bool focused);
   164 void grabbuttons(Client *c, Bool focused);
   164 void grabkeys(void);
   165 void grabkeys(void);
   165 unsigned int idxoftag(const char *tag);
   166 unsigned int idxoftag(const char *tag);
   178 void propertynotify(XEvent *e);
   179 void propertynotify(XEvent *e);
   179 void quit(const char *arg);
   180 void quit(const char *arg);
   180 void reapply(const char *arg);
   181 void reapply(const char *arg);
   181 void resize(Client *c, int x, int y, int w, int h, Bool sizehints);
   182 void resize(Client *c, int x, int y, int w, int h, Bool sizehints);
   182 void resizemouse(Client *c);
   183 void resizemouse(Client *c);
   183 void restack(void);
   184 void restack(Monitor *m);
   184 void run(void);
   185 void run(void);
   185 void scan(void);
   186 void scan(void);
   186 void setclientstate(Client *c, long state);
   187 void setclientstate(Client *c, long state);
   187 void setlayout(const char *arg);
   188 void setlayout(const char *arg);
   188 void setmwfact(const char *arg);
   189 void setmwfact(const char *arg);
   307 		else
   308 		else
   308 			ban(c);
   309 			ban(c);
   309 
   310 
   310 	monitors[selmonitor].layout->arrange(&monitors[selmonitor]);
   311 	monitors[selmonitor].layout->arrange(&monitors[selmonitor]);
   311 	focus(NULL);
   312 	focus(NULL);
   312 	restack();
   313 	restack(&monitors[selmonitor]);
   313 }
   314 }
   314 
   315 
   315 void
   316 void
   316 attach(Client *c) {
   317 attach(Client *c) {
   317 	if(clients)
   318 	if(clients)
   368 	else if((c = getclient(ev->window))) {
   369 	else if((c = getclient(ev->window))) {
   369 		focus(c);
   370 		focus(c);
   370 		if(CLEANMASK(ev->state) != MODKEY)
   371 		if(CLEANMASK(ev->state) != MODKEY)
   371 			return;
   372 			return;
   372 		if(ev->button == Button1) {
   373 		if(ev->button == Button1) {
   373 			restack();
   374 			restack(&monitors[c->monitor]);
   374 			movemouse(c);
   375 			movemouse(c);
   375 		}
   376 		}
   376 		else if(ev->button == Button2) {
   377 		else if(ev->button == Button2) {
   377 			if((floating != m->layout->arrange) && c->isfloating)
   378 			if((floating != m->layout->arrange) && c->isfloating)
   378 				togglefloating(NULL);
   379 				togglefloating(NULL);
   379 			else
   380 			else
   380 				zoom(NULL);
   381 				zoom(NULL);
   381 		}
   382 		}
   382 		else if(ev->button == Button3 && !c->isfixed) {
   383 		else if(ev->button == Button3 && !c->isfixed) {
   383 			restack();
   384 			restack(&monitors[c->monitor]);
   384 			resizemouse(c);
   385 			resizemouse(c);
   385 		}
   386 		}
   386 	}
   387 	}
   387 }
   388 }
   388 
   389 
   560 	for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext);
   561 	for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext);
   561 	*tc = c->snext;
   562 	*tc = c->snext;
   562 }
   563 }
   563 
   564 
   564 void
   565 void
   565 drawbar(void) {
   566 drawbar(Monitor *m) {
   566 	int i, j, x;
   567 	int j, x;
   567 	Client *c;
   568 	Client *c;
   568 
   569 
   569 	for(i = 0; i < mcount; i++) {
   570 	dc.x = 0;
   570 		Monitor *m = &monitors[i];
   571 	for(c = stack; c && !isvisible(c, m->id); c = c->snext);
   571 		dc.x = 0;
   572 	for(j = 0; j < LENGTH(tags); j++) {
   572 		for(c = stack; c && !isvisible(c, i); c = c->snext);
   573 		dc.w = textw(tags[j]);
   573 		fprintf(stderr, "m%d %s\n", i, c ? c->name : "NIL");
   574 		if(m->seltags[j]) {
   574 		for(j = 0; j < LENGTH(tags); j++) {
   575 			drawtext(m, tags[j], dc.sel, isurgent(m->id, j));
   575 			dc.w = textw(tags[j]);
   576 			drawsquare(m, c && c->tags[j] && c->monitor == m->id,
   576 			if(m->seltags[j]) {
   577 					isoccupied(m->id, j), isurgent(m->id, j), dc.sel);
   577 				drawtext(m, tags[j], dc.sel, isurgent(i, j));
   578 		}
   578 				drawsquare(m, c && c->tags[j] && c->monitor == i,
   579 		else {
   579 						isoccupied(i, j), isurgent(i, j), dc.sel);
   580 			drawtext(m, tags[j], dc.norm, isurgent(m->id, j));
   580 			}
   581 			drawsquare(m, c && c->tags[j] && c->monitor == m->id,
   581 			else {
   582 					isoccupied(m->id, j), isurgent(m->id, j), dc.norm);
   582 				drawtext(m, tags[j], dc.norm, isurgent(i, j));
   583 		}
   583 				drawsquare(m, c && c->tags[j] && c->monitor == i,
   584 		dc.x += dc.w;
   584 						isoccupied(i, j), isurgent(i, j), dc.norm);
   585 	}
   585 			}
   586 	dc.w = blw;
   586 			dc.x += dc.w;
   587 	drawtext(m, m->layout->symbol, dc.norm, False);
   587 		}
   588 	x = dc.x + dc.w;
   588 		dc.w = blw;
   589 	if(m->id == selmonitor) {
   589 		drawtext(m, m->layout->symbol, dc.norm, False);
   590 		dc.w = textw(stext);
   590 		x = dc.x + dc.w;
   591 		dc.x = m->sw - dc.w;
   591 		if(i == selmonitor) {
   592 		if(dc.x < x) {
   592 			dc.w = textw(stext);
   593 			dc.x = x;
   593 			dc.x = m->sw - dc.w;
   594 			dc.w = m->sw - x;
   594 			if(dc.x < x) {
   595 		}
   595 				dc.x = x;
   596 		drawtext(m, stext, dc.norm, False);
   596 				dc.w = m->sw - x;
   597 	}
   597 			}
   598 	else
   598 			drawtext(m, stext, dc.norm, False);
   599 		dc.x = m->sw;
       
   600 	if((dc.w = dc.x - x) > bh) {
       
   601 		dc.x = x;
       
   602 		if(c) {
       
   603 			drawtext(m, c->name, dc.sel, False);
       
   604 			drawsquare(m, False, c->isfloating, False, dc.sel);
   599 		}
   605 		}
   600 		else
   606 		else
   601 			dc.x = m->sw;
   607 			drawtext(m, NULL, dc.norm, False);
   602 		if((dc.w = dc.x - x) > bh) {
   608 	}
   603 			dc.x = x;
   609 	XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->sw, bh, 0, 0);
   604 			if(c) {
   610 	XSync(dpy, False);
   605 				drawtext(m, c->name, dc.sel, False);
       
   606 				drawsquare(m, False, c->isfloating, False, dc.sel);
       
   607 			}
       
   608 			else
       
   609 				drawtext(m, NULL, dc.norm, False);
       
   610 		}
       
   611 		XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->sw, bh, 0, 0);
       
   612 		XSync(dpy, False);
       
   613 	}
       
   614 }
   611 }
   615 
   612 
   616 void
   613 void
   617 drawsquare(Monitor *m, Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
   614 drawsquare(Monitor *m, Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
   618 	int x;
   615 	int x;
   711 	exit(EXIT_FAILURE);
   708 	exit(EXIT_FAILURE);
   712 }
   709 }
   713 
   710 
   714 void
   711 void
   715 expose(XEvent *e) {
   712 expose(XEvent *e) {
       
   713 	Monitor *m;
   716 	XExposeEvent *ev = &e->xexpose;
   714 	XExposeEvent *ev = &e->xexpose;
   717 
   715 
   718 	if(ev->count == 0) {
   716 	if(ev->count == 0 && (m = getmonitor(ev->window)))
   719 		if(ev->window == monitors[selmonitor].barwin)
   717 		drawbar(m);
   720 			drawbar();
       
   721 	}
       
   722 }
   718 }
   723 
   719 
   724 void
   720 void
   725 floating(Monitor *m) { /* default floating layout */
   721 floating(Monitor *m) { /* default floating layout */
   726 	Client *c;
   722 	Client *c;
   748 		detachstack(c);
   744 		detachstack(c);
   749 		attachstack(c);
   745 		attachstack(c);
   750 		grabbuttons(c, True);
   746 		grabbuttons(c, True);
   751 	}
   747 	}
   752 	sel = c;
   748 	sel = c;
   753 	drawbar();
       
   754 	if(c) {
   749 	if(c) {
   755 		XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
   750 		XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
   756 		XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   751 		XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   757 		selmonitor = c->monitor;
   752 		selmonitor = c->monitor;
   758 	}
   753 	}
   759 	else {
   754 	else
   760 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
   755 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
   761 		drawbar();
   756 	drawbar(&monitors[selmonitor]);
   762 	}
       
   763 }
   757 }
   764 
   758 
   765 void
   759 void
   766 focusin(XEvent *e) { /* there are some broken focus acquiring clients */
   760 focusin(XEvent *e) { /* there are some broken focus acquiring clients */
   767 	XFocusChangeEvent *ev = &e->xfocus;
   761 	XFocusChangeEvent *ev = &e->xfocus;
   779 	for(c = sel->next; c && !isvisible(c, selmonitor); c = c->next);
   773 	for(c = sel->next; c && !isvisible(c, selmonitor); c = c->next);
   780 	if(!c)
   774 	if(!c)
   781 		for(c = clients; c && !isvisible(c, selmonitor); c = c->next);
   775 		for(c = clients; c && !isvisible(c, selmonitor); c = c->next);
   782 	if(c) {
   776 	if(c) {
   783 		focus(c);
   777 		focus(c);
   784 		restack();
   778 		restack(&monitors[c->monitor]);
   785 	}
   779 	}
   786 }
   780 }
   787 
   781 
   788 void
   782 void
   789 focusprev(const char *arg) {
   783 focusprev(const char *arg) {
   796 		for(c = clients; c && c->next; c = c->next);
   790 		for(c = clients; c && c->next; c = c->next);
   797 		for(; c && !isvisible(c, selmonitor); c = c->prev);
   791 		for(; c && !isvisible(c, selmonitor); c = c->prev);
   798 	}
   792 	}
   799 	if(c) {
   793 	if(c) {
   800 		focus(c);
   794 		focus(c);
   801 		restack();
   795 		restack(&monitors[c->monitor]);
   802 	}
   796 	}
   803 }
   797 }
   804 
   798 
   805 Client *
   799 Client *
   806 getclient(Window w) {
   800 getclient(Window w) {
   816 	XColor color;
   810 	XColor color;
   817 
   811 
   818 	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
   812 	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
   819 		eprint("error, cannot allocate color '%s'\n", colstr);
   813 		eprint("error, cannot allocate color '%s'\n", colstr);
   820 	return color.pixel;
   814 	return color.pixel;
       
   815 }
       
   816 
       
   817 Monitor *
       
   818 getmonitor(Window barwin) {
       
   819 	unsigned int i;
       
   820 
       
   821 	for(i = 0; i < mcount; i++)
       
   822 		if(monitors[i].barwin == barwin)
       
   823 			return &monitors[i];
       
   824 	return NULL;
   821 }
   825 }
   822 
   826 
   823 long
   827 long
   824 getstate(Window w) {
   828 getstate(Window w) {
   825 	int format, status;
   829 	int format, status;
  1223 
  1227 
  1224 	if(ev->state == PropertyDelete)
  1228 	if(ev->state == PropertyDelete)
  1225 		return; /* ignore */
  1229 		return; /* ignore */
  1226 	if((c = getclient(ev->window))) {
  1230 	if((c = getclient(ev->window))) {
  1227 		switch (ev->atom) {
  1231 		switch (ev->atom) {
  1228 			default: break;
  1232 		default: break;
  1229 			case XA_WM_TRANSIENT_FOR:
  1233 		case XA_WM_TRANSIENT_FOR:
  1230 				XGetTransientForHint(dpy, c->win, &trans);
  1234 			XGetTransientForHint(dpy, c->win, &trans);
  1231 				if(!c->isfloating && (c->isfloating = (getclient(trans) != NULL)))
  1235 			if(!c->isfloating && (c->isfloating = (getclient(trans) != NULL)))
  1232 					arrange();
  1236 				arrange();
  1233 				break;
  1237 			break;
  1234 			case XA_WM_NORMAL_HINTS:
  1238 		case XA_WM_NORMAL_HINTS:
  1235 				updatesizehints(c);
  1239 			updatesizehints(c);
  1236 				break;
  1240 			break;
  1237 			case XA_WM_HINTS:
  1241 		case XA_WM_HINTS:
  1238 				updatewmhints(c);
  1242 			updatewmhints(c);
  1239 				drawbar();
  1243 			drawbar(&monitors[c->monitor]);
  1240 				break;
  1244 			break;
  1241 		}
  1245 		}
  1242 		if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
  1246 		if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
  1243 			updatetitle(c);
  1247 			updatetitle(c);
  1244 			if(c == sel)
  1248 			if(c == sel)
  1245 				drawbar();
  1249 				drawbar(&monitors[c->monitor]);
  1246 		}
  1250 		}
  1247 	}
  1251 	}
  1248 }
  1252 }
  1249 
  1253 
  1250 void
  1254 void
  1373 		}
  1377 		}
  1374 	}
  1378 	}
  1375 }
  1379 }
  1376 
  1380 
  1377 void
  1381 void
  1378 restack(void) {
  1382 restack(Monitor *m) {
  1379 	unsigned int i;
       
  1380 	Client *c;
  1383 	Client *c;
  1381 	XEvent ev;
  1384 	XEvent ev;
  1382 	XWindowChanges wc;
  1385 	XWindowChanges wc;
  1383 
  1386 
  1384 	drawbar();
  1387 	drawbar(m);
  1385 	if(!sel)
  1388 	if(!sel)
  1386 		return;
  1389 		return;
  1387 	if(sel->isfloating || (monitors[selmonitor].layout->arrange == floating))
  1390 	if(sel->isfloating || (m->layout->arrange == floating))
  1388 		XRaiseWindow(dpy, sel->win);
  1391 		XRaiseWindow(dpy, sel->win);
  1389 	if(monitors[selmonitor].layout->arrange != floating) {
  1392 	if(m->layout->arrange != floating) {
  1390 		wc.stack_mode = Below;
  1393 		wc.stack_mode = Below;
  1391 		wc.sibling = monitors[selmonitor].barwin;
  1394 		wc.sibling = m->barwin;
  1392 		if(!sel->isfloating) {
  1395 		if(!sel->isfloating) {
  1393 			XConfigureWindow(dpy, sel->win, CWSibling | CWStackMode, &wc);
  1396 			XConfigureWindow(dpy, sel->win, CWSibling | CWStackMode, &wc);
  1394 			wc.sibling = sel->win;
  1397 			wc.sibling = sel->win;
  1395 		}
  1398 		}
  1396 		for(i = 0; i < mcount; i++) {
  1399 		for(c = nexttiled(clients, m->id); c; c = nexttiled(c->next, m->id)) {
  1397 			for(c = nexttiled(clients, i); c; c = nexttiled(c->next, i)) {
  1400 			if(c == sel)
  1398 				if(c == sel)
  1401 				continue;
  1399 					continue;
  1402 			XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc);
  1400 				XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc);
  1403 			wc.sibling = c->win;
  1401 				wc.sibling = c->win;
       
  1402 			}
       
  1403 		}
  1404 		}
  1404 	}
  1405 	}
  1405 	XSync(dpy, False);
  1406 	XSync(dpy, False);
  1406 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  1407 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  1407 }
  1408 }
  1454 							memmove(buf, p - r + 1, r);
  1455 							memmove(buf, p - r + 1, r);
  1455 						break;
  1456 						break;
  1456 					}
  1457 					}
  1457 				break;
  1458 				break;
  1458 			}
  1459 			}
  1459 			drawbar();
  1460 			drawbar(&monitors[selmonitor]);
  1460 		}
  1461 		}
  1461 		while(XPending(dpy)) {
  1462 		while(XPending(dpy)) {
  1462 			XNextEvent(dpy, &ev);
  1463 			XNextEvent(dpy, &ev);
  1463 			if(handler[ev.type])
  1464 			if(handler[ev.type])
  1464 				(handler[ev.type])(&ev); /* call handler */
  1465 				(handler[ev.type])(&ev); /* call handler */
  1520 		m->layout = &layouts[i];
  1521 		m->layout = &layouts[i];
  1521 	}
  1522 	}
  1522 	if(sel)
  1523 	if(sel)
  1523 		arrange();
  1524 		arrange();
  1524 	else
  1525 	else
  1525 		drawbar();
  1526 		drawbar(m);
  1526 }
  1527 }
  1527 
  1528 
  1528 void
  1529 void
  1529 setmwfact(const char *arg) {
  1530 setmwfact(const char *arg) {
  1530 	double delta;
  1531 	double delta;
  1649 		/* select for events */
  1650 		/* select for events */
  1650 		wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
  1651 		wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
  1651 				| EnterWindowMask | LeaveWindowMask | StructureNotifyMask;
  1652 				| EnterWindowMask | LeaveWindowMask | StructureNotifyMask;
  1652 		XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
  1653 		XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
  1653 		XSelectInput(dpy, root, wa.event_mask);
  1654 		XSelectInput(dpy, root, wa.event_mask);
       
  1655 
       
  1656 		drawbar(m);
  1654 	}
  1657 	}
  1655 	if(info)
  1658 	if(info)
  1656 		XFree(info);
  1659 		XFree(info);
  1657 
  1660 
  1658 	/* grab keys */
  1661 	/* grab keys */
  2052 	if(!(dpy = XOpenDisplay(0)))
  2055 	if(!(dpy = XOpenDisplay(0)))
  2053 		eprint("dwm: cannot open display\n");
  2056 		eprint("dwm: cannot open display\n");
  2054 
  2057 
  2055 	checkotherwm();
  2058 	checkotherwm();
  2056 	setup();
  2059 	setup();
  2057 	drawbar();
       
  2058 	scan();
  2060 	scan();
  2059 	run();
  2061 	run();
  2060 	cleanup();
  2062 	cleanup();
  2061 
  2063 
  2062 	XCloseDisplay(dpy);
  2064 	XCloseDisplay(dpy);