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

From: subversion at stage.maemo.org subversion at stage.maemo.org
Date: Thu Aug 6 09:21:34 EEST 2009
Author: kihamala
Date: 2009-08-06 09:21:23 +0300 (Thu, 06 Aug 2009)
New Revision: 19057

Added:
   projects/haf/trunk/hildon-control-panel/src/hcp-app-loader.c
Modified:
   projects/haf/trunk/hildon-control-panel/ChangeLog
   projects/haf/trunk/hildon-control-panel/debian/control
   projects/haf/trunk/hildon-control-panel/src/hcp-app.c
Log:
fixes from David + ChangeLog


Modified: projects/haf/trunk/hildon-control-panel/ChangeLog
===================================================================
--- projects/haf/trunk/hildon-control-panel/ChangeLog	2009-08-05 16:07:21 UTC (rev 19056)
+++ projects/haf/trunk/hildon-control-panel/ChangeLog	2009-08-06 06:21:23 UTC (rev 19057)
@@ -1,3 +1,46 @@
+2009-08-05 David Kedves <dkedves at blumsoft.eu>
+
+	* debian/rules:
+	* src/hcp-app-loader.c:
+	* src/Makefile.am:
+	 - Moving applet-running code to hcp-app-loader.c, it's needed
+	   because applets should run in a separate process from HCP.
+	   (I tried fork () too but all applets crashed somewhere... :-S )
+	  - Setting the WM_CLASS to some known value,
+	    to get the applet window later.
+	  - HCP main window-Xid passed by hpc-app.c, create a wrapper widget
+	    for proper transiency setting in applets
+	* src/hcp-app.[ch]:
+	 - Support for topping a previously opened applet
+	 - Maintaining a list (program->running_applets) of running applets
+	   for proper state saving
+	 + Added some function to get applets XID by WM_CLASS:
+	  - search_window_r, get_xid_by_wm_class, wm_class_from_so_name
+	 + other new functions:
+	  - hcp_app_get_plugin, cpa_child_watch, try_focues
+	 + Dropped functions (cpa_loader doing these now):
+	  - hcp_app_load, hcp_app_unload, hcp_app_idle_launch
+	 + HCPApp private struct changes:
+	  - removed handle and execute / save state function pointers
+	  - added wm_class, pid
+	 + Support to run multiple different applets concurrently :
+	   by g_spawn_async, so applets aren't block the HCP anymore
+	* src/hcp-program.[ch]:
+	 - run_applet RPC method always present the HCP window first
+	 + dropped old (unused) RPC method implementations:
+	  - save_state_applet / is_applet_running
+	 + State saving related changes:
+	  - removed execute from widget struct
+	  - added running_applets list to widget struct
+	* src/hcp-window.[ch]:
+	 + State saving related changes:
+	  - Changed Focussed entry in state file to Running applets list
+	  - On enforce-state reloading applets with the proper ordering 
+	  - Added a signal-handler to state-saving (HD sends SIGTERM on bgkill)
+	  - On window_quit we should not save the state, but clear it
+	  - enforce_state should be run on window show event instead of
+	    size-allocate
+
 2009-07-10 Peter Aradi <peter.aradi at maemo.org>
 
 	* src/hcp-app.c:

Modified: projects/haf/trunk/hildon-control-panel/debian/control
===================================================================
--- projects/haf/trunk/hildon-control-panel/debian/control	2009-08-05 16:07:21 UTC (rev 19056)
+++ projects/haf/trunk/hildon-control-panel/debian/control	2009-08-06 06:21:23 UTC (rev 19057)
@@ -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, libosso1 (>> 2.23-1)
+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
 Recommends: hildon-theme-alpha, hildon-keyboard, matchbox-window-manager
 Suggests: hildon-tests
 Conflicts: hildon-base

