? birnan
? sms
? dvi/dviviewer
? dvi/fest.aux
? dvi/fest.dvi
? dvi/fest.log
? dvi/dvilib/Makefile
? dvi/dvilib/Makefile.in
? help/el/.xml2po.mo
? help/el/evince.xml
? help/uk/.xml2po.mo
? help/uk/evince.xml
? pdf/fofi/Makefile
? pdf/fofi/Makefile.in
? pdf/goo/Makefile
? pdf/goo/Makefile.in
? pdf/splash/Makefile
? pdf/splash/Makefile.in
? pdf/xpdf/Makefile
? pdf/xpdf/Makefile.in
? pdf/xpdf/test-gdk-output-dev
? shell/birnan
? shell/blah
? shell/core.6202
? shell/smooth-scroll-2.patch
? shell/smoothscroll-1.patch
? shell/smoothscroll-3.patch
? shell/smoothscroll-4.patch
Index: shell/ev-pixbuf-cache.c
===================================================================
RCS file: /cvs/gnome/evince/shell/ev-pixbuf-cache.c,v
retrieving revision 1.18
diff -u -p -u -r1.18 ev-pixbuf-cache.c
--- shell/ev-pixbuf-cache.c	6 Aug 2005 18:14:24 -0000	1.18
+++ shell/ev-pixbuf-cache.c	2 Sep 2005 22:00:56 -0000
@@ -7,6 +7,7 @@ typedef struct _CacheJobInfo
 {
 	EvJob *job;
 	GdkPixbuf *pixbuf;
+	GdkPixmap *pixmap;
 	EvRenderContext *rc;
 	GList *link_mapping;
 	GdkRegion *text_mapping;
@@ -144,6 +145,10 @@ dispose_cache_job_info (CacheJobInfo *jo
 		g_object_unref (G_OBJECT (job_info->pixbuf));
 		job_info->pixbuf = NULL;
 	}
+	if (job_info->pixmap) {
+		g_object_unref (G_OBJECT (job_info->pixmap));
+		job_info->pixmap = NULL;
+	}
 	if (job_info->link_mapping) {
 		ev_link_mapping_free (job_info->link_mapping);
 		job_info->link_mapping = NULL;
@@ -198,6 +203,34 @@ ev_pixbuf_cache_new (GtkWidget  *view,
 	return pixbuf_cache;
 }
 
+static GdkPixmap *
+create_pixmap_from_pixbuf (GdkWindow *window,
+			   GdkPixbuf *pixbuf)
+{
+	GdkPixmap *pixmap;
+	int width;
+	int height;
+	
+	if (!window)
+		return NULL;
+
+#if 0
+	g_print ("generating pixmap\n");
+#endif
+	
+	width = gdk_pixbuf_get_width (pixbuf);
+	height = gdk_pixbuf_get_height (pixbuf);
+	
+	pixmap = gdk_pixmap_new (window, width, height, -1);
+
+	g_assert (pixmap);
+
+	gdk_draw_pixbuf (pixmap, NULL, pixbuf, 0, 0, 0, 0, -1, -1,
+			 GDK_RGB_DITHER_NORMAL, 0, 0);
+
+	return pixmap;
+}
+
 static void
 job_finished_cb (EvJob         *job,
 		 EvPixbufCache *pixbuf_cache)
@@ -218,7 +251,13 @@ job_finished_cb (EvJob         *job,
 	pixbuf = g_object_ref (job_render->pixbuf);
 	if (job_info->pixbuf)
 		g_object_unref (job_info->pixbuf);
+	if (job_info->pixmap)
+		g_object_unref (job_info->pixmap);
+	
 	job_info->pixbuf = pixbuf;
+	job_info->pixmap = create_pixmap_from_pixbuf (pixbuf_cache->view->window, job_info->pixbuf);
+	if (job_info->pixbuf)
+		g_assert (job_info->pixmap);
 
 	if (job_render->link_mapping) {
 		if (job_info->link_mapping)
@@ -428,6 +467,8 @@ copy_job_to_job_info (EvJobRender   *job
 	dispose_cache_job_info (job_info, pixbuf_cache);
 
 	job_info->pixbuf = pixbuf;
+	job_info->pixmap = create_pixmap_from_pixbuf (pixbuf_cache->view->window, job_info->pixbuf);
+	
 	if (job_render->link_mapping)
 		job_info->link_mapping = job_render->link_mapping;
 	if (job_render->text_mapping)
@@ -653,6 +694,25 @@ ev_pixbuf_cache_get_pixbuf (EvPixbufCach
 	}
 
 	return job_info->pixbuf;
+}
+
+GdkPixmap *
+ev_pixbuf_cache_get_pixmap (EvPixbufCache *pixbuf_cache,
+			    gint	   page)
+{
+	CacheJobInfo *job_info;
+
+	job_info = find_job_cache (pixbuf_cache, page);
+	if (job_info == NULL)
+		return NULL;
+
+	/* We don't need to wait for the idle to handle the callback */
+	if (job_info->job &&
+	    EV_JOB (job_info->job)->finished) {
+		copy_job_to_job_info (EV_JOB_RENDER (job_info->job), job_info, pixbuf_cache);
+	}
+
+	return job_info->pixmap;
 }
 
 GList *
Index: shell/ev-pixbuf-cache.h
===================================================================
RCS file: /cvs/gnome/evince/shell/ev-pixbuf-cache.h,v
retrieving revision 1.9
diff -u -p -u -r1.9 ev-pixbuf-cache.h
--- shell/ev-pixbuf-cache.h	6 Aug 2005 05:13:20 -0000	1.9
+++ shell/ev-pixbuf-cache.h	2 Sep 2005 22:00:56 -0000
@@ -59,6 +59,8 @@ void           ev_pixbuf_cache_set_page_
 						     GList          *selection_list);
 GdkPixbuf     *ev_pixbuf_cache_get_pixbuf           (EvPixbufCache *pixbuf_cache,
 						     gint           page);
+GdkPixmap     *ev_pixbuf_cache_get_pixmap           (EvPixbufCache *pixbuf_cache,
+						     gint	    page);
 GList         *ev_pixbuf_cache_get_link_mapping     (EvPixbufCache *pixbuf_cache,
 						     gint           page);
 GdkRegion     *ev_pixbuf_cache_get_text_mapping     (EvPixbufCache *pixbuf_cache,
Index: shell/ev-view.c
===================================================================
RCS file: /cvs/gnome/evince/shell/ev-view.c,v
retrieving revision 1.150
diff -u -p -u -r1.150 ev-view.c
--- shell/ev-view.c	26 Aug 2005 04:25:41 -0000	1.150
+++ shell/ev-view.c	2 Sep 2005 22:00:56 -0000
@@ -99,6 +99,17 @@ typedef enum {
 #define MIN_SCALE 0.05409
 #define MAX_SCALE 4.0
 
+/* Information for smooth scrolling */
+typedef struct {
+	GTimer *timer;
+	int idle_id;
+	int start_x;
+	int start_y;
+	int target_x;
+	int target_y;
+	EvView *view;
+} SmoothScrollInfo;
+
 /* Information for middle clicking and moving around the doc */
 typedef struct {
         gboolean in_drag;
@@ -135,6 +146,8 @@ struct _EvView {
 	gint scroll_x;
 	gint scroll_y;
 
+	SmoothScrollInfo *smooth_scroll;
+
 	/* Information for middle clicking and dragging around. */
 	DragInfo drag_info;
 
@@ -1327,10 +1340,135 @@ ev_view_unrealize (GtkWidget *widget)
 	GTK_WIDGET_CLASS (ev_view_parent_class)->unrealize (widget);
 }
 
+static void
+destroy_smooth_scroll (SmoothScrollInfo *smooth_scroll)
+{
+	if (!smooth_scroll)
+		return;
+	
+	g_timer_destroy (smooth_scroll->timer);
+	if (smooth_scroll->idle_id)
+		g_source_remove (smooth_scroll->idle_id);
+	smooth_scroll->view->smooth_scroll = NULL;
+	g_free (smooth_scroll);
+}
+
+static int
+interpolate (int start, int end, double fraction)
+{
+       return start + (end - start) * fraction;
+}
+
+#define SCROLL_TIME 0.1
+
+#include <gdk/gdkx.h>
+
+static void
+graphics_sync (GdkWindow *window)
+{
+	if (window)
+	{
+		XImage *image;
+		
+		image = XGetImage (GDK_WINDOW_XDISPLAY (window),
+				   GDK_WINDOW_XID (window),
+				   0, 0, 1, 1,
+				   AllPlanes, ZPixmap);
+		
+		XDestroyImage (image);
+	}
+}
+
+static gboolean
+update_smooth_scroll (gpointer data)
+{
+	SmoothScrollInfo *info = data;
+	double fraction;
+	int new_x, new_y;
+
+	fraction = g_timer_elapsed (info->timer, NULL);
+	fraction /= SCROLL_TIME;
+
+	new_x = interpolate (info->start_x,
+			     info->target_x,
+			     fraction);
+
+	new_y = interpolate (info->start_y,
+			     info->target_y,
+			     fraction);
+
+	if (info->view->hadjustment) {
+		gtk_adjustment_set_value (info->view->hadjustment,
+					  new_x);
+	}
+	
+	if (info->view->vadjustment) {
+#if 0
+		if (new_y != info->view->scroll_y)
+			g_print ("yep\n");
+		g_print ("value before: %f\n", info->view->vadjustment->value);
+#endif
+		gtk_adjustment_set_value (info->view->vadjustment,
+					  new_y);
+		graphics_sync (GTK_WIDGET (info->view)->window);
+	}
+
+	if (fraction <= 1.0) {
+		return TRUE;
+	} else {
+		destroy_smooth_scroll (info);
+		return FALSE;
+	}
+}
+
+static SmoothScrollInfo *
+reset_smooth_scroll (SmoothScrollInfo	*info,
+		     EvView		*view,
+		     int		 dx,
+		     int		 dy)
+{
+	
+	if (!info) {
+		info = g_new0 (SmoothScrollInfo, 1);
+		info->timer = g_timer_new ();
+		info->idle_id = g_idle_add (update_smooth_scroll, info);
+		info->target_x = view->scroll_x;
+		info->target_y = view->scroll_y;
+	}
+
+	info->start_x = view->scroll_x;
+	info->start_y = view->scroll_y;
+	info->target_x = info->target_x + dx;
+	info->target_y = info->target_y + dy;
+
+	g_timer_reset (info->timer);
+	info->view = view;
+
+	return info;
+}
+
+static gdouble
+get_wheel_delta (GtkAdjustment      *adj,
+		 GdkScrollDirection  direction)
+{
+	gdouble delta;
+
+	if (!adj)
+		return 0.0;
+	
+	delta = pow (adj->page_size, 2.0 / 3.0);
+	if (direction == GDK_SCROLL_UP ||
+	    direction == GDK_SCROLL_LEFT)
+		delta = - delta;
+	
+	return delta;
+}
+
 static gboolean
 ev_view_scroll_event (GtkWidget *widget, GdkEventScroll *event)
 {
  	EvView *view = EV_VIEW (widget);
+	double dx, dy;
 
 	if ((event->state & GDK_CONTROL_MASK) != 0) {
 
@@ -1356,7 +1494,32 @@ ev_view_scroll_event (GtkWidget *widget,
 			event->direction = GDK_SCROLL_RIGHT;
 	}
 
-	return FALSE;
+	
+	if (event->direction == GDK_SCROLL_UP ||
+	    event->direction == GDK_SCROLL_DOWN) {
+		dx = 0.0;
+		dy = get_wheel_delta (view->vadjustment,
+				      event->direction);
+	} else {
+		dx = get_wheel_delta (view->hadjustment,
+				      event->direction);
+		dy = 0.0;
+	}
+	
+
+#if 0
+	g_print ("dx, dy: %f %f\n", dx, dy);
+#endif
+	
+	view->smooth_scroll =
+		reset_smooth_scroll (view->smooth_scroll, view,
+				     dx, dy);
+
+#if 0
+	g_print ("idx, idy: %d %d\n", (int)dx, (int)dy);
+#endif
+
+	return TRUE;
 }
 
 static EvViewSelection *
@@ -1740,6 +1903,7 @@ draw_one_page (EvView          *view,
 		GdkPixbuf *selection_pixbuf = NULL;
 		GdkPixbuf *scaled_image;
 		GdkPixbuf *scaled_selection;
+		GdkPixmap *pixmap;
 
 		current_pixbuf = ev_pixbuf_cache_get_pixbuf (view->pixbuf_cache, page);
 
@@ -1750,6 +1914,36 @@ draw_one_page (EvView          *view,
 										 view->scale,
 										 NULL);
 
+		pixmap = ev_pixbuf_cache_get_pixmap (view->pixbuf_cache, page);
+
+#if 0
+		g_print ("pixmap: %p, pixbuf: %p\n", pixmap, current_pixbuf);
+#endif
+		
+		if (!pixmap || !current_pixbuf ||
+		    width != gdk_pixbuf_get_width (current_pixbuf) ||
+		    height != gdk_pixbuf_get_height (current_pixbuf)) {
+
+		pixmap = NULL;
+
+		}
+
+		if (pixmap) {
+#if 0
+			g_print ("draw pixmap\n");
+#endif
+			gdk_draw_drawable (GTK_WIDGET(view)->window, GTK_WIDGET(view)->style->fg_gc[GTK_STATE_NORMAL],
+					   pixmap,
+					   overlap.x - real_page_area.x,
+					   overlap.y - real_page_area.y,
+					   overlap.x, overlap.y,
+					   overlap.width, overlap.height);
+			return;
+		}
+			
+		g_print ("no pixmap\n");			
+			
+		
 		if (current_pixbuf == NULL)
 			scaled_image = NULL;
 		else if (width == gdk_pixbuf_get_width (current_pixbuf) &&
@@ -1775,6 +1969,9 @@ draw_one_page (EvView          *view,
 								    GDK_INTERP_NEAREST);
 
 		if (scaled_image) {
+#if 0
+			g_print ("%4d drawing: %d pixels \n", ++asdf, overlap.width * overlap.height);
+#endif
 			gdk_draw_pixbuf (GTK_WIDGET(view)->window,
 					 GTK_WIDGET (view)->style->fg_gc[GTK_STATE_NORMAL],
 					 scaled_image,
@@ -1811,6 +2008,8 @@ ev_view_finalize (GObject *object)
 
 	LOG ("Finalize");
 
+	destroy_smooth_scroll (view->smooth_scroll);
+	
 	g_free (view->status);
 	g_free (view->find_status);
 
@@ -2117,8 +2316,9 @@ page_changed_cb (EvPageCache *page_cache
 	}
 }
 
-static void on_adjustment_value_changed (GtkAdjustment  *adjustment,
-				         EvView *view)
+static void
+on_adjustment_value_changed (GtkAdjustment  *adjustment,
+			     EvView *view)
 {
 	int dx = 0, dy = 0;
 
@@ -2145,9 +2345,10 @@ static void on_adjustment_value_changed 
 	else
 		gdk_window_scroll (GTK_WIDGET (view)->window, dx, dy);
 
-
 	if (view->document)
 		view_update_range_and_current_page (view);
+
+	gdk_window_process_updates (GTK_WIDGET (view)->window, TRUE);
 }
 
 GtkWidget*
