aboutsummaryrefslogtreecommitdiff
path: root/libdbusmenu-glib/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdbusmenu-glib/client.c')
-rw-r--r--libdbusmenu-glib/client.c108
1 files changed, 105 insertions, 3 deletions
diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c
index 73a7aac..43bde5f 100644
--- a/libdbusmenu-glib/client.c
+++ b/libdbusmenu-glib/client.c
@@ -41,6 +41,7 @@ License version 3 and version 2.1 along with this program. If not, see
#include "client-menuitem.h"
#include "dbusmenu-client.h"
#include "server-marshal.h"
+#include "client-marshal.h"
/* Properties */
enum {
@@ -54,6 +55,8 @@ enum {
LAYOUT_UPDATED,
ROOT_CHANGED,
NEW_MENUITEM,
+ ITEM_ACTIVATE,
+ EVENT_RESULT,
LAST_SIGNAL
};
@@ -100,6 +103,16 @@ struct _properties_listener_t {
gboolean replied;
};
+typedef struct _event_data_t event_data_t;
+struct _event_data_t {
+ DbusmenuClient * client;
+ DbusmenuMenuitem * menuitem;
+ gchar * event;
+ GValue data;
+ guint timestamp;
+};
+
+
#define DBUSMENU_CLIENT_GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUSMENU_TYPE_CLIENT, DbusmenuClientPrivate))
@@ -123,6 +136,7 @@ static void update_layout (DbusmenuClient * client);
static void menuitem_get_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError * error, gpointer data);
static void get_properties_globber (DbusmenuClient * client, gint id, const gchar ** properties, org_ayatana_dbusmenu_get_properties_reply callback, gpointer user_data);
static GQuark error_domain (void);
+static void item_activated (DBusGProxy * proxy, gint id, guint timestamp, DbusmenuClient * client);
/* Build a type */
G_DEFINE_TYPE (DbusmenuClient, dbusmenu_client, G_TYPE_OBJECT);
@@ -187,6 +201,41 @@ dbusmenu_client_class_init (DbusmenuClientClass *klass)
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, G_TYPE_OBJECT);
+ /**
+ DbusmenuClient::item-activate:
+ @arg0: The #DbusmenuClient object
+ @arg1: The #DbusmenuMenuitem activated
+ @arg2: A timestamp that the event happened at
+
+ Signaled when the server wants to activate an item in
+ order to display the menu.
+ */
+ signals[ITEM_ACTIVATE] = g_signal_new(DBUSMENU_CLIENT_SIGNAL_ITEM_ACTIVATE,
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (DbusmenuClientClass, item_activate),
+ NULL, NULL,
+ _dbusmenu_client_marshal_VOID__OBJECT_UINT,
+ G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_UINT);
+ /**
+ DbusmenuClient::event-error:
+ @arg0: The #DbusmenuClient object
+ @arg1: The #DbusmenuMenuitem sent an event
+ @arg2: The ID of the event sent
+ @arg3: The data sent along with the event
+ @arg4: A timestamp that the event happened at
+ @arg5: Possibly the error in sending the event (or NULL)
+
+ Signal sent to show that there was an error in sending the event
+ to the server.
+ */
+ signals[EVENT_RESULT] = g_signal_new(DBUSMENU_CLIENT_SIGNAL_EVENT_RESULT,
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (DbusmenuClientClass, event_result),
+ NULL, NULL,
+ _dbusmenu_client_marshal_VOID__OBJECT_STRING_POINTER_UINT_POINTER,
+ G_TYPE_NONE, 5, G_TYPE_OBJECT, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_POINTER);
g_object_class_install_property (object_class, PROP_DBUSOBJECT,
g_param_spec_string(DBUSMENU_CLIENT_PROP_DBUS_OBJECT, "DBus Object we represent",
@@ -582,6 +631,30 @@ get_properties_globber (DbusmenuClient * client, gint id, const gchar ** propert
return;
}
+/* Called when a server item wants to activate the menu */
+static void
+item_activated (DBusGProxy * proxy, gint id, guint timestamp, DbusmenuClient * client)
+{
+ g_return_if_fail(DBUSMENU_IS_CLIENT(client));
+
+ DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
+
+ if (priv->root == NULL) {
+ g_warning("Asked to activate item %d when we don't have a menu structure.", id);
+ return;
+ }
+
+ DbusmenuMenuitem * menuitem = dbusmenu_menuitem_find_id(priv->root, id);
+ if (menuitem == NULL) {
+ g_warning("Unable to find menu item %d to activate.", id);
+ return;
+ }
+
+ g_signal_emit(G_OBJECT(client), signals[ITEM_ACTIVATE], 0, menuitem, timestamp, TRUE);
+
+ return;
+}
+
/* Annoying little wrapper to make the right function update */
static void
layout_update (DBusGProxy * proxy, guint revision, gint parent, DbusmenuClient * client)
@@ -821,6 +894,10 @@ build_proxies (DbusmenuClient * client)
dbus_g_proxy_add_signal(priv->menuproxy, "ItemUpdated", G_TYPE_INT, G_TYPE_INVALID);
dbus_g_proxy_connect_signal(priv->menuproxy, "ItemUpdated", G_CALLBACK(id_update), client, NULL);
+ dbus_g_object_register_marshaller(_dbusmenu_server_marshal_VOID__INT_UINT, G_TYPE_NONE, G_TYPE_INT, G_TYPE_UINT, G_TYPE_INVALID);
+ dbus_g_proxy_add_signal(priv->menuproxy, "ItemActivationRequested", G_TYPE_INT, G_TYPE_UINT, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(priv->menuproxy, "ItemActivationRequested", G_CALLBACK(item_activated), client, NULL);
+
update_layout(client);
return;
@@ -978,10 +1055,19 @@ menuitem_get_properties_new_cb (DBusGProxy * proxy, GHashTable * properties, GEr
static void
menuitem_call_cb (DBusGProxy * proxy, GError * error, gpointer userdata)
{
+ event_data_t * edata = (event_data_t *)userdata;
+
if (error != NULL) {
g_warning("Unable to call menu item %d: %s", GPOINTER_TO_INT(userdata), error->message);
}
+ g_signal_emit(edata->client, signals[EVENT_RESULT], 0, edata->menuitem, edata->event, edata->data, edata->timestamp, error, TRUE);
+
+ g_value_unset(&edata->data);
+ g_free(edata->event);
+ g_object_unref(edata->menuitem);
+ g_free(edata);
+
return;
}
@@ -994,6 +1080,13 @@ dbusmenu_client_send_event (DbusmenuClient * client, gint id, const gchar * name
g_return_if_fail(id >= 0);
g_return_if_fail(name != NULL);
+ DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
+ DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, id);
+ if (mi == NULL) {
+ g_warning("Asked to activate a menuitem %d that we don't know about", id);
+ return;
+ }
+
if (value == NULL) {
GValue internalval = {0};
g_value_init(&internalval, G_TYPE_INT);
@@ -1001,8 +1094,16 @@ dbusmenu_client_send_event (DbusmenuClient * client, gint id, const gchar * name
value = &internalval;
}
- DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
- org_ayatana_dbusmenu_event_async (priv->menuproxy, id, name, value, timestamp, menuitem_call_cb, GINT_TO_POINTER(id));
+ event_data_t * edata = g_new0(event_data_t, 1);
+ edata->client = client;
+ edata->menuitem = mi;
+ g_object_ref(edata->menuitem);
+ edata->event = g_strdup(name);
+ g_value_init(&edata->data, G_VALUE_TYPE(value));
+ g_value_copy(value, &edata->data);
+ edata->timestamp = timestamp;
+
+ org_ayatana_dbusmenu_event_async (priv->menuproxy, id, name, value, timestamp, menuitem_call_cb, edata);
return;
}
@@ -1225,7 +1326,8 @@ parse_layout (DbusmenuClient * client, const gchar * layout)
xmlDocPtr xmldoc;
- xmldoc = xmlReadMemory(layout, g_utf8_strlen(layout, 16*1024), "dbusmenu.xml", NULL, 0);
+ /* No one should need more characters than this! */
+ xmldoc = xmlReadMemory(layout, g_utf8_strlen(layout, 1024*1024), "dbusmenu.xml", NULL, 0);
xmlNodePtr root = xmlDocGetRootElement(xmldoc);