dwm.c
changeset 1087 197bfedb953c
parent 1086 dadc0b94f695
child 1088 06fbc117e7d8
equal deleted inserted replaced
1086:dadc0b94f695 1087:197bfedb953c
   116 	regex_t *tagregex;
   116 	regex_t *tagregex;
   117 } Regs;
   117 } Regs;
   118 
   118 
   119 typedef struct {
   119 typedef struct {
   120 	int screen;
   120 	int screen;
   121 	Window root;
       
   122 	Window barwin;
   121 	Window barwin;
   123 	int sx, sy, sw, sh, wax, way, wah, waw;
   122 	int sx, sy, sw, sh, wax, way, wah, waw;
   124 	DC dc;
   123 	DC dc;
   125 	Bool *seltags;
   124 	Bool *seltags;
   126 	Bool *prevtags;
   125 	Bool *prevtags;
   214 void selectmonitor(const char *arg);
   213 void selectmonitor(const char *arg);
   215 
   214 
   216 /* variables */
   215 /* variables */
   217 char stext[256];
   216 char stext[256];
   218 int mcount = 1;
   217 int mcount = 1;
       
   218 int selmonitor = 0;
   219 int (*xerrorxlib)(Display *, XErrorEvent *);
   219 int (*xerrorxlib)(Display *, XErrorEvent *);
   220 unsigned int bh, bpos;
   220 unsigned int bh, bpos;
   221 unsigned int blw = 0;
   221 unsigned int blw = 0;
   222 unsigned int numlockmask = 0;
   222 unsigned int numlockmask = 0;
   223 void (*handler[LASTEvent]) (XEvent *) = {
   223 void (*handler[LASTEvent]) (XEvent *) = {
   246 Cursor cursor[CurLast];
   246 Cursor cursor[CurLast];
   247 Display *dpy;
   247 Display *dpy;
   248 DC dc = {0};
   248 DC dc = {0};
   249 Regs *regs = NULL;
   249 Regs *regs = NULL;
   250 Monitor *monitors;
   250 Monitor *monitors;
   251 int selmonitor = 0;
   251 Window root;
   252 
   252 
   253 /* configuration, allows nested code to access above variables */
   253 /* configuration, allows nested code to access above variables */
   254 #include "config.h"
   254 #include "config.h"
   255 
   255 
   256 //Bool prevtags[LENGTH(tags)];
   256 //Bool prevtags[LENGTH(tags)];
   412 		Monitor *m = &monitors[i];
   412 		Monitor *m = &monitors[i];
   413 		if(m->dc.font.set)
   413 		if(m->dc.font.set)
   414 			XFreeFontSet(dpy, m->dc.font.set);
   414 			XFreeFontSet(dpy, m->dc.font.set);
   415 		else
   415 		else
   416 			XFreeFont(dpy, m->dc.font.xfont);
   416 			XFreeFont(dpy, m->dc.font.xfont);
   417 		XUngrabKey(dpy, AnyKey, AnyModifier, m->root);
   417 		XUngrabKey(dpy, AnyKey, AnyModifier, root);
   418 		XFreePixmap(dpy, m->dc.drawable);
   418 		XFreePixmap(dpy, m->dc.drawable);
   419 		XFreeGC(dpy, m->dc.gc);
   419 		XFreeGC(dpy, m->dc.gc);
   420 		XDestroyWindow(dpy, m->barwin);
   420 		XDestroyWindow(dpy, m->barwin);
   421 		XFreeCursor(dpy, cursor[CurNormal]);
   421 		XFreeCursor(dpy, cursor[CurNormal]);
   422 		XFreeCursor(dpy, cursor[CurResize]);
   422 		XFreeCursor(dpy, cursor[CurResize]);
   473 void
   473 void
   474 configurenotify(XEvent *e) {
   474 configurenotify(XEvent *e) {
   475 	XConfigureEvent *ev = &e->xconfigure;
   475 	XConfigureEvent *ev = &e->xconfigure;
   476 	Monitor *m = &monitors[selmonitor];
   476 	Monitor *m = &monitors[selmonitor];
   477 
   477 
   478 	if(ev->window == m->root && (ev->width != m->sw || ev->height != m->sh)) {
   478 	if(ev->window == root && (ev->width != m->sw || ev->height != m->sh)) {
   479 		m->sw = ev->width;
   479 		m->sw = ev->width;
   480 		m->sh = ev->height;
   480 		m->sh = ev->height;
   481 		XFreePixmap(dpy, dc.drawable);
   481 		XFreePixmap(dpy, dc.drawable);
   482 		dc.drawable = XCreatePixmap(dpy, m->root, m->sw, bh, DefaultDepth(dpy, m->screen));
   482 		dc.drawable = XCreatePixmap(dpy, root, m->sw, bh, DefaultDepth(dpy, m->screen));
   483 		XResizeWindow(dpy, m->barwin, m->sw, bh);
   483 		XResizeWindow(dpy, m->barwin, m->sw, bh);
   484 		updatebarpos(m);
   484 		updatebarpos(m);
   485 		arrange();
   485 		arrange();
   486 	}
   486 	}
   487 }
   487 }
   685 enternotify(XEvent *e) {
   685 enternotify(XEvent *e) {
   686 	Client *c;
   686 	Client *c;
   687 	XCrossingEvent *ev = &e->xcrossing;
   687 	XCrossingEvent *ev = &e->xcrossing;
   688 
   688 
   689 	if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) {
   689 	if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) {
   690 		if(!isxinerama || ev->window != monitors[selmonitor].root)
   690 		if(!isxinerama || ev->window != root)
   691 			return;
   691 			return;
   692 	}
   692 	}
   693 	if((c = getclient(ev->window)))
   693 	if((c = getclient(ev->window)))
   694 		focus(c);
   694 		focus(c);
   695 	else {
   695 	else {
   753 		XSetWindowBorder(dpy, c->win, m->dc.sel[ColBorder]);
   753 		XSetWindowBorder(dpy, c->win, m->dc.sel[ColBorder]);
   754 		XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   754 		XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   755 		selmonitor = c->monitor;
   755 		selmonitor = c->monitor;
   756 	}
   756 	}
   757 	else {
   757 	else {
   758 		XSetInputFocus(dpy, m->root, RevertToPointerRoot, CurrentTime);
   758 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
   759 		drawbar();
   759 		drawbar();
   760 	}
   760 	}
   761 }
   761 }
   762 
   762 
   763 void
   763 void
   912 			if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock))
   912 			if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock))
   913 				numlockmask = (1 << i);
   913 				numlockmask = (1 << i);
   914 		}
   914 		}
   915 	XFreeModifiermap(modmap);
   915 	XFreeModifiermap(modmap);
   916 
   916 
   917 	for(i = 0; i < mcount; i++) {
   917 	XUngrabKey(dpy, AnyKey, AnyModifier, root);
   918 		Monitor *m = &monitors[i];
   918 	for(i = 0; i < LENGTH(keys); i++) {
   919 		XUngrabKey(dpy, AnyKey, AnyModifier, m->root);
   919 		code = XKeysymToKeycode(dpy, keys[i].keysym);
   920 		for(j = 0; j < LENGTH(keys); j++) {
   920 		XGrabKey(dpy, code, keys[i].mod, root, True,
   921 			code = XKeysymToKeycode(dpy, keys[j].keysym);
   921 				GrabModeAsync, GrabModeAsync);
   922 			XGrabKey(dpy, code, keys[j].mod, m->root, True,
   922 		XGrabKey(dpy, code, keys[i].mod | LockMask, root, True,
   923 					GrabModeAsync, GrabModeAsync);
   923 				GrabModeAsync, GrabModeAsync);
   924 			XGrabKey(dpy, code, keys[j].mod | LockMask, m->root, True,
   924 		XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True,
   925 					GrabModeAsync, GrabModeAsync);
   925 				GrabModeAsync, GrabModeAsync);
   926 			XGrabKey(dpy, code, keys[j].mod | numlockmask, m->root, True,
   926 		XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True,
   927 					GrabModeAsync, GrabModeAsync);
   927 				GrabModeAsync, GrabModeAsync);
   928 			XGrabKey(dpy, code, keys[j].mod | numlockmask | LockMask, m->root, True,
       
   929 					GrabModeAsync, GrabModeAsync);
       
   930 		}
       
   931 	}
   928 	}
   932 }
   929 }
   933 
   930 
   934 unsigned int
   931 unsigned int
   935 idxoftag(const char *tag) {
   932 idxoftag(const char *tag) {
  1151 monitorat() {
  1148 monitorat() {
  1152 	int i, x, y;
  1149 	int i, x, y;
  1153 	Window win;
  1150 	Window win;
  1154 	unsigned int mask;
  1151 	unsigned int mask;
  1155 
  1152 
  1156 	XQueryPointer(dpy, monitors[selmonitor].root, &win, &win, &x, &y, &i, &i, &mask);
  1153 	XQueryPointer(dpy, root, &win, &win, &x, &y, &i, &i, &mask);
  1157 	for(i = 0; i < mcount; i++) {
  1154 	for(i = 0; i < mcount; i++) {
  1158 		if((x >= monitors[i].sx && x < monitors[i].sx + monitors[i].sw)
  1155 		if((x >= monitors[i].sx && x < monitors[i].sx + monitors[i].sw)
  1159 		&& (y >= monitors[i].sy && y < monitors[i].sy + monitors[i].sh)) {
  1156 		&& (y >= monitors[i].sy && y < monitors[i].sy + monitors[i].sh)) {
  1160 			return i;
  1157 			return i;
  1161 		}
  1158 		}
  1170 	Window dummy;
  1167 	Window dummy;
  1171 	XEvent ev;
  1168 	XEvent ev;
  1172 
  1169 
  1173 	ocx = nx = c->x;
  1170 	ocx = nx = c->x;
  1174 	ocy = ny = c->y;
  1171 	ocy = ny = c->y;
  1175 	if(XGrabPointer(dpy, monitors[selmonitor].root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
  1172 	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
  1176 			None, cursor[CurMove], CurrentTime) != GrabSuccess)
  1173 			None, cursor[CurMove], CurrentTime) != GrabSuccess)
  1177 		return;
  1174 		return;
  1178 	XQueryPointer(dpy, monitors[selmonitor].root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
  1175 	XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
  1179 	for(;;) {
  1176 	for(;;) {
  1180 		XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev);
  1177 		XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev);
  1181 		switch (ev.type) {
  1178 		switch (ev.type) {
  1182 		case ButtonRelease:
  1179 		case ButtonRelease:
  1183 			XUngrabPointer(dpy, CurrentTime);
  1180 			XUngrabPointer(dpy, CurrentTime);
  1340 	int nw, nh;
  1337 	int nw, nh;
  1341 	XEvent ev;
  1338 	XEvent ev;
  1342 
  1339 
  1343 	ocx = c->x;
  1340 	ocx = c->x;
  1344 	ocy = c->y;
  1341 	ocy = c->y;
  1345 	if(XGrabPointer(dpy, monitors[selmonitor].root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
  1342 	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
  1346 			None, cursor[CurResize], CurrentTime) != GrabSuccess)
  1343 			None, cursor[CurResize], CurrentTime) != GrabSuccess)
  1347 		return;
  1344 		return;
  1348 	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1);
  1345 	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1);
  1349 	for(;;) {
  1346 	for(;;) {
  1350 		XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev);
  1347 		XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev);
  1467 	}
  1464 	}
  1468 }
  1465 }
  1469 
  1466 
  1470 void
  1467 void
  1471 scan(void) {
  1468 scan(void) {
  1472 	unsigned int i, j, num;
  1469 	unsigned int i, num;
  1473 	Window *wins, d1, d2;
  1470 	Window *wins, d1, d2;
  1474 	XWindowAttributes wa;
  1471 	XWindowAttributes wa;
  1475 
  1472 
  1476 	for(i = 0; i < mcount; i++) {
  1473 	wins = NULL;
  1477 		Monitor *m = &monitors[i];
  1474 	if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
  1478 		wins = NULL;
  1475 		for(i = 0; i < num; i++) {
  1479 		if(XQueryTree(dpy, m->root, &d1, &d2, &wins, &num)) {
  1476 			if(!XGetWindowAttributes(dpy, wins[i], &wa)
  1480 			for(j = 0; j < num; j++) {
  1477 					|| wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
  1481 				if(!XGetWindowAttributes(dpy, wins[j], &wa)
  1478 				continue;
  1482 				|| wa.override_redirect || XGetTransientForHint(dpy, wins[j], &d1))
  1479 			if(wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
  1483 					continue;
  1480 				manage(wins[i], &wa);
  1484 				if(wa.map_state == IsViewable || getstate(wins[j]) == IconicState)
  1481 		}
  1485 					manage(wins[j], &wa);
  1482 		for(i = 0; i < num; i++) { /* now the transients */
  1486 			}
  1483 			if(!XGetWindowAttributes(dpy, wins[i], &wa))
  1487 			for(j = 0; j < num; j++) { /* now the transients */
  1484 				continue;
  1488 				if(!XGetWindowAttributes(dpy, wins[j], &wa))
  1485 			if(XGetTransientForHint(dpy, wins[i], &d1)
  1489 					continue;
  1486 					&& (wa.map_state == IsViewable || getstate(wins[i]) == IconicState))
  1490 				if(XGetTransientForHint(dpy, wins[j], &d1)
  1487 				manage(wins[i], &wa);
  1491 				&& (wa.map_state == IsViewable || getstate(wins[j]) == IconicState))
  1488 		}
  1492 					manage(wins[j], &wa);
  1489 	}
  1493 			}
  1490 	if(wins)
  1494 		}
  1491 		XFree(wins);
  1495 		if(wins)
       
  1496 			XFree(wins);
       
  1497 	}
       
  1498 }
  1492 }
  1499 
  1493 
  1500 void
  1494 void
  1501 setclientstate(Client *c, long state) {
  1495 setclientstate(Client *c, long state) {
  1502 	long data[] = {state, None};
  1496 	long data[] = {state, None};
  1577 	mcount = 1;
  1571 	mcount = 1;
  1578 	if((isxinerama = XineramaIsActive(dpy)))
  1572 	if((isxinerama = XineramaIsActive(dpy)))
  1579 		info = XineramaQueryScreens(dpy, &mcount);
  1573 		info = XineramaQueryScreens(dpy, &mcount);
  1580 	monitors = emallocz(mcount * sizeof(Monitor));
  1574 	monitors = emallocz(mcount * sizeof(Monitor));
  1581 
  1575 
       
  1576 	root = DefaultRootWindow(dpy);
       
  1577 
  1582 	for(i = 0; i < mcount; i++) {
  1578 	for(i = 0; i < mcount; i++) {
  1583 		/* init geometry */
  1579 		/* init geometry */
  1584 		m = &monitors[i];
  1580 		m = &monitors[i];
  1585 
  1581 
  1586 		m->screen = isxinerama ? 0 : i;
  1582 		m->screen = isxinerama ? 0 : i;
  1587 		m->root = RootWindow(dpy, m->screen);
       
  1588 
  1583 
  1589 		if (mcount != 1 && isxinerama) {
  1584 		if (mcount != 1 && isxinerama) {
  1590 			m->sx = info[i].x_org;
  1585 			m->sx = info[i].x_org;
  1591 			m->sy = info[i].y_org;
  1586 			m->sy = info[i].y_org;
  1592 			m->sw = info[i].width;
  1587 			m->sw = info[i].width;
  1630 		wa.override_redirect = 1;
  1625 		wa.override_redirect = 1;
  1631 		wa.background_pixmap = ParentRelative;
  1626 		wa.background_pixmap = ParentRelative;
  1632 		wa.event_mask = ButtonPressMask | ExposureMask;
  1627 		wa.event_mask = ButtonPressMask | ExposureMask;
  1633 
  1628 
  1634 		/* init bars */
  1629 		/* init bars */
  1635 		m->barwin = XCreateWindow(dpy, m->root, m->sx, m->sy, m->sw, bh, 0,
  1630 		m->barwin = XCreateWindow(dpy, root, m->sx, m->sy, m->sw, bh, 0,
  1636 				DefaultDepth(dpy, m->screen), CopyFromParent, DefaultVisual(dpy, m->screen),
  1631 				DefaultDepth(dpy, m->screen), CopyFromParent, DefaultVisual(dpy, m->screen),
  1637 				CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
  1632 				CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
  1638 		XDefineCursor(dpy, m->barwin, cursor[CurNormal]);
  1633 		XDefineCursor(dpy, m->barwin, cursor[CurNormal]);
  1639 		updatebarpos(m);
  1634 		updatebarpos(m);
  1640 		XMapRaised(dpy, m->barwin);
  1635 		XMapRaised(dpy, m->barwin);
  1641 		strcpy(stext, "dwm-"VERSION);
  1636 		strcpy(stext, "dwm-"VERSION);
  1642 		m->dc.drawable = XCreatePixmap(dpy, m->root, m->sw, bh, DefaultDepth(dpy, m->screen));
  1637 		m->dc.drawable = XCreatePixmap(dpy, root, m->sw, bh, DefaultDepth(dpy, m->screen));
  1643 		m->dc.gc = XCreateGC(dpy, m->root, 0, 0);
  1638 		m->dc.gc = XCreateGC(dpy, root, 0, 0);
  1644 		XSetLineAttributes(dpy, m->dc.gc, 1, LineSolid, CapButt, JoinMiter);
  1639 		XSetLineAttributes(dpy, m->dc.gc, 1, LineSolid, CapButt, JoinMiter);
  1645 		if(!m->dc.font.set)
  1640 		if(!m->dc.font.set)
  1646 			XSetFont(dpy, m->dc.gc, m->dc.font.xfont->fid);
  1641 			XSetFont(dpy, m->dc.gc, m->dc.font.xfont->fid);
  1647 
  1642 
  1648 		/* EWMH support per monitor */
  1643 		/* EWMH support per monitor */
  1649 		XChangeProperty(dpy, m->root, netatom[NetSupported], XA_ATOM, 32,
  1644 		XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
  1650 				PropModeReplace, (unsigned char *) netatom, NetLast);
  1645 				PropModeReplace, (unsigned char *) netatom, NetLast);
  1651 
  1646 
  1652 		/* select for events */
  1647 		/* select for events */
  1653 		wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
  1648 		wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
  1654 				| EnterWindowMask | LeaveWindowMask | StructureNotifyMask;
  1649 				| EnterWindowMask | LeaveWindowMask | StructureNotifyMask;
  1655 		XChangeWindowAttributes(dpy, m->root, CWEventMask | CWCursor, &wa);
  1650 		XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
  1656 		XSelectInput(dpy, m->root, wa.event_mask);
  1651 		XSelectInput(dpy, root, wa.event_mask);
  1657 	}
  1652 	}
  1658 	if(info)
  1653 	if(info)
  1659 		XFree(info);
  1654 		XFree(info);
  1660 
  1655 
  1661 	/* grab keys */
  1656 	/* grab keys */
  2042 
  2037 
  2043 void
  2038 void
  2044 selectmonitor(const char *arg) {
  2039 selectmonitor(const char *arg) {
  2045 	Monitor *m = &monitors[arg ? atoi(arg) : (monitorat()+1) % mcount];
  2040 	Monitor *m = &monitors[arg ? atoi(arg) : (monitorat()+1) % mcount];
  2046 
  2041 
  2047 	XWarpPointer(dpy, None, m->root, 0, 0, 0, 0, m->wax+m->waw/2, m->way+m->wah/2);
  2042 	XWarpPointer(dpy, None, root, 0, 0, 0, 0, m->wax+m->waw/2, m->way+m->wah/2);
  2048 	focus(NULL);
  2043 	focus(NULL);
  2049 }
  2044 }
  2050 
  2045 
  2051 
  2046 
  2052 int
  2047 int