[gcompris-devel] Sugar related patches for v9

Aleksey Lim alsroot at member.fsf.org
Thu Jan 14 14:21:52 UTC 2010


Hi all,

While packaging GCompris for sugar[1], I've made some patches to
gcomprixogoo branch

* add optional sugar look&feel(requires sugat-toolkit library[2])
* support pluggable activity and score bars
* add zoom option to sidable scaling on restricted systems
* add optional timing setup for some activities on restricted systems
* remove hardcoded pycairo > 1.8 (and thus python26) requirements
  and add version checking to the code to support several pycairo APIs

If it's worth adding such changes to upsteam project, please review
patches and submit feedback.

[1] http://activities.sugarlabs.org/sugar/collection/gcompris
[2] http://people.sugarlabs.org/~alsroot/tmp/sugar-toolkit-1-4.tar.bz2

-- 
Aleksey
-------------- next part --------------
>From c68e2411518ff9899a154e4437aa7a0b66ad057a Mon Sep 17 00:00:00 2001
From: Aleksey Lim <alsroot at member.fsf.org>
Date: Mon, 11 Jan 2010 23:14:13 +0000
Subject: Initial support of Sugar look&feel


diff --git a/configure.ac b/configure.ac
index 0956c0e..435889a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -409,6 +409,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_MSG_ERROR([*** Sugar not found!]))
+  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],
@@ -834,6 +851,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/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..f6868aa 100644
--- a/src/gcompris/bar.c
+++ b/src/gcompris/bar.c
@@ -48,6 +48,7 @@ static gboolean item_event_bar (GooCanvasItem  *item,
 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);
@@ -610,7 +613,7 @@ item_event_bar (GooCanvasItem  *item,
       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/gcompris.c b/src/gcompris/gcompris.c
index be48140..8dc95dd 100644
--- a/src/gcompris/gcompris.c
+++ b/src/gcompris/gcompris.c
@@ -56,20 +56,13 @@ static double zoom_factor = 1.0;
 #define GC_LOCK_LIMIT 30 /* seconds */
 
 static GtkWidget *window;
+static GtkWidget *workspace;
 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 +139,8 @@ static gchar *popt_cache_dir       = NULL;
 static gchar *popt_drag_mode       = NULL;
 static gchar *sugarBundleId        = NULL;
 static gchar *sugarActivityId      = NULL;
+static gint sugar_look             = FALSE;
+static gint no_zoom                = FALSE;
 
 static GOptionEntry options[] = {
   {"fullscreen", 'f', 0, G_OPTION_ARG_NONE, &popt_fullscreen,
@@ -250,6 +245,12 @@ static GOptionEntry options[] = {
   {"sugarActivityId", '\0', 0, G_OPTION_ARG_STRING, &sugarActivityId,
    "Sugar Activity Id", NULL},
 
+  {"sugar",'\0', 0, G_OPTION_ARG_NONE, &sugar_look,
+   ("Use Sugar DE look&feel"), NULL},
+
+  {"no-zoom",'\0', 0, G_OPTION_ARG_NONE, &no_zoom,
+   ("Disable maximization zoom"), NULL},
+
   { NULL }
 };
 
@@ -272,30 +273,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 (no_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 +616,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 +646,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));
+  GtkWidget *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 +759,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 (!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 +785,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);
 
@@ -841,10 +814,10 @@ 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();
 
-  init_background();
+  /* Run the bar */
+  gc_bar_start(GTK_CONTAINER(workspace), GOO_CANVAS(canvas));
 
   board_to_start = get_board_to_start();
 
@@ -1785,6 +1758,16 @@ main (int argc, char *argv[])
     exit(0);
   }
 
+  if (sugar_look){
+    #ifdef USE_SUGAR
+      extern Bar sugar_bar;
+      gc_bar_register(&sugar_bar);
+    #else
+	  printf("GCompris was not built with Sugar DE support.\n");
+      sugar_look = FALSE;
+    #endif
+  }
+
   /*------------------------------------------------------------*/
 
   single_instance_check();
diff --git a/src/gcompris/gcompris.h b/src/gcompris/gcompris.h
index bf8731e..ca6189e 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.
@@ -225,6 +225,19 @@ GList		*gc_menu_getlist(gchar *section);
 GcomprisBoard   *gc_menu_section_get(gchar *section);
 GList           *gc_menu_get_boards();
 
+/* bar registration */
+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);
+
 /*=========================================================*/
 /* Some global definition to keep a constant look and feel */
 /* Boards coders are invited to use them                   */
