[maemo-commits] [maemo-commits] r19040 - in projects/haf/trunk/hildon-control-panel: debian src

From: subversion at stage.maemo.org subversion at stage.maemo.org
Date: Wed Aug 5 09:22:43 EEST 2009
Author: kihamala
Date: 2009-08-05 09:22:29 +0300 (Wed, 05 Aug 2009)
New Revision: 19040

Modified:
   projects/haf/trunk/hildon-control-panel/debian/changelog
   projects/haf/trunk/hildon-control-panel/debian/control
   projects/haf/trunk/hildon-control-panel/debian/rules
   projects/haf/trunk/hildon-control-panel/src/Makefile.am
   projects/haf/trunk/hildon-control-panel/src/hcp-app.c
   projects/haf/trunk/hildon-control-panel/src/hcp-app.h
   projects/haf/trunk/hildon-control-panel/src/hcp-program.c
   projects/haf/trunk/hildon-control-panel/src/hcp-program.h
   projects/haf/trunk/hildon-control-panel/src/hcp-window.c
Log:
Changes from David


Modified: projects/haf/trunk/hildon-control-panel/debian/changelog
===================================================================
--- projects/haf/trunk/hildon-control-panel/debian/changelog	2009-08-04 18:07:02 UTC (rev 19039)
+++ projects/haf/trunk/hildon-control-panel/debian/changelog	2009-08-05 06:22:29 UTC (rev 19040)
@@ -1,3 +1,18 @@
+hildon-control-panel (1:2.2.12-1~unreleased) unstable; urgency=low
+
+  David Kedves:
+  * Applets now running in separate processes from HCP
+  * Applets always transient for hildon-control-panel
+  * State saving support for multiple applets
+  * Fixes: NB#98750 - Two instances of Language and Regional settings CPA is
+    shown
+  * Fixes: NB#96278 - Closing one instance of the applet does not close the
+    other.
+  * Fixes: NB#102740 - The maesync CP dialog is not closed when clicked on the
+    status area.
+
+ -- Kimmo Hämäläinen <kimmo.hamalainen at nokia.com>  Tue, 04 Aug 2009 17:14:28 +0300
+
 hildon-control-panel (1:2.2.11-2) unstable; urgency=low
 
   * Fixes: NB#97295 - Applet order not following UI spec

Modified: projects/haf/trunk/hildon-control-panel/debian/control
===================================================================
--- projects/haf/trunk/hildon-control-panel/debian/control	2009-08-04 18:07:02 UTC (rev 19039)
+++ projects/haf/trunk/hildon-control-panel/debian/control	2009-08-05 06:22:29 UTC (rev 19040)
@@ -8,7 +8,7 @@
 Package: hildon-control-panel
 Section: x11
 Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, ${launcher:Depends}, hildon-control-panel-l10n-mr | hildon-control-panel-l10n-mr0, osso-app-killer (>= 1.1), osso-system-lock-l10n-mr | osso-system-lock-l10n-mr0
+Depends: ${shlibs:Depends}, ${misc:Depends}, ${launcher:Depends}, hildon-control-panel-l10n-mr | hildon-control-panel-l10n-mr0, osso-app-killer (>= 1.1), osso-system-lock-l10n-mr | osso-system-lock-l10n-mr0, libosso1 (>> 2.23-1)
 Recommends: hildon-theme-alpha, hildon-keyboard, matchbox-window-manager
 Suggests: hildon-tests
 Conflicts: hildon-base

Modified: projects/haf/trunk/hildon-control-panel/debian/rules
===================================================================
--- projects/haf/trunk/hildon-control-panel/debian/rules	2009-08-04 18:07:02 UTC (rev 19039)
+++ projects/haf/trunk/hildon-control-panel/debian/rules	2009-08-05 06:22:29 UTC (rev 19040)
@@ -102,6 +102,10 @@
     $(CURDIR)/debian/build/usr/bin/controlpanel.launch
 	ln -s /usr/bin/maemo-invoker \
               $(CURDIR)/debian/build/usr/bin/controlpanel
+	mv $(CURDIR)/debian/build/usr/bin/cpa_loader \
+    $(CURDIR)/debian/build/usr/bin/cpa_loader.launch
+	ln -s /usr/bin/maemo-invoker \
+              $(CURDIR)/debian/build/usr/bin/cpa_loader
 endif 
 
 

Modified: projects/haf/trunk/hildon-control-panel/src/Makefile.am
===================================================================
--- projects/haf/trunk/hildon-control-panel/src/Makefile.am	2009-08-04 18:07:02 UTC (rev 19039)
+++ projects/haf/trunk/hildon-control-panel/src/Makefile.am	2009-08-05 06:22:29 UTC (rev 19040)
@@ -33,7 +33,7 @@
 hcp-marshalers.c: hcp-marshalers.list
 	$(GLIB_GENMARSHAL) $< --header --body --prefix=hcp_marshal > $@
 
-bin_PROGRAMS = controlpanel
+bin_PROGRAMS = controlpanel cpa_loader
 
 controlpanel_SOURCES = \
 	$(BUILT_SOURCES) \
