Compare commits

..

29 Commits
5.0 ... 5.1

Author SHA1 Message Date
4a2902efe4 forcing fullscreen windows to bw=0, though most fullscreen apps are broken anyways 2008-07-29 11:32:22 +01:00
6fad4c49f1 potential crash fix if xinerama behaves broken, though I doubt it 2008-07-18 20:18:45 +01:00
78f0f8595f make hg tip compilable with default config 2008-07-18 10:57:32 +02:00
7ecadcee39 local use of xidx is useless, got rid of it, falling back to screen 0 if pointer query fails for whatever reason 2008-07-16 18:39:48 +01:00
c86ed46a1b got rid of compile time xidx configuration, querying mouse pointer instead 2008-07-16 18:33:51 +01:00
9086f98068 reverted uint redefinition 2008-07-16 18:17:42 +01:00
9aa4a9043d applied anydot's urgency hint patch, thanks! 2008-07-13 18:08:55 +01:00
d5893f55be renamed eprint die 2008-07-03 17:05:56 +01:00
f529d41ca1 simplified detach() 2008-07-03 10:58:35 +01:00
45768ee04b removed aux* stuff from Client 2008-07-02 11:54:36 +01:00
a6d23fb61c removed useless comment 2008-07-02 11:19:02 +01:00
bf76cefe47 minor fix to view() 2008-07-02 11:06:46 +01:00
9bb0f20515 applied Frederik Ternerot's grabbuttons patch with slight modifications 2008-07-01 19:26:17 +01:00
2431ae7df7 locale update 2008-06-30 09:57:45 +01:00
829b6b57e7 removed useless characters 2008-06-24 12:40:48 +01:00
7b4c512e62 applied James Turner's dwm.1 patch, thanks James! 2008-06-23 08:59:19 +01:00
7f7c3140a9 fix of monocle 2008-06-22 09:33:49 +01:00
277155cf77 another merge 2008-06-22 09:29:35 +01:00
0c38ec7cd6 does this fix anything? 2008-06-22 09:29:06 +01:00
deef4c9bfd fixed Gottox' buttonpress/ClkTagBar code 2008-06-21 13:49:43 +01:00
b86c818599 applied Gottox' ClkTagBar patch 2008-06-20 16:52:07 +01:00
c2a916bf30 made arrange again like it was once 2008-06-19 14:58:19 +01:00
2bd46d1ce6 fix 2008-06-19 14:13:07 +01:00
6e0ce46365 use sel instead of seeking the list 2008-06-19 14:07:55 +01:00
c853d5e9bb resize should apply if !banned 2008-06-19 14:01:40 +01:00
31da0b7525 applied Gottox patch 2008-06-19 12:28:56 +01:00
12ea925076 untested monocle 2008-06-19 11:38:53 +01:00
79ecbeca7e non-zero 2008-06-19 09:11:11 +01:00
cf98ea2a9c Added tag 5.0 for changeset 06eb9644e2da 2008-06-18 18:22:54 +01:00
5 changed files with 234 additions and 213 deletions

View File

@ -53,3 +53,4 @@ bcd7e18e196a00cc2e97ff3a4a58f3cdaba13856 4.6
d6d3085307d8d98b8b012b669e858fd787befeb1 4.7
607015ddb091d49cbd3457af41713691aa69f4d6 4.8
22c669b2dd3673785c3476b9976da21e8783f745 4.9
06eb9644e2dad7667d97495eb7d7bc62aa0429e8 5.0

View File