Added: projects/haf/trunk/hildon-control-panel/src/hcp-app-loader.c
===================================================================
--- projects/haf/trunk/hildon-control-panel/src/hcp-app-loader.c	2009-08-05 16:07:21 UTC (rev 19056)
+++ projects/haf/trunk/hildon-control-panel/src/hcp-app-loader.c	2009-08-06 06:21:23 UTC (rev 19057)
@@ -0,0 +1,172 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <libosso.h>
+#include <dlfcn.h>
+#include <ctype.h>
+#include <string.h>
+#include <signal.h>
+#include <stdlib.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <hildon/hildon.h>
+
+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);
+
+typedef struct {
+  gchar                   *soname;
+  gchar                   *name;
+  gboolean                 user_activated;
+  void                    *handle;
+  hcp_plugin_exec_f       *exec;
+  hcp_plugin_save_state_f *save_state;
+  osso_context_t          *osso;
+  GtkWidget               *parent;
+} hcp_app_data;
+
+/* Its ugly, but i cannot pass this parameter to sighandler ...  */
+hcp_app_data *plugin_data = NULL;
+
+static void
+save_state (int signal)
+{
+/*  g_debug ("%s : save_state ()", plugin_data->soname); */
+  if (plugin_data->save_state)
+    plugin_data->save_state (plugin_data->osso, NULL);
+  /* State saved, immediatly exiting ... */
+  exit (0);
+}
+
+static gboolean
+open_plugin (hcp_app_data *plugin)
+{
+  gchar* full_path = NULL;
+  if (*plugin->soname == G_DIR_SEPARATOR)
+    full_path = g_strdup (plugin->soname); /* we has the full path :-) */
+  else
+    full_path = g_build_filename (HCP_PLUGIN_DIR, plugin->soname, NULL);
+
+  if (!(plugin->handle = dlopen (full_path, RTLD_LAZY | RTLD_LOCAL)))
+  {
+    g_warning ("Could not load the control-panel applet: %s: %s",
+               plugin->soname, dlerror ());
+    return FALSE;
+  }
+
+  if (!(plugin->exec = dlsym (plugin->handle, "execute" )))
+  {
+    g_warning ("Could not find \"execute\" symbol in "
+               "control-panel applet %s: %s", plugin->soname, dlerror ());
+    return FALSE;
+  }
+
+  plugin->save_state = dlsym (plugin->handle, "save_state");
+
+  return TRUE;
+}
+
+static void
+close_plugin (hcp_app_data* plugin)
+{
+  if (!plugin->handle)
+    return;
+
+  if (dlclose (plugin->handle))
+    g_warning ("An error occured on unloading control-panel applet %s: %s",
+               plugin->soname, dlerror ());
+
+  return;
+}
+
+static gboolean
+execute_plugin (hcp_app_data *plugin)
+{
+  if (open_plugin (plugin))
+    plugin->exec (plugin->osso, plugin->parent, plugin->user_activated);
+  
+  close_plugin (plugin);
+
+  gtk_main_quit ();
+
+  return FALSE;
+}
+
+int
+main (int argc, char **argv)
+{
+  hcp_app_data *plugin;
+  Window        hcp;
+
+  if (argc != 5)
+  {
+  /*
+   * argv[0] "cpa_laucher"
+   * argv[1] "/somewhere/plugin.so"
+   * argv[2] "Plugin name"
+   * argv[3] "0" / "1" -> user_activated
+   * argv[4] "%lu" -> CPA_parent xid
+   */
+    g_debug ("Parameters are: %s plugin.so plugin-name"
+             " 0/1 [user_activated]", argv[0]);
+    return 1;
+  }
+
+  if (!g_thread_supported ()) g_thread_init (NULL);
+  
+  hildon_gtk_init (&argc, &argv);
+
+  gnome_vfs_init ();
+
+  plugin = g_new0 (hcp_app_data, 1); 
+
+  plugin->soname = g_strdup (argv[1]);
+  plugin->name = argv[2];
+  /* Set WM_CLASS ... */
+/*  g_debug ("Set WM_CLASS to '%s'", argv[2]); */
+  g_set_prgname (argv[2]);
+  gdk_set_program_class (argv[2]);
+
+  g_set_application_name ("");
+
+  plugin->user_activated = (argv[3][0] == '1');
+
+  sscanf (argv[4], "%lu", (unsigned long*) &hcp);
+
+  /* Hack begin ... */
+  plugin->parent = gtk_widget_new (GTK_TYPE_WINDOW, "type", GTK_WINDOW_TOPLEVEL, NULL);
+  GTK_OBJECT_FLAGS (plugin->parent) |= (GTK_REALIZED);
+  plugin->parent->window = gdk_window_foreign_new ((GdkNativeWindow) hcp);
+  /* ... hack end */
+
+  plugin->osso = osso_initialize (plugin->name, "1.0",  FALSE, NULL);
+
+  /* To save stating, we should handle SIGTERM */
+  plugin_data = plugin;
+  signal (15, save_state);
+
+  g_idle_add ((GSourceFunc) execute_plugin, plugin);
+
+  gtk_main ();
+
+  /* Clean up ... */
+  osso_deinitialize (plugin->osso);
+  g_free (plugin->soname);
+  g_free (plugin->name);
+  g_free (plugin);
+
+  return 0;
+}

