8eb0857575f2feef5b2c43bb633eb6bee915fd25
diff --git a/shell/ev-view-private.h b/shell/ev-view-private.h
index a2a2812..c36cd57 100644
--- a/shell/ev-view-private.h
+++ b/shell/ev-view-private.h
@@ -27,6 +27,7 @@
 #include "ev-image.h"
 #include "ev-form-field.h"
 #include "ev-selection.h"
+#include "ev-transition-animation.h"
 
 #define DRAG_HISTORY 10
 
@@ -172,6 +173,8 @@ struct _EvView {
 	/* Goto Popup */
 	GtkWidget *goto_window;
 	GtkWidget *goto_entry;
+
+	EvTransitionAnimation *animation;
 };
 
 struct _EvViewClass {
diff --git a/shell/ev-view.c b/shell/ev-view.c
index 5944e34..4e131e4 100644
--- a/shell/ev-view.c
+++ b/shell/ev-view.c
@@ -42,6 +42,7 @@
 #include "ev-job-queue.h"
 #include "ev-page-cache.h"
 #include "ev-pixbuf-cache.h"
+#include "ev-transition-animation.h"
 #if !GTK_CHECK_VERSION (2, 11, 7)
 #include "ev-tooltip.h"
 #endif
@@ -2479,6 +2480,24 @@ ev_view_expose_event (GtkWidget      *widget,
 	cairo_t *cr;
 	gint     i;
 
+	if (view->animation) {
+		GdkRectangle page_area;
+		GtkBorder    border;
+
+		if (get_page_extents (view, view->current_page, &page_area, &border)) {
+			cr = gdk_cairo_create (view->layout.bin_window);
+
+			/* normalize to x=0, y=0 */
+			cairo_translate (cr, page_area.x, page_area.y);
+			page_area.x = page_area.y = 0;
+
+			ev_transition_animation_paint (view->animation, cr, page_area);
+			cairo_destroy (cr);
+		}
+
+		return TRUE;
+	}
+
 	if (view->presentation) {
 		switch (view->presentation_state) {
 		        case EV_PRESENTATION_END: {
@@ -3725,7 +3744,7 @@ draw_one_page (EvView       *view,
 
 		cairo_save (cr);
 		cairo_translate (cr, overlap.x, overlap.y);
-		
+
 		if (width != page_width || height != page_height) {
 			cairo_pattern_set_filter (cairo_get_source (cr),
 						  CAIRO_FILTER_FAST);
@@ -4205,6 +4224,73 @@ find_changed_cb (EvDocument *document, int page, EvView *view)
 }
 
 static void
+ev_view_change_page (EvView *view,
+		     gint    new_page)
+{
+	gint x, y;
+
+	if (view->current_page == new_page)
+		return;
+
+	view->current_page = new_page;
+	view->pending_scroll = SCROLL_TO_PAGE_POSITION;
+
+	ev_view_presentation_transition_start (view);
+
+	gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
+	ev_view_handle_cursor_over_xy (view, x, y);
+
+	gtk_widget_queue_resize (GTK_WIDGET (view));
+}
+
+static void
+ev_view_transition_animation_finish (EvTransitionAnimation *animation,
+				     EvView                *view)
+{
+	gint new_page;
+
+	new_page = ev_transition_animation_get_page_to (animation);
+
+	g_object_unref (view->animation);
+	view->animation = NULL;
+
+	ev_view_change_page (view, new_page);
+}
+
+static void
+ev_view_transition_animation_frame (EvTransitionAnimation *animation,
+				    gdouble                progress,
+				    EvView                *view)
+{
+	gtk_widget_queue_draw (GTK_WIDGET (view));
+}
+
+static void
+ev_view_presentation_animation_start (EvView *view,
+                                      int     new_page)
+{
+	EvTransitionEffect *effect = NULL;
+
+        if (view->presentation &&
+	    EV_IS_DOCUMENT_TRANSITION (view->document))
+		effect = ev_document_transition_get_effect (EV_DOCUMENT_TRANSITION (view->document),
+							    view->current_page);
+
+	if (effect) {
+		view->animation = ev_transition_animation_new (view->pixbuf_cache, effect, 
+							       view->current_page, new_page);
+		g_signal_connect (view->animation, "frame",
+				  G_CALLBACK (ev_view_transition_animation_frame), view);
+		g_signal_connect (view->animation, "finished",
+				  G_CALLBACK (ev_view_transition_animation_finish), view);
+
+		ev_timeline_start (EV_TIMELINE (view->animation));
+	} else {
+		ev_view_change_page (view, new_page);
+	}
+}
+
+static void
 job_finished_cb (EvPixbufCache *pixbuf_cache,
 		 GdkRegion     *region,
 		 EvView        *view)
@@ -4223,18 +4309,11 @@ page_changed_cb (EvPageCache *page_cache,
 		 EvView      *view)
 {
 	if (view->current_page != new_page) {
-		gint x, y;
-		
-		view->current_page = new_page;
-		view->pending_scroll = SCROLL_TO_PAGE_POSITION;
-
-		if (view->presentation)
-			ev_view_presentation_transition_start (view);
-		
-		gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
-		ev_view_handle_cursor_over_xy (view, x, y);
-		
-		gtk_widget_queue_resize (GTK_WIDGET (view));
+		if (view->presentation) {
+			ev_view_presentation_animation_start (view, new_page);
+		} else {
+			ev_view_change_page (view, new_page);
+		}
 	} else {
 		gtk_widget_queue_draw (GTK_WIDGET (view));
 	}
@@ -4579,9 +4658,15 @@ ev_view_set_presentation (EvView   *view,
 
 	if (presentation)
 		ev_view_presentation_transition_start (view);
-	else
+	else {
 		ev_view_presentation_transition_stop (view);
 
+		if (view->animation) {
+			/* stop any running animation */
+			ev_view_transition_animation_finish (view->animation, view);
+		}
+	}
+
 	if (GTK_WIDGET_REALIZED (view)) {
 		if (view->presentation)
 			gdk_window_set_background (view->layout.bin_window,
@@ -5771,7 +5856,12 @@ ev_view_next_page (EvView *view)
 	     view->presentation_state == EV_PRESENTATION_WHITE)) {
 		ev_view_reset_presentation_state (view);
 		return FALSE; 
-	}	
+	}
+
+	if (view->animation) {
+		ev_view_transition_animation_finish (view->animation, view);
+		return TRUE;
+	}
 
 	ev_view_presentation_transition_stop (view);
 	ev_view_reset_presentation_state (view);