diff --git a/src/gcompris/sugar.c b/src/gcompris/sugar.c
new file mode 100644
index 0000000..6d6f3a9
--- /dev/null
+++ b/src/gcompris/sugar.c
@@ -0,0 +1,43 @@
+/* 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 "gcompris.h"
+
+static void
+start(GtkContainer *workspace, GooCanvas *theCanvas)
+{
+}
+
+static void
+set_level(GcomprisBoard *gcomprisBoard)
+{
+}
+
+static void
+set_flags(const GComprisBarFlags flags)
+{
+}
+
+Bar sugar_bar = {
+  start,
+  set_level,
+  NULL,
+  NULL,
+  set_flags,
+  NULL
+};
-- 
1.6.5.3


>From f30d9e68470b068320739bdc6e5bd118180a6750 Mon Sep 17 00:00:00 2001
From: Aleksey Lim <alsroot at member.fsf.org>
Date: Tue, 12 Jan 2010 12:12:54 +0000
Subject: Implement sugar bar


diff --git a/src/gcompris/bar.c b/src/gcompris/bar.c
index f6868aa..6b298b0 100644
--- a/src/gcompris/bar.c
+++ b/src/gcompris/bar.c
@@ -47,7 +47,6 @@ 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;
@@ -545,8 +544,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);
@@ -594,7 +593,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:
@@ -608,7 +607,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_HOME:
diff --git a/src/gcompris/gcompris.c b/src/gcompris/gcompris.c
index 8dc95dd..2aec15d 100644
--- a/src/gcompris/gcompris.c
+++ b/src/gcompris/gcompris.c
@@ -801,9 +801,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();
@@ -816,6 +813,9 @@ static void setup_window ()
 
   init_workspace();
 
+  GTK_WIDGET_SET_FLAGS (canvas, GTK_CAN_FOCUS);
+  gtk_widget_grab_focus (canvas);
+
   /* Run the bar */
   gc_bar_start(GTK_CONTAINER(workspace), GOO_CANVAS(canvas));
 
diff --git a/src/gcompris/gcompris.h b/src/gcompris/gcompris.h
index ca6189e..e4ffdd2 100644
--- a/src/gcompris/gcompris.h
+++ b/src/gcompris/gcompris.h
@@ -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);
diff --git a/src/gcompris/sugar.c b/src/gcompris/sugar.c
index 6d6f3a9..be79284 100644
--- a/src/gcompris/sugar.c
+++ b/src/gcompris/sugar.c
@@ -16,28 +16,259 @@
  *   along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <sugar/toolkit.h>
+
 #include "gcompris.h"
+#include "gc_core.h"
+
+static void start(GtkContainer*, GooCanvas*);
+static void set_level(GcomprisBoard*);
+static void set_flags(const GComprisBarFlags);
+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 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* separator_new();
+
+/* export sugar bar */
+Bar sugar_bar = {
+  start,
+  set_level,
+  NULL,
+  NULL,
+  set_flags,
+  NULL
+};
+
+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, 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_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 gint current_level = -1;
 
 static void
 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);
+  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_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 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*
+separator_new()
+{
+  GtkToolItem *separator = gtk_separator_tool_item_new();
+  gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(separator), FALSE);
+  gtk_tool_item_set_expand(GTK_TOOL_ITEM(separator), TRUE);
+  return separator;
+}
+
+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
-set_level(GcomprisBoard *gcomprisBoard)
+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
+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)
+{
+  gc_exit();
 }
 
 static void
 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_SEPARATOR, TRUE);
