# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: geoffrey.antos@gmail.com-20080811034823-\
#   ld7b4gmbxazw81nz
# target_branch: ../upstream/
# testament_sha1: 9a1c49222135b1ccfec39e85eaf5d537082eca7c
# timestamp: 2008-08-10 20:48:50 -0700
# source_branch: .
# base_revision_id: geoffrey.antos@gmail.com-20080808181443-\
#   q8ns8grkps0v5w28
# 
# Begin patch
=== modified file 'ChangeLog'
--- ChangeLog	2008-08-08 18:14:43 +0000
+++ ChangeLog	2008-08-11 03:27:17 +0000
@@ -1,3 +1,74 @@
+2008-08-10  Geoffrey Antos <dynamotwain@aim.com>
+	* configure.in, Makefile.am, modules/Makefile.am,
+	transitions/Makefile.am:
+		Added new directory to told transition modules.
+	
+	* data/glade/gthumb_preferences.glade:
+	* src/dlg-preferences.c: (apply_cb), (transition_toggled_cb),
+	(transition_mode_changed_cb), (transition_sort_byname),
+	(dlg_preferences)
+		Added widgets to Slideshow tab to select which transitions
+		are used.
+	
+	* data/gthumb.schemas.in:
+		Added `/apps/gthumb/slideshow/transitions' key to hold list
+		of enabled transitions
+	
+	* libgthumb/Makefile.am, libgthumb/gth-module.c,
+	libgthumb/gth-module.h, libgthumb/gth-transition.h,
+	libgthumb/gth-transition.c, libgthumb/gth-transition-manager.h,
+	libgthumb/gth-transition-manager.c:
+		Added new files containing GObject framework for transition
+		modules.
+	
+	* src/main.c: (initialize_data), (release_data):
+	  src/main.h:
+		Scan for available transition modules at startup.
+
+	* libgthumb/image-viewer.c: (hadj_value_changed),
+	(vadj_value_changed), (image_viewer_expose), (image_viewer_scroll_to),
+	(scroll_relative_no_scrollbar), (image_viewer_finalize),
+	(image_viewer_get_current_pixbuf), (image_viewer_size_allocate),
+	(set_zoom), (image_viewer_get_zoom), (image_viewer_scroll_event),
+	(image_viewer_is_void), (image_viewer_get_image_filename),
+	(image_viewer_get_image_width), (image_viewer_get_image_height),
+	(image_viewer_get_image_bps), (image_viewer_get_has_alpha),
+	(image_viewer_start_animation), (image_viewer_stop_animation),
+	(image_viewer_step_animation), (image_viewer_is_animation),
+	(create_image), (image_viewer_zoom_in), (image_viewer_zoom_out),
+	(image_viewer_set_fit_mode), (image_viewer_get_scroll_offset):
+		Renamed `priv->image' to `priv->current_image' to provide a
+		clearer name. `current_image' and `next_image' contain the
+		pixbufs and animations used directly by the widget and via
+		transitions.
+
+	* libgthumb/image-viewer.c: (create_image), (set_pixbuf__step2),
+	(image_loaded):
+		Cleanup unused parameter in call to create_image.
+		
+	* libgthumb/image-viewer.c: (pref_transitions_changed),
+	(image_viewer_init), (image_viewer_expose), (image_viewer_finalize),
+	(image_viewer_set_void), (create_image),
+	(image_viewer_get_use_transitions), (image_viewer_set_use_transitions):
+	* libgthumb/image-viewer.h:
+	* libgthumb/preferences.c: (pref_get_slideshow_transitions),
+	(pref_set_slideshow_transitions):
+	* libgthumb/preferences.h:
+		Added support for transitions to the ImageViewer widget.
+
+	* modules/transitions/crossfade.c:
+	* modules/transitions/tobackground.c:
+		Added two simple transition modules.
+
+	* po/POTFILES.in:
+		Added all new source files to the list.
+
+	* src/gth-fullscreen.c: (gth_fullscreen_construct)
+		Enable transitions when in fullscreen/slideshow mode.
+	
+	* src/gth-fullscreen.c: (gth_fullscreen_show)
+		Remove one last reference to previous fading preference.
+
 2008-08-08  Geoffrey Antos <dynamotwain@aim.com>
 	* libgthumb/image-viewer.c: (image_viewer_size_allocate):
 		Finally make scrollbars go away in zoom-to-fit modes.

=== modified file 'Makefile.am'
--- Makefile.am	2006-11-30 17:13:34 +0000
+++ Makefile.am	2008-08-11 03:27:17 +0000
@@ -2,6 +2,7 @@
 SUBDIRS =		\
 	po		\
 	libgthumb	\
+	modules         \
 	src		\
 	doc		\
 	data

=== modified file 'configure.in'
--- configure.in	2008-07-31 20:48:31 +0000
+++ configure.in	2008-08-11 03:27:17 +0000
@@ -293,6 +293,8 @@
 libgthumb/cursors/Makefile
 libgthumb/icons/Makefile
 libgthumb/jpegutils/Makefile
+modules/Makefile
+modules/transitions/Makefile
 src/Makefile
 src/icons/Makefile
 doc/Makefile

=== modified file 'data/glade/gthumb_preferences.glade'
--- data/glade/gthumb_preferences.glade	2008-07-10 20:38:00 +0000
+++ data/glade/gthumb_preferences.glade	2008-08-11 03:27:17 +0000
@@ -2131,6 +2131,213 @@
 	      </child>
 
 	      <child>
+		<widget class="GtkVBox" id="vbox1">
+		  <property name="visible">True</property>
+
+		  <child>
+		    <widget class="GtkHBox" id="hbox1">
+		      <property name="visible">True</property>
+		      <property name="spacing">5</property>
+
+		      <child>
+			<widget class="GtkLabel" id="label1">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">&lt;b&gt;Transitions&lt;/b&gt;</property>
+			  <property name="use_underline">False</property>
+			  <property name="use_markup">True</property>
+			  <property name="justify">GTK_JUSTIFY_CENTER</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">False</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			  <property name="width_chars">-1</property>
+			  <property name="single_line_mode">False</property>
+			  <property name="angle">0</property>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">False</property>
+			  <property name="fill">False</property>
+			</packing>
+		      </child>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">False</property>
+		      <property name="fill">True</property>
+		    </packing>
+		  </child>
+
+		  <child>
+		    <widget class="GtkHBox" id="hbox2">
+		      <property name="visible">True</property>
+
+		      <child>
+			<widget class="GtkLabel" id="label2">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">    </property>
+			  <property name="use_underline">False</property>
+			  <property name="use_markup">False</property>
+			  <property name="justify">GTK_JUSTIFY_LEFT</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">False</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			  <property name="width_chars">-1</property>
+			  <property name="single_line_mode">False</property>
+			  <property name="angle">0</property>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">False</property>
+			  <property name="fill">False</property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkVBox" id="vbox2">
+			  <property name="visible">True</property>
+			  <property name="homogeneous">False</property>
+			  <property name="spacing">6</property>
+
+			  <child>
+			    <widget class="GtkHBox" id="hbox3">
+			      <property name="visible">True</property>
+			      <property name="homogeneous">False</property>
+			      <property name="spacing">12</property>
+
+			      <child>
+				<widget class="GtkLabel" id="label3">
+				  <property name="visible">True</property>
+				  <property name="label" translatable="yes">Mode:</property>
+				  <property name="use_underline">False</property>
+				  <property name="use_markup">False</property>
+				  <property name="justify">GTK_JUSTIFY_LEFT</property>
+				  <property name="wrap">False</property>
+				  <property name="selectable">False</property>
+				  <property name="xalign">0.5</property>
+				  <property name="yalign">0.5</property>
+				  <property name="xpad">0</property>
+				  <property name="ypad">0</property>
+				  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+				  <property name="width_chars">-1</property>
+				  <property name="single_line_mode">False</property>
+				  <property name="angle">0</property>
+				</widget>
+				<packing>
+				  <property name="padding">0</property>
+				  <property name="expand">False</property>
+				  <property name="fill">False</property>
+				</packing>
+			      </child>
+
+			      <child>
+				<widget class="GtkOptionMenu" id="opt_transition_mode">
+				  <property name="visible">True</property>
+				  <property name="can_focus">True</property>
+				  <property name="history">0</property>
+
+				  <child internal-child="menu">
+				    <widget class="GtkMenu" id="transition_mode_menu_popup">
+				      <property name="visible">True</property>
+				      
+				      <child>
+					<widget class="GtkMenuItem" id="transitions_disable">
+					  <property name="visible">True</property>
+					  <property name="tooltip" translatable="yes">Never transition between images.</property>
+					  <property name="label" translatable="yes">_Disable Transitions</property>
+					  <property name="use_underline">True</property>
+					</widget>
+				      </child>
+
+				      <child>
+					<widget class="GtkMenuItem" id="transitions_single_menuitem">
+					  <property name="visible">True</property>
+					  <property name="tooltip" translatable="yes">When in slideshow mode, always use the transition selected below.</property>
+					  <property name="label" translatable="yes">_Single Transition</property>
+					  <property name="use_underline">True</property>
+					</widget>
+				      </child>
+
+				      <child>
+					<widget class="GtkMenuItem" id="transitions_multiple">
+					  <property name="visible">True</property>
+					  <property name="tooltip" translatable="yes">When in slideshow mode, randomly select from the transitions selected below.</property>
+					  <property name="label" translatable="yes">_Multiple Transitions</property>
+					  <property name="use_underline">True</property>
+					</widget>
+				      </child>
+				    </widget>
+				  </child>
+				</widget>
+				<packing>
+				  <property name="padding">0</property>
+				  <property name="expand">False</property>
+				  <property name="fill">False</property>
+				</packing>
+			      </child>
+			    </widget>
+			    <packing>
+			      <property name="padding">0</property>
+			      <property name="expand">False</property>
+			      <property name="fill">False</property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkScrolledWindow" id="scrolltransitions">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+			      <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+			      <property name="shadow_type">GTK_SHADOW_IN</property>
+
+			      <child>
+				<widget class="GtkTreeView" id="transition_list">
+				  <property name="visible">True</property>
+				  <property name="can_focus">True</property>
+				  <property name="headers_visible">False</property>
+				  <property name="rules_hint">True</property>
+				  <property name="reorderable">False</property>
+				  <property name="enable_search">True</property>
+				</widget>
+			      </child>
+			    </widget>
+			    <packing>
+			      <property name="padding">0</property>
+			      <property name="expand">True</property>
+			      <property name="fill">True</property>
+			    </packing>
+			  </child>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">True</property>
+			  <property name="fill">True</property>
+			</packing>
+		      </child>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">True</property>
+		      <property name="fill">True</property>
+		    </packing>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">True</property>
+		  <property name="fill">True</property>
+		</packing>
+	      </child>
+
+	      <child>
 		<widget class="GtkVBox" id="vbox42">
 		  <property name="visible">True</property>
 		  <property name="homogeneous">False</property>