@@ -53,6 +53,9 @@
 	hcp-grid.c \
 	hildon-cp-plugin-interface.h
 
+cpa_loader_SOURCES = \
+        hcp-app-loader.c
+
 if USE_MAEMO_TOOLS
 controlpanel_SOURCES += \
 	hcp-rfs.c \
@@ -64,9 +67,12 @@
 
 controlpanel_LDFLAGS = $(MAEMO_LAUNCHER_LDFLAGS)
 
-controlpanel_LDADD = \
-	$(HCP_DEPS_LIBS)
+controlpanel_LDADD = $(HCP_DEPS_LIBS)
 
+cpa_loader_LDFLAGS = $(MAEMO_LAUNCHER_LDFLAGS)
+
+cpa_loader_LDADD = $(HCP_DEPS_LIBS)
+
 hildon_cp_pluginincludeinstdir=$(includedir)/hildon-cp-plugin
 hildon_cp_pluginincludeinst_DATA = hildon-cp-plugin-interface.h
 

Modified: projects/haf/trunk/hildon-control-panel/src/hcp-app.c
===================================================================
--- projects/haf/trunk/hildon-control-panel/src/hcp-app.c	2009-08-04 18:07:02 UTC (rev 19039)
+++ projects/haf/trunk/hildon-control-panel/src/hcp-app.c	2009-08-05 06:22:29 UTC (rev 19040)
@@ -26,12 +26,20 @@
 #include <config.h>
 #endif
 
+#define _XOPEN_SOURCE
+#include <unistd.h>
 #include <dlfcn.h>
 #include <string.h>
+#include <strings.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <signal.h>
 
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
 
 #include "hcp-program.h"
 #include "hcp-app.h"
@@ -65,20 +73,18 @@
     gint                     item_pos;
     gint                     sugg_pos;
     gchar                   *text_domain;
-    void                    *handle;
-    hcp_plugin_exec_f       *exec;
-    hcp_plugin_save_state_f *save_state;
+    gchar                   *wm_class;
+    Window                   xid;
+    GPid                     pid;
 };
 
 typedef struct _PluginLaunchData
 {
   HCPApp     *app;
   gboolean    user_activated;
+  char       *hcp_xid;
 } PluginLaunchData;
 
-#define HCP_PLUGIN_EXEC_SYMBOL        "execute"
-#define HCP_PLUGIN_SAVE_STATE_SYMBOL  "save_state"
-
 static void
 hcp_app_init (HCPApp *app)
 {
@@ -86,147 +92,17 @@
 
   app->priv->name = NULL;
   app->priv->plugin = NULL;
+  app->priv->wm_class = NULL;
   app->priv->icon = NULL;
   app->priv->category = NULL;
   app->priv->is_running = FALSE;
   app->priv->grid = NULL;
   app->priv->item_pos = -1;
   app->priv->text_domain = NULL;
-  app->priv->save_state = NULL;
   app->priv->sugg_pos = G_MAXINT;
 }
 
 static void
-hcp_app_load (HCPApp *app)
-{
-  gchar *plugin_path = NULL;
-  HCPAppPrivate *priv;
-
-  g_return_if_fail (app);
-  g_return_if_fail (HCP_IS_APP (app));
-
-  priv = app->priv; 
-
-  g_return_if_fail (priv->plugin);
-
-  if (*priv->plugin == G_DIR_SEPARATOR)
-  {
-    /* .desktop provided fullpath, use that */
-    plugin_path = g_strdup (priv->plugin);
-  }
-  else
-  {
-    plugin_path = g_build_filename (HCP_PLUGIN_DIR, priv->plugin, NULL);
-  }
-
-  if (!priv->handle)
-  {
-    priv->handle = dlopen (plugin_path, RTLD_LAZY);
-  }
- 
-  g_free (plugin_path);
-
-  if (!priv->handle)
-  {
-    g_warning ("Could not load hildon-control-panel applet %s: %s",
-               priv->plugin,
-               dlerror());
-    return;
-  }
-
-  if (!priv->exec)
-  {
-    priv->exec = dlsym (priv->handle, HCP_PLUGIN_EXEC_SYMBOL);
-  }
-    
-  if (!priv->exec)
-  {
-    g_warning ("Could not find "HCP_PLUGIN_EXEC_SYMBOL" symbol in "
-               "hildon-control-panel applet %s: %s",
-               priv->plugin,
-               dlerror ());
-
-    dlclose (priv->handle);
-
-    priv->handle = NULL;
-	return;
-  }
-
-  if (!priv->save_state)
-  {
-    priv->save_state = dlsym (priv->handle, HCP_PLUGIN_SAVE_STATE_SYMBOL);
-  }
-}
-
-#if 0
-static void
-hcp_app_unload (HCPApp *app)
-{
-  HCPAppPrivate *priv;
-
-  g_return_if_fail (app);
-  g_return_if_fail (HCP_IS_APP (app));
-  g_return_if_fail (plugin->handle);
-
-  priv = app->priv; 
-
-  if (dlclose (priv->handle))
-  {
-      g_warning ("An error occurred when unloading hildon-control-panel "
-                 "applet %s: %s",
-                 priv->plugin,
-                 dlerror ());
-  }
-}
-#endif
-
-static gboolean
-hcp_app_idle_launch (PluginLaunchData *d)
-{
-  HCPAppPrivate *priv;
-  HCPProgram *program = hcp_program_get_instance ();
-
-  g_return_val_if_fail (d, FALSE);
-  g_return_val_if_fail (d->app, FALSE);
-  g_return_val_if_fail (HCP_IS_APP (d->app), FALSE);
-
-  priv = d->app->priv;
-
-  /* required for checking eg. save_state availability and to be on the safe side */
-  hcp_app_load (d->app);
-
-  if (!priv->handle)
-    goto cleanup;
-
-  priv->is_running = TRUE;
-
-  /* Always use hcp->window as parent. */
-
-  priv->exec (program->osso, program->window, d->user_activated);
-
-  priv->is_running = FALSE;
-
-  program->execute = 0;
-
-#if 0
-  /* Do not close the module and reuse it to avoid GType related
-   * errors. */
-  hcp_app_unload (d->app, p);
-#endif
-  
-  /* HCP was launched window less, so we can exit once we are done
-   * with this applet */
-  if (!program->window)
-     gtk_main_quit ();
-
-cleanup:
-  g_object_unref (d->app);
-  g_free (d);
-
-  return FALSE;
-}
-
-static void
 hcp_app_finalize (GObject *object)
 {
   HCPApp *app;
@@ -250,6 +126,12 @@
     priv->plugin = NULL;
   }
 
