X-Git-Url: https://jasonwoof.com/gitweb/?p=dwm.git;a=blobdiff_plain;f=dwm.c;h=58a5746bb5a4f5e1b98b32c47ce7766de4ca35f8;hp=402b2b9e1b8d029e755c6e36df3f6b4f52dcfce7;hb=e5a1e77351bb4538a1a475739a00dcb41aa35701;hpb=a372248b803e92e6e781d26703a7fee96550ef3a diff --git a/dwm.c b/dwm.c index 402b2b9..58a5746 100644 --- a/dwm.c +++ b/dwm.c @@ -58,7 +58,8 @@ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ enum { NetSupported, NetWMName, NetWMState, - NetWMFullscreen, NetActiveWindow, NetLast }; /* EWMH atoms */ + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ @@ -125,6 +126,7 @@ typedef struct { struct Monitor { char ltsymbol[16]; float mfact; + int nmaster; int num; int by; /* bar geometry */ int mx, my, mw, mh; /* screen size */ @@ -189,6 +191,7 @@ static long getstate(Window w); static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); static void grabbuttons(Client *c, Bool focused); static void grabkeys(void); +static void incnmaster(const Arg *arg); static void initfont(const char *fontstr); static void keypress(XEvent *e); static void killclient(const Arg *arg); @@ -235,6 +238,7 @@ static void updatebars(void); static void updatenumlockmask(void); static void updatesizehints(Client *c); static void updatestatus(void); +static void updatewindowtype(Client *c); static void updatetitle(Client *c); static void updatewmhints(Client *c); static void view(const Arg *arg); @@ -289,31 +293,31 @@ applyrules(Client *c) { unsigned int i; const Rule *r; Monitor *m; - XClassHint ch = { 0 }; + XClassHint ch = { NULL, NULL }; /* rule matching */ c->isfloating = c->tags = 0; - if(XGetClassHint(dpy, c->win, &ch)) { - class = ch.res_class ? ch.res_class : broken; - instance = ch.res_name ? ch.res_name : broken; - for(i = 0; i < LENGTH(rules); i++) { - r = &rules[i]; - if((!r->title || strstr(c->name, r->title)) - && (!r->class || strstr(class, r->class)) - && (!r->instance || strstr(instance, r->instance))) - { - c->isfloating = r->isfloating; - c->tags |= r->tags; - for(m = mons; m && m->num != r->monitor; m = m->next); - if(m) - c->mon = m; - } + XGetClassHint(dpy, c->win, &ch); + class = ch.res_class ? ch.res_class : broken; + instance = ch.res_name ? ch.res_name : broken; + + for(i = 0; i < LENGTH(rules); i++) { + r = &rules[i]; + if((!r->title || strstr(c->name, r->title)) + && (!r->class || strstr(class, r->class)) + && (!r->instance || strstr(instance, r->instance))) + { + c->isfloating = r->isfloating; + c->tags |= r->tags; + for(m = mons; m && m->num != r->monitor; m = m->next); + if(m) + c->mon = m; } - if(ch.res_class) - XFree(ch.res_class); - if(ch.res_name) - XFree(ch.res_name); } + if(ch.res_class) + XFree(ch.res_class); + if(ch.res_name) + XFree(ch.res_name); c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; } @@ -336,20 +340,20 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact) { *y = 0; } else { - if(*x > m->mx + m->mw) - *x = m->mx + m->mw - WIDTH(c); - if(*y > m->my + m->mh) - *y = m->my + m->mh - HEIGHT(c); - if(*x + *w + 2 * c->bw < m->mx) - *x = m->mx; - if(*y + *h + 2 * c->bw < m->my) - *y = m->my; + if(*x >= m->wx + m->ww) + *x = m->wx + m->ww - WIDTH(c); + if(*y >= m->wy + m->wh) + *y = m->wy + m->wh - HEIGHT(c); + if(*x + *w + 2 * c->bw <= m->wx) + *x = m->wx; + if(*y + *h + 2 * c->bw <= m->wy) + *y = m->wy; } if(*h < bh) *h = bh; if(*w < bh) *w = bh; - if(resizehints || c->isfloating) { + if(resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { /* see last two sentences in ICCCM 4.1.2.3 */ baseismin = c->basew == c->minw && c->baseh == c->minh; if(!baseismin) { /* temporarily remove base dimensions */ @@ -389,7 +393,6 @@ arrange(Monitor *m) { showhide(m->stack); else for(m = mons; m; m = m->next) showhide(m->stack); - focus(NULL); if(m) arrangemon(m); else for(m = mons; m; m = m->next) @@ -598,6 +601,7 @@ configurenotify(XEvent *e) { updatebars(); for(m = mons; m; m = m->next) XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + focus(NULL); arrange(NULL); } } @@ -664,6 +668,7 @@ createmon(void) { die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); m->tagset[0] = m->tagset[1] = 1; m->mfact = mfact; + m->nmaster = nmaster; m->showbar = showbar; m->topbar = topbar; m->lt[0] = &layouts[0]; @@ -1024,6 +1029,12 @@ grabkeys(void) { } void +incnmaster(const Arg *arg) { + selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); +} + +void initfont(const char *fontstr) { char *def, **missing; int n; @@ -1135,7 +1146,7 @@ manage(Window w, XWindowAttributes *wa) { c->y = c->mon->my + c->mon->mh - HEIGHT(c); c->x = MAX(c->x, c->mon->mx); /* only fix client y-offset, if the client center might cover the bar */ - c->y = MAX(c->y, ((c->mon->by == 0) && (c->x + (c->w / 2) >= c->mon->wx) + c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); c->bw = borderpx; } @@ -1143,6 +1154,7 @@ manage(Window w, XWindowAttributes *wa) { XConfigureWindow(dpy, w, CWBorderWidth, &wc); XSetWindowBorder(dpy, w, dc.norm[ColBorder]); configure(c); /* propagates border_width, if size doesn't change */ + updatewindowtype(c); updatesizehints(c); updatewmhints(c); XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); @@ -1154,9 +1166,13 @@ manage(Window w, XWindowAttributes *wa) { attach(c); attachstack(c); XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ - XMapWindow(dpy, c->win); setclientstate(c, NormalState); + if (c->mon == selmon) + unfocus(selmon->sel, False); + c->mon->sel = c; arrange(c->mon); + XMapWindow(dpy, c->win); + focus(NULL); } void @@ -1295,6 +1311,8 @@ propertynotify(XEvent *e) { if(c == c->mon->sel) drawbar(c->mon); } + if(ev->atom == netatom[NetWMWindowType]) + updatewindowtype(c); } } @@ -1549,6 +1567,8 @@ setup(void) { netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); + netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); + netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); /* init cursors */ cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); @@ -1593,7 +1613,7 @@ showhide(Client *c) { } else { /* hide clients bottom up */ showhide(c->snext); - XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); + XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); } } @@ -1621,6 +1641,7 @@ void tag(const Arg *arg) { if(selmon->sel && arg->ui & TAGMASK) { selmon->sel->tags = arg->ui & TAGMASK; + focus(NULL); arrange(selmon); } } @@ -1645,32 +1666,28 @@ textnw(const char *text, unsigned int len) { void tile(Monitor *m) { - int x, y, h, w, mw; - unsigned int i, n; + unsigned int i, n, h, mw, my, ty; Client *c; for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); if(n == 0) return; - /* master */ - c = nexttiled(m->clients); - mw = m->mfact * m->ww; - resize(c, m->wx, m->wy, (n == 1 ? m->ww : mw) - 2 * c->bw, m->wh - 2 * c->bw, False); - if(--n == 0) - return; - /* tile stack */ - x = (m->wx > c->x) ? c->x + mw + 2 * c->bw : m->wx + mw; - y = m->wy; - w = (m->wx > c->x) ? m->wx + m->ww - x : m->ww - mw; - h = m->wh / n; - if(h < bh) - h = m->wh; - for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) { - resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n) - ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw), False); - if(h != m->wh) - y = c->y + HEIGHT(c); - } + + if(n > m->nmaster) + mw = m->nmaster ? m->ww * m->mfact : 0; + else + mw = m->ww; + for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if(i < m->nmaster) { + h = (m->wh - my) / (MIN(n, m->nmaster) - i); + resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), False); + my += HEIGHT(c); + } + else { + h = (m->wh - ty) / (n - i); + resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), False); + ty += HEIGHT(c); + } } void @@ -1701,6 +1718,7 @@ toggletag(const Arg *arg) { newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); if(newtags) { selmon->sel->tags = newtags; + focus(NULL); arrange(selmon); } } @@ -1711,6 +1729,7 @@ toggleview(const Arg *arg) { if(newtagset) { selmon->tagset[selmon->seltags] = newtagset; + focus(NULL); arrange(selmon); } } @@ -1754,8 +1773,12 @@ unmapnotify(XEvent *e) { Client *c; XUnmapEvent *ev = &e->xunmap; - if((c = wintoclient(ev->window))) - unmanage(c, False); + if((c = wintoclient(ev->window))) { + if(ev->send_event) + setclientstate(c, WithdrawnState); + else + unmanage(c, False); + } } void @@ -1951,6 +1974,25 @@ updatestatus(void) { } void +updatewindowtype(Client *c) +{ + Atom wtype, real; + int format; + unsigned long n, extra; + unsigned char *p = NULL; + + if(XGetWindowProperty(dpy, c->win, netatom[NetWMWindowType], 0L, + sizeof(Atom), False, XA_ATOM, &real, &format, + &n, &extra, (unsigned char **)&p) == Success && p) { + wtype = *(Atom *)p; + XFree(p); + + if(wtype == netatom[NetWMWindowTypeDialog]) + c->isfloating = True; + } +} + +void updatewmhints(Client *c) { XWMHints *wmh; @@ -1976,6 +2018,7 @@ view(const Arg *arg) { selmon->seltags ^= 1; /* toggle sel tagset */ if(arg->ui & TAGMASK) selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + focus(NULL); arrange(selmon); }