diff options
author | Ted Gould <ted@canonical.com> | 2009-08-22 13:02:21 -0500 |
---|---|---|
committer | Ted Gould <ted@canonical.com> | 2009-08-22 13:02:21 -0500 |
commit | b0b6d92b05c7a49368ba500c37bb0fe4d4f039cc (patch) | |
tree | 361a7d3d76c584d2dc9bb052da4e7d85fd250d5d | |
parent | 34d5ad139068779a39a78eec6d906c75c1687916 (diff) | |
parent | acf054710bea98ee0a63c72cf5e5bcbff8b9bc74 (diff) | |
download | ayatana-indicator-messages-b0b6d92b05c7a49368ba500c37bb0fe4d4f039cc.tar.gz ayatana-indicator-messages-b0b6d92b05c7a49368ba500c37bb0fe4d4f039cc.tar.bz2 ayatana-indicator-messages-b0b6d92b05c7a49368ba500c37bb0fe4d4f039cc.zip |
Updated from the dirwatch branch
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | debian/changelog | 6 | ||||
-rw-r--r-- | src/Makefile.am | 23 | ||||
-rw-r--r-- | src/app-menu-item.c | 27 | ||||
-rw-r--r-- | src/app-menu-item.h | 1 | ||||
-rw-r--r-- | src/dirs.h | 3 | ||||
-rw-r--r-- | src/launcher-menu-item.c | 196 | ||||
-rw-r--r-- | src/launcher-menu-item.h | 64 | ||||
-rw-r--r-- | src/messages-service.c (renamed from src/indicator-service.c) | 519 |
9 files changed, 832 insertions, 9 deletions
diff --git a/configure.ac b/configure.ac index 9093512..19a549c 100644 --- a/configure.ac +++ b/configure.ac @@ -17,6 +17,8 @@ AC_PROG_LIBTOOL AC_SUBST(VERSION) AC_CONFIG_MACRO_DIR([m4]) +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) + ########################### # Dependencies ########################### diff --git a/debian/changelog b/debian/changelog index b24410d..e243fa9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +indicator-messages (0.2.0~bzr121-0ubuntu3~ppa2~dirwatch1) UNRELEASED; urgency=low + + * Updated from the dirwatch branch + + -- Ted Gould <ted@ubuntu.com> Sat, 22 Aug 2009 13:01:59 -0500 + indicator-messages (0.2.0~bzr121-0ubuntu3~ppa1) karmic; urgency=low * Fix to dereference the application menu items correctly so that diff --git a/src/Makefile.am b/src/Makefile.am index 74db2df..0678537 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,13 +1,32 @@ bin_PROGRAMS = indicator-messages-service +###################################### +# Building the messages indicator +###################################### + messaginglibdir = $(INDICATORDIR) messaginglib_LTLIBRARIES = libmessaging.la -libmessaging_la_SOURCES = indicator-messages.c im-menu-item.c im-menu-item.h app-menu-item.c app-menu-item.h +libmessaging_la_SOURCES = \ + indicator-messages.c\ + dbus-data.h libmessaging_la_CFLAGS = $(APPLET_CFLAGS) -Wall -Wl,-Bsymbolic-functions -Wl,-z,defs -Wl,--as-needed -Werror libmessaging_la_LIBADD = $(APPLET_LIBS) libmessaging_la_LDFLAGS = -module -avoid-version -indicator_messages_service_SOURCES = indicator-service.c im-menu-item.c im-menu-item.h app-menu-item.c app-menu-item.h +###################################### +# Building the messages service +###################################### + +indicator_messages_service_SOURCES = \ + messages-service.c \ + im-menu-item.c \ + im-menu-item.h \ + app-menu-item.c \ + app-menu-item.h \ + launcher-menu-item.c \ + launcher-menu-item.h \ + dirs.h \ + dbus-data.h indicator_messages_service_CFLAGS = $(APPLET_CFLAGS) -Wall -Wl,-Bsymbolic-functions -Wl,-z,defs -Wl,--as-needed -Werror indicator_messages_service_LDADD = $(APPLET_LIBS) diff --git a/src/app-menu-item.c b/src/app-menu-item.c index 2212be5..3a2c795 100644 --- a/src/app-menu-item.c +++ b/src/app-menu-item.c @@ -45,6 +45,7 @@ struct _AppMenuItemPrivate gchar * type; GAppInfo * appinfo; + gchar * desktop; guint unreadcount; gboolean count_on_label; }; @@ -105,6 +106,7 @@ app_menu_item_init (AppMenuItem *self) priv->server = NULL; priv->type = NULL; priv->appinfo = NULL; + priv->desktop = NULL; priv->unreadcount = 0; priv->count_on_label = FALSE; @@ -136,6 +138,10 @@ app_menu_item_finalize (GObject *object) g_free(priv->type); } + if (priv->desktop != NULL) { + g_free(priv->desktop); + } + if (priv->appinfo != NULL) { g_object_unref(priv->appinfo); } @@ -229,15 +235,23 @@ desktop_cb (IndicateListener * listener, IndicateListenerServer * server, gchar if (priv->appinfo != NULL) { g_object_unref(G_OBJECT(priv->appinfo)); + priv->appinfo = NULL; + } + + if (priv->desktop != NULL) { + g_free(priv->desktop); + priv->desktop = NULL; } if (value == NULL || value[0] == '\0') { return; } - + priv->appinfo = G_APP_INFO(g_desktop_app_info_new_from_filename(value)); g_return_if_fail(priv->appinfo != NULL); + priv->desktop = g_strdup(value); + update_label(self); g_signal_emit(G_OBJECT(self), signals[NAME_CHANGED], 0, app_menu_item_get_name(self), TRUE); @@ -297,6 +311,7 @@ indicator_removed_cb (IndicateListener * listener, IndicateListenerServer * serv guint app_menu_item_get_count (AppMenuItem * appitem) { + g_return_val_if_fail(IS_APP_MENU_ITEM(appitem), 0); AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(appitem); return priv->unreadcount; @@ -304,6 +319,7 @@ app_menu_item_get_count (AppMenuItem * appitem) IndicateListenerServer * app_menu_item_get_server (AppMenuItem * appitem) { + g_return_val_if_fail(IS_APP_MENU_ITEM(appitem), NULL); AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(appitem); return priv->server; @@ -312,6 +328,7 @@ app_menu_item_get_server (AppMenuItem * appitem) { const gchar * app_menu_item_get_name (AppMenuItem * appitem) { + g_return_val_if_fail(IS_APP_MENU_ITEM(appitem), NULL); AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(appitem); if (priv->appinfo == NULL) { @@ -320,3 +337,11 @@ app_menu_item_get_name (AppMenuItem * appitem) return g_app_info_get_name(priv->appinfo); } } + +const gchar * +app_menu_item_get_desktop (AppMenuItem * appitem) +{ + g_return_val_if_fail(IS_APP_MENU_ITEM(appitem), NULL); + AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(appitem); + return priv->desktop; +} diff --git a/src/app-menu-item.h b/src/app-menu-item.h index dda4765..583d50d 100644 --- a/src/app-menu-item.h +++ b/src/app-menu-item.h @@ -59,6 +59,7 @@ AppMenuItem * app_menu_item_new (IndicateListener * listener, IndicateListenerSe guint app_menu_item_get_count (AppMenuItem * appitem); IndicateListenerServer * app_menu_item_get_server (AppMenuItem * appitem); const gchar * app_menu_item_get_name (AppMenuItem * appitem); +const gchar * app_menu_item_get_desktop (AppMenuItem * appitem); G_END_DECLS diff --git a/src/dirs.h b/src/dirs.h new file mode 100644 index 0000000..a994ff5 --- /dev/null +++ b/src/dirs.h @@ -0,0 +1,3 @@ +#define SYSTEM_APPS_DIR "/etc/indicators/messages/applications" +#define USER_APPS_DIR "indicators/messages/applications" +#define USER_BLACKLIST_DIR "indicators/messages/applications-blacklist" diff --git a/src/launcher-menu-item.c b/src/launcher-menu-item.c new file mode 100644 index 0000000..6c79adb --- /dev/null +++ b/src/launcher-menu-item.c @@ -0,0 +1,196 @@ +/* +An indicator to show information that is in messaging applications +that the user is using. + +Copyright 2009 Canonical Ltd. + +Authors: + Ted Gould <ted@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gdk/gdk.h> +#include <glib/gi18n.h> +#include <gio/gdesktopappinfo.h> +#include "launcher-menu-item.h" + +enum { + NAME_CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +typedef struct _LauncherMenuItemPrivate LauncherMenuItemPrivate; +struct _LauncherMenuItemPrivate +{ + GAppInfo * appinfo; + gchar * desktop; +}; + +#define LAUNCHER_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), LAUNCHER_MENU_ITEM_TYPE, LauncherMenuItemPrivate)) + +/* Prototypes */ +static void launcher_menu_item_class_init (LauncherMenuItemClass *klass); +static void launcher_menu_item_init (LauncherMenuItem *self); +static void launcher_menu_item_dispose (GObject *object); +static void launcher_menu_item_finalize (GObject *object); +static void activate_cb (LauncherMenuItem * self, gpointer data); + + +G_DEFINE_TYPE (LauncherMenuItem, launcher_menu_item, DBUSMENU_TYPE_MENUITEM); + +static void +launcher_menu_item_class_init (LauncherMenuItemClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (LauncherMenuItemPrivate)); + + object_class->dispose = launcher_menu_item_dispose; + object_class->finalize = launcher_menu_item_finalize; + + signals[NAME_CHANGED] = g_signal_new(LAUNCHER_MENU_ITEM_SIGNAL_NAME_CHANGED, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (LauncherMenuItemClass, name_changed), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); + + return; +} + +static void +launcher_menu_item_init (LauncherMenuItem *self) +{ + g_debug("Building new Launcher Menu Item"); + LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(self); + + priv->appinfo = NULL; + priv->desktop = NULL; + + return; +} + +static void +launcher_menu_item_dispose (GObject *object) +{ + // LauncherMenuItem * self = LAUNCHER_MENU_ITEM(object); + // LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(self); + + G_OBJECT_CLASS (launcher_menu_item_parent_class)->dispose (object); +} + +static void +launcher_menu_item_finalize (GObject *object) +{ + LauncherMenuItem * self = LAUNCHER_MENU_ITEM(object); + LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(self); + + if (priv->appinfo != NULL) { + g_object_unref(priv->appinfo); + priv->appinfo = NULL; + } + + if (priv->desktop != NULL) { + g_free(priv->desktop); + priv->desktop = NULL; + } + + G_OBJECT_CLASS (launcher_menu_item_parent_class)->finalize (object); + + return; +} + +LauncherMenuItem * +launcher_menu_item_new (const gchar * desktop_file) +{ + LauncherMenuItem * self = g_object_new(LAUNCHER_MENU_ITEM_TYPE, NULL); + g_debug("\tDesktop file: %s", desktop_file); + + LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(self); + + priv->appinfo = G_APP_INFO(g_desktop_app_info_new_from_filename(desktop_file)); + priv->desktop = g_strdup(desktop_file); + + g_debug("\tName: %s", launcher_menu_item_get_name(self)); + dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), "label", launcher_menu_item_get_name(self)); + + g_signal_connect(G_OBJECT(self), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), NULL); + + return self; +} + +const gchar * +launcher_menu_item_get_name (LauncherMenuItem * appitem) +{ + LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(appitem); + + if (priv->appinfo == NULL) { + return NULL; + } else { + return g_app_info_get_name(priv->appinfo); + } +} + +/* When the menu item is clicked on it tries to launch + the application that is represented by the desktop file */ +static void +activate_cb (LauncherMenuItem * self, gpointer data) +{ + LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(self); + g_return_if_fail(priv->appinfo != NULL); + + /* This should manage the X stuff for us */ + GdkAppLaunchContext * context = gdk_app_launch_context_new(); + + /* Using the current time as we don't have the event + time as that's not sent across the bus */ + GTimeVal time; + g_get_current_time(&time); + gdk_app_launch_context_set_timestamp(context, time.tv_usec / 1000); + + GError * error = NULL; + if (!g_app_info_launch(priv->appinfo, NULL, G_APP_LAUNCH_CONTEXT(context), &error)) { + g_warning("Application failed to launch '%s' because: %s", launcher_menu_item_get_name(self), error->message); + g_error_free(error); + } + + g_object_unref(G_OBJECT(context)); + + return; +} + +const gchar * +launcher_menu_item_get_desktop (LauncherMenuItem * launchitem) +{ + g_return_val_if_fail(IS_LAUNCHER_MENU_ITEM(launchitem), NULL); + LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(launchitem); + return priv->desktop; +} + +/* Hides the menu item based on whether it is eclipsed + or not. */ +void +launcher_menu_item_set_eclipsed (LauncherMenuItem * li, gboolean eclipsed) +{ + g_debug("Laucher '%s' is %s", launcher_menu_item_get_name(li), eclipsed ? "now eclipsed" : "shown again"); + dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(li), "show", eclipsed ? "false" : "true"); + return; +} diff --git a/src/launcher-menu-item.h b/src/launcher-menu-item.h new file mode 100644 index 0000000..2b39073 --- /dev/null +++ b/src/launcher-menu-item.h @@ -0,0 +1,64 @@ +/* +An indicator to show information that is in messaging applications +that the user is using. + +Copyright 2009 Canonical Ltd. + +Authors: + Ted Gould <ted@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __LAUNCHER_MENU_ITEM_H__ +#define __LAUNCHER_MENU_ITEM_H__ + +#include <glib.h> +#include <glib-object.h> + +#include <libdbusmenu-glib/menuitem.h> + +G_BEGIN_DECLS + +#define LAUNCHER_MENU_ITEM_TYPE (launcher_menu_item_get_type ()) +#define LAUNCHER_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LAUNCHER_MENU_ITEM_TYPE, LauncherMenuItem)) +#define LAUNCHER_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), LAUNCHER_MENU_ITEM_TYPE, LauncherMenuItemClass)) +#define IS_LAUNCHER_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LAUNCHER_MENU_ITEM_TYPE)) +#define IS_LAUNCHER_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LAUNCHER_MENU_ITEM_TYPE)) +#define LAUNCHER_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), LAUNCHER_MENU_ITEM_TYPE, LauncherMenuItemClass)) + +#define LAUNCHER_MENU_ITEM_SIGNAL_NAME_CHANGED "name-changed" + +typedef struct _LauncherMenuItem LauncherMenuItem; +typedef struct _LauncherMenuItemClass LauncherMenuItemClass; + +struct _LauncherMenuItemClass { + DbusmenuMenuitemClass parent_class; + + void (* name_changed) (gchar * name); +}; + +struct _LauncherMenuItem { + DbusmenuMenuitem parent; +}; + +GType launcher_menu_item_get_type (void); +LauncherMenuItem * launcher_menu_item_new (const gchar * desktop_file); +const gchar * launcher_menu_item_get_name (LauncherMenuItem * appitem); +const gchar * launcher_menu_item_get_desktop (LauncherMenuItem * launchitem); +void launcher_menu_item_set_eclipsed (LauncherMenuItem * li, gboolean eclipsed); + +G_END_DECLS + +#endif /* __LAUNCHER_MENU_ITEM_H__ */ + diff --git a/src/indicator-service.c b/src/messages-service.c index cb7e23a..384198a 100644 --- a/src/indicator-service.c +++ b/src/messages-service.c @@ -21,17 +21,22 @@ with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <string.h> +#include <pango/pango-utils.h> #include <dbus/dbus-glib-bindings.h> #include <libindicate/listener.h> +#include <gio/gio.h> #include <libdbusmenu-glib/server.h> #include "im-menu-item.h" #include "app-menu-item.h" +#include "launcher-menu-item.h" #include "dbus-data.h" +#include "dirs.h" static IndicateListener * listener; -static GList * serverList; +static GList * serverList = NULL; +static GList * launcherList = NULL; static DbusmenuMenuitem * root_menuitem = NULL; static GMainLoop * mainloop = NULL; @@ -40,8 +45,23 @@ static GMainLoop * mainloop = NULL; static void server_count_changed (AppMenuItem * appitem, guint count, gpointer data); static void server_name_changed (AppMenuItem * appitem, gchar * name, gpointer data); static void im_time_changed (ImMenuItem * imitem, glong seconds, gpointer data); -static void reconsile_list_and_menu (GList * serverlist, DbusmenuMenuitem * menushell); +static void resort_menu (DbusmenuMenuitem * menushell); static void indicator_removed (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * type, gpointer data); +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 { @@ -78,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; @@ -116,6 +140,225 @@ 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 +launcherList_sort (gconstpointer a, gconstpointer b) +{ + launcherList_t * pa, * pb; + + pa = (launcherList_t *)a; + pb = (launcherList_t *)b; + + const gchar * pan = launcher_menu_item_get_name(pa->menuitem); + const gchar * pbn = launcher_menu_item_get_name(pb->menuitem); + + 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) { @@ -162,7 +405,7 @@ server_added (IndicateListener * listener, IndicateListenerServer * server, gcha dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(menuitem)); /* Should be prepend ^ */ - reconsile_list_and_menu(serverList, menushell); + resort_menu(menushell); return; } @@ -171,7 +414,8 @@ static void server_name_changed (AppMenuItem * appitem, gchar * name, gpointer data) { serverList = g_list_sort(serverList, serverList_sort); - reconsile_list_and_menu(serverList, DBUSMENU_MENUITEM(data)); + check_eclipses(appitem); + resort_menu(DBUSMENU_MENUITEM(data)); return; } @@ -226,7 +470,7 @@ im_time_changed (ImMenuItem * imitem, glong seconds, gpointer data) { serverList_t * sl = (serverList_t *)data; sl->imList = g_list_sort(sl->imList, imList_sort); - reconsile_list_and_menu(serverList, root_menuitem); + resort_menu(root_menuitem); return; } @@ -245,6 +489,8 @@ server_removed (IndicateListener * listener, IndicateListenerServer * server, gc serverList_t * sltp = (serverList_t *)lookup->data; + remove_eclipses(sltp->menuitem); + while (sltp->imList) { imList_t * imitem = (imList_t *)sltp->imList->data; indicator_removed(listener, server, imitem->indicator, "message", data); @@ -294,15 +540,31 @@ menushell_foreach_cb (DbusmenuMenuitem * data_mi, gpointer data_ms) { } static void -reconsile_list_and_menu (GList * serverlist, DbusmenuMenuitem * menushell) +resort_menu (DbusmenuMenuitem * menushell) { guint position = 0; GList * serverentry; + GList * launcherentry = launcherList; g_debug("Reordering Menu:"); for (serverentry = serverList; serverentry != NULL; serverentry = serverentry->next) { serverList_t * si = (serverList_t *)serverentry->data; + + if (launcherentry != NULL) { + launcherList_t * li = (launcherList_t *)launcherentry->data; + while (launcherentry != NULL && g_strcmp0(launcher_menu_item_get_name(li->menuitem), app_menu_item_get_name(si->menuitem)) < 0) { + g_debug("\tMoving launcher '%s' to position %d", launcher_menu_item_get_name(li->menuitem), position); + dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(li->menuitem), position); + + position++; + launcherentry = launcherentry->next; + if (launcherentry != NULL) { + li = (launcherList_t *)launcherentry->data; + } + } + } + if (si->menuitem != NULL) { g_debug("\tMoving app %s to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(si->server), position); dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(si->menuitem), position); @@ -321,6 +583,15 @@ reconsile_list_and_menu (GList * serverlist, DbusmenuMenuitem * menushell) } } + while (launcherentry != NULL) { + launcherList_t * li = (launcherList_t *)launcherentry->data; + g_debug("\tMoving launcher '%s' to position %d", launcher_menu_item_get_name(li->menuitem), position); + dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(li->menuitem), position); + + position++; + launcherentry = launcherentry->next; + } + return; } @@ -466,6 +737,235 @@ 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 */ +static void +check_eclipses (AppMenuItem * ai) +{ + g_debug("Checking eclipsing"); + const gchar * aidesktop = app_menu_item_get_desktop(ai); + if (aidesktop == NULL) return; + g_debug("\tApp desktop: %s", aidesktop); + + GList * llitem; + for (llitem = launcherList; llitem != NULL; llitem = llitem->next) { + launcherList_t * ll = (launcherList_t *)llitem->data; + const gchar * lidesktop = launcher_menu_item_get_desktop(ll->menuitem); + g_debug("\tLauncher desktop: %s", lidesktop); + + if (!g_strcmp0(aidesktop, lidesktop)) { + launcher_menu_item_set_eclipsed(ll->menuitem, TRUE); + break; + } + } + + return; +} + +/* Remove any eclipses that might have been caused + by this app item that is now retiring */ +static void +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; + const gchar * lidesktop = launcher_menu_item_get_desktop(ll->menuitem); + + if (!g_strcmp0(aidesktop, lidesktop)) { + launcher_menu_item_set_eclipsed(ll->menuitem, FALSE); + break; + } + } + + 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 +build_launcher (gpointer data) +{ + /* Read the file get the data */ + gchar * path = (gchar *)data; + g_debug("\tpath: %s", path); + gchar * desktop = NULL; + + g_file_get_contents(path, &desktop, NULL, NULL); + + if (desktop == NULL) { + return FALSE; + } + + gchar * trimdesktop = pango_trim_string(desktop); + g_free(desktop); + g_debug("\tcontents: %s", 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; + } + } + + 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 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; +} + +/* This function goes through all the launchers that we're + supposed to be grabbing and decides to show turn them + into menu items or not. It doens't do the work, but it + makes the decision. */ +static gboolean +build_launchers (gpointer data) +{ + 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(directory, 0, &error); + if (dir == NULL) { + g_warning("Unable to open system apps directory: %s", error->message); + g_error_free(error); + 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(directory, filename, NULL); + g_idle_add(build_launcher, path); + } + + g_dir_close(dir); + launcherList = g_list_sort(launcherList, launcherList_sort); + return FALSE; +} + +/* Oh, if you don't know what main() is for + we really shouldn't be talking. */ int main (int argc, char ** argv) { @@ -498,8 +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(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; } |