+  if (priv->wm_class != NULL) 
+  {
+    g_free (priv->wm_class);
+    priv->wm_class = NULL;
+  }
+
   if (priv->icon != NULL) 
   {
     g_free (priv->icon);
@@ -331,6 +213,21 @@
   }
 }
 
+static gchar *
+wm_class_from_so_name (const gchar* so_name)
+{
+  char* ret = g_path_get_basename (so_name);
+  int i, len = strlen (ret);
+  for (i = 0; i < len; i++)
+  {
+    if (!isalpha (ret[i]))
+      ret[i] = '_';
+    else
+      ret[i] = toupper (ret[i]);
+  }
+  return (gchar*) ret;
+}
+
 static void
 hcp_app_set_property (GObject      *gobject,
                       guint        prop_id,
@@ -351,6 +248,8 @@
     case PROP_PLUGIN:
       g_free (priv->plugin);
       priv->plugin = g_strdup (g_value_get_string (value));
+      g_free (priv->wm_class);
+      priv->wm_class =wm_class_from_so_name (priv->plugin);
       break;
 
     case PROP_ICON:
@@ -489,31 +388,170 @@
   return app;
 }
 
+static void
+search_window_r (gchar *wm_class, 
+                 Atom           atom, 
+		 Window         w, 
+		 GSList       **result)
+{
+  unsigned long  nItems;
+  unsigned long  bytesAfter;
+  unsigned char *prop = NULL;
+  Atom           type;
+  int            format;
+  Window         root;
+  Window         parent;
+  Window        *children;
+  unsigned int   count;
+  unsigned int   i;
+
+  /* to avoid HCP exiting on X error ... */
+  gdk_error_trap_push ();
+
+  /* Get the _NET_WM_PID property ... */
+  if (XGetWindowProperty (GDK_DISPLAY (), w, atom,
+                          0, 200, False, XA_STRING, &type, &format, &nItems,
+			  &bytesAfter, &prop) == Success)
+  {
+    /* in case of hit, prepend to result list  */
+    if (prop)
+    {
+      if (strcasecmp ((char*) prop, wm_class) == 0)
+        *result = g_slist_append (*result, GUINT_TO_POINTER (w));
+      XFree (prop);
+    }
+  }
+
+  if (gdk_error_trap_pop () == BadWindow)
+    return; /* Current 'w' Window is closed meanwhile ... */
+
+  /* Recursion to child windows ... */
+  if (XQueryTree(GDK_DISPLAY (), w, &root, &parent, &children, &count))
+  {
+    for (i = 0; i < count; i++)
+      search_window_r (wm_class, atom, children[i], result);
+  }
+}
+
+static Window
+get_xid_by_wm_class (gchar *wm_class)
+{
+  GdkAtom atom_pid;
+  GSList *results = NULL;
+  Window  ret;
+  atom_pid = gdk_atom_intern ("WM_CLASS", FALSE);
+  search_window_r (wm_class, gdk_x11_atom_to_xatom (atom_pid),
+                   GDK_ROOT_WINDOW (), &results);
+
+  if (!results)
+    ret = None;
+  else
+  {
+   /* Return the topmost window xid */
+    ret = GPOINTER_TO_UINT (results->data);
+    g_slist_free (results);
+  }
+
+  return ret; 
+}
+
+static gboolean
+try_focus (HCPApp *app)
+{
+  GdkWindow   *applet;
+  HCPProgram  *program = hcp_program_get_instance ();
+  g_return_val_if_fail (hcp_app_is_running (app), FALSE);
+
+  if (app->priv->xid == None)
+    app->priv->xid = get_xid_by_wm_class (app->priv->wm_class);
+
+  if (app->priv->xid == None)
+    return FALSE; /* applet closed meanwhile ... */
+
+  applet = gdk_window_foreign_new ((GdkNativeWindow) app->priv->xid);
+  if (applet == NULL)
+    return FALSE; /* applet closed meanwhile ... */
+
+  gdk_window_focus (applet, GDK_CURRENT_TIME);
+
+  /* move to the end of the list (to save proper ordering...) */
+  program->running_applets = g_list_remove (program->running_applets,
+                                            (gconstpointer) app);
+  program->running_applets = g_list_append (program->running_applets,
+                                            (gpointer) app);
+
+  g_object_unref (applet);
+
+  return TRUE;
+}
+
+static void
+cpa_child_watch (GPid pid,
+                 gint status,
+		 PluginLaunchData *d)
+{
+  HCPApp      *app = d->app;
+  HCPProgram  *program = hcp_program_get_instance ();
+
+  app->priv->is_running = FALSE;
+  app->priv->xid = None;
+  program->running_applets = g_list_remove (program->running_applets,
+                                            (gconstpointer) app);
+
+  g_debug ("CPA process exited with status = '%d'", status);
+
+  g_object_unref (app);
+  g_free (d->hcp_xid);
+  g_free (d);
+  return;
+}
+
 void
 hcp_app_launch (HCPApp *app, gboolean user_activated)
 {
-  PluginLaunchData *d;
-  HCPProgram *program = hcp_program_get_instance ();
-
   g_return_if_fail (app);
   g_return_if_fail (HCP_IS_APP (app));
-  g_return_if_fail (!hcp_app_is_running (app));
 
-  if (!program->execute)
+  char             *argv[6];
+  PluginLaunchData *d;
+  HCPProgram       *program = hcp_program_get_instance ();
+
+  if (hcp_app_is_running (app))
   {
-      program->execute = 1;
+    try_focus (app);
+    return;
+  }
 
-      d = g_new0 (PluginLaunchData, 1);
+  program->running_applets = g_list_append (program->running_applets,
+                                            (gpointer) app);
 
-      d->user_activated = user_activated;
-      d->app = g_object_ref (app);
+  d = g_new0 (PluginLaunchData, 1);
 
-      /* We launch plugins inside an idle loop so we are still able
-       * to receive DBus messages */
-      g_idle_add ((GSourceFunc) hcp_app_idle_launch, d);
-  }
+  d->user_activated = user_activated;
+  d->app = g_object_ref (app);
+  d->hcp_xid = g_strdup_printf ("%lu", (unsigned long) GDK_WINDOW_XID 
+                                       (GTK_WIDGET (program->window)->window));
+
+  app->priv->is_running = TRUE;
+  app->priv->xid = None;
+
+  argv[0] = "/usr/bin/cpa_loader";
+  argv[1] = app->priv->plugin;
+  argv[2] = app->priv->wm_class;
+  argv[3] = ( d->user_activated ? "1" : "0" );
+  argv[4] = d->hcp_xid;
+  argv[5] = NULL;
+
+  g_spawn_async (NULL, (char**) argv, NULL,
+                 (GSpawnFlags) G_SPAWN_DO_NOT_REAP_CHILD,
+                 NULL, NULL, &app->priv->pid, NULL);
+
+  /* For watching applet exiting ... */
+  g_child_watch_add (app->priv->pid, 
+                     (GChildWatchFunc) cpa_child_watch, d);
 }
 
