diff --git a/src/eog-scroll-view.c b/src/eog-scroll-view.c
index bb4d4e0..482fb9d 100644
--- a/src/eog-scroll-view.c
+++ b/src/eog-scroll-view.c
@@ -123,6 +123,11 @@ struct _EogScrollViewPrivate {
 	int drag_ofs_x, drag_ofs_y;
 	guint dragging : 1;
 
+	/* multiple pointer interaction */
+	guint multidevice : 1;
+	GtkDeviceGroup *device_group;
+	gdouble distance;
+
 	/* status of progressive loading */
 	ProgressiveState progressive_state;
 
@@ -1254,9 +1259,14 @@ eog_scroll_view_button_press_event (GtkWidget *widget, GdkEventButton *event, gp
 	if (!gtk_widget_has_focus (priv->display))
 		gtk_widget_grab_focus (GTK_WIDGET (priv->display));
 
+	gtk_device_group_add_device (priv->device_group, event->device);
+
 	if (priv->dragging)
 		return FALSE;
 
+	if (priv->multidevice)
+		return FALSE;
+
 	switch (event->button) {
 		case 1:
 		case 2:
@@ -1302,10 +1312,17 @@ eog_scroll_view_button_release_event (GtkWidget *widget, GdkEventButton *event,
 {
 	EogScrollView *view;
 	EogScrollViewPrivate *priv;
+	GList *devices;
 
 	view = EOG_SCROLL_VIEW (data);
 	priv = view->priv;
 
+	gtk_device_group_remove_device (priv->device_group, event->device);
+	devices = gtk_device_group_get_devices (priv->device_group);
+
+	if (g_list_length (devices) > 0)
+		return FALSE;
+
 	if (!priv->dragging)
 		return FALSE;
 
@@ -1397,32 +1414,69 @@ eog_scroll_view_scroll_event (GtkWidget *widget, GdkEventScroll *event, gpointer
 	return TRUE;
 }
 
-/* Motion event handler for the image view */
-static gboolean
-eog_scroll_view_motion_event (GtkWidget *widget, GdkEventMotion *event, gpointer data)
+static void
+eog_scroll_view_multidevice_event (GtkWidget *widget, GtkDeviceGroup *group, GtkMultiDeviceEvent *event, gpointer data)
 {
 	EogScrollView *view;
 	EogScrollViewPrivate *priv;
-	gint x, y;
-	GdkModifierType mods;
+	gdouble distance, x, y;
+	gdouble zoom_factor;
 
 	view = EOG_SCROLL_VIEW (data);
 	priv = view->priv;
 
-	if (!priv->dragging)
-		return FALSE;
+	if (event->n_events == 1) {
+		if (event->type == GTK_EVENT_DEVICE_REMOVED)
+			priv->multidevice = FALSE;
 
-	if (event->is_hint)
-		gdk_window_get_pointer (gtk_widget_get_window (GTK_WIDGET (priv->display)), &x, &y, &mods);
-	else {
-		x = event->x;
-		y = event->y;
-	}
+		if (!gdk_event_get_coords ((GdkEvent *) event->events[0], &x, &y))
+			return;
 
-	drag_to (view, x, y);
-	return TRUE;
+		if ((event->type == GTK_EVENT_DEVICE_ADDED ||
+		     event->type == GTK_EVENT_DEVICE_REMOVED) &&
+		    is_image_movable (view)) {
+			priv->dragging = TRUE;
+
+			/* Reset drag anchor */
+			priv->drag_anchor_x = x;
+			priv->drag_anchor_y = y;
+
+			priv->drag_ofs_x = priv->xofs;
+			priv->drag_ofs_y = priv->yofs;
+		}
+
+		drag_to (view, (gint) x, (gint) y);
+	} else if (event->n_events == 2) {
+		if (event->type == GTK_EVENT_DEVICE_ADDED)
+			priv->multidevice = TRUE;
+
+		if (!gdk_events_get_distance ((GdkEvent *) event->events[0],
+					      (GdkEvent *) event->events[1],
+					      &distance))
+			return;
+
+		if (!gdk_events_get_center ((GdkEvent *) event->events[0],
+					    (GdkEvent *) event->events[1],
+					    &x, &y))
+			return;
+
+		if (event->type == GTK_EVENT_DEVICE_ADDED) {
+			/* Second device was just added, only save initial distance */
+			priv->distance = distance;
+			return;
+		}
+
+		zoom_factor = distance / priv->distance;
+
+		set_zoom (view, priv->zoom * zoom_factor,
+			  TRUE, (gint) x, (gint) y);
+
+		priv->distance = distance;
+		priv->multidevice = TRUE;
+	}
 }
 
+
 static void
 display_map_event (GtkWidget *widget, GdkEvent *event, gpointer data)
 {
@@ -2149,10 +2203,14 @@ eog_scroll_view_new (void)
 	/* We don't want to be double-buffered as we are SuperSmart(tm) */
 	gtk_widget_set_double_buffered (GTK_WIDGET (priv->display), FALSE);
 
+	gtk_widget_set_support_multidevice (priv->display, TRUE);
+	priv->device_group = gtk_widget_create_device_group (priv->display);
+
 	gtk_widget_add_events (GTK_WIDGET (priv->display),
 			       GDK_EXPOSURE_MASK
 			       | GDK_BUTTON_PRESS_MASK
 			       | GDK_BUTTON_RELEASE_MASK
+			       | GDK_BUTTON_MOTION_MASK
 			       | GDK_POINTER_MOTION_MASK
 			       | GDK_POINTER_MOTION_HINT_MASK
 			       | GDK_SCROLL_MASK
@@ -2161,11 +2219,11 @@ eog_scroll_view_new (void)
 	g_signal_connect (G_OBJECT (priv->display), "expose_event", G_CALLBACK (display_expose_event), view);
 	g_signal_connect (G_OBJECT (priv->display), "map_event", G_CALLBACK (display_map_event), view);
 	g_signal_connect (G_OBJECT (priv->display), "button_press_event", G_CALLBACK (eog_scroll_view_button_press_event), view);
-	g_signal_connect (G_OBJECT (priv->display), "motion_notify_event", G_CALLBACK (eog_scroll_view_motion_event), view);
 	g_signal_connect (G_OBJECT (priv->display), "button_release_event", G_CALLBACK (eog_scroll_view_button_release_event), view);
 	g_signal_connect (G_OBJECT (priv->display), "scroll_event", G_CALLBACK (eog_scroll_view_scroll_event), view);
 	g_signal_connect (G_OBJECT (priv->display), "focus_in_event", G_CALLBACK (eog_scroll_view_focus_in_event), NULL);
 	g_signal_connect (G_OBJECT (priv->display), "focus_out_event", G_CALLBACK (eog_scroll_view_focus_out_event), NULL);
+	g_signal_connect (G_OBJECT (priv->display), "multidevice-event", G_CALLBACK (eog_scroll_view_multidevice_event), view);
 
 	g_signal_connect (G_OBJECT (widget), "key_press_event", G_CALLBACK (display_key_press_event), view);
 
diff --git a/src/main.c b/src/main.c
index c37dd32..de12f06 100644
--- a/src/main.c
+++ b/src/main.c
@@ -182,6 +182,8 @@ main (int argc, char **argv)
 
 	gtk_rc_parse (EOG_DATA_DIR G_DIR_SEPARATOR_S "gtkrc");
 
+	gdk_enable_multidevice ();
+
 	ctx = g_option_context_new (NULL);
 	g_option_context_add_main_entries (ctx, goption_options, PACKAGE);
 	/* Option groups are free'd together with the context 
