diff --git a/Makefile b/Makefile
index e7b9c9c..97b23c1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 all: sxiv
 
-VERSION=0.3
+VERSION=git-20110129
 
 CC?=gcc
 PREFIX?=/usr/local
diff --git a/image.c b/image.c
index d6488ef..4673c63 100644
--- a/image.c
+++ b/image.c
@@ -230,7 +230,7 @@ int img_zoom_out(img_t *img) {
 	return 0;
 }
 
-int img_pan(img_t *img, win_t *win, pandir_t dir) {
+int img_move(img_t *img, win_t *win, int dx, int dy) {
 	int ox, oy;
 
 	if (!img || !win)
@@ -239,26 +239,32 @@ int img_pan(img_t *img, win_t *win, pandir_t dir) {
 	ox = img->x;
 	oy = img->y;
 
-	switch (dir) {
-		case PAN_LEFT:
-			img->x += win->w / 5;
-			break;
-		case PAN_RIGHT:
-			img->x -= win->w / 5;
-			break;
-		case PAN_UP:
-			img->y += win->h / 5;
-			break;
-		case PAN_DOWN:
-			img->y -= win->h / 5;
-			break;
-	}
+	img->x += dx;
+	img->y += dy;
 
 	img_check_pan(img, win);
 
 	return ox != img->x || oy != img->y;
 }
 
+int img_pan(img_t *img, win_t *win, pandir_t dir) {
+	if (!img || !win)
+		return 0;
+
+	switch (dir) {
+		case PAN_LEFT:
+			return img_move(img, win, win->w / 5, 0);
+		case PAN_RIGHT:
+			return img_move(img, win, -win->w / 5, 0);
+		case PAN_UP:
+			return img_move(img, win, 0, win->h / 5);
+		case PAN_DOWN:
+			return img_move(img, win, 0, -win->h / 5);
+	}
+
+	return 0;
+}
+
 int img_rotate(img_t *img, win_t *win, int d) {
 	int ox, oy, tmp;
 
diff --git a/image.h b/image.h
index c3f9767..450a739 100644
--- a/image.h
+++ b/image.h
@@ -58,6 +58,7 @@ void img_center(img_t*, win_t*);
 int img_zoom_in(img_t*);
 int img_zoom_out(img_t*);
 
+int img_move(img_t*, win_t*, int, int);
 int img_pan(img_t*, win_t*, pandir_t);
 
 int img_rotate_left(img_t*, win_t*);
diff --git a/main.c b/main.c
index aa21426..df4ef9e 100644
--- a/main.c
+++ b/main.c
@@ -31,6 +31,8 @@
 
 void on_keypress(XEvent*);
 void on_buttonpress(XEvent*);
+void on_buttonrelease(XEvent*);
+void on_motionnotify(XEvent*);
 void on_configurenotify(XEvent*);
 
 void update_title();
@@ -38,6 +40,8 @@ void update_title();
 static void (*handler[LASTEvent])(XEvent*) = {
 	[KeyPress] = on_keypress,
 	[ButtonPress] = on_buttonpress,
+	[ButtonRelease] = on_buttonrelease,
+	[MotionNotify] = on_motionnotify,
 	[ConfigureNotify] = on_configurenotify
 };
 
@@ -49,6 +53,9 @@ int filecnt, fileidx;
 
 unsigned char timeout;
 
+int mox;
+int moy;
+
 #define TITLE_LEN 256
 char win_title[TITLE_LEN];
 
@@ -276,6 +283,11 @@ void on_buttonpress(XEvent *ev) {
 				changed = 1;
 			}
 			break;
+		case Button2:
+			mox = ev->xbutton.x;
+			moy = ev->xbutton.y;
+			win_set_cursor(&win, CURSOR_HAND);
+			break;
 		case Button3:
 			if (fileidx > 0) {
 				img_load(&img, filenames[--fileidx]);
@@ -313,6 +325,31 @@ void on_buttonpress(XEvent *ev) {
 	}
 }
 
+void on_buttonrelease(XEvent *ev) {
+	if (!ev)
+		return;
+
+	if (ev->xbutton.button == Button2)
+		win_set_cursor(&win, CURSOR_ARROW);
+}
+
+void on_motionnotify(XEvent *ev) {
+	XMotionEvent *m;
+
+	if (!ev)
+		return;
+
+	m = &ev->xmotion;
+	
+	if (m->x >= 0 && m->x <= win.w && m->y >= 0 && m->y <= win.h) {
+		if (img_move(&img, &win, m->x - mox, m->y - moy))
+			timeout = 1;
+
+		mox = m->x;
+		moy = m->y;
+	}
+}
+
 void on_configurenotify(XEvent *ev) {
 	if (!ev)
 		return;
diff --git a/window.c b/window.c
index ea86ad3..d5f5f4f 100644
--- a/window.c
+++ b/window.c
@@ -21,12 +21,16 @@
 #include <string.h>
 
 #include <X11/Xutil.h>
+#include <X11/cursorfont.h>
 
 #include "sxiv.h"
 #include "options.h"
 #include "window.h"
 
-GC bgc;
+static Cursor arrow;
+static Cursor hand;
+
+static GC bgc;
 
 void win_open(win_t *win) {
 	win_env_t *e;
@@ -66,8 +70,11 @@ void win_open(win_t *win) {
 	if (win->xwin == None)
 		DIE("could not create window");
 	
-	XSelectInput(e->dpy, win->xwin,
-	             StructureNotifyMask | KeyPressMask | ButtonPressMask);
+	XSelectInput(e->dpy, win->xwin, StructureNotifyMask | KeyPressMask |
+	             ButtonPressMask | ButtonReleaseMask | Button2MotionMask);
+
+	arrow = XCreateFontCursor(e->dpy, XC_left_ptr);
+	hand = XCreateFontCursor(e->dpy, XC_fleur);
 
 	bgc = XCreateGC(e->dpy, win->xwin, 0, None);
 
@@ -91,6 +98,11 @@ void win_close(win_t *win) {
 	if (!win)
 		return;
 
+	XFreeCursor(win->env.dpy, arrow);
+	XFreeCursor(win->env.dpy, hand);
+
+	XFreeGC(win->env.dpy, bgc);
+
 	XDestroyWindow(win->env.dpy, win->xwin);
 	XCloseDisplay(win->env.dpy);
 }
@@ -174,3 +186,18 @@ void win_draw(win_t *win) {
 	XSetWindowBackgroundPixmap(win->env.dpy, win->xwin, win->pm);
 	XClearWindow(win->env.dpy, win->xwin);
 }
+
+void win_set_cursor(win_t *win, win_cur_t cursor) {
+	if (!win)
+		return;
+
+	switch (cursor) {
+		case CURSOR_HAND:
+			XDefineCursor(win->env.dpy, win->xwin, hand);
+			break;
+		case CURSOR_ARROW:
+		default:
+			XDefineCursor(win->env.dpy, win->xwin, arrow);
+			break;
+	}
+}
diff --git a/window.h b/window.h
index 47de1a1..52fd759 100644
--- a/window.h
+++ b/window.h
@@ -23,6 +23,11 @@
 
 #define CLEANMASK(mask) ((mask) & ~LockMask)
 
+typedef enum win_cur_e {
+	CURSOR_ARROW = 0,
+	CURSOR_HAND
+} win_cur_t;
+
 typedef struct win_env_s {
 	Display *dpy;
 	int scr;
@@ -59,4 +64,6 @@ void win_toggle_fullscreen(win_t*);
 void win_clear(win_t*);
 void win_draw(win_t*);
 
+void win_set_cursor(win_t*, win_cur_t);
+
 #endif /* WINDOW_H */