diff --git a/dwm.c b/dwm.c
--- a/dwm.c
+++ b/dwm.c
@@ -90,8 +90,10 @@
 	int oldx, oldy, oldw, oldh;
 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
 	int bw, oldbw;
+	int expandx1, expandx2, expandy1, expandy2;
+	unsigned char expandmask;
 	unsigned int tags;
-	Bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
+	Bool isfixed, wasfloating, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
 	Client *next;
 	Client *snext;
 	Monitor *mon;
@@ -1158,6 +1160,8 @@
 	updatewmhints(c);
 	XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
 	grabbuttons(c, False);
+	c->wasfloating = False;
+	c->expandmask = 0;
 	if(!c->isfloating)
 		c->isfloating = c->oldstate = trans != None || c->isfixed;
 	if(c->isfloating)
@@ -1367,6 +1371,7 @@
 	c->oldy = c->y; c->y = wc.y = y;
 	c->oldw = c->w; c->w = wc.width = w;
 	c->oldh = c->h; c->h = wc.height = h;
+	c->expandmask = 0;
 	wc.border_width = c->bw;
 	XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
 	configure(c);
diff --git a/exresize.c b/exresize.c
new file mode 100644
--- /dev/null
+++ b/exresize.c
@@ -0,0 +1,193 @@
+#define EXPAND_LEFT  (1 << 0)
+#define EXPAND_RIGHT (1 << 2)
+#define EXPAND_UP    (1 << 4)
+#define EXPAND_DOWN  (1 << 6)
+
+#define IS_SET(q, w) ((q & w) != 0)
+#define IS_FORCED(q, w) IS_SET((q << 1), w)
+
+#define EXPANDALL       (EXPAND_LEFT | EXPAND_RIGHT | EXPAND_UP | EXPAND_DOWN)
+#define UNEXPAND       (EXPANDALL << 1) // Force all directions to 0
+#define FORCE_EXPANDALL ~0 // Force expand in all directions
+
+enum { EX_NW, EX_N, EX_NE, EX_W, EX_C, EX_E, EX_SW, EX_S, EX_SE };
+
+void expand(unsigned char mask);
+
+void togglemaximize(const Arg *arg);
+void toggleverticalexpand(const Arg *arg);
+void togglehorizontalexpand(const Arg *arg);
+void exresize(const Arg *arg);
+void explace(const Arg *arg);
+
+void
+exresize(const Arg *arg) {
+	Client *c;
+	int x, y, nx, ny, nw, nh;
+	c = selmon->sel;
+
+	if (!c || !arg) return;
+	if (selmon->lt[selmon->sellt]->arrange && !c->isfloating)
+		togglefloating(NULL);
+	if (c->expandmask != 0)
+		expand(UNEXPAND);
+
+	x = ((int *)arg->v)[0];
+	y = ((int *)arg->v)[1];
+
+	nw = MIN(selmon->ww - c->bw*2, c->w + x);
+	nh = MIN(selmon->wh - c->bw*2, c->h + y);
+	nx = c->x - x/2;
+	ny = c->y - y/2;
+
+	if (!((abs(c->x + c->w/2 - (selmon->wx + selmon->ww/2)) < snap) &&
+				(abs(c->y + c->h/2 - (selmon->wy + selmon->wh/2)) < snap))) {
+		if ((nw == selmon->ww) || 
+				(nx < selmon->wx) ||
+				(abs(selmon->wx - c->x) < snap))
+			nx = selmon->wx;
+		else if ((nx+nw > (selmon->wx + selmon->ww)) || 
+				(abs((selmon->wx + selmon->ww) - (c->x + c->w)) < snap))
+			nx = (selmon->wx + selmon->ww) - nw - c->bw*2;
+
+		if ((nh == selmon->wh) || 
+				(ny < selmon->wy) ||
+				(abs(selmon->wy - c->y) < snap))
+			ny = selmon->wy;
+		else if ((ny+nh > (selmon->wy + selmon->wh)) ||
+				(abs((selmon->wy + selmon->wh) - (c->y + c->h)) < snap))
+			ny = (selmon->wy + selmon->wh) - nh - c->bw*2;
+	} else {
+		nx = selmon->wx + selmon->ww/2 - nw/2;
+		ny = selmon->wy + selmon->wh/2 - nh/2;
+	}
+
+	resizeclient(c, nx, ny, MAX(nw, 32), MAX(nh, 32));
+	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2);
+}
+
+void
+explace(const Arg *arg) {
+	Client *c;
+	int nx, ny;
+
+	c = selmon->sel;
+	if (!c || (arg->ui >= 9)) return;
+	if (selmon->lt[selmon->sellt]->arrange && !c->isfloating)
+		togglefloating(NULL);
+
+	nx = (arg->ui % 3) - 1;
+	ny = (arg->ui / 3) - 1;
+
+	if (nx < 0) nx = selmon->wx;
+	else if (nx > 0) nx = selmon->wx + selmon->ww - c->w - c->bw*2;
+	else nx = selmon->wx + selmon->ww/2 - c->w/2;
+
+	if (ny < 0) ny = selmon->wy;
+	else if (ny > 0) ny = selmon->wy + selmon->wh - c->h - c->bw*2;
+	else ny = selmon->wy + selmon->wh/2 - c->h/2;
+
+	resize(c, nx, ny, c->w, c->h, True);
+	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2);
+}
+
+int
+calculate_expand(unsigned char mask, unsigned char curmask,
+		unsigned char *newmask, unsigned char key,
+		int *reset_value, int new_reset_value,
+		int max_value, int old_value) {
+	if (IS_SET(key, mask) ||
+			(IS_SET(key, curmask) && (!IS_SET(key, mask) && IS_FORCED(key, mask))) ||
+			(!IS_SET(key, curmask) && (IS_SET(key, mask) && IS_FORCED(key, mask)))) {
+
+		if (IS_SET(key, mask) && (!IS_SET(key,curmask) || IS_FORCED(key,mask)))
+		{
+			if (!IS_SET(key, curmask))
+				*reset_value = new_reset_value;
+			*newmask |= key;
+			return max_value;
+		} else if ((IS_SET(key,curmask) && IS_SET(key, mask)) ||
+				(!IS_SET(key, mask) && IS_FORCED(key, mask))) {
+			*newmask &= ~key;
+			return *reset_value;
+		} else {
+			*newmask &= ~key;
+			return old_value;
+		}
+	} else
+		return new_reset_value;
+}
+
+void
+expand(unsigned char mask) {
+	XEvent ev;
+	int nx1, ny1, nx2, ny2;
+	unsigned char curmask;
+	unsigned char newmask;
+
+	if(!selmon->sel || selmon->sel->isfixed)
+		return;
+	XRaiseWindow(dpy, selmon->sel->win);
+	newmask = curmask = selmon->sel->expandmask;
+
+	if (curmask == 0) {
+		if(!selmon->lt[selmon->sellt]->arrange || selmon->sel->isfloating)
+			selmon->sel->wasfloating = True;
+		else {
+			togglefloating(NULL);
+			selmon->sel->wasfloating = False;
+		}
+	}
+
+	nx1 = calculate_expand(mask, curmask, &newmask,
+			EXPAND_LEFT, &selmon->sel->expandx1,
+			selmon->sel->x,
+			selmon->wx,
+			selmon->sel->oldx);
+	nx2 = calculate_expand(mask, curmask, &newmask,
+			EXPAND_RIGHT, &selmon->sel->expandx2,
+			selmon->sel->x + selmon->sel->w,
+			selmon->wx + selmon->ww - 2*borderpx,
+			selmon->sel->oldw + selmon->sel->x);
+	ny1 = calculate_expand(mask, curmask, &newmask,
+			EXPAND_UP, &selmon->sel->expandy1,
+			selmon->sel->y,
+			selmon->wy,
+			selmon->sel->oldy);
+	ny2 = calculate_expand(mask, curmask, &newmask,
+			EXPAND_DOWN, &selmon->sel->expandy2,
+			selmon->sel->y + selmon->sel->h,
+			selmon->wy + selmon->wh - 2*borderpx,
+			selmon->sel->oldh + selmon->sel->y);
+
+
+	resizeclient(selmon->sel, nx1, ny1, MAX(nx2-nx1, 32), MAX(ny2-ny1, 32));
+
+	if ((newmask == 0) && (!selmon->sel->wasfloating))
+		togglefloating(NULL);
+	selmon->sel->expandmask = newmask;
+	drawbar(selmon);
+	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
+}
+
+void
+togglemaximize(const Arg *arg) {
+	if (arg->i > 0) expand(FORCE_EXPANDALL);
+	else if (arg->i < 0) expand(UNEXPAND);
+	else expand(EXPANDALL);
+}
+
+void
+toggleverticalexpand(const Arg *arg) {
+	if (arg->i < 0) expand(EXPAND_DOWN);
+	else if (arg->i > 0) expand(EXPAND_UP);
+	else expand(EXPAND_DOWN | EXPAND_UP);
+}
+
+void
+togglehorizontalexpand(const Arg *arg) {
+	if (arg->i < 0) expand(EXPAND_LEFT);
+	else if (arg->i > 0) expand(EXPAND_RIGHT);
+	else expand(EXPAND_LEFT | EXPAND_RIGHT);
+}
+
