[gcompris/gcomprixogoo] Initial support of Sugar look&feel



commit 7a32affa58b261331066055be69daf4172ab971a
Author: Aleksey Lim <alsroot member fsf org>
Date:   Mon Jan 11 23:14:13 2010 +0000

    Initial support of Sugar look&feel

 configure.ac                                       |   31 ++-
 src/boards/goocanvasmodule.c                       |    3 +-
 src/boards/py-mod-gcompris.c                       |    7 +-
 src/gcompris/Makefile.am                           |    6 +
 src/gcompris/bar.c                                 |  103 +++++-
 src/gcompris/bar.h                                 |   36 ++
 src/gcompris/config.c                              |   34 ++
 src/gcompris/gcompris.c                            |  172 ++++++----
 src/gcompris/gcompris.h                            |   12 +-
 src/gcompris/properties.c                          |    9 +-
 src/gcompris/properties.h                          |    1 +
 src/gcompris/score.c                               |   49 +++-
 src/gcompris/score.h                               |    9 +
 src/gcompris/sugar.c                               |  362 ++++++++++++++++++++
 src/gletters-activity/gletters.c                   |    7 +-
 src/paratrooper-activity/paratrooper.c             |    9 +-
 .../resources/redraw_symmetrical/Makefile.am       |    2 +-
 src/smallnumbers-activity/smallnumbers.c           |    5 +-
 src/wordsgame-activity/wordsgame.c                 |    3 +-
 19 files changed, 741 insertions(+), 119 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 0956c0e..cb4315d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -45,6 +45,8 @@ AM_GLIB_GNU_GETTEXT
 #*******************************************************************************
 
 GTK_REQUIRED=2.4.0
+LIBRSVG_REQUIRED=2.26.0
+LIBXML_REQUIRED=2.7.3
 
 dnl
 dnl Start of pkg-config checks
@@ -53,8 +55,8 @@ dnl
 PKG_CHECK_MODULES(GCOMPRIS, \
   gtk+-2.0 >= $GTK_REQUIRED \
   gstreamer-0.10 \
-  librsvg-2.0 \
-  libxml-2.0)
+  librsvg-2.0 >= $LIBRSVG_REQUIRED \
+  libxml-2.0 >= $LIBXML_REQUIRED)
 
 AC_SUBST(GCOMPRIS_CFLAGS)
 AC_SUBST(GCOMPRIS_LIBS)
@@ -409,6 +411,23 @@ if test x$with_dbus = xyes; then
   AC_DEFINE([USE_DBUS], 1,[DBUS support is enabled])
 fi
 