+
 void
 hcp_app_focus (HCPApp *app)
 {
@@ -538,16 +576,16 @@
 void
 hcp_app_save_state (HCPApp *app)
 {
-  HCPAppPrivate *priv;
-  HCPProgram *program = hcp_program_get_instance ();
-
   g_return_if_fail (app);
   g_return_if_fail (HCP_IS_APP (app));
+  g_return_if_fail (hcp_app_is_running (app));
 
-  priv = app->priv;
-
-  if (priv->save_state)
-    priv->save_state (program->osso, NULL);
+  if (app->priv->pid > 0)
+  {
+    /* Kill SIGTERM to plugin (to save state ... ) */
+    kill ((pid_t) app->priv->pid, 15);
+/*    g_debug ("hcp_app_save_state ('%s')", app->priv->name); */
+  }
 }
 
 gboolean
@@ -566,14 +604,8 @@
 gboolean
 hcp_app_can_save_state (HCPApp *app)
 {
-  HCPAppPrivate *priv;
-
-  g_return_val_if_fail (app, FALSE);
-  g_return_val_if_fail (HCP_IS_APP (app), FALSE);
-
-  priv = app->priv;
-
-  return (priv->save_state != NULL);
+  /* Lets cpa_loader to decide applet can save itself state */
+  return TRUE;
 }
 
 gint
@@ -588,3 +620,13 @@
 
   return ret;
 }
