diff --git a/README.md b/README.md
index fced5f8..36c335b 100644
--- a/README.md
+++ b/README.md
@@ -41,8 +41,19 @@ Use the following keys to control sxiv:
     [/]          Go 10 images backward/forward
     +,=          Zoom in
     -            Zoom out
-    h,j,k,l      Scroll left/down/up/right
+    h,j,k,l      Pan image left/down/up/right
     <,>          Rotate image (counter-)clockwise by 90 degrees
     f            Toggle fullscreen mode (requires an EWMH/NetWM compliant
                  window manager)
     a            Toggle anti-aliasing
+
+Additionally, sxiv can be controlled via the following mouse commands:
+
+    Button1           Go to the next image
+    Button3           Go to the previous image
+    ScrollUp          Pan image up
+    ScrollDown        Pan image down
+    Shift+ScrollUp    Pan image left
+    Shift+ScrollDown  Pan image right
+    Ctrl+ScrollUp     Zoom in
+    Ctrl+ScrollDown   Zoom out
diff --git a/TODO b/TODO
index 7653411..8b6d11e 100644
--- a/TODO
+++ b/TODO
@@ -1,3 +1,2 @@
-- mouse scrolling and zooming
 - add some useful command line options
 - view all images in directories (recursive mode)
diff --git a/main.c b/main.c
index ad2d4a4..7d1e682 100644
--- a/main.c
+++ b/main.c
@@ -30,14 +30,14 @@
 #include "window.h"
 
 void on_keypress(XEvent*);
-void on_configurenotify(XEvent*);
 void on_buttonpress(XEvent*);
+void on_configurenotify(XEvent*);
 
 void update_title();
 
 static void (*handler[LASTEvent])(XEvent*) = {
-	[ButtonPress] = on_buttonpress,
 	[KeyPress] = on_keypress,
+	[ButtonPress] = on_buttonpress,
 	[ConfigureNotify] = on_configurenotify
 };
 
@@ -128,31 +128,6 @@ void cleanup() {
 	}
 }
 
-void on_buttonpress(XEvent *ev) {
-	int changed;
-	XButtonEvent *buttonevent;
-
-	changed = 0;
-	buttonevent = &ev->xbutton;
-
-	switch (buttonevent->button) {
-		case Button4:
-			changed = img_zoom_in(&img);
-			break;
-		case Button5:
-			changed = img_zoom_out(&img);
-			break;
-		default:
-			return;
-	}
-
-	if (changed) {
-		img_render(&img, &win);
-		update_title();
-		timeout = 0;
-	}
-}
-
 void on_keypress(XEvent *ev) {
 	char key;
 	KeySym keysym;
@@ -272,6 +247,60 @@ void on_keypress(XEvent *ev) {
 	}
 }
 
+void on_buttonpress(XEvent *ev) {
+	int changed;
+	unsigned int mask;
+
+	if (!ev)
+		return;
+
+	mask = CLEANMASK(ev->xbutton.state);
+	changed = 0;
+
+	switch (ev->xbutton.button) {
+		case Button1:
+			if (fileidx + 1 < filecnt) {
+				img_load(&img, filenames[++fileidx]);
+				changed = 1;
+			}
+			break;
+		case Button3:
+			if (fileidx > 0) {
+				img_load(&img, filenames[--fileidx]);
+				changed = 1;
+			}
+			break;
+		case Button4:
+			if (mask == ControlMask)
+				changed = img_zoom_in(&img);
+			else if (mask == ShiftMask)
+				changed = img_pan(&img, &win, PAN_LEFT);
+			else
+				changed = img_pan(&img, &win, PAN_UP);
+			break;
+		case Button5:
+			if (mask == ControlMask)
+				changed = img_zoom_out(&img);
+			else if (mask == ShiftMask)
+				changed = img_pan(&img, &win, PAN_RIGHT);
+			else
+				changed = img_pan(&img, &win, PAN_DOWN);
+			break;
+		case 6:
+			changed = img_pan(&img, &win, PAN_LEFT);
+			break;
+		case 7:
+			changed = img_pan(&img, &win, PAN_RIGHT);
+			break;
+	}
+
+	if (changed) {
+		img_render(&img, &win);
+		update_title();
+		timeout = 0;
+	}
+}
+
 void on_configurenotify(XEvent *ev) {
 	if (!ev)
 		return;
diff --git a/sxiv.1 b/sxiv.1
index 3299cb1..14e34c5 100644
--- a/sxiv.1
+++ b/sxiv.1
@@ -26,7 +26,7 @@ Quit sxiv.
 .TP
 .B Escape
 Quit sxiv and return an exit value of 2.
-.SS Navigate image list 
+.SS Navigate image list
 .TP
 .BR Space ", " n
 Go to the next image.
@@ -80,6 +80,34 @@ Toggle fullscreen mode.
 .TP
 .B a
 Toggle anti-aliasing.
+.SH MOUSE COMMANDS
+.SS Navigate image list
+.TP
+.B Button1
+Go to the next image.
+.TP
+.B Button3
+Go to the previous image.
+.SS Zooming
+.TP
+.B Ctrl+ScrollUp
+Zoom in.
+.TP
+.B Ctrl+ScrollDown
+Zoom out.
+.SS Panning
+.TP
+.B ScrollUp
+Pan up.
+.TP
+.B ScrollDown
+Pan down.
+.TP
+.B Shift+ScrollUp
+Pan left.
+.TP
+.B Shift+ScrollDown
+Pan right.
 .SH AUTHORS
 .TP
 Bert Muennich <ber.t at gmx.com>
@@ -87,4 +115,5 @@ Bert Muennich <ber.t at gmx.com>
 .TP
 http://github.com/muennich/sxiv
 .SH SEE ALSO
-.BR feh (1), qiv (1)
+.BR feh (1),
+.BR qiv (1)
diff --git a/window.h b/window.h
index 79b5787..36e15ef 100644
--- a/window.h
+++ b/window.h
@@ -21,6 +21,8 @@
 
 #include <X11/Xlib.h>
 
+#define CLEANMASK(mask) ((mask) & ~LockMask)
+
 typedef struct win_env_s {
 	Display *dpy;
 	int scr;