X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=dwm.c;h=f1d364127731e0c41d59d17da6fd1d711b37a464;hb=12ea925076c4f1c013502651b0be90c05e0febac;hp=f5aa010aaec2d0b3d7e9563f934ed2f08b909faf;hpb=8f052596b2c79e74c0e47b93595f13a754b3e2ef;p=dwm.git diff --git a/dwm.c b/dwm.c index f5aa010..f1d3641 100644 --- a/dwm.c +++ b/dwm.c @@ -59,19 +59,37 @@ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */ +enum { ClkLtSymbol = 64, ClkStatusText, ClkWinTitle, + ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ /* typedefs */ typedef unsigned int uint; typedef unsigned long ulong; + +typedef union { + int i; + uint ui; + float f; + void *v; +} Arg; + +typedef struct { + uint click; + uint mask; + uint button; + void (*func)(const Arg *arg); + const Arg arg; +} Button; + typedef struct Client Client; struct Client { char name[256]; + float mina, maxa; int x, y, w, h; int basew, baseh, incw, inch, maxw, maxh, minw, minh; - float mina, maxa; int bw, oldbw; - Bool isbanned, isfixed, isfloating, ismoved, isurgent; uint tags; + Bool isbanned, isfixed, isfloating, isurgent; Client *next; Client *snext; Window win; @@ -92,13 +110,6 @@ typedef struct { } font; } DC; /* draw context */ -typedef union { - int i; - uint ui; - float f; - void *v; -} Arg; - typedef struct { uint mod; KeySym keysym; @@ -157,16 +168,18 @@ static void killclient(const Arg *arg); static void manage(Window w, XWindowAttributes *wa); static void mappingnotify(XEvent *e); static void maprequest(XEvent *e); -static void movemouse(Client *c); +static void monocle(void); +static void movemouse(const Arg *arg); static Client *nexttiled(Client *c); static void propertynotify(XEvent *e); static void quit(const Arg *arg); static void resize(Client *c, int x, int y, int w, int h, Bool sizehints); -static void resizemouse(Client *c); +static void resizemouse(const Arg *arg); static void restack(void); static void run(void); static void scan(void); static void setclientstate(Client *c, long state); +static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setup(void); static void spawn(const Arg *arg); @@ -175,8 +188,6 @@ static int textnw(const char *text, uint len); static void tile(void); static void togglebar(const Arg *arg); static void togglefloating(const Arg *arg); -static void togglelayout(const Arg *arg); -static void togglemax(const Arg *arg); static void toggletag(const Arg *arg); static void toggleview(const Arg *arg); static void unmanage(Client *c); @@ -214,7 +225,6 @@ static void (*handler[LASTEvent]) (XEvent *) = { [UnmapNotify] = unmapnotify }; static Atom wmatom[WMLast], netatom[NetLast]; -static Bool ismax = False; static Bool otherwm, readin; static Bool running = True; static uint tagset[] = {1, 1}; /* after start, first tag is selected */ @@ -264,21 +274,17 @@ arrange(void) { for(c = clients; c; c = c->next) if(c->tags & tagset[seltags]) { /* is visible */ - if(ismax && !c->isfixed) { - XMoveResizeWindow(dpy, c->win, wx, wy, ww - 2 * c->bw, wh - 2 * c->bw); - c->ismoved = True; - } - else if(!lt->arrange || c->isfloating) + if(!lt->arrange || c->isfloating) resize(c, c->x, c->y, c->w, c->h, True); c->isbanned = False; } else if(!c->isbanned) { XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); - c->isbanned = c->ismoved = True; + c->isbanned = True; } focus(NULL); - if(lt->arrange && !ismax) + if(lt->arrange) lt->arrange(); restack(); } @@ -297,50 +303,34 @@ attachstack(Client *c) { void buttonpress(XEvent *e) { - uint i, mask; - int x; + uint i, x, click; Client *c; XButtonPressedEvent *ev = &e->xbutton; + click = ClkRootWin; if(ev->window == barwin) { - x = 0; - for(i = 0; i < LENGTH(tags); i++) { + i = x = 0; + do x += TEXTW(tags[i]); - if(ev->x < x) { - mask = 1 << i; - if(ev->button == Button1) { - if(ev->state & MODKEY) - tag((Arg*)&mask); - else - view((Arg*)&mask); - } - else if(ev->button == Button3) { - if(ev->state & MODKEY) - toggletag((Arg*)&mask); - else - toggleview((Arg*)&mask); - } - return; - } - } - if(ev->x < x + blw) { - if(ev->button == Button1) - togglelayout(NULL); - else if(ev->button == Button3) - togglemax(NULL); - } + while(ev->x >= x && ++i < LENGTH(tags)); + if(i < LENGTH(tags)) + click = i; + else if(ev->x < x + blw) + click = ClkLtSymbol; + else if(ev->x > wx + ww - TEXTW(stext)) + click = ClkStatusText; + else + click = ClkWinTitle; } else if((c = getclient(ev->window))) { focus(c); - if(CLEANMASK(ev->state) != MODKEY || (ismax && !c->isfixed)) - return; - if(ev->button == Button1) - movemouse(c); - else if(ev->button == Button2) - togglefloating(NULL); - else if(ev->button == Button3 && !c->isfixed) - resizemouse(c); + click = ClkClientWin; } + + for(i = 0; i < LENGTH(buttons); i++) + if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button + && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) + buttons[i].func(&buttons[i].arg); } void @@ -423,8 +413,6 @@ configurerequest(XEvent *e) { if((c = getclient(ev->window))) { if(ev->value_mask & CWBorderWidth) c->bw = ev->border_width; - if(ismax && !c->isbanned && !c->isfixed) - XMoveResizeWindow(dpy, c->win, wx, wy, ww - 2 * c->bw, wh + 2 * c->bw); else if(c->isfloating || !lt->arrange) { if(ev->value_mask & CWX) c->x = sx + ev->x; @@ -512,7 +500,7 @@ drawbar(void) { } if(blw > 0) { dc.w = blw; - drawtext(lt->symbol, dc.norm, ismax); + drawtext(lt->symbol, dc.norm, False); x = dc.x + dc.w; } else @@ -662,7 +650,7 @@ focusstack(const Arg *arg) { for(i = clients; i != sel; i = i->next) if (!i->isbanned) c = i; - if(!c) + if(!c) for(; i; i = i->next) if (!i->isbanned) c = i; @@ -918,7 +906,8 @@ manage(Window w, XWindowAttributes *wa) { if(c->y + c->h + 2 * c->bw > sy + sh) c->y = sy + sh - c->h - 2 * c->bw; c->x = MAX(c->x, sx); - c->y = MAX(c->y, by == 0 ? bh : sy); + /* only fix client y-offset, if the client center might cover the bar */ + c->y = MAX(c->y, ((by == 0) && (c->x + (c->w / 2) >= wx) && (c->x + (c->w / 2) < wx + ww)) ? bh : sy); c->bw = borderpx; } @@ -971,12 +960,23 @@ maprequest(XEvent *e) { } void -movemouse(Client *c) { +monocle(void) { + Client *c; + + for(c = nexttiled(clients); c; c = nexttiled(c->next)) + resize(c, wx, wy, ww, wh, resizehints); +} + +void +movemouse(const Arg *arg) { int x1, y1, ocx, ocy, di, nx, ny; uint dui; + Client *c; Window dummy; XEvent ev; + if(!(c = sel)) + return; restack(); ocx = nx = c->x; ocy = ny = c->y; @@ -1095,11 +1095,11 @@ resize(Client *c, int x, int y, int w, int h, Bool sizehints) { w = MAX(w, c->minw); h = MAX(h, c->minh); - - if (c->maxw) + + if(c->maxw) w = MIN(w, c->maxw); - if (c->maxh) + if(c->maxh) h = MIN(h, c->maxh); } if(w <= 0 || h <= 0) @@ -1116,8 +1116,7 @@ resize(Client *c, int x, int y, int w, int h, Bool sizehints) { h = bh; if(w < bh) w = bh; - if(c->x != x || c->y != y || c->w != w || c->h != h || c->ismoved) { - c->ismoved = False; + if(c->x != x || c->y != y || c->w != w || c->h != h) { c->x = wc.x = x; c->y = wc.y = y; c->w = wc.width = w; @@ -1131,11 +1130,14 @@ resize(Client *c, int x, int y, int w, int h, Bool sizehints) { } void -resizemouse(Client *c) { +resizemouse(const Arg *arg) { int ocx, ocy; int nw, nh; + Client *c; XEvent ev; + if(!(c = sel)) + return; restack(); ocx = c->x; ocy = c->y; @@ -1184,9 +1186,9 @@ restack(void) { drawbar(); if(!sel) return; - if(ismax || sel->isfloating || !lt->arrange) + if(sel->isfloating || !lt->arrange) XRaiseWindow(dpy, sel->win); - if(!ismax && lt->arrange) { + if(lt->arrange) { wc.stack_mode = Below; wc.sibling = barwin; for(c = stack; c; c = c->snext) @@ -1294,6 +1296,22 @@ setclientstate(Client *c, long state) { PropModeReplace, (unsigned char *)data, 2); } +void +setlayout(const Arg *arg) { + static Layout *prevlt = &layouts[1 % LENGTH(layouts)]; + + if(!arg || !arg->v || arg->v == lt) + lt = prevlt; + else { + prevlt = lt; + lt = (Layout *)arg->v; + } + if(sel) + arrange(); + else + drawbar(); +} + /* arg > 1.0 will set mfact absolutly */ void setmfact(const Arg *arg) { @@ -1317,12 +1335,12 @@ setup(void) { /* init screen */ screen = DefaultScreen(dpy); root = RootWindow(dpy, screen); - initfont(FONT); + initfont(font); sx = 0; sy = 0; sw = DisplayWidth(dpy, screen); sh = DisplayHeight(dpy, screen); - bh = dc.font.height + 2; + bh = dc.h = dc.font.height + 2; lt = layouts; updategeom(); @@ -1340,14 +1358,12 @@ setup(void) { cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); /* init appearance */ - dc.norm[ColBorder] = getcolor(NORMBORDERCOLOR); - dc.norm[ColBG] = getcolor(NORMBGCOLOR); - dc.norm[ColFG] = getcolor(NORMFGCOLOR); - dc.sel[ColBorder] = getcolor(SELBORDERCOLOR); - dc.sel[ColBG] = getcolor(SELBGCOLOR); - dc.sel[ColFG] = getcolor(SELFGCOLOR); - initfont(FONT); - dc.h = bh; + dc.norm[ColBorder] = getcolor(normbordercolor); + dc.norm[ColBG] = getcolor(normbgcolor); + dc.norm[ColFG] = getcolor(normfgcolor); + dc.sel[ColBorder] = getcolor(selbordercolor); + dc.sel[ColBG] = getcolor(selbgcolor); + dc.sel[ColFG] = getcolor(selfgcolor); dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen)); dc.gc = XCreateGC(dpy, root, 0, 0); XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); @@ -1377,7 +1393,7 @@ setup(void) { PropModeReplace, (unsigned char *) netatom, NetLast); /* select for events */ - wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask + wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask |EnterWindowMask|LeaveWindowMask|StructureNotifyMask; XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); XSelectInput(dpy, root, wa.event_mask); @@ -1477,33 +1493,23 @@ togglefloating(const Arg *arg) { } void -togglelayout(const Arg *arg) { - if(arg && arg->v) - lt = (Layout *)arg->v; - else if(++lt == &layouts[LENGTH(layouts)]) - lt = &layouts[0]; - if(sel) - arrange(); - else - drawbar(); -} - -void -togglemax(const Arg *arg) { - ismax = !ismax; - arrange(); -} - -void toggletag(const Arg *arg) { - if(sel && (sel->tags ^= (arg->ui & TAGMASK))) + uint mask = sel->tags ^ (arg->ui & TAGMASK); + + if(sel && mask) { + sel->tags = mask; arrange(); + } } void toggleview(const Arg *arg) { - if((tagset[seltags] ^= (arg->ui & TAGMASK))) + uint mask = tagset[seltags] ^ (arg->ui & TAGMASK); + + if(mask) { + tagset[seltags] = mask; arrange(); + } } void @@ -1554,10 +1560,10 @@ updategeom(void) { /* window area geometry */ if(XineramaIsActive(dpy)) { info = XineramaQueryScreens(dpy, &i); - wx = info[0].x_org; - wy = showbar && topbar ? info[0].y_org + bh : info[0].y_org; - ww = info[0].width; - wh = showbar ? info[0].height - bh : info[0].height; + wx = info[xidx].x_org; + wy = showbar && topbar ? info[xidx].y_org + bh : info[xidx].y_org; + ww = info[xidx].width; + wh = showbar ? info[xidx].height - bh : info[xidx].height; XFree(info); } else @@ -1685,7 +1691,7 @@ void zoom(const Arg *arg) { Client *c = sel; - if(ismax || !lt->arrange || (sel && sel->isfloating)) + if(!lt->arrange || lt->arrange == monocle || (sel && sel->isfloating)) return; if(c == nexttiled(clients)) if(!c || !(c = nexttiled(c->next)))