aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Gould <ted@canonical.com>2009-08-25 10:25:14 -0500
committerTed Gould <ted@canonical.com>2009-08-25 10:25:14 -0500
commitdfc4d6f1ac1e6c73fb7334a4192f176579fde0b8 (patch)
tree9503734e5b94726859e9e31d05749b000a0d02c4
parentb42f05f6fbec5abbaa8f34837ffe16d536a89493 (diff)
parentacf054710bea98ee0a63c72cf5e5bcbff8b9bc74 (diff)
downloadayatana-indicator-messages-dfc4d6f1ac1e6c73fb7334a4192f176579fde0b8.tar.gz
ayatana-indicator-messages-dfc4d6f1ac1e6c73fb7334a4192f176579fde0b8.tar.bz2
ayatana-indicator-messages-dfc4d6f1ac1e6c73fb7334a4192f176579fde0b8.zip
Merging in the dirwatch branch
-rw-r--r--src/messages-service.c361
1 files changed, 347 insertions, 14 deletions
diff --git a/src/messages-service.c b/src/messages-service.c
index 2020dd3..384198a 100644
--- a/src/messages-service.c
+++ b/src/messages-service.c
@@ -24,6 +24,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <pango/pango-utils.h>
#include <dbus/dbus-glib-bindings.h>
#include <libindicate/listener.h>
+#include <gio/gio.h>
#include <libdbusmenu-glib/server.h>
@@ -50,6 +51,17 @@ static void check_eclipses (AppMenuItem * ai);
static void remove_eclipses (AppMenuItem * ai);
static gboolean build_launcher (gpointer data);
static gboolean build_launchers (gpointer data);
+static gboolean blacklist_init (gpointer data);
+static gboolean blacklist_add (gpointer data);
+static gboolean blacklist_remove (gpointer data);
+static void blacklist_dir_changed (GFileMonitor * monitor, GFile * file, GFile * other_file, GFileMonitorEvent event_type, gpointer user_data);
+static void app_dir_changed (GFileMonitor * monitor, GFile * file, GFile * other_file, GFileMonitorEvent event_type, gpointer user_data);
+static gboolean destroy_launcher (gpointer data);
+
+
+/*
+ * Server List
+ */
typedef struct _serverList_t serverList_t;
struct _serverList_t {
@@ -86,6 +98,10 @@ serverList_sort (gconstpointer a, gconstpointer b)
return g_strcmp0(pan, pbn);
}
+/*
+ * Item List
+ */
+
typedef struct _imList_t imList_t;
struct _imList_t {
IndicateListenerServer * server;
@@ -124,9 +140,14 @@ imList_sort (gconstpointer a, gconstpointer b)
return (gint)(im_menu_item_get_seconds(IM_MENU_ITEM(pb->menuitem)) - im_menu_item_get_seconds(IM_MENU_ITEM(pa->menuitem)));
}
+/*
+ * Launcher List
+ */
+
typedef struct _launcherList_t launcherList_t;
struct _launcherList_t {
LauncherMenuItem * menuitem;
+ GList * appdiritems;
};
static gint
@@ -143,6 +164,201 @@ launcherList_sort (gconstpointer a, gconstpointer b)
return g_strcmp0(pan, pbn);
}
+/*
+ * Black List
+ */
+
+static GHashTable * blacklist = NULL;
+static GFileMonitor * blacklistdirmon = NULL;
+
+/* Initialize the black list and start to setup
+ handlers for it. */
+static gboolean
+blacklist_init (gpointer data)
+{
+ blacklist = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, g_free);
+
+ gchar * blacklistdir = g_build_filename(g_get_user_config_dir(), USER_BLACKLIST_DIR, NULL);
+ g_debug("Looking at blacklist: %s", blacklistdir);
+ if (!g_file_test(blacklistdir, G_FILE_TEST_IS_DIR)) {
+ g_free(blacklistdir);
+ return FALSE;
+ }
+
+ GFile * filedir = g_file_new_for_path(blacklistdir);
+ blacklistdirmon = g_file_monitor_directory(filedir, G_FILE_MONITOR_NONE, NULL, NULL);
+ if (blacklistdirmon != NULL) {
+ g_signal_connect(G_OBJECT(blacklistdirmon), "changed", G_CALLBACK(blacklist_dir_changed), NULL);
+ }
+
+ GError * error = NULL;
+ GDir * dir = g_dir_open(blacklistdir, 0, &error);
+ if (dir == NULL) {
+ g_warning("Unable to open blacklist directory (%s): %s", blacklistdir, error->message);
+ g_error_free(error);
+ g_free(blacklistdir);
+ return FALSE;
+ }
+
+ const gchar * filename = NULL;
+ while ((filename = g_dir_read_name(dir)) != NULL) {
+ g_debug("Found file: %s", filename);
+ gchar * path = g_build_filename(blacklistdir, filename, NULL);
+ g_idle_add(blacklist_add, path);
+ }
+
+ g_dir_close(dir);
+ g_free(blacklistdir);
+
+ return FALSE;
+}
+
+/* Add a definition file into the black list and eclipse
+ and launchers that have the same file. */
+static gboolean
+blacklist_add (gpointer udata)
+{
+ gchar * definition_file = (gchar *)udata;
+ /* Dump the file */
+ gchar * desktop;
+ g_file_get_contents(definition_file, &desktop, NULL, NULL);
+ if (desktop == NULL) {
+ g_warning("Couldn't get data out of: %s", definition_file);
+ return FALSE;
+ }
+
+ /* Clean up the data */
+ gchar * trimdesktop = pango_trim_string(desktop);
+ g_free(desktop);
+
+ /* Check for conflicts */
+ gpointer data = g_hash_table_lookup(blacklist, trimdesktop);
+ if (data != NULL) {
+ gchar * oldfile = (gchar *)data;
+ if (!g_strcmp0(oldfile, definition_file)) {
+ g_warning("Already added file '%s'", oldfile);
+ } else {
+ g_warning("Already have desktop file '%s' in blacklist file '%s' not adding from '%s'", trimdesktop, oldfile, definition_file);
+ }
+
+ g_free(trimdesktop);
+ g_free(definition_file);
+ return FALSE;
+ }
+
+ /* Actually blacklist this thing */
+ g_hash_table_insert(blacklist, trimdesktop, definition_file);
+ g_debug("Adding Blacklist item '%s' for desktop '%s'", definition_file, trimdesktop);
+
+ /* Go through and eclipse folks */
+ GList * launcher;
+ for (launcher = launcherList; launcher != NULL; launcher = launcher->next) {
+ launcherList_t * item = (launcherList_t *)launcher->data;
+ if (!g_strcmp0(trimdesktop, launcher_menu_item_get_desktop(item->menuitem))) {
+ launcher_menu_item_set_eclipsed(item->menuitem, TRUE);
+ }
+ }
+
+ return FALSE;
+}
+
+/* Remove a black list item based on the definition file
+ and uneclipse those launchers blocked by it. */
+static gboolean
+blacklist_remove (gpointer data)
+{
+ gchar * definition_file = (gchar *)data;
+ g_debug("Removing: %s", definition_file);
+
+ GHashTableIter iter;
+ gpointer key, value;
+ gboolean found = FALSE;
+
+ g_hash_table_iter_init(&iter, blacklist);
+ while (g_hash_table_iter_next(&iter, &key, &value)) {
+ if (!g_strcmp0((gchar *)value, definition_file)) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ g_debug("\tNot found!");
+ return FALSE;
+ }
+
+ GList * launcheritem;
+ for (launcheritem = launcherList; launcheritem != NULL; launcheritem = launcheritem->next) {
+ launcherList_t * li = (launcherList_t *)launcheritem->data;
+ if (!g_strcmp0(launcher_menu_item_get_desktop(li->menuitem), (gchar *)key)) {
+ GList * serveritem;
+ for (serveritem = serverList; serveritem != NULL; serveritem = serveritem->next) {
+ serverList_t * si = (serverList_t *)serveritem->data;
+ if (!g_strcmp0(app_menu_item_get_desktop(si->menuitem), (gchar *)key)) {
+ break;
+ }
+ }
+ if (serveritem == NULL) {
+ launcher_menu_item_set_eclipsed(li->menuitem, FALSE);
+ }
+ }
+ }
+
+ if (!g_hash_table_remove(blacklist, key)) {
+ g_warning("Unable to remove '%s' with value '%s'", definition_file, (gchar *)key);
+ }
+
+ return FALSE;
+}
+
+/* Check to see if a particular desktop file is
+ in the blacklist. */
+static gboolean
+blacklist_check (const gchar * desktop_file)
+{
+ g_debug("Checking blacklist for: %s", desktop_file);
+ if (blacklist == NULL) return FALSE;
+
+ if (g_hash_table_lookup(blacklist, desktop_file)) {
+ g_debug("\tFound!");
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* A callback everytime the blacklist directory changes
+ in some way. It needs to handle that. */
+static void
+blacklist_dir_changed (GFileMonitor * monitor, GFile * file, GFile * other_file, GFileMonitorEvent event_type, gpointer user_data)
+{
+ g_debug("Blacklist directory changed!");
+
+ switch (event_type) {
+ case G_FILE_MONITOR_EVENT_DELETED: {
+ gchar * path = g_file_get_path(file);
+ g_debug("\tDelete: %s", path);
+ g_idle_add(blacklist_remove, path);
+ break;
+ }
+ case G_FILE_MONITOR_EVENT_CREATED: {
+ gchar * path = g_file_get_path(file);
+ g_debug("\tCreate: %s", path);
+ g_idle_add(blacklist_add, path);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return;
+}
+
+/*
+ * More code
+ */
+
static void
server_added (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data)
{
@@ -521,6 +737,32 @@ indicator_removed (IndicateListener * listener, IndicateListenerServer * server,
return;
}
+static void
+app_dir_changed (GFileMonitor * monitor, GFile * file, GFile * other_file, GFileMonitorEvent event_type, gpointer user_data)
+{
+ gchar * directory = (gchar *)user_data;
+ g_debug("Application directory changed: %s", directory);
+
+ switch (event_type) {
+ case G_FILE_MONITOR_EVENT_DELETED: {
+ gchar * path = g_file_get_path(file);
+ g_debug("\tDelete: %s", path);
+ g_idle_add(destroy_launcher, path);
+ break;
+ }
+ case G_FILE_MONITOR_EVENT_CREATED: {
+ gchar * path = g_file_get_path(file);
+ g_debug("\tCreate: %s", path);
+ g_idle_add(build_launcher, path);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return;
+}
+
/* Check to see if a new desktop file causes
any of the launchers to be eclipsed by a running
process */
@@ -555,6 +797,8 @@ remove_eclipses (AppMenuItem * ai)
const gchar * aidesktop = app_menu_item_get_desktop(ai);
if (aidesktop == NULL) return;
+ if (blacklist_check(aidesktop)) return;
+
GList * llitem;
for (llitem = launcherList; llitem != NULL; llitem = llitem->next) {
launcherList_t * ll = (launcherList_t *)llitem->data;
@@ -569,6 +813,62 @@ remove_eclipses (AppMenuItem * ai)
return;
}
+/* Remove a launcher from the system. We need to figure
+ out what it's up to! */
+static gboolean
+destroy_launcher (gpointer data)
+{
+ gchar * appdirentry = (gchar *)data;
+
+ GList * listitem;
+ GList * direntry;
+ launcherList_t * li;
+ gchar * appdir;
+
+ for (listitem = launcherList; listitem != NULL; listitem = listitem->next) {
+ li = (launcherList_t *)listitem->data;
+ for (direntry = li->appdiritems; direntry != NULL; direntry = direntry->next) {
+ appdir = (gchar *)direntry->data;
+ if (!g_strcmp0(appdir, appdirentry)) {
+ break;
+ }
+ }
+
+ if (direntry != NULL) {
+ break;
+ }
+ }
+
+ if (listitem == NULL) {
+ g_warning("Removed '%s' by the way of it not seeming to exist anywhere.", appdirentry);
+ return FALSE;
+ }
+
+ if (g_list_length(li->appdiritems) > 1) {
+ /* Just remove this item, and we can move on */
+ g_debug("Just removing file entry: %s", appdir);
+ li->appdiritems = g_list_remove(li->appdiritems, appdir);
+ g_free(appdir);
+ return FALSE;
+ }
+
+ /* Full Destroy */
+ g_free(appdir);
+ g_list_free(li->appdiritems);
+
+ if (li->menuitem != NULL) {
+ dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(li->menuitem), "visible", "false");
+ dbusmenu_menuitem_child_delete(root_menuitem, DBUSMENU_MENUITEM(li->menuitem));
+ g_object_unref(G_OBJECT(li->menuitem));
+ li->menuitem = NULL;
+ }
+
+ launcherList = g_list_remove(launcherList, li);
+ g_free(li);
+
+ return FALSE;
+}
+
/* This function turns a specific file into a menu
item and registers it appropriately with everyone */
static gboolean
@@ -580,7 +880,6 @@ build_launcher (gpointer data)
gchar * desktop = NULL;
g_file_get_contents(path, &desktop, NULL, NULL);
- g_free(path);
if (desktop == NULL) {
return FALSE;
@@ -590,17 +889,38 @@ build_launcher (gpointer data)
g_free(desktop);
g_debug("\tcontents: %s", trimdesktop);
- /* Build the item */
- launcherList_t * ll = g_new0(launcherList_t, 1);
- ll->menuitem = launcher_menu_item_new(trimdesktop);
- g_free(trimdesktop);
+ /* Check to see if we already have a launcher */
+ GList * listitem;
+ for (listitem = launcherList; listitem != NULL; listitem = listitem->next) {
+ launcherList_t * li = (launcherList_t *)listitem->data;
+ if (!g_strcmp0(launcher_menu_item_get_desktop(li->menuitem), trimdesktop)) {
+ break;
+ }
+ }
- /* Add it to the list */
- launcherList = g_list_insert_sorted(launcherList, ll, launcherList_sort);
+ if (listitem == NULL) {
+ /* If not */
+ /* Build the item */
+ launcherList_t * ll = g_new0(launcherList_t, 1);
+ ll->menuitem = launcher_menu_item_new(trimdesktop);
+ g_free(trimdesktop);
+ ll->appdiritems = g_list_append(NULL, path);
- /* Add it to the menu */
- dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(ll->menuitem));
- resort_menu(root_menuitem);
+ /* Add it to the list */
+ launcherList = g_list_insert_sorted(launcherList, ll, launcherList_sort);
+
+ /* Add it to the menu */
+ dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(ll->menuitem));
+ resort_menu(root_menuitem);
+
+ if (blacklist_check(launcher_menu_item_get_desktop(ll->menuitem))) {
+ launcher_menu_item_set_eclipsed(ll->menuitem, TRUE);
+ }
+ } else {
+ /* If so add ourselves */
+ launcherList_t * ll = (launcherList_t *)listitem->data;
+ ll->appdiritems = g_list_append(ll->appdiritems, path);
+ }
return FALSE;
}
@@ -612,12 +932,20 @@ build_launcher (gpointer data)
static gboolean
build_launchers (gpointer data)
{
- if (!g_file_test(SYSTEM_APPS_DIR, G_FILE_TEST_IS_DIR)) {
+ gchar * directory = (gchar *)data;
+
+ if (!g_file_test(directory, G_FILE_TEST_IS_DIR)) {
return FALSE;
}
+ GFile * filedir = g_file_new_for_path(directory);
+ GFileMonitor * dirmon = g_file_monitor_directory(filedir, G_FILE_MONITOR_NONE, NULL, NULL);
+ if (dirmon != NULL) {
+ g_signal_connect(G_OBJECT(dirmon), "changed", G_CALLBACK(app_dir_changed), directory);
+ }
+
GError * error = NULL;
- GDir * dir = g_dir_open(SYSTEM_APPS_DIR, 0, &error);
+ GDir * dir = g_dir_open(directory, 0, &error);
if (dir == NULL) {
g_warning("Unable to open system apps directory: %s", error->message);
g_error_free(error);
@@ -627,7 +955,7 @@ build_launchers (gpointer data)
const gchar * filename = NULL;
while ((filename = g_dir_read_name(dir)) != NULL) {
g_debug("Found file: %s", filename);
- gchar * path = g_build_filename(SYSTEM_APPS_DIR, filename, NULL);
+ gchar * path = g_build_filename(directory, filename, NULL);
g_idle_add(build_launcher, path);
}
@@ -670,10 +998,15 @@ main (int argc, char ** argv)
g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_SERVER_ADDED, G_CALLBACK(server_added), root_menuitem);
g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_SERVER_REMOVED, G_CALLBACK(server_removed), root_menuitem);
- g_idle_add(build_launchers, NULL);
+ g_idle_add(blacklist_init, NULL);
+ g_idle_add(build_launchers, SYSTEM_APPS_DIR);
+ gchar * userdir = g_build_filename(g_get_user_config_dir(), USER_APPS_DIR, NULL);
+ g_idle_add(build_launchers, userdir);
mainloop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(mainloop);
+ g_free(userdir);
+
return 0;
}