aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac8
-rw-r--r--docs/reference/libappindicator-sections.txt1
-rw-r--r--src/Makefile.am4
-rw-r--r--src/app-indicator.c121
-rw-r--r--src/app-indicator.h5
-rw-r--r--tests/Makefile.am5
-rw-r--r--tests/test-libappindicator.c126
-rw-r--r--tests/test-libappindicator.desktop23
8 files changed, 289 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac
index 4409c42..9c3f61f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -72,6 +72,14 @@ AS_IF([test "x$with_gtk" = x3],
)
AM_CONDITIONAL(USE_GTK3, [test "x$with_gtk" = x3])
+PKG_CHECK_MODULES(LIBRARY, gtk+-2.0 >= $GTK_REQUIRED_VERSION
+ indicator >= $INDICATOR_REQUIRED_VERSION
+ dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION
+ dbusmenu-gtk >= $DBUSMENUGTK_REQUIRED_VERSION)
+
+AC_SUBST(LIBRARY_CFLAGS)
+AC_SUBST(LIBRARY_LIBS)
+
###########################
# GObject Introspection
###########################
diff --git a/docs/reference/libappindicator-sections.txt b/docs/reference/libappindicator-sections.txt
index e0effd1..41ff7fa 100644
--- a/docs/reference/libappindicator-sections.txt
+++ b/docs/reference/libappindicator-sections.txt
@@ -38,5 +38,6 @@ app_indicator_get_menu
app_indicator_get_label
app_indicator_get_label_guide
app_indicator_get_ordering_index
+app_indicator_build_menu_from_desktop
</SECTION>
diff --git a/src/Makefile.am b/src/Makefile.am
index e3d9184..e89aa84 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -120,12 +120,12 @@ libappindicator_la_LDFLAGS = \
-export-symbols-regex "^[^_d].*"
libappindicator_la_CFLAGS = \
- $(INDICATOR_CFLAGS) \
+ $(LIBRARY_CFLAGS) \
-Wall -Werror \
-DG_LOG_DOMAIN=\"libappindicator\"
libappindicator_la_LIBADD = \
- $(INDICATOR_LIBS)
+ $(LIBRARY_LIBS)
# We duplicate these here because Automake won't let us use $(VER) on the left hand side.
# Since we carefully use $(VER) in the right hand side above, we can assign the same values.
diff --git a/src/app-indicator.c b/src/app-indicator.c
index 98663c1..4886605 100644
--- a/src/app-indicator.c
+++ b/src/app-indicator.c
@@ -34,6 +34,7 @@ License version 3 and version 2.1 along with this program. If not, see
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-bindings.h>
+#include <libdbusmenu-glib/menuitem.h>
#include <libdbusmenu-glib/server.h>
#ifdef HAVE_GTK3
#include <libdbusmenu-gtk3/client.h>
@@ -41,6 +42,8 @@ License version 3 and version 2.1 along with this program. If not, see
#include <libdbusmenu-gtk/client.h>
#endif
+#include <libindicator/indicator-desktop-shortcuts.h>
+
#include "app-indicator.h"
#include "app-indicator-enum-types.h"
#include "application-service-marshal.h"
@@ -92,6 +95,9 @@ struct _AppIndicatorPrivate {
DBusGProxy *watcher_proxy;
DBusGConnection *connection;
DBusGProxy * dbus_proxy;
+
+ /* Might be used */
+ IndicatorDesktopShortcuts * shorties;
};
/* Signals Stuff */
@@ -125,7 +131,8 @@ enum {
PROP_X_LABEL,
PROP_X_LABEL_GUIDE,
PROP_ORDERING_INDEX,
- PROP_X_ORDERING_INDEX
+ PROP_X_ORDERING_INDEX,
+ PROP_DBUS_MENU_SERVER
};
/* The strings so that they can be slowly looked up. */
@@ -143,6 +150,7 @@ enum {
#define PROP_X_LABEL_GUIDE_S ("x-ayatana-" PROP_LABEL_GUIDE_S)
#define PROP_ORDERING_INDEX_S "ordering-index"
#define PROP_X_ORDERING_INDEX_S ("x-ayatana-" PROP_ORDERING_INDEX_S)
+#define PROP_DBUS_MENU_SERVER_S "dbus-menu-server"
/* Private macro, shhhh! */
#define APP_INDICATOR_GET_PRIVATE(o) \
@@ -410,6 +418,19 @@ app_indicator_class_init (AppIndicatorClass *klass)
"A wrapper, please don't use.",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ /**
+ AppIndicator:dbus-menu-server:
+
+ A way to get the internal dbusmenu server if it is available.
+ This should only be used for testing.
+ */
+ g_object_class_install_property(object_class,
+ PROP_DBUS_MENU_SERVER,
+ g_param_spec_object (PROP_DBUS_MENU_SERVER_S,
+ "The internal DBusmenu Server",
+ "DBusmenu server which is available for testing the application indicators.",
+ DBUSMENU_TYPE_SERVER,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/* Signals */
@@ -554,6 +575,8 @@ app_indicator_init (AppIndicator *self)
priv->status_icon = NULL;
priv->fallback_timer = 0;
+ priv->shorties = NULL;
+
/* Put the object on DBus */
GError * error = NULL;
priv->connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
@@ -580,6 +603,11 @@ app_indicator_dispose (GObject *object)
AppIndicator *self = APP_INDICATOR (object);
AppIndicatorPrivate *priv = self->priv;
+ if (priv->shorties != NULL) {
+ g_object_unref(G_OBJECT(priv->shorties));
+ priv->shorties = NULL;
+ }
+
if (priv->status != APP_INDICATOR_STATUS_PASSIVE) {
app_indicator_set_status(self, APP_INDICATOR_STATUS_PASSIVE);
}
@@ -798,6 +826,14 @@ app_indicator_set_property (GObject * object, guint prop_id, const GValue * valu
priv->ordering_index = g_value_get_uint(value);
break;
+ case PROP_DBUS_MENU_SERVER:
+ if (priv->menuservice != NULL) {
+ g_object_unref (priv->menuservice);
+ }
+ gpointer val = g_value_dup_object(value);
+ priv->menuservice = DBUSMENU_SERVER(val);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -870,6 +906,10 @@ app_indicator_get_property (GObject * object, guint prop_id, GValue * value, GPa
g_value_set_uint(value, priv->ordering_index);
break;
+ case PROP_DBUS_MENU_SERVER:
+ g_value_set_object(value, priv->menuservice);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -2116,3 +2156,82 @@ app_indicator_get_ordering_index (AppIndicator *self)
}
}
+#define APP_INDICATOR_SHORTY_NICK "app-indicator-shorty-nick"
+
+/* Callback when an item from the desktop shortcuts gets
+ called. */
+static void
+shorty_activated_cb (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data)
+{
+ gchar * nick = g_object_get_data(G_OBJECT(mi), APP_INDICATOR_SHORTY_NICK);
+ g_return_if_fail(nick != NULL);
+
+ g_return_if_fail(IS_APP_INDICATOR(user_data));
+ AppIndicator * self = APP_INDICATOR(user_data);
+ AppIndicatorPrivate *priv = self->priv;
+
+ g_return_if_fail(priv->shorties != NULL);
+
+ indicator_desktop_shortcuts_nick_exec(priv->shorties, nick);
+
+ return;
+}
+
+/**
+ app_indicator_build_menu_from_desktop:
+ @self: The #AppIndicator object to use
+ @desktop_file: A path to the desktop file to build the menu from
+ @desktop_profile: Which entries should be used from the desktop file
+
+ This function allows for building the Application Indicator menu
+ from a static desktop file.
+*/
+void
+app_indicator_build_menu_from_desktop (AppIndicator * self, const gchar * desktop_file, const gchar * desktop_profile)
+{
+ g_return_if_fail(IS_APP_INDICATOR(self));
+ AppIndicatorPrivate *priv = self->priv;
+
+ /* Build a new shortcuts object */
+ if (priv->shorties != NULL) {
+ g_object_unref(priv->shorties);
+ priv->shorties = NULL;
+ }
+ priv->shorties = indicator_desktop_shortcuts_new(desktop_file, desktop_profile);
+ g_return_if_fail(priv->shorties != NULL);
+
+ const gchar ** nicks = indicator_desktop_shortcuts_get_nicks(priv->shorties);
+ int nick_num;
+
+ /* Place the items on a dbusmenu */
+ DbusmenuMenuitem * root = dbusmenu_menuitem_new();
+
+ for (nick_num = 0; nicks[nick_num] != NULL; nick_num++) {
+ DbusmenuMenuitem * item = dbusmenu_menuitem_new();
+ g_object_set_data(G_OBJECT(item), APP_INDICATOR_SHORTY_NICK, (gpointer)nicks[nick_num]);
+
+ gchar * name = indicator_desktop_shortcuts_nick_get_name(priv->shorties, nicks[nick_num]);
+ dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_LABEL, name);
+ g_free(name);
+
+ g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(shorty_activated_cb), self);
+
+ dbusmenu_menuitem_child_append(root, item);
+ }
+
+ /* Swap it if needed */
+ if (priv->menuservice == NULL) {
+ gchar * path = g_strdup_printf(DEFAULT_ITEM_PATH "/%s/Menu", priv->clean_id);
+ priv->menuservice = dbusmenu_server_new (path);
+ g_free(path);
+ }
+
+ dbusmenu_server_set_root (priv->menuservice, root);
+
+ if (priv->menu != NULL) {
+ g_object_unref(G_OBJECT(priv->menu));
+ priv->menu = NULL;
+ }
+
+ return;
+}
diff --git a/src/app-indicator.h b/src/app-indicator.h
index ce152bb..3e159db 100644
--- a/src/app-indicator.h
+++ b/src/app-indicator.h
@@ -280,6 +280,11 @@ const gchar * app_indicator_get_label (AppIndicator *
const gchar * app_indicator_get_label_guide (AppIndicator *self);
guint32 app_indicator_get_ordering_index (AppIndicator *self);
+/* Helpers */
+void app_indicator_build_menu_from_desktop (AppIndicator * self,
+ const gchar * desktop_file,
+ const gchar * desktop_profile);
+
G_END_DECLS
/**
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f2bdbb2..9cecd5e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -13,7 +13,9 @@ check_PROGRAMS = \
TESTS =
DISTCLEANFILES = $(TESTS)
-EXTRA_DIST = run-xvfb.sh
+EXTRA_DIST = \
+ run-xvfb.sh \
+ test-libappindicator.desktop
#########################################
## test-libappindicator
@@ -24,6 +26,7 @@ test_libappindicator_SOURCES = \
test_libappindicator_CFLAGS = \
$(INDICATOR_CFLAGS) \
+ -DSRCDIR="\"$(srcdir)\"" \
-Wall -Werror \
-I$(top_srcdir)/src
diff --git a/tests/test-libappindicator.c b/tests/test-libappindicator.c
index 8d12ac5..cadf783 100644
--- a/tests/test-libappindicator.c
+++ b/tests/test-libappindicator.c
@@ -25,6 +25,9 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <app-indicator.h>
+#include <libdbusmenu-glib/menuitem.h>
+#include <libdbusmenu-glib/server.h>
+
void
test_libappindicator_prop_signals_status_helper (AppIndicator * ci, gchar * status, gboolean * signalactivated)
{
@@ -225,6 +228,57 @@ test_libappindicator_set_label (void)
}
void
+test_libappindicator_set_menu (void)
+{
+ AppIndicator * ci = app_indicator_new ("my-id",
+ "my-name",
+ APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
+
+ g_assert(ci != NULL);
+
+ GtkMenu * menu = GTK_MENU(gtk_menu_new());
+
+ GtkMenuItem * item = GTK_MENU_ITEM(gtk_menu_item_new_with_label("Test Label"));
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(item));
+ gtk_widget_show(GTK_WIDGET(item));
+
+ app_indicator_set_menu(ci, menu);
+
+ g_assert(app_indicator_get_menu(ci) != NULL);
+
+ GValue serverval = {0};
+ g_value_init(&serverval, DBUSMENU_TYPE_SERVER);
+ g_object_get_property(G_OBJECT(ci), "dbus-menu-server", &serverval);
+
+ DbusmenuServer * server = DBUSMENU_SERVER(g_value_get_object(&serverval));
+ g_assert(server != NULL);
+
+ GValue rootval = {0};
+ g_value_init(&rootval, DBUSMENU_TYPE_MENUITEM);
+ g_object_get_property(G_OBJECT(server), DBUSMENU_SERVER_PROP_ROOT_NODE, &rootval);
+ DbusmenuMenuitem * root = DBUSMENU_MENUITEM(g_value_get_object(&rootval));
+ g_assert(root != NULL);
+
+ GList * children = dbusmenu_menuitem_get_children(root);
+ g_assert(children != NULL);
+ g_assert(g_list_length(children) == 1);
+
+ const gchar * label = dbusmenu_menuitem_property_get(DBUSMENU_MENUITEM(children->data), DBUSMENU_MENUITEM_PROP_LABEL);
+ g_assert(label != NULL);
+ g_assert(g_strcmp0(label, "Test Label") == 0);
+
+ /* Interesting, eh? We need this because we send out events on the bus
+ but they don't come back until the idle is run. So we need those
+ events to clear before removing the object */
+ while (g_main_context_pending(NULL)) {
+ g_main_context_iteration(NULL, TRUE);
+ }
+
+ g_object_unref(G_OBJECT(ci));
+ return;
+}
+
+void
label_signals_cb (AppIndicator * appindicator, gchar * label, gchar * guide, gpointer user_data)
{
gint * label_signals_count = (gint *)user_data;
@@ -294,6 +348,75 @@ test_libappindicator_label_signals (void)
}
void
+test_libappindicator_desktop_menu (void)
+{
+ AppIndicator * ci = app_indicator_new ("my-id-desktop-menu",
+ "my-name",
+ APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
+
+ g_assert(ci != NULL);
+ g_assert(app_indicator_get_label(ci) == NULL);
+ g_assert(app_indicator_get_label_guide(ci) == NULL);
+
+ app_indicator_build_menu_from_desktop(ci, SRCDIR "/test-libappindicator.desktop", "Test Program");
+
+ GValue serverval = {0};
+ g_value_init(&serverval, DBUSMENU_TYPE_SERVER);
+ g_object_get_property(G_OBJECT(ci), "dbus-menu-server", &serverval);
+
+ DbusmenuServer * server = DBUSMENU_SERVER(g_value_get_object(&serverval));
+ g_assert(server != NULL);
+
+ GValue rootval = {0};
+ g_value_init(&rootval, DBUSMENU_TYPE_MENUITEM);
+ g_object_get_property(G_OBJECT(server), DBUSMENU_SERVER_PROP_ROOT_NODE, &rootval);
+ DbusmenuMenuitem * root = DBUSMENU_MENUITEM(g_value_get_object(&rootval));
+ g_assert(root != NULL);
+
+ GList * children = dbusmenu_menuitem_get_children(root);
+ g_assert(children != NULL);
+ g_assert(g_list_length(children) == 3);
+
+
+
+ g_object_unref(G_OBJECT(ci));
+ return;
+}
+
+void
+test_libappindicator_desktop_menu_bad (void)
+{
+ AppIndicator * ci = app_indicator_new ("my-id-desktop-menu-bad",
+ "my-name",
+ APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
+
+ g_assert(ci != NULL);
+ g_assert(app_indicator_get_label(ci) == NULL);
+ g_assert(app_indicator_get_label_guide(ci) == NULL);
+
+ app_indicator_build_menu_from_desktop(ci, SRCDIR "/test-libappindicator.desktop", "Not Test Program");
+
+ GValue serverval = {0};
+ g_value_init(&serverval, DBUSMENU_TYPE_SERVER);
+ g_object_get_property(G_OBJECT(ci), "dbus-menu-server", &serverval);
+
+ DbusmenuServer * server = DBUSMENU_SERVER(g_value_get_object(&serverval));
+ g_assert(server != NULL);
+
+ GValue rootval = {0};
+ g_value_init(&rootval, DBUSMENU_TYPE_MENUITEM);
+ g_object_get_property(G_OBJECT(server), DBUSMENU_SERVER_PROP_ROOT_NODE, &rootval);
+ DbusmenuMenuitem * root = DBUSMENU_MENUITEM(g_value_get_object(&rootval));
+ g_assert(root != NULL);
+
+ GList * children = dbusmenu_menuitem_get_children(root);
+ g_assert(g_list_length(children) == 0);
+
+ g_object_unref(G_OBJECT(ci));
+ return;
+}
+
+void
test_libappindicator_props_suite (void)
{
g_test_add_func ("/indicator-application/libappindicator/init", test_libappindicator_init);
@@ -301,7 +424,10 @@ test_libappindicator_props_suite (void)
g_test_add_func ("/indicator-application/libappindicator/init_set_props", test_libappindicator_init_set_props);
g_test_add_func ("/indicator-application/libappindicator/prop_signals", test_libappindicator_prop_signals);
g_test_add_func ("/indicator-application/libappindicator/set_label", test_libappindicator_set_label);
+ g_test_add_func ("/indicator-application/libappindicator/set_menu", test_libappindicator_set_menu);
g_test_add_func ("/indicator-application/libappindicator/label_signals", test_libappindicator_label_signals);
+ g_test_add_func ("/indicator-application/libappindicator/desktop_menu", test_libappindicator_desktop_menu);
+ g_test_add_func ("/indicator-application/libappindicator/desktop_menu_bad",test_libappindicator_desktop_menu_bad);
return;
}
diff --git a/tests/test-libappindicator.desktop b/tests/test-libappindicator.desktop
new file mode 100644
index 0000000..59be810
--- /dev/null
+++ b/tests/test-libappindicator.desktop
@@ -0,0 +1,23 @@
+[Desktop Entry]
+Name=AppIndicator Test
+GenericName=Test
+Comment=This is only a test
+Exec=/usr/bin/false
+Terminal=false
+Type=Application
+X-Ayatana-Desktop-Shortcuts=Short1;Short2;Short3;
+
+[Short1 Shortcut Group]
+Name=Shortcut 1
+Exec=/usr/bin/true
+OnlyShowIn=Test Program;
+
+[Short2 Shortcut Group]
+Name=Shortcut 2
+Exec=/usr/bin/true
+OnlyShowIn=Test Program;
+
+[Short3 Shortcut Group]
+Name=Shortcut 3
+Exec=/usr/bin/true
+OnlyShowIn=Test Program;