summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.def.h25
-rw-r--r--drw.c2
-rw-r--r--drw.h2
-rw-r--r--dwm.113
-rw-r--r--dwm.c233
5 files changed, 211 insertions, 64 deletions
diff --git a/config.def.h b/config.def.h
index 9efa774..32d6fb9 100644
--- a/config.def.h
+++ b/config.def.h
@@ -5,17 +5,19 @@ static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int snap = 32; /* snap pixel */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
+static const int focusonwheel = 0;
static const char *fonts[] = { "monospace:size=10" };
static const char dmenufont[] = "monospace:size=10";
-static const char col_gray1[] = "#222222";
-static const char col_gray2[] = "#444444";
-static const char col_gray3[] = "#bbbbbb";
-static const char col_gray4[] = "#eeeeee";
-static const char col_cyan[] = "#005577";
-static const char *colors[][3] = {
- /* fg bg border */
- [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
- [SchemeSel] = { col_gray4, col_cyan, col_cyan },
+static char normbgcolor[] = "#222222";
+static char normbordercolor[] = "#444444";
+static char normfgcolor[] = "#bbbbbb";
+static char selfgcolor[] = "#eeeeee";
+static char selbordercolor[] = "#005577";
+static char selbgcolor[] = "#005577";
+static char *colors[][3] = {
+ /* fg bg border */
+ [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor },
+ [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor },
};
/* tagging */
@@ -57,7 +59,7 @@ static const Layout layouts[] = {
/* commands */
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
-static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
+static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbordercolor, "-sf", selfgcolor, NULL };
static const char *termcmd[] = { "st", NULL };
static const Key keys[] = {
@@ -79,12 +81,14 @@ static const Key keys[] = {
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
+ { MODKEY|ShiftMask, XK_f, togglefullscr, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
{ MODKEY, XK_period, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
+ { MODKEY, XK_F5, xrdb, {.v = NULL } },
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
@@ -95,6 +99,7 @@ static const Key keys[] = {
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
{ MODKEY|ShiftMask, XK_q, quit, {0} },
+ { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} },
};
/* button definitions */
diff --git a/drw.c b/drw.c
index a58a2b4..f8a82f5 100644
--- a/drw.c
+++ b/drw.c
@@ -195,7 +195,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
/* Wrapper to create color schemes. The caller has to call free(3) on the
* returned color scheme when done using it. */
Clr *
-drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
+drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount)
{
size_t i;
Clr *ret;
diff --git a/drw.h b/drw.h
index 6471431..bdbf950 100644
--- a/drw.h
+++ b/drw.h
@@ -40,7 +40,7 @@ void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned in
/* Colorscheme abstraction */
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
-Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
+Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount);
/* Cursor abstraction */
Cur *drw_cur_create(Drw *drw, int shape);
diff --git a/dwm.1 b/dwm.1
index ddc8321..837d02a 100644
--- a/dwm.1
+++ b/dwm.1
@@ -116,6 +116,9 @@ Zooms/cycles focused window to/from master area (tiled layouts only).
.B Mod1\-Shift\-c
Close focused window.
.TP
+.B Mod1\-Shift\-f
+Toggle fullscreen for focused window.
+.TP
.B Mod1\-Shift\-space
Toggle focused window between tiled and floating state.
.TP
@@ -142,6 +145,9 @@ Add/remove all windows with nth tag to/from the view.
.TP
.B Mod1\-Shift\-q
Quit dwm.
+.TP
+.B Mod1\-Control\-Shift\-q
+Restart dwm.
.SS Mouse commands
.TP
.B Mod1\-Button1
@@ -155,6 +161,13 @@ Resize focused window while dragging. Tiled windows will be toggled to the float
.SH CUSTOMIZATION
dwm is customized by creating a custom config.h and (re)compiling the source
code. This keeps it fast, secure and simple.
+.SH SIGNALS
+.TP
+.B SIGHUP - 1
+Restart the dwm process.
+.TP
+.B SIGTERM - 15
+Cleanly terminate the dwm process.
.SH SEE ALSO
.BR dmenu (1),
.BR st (1)
diff --git a/dwm.c b/dwm.c
index 071e9f2..900aed3 100644
--- a/dwm.c
+++ b/dwm.c
@@ -35,6 +35,7 @@
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xproto.h>
+#include <X11/Xresource.h>
#include <X11/Xutil.h>
#ifdef XINERAMA
#include <X11/extensions/Xinerama.h>
@@ -56,6 +57,21 @@
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
#define TAGMASK ((1 << LENGTH(tags)) - 1)
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
+#define XRDB_LOAD_COLOR(R,V) if (XrmGetResource(xrdb, R, NULL, &type, &value) == True) { \
+ if (value.addr != NULL && strnlen(value.addr, 8) == 7 && value.addr[0] == '#') { \
+ int i = 1; \
+ for (; i <= 6; i++) { \
+ if (value.addr[i] < 48) break; \
+ if (value.addr[i] > 57 && value.addr[i] < 65) break; \
+ if (value.addr[i] > 70 && value.addr[i] < 97) break; \
+ if (value.addr[i] > 102) break; \
+ } \
+ if (i == 7) { \
+ strncpy(V, value.addr, 7); \
+ V[7] = '\0'; \
+ } \
+ } \
+ }
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
@@ -111,6 +127,7 @@ typedef struct {
void (*arrange)(Monitor *);
} Layout;
+typedef struct Pertag Pertag;
struct Monitor {
char ltsymbol[16];
float mfact;
@@ -130,6 +147,7 @@ struct Monitor {
Monitor *next;
Window barwin;
const Layout *lt[2];
+ Pertag *pertag;
};
typedef struct {
@@ -163,7 +181,6 @@ static void detachstack(Client *c);
static Monitor *dirtomon(int dir);
static void drawbar(Monitor *m);
static void drawbars(void);
-static void enternotify(XEvent *e);
static void expose(XEvent *e);
static void focus(Client *c);
static void focusin(XEvent *e);
@@ -178,11 +195,11 @@ static void grabkeys(void);
static void incnmaster(const Arg *arg);
static void keypress(XEvent *e);
static void killclient(const Arg *arg);
+static void loadxrdb(void);
static void manage(Window w, XWindowAttributes *wa);
static void mappingnotify(XEvent *e);
static void maprequest(XEvent *e);
static void monocle(Monitor *m);
-static void motionnotify(XEvent *e);
static void movemouse(const Arg *arg);
static Client *nexttiled(Client *c);
static void pop(Client *c);
@@ -206,12 +223,15 @@ static void setmfact(const Arg *arg);
static void setup(void);
static void seturgent(Client *c, int urg);
static void showhide(Client *c);
+static void sighup(int unused);
+static void sigterm(int unused);
static void spawn(const Arg *arg);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static void tile(Monitor *m);
static void togglebar(const Arg *arg);
static void togglefloating(const Arg *arg);
+static void togglefullscr(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void unfocus(Client *c, int setfocus);
@@ -233,6 +253,7 @@ static Monitor *wintomon(Window w);
static int xerror(Display *dpy, XErrorEvent *ee);
static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
+static void xrdb(const Arg *arg);
static void zoom(const Arg *arg);
/* variables */
@@ -250,17 +271,16 @@ static void (*handler[LASTEvent]) (XEvent *) = {
[ConfigureRequest] = configurerequest,
[ConfigureNotify] = configurenotify,
[DestroyNotify] = destroynotify,
- [EnterNotify] = enternotify,
[Expose] = expose,
[FocusIn] = focusin,
[KeyPress] = keypress,
[MappingNotify] = mappingnotify,
[MapRequest] = maprequest,
- [MotionNotify] = motionnotify,
[PropertyNotify] = propertynotify,
[UnmapNotify] = unmapnotify
};
static Atom wmatom[WMLast], netatom[NetLast];
+static int restart = 0;
static int running = 1;
static Cur *cursor[CurLast];
static Clr **scheme;
@@ -272,6 +292,15 @@ static Window root, wmcheckwin;
/* configuration, allows nested code to access above variables */
#include "config.h"
+struct Pertag {
+ unsigned int curtag, prevtag; /* current and previous tag */
+ int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */
+ float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */
+ unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */
+ const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */
+ int showbars[LENGTH(tags) + 1]; /* display bar for the current tag */
+};
+
/* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
@@ -427,7 +456,8 @@ buttonpress(XEvent *e)
click = ClkRootWin;
/* focus monitor if necessary */
- if ((m = wintomon(ev->window)) && m != selmon) {
+ if ((m = wintomon(ev->window)) && m != selmon
+ && (focusonwheel || (ev->button != Button4 && ev->button != Button5))) {
unfocus(selmon->sel, 1);
selmon = m;
focus(NULL);
@@ -447,10 +477,10 @@ buttonpress(XEvent *e)
else
click = ClkWinTitle;
} else if ((c = wintoclient(ev->window))) {
- focus(c);
- restack(selmon);
- XAllowEvents(dpy, ReplayPointer, CurrentTime);
- click = ClkClientWin;
+ if (focusonwheel || (ev->button != Button4 && ev->button != Button5))
+ focus(c);
+ XAllowEvents(dpy, ReplayPointer, CurrentTime);
+ click = ClkClientWin;
}
for (i = 0; i < LENGTH(buttons); i++)
if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
@@ -635,6 +665,7 @@ Monitor *
createmon(void)
{
Monitor *m;
+ unsigned int i;
m = ecalloc(1, sizeof(Monitor));
m->tagset[0] = m->tagset[1] = 1;
@@ -645,6 +676,20 @@ createmon(void)
m->lt[0] = &layouts[0];
m->lt[1] = &layouts[1 % LENGTH(layouts)];
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
+ m->pertag = ecalloc(1, sizeof(Pertag));
+ m->pertag->curtag = m->pertag->prevtag = 1;
+
+ for (i = 0; i <= LENGTH(tags); i++) {
+ m->pertag->nmasters[i] = m->nmaster;
+ m->pertag->mfacts[i] = m->mfact;
+
+ m->pertag->ltidxs[i][0] = m->lt[0];
+ m->pertag->ltidxs[i][1] = m->lt[1];
+ m->pertag->sellts[i] = m->sellt;
+
+ m->pertag->showbars[i] = m->showbar;
+ }
+
return m;
}
@@ -759,25 +804,6 @@ drawbars(void)
}
void
-enternotify(XEvent *e)
-{
- Client *c;
- Monitor *m;
- XCrossingEvent *ev = &e->xcrossing;
-
- if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root)
- return;
- c = wintoclient(ev->window);
- m = c ? c->mon : wintomon(ev->window);
- if (m != selmon) {
- unfocus(selmon->sel, 1);
- selmon = m;
- } else if (!c || c == selmon->sel)
- return;
- focus(c);
-}
-
-void
expose(XEvent *e)
{
Monitor *m;
@@ -946,7 +972,7 @@ grabbuttons(Client *c, int focused)
XGrabButton(dpy, buttons[i].button,
buttons[i].mask | modifiers[j],
c->win, False, BUTTONMASK,
- GrabModeAsync, GrabModeSync, None, None);
+ GrabModeSync, GrabModeSync, None, None);
}
}
@@ -981,7 +1007,7 @@ grabkeys(void)
void
incnmaster(const Arg *arg)
{
- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0);
arrange(selmon);
}
@@ -1030,6 +1056,37 @@ killclient(const Arg *arg)
}
void
+loadxrdb()
+{
+ Display *display;
+ char * resm;
+ XrmDatabase xrdb;
+ char *type;
+ XrmValue value;
+
+ display = XOpenDisplay(NULL);
+
+ if (display != NULL) {
+ resm = XResourceManagerString(display);
+
+ if (resm != NULL) {
+ xrdb = XrmGetStringDatabase(resm);
+
+ if (xrdb != NULL) {
+ XRDB_LOAD_COLOR("background", normbordercolor);
+ XRDB_LOAD_COLOR("background", normbgcolor);
+ XRDB_LOAD_COLOR("foreground", normfgcolor);
+ XRDB_LOAD_COLOR("foreground", selbordercolor);
+ XRDB_LOAD_COLOR("foreground", selbgcolor);
+ XRDB_LOAD_COLOR("background", selfgcolor);
+ }
+ }
+ }
+
+ XCloseDisplay(display);
+}
+
+void
manage(Window w, XWindowAttributes *wa)
{
Client *c, *t = NULL;
@@ -1147,23 +1204,6 @@ monocle(Monitor *m)
}
void
-motionnotify(XEvent *e)
-{
- static Monitor *mon = NULL;
- Monitor *m;
- XMotionEvent *ev = &e->xmotion;
-
- if (ev->window != root)
- return;
- if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) {
- unfocus(selmon->sel, 1);
- selmon = m;
- focus(NULL);
- }
- mon = m;
-}
-
-void
movemouse(const Arg *arg)
{
int x, y, ocx, ocy, nx, ny;
@@ -1279,6 +1319,7 @@ propertynotify(XEvent *e)
void
quit(const Arg *arg)
{
+ if(arg->i) restart = 1;
running = 0;
}
@@ -1533,9 +1574,9 @@ void
setlayout(const Arg *arg)
{
if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
- selmon->sellt ^= 1;
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1;
if (arg && arg->v)
- selmon->lt[selmon->sellt] = (Layout *)arg->v;
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v;
strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
if (selmon->sel)
arrange(selmon);
@@ -1554,7 +1595,7 @@ setmfact(const Arg *arg)
f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
if (f < 0.05 || f > 0.95)
return;
- selmon->mfact = f;
+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f;
arrange(selmon);
}
@@ -1575,6 +1616,9 @@ setup(void)
/* clean up any zombies (inherited from .xinitrc etc) immediately */
while (waitpid(-1, NULL, WNOHANG) > 0);
+ signal(SIGHUP, sighup);
+ signal(SIGTERM, sigterm);
+
/* init screen */
screen = DefaultScreen(dpy);
sw = DisplayWidth(dpy, screen);
@@ -1669,6 +1713,20 @@ showhide(Client *c)
}
void
+sighup(int unused)
+{
+ Arg a = {.i = 1};
+ quit(&a);
+}
+
+void
+sigterm(int unused)
+{
+ Arg a = {.i = 0};
+ quit(&a);
+}
+
+void
spawn(const Arg *arg)
{
struct sigaction sa;
@@ -1750,7 +1808,7 @@ tile(Monitor *m)
void
togglebar(const Arg *arg)
{
- selmon->showbar = !selmon->showbar;
+ selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar;
updatebarpos(selmon);
XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
arrange(selmon);
@@ -1771,6 +1829,13 @@ togglefloating(const Arg *arg)
}
void
+togglefullscr(const Arg *arg)
+{
+ if(selmon->sel)
+ setfullscreen(selmon->sel, !selmon->sel->isfullscreen);
+}
+
+void
toggletag(const Arg *arg)
{
unsigned int newtags;
@@ -1790,9 +1855,33 @@ void
toggleview(const Arg *arg)
{
unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
+ int i;
if (newtagset) {
selmon->tagset[selmon->seltags] = newtagset;
+
+ if (newtagset == ~0) {
+ selmon->pertag->prevtag = selmon->pertag->curtag;
+ selmon->pertag->curtag = 0;
+ }
+
+ /* test if the user did not select the same tag */
+ if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) {
+ selmon->pertag->prevtag = selmon->pertag->curtag;
+ for (i = 0; !(newtagset & 1 << i); i++) ;
+ selmon->pertag->curtag = i + 1;
+ }
+
+ /* apply settings for this view */
+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
+
+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
+ togglebar(NULL);
+
focus(NULL);
arrange(selmon);
}
@@ -2089,11 +2178,37 @@ updatewmhints(Client *c)
void
view(const Arg *arg)
{
+ int i;
+ unsigned int tmptag;
+
if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
return;
selmon->seltags ^= 1; /* toggle sel tagset */
- if (arg->ui & TAGMASK)
+ if (arg->ui & TAGMASK) {
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
+ selmon->pertag->prevtag = selmon->pertag->curtag;
+
+ if (arg->ui == ~0)
+ selmon->pertag->curtag = 0;
+ else {
+ for (i = 0; !(arg->ui & 1 << i); i++) ;
+ selmon->pertag->curtag = i + 1;
+ }
+ } else {
+ tmptag = selmon->pertag->prevtag;
+ selmon->pertag->prevtag = selmon->pertag->curtag;
+ selmon->pertag->curtag = tmptag;
+ }
+
+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
+
+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
+ togglebar(NULL);
+
focus(NULL);
arrange(selmon);
}
@@ -2165,6 +2280,17 @@ xerrorstart(Display *dpy, XErrorEvent *ee)
}
void
+xrdb(const Arg *arg)
+{
+ loadxrdb();
+ int i;
+ for (i = 0; i < LENGTH(colors); i++)
+ scheme[i] = drw_scm_create(drw, colors[i], 3);
+ focus(NULL);
+ arrange(NULL);
+}
+
+void
zoom(const Arg *arg)
{
Client *c = selmon->sel;
@@ -2188,6 +2314,8 @@ main(int argc, char *argv[])
if (!(dpy = XOpenDisplay(NULL)))
die("dwm: cannot open display");
checkotherwm();
+ XrmInitialize();
+ loadxrdb();
setup();
#ifdef __OpenBSD__
if (pledge("stdio rpath proc exec", NULL) == -1)
@@ -2195,6 +2323,7 @@ main(int argc, char *argv[])
#endif /* __OpenBSD__ */
scan();
run();
+ if(restart) execvp(argv[0], argv);
cleanup();
XCloseDisplay(dpy);
return EXIT_SUCCESS;