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 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); }
/* Save app data lists to file */ static gboolean idle_save_application_usage (gpointer data) { ShellAppUsage *self = SHELL_APP_USAGE (data); UsageIterator iter; const char *current_context; const char *context; const char *id; UsageData *usage; GFileOutputStream *output; GOutputStream *buffered_output; GDataOutputStream *data_output; GError *error = NULL; self->save_id = 0; /* Parent directory is already created by shell-global */ output = g_file_replace (self->configfile, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error); if (!output) { g_debug ("Could not save applications usage data: %s", error->message); g_error_free (error); return FALSE; } buffered_output = g_buffered_output_stream_new (G_OUTPUT_STREAM (output)); g_object_unref (output); data_output = g_data_output_stream_new (G_OUTPUT_STREAM (buffered_output)); g_object_unref (buffered_output); if (!g_data_output_stream_put_string (data_output, "<?xml version=\"1.0\"?>\n<application-state>\n", NULL, &error)) goto out; usage_iterator_init (self, &iter); current_context = NULL; while (usage_iterator_next (self, &iter, &context, &id, &usage)) { ShellApp *app; app = shell_app_system_lookup_app (shell_app_system_get_default(), id); if (!app) continue; if (context != current_context) { if (current_context != NULL) { if (!g_data_output_stream_put_string (data_output, " </context>", NULL, &error)) goto out; } current_context = context; if (!g_data_output_stream_put_string (data_output, " <context", NULL, &error)) goto out; if (!write_attribute_string (data_output, "id", context, &error)) goto out; if (!g_data_output_stream_put_string (data_output, ">\n", NULL, &error)) goto out; } if (!g_data_output_stream_put_string (data_output, " <application", NULL, &error)) goto out; if (!write_attribute_string (data_output, "id", id, &error)) goto out; if (!write_attribute_uint (data_output, "open-window-count", shell_app_get_n_windows (app), &error)) goto out; if (!write_attribute_double (data_output, "score", usage->score, &error)) goto out; if (!write_attribute_uint (data_output, "last-seen", usage->last_seen, &error)) goto out; if (!g_data_output_stream_put_string (data_output, "/>\n", NULL, &error)) goto out; } if (current_context != NULL) { if (!g_data_output_stream_put_string (data_output, " </context>\n", NULL, &error)) goto out; } if (!g_data_output_stream_put_string (data_output, "</application-state>\n", NULL, &error)) goto out; out: if (!error) g_output_stream_close_async (G_OUTPUT_STREAM (data_output), 0, NULL, NULL, NULL); g_object_unref (data_output); if (error) { g_debug ("Could not save applications usage data: %s", error->message); g_error_free (error); } return FALSE; }