[gnome-shell] Use new GLib application API for launching



commit a138f59cb091f08e35719ddb2125e9cf33af4742
Author: Colin Walters <walters verbum org>
Date:   Mon Dec 20 21:06:03 2010 -0500

    Use new GLib application API for launching
    
    Launch child processes more directly; we retrieve the PID, and
    use it to keep track of the .desktop file we launched.
    
    Now, when we get a window, since the X window has a PID, we
    have a pretty strong association.
    
    .desktop file <-> PID <-> window
    
    And can thus map window back to .desktop file.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=637745

 src/shell-app-system.c             |   32 +++++++++++++++++++-
 src/shell-window-tracker-private.h |    4 ++
 src/shell-window-tracker.c         |   59 ++++++++++++++++++++++++++++++++++++
 3 files changed, 94 insertions(+), 1 deletions(-)
---
diff --git a/src/shell-app-system.c b/src/shell-app-system.c
index 0cf0bbb..0d54901 100644
--- a/src/shell-app-system.c
+++ b/src/shell-app-system.c
@@ -12,6 +12,7 @@
 #include <glib/gi18n.h>
 
 #include "shell-app-private.h"
+#include "shell-window-tracker-private.h"
 #include "shell-global.h"
 #include "display.h"
 #include "st.h"
@@ -1296,6 +1297,26 @@ shell_app_info_get_source_window (ShellAppInfo *info)
   return NULL;
 }
 
+static void
+_gather_pid_callback (GDesktopAppInfo   *gapp,
+                      GPid               pid,
+                      gpointer           data)
+{
+  ShellApp *app;
+  ShellAppSystem *appsys;
+  ShellWindowTracker *tracker;
+
+  g_return_if_fail (data != NULL);
+
+  app = SHELL_APP (data);
+  tracker = shell_window_tracker_get_default ();
+  appsys = shell_app_system_get_default ();
+
+  _shell_window_tracker_add_child_process_app (tracker,
+                                               pid,
+                                               app);
+}
+
 /**
  * shell_app_info_launch_full:
  * @timestamp: Event timestamp, or 0 for current event timestamp
@@ -1312,6 +1333,7 @@ shell_app_info_launch_full (ShellAppInfo *info,
                             char        **startup_id,
                             GError      **error)
 {
+  ShellApp *shell_app;
   GDesktopAppInfo *gapp;
   GdkAppLaunchContext *context;
   gboolean ret;
@@ -1363,7 +1385,15 @@ shell_app_info_launch_full (ShellAppInfo *info,
   gdk_app_launch_context_set_timestamp (context, timestamp);
   gdk_app_launch_context_set_desktop (context, workspace);
 
-  ret = g_app_info_launch (G_APP_INFO (gapp), uris, (GAppLaunchContext*) context, error);
+  shell_app = shell_app_system_get_app (shell_app_system_get_default (),
+                                        shell_app_info_get_id (info));
+
+  ret = g_desktop_app_info_launch_uris_as_manager (gapp, uris,
+                                                   (GAppLaunchContext*) context,
+                                                   G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+                                                   NULL, NULL,
+                                                   _gather_pid_callback, shell_app,
+                                                   error);
 
   g_object_unref (G_OBJECT (gapp));
 
diff --git a/src/shell-window-tracker-private.h b/src/shell-window-tracker-private.h
index b854615..0b60a88 100644
--- a/src/shell-window-tracker-private.h
+++ b/src/shell-window-tracker-private.h
@@ -6,4 +6,8 @@
 
 void _shell_window_tracker_notify_app_state_changed (ShellWindowTracker *tracker, ShellApp *self);
 
+void _shell_window_tracker_add_child_process_app (ShellWindowTracker *tracker,
+                                                  GPid                pid,
+                                                  ShellApp           *app);
+
 #endif
diff --git a/src/shell-window-tracker.c b/src/shell-window-tracker.c
index c2ff932..61912bd 100644
--- a/src/shell-window-tracker.c
+++ b/src/shell-window-tracker.c
@@ -71,6 +71,9 @@ struct _ShellWindowTracker
 
   /* <const char *id, ShellApp *app> */
   GHashTable *running_apps;
+
+  /* <int, ShellApp *app> */
+  GHashTable *launched_pid_to_app;
 };
 
 G_DEFINE_TYPE (ShellWindowTracker, shell_window_tracker, G_TYPE_OBJECT);
@@ -379,6 +382,20 @@ get_app_from_window_group (ShellWindowTracker  *monitor,
   return result;
 }
 
+static ShellApp *
+get_app_from_window_pid (ShellWindowTracker  *tracker,
+                         MetaWindow          *window)
+{
+  int pid;
+
+  if (meta_window_is_remote (window))
+    return NULL;
+
+  pid = meta_window_get_pid (window);
+
+  return g_hash_table_lookup (tracker->launched_pid_to_app, GINT_TO_POINTER (pid));
+}
+
 /**
  * get_app_for_window:
  *
@@ -410,6 +427,10 @@ get_app_for_window (ShellWindowTracker    *monitor,
         }
     }
 
+  result = get_app_from_window_pid (monitor, window);
+  if (result != NULL)
+    return result;
+
   /* Check if the app's WM_CLASS specifies an app */
   result = get_app_from_window_wmclass (window);
   if (result != NULL)
@@ -673,6 +694,8 @@ shell_window_tracker_init (ShellWindowTracker *self)
 
   self->running_apps = g_hash_table_new (g_str_hash, g_str_equal);
 
+  self->launched_pid_to_app = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_object_unref);
+
   screen = shell_global_get_screen (shell_global_get ());
 
   g_signal_connect (G_OBJECT (screen), "startup-sequence-changed",
@@ -690,6 +713,8 @@ shell_window_tracker_finalize (GObject *object)
 
   g_hash_table_destroy (self->running_apps);
   g_hash_table_destroy (self->window_to_app);
+  g_hash_table_destroy (self->launched_pid_to_app);
+
   for (i = 0; title_patterns[i].app_id; i++)
     g_regex_unref (title_patterns[i].regex);
 
@@ -803,6 +828,40 @@ shell_window_tracker_get_running_apps (ShellWindowTracker *monitor,
 }
 
 static void
+on_child_exited (GPid      pid,
+                 gint      status,
+                 gpointer  unused_data)
+{
+  ShellWindowTracker *tracker;
+
+  tracker = shell_window_tracker_get_default ();
+
+  g_hash_table_remove (tracker->launched_pid_to_app, GINT_TO_POINTER((gint)pid));
+}
+
+void
+_shell_window_tracker_add_child_process_app (ShellWindowTracker *tracker,
+                                             GPid                pid,
+                                             ShellApp           *app)
+{
+  int pid_int = (int) pid;
+
+  if (g_hash_table_lookup (tracker->launched_pid_to_app,
+                           &pid_int))
+    return;
+
+  g_hash_table_insert (tracker->launched_pid_to_app,
+                       GINT_TO_POINTER (pid_int),
+                       g_object_ref (app));
+  g_child_watch_add (pid, on_child_exited, NULL);
+  /* TODO: rescan unassociated windows
+   * Very unlikely in practice that the launched app gets ahead of us
+   * enough to map an X window before we get scheduled after the fork(),
+   * but adding this note for future reference.
+   */
+}
+
+static void
 set_focus_app (ShellWindowTracker  *tracker,
                ShellApp            *new_focus_app)
 {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]