328 } |
328 } |
329 if(*h < bh) |
329 if(*h < bh) |
330 *h = bh; |
330 *h = bh; |
331 if(*w < bh) |
331 if(*w < bh) |
332 *w = bh; |
332 *w = bh; |
333 |
|
334 if(resizehints || c->isfloating) { |
333 if(resizehints || c->isfloating) { |
335 /* see last two sentences in ICCCM 4.1.2.3 */ |
334 /* see last two sentences in ICCCM 4.1.2.3 */ |
336 baseismin = c->basew == c->minw && c->baseh == c->minh; |
335 baseismin = c->basew == c->minw && c->baseh == c->minh; |
337 |
|
338 if(!baseismin) { /* temporarily remove base dimensions */ |
336 if(!baseismin) { /* temporarily remove base dimensions */ |
339 *w -= c->basew; |
337 *w -= c->basew; |
340 *h -= c->baseh; |
338 *h -= c->baseh; |
341 } |
339 } |
342 |
|
343 /* adjust for aspect limits */ |
340 /* adjust for aspect limits */ |
344 if(c->mina > 0 && c->maxa > 0) { |
341 if(c->mina > 0 && c->maxa > 0) { |
345 if(c->maxa < (float)*w / *h) |
342 if(c->maxa < (float)*w / *h) |
346 *w = *h * c->maxa; |
343 *w = *h * c->maxa; |
347 else if(c->mina < (float)*h / *w) |
344 else if(c->mina < (float)*h / *w) |
348 *h = *w * c->mina; |
345 *h = *w * c->mina; |
349 } |
346 } |
350 |
|
351 if(baseismin) { /* increment calculation requires this */ |
347 if(baseismin) { /* increment calculation requires this */ |
352 *w -= c->basew; |
348 *w -= c->basew; |
353 *h -= c->baseh; |
349 *h -= c->baseh; |
354 } |
350 } |
355 |
|
356 /* adjust for increment value */ |
351 /* adjust for increment value */ |
357 if(c->incw) |
352 if(c->incw) |
358 *w -= *w % c->incw; |
353 *w -= *w % c->incw; |
359 if(c->inch) |
354 if(c->inch) |
360 *h -= *h % c->inch; |
355 *h -= *h % c->inch; |
361 |
|
362 /* restore base dimensions */ |
356 /* restore base dimensions */ |
363 *w += c->basew; |
357 *w += c->basew; |
364 *h += c->baseh; |
358 *h += c->baseh; |
365 |
|
366 *w = MAX(*w, c->minw); |
359 *w = MAX(*w, c->minw); |
367 *h = MAX(*h, c->minh); |
360 *h = MAX(*h, c->minh); |
368 |
|
369 if(c->maxw) |
361 if(c->maxw) |
370 *w = MIN(*w, c->maxw); |
362 *w = MIN(*w, c->maxw); |
371 |
|
372 if(c->maxh) |
363 if(c->maxh) |
373 *h = MIN(*h, c->maxh); |
364 *h = MIN(*h, c->maxh); |
374 } |
365 } |
375 return *x != c->x || *y != c->y || *w != c->w || *h != c->h; |
366 return *x != c->x || *y != c->y || *w != c->w || *h != c->h; |
376 } |
367 } |
436 } |
427 } |
437 else if((c = wintoclient(ev->window))) { |
428 else if((c = wintoclient(ev->window))) { |
438 focus(c); |
429 focus(c); |
439 click = ClkClientWin; |
430 click = ClkClientWin; |
440 } |
431 } |
441 |
|
442 for(i = 0; i < LENGTH(buttons); i++) |
432 for(i = 0; i < LENGTH(buttons); i++) |
443 if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button |
433 if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button |
444 && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) |
434 && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) |
445 buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); |
435 buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); |
446 } |
436 } |
447 |
437 |
448 void |
438 void |
449 checkotherwm(void) { |
439 checkotherwm(void) { |
450 otherwm = False; |
440 otherwm = False; |
451 xerrorxlib = XSetErrorHandler(xerrorstart); |
441 xerrorxlib = XSetErrorHandler(xerrorstart); |
452 |
|
453 /* this causes an error if some other window manager is running */ |
442 /* this causes an error if some other window manager is running */ |
454 XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); |
443 XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); |
455 XSync(dpy, False); |
444 XSync(dpy, False); |
456 if(otherwm) |
445 if(otherwm) |
457 die("dwm: another window manager is already running\n"); |
446 die("dwm: another window manager is already running\n"); |
1048 |
1036 |
1049 if(!(c = malloc(sizeof(Client)))) |
1037 if(!(c = malloc(sizeof(Client)))) |
1050 die("fatal: could not malloc() %u bytes\n", sizeof(Client)); |
1038 die("fatal: could not malloc() %u bytes\n", sizeof(Client)); |
1051 *c = cz; |
1039 *c = cz; |
1052 c->win = w; |
1040 c->win = w; |
1053 |
|
1054 if(XGetTransientForHint(dpy, w, &trans)) |
1041 if(XGetTransientForHint(dpy, w, &trans)) |
1055 t = wintoclient(trans); |
1042 t = wintoclient(trans); |
1056 if(t) { |
1043 if(t) { |
1057 c->mon = t->mon; |
1044 c->mon = t->mon; |
1058 c->tags = t->tags; |
1045 c->tags = t->tags; |
1059 } |
1046 } |
1060 else { |
1047 else { |
1061 c->mon = selmon; |
1048 c->mon = selmon; |
1062 applyrules(c); |
1049 applyrules(c); |
1063 } |
1050 } |
1064 |
|
1065 /* geometry */ |
1051 /* geometry */ |
1066 c->x = wa->x + c->mon->wx; |
1052 c->x = wa->x + c->mon->wx; |
1067 c->y = wa->y + c->mon->wy; |
1053 c->y = wa->y + c->mon->wy; |
1068 c->w = wa->width; |
1054 c->w = wa->width; |
1069 c->h = wa->height; |
1055 c->h = wa->height; |
1082 /* only fix client y-offset, if the client center might cover the bar */ |
1068 /* only fix client y-offset, if the client center might cover the bar */ |
1083 c->y = MAX(c->y, ((c->mon->by == 0) && (c->x + (c->w / 2) >= c->mon->wx) |
1069 c->y = MAX(c->y, ((c->mon->by == 0) && (c->x + (c->w / 2) >= c->mon->wx) |
1084 && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); |
1070 && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); |
1085 c->bw = borderpx; |
1071 c->bw = borderpx; |
1086 } |
1072 } |
1087 |
|
1088 wc.border_width = c->bw; |
1073 wc.border_width = c->bw; |
1089 XConfigureWindow(dpy, w, CWBorderWidth, &wc); |
1074 XConfigureWindow(dpy, w, CWBorderWidth, &wc); |
1090 XSetWindowBorder(dpy, w, dc.norm[ColBorder]); |
1075 XSetWindowBorder(dpy, w, dc.norm[ColBorder]); |
1091 configure(c); /* propagates border_width, if size doesn't change */ |
1076 configure(c); /* propagates border_width, if size doesn't change */ |
1092 updatesizehints(c); |
1077 updatesizehints(c); |
1288 handler[ev.type](&ev); |
1273 handler[ev.type](&ev); |
1289 break; |
1274 break; |
1290 case MotionNotify: |
1275 case MotionNotify: |
1291 nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); |
1276 nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); |
1292 nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); |
1277 nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); |
1293 |
|
1294 if(snap && nw >= selmon->wx && nw <= selmon->wx + selmon->ww |
1278 if(snap && nw >= selmon->wx && nw <= selmon->wx + selmon->ww |
1295 && nh >= selmon->wy && nh <= selmon->wy + selmon->wh) { |
1279 && nh >= selmon->wy && nh <= selmon->wy + selmon->wh) { |
1296 if(!c->isfloating && lt[selmon->sellt]->arrange |
1280 if(!c->isfloating && lt[selmon->sellt]->arrange |
1297 && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) |
1281 && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) |
1298 togglefloating(NULL); |
1282 togglefloating(NULL); |
1438 sh = DisplayHeight(dpy, screen); |
1422 sh = DisplayHeight(dpy, screen); |
1439 bh = dc.h = dc.font.height + 2; |
1423 bh = dc.h = dc.font.height + 2; |
1440 lt[0] = &layouts[0]; |
1424 lt[0] = &layouts[0]; |
1441 lt[1] = &layouts[1 % LENGTH(layouts)]; |
1425 lt[1] = &layouts[1 % LENGTH(layouts)]; |
1442 updategeom(); |
1426 updategeom(); |
1443 |
|
1444 /* init atoms */ |
1427 /* init atoms */ |
1445 wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); |
1428 wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); |
1446 wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); |
1429 wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); |
1447 wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); |
1430 wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); |
1448 netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); |
1431 netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); |
1449 netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); |
1432 netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); |
1450 |
|
1451 /* init cursors */ |
1433 /* init cursors */ |
1452 cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); |
1434 cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); |
1453 cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); |
1435 cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); |
1454 cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); |
1436 cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); |
1455 |
|
1456 /* init appearance */ |
1437 /* init appearance */ |
1457 dc.norm[ColBorder] = getcolor(normbordercolor); |
1438 dc.norm[ColBorder] = getcolor(normbordercolor); |
1458 dc.norm[ColBG] = getcolor(normbgcolor); |
1439 dc.norm[ColBG] = getcolor(normbgcolor); |
1459 dc.norm[ColFG] = getcolor(normfgcolor); |
1440 dc.norm[ColFG] = getcolor(normfgcolor); |
1460 dc.sel[ColBorder] = getcolor(selbordercolor); |
1441 dc.sel[ColBorder] = getcolor(selbordercolor); |
1463 dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen)); |
1444 dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen)); |
1464 dc.gc = XCreateGC(dpy, root, 0, NULL); |
1445 dc.gc = XCreateGC(dpy, root, 0, NULL); |
1465 XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); |
1446 XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); |
1466 if(!dc.font.set) |
1447 if(!dc.font.set) |
1467 XSetFont(dpy, dc.gc, dc.font.xfont->fid); |
1448 XSetFont(dpy, dc.gc, dc.font.xfont->fid); |
1468 |
|
1469 /* init bars */ |
1449 /* init bars */ |
1470 for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) { |
1450 for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) { |
1471 w = TEXTW(layouts[i].symbol); |
1451 w = TEXTW(layouts[i].symbol); |
1472 blw = MAX(blw, w); |
1452 blw = MAX(blw, w); |
1473 } |
1453 } |
1474 updatebars(); |
1454 updatebars(); |
1475 updatestatus(); |
1455 updatestatus(); |
1476 |
|
1477 /* EWMH support per view */ |
1456 /* EWMH support per view */ |
1478 XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, |
1457 XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, |
1479 PropModeReplace, (unsigned char *) netatom, NetLast); |
1458 PropModeReplace, (unsigned char *) netatom, NetLast); |
1480 |
|
1481 /* select for events */ |
1459 /* select for events */ |
1482 wa.cursor = cursor[CurNormal]; |
1460 wa.cursor = cursor[CurNormal]; |
1483 wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask |
1461 wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask |
1484 |EnterWindowMask|LeaveWindowMask|StructureNotifyMask |
1462 |EnterWindowMask|LeaveWindowMask|StructureNotifyMask |
1485 |PropertyChangeMask; |
1463 |PropertyChangeMask; |
1486 XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); |
1464 XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); |
1487 XSelectInput(dpy, root, wa.event_mask); |
1465 XSelectInput(dpy, root, wa.event_mask); |
1488 |
|
1489 grabkeys(); |
1466 grabkeys(); |
1490 } |
1467 } |
1491 |
1468 |
1492 void |
1469 void |
1493 showhide(Client *c) { |
1470 showhide(Client *c) { |
1560 Client *c; |
1537 Client *c; |
1561 |
1538 |
1562 for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); |
1539 for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); |
1563 if(n == 0) |
1540 if(n == 0) |
1564 return; |
1541 return; |
1565 |
|
1566 /* master */ |
1542 /* master */ |
1567 c = nexttiled(m->clients); |
1543 c = nexttiled(m->clients); |
1568 mw = m->mfact * m->ww; |
1544 mw = m->mfact * m->ww; |
1569 resize(c, m->wx, m->wy, (n == 1 ? m->ww : mw) - 2 * c->bw, m->wh - 2 * c->bw, False); |
1545 resize(c, m->wx, m->wy, (n == 1 ? m->ww : mw) - 2 * c->bw, m->wh - 2 * c->bw, False); |
1570 |
|
1571 if(--n == 0) |
1546 if(--n == 0) |
1572 return; |
1547 return; |
1573 |
|
1574 /* tile stack */ |
1548 /* tile stack */ |
1575 x = (m->wx + mw > c->x + c->w) ? c->x + c->w + 2 * c->bw : m->wx + mw; |
1549 x = (m->wx + mw > c->x + c->w) ? c->x + c->w + 2 * c->bw : m->wx + mw; |
1576 y = m->wy; |
1550 y = m->wy; |
1577 w = (m->wx + mw > c->x + c->w) ? m->wx + m->ww - x : m->ww - mw; |
1551 w = (m->wx + mw > c->x + c->w) ? m->wx + m->ww - x : m->ww - mw; |
1578 h = m->wh / n; |
1552 h = m->wh / n; |
1579 if(h < bh) |
1553 if(h < bh) |
1580 h = m->wh; |
1554 h = m->wh; |
1581 |
|
1582 for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) { |
1555 for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) { |
1583 resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n) |
1556 resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n) |
1584 ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw), False); |
1557 ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw), False); |
1585 if(h != m->wh) |
1558 if(h != m->wh) |
1586 y = c->y + HEIGHT(c); |
1559 y = c->y + HEIGHT(c); |
1675 XSetWindowAttributes wa; |
1647 XSetWindowAttributes wa; |
1676 |
1648 |
1677 wa.override_redirect = True; |
1649 wa.override_redirect = True; |
1678 wa.background_pixmap = ParentRelative; |
1650 wa.background_pixmap = ParentRelative; |
1679 wa.event_mask = ButtonPressMask|ExposureMask; |
1651 wa.event_mask = ButtonPressMask|ExposureMask; |
1680 |
|
1681 for(m = mons; m; m = m->next) { |
1652 for(m = mons; m; m = m->next) { |
1682 m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), |
1653 m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), |
1683 |
|
1684 CopyFromParent, DefaultVisual(dpy, screen), |
1654 CopyFromParent, DefaultVisual(dpy, screen), |
1685 CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); |
1655 CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); |
1686 XDefineCursor(dpy, m->barwin, cursor[CurNormal]); |
1656 XDefineCursor(dpy, m->barwin, cursor[CurNormal]); |
1687 XMapRaised(dpy, m->barwin); |
1657 XMapRaised(dpy, m->barwin); |
1688 } |
1658 } |
1717 for(i = 0; i < n; i++) { |
1687 for(i = 0; i < n; i++) { |
1718 m = (Monitor *)malloc(sizeof(Monitor)); |
1688 m = (Monitor *)malloc(sizeof(Monitor)); |
1719 m->next = newmons; |
1689 m->next = newmons; |
1720 newmons = m; |
1690 newmons = m; |
1721 } |
1691 } |
1722 |
|
1723 /* initialise monitor(s) */ |
1692 /* initialise monitor(s) */ |
1724 #ifdef XINERAMA |
1693 #ifdef XINERAMA |
1725 if(XineramaIsActive(dpy)) { |
1694 if(XineramaIsActive(dpy)) { |
1726 for(i = 0, m = newmons; m; m = m->next, i++) { |
1695 for(i = 0, m = newmons; m; m = m->next, i++) { |
1727 m->screen_number = info[i].screen_number; |
1696 m->screen_number = info[i].screen_number; |
1752 m->mfact = mfact; |
1720 m->mfact = mfact; |
1753 m->showbar = SHOWBAR; |
1721 m->showbar = SHOWBAR; |
1754 m->topbar = TOPBAR; |
1722 m->topbar = TOPBAR; |
1755 updatebarpos(m); |
1723 updatebarpos(m); |
1756 } |
1724 } |
1757 |
|
1758 /* reassign left over clients of disappeared monitors */ |
1725 /* reassign left over clients of disappeared monitors */ |
1759 for(tm = mons; tm; tm = tm->next) |
1726 for(tm = mons; tm; tm = tm->next) |
1760 while(tm->clients) { |
1727 while(tm->clients) { |
1761 c = tm->clients; |
1728 c = tm->clients; |
1762 tm->clients = c->next; |
1729 tm->clients = c->next; |
1763 detachstack(c); |
1730 detachstack(c); |
1764 c->mon = newmons; |
1731 c->mon = newmons; |
1765 attach(c); |
1732 attach(c); |
1766 attachstack(c); |
1733 attachstack(c); |
1767 } |
1734 } |
1768 |
|
1769 /* select focused monitor */ |
1735 /* select focused monitor */ |
1770 cleanupmons(); |
1736 cleanupmons(); |
1771 selmon = mons = newmons; |
1737 selmon = mons = newmons; |
1772 selmon = wintomon(root); |
1738 selmon = wintomon(root); |
1773 } |
1739 } |
1956 main(int argc, char *argv[]) { |
1923 main(int argc, char *argv[]) { |
1957 if(argc == 2 && !strcmp("-v", argv[1])) |
1924 if(argc == 2 && !strcmp("-v", argv[1])) |
1958 die("dwm-"VERSION", © 2006-2009 dwm engineers, see LICENSE for details\n"); |
1925 die("dwm-"VERSION", © 2006-2009 dwm engineers, see LICENSE for details\n"); |
1959 else if(argc != 1) |
1926 else if(argc != 1) |
1960 die("usage: dwm [-v]\n"); |
1927 die("usage: dwm [-v]\n"); |
1961 |
|
1962 if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) |
1928 if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) |
1963 fputs("warning: no locale support\n", stderr); |
1929 fputs("warning: no locale support\n", stderr); |
1964 |
|
1965 if(!(dpy = XOpenDisplay(NULL))) |
1930 if(!(dpy = XOpenDisplay(NULL))) |
1966 die("dwm: cannot open display\n"); |
1931 die("dwm: cannot open display\n"); |
1967 |
|
1968 checkotherwm(); |
1932 checkotherwm(); |
1969 setup(); |
1933 setup(); |
1970 scan(); |
1934 scan(); |
1971 run(); |
1935 run(); |
1972 cleanup(); |
1936 cleanup(); |
1973 |
|
1974 XCloseDisplay(dpy); |
1937 XCloseDisplay(dpy); |
1975 return 0; |
1938 return 0; |
1976 } |
1939 } |