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
This commit is contained in:
parent
d3e223c217
commit
a138f59cb0
@ -12,6 +12,7 @@
|
|||||||
#include <glib/gi18n.h>
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
#include "shell-app-private.h"
|
#include "shell-app-private.h"
|
||||||
|
#include "shell-window-tracker-private.h"
|
||||||
#include "shell-global.h"
|
#include "shell-global.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "st.h"
|
#include "st.h"
|
||||||
@ -1296,6 +1297,26 @@ shell_app_info_get_source_window (ShellAppInfo *info)
|
|||||||
return NULL;
|
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:
|
* shell_app_info_launch_full:
|
||||||
* @timestamp: Event timestamp, or 0 for current event timestamp
|
* @timestamp: Event timestamp, or 0 for current event timestamp
|
||||||
@ -1312,6 +1333,7 @@ shell_app_info_launch_full (ShellAppInfo *info,
|
|||||||
char **startup_id,
|
char **startup_id,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
|
ShellApp *shell_app;
|
||||||
GDesktopAppInfo *gapp;
|
GDesktopAppInfo *gapp;
|
||||||
GdkAppLaunchContext *context;
|
GdkAppLaunchContext *context;
|
||||||
gboolean ret;
|
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_timestamp (context, timestamp);
|
||||||
gdk_app_launch_context_set_desktop (context, workspace);
|
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));
|
g_object_unref (G_OBJECT (gapp));
|
||||||
|
|
||||||
|
@ -6,4 +6,8 @@
|
|||||||
|
|
||||||
void _shell_window_tracker_notify_app_state_changed (ShellWindowTracker *tracker, ShellApp *self);
|
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
|
#endif
|
||||||
|
@ -71,6 +71,9 @@ struct _ShellWindowTracker
|
|||||||
|
|
||||||
/* <const char *id, ShellApp *app> */
|
/* <const char *id, ShellApp *app> */
|
||||||
GHashTable *running_apps;
|
GHashTable *running_apps;
|
||||||
|
|
||||||
|
/* <int, ShellApp *app> */
|
||||||
|
GHashTable *launched_pid_to_app;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (ShellWindowTracker, shell_window_tracker, G_TYPE_OBJECT);
|
G_DEFINE_TYPE (ShellWindowTracker, shell_window_tracker, G_TYPE_OBJECT);
|
||||||
@ -379,6 +382,20 @@ get_app_from_window_group (ShellWindowTracker *monitor,
|
|||||||
return result;
|
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:
|
* 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 */
|
/* Check if the app's WM_CLASS specifies an app */
|
||||||
result = get_app_from_window_wmclass (window);
|
result = get_app_from_window_wmclass (window);
|
||||||
if (result != NULL)
|
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->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 ());
|
screen = shell_global_get_screen (shell_global_get ());
|
||||||
|
|
||||||
g_signal_connect (G_OBJECT (screen), "startup-sequence-changed",
|
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->running_apps);
|
||||||
g_hash_table_destroy (self->window_to_app);
|
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++)
|
for (i = 0; title_patterns[i].app_id; i++)
|
||||||
g_regex_unref (title_patterns[i].regex);
|
g_regex_unref (title_patterns[i].regex);
|
||||||
|
|
||||||
@ -802,6 +827,40 @@ shell_window_tracker_get_running_apps (ShellWindowTracker *monitor,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static void
|
||||||
set_focus_app (ShellWindowTracker *tracker,
|
set_focus_app (ShellWindowTracker *tracker,
|
||||||
ShellApp *new_focus_app)
|
ShellApp *new_focus_app)
|
||||||
|
Loading…
Reference in New Issue
Block a user