=== modified file 'data/gthumb.schemas.in'
--- data/gthumb.schemas.in	2008-07-31 20:48:31 +0000
+++ data/gthumb.schemas.in	2008-08-11 03:27:17 +0000
@@ -468,6 +468,20 @@
       </schema>
 
       <schema>
+      	<key>/schemas/apps/gthumb/slideshow/transitions</key>
+      	<applyto>/apps/gthumb/slideshow/transitions</applyto>
+      	<owner>gthumb</owner>
+      	<type>list</type>
+      	<list_type>string</list_type>
+      	<default></default>
+      	<locale name="C">
+      	  <short></short>
+      	  <long>
+      	  </long>
+      	</locale>
+      </schema>
+
+      <schema>
 	<key>/schemas/apps/gthumb/hotkeys/hotkey0</key>
 	<applyto>/apps/gthumb/hotkeys/hotkey0</applyto>
 	<owner>gthumb</owner>

=== modified file 'libgthumb/Makefile.am'
--- libgthumb/Makefile.am	2008-07-10 05:24:11 +0000
+++ libgthumb/Makefile.am	2008-08-11 03:27:17 +0000
@@ -55,7 +55,10 @@
 	gth-file-view-list.h		\
 	gth-file-view-thumbs.h		\
 	gth-gstreamer-utils.h		\
+	gth-module.h			\
 	gth-nav-window.h		\
+	gth-transition.h		\
+	gth-transition-manager.h	\
 	gth-pixbuf-op.h			\
 	gth-sort-utils.h		\
 	gth-utils.h			\
@@ -117,8 +120,11 @@
 	gth-file-view-list.c		\
 	gth-file-view-thumbs.c		\
 	gth-gstreamer-utils.c		\
+	gth-module.c			\
 	gth-nav-window.c		\
 	gth-sort-utils.c		\
+	gth-transition.c		\
+	gth-transition-manager.c	\
 	gth-utils.c			\
 	gthumb-error.c			\
 	gthumb-histogram.c		\

=== added file 'libgthumb/gth-module.c'
--- libgthumb/gth-module.c	1970-01-01 00:00:00 +0000
+++ libgthumb/gth-module.c	2008-08-11 03:27:17 +0000
@@ -0,0 +1,139 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2001-2008 The Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include "gth-module.h"
+
+typedef struct _GthModulePrivate GthModulePrivate;
+
+struct _GthModulePrivate {
+	gchar     *path;
+	GModule   *module;
+	gboolean (* load)   (GthModule* module);
+	void     (* unload) (GthModule* module);
+};
+
+G_DEFINE_TYPE(GthModule, gth_module, G_TYPE_TYPE_MODULE)
+#define GTH_MODULE_GET_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+				    GTH_MODULE_TYPE, GthModulePrivate))
+
+static void     gth_module_finalize (GObject     *object);
+static gboolean gth_module_load     (GTypeModule *typemodule);
+static void     gth_module_unload   (GTypeModule *typemodule);
+
+
+static void
+gth_module_class_init (GthModuleClass *klass)
+{
+	GObjectClass     *object_class     = G_OBJECT_CLASS      (klass);
+	GTypeModuleClass *typemodule_class = G_TYPE_MODULE_CLASS (klass);
+
+	object_class->finalize    = gth_module_finalize;
+
+	typemodule_class->load    = gth_module_load;
+	typemodule_class->unload  = gth_module_unload;
+
+	g_type_class_add_private (klass, sizeof (GthModulePrivate));
+}
+
+
+static void
+gth_module_init (GthModule *module)
+{
+	GthModulePrivate *priv = GTH_MODULE_GET_PRIVATE (module);
+
+	priv->path   = NULL;
+	priv->module = NULL;
+	priv->load   = NULL;
+	priv->unload = NULL;
+}
+
+
+static void
+gth_module_finalize (GObject *object)
+{
+	GthModule        *module = GTH_MODULE (object);
+	GthModulePrivate *priv   = GTH_MODULE_GET_PRIVATE (module);
+	GObjectClass     *object_class;
+
+	object_class = G_OBJECT_CLASS (gth_module_parent_class);
+
+	g_free (priv->path);
+
+	/* Chain up */
+	object_class->finalize (object);
+	
+}
+
+GthModule*
+gth_module_new (gchar *path)
+{
+	GthModule        *module;
+	GthModulePrivate *priv;
+
+	g_return_val_if_fail (path != NULL, NULL);
+
+	module = g_object_new (GTH_MODULE_TYPE, NULL);
+	priv = GTH_MODULE_GET_PRIVATE (module);
+	priv->path = g_strdup (path);
+	
+	return module;
+}
+
+static gboolean
+gth_module_load (GTypeModule *typemodule)
+{
+	GthModule        *module = GTH_MODULE (typemodule);
+	GthModulePrivate *priv   = GTH_MODULE_GET_PRIVATE (module);
+
+	priv->module = g_module_open (priv->path,
+				      G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+
+	if (! priv->module) {
+		g_printerr ("%s\n", g_module_error ());
+		return FALSE;
+	}
+
+	if (! g_module_symbol (priv->module, "gth_module_load",
+			       (gpointer *) &priv->load) ||
+	    ! g_module_symbol (priv->module, "gth_module_unload",
+                               (gpointer *) &priv->unload)) {
+		g_printerr ("%s\n", g_module_error ());
+		g_module_close (priv->module);
+		return FALSE;
+	}
+
+	return priv->load (module);
+}
+
+static void
+gth_module_unload (GTypeModule *typemodule)
+{
+	GthModule        *module = GTH_MODULE (typemodule);
+	GthModulePrivate *priv   = GTH_MODULE_GET_PRIVATE (module);
+
+	priv->unload (module);
+
+	g_module_close (priv->module);
+	priv->module = NULL;
+	priv->load   = NULL;
+	priv->unload = NULL;
+}

=== added file 'libgthumb/gth-module.h'
--- libgthumb/gth-module.h	1970-01-01 00:00:00 +0000
+++ libgthumb/gth-module.h	2008-08-11 03:27:17 +0000
@@ -0,0 +1,73 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2001-2008 The Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GTH_MODULE_H
+#define GTH_MODULE_H
+
+#include <glib-object.h>
+#include <gmodule.h>
+
+G_BEGIN_DECLS
+
+#define GTH_MODULE_SYMBOLS(t_n)						\
+G_MODULE_EXPORT gboolean gth_module_load   (GthModule *module);		\
+G_MODULE_EXPORT void     gth_module_unload (GthModule *module);		\
+gboolean gth_module_load (GthModule *module)				\
+{									\
+	t_n##_register_type (G_TYPE_MODULE (module));			\
+	return TRUE;							\
+}									\
+void gth_module_unload (GthModule* module)				\
+{									\
+}
+
+#define GTH_DEFINE_MODULE(TN, t_n, T_P)					\
+G_DEFINE_DYNAMIC_TYPE    (TN, t_n, T_P)					\
+GTH_MODULE_SYMBOLS (t_n)
+
+
+#define GTH_MODULE_TYPE            (gth_module_get_type ())
+#define GTH_MODULE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_MODULE_TYPE, GthModule))
+#define GTH_MODULE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_MODULE_TYPE, GthModuleClass))
+#define IS_GTH_MODULE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_MODULE_TYPE))
+#define IS_GTH_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_MODULE_TYPE))
+#define GTH_MODULE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_MODULE_TYPE, GthModuleClass))
+
+typedef struct _GthModule      GthModule;
+typedef struct _GthModuleClass GthModuleClass;
+
+struct _GthModule
+{
+	GTypeModule parent;
+};
+
+struct _GthModuleClass
+{
+	GTypeModuleClass parent;
+};
+
+GType      gth_module_get_type (void);
+GthModule* gth_module_new      (gchar* filename);
+
+G_END_DECLS
+
+#endif

=== modified file 'libgthumb/gth-nav-window.c'
--- libgthumb/gth-nav-window.c	2008-07-31 01:04:16 +0000
+++ libgthumb/gth-nav-window.c	2008-08-11 03:27:17 +0000
@@ -158,7 +158,7 @@
 			  priv->viewer);
 
 	hbox = gtk_hbox_new (FALSE, 0);
