Bug 533017 - Bring Fennec to the top when clicking on it from the hildon desktop [r=stuart]
authorMark Finkle <mfinkle@mozilla.com>
Thu, 10 Dec 2009 17:00:19 -0500
changeset 35528 c3a97b86e763f10e2c41ea9ee1c0bcc7710ce497
parent 35527 fc916a0487c3d67302e52586ace1770395157b2d
child 35529 b7824c1c8596ad93790c8f8e3c0f5135c8f2ddac
push idunknown
push userunknown
push dateunknown
reviewersstuart
bugs533017
milestone1.9.3a1pre
Bug 533017 - Bring Fennec to the top when clicking on it from the hildon desktop [r=stuart]
toolkit/xre/nsNativeAppSupportUnix.cpp
--- a/toolkit/xre/nsNativeAppSupportUnix.cpp
+++ b/toolkit/xre/nsNativeAppSupportUnix.cpp
@@ -43,28 +43,33 @@
 #include "nsISupportsPrimitives.h"
 #include "nsIObserverService.h"
 #include "nsIAppStartup.h"
 #include "nsServiceManagerUtils.h"
 #include "prlink.h"
 #include "nsXREDirProvider.h"
 #include "nsReadableUtils.h"
 
+#include "nsIFile.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsICommandLineRunner.h"
+#include "nsIWindowMediator.h"
+#include "nsIDOMWindowInternal.h"
+
 #include <stdlib.h>
 #include <glib.h>
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
 #ifdef NS_OSSO
 struct DBusMessage;  /* libosso.h references internals of dbus */
 
 #include <dbus/dbus.h>
 #include <dbus/dbus-protocol.h>
 #include <libosso.h>
-
 #endif
 
 #define MIN_GTK_MAJOR_VERSION 2
 #define MIN_GTK_MINOR_VERSION 10
 #define UNSUPPORTED_GTK_MSG "We're sorry, this application requires a version of the GTK+ library that is not installed on your computer.\n\n\
 You have GTK+ %d.%d.\nThis application requires GTK+ %d.%d or newer.\n\n\
 Please upgrade your GTK+ library if you wish to use this application."
 