+
+gchar *
+hcp_app_get_plugin (HCPApp *app)
+{
+  g_return_val_if_fail (app, NULL);
+  g_return_val_if_fail (HCP_IS_APP (app), NULL);
+
+  return app->priv->plugin;
+}
+

Modified: projects/haf/trunk/hildon-control-panel/src/hcp-app.h
===================================================================
--- projects/haf/trunk/hildon-control-panel/src/hcp-app.h	2009-08-04 18:07:02 UTC (rev 19039)
+++ projects/haf/trunk/hildon-control-panel/src/hcp-app.h	2009-08-05 06:22:29 UTC (rev 19040)
@@ -42,15 +42,6 @@
 #define HCP_IS_APP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  HCP_TYPE_APP))
 #define HCP_APP_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  HCP_TYPE_APP, HCPAppClass))
 
-typedef osso_return_t (hcp_plugin_exec_f) (
-                       osso_context_t * osso,
-                       gpointer data,
-                       gboolean user_activated);
-
-typedef osso_return_t (hcp_plugin_save_state_f) (
-                       osso_context_t * osso,
-                       gpointer data);
-
 struct _HCPApp 
 {
   GObject gobject;
@@ -81,6 +72,9 @@
 gint         hcp_app_sort_func      (const HCPApp *a, 
                                      const HCPApp *b);
 
+/* result shouldn't be freed */
+gchar       *hcp_app_get_plugin     (HCPApp   *app);
+
 G_END_DECLS
 
 #endif

Modified: projects/haf/trunk/hildon-control-panel/src/hcp-program.c
===================================================================
--- projects/haf/trunk/hildon-control-panel/src/hcp-program.c	2009-08-04 18:07:02 UTC (rev 19039)
+++ projects/haf/trunk/hildon-control-panel/src/hcp-program.c	2009-08-05 06:22:29 UTC (rev 19040)
@@ -40,15 +40,13 @@
 G_DEFINE_TYPE (HCPProgram, hcp_program, G_TYPE_OBJECT);
 
 #define HCP_APP_NAME     "controlpanel"
-#define HCP_APP_VERSION  "0.1"
+#define HCP_APP_VERSION  "0.2"
 
 #define HCP_RPC_SERVICE                     "com.nokia.controlpanel"
 #define HCP_RPC_PATH                        "/com/nokia/controlpanel/rpc"
 #define HCP_RPC_INTERFACE                   "com.nokia.controlpanel.rpc"
 #define HCP_RPC_METHOD_RUN_APPLET           "run_applet"
-#define HCP_RPC_METHOD_SAVE_STATE_APPLET    "save_state_applet"
 #define HCP_RPC_METHOD_TOP_APPLICATION      "top_application"
-#define HCP_RPC_METHOD_IS_APPLET_RUNNING    "is_applet_running"
 
 static void
 hcp_program_show_window (HCPProgram *program)
@@ -93,13 +91,12 @@
 
     if (app)
     {
-      if (!hcp_app_is_running (app))
-      {
-          hcp_app_launch (app, user_activated.value.b);
-      }
+      if (!program->window)
+        hcp_program_show_window (program);
+      else
+        gtk_window_present (GTK_WINDOW (program->window));
 
-      if (GTK_IS_WINDOW (program->window))
-          gtk_window_present (GTK_WINDOW (program->window));
+      hcp_app_launch (app, user_activated.value.b);
 
       retval->type = DBUS_TYPE_INT32;
       retval->value.i = 0;
@@ -107,66 +104,6 @@
       return OSSO_OK;
     }
   }