+  set_button(BUTTON_BACK, board && board->previous_board);
+  set_button(BUTTON_STOP, TRUE);
+
+  gtk_widget_show_all(GTK_WIDGET(toolbar));
 }
 
-Bar sugar_bar = {
-  start,
-  set_level,
-  NULL,
-  NULL,
-  set_flags,
-  NULL
-};
+static void
+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();
+}
-- 
1.6.5.3


>From 7336cdc00c30372f2ec27b987590c93c905c0f3b Mon Sep 17 00:00:00 2001
From: Aleksey Lim <alsroot at member.fsf.org>
Date: Tue, 12 Jan 2010 13:26:53 +0000
Subject: Let users disable zooming on restricted systems


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 2aec15d..09885bc 100644
--- a/src/gcompris/gcompris.c
+++ b/src/gcompris/gcompris.c
@@ -57,6 +57,7 @@ static double zoom_factor = 1.0;
 
 static GtkWidget *window;
 static GtkWidget *workspace;
+static GtkWidget *alignment;
 static GtkWidget *canvas;
 gchar * exec_prefix = NULL;
 
@@ -139,8 +140,8 @@ static gchar *popt_cache_dir       = NULL;
 static gchar *popt_drag_mode       = NULL;
 static gchar *sugarBundleId        = NULL;
 static gchar *sugarActivityId      = NULL;