+dnl Sugar DE support
+AC_MSG_CHECKING([wether we build with Sugar DE support])
+AC_ARG_ENABLE(sugar,
+          AC_HELP_STRING(
+          [--enable-sugar],
+          [Turn on sugar support (will let GCompris integrate well on Sugar DE)]),
+          with_sugar="$enableval", with_sugar="no")
+AC_MSG_RESULT($with_sugar)
+if test x$with_sugar = xyes; then
+  if test x$with_dbus = xno; then
+    AC_MSG_ERROR([You need to add DBUS support as well.])
+  fi
+  PKG_CHECK_MODULES(SUGAR, [sugar-toolkit])
+  AC_DEFINE([USE_SUGAR], 1, [Sugar DE support is enabled])
+fi
+AM_CONDITIONAL([SUGAR], [test x$with_sugar = xyes])
+
 dnl check for python
 AC_ARG_WITH(python,AC_HELP_STRING(
     [--with-python=path],
@@ -422,7 +441,7 @@ if test x$python_path != xnot ; then
 PYTHON=$python_path
 fi
 
-AM_PATH_PYTHON(2.6)
+AM_PATH_PYTHON
 AM_CHECK_PYTHON_HEADERS( [build_python_plugin="yes"], [build_python_plugin="no"] )
 
 fi
@@ -442,7 +461,10 @@ if test x$build_python_plugin = xno; then
   AC_MSG_NOTICE([Python plugin is disabled.])
 else
   dnl Python interpreter is available so check for pygtk
-  PKG_CHECK_MODULES(PYGTK, pygtk-2.0 pycairo >= 1.8)
+  PKG_CHECK_MODULES(PYGTK, pygtk-2.0 pycairo)
+
+  PYCAIRO_VERSION=$(pkg-config pycairo --modversion | awk -F. '{print ($1 * 1000) + $2 }')
+  AC_DEFINE_UNQUOTED([PYCAIRO_VERSION], $PYCAIRO_VERSION, [pycairo version])
 
   AC_MSG_CHECKING([for pygtk defs])
   PYGTK_DEFSDIR=`$PKG_CONFIG --variable=defsdir pygtk-2.0`
@@ -834,6 +856,7 @@ echo "Python plugin                            = $build_python_plugin"
 echo "SQLITE database (--enable-sqlite)        = $with_sqlite (profiles depend on this)"
 
 echo "DBUS Support (OLPC XO Sugar)             = $with_dbus"
+echo "Sugar DE Support                         = $with_sugar"
 echo "GNET Networking (--enable-gnet)          = $with_gnet (networking depends on this)"
 echo "BINRELOC (--enable-binreloc)             = $br_cv_binreloc"
 echo "NSBundle (--enable-nsbundle)             = $nsbundle"
diff --git a/src/boards/goocanvasmodule.c b/src/boards/goocanvasmodule.c
index 4e68ce1..422478f 100644
--- a/src/boards/goocanvasmodule.c
+++ b/src/boards/goocanvasmodule.c
@@ -35,8 +35,7 @@ _cairo_matrix_to_gvalue(GValue *value, PyObject *obj)
 static PyObject *
 _cairo_pattern_from_gvalue(const GValue *value)
 {
-#if defined WIN32
-    // On windows we have the old cairo API for now
+#if PYCAIRO_VERSION < 1008
     return PycairoPattern_FromPattern(cairo_pattern_reference((cairo_pattern_t *) g_value_get_boxed(value)));
 #else
     return PycairoPattern_FromPattern(cairo_pattern_reference((cairo_pattern_t *) g_value_get_boxed(value)), NULL);
diff --git a/src/boards/py-mod-gcompris.c b/src/boards/py-mod-gcompris.c
index 159b580..fc7a6ae 100644
--- a/src/boards/py-mod-gcompris.c
+++ b/src/boards/py-mod-gcompris.c
@@ -113,16 +113,19 @@ py_gc_board_end(PyObject* self, PyObject* args)
 static PyObject*
 py_gc_bar_start(PyObject* self, PyObject* args)
 {
+  PyObject* pyWorkspace;
   PyObject* pyCanvas;
+  GtkContainer* workspace;
   GooCanvas* canvas;
 
   /* Parse arguments */
-  if(!PyArg_ParseTuple(args, "O:gc_bar_start", &pyCanvas))
+  if(!PyArg_ParseTuple(args, "OO:gc_bar_start", &pyWorkspace, &pyCanvas))
     return NULL;
+  workspace = (GtkContainer*) pygobject_get(pyWorkspace);
   canvas = (GooCanvas*) pygobject_get(pyCanvas);
 
   /* Call the corresponding C function */
-  gc_bar_start(canvas);
+  gc_bar_start(workspace, canvas);
 
   /* Create and return the result */
   Py_INCREF(Py_None);
diff --git a/src/gcompris/Makefile.am b/src/gcompris/Makefile.am
index 367bc6c..06d7810 100644
--- a/src/gcompris/Makefile.am
+++ b/src/gcompris/Makefile.am
@@ -147,3 +147,9 @@ EXTRA_DIST = \
 DONT_DIST_SOURCE = $(marshal_sources)
 
 gcompris_nsbundle_CPPFLAGS = -fconstant-string-class=NSConstantString
+
+if SUGAR
+INCLUDES += $(SUGAR_CFLAGS)
+gcompris_SOURCES += sugar.c
+gcompris_LDADD += $(SUGAR_LIBS)
+endif
diff --git a/src/gcompris/bar.c b/src/gcompris/bar.c
index 7a06c72..a42c08e 100644
--- a/src/gcompris/bar.c
+++ b/src/gcompris/bar.c
@@ -27,6 +27,7 @@
 #include "gc_core.h"
 #include "gcompris_config.h"
 #include "about.h"
+#include "bar.h"
 
 #define SOUNDLISTFILE PACKAGE
 
@@ -47,7 +48,7 @@ static gboolean item_event_bar (GooCanvasItem  *item,
                                 GComprisBarFlags flag);
 static void	 bar_reset_sound_id (void);
 static gint	 bar_play_sound (GooCanvasItem *item);
-static void	 play_level_voice(int level);
+static void  bar_set (const GComprisBarFlags flags);
 
 static gint current_level = -1;
 static gint current_flags = 0;
@@ -146,7 +147,8 @@ new_button(GooCanvasItem *rootitem,
 /*
  * Do all the bar display and register the events
  */
-void gc_bar_start (GooCanvas *theCanvas)
+static void
+bar_start (GooCanvas *theCanvas)
 {
   GcomprisProperties *properties = gc_prop_get();
   gint16       height;
@@ -275,13 +277,14 @@ void gc_bar_start (GooCanvas *theCanvas)
 
   update_exit_button();
 
-  gc_bar_set(0);
+  bar_set(0);
 
   _hidden = FALSE;
 }
 
 
-void gc_bar_set_level(GcomprisBoard *gcomprisBoard)
+static void
+bar_set_level(GcomprisBoard *gcomprisBoard)
 {
 
   goo_canvas_item_raise(rootitem, NULL);
@@ -315,8 +318,8 @@ void gc_bar_set_level(GcomprisBoard *gcomprisBoard)
  * This must be called before calling gc_bar_set with GC_BAR_REPEAT_ICON
  * the given svg_handle is not freed.
  */
-void
-gc_bar_set_repeat_icon (RsvgHandle *svg_handle)
+static void
+bar_set_repeat_icon (RsvgHandle *svg_handle)
 {
   GooCanvasItem *item;
   goo_canvas_item_raise(rootitem, NULL);
@@ -338,8 +341,8 @@ gc_bar_set_repeat_icon (RsvgHandle *svg_handle)
  * @param[in] y the bar y coordinate, -1 to set the default
  * @param[in] zoom the bar zoom factor, -1 to set the default
  */
-void
-gc_bar_location (int x, int y, double zoom)
+static void
+bar_location (int x, int y, double zoom)
 {
   // Make the y coord be assigned at its bottom
   int ny = (y == -1 ? _default_y : y);
@@ -358,8 +361,8 @@ gc_bar_location (int x, int y, double zoom)
 }
 
 /* Setting list of available icons in the control bar */
-void
-gc_bar_set (const GComprisBarFlags flags)
+static void
+bar_set (const GComprisBarFlags flags)
 {
   // Always reset the zoom factor or the calculation
   // will be wrong
@@ -431,14 +434,14 @@ gc_bar_set (const GComprisBarFlags flags)
 
   // Always center the bar with its new bounds
   //SET_ITEM_LOCATION(rootitem, 0, _default_y);
-  gc_bar_location (-1, -1, -1);
+  bar_location (-1, -1, -1);
 }
 
 /* Hide all icons in the control bar
  * or restore the icons to the previous value
  */
-void
-gc_bar_hide (gboolean hide)
+static void
+bar_hide (gboolean hide)
 {
   /* Non yet initialized : Something Wrong */
   g_assert(rootitem);
@@ -542,8 +545,8 @@ on_leave_notify (GooCanvasItem  *item,
 
 /** Play the audio number given in @level
  */
-static void
-play_level_voice(int level)
+void
+gc_bar_play_level_voice(int level)
 {
   /* Play the audio level number */
   gchar *number_str = g_strdup_printf("%d", level);
@@ -591,7 +594,7 @@ item_event_bar (GooCanvasItem  *item,
         if(gcomprisBoard && gcomprisBoard->plugin->set_level != NULL)
           gcomprisBoard->plugin->set_level(current_level);
 
-        play_level_voice(current_level);
+        gc_bar_play_level_voice(current_level);
       }
       break;
     case GC_BAR_LEVEL_DOWN:
@@ -605,12 +608,12 @@ item_event_bar (GooCanvasItem  *item,
         if(gcomprisBoard && gcomprisBoard->plugin->set_level != NULL)
           gcomprisBoard->plugin->set_level(current_level);
 
-        play_level_voice(current_level);
+        gc_bar_play_level_voice(current_level);
       }
       break;
     case GC_BAR_HOME:
       {
-        gc_bar_hide (TRUE);
+        bar_hide (TRUE);
         gc_board_stop();
       }
       break;
@@ -668,3 +671,67 @@ confirm_quit(gboolean answer)
   if (answer)
     gc_exit();
 }
+
+/* bar registration */
+
+static Bar *custom_bar = NULL;
+
+void
+gc_bar_register (Bar *bar)
+{
+    custom_bar = bar;
+}
+
+void
+gc_bar_start (GtkContainer *workspace, GooCanvas *theCanvas)
+{
+    if (custom_bar == NULL)
+        bar_start (theCanvas);
+    else if (custom_bar->start != NULL)
+        custom_bar->start (workspace, theCanvas);
+}
+
+void
+gc_bar_set_level (GcomprisBoard *gcomprisBoard)
+{
+    if (custom_bar == NULL)
+        bar_set_level (gcomprisBoard);
+    else if (custom_bar->set_level != NULL)
+        custom_bar->set_level (gcomprisBoard);
+}
+
+void
+gc_bar_set_repeat_icon (RsvgHandle *svg_handle)
+{
+    if (custom_bar == NULL)
+        bar_set_repeat_icon (svg_handle);
+    else if (custom_bar->set_repeat_icon != NULL)
+        custom_bar->set_repeat_icon (svg_handle);
+}
+
+void
+gc_bar_location (int x, int y, double zoom)
+{
+    if (custom_bar == NULL)
+        bar_location (x, y, zoom);
+    else if (custom_bar->set_location != NULL)
+        custom_bar->set_location (x, y, zoom);
+}
+
+void
+gc_bar_set (const GComprisBarFlags flags)
+{
+    if (custom_bar == NULL)
+        bar_set (flags);
+    else if (custom_bar->set_flags != NULL)
+        custom_bar->set_flags (flags);
+}
+
+void
+gc_bar_hide (gboolean hide)
+{
+    if (custom_bar == NULL)
+        bar_hide (hide);
+    else if (custom_bar->set_hide != NULL)
+        custom_bar->set_hide (hide);
+}
diff --git a/src/gcompris/bar.h b/src/gcompris/bar.h
new file mode 100644
index 0000000..0c1b24c
--- /dev/null
+++ b/src/gcompris/bar.h
@@ -0,0 +1,36 @@
+/* gcompris - bar.h
+ *
+ * Copyright (C) 2010, Aleksey Lim
+ *
+ *   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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef BAR_H
+#define BAR_H
+
+#include "gcompris.h"
+
+typedef struct
+{
+  void (*start) (GtkContainer *workspace, GooCanvas *theCanvas);
+  void (*set_level) (GcomprisBoard *gcomprisBoard);
+  void (*set_repeat_icon) (RsvgHandle *svg_handle);
+  void (*set_location) (int x, int y, double zoom);
+  void (*set_flags) (const GComprisBarFlags flags);
+  void (*set_hide) (gboolean hide);
+} Bar;
+
+void gc_bar_register (Bar *bar);
+
+#endif
diff --git a/src/gcompris/config.c b/src/gcompris/config.c
index f3f5138..29e1c49 100644
--- a/src/gcompris/config.c
+++ b/src/gcompris/config.c
@@ -316,6 +316,31 @@ gc_config_start ()
 		       "fill-color-rgba", gc_skin_color_content,
 		       NULL);
 
+  // Zoom
+  y_start += Y_GAP;
+
+  item = goo_canvas_svg_new (rootitem,
+			     gc_skin_rsvg_get(),
+			     "svg-id", (properties->zoom ? pixmap_checked : pixmap_unchecked),
+			     "autocrop", TRUE,
+			     NULL);
+  SET_ITEM_LOCATION(item, x_start, y_start - pixmap_width/2);
+
+  g_signal_connect(item, "button_press_event",
+		   (GtkSignalFunc) item_event_ok,
+		   "zoom");
+  gc_item_focus_init(item, NULL);
+
+  goo_canvas_text_new (rootitem,
+		       _("Zoom"),
+		       (gdouble) x_text_start,
+		       (gdouble) y_start,
+		       -1,
+		       GTK_ANCHOR_WEST,
+		       "font", gc_skin_font_subtitle,
+		       "fill-color-rgba", gc_skin_color_content,
+		       NULL);
+
   // Timer
   y_start += Y_GAP;
 
@@ -729,6 +754,15 @@ item_event_ok(GooCanvasItem *item,
 		    NULL);
       gc_item_focus_init(item, NULL);
     }
+  else if(!strcmp((char *)data, "zoom"))
+    {
+      properties->zoom = (properties->zoom ? 0 : 1);
+      gc_update_canvas_zoom();
+      g_object_set (item,
+		    "svg-id", (properties->zoom ? pixmap_checked : pixmap_unchecked),
+		    NULL);
+      gc_item_focus_init(item, NULL);
+    }
   else if(!strcmp((char *)data, "locale_previous"))
     {
       current_locale = get_previous_locale(current_locale);
diff --git a/src/gcompris/gcompris.c b/src/gcompris/gcompris.c
index be48140..89dbc93 100644
--- a/src/gcompris/gcompris.c
+++ b/src/gcompris/gcompris.c
@@ -37,6 +37,7 @@
 #include "gc_core.h"
 #include "gcompris_config.h"
 #include "about.h"
+#include "bar.h"
 #include <locale.h>
 
 #include "binreloc.h"
@@ -56,20 +57,14 @@ static double zoom_factor = 1.0;
 #define GC_LOCK_LIMIT 30 /* seconds */
 
 static GtkWidget *window;
+static GtkWidget *workspace;
+static GtkWidget *alignment;
 static GtkWidget *canvas;
-static GtkWidget *fixed;
-static GtkWidget *drawing_area;
 gchar * exec_prefix = NULL;
 
 //static gint pause_board_cb (GtkWidget *widget, gpointer data);
 static void quit_cb (GtkWidget *widget, gpointer data);
 static void map_cb  (GtkWidget *widget, gpointer data);
-static gint _gc_configure_event_callback (GtkWidget   *widget,
-					  GdkEventConfigure *event,
-					  gpointer     client_data);
-static gboolean _expose_background_callback (GtkWidget *widget,
-					     GdkEventExpose *event,
-					     gpointer data);
 #ifndef WIN32
 static gboolean _realize_callback (GtkWidget *widget, GdkEventExpose *event,
 				   gpointer data);
@@ -146,6 +141,10 @@ static gchar *popt_cache_dir       = NULL;
 static gchar *popt_drag_mode       = NULL;
 static gchar *sugarBundleId        = NULL;
 static gchar *sugarActivityId      = NULL;
+static gint popt_sugar_look        = FALSE;
+static gint popt_no_zoom           = FALSE;
+static gdouble popt_timing_base    = 1.0;
+static gdouble popt_timing_mult    = 1.0;
 
 static GOptionEntry options[] = {
   {"fullscreen", 'f', 0, G_OPTION_ARG_NONE, &popt_fullscreen,
@@ -250,6 +249,18 @@ static GOptionEntry options[] = {
   {"sugarActivityId", '\0', 0, G_OPTION_ARG_STRING, &sugarActivityId,
    "Sugar Activity Id", NULL},
 
+  {"sugar",'\0', 0, G_OPTION_ARG_NONE, &popt_sugar_look,
+   ("Use Sugar DE look&feel"), NULL},
+
+  {"no-zoom",'\0', 0, G_OPTION_ARG_NONE, &popt_no_zoom,
+   ("Disable maximization zoom"), NULL},
+
+  {"timing-base",'\0', 0, G_OPTION_ARG_DOUBLE, &popt_timing_base,
+   ("Increase activiites' timeout delays; useful values > 1.0; 1.0 to not change hardcoded value"), NULL},
+
+  {"timing-mult",'\0', 0, G_OPTION_ARG_DOUBLE, &popt_timing_mult,
+   ("How activiites' timeout delays are growing for several actors; useful values < 1.0; 1.0 to not change hardcoded value"), NULL},
+
   { NULL }
 };
 
@@ -272,30 +283,27 @@ double gc_zoom_factor_get()
 }
 
 static gint
-_gc_configure_event_callback (GtkWidget   *widget,
-			      GdkEventConfigure *event,
+_gc_size_allocate_event_callback (GtkWidget   *widget,
+			      GtkAllocation *allocation,
 			      gpointer     client_data)
 {
   double xratio, yratio;
-  gint screen_height, screen_width;
-
-  gdk_drawable_get_size(GDK_DRAWABLE (window->window),
-			&screen_width,
-			&screen_height);
+  double canvas_width, canvas_height;
 
-  yratio=screen_height/(float)(BOARDHEIGHT);
-  xratio=screen_width/(float)BOARDWIDTH;
+  yratio=allocation->height/(float)(BOARDHEIGHT);
+  xratio=allocation->width/(float)BOARDWIDTH;
   zoom_factor = MIN(xratio, yratio);
   g_message("The screen_width=%f screen_height=%f ratio=%f\n",
-	    (double)screen_width, (double)screen_height, zoom_factor);
+	    (double)allocation->width, (double)allocation->height, zoom_factor);
 
-  gtk_widget_set_usize (canvas, BOARDWIDTH*zoom_factor, BOARDHEIGHT*zoom_factor);
-  goo_canvas_set_scale (GOO_CANVAS(canvas), zoom_factor);
-  gtk_fixed_move(GTK_FIXED(fixed), canvas,
-		 (screen_width-BOARDWIDTH*zoom_factor)/2,
-		 (screen_height-BOARDHEIGHT*zoom_factor)/2);
+  if (!properties->zoom && zoom_factor > 1.)
+      zoom_factor = 1.;
+
+  canvas_width = BOARDWIDTH * zoom_factor;
+  canvas_height = BOARDHEIGHT * zoom_factor;
 
-  _expose_background_callback (drawing_area, NULL, NULL);
+  gtk_widget_set_size_request(canvas, canvas_width, canvas_height);
+  goo_canvas_set_scale (GOO_CANVAS(canvas), zoom_factor);
 
   return FALSE;
 }
@@ -618,27 +626,6 @@ gc_set_default_background(GooCanvasItem *parent)
 			  "#BACKGROUND");
 }
 
-/* Redraw the black background
- */
-static gboolean
-_expose_background_callback (GtkWidget *widget,
-			     GdkEventExpose *event, gpointer data)
-{
-  gint screen_height, screen_width;
-
-  gdk_drawable_get_size(GDK_DRAWABLE (window->window),
-			&screen_width,
-			&screen_height);
-
-  gtk_widget_set_size_request (widget, screen_width, screen_height);
-  gdk_draw_rectangle (widget->window,
-		      widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
-		      TRUE,
-		      0, 0, widget->allocation.width, widget->allocation.height);
-
-  return FALSE;
-}
-
 /*
  * Sugar requires properties to be set before the windows is realized
  */
@@ -669,28 +656,28 @@ _realize_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data)
 #endif
 
 static void
-init_background()
+init_workspace()
 {
-  drawing_area = gtk_drawing_area_new ();
-  gtk_widget_set_size_request (drawing_area, BOARDWIDTH, BOARDHEIGHT);
-  g_signal_connect (G_OBJECT (drawing_area), "expose_event",
-		    G_CALLBACK (_expose_background_callback), NULL);
-  /* Create a vertical box in which I put first the play board area, then the button bar */
-  fixed = gtk_fixed_new ();
-  gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(fixed));
+  workspace = gtk_vbox_new(FALSE, 0);
+  gtk_container_add(GTK_CONTAINER(window), workspace);
 
-  gtk_fixed_put (GTK_FIXED(fixed), GTK_WIDGET(drawing_area), 0, 0);
-  gtk_fixed_put (GTK_FIXED(fixed), GTK_WIDGET(canvas), 0, 0);
+  GtkWidget *background = gtk_event_box_new();
+  GdkColor black = {0, 0, 0, 0};
+  gtk_widget_modify_bg(background, GTK_STATE_NORMAL, &black);
+  gtk_box_pack_end(GTK_BOX(workspace), background, TRUE, TRUE, 0);
 
-  gtk_widget_show (GTK_WIDGET(fixed));
-  gtk_widget_show (GTK_WIDGET(canvas));
+  alignment = gtk_alignment_new(.5, .5, 0., 0.);
+  g_signal_connect (GTK_OBJECT (alignment), "size-allocate",
+		      G_CALLBACK (_gc_size_allocate_event_callback), NULL);
+  gtk_container_add(GTK_CONTAINER(background), alignment);
 
-  gtk_widget_set_usize (GTK_WIDGET(canvas), BOARDWIDTH, BOARDHEIGHT);
+  gtk_container_add(GTK_CONTAINER(alignment), canvas);
+  gtk_widget_set_size_request (GTK_WIDGET(canvas), BOARDWIDTH, BOARDHEIGHT);
   goo_canvas_set_bounds (GOO_CANVAS(canvas),
 			 0, 0,
 			 BOARDWIDTH,
 			 BOARDHEIGHT);
-
+  g_object_set (G_OBJECT(canvas), "background-color", "#000", NULL);
 }
 
 static GcomprisBoard *get_board_to_start()
@@ -782,13 +769,12 @@ static void setup_window ()
   hints.height_inc = 1;
   hints.min_aspect = (float)BOARDWIDTH/BOARDHEIGHT;
   hints.max_aspect = (float)BOARDWIDTH/BOARDHEIGHT;
-  gtk_window_set_geometry_hints (GTK_WINDOW (window),
-				 NULL,
-				 &hints,
-				 GDK_HINT_RESIZE_INC |
-				 GDK_HINT_MIN_SIZE |
-				 GDK_HINT_BASE_SIZE |
-				 GDK_HINT_ASPECT);
+  gint geom_mask = GDK_HINT_RESIZE_INC |
+                   GDK_HINT_MIN_SIZE |
+                   GDK_HINT_BASE_SIZE;
+  if (!popt_sugar_look)
+      geom_mask |= GDK_HINT_ASPECT;
+  gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL, &hints, geom_mask);
 
   /*
    * Set the main window
@@ -809,9 +795,6 @@ static void setup_window ()
   gtk_signal_connect (GTK_OBJECT (window), "map_event",
 		      GTK_SIGNAL_FUNC (map_cb), NULL);
 
-  gtk_signal_connect (GTK_OBJECT (window), "configure_event",
-		      GTK_SIGNAL_FUNC (_gc_configure_event_callback), NULL);
-
   // Set the cursor
   gc_cursor_set(GCOMPRIS_DEFAULT_CURSOR);
 
@@ -828,9 +811,6 @@ static void setup_window ()
 			  "key_press_event",
 			  GTK_SIGNAL_FUNC (board_widget_key_press_callback), 0);
 
-  GTK_WIDGET_SET_FLAGS (canvas, GTK_CAN_FOCUS);
-  gtk_widget_grab_focus (canvas);
-
   gc_im_init(window);
 
   gc_board_init();
@@ -841,10 +821,13 @@ static void setup_window ()
   /* Save the root_menu */
   properties->menu_board = gc_menu_section_get(properties->root_menu);
 
-  /* Run the bar */
-  gc_bar_start(GOO_CANVAS(canvas));
+  init_workspace();
+
+  GTK_WIDGET_SET_FLAGS (canvas, GTK_CAN_FOCUS);
+  gtk_widget_grab_focus (canvas);
 
-  init_background();
+  /* Run the bar */
+  gc_bar_start(GTK_CONTAINER(workspace), GOO_CANVAS(canvas));
 
   board_to_start = get_board_to_start();
 
@@ -1056,7 +1039,10 @@ void gc_fullscreen_set(gboolean state)
   if(state)
     {
       gdk_window_set_decorations (window->window, 0);
-      gtk_window_fullscreen (GTK_WINDOW(window));
+      if (popt_sugar_look)
+        gtk_window_maximize (GTK_WINDOW(window));
+      else
+        gtk_window_fullscreen (GTK_WINDOW(window));
       gtk_widget_set_uposition (window, 0, 0);
     }
   else
@@ -1313,6 +1299,13 @@ void gc_log_handler (const gchar *log_domain,
     g_printerr ("%s: %s\n\n", "gcompris", message);
 }
 
+/* Refresh canvas zoom e.g. after setting zoom setting */
+void
+gc_update_canvas_zoom()
+{
+  _gc_size_allocate_event_callback(NULL, &alignment->allocation, NULL);
+}
+
 static void
 start_bg_music (gchar *file)
 {
@@ -1785,6 +1778,23 @@ main (int argc, char *argv[])
     exit(0);
   }
 
+  if (popt_sugar_look){
+    #ifdef USE_SUGAR
+      extern Bar sugar_bar;
+      gc_bar_register(&sugar_bar);
+      extern Score sugar_score;
+      gc_score_register(&sugar_score);
+    #else
+	  printf("GCompris was not built with Sugar DE support.\n");
+      popt_sugar_look = FALSE;
+    #endif
+  }
+
+  if (popt_no_zoom){
+    g_message("Zoom disabled");
+    properties->zoom = FALSE;
+  }
+
   /*------------------------------------------------------------*/
 
   single_instance_check();
@@ -1832,3 +1842,13 @@ main (int argc, char *argv[])
 
   return(0);
 }
+
+gint
+gc_timing (gint timeout, gint actors_number)
+{
+  if (popt_timing_base > 1.0)
+    timeout = (int) (timeout * popt_timing_base);
+  if (popt_timing_mult < 1.0 && actors_number > 1)
+    timeout += (int) (timeout * actors_number * popt_timing_mult);
+  return timeout;
+}
diff --git a/src/gcompris/gcompris.h b/src/gcompris/gcompris.h
index bf8731e..6ed7516 100644
--- a/src/gcompris/gcompris.h
+++ b/src/gcompris/gcompris.h
@@ -83,7 +83,7 @@
 void		 gc_board_end(void);
 
 /* Control Bar methods */
-void		 gc_bar_start (GooCanvas *theCanvas);
+void		 gc_bar_start (GtkContainer *workspace, GooCanvas *theCanvas);
 
 /** Set the default background of your activity.
  *  Always set the background in your activity startup.
@@ -156,6 +156,10 @@ void		 gc_bar_hide (gboolean hide);
  *  @param[in] zoom is the zoom factor. Set to -1 to keep the default.
  */
 void		 gc_bar_location (int x, int y, double zoom);
+/** Pronounce level changing notification
+ *  @param[in] level to pronounce, should be < 10
+ */
+void		 gc_bar_play_level_voice (int level);
 
 /* General */
 GooCanvas       *gc_get_canvas(void);
@@ -220,11 +224,17 @@ void		 gc_log_set_comment (GcomprisBoard *gcomprisBoard, gchar *expected, gchar*
 /* Do not use it if you use the bonus API in your board */
 void		 gc_log_end (GcomprisBoard *gcomprisBoard, GCBonusStatusList status);
 
+/* Refresh canvas zoom e.g. after setting zoom setting */
+void         gc_update_canvas_zoom();
+
 /* For menu type activity */
 GList		*gc_menu_getlist(gchar *section);
 GcomprisBoard   *gc_menu_section_get(gchar *section);
 GList           *gc_menu_get_boards();
 
+/* Correct timeout delay for activity timings */
+gint gc_timing (gint timeout, gint actors_number);
+
 /*=========================================================*/
 /* Some global definition to keep a constant look and feel */
 /* Boards coders are invited to use them                   */
diff --git a/src/gcompris/properties.c b/src/gcompris/properties.c
index 6b0fe3a..826b346 100644
--- a/src/gcompris/properties.c
+++ b/src/gcompris/properties.c
@@ -176,6 +176,8 @@ gc_prop_new ()
   tmp->server	                  = NULL;
   tmp->drag_mode                  = GC_DRAG_MODE_GRAB;
 
+  tmp->zoom                       = 1;
+
   tmp->config_dir = gc_prop_default_config_directory_get();
   tmp->user_dir = gc_prop_default_user_directory_get();
   tmp->database = NULL;
@@ -424,7 +426,10 @@ gc_prop_load (GcomprisProperties *props, GCPropSourceConf source_conf)
 	  props->key = scan_get_string(scanner);
 	  if(!props->key)
 	    g_warning("Config file parsing error on token %s", token);
-	}
+	} else if(!strcmp(value.v_identifier, "zoom")) {
+	  if(!scan_get_int(scanner, &props->zoom))
+	    g_warning("Config file parsing error on token %s", token);
+    }
 	g_free(token);
 	break;
       }
@@ -556,6 +561,8 @@ gc_prop_save (GcomprisProperties *props)
   fprintf(filefd, "%s=\"%s\"\n", "locale",		props->locale);
   fprintf(filefd, "%s=\"%s\"\n", "key",			props->key);
 
+  fprintf(filefd, "%s=%d\n", "zoom",			props->zoom);
+
   fclose(filefd);
 
   g_free(config_file);
diff --git a/src/gcompris/properties.h b/src/gcompris/properties.h
index 1eb995c..b4d1d54 100644
--- a/src/gcompris/properties.h
+++ b/src/gcompris/properties.h
@@ -65,6 +65,7 @@ typedef struct {
   gint          experimental;
   gchar        *server;
   gint		drag_mode;
+  gint		zoom;
 } GcomprisProperties;
 
 GcomprisProperties	*gc_prop_get (void);
diff --git a/src/gcompris/score.c b/src/gcompris/score.c
index 3f5fc70..495393f 100644
--- a/src/gcompris/score.c
+++ b/src/gcompris/score.c
@@ -46,8 +46,8 @@ static void display_number(GooCanvasItem *parent,
 /*
  * Do all the score display
  */
-void
-gc_score_start (ScoreStyleList style, guint gx, guint gy, guint gmax)
+static void
+score_start (ScoreStyleList style, guint gx, guint gy, guint gmax)
 {
 
   currentStyle = style;
@@ -65,8 +65,8 @@ gc_score_start (ScoreStyleList style, guint gx, guint gy, guint gmax)
 }
 
 
-void
-gc_score_end()
+static void
+score_end()
 {
   if(boardRootItem!=NULL)
     goo_canvas_item_remove(boardRootItem);
@@ -74,8 +74,8 @@ gc_score_end()
   boardRootItem=NULL;
 }
 
-void
-gc_score_set(guint value)
+static void
+score_set(guint value)
 {
 
   if(boardRootItem!=NULL)
@@ -152,3 +152,40 @@ display_number(GooCanvasItem *parent,
 		       "fill-color-rgba", 0xe5e532FF,
 		       NULL);
 }
+
+/* custom score registration */
+
+static Score *custom_score = NULL;
+
+void
+gc_score_register (Score *score)
+{
+    custom_score = score;
+}
+
+void
+gc_score_start (ScoreStyleList style, guint x, guint y, guint max)
+{
+    if (custom_score == NULL)
+        score_start (style, x, y, max);
+    else if (custom_score->start != NULL)
+        custom_score->start (style, x, y, max);
+}
+
+void
+gc_score_end ()
+{
+    if (custom_score == NULL)
+        score_end ();
+    else if (custom_score->end != NULL)
+        custom_score->end ();
+}
+
+void
+gc_score_set (guint value)
+{
+    if (custom_score == NULL)
+        score_set (value);
+    else if (custom_score->set != NULL)
+        custom_score->set (value);
+}
diff --git a/src/gcompris/score.h b/src/gcompris/score.h
index 8e3f46c..e81527a 100644
--- a/src/gcompris/score.h
+++ b/src/gcompris/score.h
@@ -31,4 +31,13 @@ void gc_score_start (ScoreStyleList style, guint x, guint y, guint max);
 void gc_score_end();
 void gc_score_set(guint value);
 
+typedef struct
+{
+  void (*start) (ScoreStyleList style, guint x, guint y, guint max);
+  void (*end) ();
+  void (*set) (guint value);
+} Score;
+
+void gc_score_register (Score *score);
+
 #endif
diff --git a/src/gcompris/sugar.c b/src/gcompris/sugar.c
new file mode 100644
index 0000000..c568773
--- /dev/null
+++ b/src/gcompris/sugar.c
@@ -0,0 +1,362 @@
+/* gcompris - sugar.c
+ *
+ * Copyright (C) 2010, Aleksey Lim
+ *
+ *   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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sugar/toolkit.h>
+
+#include "gcompris.h"
+#include "gc_core.h"
+#include "bar.h"
+#include "score.h"
+
+static void bar_start(GtkContainer*, GooCanvas*);
+static void bar_set_level(GcomprisBoard*);
+static void bar_set_flags(const GComprisBarFlags);
+static void score_start(ScoreStyleList, guint, guint, guint);
+static void score_end();
+static void score_set(guint);
+static void help_clicked_cb(GtkToolButton*, gpointer);
+static void about_clicked_cb(GtkToolButton*, gpointer);
+static void level_clicked_cb(GtkToolButton*, gpointer);
+static void refresh_clicked_cb(GtkToolButton*, gpointer);
+static void zoom_clicked_cb(GtkToolButton*, gpointer);
+static void config_clicked_cb(GtkToolButton*, gpointer);
+static void back_clicked_cb(GtkToolButton*, gpointer);
+static void stop_clicked_cb(GtkToolButton*, gpointer);
+static GtkToolItem* level_widget_new();
+static GtkToolItem* score_widget_new();
+static GtkToolItem* expander_new();
+static GtkToolItem* separator_new();
+
+/* export sugar bar */
+Bar sugar_bar = {
+  bar_start,
+  bar_set_level,
+  NULL,
+  NULL,
+  bar_set_flags,
+  NULL
+};
+
+/* export sugar score */
+Score sugar_score = {
+  score_start,
+  score_end,
+  score_set
+};
+
+typedef struct {
+  const gchar *icon;
+  const gchar *label;
+  gpointer cb;
+  gpointer user_data;
+} Button;
+
+static Button buttons[] = {
+  { "emblem-question", N_("Help"), help_clicked_cb, NULL },
+  { "stock_home", N_("About"), about_clicked_cb, NULL },
+  { "go-previous-paired", N_("Previous level"), level_clicked_cb,
+      GINT_TO_POINTER(-1) },
+  { NULL, NULL, level_widget_new, NULL },
+  { "go-next-paired", N_("Next level"), level_clicked_cb,
+      GINT_TO_POINTER(+1) },
+  { "stock_refresh", N_("Refresh"), refresh_clicked_cb, NULL },
+  { "preferences-system", N_("Settings"), config_clicked_cb, NULL },
+  { NULL, NULL, expander_new, NULL },
+  { NULL, NULL, score_widget_new, NULL },
+  { NULL, NULL, expander_new, NULL },
+  { "view-fullscreen", N_("Zoom"), zoom_clicked_cb, NULL },
+  { NULL, NULL, separator_new, NULL },
+  { "go-previous", N_("Back"), back_clicked_cb, NULL },
+  { "activity-stop", N_("Stop"), stop_clicked_cb, NULL }
+};
+
+enum {
+  BUTTON_HELP = 0,
+  BUTTON_ABOUT,
+  BUTTON_PREV,
+  BUTTON_LEVEL,
+  BUTTON_NEXT,
+  BUTTON_REFRESH,
+  BUTTON_CONFIG,
+  BUTTON_EXPANDER_1,
+  BUTTON_SCORE,
+  BUTTON_EXPANDER_2,
+  BUTTON_ZOOM,
+  BUTTON_SEPARATOR,
+  BUTTON_BACK,
+  BUTTON_STOP,
+  BUTTONS_COUNT
+};
+
+static gint16 buttons_mask;
+static GtkToolItem *button_widgets[BUTTONS_COUNT];
+static GtkToolbar *toolbar;
+static SugarToolkitToolText *level_widget;
+static SugarToolkitToolText *score_widget;
+static gint current_level = -1;
+static gint max_score;
+
+static void
+bar_start(GtkContainer *workspace, GooCanvas *theCanvas)
+{
+  SugarToolkitToolbarBox *toolbox = sugar_toolkit_toolbar_box_new(-1);
+  gtk_box_pack_start(GTK_BOX(workspace), GTK_WIDGET(toolbox), FALSE, TRUE, 0);
+  toolbar = sugar_toolkit_toolbar_box_get_toolbar(toolbox);
+  gtk_widget_show(GTK_WIDGET(toolbar));
+  current_level = 1;
+}
+
+static void
+set_button(gint number, gboolean visible)
+{
+  Button *button = &buttons[number];
+  GtkToolItem *item = button_widgets[number];
+
+  if (item == NULL) {
+    if (button->icon == NULL)
+      item = ((GtkToolItem* (*)(void))button->cb)();
+    else {
+      item = gtk_tool_button_new(NULL, button->label);
+      gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(item), button->icon);
+      g_signal_connect(item, "clicked", G_CALLBACK(button->cb),
+                button->user_data);
+    }
+
+    g_object_ref_sink(item);
+    button_widgets[number] = item;
+  }
+
+  if (visible) {
+    if (gtk_widget_get_parent(GTK_WIDGET(item)) == NULL) {
+      int i;
+      int item_pos = 0;
+      for (i = 0; i < number; ++i)
+        if (buttons_mask & (1 << i))
+          ++item_pos;
+
+      gtk_widget_show(GTK_WIDGET(item));
+      gtk_toolbar_insert(toolbar, item, item_pos);
+      buttons_mask |= (1 << number);
+    }
+  } else {
+    if (gtk_widget_get_parent(GTK_WIDGET(item))) {
+      gtk_container_remove(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
+      buttons_mask &= ~(1 << number);
+    }
+  }
+}
+
+static void
+update_level()
+{
+  gchar level_string[256];
+  snprintf(level_string, sizeof(level_string), "%d", current_level);
+  g_object_set(level_widget, "text", level_string, NULL);
+}
+
+static void
+update_score(guint value)
+{
+  gchar score_string[256];
+  snprintf(score_string, sizeof(score_string), "%d/%d", value, max_score);
+  g_object_set(score_widget, "text", score_string, NULL);
+}
+
+static GtkToolItem*
+level_widget_new()
+{
+    g_assert(level_widget == NULL);
+    level_widget = sugar_toolkit_tool_text_new();
+    update_level();
+    return GTK_TOOL_ITEM(level_widget);
+}
+
+static GtkToolItem*
+score_widget_new()
+{
+    g_assert(score_widget == NULL);
+    score_widget = sugar_toolkit_tool_text_new();
+    return GTK_TOOL_ITEM(score_widget);
+}
+
+static GtkToolItem*
+separator_new()
+{
+  GtkToolItem *separator = gtk_separator_tool_item_new();
+  gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(separator), FALSE);
+  return separator;
+}
+
+static GtkToolItem*
+expander_new()
+{
+  GtkToolItem *expander = gtk_separator_tool_item_new();
+  gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(expander), FALSE);
+  gtk_tool_item_set_expand(GTK_TOOL_ITEM(expander), TRUE);
+  return expander;
+}
+
+static void
+beep()
+{
+  gc_sound_play_ogg("sounds/bleep.wav", NULL);
+}
+
+static void
+help_clicked_cb(GtkToolButton *button, gpointer user_data)
+{
+  beep();
+  GcomprisBoard *board = gc_board_get_current();
+  gc_help_start(board);
+}
+
+static void
+about_clicked_cb(GtkToolButton *button, gpointer user_data)
+{
+  beep();
+  gc_about_start();
+}
+
+static void
+level_clicked_cb(GtkToolButton *button, gpointer user_data)
+{
+  beep();
+
+  GcomprisBoard *board = gc_board_get_current();
+  if (board == NULL)
+      return;
+          
+  gint delta = GPOINTER_TO_INT(user_data);
+  current_level += delta;
+
+  if (current_level > board->maxlevel)
+    current_level = 1;
+  else if (current_level < 1)
+    current_level = board->maxlevel;
+
+  update_level();
+
+  if (board->plugin->set_level != NULL)
+    board->plugin->set_level(current_level);
+
+  gc_bar_play_level_voice(current_level);
+}
+
+static void
+refresh_clicked_cb(GtkToolButton *button, gpointer user_data)
+{
+  beep();
+  GcomprisBoard *board = gc_board_get_current();
+  if(board && board->plugin->repeat != NULL)
+    board->plugin->repeat();
+}
+
+static void
+zoom_clicked_cb(GtkToolButton *button, gpointer user_data)
+{
+  beep();
+  GcomprisProperties *properties = gc_prop_get();
+  properties->zoom = (properties->zoom ? 0 : 1);
+  gc_update_canvas_zoom();
+}
+
+static void
+config_clicked_cb(GtkToolButton *button, gpointer user_data)
+{
+  beep();
+  GcomprisBoard *board = gc_board_get_current();
+  if(board && board->plugin->config_start != NULL)
+    board->plugin->config_start(board, gc_profile_get_current());
+}
+
+static void
+back_clicked_cb(GtkToolButton *button, gpointer user_data)
+{
+  gc_board_stop();
+}
+
+static void
+stop_clicked_cb(GtkToolButton *button, gpointer user_data)
+{
+  // save zoom setting
+  GcomprisProperties *properties = gc_prop_get();
+  gc_prop_save(properties);
+
+  gc_exit();
+}
+
+static void
+bar_set_flags(const GComprisBarFlags flags)
+{
+  GcomprisBoard *board = gc_board_get_current();
+
+  set_button(BUTTON_HELP, flags & GC_BAR_HELP || gc_help_has_board(board));
+  set_button(BUTTON_ABOUT, flags & GC_BAR_ABOUT);
+
+  set_button(BUTTON_PREV, flags & GC_BAR_LEVEL);
+  set_button(BUTTON_LEVEL, flags & GC_BAR_LEVEL);
+  set_button(BUTTON_NEXT, flags & GC_BAR_LEVEL);
+
+  set_button(BUTTON_REFRESH, flags & (GC_BAR_REPEAT | GC_BAR_REPEAT_ICON));
+  set_button(BUTTON_CONFIG, flags & GC_BAR_CONFIG);
+
+  set_button(BUTTON_EXPANDER_1, TRUE);
+  set_button(BUTTON_SCORE, max_score);
+  set_button(BUTTON_EXPANDER_2, TRUE);
+
+  set_button(BUTTON_ZOOM, TRUE);
+  set_button(BUTTON_SEPARATOR, TRUE);
+  set_button(BUTTON_BACK, board && board->previous_board);
+  set_button(BUTTON_STOP, TRUE);
+}
+
+static void
+score_start(ScoreStyleList style, guint x, guint y, guint max)
+{
+  max_score = max;
+  set_button(BUTTON_SCORE, TRUE);
+  update_score(0);
+}
+
+static void
+score_end()
+{
+  max_score = 0;
+  set_button(BUTTON_SCORE, FALSE);
+}
+
+static void
+score_set(guint value)
+{
+  update_score(value);
+}
+
+static void
+bar_set_level(GcomprisBoard *board)
+{
+  if (board == NULL)
+      return;
+
+  if (level_widget == NULL) {
+    g_message("in bar_set_level, level_item uninitialized : should not happen\n");
+    return;
+  }
+
+  current_level = board->level;
+  update_level();
+}
diff --git a/src/gletters-activity/gletters.c b/src/gletters-activity/gletters.c
index 4852a02..987e483 100644
--- a/src/gletters-activity/gletters.c
+++ b/src/gletters-activity/gletters.c
@@ -25,6 +25,7 @@
 
 static GList *item_list = NULL;
 static GList *item2del_list = NULL;
+static guint actors_count = 0;
 
 static GcomprisBoard *gcomprisBoard = NULL;
 
@@ -514,6 +515,7 @@ static void gletters_destroy_item(GooCanvasItem *item)
   key = key_find_by_item(item);
 
   item_list = g_list_remove (item_list, item);
+  --actors_count;
 
   item2del_list = g_list_remove (item2del_list, item);
 
@@ -546,6 +548,8 @@ static void gletters_destroy_all_items()
 	gletters_destroy_item(item);
       }
 
