diff --git a/TODO b/TODO
index 7b87fba..fadb409 100644
--- a/TODO
+++ b/TODO
@@ -2,5 +2,4 @@
 - add some useful command line options
 - write man page
 - toggle aliasing
-- fullscreen mode
 - view all images in directories (recursive mode)
diff --git a/main.c b/main.c
index a73fbf2..fca12e8 100644
--- a/main.c
+++ b/main.c
@@ -218,6 +218,11 @@ void on_keypress(XEvent *ev) {
 		case 'l':
 			changed = img_pan(&img, &win, PAN_RIGHT);
 			break;
+
+		/* change window state */
+		case 'f':
+			win_toggle_fullscreen(&win);
+			break;
 	}
 
 	if (changed) {
diff --git a/window.c b/window.c
index 752f045..516f862 100644
--- a/window.c
+++ b/window.c
@@ -18,17 +18,19 @@
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 
 #include <X11/Xutil.h>
 
 #include "sxiv.h"
 #include "window.h"
 
+GC bgc;
+
 void win_open(win_t *win) {
 	win_env_t *e;
 	XClassHint *classhint;
 	XColor bgcol;
-	XGCValues gcval;
 
 	if (!win)
 		return;
@@ -48,6 +50,9 @@ void win_open(win_t *win) {
 		                    &bgcol, &bgcol))
 		DIE("could not allocate color: %s", BG_COLOR);
 
+	win->bgcol = bgcol.pixel;
+	win->pm = 0;
+
 	win->w = WIN_WIDTH;
 	win->h = WIN_HEIGHT;
 	if (win->w > e->scrw)
@@ -66,9 +71,7 @@ void win_open(win_t *win) {
 	XSelectInput(e->dpy, win->xwin,
 	             StructureNotifyMask | KeyPressMask);
 
-	gcval.foreground = bgcol.pixel;
-	win->bgc = XCreateGC(e->dpy, win->xwin, GCForeground, &gcval);
-	win->pm = 0;
+	bgc = XCreateGC(e->dpy, win->xwin, 0, None);
 
 	win_set_title(win, "sxiv");
 
@@ -119,8 +122,34 @@ int win_configure(win_t *win, XConfigureEvent *c) {
 	return changed;
 }
 
+void win_toggle_fullscreen(win_t *win) {
+	XEvent ev;
+	XClientMessageEvent *cm;
+
+	if (!win)
+		return;
+
+	win->fullscreen ^= 1;
+
+	memset(&ev, 0, sizeof(ev));
+	ev.type = ClientMessage;
+
+	cm = &ev.xclient;
+	cm->window = win->xwin;
+	cm->message_type = XInternAtom(win->env.dpy, "_NET_WM_STATE", False);
+	cm->format = 32;
+	cm->data.l[0] = win->fullscreen;
+	cm->data.l[1] = XInternAtom(win->env.dpy, "_NET_WM_STATE_FULLSCREEN", False);
+	cm->data.l[2] = XInternAtom(win->env.dpy, "_NET_WM_STATE_ABOVE", False);
+	cm->data.l[3] = 0;
+
+	XSendEvent(win->env.dpy, DefaultRootWindow(win->env.dpy), False,
+	           SubstructureNotifyMask, &ev);
+}
+
 void win_clear(win_t *win) {
 	win_env_t *e;
+	XGCValues gcval;
 
 	if (!win)
 		return;
@@ -130,7 +159,11 @@ void win_clear(win_t *win) {
 	if (win->pm)
 		XFreePixmap(e->dpy, win->pm);
 	win->pm = XCreatePixmap(e->dpy, win->xwin, e->scrw, e->scrh, e->depth);
-	XFillRectangle(e->dpy, win->pm, win->bgc, 0, 0, e->scrw, e->scrh);
+
+	gcval.foreground = win->fullscreen ? BlackPixel(e->dpy, e->scr) : win->bgcol;
+	XChangeGC(e->dpy, bgc, GCForeground, &gcval);
+
+	XFillRectangle(e->dpy, win->pm, bgc, 0, 0, e->scrw, e->scrh);
 }
 
 void win_draw(win_t *win) {
diff --git a/window.h b/window.h
index 38d8091..79b5787 100644
--- a/window.h
+++ b/window.h
@@ -33,7 +33,8 @@ typedef struct win_env_s {
 typedef struct win_s {
 	Window xwin;
 	win_env_t env;
-	GC bgc;
+
+	unsigned long bgcol;
 	Pixmap pm;
 
 	int w;
@@ -51,6 +52,7 @@ void win_close(win_t*);
 void win_set_title(win_t*, const char*);
 
 int win_configure(win_t*, XConfigureEvent*);
+void win_toggle_fullscreen(win_t*);
 
 void win_clear(win_t*);
 void win_draw(win_t*);