aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Gould <ted@canonical.com>2009-08-22 13:02:21 -0500
committerTed Gould <ted@canonical.com>2009-08-22 13:02:21 -0500
commitb0b6d92b05c7a49368ba500c37bb0fe4d4f039cc (patch)
tree361a7d3d76c584d2dc9bb052da4e7d85fd250d5d
parent34d5ad139068779a39a78eec6d906c75c1687916 (diff)
parentacf054710bea98ee0a63c72cf5e5bcbff8b9bc74 (diff)
downloadayatana-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.ac2
-rw-r--r--debian/changelog6
-rw-r--r--src/Makefile.am23
-rw-r--r--src/app-menu-item.c27
-rw-r--r--src/app-menu-item.h1
-rw-r--r--src/dirs.h3
-rw-r--r--src/launcher-menu-item.c196
-rw-r--r--src/launcher-menu-item.h64
-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;
}