2008-11-21 00:53:11 +00:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
|
2009-11-24 14:07:40 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
2009-04-22 19:21:35 +00:00
|
|
|
#include "shell-app-system.h"
|
2011-10-05 14:44:50 +00:00
|
|
|
#include "shell-app-usage.h"
|
2009-06-25 21:43:54 +00:00
|
|
|
#include <string.h>
|
2008-11-21 00:53:11 +00:00
|
|
|
|
|
|
|
#include <gio/gio.h>
|
2010-11-05 16:47:50 +00:00
|
|
|
#include <glib/gi18n.h>
|
2008-11-21 00:53:11 +00:00
|
|
|
|
2020-02-28 03:36:14 +00:00
|
|
|
#include "shell-app-cache-private.h"
|
2009-10-15 23:28:29 +00:00
|
|
|
#include "shell-app-private.h"
|
2010-12-21 02:06:03 +00:00
|
|
|
#include "shell-window-tracker-private.h"
|
apps: Ensure running apps override new .desktop file data
This patch fixes the "apps vanish from alt-TAB bug".
If a "package system" rips away and possibly replaces .desktop files
at some random time, we have historically used inotify to detect this
and reread state (in a racy way, but...). In GNOME 2, this was
generally not too problematic because the menu widget was totally
separate from the list of windows - and the data they operate on was
disjoint as well.
In GNOME 3 we unify these, and this creates architectural problems
because the windows are tied to the app.
What this patch tries to do is, when rereading the application state,
if we have a running application, we keep that app around instead of
making a new instance. This ensures we preserve any state such as the
set of open windows.
This requires moving the running state into ShellAppSystem. Adjust
callers as necessary, and while we're at it drop the unused "contexts"
stuff.
This is just a somewhat quick band-aid; a REAL fix would require us
having low-level control over application installation. As long as
we're on top of random broken tar+wget wrappers, it will be gross.
A slight future improvement to this patch would add an explicit
"merge" between the old and new data. I think probably we always keep
around the ShellApp corresponding to a given ID, but replace its
GMenuTreeEntry.
https://bugzilla.gnome.org/show_bug.cgi?id=657990
2011-09-03 14:32:06 +00:00
|
|
|
#include "shell-app-system-private.h"
|
2009-07-07 20:08:41 +00:00
|
|
|
#include "shell-global.h"
|
2011-08-10 16:58:40 +00:00
|
|
|
#include "shell-util.h"
|
2019-08-01 23:58:20 +00:00
|
|
|
#include "st.h"
|
|
|
|
|
|
|
|
/* Rescan for at most RESCAN_TIMEOUT_MS * MAX_RESCAN_RETRIES. That
|
|
|
|
* should be plenty of time for even a slow spinning drive to update
|
|
|
|
* the icon cache.
|
|
|
|
*/
|
|
|
|
#define RESCAN_TIMEOUT_MS 2500
|
|
|
|
#define MAX_RESCAN_RETRIES 6
|
2009-07-07 20:08:41 +00:00
|
|
|
|
2009-08-21 18:48:14 +00:00
|
|
|
/* Vendor prefixes are something that can be preprended to a .desktop
|
|
|
|
* file name. Undo this.
|
|
|
|
*/
|
2011-03-17 22:44:41 +00:00
|
|
|
static const char*const vendor_prefixes[] = { "gnome-",
|
|
|
|
"fedora-",
|
|
|
|
"mozilla-",
|
2011-12-06 02:24:47 +00:00
|
|
|
"debian-",
|
2011-03-17 22:44:41 +00:00
|
|
|
NULL };
|
2009-08-21 18:48:14 +00:00
|
|
|
|
2008-11-21 00:53:11 +00:00
|
|
|
enum {
|
|
|
|
PROP_0,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
apps: Ensure running apps override new .desktop file data
This patch fixes the "apps vanish from alt-TAB bug".
If a "package system" rips away and possibly replaces .desktop files
at some random time, we have historically used inotify to detect this
and reread state (in a racy way, but...). In GNOME 2, this was
generally not too problematic because the menu widget was totally
separate from the list of windows - and the data they operate on was
disjoint as well.
In GNOME 3 we unify these, and this creates architectural problems
because the windows are tied to the app.
What this patch tries to do is, when rereading the application state,
if we have a running application, we keep that app around instead of
making a new instance. This ensures we preserve any state such as the
set of open windows.
This requires moving the running state into ShellAppSystem. Adjust
callers as necessary, and while we're at it drop the unused "contexts"
stuff.
This is just a somewhat quick band-aid; a REAL fix would require us
having low-level control over application installation. As long as
we're on top of random broken tar+wget wrappers, it will be gross.
A slight future improvement to this patch would add an explicit
"merge" between the old and new data. I think probably we always keep
around the ShellApp corresponding to a given ID, but replace its
GMenuTreeEntry.
https://bugzilla.gnome.org/show_bug.cgi?id=657990
2011-09-03 14:32:06 +00:00
|
|
|
APP_STATE_CHANGED,
|
2009-06-25 21:43:54 +00:00
|
|
|
INSTALLED_CHANGED,
|
2008-11-21 00:53:11 +00:00
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
|
|
|
|
|
|
|
static guint signals[LAST_SIGNAL] = { 0 };
|
|
|
|
|
2015-09-24 18:07:44 +00:00
|
|
|
typedef struct _ShellAppSystemPrivate ShellAppSystemPrivate;
|
|
|
|
|
|
|
|
struct _ShellAppSystem
|
|
|
|
{
|
|
|
|
GObject parent;
|
|
|
|
|
|
|
|
ShellAppSystemPrivate *priv;
|
|
|
|
};
|
|
|
|
|
2009-04-22 19:21:35 +00:00
|
|
|
struct _ShellAppSystemPrivate {
|
apps: Ensure running apps override new .desktop file data
This patch fixes the "apps vanish from alt-TAB bug".
If a "package system" rips away and possibly replaces .desktop files
at some random time, we have historically used inotify to detect this
and reread state (in a racy way, but...). In GNOME 2, this was
generally not too problematic because the menu widget was totally
separate from the list of windows - and the data they operate on was
disjoint as well.
In GNOME 3 we unify these, and this creates architectural problems
because the windows are tied to the app.
What this patch tries to do is, when rereading the application state,
if we have a running application, we keep that app around instead of
making a new instance. This ensures we preserve any state such as the
set of open windows.
This requires moving the running state into ShellAppSystem. Adjust
callers as necessary, and while we're at it drop the unused "contexts"
stuff.
This is just a somewhat quick band-aid; a REAL fix would require us
having low-level control over application installation. As long as
we're on top of random broken tar+wget wrappers, it will be gross.
A slight future improvement to this patch would add an explicit
"merge" between the old and new data. I think probably we always keep
around the ShellApp corresponding to a given ID, but replace its
GMenuTreeEntry.
https://bugzilla.gnome.org/show_bug.cgi?id=657990
2011-09-03 14:32:06 +00:00
|
|
|
GHashTable *running_apps;
|
2011-09-19 16:49:05 +00:00
|
|
|
GHashTable *id_to_app;
|
2013-10-02 22:16:45 +00:00
|
|
|
GHashTable *startup_wm_class_to_id;
|
2018-12-19 12:13:42 +00:00
|
|
|
GList *installed_apps;
|
2019-08-01 23:58:20 +00:00
|
|
|
|
|
|
|
guint rescan_icons_timeout_id;
|
|
|
|
guint n_rescan_retries;
|
2008-11-21 00:53:11 +00:00
|
|
|
};
|
|
|
|
|
2009-04-22 19:21:35 +00:00
|
|
|
static void shell_app_system_finalize (GObject *object);
|
2008-11-21 00:53:11 +00:00
|
|
|
|
2015-09-24 16:56:13 +00:00
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (ShellAppSystem, shell_app_system, G_TYPE_OBJECT);
|
2008-11-21 00:53:11 +00:00
|
|
|
|
2009-04-22 19:21:35 +00:00
|
|
|
static void shell_app_system_class_init(ShellAppSystemClass *klass)
|
2008-11-21 00:53:11 +00:00
|
|
|
{
|
|
|
|
GObjectClass *gobject_class = (GObjectClass *)klass;
|
|
|
|
|
2009-04-22 19:21:35 +00:00
|
|
|
gobject_class->finalize = shell_app_system_finalize;
|
2008-11-21 00:53:11 +00:00
|
|
|
|
apps: Ensure running apps override new .desktop file data
This patch fixes the "apps vanish from alt-TAB bug".
If a "package system" rips away and possibly replaces .desktop files
at some random time, we have historically used inotify to detect this
and reread state (in a racy way, but...). In GNOME 2, this was
generally not too problematic because the menu widget was totally
separate from the list of windows - and the data they operate on was
disjoint as well.
In GNOME 3 we unify these, and this creates architectural problems
because the windows are tied to the app.
What this patch tries to do is, when rereading the application state,
if we have a running application, we keep that app around instead of
making a new instance. This ensures we preserve any state such as the
set of open windows.
This requires moving the running state into ShellAppSystem. Adjust
callers as necessary, and while we're at it drop the unused "contexts"
stuff.
This is just a somewhat quick band-aid; a REAL fix would require us
having low-level control over application installation. As long as
we're on top of random broken tar+wget wrappers, it will be gross.
A slight future improvement to this patch would add an explicit
"merge" between the old and new data. I think probably we always keep
around the ShellApp corresponding to a given ID, but replace its
GMenuTreeEntry.
https://bugzilla.gnome.org/show_bug.cgi?id=657990
2011-09-03 14:32:06 +00:00
|
|
|
signals[APP_STATE_CHANGED] = g_signal_new ("app-state-changed",
|
|
|
|
SHELL_TYPE_APP_SYSTEM,
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0,
|
2011-10-18 22:19:32 +00:00
|
|
|
NULL, NULL, NULL,
|
apps: Ensure running apps override new .desktop file data
This patch fixes the "apps vanish from alt-TAB bug".
If a "package system" rips away and possibly replaces .desktop files
at some random time, we have historically used inotify to detect this
and reread state (in a racy way, but...). In GNOME 2, this was
generally not too problematic because the menu widget was totally
separate from the list of windows - and the data they operate on was
disjoint as well.
In GNOME 3 we unify these, and this creates architectural problems
because the windows are tied to the app.
What this patch tries to do is, when rereading the application state,
if we have a running application, we keep that app around instead of
making a new instance. This ensures we preserve any state such as the
set of open windows.
This requires moving the running state into ShellAppSystem. Adjust
callers as necessary, and while we're at it drop the unused "contexts"
stuff.
This is just a somewhat quick band-aid; a REAL fix would require us
having low-level control over application installation. As long as
we're on top of random broken tar+wget wrappers, it will be gross.
A slight future improvement to this patch would add an explicit
"merge" between the old and new data. I think probably we always keep
around the ShellApp corresponding to a given ID, but replace its
GMenuTreeEntry.
https://bugzilla.gnome.org/show_bug.cgi?id=657990
2011-09-03 14:32:06 +00:00
|
|
|
G_TYPE_NONE, 1,
|
|
|
|
SHELL_TYPE_APP);
|
2009-06-25 21:43:54 +00:00
|
|
|
signals[INSTALLED_CHANGED] =
|
|
|
|
g_signal_new ("installed-changed",
|
2009-04-22 19:21:35 +00:00
|
|
|
SHELL_TYPE_APP_SYSTEM,
|
2008-11-21 00:53:11 +00:00
|
|
|
G_SIGNAL_RUN_LAST,
|
2015-10-15 20:13:18 +00:00
|
|
|
0,
|
|
|
|
NULL, NULL, NULL,
|
2008-11-21 00:53:11 +00:00
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
}
|
|
|
|
|
2023-03-23 23:02:16 +00:00
|
|
|
/*
|
|
|
|
* Check whether @wm_class matches @id exactly when ignoring the .desktop suffix
|
|
|
|
*/
|
|
|
|
static gboolean
|
|
|
|
startup_wm_class_is_exact_match (const char *id,
|
|
|
|
const char *wm_class)
|
|
|
|
{
|
|
|
|
size_t wm_class_len;
|
|
|
|
|
|
|
|
if (!g_str_has_prefix (id, wm_class))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
wm_class_len = strlen (wm_class);
|
|
|
|
if (id[wm_class_len] == '\0')
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return g_str_equal (id + wm_class_len, ".desktop");
|
|
|
|
}
|
|
|
|
|
2013-09-26 21:19:21 +00:00
|
|
|
static void
|
|
|
|
scan_startup_wm_class_to_id (ShellAppSystem *self)
|
|
|
|
{
|
|
|
|
ShellAppSystemPrivate *priv = self->priv;
|
2023-03-23 23:25:06 +00:00
|
|
|
g_autoptr(GPtrArray) no_show_ids = NULL;
|
2020-02-28 03:36:14 +00:00
|
|
|
const GList *l;
|
|
|
|
GList *all;
|
2013-09-26 21:19:21 +00:00
|
|
|
|
|
|
|
g_hash_table_remove_all (priv->startup_wm_class_to_id);
|
|
|
|
|
2020-02-28 03:36:14 +00:00
|
|
|
all = shell_app_cache_get_all (shell_app_cache_get_default ());
|
2023-03-23 23:25:06 +00:00
|
|
|
no_show_ids = g_ptr_array_new ();
|
2018-12-19 12:13:42 +00:00
|
|
|
|
2020-02-28 03:36:14 +00:00
|
|
|
for (l = all; l != NULL; l = l->next)
|
2013-09-26 21:19:21 +00:00
|
|
|
{
|
|
|
|
GAppInfo *info = l->data;
|
2015-06-26 11:46:11 +00:00
|
|
|
const char *startup_wm_class, *id, *old_id;
|
2023-03-23 23:25:06 +00:00
|
|
|
gboolean should_show;
|
2013-09-26 21:19:21 +00:00
|
|
|
|
|
|
|
id = g_app_info_get_id (info);
|
|
|
|
startup_wm_class = g_desktop_app_info_get_startup_wm_class (G_DESKTOP_APP_INFO (info));
|
2013-12-25 19:35:13 +00:00
|
|
|
|
2015-06-26 11:46:11 +00:00
|
|
|
if (startup_wm_class == NULL)
|
|
|
|
continue;
|
|
|
|
|
2023-03-23 23:25:06 +00:00
|
|
|
should_show = g_app_info_should_show (info);
|
|
|
|
if (!should_show)
|
|
|
|
g_ptr_array_add (no_show_ids, (char *) id);
|
|
|
|
|
2015-06-26 11:46:11 +00:00
|
|
|
/* In case multiple .desktop files set the same StartupWMClass, prefer
|
|
|
|
* the one where ID and StartupWMClass match */
|
|
|
|
old_id = g_hash_table_lookup (priv->startup_wm_class_to_id, startup_wm_class);
|
2023-03-23 23:25:06 +00:00
|
|
|
|
|
|
|
if (old_id && startup_wm_class_is_exact_match (id, startup_wm_class))
|
|
|
|
old_id = NULL;
|
|
|
|
|
|
|
|
/* Give priority to the desktop files that should be shown */
|
|
|
|
if (old_id && should_show &&
|
|
|
|
g_ptr_array_find_with_equal_func (no_show_ids, old_id, g_str_equal, NULL))
|
|
|
|
old_id = NULL;
|
|
|
|
|
|
|
|
if (!old_id)
|
2014-01-10 20:19:07 +00:00
|
|
|
g_hash_table_insert (priv->startup_wm_class_to_id,
|
|
|
|
g_strdup (startup_wm_class), g_strdup (id));
|
2013-09-26 21:19:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-15 10:24:27 +00:00
|
|
|
static gboolean
|
|
|
|
app_is_stale (ShellApp *app)
|
|
|
|
{
|
2016-11-07 18:59:03 +00:00
|
|
|
GDesktopAppInfo *info, *old;
|
|
|
|
GAppInfo *old_info, *new_info;
|
|
|
|
gboolean is_unchanged;
|
2014-03-15 10:24:27 +00:00
|
|
|
|
|
|
|
if (shell_app_is_window_backed (app))
|
|
|
|
return FALSE;
|
|
|
|
|
2020-02-28 03:36:14 +00:00
|
|
|
info = shell_app_cache_get_info (shell_app_cache_get_default (),
|
|
|
|
shell_app_get_id (app));
|
2016-11-07 18:59:03 +00:00
|
|
|
if (!info)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
old = shell_app_get_app_info (app);
|
|
|
|
old_info = G_APP_INFO (old);
|
|
|
|
new_info = G_APP_INFO (info);
|
|
|
|
|
|
|
|
is_unchanged =
|
|
|
|
g_app_info_should_show (old_info) == g_app_info_should_show (new_info) &&
|
|
|
|
strcmp (g_desktop_app_info_get_filename (old),
|
|
|
|
g_desktop_app_info_get_filename (info)) == 0 &&
|
|
|
|
g_strcmp0 (g_app_info_get_executable (old_info),
|
|
|
|
g_app_info_get_executable (new_info)) == 0 &&
|
|
|
|
g_strcmp0 (g_app_info_get_commandline (old_info),
|
|
|
|
g_app_info_get_commandline (new_info)) == 0 &&
|
|
|
|
strcmp (g_app_info_get_name (old_info),
|
|
|
|
g_app_info_get_name (new_info)) == 0 &&
|
|
|
|
g_strcmp0 (g_app_info_get_description (old_info),
|
|
|
|
g_app_info_get_description (new_info)) == 0 &&
|
|
|
|
strcmp (g_app_info_get_display_name (old_info),
|
|
|
|
g_app_info_get_display_name (new_info)) == 0 &&
|
|
|
|
g_icon_equal (g_app_info_get_icon (old_info),
|
|
|
|
g_app_info_get_icon (new_info));
|
|
|
|
|
|
|
|
return !is_unchanged;
|
2014-03-15 10:24:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
stale_app_remove_func (gpointer key,
|
|
|
|
gpointer value,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
return app_is_stale (value);
|
|
|
|
}
|
|
|
|
|
2022-09-09 16:25:22 +00:00
|
|
|
static void
|
|
|
|
collect_stale_windows (gpointer key,
|
|
|
|
gpointer value,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
ShellApp *app = key;
|
|
|
|
GDesktopAppInfo *info;
|
|
|
|
GPtrArray *windows = user_data;
|
|
|
|
|
|
|
|
info = shell_app_cache_get_info (shell_app_cache_get_default (),
|
|
|
|
shell_app_get_id (app));
|
|
|
|
|
|
|
|
/* No info either means that the app became stale, or that it is
|
|
|
|
* window-backed. Re-tracking the app's windows allows us to reflect
|
|
|
|
* changes in either direction, i.e. from stale app to window-backed,
|
|
|
|
* or from window-backed to app-backed (if the app was launched right
|
|
|
|
* between installing the app and updating the app cache).
|
|
|
|
*/
|
|
|
|
if (info == NULL)
|
|
|
|
{
|
|
|
|
GSList *l;
|
|
|
|
|
|
|
|
for (l = shell_app_get_windows (app); l; l = l->next)
|
|
|
|
g_ptr_array_add (windows, l->data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
retrack_window (gpointer data,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
GObject *window = data;
|
|
|
|
|
|
|
|
/* Make ShellWindowTracker retrack the window */
|
|
|
|
g_object_notify (window, "wm-class");
|
|
|
|
}
|
|
|
|
|
2019-08-01 23:58:20 +00:00
|
|
|
static gboolean
|
|
|
|
rescan_icon_theme_cb (gpointer user_data)
|
|
|
|
{
|
|
|
|
ShellAppSystemPrivate *priv;
|
|
|
|
ShellAppSystem *self;
|
|
|
|
StTextureCache *texture_cache;
|
|
|
|
gboolean rescanned;
|
|
|
|
|
|
|
|
self = (ShellAppSystem *) user_data;
|
|
|
|
priv = self->priv;
|
|
|
|
|
|
|
|
texture_cache = st_texture_cache_get_default ();
|
|
|
|
rescanned = st_texture_cache_rescan_icon_theme (texture_cache);
|
|
|
|
|
|
|
|
priv->n_rescan_retries++;
|
|
|
|
|
|
|
|
if (rescanned || priv->n_rescan_retries >= MAX_RESCAN_RETRIES)
|
|
|
|
{
|
|
|
|
priv->n_rescan_retries = 0;
|
|
|
|
priv->rescan_icons_timeout_id = 0;
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return G_SOURCE_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rescan_icon_theme (ShellAppSystem *self)
|
|
|
|
{
|
|
|
|
ShellAppSystemPrivate *priv = self->priv;
|
|
|
|
|
|
|
|
priv->n_rescan_retries = 0;
|
|
|
|
|
|
|
|
if (priv->rescan_icons_timeout_id > 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
priv->rescan_icons_timeout_id = g_timeout_add (RESCAN_TIMEOUT_MS,
|
|
|
|
rescan_icon_theme_cb,
|
|
|
|
self);
|
|
|
|
}
|
|
|
|
|
2013-09-26 21:11:45 +00:00
|
|
|
static void
|
2020-02-28 03:36:14 +00:00
|
|
|
installed_changed (ShellAppCache *cache,
|
|
|
|
ShellAppSystem *self)
|
2013-09-26 21:11:45 +00:00
|
|
|
{
|
2022-09-09 16:25:22 +00:00
|
|
|
GPtrArray *windows = g_ptr_array_new ();
|
|
|
|
|
2019-08-01 23:58:20 +00:00
|
|
|
rescan_icon_theme (self);
|
2013-09-26 21:19:21 +00:00
|
|
|
scan_startup_wm_class_to_id (self);
|
|
|
|
|
2014-03-15 10:24:27 +00:00
|
|
|
g_hash_table_foreach_remove (self->priv->id_to_app, stale_app_remove_func, NULL);
|
2022-09-09 16:25:22 +00:00
|
|
|
g_hash_table_foreach (self->priv->running_apps, collect_stale_windows, windows);
|
|
|
|
|
|
|
|
g_ptr_array_foreach (windows, retrack_window, NULL);
|
|
|
|
g_ptr_array_free (windows, TRUE);
|
2014-03-15 10:24:27 +00:00
|
|
|
|
2013-09-26 21:11:45 +00:00
|
|
|
g_signal_emit (self, signals[INSTALLED_CHANGED], 0, NULL);
|
|
|
|
}
|
|
|
|
|
2008-11-21 00:53:11 +00:00
|
|
|
static void
|
2009-04-22 19:21:35 +00:00
|
|
|
shell_app_system_init (ShellAppSystem *self)
|
2008-11-21 00:53:11 +00:00
|
|
|
{
|
2009-04-22 19:21:35 +00:00
|
|
|
ShellAppSystemPrivate *priv;
|
2020-02-28 03:36:14 +00:00
|
|
|
ShellAppCache *cache;
|
2009-06-25 21:43:54 +00:00
|
|
|
|
2015-09-24 16:56:13 +00:00
|
|
|
self->priv = priv = shell_app_system_get_instance_private (self);
|
2009-04-01 19:51:17 +00:00
|
|
|
|
2011-09-19 16:49:05 +00:00
|
|
|
priv->running_apps = g_hash_table_new_full (NULL, NULL, (GDestroyNotify) g_object_unref, NULL);
|
|
|
|
priv->id_to_app = g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
|
|
NULL,
|
|
|
|
(GDestroyNotify)g_object_unref);
|
2012-06-19 15:35:05 +00:00
|
|
|
|
2013-12-25 19:35:13 +00:00
|
|
|
priv->startup_wm_class_to_id = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
2013-09-26 21:11:45 +00:00
|
|
|
|
2020-02-28 03:36:14 +00:00
|
|
|
cache = shell_app_cache_get_default ();
|
|
|
|
g_signal_connect (cache, "changed", G_CALLBACK (installed_changed), self);
|
|
|
|
installed_changed (cache, self);
|
2008-11-21 00:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-04-22 19:21:35 +00:00
|
|
|
shell_app_system_finalize (GObject *object)
|
2008-11-21 00:53:11 +00:00
|
|
|
{
|
2009-04-22 19:21:35 +00:00
|
|
|
ShellAppSystem *self = SHELL_APP_SYSTEM (object);
|
|
|
|
ShellAppSystemPrivate *priv = self->priv;
|
2008-11-21 00:53:11 +00:00
|
|
|
|
apps: Ensure running apps override new .desktop file data
This patch fixes the "apps vanish from alt-TAB bug".
If a "package system" rips away and possibly replaces .desktop files
at some random time, we have historically used inotify to detect this
and reread state (in a racy way, but...). In GNOME 2, this was
generally not too problematic because the menu widget was totally
separate from the list of windows - and the data they operate on was
disjoint as well.
In GNOME 3 we unify these, and this creates architectural problems
because the windows are tied to the app.
What this patch tries to do is, when rereading the application state,
if we have a running application, we keep that app around instead of
making a new instance. This ensures we preserve any state such as the
set of open windows.
This requires moving the running state into ShellAppSystem. Adjust
callers as necessary, and while we're at it drop the unused "contexts"
stuff.
This is just a somewhat quick band-aid; a REAL fix would require us
having low-level control over application installation. As long as
we're on top of random broken tar+wget wrappers, it will be gross.
A slight future improvement to this patch would add an explicit
"merge" between the old and new data. I think probably we always keep
around the ShellApp corresponding to a given ID, but replace its
GMenuTreeEntry.
https://bugzilla.gnome.org/show_bug.cgi?id=657990
2011-09-03 14:32:06 +00:00
|
|
|
g_hash_table_destroy (priv->running_apps);
|
2011-09-19 16:49:05 +00:00
|
|
|
g_hash_table_destroy (priv->id_to_app);
|
2013-10-02 22:16:45 +00:00
|
|
|
g_hash_table_destroy (priv->startup_wm_class_to_id);
|
2018-12-19 12:13:42 +00:00
|
|
|
g_list_free_full (priv->installed_apps, g_object_unref);
|
2019-08-01 23:58:20 +00:00
|
|
|
g_clear_handle_id (&priv->rescan_icons_timeout_id, g_source_remove);
|
2011-03-17 22:44:41 +00:00
|
|
|
|
Kill off ShellAppInfo, move into ShellApp
This dramatically thins down and sanitizes the application code.
The ShellAppSystem changes in a number of ways:
* Preferences are special cased more explicitly; they aren't apps,
they're shortcuts for an app), and we don't have many of them, so
don't need e.g. the optimizations in ShellAppSystem for searching.
* get_app() changes to lookup_app() and returns null if an app isn't
found. The semantics where it tried to find the .desktop file
if we didn't know about it were just broken; I am pretty sure no
caller needs this, and if they do we'll fix them.
* ShellAppSystem maintains two indexes on apps (by desktop file id
and by GMenuTreeEntry), but is no longer in the business of
dealing with GMenuTree as far as hierarchy and categories go. That
is moved up into js/ui/appDisplay.js. Actually, it flattens both
apps and settings.
Also, ShellWindowTracker is now the sole reference-owner for
window-backed apps. We still do the weird "window:0x1234beef" id
for these apps, but a reference is not stored in ShellAppSystem.
The js/ui/appDisplay.js code is rewritten, and sucks a lot less.
Variable names are clearer:
_apps -> _appIcons
_filterApp -> _visibleApps
_filters -> _categoryBox
Similarly for function names. We no longer call (for every app) a
recursive lookup in GMenuTree to see if it's in a particular section
on every category switch; it's all cached.
NOTE - this intentionally reverts the incremental loading code from
commit 7813c5b93f6bcde8c4beae286e82bfc472b2b656. It's fast enough
here without that.
https://bugzilla.gnome.org/show_bug.cgi?id=648149
2011-04-21 17:35:01 +00:00
|
|
|
G_OBJECT_CLASS (shell_app_system_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
2009-06-18 16:27:19 +00:00
|
|
|
/**
|
|
|
|
* shell_app_system_get_default:
|
|
|
|
*
|
|
|
|
* Return Value: (transfer none): The global #ShellAppSystem singleton
|
|
|
|
*/
|
|
|
|
ShellAppSystem *
|
2015-09-23 18:40:03 +00:00
|
|
|
shell_app_system_get_default (void)
|
2009-06-18 16:27:19 +00:00
|
|
|
{
|
2023-03-24 09:16:07 +00:00
|
|
|
return shell_global_get_app_system (shell_global_get ());
|
2009-06-18 16:27:19 +00:00
|
|
|
}
|
2009-06-25 21:43:54 +00:00
|
|
|
|
2009-10-15 23:28:29 +00:00
|
|
|
/**
|
Kill off ShellAppInfo, move into ShellApp
This dramatically thins down and sanitizes the application code.
The ShellAppSystem changes in a number of ways:
* Preferences are special cased more explicitly; they aren't apps,
they're shortcuts for an app), and we don't have many of them, so
don't need e.g. the optimizations in ShellAppSystem for searching.
* get_app() changes to lookup_app() and returns null if an app isn't
found. The semantics where it tried to find the .desktop file
if we didn't know about it were just broken; I am pretty sure no
caller needs this, and if they do we'll fix them.
* ShellAppSystem maintains two indexes on apps (by desktop file id
and by GMenuTreeEntry), but is no longer in the business of
dealing with GMenuTree as far as hierarchy and categories go. That
is moved up into js/ui/appDisplay.js. Actually, it flattens both
apps and settings.
Also, ShellWindowTracker is now the sole reference-owner for
window-backed apps. We still do the weird "window:0x1234beef" id
for these apps, but a reference is not stored in ShellAppSystem.
The js/ui/appDisplay.js code is rewritten, and sucks a lot less.
Variable names are clearer:
_apps -> _appIcons
_filterApp -> _visibleApps
_filters -> _categoryBox
Similarly for function names. We no longer call (for every app) a
recursive lookup in GMenuTree to see if it's in a particular section
on every category switch; it's all cached.
NOTE - this intentionally reverts the incremental loading code from
commit 7813c5b93f6bcde8c4beae286e82bfc472b2b656. It's fast enough
here without that.
https://bugzilla.gnome.org/show_bug.cgi?id=648149
2011-04-21 17:35:01 +00:00
|
|
|
* shell_app_system_lookup_app:
|
2009-10-15 23:28:29 +00:00
|
|
|
*
|
Kill off ShellAppInfo, move into ShellApp
This dramatically thins down and sanitizes the application code.
The ShellAppSystem changes in a number of ways:
* Preferences are special cased more explicitly; they aren't apps,
they're shortcuts for an app), and we don't have many of them, so
don't need e.g. the optimizations in ShellAppSystem for searching.
* get_app() changes to lookup_app() and returns null if an app isn't
found. The semantics where it tried to find the .desktop file
if we didn't know about it were just broken; I am pretty sure no
caller needs this, and if they do we'll fix them.
* ShellAppSystem maintains two indexes on apps (by desktop file id
and by GMenuTreeEntry), but is no longer in the business of
dealing with GMenuTree as far as hierarchy and categories go. That
is moved up into js/ui/appDisplay.js. Actually, it flattens both
apps and settings.
Also, ShellWindowTracker is now the sole reference-owner for
window-backed apps. We still do the weird "window:0x1234beef" id
for these apps, but a reference is not stored in ShellAppSystem.
The js/ui/appDisplay.js code is rewritten, and sucks a lot less.
Variable names are clearer:
_apps -> _appIcons
_filterApp -> _visibleApps
_filters -> _categoryBox
Similarly for function names. We no longer call (for every app) a
recursive lookup in GMenuTree to see if it's in a particular section
on every category switch; it's all cached.
NOTE - this intentionally reverts the incremental loading code from
commit 7813c5b93f6bcde8c4beae286e82bfc472b2b656. It's fast enough
here without that.
https://bugzilla.gnome.org/show_bug.cgi?id=648149
2011-04-21 17:35:01 +00:00
|
|
|
* Find a #ShellApp corresponding to an id.
|
2009-10-15 23:28:29 +00:00
|
|
|
*
|
Kill off ShellAppInfo, move into ShellApp
This dramatically thins down and sanitizes the application code.
The ShellAppSystem changes in a number of ways:
* Preferences are special cased more explicitly; they aren't apps,
they're shortcuts for an app), and we don't have many of them, so
don't need e.g. the optimizations in ShellAppSystem for searching.
* get_app() changes to lookup_app() and returns null if an app isn't
found. The semantics where it tried to find the .desktop file
if we didn't know about it were just broken; I am pretty sure no
caller needs this, and if they do we'll fix them.
* ShellAppSystem maintains two indexes on apps (by desktop file id
and by GMenuTreeEntry), but is no longer in the business of
dealing with GMenuTree as far as hierarchy and categories go. That
is moved up into js/ui/appDisplay.js. Actually, it flattens both
apps and settings.
Also, ShellWindowTracker is now the sole reference-owner for
window-backed apps. We still do the weird "window:0x1234beef" id
for these apps, but a reference is not stored in ShellAppSystem.
The js/ui/appDisplay.js code is rewritten, and sucks a lot less.
Variable names are clearer:
_apps -> _appIcons
_filterApp -> _visibleApps
_filters -> _categoryBox
Similarly for function names. We no longer call (for every app) a
recursive lookup in GMenuTree to see if it's in a particular section
on every category switch; it's all cached.
NOTE - this intentionally reverts the incremental loading code from
commit 7813c5b93f6bcde8c4beae286e82bfc472b2b656. It's fast enough
here without that.
https://bugzilla.gnome.org/show_bug.cgi?id=648149
2011-04-21 17:35:01 +00:00
|
|
|
* Return value: (transfer none): The #ShellApp for id, or %NULL if none
|
2009-10-15 23:28:29 +00:00
|
|
|
*/
|
|
|
|
ShellApp *
|
Kill off ShellAppInfo, move into ShellApp
This dramatically thins down and sanitizes the application code.
The ShellAppSystem changes in a number of ways:
* Preferences are special cased more explicitly; they aren't apps,
they're shortcuts for an app), and we don't have many of them, so
don't need e.g. the optimizations in ShellAppSystem for searching.
* get_app() changes to lookup_app() and returns null if an app isn't
found. The semantics where it tried to find the .desktop file
if we didn't know about it were just broken; I am pretty sure no
caller needs this, and if they do we'll fix them.
* ShellAppSystem maintains two indexes on apps (by desktop file id
and by GMenuTreeEntry), but is no longer in the business of
dealing with GMenuTree as far as hierarchy and categories go. That
is moved up into js/ui/appDisplay.js. Actually, it flattens both
apps and settings.
Also, ShellWindowTracker is now the sole reference-owner for
window-backed apps. We still do the weird "window:0x1234beef" id
for these apps, but a reference is not stored in ShellAppSystem.
The js/ui/appDisplay.js code is rewritten, and sucks a lot less.
Variable names are clearer:
_apps -> _appIcons
_filterApp -> _visibleApps
_filters -> _categoryBox
Similarly for function names. We no longer call (for every app) a
recursive lookup in GMenuTree to see if it's in a particular section
on every category switch; it's all cached.
NOTE - this intentionally reverts the incremental loading code from
commit 7813c5b93f6bcde8c4beae286e82bfc472b2b656. It's fast enough
here without that.
https://bugzilla.gnome.org/show_bug.cgi?id=648149
2011-04-21 17:35:01 +00:00
|
|
|
shell_app_system_lookup_app (ShellAppSystem *self,
|
|
|
|
const char *id)
|
2009-06-25 21:43:54 +00:00
|
|
|
{
|
2013-09-26 21:06:47 +00:00
|
|
|
ShellAppSystemPrivate *priv = self->priv;
|
|
|
|
ShellApp *app;
|
|
|
|
GDesktopAppInfo *info;
|
|
|
|
|
|
|
|
app = g_hash_table_lookup (priv->id_to_app, id);
|
|
|
|
if (app)
|
|
|
|
return app;
|
|
|
|
|
2020-02-28 03:36:14 +00:00
|
|
|
info = shell_app_cache_get_info (shell_app_cache_get_default (), id);
|
2013-09-26 21:06:47 +00:00
|
|
|
if (!info)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
app = _shell_app_new (info);
|
2013-11-03 21:19:35 +00:00
|
|
|
g_hash_table_insert (priv->id_to_app, (char *) shell_app_get_id (app), app);
|
2013-09-26 21:06:47 +00:00
|
|
|
return app;
|
Kill off ShellAppInfo, move into ShellApp
This dramatically thins down and sanitizes the application code.
The ShellAppSystem changes in a number of ways:
* Preferences are special cased more explicitly; they aren't apps,
they're shortcuts for an app), and we don't have many of them, so
don't need e.g. the optimizations in ShellAppSystem for searching.
* get_app() changes to lookup_app() and returns null if an app isn't
found. The semantics where it tried to find the .desktop file
if we didn't know about it were just broken; I am pretty sure no
caller needs this, and if they do we'll fix them.
* ShellAppSystem maintains two indexes on apps (by desktop file id
and by GMenuTreeEntry), but is no longer in the business of
dealing with GMenuTree as far as hierarchy and categories go. That
is moved up into js/ui/appDisplay.js. Actually, it flattens both
apps and settings.
Also, ShellWindowTracker is now the sole reference-owner for
window-backed apps. We still do the weird "window:0x1234beef" id
for these apps, but a reference is not stored in ShellAppSystem.
The js/ui/appDisplay.js code is rewritten, and sucks a lot less.
Variable names are clearer:
_apps -> _appIcons
_filterApp -> _visibleApps
_filters -> _categoryBox
Similarly for function names. We no longer call (for every app) a
recursive lookup in GMenuTree to see if it's in a particular section
on every category switch; it's all cached.
NOTE - this intentionally reverts the incremental loading code from
commit 7813c5b93f6bcde8c4beae286e82bfc472b2b656. It's fast enough
here without that.
https://bugzilla.gnome.org/show_bug.cgi?id=648149
2011-04-21 17:35:01 +00:00
|
|
|
}
|
2009-06-25 21:43:54 +00:00
|
|
|
|
2009-07-07 20:08:41 +00:00
|
|
|
/**
|
|
|
|
* shell_app_system_lookup_heuristic_basename:
|
2010-09-15 00:56:34 +00:00
|
|
|
* @system: a #ShellAppSystem
|
|
|
|
* @id: Probable application identifier
|
2009-07-07 20:08:41 +00:00
|
|
|
*
|
|
|
|
* Find a valid application corresponding to a given
|
|
|
|
* heuristically determined application identifier
|
|
|
|
* string, or %NULL if none.
|
|
|
|
*
|
Kill off ShellAppInfo, move into ShellApp
This dramatically thins down and sanitizes the application code.
The ShellAppSystem changes in a number of ways:
* Preferences are special cased more explicitly; they aren't apps,
they're shortcuts for an app), and we don't have many of them, so
don't need e.g. the optimizations in ShellAppSystem for searching.
* get_app() changes to lookup_app() and returns null if an app isn't
found. The semantics where it tried to find the .desktop file
if we didn't know about it were just broken; I am pretty sure no
caller needs this, and if they do we'll fix them.
* ShellAppSystem maintains two indexes on apps (by desktop file id
and by GMenuTreeEntry), but is no longer in the business of
dealing with GMenuTree as far as hierarchy and categories go. That
is moved up into js/ui/appDisplay.js. Actually, it flattens both
apps and settings.
Also, ShellWindowTracker is now the sole reference-owner for
window-backed apps. We still do the weird "window:0x1234beef" id
for these apps, but a reference is not stored in ShellAppSystem.
The js/ui/appDisplay.js code is rewritten, and sucks a lot less.
Variable names are clearer:
_apps -> _appIcons
_filterApp -> _visibleApps
_filters -> _categoryBox
Similarly for function names. We no longer call (for every app) a
recursive lookup in GMenuTree to see if it's in a particular section
on every category switch; it's all cached.
NOTE - this intentionally reverts the incremental loading code from
commit 7813c5b93f6bcde8c4beae286e82bfc472b2b656. It's fast enough
here without that.
https://bugzilla.gnome.org/show_bug.cgi?id=648149
2011-04-21 17:35:01 +00:00
|
|
|
* Returns: (transfer none): A #ShellApp for @name
|
2009-07-07 20:08:41 +00:00
|
|
|
*/
|
2009-10-15 23:28:29 +00:00
|
|
|
ShellApp *
|
2009-07-07 20:08:41 +00:00
|
|
|
shell_app_system_lookup_heuristic_basename (ShellAppSystem *system,
|
Kill off ShellAppInfo, move into ShellApp
This dramatically thins down and sanitizes the application code.
The ShellAppSystem changes in a number of ways:
* Preferences are special cased more explicitly; they aren't apps,
they're shortcuts for an app), and we don't have many of them, so
don't need e.g. the optimizations in ShellAppSystem for searching.
* get_app() changes to lookup_app() and returns null if an app isn't
found. The semantics where it tried to find the .desktop file
if we didn't know about it were just broken; I am pretty sure no
caller needs this, and if they do we'll fix them.
* ShellAppSystem maintains two indexes on apps (by desktop file id
and by GMenuTreeEntry), but is no longer in the business of
dealing with GMenuTree as far as hierarchy and categories go. That
is moved up into js/ui/appDisplay.js. Actually, it flattens both
apps and settings.
Also, ShellWindowTracker is now the sole reference-owner for
window-backed apps. We still do the weird "window:0x1234beef" id
for these apps, but a reference is not stored in ShellAppSystem.
The js/ui/appDisplay.js code is rewritten, and sucks a lot less.
Variable names are clearer:
_apps -> _appIcons
_filterApp -> _visibleApps
_filters -> _categoryBox
Similarly for function names. We no longer call (for every app) a
recursive lookup in GMenuTree to see if it's in a particular section
on every category switch; it's all cached.
NOTE - this intentionally reverts the incremental loading code from
commit 7813c5b93f6bcde8c4beae286e82bfc472b2b656. It's fast enough
here without that.
https://bugzilla.gnome.org/show_bug.cgi?id=648149
2011-04-21 17:35:01 +00:00
|
|
|
const char *name)
|
2009-07-07 20:08:41 +00:00
|
|
|
{
|
2009-10-15 23:28:29 +00:00
|
|
|
ShellApp *result;
|
2013-04-20 21:15:10 +00:00
|
|
|
const char *const *prefix;
|
Kill off ShellAppInfo, move into ShellApp
This dramatically thins down and sanitizes the application code.
The ShellAppSystem changes in a number of ways:
* Preferences are special cased more explicitly; they aren't apps,
they're shortcuts for an app), and we don't have many of them, so
don't need e.g. the optimizations in ShellAppSystem for searching.
* get_app() changes to lookup_app() and returns null if an app isn't
found. The semantics where it tried to find the .desktop file
if we didn't know about it were just broken; I am pretty sure no
caller needs this, and if they do we'll fix them.
* ShellAppSystem maintains two indexes on apps (by desktop file id
and by GMenuTreeEntry), but is no longer in the business of
dealing with GMenuTree as far as hierarchy and categories go. That
is moved up into js/ui/appDisplay.js. Actually, it flattens both
apps and settings.
Also, ShellWindowTracker is now the sole reference-owner for
window-backed apps. We still do the weird "window:0x1234beef" id
for these apps, but a reference is not stored in ShellAppSystem.
The js/ui/appDisplay.js code is rewritten, and sucks a lot less.
Variable names are clearer:
_apps -> _appIcons
_filterApp -> _visibleApps
_filters -> _categoryBox
Similarly for function names. We no longer call (for every app) a
recursive lookup in GMenuTree to see if it's in a particular section
on every category switch; it's all cached.
NOTE - this intentionally reverts the incremental loading code from
commit 7813c5b93f6bcde8c4beae286e82bfc472b2b656. It's fast enough
here without that.
https://bugzilla.gnome.org/show_bug.cgi?id=648149
2011-04-21 17:35:01 +00:00
|
|
|
|
|
|
|
result = shell_app_system_lookup_app (system, name);
|
2009-07-07 20:08:41 +00:00
|
|
|
if (result != NULL)
|
|
|
|
return result;
|
Kill off ShellAppInfo, move into ShellApp
This dramatically thins down and sanitizes the application code.
The ShellAppSystem changes in a number of ways:
* Preferences are special cased more explicitly; they aren't apps,
they're shortcuts for an app), and we don't have many of them, so
don't need e.g. the optimizations in ShellAppSystem for searching.
* get_app() changes to lookup_app() and returns null if an app isn't
found. The semantics where it tried to find the .desktop file
if we didn't know about it were just broken; I am pretty sure no
caller needs this, and if they do we'll fix them.
* ShellAppSystem maintains two indexes on apps (by desktop file id
and by GMenuTreeEntry), but is no longer in the business of
dealing with GMenuTree as far as hierarchy and categories go. That
is moved up into js/ui/appDisplay.js. Actually, it flattens both
apps and settings.
Also, ShellWindowTracker is now the sole reference-owner for
window-backed apps. We still do the weird "window:0x1234beef" id
for these apps, but a reference is not stored in ShellAppSystem.
The js/ui/appDisplay.js code is rewritten, and sucks a lot less.
Variable names are clearer:
_apps -> _appIcons
_filterApp -> _visibleApps
_filters -> _categoryBox
Similarly for function names. We no longer call (for every app) a
recursive lookup in GMenuTree to see if it's in a particular section
on every category switch; it's all cached.
NOTE - this intentionally reverts the incremental loading code from
commit 7813c5b93f6bcde8c4beae286e82bfc472b2b656. It's fast enough
here without that.
https://bugzilla.gnome.org/show_bug.cgi?id=648149
2011-04-21 17:35:01 +00:00
|
|
|
|
2013-04-20 21:15:10 +00:00
|
|
|
for (prefix = vendor_prefixes; *prefix != NULL; prefix++)
|
2009-08-21 18:48:14 +00:00
|
|
|
{
|
2013-04-20 21:15:10 +00:00
|
|
|
char *tmpid = g_strconcat (*prefix, name, NULL);
|
Kill off ShellAppInfo, move into ShellApp
This dramatically thins down and sanitizes the application code.
The ShellAppSystem changes in a number of ways:
* Preferences are special cased more explicitly; they aren't apps,
they're shortcuts for an app), and we don't have many of them, so
don't need e.g. the optimizations in ShellAppSystem for searching.
* get_app() changes to lookup_app() and returns null if an app isn't
found. The semantics where it tried to find the .desktop file
if we didn't know about it were just broken; I am pretty sure no
caller needs this, and if they do we'll fix them.
* ShellAppSystem maintains two indexes on apps (by desktop file id
and by GMenuTreeEntry), but is no longer in the business of
dealing with GMenuTree as far as hierarchy and categories go. That
is moved up into js/ui/appDisplay.js. Actually, it flattens both
apps and settings.
Also, ShellWindowTracker is now the sole reference-owner for
window-backed apps. We still do the weird "window:0x1234beef" id
for these apps, but a reference is not stored in ShellAppSystem.
The js/ui/appDisplay.js code is rewritten, and sucks a lot less.
Variable names are clearer:
_apps -> _appIcons
_filterApp -> _visibleApps
_filters -> _categoryBox
Similarly for function names. We no longer call (for every app) a
recursive lookup in GMenuTree to see if it's in a particular section
on every category switch; it's all cached.
NOTE - this intentionally reverts the incremental loading code from
commit 7813c5b93f6bcde8c4beae286e82bfc472b2b656. It's fast enough
here without that.
https://bugzilla.gnome.org/show_bug.cgi?id=648149
2011-04-21 17:35:01 +00:00
|
|
|
result = shell_app_system_lookup_app (system, tmpid);
|
2009-08-21 18:48:14 +00:00
|
|
|
g_free (tmpid);
|
|
|
|
if (result != NULL)
|
|
|
|
return result;
|
|
|
|
}
|
2009-07-07 20:08:41 +00:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-04-09 01:39:59 +00:00
|
|
|
/**
|
2012-04-06 18:02:04 +00:00
|
|
|
* shell_app_system_lookup_desktop_wmclass:
|
2012-04-09 01:39:59 +00:00
|
|
|
* @system: a #ShellAppSystem
|
2014-05-28 19:54:02 +00:00
|
|
|
* @wmclass: (nullable): A WM_CLASS value
|
2012-04-09 01:39:59 +00:00
|
|
|
*
|
2012-04-06 18:02:04 +00:00
|
|
|
* Find a valid application whose .desktop file, without the extension
|
|
|
|
* and properly canonicalized, matches @wmclass.
|
2012-04-09 01:39:59 +00:00
|
|
|
*
|
|
|
|
* Returns: (transfer none): A #ShellApp for @wmclass
|
|
|
|
*/
|
|
|
|
ShellApp *
|
2012-04-06 18:02:04 +00:00
|
|
|
shell_app_system_lookup_desktop_wmclass (ShellAppSystem *system,
|
|
|
|
const char *wmclass)
|
2012-04-09 01:39:59 +00:00
|
|
|
{
|
|
|
|
char *canonicalized;
|
|
|
|
char *desktop_file;
|
|
|
|
ShellApp *app;
|
|
|
|
|
|
|
|
if (wmclass == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2013-08-18 16:26:37 +00:00
|
|
|
/* First try without changing the case (this handles
|
|
|
|
org.example.Foo.Bar.desktop applications)
|
|
|
|
|
|
|
|
Note that is slightly wrong in that Gtk+ would set
|
|
|
|
the WM_CLASS to Org.example.Foo.Bar, but it also
|
|
|
|
sets the instance part to org.example.Foo.Bar, so we're ok
|
|
|
|
*/
|
|
|
|
desktop_file = g_strconcat (wmclass, ".desktop", NULL);
|
|
|
|
app = shell_app_system_lookup_heuristic_basename (system, desktop_file);
|
|
|
|
g_free (desktop_file);
|
|
|
|
|
|
|
|
if (app)
|
|
|
|
return app;
|
|
|
|
|
2012-04-09 01:39:59 +00:00
|
|
|
canonicalized = g_ascii_strdown (wmclass, -1);
|
|
|
|
|
|
|
|
/* This handles "Fedora Eclipse", probably others.
|
|
|
|
* Note g_strdelimit is modify-in-place. */
|
|
|
|
g_strdelimit (canonicalized, " ", '-');
|
|
|
|
|
|
|
|
desktop_file = g_strconcat (canonicalized, ".desktop", NULL);
|
|
|
|
|
|
|
|
app = shell_app_system_lookup_heuristic_basename (system, desktop_file);
|
|
|
|
|
|
|
|
g_free (canonicalized);
|
|
|
|
g_free (desktop_file);
|
|
|
|
|
|
|
|
return app;
|
|
|
|
}
|
|
|
|
|
2012-04-06 18:02:04 +00:00
|
|
|
/**
|
|
|
|
* shell_app_system_lookup_startup_wmclass:
|
|
|
|
* @system: a #ShellAppSystem
|
2014-05-28 19:54:02 +00:00
|
|
|
* @wmclass: (nullable): A WM_CLASS value
|
2012-04-06 18:02:04 +00:00
|
|
|
*
|
|
|
|
* Find a valid application whose .desktop file contains a
|
|
|
|
* StartupWMClass entry matching @wmclass.
|
|
|
|
*
|
|
|
|
* Returns: (transfer none): A #ShellApp for @wmclass
|
|
|
|
*/
|
|
|
|
ShellApp *
|
|
|
|
shell_app_system_lookup_startup_wmclass (ShellAppSystem *system,
|
|
|
|
const char *wmclass)
|
|
|
|
{
|
2013-10-02 22:16:45 +00:00
|
|
|
const char *id;
|
|
|
|
|
2013-08-08 08:40:01 +00:00
|
|
|
if (wmclass == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2013-10-02 22:16:45 +00:00
|
|
|
id = g_hash_table_lookup (system->priv->startup_wm_class_to_id, wmclass);
|
|
|
|
if (id == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return shell_app_system_lookup_app (system, id);
|
2012-04-06 18:02:04 +00:00
|
|
|
}
|
|
|
|
|
apps: Ensure running apps override new .desktop file data
This patch fixes the "apps vanish from alt-TAB bug".
If a "package system" rips away and possibly replaces .desktop files
at some random time, we have historically used inotify to detect this
and reread state (in a racy way, but...). In GNOME 2, this was
generally not too problematic because the menu widget was totally
separate from the list of windows - and the data they operate on was
disjoint as well.
In GNOME 3 we unify these, and this creates architectural problems
because the windows are tied to the app.
What this patch tries to do is, when rereading the application state,
if we have a running application, we keep that app around instead of
making a new instance. This ensures we preserve any state such as the
set of open windows.
This requires moving the running state into ShellAppSystem. Adjust
callers as necessary, and while we're at it drop the unused "contexts"
stuff.
This is just a somewhat quick band-aid; a REAL fix would require us
having low-level control over application installation. As long as
we're on top of random broken tar+wget wrappers, it will be gross.
A slight future improvement to this patch would add an explicit
"merge" between the old and new data. I think probably we always keep
around the ShellApp corresponding to a given ID, but replace its
GMenuTreeEntry.
https://bugzilla.gnome.org/show_bug.cgi?id=657990
2011-09-03 14:32:06 +00:00
|
|
|
void
|
|
|
|
_shell_app_system_notify_app_state_changed (ShellAppSystem *self,
|
|
|
|
ShellApp *app)
|
|
|
|
{
|
|
|
|
ShellAppState state = shell_app_get_state (app);
|
|
|
|
|
|
|
|
switch (state)
|
|
|
|
{
|
|
|
|
case SHELL_APP_STATE_RUNNING:
|
2011-09-19 16:49:05 +00:00
|
|
|
g_hash_table_insert (self->priv->running_apps, g_object_ref (app), NULL);
|
apps: Ensure running apps override new .desktop file data
This patch fixes the "apps vanish from alt-TAB bug".
If a "package system" rips away and possibly replaces .desktop files
at some random time, we have historically used inotify to detect this
and reread state (in a racy way, but...). In GNOME 2, this was
generally not too problematic because the menu widget was totally
separate from the list of windows - and the data they operate on was
disjoint as well.
In GNOME 3 we unify these, and this creates architectural problems
because the windows are tied to the app.
What this patch tries to do is, when rereading the application state,
if we have a running application, we keep that app around instead of
making a new instance. This ensures we preserve any state such as the
set of open windows.
This requires moving the running state into ShellAppSystem. Adjust
callers as necessary, and while we're at it drop the unused "contexts"
stuff.
This is just a somewhat quick band-aid; a REAL fix would require us
having low-level control over application installation. As long as
we're on top of random broken tar+wget wrappers, it will be gross.
A slight future improvement to this patch would add an explicit
"merge" between the old and new data. I think probably we always keep
around the ShellApp corresponding to a given ID, but replace its
GMenuTreeEntry.
https://bugzilla.gnome.org/show_bug.cgi?id=657990
2011-09-03 14:32:06 +00:00
|
|
|
break;
|
|
|
|
case SHELL_APP_STATE_STARTING:
|
|
|
|
break;
|
|
|
|
case SHELL_APP_STATE_STOPPED:
|
2011-09-19 16:49:05 +00:00
|
|
|
g_hash_table_remove (self->priv->running_apps, app);
|
apps: Ensure running apps override new .desktop file data
This patch fixes the "apps vanish from alt-TAB bug".
If a "package system" rips away and possibly replaces .desktop files
at some random time, we have historically used inotify to detect this
and reread state (in a racy way, but...). In GNOME 2, this was
generally not too problematic because the menu widget was totally
separate from the list of windows - and the data they operate on was
disjoint as well.
In GNOME 3 we unify these, and this creates architectural problems
because the windows are tied to the app.
What this patch tries to do is, when rereading the application state,
if we have a running application, we keep that app around instead of
making a new instance. This ensures we preserve any state such as the
set of open windows.
This requires moving the running state into ShellAppSystem. Adjust
callers as necessary, and while we're at it drop the unused "contexts"
stuff.
This is just a somewhat quick band-aid; a REAL fix would require us
having low-level control over application installation. As long as
we're on top of random broken tar+wget wrappers, it will be gross.
A slight future improvement to this patch would add an explicit
"merge" between the old and new data. I think probably we always keep
around the ShellApp corresponding to a given ID, but replace its
GMenuTreeEntry.
https://bugzilla.gnome.org/show_bug.cgi?id=657990
2011-09-03 14:32:06 +00:00
|
|
|
break;
|
2015-09-23 17:10:16 +00:00
|
|
|
default:
|
|
|
|
g_warn_if_reached();
|
|
|
|
break;
|
apps: Ensure running apps override new .desktop file data
This patch fixes the "apps vanish from alt-TAB bug".
If a "package system" rips away and possibly replaces .desktop files
at some random time, we have historically used inotify to detect this
and reread state (in a racy way, but...). In GNOME 2, this was
generally not too problematic because the menu widget was totally
separate from the list of windows - and the data they operate on was
disjoint as well.
In GNOME 3 we unify these, and this creates architectural problems
because the windows are tied to the app.
What this patch tries to do is, when rereading the application state,
if we have a running application, we keep that app around instead of
making a new instance. This ensures we preserve any state such as the
set of open windows.
This requires moving the running state into ShellAppSystem. Adjust
callers as necessary, and while we're at it drop the unused "contexts"
stuff.
This is just a somewhat quick band-aid; a REAL fix would require us
having low-level control over application installation. As long as
we're on top of random broken tar+wget wrappers, it will be gross.
A slight future improvement to this patch would add an explicit
"merge" between the old and new data. I think probably we always keep
around the ShellApp corresponding to a given ID, but replace its
GMenuTreeEntry.
https://bugzilla.gnome.org/show_bug.cgi?id=657990
2011-09-03 14:32:06 +00:00
|
|
|
}
|
|
|
|
g_signal_emit (self, signals[APP_STATE_CHANGED], 0, app);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_app_system_get_running:
|
|
|
|
* @self: A #ShellAppSystem
|
|
|
|
*
|
|
|
|
* Returns the set of applications which currently have at least one
|
2012-04-09 06:27:47 +00:00
|
|
|
* open window. The returned list will be sorted by shell_app_compare().
|
apps: Ensure running apps override new .desktop file data
This patch fixes the "apps vanish from alt-TAB bug".
If a "package system" rips away and possibly replaces .desktop files
at some random time, we have historically used inotify to detect this
and reread state (in a racy way, but...). In GNOME 2, this was
generally not too problematic because the menu widget was totally
separate from the list of windows - and the data they operate on was
disjoint as well.
In GNOME 3 we unify these, and this creates architectural problems
because the windows are tied to the app.
What this patch tries to do is, when rereading the application state,
if we have a running application, we keep that app around instead of
making a new instance. This ensures we preserve any state such as the
set of open windows.
This requires moving the running state into ShellAppSystem. Adjust
callers as necessary, and while we're at it drop the unused "contexts"
stuff.
This is just a somewhat quick band-aid; a REAL fix would require us
having low-level control over application installation. As long as
we're on top of random broken tar+wget wrappers, it will be gross.
A slight future improvement to this patch would add an explicit
"merge" between the old and new data. I think probably we always keep
around the ShellApp corresponding to a given ID, but replace its
GMenuTreeEntry.
https://bugzilla.gnome.org/show_bug.cgi?id=657990
2011-09-03 14:32:06 +00:00
|
|
|
*
|
|
|
|
* Returns: (element-type ShellApp) (transfer container): Active applications
|
|
|
|
*/
|
|
|
|
GSList *
|
|
|
|
shell_app_system_get_running (ShellAppSystem *self)
|
|
|
|
{
|
|
|
|
gpointer key, value;
|
|
|
|
GSList *ret;
|
|
|
|
GHashTableIter iter;
|
|
|
|
|
|
|
|
g_hash_table_iter_init (&iter, self->priv->running_apps);
|
|
|
|
|
|
|
|
ret = NULL;
|
|
|
|
while (g_hash_table_iter_next (&iter, &key, &value))
|
|
|
|
{
|
2011-09-19 16:49:05 +00:00
|
|
|
ShellApp *app = key;
|
apps: Ensure running apps override new .desktop file data
This patch fixes the "apps vanish from alt-TAB bug".
If a "package system" rips away and possibly replaces .desktop files
at some random time, we have historically used inotify to detect this
and reread state (in a racy way, but...). In GNOME 2, this was
generally not too problematic because the menu widget was totally
separate from the list of windows - and the data they operate on was
disjoint as well.
In GNOME 3 we unify these, and this creates architectural problems
because the windows are tied to the app.
What this patch tries to do is, when rereading the application state,
if we have a running application, we keep that app around instead of
making a new instance. This ensures we preserve any state such as the
set of open windows.
This requires moving the running state into ShellAppSystem. Adjust
callers as necessary, and while we're at it drop the unused "contexts"
stuff.
This is just a somewhat quick band-aid; a REAL fix would require us
having low-level control over application installation. As long as
we're on top of random broken tar+wget wrappers, it will be gross.
A slight future improvement to this patch would add an explicit
"merge" between the old and new data. I think probably we always keep
around the ShellApp corresponding to a given ID, but replace its
GMenuTreeEntry.
https://bugzilla.gnome.org/show_bug.cgi?id=657990
2011-09-03 14:32:06 +00:00
|
|
|
|
|
|
|
ret = g_slist_prepend (ret, app);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = g_slist_sort (ret, (GCompareFunc)shell_app_compare);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2015-07-30 17:55:19 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_app_system_search:
|
|
|
|
* @search_string: the search string to use
|
|
|
|
*
|
|
|
|
* Wrapper around g_desktop_app_info_search() that replaces results that
|
|
|
|
* don't validate as UTF-8 with the empty string.
|
|
|
|
*
|
|
|
|
* Returns: (array zero-terminated=1) (element-type GStrv) (transfer full): a
|
|
|
|
* list of strvs. Free each item with g_strfreev() and free the outer
|
|
|
|
* list with g_free().
|
|
|
|
*/
|
|
|
|
char ***
|
|
|
|
shell_app_system_search (const char *search_string)
|
|
|
|
{
|
2016-02-16 16:33:52 +00:00
|
|
|
char ***results = g_desktop_app_info_search (search_string);
|
|
|
|
char ***groups, **ids;
|
2015-07-30 17:55:19 +00:00
|
|
|
|
2016-02-16 16:33:52 +00:00
|
|
|
for (groups = results; *groups; groups++)
|
|
|
|
for (ids = *groups; *ids; ids++)
|
|
|
|
if (!g_utf8_validate (*ids, -1, NULL))
|
|
|
|
**ids = '\0';
|
2015-07-30 17:55:19 +00:00
|
|
|
|
2016-02-09 18:10:03 +00:00
|
|
|
return results;
|
2015-07-30 17:55:19 +00:00
|
|
|
}
|
2018-12-19 12:13:42 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_app_system_get_installed:
|
|
|
|
* @self: the #ShellAppSystem
|
|
|
|
*
|
|
|
|
* Returns all installed apps, as a list of #GAppInfo
|
|
|
|
*
|
|
|
|
* Returns: (transfer none) (element-type GAppInfo): a list of #GAppInfo
|
|
|
|
* describing all known applications. This memory is owned by the
|
|
|
|
* #ShellAppSystem and should not be freed.
|
|
|
|
**/
|
|
|
|
GList *
|
|
|
|
shell_app_system_get_installed (ShellAppSystem *self)
|
|
|
|
{
|
2020-02-28 03:36:14 +00:00
|
|
|
return shell_app_cache_get_all (shell_app_cache_get_default ());
|
2018-12-19 12:13:42 +00:00
|
|
|
}
|