Modified: projects/haf/trunk/hildon-control-panel/src/hcp-app.c
===================================================================
--- projects/haf/trunk/hildon-control-panel/src/hcp-app.c	2009-08-05 16:07:21 UTC (rev 19056)
+++ projects/haf/trunk/hildon-control-panel/src/hcp-app.c	2009-08-06 06:21:23 UTC (rev 19057)
@@ -422,7 +422,9 @@
     }
   }
 
-  if (gdk_error_trap_pop () == BadWindow)
+  /* On X error, should not try query the actual window tree */
+  gdk_flush (); /* for trap_pop */
+  if (gdk_error_trap_pop ())
     return; /* Current 'w' Window is closed meanwhile ... */
 
   /* Recursion to child windows ... */
@@ -458,30 +460,62 @@
 static gboolean
 try_focus (HCPApp *app)
 {
-  GdkWindow   *applet;
-  HCPProgram  *program = hcp_program_get_instance ();
+#ifdef HD_PROPERLY_RAISING
+  XClientMessageEvent  xclient;
+#endif
+  HCPProgram          *program = hcp_program_get_instance ();
   g_return_val_if_fail (hcp_app_is_running (app), FALSE);
 
+  if (!program->running_applets ||
+      !program->running_applets->next)
+    return FALSE; /* only one applet shown, no need to raising */
+
   if (app->priv->xid == None)
     app->priv->xid = get_xid_by_wm_class (app->priv->wm_class);
 
+  g_debug ("applet xid: 0x%lx", (unsigned long) app->priv->xid);
+
   if (app->priv->xid == None)
-    return FALSE; /* applet closed meanwhile ... */
+    return FALSE; /* plugin window isn't exists anymore ...*/
 
-  applet = gdk_window_foreign_new ((GdkNativeWindow) app->priv->xid);
-  if (applet == NULL)
-    return FALSE; /* applet closed meanwhile ... */
+#ifndef HD_PROPERLY_RAISING
+  /* XXX: HACK: force restacking with quickly unmapping / mapping */
+  gdk_error_trap_push ();
+  XUnmapWindow (GDK_DISPLAY (), app->priv->xid);
+  gdk_error_trap_pop ();
 
-  gdk_window_focus (applet, GDK_CURRENT_TIME);
+  gdk_error_trap_push ();
+  XMapRaised (GDK_DISPLAY (), app->priv->xid);
+  gdk_error_trap_pop ();
+#else /* HD_PROPERLY_RAISING */
+  gdk_error_trap_push ();
+  XRaiseWindow (GDK_DISPLAY (), app->priv->xid);
+  gdk_error_trap_pop ();
 
+  memset (&xclient, 0, sizeof (xclient));
+  xclient.type = ClientMessage;
+  xclient.window = app->priv->xid;
+  xclient.message_type = gdk_x11_get_xatom_by_name ("_NET_ACTIVE_WINDOW");
+  xclient.format = 32;
+  xclient.data.l[0] = 1; /* requestor type; we're an app */
+  xclient.data.l[1] = 0;
+  xclient.data.l[2] = None; /* currently active window */
+  xclient.data.l[3] = 0; 
+  xclient.data.l[4] = 0; 
+  
+  gdk_error_trap_push ();
+  XSendEvent (GDK_DISPLAY (), GDK_ROOT_WINDOW (), False,
+              SubstructureRedirectMask | SubstructureNotifyMask,
+              (XEvent *)&xclient);
+  gdk_error_trap_pop ();
+#endif
+
   /* 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;
 }
 

More information about the maemo-commits mailing list