[maemo-commits] [maemo-commits] r8839 - in projects/haf/branches/maemo-af-desktop/hildon-desktop: . background-manager

From: subversion at stage.maemo.org subversion at stage.maemo.org
Date: Wed Dec 20 15:02:11 EET 2006
Author: jobi
Date: 2006-12-20 15:02:10 +0200 (Wed, 20 Dec 2006)
New Revision: 8839

Added:
   projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/
   projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/Makefile.am
   projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/background-manager.c
   projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/background-manager.h
   projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/background-manager.xml
   projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/main.c
Modified:
   projects/haf/branches/maemo-af-desktop/hildon-desktop/Makefile.am
   projects/haf/branches/maemo-af-desktop/hildon-desktop/configure.ac
Log:

2006-12-19  Johan Bilien  <johan.bilien at nokia.com>

	* background-manager/*:
	- added
	- simple and dummy DBus service to composite and set the background



Modified: projects/haf/branches/maemo-af-desktop/hildon-desktop/Makefile.am
===================================================================
--- projects/haf/branches/maemo-af-desktop/hildon-desktop/Makefile.am	2006-12-20 12:39:29 UTC (rev 8838)
+++ projects/haf/branches/maemo-af-desktop/hildon-desktop/Makefile.am	2006-12-20 13:02:10 UTC (rev 8839)
@@ -1 +1 @@
-SUBDIRS = data libhildonwm libhildondesktop src
+SUBDIRS = data libhildonwm libhildondesktop background-manager src

Added: projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/Makefile.am
===================================================================
--- projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/Makefile.am	2006-12-20 12:39:29 UTC (rev 8838)
+++ projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/Makefile.am	2006-12-20 13:02:10 UTC (rev 8839)
@@ -0,0 +1,26 @@
+bin_PROGRAMS = hildon-background-manager
+
+BUILT_SOURCES = background-manager-glue.h
+CLEANFILES = $(BUILT_SOURCES)
+EXTRA_DIST = background-manager.xml
+
+background-manager-glue.h:
+	$(LIBTOOL) --mode=execute $(DBUS_BINDING_TOOL) --prefix=background_manager \
+		       --mode=glib-server --output=background-manager-glue.h \
+			   background-manager.xml
+
+hildon_background_manager_CPPFLAGS = @GNOME_VFS_CFLAGS@ \
+									 @GCONF_CFLAGS@ \
+									 @DBUS_GLIB_CFLAGS@ \
+									 @OSSO_CFLAGS@ \
+									 @GTK_CFLAGS@
+hildon_background_manager_LDFLAGS  = @GNOME_VFS_LIBS@ \
+									 @GCONF_LIBS@ \
+									 @DBUS_GLIB_LIBS@ \
+									 @OSSO_LIBS@ \
+								   	 @GTK_LIBS@
+
+hildon_background_manager_SOURCES = $(BUILT_SOURCES) \
+									background-manager.c \
+									background-manager.h \
+									main.c

Added: projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/background-manager.c
===================================================================
--- projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/background-manager.c	2006-12-20 12:39:29 UTC (rev 8838)
+++ projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/background-manager.c	2006-12-20 13:02:10 UTC (rev 8839)
@@ -0,0 +1,929 @@
+/* -*- mode:C; c-file-style:"gnu"; -*- */
+/*
+ * This file is part of maemo-af-desktop
+ *
+ * Copyright (C) 2006 Nokia Corporation.
+ *
+ * Contact: Karoliina Salminen <karoliina.t.salminen at nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "background-manager.h"
+#include "background-manager-glue.h"
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+/*SAW (allocation watchdog facilities)*/
+#include <osso-mem.h>
+
+#include <libgnomevfs/gnome-vfs.h>
+#include <gconf/gconf-client.h>
+
+#include <hildon-widgets/hildon-banner.h>
+#include <hildon-widgets/hildon-note.h>
+
+
+#define HILDON_HOME_IMAGE_FORMAT           "png"
+#define HILDON_HOME_IMAGE_ALPHA_FULL       255
+#define HILDON_HOME_GCONF_MMC_COVER_OPEN   "/system/osso/af/mmc-cover-open"
+#define HILDON_HOME_TASKNAV_WIDTH          80
+#define HILDON_HOME_TITLEBAR_HEIGHT        60
+
+#define HILDON_HOME_ENV_MMC_MOUNTPOINT     "MMC_MOUNTPOINT"
+
+
+GQuark
+background_manager_error_quark (void)
+{
+  return g_quark_from_static_string ("background-manager-error-quark");
+}
+
+GType
+background_mode_get_type (void)
+{
+  static GType etype = 0;
+
+  if (!etype)
+    {
+      static const GEnumValue values[] =
+      {
+        { BACKGROUND_CENTERED, "BACKGROUND_CENTERED", "centered" },
+        { BACKGROUND_SCALED, "BACKGROUND_SCALED", "scaled" },
+        { BACKGROUND_STRETCHED, "BACKGROUND_STRETCHED", "stretched" },
+        { BACKGROUND_TILED, "BACKGROUND_TILED", "tiled" },
+        { 0, NULL, NULL }
+      };
+      
+      etype = g_enum_register_static ("BackgroundMode", values);
+    }
+
+  return etype;
+}
+
+#define BACKGROUND_MANAGER_GET_PRIVATE(obj) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_BACKGROUND_MANAGER, BackgroundManagerPrivate))
+
+typedef struct _BackgroundData
+{
+  gchar        *image_uri;
+  gchar        *left_bar;
+  gchar        *top_bar;
+  GdkColor     *color;
+  GdkWindow    *window;
+} BackgroundData;
+
+struct _BackgroundManagerPrivate
+{
+  BackgroundData *current;
+  
+  guint is_screen_singleton : 1;
+  GdkScreen *screen;
+  
+  guint bg_timeout;
+  guint loading_note_update_timeout;
+  GtkWidget *loading_note;
+};
+
+static BackgroundData *
+background_data_new ()
+{
+  BackgroundData *data;
+
+  data = g_new0 (BackgroundData, 1);
+  data->color = g_new0 (GdkColor, 1);
+  return data;
+}
+
+static void
+background_data_free (BackgroundData *data)
+{
+  g_free (data->color);
+  g_free (data);
+}
+
+G_DEFINE_TYPE (BackgroundManager, background_manager, G_TYPE_OBJECT);
+
+static void
+background_manager_set_property (GObject      *object,
+				 guint         prop_id,
+				 const GValue *value,
+				 GParamSpec   *pspec)
+{
+  switch (prop_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+background_manager_get_property (GObject    *object,
+				 guint       prop_id,
+				 GValue     *value,
+				 GParamSpec *pspec)
+{
+  switch (prop_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+background_manager_finalize (GObject *object)
+{
+  BackgroundManager *manager = BACKGROUND_MANAGER (object);
+  BackgroundManagerPrivate *priv = manager->priv;
+
+  background_data_free (priv->current);
+  priv->current = NULL;
+
+  G_OBJECT_CLASS (background_manager_parent_class)->finalize (object);
+}
+
+static void
+load_image_oom_cb (size_t  current_size,
+		   size_t  max_size,
+		   void   *context)
+{
+  *(gboolean *) context = TRUE;
+}
+
+#define BUFFER_SIZE	8192
+
+static GdkPixbuf *
+load_image_from_uri (const gchar  *uri,
+                     gboolean      oom_check,
+                     gboolean      cancellable,
+                     GError      **error)
+{
+  GConfClient *client;
+  GdkPixbufLoader *loader;
+  GdkPixbuf *retval = NULL;
+  GnomeVFSHandle *handle = NULL;
+  GnomeVFSResult result;
+  guchar buffer[BUFFER_SIZE];
+  gchar *mmc_mount_point;
+  gboolean image_from_mmc = FALSE;
+  gboolean mmc_cover_open = FALSE;
+  gboolean oom = FALSE;
+
+  g_return_val_if_fail (uri != NULL, NULL);
+
+  client = gconf_client_get_default ();
+  g_assert (GCONF_IS_CLIENT (client));
+
+  mmc_mount_point = g_strconcat ("file://",
+                                 g_getenv (HILDON_HOME_ENV_MMC_MOUNTPOINT),
+                                 NULL);
+  if (g_str_has_prefix (uri, mmc_mount_point))
+    {
+      GError *gconf_error = NULL;
+
+      image_from_mmc = TRUE;
+
+      mmc_cover_open = gconf_client_get_bool (client,
+                                              HILDON_HOME_GCONF_MMC_COVER_OPEN,
+                                              &gconf_error);
+      if (gconf_error)
+        {
+          g_set_error (error, BACKGROUND_MANAGER_ERROR,
+                       BACKGROUND_MANAGER_ERROR_SYSTEM_RESOURCES,
+                       "Unable to check key `%s' from GConf: %s",
+                       HILDON_HOME_GCONF_MMC_COVER_OPEN,
+                       gconf_error->message);
+
+          g_error_free (gconf_error);
+          g_object_unref (client);
+
+          return NULL;
+        }
+
+      if (mmc_cover_open)
+        {
+          g_set_error (error, BACKGROUND_MANAGER_ERROR,
+                       BACKGROUND_MANAGER_ERROR_MMC_OPEN,
+                       "MMC cover is open");
+
+          g_object_unref (client);
+
+          return NULL;
+        }
+    }
+
+  g_free (mmc_mount_point);
+
+  result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
+  if (result != GNOME_VFS_OK)
+    {
+      g_set_error (error, BACKGROUND_MANAGER_ERROR,
+                   BACKGROUND_MANAGER_ERROR_UNREADABLE,
+                   "Unable to open `%s': %s",
+                   uri,
+                   gnome_vfs_result_to_string (result));
+
+      g_object_unref (client);
+
+      return NULL;
+    }
+
+  if (!oom_check &&
+      osso_mem_saw_enable (3 << 20, 32767, load_image_oom_cb, (void *) &oom))
+    {
+      oom = TRUE;
+    }
+
+  loader = gdk_pixbuf_loader_new ();
+
+  result = GNOME_VFS_OK;
+  while (!oom && (result == GNOME_VFS_OK) && (!image_from_mmc || !mmc_cover_open))
+    {
+      GnomeVFSFileSize bytes_read;
+
+      result = gnome_vfs_read (handle, buffer, BUFFER_SIZE, &bytes_read);
+      if (result == GNOME_VFS_ERROR_IO)
+        {
+          gdk_pixbuf_loader_close (loader, NULL);
+          gnome_vfs_close (handle);
+
+          g_set_error (error, BACKGROUND_MANAGER_ERROR,
+                       BACKGROUND_MANAGER_ERROR_IO,
+                       "Unable to load `%s': read failed",
+                       uri);
+          g_debug ((*error)->message);
+
+          g_object_unref (loader);
+          g_object_unref (client);
+
+          retval = NULL;
+          break;
+        }
+
+      if ((result == GNOME_VFS_ERROR_EOF) || (bytes_read == 0))
+        {
+          g_debug ("Reached EOF of `%s', building the pixbuf", uri);
+
+          gdk_pixbuf_loader_close (loader, NULL);
+          gnome_vfs_close (handle);
+
+          retval = gdk_pixbuf_loader_get_pixbuf (loader);
+          if (!retval)
+            {
+              g_set_error (error, BACKGROUND_MANAGER_ERROR,
+                           BACKGROUND_MANAGER_ERROR_CORRUPT,
+                           "Unable to load `%s': loader failed",
+                           uri);
+
+              g_object_unref (loader);
+              g_object_unref (client);
+
+              retval = NULL;
+              break;
+            }
+          else
+            {
+              GdkPixbufFormat *format;
+              gchar *name;
+
+              format = gdk_pixbuf_loader_get_format (loader);
+              name = gdk_pixbuf_format_get_name (format);
+
+              g_debug ("we got the pixbuf (w:%d, h:%d), format: %s",
+                       gdk_pixbuf_get_width (retval),
+                       gdk_pixbuf_get_height (retval),
+                       name);
+
+              g_free (name);
+
+              g_object_ref (retval);
+
+              g_object_unref (client);
+              g_object_unref (loader);
+
+              break;
+            }
+        }
+
+      if (!oom)
+        {
+          GError *load_error = NULL;
+
+          gdk_pixbuf_loader_write (loader, buffer, bytes_read, &load_error);
+          if (load_error &&
+              (load_error->domain == GDK_PIXBUF_ERROR) &&
+              ((load_error->code == GDK_PIXBUF_ERROR_CORRUPT_IMAGE) ||
+               (load_error->code == GDK_PIXBUF_ERROR_UNKNOWN_TYPE)))
+            {
+              g_set_error (error, BACKGROUND_MANAGER_ERROR,
+                           BACKGROUND_MANAGER_ERROR_CORRUPT,
+                           "Unable to load `%s': %s",
+                           uri,
+                           load_error->message);
+
+              g_error_free (load_error);
+              g_object_unref (client);
+
+              retval = NULL;
+              break;
+            }
+        }
+
+      if (!oom && image_from_mmc)
+        {
+          GError *gconf_error = NULL;
+
+          g_debug ("checking if the mmc cover has been opened");
+
+          mmc_cover_open = gconf_client_get_bool (client,
+                                                  HILDON_HOME_GCONF_MMC_COVER_OPEN,
+                                                  &gconf_error);
+          if (gconf_error)
+            {
+              g_set_error (error, BACKGROUND_MANAGER_ERROR,
+                           BACKGROUND_MANAGER_ERROR_SYSTEM_RESOURCES,
+                           "Unable to check key `%s' from GConf: %s",
+                           HILDON_HOME_GCONF_MMC_COVER_OPEN,
+                           gconf_error->message);
+
+              g_error_free (gconf_error);
+              gdk_pixbuf_loader_close (loader, NULL);
+              gnome_vfs_close (handle);
+              g_object_unref (client);
+
+              retval = NULL;
+              break;
+            }
+
+          if (mmc_cover_open)
+            {
+              g_set_error (error, BACKGROUND_MANAGER_ERROR,
+                           BACKGROUND_MANAGER_ERROR_MMC_OPEN,
+                           "MMC cover is open");
+
+              gdk_pixbuf_loader_close (loader, NULL);
+              gnome_vfs_close (handle);
+              g_object_unref (client);
+
+              retval = NULL;
+              break;
+            }
+        }
+    }
+
+  if (oom_check)
+    osso_mem_saw_disable ();
+
+  return retval;
+}
+
+static GdkPixbuf *
+load_image_from_file (const gchar  *filename,
+                      gboolean cancellable,
+                      GError      **error)
+{
+  gchar *filename_uri;
+  GdkPixbuf *retval;
+  GError *uri_error;
+  GError *load_error;
+
+  uri_error = NULL;
+  filename_uri = g_filename_to_uri (filename, NULL, &uri_error);
+  if (uri_error)
+    {
+      g_set_error (error, BACKGROUND_MANAGER_ERROR,
+		   BACKGROUND_MANAGER_ERROR_UNKNOWN,
+		   "Unable to convert `%s' to a valid URI: %s",
+		   filename,
+		   uri_error->message);
+      g_error_free (uri_error);
+
+      return NULL;
+    }
+
+  load_error = NULL;
+  retval = load_image_from_uri (filename_uri, TRUE, cancellable, &load_error);
+  if (load_error)
+    {
+      g_propagate_error (error, load_error);
+    }
+
+  g_free (filename_uri);
+
+  return retval;
+}
+
+
+static GdkPixbuf *
+create_background_from_color (const GdkColor  *src,
+			      gint             width,
+			      gint             height)
+{
+  GdkPixbuf *dest;
+  guint32 color = 0;
+
+  g_return_val_if_fail (src != NULL, NULL);
+
+  color = (guint8) (src->red >> 8) << 24 |
+	  (guint8) (src->green >> 8) << 16 |
+	  (guint8) (src->blue >> 8) << 8 |
+	  0xff;
+
+  dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
+  gdk_pixbuf_fill (dest, color);
+
+  return dest;
+}
+
+/* this gets rather convoluted because we want to create a background
+ * pixbuf of the same size of the screen and we must account the white
+ * space left for the task navigator; so, we must shift the image of
+ * HILDON_HOME_TASKNAV_WIDTH pixels on the x axis.
+ */
+static GdkPixbuf *
+create_background_from_pixbuf (const GdkPixbuf  *src,
+                               const GdkColor   *fill,
+                               BackgroundMode    mode,
+                               gint              width,
+                               gint              height,
+                               GError          **error)
+{
+  GdkPixbuf *dest = NULL;
+  gint src_width, src_height;
+  gint dest_x, dest_y;
+  gdouble scaling_ratio;
+  gdouble off_x, off_y;
+
+  g_return_val_if_fail (src != NULL, NULL);
+  g_return_val_if_fail (fill != NULL, NULL);
+
+  dest = create_background_from_color (fill, width, height);
+  if (!dest)
+    {
+      g_set_error (error, BACKGROUND_MANAGER_ERROR,
+		   BACKGROUND_MANAGER_ERROR_SYSTEM_RESOURCES,
+		   "Unable to create background color");
+
+      return NULL;
+    }
+
+  src_width = gdk_pixbuf_get_width (src);
+  src_height = gdk_pixbuf_get_height (src);
+
+  g_debug ("*** background: (w:%d, h:%d), mode: %d",
+	   src_width,
+	   src_height,
+	   mode);
+
+  if (src_width == (width - HILDON_HOME_TASKNAV_WIDTH) &&
+      src_height == height)
+    {
+      gdk_pixbuf_composite (src,
+		            dest,
+			    0, 0,
+			    width, height,
+			    HILDON_HOME_TASKNAV_WIDTH, 0,
+			    1.0, 1.0,
+			    GDK_INTERP_NEAREST,
+			    0xFF);
+      if (!dest)
+        {
+          g_set_error (error, BACKGROUND_MANAGER_ERROR,
+		       BACKGROUND_MANAGER_ERROR_SYSTEM_RESOURCES,
+		       "Unable to composite the background color with the image");
+
+	  return NULL;
+	}
+
+      g_debug ("*** We got a background pixbuf");
+
+      return dest;
+    }
+  
+  switch (mode)
+    {
+    case BACKGROUND_CENTERED:
+      if (src_width < (width - HILDON_HOME_TASKNAV_WIDTH))
+        {
+          dest_x = MAX (HILDON_HOME_TASKNAV_WIDTH,
+                        (width - HILDON_HOME_TASKNAV_WIDTH - src_width)
+                         / 2
+                         + HILDON_HOME_TASKNAV_WIDTH);
+	}
+      else
+	{
+	  dest_x = MAX (HILDON_HOME_TASKNAV_WIDTH,
+                        (width - HILDON_HOME_TASKNAV_WIDTH - src_width)
+                        / 2
+                        + HILDON_HOME_TASKNAV_WIDTH);
+	}
+
+      if (src_height < height)
+        {
+          dest_y = MAX (0, (height - src_height) / 2);
+	}
+      else
+        {
+	  dest_y = MAX (0, (height - src_height) / 2);
+	}
+      
+      off_x = (width - HILDON_HOME_TASKNAV_WIDTH - src_width)
+              / 2
+              + HILDON_HOME_TASKNAV_WIDTH;
+      off_y = (height-src_height) / 2;
+      
+      gdk_pixbuf_composite (src, dest,
+		            dest_x, dest_y,
+		            MIN (src_width, width - HILDON_HOME_TASKNAV_WIDTH),
+			    MIN (src_height, height),
+			    off_x, off_y,
+			    1.0, 1.0,
+			    GDK_INTERP_NEAREST,
+			    HILDON_HOME_IMAGE_ALPHA_FULL);
+      break;
+    case BACKGROUND_SCALED:
+      scaling_ratio = MIN ((gdouble) ((gdouble) (width - HILDON_HOME_TASKNAV_WIDTH) / src_width),
+		           (gdouble) height / src_height);
+      dest_x = (gint) (MAX (HILDON_HOME_TASKNAV_WIDTH,
+                HILDON_HOME_TASKNAV_WIDTH +
+			    (width
+			     - HILDON_HOME_TASKNAV_WIDTH
+			     - scaling_ratio
+			     * src_width) / 2));
+      dest_y = (gint) (MAX (0,
+			    (height
+			     - scaling_ratio
+			     * src_height) / 2));
+
+      gdk_pixbuf_composite (src, dest,
+			    dest_x, dest_y,
+		        scaling_ratio * src_width,
+			    scaling_ratio * src_height,
+			    MAX (HILDON_HOME_TASKNAV_WIDTH,
+                 HILDON_HOME_TASKNAV_WIDTH +
+				 (width
+				  - HILDON_HOME_TASKNAV_WIDTH
+				  - scaling_ratio
+				  * src_width) / 2),
+			    MAX (0, 
+				 (height
+				  - scaling_ratio
+				  * src_height) / 2),
+			    scaling_ratio, scaling_ratio,
+			    GDK_INTERP_NEAREST,
+			    HILDON_HOME_IMAGE_ALPHA_FULL);
+      break;
+    case BACKGROUND_TILED:
+        for (dest_x = HILDON_HOME_TASKNAV_WIDTH;
+	     dest_x < width;
+	     dest_x += src_width)
+          {
+            for (dest_y = 0;
+	         dest_y < height;
+                 dest_y += src_height)
+              {
+                gdk_pixbuf_composite (src, dest,
+				      dest_x, dest_y,
+				      MIN (src_width, width - dest_x),
+				      MIN (src_height, height - dest_y),
+				      dest_x, dest_y,
+				      1.0, 1.0,
+				      GDK_INTERP_NEAREST,
+				      HILDON_HOME_IMAGE_ALPHA_FULL);
+              }
+	  }
+      break;
+    case BACKGROUND_STRETCHED:
+      gdk_pixbuf_composite (src, dest,
+	      		    HILDON_HOME_TASKNAV_WIDTH, 0,
+			    width - HILDON_HOME_TASKNAV_WIDTH, height,
+			    HILDON_HOME_TASKNAV_WIDTH, 0,
+			    (gdouble) (width-HILDON_HOME_TASKNAV_WIDTH) / src_width,
+			    ((gdouble) height) / src_height,
+			    GDK_INTERP_NEAREST,
+			    HILDON_HOME_IMAGE_ALPHA_FULL);
+      break;
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  return dest;
+}
+
+/* We create the cached pixbuf compositing the sidebar and the titlebar
+ * pixbufs from their relative files; we use a child process to retain
+ * some interactivity; we use a pipe to move the error messages from
+ * the child process to the background manager. the child process saves
+ * the composed image to the cache file and we read it inside the
+ * child notification callback
+ */
+static GdkPixbuf *
+composite_background (const GdkPixbuf  *bg_image,
+                      const GdkColor   *bg_color,
+                      BackgroundMode    mode,
+                      const gchar      *sidebar_path,
+                      const gchar      *titlebar_path,
+                      gint              window_width,
+                      gint              window_height,
+                      gboolean          cancellable,
+                      GError          **error)
+{
+  GError *bg_error;
+  GdkPixbuf *pixbuf;
+  GdkPixbuf *compose;
+
+  g_debug ("Compositing background image...");
+
+  bg_error = NULL;
+
+  if (bg_image)
+    {
+      pixbuf = create_background_from_pixbuf (bg_image,
+					      bg_color,
+					      mode,
+					      window_width,
+					      window_height,
+					      &bg_error);
+    }
+  else
+    {
+      pixbuf = create_background_from_color (bg_color,
+					     window_width,
+					     window_height
+                         );
+
+      g_return_val_if_fail (pixbuf, NULL);
+    }
+  
+  if (bg_error)
+    {
+      g_propagate_error (error, bg_error);
+
+      return NULL;
+    }
+
+  compose = load_image_from_file (titlebar_path, cancellable, &bg_error);
+
+  if (bg_error)
+    {
+      g_warning ("Unable to load titlebar pixbuf: %s", bg_error->message);
+      
+      g_error_free (bg_error);
+      bg_error = NULL;
+    }
+  else if (!compose)
+    {
+      g_debug ("Assuming loading of titlebar cancelled");
+      if (pixbuf)
+        g_object_unref (pixbuf);
+      return NULL;
+    }
+  else
+    {
+      g_debug ("Compositing titlebar");
+      
+      gdk_pixbuf_composite (compose,
+		            pixbuf,
+			    HILDON_HOME_TASKNAV_WIDTH, 0,
+			    gdk_pixbuf_get_width (compose),
+			    gdk_pixbuf_get_height (compose),
+			    HILDON_HOME_TASKNAV_WIDTH, 0,
+			    1.0, 1.0,
+			    GDK_INTERP_NEAREST,
+			    HILDON_HOME_IMAGE_ALPHA_FULL);
+
+      g_object_unref (compose);
+      compose = NULL;
+    }
+ 
+  compose = load_image_from_file (sidebar_path, cancellable, &bg_error);
+  if (bg_error)
+    {
+      g_warning ("Unable to load sidebar pixbuf: %s", bg_error->message);
+      
+      g_error_free (bg_error);
+      bg_error = NULL;
+    }
+  else if (!compose)
+    {
+      g_debug ("Assuming loading of sidebar cancelled");
+      if (pixbuf)
+        g_object_unref (pixbuf);
+      return NULL;
+    }
+  else
+    {
+      gint width = gdk_pixbuf_get_width (compose);
+      gint height = gdk_pixbuf_get_height (compose);
+      gint sidebar_height;
+      
+      g_debug ("Compositing sidebar (w:%d, h:%d)",
+	       width, height);
+      
+      sidebar_height = window_height
+	               - HILDON_HOME_TITLEBAR_HEIGHT;
+      if (height != sidebar_height)
+        {
+          GdkPixbuf *scaled;
+	  gint i;
+
+	  scaled = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+			           width, sidebar_height);
+	  for (i = 0; i < (sidebar_height - height); i += height)
+            {
+              gdk_pixbuf_copy_area (compose,
+			            0, 0,
+				    width, height,
+				    scaled,
+				    0, i + height);
+	    }
+
+	  g_object_unref (compose);
+	  compose = scaled;
+	}
+      
+      gdk_pixbuf_composite (compose,
+		            pixbuf,
+			    HILDON_HOME_TASKNAV_WIDTH,
+			    HILDON_HOME_TITLEBAR_HEIGHT,
+			    gdk_pixbuf_get_width (compose),
+			    gdk_pixbuf_get_height (compose),
+			    HILDON_HOME_TASKNAV_WIDTH,
+			    0,
+			    1.0, 1.0,
+			    GDK_INTERP_NEAREST,
+			    HILDON_HOME_IMAGE_ALPHA_FULL);
+
+      g_object_unref (compose);
+      compose = NULL;
+    }
+  
+  return pixbuf;
+}
+
+
+static void
+background_manager_class_init (BackgroundManagerClass *klass)
+{
+  GObjectClass     *gobject_class = G_OBJECT_CLASS (klass);
+  GError           *error = NULL;
+
+  gobject_class->set_property = background_manager_set_property;
+  gobject_class->get_property = background_manager_get_property;
+  gobject_class->finalize = background_manager_finalize;
+  g_type_class_add_private (gobject_class, sizeof (BackgroundManagerPrivate));
+
+  klass->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+
+  if (error)
+    {
+      klass->connection = NULL;
+      g_warning ("Could not get DBus connection");
+      g_error_free (error);
+      return;
+    }
+
+  dbus_g_object_type_install_info (TYPE_BACKGROUND_MANAGER,
+                                   &dbus_glib_background_manager_object_info);
+}
+
+static void
+background_manager_init (BackgroundManager *manager)
+{
+  BackgroundManagerPrivate     *priv;
+  BackgroundManagerClass       *klass;
+
+  manager->priv = priv = BACKGROUND_MANAGER_GET_PRIVATE (manager);
+
+  klass = BACKGROUND_MANAGER_GET_CLASS (manager);
+  if (klass->connection)
+    dbus_g_connection_register_g_object (klass->connection,
+                                         BACKGROUND_MANAGER_DBUS_OBJECT_PATH,
+                                         G_OBJECT (manager));
+
+}
+
+/* RPC method */
+gboolean
+background_manager_set_background (BackgroundManager   *manager,
+                                   gint                 window_xid,
+                                   const gchar         *filename,
+                                   const gchar         *top_bar,
+                                   const gchar         *left_bar,
+                                   guint16              red,
+                                   guint16              green,
+                                   guint16              blue,
+                                   BackgroundMode       mode,
+                                   GError             **error)
+{
+  BackgroundManagerPrivate *priv;
+  BackgroundData           *data;
+  GdkWindow                *window;
+  GdkPixbuf                *image = NULL;
+  GdkPixbuf                *background = NULL;
+  GdkColormap              *colormap;
+  GdkPixmap                *pixmap  = NULL;
+  GdkBitmap                *bitmask = NULL;
+  GError                   *local_error = NULL;
+  gint                      width, height;
+  
+  window = gdk_window_foreign_new (window_xid);
+
+  if (!window)
+    {
+      g_set_error (error,
+                   background_manager_error_quark (),
+                   BACKGROUND_MANAGER_ERROR_WINDOW,
+                   "Window not found");
+      return FALSE;
+    }
+  
+  priv = BACKGROUND_MANAGER_GET_PRIVATE (manager);
+
+  background_data_free (priv->current);
+  priv->current = data = background_data_new ();
+
+  data->color->red   = red;
+  data->color->blue  = blue;
+  data->color->green = green;
+
+  data->window = window;
+
+  data->image_uri = g_strdup (filename);
+  data->top_bar   = g_strdup (top_bar);
+  data->left_bar  = g_strdup (left_bar);
+
+  if (data->image_uri)
+    {
+      image = load_image_from_uri (data->image_uri,
+                                   TRUE, 
+                                   TRUE,
+                                   &local_error);
+      if (local_error)
+        {
+          g_propagate_error (error, local_error);
+          return FALSE;
+        }
+    }
+
+  gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
+
+  background = composite_background (image,
+                                     data->color,
+                                     mode,
+                                     data->top_bar,
+                                     data->left_bar,
+                                     width,
+                                     height,
+                                     TRUE,
+                                     &local_error);
+
+  if (image)
+    g_object_unref (image);
+
+  if (local_error)
+    {
+      g_propagate_error (error, local_error);
+      return FALSE;
+    }
+  
+  colormap = gdk_drawable_get_colormap (GDK_DRAWABLE (window));
+
+  gdk_pixbuf_render_pixmap_and_mask_for_colormap (background,
+                                                  colormap,
+                                                  &pixmap,
+                                                  &bitmask,
+                                                  0);
+  if (pixmap)
+    {
+      gdk_window_set_back_pixmap (window, pixmap, FALSE);
+      g_object_unref (pixmap);
+    }
+
+  if (bitmask)
+    g_object_unref (bitmask);
+
+  if (background)
+    g_object_unref (background);
+
+  gdk_flush ();
+  return TRUE;
+}

Added: projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/background-manager.h
===================================================================
--- projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/background-manager.h	2006-12-20 12:39:29 UTC (rev 8838)
+++ projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/background-manager.h	2006-12-20 13:02:10 UTC (rev 8839)
@@ -0,0 +1,110 @@
+/* -*- mode:C; c-file-style:"gnu"; -*- */
+/*
+ * This file is part of maemo-af-desktop
+ *
+ * Copyright (C) 2006 Nokia Corporation.
+ *
+ * Contact: Karoliina Salminen <karoliina.t.salminen at nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __BACKGROUND_MANAGER_H__
+#define __BACKGROUND_MANAGER_H__
+
+#include <glib-object.h>
+#include <gdk/gdkcolor.h>
+#include <gdk/gdkwindow.h>
+
+#include <dbus/dbus-glib-bindings.h>
+
+#define TYPE_BACKGROUND_MODE			(background_mode_get_type ())
+#define TYPE_BACKGROUND_MANAGER			(background_manager_get_type ())
+#define BACKGROUND_MANAGER_ERROR		(background_manager_error_quark ())
+
+#define BACKGROUND_MANAGER(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BACKGROUND_MANAGER, BackgroundManager))
+#define IS_BACKGROUND_MANAGER(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BACKGROUND_MANAGER))
+#define BACKGROUND_MANAGER_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BACKGROUND_MANAGER, BackgroundManagerClass))
+#define IS_BACKGROUND_MANAGER_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BACKGROUND_MANAGER))
+#define BACKGROUND_MANAGER_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BACKGROUND_MANAGER, BackgroundManagerClass))
+
+#define BACKGROUND_MANAGER_DBUS_OBJECT_PATH "/org/maemo/hildon/background_manager"
+
+
+G_BEGIN_DECLS
+
+typedef struct _BackgroundManager		    BackgroundManager;
+typedef struct _BackgroundManagerPrivate	BackgroundManagerPrivate;
+typedef struct _BackgroundManagerClass		BackgroundManagerClass;
+
+typedef enum {
+  BACKGROUND_CENTERED,
+  BACKGROUND_SCALED,
+  BACKGROUND_STRETCHED,
+  BACKGROUND_TILED
+} BackgroundMode;
+
+GType background_mode_get_type (void) G_GNUC_CONST;
+
+typedef enum {
+  BACKGROUND_MANAGER_ERROR_MEMORY,
+  BACKGROUND_MANAGER_ERROR_CONNECTIVITY,
+  BACKGROUND_MANAGER_ERROR_CORRUPT,
+  BACKGROUND_MANAGER_ERROR_UNREADABLE,
+  BACKGROUND_MANAGER_ERROR_MMC_OPEN,
+  BACKGROUND_MANAGER_ERROR_SYSTEM_RESOURCES,
+  BACKGROUND_MANAGER_ERROR_FLASH_FULL,
+  BACKGROUND_MANAGER_ERROR_IO,
+  BACKGROUND_MANAGER_ERROR_WINDOW,
+
+  BACKGROUND_MANAGER_ERROR_UNKNOWN
+} BackgroundManagerError;
+
+GQuark background_manager_error_quark (void);
+
+
+struct _BackgroundManager
+{
+  GObject parent_instance;
+
+  BackgroundManagerPrivate *priv;
+};
+
+struct _BackgroundManagerClass
+{
+  GObjectClass parent_class;
+
+  DBusGConnection  *connection;
+};
+
+GType                 background_manager_get_type          (void) G_GNUC_CONST;
+
+gboolean              background_manager_set_background 
+                            (BackgroundManager   *manager,
+                             gint                 window_xid,
+                             const gchar         *filename,
+                             const gchar         *top_bar,
+                             const gchar         *left_bar,
+                             guint16              red,
+                             guint16              green,
+                             guint16              blue,
+                             BackgroundMode       mode,
+                             GError             **error);
+
+
+G_END_DECLS
+
+#endif /* __BACKGROUND_MANAGER_H__ */

Added: projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/background-manager.xml
===================================================================
--- projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/background-manager.xml	2006-12-20 12:39:29 UTC (rev 8838)
+++ projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/background-manager.xml	2006-12-20 13:02:10 UTC (rev 8839)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/">
+  <interface name="com.nokia.HildonBackgroundManager">
+    <method name="SetBackground">
+      <arg type="i"/>
+      <arg type="s"/>
+      <arg type="s"/>
+      <arg type="s"/>
+      <arg type="i"/>
+      <arg type="i"/>
+      <arg type="i"/>
+      <arg type="i"/>
+    </method>
+  </interface>
+</node>

Added: projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/main.c
===================================================================
--- projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/main.c	2006-12-20 12:39:29 UTC (rev 8838)
+++ projects/haf/branches/maemo-af-desktop/hildon-desktop/background-manager/main.c	2006-12-20 13:02:10 UTC (rev 8839)
@@ -0,0 +1,72 @@
+/*
+ * This file is part of hildon-desktop
+ *
+ * Copyright (C) 2006 Nokia Corporation.
+ *
+ * Author: Johan Bilien <johan.bilien at nokia.com>
+ * Contact: Karoliina Salminen <karoliina.t.salminen at nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "background-manager.h"
+
+#include <dbus/dbus-glib.h>
+#include <gtk/gtkmain.h>
+
+#define BACKGROUND_MANAGER_SERVICE_NAME "org.maemo.hildon"
+
+int
+main (int argc, char **argv)
+{
+  GObject              *bm;
+  DBusGConnection      *connection;
+  DBusGProxy           *driver_proxy;
+  GError               *error = NULL;
+  gint                  request_ret;
+  
+  gtk_init (&argc, &argv);
+
+  connection = dbus_g_bus_get (DBUS_BUS_STARTER, &error);
+  if (error)
+    {
+      g_warning ("Could not get the DBus connection: %s", error->message);
+      g_error_free (error);
+      return 1;
+    }
+
+  bm = g_object_new (TYPE_BACKGROUND_MANAGER, NULL);
+
+  /* Get the proxy for the DBus object */
+  driver_proxy = dbus_g_proxy_new_for_name (connection,
+                                            DBUS_SERVICE_DBUS,
+                                            DBUS_PATH_DBUS,
+                                            DBUS_INTERFACE_DBUS);
+
+  if(!org_freedesktop_DBus_request_name (driver_proxy,
+                                         BACKGROUND_MANAGER_SERVICE_NAME,
+                                         0,
+                                         &request_ret,
+                                         &error))
+    {
+      g_warning ("Unable to register service: %s", error->message);
+      g_error_free (error);
+      return -1;
+    }
+
+  gtk_main ();
+  return 0;
+}

Modified: projects/haf/branches/maemo-af-desktop/hildon-desktop/configure.ac
===================================================================
--- projects/haf/branches/maemo-af-desktop/hildon-desktop/configure.ac	2006-12-20 12:39:29 UTC (rev 8838)
+++ projects/haf/branches/maemo-af-desktop/hildon-desktop/configure.ac	2006-12-20 13:02:10 UTC (rev 8839)
@@ -30,6 +30,7 @@
 AC_HEADER_STDC
 
 AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal)
+AC_PATH_PROG(DBUS_BINDING_TOOL, dbus-binding-tool)
 
 if test foobar${hildon_use_timestamping} = foobaryes
 then
@@ -76,6 +77,10 @@
 AC_SUBST(OSSO_LIBS)
 AC_SUBST(OSSO_CFLAGS)
 
+PKG_CHECK_MODULES(DBUS_GLIB, dbus-glib-1)
+AC_SUBST(DBUS_GLIB_LIBS)
+AC_SUBST(DBUS_GLIB_CFLAGS)
+
 PKG_CHECK_MODULES(HILDONBASELIB, hildon-base-lib >= 0.7.4)
 AC_SUBST(HILDONBASELIB_LIBS)
 AC_SUBST(HILDONBASELIB_CFLAGS)
@@ -88,6 +93,10 @@
 AC_SUBST(GCONF_LIBS)
 AC_SUBST(GCONF_CFLAGS)
 
+PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.6)
+AC_SUBST(GTK_LIBS)
+AC_SUBST(GTK_CFLAGS)
+
 PKG_CHECK_MODULES(GNOME_VFS, gnome-vfs-2.0 >= 2.8.3)
 AC_SUBST(GNOME_VFS_CFLAGS)
 AC_SUBST(GNOME_VFS_LIBS)
@@ -141,5 +150,6 @@
 	libhildonwm/libhildonwm.pc \
 	libhildondesktop/Makefile \
 	libhildondesktop/libhildondesktop.pc \
+    background-manager/Makefile \
 	data/Makefile \
 	src/Makefile)


More information about the maemo-commits mailing list