diff options
Diffstat (limited to 'libdbusmenu-glib/client.c')
-rw-r--r-- | libdbusmenu-glib/client.c | 108 |
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); |