+   actors_count= 0;
+
   /* Delete the letters_table */
   if(letters_table) {
     g_hash_table_destroy (letters_table);
@@ -564,7 +568,7 @@ static gint gletters_move_items (GtkWidget *widget, gpointer data)
   /* Destroy items that falls out of the canvas */
   gletters_destroy_items();
 
-  dummy_id = gtk_timeout_add (speed,
+  dummy_id = gtk_timeout_add (gc_timing (speed, actors_count),
 			      (GtkFunction) gletters_move_items, NULL);
 
   return(FALSE);
@@ -668,6 +672,7 @@ static GooCanvasItem *gletters_create_item(GooCanvasItem *parent)
   g_object_set_data (G_OBJECT(item), "utf8_key", letter);
 
   item_list = g_list_append (item_list, item);
+  ++actors_count;
 
   /* Add letter to hash table of all falling letters. */
   g_hash_table_insert (letters_table, lettersItem, item);
diff --git a/src/paratrooper-activity/paratrooper.c b/src/paratrooper-activity/paratrooper.c
index 4c87913..7161e5d 100644
--- a/src/paratrooper-activity/paratrooper.c
+++ b/src/paratrooper-activity/paratrooper.c
@@ -330,7 +330,7 @@ static void paratrooper_next_level()
 			  0,
 			  FALSE,
 			  BOARDWIDTH * speed,
-			  speed*1.5,
+			  gc_timing (speed * 1.5, 4),
 			  GOO_CANVAS_ANIMATE_RESTART);
 
   g_signal_connect(planeitem, "button-press-event",
@@ -373,7 +373,7 @@ static void paratrooper_next_level()
 			  0,
 			  TRUE,
 			  BOARDWIDTH/2 * 30,
-			  40*2,
+			  gc_timing (40 * 2, 4),
 			  GOO_CANVAS_ANIMATE_FREEZE);
 
   g_object_unref(svg_handle);
@@ -543,7 +543,7 @@ paratrooper_create_cloud(GooCanvasItem *parent)
 			  0,
 			  TRUE,
 			  BOARDWIDTH * (80 / ABS(windspeed)),
-			  40,
+			  gc_timing (40, 4),
 			  GOO_CANVAS_ANIMATE_RESTART);
   g_object_unref(svg_handle);
 