-	gtk_container_add (GTK_CONTAINER (hbox), GTK_WIDGET (priv->viewer));
+	gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (priv->viewer), TRUE, TRUE, 0);
 
 	table = gtk_table_new (2, 2, FALSE);
 	gtk_table_attach (GTK_TABLE (table), hbox, 0, 1, 0, 1,

=== added file 'libgthumb/gth-transition-manager.c'
--- libgthumb/gth-transition-manager.c	1970-01-01 00:00:00 +0000
+++ libgthumb/gth-transition-manager.c	2008-08-11 03:27:17 +0000
@@ -0,0 +1,127 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2001-2008 The Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <gmodule.h>
+
+#include "gth-module.h"
+#include "gth-transition-manager.h"
+
+#define GTHUMB_TRANSITIONSDIR (GTHUMB_MODULEDIR "/transitions")
+
+G_DEFINE_TYPE(GthTransitionManager, gth_transition_manager, G_TYPE_OBJECT)
+
+static GObject * gth_transition_manager_constructor (GType                 type,
+                                                     guint                 n_params,
+                                                     GObjectConstructParam *params);
+
+static void
+gth_transition_manager_class_init (GthTransitionManagerClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->constructor = gth_transition_manager_constructor;
+}
+
+
+static GthTransitionManager *the_one_and_only = NULL;
+
+
+static void
+gth_transition_manager_init (GthTransitionManager *manager)
+{
+	g_assert (the_one_and_only == NULL);
+	the_one_and_only = manager;
+}
+
+
+static void query_modules (GthTransitionManager *manager);
+
+
+static GObject *
+gth_transition_manager_constructor (GType                  type,
+                                    guint                  n_params,
+                                    GObjectConstructParam *params)
+{
+	if (the_one_and_only) {
+		return g_object_ref (G_OBJECT (the_one_and_only));
+	} else {
+		GObjectClass         *object_class;
+		GObject              *object;
+		GthTransitionManager *manager;
+
+		object_class = G_OBJECT_CLASS (gth_transition_manager_parent_class);
+		object = object_class->constructor (type, n_params, params);
+
+		manager = GTH_TRANSITION_MANAGER (object);
+		query_modules (manager);
+		return object;
+	}	
+}
+
+
+GthTransitionManager*
+gth_transition_manager_new (void)
+{
+	return g_object_new (GTH_TRANSITION_MANAGER_TYPE, NULL);
+}
+
+
+static void
+query_modules (GthTransitionManager *manager)
+{
+	GDir                        *dir;
+	GError                      *err = NULL;
+	const gchar                 *name;
+
+
+	dir = g_dir_open (GTHUMB_TRANSITIONSDIR, 0, &err);
+	if (!dir) {
+		g_printerr ("Error while opening dir: %s\n", err->message);
+		g_clear_error (&err);
+		return;
+	}
+
+	while ((name = g_dir_read_name (dir))) {
+		GthModule *module;
+		gchar     *path;
+		gboolean   success;
+
+		if (!g_str_has_suffix (name, "." G_MODULE_SUFFIX))
+			continue;
+
+		path = g_build_filename (GTHUMB_TRANSITIONSDIR, name, NULL);
+		module = gth_module_new (path);
+
+		success = g_type_module_use (G_TYPE_MODULE (module));
+
+		if (success) {
+			g_type_module_unuse (G_TYPE_MODULE (module));
+		} else { 
+			g_printerr ("Module failed to load: %s\n", path);
+			g_object_unref (module);
+		}
+
+		g_free (path);
+	}
+
+	g_dir_close (dir);
+}

=== added file 'libgthumb/gth-transition-manager.h'
--- libgthumb/gth-transition-manager.h	1970-01-01 00:00:00 +0000
+++ libgthumb/gth-transition-manager.h	2008-08-11 03:27:17 +0000
@@ -0,0 +1,54 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2001-2008 The Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GTH_TRANSITION_MANAGER_H
+#define GTH_TRANSITION_MANAGER_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GTH_TRANSITION_MANAGER_TYPE            (gth_transition_manager_get_type ())
+#define GTH_TRANSITION_MANAGER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TRANSITION_MANAGER_TYPE, GthTransitionManager))
+#define GTH_TRANSITION_MANAGER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TRANSITION_MANAGER_TYPE, GthTransitionManagerClass))
+#define IS_GTH_TRANSITION_MANAGER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TRANSITION_MANAGER_TYPE))
+#define IS_GTH_TRANSITION_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TRANSITION_MANAGER_TYPE))
+#define GTH_TRANSITION_MANAGER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TRANSITION_MANAGER_TYPE, GthTransitionManagerClass))
+
+typedef struct _GthTransitionManager      GthTransitionManager;
+typedef struct _GthTransitionManagerClass GthTransitionManagerClass;
+
+struct _GthTransitionManager {
+	GObject parent;
+};
+
+struct _GthTransitionManagerClass {
+	GObjectClass parent;
+};
+
+GType gth_transition_manager_get_type (void);
+
+GthTransitionManager* gth_transition_manager_new (void);
+
+G_END_DECLS
+
+#endif

=== added file 'libgthumb/gth-transition.c'
--- libgthumb/gth-transition.c	1970-01-01 00:00:00 +0000
+++ libgthumb/gth-transition.c	2008-08-11 03:27:17 +0000
@@ -0,0 +1,158 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2001-2008 The Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <gtk/gtkwidget.h>
+
+#include "gth-transition.h"
+
+#define FRAME_DELAY 50
+
+typedef struct _GthTransitionPrivate GthTransitionPrivate;
+
+struct _GthTransitionPrivate {
+	GTimer      *elapsed;
+	guint        source_id;
+	ImageViewer *viewer;
+};
+
+G_DEFINE_ABSTRACT_TYPE(GthTransition, gth_transition, G_TYPE_OBJECT)
+#define GTH_TRANSITION_GET_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+					GTH_TRANSITION_TYPE, \
+					GthTransitionPrivate))
+
+static void     gth_transition_finalize (GObject *object);
+
+static gboolean refresh (gpointer data);
+
+static void
+gth_transition_class_init (GthTransitionClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	klass->name    = NULL;
+	klass->compose = NULL;
+
+	object_class->finalize = gth_transition_finalize;
+
+	g_type_class_add_private (klass, sizeof (GthTransitionPrivate));
+}
+
+
+static void
+gth_transition_finalize (GObject *object)
+{
+	GthTransition        *transition = GTH_TRANSITION (object);
+	GthTransitionPrivate *priv       = GTH_TRANSITION_GET_PRIVATE (transition);
+
+	if (priv->elapsed != NULL) {
+		g_timer_destroy (priv->elapsed);
+		priv->elapsed = NULL;
+	}
+
+	if (priv->source_id != 0) {
+		g_source_remove (priv->source_id);
+		priv->source_id = 0;
+	}
+}
+
+
+static void
+gth_transition_init (GthTransition* transition)
+{
+	GthTransitionPrivate *priv = GTH_TRANSITION_GET_PRIVATE (transition);
+
+	priv->elapsed   = g_timer_new ();
+}
+
+GthTransition*
+gth_transition_new (GType type, ImageViewer *viewer)
+{
+	GthTransition        *transition; 
+	GthTransitionPrivate *priv;
+
+	g_return_val_if_fail (g_type_is_a (type, GTH_TRANSITION_TYPE), NULL);
+
+	transition = g_object_new (type, NULL);
+	priv = GTH_TRANSITION_GET_PRIVATE (transition);
+
+	priv->source_id = g_timeout_add (FRAME_DELAY, refresh, transition);
+	priv->viewer = viewer;
+
+	return transition;
+}
+
+
+gboolean
+gth_transition_compose (GthTransition *transition,
+			cairo_t         *cr,
+			cairo_surface_t *image1,
+			cairo_surface_t *image2,
+			gint             width,
+			gint             height)
+{
+	GthTransitionClass   *klass = GTH_TRANSITION_GET_CLASS (transition);
+	GthTransitionPrivate *priv;
+	gboolean              cont;
+
+	g_return_val_if_fail (transition != NULL, FALSE);
+	g_return_val_if_fail (klass->compose != NULL, FALSE);
+
+	priv = GTH_TRANSITION_GET_PRIVATE (transition);
+
+	cont = klass->compose (transition, cr, image1, image2, width, height);
+	if (cont) {
+		if (priv->source_id)
+			g_source_remove (priv->source_id);
+		priv->source_id = g_timeout_add (FRAME_DELAY, refresh, transition);
+	}
+	return cont;
+}
+
+
+gdouble gth_transition_get_elapsed_time (GthTransition *transition)
+{
+	GthTransitionPrivate *priv;
+	
+	g_return_val_if_fail (transition != NULL, 0);
+	
+	priv = GTH_TRANSITION_GET_PRIVATE (transition);
+
+	return g_timer_elapsed (priv->elapsed, NULL);
+}
+
+
+gdouble gth_transition_get_length (void)
+{
+	return 1.0;
+}
+
+
+static gboolean
+refresh (gpointer data)
+{
+	GthTransition        *transition = GTH_TRANSITION (data);
+	GthTransitionPrivate *priv       = GTH_TRANSITION_GET_PRIVATE (transition);
+
+	gtk_widget_queue_draw (GTK_WIDGET (priv->viewer));
+
+	return FALSE;
+}

=== added file 'libgthumb/gth-transition.h'
--- libgthumb/gth-transition.h	1970-01-01 00:00:00 +0000
+++ libgthumb/gth-transition.h	2008-08-11 03:27:17 +0000
@@ -0,0 +1,77 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2001-2008 The Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GTH_TRANSITION_H
+#define GTH_TRANSITION_H
+
+#include <cairo.h>
+#include <glib.h>
+#include <glib-object.h>
+
+#include "image-viewer.h"
+
+G_BEGIN_DECLS
+
+#define GTH_TRANSITION_TYPE            (gth_transition_get_type ())
+#define GTH_TRANSITION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TRANSITION_TYPE, GthTransition))
+#define GTH_TRANSITION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TRANSITION_TYPE, GthTransitionClass))
+#define IS_GTH_TRANSITION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TRANSITION_TYPE))
+#define IS_GTH_TRANSITION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TRANSITION_TYPE))
+#define GTH_TRANSITION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TRANSITION_TYPE, GthTransitionClass))
+
+typedef struct _GthTransition      GthTransition;
+typedef struct _GthTransitionClass GthTransitionClass;
+
+struct _GthTransition {
+	GObject  parent;
+};
+
+struct _GthTransitionClass {
+	GObjectClass parent;
+
+	gchar  *name;
+
+	gboolean (* compose) (GthTransition *transition,
+			      cairo_t *cr,
+			      cairo_surface_t* image1,
+    			      cairo_surface_t* image2,
+    			      gint             width,
+    			      gint             height);
+};
+
+GType   gth_transition_get_type          (void);
+
+GthTransition* gth_transition_new        (GType type, ImageViewer *viewer);
+
+gboolean gth_transition_compose          (GthTransition   *transition,
+					  cairo_t         *cr,
+					  cairo_surface_t *image1,
+					  cairo_surface_t *image2,
+					  gint             width,
+					  gint             height);
+
+gdouble  gth_transition_get_elapsed_time (GthTransition *transition);
+gdouble  gth_transition_get_length       (void);
+
+G_END_DECLS
+
+#endif

=== modified file 'libgthumb/image-viewer.c'
--- libgthumb/image-viewer.c	2008-08-08 18:14:43 +0000
+++ libgthumb/image-viewer.c	2008-08-11 03:27:17 +0000
@@ -32,11 +32,14 @@
 #include <libgnomevfs/gnome-vfs-uri.h>
 #include <libgnomevfs/gnome-vfs-utils.h>
 
+#include "gconf-utils.h"
 #include "gth-iviewer.h"
+#include "gth-transition.h"
 #include "image-viewer.h"
 #include "image-viewer-image.h"
 #include "cursors.h"
 #include "pixbuf-utils.h"
+#include "preferences.h"
 #include "gthumb-marshal.h"
 #include "gthumb-enum-types.h"
 #include "glib-utils.h"