-  else if ((!strcmp (method, HCP_RPC_METHOD_SAVE_STATE_APPLET)))
-  {
-    osso_rpc_t applet;
-    GHashTable *apps = NULL;
-    HCPApp *app = NULL;
-    
-    if (arguments->len != 1)
-      goto error;
-
-    applet = g_array_index (arguments, osso_rpc_t, 0);
-
-    if (applet.type != DBUS_TYPE_STRING)
-      goto error;
-    
-    g_object_get (G_OBJECT (program->al),
-                  "apps", &apps,
-                  NULL);
-
-    app = g_hash_table_lookup (apps, applet.value.s);
-
-    if (app)
-    {
-      if (hcp_app_is_running (app))
-      {
-        hcp_app_save_state (app);
-      }
-
-      retval->type = DBUS_TYPE_INT32;
-      retval->value.i = 0;
-
-      return OSSO_OK;
-    }
-  }
-  else if ((!strcmp (method, HCP_RPC_METHOD_IS_APPLET_RUNNING)))
-  {
-    osso_rpc_t applet;
-    GHashTable *apps = NULL;
-    HCPApp *app = NULL;
-    
-    if (arguments->len != 1)
-      goto error;
-
-    applet = g_array_index (arguments, osso_rpc_t, 0);
-
-    if (applet.type != DBUS_TYPE_STRING)
-      goto error;
-    
-    g_object_get (G_OBJECT (program->al),
-                  "apps", &apps,
-                  NULL);
-
-    app = g_hash_table_lookup (apps, applet.value.s);
-
-    retval->type = DBUS_TYPE_BOOLEAN;
-    retval->value.b = (app && hcp_app_is_running (app))?
-                            TRUE:
-                            FALSE;
-
-    return OSSO_OK;
-  }
   else if ((!strcmp (method, HCP_RPC_METHOD_TOP_APPLICATION)))
   {
     if (!program->window)
@@ -226,7 +163,7 @@
 static void
 hcp_program_init (HCPProgram *program)
 {
-  program->execute = 0;
+  program->running_applets = NULL;
 
   program->al = (HCPAppList *) hcp_app_list_new ();
   hcp_app_list_update (program->al);
@@ -249,6 +186,11 @@
 
   program = HCP_PROGRAM (object);
 
+  if (program->running_applets != NULL)
+  {
+    g_list_free (program->running_applets);
+  }
+
   if (program->al != NULL) 
   {
     g_object_unref (program->al);

Modified: projects/haf/trunk/hildon-control-panel/src/hcp-program.h
===================================================================
--- projects/haf/trunk/hildon-control-panel/src/hcp-program.h	2009-08-04 18:07:02 UTC (rev 19039)
+++ projects/haf/trunk/hildon-control-panel/src/hcp-program.h	2009-08-05 06:22:29 UTC (rev 19040)
@@ -54,7 +54,7 @@
   GtkWidget      *window;
   HCPAppList     *al;
   osso_context_t *osso;
-  gint            execute;
+  GList          *running_applets;
 };
 
 struct _HCPProgramClass 

Modified: projects/haf/trunk/hildon-control-panel/src/hcp-window.c
===================================================================
--- projects/haf/trunk/hildon-control-panel/src/hcp-window.c	2009-08-04 18:07:02 UTC (rev 19039)
+++ projects/haf/trunk/hildon-control-panel/src/hcp-window.c	2009-08-05 06:22:29 UTC (rev 19040)
@@ -27,6 +27,8 @@
 #endif
 
 #include <libosso.h>
+#include <stdlib.h>
+#include <signal.h>
 #include <hildon/hildon-window.h>
 #include <hildon/hildon-program.h>
 #include <hildon/hildon-defines.h>
@@ -61,8 +63,8 @@
   HCPAppList     *al;
   GtkWidget      *view;
 
-  /* For state save data */
-  gchar          *saved_focused_filename;
+  /* For retrieve/state save data */
+  gchar         **running_apps;
   gint            scroll_value;
 };
 
@@ -71,9 +73,8 @@
 #define HCP_MENU_CUD          _("copa_me_tools_cud")
 
 #define HCP_STATE_GROUP         "HildonControlPanel"
-#define HCP_STATE_FOCUSED       "Focussed"
+#define HCP_STATE_FOCUSED       "Running"
 #define HCP_STATE_SCROLL_VALUE  "ScrollValue"
-#define HCP_STATE_EXECUTE       "Execute"
 
 #define HCP_OPERATOR_WIZARD_DBUS_SERVICE "operator_wizard"
 #define HCP_OPERATOR_WIZARD_LAUNCH       "launch_operator_wizard"
@@ -94,31 +95,44 @@
 
   priv = window->priv;
 
+/*  g_debug ("ENFORCE STATE"); */
+
   /* Actually enforce the saved state */
-  /* If the saved focused item filename is defined, try to 
-   * focus on the item. */
-  if (priv->saved_focused_filename)
+  /* Load previously opened applets ... */
+  if (priv->running_apps)
   {
     GHashTable *apps = NULL;
-    HCPApp *app = NULL;
+    HCPApp     *app = NULL;
+    gint        i;
 
     g_object_get (G_OBJECT (priv->al),
                   "apps", &apps,
                   NULL);
 
-    app = g_hash_table_lookup (apps,
-                               priv->saved_focused_filename);
+    for (i = 0; priv->running_apps && priv->running_apps[i] != NULL; i++)
+    {
+/*      g_debug ("reload applet [%d]: '%s'", i, priv->running_apps[i]); */
+      app = g_hash_table_lookup (apps,
+                                 priv->running_apps[i]);
+      hcp_app_launch (app, FALSE); /* load/restore applet ... */
+    }
     
+    /* the latest/topmost applet should be focused : */
     if (app)
  /*     hcp_app_focus (app); */
       priv->focused_item = app;
 
-    g_free (priv->saved_focused_filename);
-    priv->saved_focused_filename = NULL;
+    g_strfreev (priv->running_apps);
+    priv->running_apps = NULL;
   }
+}
 
-  /* HCPProgram will start the possible plugin in 
-   * program->execute */
+static void 
+hcp_window_showed (GtkWidget *unused,
+                   HCPWindow *window)
+{
+  /* For restoring previous state ... */
+  hcp_window_enforce_state (window);
 }
 
 static void 
@@ -130,15 +144,15 @@
   GKeyFile *keyfile = NULL;
   osso_return_t ret;
   GError *error = NULL;
-  gchar *focused = NULL;
   gint scroll_value;
-  gboolean execute;
 
   g_return_if_fail (window);
   g_return_if_fail (HCP_IS_WINDOW (window));
 
   priv = window->priv;
 