@@ -597,7 +597,8 @@ void next_state()
 				  (bounds.x1 > 0 ? bounds.x1 : 0),
 				  bounds.y2);
 	drop_tux_id = \
-	  gtk_timeout_add (10, (GtkFunction) paratrooper_move_tux, NULL);
+	  gtk_timeout_add (gc_timing (10, 4),
+              (GtkFunction) paratrooper_move_tux, NULL);
 
         gc_item_focus_remove(planeitem, NULL);
       }
diff --git a/src/redraw_symmetrical-activity/resources/redraw_symmetrical/Makefile.am b/src/redraw_symmetrical-activity/resources/redraw_symmetrical/Makefile.am
index 543b4d6..82765da 100644
--- a/src/redraw_symmetrical-activity/resources/redraw_symmetrical/Makefile.am
+++ b/src/redraw_symmetrical-activity/resources/redraw_symmetrical/Makefile.am
@@ -1,4 +1,4 @@
-imgdir = $(pkgdatadir)/@PACKAGE_DATA_DIR@/redraw
+imgdir = $(pkgdatadir)/@PACKAGE_DATA_DIR@/redraw_symmetrical
 img_DATA = \
 	redraw_symmetry.svg
 
diff --git a/src/smallnumbers-activity/smallnumbers.c b/src/smallnumbers-activity/smallnumbers.c
index 0051195..2c7fbbe 100644
--- a/src/smallnumbers-activity/smallnumbers.c
+++ b/src/smallnumbers-activity/smallnumbers.c
@@ -346,12 +346,13 @@ static void smallnumbers_move_item(GooCanvasItem *item)
 static gint smallnumbers_move_items (GtkWidget *widget, gpointer data)
 {
   int i;
+  int count = goo_canvas_item_get_n_children(boardRootItem);
 
   /* For each item we need to move */
-  for(i=0; i<goo_canvas_item_get_n_children(boardRootItem); i++)
+  for(i=0; i<count; i++)
     smallnumbers_move_item(goo_canvas_item_get_child(boardRootItem, i));
 
-  dummy_id = gtk_timeout_add (speed,
+  dummy_id = gtk_timeout_add (gc_timing (speed, count),
 			      (GtkFunction) smallnumbers_move_items, NULL);
 
   return(FALSE);
diff --git a/src/wordsgame-activity/wordsgame.c b/src/wordsgame-activity/wordsgame.c
index f792950..f722651 100644
--- a/src/wordsgame-activity/wordsgame.c
+++ b/src/wordsgame-activity/wordsgame.c
@@ -507,7 +507,8 @@ static gint wordsgame_move_items (GtkWidget *widget, gpointer data)
       g_static_rw_lock_reader_unlock (&items_lock);
       wordsgame_move_item(item);
     }
-  dummy_id = g_timeout_add (speed,(GtkFunction) wordsgame_move_items, NULL);
+  dummy_id = g_timeout_add (gc_timing (speed, items->len),
+          (GtkFunction) wordsgame_move_items, NULL);
   return (FALSE);
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]