@@ -52,13 +55,17 @@
 			       * smaller than this value. */
 #define STEP_INCREMENT  20.0  /* Scroll increment. */
 
+#define GCONF_NOTIFICATIONS 1
+
 #define FLOAT_EQUAL(a,b) (fabs ((a) - (b)) < 1e-6)
 
 typedef struct _ImageViewerPrivate ImageViewerPrivate;
 
 struct _ImageViewerPrivate {
 	ImageLoader      *loader;
-	ImageViewerImage *image;
+	ImageViewerImage *current_image;
+	ImageViewerImage *next_image;
+	GthTransition    *current_transition;
 
 	gboolean         play_animation;
 
@@ -97,7 +104,14 @@
 	gboolean         skip_zoom_change;
 	gboolean         skip_size_change;
 
-	gboolean         reset_scrollbars;	
+	gboolean         reset_scrollbars;
+
+	GSList          *transitions;
+	guint            transitions_length;
+	gboolean         use_transitions;
+
+	guint            cnxn_id[GCONF_NOTIFICATIONS];
+
 };
 
 
@@ -441,7 +455,7 @@
 }
 
 
-static void create_image   (ImageLoader *il, gpointer data);
+static void create_image   (ImageViewer *viewer);
 static void image_loaded   (ImageLoader *il, gpointer data);
 static void image_error    (ImageLoader *il, gpointer data);
 static void image_progress (ImageLoader *il, float progress, gpointer data);
@@ -454,10 +468,10 @@
 	ImageViewerPrivate  *priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 	gdouble              x_ofs, y_ofs;
 
-	g_return_val_if_fail (priv->image != NULL, FALSE);
+	g_return_val_if_fail (priv->current_image != NULL, FALSE);
 
 	x_ofs = floor (adj->value + adj->page_size / 2) -
-		image_viewer_image_get_x_offset (priv->image);
+		image_viewer_image_get_x_offset (priv->current_image);
 	y_ofs = 0;
 	scroll_relative_no_scrollbar (viewer, x_ofs, y_ofs);
 
@@ -472,21 +486,38 @@
 	ImageViewerPrivate  *priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 	gdouble              x_ofs, y_ofs;
 	
-	g_return_val_if_fail (priv->image != NULL, FALSE);
+	g_return_val_if_fail (priv->current_image != NULL, FALSE);
 
 	x_ofs = 0;
 	y_ofs = floor (adj->value + adj->page_size / 2) -
-		image_viewer_image_get_y_offset (priv->image);
+		image_viewer_image_get_y_offset (priv->current_image);
 	scroll_relative_no_scrollbar (viewer, x_ofs, y_ofs);
 
 	return FALSE;
 }
 
+static void
+pref_slideshow_transitions_changed (GConfClient *client,
+				    guint        cnxn_id,
+				    GConfEntry  *entry,
+				    gpointer     user_data)
+{
+	ImageViewer         *viewer = user_data;
+	ImageViewerPrivate  *priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
+
+	if (priv->transitions != NULL)
+		g_slist_free (priv->transitions);
+
+	priv->transitions        = pref_get_slideshow_transitions ();
+	priv->transitions_length = g_slist_length (priv->transitions);
+}
+
 
 static void
 image_viewer_init (ImageViewer *viewer)
 {
 	ImageViewerPrivate  *priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
+	int                  i;
 
 	GTK_WIDGET_SET_FLAGS (viewer, GTK_CAN_FOCUS);
 	/*GTK_WIDGET_UNSET_FLAGS (viewer, GTK_DOUBLE_BUFFERED);*/
@@ -519,6 +550,10 @@
 			  G_CALLBACK (image_progress),
 			  viewer);
 
+	priv->current_image      = NULL;
+	priv->next_image         = NULL;
+	priv->current_transition = NULL;
+
 	priv->skip_zoom_change = FALSE;
 	priv->skip_size_change = FALSE;
 
@@ -533,6 +568,16 @@
 
 	priv->reset_scrollbars = TRUE;
 
+	priv->transitions        = pref_get_slideshow_transitions ();
+	priv->transitions_length = g_slist_length (priv->transitions);
+	priv->use_transitions    = FALSE;
+
+	i = 0;
+	priv->cnxn_id[i++] = eel_gconf_notification_add (
+					   PREF_SLIDESHOW_TRANSITIONS,
+					   pref_slideshow_transitions_changed,
+					   viewer);
+
 	/* Create the widget. */
 
 	priv->hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 1.0, 0.0,
@@ -576,8 +621,65 @@
 	gdk_width    = alloc_width - priv->frame_border2;
 	gdk_height   = alloc_height - priv->frame_border2;
 
-	if (priv->image != NULL)
-	{
+	if (priv->current_transition != NULL) {
+		/* TODO - cache surfaces to avoid reallocations,
+		 * cache scaled images on said surfaces to avoid rescaling when possible.
+		 * Anything and everything that can be done to speed this up needs to be done.
+		 * I'm only getting 2-4fps on my computer. */
+		cairo_surface_t *buf1 = NULL, *buf2 = NULL;
+		cairo_t *cr;
+
+		cr = gdk_cairo_create (GTK_WIDGET (viewer)->window);
+
+		/* Only actually paint the regions that need redrawn */
+		gdk_cairo_region (cr, event->region);
+		cairo_clip (cr);
+
+		if (priv->current_image != NULL) {
+			cairo_t *cr2;
+			buf1 = cairo_surface_create_similar (cairo_get_target (cr),
+							     CAIRO_CONTENT_COLOR_ALPHA,
+							     alloc_width, alloc_height);
+			cr2 = cairo_create (buf1);
+
+			gdk_cairo_region (cr2, event->region);
+			cairo_clip (cr2);
+			image_viewer_image_paint (priv->current_image, cr2);
+			cairo_destroy (cr2);
+		}
+		if (priv->next_image != NULL) {
+			cairo_t *cr2;
+			buf2 = cairo_surface_create_similar (cairo_get_target (cr),
+							     CAIRO_CONTENT_COLOR_ALPHA,
+							     alloc_width, alloc_height);
+			cr2 = cairo_create (buf2);
+			gdk_cairo_region (cr2, event->region);
+			cairo_clip (cr2);
+			image_viewer_image_paint (priv->next_image, cr2);
+			cairo_destroy (cr2);
+		}
+
+		if (! gth_transition_compose (priv->current_transition, cr, buf1, buf2, alloc_width, alloc_height)) {
+			/* Transition has ended... do cleanup. */
+			g_object_unref (priv->current_transition);
+			priv->current_transition = NULL;
+
+			if (priv->current_image != NULL)
+				g_object_unref (priv->current_image);
+
+			priv->current_image = priv->next_image;
+			priv->next_image = NULL;
+		}
+
+		if (buf1 != NULL)
+			cairo_surface_destroy (buf1);
+
+		if (buf2 != NULL)
+			cairo_surface_destroy (buf2);
+
+		cairo_destroy (cr);
+	}
+	else if (priv->current_image != NULL) {
 		cairo_t *cr;
 		cr = gdk_cairo_create (GTK_WIDGET (viewer)->window);
 
@@ -586,7 +688,7 @@
 		cairo_clip (cr);
 
 		/* Paint the image */
-		image_viewer_image_paint (priv->image, cr);
+		image_viewer_image_paint (priv->current_image, cr);
 
 		cairo_destroy (cr);
 	}
@@ -629,12 +731,12 @@
 
 	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
-	g_return_if_fail (priv->image != NULL);
+	g_return_if_fail (priv->current_image != NULL);
 
 	if (priv->rendering)
 		return;
 
-	image_viewer_image_get_scroll_offsets (priv->image, &x, &y);
+	image_viewer_image_get_scroll_offsets (priv->current_image, &x, &y);
 
 	/* Convert absolute offset to relative change */
 	x = x_offset - x;
@@ -675,7 +777,11 @@
 {
 	ImageViewerPrivate *priv     = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
-	image_viewer_image_scroll_relative (priv->image, delta_x, delta_y);
+	image_viewer_image_scroll_relative (priv->current_image, delta_x, delta_y);
+
+	if (priv->next_image != NULL)
+		image_viewer_image_scroll_relative (priv->next_image,
+						    delta_x, delta_y);
 
 	gtk_widget_queue_draw (GTK_WIDGET (viewer));
 }
@@ -808,6 +914,7 @@
 {
         ImageViewer        *viewer;
 	ImageViewerPrivate *priv;
+	int                 i;
 
         g_return_if_fail (object != NULL);
         g_return_if_fail (IS_IMAGE_VIEWER (object));
@@ -820,9 +927,19 @@
 		priv->loader = NULL;
 	}
 
-	if (priv->image != NULL) {
-		g_object_unref (G_OBJECT (priv->image));
-		priv->image = NULL;
+	if (priv->current_image != NULL) {
+		g_object_unref (G_OBJECT (priv->current_image));
+		priv->current_image = NULL;
+	}
+
+	if (priv->next_image != NULL) {
+		g_object_unref (G_OBJECT (priv->next_image));
+		priv->next_image = NULL;
+	}
+
+	if (priv->current_transition != NULL) {
+		g_object_unref (G_OBJECT (priv->current_transition));
+		priv->current_transition = NULL;
 	}
 
 	if (priv->cursor != NULL) {
@@ -841,6 +958,7 @@
 		g_object_unref (priv->hadj);
 		priv->hadj = NULL;
 	}
+
 	if (priv->vadj != NULL) {
 		g_signal_handlers_disconnect_by_data (G_OBJECT (priv->vadj),
 						      viewer);
@@ -848,11 +966,15 @@
 		priv->vadj = NULL;
 	}
 
-	/*if (priv->area_pixbuf != NULL) {
-		g_object_unref (priv->area_pixbuf);
-		priv->area_pixbuf = NULL;
-	}*/
+	if (priv->transitions != NULL) {
+		g_slist_free (priv->transitions);
+		priv->transitions = NULL;
+	}
 
+	for (i = 0; i < GCONF_NOTIFICATIONS; i++)
+		if (priv->cnxn_id[i] != EEL_GCONF_UNDEFINED_CONNECTION)
+			eel_gconf_notification_remove (priv->cnxn_id[i]);
+	
         /* Chain up */
 	G_OBJECT_CLASS (image_viewer_parent_class)->finalize (object);
 }
@@ -940,9 +1062,9 @@
 
 	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
-	if (priv->image == NULL) return NULL;
+	if (priv->current_image == NULL) return NULL;
 
-	return image_viewer_image_get_pixbuf (priv->image);
+	return image_viewer_image_get_pixbuf (priv->current_image);
 }
 
 