+/*  g_debug ("LOAD STATE"); */
+
   ret = osso_state_read (program->osso, &state);
 
   if (ret != OSSO_OK)
@@ -168,10 +182,10 @@
     goto cleanup;
   }
 
-  focused = g_key_file_get_string (keyfile,
-                                   HCP_STATE_GROUP,
-                                   HCP_STATE_FOCUSED,
-                                   &error);
+  priv->running_apps = g_key_file_get_string_list (keyfile,
+                                                   HCP_STATE_GROUP,
+                                                   HCP_STATE_FOCUSED,
+                                                   NULL, &error);
 
   if (error)
   {
@@ -180,16 +194,6 @@
     goto cleanup;
   }
 
-  if (g_str_has_suffix (focused, ".so"))
-  {
-    priv->saved_focused_filename = focused;
-  }
-  else
-  {
-    priv->saved_focused_filename = NULL;
-    g_free (focused);
-  }
-	  
   scroll_value = g_key_file_get_integer (keyfile,
                                          HCP_STATE_GROUP,
                                          HCP_STATE_SCROLL_VALUE,
@@ -204,20 +208,6 @@
   
   priv->scroll_value = scroll_value;
   
-  execute = g_key_file_get_boolean (keyfile,
-                                    HCP_STATE_GROUP,
-                                    HCP_STATE_EXECUTE,
-                                    &error);
-
-  if (error)
-  {
-    g_warning ("An error occured when reading application state: %s",
-               error->message);
-    goto cleanup;
-  }
-  
-  program->execute = execute;
-
 cleanup:
   if (error)
     g_error_free (error);
@@ -235,8 +225,9 @@
   HCPProgram *program = hcp_program_get_instance ();
   osso_state_t state = { 0, };
   GKeyFile *keyfile = NULL;
+  GList *temp;
+  gint i;
   osso_return_t ret;
-  gchar *focused = NULL;
   GError *error = NULL;
 
   g_return_if_fail (window);
@@ -259,27 +250,36 @@
 
   keyfile = g_key_file_new ();
 
-  g_object_get (G_OBJECT (priv->focused_item),
-                "plugin", &focused,
-                NULL);
+/* ====== Save the running applets with correct ordering ... ====== */
+  int length = g_list_length (program->running_applets);
+  /* yes, i really want a pointer array ... */
+  priv->running_apps = g_new0 (gchar*, length + 1);
 
-  g_key_file_set_string (keyfile,
-                         HCP_STATE_GROUP,
-                         HCP_STATE_FOCUSED,
-                         priv->focused_item?focused:"");
+/*  g_debug ("SAVING STATE"); */
 
-  g_free (focused);
+  /* Get the plugin so-name string array */
+  for (temp = program->running_applets, i = 0;
+       temp != NULL; temp = temp->next, i++)
+  {
+    priv->running_apps[i] = hcp_app_get_plugin (((HCPApp*) temp->data));
+/*    g_debug ("running_apps[%d] = '%s'", i, priv->running_apps[i]); */
+  }
+
+  g_key_file_set_string_list (keyfile,
+                              HCP_STATE_GROUP,
+                              HCP_STATE_FOCUSED,
+              (const gchar**) priv->running_apps,
+                      (gsize) length);
+
+  g_free (priv->running_apps);
+
+/* ====== Save scroll value ... ====== */
   
   g_key_file_set_integer (keyfile,
                           HCP_STATE_GROUP,
                           HCP_STATE_SCROLL_VALUE,
                           priv->scroll_value);
 
-  g_key_file_set_boolean (keyfile,
-                          HCP_STATE_GROUP,
-                          HCP_STATE_EXECUTE,
-                          program->execute);
-
   state.state_data = g_key_file_to_data (keyfile,
                                          &state.state_size,
                                          &error);
@@ -294,12 +294,11 @@
     g_warning ("An error occured when writing application state");
   }
 
-  /* If a plugin is running, save its state */
-  if (program->execute && priv->focused_item && 
-      hcp_app_is_running (priv->focused_item))
-  {
-    hcp_app_save_state (priv->focused_item);
-  }
+  /* If some plugins are running, save their state */
+  if (program->running_applets)
+    g_list_foreach (program->running_applets,
+                    (GFunc) hcp_app_save_state,
+		    NULL);
 
 cleanup:
   if (error)
@@ -315,6 +314,19 @@
     g_key_file_free (keyfile);
 }
 
+static void
+save_state_now (int signal)
+{
+  if (signal == 15)
+  {
+    HCPProgram *program = hcp_program_get_instance ();
+    hcp_window_save_state (HCP_WINDOW (program->window), FALSE);
+
+    /* Immediatly exit ... */
+    exit (0);
+  }
+}
+
 /* Retrieve the configuration (large/small icons)  */
 static void 
 hcp_window_retrieve_configuration (HCPWindow *window)
@@ -391,34 +403,6 @@
 #endif
 
 static void 