-static gint sugar_look             = FALSE;
-static gint no_zoom                = FALSE;
+static gint popt_sugar_look        = FALSE;
+static gint popt_no_zoom           = FALSE;
 
 static GOptionEntry options[] = {
   {"fullscreen", 'f', 0, G_OPTION_ARG_NONE, &popt_fullscreen,
@@ -245,10 +246,10 @@ static GOptionEntry options[] = {
   {"sugarActivityId", '\0', 0, G_OPTION_ARG_STRING, &sugarActivityId,
    "Sugar Activity Id", NULL},
 
-  {"sugar",'\0', 0, G_OPTION_ARG_NONE, &sugar_look,
+  {"sugar",'\0', 0, G_OPTION_ARG_NONE, &popt_sugar_look,
    ("Use Sugar DE look&feel"), NULL},
 
-  {"no-zoom",'\0', 0, G_OPTION_ARG_NONE, &no_zoom,
+  {"no-zoom",'\0', 0, G_OPTION_ARG_NONE, &popt_no_zoom,
    ("Disable maximization zoom"), NULL},
 
   { NULL }
@@ -286,7 +287,7 @@ _gc_size_allocate_event_callback (GtkWidget   *widget,
   g_message("The screen_width=%f screen_height=%f ratio=%f\n",
 	    (double)allocation->width, (double)allocation->height, zoom_factor);
 
-  if (no_zoom && zoom_factor > 1.)
+  if (!properties->zoom && zoom_factor > 1.)
       zoom_factor = 1.;
 
   canvas_width = BOARDWIDTH * zoom_factor;
@@ -656,7 +657,7 @@ init_workspace()
   gtk_widget_modify_bg(background, GTK_STATE_NORMAL, &black);
   gtk_box_pack_end(GTK_BOX(workspace), background, TRUE, TRUE, 0);
 
-  GtkWidget *alignment = gtk_alignment_new(.5, .5, 0., 0.);
+  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);
@@ -762,7 +763,7 @@ static void setup_window ()
   gint geom_mask = GDK_HINT_RESIZE_INC |
                    GDK_HINT_MIN_SIZE |
                    GDK_HINT_BASE_SIZE;
-  if (!sugar_look)
+  if (!popt_sugar_look)
       geom_mask |= GDK_HINT_ASPECT;
   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL, &hints, geom_mask);
 
@@ -1286,6 +1287,15 @@ 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()
+{
+  GtkAllocation allocation;
+  gtk_widget_get_allocation(alignment, &allocation);
+  _gc_size_allocate_event_callback(NULL, &allocation, NULL);
+}
+
 static void
 start_bg_music (gchar *file)
 {
@@ -1758,16 +1768,21 @@ main (int argc, char *argv[])
     exit(0);
   }
 
-  if (sugar_look){
+  if (popt_sugar_look){
     #ifdef USE_SUGAR
       extern Bar sugar_bar;
       gc_bar_register(&sugar_bar);
     #else
 	  printf("GCompris was not built with Sugar DE support.\n");
-      sugar_look = FALSE;
+      popt_sugar_look = FALSE;
     #endif
   }
 
+  if (popt_no_zoom){
+    g_message("Zoom disabled");
+    properties->zoom = FALSE;
+  }
+
   /*------------------------------------------------------------*/
 
   single_instance_check();
diff --git a/src/gcompris/gcompris.h b/src/gcompris/gcompris.h
index e4ffdd2..4359aa2 100644
--- a/src/gcompris/gcompris.h
+++ b/src/gcompris/gcompris.h
@@ -224,6 +224,9 @@ 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);
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/sugar.c b/src/gcompris/sugar.c
index be79284..d2eea5e 100644
--- a/src/gcompris/sugar.c
+++ b/src/gcompris/sugar.c
@@ -28,10 +28,12 @@ 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* expander_new();
 static GtkToolItem* separator_new();
 
 /* export sugar bar */
@@ -61,6 +63,8 @@ static Button buttons[] = {
       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 },
+  { "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 }
@@ -74,6 +78,8 @@ enum {
   BUTTON_NEXT,
   BUTTON_REFRESH,
   BUTTON_CONFIG,
+  BUTTON_EXPANDER,
+  BUTTON_ZOOM,
   BUTTON_SEPARATOR,
   BUTTON_BACK,
   BUTTON_STOP,
@@ -156,10 +162,18 @@ separator_new()
 {
   GtkToolItem *separator = gtk_separator_tool_item_new();
   gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(separator), FALSE);
-  gtk_tool_item_set_expand(GTK_TOOL_ITEM(separator), TRUE);
   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()
 {
@@ -216,6 +230,15 @@ refresh_clicked_cb(GtkToolButton *button, gpointer user_data)
 }
 
 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();
@@ -233,6 +256,10 @@ back_clicked_cb(GtkToolButton *button, gpointer user_data)
 static void
 stop_clicked_cb(GtkToolButton *button, gpointer user_data)
 {
+  // save zoom setting
+  GcomprisProperties *properties = gc_prop_get();
+  gc_prop_save(properties);
+
   gc_exit();
 }
 
@@ -251,6 +278,8 @@ set_flags(const GComprisBarFlags flags)
   set_button(BUTTON_REFRESH, flags & (GC_BAR_REPEAT | GC_BAR_REPEAT_ICON));
   set_button(BUTTON_CONFIG, flags & GC_BAR_CONFIG);
 
+  set_button(BUTTON_EXPANDER, TRUE);
+  set_button(BUTTON_ZOOM, TRUE);
   set_button(BUTTON_SEPARATOR, TRUE);
   set_button(BUTTON_BACK, board && board->previous_board);
   set_button(BUTTON_STOP, TRUE);
-- 
1.6.5.3


>From 79024fe71899f24f4132fe8b15720fe256b7a003 Mon Sep 17 00:00:00 2001
From: Aleksey Lim <alsroot at member.fsf.org>
Date: Tue, 12 Jan 2010 14:18:04 +0000
Subject: Move bar registration declarations to bar.h to keep it constent with score.h


diff --git a/src/gcompris/bar.c b/src/gcompris/bar.c
index 6b298b0..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
 
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/gcompris.c b/src/gcompris/gcompris.c
index 09885bc..ecaa2b9 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"
diff --git a/src/gcompris/gcompris.h b/src/gcompris/gcompris.h
index 4359aa2..bd0f5c0 100644
--- a/src/gcompris/gcompris.h
+++ b/src/gcompris/gcompris.h
@@ -232,19 +232,6 @@ GList		*gc_menu_getlist(gchar *section);
 GcomprisBoard   *gc_menu_section_get(gchar *section);
 GList           *gc_menu_get_boards();
 
-/* bar registration */
-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);
-
 /*=========================================================*/
 /* Some global definition to keep a constant look and feel */
 /* Boards coders are invited to use them                   */
diff --git a/src/gcompris/sugar.c b/src/gcompris/sugar.c
index d2eea5e..b9139ee 100644
--- a/src/gcompris/sugar.c
+++ b/src/gcompris/sugar.c
@@ -20,6 +20,7 @@
 
 #include "gcompris.h"
 #include "gc_core.h"
+#include "bar.h"
 
 static void start(GtkContainer*, GooCanvas*);
 static void set_level(GcomprisBoard*);
-- 
1.6.5.3


>From cc85af81ed72cbaf027ccd5713f46a354765a2e9 Mon Sep 17 00:00:00 2001
From: Aleksey Lim <alsroot at member.fsf.org>
Date: Wed, 13 Jan 2010 15:56:25 +0000
Subject: Fix python binding to follow last API changes


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);
-- 
1.6.5.3


>From 2355a07733bb0032158d4eaf32f65b2b34b7d675 Mon Sep 17 00:00:00 2001
From: Aleksey Lim <alsroot at member.fsf.org>
Date: Wed, 13 Jan 2010 15:57:32 +0000
Subject: Sugarize score board


diff --git a/src/gcompris/gcompris.c b/src/gcompris/gcompris.c
index ecaa2b9..0c1f4e3 100644
--- a/src/gcompris/gcompris.c
+++ b/src/gcompris/gcompris.c
@@ -1773,6 +1773,8 @@ main (int argc, char *argv[])
     #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;
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
index b9139ee..ee3b20f 100644
--- a/src/gcompris/sugar.c
+++ b/src/gcompris/sugar.c
@@ -21,10 +21,14 @@
 #include "gcompris.h"
 #include "gc_core.h"
 #include "bar.h"
-
-static void start(GtkContainer*, GooCanvas*);
-static void set_level(GcomprisBoard*);
-static void set_flags(const GComprisBarFlags);
+#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);
@@ -34,19 +38,27 @@ 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 = {
-  start,
-  set_level,
+  bar_start,
+  bar_set_level,
   NULL,
   NULL,
-  set_flags,
+  bar_set_flags,
   NULL
 };
 
+/* export sugar score */
+Score sugar_score = {
+  score_start,
+  score_end,
+  score_set
+};
+
 typedef struct {
   const gchar *icon;
   const gchar *label;
@@ -65,6 +77,8 @@ static Button buttons[] = {
   { "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 },
@@ -79,7 +93,9 @@ enum {
   BUTTON_NEXT,
   BUTTON_REFRESH,
   BUTTON_CONFIG,
-  BUTTON_EXPANDER,
+  BUTTON_EXPANDER_1,
+  BUTTON_SCORE,
+  BUTTON_EXPANDER_2,
   BUTTON_ZOOM,
   BUTTON_SEPARATOR,
   BUTTON_BACK,
@@ -91,15 +107,18 @@ 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
-start(GtkContainer *workspace, GooCanvas *theCanvas)
+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);
   current_level = 1;
+  max_score = 0;
 }
 
 static void
@@ -149,6 +168,14 @@ update_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()
 {
@@ -159,6 +186,14 @@ level_widget_new()
 }
 
 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();
@@ -265,7 +300,7 @@ stop_clicked_cb(GtkToolButton *button, gpointer user_data)
 }
 
 static void
-set_flags(const GComprisBarFlags flags)
+bar_set_flags(const GComprisBarFlags flags)
 {
   GcomprisBoard *board = gc_board_get_current();
 
@@ -279,7 +314,10 @@ set_flags(const GComprisBarFlags flags)
   set_button(BUTTON_REFRESH, flags & (GC_BAR_REPEAT | GC_BAR_REPEAT_ICON));
   set_button(BUTTON_CONFIG, flags & GC_BAR_CONFIG);
 
-  set_button(BUTTON_EXPANDER, TRUE);
+  set_button(BUTTON_EXPANDER_1, TRUE);
+  set_button(BUTTON_SCORE, FALSE);
+  set_button(BUTTON_EXPANDER_2, TRUE);
+
   set_button(BUTTON_ZOOM, TRUE);
   set_button(BUTTON_SEPARATOR, TRUE);
   set_button(BUTTON_BACK, board && board->previous_board);
@@ -289,7 +327,27 @@ set_flags(const GComprisBarFlags flags)
 }
 
 static void
-set_level(GcomprisBoard *board)
+score_start(ScoreStyleList style, guint x, guint y, guint max)
+{
+  max_score = max;
+  update_score(0);
+  set_button(BUTTON_SCORE, TRUE);
+}
+
+static void
+score_end()
+{
+  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;
-- 
1.6.5.3


>From 50fe80799c17f07dbb841b5a859531049a8558af Mon Sep 17 00:00:00 2001
From: Aleksey Lim <alsroot at member.fsf.org>
Date: Wed, 13 Jan 2010 18:34:30 +0000
Subject: Do not go to real fullscreen mode in sugar


diff --git a/src/gcompris/gcompris.c b/src/gcompris/gcompris.c
index 0c1f4e3..56e37fd 100644
--- a/src/gcompris/gcompris.c
+++ b/src/gcompris/gcompris.c
@@ -1031,7 +1031,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
-- 
1.6.5.3


>From d583c8c97a9de77c9a176bc30687d7b11b9ccf22 Mon Sep 17 00:00:00 2001
From: Aleksey Lim <alsroot at member.fsf.org>
Date: Thu, 14 Jan 2010 02:28:32 +0000
Subject: Fix wrong Makefile.am


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
 
-- 
1.6.5.3


>From bda8fe9a2197fb7888132437857a860fc357eb77 Mon Sep 17 00:00:00 2001
From: Aleksey Lim <alsroot at member.fsf.org>
Date: Thu, 14 Jan 2010 03:08:00 +0000
Subject: Suppport pycairo<1.8 and remove hard requirement for 2.6 python version


diff --git a/configure.ac b/configure.ac
index 435889a..2a14329 100644
--- a/configure.ac
+++ b/configure.ac
@@ -439,7 +439,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
@@ -459,7 +459,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`
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);
-- 
1.6.5.3


>From f91f4f8ac1008726b9aeb8c1dd5be1ce47fc7d94 Mon Sep 17 00:00:00 2001
From: Aleksey Lim <alsroot at member.fsf.org>
Date: Thu, 14 Jan 2010 03:16:31 +0000
Subject: Build against gtk+<2.18


diff --git a/src/gcompris/gcompris.c b/src/gcompris/gcompris.c
index 56e37fd..7aacdf5 100644
--- a/src/gcompris/gcompris.c
+++ b/src/gcompris/gcompris.c
@@ -1295,9 +1295,7 @@ void gc_log_handler (const gchar *log_domain,
 void
 gc_update_canvas_zoom()
 {
-  GtkAllocation allocation;
-  gtk_widget_get_allocation(alignment, &allocation);
-  _gc_size_allocate_event_callback(NULL, &allocation, NULL);
+  _gc_size_allocate_event_callback(NULL, &alignment->allocation, NULL);
 }
 
 static void
-- 
1.6.5.3


>From 52b0f61e48759b5a165037962ca356d9076d98e6 Mon Sep 17 00:00:00 2001
From: Aleksey Lim <alsroot at member.fsf.org>
Date: Thu, 14 Jan 2010 03:39:12 +0000
Subject: Add customizable timings for several activities to make them useful on XO-1


diff --git a/src/gcompris/gcompris.c b/src/gcompris/gcompris.c
index 7aacdf5..89dbc93 100644
--- a/src/gcompris/gcompris.c
+++ b/src/gcompris/gcompris.c
@@ -143,6 +143,8 @@ 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,
@@ -253,6 +255,12 @@ static GOptionEntry options[] = {
   {"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 }
 };
 
@@ -1834,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 bd0f5c0..6ed7516 100644
--- a/src/gcompris/gcompris.h
+++ b/src/gcompris/gcompris.h
@@ -232,6 +232,9 @@ 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/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/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);
 }
 
-- 
1.6.5.3



More information about the Gcompris-devel mailing list