@@ -960,17 +1082,17 @@
 
 	/* If a fit type is active update the zoom level. */
 
-	if (priv->image != NULL) {
+	if (priv->current_image != NULL) {
 		gdouble    width, height;
 		gdouble	   off_x, off_y;
 
 		/* Re-fit the image to the new widget size if a fit-mode is active */
-		image_viewer_image_set_fit_mode (priv->image,
-				image_viewer_image_get_fit_mode (priv->image));
-
-		image_viewer_image_get_scroll_offsets (priv->image, &off_x, &off_y);
-
-		image_viewer_image_get_zoomed_size (priv->image, &width, &height);
+		image_viewer_image_set_fit_mode (priv->current_image,
+				image_viewer_image_get_fit_mode (priv->current_image));
+
+		image_viewer_image_get_scroll_offsets (priv->current_image, &off_x, &off_y);
+
+		image_viewer_image_get_zoomed_size (priv->current_image, &width, &height);
 
 		if (!FLOAT_EQUAL(width,  priv->hadj->upper - priv->hadj->lower) ||
 		    !FLOAT_EQUAL(height, priv->vadj->upper - priv->vadj->lower))
@@ -1004,6 +1126,10 @@
 		priv->vadj->page_size = 1.0;
 	}
 
+	if (priv->next_image != NULL)
+		image_viewer_image_set_fit_mode (priv->next_image,
+				image_viewer_image_get_fit_mode (priv->next_image));
+
 	g_signal_handlers_block_by_data (G_OBJECT (priv->hadj), viewer);
 	g_signal_handlers_block_by_data (G_OBJECT (priv->vadj), viewer);
 	gtk_adjustment_changed (priv->hadj);
@@ -1053,7 +1179,7 @@
 {
 	ImageViewerPrivate *priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
-	image_viewer_image_zoom_at_point (priv->image, zoom_level, center_x, center_y);
+	image_viewer_image_zoom_at_point (priv->current_image, zoom_level, center_x, center_y);
 
 	if (priv->fit != GTH_FIT_NONE) {
 		/*gtk_widget_queue_resize (GTK_WIDGET (viewer));*/
@@ -1108,9 +1234,9 @@
 
 	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
-	if (priv->image == NULL) return 1.0;
+	if (priv->current_image == NULL) return 1.0;
 
-	return image_viewer_image_get_zoom_level (priv->image);
+	return image_viewer_image_get_zoom_level (priv->current_image);
 }
 
 
@@ -1131,16 +1257,28 @@
 	if (event->state & GDK_CONTROL_MASK) {
 		if (event->direction == GDK_SCROLL_UP) {
 			image_viewer_image_zoom_in_at_point(
-					priv->image,
+					priv->current_image,
 					event->x,
 					event->y);
+
+			if (priv->next_image != NULL)
+				image_viewer_image_zoom_in_at_point(
+						priv->next_image,
+						event->x,
+						event->y);
 			return TRUE;
 		}
 		if (event->direction == GDK_SCROLL_DOWN) {
 			image_viewer_image_zoom_out_at_point(
-					priv->image,
+					priv->current_image,
 					event->x,
 					event->y);
+
+			if (priv->next_image != NULL)
+				image_viewer_image_zoom_out_at_point(
+						priv->next_image,
+						event->x,
+						event->y);
 			return TRUE;
 		}
 	}
@@ -1364,7 +1502,7 @@
 
 	image_loader_set_file   (priv->loader, NULL);
 	image_loader_set_pixbuf (priv->loader, pixbuf);
-	create_image (priv->loader, ivl_data->viewer);
+	create_image (ivl_data->viewer);
 
 	g_object_unref (G_OBJECT (pixbuf));
 	g_free (ivl_data);
@@ -1398,16 +1536,7 @@
 void
 image_viewer_set_void (ImageViewer *viewer)
 {
-	ImageViewerPrivate* priv;
-
-	g_return_if_fail (viewer != NULL);
-
-	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
-
-	g_object_unref (priv->image);
-	priv->image = NULL;
-
-	gtk_widget_queue_resize (GTK_WIDGET (viewer));
+	image_viewer_set_pixbuf (viewer, NULL);
 }
 
 
@@ -1420,7 +1549,7 @@
 
 	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
-	return (priv->image == NULL);
+	return (priv->current_image == NULL);
 }
 
 
@@ -1442,9 +1571,9 @@
 
 	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
-	if (priv->image == NULL) return NULL;
+	if (priv->current_image == NULL) return NULL;
 
-	return image_viewer_image_get_path (priv->image);
+	return image_viewer_image_get_path (priv->current_image);
 }
 
 
@@ -1457,9 +1586,9 @@
 
 	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
-	if (priv->image == NULL) return 0;
+	if (priv->current_image == NULL) return 0;
 
-	return image_viewer_image_get_width (priv->image);
+	return image_viewer_image_get_width (priv->current_image);
 }
 
 
@@ -1472,9 +1601,9 @@
 
 	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
-	if (priv->image == NULL) return 0;
+	if (priv->current_image == NULL) return 0;
 
-	return image_viewer_image_get_height (priv->image);
+	return image_viewer_image_get_height (priv->current_image);
 }
 
 
@@ -1487,9 +1616,9 @@
 
 	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
-	if (priv->image == NULL) return 0;
+	if (priv->current_image == NULL) return 0;
 
-	return image_viewer_image_get_bps (priv->image);
+	return image_viewer_image_get_bps (priv->current_image);
 }
 
 
@@ -1502,9 +1631,9 @@
 
 	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
-	if (priv->image == NULL) return FALSE;
+	if (priv->current_image == NULL) return FALSE;
 
-	return image_viewer_image_get_has_alpha (priv->image);
+	return image_viewer_image_get_has_alpha (priv->current_image);
 }
 
 
@@ -1518,7 +1647,10 @@
 	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
 	priv->play_animation = TRUE;
-	image_viewer_image_start_animation (priv->image);
+	image_viewer_image_start_animation (priv->current_image);
+
+	if (priv->next_image != NULL)
+		image_viewer_image_start_animation (priv->next_image);
 }
 
 
@@ -1532,7 +1664,10 @@
 	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
 	priv->play_animation = FALSE;
-	image_viewer_image_stop_animation (priv->image);
+	image_viewer_image_stop_animation (priv->current_image);
+
+	if (priv->next_image != NULL)
+		image_viewer_image_stop_animation (priv->next_image);
 }
 
 
@@ -1548,7 +1683,10 @@
 	g_return_if_fail (priv->play_animation == FALSE);
 	g_return_if_fail (priv->rendering == FALSE);
 
-	image_viewer_image_step_animation (priv->image);
+	image_viewer_image_step_animation (priv->current_image);
+
+	if (priv->next_image != NULL)
+		image_viewer_image_step_animation (priv->next_image);
 }
 
 
@@ -1574,9 +1712,9 @@
 
 	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
-	if (priv->image == NULL) return FALSE;
+	if (priv->current_image == NULL) return FALSE;
 
-	return image_viewer_image_get_is_animation(priv->image);
+	return image_viewer_image_get_is_animation(priv->current_image);
 }
 
 
@@ -1628,7 +1766,7 @@
 {
 	ImageViewer        *viewer = data;
 
-	create_image (il, data);
+	create_image (viewer);
 
 	g_signal_emit (G_OBJECT (viewer),
 		       image_viewer_signals[IMAGE_LOADED],
@@ -1637,18 +1775,16 @@
 
 
 static void
-create_image (ImageLoader *il,
-	      gpointer data)
+create_image (ImageViewer* viewer)
 {
-	ImageViewer        *viewer = data;
 	ImageViewerPrivate *priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 	ImageViewerImage   *next;
 
 	next = image_viewer_image_new (viewer, priv->loader);
 
-	if (priv->reset_scrollbars == FALSE && priv->image != NULL) {
+	if (priv->reset_scrollbars == FALSE && priv->current_image != NULL) {
 		gdouble x_ofs, y_ofs;
-		image_viewer_image_get_scroll_offsets (priv->image, &x_ofs, &y_ofs);
+		image_viewer_image_get_scroll_offsets (priv->current_image, &x_ofs, &y_ofs);
 		image_viewer_image_set_scroll_offsets (next, x_ofs, y_ofs);
 	}
 
@@ -1657,9 +1793,9 @@
 		break;
 
 	case GTH_ZOOM_CHANGE_KEEP_PREV:
-		if (priv->image != NULL)
+		if (priv->current_image != NULL)
 			image_viewer_image_zoom_centered (next,
-				image_viewer_image_get_zoom_level (priv->image));
+				image_viewer_image_get_zoom_level (priv->current_image));
 		break;
 
 	case GTH_ZOOM_CHANGE_FIT_SIZE:
@@ -1682,14 +1818,35 @@
 	if (priv->play_animation)
 		image_viewer_image_start_animation (next);
 
-	if (priv->image != NULL)
-		g_object_unref (priv->image);
-
-	priv->image = next;
-
 	g_signal_connect (G_OBJECT (next), "zoom_changed",
 			  G_CALLBACK (zoom_changed_cb), viewer);
 
+	if (priv->use_transitions && priv->transitions != NULL) {
+		GType          transition_type;
+
+		if (priv->next_image != NULL) {
+			if (priv->current_image != NULL)
+				g_object_unref (priv->current_image);
+			priv->current_image = priv->next_image;
+		}
+		priv->next_image = next;
+
+		transition_type = GPOINTER_TO_SIZE (g_slist_nth_data (
+					priv->transitions,
+					g_random_int_range (0, priv->transitions_length)));
+
+		if (priv->current_transition != NULL)
+			g_object_unref (priv->current_transition);
+
+		priv->current_transition = gth_transition_new (transition_type,
+							       viewer);
+	} else {
+		if (priv->current_image != NULL)
+			g_object_unref (priv->current_image);
+
+		priv->current_image = next;
+	}
+
 	gtk_widget_queue_resize (GTK_WIDGET (viewer));
 }
 
@@ -1760,9 +1917,11 @@
 
 	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
-	g_return_if_fail (priv->image != NULL);
+	if (priv->current_image != NULL)
+		image_viewer_image_zoom_in_centered (priv->current_image);
 
-	image_viewer_image_zoom_in_centered (priv->image);
+	if (priv->next_image != NULL)
+		image_viewer_image_zoom_in_centered (priv->next_image);
 }
 
 
@@ -1775,9 +1934,11 @@
 
 	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
-	g_return_if_fail (priv->image != NULL);
+	if (priv->current_image != NULL)
+		image_viewer_image_zoom_out_centered (priv->current_image);
 
-	image_viewer_image_zoom_out_centered (priv->image);
+	if (priv->next_image != NULL)
+		image_viewer_image_zoom_out_centered (priv->next_image);
 }
 
 
