aboutsummaryrefslogtreecommitdiff
path: root/src/indicator-messages.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/indicator-messages.c')
-rw-r--r--src/indicator-messages.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/src/indicator-messages.c b/src/indicator-messages.c
index c410ef7..a3f22aa 100644
--- a/src/indicator-messages.c
+++ b/src/indicator-messages.c
@@ -24,6 +24,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <glib.h>
#include <gtk/gtk.h>
#include <libdbusmenu-gtk/menu.h>
+#include <libdbusmenu-gtk/menuitem.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-bindings.h>
@@ -41,6 +42,8 @@ static GtkIconSize design_team_size;
static DBusGProxy * icon_proxy = NULL;
+static GtkSizeGroup * indicator_right_group = NULL;
+
static void
attention_changed_cb (DBusGProxy * proxy, gboolean dot, gpointer userdata)
{
@@ -137,6 +140,91 @@ setup_icon_proxy (gpointer userdata)
return FALSE;
}
+typedef struct _indicator_item_t indicator_item_t;
+struct _indicator_item_t {
+ GtkWidget * icon;
+ GtkWidget * label;
+ GtkWidget * right;
+};
+
+/* Whenever we have a property change on a DbusmenuMenuitem
+ we need to be responsive to that. */
+static void
+indicator_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, gchar * value, indicator_item_t * mi_data)
+{
+ if (!g_strcmp0(prop, INDICATOR_MENUITEM_PROP_LABEL)) {
+ /* Set the main label */
+ gtk_label_set_text(GTK_LABEL(mi_data->label), value);
+ } else if (!g_strcmp0(prop, INDICATOR_MENUITEM_PROP_RIGHT)) {
+ /* Set the right label */
+ gtk_label_set_text(GTK_LABEL(mi_data->right), value);
+ } else if (!g_strcmp0(prop, INDICATOR_MENUITEM_PROP_ICON)) {
+ /* We don't use the value here, which is probably less efficient,
+ but it's easier to use the easy function. And since th value
+ is already cached, shouldn't be a big deal really. */
+ GdkPixbuf * pixbuf = dbusmenu_menuitem_property_get_image(mi, INDICATOR_MENUITEM_PROP_ICON);
+ if (pixbuf != NULL) {
+ gtk_image_set_from_pixbuf(GTK_IMAGE(mi_data->icon), pixbuf);
+ }
+ } else {
+ g_warning("Indicator Item property '%s' unknown", prop);
+ }
+
+ return;
+}
+
+/* We have a small little menuitem type that handles all
+ of the fun stuff for indicators. Mostly this is the
+ shifting over and putting the icon in with some right
+ side text that'll be determined by the service. */
+static gboolean
+new_indicator_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
+{
+ indicator_item_t * mi_data = g_new0(indicator_item_t, 1);
+
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
+ g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
+ /* Note: not checking parent, it's reasonable for it to be NULL */
+
+ GtkMenuItem * gmi = GTK_MENU_ITEM(gtk_menu_item_new());
+
+ GtkWidget * hbox = gtk_hbox_new(FALSE, 4);
+
+ /* Icon, probably someone's face or avatar on an IM */
+ mi_data->icon = gtk_image_new();
+ GdkPixbuf * pixbuf = dbusmenu_menuitem_property_get_image(newitem, INDICATOR_MENUITEM_PROP_ICON);
+ if (pixbuf != NULL) {
+ gtk_image_set_from_pixbuf(GTK_IMAGE(mi_data->icon), pixbuf);
+ }
+ gtk_misc_set_alignment(GTK_MISC(mi_data->icon), 0.0, 0.5);
+ gtk_box_pack_start(GTK_BOX(hbox), mi_data->icon, FALSE, FALSE, 0);
+ gtk_widget_show(mi_data->icon);
+
+ /* Label, probably a username, chat room or mailbox name */
+ mi_data->label = gtk_label_new(dbusmenu_menuitem_property_get(newitem, INDICATOR_MENUITEM_PROP_LABEL));
+ gtk_misc_set_alignment(GTK_MISC(mi_data->label), 0.0, 0.5);
+ gtk_box_pack_start(GTK_BOX(hbox), mi_data->label, TRUE, TRUE, 0);
+ gtk_widget_show(mi_data->label);
+
+ /* Usually either the time or the count on the individual
+ item. */
+ mi_data->right = gtk_label_new(dbusmenu_menuitem_property_get(newitem, INDICATOR_MENUITEM_PROP_RIGHT));
+ gtk_size_group_add_widget(indicator_right_group, mi_data->right);
+ gtk_misc_set_alignment(GTK_MISC(mi_data->right), 1.0, 0.5);
+ gtk_box_pack_start(GTK_BOX(hbox), mi_data->right, FALSE, FALSE, 0);
+ gtk_widget_show(mi_data->right);
+
+ gtk_container_add(GTK_CONTAINER(gmi), hbox);
+ gtk_widget_show(hbox);
+
+ dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent);
+
+ g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(indicator_prop_change_cb), mi_data);
+ g_signal_connect(G_OBJECT(newitem), "destroyed", G_CALLBACK(g_free), mi_data);
+
+ return TRUE;
+}
+
static gboolean
new_launcher_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
{
@@ -207,12 +295,15 @@ get_menu (void)
return NULL;
}
+ indicator_right_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+
g_idle_add(setup_icon_proxy, NULL);
DbusmenuGtkMenu * menu = dbusmenu_gtkmenu_new(INDICATOR_MESSAGES_DBUS_NAME, INDICATOR_MESSAGES_DBUS_OBJECT);
DbusmenuGtkClient * client = dbusmenu_gtkmenu_get_client(menu);
dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), LAUNCHER_MENUITEM_TYPE, new_launcher_item);
+ dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), INDICATOR_MENUITEM_TYPE, new_indicator_item);
return GTK_MENU(menu);
}