Split ShellAppMonitor into ShellWindowTracker, ShellAppUsage

The two parts were mapping windows to applications, and
recording application usage statistics.  The latter part
(now called ShellAppUsage) is much more naturally built on top of
the former (now called ShellWindowTracker).

ShellWindowTracker retains the startup-notification handling.

ShellWindowTracker also gains a focus-app property, which is
what most things in the shell UI are interested in (instead of
window focus).

ShellAppSystem moves to exporting ShellApp from more of its
public API, rather than ShellAppInfo.  ShellAppSystem also
ensures that ShellApp instances are unique by holding
a hash on the ids.

ShellApp's private API is split off into a shell-app-private.h,
so shell-app.h can be included in shell-app-system.h.

Favorites handling is removed from ShellAppSystem, now inside
appFavorites.js.

Port all of the JavaScript for these changes.

https://bugzilla.gnome.org/show_bug.cgi?id=598646
This commit is contained in:
Colin Walters
2009-10-15 19:28:29 -04:00
parent 77cf9ae077
commit e941e8088b
20 changed files with 2162 additions and 2165 deletions

View File

@@ -10,6 +10,7 @@
#include <gconf/gconf-client.h>
#include <clutter/clutter.h>
#include "shell-app-private.h"
#include "shell-global.h"
#include "shell-texture-cache.h"
#include "display.h"
@@ -33,7 +34,6 @@ enum {
enum {
INSTALLED_CHANGED,
FAVORITES_CHANGED,
LAST_SIGNAL
};
@@ -43,6 +43,7 @@ struct _ShellAppSystemPrivate {
GMenuTree *apps_tree;
GMenuTree *settings_tree;
GHashTable *app_id_to_info;
GHashTable *app_id_to_app;
GHashTable *cached_menu_contents; /* <char *id, GSList<ShellAppInfo*>> */
@@ -50,8 +51,6 @@ struct _ShellAppSystemPrivate {
GSList *cached_settings; /* ShellAppInfo */
GList *cached_favorites; /* utf8 */
gint app_monitor_id;
guint app_change_timeout_id;
@@ -62,8 +61,6 @@ static void shell_app_system_finalize (GObject *object);
static gboolean on_tree_changed (gpointer user_data);
static void on_tree_changed_cb (GMenuTree *tree, gpointer user_data);
static void reread_menus (ShellAppSystem *self);
static void on_favorite_apps_changed (GConfClient *client, guint id, GConfEntry *entry, gpointer user_data);
static void reread_favorite_apps (ShellAppSystem *system);
G_DEFINE_TYPE(ShellAppSystem, shell_app_system, G_TYPE_OBJECT);
@@ -205,14 +202,6 @@ static void shell_app_system_class_init(ShellAppSystemClass *klass)
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[FAVORITES_CHANGED] =
g_signal_new ("favorites-changed",
SHELL_TYPE_APP_SYSTEM,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ShellAppSystemClass, favorites_changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
g_type_class_add_private (gobject_class, sizeof (ShellAppSystemPrivate));
}
@@ -228,8 +217,11 @@ shell_app_system_init (ShellAppSystem *self)
ShellAppSystemPrivate);
/* The key is owned by the value */
priv->app_id_to_app = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, (GDestroyNotify) shell_app_info_unref);
priv->app_id_to_info = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, (GDestroyNotify) shell_app_info_unref);
/* Key is owned by info */
priv->app_id_to_app = g_hash_table_new (g_str_hash, g_str_equal);
priv->cached_menu_contents = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, free_appinfo_gslist);
@@ -249,10 +241,6 @@ shell_app_system_init (ShellAppSystem *self)
reread_menus (self);
client = gconf_client_get_default ();
self->priv->app_monitor_id = gconf_client_notify_add (client, SHELL_APP_FAVORITES_KEY,
on_favorite_apps_changed, self, NULL, NULL);
reread_favorite_apps (self);
}
static void
@@ -269,6 +257,7 @@ shell_app_system_finalize (GObject *object)
g_hash_table_destroy (priv->cached_menu_contents);
g_hash_table_destroy (priv->app_id_to_info);
g_hash_table_destroy (priv->app_id_to_app);
g_slist_foreach (priv->cached_app_menus, (GFunc)shell_app_menu_entry_free, NULL);
@@ -279,10 +268,6 @@ shell_app_system_finalize (GObject *object)
g_slist_free (priv->cached_settings);
priv->cached_settings = NULL;
g_list_free (priv->cached_favorites);
gconf_client_notify_remove (gconf_client_get_default (), priv->app_monitor_id);
G_OBJECT_CLASS (shell_app_system_parent_class)->finalize(object);
}
@@ -404,7 +389,7 @@ cache_by_id (ShellAppSystem *self, GSList *apps, gboolean ref)
if (ref)
shell_app_info_ref (info);
/* the name is owned by the info itself */
g_hash_table_insert (self->priv->app_id_to_app, (char*)shell_app_info_get_id (info),
g_hash_table_insert (self->priv->app_id_to_info, (char*)shell_app_info_get_id (info),
info);
}
}
@@ -421,7 +406,7 @@ reread_menus (ShellAppSystem *self)
/* Now loop over applications.menu and settings.menu, inserting each by desktop file
* ID into a hash */
g_hash_table_remove_all (self->priv->app_id_to_app);
g_hash_table_remove_all (self->priv->app_id_to_info);
trunk = gmenu_tree_get_root_directory (self->priv->apps_tree);
apps = gather_entries_recurse (self, NULL, trunk);
gmenu_tree_item_unref (trunk);
@@ -469,63 +454,6 @@ on_tree_changed_cb (GMenuTree *monitor, gpointer user_data)
self, NULL);
}
static GList *
convert_gconf_value_string_list_to_list_uniquify (GConfValue *value )
{
GSList *list;
GSList *tmp;
GList *result = NULL;
GHashTable *tmp_table = g_hash_table_new (g_str_hash, g_str_equal);
list = gconf_value_get_list (value);
for (tmp = list ; tmp; tmp = tmp->next)
{
GConfValue *value = tmp->data;
char *str = g_strdup (gconf_value_get_string (value));
if (!str)
continue;
if (g_hash_table_lookup (tmp_table, str))
{
g_free (str);
continue;
}
g_hash_table_insert (tmp_table, str, GUINT_TO_POINTER(1));
result = g_list_prepend (result, str);
}
g_hash_table_destroy (tmp_table);
return g_list_reverse (result);
}
static void
reread_favorite_apps (ShellAppSystem *system)
{
GConfClient *client = gconf_client_get_default ();
GConfValue *val;
val = gconf_client_get (client, SHELL_APP_FAVORITES_KEY, NULL);
if (!(val && val->type == GCONF_VALUE_LIST && gconf_value_get_list_type (val) == GCONF_VALUE_STRING))
return;
g_list_foreach (system->priv->cached_favorites, (GFunc) g_free, NULL);
g_list_free (system->priv->cached_favorites);
system->priv->cached_favorites = convert_gconf_value_string_list_to_list_uniquify (val);
gconf_value_free (val);
}
void
on_favorite_apps_changed (GConfClient *client,
guint id,
GConfEntry *entry,
gpointer user_data)
{
ShellAppSystem *system = SHELL_APP_SYSTEM (user_data);
reread_favorite_apps (system);
g_signal_emit (G_OBJECT (system), signals[FAVORITES_CHANGED], 0);
}
GType
shell_app_info_get_type (void)
{
@@ -628,93 +556,70 @@ shell_app_system_get_default ()
return instance;
}
/**
* shell_app_system_get_favorites:
*
* Return the list of applications which have been explicitly added to the
* favorites.
*
* Return value: (transfer none) (element-type utf8): List of favorite application ids
*/
GList *
shell_app_system_get_favorites (ShellAppSystem *system)
{
return system->priv->cached_favorites;
}
typedef struct {
ShellAppSystem *appsys;
ShellAppInfo *info;
} ShellAppRef;
static void
set_gconf_value_string_list (GConfValue *val, GList *items)
shell_app_system_on_app_weakref (gpointer data,
GObject *location)
{
GList *iter;
GSList *tmp = NULL;
ShellAppRef *ref = data;
for (iter = items; iter; iter = iter->next)
{
const char *str = iter->data;
GConfValue *strval = gconf_value_new (GCONF_VALUE_STRING);
gconf_value_set_string (strval, str);
tmp = g_slist_prepend (tmp, strval);
}
tmp = g_slist_reverse (tmp);
gconf_value_set_list (val, tmp);
g_slist_free (tmp);
}
void
shell_app_system_add_favorite (ShellAppSystem *system, const char *id)
{
GConfClient *client = gconf_client_get_default ();
GConfValue *val;
GList *iter;
iter = g_list_find_custom (system->priv->cached_favorites, id, (GCompareFunc)strcmp);
if (iter)
return;
val = gconf_value_new (GCONF_VALUE_LIST);
gconf_value_set_list_type (val, GCONF_VALUE_STRING);
system->priv->cached_favorites = g_list_append (system->priv->cached_favorites, g_strdup (id));
set_gconf_value_string_list (val, system->priv->cached_favorites);
gconf_client_set (client, SHELL_APP_FAVORITES_KEY, val, NULL);
}
void
shell_app_system_remove_favorite (ShellAppSystem *system, const char *id)
{
GConfClient *client = gconf_client_get_default ();
GConfValue *val;
GList *iter;
iter = g_list_find_custom (system->priv->cached_favorites, id, (GCompareFunc)strcmp);
if (!iter)
return;
g_free (iter->data);
system->priv->cached_favorites = g_list_delete_link (system->priv->cached_favorites, iter);
val = gconf_value_new (GCONF_VALUE_LIST);
gconf_value_set_list_type (val, GCONF_VALUE_STRING);
set_gconf_value_string_list (val, system->priv->cached_favorites);
gconf_client_set (client, SHELL_APP_FAVORITES_KEY, val, NULL);
g_hash_table_remove (ref->appsys->priv->app_id_to_app, shell_app_info_get_id (ref->info));
shell_app_info_unref (ref->info);
g_free (ref);
}
/**
* shell_app_system_lookup_app:
* shell_app_system_get_app:
*
* Return value: (transfer full): The #ShellAppInfo for id, or %NULL if none
* Find or create a #ShellApp corresponding to an id; if already cached
* elsewhere in memory, return that instance. Otherwise, create a new
* one.
*
* Return value: (transfer full): The #ShellApp for id, or %NULL if none
*/
ShellAppInfo *
shell_app_system_lookup_cached_app (ShellAppSystem *self, const char *id)
ShellApp *
shell_app_system_get_app (ShellAppSystem *self,
const char *id)
{
ShellAppInfo *info;
ShellApp *app;
info = g_hash_table_lookup (self->priv->app_id_to_app, id);
if (info)
shell_app_info_ref (info);
return info;
app = g_hash_table_lookup (self->priv->app_id_to_app, id);
if (app)
return g_object_ref (app);
info = g_hash_table_lookup (self->priv->app_id_to_info, id);
if (!info)
return NULL;
app = _shell_app_new (info);
return app;
}
/* ShellAppSystem ensures we have a unique instance of
* apps per id.
*/
void
_shell_app_system_register_app (ShellAppSystem *self,
ShellApp *app)
{
const char *id;
ShellAppRef *ref;
id = shell_app_get_id (app);
g_return_if_fail (g_hash_table_lookup (self->priv->app_id_to_app, id) == NULL);
ref = g_new0 (ShellAppRef, 1);
ref->appsys = self;
ref->info = shell_app_info_ref (_shell_app_get_info (app));
g_hash_table_insert (self->priv->app_id_to_app, (char*)shell_app_info_get_id (ref->info), app);
g_object_weak_ref (G_OBJECT (app), shell_app_system_on_app_weakref, ref);
}
ShellAppInfo *
@@ -778,16 +683,16 @@ shell_app_system_create_from_window (ShellAppSystem *system, MetaWindow *window)
* heuristically determined application identifier
* string, or %NULL if none.
*
* Returns: (transfer full): A #ShellAppInfo for name
* Returns: (transfer full): A #ShellApp for name
*/
ShellAppInfo *
ShellApp *
shell_app_system_lookup_heuristic_basename (ShellAppSystem *system,
const char *name)
{
ShellAppInfo *result;
ShellApp *result;
char **vendor_prefixes;
result = shell_app_system_lookup_cached_app (system, name);
result = shell_app_system_get_app (system, name);
if (result != NULL)
return result;
@@ -795,7 +700,7 @@ shell_app_system_lookup_heuristic_basename (ShellAppSystem *system,
*vendor_prefixes; vendor_prefixes++)
{
char *tmpid = g_strjoin (NULL, *vendor_prefixes, "-", name, NULL);
result = shell_app_system_lookup_cached_app (system, tmpid);
result = shell_app_system_get_app (system, tmpid);
g_free (tmpid);
if (result != NULL)
return result;