@@ -1793,13 +1954,11 @@
 
 	priv->fit = fit_mode;
 
-	if (priv->image)
-	{
-		image_viewer_image_set_fit_mode (priv->image, fit_mode);
+	if (priv->current_image != NULL)
+		image_viewer_image_set_fit_mode (priv->current_image, fit_mode);
 
-		/*if (fit_mode != GTH_FIT_NONE)
-			gtk_widget_queue_resize (GTK_WIDGET (viewer));*/
-	}
+	if (priv->next_image != NULL)
+		image_viewer_image_set_fit_mode (priv->next_image, fit_mode);
 }
 
 
@@ -2082,9 +2241,9 @@
 
 	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
-	g_return_if_fail (priv->image != NULL);
+	g_return_if_fail (priv->current_image != NULL);
 
-	image_viewer_image_get_scroll_offsets (priv->image, &xd, &yd);
+	image_viewer_image_get_scroll_offsets (priv->current_image, &xd, &yd);
 
 	*x = (int) xd;
 	*y = (int) yd;
@@ -2244,3 +2403,27 @@
 	return priv->frame_visible;
 }
 
+
+gboolean
+image_viewer_get_use_transitions (ImageViewer *viewer)
+{
+	ImageViewerPrivate *priv;
+
+	g_return_val_if_fail (viewer != NULL, FALSE);
+
+	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
+	return priv->use_transitions;
+}
+ 
+void
+image_viewer_set_use_transitions (ImageViewer *viewer,
+				  gboolean     use_transitions)
+{
+	ImageViewerPrivate *priv;
+
+	g_return_if_fail (viewer != NULL);
+
+	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
+	priv->use_transitions = use_transitions;
+}
+

=== modified file 'libgthumb/image-viewer.h'
--- libgthumb/image-viewer.h	2008-07-10 05:24:11 +0000
+++ libgthumb/image-viewer.h	2008-08-11 03:27:17 +0000
@@ -148,6 +148,10 @@
 						      GthCheckSize     check_size);
 GthCheckSize   image_viewer_get_check_size           (ImageViewer     *viewer);
 
+gboolean       image_viewer_get_use_transitions      (ImageViewer *viewer);
+void           image_viewer_set_use_transitions      (ImageViewer *viewer,
+						      gboolean     use_transitions);
+
 /* misc. */
 
 void           image_viewer_clicked                  (ImageViewer     *viewer);

=== modified file 'libgthumb/preferences.c'
--- libgthumb/preferences.c	2007-12-07 20:34:33 +0000
+++ libgthumb/preferences.c	2008-08-11 03:27:17 +0000
@@ -635,3 +635,44 @@
 	gtk_window_present (window);
 	*/
 }
+
+
+GSList*
+pref_get_slideshow_transitions (void)
+{
+	GSList *typelist = NULL;
+	GSList *strlist = eel_gconf_get_string_list (PREF_SLIDESHOW_TRANSITIONS);
+	GSList *iter;
+
+	for (iter = strlist; iter != NULL; iter = iter->next) {
+		GType type = g_type_from_name (iter->data);
+
+		g_free (iter->data);
+
+		if (type != 0)
+			typelist = g_slist_prepend (typelist, GSIZE_TO_POINTER (type));
+	}
+
+	g_slist_free (strlist);
+
+	return typelist;
+
+}
+
+
+void
+pref_set_slideshow_transitions (const GSList* typelist)
+{
+	GSList* strlist = NULL;
+
+	while (typelist != NULL) {
+		strlist = g_slist_prepend (strlist, (gpointer*) g_type_name (
+					GPOINTER_TO_SIZE (typelist->data)));
+		typelist = typelist->next;
+	}
+
+	eel_gconf_set_string_list (PREF_SLIDESHOW_TRANSITIONS, strlist);
+
+	g_slist_free (strlist);
+}
+

=== modified file 'libgthumb/preferences.h'
--- libgthumb/preferences.h	2008-02-14 13:08:11 +0000
+++ libgthumb/preferences.h	2008-08-11 03:27:17 +0000
@@ -74,7 +74,7 @@
 #define  PREF_SLIDESHOW_DIR          "/apps/gthumb/slideshow/direction"
 #define  PREF_SLIDESHOW_DELAY        "/apps/gthumb/slideshow/change_delay"
 #define  PREF_SLIDESHOW_WRAP_AROUND  "/apps/gthumb/slideshow/wrap_around"
-#define  PREF_SLIDESHOW_FADING       "/apps/gthumb/slideshow/fading"
+#define  PREF_SLIDESHOW_TRANSITIONS  "/apps/gthumb/slideshow/transitions"
 
 #define  PREF_HOTKEY_PREFIX          "/apps/gthumb/hotkeys/hotkey"
 
@@ -328,5 +328,7 @@
 GthCropRatio       pref_get_crop_ratio             (void);
 GthSubFolder       pref_get_import_subfolder       (void);
 void               pref_set_import_subfolder       (GthSubFolder value);
+GSList*            pref_get_slideshow_transitions  (void);
+void               pref_set_slideshow_transitions  (const GSList* list);
 
 #endif /* PREFERENCES_H */

=== added directory 'modules'
=== added file 'modules/Makefile.am'
--- modules/Makefile.am	1970-01-01 00:00:00 +0000
+++ modules/Makefile.am	2008-08-11 03:27:17 +0000
@@ -0,0 +1,1 @@
+SUBDIRS = transitions

=== added directory 'modules/transitions'
=== added file 'modules/transitions/Makefile.am'
--- modules/transitions/Makefile.am	1970-01-01 00:00:00 +0000
+++ modules/transitions/Makefile.am	2008-08-11 03:27:17 +0000
@@ -0,0 +1,17 @@
+AM_CPPFLAGS = $(GTHUMB_CFLAGS)
+
+LIBADD = $(GTHUMB_LIBS)				\
+	 $(top_builddir)/libgthumb/libgthumb.la
+
+AM_LDFLAGS = -avoid-version -module
+
+transitionsdir = $(libdir)/gthumb/modules/transitions
+
+transitions_LTLIBRARIES = crossfade.la tobackground.la
+
+crossfade_la_SOURCES = crossfade.c
+crossfade_la_LIBADD = $(LIBADD)
+
+tobackground_la_SOURCES = tobackground.c
+tobackground_la_LIBADD = $(LIBADD)
+

=== added file 'modules/transitions/crossfade.c'
--- modules/transitions/crossfade.c	1970-01-01 00:00:00 +0000
+++ modules/transitions/crossfade.c	2008-08-11 03:48:23 +0000
@@ -0,0 +1,97 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2001-2008 The Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <glib/gi18n.h>
+
+#include <libgthumb/gth-module.h>
+#include <libgthumb/gth-transition.h>
+
+#define GTH_TRANSITION_CROSSFADE_TYPE            (gth_transition_crossfade_get_type ())
+#define GTH_TRANSITION_CROSSFADE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TRANSITION_CROSSFADE_TYPE, GthTransitionCrossfade))
+#define GTH_TRANSITION_CROSSFADE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TRANSITION_CROSSFADE_TYPE, GthTransitionCrossfadeClass))
+#define IS_GTH_TRANSITION_CROSSFADE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TRANSITION_CROSSFADE_TYPE))
+#define IS_GTH_TRANSITION_CROSSFADE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TRANSITION_CROSSFADE_TYPE))
+#define GTH_TRANSITION_CROSSFADE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TRANSITION_CROSSFADE_TYPE, GthTransitionCrossfadeClass))
+
+typedef struct _GthTransitionCrossfade      GthTransitionCrossfade;
+typedef struct _GthTransitionCrossfadeClass GthTransitionCrossfadeClass;
+
+struct _GthTransitionCrossfade
+{
+	GthTransition parent;
+};
+
+struct _GthTransitionCrossfadeClass
+{
+	GthTransitionClass parent;
+};
+
+
+GTH_DEFINE_MODULE (GthTransitionCrossfade, gth_transition_crossfade, GTH_TRANSITION_TYPE)
+
+static gboolean compose (GthTransition   *transition, cairo_t *cr,
+			 cairo_surface_t *image1,     cairo_surface_t *image2,
+			 gint             width,      gint             height);
+
+static void
+gth_transition_crossfade_class_init (GthTransitionCrossfadeClass *klass)
+{
+	GthTransitionClass *transition_class = GTH_TRANSITION_CLASS (klass);
+	transition_class->name    = _("Crossfade");
+	transition_class->compose = compose;
+}
+
+static void
+gth_transition_crossfade_class_finalize (GthTransitionCrossfadeClass *klass)
+{ }
+
+
+static void
+gth_transition_crossfade_init (GthTransitionCrossfade *transition)
+{ }
+
+static gboolean
+compose (GthTransition   *transition, cairo_t *cr,
+	 cairo_surface_t *image1,     cairo_surface_t *image2,
+	 gint             width,      gint             height)
+{
+	double amount = gth_transition_get_elapsed_time (transition) /
+				gth_transition_get_length ();
+	amount = CLAMP(amount, 0, 1);
+
+	if (image1 != NULL && image2 != NULL) {
+		cairo_set_source_surface (cr, image1, 0, 0);
+		cairo_paint_with_alpha (cr, 1 - amount);
+		cairo_set_source_surface (cr, image2, 0, 0);
+		cairo_paint_with_alpha (cr, amount);
+	}
+	else if (image1 != NULL) {
+		cairo_set_source_surface (cr, image1, 0, 0);
+		cairo_paint_with_alpha (cr, 1 - amount);
+	}
+	else if (image2 != NULL) {
+		cairo_set_source_surface (cr, image2, 0, 0);
+		cairo_paint_with_alpha (cr, amount);
+	}
+
+	return amount < 1;
+}