@ -8,15 +8,11 @@ static const char normfgcolor[] = "#000000";
static const char selbordercolor[] = "#0066ff";
static const char selbgcolor[] = "#0066ff";
static const char selfgcolor[] = "#ffffff";
static uint borderpx = 1; /* border pixel of windows */
static uint snap = 32; /* snap pixel */
static unsigned int borderpx = 1; /* border pixel of windows */
static unsigned int snap = 32; /* snap pixel */
static Bool showbar = True; /* False means no bar */
static Bool topbar = True; /* False means bottom bar */
#ifdef XINERAMA
static uint xidx = 0; /* Xinerama screen index to use */
#endif
/* tagging */
static const char tags[][MAXTAGLEN] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
@ -32,8 +28,9 @@ static Bool resizehints = True; /* False means respect size hints in tiled resiz
static Layout layouts[] = {
/* symbol arrange function */
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
};
/* key definitions */
@ -60,11 +57,13 @@ static Key keys[] = {
{ MODKEY, XK_k, focusstack, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
{ MODKEY, XK_m, togglemax, {0} },
{ MODKEY, XK_Return, zoom, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
{ MODKEY, XK_space, togglelayout, {0} },
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
@ -81,31 +80,20 @@ static Key keys[] = {
};
/* button definitions */
#define TAGBUTTONS(TAG) \
{ TAG, 0, Button1, view, {.ui = 1 << TAG} }, \
{ TAG, 0, Button3, toggleview, {.ui = 1 << TAG} }, \
{ TAG, MODKEY, Button1, tag, {.ui = 1 << TAG} }, \
{ TAG, MODKEY, Button3, toggletag, {.ui = 1 << TAG} },
/* click can be a tag number (starting at 0),
* ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static Button buttons[] = {
/* click event mask button function argument */
{ ClkLtSymbol, 0, Button1, togglelayout, {0} },
{ ClkLtSymbol, 0, Button3, togglemax, {0} },
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
TAGBUTTONS(0)
TAGBUTTONS(1)
TAGBUTTONS(2)
TAGBUTTONS(3)
TAGBUTTONS(4)
TAGBUTTONS(5)
TAGBUTTONS(6)
TAGBUTTONS(7)
TAGBUTTONS(8)
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
};

View File

@ -1,5 +1,5 @@
# dwm version
VERSION = 5.0
VERSION = 5.1
# Customize below to fit your system

14
dwm.1
View File

@ -60,8 +60,17 @@ Start
.B Mod1\-b
Toggles bar on and off.
.TP
.B Mod1\-t
Sets tiled layout.
.TP
.B Mod1\-f
Sets floating layout.
.TP
.B Mod1\-m
Sets monocle layout.
.TP
.B Mod1\-space
Toggles between layouts.
Toggles between current and previous layout.
.TP
.B Mod1\-j
Focus next window.
@ -75,9 +84,6 @@ Decrease master area size.
.B Mod1\-l
Increase master area size.
.TP
.B Mod1\-m
Toggle between maximisation meta-layout and active layout.
.TP
.B Mod1\-Return
Zooms/cycles focused window to/from master area (tiled layouts only).
.TP

388
dwm.c
View File

@ -44,39 +44,37 @@
#endif
/* macros */
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask))
#define LENGTH(x) (sizeof x / sizeof x[0])
#define MAXTAGLEN 16
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define TAGMASK ((int)((1LL << LENGTH(tags)) - 1))
#define TEXTW(x) (textnw(x, strlen(x)) + dc.font.height)
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask))
#define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH))
#define ISVISIBLE(x) (x->tags & tagset[seltags])
#define LENGTH(x) (sizeof x / sizeof x[0])
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAXTAGLEN 16
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define TAGMASK ((int)((1LL << LENGTH(tags)) - 1))
#define TEXTW(x) (textnw(x, strlen(x)) + dc.font.height)
/* enums */
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,
enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
/* typedefs */
typedef unsigned int uint;
typedef unsigned long ulong;
typedef union {
int i;
uint ui;
unsigned int ui;
float f;
void *v;
} Arg;
typedef struct {
uint click;
uint mask;
uint button;
unsigned int click;
unsigned int mask;
unsigned int button;
void (*func)(const Arg *arg);
const Arg arg;
} Button;
@ -88,8 +86,8 @@ struct Client {
int x, y, w, h;
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
int bw, oldbw;
uint tags;
Bool isbanned, isfixed, isfloating, ismoved, isurgent;
unsigned int tags;
Bool isfixed, isfloating, isurgent;
Client *next;
Client *snext;
Window win;
@ -97,8 +95,8 @@ struct Client {
typedef struct {
int x, y, w, h;
ulong norm[ColLast];
ulong sel[ColLast];
unsigned long norm[ColLast];
unsigned long sel[ColLast];
Drawable drawable;
GC gc;
struct {
@ -111,7 +109,7 @@ typedef struct {
} DC; /* draw context */
typedef struct {
uint mod;
unsigned int mod;
KeySym keysym;
void (*func)(const Arg *);
const Arg arg;
@ -126,7 +124,7 @@ typedef struct {
const char *class;
const char *instance;
const char *title;
uint tags;
unsigned int tags;
Bool isfloating;
} Rule;
@ -138,36 +136,38 @@ static void attachstack(Client *c);
static void buttonpress(XEvent *e);
static void checkotherwm(void);
static void cleanup(void);
static void clearurgent(void);
static void configure(Client *c);
static void configurenotify(XEvent *e);
static void configurerequest(XEvent *e);
static void destroynotify(XEvent *e);
static void detach(Client *c);
static void detachstack(Client *c);
static void die(const char *errstr, ...);
static void drawbar(void);
static void drawsquare(Bool filled, Bool empty, Bool invert, ulong col[ColLast]);
static void drawtext(const char *text, ulong col[ColLast], Bool invert);
static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
static void drawtext(const char *text, unsigned long col[ColLast], Bool invert);
static void enternotify(XEvent *e);
static void eprint(const char *errstr, ...);
static void expose(XEvent *e);
static void focus(Client *c);
static void focusin(XEvent *e);
static void focusstack(const Arg *arg);
static Client *getclient(Window w);
static ulong getcolor(const char *colstr);
static unsigned long getcolor(const char *colstr);
static long getstate(Window w);
static Bool gettextprop(Window w, Atom atom, char *text, uint size);
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 initfont(const char *fontstr);
static Bool isoccupied(uint t);
static Bool isoccupied(unsigned int t);
static Bool isprotodel(Client *c);
static Bool isurgent(uint t);
static Bool isurgent(unsigned int t);
static void keypress(XEvent *e);
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 monocle(void);
static void movemouse(const Arg *arg);
static Client *nexttiled(Client *c);
static void propertynotify(XEvent *e);
@ -178,16 +178,15 @@ 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);
static void tag(const Arg *arg);
static int textnw(const char *text, uint len);
static int textnw(const char *text, unsigned int 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);
@ -207,9 +206,9 @@ static void zoom(const Arg *arg);
static char stext[256];
static int screen, sx, sy, sw, sh;
static int by, bh, blw, wx, wy, ww, wh;
static uint seltags = 0;
static unsigned int seltags = 0, sellt = 0;
static int (*xerrorxlib)(Display *, XErrorEvent *);
static uint numlockmask = 0;
static unsigned int numlockmask = 0;
static void (*handler[LASTEvent]) (XEvent *) = {
[ButtonPress] = buttonpress,
[ConfigureRequest] = configurerequest,
@ -225,28 +224,27 @@ 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 */
static unsigned int tagset[] = {1, 1}; /* after start, first tag is selected */
static Client *clients = NULL;
static Client *sel = NULL;
static Client *stack = NULL;
static Cursor cursor[CurLast];
static Display *dpy;
static DC dc = {0};
static Layout *lt = NULL;
static Layout *lt[] = { NULL, NULL };
static Window root, barwin;
/* configuration, allows nested code to access above variables */
#include "config.h"
/* compile-time check if all tags fit into an uint bit array. */
struct NumTags { char limitexceeded[sizeof(uint) * 8 < LENGTH(tags) ? -1 : 1]; };
/* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags { char limitexceeded[sizeof(unsigned int) * 8 < LENGTH(tags) ? -1 : 1]; };
/* function implementations */
void
applyrules(Client *c) {
uint i;
unsigned int i;
Rule *r;
XClassHint ch = { 0 };
@ -274,23 +272,18 @@ arrange(void) {
Client *c;
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(ISVISIBLE(c)) {
XMoveWindow(dpy, c->win, c->x, c->y);
if(!lt[sellt]->arrange || c->isfloating)
resize(c, c->x, c->y, c->w, c->h, True);
c->isbanned = False;
}
else if(!c->isbanned) {
else {
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
c->isbanned = c->ismoved = True;
}
focus(NULL);
if(lt->arrange && !ismax)
lt->arrange();
if(lt[sellt]->arrange)
lt[sellt]->arrange();
restack();
}
@ -308,18 +301,19 @@ attachstack(Client *c) {
void
buttonpress(XEvent *e) {
uint i, x, click;
unsigned int i, x, click;
Arg arg = {0};
Client *c;
XButtonPressedEvent *ev = &e->xbutton;
click = ClkRootWin;
if(ev->window == barwin) {
i = x = 0;
do
x += TEXTW(tags[i]);
while(ev->x >= x && ++i < LENGTH(tags));
if(i < LENGTH(tags))
click = i;
do x += TEXTW(tags[i]); while(ev->x >= x && ++i < LENGTH(tags));
if(i < LENGTH(tags)) {
click = ClkTagBar;
arg.ui = 1 << i;
}
else if(ev->x < x + blw)
click = ClkLtSymbol;
else if(ev->x > wx + ww - TEXTW(stext))
@ -335,7 +329,7 @@ buttonpress(XEvent *e) {
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);
buttons[i].func(click == ClkTagBar ? &arg : &buttons[i].arg);
}
void
@ -347,7 +341,7 @@ checkotherwm(void) {
XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask);
XSync(dpy, False);
if(otherwm)
eprint("dwm: another window manager is already running\n");
die("dwm: another window manager is already running\n");
XSetErrorHandler(NULL);
xerrorxlib = XSetErrorHandler(xerror);
XSync(dpy, False);
@ -360,7 +354,7 @@ cleanup(void) {
close(STDIN_FILENO);
view(&a);
lt = &foo;
lt[sellt] = &foo;
while(stack)
unmanage(stack);
if(dc.font.set)
@ -378,6 +372,23 @@ cleanup(void) {
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
}
void
clearurgent(void) {
XWMHints *wmh;
Client *c;
for(c = clients; c; c = c->next)
if(ISVISIBLE(c) && c->isurgent) {
c->isurgent = False;
if (!(wmh = XGetWMHints(dpy, c->win)))
continue;
wmh->flags &= ~XUrgencyHint;
XSetWMHints(dpy, c->win, wmh);
XFree(wmh);
}
}
void
configure(Client *c) {
XConfigureEvent ce;
@ -418,9 +429,7 @@ 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) {
else if(c->isfloating || !lt[sellt]->arrange) {
if(ev->value_mask & CWX)
c->x = sx + ev->x;
if(ev->value_mask & CWY)
@ -433,10 +442,9 @@ configurerequest(XEvent *e) {
c->x = sx + (sw / 2 - c->w / 2); /* center in x direction */
if((c->y - sy + c->h) > sh && c->isfloating)
c->y = sy + (sh / 2 - c->h / 2); /* center in y direction */
if((ev->value_mask & (CWX|CWY))
&& !(ev->value_mask & (CWWidth|CWHeight)))
if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
configure(c);
if(!c->isbanned)
if(ISVISIBLE(c))
XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
}
else
@ -466,16 +474,10 @@ destroynotify(XEvent *e) {
void
detach(Client *c) {
Client *i;
Client **tc;
if (c != clients) {
for(i = clients; i->next != c; i = i->next);
i->next = c->next;
}
else {
clients = c->next;
}
c->next = NULL;
for(tc = &clients; *tc && *tc != c; tc = &(*tc)->next);
*tc = c->next;
}
void
@ -486,28 +488,36 @@ detachstack(Client *c) {
*tc = c->snext;
}
void
die(const char *errstr, ...) {
va_list ap;
va_start(ap, errstr);
vfprintf(stderr, errstr, ap);
va_end(ap);
exit(EXIT_FAILURE);
}
void
drawbar(void) {
int i, x;
Client *c;
dc.x = 0;
for(c = stack; c && c->isbanned; c = c->snext);
for(i = 0; i < LENGTH(tags); i++) {
dc.w = TEXTW(tags[i]);
if(tagset[seltags] & 1 << i) {
drawtext(tags[i], dc.sel, isurgent(i));
drawsquare(c && c->tags & 1 << i, isoccupied(i), isurgent(i), dc.sel);
drawsquare(sel && sel->tags & 1 << i, isoccupied(i), isurgent(i), dc.sel);
}
else {
drawtext(tags[i], dc.norm, isurgent(i));
drawsquare(c && c->tags & 1 << i, isoccupied(i), isurgent(i), dc.norm);
drawsquare(sel && sel->tags & 1 << i, isoccupied(i), isurgent(i), dc.norm);
}
dc.x += dc.w;
}
if(blw > 0) {
dc.w = blw;
drawtext(lt->symbol, dc.norm, ismax);
drawtext(lt[sellt]->symbol, dc.norm, False);
x = dc.x + dc.w;
}
else
@ -521,9 +531,9 @@ drawbar(void) {
drawtext(stext, dc.norm, False);
if((dc.w = dc.x - x) > bh) {
dc.x = x;
if(c) {
drawtext(c->name, dc.sel, False);
drawsquare(c->isfixed, c->isfloating, False, dc.sel);
if(sel) {
drawtext(sel->name, dc.sel, False);
drawsquare(sel->isfixed, sel->isfloating, False, dc.sel);
}
else
drawtext(NULL, dc.norm, False);
@ -533,7 +543,7 @@ drawbar(void) {
}
void
drawsquare(Bool filled, Bool empty, Bool invert, ulong col[ColLast]) {
drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
int x;
XGCValues gcv;
XRectangle r = { dc.x, dc.y, dc.w, dc.h };
@ -554,7 +564,7 @@ drawsquare(Bool filled, Bool empty, Bool invert, ulong col[ColLast]) {
}
void
drawtext(const char *text, ulong col[ColLast], Bool invert) {
drawtext(const char *text, unsigned long col[ColLast], Bool invert) {
int i, x, y, h, len, olen;
XRectangle r = { dc.x, dc.y, dc.w, dc.h };
char buf[256];
@ -595,16 +605,6 @@ enternotify(XEvent *e) {
focus(NULL);
}
void
eprint(const char *errstr, ...) {
va_list ap;
va_start(ap, errstr);
vfprintf(stderr, errstr, ap);
va_end(ap);
exit(EXIT_FAILURE);
}
void
expose(XEvent *e) {
XExposeEvent *ev = &e->xexpose;
@ -615,8 +615,8 @@ expose(XEvent *e) {
void
focus(Client *c) {
if(!c || c->isbanned)
for(c = stack; c && c->isbanned; c = c->snext);
if(!c || !ISVISIBLE(c))
for(c = stack; c && !ISVISIBLE(c); c = c->snext);
if(sel && sel != c) {
grabbuttons(sel, False);
XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]);
@ -649,17 +649,17 @@ focusstack(const Arg *arg) {
if(!sel)
return;
if (arg->i > 0) {
for(c = sel->next; c && c->isbanned; c = c->next);
for(c = sel->next; c && !ISVISIBLE(c); c = c->next);
if(!c)
for(c = clients; c && c->isbanned; c = c->next);
for(c = clients; c && !ISVISIBLE(c); c = c->next);
}
else {
for(i = clients; i != sel; i = i->next)
if (!i->isbanned)
if(ISVISIBLE(i))
c = i;
if(!c)
for(; i; i = i->next)
if (!i->isbanned)
if(ISVISIBLE(i))
c = i;
}
if(c) {
@ -676,13 +676,13 @@ getclient(Window w) {
return c;
}
ulong
unsigned long
getcolor(const char *colstr) {
Colormap cmap = DefaultColormap(dpy, screen);
XColor color;
if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
eprint("error, cannot allocate color '%s'\n", colstr);
die("error, cannot allocate color '%s'\n", colstr);
return color.pixel;
}
@ -691,7 +691,7 @@ getstate(Window w) {
int format, status;
long result = -1;
unsigned char *p = NULL;
ulong n, extra;
unsigned long n, extra;
Atom real;
status = XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
@ -705,7 +705,7 @@ getstate(Window w) {
}
Bool
gettextprop(Window w, Atom atom, char *text, uint size) {
gettextprop(Window w, Atom atom, char *text, unsigned int size) {
char **list = NULL;
int n;
XTextProperty name;
@ -732,24 +732,23 @@ gettextprop(Window w, Atom atom, char *text, uint size) {
void
grabbuttons(Client *c, Bool focused) {
int i, j;
uint buttons[] = { Button1, Button2, Button3 };
uint modifiers[] = { MODKEY, MODKEY|LockMask, MODKEY|numlockmask, MODKEY|numlockmask|LockMask };
unsigned int i, j;
unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
if(focused)
if(focused) {
for(i = 0; i < LENGTH(buttons); i++)
for(j = 0; j < LENGTH(modifiers); j++)
XGrabButton(dpy, buttons[i], modifiers[j], c->win, False,
BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
else
if(buttons[i].click == ClkClientWin)
for(j = 0; j < LENGTH(modifiers); j++)
XGrabButton(dpy, buttons[i].button, buttons[i].mask | modifiers[j], c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
} else
XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,
BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
}
void
grabkeys(void) {
uint i, j;
unsigned int i, j;
KeyCode code;
XModifierKeymap *modmap;
@ -809,7 +808,7 @@ initfont(const char *fontstr) {
dc.font.xfont = NULL;
if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))
&& !(dc.font.xfont = XLoadQueryFont(dpy, "fixed")))
eprint("error, cannot load font: '%s'\n", fontstr);
die("error, cannot load font: '%s'\n", fontstr);
dc.font.ascent = dc.font.xfont->ascent;
dc.font.descent = dc.font.xfont->descent;
}
@ -817,7 +816,7 @@ initfont(const char *fontstr) {
}
Bool
isoccupied(uint t) {
isoccupied(unsigned int t) {
Client *c;
for(c = clients; c; c = c->next)
@ -842,7 +841,7 @@ isprotodel(Client *c) {
}
Bool
isurgent(uint t) {
isurgent(unsigned int t) {
Client *c;
for(c = clients; c; c = c->next)
@ -853,7 +852,7 @@ isurgent(uint t) {
void
keypress(XEvent *e) {
uint i;
unsigned int i;
KeySym keysym;
XKeyEvent *ev;
@ -893,7 +892,7 @@ manage(Window w, XWindowAttributes *wa) {
XWindowChanges wc;
if(!(c = calloc(1, sizeof(Client))))
eprint("fatal: could not calloc() %u bytes\n", sizeof(Client));
die("fatal: could not calloc() %u bytes\n", sizeof(Client));
c->win = w;
/* geometry */
@ -905,7 +904,7 @@ manage(Window w, XWindowAttributes *wa) {
if(c->w == sw && c->h == sh) {
c->x = sx;
c->y = sy;
c->bw = wa->border_width;
c->bw = 0;
}
else {
if(c->x + c->w + 2 * c->bw > sx + sw)
@ -938,7 +937,7 @@ manage(Window w, XWindowAttributes *wa) {
XRaiseWindow(dpy, c->win);
attach(c);
attachstack(c);
XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); /* some windows require this */
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);
arrange();
@ -966,10 +965,18 @@ maprequest(XEvent *e) {
manage(ev->window, &wa);
}
void
monocle(void) {
Client *c;
for(c = nexttiled(clients); c; c = nexttiled(c->next))
resize(c, wx, wy, ww - 2 * c->bw, wh - 2 * c->bw, resizehints);
}
void
movemouse(const Arg *arg) {
int x1, y1, ocx, ocy, di, nx, ny;
uint dui;
int x, y, ocx, ocy, di, nx, ny;
unsigned int dui;
Client *c;
Window dummy;
XEvent ev;
@ -982,7 +989,7 @@ movemouse(const Arg *arg) {
if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
None, cursor[CurMove], CurrentTime) != GrabSuccess)
return;
XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui);
for(;;) {
XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
switch (ev.type) {
@ -996,8 +1003,8 @@ movemouse(const Arg *arg) {
break;
case MotionNotify:
XSync(dpy, False);
nx = ocx + (ev.xmotion.x - x1);
ny = ocy + (ev.xmotion.y - y1);
nx = ocx + (ev.xmotion.x - x);
ny = ocy + (ev.xmotion.y - y);
if(snap && nx >= wx && nx <= wx + ww
&& ny >= wy && ny <= wy + wh) {
if(abs(wx - nx) < snap)
@ -1008,10 +1015,10 @@ movemouse(const Arg *arg) {
ny = wy;
else if(abs((wy + wh) - (ny + c->h + 2 * c->bw)) < snap)
ny = wy + wh - c->h - 2 * c->bw;
if(!c->isfloating && lt->arrange && (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
if(!c->isfloating && lt[sellt]->arrange && (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
togglefloating(NULL);
}
if(!lt->arrange || c->isfloating)
if(!lt[sellt]->arrange || c->isfloating)
resize(c, nx, ny, c->w, c->h, False);
break;
}
@ -1020,7 +1027,7 @@ movemouse(const Arg *arg) {
Client *
nexttiled(Client *c) {
for(; c && (c->isfloating || c->isbanned); c = c->next);
for(; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
return c;
}
@ -1115,8 +1122,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;
@ -1166,11 +1172,11 @@ resizemouse(const Arg *arg) {
if(snap && nw >= wx && nw <= wx + ww
&& nh >= wy && nh <= wy + wh) {
if(!c->isfloating && lt->arrange
if(!c->isfloating && lt[sellt]->arrange
&& (abs(nw - c->w) > snap || abs(nh - c->h) > snap))
togglefloating(NULL);
}
if(!lt->arrange || c->isfloating)
if(!lt[sellt]->arrange || c->isfloating)
resize(c, c->x, c->y, nw, nh, True);
break;
}
@ -1186,13 +1192,13 @@ restack(void) {
drawbar();
if(!sel)
return;
if(ismax || sel->isfloating || !lt->arrange)
if(sel->isfloating || !lt[sellt]->arrange)
XRaiseWindow(dpy, sel->win);
if(!ismax && lt->arrange) {
if(lt[sellt]->arrange) {
wc.stack_mode = Below;
wc.sibling = barwin;
for(c = stack; c; c = c->snext)
if(!c->isfloating && !c->isbanned) {
if(!c->isfloating && ISVISIBLE(c)) {
XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
wc.sibling = c->win;
}
@ -1207,7 +1213,7 @@ run(void) {
char sbuf[sizeof stext];
fd_set rd;
int r, xfd;
uint len, offset;
unsigned int len, offset;
XEvent ev;
/* main event loop, also reads status text from stdin */
@ -1225,7 +1231,7 @@ run(void) {
if(select(xfd + 1, &rd, NULL, NULL, NULL) == -1) {
if(errno == EINTR)
continue;
eprint("select failed\n");
die("select failed\n");
}
if(FD_ISSET(STDIN_FILENO, &rd)) {
switch((r = read(STDIN_FILENO, sbuf + offset, len - offset))) {
@ -1263,7 +1269,7 @@ run(void) {
void
scan(void) {
uint i, num;
unsigned int i, num;
Window *wins, d1, d2;
XWindowAttributes wa;
@ -1296,12 +1302,24 @@ setclientstate(Client *c, long state) {
PropModeReplace, (unsigned char *)data, 2);
}
void
setlayout(const Arg *arg) {
if(!arg || !arg->v || arg->v != lt[sellt])
sellt ^= 1;
if(arg && arg->v)
lt[sellt] = (Layout *)arg->v;
if(sel)
arrange();
else
drawbar();
}
/* arg > 1.0 will set mfact absolutly */
void
setmfact(const Arg *arg) {
float f;
if(!arg || !lt->arrange)
if(!arg || !lt[sellt]->arrange)
return;
f = arg->f < 1.0 ? arg->f + mfact : arg->f - 1.0;
if(f < 0.1 || f > 0.9)
@ -1312,7 +1330,7 @@ setmfact(const Arg *arg) {
void
setup(void) {
uint i;
unsigned int i;
int w;
XSetWindowAttributes wa;
@ -1325,7 +1343,8 @@ setup(void) {
sw = DisplayWidth(dpy, screen);
sh = DisplayHeight(dpy, screen);
bh = dc.h = dc.font.height + 2;
lt = layouts;
lt[0] = &layouts[0];
lt[1] = &layouts[1 % LENGTH(layouts)];
updategeom();
/* init atoms */
@ -1414,7 +1433,7 @@ tag(const Arg *arg) {
}
int
textnw(const char *text, uint len) {
textnw(const char *text, unsigned int len) {
XRectangle r;
if(dc.font.set) {
@ -1427,7 +1446,7 @@ textnw(const char *text, uint len) {
void
tile(void) {
int x, y, h, w, mw;
uint i, n;
unsigned int i, n;
Client *c;
for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), n++);
@ -1476,34 +1495,25 @@ togglefloating(const Arg *arg) {
arrange();
}
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)))
unsigned int mask = sel->tags ^ (arg->ui & TAGMASK);
if(sel && mask) {
sel->tags = mask;
arrange();
}
}
void
toggleview(const Arg *arg) {
if((tagset[seltags] ^= (arg->ui & TAGMASK)))
unsigned int mask = tagset[seltags] ^ (arg->ui & TAGMASK);
if(mask) {
tagset[seltags] = mask;
clearurgent();
arrange();
}
}
void
@ -1548,16 +1558,24 @@ updatebar(void) {
void
updategeom(void) {
#ifdef XINERAMA
int i;
int n, i = 0;
XineramaScreenInfo *info = NULL;
/* window area geometry */
if(XineramaIsActive(dpy)) {
info = XineramaQueryScreens(dpy, &i);
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;
if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) {
if(n > 1) {
int di, x, y;
unsigned int dui;
Window dummy;
if(XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui))
for(i = 0; i < n; i++)
if(INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height))
break;
}
wx = info[i].x_org;
wy = showbar && topbar ? info[i].y_org + bh : info[i].y_org;
ww = info[i].width;
wh = showbar ? info[i].height - bh : info[i].height;
XFree(info);
}
else
@ -1632,19 +1650,25 @@ updatewmhints(Client *c) {
XWMHints *wmh;
if((wmh = XGetWMHints(dpy, c->win))) {
if(c == sel)
sel->isurgent = False;
if(ISVISIBLE(c) && wmh->flags & XUrgencyHint) {
wmh->flags &= ~XUrgencyHint;
XSetWMHints(dpy, c->win, wmh);
}
else
c->isurgent = (wmh->flags & XUrgencyHint) ? True : False;
XFree(wmh);
}
}
void
view(const Arg *arg) {
if(arg && (arg->i & TAGMASK) == tagset[seltags])
return;
seltags ^= 1; /* toggle sel tagset */
if(arg && (arg->ui & TAGMASK))
tagset[seltags] = arg->i & TAGMASK;
clearurgent();
arrange();
}
@ -1685,7 +1709,7 @@ void
zoom(const Arg *arg) {
Client *c = sel;
if(ismax || !lt->arrange || (sel && sel->isfloating))
if(!lt[sellt]->arrange || lt[sellt]->arrange == monocle || (sel && sel->isfloating))
return;
if(c == nexttiled(clients))
if(!c || !(c = nexttiled(c->next)))
@ -1699,13 +1723,15 @@ zoom(const Arg *arg) {
int
main(int argc, char *argv[]) {
if(argc == 2 && !strcmp("-v", argv[1]))
eprint("dwm-"VERSION", © 2006-2008 dwm engineers, see LICENSE for details\n");
die("dwm-"VERSION", © 2006-2008 dwm engineers, see LICENSE for details\n");
else if(argc != 1)
eprint("usage: dwm [-v]\n");
die("usage: dwm [-v]\n");
if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
fprintf(stderr, "warning: no locale support\n");
setlocale(LC_CTYPE, "");
if(!(dpy = XOpenDisplay(0)))
eprint("dwm: cannot open display\n");
die("dwm: cannot open display\n");
checkotherwm();
setup();