-hcp_window_topmost_status_change (GObject *gobject, 
-		                  GParamSpec *arg1,
-			          HCPWindow *window)
-{
-  HCPWindowPrivate *priv;
-  HildonProgram *program = HILDON_PROGRAM (gobject);
-
-  g_return_if_fail (window);
-  g_return_if_fail (HCP_IS_WINDOW (window));
-
-  priv = window->priv;
-
-  if (hildon_program_get_is_topmost (program)) {
-    hildon_program_set_can_hibernate (program, FALSE);
-  } else {
-    /* Do not set ourselves as background killable if we are
-     * running an applet which doesn't implement state-saving */
-    if (!priv->focused_item ||
-        (!hcp_app_is_running (priv->focused_item) || 
-         hcp_app_can_save_state (priv->focused_item)))
-    {
-        hcp_window_save_state (window, FALSE);
-        hildon_program_set_can_hibernate (program, TRUE);
-    }
-  }
-}
-
-static void 
 hcp_window_app_view_focus_cb (HCPAppView *view,
                               HCPApp     *app, 
                               HCPWindow  *window)
@@ -481,18 +465,15 @@
   hcp_window_enforce_state (window);
 }
 
+/* Normal quit ... */
 static void hcp_window_quit (GtkWidget *widget, HCPWindow *window)
 {
   g_return_if_fail (window);
   g_return_if_fail (HCP_IS_WINDOW (window));
 
-  /* we can only close the window, when no applets are running */
-  /**@TODO review this */
-  HCPProgram *program = hcp_program_get_instance ();
-  program->execute = 0;
+  /* Clear the previously save state */
+  hcp_window_save_state (window, TRUE);
 
-  hcp_window_save_state (window, FALSE);
-
   gtk_widget_destroy (GTK_WIDGET (window));
 
   gtk_main_quit ();
@@ -542,8 +523,8 @@
   g_signal_connect (G_OBJECT (window), "destroy",
                     G_CALLBACK (hcp_window_quit), window);
 
-  g_signal_connect(G_OBJECT (program), "notify::is-topmost",
-                   G_CALLBACK (hcp_window_topmost_status_change), window);
+  g_signal_connect_after (G_OBJECT (window), "show",
+                          G_CALLBACK (hcp_window_showed), window);
 
   menu = HILDON_APP_MENU (hildon_app_menu_new ());
 
@@ -553,9 +534,9 @@
 
   /* Reset Factory Settings */
   mi = hildon_button_new_with_text (HILDON_SIZE_AUTO_WIDTH |
-									HILDON_SIZE_FINGER_HEIGHT, 
-									HILDON_BUTTON_ARRANGEMENT_VERTICAL,
-									HCP_MENU_RFS, NULL);
+                                    HILDON_SIZE_FINGER_HEIGHT, 
+                                    HILDON_BUTTON_ARRANGEMENT_VERTICAL,
+                                    HCP_MENU_RFS, NULL);
   hildon_helper_set_logical_font (mi, "SmallSystemFont");
  
   hildon_app_menu_append (menu, GTK_BUTTON(mi));
@@ -599,6 +580,9 @@
           HILDON_PANNABLE_AREA (scrolled_window),
           align);
 
+  /* hildon-desktop will send SIGTERM (15) signal on bgkilling */
+  signal (15, save_state_now); 
+  hildon_program_set_can_hibernate (program, TRUE);
 }
 
 static void
@@ -612,7 +596,6 @@
   priv = window->priv;
 
   priv->focused_item = NULL;
-  priv->saved_focused_filename = NULL;
   priv->scroll_value = 0;
 
   priv->al = g_object_ref (program->al);
@@ -655,49 +638,16 @@
     priv->focused_item = NULL;
   }
 
-  if (priv->saved_focused_filename)
-  {
-    g_free (priv->saved_focused_filename);
-    priv->saved_focused_filename = NULL;
-  }
-
   G_OBJECT_CLASS (hcp_window_parent_class)->finalize (object);
 }
 
 static void
-hcp_window_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
-{
-/* Buggy applets can crash controlpanel, so disabled for now */
-  static gboolean enforce_state = FALSE;
-	
-  GTK_WIDGET_CLASS (hcp_window_parent_class)->size_allocate (widget, allocation);
-
-  if (enforce_state)
-  {
-    HCPProgram *program = hcp_program_get_instance ();
-    HCPWindow *window = HCP_WINDOW (widget);
-
-    hcp_window_enforce_state (HCP_WINDOW (widget));
-
-    if (program->execute == 1 && window->priv->focused_item) 
-    {
-      program->execute = 0;
-      hcp_app_launch (window->priv->focused_item, FALSE);
-    }
-    enforce_state = FALSE;
-  }
-}
-
-static void
 hcp_window_class_init (HCPWindowClass *class)
 {
   GObjectClass *g_object_class = (GObjectClass *) class;
-  GtkWidgetClass *widget_class = (GtkWidgetClass *) class;
 
   g_object_class->finalize = hcp_window_finalize;
 
-  widget_class->size_allocate = hcp_window_size_allocate;
-
   g_type_class_add_private (g_object_class, sizeof (HCPWindowPrivate));
 }
  

More information about the maemo-commits mailing list