=== added file 'modules/transitions/tobackground.c'
--- modules/transitions/tobackground.c	1970-01-01 00:00:00 +0000
+++ modules/transitions/tobackground.c	2008-08-11 03:27:17 +0000
@@ -0,0 +1,91 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2001-2008 The Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <glib/gi18n.h>
+
+#include <libgthumb/gth-module.h>
+#include <libgthumb/gth-transition.h>
+
+#define GTH_TRANSITION_TOBACKGROUND_TYPE            (gth_transition_to_background_get_type ())
+#define GTH_TRANSITION_TOBACKGROUND(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TRANSITION_TOBACKGROUND_TYPE, GthTransitionToBackground))
+#define GTH_TRANSITION_TOBACKGROUND_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TRANSITION_TOBACKGROUND_TYPE, GthTransitionToBackgroundClass))
+#define IS_GTH_TRANSITION_TOBACKGROUND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TRANSITION_TOBACKGROUND_TYPE))
+#define IS_GTH_TRANSITION_TOBACKGROUND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TRANSITION_TOBACKGROUND_TYPE))
+#define GTH_TRANSITION_TOBACKGROUND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TRANSITION_TOBACKGROUND_TYPE, GthTransitionToBackgroundClass))
+
+typedef struct _GthTransitionToBackground      GthTransitionToBackground;
+typedef struct _GthTransitionToBackgroundClass GthTransitionToBackgroundClass;
+
+struct _GthTransitionToBackground
+{
+	GthTransition parent;
+};
+
+struct _GthTransitionToBackgroundClass
+{
+	GthTransitionClass parent;
+};
+
+
+GTH_DEFINE_MODULE (GthTransitionToBackground, gth_transition_to_background, GTH_TRANSITION_TYPE)
+
+static gboolean compose (GthTransition   *transition, cairo_t *cr,
+			 cairo_surface_t *image1,     cairo_surface_t *image2,
+			 gint             width,      gint             height);
+
+static void
+gth_transition_to_background_class_init (GthTransitionToBackgroundClass *klass)
+{
+	GthTransitionClass *transition_class = GTH_TRANSITION_CLASS (klass);
+	transition_class->name    = _("Fade to Background");
+	transition_class->compose = compose;
+}
+
+static void
+gth_transition_to_background_class_finalize (GthTransitionToBackgroundClass *klass)
+{ }
+
+
+static void
+gth_transition_to_background_init (GthTransitionToBackground *transition)
+{ }
+
+static gboolean
+compose (GthTransition   *transition, cairo_t *cr,
+	 cairo_surface_t *image1,     cairo_surface_t *image2,
+	 gint             width,      gint             height)
+{
+	double amount = gth_transition_get_elapsed_time (transition) /
+				gth_transition_get_length ();
+	amount = CLAMP (amount, 0, 1);
+
+	if (amount < 0.5 && image1 != NULL) {
+		cairo_set_source_surface (cr, image1, 0, 0);
+		cairo_paint_with_alpha (cr, 1 - amount * 2);
+	}
+	else if (amount >= 0.5 && image2 != NULL) {
+		cairo_set_source_surface (cr, image2, 0, 0);
+		cairo_paint_with_alpha (cr, amount * 2 - 1);
+	}
+
+	return amount < 1;
+}

=== modified file 'po/POTFILES.in'
--- po/POTFILES.in	2007-12-13 17:52:35 +0000
+++ po/POTFILES.in	2008-08-11 03:27:17 +0000
@@ -52,8 +52,14 @@
 libgthumb/gth-gstreamer-utils.h
 libgthumb/gth-image-list.c
 libgthumb/gth-image-list.h
+libgthumb/gth-module.c
+libgthumb/gth-module.h
 libgthumb/gth-pixbuf-op.c
 libgthumb/gth-pixbuf-op.h
+libgthumb/gth-transition.c
+libgthumb/gth-transition.h
+libgthumb/gth-transition-manager.c
+libgthumb/gth-transition-manager.h
 libgthumb/gth-utils.c
 libgthumb/gth-utils.h
 libgthumb/gthumb-error.c
@@ -76,6 +82,9 @@
 libgthumb/image-loader.h
 libgthumb/image-viewer.c
 libgthumb/image-viewer.h
+libgthumb/image-viewer-enums.h
+libgthumb/image-viewer-image.c
+libgthumb/image-viewer-image.h
 libgthumb/nav-window.c
 libgthumb/nav-window.h
 libgthumb/pixbuf-utils.c
@@ -91,6 +100,8 @@
 libgthumb/thumb-loader.c
 libgthumb/thumb-loader.h
 libgthumb/typedefs.h
+modules/transitions/crossfade.c
+modules/transitions/tobackground.c
 src/albumtheme.c
 src/albumtheme-private.c
 src/albumtheme-private.h

=== modified file 'src/Makefile.am'
--- src/Makefile.am	2008-07-10 20:38:00 +0000
+++ src/Makefile.am	2008-08-11 03:27:17 +0000
@@ -157,7 +157,6 @@
 	$(TIFF_LIBS)				\
 	$(RENDER_LIBS)				\
 	$(GPHOTO_LIBS)				\
-	$(XF86GAMMA_LIBS)			\
 	$(XTEST_LIBS)				\
 	$(GTKUNIQUE_LIBS)
 

=== modified file 'src/dlg-preferences.c'
--- src/dlg-preferences.c	2008-07-10 20:38:00 +0000
+++ src/dlg-preferences.c	2008-08-11 03:27:17 +0000
@@ -36,6 +36,7 @@
 #include "thumb-cache.h"
 #include "comments.h"
 #include "file-utils.h"
+#include "gth-transition.h"
 #include "gth-utils.h"
 #include "gtk-utils.h"
 #include "main.h"
@@ -96,6 +97,11 @@
 
 	GtkWidget  *toggle_reset_scrollbars;
 
+	GtkListStore    *transition_store;
+	GtkWidget       *opt_transition_mode;
+	GtkWidget       *transition_list;
+	GtkCellRenderer *toggle_transition_active;
+
 	GtkWidget  *radio_ss_direction_forward;
 	GtkWidget  *radio_ss_direction_reverse;
 	GtkWidget  *radio_ss_direction_random;
@@ -104,6 +110,12 @@
 
 } DialogData;
 
+enum {
+	COL_ACTIVE,
+	COL_NAME,
+	COL_TYPE,
+	NUM_COLS
+};
 
 /* called when the main dialog is closed. */
 static void
@@ -120,7 +132,11 @@
 apply_cb (GtkWidget  *widget,
 	  DialogData *data)
 {
-	GthDirectionType direction = GTH_DIRECTION_FORWARD;
+	GthDirectionType  direction = GTH_DIRECTION_FORWARD;
+	GtkTreeIter       iter;
+	GSList           *transitions = NULL;
+	gboolean          active;
+	GType             transition_type;
 
 	/* Startup dir. */
 
@@ -144,6 +160,24 @@
 
 	/**/
 
+	/* Serialize transition selection to pref string. */
+	if (gtk_option_menu_get_history (GTK_OPTION_MENU (data->opt_transition_mode)) != 0 &&
+	    gtk_tree_model_get_iter_first (GTK_TREE_MODEL (data->transition_store), &iter))
+		do {
+			gtk_tree_model_get (GTK_TREE_MODEL (data->transition_store), &iter,
+					COL_ACTIVE, &active,
+					COL_TYPE, &transition_type,
+					-1);
+			if (active)
+				transitions = g_slist_prepend (transitions, GSIZE_TO_POINTER (transition_type));
+
+		} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (data->transition_store), &iter));
+
+	pref_set_slideshow_transitions (transitions);
+	g_slist_free (transitions);
+
+	/**/
+
 	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->radio_ss_direction_forward)))
 		direction = GTH_DIRECTION_FORWARD;
 	else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->radio_ss_direction_reverse)))
@@ -368,16 +402,119 @@
 }
 
 