@@ -200,17 +205,17 @@ void die_cb(GnomeClient *client, gpointe
   if (appService)
     appService->Quit(nsIAppStartup::eForceQuit);
 }
 
 class nsNativeAppSupportUnix : public nsNativeAppSupportBase
 {
 public:
   NS_IMETHOD Start(PRBool* aRetVal);
-  NS_IMETHOD Stop( PRBool *aResult);
+  NS_IMETHOD Stop(PRBool *aResult);
 
 private:
 #ifdef NS_OSSO
   osso_context_t *m_osso_context;    
   /* A note about why we need to have m_hw_state:
      the osso hardware callback does not tell us what changed, just
      that something has changed.  We need to keep track of state so
      that we can determine what has changed.
@@ -236,17 +241,17 @@ static void OssoDisplayCallback(osso_dis
 static void OssoHardwareCallback(osso_hw_state_t *state, gpointer data)
 {
   NS_ASSERTION(state, "osso_hw_state_t must not be null.");
   NS_ASSERTION(data, "data must not be null.");
 
   osso_hw_state_t* ourState = (osso_hw_state_t*) data;
 
   if (state->shutdown_ind) {
-    nsCOMPtr<nsIAppStartup> appService =  do_GetService("@mozilla.org/toolkit/app-startup;1");
+    nsCOMPtr<nsIAppStartup> appService = do_GetService("@mozilla.org/toolkit/app-startup;1");
     if (appService)
       appService->Quit(nsIAppStartup::eForceQuit);
     return;
   }
 
   if (state->memory_low_ind) {
       if (! ourState->memory_low_ind) {
       nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1");
@@ -264,16 +269,83 @@ static void OssoHardwareCallback(osso_hw
           os->NotifyObservers(nsnull, "system-idle", nsnull);
       else
           os->NotifyObservers(nsnull, "system-active", nsnull);
   }
 
   memcpy(ourState, state, sizeof(osso_hw_state_t));
 }
 
+static gint
+OssoDbusCallback(const gchar *interface, const gchar *method,
+                 GArray *arguments, gpointer data, osso_rpc_t *retval)
+{
+  retval->type = DBUS_TYPE_INVALID;
+
+  // The "top_application" method just wants us to focus the top-most window.
+  if (!strcmp("top_application", method)) {
+    nsCOMPtr<nsIWindowMediator> wm = do_GetService("@mozilla.org/appshell/window-mediator;1");
+
+    nsCOMPtr<nsIDOMWindowInternal> window;
+    wm->GetMostRecentWindow(NS_LITERAL_STRING("").get(), getter_AddRefs(window));
+    if (window) {
+      window->Focus();
+    }
+    return OSSO_OK;
+  }
+
+  if (!strcmp("quit", method)) {
+    nsCOMPtr<nsIAppStartup> appService = do_GetService("@mozilla.org/toolkit/app-startup;1");
+    if (appService)
+      appService->Quit(nsIAppStartup::eForceQuit);
+
+    return OSSO_OK;
+  }
+
+  // Other methods can have arguments, which we convert and send to commandline
+  // handlers.
+  nsCOMPtr<nsICommandLineRunner> cmdLine
+    (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
+
+  nsCOMPtr<nsIFile> workingDir;
+  NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR,
+                         getter_AddRefs(workingDir));
+
+  char** argv = 0;
+  int argc = 0;
+
+  // Not all DBus methods pass arguments
+  if (arguments && arguments->len > 0) {
+    // Create argument list with a dummy argv[0]
+    argc = arguments->len + 1;
+    argv = (char**)calloc(1, argc * sizeof(*argv));
+
+    // Start at 1 to skip the dummy argv[0]
+    for (int i = 1; i < argc; i++) {
+      osso_rpc_t* entry = (osso_rpc_t*)&g_array_index(arguments, osso_rpc_t, i - 1);
+      if (entry->type != DBUS_TYPE_STRING)
+        continue;
+
+      argv[i] = strdup(entry->value.s);
+    }
+  }
+
+  cmdLine->Init(argc, argv, workingDir, nsICommandLine::STATE_REMOTE_AUTO);
+
+  // Cleanup argument list
+  while (argc) {
+    free(argv[--argc]);
+  }
+  free(argv);
+
+  cmdLine->Run();
+
+  return OSSO_OK;
+}
+
 #endif
 
 NS_IMETHODIMP
 nsNativeAppSupportUnix::Start(PRBool *aRetVal)
 {
   NS_ASSERTION(gAppData, "gAppData must not be null.");
 
   if (gtk_major_version < MIN_GTK_MAJOR_VERSION ||
@@ -319,29 +391,19 @@ nsNativeAppSupportUnix::Start(PRBool *aR
                                    PR_TRUE,
                                    nsnull);
 
   /* Check that initilialization was ok */
   if (m_osso_context == nsnull) {
       return NS_ERROR_FAILURE;
   }
 
-  osso_hw_set_event_cb(m_osso_context,
-                       nsnull,
-                       OssoHardwareCallback,
-                       &m_hw_state);
-
-
-  osso_hw_set_display_event_cb(m_osso_context,
-                               OssoDisplayCallback,
-                               nsnull);
-
-
-
-
+  osso_hw_set_event_cb(m_osso_context, nsnull, OssoHardwareCallback, &m_hw_state);
+  osso_hw_set_display_event_cb(m_osso_context, OssoDisplayCallback, nsnull);
+  osso_rpc_set_default_cb_f(m_osso_context, OssoDbusCallback, nsnull);
 #endif
 
   *aRetVal = PR_TRUE;
 
 #ifdef MOZ_X11
 
   PRLibrary *gnomeuiLib = PR_LoadLibrary("libgnomeui-2.so.0");
   if (!gnomeuiLib)
@@ -408,25 +470,25 @@ nsNativeAppSupportUnix::Start(PRBool *aR
   g_signal_connect(client, "save-yourself", G_CALLBACK(save_yourself_cb), NULL);
   g_signal_connect(client, "die", G_CALLBACK(die_cb), NULL);
 #endif /* MOZ_X11 */
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsNativeAppSupportUnix::Stop( PRBool *aResult )
+nsNativeAppSupportUnix::Stop(PRBool *aResult)
 {
-  NS_ENSURE_ARG( aResult );
+  NS_ENSURE_ARG(aResult);
   *aResult = PR_TRUE;
 
 #ifdef NS_OSSO
-  if (m_osso_context)
-  {
+  if (m_osso_context) {
     osso_hw_unset_event_cb(m_osso_context, nsnull);
+    osso_rpc_unset_default_cb_f(m_osso_context, OssoDbusCallback, nsnull);
     osso_deinitialize(m_osso_context);
     m_osso_context = nsnull;
   }
 #endif
   return NS_OK;
 }
 
 nsresult