[gnome-shell] Use new GLib application API for launching
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] Use new GLib application API for launching
- Date: Tue, 8 Feb 2011 16:12:15 +0000 (UTC)
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]