+static void
+transition_toggled_cb (GtkCellRendererToggle *toggle,
+		       gchar                 *path,
+		       DialogData            *data)
+{
+	gint         mode = gtk_option_menu_get_history (GTK_OPTION_MENU (data->opt_transition_mode));
+	GtkTreeIter  iter;
+	gboolean     active;
+
+	switch (mode)
+	{
+		case 1:
+			/* Disable all transitions, enable only the one selected in path */
+			if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (data->transition_store), &iter))
+				do {
+					gtk_list_store_set (data->transition_store, &iter,
+							COL_ACTIVE, FALSE,
+							-1);
+				} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (data->transition_store), &iter));
+
+			gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (data->transition_store), &iter, path);
+			gtk_list_store_set (data->transition_store, &iter,
+					    COL_ACTIVE, TRUE);
+
+			break;
+		case 2:
+			/* Toggles the value of thing selected in path. */
+			gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (data->transition_store), &iter, path);
+			gtk_tree_model_get (GTK_TREE_MODEL (data->transition_store), &iter,
+					    COL_ACTIVE, &active,
+					    -1);
+			gtk_list_store_set (data->transition_store, &iter,
+					    COL_ACTIVE, !active,
+					    -1);
+			break;
+		default:
+			g_assert_not_reached ();
+	}
+}
+
+static void
+transition_mode_changed_cb (GtkOptionMenu *option_menu,
+			    DialogData    *data)
+{
+	gint mode = gtk_option_menu_get_history (GTK_OPTION_MENU (data->opt_transition_mode));
+
+	gtk_widget_set_sensitive (GTK_WIDGET (data->transition_list), mode != 0);
+
+	if (mode == 1) {
+		GtkTreeIter iter;
+		gboolean first = TRUE;
+
+		/* Disable all transitions except first transition set */
+		if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (data->transition_store), &iter))
+			do {
+				gboolean current;
+
+				gtk_tree_model_get (GTK_TREE_MODEL (data->transition_store), &iter,
+						   COL_ACTIVE, &current, -1);
+
+				gtk_list_store_set (data->transition_store, &iter,
+						    COL_ACTIVE, current && first,
+						    -1);
+
+				if (current && first)
+					first = FALSE;
+
+			} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (data->transition_store), &iter));
+	}
+		
+	/* Change cell renderer to use radio buttons or check boxes as appropriate */
+	gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (data->toggle_transition_active), mode == 1);
+}
+
+
+static gint
+transition_sort_byname (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data)
+{
+	gchar *str_a, *str_b;
+	gchar *casefold_a, *casefold_b;
+	gint ret;
+	gtk_tree_model_get (model, a, COL_NAME, &str_a, -1);
+	gtk_tree_model_get (model, b, COL_NAME, &str_b, -1);
+
+	casefold_a = g_utf8_casefold (str_a, -1);
+	g_free (str_a);
+
+	casefold_b = g_utf8_casefold (str_b, -1);
+	g_free (str_b);
+
+	ret = g_utf8_collate (casefold_a, casefold_b);
+
+	g_free (casefold_a);
+	g_free (casefold_b);
+
+	return ret;
+}
+
 /* create the main dialog. */
 void
 dlg_preferences (GthBrowser *browser)
 {
-	DialogData       *data;
-	GtkWidget        *btn_close;
-	GtkWidget        *btn_help;
-	int               layout_type;
-	char             *startup_location;
-	GthDirectionType  direction;
+	DialogData        *data;
+	GtkWidget         *btn_close;
+	GtkWidget         *btn_help;
+	int                layout_type;
+	char              *startup_location;
+	GthDirectionType   direction;
+	GtkTreeViewColumn *column;
+	GtkCellRenderer   *renderer;
+	GType             *transitions, *iter;
+	GSList            *enabled_transitions;
+	guint              num_enabled_transitions = 0;
 
 	data = g_new0 (DialogData, 1);
 	data->browser = browser;
@@ -428,6 +565,54 @@
 
 	data->toggle_reset_scrollbars = glade_xml_get_widget (data->gui, "toggle_reset_scrollbars");
 
+	data->opt_transition_mode = glade_xml_get_widget (data->gui, "opt_transition_mode");
+	data->transition_list = glade_xml_get_widget (data->gui, "transition_list");
+
+	gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (data->transition_list)),
+				     GTK_SELECTION_NONE);
+
+	data->toggle_transition_active = gtk_cell_renderer_toggle_new ();
+	g_signal_connect (G_OBJECT (data->toggle_transition_active), "toggled", G_CALLBACK (transition_toggled_cb), data);
+
+	column = gtk_tree_view_column_new ();
+	gtk_tree_view_column_pack_start (column, data->toggle_transition_active, FALSE);
+	gtk_tree_view_column_add_attribute (column, data->toggle_transition_active, "active", COL_ACTIVE);
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_tree_view_column_pack_start (column, renderer, TRUE);
+	gtk_tree_view_column_add_attribute (column, renderer, "text", COL_NAME);
+	gtk_tree_view_insert_column (GTK_TREE_VIEW (data->transition_list), column, -1);
+
+	data->transition_store = gtk_list_store_new (3, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_GTYPE);
+
+	enabled_transitions = pref_get_slideshow_transitions ();
+	transitions = g_type_children (GTH_TRANSITION_TYPE, NULL);
+	for (iter = transitions; *iter != 0; iter++) {
+		GthTransitionClass *klass = GTH_TRANSITION_CLASS (g_type_class_ref(*iter));
+		GtkTreeIter row;
+		gboolean    active = (g_slist_find (enabled_transitions, GSIZE_TO_POINTER(*iter)) != NULL);
+
+		if (active)
+			num_enabled_transitions++;
+
+		gtk_list_store_append (data->transition_store, &row);
+		gtk_list_store_set (data->transition_store, &row,
+				    COL_ACTIVE, active,
+				    COL_NAME, klass->name,
+				    COL_TYPE, *iter,
+				    -1);
+		g_type_class_unref (klass);
+	}
+
+	g_slist_free (enabled_transitions);
+	g_free (transitions);
+
+	gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (data->transition_store), transition_sort_byname, NULL, NULL);
+	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (data->transition_store),
+					      GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
+					      GTK_SORT_ASCENDING);
+	gtk_tree_view_set_model (GTK_TREE_VIEW (data->transition_list),
+				 GTK_TREE_MODEL (data->transition_store));
+
         data->radio_ss_direction_forward = glade_xml_get_widget (data->gui, "radio_ss_direction_forward");
         data->radio_ss_direction_reverse = glade_xml_get_widget (data->gui, "radio_ss_direction_reverse");
         data->radio_ss_direction_random = glade_xml_get_widget (data->gui, "radio_ss_direction_random");
@@ -522,6 +707,12 @@
 				   eel_gconf_get_float (PREF_SLIDESHOW_DELAY, 4.0));
 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->toggle_ss_wrap_around), eel_gconf_get_boolean (PREF_SLIDESHOW_WRAP_AROUND, FALSE));
 
+	if (num_enabled_transitions > 2)
+		num_enabled_transitions = 2;
+
+	gtk_option_menu_set_history (GTK_OPTION_MENU (data->opt_transition_mode), num_enabled_transitions);
+	transition_mode_changed_cb (GTK_OPTION_MENU (data->opt_transition_mode), data);
+
 	/* Set the signals handlers. */
 
 	g_signal_connect (G_OBJECT (data->dialog),
@@ -630,6 +821,11 @@
                           G_CALLBACK (reset_scrollbars_toggled_cb),
                           data);
 
+        g_signal_connect (G_OBJECT (data->opt_transition_mode),
+        		  "changed",
+        		  G_CALLBACK (transition_mode_changed_cb),
+        		  data);
+
 	/* run dialog. */
 
 	gtk_window_set_transient_for (GTK_WINDOW (data->dialog),

=== modified file 'src/gth-fullscreen.c'
--- src/gth-fullscreen.c	2008-07-31 01:04:16 +0000
+++ src/gth-fullscreen.c	2008-08-11 03:27:17 +0000
@@ -73,7 +73,6 @@
 	GthDirectionType slideshow_direction;
 	int              slideshow_delay;
 	gboolean         slideshow_wrap_around;
-	gboolean         fading_activated;
 	guint            slideshow_timeout;
 	guint            slideshow_paused;
 
@@ -1588,6 +1587,7 @@
 				       pref_get_transp_type ());
 	image_viewer_set_black_background (IMAGE_VIEWER (priv->viewer), TRUE);
 	image_viewer_hide_frame (IMAGE_VIEWER (priv->viewer));
+	image_viewer_set_use_transitions (IMAGE_VIEWER (priv->viewer), TRUE);
 
 	if (zoom_change == GTH_ZOOM_CHANGE_FIT_SIZE)
 		image_viewer_set_fit_mode (IMAGE_VIEWER (priv->viewer), GTH_FIT_SIZE);
@@ -1770,7 +1770,6 @@
 	priv->slideshow_direction = pref_get_slideshow_direction ();
 	priv->slideshow_delay = eel_gconf_get_float (PREF_SLIDESHOW_DELAY, DEF_SLIDESHOW_DELAY);
 	priv->slideshow_wrap_around = eel_gconf_get_boolean (PREF_SLIDESHOW_WRAP_AROUND, FALSE);
-	priv->fading_activated = eel_gconf_get_boolean (PREF_SLIDESHOW_FADING, TRUE);
 
 	image_viewer_hide_cursor (IMAGE_VIEWER (priv->viewer));
 

=== modified file 'src/main.c'
--- src/main.c	2008-05-16 15:06:55 +0000
+++ src/main.c	2008-08-11 03:27:17 +0000
@@ -63,18 +63,19 @@
 					   "gnome-fs-home",
 					   "gnome-fs-desktop" };
 
-GthMonitor    *gth_monitor = NULL;
-GList         *file_urls = NULL, *dir_urls = NULL;
-int            n_file_urls, n_dir_urls;
-int            StartInFullscreen = FALSE;
-int            StartSlideshow = FALSE;
-int            ViewFirstImage = FALSE;
-int            HideSidebar = FALSE;
-gboolean       ExitAll = FALSE;
-char          *ImageToDisplay = NULL;
-gboolean       FirstStart = TRUE;
-gboolean       ImportPhotos = FALSE;
-gboolean       UseViewer = FALSE;
+GthMonitor           *gth_monitor = NULL;
+GthTransitionManager *transition_manager = NULL;
+GList                *file_urls = NULL, *dir_urls = NULL;
+int                   n_file_urls, n_dir_urls;
+int                   StartInFullscreen = FALSE;
+int                   StartSlideshow = FALSE;
+int                   ViewFirstImage = FALSE;
+int                   HideSidebar = FALSE;
+gboolean              ExitAll = FALSE;
+char                 *ImageToDisplay = NULL;
+gboolean              FirstStart = TRUE;
+gboolean              ImportPhotos = FALSE;
+gboolean              UseViewer = FALSE;
 
 static gboolean         view_comline_catalog = FALSE;
 static gboolean         view_single_image = FALSE;
@@ -424,6 +425,8 @@
 
 	gth_monitor = gth_monitor_new ();
 
+	transition_manager = gth_transition_manager_new ();
+
 	/* Icon theme */
 
 	icon_theme = gtk_icon_theme_get_default ();
@@ -525,6 +528,11 @@
 		gth_monitor = NULL;
 	}
 
+	if (transition_manager != NULL) {
+		g_object_unref (transition_manager);
+		transition_manager = NULL;
+	}
+
 	gthumb_release ();
 	eel_global_client_free ();
 }

=== modified file 'src/main.h'
--- src/main.h	2007-12-07 20:28:57 +0000
+++ src/main.h	2008-08-11 03:27:17 +0000
@@ -29,6 +29,7 @@
 
 #include "image-viewer.h"
 #include "gth-monitor.h"
+#include "gth-transition-manager.h"
 #include "gth-window.h"
 #include "preferences.h"
 
@@ -36,19 +37,20 @@
 extern GtkUniqueApp     *gth_application;
 #endif /* HAVE_GTKUNIQUE */
 
-extern GthWindow        *current_window;
-extern GthMonitor       *gth_monitor;
-extern Preferences       preferences;
+extern GthWindow            *current_window;
+extern GthMonitor           *gth_monitor;
+extern GthTransitionManager *transition_manager;
+extern Preferences           preferences;
 
-extern gboolean          StartInFullscreen;
-extern gboolean          StartSlideshow;
-extern gboolean          ViewFirstImage;
-extern gboolean          HideSidebar;
-extern gboolean          ExitAll;
-extern char             *ImageToDisplay;
-extern gboolean          FirstStart;
-extern gboolean          ImportPhotos;
-extern gboolean          UseViewer;
+extern gboolean              StartInFullscreen;
+extern gboolean              StartSlideshow;
+extern gboolean              ViewFirstImage;
+extern gboolean              HideSidebar;
+extern gboolean              ExitAll;
+extern char                 *ImageToDisplay;
+extern gboolean              FirstStart;
+extern gboolean              ImportPhotos;
+extern gboolean              UseViewer;
 
 #define MENU_ICON_SIZE 20.0
 #define LIST_ICON_SIZE 20.0

