/** * shell_app_usage_compare: * @self: the usage instance to request * @context: Activity identifier * @app_a: First app * @app_b: Second app * * Compare @app_a and @app_b based on frequency of use. * * Returns: -1 if @app_a ranks higher than @app_b, 1 if @app_b ranks higher * than @app_a, and 0 if both rank equally. */ int shell_app_usage_compare (ShellAppUsage *self, const char *context, ShellApp *app_a, ShellApp *app_b) { GHashTable *usages; UsageData *usage_a, *usage_b; usages = g_hash_table_lookup (self->app_usages_for_context, context); if (usages == NULL) return 0; usage_a = g_hash_table_lookup (usages, shell_app_get_id (app_a)); usage_b = g_hash_table_lookup (usages, shell_app_get_id (app_b)); if (usage_a == NULL && usage_b == NULL) return 0; else if (usage_a == NULL) return 1; else if (usage_b == NULL) return -1; return usage_b->score - usage_a->score; }
static void disassociate_window (ShellWindowTracker *self, MetaWindow *window) { ShellApp *app; app = g_hash_table_lookup (self->window_to_app, window); if (!app) return; g_object_ref (app); g_hash_table_remove (self->window_to_app, window); _shell_app_remove_window (app, window); if (shell_app_get_n_windows (app) == 0) { const char *id = shell_app_get_id (app); g_hash_table_remove (self->running_apps, id); g_signal_emit (self, signals[APP_RUNNING_CHANGED], 0, app); } g_signal_emit (self, signals[TRACKED_WINDOWS_CHANGED], 0); g_object_unref (app); }
static int sort_apps_by_usage (gconstpointer a, gconstpointer b, gpointer datap) { SortAppsByUsageData *data = datap; ShellApp *app_a, *app_b; UsageData *usage_a, *usage_b; app_a = (ShellApp*)a; app_b = (ShellApp*)b; usage_a = g_hash_table_lookup (data->context_usages, shell_app_get_id (app_a)); usage_b = g_hash_table_lookup (data->context_usages, shell_app_get_id (app_b)); return usage_b->score - usage_a->score; }
static UsageData * get_usage_for_app (ShellAppUsage *self, ShellApp *app) { const char *context; context = _shell_window_tracker_get_app_context (shell_window_tracker_get_default (), app); return get_app_usage_for_context_and_id (self, context, shell_app_get_id (app)); }
void _shell_window_tracker_notify_app_state_changed (ShellWindowTracker *self, ShellApp *app) { ShellAppState state = shell_app_get_state (app); switch (state) { case SHELL_APP_STATE_RUNNING: /* key is owned by the app */ g_hash_table_insert (self->running_apps, (char*)shell_app_get_id (app), app); break; case SHELL_APP_STATE_STARTING: break; case SHELL_APP_STATE_STOPPED: g_hash_table_remove (self->running_apps, shell_app_get_id (app)); break; } g_signal_emit (self, signals[APP_STATE_CHANGED], 0, 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); }
static gboolean app_is_stale (ShellApp *app) { GDesktopAppInfo *info; gboolean is_stale; if (shell_app_is_window_backed (app)) return FALSE; info = g_desktop_app_info_new (shell_app_get_id (app)); is_stale = (info == NULL); if (info) g_object_unref (info); return is_stale; }
static void track_window (ShellWindowTracker *self, MetaWindow *window) { ShellApp *app; if (!window_is_tracked (window)) return; app = get_app_for_window (self, window); if (!app) return; /* At this point we've stored the association from window -> application */ g_hash_table_insert (self->window_to_app, window, app); /* However, only put interesting windows in the window list for an app. */ if (!shell_window_tracker_is_window_interesting (window)) return; if (shell_app_is_transient (app)) { /* For a transient application, it's possible one of our title regexps * will match at a later time, i.e. the application may not have set * its title fully at the time it initially maps a window. Watch * for title changes and recompute the app. */ g_signal_connect (window, "notify::title", G_CALLBACK (on_transient_window_title_changed), self); } _shell_app_add_window (app, window); if (shell_app_get_n_windows (app) == 1) { /* key is owned by the app */ g_hash_table_insert (self->running_apps, (char*)shell_app_get_id (app), app); g_signal_emit (self, signals[APP_RUNNING_CHANGED], 0, app); } g_signal_emit (self, signals[TRACKED_WINDOWS_CHANGED], 0); }
/** * shell_app_system_lookup_app: * * Find a #ShellApp corresponding to an id. * * Return value: (transfer none): The #ShellApp for id, or %NULL if none */ ShellApp * shell_app_system_lookup_app (ShellAppSystem *self, const char *id) { ShellAppSystemPrivate *priv = self->priv; ShellApp *app; GDesktopAppInfo *info; app = g_hash_table_lookup (priv->id_to_app, id); if (app) return app; info = g_desktop_app_info_new (id); if (!info) return NULL; app = _shell_app_new (info); g_hash_table_insert (priv->id_to_app, (char *) shell_app_get_id (app), app); g_object_unref (info); return app; }