diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 31 | ||||
-rw-r--r-- | src/dbus-data.h | 7 | ||||
-rw-r--r-- | src/indicator-messages.c | 105 | ||||
-rw-r--r-- | src/launcher-menu-item.c | 14 | ||||
-rw-r--r-- | src/launcher-menu-item.h | 1 | ||||
-rw-r--r-- | src/messages-service-dbus.c | 184 | ||||
-rw-r--r-- | src/messages-service-dbus.h | 62 | ||||
-rw-r--r-- | src/messages-service.c | 57 | ||||
-rw-r--r-- | src/messages-service.xml | 25 |
9 files changed, 478 insertions, 8 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 0678537..38787a1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,7 +8,8 @@ bin_PROGRAMS = indicator-messages-service messaginglibdir = $(INDICATORDIR) messaginglib_LTLIBRARIES = libmessaging.la libmessaging_la_SOURCES = \ - indicator-messages.c\ + indicator-messages.c \ + messages-service-client.h \ dbus-data.h libmessaging_la_CFLAGS = $(APPLET_CFLAGS) -Wall -Wl,-Bsymbolic-functions -Wl,-z,defs -Wl,--as-needed -Werror libmessaging_la_LIBADD = $(APPLET_LIBS) @@ -20,6 +21,9 @@ libmessaging_la_LDFLAGS = -module -avoid-version indicator_messages_service_SOURCES = \ messages-service.c \ + messages-service-server.h \ + messages-service-dbus.c \ + messages-service-dbus.h \ im-menu-item.c \ im-menu-item.h \ app-menu-item.c \ @@ -30,3 +34,28 @@ indicator_messages_service_SOURCES = \ 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) + +messages-service-client.h: $(srcdir)/messages-service.xml + dbus-binding-tool \ + --prefix=_messages_service_client \ + --mode=glib-client \ + --output=messages-service-client.h \ + $(srcdir)/messages-service.xml + +messages-service-server.h: $(srcdir)/messages-service.xml + dbus-binding-tool \ + --prefix=_messages_service_server \ + --mode=glib-server \ + --output=messages-service-server.h \ + $(srcdir)/messages-service.xml + +BUILT_SOURCES = \ + messages-service-client.h \ + messages-service-server.h + +CLEANFILES = \ + $(BUILT_SOURCES) + +EXTRA_DIST = \ + messages-service.xml + diff --git a/src/dbus-data.h b/src/dbus-data.h index 4aeedf0..e7d4d26 100644 --- a/src/dbus-data.h +++ b/src/dbus-data.h @@ -2,7 +2,10 @@ #ifndef __DBUS_DATA_H__ #define __DBUS_DATA_H__ 1 -#define INDICATOR_MESSAGES_DBUS_NAME "com.ubuntu.indicator.messages" -#define INDICATOR_MESSAGES_DBUS_OBJECT "/com/ubuntu/indicator/messages" +#define INDICATOR_MESSAGES_DBUS_NAME "org.ayatana.indicator.messages" +#define INDICATOR_MESSAGES_DBUS_OBJECT "/org/ayatana/indicator/messages/menu" + +#define INDICATOR_MESSAGES_DBUS_SERVICE_OBJECT "/org/ayatana/indicator/messages/service" +#define INDICATOR_MESSAGES_DBUS_SERVICE_INTERFACE "org.ayatana.indicator.messages.service" #endif /* __DBUS_DATA_H__ */ diff --git a/src/indicator-messages.c b/src/indicator-messages.c index efb52b2..0d2854b 100644 --- a/src/indicator-messages.c +++ b/src/indicator-messages.c @@ -31,12 +31,111 @@ INDICATOR_SET_VERSION INDICATOR_SET_NAME("messages") #include "dbus-data.h" +#include "messages-service-client.h" -static GtkWidget * main_image; +static GtkWidget * main_image = NULL; #define DESIGN_TEAM_SIZE design_team_size static GtkIconSize design_team_size; +static DBusGProxy * icon_proxy = NULL; + +static void +attention_changed_cb (DBusGProxy * proxy, gboolean dot, gpointer userdata) +{ + if (dot) { + gtk_image_set_from_icon_name(GTK_IMAGE(main_image), "indicator-messages-new", DESIGN_TEAM_SIZE); + } else { + gtk_image_set_from_icon_name(GTK_IMAGE(main_image), "indicator-messages", DESIGN_TEAM_SIZE); + } + return; +} + +static void +icon_changed_cb (DBusGProxy * proxy, gboolean hidden, gpointer userdata) +{ + if (hidden) { + gtk_widget_hide(main_image); + } else { + gtk_widget_show(main_image); + } + return; +} + +static void +watch_cb (DBusGProxy * proxy, GError * error, gpointer userdata) +{ + if (error != NULL) { + g_warning("Watch failed! %s", error->message); + g_error_free(error); + } + return; +} + +static void +attention_cb (DBusGProxy * proxy, gboolean dot, GError * error, gpointer userdata) +{ + if (error != NULL) { + g_warning("Unable to get attention status: %s", error->message); + g_error_free(error); + return; + } + + return attention_changed_cb(proxy, dot, userdata); +} + +static void +icon_cb (DBusGProxy * proxy, gboolean hidden, GError * error, gpointer userdata) +{ + if (error != NULL) { + g_warning("Unable to get icon visibility: %s", error->message); + g_error_free(error); + return; + } + + return icon_changed_cb(proxy, hidden, userdata); +} + +static gboolean +setup_icon_proxy (gpointer userdata) +{ + DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); + if (connection == NULL) { + g_warning("Unable to get session bus"); + return FALSE; /* TRUE? */ + } + + icon_proxy = dbus_g_proxy_new_for_name(connection, + INDICATOR_MESSAGES_DBUS_NAME, + INDICATOR_MESSAGES_DBUS_SERVICE_OBJECT, + INDICATOR_MESSAGES_DBUS_SERVICE_INTERFACE); + if (icon_proxy == NULL) { + g_warning("Unable to get messages service interface."); + return FALSE; + } + + org_ayatana_indicator_messages_service_watch_async(icon_proxy, watch_cb, NULL); + + dbus_g_proxy_add_signal(icon_proxy, "AttentionChanged", G_TYPE_BOOLEAN, G_TYPE_INVALID); + dbus_g_proxy_connect_signal(icon_proxy, + "AttentionChanged", + G_CALLBACK(attention_changed_cb), + NULL, + NULL); + + dbus_g_proxy_add_signal(icon_proxy, "IconChanged", G_TYPE_BOOLEAN, G_TYPE_INVALID); + dbus_g_proxy_connect_signal(icon_proxy, + "IconChanged", + G_CALLBACK(icon_changed_cb), + NULL, + NULL); + + org_ayatana_indicator_messages_service_attention_requested_async(icon_proxy, attention_cb, NULL); + org_ayatana_indicator_messages_service_icon_shown_async(icon_proxy, icon_cb, NULL); + + return FALSE; +} + GtkLabel * get_label (void) { @@ -51,8 +150,6 @@ get_icon (void) main_image = gtk_image_new_from_icon_name("indicator-messages", DESIGN_TEAM_SIZE); gtk_widget_show(main_image); - /* Need a proxy here to figure out when the icon changes */ - return GTK_IMAGE(main_image); } @@ -76,6 +173,8 @@ get_menu (void) return NULL; } + g_idle_add(setup_icon_proxy, NULL); + return GTK_MENU(dbusmenu_gtkmenu_new(INDICATOR_MESSAGES_DBUS_NAME, INDICATOR_MESSAGES_DBUS_OBJECT)); } diff --git a/src/launcher-menu-item.c b/src/launcher-menu-item.c index 6c79adb..802575f 100644 --- a/src/launcher-menu-item.c +++ b/src/launcher-menu-item.c @@ -194,3 +194,17 @@ launcher_menu_item_set_eclipsed (LauncherMenuItem * li, gboolean eclipsed) dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(li), "show", eclipsed ? "false" : "true"); return; } + +gboolean +launcher_menu_item_get_eclipsed (LauncherMenuItem * li) +{ + const gchar * show = dbusmenu_menuitem_property_get(DBUSMENU_MENUITEM(li), "show"); + if (show == NULL) { + return FALSE; + } + g_debug("Launcher check eclipse: %s", show); + if (!g_strcmp0(show, "false")) { + return TRUE; + } + return FALSE; +} diff --git a/src/launcher-menu-item.h b/src/launcher-menu-item.h index 2b39073..920194e 100644 --- a/src/launcher-menu-item.h +++ b/src/launcher-menu-item.h @@ -57,6 +57,7 @@ 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); +gboolean launcher_menu_item_get_eclipsed (LauncherMenuItem * li); G_END_DECLS diff --git a/src/messages-service-dbus.c b/src/messages-service-dbus.c new file mode 100644 index 0000000..d9c0e8d --- /dev/null +++ b/src/messages-service-dbus.c @@ -0,0 +1,184 @@ +/* +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 <dbus/dbus-glib.h> +#include "messages-service-dbus.h" +#include "dbus-data.h" + +enum { + ATTENTION_CHANGED, + ICON_CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +typedef struct _MessageServiceDbusPrivate MessageServiceDbusPrivate; + +struct _MessageServiceDbusPrivate +{ + gboolean dot; + gboolean hidden; +}; + +#define MESSAGE_SERVICE_DBUS_GET_PRIVATE(o) \ +(G_TYPE_INSTANCE_GET_PRIVATE ((o), MESSAGE_SERVICE_DBUS_TYPE, MessageServiceDbusPrivate)) + +static void message_service_dbus_class_init (MessageServiceDbusClass *klass); +static void message_service_dbus_init (MessageServiceDbus *self); +static void message_service_dbus_dispose (GObject *object); +static void message_service_dbus_finalize (GObject *object); + +static void _messages_service_server_watch (void); +static gboolean _messages_service_server_attention_requested (MessageServiceDbus * self, gboolean * dot, GError ** error); +static gboolean _messages_service_server_icon_shown (MessageServiceDbus * self, gboolean * hidden, GError ** error); + +#include "messages-service-server.h" + +G_DEFINE_TYPE (MessageServiceDbus, message_service_dbus, G_TYPE_OBJECT); + +static void +message_service_dbus_class_init (MessageServiceDbusClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (MessageServiceDbusPrivate)); + + object_class->dispose = message_service_dbus_dispose; + object_class->finalize = message_service_dbus_finalize; + + signals[ATTENTION_CHANGED] = g_signal_new(MESSAGE_SERVICE_DBUS_SIGNAL_ATTENTION_CHANGED, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MessageServiceDbusClass, attention_changed), + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + + signals[ICON_CHANGED] = g_signal_new(MESSAGE_SERVICE_DBUS_SIGNAL_ICON_CHANGED, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MessageServiceDbusClass, icon_changed), + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + + + dbus_g_object_type_install_info(MESSAGE_SERVICE_DBUS_TYPE, &dbus_glib__messages_service_server_object_info); + + return; +} + +static void +message_service_dbus_init (MessageServiceDbus *self) +{ + DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); + dbus_g_connection_register_g_object(connection, + INDICATOR_MESSAGES_DBUS_SERVICE_OBJECT, + G_OBJECT(self)); + + MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(self); + + priv->dot = FALSE; + priv->hidden = FALSE; + + return; +} + +static void +message_service_dbus_dispose (GObject *object) +{ + + + G_OBJECT_CLASS (message_service_dbus_parent_class)->dispose (object); + return; +} + +static void +message_service_dbus_finalize (GObject *object) +{ + + + G_OBJECT_CLASS (message_service_dbus_parent_class)->finalize (object); + return; +} + +MessageServiceDbus * +message_service_dbus_new (void) +{ + return MESSAGE_SERVICE_DBUS(g_object_new(MESSAGE_SERVICE_DBUS_TYPE, NULL)); +} + +/* DBus function to say that someone is watching */ +static void +_messages_service_server_watch (void) +{ + +} + +/* DBus interface to request the private variable to know + whether there is a green dot. */ +static gboolean +_messages_service_server_attention_requested (MessageServiceDbus * self, gboolean * dot, GError ** error) +{ + MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(self); + *dot = priv->dot; + return TRUE; +} + +/* DBus interface to request the private variable to know + whether the icon is hidden. */ +static gboolean +_messages_service_server_icon_shown (MessageServiceDbus * self, gboolean * hidden, GError ** error) +{ + MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(self); + *hidden = priv->hidden; + return TRUE; +} + +void +message_service_dbus_set_attention (MessageServiceDbus * self, gboolean attention) +{ + MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(self); + /* Do signal */ + if (attention != priv->dot) { + priv->dot = attention; + g_signal_emit(G_OBJECT(self), signals[ATTENTION_CHANGED], 0, priv->dot, TRUE); + } + return; +} + +void +message_service_dbus_set_icon (MessageServiceDbus * self, gboolean hidden) +{ + MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(self); + /* Do signal */ + if (hidden != priv->hidden) { + priv->hidden = hidden; + g_signal_emit(G_OBJECT(self), signals[ICON_CHANGED], 0, priv->hidden, TRUE); + } + return; +} diff --git a/src/messages-service-dbus.h b/src/messages-service-dbus.h new file mode 100644 index 0000000..7a8574e --- /dev/null +++ b/src/messages-service-dbus.h @@ -0,0 +1,62 @@ +/* +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 __MESSAGE_SERVICE_DBUS_H__ +#define __MESSAGE_SERVICE_DBUS_H__ + +#include <glib.h> +#include <glib-object.h> + +G_BEGIN_DECLS + +#define MESSAGE_SERVICE_DBUS_TYPE (message_service_dbus_get_type ()) +#define MESSAGE_SERVICE_DBUS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MESSAGE_SERVICE_DBUS_TYPE, MessageServiceDbus)) +#define MESSAGE_SERVICE_DBUS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MESSAGE_SERVICE_DBUS_TYPE, MessageServiceDbusClass)) +#define IS_MESSAGE_SERVICE_DBUS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MESSAGE_SERVICE_DBUS_TYPE)) +#define IS_MESSAGE_SERVICE_DBUS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MESSAGE_SERVICE_DBUS_TYPE)) +#define MESSAGE_SERVICE_DBUS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MESSAGE_SERVICE_DBUS_TYPE, MessageServiceDbusClass)) + +#define MESSAGE_SERVICE_DBUS_SIGNAL_ATTENTION_CHANGED "attention-changed" +#define MESSAGE_SERVICE_DBUS_SIGNAL_ICON_CHANGED "icon-changed" + +typedef struct _MessageServiceDbus MessageServiceDbus; +typedef struct _MessageServiceDbusClass MessageServiceDbusClass; + +struct _MessageServiceDbusClass { + GObjectClass parent_class; + + void (*attention_changed) (gboolean dot); + void (*icon_changed) (gboolean hidden); +}; + +struct _MessageServiceDbus { + GObject parent; +}; + +GType message_service_dbus_get_type (void); +MessageServiceDbus * message_service_dbus_new (void); +void message_service_dbus_set_attention (MessageServiceDbus * self, gboolean attention); +void message_service_dbus_set_icon (MessageServiceDbus * self, gboolean hidden); + +G_END_DECLS + +#endif diff --git a/src/messages-service.c b/src/messages-service.c index e4982a2..a5af895 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -33,6 +33,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include "launcher-menu-item.h" #include "dbus-data.h" #include "dirs.h" +#include "messages-service-dbus.h" static IndicateListener * listener; static GList * serverList = NULL; @@ -41,6 +42,8 @@ static GList * launcherList = NULL; static DbusmenuMenuitem * root_menuitem = NULL; static GMainLoop * mainloop = NULL; +static MessageServiceDbus * dbus_interface = NULL; + static void server_count_changed (AppMenuItem * appitem, guint count, gpointer data); static void server_name_changed (AppMenuItem * appitem, gchar * name, gpointer data); @@ -57,6 +60,7 @@ 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); +static void check_hidden (void); /* @@ -164,6 +168,29 @@ launcherList_sort (gconstpointer a, gconstpointer b) return g_strcmp0(pan, pbn); } +static void +launcherList_count_helper (gpointer data, gpointer user_data) +{ + guint * count = (guint *)user_data; + launcherList_t * li = (launcherList_t *)data; + + if (!launcher_menu_item_get_eclipsed(li->menuitem)) { + *count = *count + 1; + } + + return; +} + +static guint +launcherList_count (void) +{ + guint count = 0; + + g_list_foreach(launcherList, launcherList_count_helper, &count); + + return count; +} + /* * Black List */ @@ -260,6 +287,8 @@ blacklist_add (gpointer udata) } } + check_hidden(); + return FALSE; } @@ -309,6 +338,8 @@ blacklist_remove (gpointer data) g_warning("Unable to remove '%s' with value '%s'", definition_file, (gchar *)key); } + check_hidden(); + return FALSE; } @@ -406,6 +437,7 @@ server_added (IndicateListener * listener, IndicateListenerServer * server, gcha /* Should be prepend ^ */ resort_menu(menushell); + check_hidden(); return; } @@ -438,7 +470,7 @@ server_count_changed (AppMenuItem * appitem, guint count, gpointer data) if (count != 0) { g_debug("Setting image to 'new'"); showing_new_icon = TRUE; - /* gtk_image_set_from_icon_name(GTK_IMAGE(main_image), "indicator-messages-new", DESIGN_TEAM_SIZE); */ + message_service_dbus_set_attention(dbus_interface, TRUE); return; } @@ -459,7 +491,7 @@ server_count_changed (AppMenuItem * appitem, guint count, gpointer data) if (!we_have_indicators) { g_debug("Setting image to boring"); showing_new_icon = FALSE; - /* gtk_image_set_from_icon_name(GTK_IMAGE(main_image), "indicator-messages", DESIGN_TEAM_SIZE); */ + message_service_dbus_set_attention(dbus_interface, FALSE); } return; @@ -508,6 +540,7 @@ server_removed (IndicateListener * listener, IndicateListenerServer * server, gc /* Simulate a server saying zero to recalculate icon */ server_count_changed(NULL, 0, NULL); + check_hidden(); return; } @@ -540,6 +573,24 @@ menushell_foreach_cb (DbusmenuMenuitem * data_mi, gpointer data_ms) { } static void +check_hidden (void) +{ + g_debug("Checking Hidden..."); + gboolean hide = FALSE; + if (launcherList_count() == 0) { + g_debug("\tZero Launchers"); + /* If we don't have visible launchers we need to look more */ + if (g_list_length(serverList) == 0) { + g_debug("\tZero Applications"); + hide = TRUE; + } + } + + message_service_dbus_set_icon(dbus_interface, hide); + return; +} + +static void resort_menu (DbusmenuMenuitem * menushell) { guint position = 0; @@ -986,6 +1037,8 @@ main (int argc, char ** argv) return 1; } + dbus_interface = message_service_dbus_new(); + listener = indicate_listener_ref_default(); serverList = NULL; diff --git a/src/messages-service.xml b/src/messages-service.xml new file mode 100644 index 0000000..f991179 --- /dev/null +++ b/src/messages-service.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<node name="/"> + <interface name="org.ayatana.indicator.messages.service"> + +<!-- Methods --> + <method name="Watch"> + <annotation name="org.freedesktop.DBus.GLib.Async" value="true" /> + </method> + <method name="AttentionRequested"> + <arg type="b" name="dot" direction="out" /> + </method> + <method name="IconShown"> + <arg type="b" name="hidden" direction="out" /> + </method> + +<!-- Signals --> + <signal name="AttentionChanged"> + <arg type="b" name="dot" direction="out" /> + </signal> + <signal name="IconChanged"> + <arg type="b" name="hidden" direction="out" /> + </signal> + + </interface> +</node> |