app-system: Remove use of gnome-menus internally
We want to transition to a system in the future where we have a desktop file cache. As we no longer differentiate categories or similar, it no longer makes sense to have app visibility based on categories. Thus, we no longer need to use gnome-menus to list all apps. The potential issue here is reloading all desktop files when new files are created, but this can be dealt with individually. The "All Applications" view still uses gnome-menus. https://bugzilla.gnome.org/show_bug.cgi?id=698486
This commit is contained in:
parent
634a599db6
commit
d27d9fe694
@ -71,7 +71,6 @@ POLKIT_MIN_VERSION=0.100
|
|||||||
STARTUP_NOTIFICATION_MIN_VERSION=0.11
|
STARTUP_NOTIFICATION_MIN_VERSION=0.11
|
||||||
GCR_MIN_VERSION=3.7.5
|
GCR_MIN_VERSION=3.7.5
|
||||||
GNOME_DESKTOP_REQUIRED_VERSION=3.7.90
|
GNOME_DESKTOP_REQUIRED_VERSION=3.7.90
|
||||||
GNOME_MENUS_REQUIRED_VERSION=3.5.3
|
|
||||||
NETWORKMANAGER_MIN_VERSION=0.9.8
|
NETWORKMANAGER_MIN_VERSION=0.9.8
|
||||||
PULSE_MIN_VERS=2.0
|
PULSE_MIN_VERS=2.0
|
||||||
|
|
||||||
@ -81,7 +80,6 @@ SHARED_PCS="gio-unix-2.0 >= $GIO_MIN_VERSION
|
|||||||
gtk+-3.0 >= $GTK_MIN_VERSION
|
gtk+-3.0 >= $GTK_MIN_VERSION
|
||||||
atk-bridge-2.0
|
atk-bridge-2.0
|
||||||
gjs-internals-1.0 >= $GJS_MIN_VERSION
|
gjs-internals-1.0 >= $GJS_MIN_VERSION
|
||||||
libgnome-menu-3.0 >= $GNOME_MENUS_REQUIRED_VERSION
|
|
||||||
$recorder_modules
|
$recorder_modules
|
||||||
gdk-x11-3.0 libsoup-2.4
|
gdk-x11-3.0 libsoup-2.4
|
||||||
xtst
|
xtst
|
||||||
|
@ -38,15 +38,12 @@ enum {
|
|||||||
static guint signals[LAST_SIGNAL] = { 0 };
|
static guint signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
struct _ShellAppSystemPrivate {
|
struct _ShellAppSystemPrivate {
|
||||||
GMenuTree *apps_tree;
|
|
||||||
|
|
||||||
GHashTable *running_apps;
|
GHashTable *running_apps;
|
||||||
GHashTable *id_to_app;
|
GHashTable *id_to_app;
|
||||||
GHashTable *startup_wm_class_to_id;
|
GHashTable *startup_wm_class_to_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void shell_app_system_finalize (GObject *object);
|
static void shell_app_system_finalize (GObject *object);
|
||||||
static void on_apps_tree_changed_cb (GMenuTree *tree, gpointer user_data);
|
|
||||||
|
|
||||||
G_DEFINE_TYPE(ShellAppSystem, shell_app_system, G_TYPE_OBJECT);
|
G_DEFINE_TYPE(ShellAppSystem, shell_app_system, G_TYPE_OBJECT);
|
||||||
|
|
||||||
@ -74,6 +71,26 @@ static void shell_app_system_class_init(ShellAppSystemClass *klass)
|
|||||||
g_type_class_add_private (gobject_class, sizeof (ShellAppSystemPrivate));
|
g_type_class_add_private (gobject_class, sizeof (ShellAppSystemPrivate));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
load_apps (ShellAppSystem *self)
|
||||||
|
{
|
||||||
|
ShellAppSystemPrivate *priv = self->priv;
|
||||||
|
GList *apps, *l;
|
||||||
|
|
||||||
|
apps = g_app_info_get_all ();
|
||||||
|
for (l = apps; l != NULL; l = l->next)
|
||||||
|
{
|
||||||
|
GAppInfo *info = l->data;
|
||||||
|
g_hash_table_insert (priv->id_to_app,
|
||||||
|
(char *) g_app_info_get_id (info),
|
||||||
|
_shell_app_new (G_DESKTOP_APP_INFO (info)));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free_full (apps, g_object_unref);
|
||||||
|
|
||||||
|
g_signal_emit (self, signals[INSTALLED_CHANGED], 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
shell_app_system_init (ShellAppSystem *self)
|
shell_app_system_init (ShellAppSystem *self)
|
||||||
{
|
{
|
||||||
@ -90,12 +107,7 @@ shell_app_system_init (ShellAppSystem *self)
|
|||||||
|
|
||||||
priv->startup_wm_class_to_id = g_hash_table_new (g_str_hash, g_str_equal);
|
priv->startup_wm_class_to_id = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
|
|
||||||
/* We want to track NoDisplay apps, so we add INCLUDE_NODISPLAY. We'll
|
load_apps (self);
|
||||||
* filter NoDisplay apps out when showing them to the user. */
|
|
||||||
priv->apps_tree = gmenu_tree_new ("applications.menu", GMENU_TREE_FLAGS_INCLUDE_NODISPLAY);
|
|
||||||
g_signal_connect (priv->apps_tree, "changed", G_CALLBACK (on_apps_tree_changed_cb), self);
|
|
||||||
|
|
||||||
on_apps_tree_changed_cb (priv->apps_tree, self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -104,8 +116,6 @@ shell_app_system_finalize (GObject *object)
|
|||||||
ShellAppSystem *self = SHELL_APP_SYSTEM (object);
|
ShellAppSystem *self = SHELL_APP_SYSTEM (object);
|
||||||
ShellAppSystemPrivate *priv = self->priv;
|
ShellAppSystemPrivate *priv = self->priv;
|
||||||
|
|
||||||
g_object_unref (priv->apps_tree);
|
|
||||||
|
|
||||||
g_hash_table_destroy (priv->running_apps);
|
g_hash_table_destroy (priv->running_apps);
|
||||||
g_hash_table_destroy (priv->id_to_app);
|
g_hash_table_destroy (priv->id_to_app);
|
||||||
g_hash_table_destroy (priv->startup_wm_class_to_id);
|
g_hash_table_destroy (priv->startup_wm_class_to_id);
|
||||||
@ -113,150 +123,6 @@ shell_app_system_finalize (GObject *object)
|
|||||||
G_OBJECT_CLASS (shell_app_system_parent_class)->finalize (object);
|
G_OBJECT_CLASS (shell_app_system_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
get_flattened_entries_recurse (GMenuTreeDirectory *dir,
|
|
||||||
GHashTable *entry_set)
|
|
||||||
{
|
|
||||||
GMenuTreeIter *iter = gmenu_tree_directory_iter (dir);
|
|
||||||
GMenuTreeItemType next_type;
|
|
||||||
|
|
||||||
while ((next_type = gmenu_tree_iter_next (iter)) != GMENU_TREE_ITEM_INVALID)
|
|
||||||
{
|
|
||||||
gpointer item = NULL;
|
|
||||||
|
|
||||||
switch (next_type)
|
|
||||||
{
|
|
||||||
case GMENU_TREE_ITEM_ENTRY:
|
|
||||||
{
|
|
||||||
GMenuTreeEntry *entry;
|
|
||||||
item = entry = gmenu_tree_iter_get_entry (iter);
|
|
||||||
/* Key is owned by entry */
|
|
||||||
g_hash_table_replace (entry_set,
|
|
||||||
(char*)gmenu_tree_entry_get_desktop_file_id (entry),
|
|
||||||
gmenu_tree_item_ref (entry));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GMENU_TREE_ITEM_DIRECTORY:
|
|
||||||
{
|
|
||||||
item = gmenu_tree_iter_get_directory (iter);
|
|
||||||
get_flattened_entries_recurse ((GMenuTreeDirectory*)item, entry_set);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (item != NULL)
|
|
||||||
gmenu_tree_item_unref (item);
|
|
||||||
}
|
|
||||||
|
|
||||||
gmenu_tree_iter_unref (iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GHashTable *
|
|
||||||
get_flattened_entries_from_tree (GMenuTree *tree)
|
|
||||||
{
|
|
||||||
GHashTable *table;
|
|
||||||
GMenuTreeDirectory *root;
|
|
||||||
|
|
||||||
table = g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
||||||
(GDestroyNotify) NULL,
|
|
||||||
(GDestroyNotify) gmenu_tree_item_unref);
|
|
||||||
|
|
||||||
root = gmenu_tree_get_root_directory (tree);
|
|
||||||
|
|
||||||
if (root != NULL)
|
|
||||||
get_flattened_entries_recurse (root, table);
|
|
||||||
|
|
||||||
gmenu_tree_item_unref (root);
|
|
||||||
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_apps_tree_changed_cb (GMenuTree *tree,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
ShellAppSystem *self = SHELL_APP_SYSTEM (user_data);
|
|
||||||
GError *error = NULL;
|
|
||||||
GHashTable *new_apps;
|
|
||||||
GHashTableIter iter;
|
|
||||||
gpointer key, value;
|
|
||||||
|
|
||||||
g_assert (tree == self->priv->apps_tree);
|
|
||||||
|
|
||||||
if (!gmenu_tree_load_sync (self->priv->apps_tree, &error))
|
|
||||||
{
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
g_warning ("Failed to load apps: %s", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_warning ("Failed to load apps");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_apps = get_flattened_entries_from_tree (self->priv->apps_tree);
|
|
||||||
g_hash_table_iter_init (&iter, new_apps);
|
|
||||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
|
||||||
{
|
|
||||||
const char *id = key;
|
|
||||||
GMenuTreeEntry *entry = value;
|
|
||||||
ShellApp *app;
|
|
||||||
GDesktopAppInfo *info;
|
|
||||||
const char *startup_wm_class;
|
|
||||||
|
|
||||||
info = g_desktop_app_info_new (gmenu_tree_entry_get_desktop_file_id (entry));
|
|
||||||
|
|
||||||
app = g_hash_table_lookup (self->priv->id_to_app, id);
|
|
||||||
if (app != NULL)
|
|
||||||
{
|
|
||||||
GDesktopAppInfo *old_info;
|
|
||||||
const gchar *old_startup_wm_class;
|
|
||||||
|
|
||||||
old_info = shell_app_get_app_info (app);
|
|
||||||
old_startup_wm_class = g_desktop_app_info_get_startup_wm_class (old_info);
|
|
||||||
|
|
||||||
if (old_startup_wm_class)
|
|
||||||
g_hash_table_remove (self->priv->startup_wm_class_to_id, old_startup_wm_class);
|
|
||||||
|
|
||||||
_shell_app_set_app_info (app, info);
|
|
||||||
g_object_ref (app); /* Extra ref, removed in _replace below */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
app = _shell_app_new (info);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_unref (info);
|
|
||||||
|
|
||||||
g_hash_table_replace (self->priv->id_to_app, (char*)id, app);
|
|
||||||
|
|
||||||
startup_wm_class = g_desktop_app_info_get_startup_wm_class (info);
|
|
||||||
if (startup_wm_class)
|
|
||||||
g_hash_table_replace (self->priv->startup_wm_class_to_id,
|
|
||||||
(char*)startup_wm_class, (char*)id);
|
|
||||||
}
|
|
||||||
/* Now iterate over the apps again; we need to unreference any apps
|
|
||||||
* which have been removed. The JS code may still be holding a
|
|
||||||
* reference; that's fine.
|
|
||||||
*/
|
|
||||||
g_hash_table_iter_init (&iter, self->priv->id_to_app);
|
|
||||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
|
||||||
{
|
|
||||||
const char *id = key;
|
|
||||||
|
|
||||||
if (!g_hash_table_lookup (new_apps, id))
|
|
||||||
g_hash_table_iter_remove (&iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_hash_table_destroy (new_apps);
|
|
||||||
|
|
||||||
g_signal_emit (self, signals[INSTALLED_CHANGED], 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shell_app_system_get_default:
|
* shell_app_system_get_default:
|
||||||
*
|
*
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
#include <meta/window.h>
|
#include <meta/window.h>
|
||||||
#define GMENU_I_KNOW_THIS_IS_UNSTABLE
|
|
||||||
#include <gmenu-tree.h>
|
|
||||||
|
|
||||||
#include "shell-app.h"
|
#include "shell-app.h"
|
||||||
|
|
||||||
|
@ -4,9 +4,8 @@
|
|||||||
|
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
|
#include <gio/gdesktopappinfo.h>
|
||||||
#include <meta/window.h>
|
#include <meta/window.h>
|
||||||
#define GMENU_I_KNOW_THIS_IS_UNSTABLE
|
|
||||||
#include <gmenu-tree.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user