aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/app-menu-item.c474
-rw-r--r--src/app-menu-item.h17
-rw-r--r--src/dbus-data.h4
-rw-r--r--src/im-menu-item.c586
-rw-r--r--src/im-menu-item.h67
-rw-r--r--src/messages-service.c807
-rw-r--r--src/status-items.c89
-rw-r--r--src/status-items.h4
-rw-r--r--test/Makefile.am2
11 files changed, 175 insertions, 1879 deletions
diff --git a/configure.ac b/configure.ac
index 148259d..b7602a3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -41,7 +41,6 @@ AC_PROG_CXX
GTK_REQUIRED_VERSION=3.0
GIO_UNIX_REQUIRED_VERSION=2.18
PANEL_REQUIRED_VERSION=2.0.0
-INDICATE_REQUIRED_VERSION=0.6.90
INDICATOR_REQUIRED_VERSION=0.3.19
DBUSMENUGTK_REQUIRED_VERSION=0.5.90
GLIB_REQUIRED_VERSION=2.31.20
@@ -49,7 +48,6 @@ GLIB_REQUIRED_VERSION=2.31.20
PKG_CHECK_MODULES(APPLET, gtk+-3.0 >= $GTK_REQUIRED_VERSION
gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION
indicator3-0.4 >= $INDICATOR_REQUIRED_VERSION
- indicate-0.7 >= $INDICATE_REQUIRED_VERSION
dbusmenu-gtk3-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION
glib-2.0 >= $GLIB_REQUIRED_VERSION
gmodule-2.0 >= $GLIB_REQUIRED_VERSION)
diff --git a/src/Makefile.am b/src/Makefile.am
index 4fdc8a9..2527878 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -42,8 +42,6 @@ indicator_messages_service_SOURCES = \
messages-service-dbus.h \
gen-messages-service.xml.h \
gen-messages-service.xml.c \
- im-menu-item.c \
- im-menu-item.h \
app-menu-item.c \
app-menu-item.h \
dbus-data.h \
diff --git a/src/app-menu-item.c b/src/app-menu-item.c
index 48aef3e..b5d4994 100644
--- a/src/app-menu-item.c
+++ b/src/app-menu-item.c
@@ -26,17 +26,13 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <glib/gi18n.h>
#include <gio/gdesktopappinfo.h>
-#include <libdbusmenu-glib/client.h>
-#include <libdbusmenu-glib/menuitem-proxy.h>
+#include <gio/gio.h>
#include <libindicator/indicator-desktop-shortcuts.h>
#include "app-menu-item.h"
#include "dbus-data.h"
enum {
- COUNT_CHANGED,
NAME_CHANGED,
- SHORTCUT_ADDED,
- SHORTCUT_REMOVED,
LAST_SIGNAL
};
@@ -46,18 +42,13 @@ typedef struct _AppMenuItemPrivate AppMenuItemPrivate;
struct _AppMenuItemPrivate
{
- IndicateListener * listener;
- IndicateListenerServer * server;
-
- gchar * type;
GDesktopAppInfo * appinfo;
guint unreadcount;
- DbusmenuClient * client;
- DbusmenuMenuitem * root;
- GList * shortcuts;
- GList * static_shortcuts;
IndicatorDesktopShortcuts * ids;
+
+ GMenu *menu;
+ GSimpleActionGroup *static_shortcuts;
};
#define APP_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), APP_MENU_ITEM_TYPE, AppMenuItemPrivate))
@@ -66,16 +57,12 @@ struct _AppMenuItemPrivate
static void app_menu_item_class_init (AppMenuItemClass *klass);
static void app_menu_item_init (AppMenuItem *self);
static void app_menu_item_dispose (GObject *object);
-static void app_menu_item_finalize (GObject *object);
-static void activate_cb (AppMenuItem * self, guint timestamp, gpointer data);
-static void count_changed (IndicateListener * listener, IndicateListenerServer * server, guint count, gpointer data);
-static void count_cb (IndicateListener * listener, IndicateListenerServer * server, guint value, gpointer data);
-static void menu_cb (IndicateListener * listener, IndicateListenerServer * server, const gchar * menupath, gpointer data);
-static void desktop_cb (IndicateListener * listener, IndicateListenerServer * server, const gchar * value, gpointer data);
-static void update_label (AppMenuItem * self);
+static void activate_cb (GSimpleAction *action,
+ GVariant *param,
+ gpointer userdata);
/* GObject Boilerplate */
-G_DEFINE_TYPE (AppMenuItem, app_menu_item, DBUSMENU_TYPE_MENUITEM);
+G_DEFINE_TYPE (AppMenuItem, app_menu_item, G_TYPE_OBJECT);
static void
app_menu_item_class_init (AppMenuItemClass *klass)
@@ -85,15 +72,7 @@ app_menu_item_class_init (AppMenuItemClass *klass)
g_type_class_add_private (klass, sizeof (AppMenuItemPrivate));
object_class->dispose = app_menu_item_dispose;
- object_class->finalize = app_menu_item_finalize;
- signals[COUNT_CHANGED] = g_signal_new(APP_MENU_ITEM_SIGNAL_COUNT_CHANGED,
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (AppMenuItemClass, count_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__UINT,
- G_TYPE_NONE, 1, G_TYPE_UINT);
signals[NAME_CHANGED] = g_signal_new(APP_MENU_ITEM_SIGNAL_NAME_CHANGED,
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST,
@@ -101,22 +80,6 @@ app_menu_item_class_init (AppMenuItemClass *klass)
NULL, NULL,
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE, 1, G_TYPE_STRING);
- signals[SHORTCUT_ADDED] = g_signal_new(APP_MENU_ITEM_SIGNAL_SHORTCUT_ADDED,
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (AppMenuItemClass, shortcut_added),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, G_TYPE_OBJECT);
- signals[SHORTCUT_REMOVED] = g_signal_new(APP_MENU_ITEM_SIGNAL_SHORTCUT_REMOVED,
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (AppMenuItemClass, shortcut_removed),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, G_TYPE_OBJECT);
-
- return;
}
static void
@@ -125,71 +88,29 @@ app_menu_item_init (AppMenuItem *self)
g_debug("Building new App Menu Item");
AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
- priv->listener = NULL;
- priv->server = NULL;
- priv->type = NULL;
priv->appinfo = NULL;
priv->unreadcount = 0;
- priv->client = NULL;
- priv->root = NULL;
- priv->shortcuts = NULL;
- priv->static_shortcuts = NULL;
-
- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
+ priv->menu = g_menu_new ();
+ priv->static_shortcuts = g_simple_action_group_new ();
return;
}
-/* A wrapper to make the prototypes work for GFunc */
-static void
-func_unref (gpointer data, gpointer user_data)
-{
- g_signal_emit(user_data, signals[SHORTCUT_REMOVED], 0, data, TRUE);
- g_object_unref(G_OBJECT(data));
- return;
-}
-
-/* Disconnect the count_changed signal and unref the listener */
static void
app_menu_item_dispose (GObject *object)
{
AppMenuItem * self = APP_MENU_ITEM(object);
AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
- if (priv->listener != NULL) {
- g_signal_handlers_disconnect_by_func(G_OBJECT(priv->listener), count_changed, self);
- g_object_unref(priv->listener);
- priv->listener = NULL;
- }
-
- if (priv->shortcuts != NULL) {
- g_list_foreach(priv->shortcuts, func_unref, object);
- g_list_free(priv->shortcuts);
- priv->shortcuts = NULL;
- }
-
- if (priv->static_shortcuts != NULL) {
- g_list_foreach(priv->static_shortcuts, func_unref, object);
- g_list_free(priv->static_shortcuts);
- priv->static_shortcuts = NULL;
- }
+ g_clear_object (&priv->menu);
+ g_clear_object (&priv->static_shortcuts);
if (priv->ids != NULL) {
g_object_unref(priv->ids);
priv->ids = NULL;
}
- if (priv->root != NULL) {
- g_object_unref(priv->root);
- priv->root = NULL;
- }
-
- if (priv->client != NULL) {
- g_object_unref(priv->client);
- priv->client = NULL;
- }
-
if (priv->appinfo != NULL) {
g_object_unref(priv->appinfo);
priv->appinfo = NULL;
@@ -198,34 +119,14 @@ app_menu_item_dispose (GObject *object)
G_OBJECT_CLASS (app_menu_item_parent_class)->dispose (object);
}
-/* Free the memory used by our type, desktop file and application
- info structures. */
-static void
-app_menu_item_finalize (GObject *object)
-{
- AppMenuItem * self = APP_MENU_ITEM(object);
- AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
-
- if (priv->type != NULL) {
- g_free(priv->type);
- priv->type = NULL;
- }
-
- G_OBJECT_CLASS (app_menu_item_parent_class)->finalize (object);
-
- return;
-}
-
/* Respond to one of the shortcuts getting clicked on. */
static void
-nick_activate_cb (DbusmenuMenuitem * self, guint timestamp, gpointer data)
+nick_activate_cb (GSimpleAction *action,
+ GVariant *param,
+ gpointer userdata)
{
- gchar * nick = g_object_get_data(G_OBJECT(self), "ids-nick-data");
- AppMenuItem * mi = APP_MENU_ITEM(data);
-
- g_return_if_fail(nick != NULL);
- g_return_if_fail(mi != NULL);
-
+ const gchar * nick = g_action_get_name (G_ACTION (action));
+ AppMenuItem * mi = APP_MENU_ITEM (userdata);
AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(mi);
g_return_if_fail(priv->ids != NULL);
@@ -234,29 +135,24 @@ nick_activate_cb (DbusmenuMenuitem * self, guint timestamp, gpointer data)
g_warning("Unable to execute nick '%s' for desktop file '%s'",
nick, g_desktop_app_info_get_filename (priv->appinfo));
}
-
- return;
}
-
static void
app_menu_item_set_appinfo (AppMenuItem *self,
GDesktopAppInfo *appinfo)
{
AppMenuItemPrivate *priv = APP_MENU_ITEM_GET_PRIVATE (self);
+ GSimpleAction *launch;
+ GMenuItem *menuitem;
GKeyFile *keyfile;
gchar *iconstr = NULL;
+ gchar *label;
g_return_if_fail (appinfo != NULL);
g_clear_object (&priv->appinfo);
priv->appinfo = g_object_ref (appinfo);
- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(self), APPLICATION_MENUITEM_PROP_RUNNING, TRUE);
-
- update_label(self);
-
keyfile = g_key_file_new();
g_key_file_load_from_file(keyfile, g_desktop_app_info_get_filename (appinfo), G_KEY_FILE_NONE, NULL);
@@ -280,29 +176,47 @@ app_menu_item_set_appinfo (AppMenuItem *self,
iconstr = g_icon_to_string(icon);
}
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), APPLICATION_MENUITEM_PROP_ICON, iconstr);
- g_free(iconstr);
+ launch = g_simple_action_new ("launch", NULL);
+ g_signal_connect (launch, "activate", G_CALLBACK (activate_cb), self);
+ g_simple_action_group_insert (priv->static_shortcuts, G_ACTION (launch));
- g_signal_emit(G_OBJECT(self), signals[NAME_CHANGED], 0, app_menu_item_get_name(self), TRUE);
+ if (priv->unreadcount > 0)
+ label = g_strdup_printf("%s (%d)", app_menu_item_get_name (self), priv->unreadcount);
+ else
+ label = g_strdup(app_menu_item_get_name (self));
+
+ menuitem = g_menu_item_new (label, "launch");
+ g_menu_item_set_attribute (menuitem, INDICATOR_MENU_ATTRIBUTE_ICON_NAME, "s", iconstr);
+ g_menu_append_item (priv->menu, menuitem);
/* Start to build static shortcuts */
priv->ids = indicator_desktop_shortcuts_new(g_desktop_app_info_get_filename (priv->appinfo), "Messaging Menu");
const gchar ** nicks = indicator_desktop_shortcuts_get_nicks(priv->ids);
gint i;
for (i = 0; nicks[i] != NULL; i++) {
- DbusmenuMenuitem * mi = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_TYPE, APPLICATION_MENUITEM_TYPE);
- g_object_set_data(G_OBJECT(mi), "ids-nick-data", (gpointer)nicks[i]);
+ gchar *name;
+ GSimpleAction *action;
+ GMenuItem *item;
- gchar *name = indicator_desktop_shortcuts_nick_get_name(priv->ids, nicks[i]);
- dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_LABEL, name);
- g_free(name);
+ name = indicator_desktop_shortcuts_nick_get_name(priv->ids, nicks[i]);
+
+ action = g_simple_action_new (name, NULL);
+ g_signal_connect(action, "activate", G_CALLBACK (nick_activate_cb), self);
+ g_simple_action_group_insert (priv->static_shortcuts, G_ACTION (action));
- g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(nick_activate_cb), self);
+ item = g_menu_item_new (name, name);
+ g_menu_append_item (priv->menu, item);
- priv->static_shortcuts = g_list_append(priv->static_shortcuts, mi);
+ g_object_unref (item);
+ g_free(name);
}
+ g_signal_emit(G_OBJECT(self), signals[NAME_CHANGED], 0, app_menu_item_get_name(self), TRUE);
+
+ g_free(label);
+ g_free(iconstr);
+ g_object_unref (launch);
+ g_object_unref (menuitem);
g_key_file_unref(keyfile);
}
@@ -315,269 +229,19 @@ app_menu_item_new (GDesktopAppInfo *appinfo)
return self;
}
-AppMenuItem *
-app_menu_item_new_with_server (IndicateListener * listener, IndicateListenerServer * server)
-{
- AppMenuItem * self = g_object_new(APP_MENU_ITEM_TYPE, NULL);
- app_menu_item_set_server (self, listener, server);
- return self;
-}
-
-void
-app_menu_item_set_server (AppMenuItem *self,
- IndicateListener *listener,
- IndicateListenerServer *server)
-{
- AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
-
- /* only allow setting this once */
- g_return_if_fail (priv->listener == NULL && priv->server == NULL);
-
- /* Copy the listener so we can use it later */
- priv->listener = listener;
- g_object_ref(G_OBJECT(listener));
-
- /* Can not ref as not real GObject */
- priv->server = server;
-
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_TYPE, APPLICATION_MENUITEM_TYPE);
-
- /* Set up listener signals */
- g_signal_connect(G_OBJECT(listener), INDICATE_LISTENER_SIGNAL_SERVER_COUNT_CHANGED, G_CALLBACK(count_changed), self);
-
- /* Get the values we care about from the server */
- indicate_listener_server_get_desktop(listener, server, desktop_cb, self);
- indicate_listener_server_get_count(listener, server, count_cb, self);
- indicate_listener_server_get_menu(listener, server, menu_cb, self);
-
- g_signal_connect(G_OBJECT(self), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), NULL);
-
- indicate_listener_server_show_interest(listener, server, INDICATE_INTEREST_SERVER_DISPLAY);
- indicate_listener_server_show_interest(listener, server, INDICATE_INTEREST_SERVER_SIGNAL);
- indicate_listener_server_show_interest(listener, server, INDICATE_INTEREST_INDICATOR_COUNT);
- indicate_listener_server_show_interest(listener, server, INDICATE_INTEREST_INDICATOR_DISPLAY);
- indicate_listener_server_show_interest(listener, server, INDICATE_INTEREST_INDICATOR_SIGNAL);
- indicate_listener_set_server_max_indicators(listener, server, MAX_NUMBER_OF_INDICATORS);
-}
-
static void
-update_label (AppMenuItem * self)
+activate_cb (GSimpleAction *action,
+ GVariant *param,
+ gpointer userdata)
{
- AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
- const gchar * name = app_menu_item_get_name(self);
-
- if (priv->unreadcount > 0) {
- /* TRANSLATORS: This is the name of the program and the number of indicators. So it
- would read something like "Mail Client (5)" */
- gchar * label = g_strdup_printf(_("%s (%d)"), _(name), priv->unreadcount);
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), APPLICATION_MENUITEM_PROP_NAME, label);
- g_free(label);
- } else {
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), APPLICATION_MENUITEM_PROP_NAME, _(name));
- }
-
- return;
-}
-
-/* Callback to the signal that the server count
- has changed to a new value. This checks to see if
- it's actually changed and if so signals everyone and
- updates the label. */
-static void
-count_changed (IndicateListener * listener, IndicateListenerServer * server, guint count, gpointer data)
-{
- g_return_if_fail(IS_APP_MENU_ITEM(data));
- AppMenuItem * self = APP_MENU_ITEM(data);
- AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
-
- if (priv->unreadcount != count) {
- priv->unreadcount = count;
- update_label(self);
- g_signal_emit(G_OBJECT(self), signals[COUNT_CHANGED], 0, priv->unreadcount, TRUE);
- }
-
- return;
-}
-
-/* Callback for getting the count property off
- of the server. */
-static void
-count_cb (IndicateListener * listener, IndicateListenerServer * server, guint value, gpointer data)
-{
- count_changed(listener, server, value, data);
- return;
-}
-
-/* Callback for when we ask the server for the path
- to it's desktop file. We then turn it into an
- app structure and start sucking data out of it.
- Mostly the name. And the icon. */
-static void
-desktop_cb (IndicateListener * listener, IndicateListenerServer * server, const gchar * value, gpointer data)
-{
- g_return_if_fail(IS_APP_MENU_ITEM(data));
- AppMenuItem * self = APP_MENU_ITEM(data);
- GDesktopAppInfo *appinfo;
-
- if (value == NULL || value[0] == '\0') {
- return;
- }
-
- appinfo = g_desktop_app_info_new_from_filename(value);
- app_menu_item_set_appinfo (self, appinfo);
- g_object_unref (appinfo);
-}
-
-/* Relay this signal into causing a rebuild of the shortcuts
- from those above us. */
-static void
-child_added_cb (DbusmenuMenuitem * root, DbusmenuMenuitem * child, guint position, gpointer data)
-{
- g_return_if_fail(IS_APP_MENU_ITEM(data));
- AppMenuItem * self = APP_MENU_ITEM(data);
- AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
- DbusmenuMenuitemProxy * mip = dbusmenu_menuitem_proxy_new(child);
-
- priv->shortcuts = g_list_insert(priv->shortcuts, mip, position);
-
- g_signal_emit(G_OBJECT(data), signals[SHORTCUT_ADDED], 0, mip, TRUE);
- return;
-}
-
-/* Relay this signal into causing a rebuild of the shortcuts
- from those above us. */
-static void
-child_removed_cb (DbusmenuMenuitem * root, DbusmenuMenuitem * child, gpointer data)
-{
- g_return_if_fail(IS_APP_MENU_ITEM(data));
- AppMenuItem * self = APP_MENU_ITEM(data);
- AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
-
- GList * pitems = priv->shortcuts;
- while (pitems != NULL) {
- DbusmenuMenuitemProxy * mip = DBUSMENU_MENUITEM_PROXY(pitems->data);
-
- if (dbusmenu_menuitem_proxy_get_wrapped(mip) == child) {
- break;
- }
-
- pitems = g_list_next(pitems);
- }
-
- if (pitems != NULL) {
- DbusmenuMenuitemProxy * mip = DBUSMENU_MENUITEM_PROXY(pitems->data);
- priv->shortcuts = g_list_remove(priv->shortcuts, mip);
-
- g_signal_emit(G_OBJECT(data), signals[SHORTCUT_REMOVED], 0, mip, TRUE);
- g_object_unref(mip);
- }
-
- return;
-}
-
-/* Relay this signal into causing a rebuild of the shortcuts
- from those above us. */
-static void
-child_moved_cb (DbusmenuMenuitem * root, DbusmenuMenuitem * child, guint newpos, guint oldpos, gpointer data)
-{
- g_return_if_fail(IS_APP_MENU_ITEM(data));
- AppMenuItem * self = APP_MENU_ITEM(data);
- AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
-
- DbusmenuMenuitemProxy * mip = DBUSMENU_MENUITEM_PROXY(g_list_nth_data(priv->shortcuts, oldpos));
-
- if (mip != NULL) {
- if (dbusmenu_menuitem_proxy_get_wrapped(mip) != child) {
- mip = NULL;
- }
- }
-
- if (mip != NULL) {
- priv->shortcuts = g_list_remove(priv->shortcuts, mip);
- priv->shortcuts = g_list_insert(priv->shortcuts, mip, newpos);
- g_signal_emit(G_OBJECT(data), signals[SHORTCUT_ADDED], 0, NULL, TRUE);
- }
-
- return;
-}
-
-/* We've got a new root. We need to proxy it and handle it's children
- if that's a relevant thing to do. */
-static void
-root_changed (DbusmenuClient * client, DbusmenuMenuitem * newroot, gpointer data)
-{
- g_debug("Root Changed");
- AppMenuItem * self = APP_MENU_ITEM(data);
- AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
-
- if (priv->root != NULL) {
- if (dbusmenu_menuitem_get_children(DBUSMENU_MENUITEM(priv->root)) != NULL) {
- g_list_foreach(priv->shortcuts, func_unref, data);
- g_list_free(priv->shortcuts);
- priv->shortcuts = NULL;
- }
- g_object_unref(priv->root);
- priv->root = NULL;
- }
-
- /* We need to proxy the new root across to the old
- world of indicator land. */
- priv->root = newroot;
-
- if (priv->root != NULL) {
- g_object_ref(priv->root);
- g_signal_connect(G_OBJECT(priv->root), DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED, G_CALLBACK(child_added_cb), self);
- g_signal_connect(G_OBJECT(priv->root), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(child_removed_cb), self);
- g_signal_connect(G_OBJECT(priv->root), DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED, G_CALLBACK(child_moved_cb), self);
-
- /* See if we have any menuitems to worry about,
- otherwise we'll just move along. */
- GList * children = dbusmenu_menuitem_get_children(DBUSMENU_MENUITEM(priv->root));
- if (children != NULL) {
- g_debug("\tProcessing %d children", g_list_length(children));
- while (children != NULL) {
- DbusmenuMenuitemProxy * mip = dbusmenu_menuitem_proxy_new(DBUSMENU_MENUITEM(children->data));
- priv->shortcuts = g_list_append(priv->shortcuts, mip);
- g_signal_emit(G_OBJECT(self), signals[SHORTCUT_ADDED], 0, mip, TRUE);
- children = g_list_next(children);
- }
- }
- }
-
- return;
-}
-
-/* Gets the path to menuitems if there are some. Now we need to
- make them special. */
-static void
-menu_cb (IndicateListener * listener, IndicateListenerServer * server, const gchar * menupath, gpointer data)
-{
- g_debug("Got Menu: %s", menupath);
- g_return_if_fail(IS_APP_MENU_ITEM(data));
- AppMenuItem * self = APP_MENU_ITEM(data);
- AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
-
- priv->client = dbusmenu_client_new(indicate_listener_server_get_dbusname(server), menupath);
- g_signal_connect(G_OBJECT(priv->client), DBUSMENU_CLIENT_SIGNAL_ROOT_CHANGED, G_CALLBACK(root_changed), self);
+ AppMenuItem * mi = APP_MENU_ITEM (userdata);
+ AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(mi);
+ GError *error = NULL;
- DbusmenuMenuitem * root = dbusmenu_client_get_root(priv->client);
- if (root != NULL) {
- root_changed(priv->client, root, self);
+ if (!g_app_info_launch (G_APP_INFO (priv->appinfo), NULL, NULL, &error)) {
+ g_warning("Unable to execute application for desktop file '%s'",
+ g_desktop_app_info_get_filename (priv->appinfo));
}
-
- return;
-}
-
-static void
-activate_cb (AppMenuItem * self, guint timestamp, gpointer data)
-{
- AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
-
- g_return_if_fail (priv->listener != NULL && priv->server != NULL);
-
- indicate_listener_display(priv->listener, priv->server, NULL, timestamp);
-
- return;
}
guint
@@ -589,14 +253,6 @@ app_menu_item_get_count (AppMenuItem * appitem)
return priv->unreadcount;
}
-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;
-}
-
const gchar *
app_menu_item_get_name (AppMenuItem * appitem)
{
@@ -606,9 +262,6 @@ app_menu_item_get_name (AppMenuItem * appitem)
if (priv->appinfo) {
return g_app_info_get_name(G_APP_INFO(priv->appinfo));
}
- else if (priv->server) {
- return INDICATE_LISTENER_SERVER_DBUS_NAME(priv->server);
- }
return NULL;
}
@@ -623,13 +276,10 @@ app_menu_item_get_desktop (AppMenuItem * appitem)
return NULL;
}
-/* Get the dynamic items added onto the end of
- and app entry. */
-GList *
-app_menu_item_get_items (AppMenuItem * appitem)
+GMenuModel *
+app_menu_item_get_menu (AppMenuItem *appitem)
{
- g_return_val_if_fail(IS_APP_MENU_ITEM(appitem), NULL);
AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(appitem);
- return g_list_concat (g_list_copy (priv->shortcuts),
- g_list_copy (priv->static_shortcuts));
+ return G_MENU_MODEL (priv->menu);
}
+
diff --git a/src/app-menu-item.h b/src/app-menu-item.h
index 74efb6a..785a997 100644
--- a/src/app-menu-item.h
+++ b/src/app-menu-item.h
@@ -22,11 +22,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef __APP_MENU_ITEM_H__
#define __APP_MENU_ITEM_H__
-#include <glib.h>
-#include <glib-object.h>
-
-#include <libdbusmenu-glib/menuitem.h>
-#include <libindicate/listener.h>
+#include <gio/gio.h>
G_BEGIN_DECLS
@@ -46,27 +42,22 @@ typedef struct _AppMenuItem AppMenuItem;
typedef struct _AppMenuItemClass AppMenuItemClass;
struct _AppMenuItemClass {
- DbusmenuMenuitemClass parent_class;
+ GObjectClass parent_class;
void (* count_changed) (guint count);
void (* name_changed) (gchar * name);
- void (* shortcut_added) (DbusmenuMenuitem * mi);
- void (* shortcut_removed) (DbusmenuMenuitem * mi);
};
struct _AppMenuItem {
- DbusmenuMenuitem parent;
+ GObject parent;
};
GType app_menu_item_get_type (void);
AppMenuItem * app_menu_item_new (GDesktopAppInfo *appinfo);
-AppMenuItem * app_menu_item_new_with_server (IndicateListener * listener, IndicateListenerServer * server);
-void app_menu_item_set_server (AppMenuItem *self, IndicateListener *listener, IndicateListenerServer *server);
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);
-GList * app_menu_item_get_items (AppMenuItem * appitem);
+GMenuModel * app_menu_item_get_menu (AppMenuItem *appitem);
G_END_DECLS
diff --git a/src/dbus-data.h b/src/dbus-data.h
index 1e82ded..d7efd86 100644
--- a/src/dbus-data.h
+++ b/src/dbus-data.h
@@ -25,4 +25,8 @@
have a better place to put it. */
#define ICON_KEY "X-Ayatana-Messaging-Menu-Icon"
+#define INDICATOR_MENU_ATTRIBUTE_VISIBLE "indicator-visible"
+#define INDICATOR_MENU_ATTRIBUTE_ENABLED "indicator-enabled"
+#define INDICATOR_MENU_ATTRIBUTE_ICON_NAME "indicator-icon-name"
+
#endif /* __DBUS_DATA_H__ */
diff --git a/src/im-menu-item.c b/src/im-menu-item.c
deleted file mode 100644
index 7466d3e..0000000
--- a/src/im-menu-item.c
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
-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 <glib/gi18n.h>
-#include <libdbusmenu-glib/client.h>
-#include <libindicate/indicator.h>
-#include <libindicate/indicator-messages.h>
-#include <libindicate/listener.h>
-#include "im-menu-item.h"
-#include "dbus-data.h"
-
-enum {
- TIME_CHANGED,
- ATTENTION_CHANGED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-typedef struct _ImMenuItemPrivate ImMenuItemPrivate;
-
-struct _ImMenuItemPrivate
-{
- IndicateListener * listener;
- IndicateListenerServer * server;
- IndicateListenerIndicator * indicator;
-
- glong creation_seconds;
- glong seconds;
- gchar * count;
- gulong indicator_changed;
- gboolean attention;
- gboolean show;
-
- guint time_update_min;
-};
-
-#define IM_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), IM_MENU_ITEM_TYPE, ImMenuItemPrivate))
-
-/* Prototypes */
-static void im_menu_item_class_init (ImMenuItemClass *klass);
-static void im_menu_item_init (ImMenuItem *self);
-static void im_menu_item_dispose (GObject *object);
-static void im_menu_item_finalize (GObject *object);
-static void sender_cb (IndicateListener * listener,
- IndicateListenerServer * server,
- IndicateListenerIndicator * indicator,
- gchar * property,
- const gchar * propertydata,
- gpointer data);
-static void time_cb (IndicateListener * listener,
- IndicateListenerServer * server,
- IndicateListenerIndicator * indicator,
- gchar * property,
- const GTimeVal * propertydata,
- gpointer data);
-static void icon_cb (IndicateListener * listener,
- IndicateListenerServer * server,
- IndicateListenerIndicator * indicator,
- gchar * property,
- const gchar * propertydata,
- gpointer data);
-static void activate_cb (ImMenuItem * self,
- guint timestamp,
- gpointer data);
-static void indicator_modified_cb (IndicateListener * listener,
- IndicateListenerServer * server,
- IndicateListenerIndicator * indicator,
- gchar * property,
- ImMenuItem * self);
-
-G_DEFINE_TYPE (ImMenuItem, im_menu_item, DBUSMENU_TYPE_MENUITEM);
-
-static void
-im_menu_item_class_init (ImMenuItemClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (ImMenuItemPrivate));
-
- object_class->dispose = im_menu_item_dispose;
- object_class->finalize = im_menu_item_finalize;
-
- signals[TIME_CHANGED] = g_signal_new(IM_MENU_ITEM_SIGNAL_TIME_CHANGED,
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ImMenuItemClass, time_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__LONG,
- G_TYPE_NONE, 1, G_TYPE_LONG);
- signals[ATTENTION_CHANGED] = g_signal_new(IM_MENU_ITEM_SIGNAL_ATTENTION_CHANGED,
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ImMenuItemClass, attention_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__BOOLEAN,
- G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
-
- return;
-}
-
-static void
-im_menu_item_init (ImMenuItem *self)
-{
- g_debug("Building new IM Menu Item");
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- /* Set the variables to NULL, but they should be
- configured further down the line. */
- priv->listener = NULL;
- priv->server = NULL;
- priv->indicator = NULL;
-
- /* A sane default, but look below */
- priv->creation_seconds = 0;
- priv->seconds = 0;
-
- /* Set the seconds to be the time when the item was
- created incase we're not given a better time. */
- GTimeVal current_time;
- g_get_current_time(&current_time);
- priv->creation_seconds = current_time.tv_sec;
-
- return;
-}
-
-static void
-im_menu_item_dispose (GObject *object)
-{
- G_OBJECT_CLASS (im_menu_item_parent_class)->dispose (object);
-
- ImMenuItem * self = IM_MENU_ITEM(object);
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- if (priv->time_update_min != 0) {
- g_source_remove(priv->time_update_min);
- }
-
- g_signal_handler_disconnect(priv->listener, priv->indicator_changed);
- priv->indicator_changed = 0;
-
- return;
-}
-
-static void
-im_menu_item_finalize (GObject *object)
-{
- G_OBJECT_CLASS (im_menu_item_parent_class)->finalize (object);
-}
-
-/* Call back for getting icon data. It just passes it along
- to the indicator so that it can visualize it. Not our problem. */
-static void
-icon_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, const gchar * propertydata, gpointer data)
-{
- gsize len;
- guchar *icon;
- icon = g_base64_decode (propertydata, &len);
- dbusmenu_menuitem_property_set_byte_array(DBUSMENU_MENUITEM(data), INDICATOR_MENUITEM_PROP_ICON, icon, len);
- g_free (icon);
- return;
-}
-
-/* This function takes the time and turns it into the appropriate
- string to put on the right side of the menu item. Of course it
- doesn't do that if there is a count set. If there's a count then
- it gets that space. */
-static void
-update_time (ImMenuItem * self)
-{
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- /* Count has been set, so it takes priority. */
- if (priv->count != NULL) {
- return;
- }
-
- /* Seconds hasn't been set, so we just want to keep the time
- area blank. */
- if (priv->seconds == 0) {
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), INDICATOR_MENUITEM_PROP_RIGHT, "");
- return;
- }
-
- gchar * timestring = NULL;
-
- GTimeVal current_time;
- g_get_current_time(&current_time);
-
- guint elapsed_seconds = current_time.tv_sec - priv->seconds;
- guint elapsed_minutes = elapsed_seconds / 60;
-
- if (elapsed_seconds % 60 > 55) {
- /* We're using fuzzy timers, so we need fuzzy comparisons */
- elapsed_minutes += 1;
- }
-
- if (elapsed_minutes < 60) {
- /* TRANSLATORS: This string is used to represent the number of minutes
- since an IM has occured. It is in the right column
- of a menu so being brief is desirable, but one character
- is not a requirement. */
- timestring = g_strdup_printf(ngettext("%d m", "%d m", elapsed_minutes), elapsed_minutes);
- } else {
- guint elapsed_hours = elapsed_minutes / 60;
-
- if (elapsed_minutes % 60 > 55) {
- /* We're using fuzzy timers, so we need fuzzy comparisons */
- elapsed_hours += 1;
- }
-
- /* TRANSLATORS: This string is used to represent the number of hours
- since an IM has occured. It is in the right column
- of a menu so being brief is desirable, but one character
- is not a requirement. */
- timestring = g_strdup_printf(ngettext("%d h", "%d h", elapsed_hours), elapsed_hours);
- }
-
- if (timestring != NULL) {
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), INDICATOR_MENUITEM_PROP_RIGHT, timestring);
- g_free(timestring);
- }
-
- return;
-}
-
-/* This is a wrapper around update_time that matches the prototype
- needed to make this a timer callback. Silly. */
-static gboolean
-time_update_cb (gpointer data)
-{
- ImMenuItem * self = IM_MENU_ITEM(data);
-
- update_time(self);
-
- return TRUE;
-}
-
-/* Yet another time function. This one takes the time as formated as
- we get it from libindicate and turns it into the seconds that we're
- looking for. It should only be called once at the init with a new
- indicator and again when the value changes. */
-static void
-time_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, const GTimeVal * propertydata, gpointer data)
-{
- g_debug("Got Time info");
- ImMenuItem * self = IM_MENU_ITEM(data);
- if (self == NULL) {
- g_error("Menu Item callback called without a menu item");
- return;
- }
-
- if (property == NULL || g_strcmp0(property, "time")) {
- g_warning("Time callback called without being sent the time.");
- return;
- }
-
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- priv->seconds = propertydata->tv_sec;
-
- update_time(self);
-
- if (priv->time_update_min == 0) {
- priv->time_update_min = g_timeout_add_seconds(60, time_update_cb, self);
- }
-
- g_signal_emit(G_OBJECT(self), signals[TIME_CHANGED], 0, priv->seconds, TRUE);
-
- return;
-}
-
-/* Returns a newly allocated string which is 'str' with all occurences of
- * consecutive whitespace collapsed into single space character. */
-static gchar *
-collapse_whitespace (const gchar *str)
-{
- GString *result;
- gboolean in_space = FALSE;
-
- if (!str)
- return NULL;
-
- result = g_string_sized_new (strlen (str));
-
- while (*str) {
- gunichar c = g_utf8_get_char_validated (str, -1);
-
- if (c < 0)
- break;
-
- if (!g_unichar_isspace (c)) {
- g_string_append_unichar (result, c);
- in_space = FALSE;
- }
- else if (!in_space) {
- g_string_append_c (result, ' ');
- in_space = TRUE;
- }
-
- str = g_utf8_next_char (str);
- }
-
- return g_string_free (result, FALSE);
-}
-
-/* Callback from libindicate that is for getting the sender information
- on a particular indicator. */
-static void
-sender_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, const gchar * propertydata, gpointer data)
-{
- gchar *label;
-
- g_debug("Got Sender Information: %s", propertydata);
- ImMenuItem * self = IM_MENU_ITEM(data);
-
- /* Our data should be right */
- g_return_if_fail(self != NULL);
- /* We should have a property name */
- g_return_if_fail(property != NULL);
- /* The Property should be sender or name */
- g_return_if_fail(!g_strcmp0(property, "sender") || !g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_NAME));
-
- /* We might get the sender variable returning a
- null string as it doesn't exist on newer clients
- but we don't want to listen to that. */
- if (!g_strcmp0(property, "sender") && propertydata[0] == '\0') {
- return;
- }
-
- label = collapse_whitespace (propertydata);
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), INDICATOR_MENUITEM_PROP_LABEL, label);
- g_free (label);
-
- return;
-}
-
-/* Callback saying that the count is updated, we need to either put
- that on the menu item or just remove it if the count is gone. If
- that's the case we can update time. */
-static void
-count_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, const gchar * propertydata, gpointer data)
-{
- g_debug("Got Count Information");
- ImMenuItem * self = IM_MENU_ITEM(data);
-
- /* Our data should be right */
- g_return_if_fail(self != NULL);
- /* We should have a property name */
- g_return_if_fail(property != NULL);
- /* The Property should be count */
- g_return_if_fail(!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_COUNT));
-
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- if (propertydata == NULL || propertydata[0] == '\0') {
- /* The count is either being unset or it was never
- set in the first place. */
- if (priv->count != NULL) {
- g_free(priv->count);
- priv->count = NULL;
- update_time(self);
- dbusmenu_menuitem_property_set_bool (DBUSMENU_MENUITEM (self),
- INDICATOR_MENUITEM_PROP_RIGHT_IS_LOZENGE,
- FALSE);
- }
- return;
- }
-
- if (priv->count != NULL) {
- g_free(priv->count);
- }
-
- priv->count = g_strdup_printf("%s", propertydata);
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), INDICATOR_MENUITEM_PROP_RIGHT, priv->count);
- dbusmenu_menuitem_property_set_bool (DBUSMENU_MENUITEM (self),
- INDICATOR_MENUITEM_PROP_RIGHT_IS_LOZENGE,
- TRUE);
-
- return;
-}
-
-/* This is getting the attention variable that's looking at whether
- this indicator should be calling for attention or not. If we are,
- we need to signal that. */
-static void
-attention_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, GVariant * propertydata, gpointer data)
-{
- g_debug("Got Attention Information");
- ImMenuItem * self = IM_MENU_ITEM(data);
-
- /* Our data should be right */
- g_return_if_fail(self != NULL);
- /* We should have a property name */
- g_return_if_fail(property != NULL);
- /* The Property should be count */
- g_return_if_fail(!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_ATTENTION));
-
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- gboolean wantit;
- if (g_variant_is_of_type(propertydata, G_VARIANT_TYPE_BOOLEAN)) {
- wantit = g_variant_get_boolean(propertydata);
- } else if (g_variant_is_of_type(propertydata, G_VARIANT_TYPE_STRING)) {
- const gchar * propstring = g_variant_get_string(propertydata, NULL);
-
- if (propstring == NULL || propstring[0] == '\0' || !g_strcmp0(propstring, "false")) {
- wantit = FALSE;
- } else {
- wantit = TRUE;
- }
- } else {
- g_warning("Got property '%s' of an unknown type.", property);
- return;
- }
-
- if (priv->attention != wantit) {
- priv->attention = wantit;
- g_signal_emit(G_OBJECT(self), signals[ATTENTION_CHANGED], 0, wantit, TRUE);
- }
-
- return;
-}
-
-/* Callback when the item gets clicked on from the Messaging Menu */
-static void
-activate_cb (ImMenuItem * self, guint timestamp, gpointer data)
-{
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- indicate_listener_display(priv->listener, priv->server, priv->indicator, timestamp);
-}
-
-/* Callback when a property gets modified. It figures out which one
- got modified and notifies the appropriate person. */
-void
-indicator_modified_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, ImMenuItem * self)
-{
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- /* Not meant for us */
- if (INDICATE_LISTENER_INDICATOR_ID(indicator) != INDICATE_LISTENER_INDICATOR_ID(priv->indicator)) return;
- if (server != priv->server) return;
-
- /* Determine which property has been changed and request the
- value go to the appropriate callback. */
- if (!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_NAME)) {
- indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_NAME, sender_cb, self);
- } else if (!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_TIME)) {
- indicate_listener_get_property_time(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_TIME, time_cb, self);
- } else if (!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_ICON)) {
- indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_ICON, icon_cb, self);
- } else if (!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_COUNT)) {
- indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_COUNT, count_cb, self);
- } else if (!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_ATTENTION)) {
- indicate_listener_get_property_variant(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_ATTENTION, attention_cb, self);
- } else if (!g_strcmp0(property, "sender")) {
- /* This is a compatibility string with v1 and should be removed */
- g_debug("Indicator is using 'sender' property which is a v1 string.");
- indicate_listener_get_property(listener, server, indicator, "sender", sender_cb, self);
- }
-
- return;
-}
-
-ImMenuItem *
-im_menu_item_new (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator)
-{
- ImMenuItem * self = g_object_new(IM_MENU_ITEM_TYPE, NULL);
-
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- priv->listener = listener;
- priv->server = server;
- priv->indicator = indicator;
- priv->count = NULL;
- priv->time_update_min = 0;
- priv->attention = FALSE;
- priv->show = TRUE;
-
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_TYPE, INDICATOR_MENUITEM_TYPE);
-
- indicate_listener_displayed(listener, server, indicator, TRUE);
-
- indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_NAME, sender_cb, self);
- indicate_listener_get_property_time(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_TIME, time_cb, self);
- indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_ICON, icon_cb, self);
- indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_COUNT, count_cb, self);
- indicate_listener_get_property_variant(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_ATTENTION, attention_cb, self);
- indicate_listener_get_property(listener, server, indicator, "sender", sender_cb, self);
-
- g_signal_connect(G_OBJECT(self), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), NULL);
- priv->indicator_changed = g_signal_connect(G_OBJECT(listener), INDICATE_LISTENER_SIGNAL_INDICATOR_MODIFIED, G_CALLBACK(indicator_modified_cb), self);
-
- return self;
-}
-
-/* Gets the number of seconds for the creator
- of this item. */
-glong
-im_menu_item_get_seconds (ImMenuItem * menuitem)
-{
- g_return_val_if_fail(IS_IM_MENU_ITEM(menuitem), 0);
-
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(menuitem);
-
- if (priv->seconds == 0) {
- return priv->creation_seconds;
- } else {
- return priv->seconds;
- }
-}
-
-/* Gets whether or not this indicator item is
- asking for attention or not. */
-gboolean
-im_menu_item_get_attention (ImMenuItem * menuitem)
-{
- g_return_val_if_fail(IS_IM_MENU_ITEM(menuitem), FALSE);
-
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(menuitem);
- return priv->attention;
-}
-
-/* This takes care of items that need to be hidden, this is
- usually because they go over the count of allowed indicators.
- Which is more than a little bit silly. We shouldn't do that.
- But we need to enforce it to save users against bad apps. */
-void
-im_menu_item_show (ImMenuItem * menuitem, gboolean show)
-{
- g_return_if_fail(IS_IM_MENU_ITEM(menuitem));
-
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(menuitem);
-
- if (priv->show == show) {
- return;
- }
-
- priv->show = show;
- /* Tell the app what we're doing to it. If it's being
- punished it needs to know about it. */
- indicate_listener_displayed(priv->listener, priv->server, priv->indicator, priv->show);
- if (priv->attention) {
- /* If we were asking for attention we can ask for it
- again if we're being shown, otherwise no. */
- g_signal_emit(G_OBJECT(menuitem), signals[ATTENTION_CHANGED], 0, priv->show, TRUE);
- }
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE, priv->show ? "true" : "false");
-
- return;
-}
-
-/* Check to see if this item is shown. Accessor for the
- internal variable. */
-gboolean
-im_menu_item_shown (ImMenuItem * menuitem)
-{
- g_return_val_if_fail(IS_IM_MENU_ITEM(menuitem), FALSE);
-
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(menuitem);
-
- return priv->show;
-}
diff --git a/src/im-menu-item.h b/src/im-menu-item.h
deleted file mode 100644
index 4279c2e..0000000
--- a/src/im-menu-item.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-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 __IM_MENU_ITEM_H__
-#define __IM_MENU_ITEM_H__
-
-#include <glib.h>
-#include <glib-object.h>
-
-#include <libdbusmenu-glib/menuitem.h>
-#include <libindicate/listener.h>
-
-G_BEGIN_DECLS
-
-#define IM_MENU_ITEM_TYPE (im_menu_item_get_type ())
-#define IM_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IM_MENU_ITEM_TYPE, ImMenuItem))
-#define IM_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), IM_MENU_ITEM_TYPE, ImMenuItemClass))
-#define IS_IM_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IM_MENU_ITEM_TYPE))
-#define IS_IM_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IM_MENU_ITEM_TYPE))
-#define IM_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), IM_MENU_ITEM_TYPE, ImMenuItemClass))
-
-#define IM_MENU_ITEM_SIGNAL_TIME_CHANGED "time-changed"
-#define IM_MENU_ITEM_SIGNAL_ATTENTION_CHANGED "attention-changed"
-
-typedef struct _ImMenuItem ImMenuItem;
-typedef struct _ImMenuItemClass ImMenuItemClass;
-
-struct _ImMenuItemClass {
- DbusmenuMenuitemClass parent_class;
-
- void (*time_changed) (glong seconds);
- void (*attention_changed) (gboolean requestit);
-};
-
-struct _ImMenuItem {
- DbusmenuMenuitem parent;
-};
-
-GType im_menu_item_get_type (void);
-ImMenuItem * im_menu_item_new (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator);
-glong im_menu_item_get_seconds (ImMenuItem * menuitem);
-gboolean im_menu_item_get_attention (ImMenuItem * menuitem);
-void im_menu_item_show (ImMenuItem * menuitem, gboolean show);
-gboolean im_menu_item_shown (ImMenuItem * menuitem);
-
-G_END_DECLS
-
-#endif
-
diff --git a/src/messages-service.c b/src/messages-service.c
index 0934b9c..432846e 100644
--- a/src/messages-service.c
+++ b/src/messages-service.c
@@ -25,46 +25,27 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <libintl.h>
#include <config.h>
#include <pango/pango-utils.h>
-#include <libindicate/listener.h>
#include <libindicator/indicator-service.h>
#include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
#include <glib/gi18n.h>
-#include <libdbusmenu-glib/client.h>
-#include <libdbusmenu-glib/server.h>
-
-#include "im-menu-item.h"
#include "app-menu-item.h"
#include "dbus-data.h"
#include "messages-service-dbus.h"
#include "status-items.h"
static IndicatorService * service = NULL;
-static IndicateListener * listener = NULL;
static GList * serverList = NULL;
-static DbusmenuMenuitem * root_menuitem = NULL;
-static DbusmenuMenuitem * status_separator = NULL;
-static DbusmenuMenuitem * clear_attention = NULL;
+static GDBusConnection *bus;
+static GSimpleActionGroup *actions;
+static GMenu *menu;
static GSettings *settings;
static GMainLoop * mainloop = NULL;
static MessageServiceDbus * dbus_interface = NULL;
-#define DESKTOP_FILE_GROUP "Messaging Menu"
-#define DESKTOP_FILE_KEY_DESKTOP "DesktopFile"
-
-static void server_shortcut_added (AppMenuItem * appitem, DbusmenuMenuitem * mi, gpointer data);
-static void server_shortcut_removed (AppMenuItem * appitem, DbusmenuMenuitem * mi, gpointer data);
-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 resort_menu (DbusmenuMenuitem * menushell);
-static void indicator_removed (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gpointer data);
-static gboolean build_launcher (gpointer data);
-static gboolean build_launchers (gpointer data);
-
/*
* Server List
@@ -72,34 +53,13 @@ static gboolean build_launchers (gpointer data);
typedef struct _serverList_t serverList_t;
struct _serverList_t {
- IndicateListenerServer * server;
AppMenuItem * menuitem;
- DbusmenuMenuitem * separator;
gboolean attention;
guint count;
GList * imList;
};
static gint
-serverList_equal (gconstpointer a, gconstpointer b)
-{
- serverList_t * pa, * pb;
-
- pa = (serverList_t *)a;
- pb = (serverList_t *)b;
-
- const gchar * pan = INDICATE_LISTENER_SERVER_DBUS_NAME(pa->server);
- const gchar * pbn = INDICATE_LISTENER_SERVER_DBUS_NAME(pb->server);
- const gchar * pap = indicate_listener_server_get_dbuspath(pa->server);
- const gchar * pbp = indicate_listener_server_get_dbuspath(pb->server);
-
- if (g_strcmp0(pan, pbn) == 0)
- return g_strcmp0(pap, pbp);
- else
- return 1;
-}
-
-static gint
serverList_sort (gconstpointer a, gconstpointer b)
{
serverList_t * pa, * pb;
@@ -113,648 +73,7 @@ serverList_sort (gconstpointer a, gconstpointer b)
return g_strcmp0(pan, pbn);
}
-/*
- * Item List
- */
-
-typedef struct _imList_t imList_t;
-struct _imList_t {
- IndicateListenerServer * server;
- IndicateListenerIndicator * indicator;
- DbusmenuMenuitem * menuitem;
- gulong timechange_cb;
- gulong attentionchange_cb;
-};
-
-static gboolean
-imList_equal (gconstpointer a, gconstpointer b)
-{
- imList_t * pa, * pb;
-
- pa = (imList_t *)a;
- pb = (imList_t *)b;
-
- const gchar * pas = INDICATE_LISTENER_SERVER_DBUS_NAME(pa->server);
- const gchar * pbs = INDICATE_LISTENER_SERVER_DBUS_NAME(pb->server);
-
- guint pai = INDICATE_LISTENER_INDICATOR_ID(pa->indicator);
- guint pbi = INDICATE_LISTENER_INDICATOR_ID(pb->indicator);
-
- g_debug("\tComparing (%s %d) to (%s %d)", pas, pai, pbs, pbi);
-
- return !((!g_strcmp0(pas, pbs)) && (pai == pbi));
-}
-
-static gint
-imList_sort (gconstpointer a, gconstpointer b)
-{
- imList_t * pa, * pb;
-
- pa = (imList_t *)a;
- pb = (imList_t *)b;
-
- return (gint)(im_menu_item_get_seconds(IM_MENU_ITEM(pb->menuitem)) - im_menu_item_get_seconds(IM_MENU_ITEM(pa->menuitem)));
-}
-
-
-/* Goes through all the servers and sees if any of them
- want attention. If they do, then well we'll give it
- to them. If they don't, let's not bother the user
- any, shall we? */
-static void
-check_attention (void)
-{
- GList * pointer;
- for (pointer = serverList; pointer != NULL; pointer = g_list_next(pointer)) {
- serverList_t * slt = (serverList_t *)pointer->data;
- if (slt->attention) {
- message_service_dbus_set_attention(dbus_interface, TRUE);
- return;
- }
- }
- message_service_dbus_set_attention(dbus_interface, FALSE);
- return;
-}
-
-/* This checks a server listing to see if it should
- have attention. It can get attention through it's
- count or by having an indicator that is requestion
- attention. */
-static void
-server_attention (serverList_t * slt)
-{
- /* Count, easy yes and out. */
- if (slt->count > 0) {
- slt->attention = TRUE;
- return;
- }
-
- /* Check to see if any of the indicators want attention */
- GList * pointer;
- for (pointer = slt->imList; pointer != NULL; pointer = g_list_next(pointer)) {
- imList_t * ilt = (imList_t *)pointer->data;
- if (im_menu_item_get_attention(IM_MENU_ITEM(ilt->menuitem))) {
- slt->attention = TRUE;
- return;
- }
- }
-
- /* Nope, no one */
- slt->attention = FALSE;
- return;
-}
-
-static void
-desktop_cb (IndicateListener *listener,
- IndicateListenerServer *server,
- const gchar *value,
- gpointer data)
-{
- DbusmenuMenuitem * menushell = DBUSMENU_MENUITEM(data);
- GList *listitem;
- serverList_t * sl_item = NULL;
-
- /* Check to see if we already have a launcher for this app */
- for (listitem = serverList; listitem != NULL; listitem = listitem->next) {
- serverList_t * slt = listitem->data;
- if (!g_strcmp0(app_menu_item_get_desktop(slt->menuitem), value)) {
- sl_item = slt;
- break;
- }
- }
-
- if (!sl_item) {
- /* Build the Menu item */
- AppMenuItem * menuitem = app_menu_item_new_with_server (listener, server);
-
- /* Build a possible server structure */
- sl_item = g_new0(serverList_t, 1);
- sl_item->server = server;
- sl_item->menuitem = menuitem;
- sl_item->imList = NULL;
- sl_item->attention = FALSE;
- sl_item->count = 0;
-
- /* Build a separator */
- sl_item->separator = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(sl_item->separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
-
- /* Connect the signals up to the menu item */
- g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_COUNT_CHANGED, G_CALLBACK(server_count_changed), sl_item);
- g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_NAME_CHANGED, G_CALLBACK(server_name_changed), menushell);
- g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_SHORTCUT_ADDED, G_CALLBACK(server_shortcut_added), menushell);
- g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_SHORTCUT_REMOVED, G_CALLBACK(server_shortcut_removed), menushell);
-
- /* Put our new menu item in, with the separator behind it.
- resort_menu will take care of whether it should be hidden
- or not. */
- dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(menuitem));
-
- /* Incase we got an indicator first */
- GList * alreadythere = g_list_find_custom(serverList, sl_item, serverList_equal);
- if (alreadythere != NULL) {
- /* Use the one we already had */
- g_free(sl_item);
- sl_item = (serverList_t *)alreadythere->data;
- sl_item->menuitem = menuitem;
- serverList = g_list_sort(serverList, serverList_sort);
- } else {
- /* Insert the new one in the list */
- serverList = g_list_insert_sorted(serverList, sl_item, serverList_sort);
- }
-
- dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(sl_item->separator));
- }
- else {
- app_menu_item_set_server (sl_item->menuitem, listener, server);
- }
-
- GList * shortcuts = app_menu_item_get_items(sl_item->menuitem);
- GList * shortcut = shortcuts;
- while (shortcut != NULL) {
- DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(shortcut->data);
- g_debug("\tAdding shortcut: %s", dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_LABEL));
- dbusmenu_menuitem_child_append(menushell, mi);
- shortcut = g_list_next(shortcut);
- }
- g_list_free (shortcuts);
-
- resort_menu(menushell);
-}
-
-/* A new server has been created on the indicate bus.
- We need to check to see if we like it. And build
- structures for it if so. */
-static void
-server_added (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data)
-{
- g_debug("Server Added '%s' of type '%s'.", INDICATE_LISTENER_SERVER_DBUS_NAME(server), type);
- if (type == NULL) {
- return;
- }
-
- if (type[0] == '\0') {
- return;
- }
-
- if (strncmp(type, "message", strlen("message"))) {
- g_debug("\tServer type '%s' is not a message based type.", type);
- return;
- }
-
- /* fetch the desktop file before creating the menu item, in case we
- * already have a launcher for it */
- indicate_listener_server_get_desktop(listener, server, desktop_cb, data);
-}
-
-/* Server shortcut has been added */
-static void
-server_shortcut_added (AppMenuItem * appitem, DbusmenuMenuitem * mi, gpointer data)
-{
- g_debug("Application Shortcut added: %s", mi != NULL ? dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_LABEL) : "none");
- DbusmenuMenuitem * shell = DBUSMENU_MENUITEM(data);
- if (mi != NULL) {
- dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_ICON_NAME, DBUSMENU_MENUITEM_ICON_NAME_BLANK);
- dbusmenu_menuitem_child_append(shell, mi);
- }
- resort_menu(shell);
- return;
-}
-
-/* Server shortcut has been removed */
-static void
-server_shortcut_removed (AppMenuItem * appitem, DbusmenuMenuitem * mi, gpointer data)
-{
- g_debug("Application Shortcut removed: %s", mi != NULL ? dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_LABEL) : "none");
- DbusmenuMenuitem * shell = DBUSMENU_MENUITEM(data);
- dbusmenu_menuitem_child_delete(shell, mi);
- return;
-}
-
-/* The name of a server has changed, we probably
- need to reorder the menu to keep it in alphabetical
- order. This happens often after we read the destkop
- file from disk. */
-static void
-server_name_changed (AppMenuItem * appitem, gchar * name, gpointer data)
-{
- serverList = g_list_sort(serverList, serverList_sort);
- resort_menu(DBUSMENU_MENUITEM(data));
- return;
-}
-
-/* If the count on the server changes, we need to know
- whether that should be grabbing attention or not. If
- it is, we need to reevaluate whether the whole thing
- should be grabbing attention or not. */
-static void
-server_count_changed (AppMenuItem * appitem, guint count, gpointer data)
-{
- serverList_t * slt = (serverList_t *)data;
- slt->count = count;
-
- if (count == 0 && slt->attention) {
- /* Regen based on indicators if the count isn't going to cause it. */
- server_attention(slt);
- /* If we're dropping let's see if we're the last. */
- if (!slt->attention) {
- check_attention();
- }
- }
-
- if (count != 0 && !slt->attention) {
- slt->attention = TRUE;
- /* Let's tell everyone about us! */
- message_service_dbus_set_attention(dbus_interface, TRUE);
- }
-
- return;
-}
-
-/* Respond to the IM entrie's time changing
- which results in it needing to resort the list
- and rebuild the menu to match. */
-static void
-im_time_changed (ImMenuItem * imitem, glong seconds, gpointer data)
-{
- serverList_t * sl = (serverList_t *)data;
- sl->imList = g_list_sort(sl->imList, imList_sort);
- resort_menu(root_menuitem);
- return;
-}
-
-/* The IM entrie's request for attention has changed
- so we need to pass that up the stack. */
-static void
-im_attention_changed (ImMenuItem * imitem, gboolean requestit, gpointer data)
-{
- serverList_t * sl = (serverList_t *)data;
-
- if (requestit) {
- sl->attention = TRUE;
- message_service_dbus_set_attention(dbus_interface, TRUE);
- } else {
- server_attention(sl);
- if (!sl->attention) {
- check_attention();
- }
- }
-
- return;
-}
-
-/* Run when a server is removed from the indicator bus. It figures
- out if we have it somewhere, and if so then we dump it out and
- clean up all of it's entries. */
-static void
-server_removed (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data)
-{
- /* Look for the server */
- g_debug("Removing server: %s", INDICATE_LISTENER_SERVER_DBUS_NAME(server));
- serverList_t slt = {0};
- slt.server = server;
- GList * lookup = g_list_find_custom(serverList, &slt, serverList_equal);
-
- /* If we don't have it, exit */
- if (lookup == NULL) {
- g_debug("\tUnable to find server: %s", INDICATE_LISTENER_SERVER_DBUS_NAME(server));
- return;
- }
-
- serverList_t * sltp = (serverList_t *)lookup->data;
-
- /* Removing indicators from this server */
- while (sltp->imList) {
- imList_t * imitem = (imList_t *)sltp->imList->data;
- indicator_removed(listener, server, imitem->indicator, data);
- }
-
- /* Remove from the server list */
- serverList = g_list_remove(serverList, sltp);
-
- /* If there is a menu item, let's get rid of it. */
- if (sltp->menuitem != NULL) {
- /* If there are shortcuts remove them */
- GList * shortcuts = app_menu_item_get_items(sltp->menuitem);
- GList * shortcut = shortcuts;
- while (shortcut != NULL) {
- g_debug("\tRemoving shortcut: %s", dbusmenu_menuitem_property_get(DBUSMENU_MENUITEM(shortcut->data), DBUSMENU_MENUITEM_PROP_LABEL));
- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(shortcut->data), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(shortcut->data));
- shortcut = g_list_next(shortcut);
- }
- g_list_free (shortcuts);
-
- g_debug("\tRemoving item");
- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(sltp->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(sltp->menuitem));
- g_object_unref(G_OBJECT(sltp->menuitem));
- } else {
- g_debug("\tNo menuitem");
- }
-
- /* If there is a separator, let's get rid of it. */
- if (sltp->separator != NULL) {
- g_debug("\tRemoving separator");
- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(sltp->separator), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(sltp->separator));
- g_object_unref(G_OBJECT(sltp->separator));
- } else {
- g_debug("\tNo separator");
- }
-
- if (sltp->attention) {
- /* Check to see if this was the server causing the menu item to
- be lit up. */
- check_attention();
- }
-
- g_free(sltp);
-
- return;
-}
-
-typedef struct _menushell_location menushell_location_t;
-struct _menushell_location {
- const IndicateListenerServer * server;
- gint position;
- gboolean found;
-};
-
-static void
-menushell_foreach_cb (DbusmenuMenuitem * data_mi, gpointer data_ms) {
- menushell_location_t * msl = (menushell_location_t *)data_ms;
-
- if (msl->found) return;
-
- if (!IS_APP_MENU_ITEM(data_mi)) {
- msl->position++;
- return;
- }
-
- AppMenuItem * appmenu = APP_MENU_ITEM(data_mi);
- if (!g_strcmp0(INDICATE_LISTENER_SERVER_DBUS_NAME((IndicateListenerServer*)msl->server), INDICATE_LISTENER_SERVER_DBUS_NAME(app_menu_item_get_server(appmenu)))) {
- GList *shortcuts = app_menu_item_get_items(appmenu);
- msl->found = TRUE;
- /* Return a position at the end of our shortcuts */
- msl->position += g_list_length(shortcuts);
- g_list_free (shortcuts);
-
- } else {
- msl->position++;
- }
-
- return;
-}
-
-/* This function takes care of putting the menu in the right order.
- It basically it rebuilds the order by looking through all the
- applications and launchers and puts them in the right place. The
- menu functions will handle the cases where they don't move so this
- is a good way to ensure everything is right. */
-static void
-resort_menu (DbusmenuMenuitem * menushell)
-{
- guint position = 0;
- GList * serverentry;
-
- g_debug("Reordering Menu:");
-
- if (DBUSMENU_IS_MENUITEM(status_separator)) {
- position = dbusmenu_menuitem_get_position(status_separator, root_menuitem) + 1;
- g_debug("\tPriming with location of status separator: %d", position);
- }
-
- for (serverentry = serverList; serverentry != NULL; serverentry = serverentry->next) {
- serverList_t * si = (serverList_t *)serverentry->data;
-
- /* Putting the app menu item in */
- 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);
- position++;
-
- /* Inserting the shortcuts from the launcher */
- GList * shortcuts = app_menu_item_get_items(si->menuitem);
- GList * shortcut = shortcuts;
- while (shortcut != NULL) {
- g_debug("\t\tMoving shortcut to position %d", position);
- dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(shortcut->data), position);
- position++;
- shortcut = g_list_next(shortcut);
- }
- g_list_free (shortcuts);
- }
-
- /* Putting all the indicators that are related to this application
- after it. */
- GList * imentry;
- for (imentry = si->imList; imentry != NULL; imentry = imentry->next) {
- imList_t * imi = (imList_t *)imentry->data;
-
- if (imi->menuitem != NULL) {
- g_debug("\tMoving indicator on %s id %d to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(imi->server), INDICATE_LISTENER_INDICATOR_ID(imi->indicator), position);
-
- if (si->menuitem == NULL || !dbusmenu_menuitem_property_get_bool(DBUSMENU_MENUITEM(si->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE)) {
- dbusmenu_menuitem_property_set_bool(imi->menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- } else {
- dbusmenu_menuitem_property_set_bool(imi->menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
- }
-
- dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(imi->menuitem), position);
- position++;
- }
- }
-
- /* Lastly putting the separator in */
- if (si->separator != NULL) {
- g_debug("\tMoving app %s separator to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(si->server), position);
-
- if (si->menuitem == NULL || !dbusmenu_menuitem_property_get_bool(DBUSMENU_MENUITEM(si->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE)) {
- dbusmenu_menuitem_property_set_bool(si->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- /* Note, this isn't the last if we can't see it */
- } else {
- dbusmenu_menuitem_property_set_bool(si->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
- }
-
- dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(si->separator), position);
- position++;
- }
- }
-
- if (clear_attention != NULL) {
- dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), clear_attention, position);
- position++; /* Not needed, but reduce bugs on code tacked on here, compiler will remove */
- }
-
- return;
-}
-
-/* Responding to a new indicator showing up on the bus. We
- need to create a menuitem for it and start populating the
- internal structures to track it. */
-static void
-indicator_added (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gpointer data)
-{
- DbusmenuMenuitem * menushell = DBUSMENU_MENUITEM(data);
- if (menushell == NULL) {
- g_error("Data in callback is not a menushell");
- return;
- }
-
- imList_t * listItem = g_new0(imList_t, 1);
- listItem->server = server;
- listItem->indicator = indicator;
-
- /* Building the IM Menu Item which is a subclass
- of DBus Menuitem */
- ImMenuItem * menuitem = im_menu_item_new(listener, server, indicator);
- listItem->menuitem = DBUSMENU_MENUITEM(menuitem);
-
- /* Looking for a server entry to attach this indicator
- to. If we can't find one then we have to build one
- and attach the indicator to it. */
- serverList_t sl_item_local = {0};
- serverList_t * sl_item = NULL;
- sl_item_local.server = server;
- GList * serverentry = g_list_find_custom(serverList, &sl_item_local, serverList_equal);
-
- if (serverentry == NULL) {
- /* This sucks, we got an indicator before the server. I guess
- that's the joy of being asynchronous */
- sl_item = g_new0(serverList_t, 1);
- sl_item->server = server;
- sl_item->menuitem = NULL;
- sl_item->imList = NULL;
- sl_item->attention = FALSE;
- sl_item->count = 0;
- sl_item->separator = NULL;
-
- serverList = g_list_insert_sorted(serverList, sl_item, serverList_sort);
- } else {
- sl_item = (serverList_t *)serverentry->data;
- }
-
- /* Added a this entry into the IM list */
- sl_item->imList = g_list_insert_sorted(sl_item->imList, listItem, imList_sort);
- listItem->timechange_cb = g_signal_connect(G_OBJECT(menuitem), IM_MENU_ITEM_SIGNAL_TIME_CHANGED, G_CALLBACK(im_time_changed), sl_item);
- listItem->attentionchange_cb = g_signal_connect(G_OBJECT(menuitem), IM_MENU_ITEM_SIGNAL_ATTENTION_CHANGED, G_CALLBACK(im_attention_changed), sl_item);
-
- /* Check the length of the list. If we've got more inidactors
- than we allow. Well. Someone's gotta pay. Sorry. I didn't
- want to do this, but you did it to yourself. */
- if (g_list_length(sl_item->imList) > MAX_NUMBER_OF_INDICATORS) {
- GList * indicatoritem;
- gint count;
- for (indicatoritem = sl_item->imList, count = 0; indicatoritem != NULL; indicatoritem = g_list_next(indicatoritem), count++) {
- imList_t * im = (imList_t *)indicatoritem->data;
- im_menu_item_show(IM_MENU_ITEM(im->menuitem), count < MAX_NUMBER_OF_INDICATORS);
- }
- }
-
- /* Placing the item into the shell. Look to see if
- we can find our server and slip in there. Otherwise
- we'll just append. */
- menushell_location_t msl;
- msl.found = FALSE;
- msl.position = 0;
- msl.server = server;
-
- dbusmenu_menuitem_foreach(DBUSMENU_MENUITEM(menushell), menushell_foreach_cb, &msl);
- if (msl.found) {
- dbusmenu_menuitem_child_add_position(menushell, DBUSMENU_MENUITEM(menuitem), msl.position);
- } else {
- g_warning("Unable to find server menu item");
- dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(menuitem));
- resort_menu (root_menuitem);
- }
-
- return;
-}
-
-/* Process and indicator getting removed from the system. We
- first need to ensure that it's one of ours and figure out
- where we put it. When we find all that out we can go through
- the process of removing the effect it had on the system. */
-static void
-indicator_removed (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gpointer data)
-{
- g_debug("Removing %s %d", INDICATE_LISTENER_SERVER_DBUS_NAME(server), INDICATE_LISTENER_INDICATOR_ID(indicator));
-
- gboolean removed = FALSE;
-
- /* Find the server that was related to this item */
- serverList_t sl_item_local = {0};
- serverList_t * sl_item = NULL;
- sl_item_local.server = server;
- GList * serverentry = g_list_find_custom(serverList, &sl_item_local, serverList_equal);
- if (serverentry == NULL) {
- /* We didn't care about that server */
- return;
- }
- sl_item = (serverList_t *)serverentry->data;
-
- /* Look in the IM Hash Table */
- imList_t listData = {0};
- listData.server = server;
- listData.indicator = indicator;
-
- GList * listItem = g_list_find_custom(sl_item->imList, &listData, imList_equal);
- DbusmenuMenuitem * menuitem = NULL;
- imList_t * ilt = NULL;
- if (listItem != NULL) {
- ilt = (imList_t *)listItem->data;
- menuitem = ilt->menuitem;
- }
-
- /* If we found a menu item and an imList_t item then
- we can go ahead and remove it. Otherwise we can
- skip this and exit. */
- if (!removed && menuitem != NULL) {
- sl_item->imList = g_list_remove(sl_item->imList, ilt);
- g_signal_handler_disconnect(menuitem, ilt->timechange_cb);
- g_signal_handler_disconnect(menuitem, ilt->attentionchange_cb);
- g_free(ilt);
-
- if (im_menu_item_get_attention(IM_MENU_ITEM(menuitem)) && im_menu_item_shown(IM_MENU_ITEM(menuitem))) {
- /* If the removed indicator menu item was asking for
- attention we need to see if this server should still
- be asking for attention. */
- server_attention(sl_item);
- /* If the server is no longer asking for attention then
- we need to check if the whole system should be. */
- if (!sl_item->attention) {
- check_attention();
- }
- }
-
- if (im_menu_item_shown(IM_MENU_ITEM(menuitem)) && g_list_length(sl_item->imList) >= MAX_NUMBER_OF_INDICATORS) {
- /* In this case we need to show a different indicator
- becasue a shown one has left. But we're going to be
- easy and set all the values. */
- GList * indicatoritem;
- gint count;
- for (indicatoritem = sl_item->imList, count = 0; indicatoritem != NULL; indicatoritem = g_list_next(indicatoritem), count++) {
- imList_t * im = (imList_t *)indicatoritem->data;
- im_menu_item_show(IM_MENU_ITEM(im->menuitem), count < MAX_NUMBER_OF_INDICATORS);
- }
- }
-
- /* Hide the item immediately, and then remove it
- which might take a little longer. */
- dbusmenu_menuitem_property_set_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), menuitem);
- removed = TRUE;
- }
-
- if (!removed) {
- g_warning("We were asked to remove %s %d but we didn't.", INDICATE_LISTENER_SERVER_DBUS_NAME(server), INDICATE_LISTENER_INDICATOR_ID(indicator));
- }
-
- return;
-}
-
-/* This function turns a specific file into a menu
+/* This function turns a specific desktop id into a menu
item and registers it appropriately with everyone */
static gboolean
build_launcher (gpointer data)
@@ -780,26 +99,12 @@ build_launcher (gpointer data)
serverList_t * sl_item = g_new0(serverList_t, 1);
sl_item->menuitem = app_menu_item_new(appinfo);
- /* Build a separator */
- sl_item->separator = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(sl_item->separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
-
- /* Add it to the list */
serverList = g_list_insert_sorted (serverList, sl_item, serverList_sort);
- /* Add it to the menu */
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(sl_item->menuitem), DBUSMENU_MENUITEM_PROP_TYPE, APPLICATION_MENUITEM_TYPE);
- dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(sl_item->menuitem));
- GList * shortcuts = app_menu_item_get_items(sl_item->menuitem);
- GList * shortcut = shortcuts;
- while (shortcut != NULL) {
- dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(shortcut->data));
- shortcut = g_list_next(shortcut);
- }
- g_list_free (shortcuts);
- dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(sl_item->separator));
-
- resort_menu(root_menuitem);
+ /* TODO insert it at the right position (alphabetically by application name) */
+ g_menu_insert_section (menu, 2,
+ app_menu_item_get_name (sl_item->menuitem),
+ app_menu_item_get_menu (sl_item->menuitem));
}
g_object_unref (appinfo);
@@ -838,36 +143,34 @@ service_shutdown (IndicatorService * service, gpointer user_data)
return;
}
-/* Respond to changing status by updating the icon that
- is on the panel */
static void
-status_update_callback (void)
+clear_action_activate (GSimpleAction *simple,
+ GVariant *param,
+ gpointer user_data)
{
- return;
+ MessageServiceDbus *msg_service = user_data;
+ message_service_dbus_set_attention(msg_service, FALSE);
}
-/* The clear attention item has been clicked on, what to do? */
static void
-clear_attention_activate (DbusmenuMenuitem * mi, guint timestamp, MessageServiceDbus * dbus)
+clear_action_handler (MessageServiceDbus *msd,
+ gboolean attention,
+ gpointer user_data)
{
- message_service_dbus_set_attention(dbus, FALSE);
- return;
+ GSimpleAction *action = user_data;
+ g_simple_action_set_enabled (action, attention);
}
-/* Handle an update of the active state to ensure that we're
- only enabled when we could do something. */
-static void
-clear_attention_handler (MessageServiceDbus * msd, gboolean attention, DbusmenuMenuitem * clearitem)
-{
- dbusmenu_menuitem_property_set_bool(clearitem, DBUSMENU_MENUITEM_PROP_ENABLED, attention);
- return;
-}
-
-/* Oh, if you don't know what main() is for
- we really shouldn't be talking. */
int
main (int argc, char ** argv)
{
+ GError *error = NULL;
+ GActionEntry entries[] = {
+ { "status", NULL, "s", "'offline'", NULL },
+ { "clear", clear_action_activate }
+ };
+ GMenuModel *status_items;
+
/* Glib init */
g_type_init();
@@ -884,36 +187,40 @@ main (int argc, char ** argv)
/* Bring up the service DBus interface */
dbus_interface = message_service_dbus_new();
- /* Build the base menu */
- root_menuitem = dbusmenu_menuitem_new();
- DbusmenuServer * server = dbusmenu_server_new(INDICATOR_MESSAGES_DBUS_OBJECT);
- dbusmenu_server_set_root(server, root_menuitem);
+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+ if (!bus) {
+ g_warning ("unable to connect to the session bus: %s", error->message);
+ g_error_free (error);
+ return 1;
+ }
+
+ actions = g_simple_action_group_new ();
+ g_simple_action_group_add_entries (actions, entries, G_N_ELEMENTS (entries), NULL);
+ g_dbus_connection_export_action_group (bus, INDICATOR_MESSAGES_DBUS_OBJECT,
+ G_ACTION_GROUP (actions), &error);
+ if (error) {
+ g_warning ("unable to export action group on dbus: %s", error->message);
+ g_error_free (error);
+ return 1;
+ }
+
+ g_signal_connect (dbus_interface, MESSAGE_SERVICE_DBUS_SIGNAL_ATTENTION_CHANGED,
+ G_CALLBACK(clear_action_handler),
+ g_action_map_lookup_action (G_ACTION_MAP (actions), "clear"));
+
+ status_items = status_items_build (g_action_map_lookup_action (G_ACTION_MAP (actions), "status"));
+
+ menu = g_menu_new ();
+ g_menu_append_section (menu, _("Status"), status_items);
+ g_menu_append (menu, _("Clear"), "clear");
- /* Add status items */
- GList * statusitems = status_items_build(&status_update_callback);
- while (statusitems != NULL) {
- dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(statusitems->data));
- statusitems = g_list_next(statusitems);
+ g_dbus_connection_export_menu_model (bus, INDICATOR_MESSAGES_DBUS_OBJECT,
+ G_MENU_MODEL (menu), &error);
+ if (error) {
+ g_warning ("unable to export menu on dbus: %s", error->message);
+ g_error_free (error);
+ return 1;
}
- status_separator = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(status_separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
- dbusmenu_menuitem_child_append(root_menuitem, status_separator);
-
- /* Add in the clear attention item */
- clear_attention = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(clear_attention, DBUSMENU_MENUITEM_PROP_LABEL, _("Clear"));
- dbusmenu_menuitem_child_append(root_menuitem, clear_attention);
- g_signal_connect(G_OBJECT(dbus_interface), MESSAGE_SERVICE_DBUS_SIGNAL_ATTENTION_CHANGED, G_CALLBACK(clear_attention_handler), clear_attention);
- g_signal_connect(G_OBJECT(clear_attention), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(clear_attention_activate), dbus_interface);
-
- /* Start up the libindicate listener */
- listener = indicate_listener_ref_default();
- serverList = NULL;
-
- g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_INDICATOR_ADDED, G_CALLBACK(indicator_added), root_menuitem);
- g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_INDICATOR_REMOVED, G_CALLBACK(indicator_removed), root_menuitem);
- 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);
settings = g_settings_new ("com.canonical.indicator.messages");
diff --git a/src/status-items.c b/src/status-items.c
index 70a2ad9..a2e3a02 100644
--- a/src/status-items.c
+++ b/src/status-items.c
@@ -22,10 +22,19 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <glib.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
-#include <libdbusmenu-glib/dbusmenu-glib.h>
#include "status-items.h"
#include "status-provider.h"
+#include "dbus-data.h"
+
+static const gchar * status_ids [STATUS_PROVIDER_STATUS_LAST] = {
+ /* STATUS_PROVIDER_STATUS_ONLINE, */ "available",
+ /* STATUS_PROVIDER_STATUS_AWAY, */ "away",
+ /* STATUS_PROVIDER_STATUS_DND */ "busy",
+ /* STATUS_PROVIDER_STATUS_INVISIBLE */ "invisible",
+ /* STATUS_PROVIDER_STATUS_OFFLINE, */ "offline",
+ /* STATUS_PROVIDER_STATUS_DISCONNECTED*/ "offline"
+};
static const gchar * status_strings [STATUS_PROVIDER_STATUS_LAST] = {
/* STATUS_PROVIDER_STATUS_ONLINE, */ N_("Available"),
@@ -66,39 +75,40 @@ static const gchar * panel_active_icons[STATUS_PROVIDER_STATUS_LAST] = {
/* Prototypes */
static gboolean provider_directory_parse (gpointer dir);
static gboolean load_status_provider (gpointer dir);
-static void user_status_change (DbusmenuMenuitem * item, guint timestamp, gpointer pstatus);
+static void user_status_change (GSimpleAction *action,
+ GVariant *value,
+ gpointer user_data);
/* Globals */
static StatusProviderStatus current_status = STATUS_PROVIDER_STATUS_DISCONNECTED;
-static GList * menuitems = NULL;
+static GMenu * menu;
+static GAction *status_action;
static GList * status_providers = NULL;
-static StatusUpdateFunc update_func = NULL;
/* Build the inital status items and start kicking off the async code
for handling all the statuses */
-GList *
-status_items_build (StatusUpdateFunc status_update_func)
+GMenuModel *
+status_items_build (GAction *action)
{
int i;
- for (i = STATUS_PROVIDER_STATUS_ONLINE; i < STATUS_PROVIDER_STATUS_DISCONNECTED; i++) {
- DbusmenuMenuitem * item = dbusmenu_menuitem_new();
+ menu = g_menu_new ();
- dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_LABEL, _(status_strings[i]));
- dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_ICON_NAME, status_icons[i]);
+ status_action = action;
+ g_signal_connect (action, "change-state", G_CALLBACK (user_status_change), NULL);
- dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
- dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE);
+ for (i = STATUS_PROVIDER_STATUS_ONLINE; i < STATUS_PROVIDER_STATUS_DISCONNECTED; i++) {
+ GMenuItem *item = g_menu_item_new (_(status_strings[i]), NULL);
- dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, DBUSMENU_MENUITEM_TOGGLE_RADIO);
- dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED);
+ g_menu_item_set_action_and_target (item, g_action_get_name (action), "s", status_ids[i]);
- g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(user_status_change), GINT_TO_POINTER(i));
+ g_menu_item_set_attribute (item, INDICATOR_MENU_ATTRIBUTE_ICON_NAME, "s", status_icons[i]);
+ g_menu_item_set_attribute (item, INDICATOR_MENU_ATTRIBUTE_VISIBLE, "b", TRUE);
+ g_menu_item_set_attribute (item, INDICATOR_MENU_ATTRIBUTE_ENABLED, "b", FALSE);
- menuitems = g_list_append(menuitems, item);
+ g_menu_append_item (menu, item);
+ g_object_unref (item);
}
- update_func = status_update_func;
-
const gchar * status_providers_env = g_getenv("INDICATOR_MESSAGES_STATUS_PROVIDER_DIR");
if (status_providers_env == NULL) {
g_idle_add(provider_directory_parse, STATUS_PROVIDER_DIR);
@@ -106,7 +116,7 @@ status_items_build (StatusUpdateFunc status_update_func)
g_idle_add(provider_directory_parse, (gpointer)status_providers_env);
}
- return menuitems;
+ return G_MENU_MODEL (menu);
}
/* Clean up our globals and stop with all this allocation
@@ -155,38 +165,33 @@ update_status (void)
current_status = status;
- if (update_func != NULL) {
- update_func();
- }
-
- GList * menu;
- int i;
- for (menu = menuitems, i = 0; menu != NULL && i < STATUS_PROVIDER_STATUS_DISCONNECTED; menu = g_list_next(menu), i++) {
- /* If we're the seleced status or if we're disconnected
- show the user that we're offline */
- if (i == current_status || (current_status == STATUS_PROVIDER_STATUS_DISCONNECTED && i == STATUS_PROVIDER_STATUS_OFFLINE)) {
- dbusmenu_menuitem_property_set_int(DBUSMENU_MENUITEM(menu->data), DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED);
- } else {
- dbusmenu_menuitem_property_set_int(DBUSMENU_MENUITEM(menu->data), DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED);
- }
-
- if (current_status == STATUS_PROVIDER_STATUS_DISCONNECTED) {
- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(menu->data), DBUSMENU_MENUITEM_PROP_ENABLED, FALSE);
- } else {
- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(menu->data), DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
- }
- }
+ g_action_change_state (status_action, g_variant_new_string (status_ids[current_status]));
return;
}
/* Handle the user requesting a status change */
static void
-user_status_change (DbusmenuMenuitem * item, guint timestamp, gpointer pstatus)
+user_status_change (GSimpleAction *action,
+ GVariant *value,
+ gpointer user_data)
{
- StatusProviderStatus status = GPOINTER_TO_INT(pstatus);
+ const gchar *status_id;
+ int i;
+ StatusProviderStatus status = STATUS_PROVIDER_STATUS_DISCONNECTED;
GList * provider;
+ g_return_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING));
+
+ status_id = g_variant_get_string (value, NULL);
+
+ for (i = STATUS_PROVIDER_STATUS_ONLINE; i < STATUS_PROVIDER_STATUS_DISCONNECTED; i++) {
+ if (!strcmp (status_id, status_ids [i])) {
+ status = i;
+ break;
+ }
+ }
+
/* Set each provider to this status */
for (provider = status_providers; provider != NULL; provider = g_list_next(provider)) {
status_provider_set_status(STATUS_PROVIDER(provider->data), status);
diff --git a/src/status-items.h b/src/status-items.h
index fe7900c..ff35dfc 100644
--- a/src/status-items.h
+++ b/src/status-items.h
@@ -26,9 +26,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
G_BEGIN_DECLS
-typedef void (*StatusUpdateFunc) (void);
-
-GList * status_items_build (StatusUpdateFunc update_func);
+GMenuModel * status_items_build (GAction *action);
const gchar * status_current_panel_icon (gboolean alert);
void status_items_cleanup (void);
diff --git a/test/Makefile.am b/test/Makefile.am
index bb58ab2..847d857 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -40,7 +40,6 @@ lib_LTLIBRARIES = \
libindicator_messages_service_la_HEADERS = \
$(top_srcdir)/src/gen-messages-service.xml.h \
- $(top_srcdir)/src/im-menu-item.h \
$(top_srcdir)/src/app-menu-item.h \
$(top_srcdir)/src/dbus-data.h \
$(top_srcdir)/src/status-items.h
@@ -49,7 +48,6 @@ libindicator_messages_service_la_SOURCES = \
$(top_srcdir)/src/messages-service.c \
$(top_srcdir)/src/messages-service-dbus.c \
$(top_srcdir)/src/gen-messages-service.xml.c \
- $(top_srcdir)/src/im-menu-item.c \
$(top_srcdir)/src/app-menu-item.c \
$(top_srcdir)/src/status-items.c