aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am.enum45
-rw-r--r--configure.ac2
-rw-r--r--debian/changelog18
-rw-r--r--libdbusmenu-glib/Makefile.am22
-rw-r--r--libdbusmenu-glib/client-marshal.list1
-rw-r--r--libdbusmenu-glib/client.c160
-rw-r--r--libdbusmenu-glib/client.h6
-rw-r--r--libdbusmenu-glib/dbus-menu-clean.xml.c8
-rw-r--r--libdbusmenu-glib/dbus-menu.xml18
-rw-r--r--libdbusmenu-glib/enum-types.c183
-rw-r--r--libdbusmenu-glib/enum-types.c.in116
-rw-r--r--libdbusmenu-glib/enum-types.h56
-rw-r--r--libdbusmenu-glib/enum-types.h.in56
-rw-r--r--libdbusmenu-glib/menuitem-marshal.c43
-rw-r--r--libdbusmenu-glib/menuitem-marshal.h8
-rw-r--r--libdbusmenu-glib/menuitem-marshal.list1
-rw-r--r--libdbusmenu-glib/menuitem-private.h1
-rw-r--r--libdbusmenu-glib/menuitem.c72
-rw-r--r--libdbusmenu-glib/menuitem.h5
-rw-r--r--libdbusmenu-glib/server.c254
-rw-r--r--libdbusmenu-glib/server.h16
-rw-r--r--libdbusmenu-glib/types.h65
-rw-r--r--po/POTFILES.in1
23 files changed, 1132 insertions, 25 deletions
diff --git a/Makefile.am.enum b/Makefile.am.enum
new file mode 100644
index 0000000..0503de0
--- /dev/null
+++ b/Makefile.am.enum
@@ -0,0 +1,45 @@
+# Rules for generating enumeration types using glib-mkenums
+#
+# Define:
+# glib_enum_h = header template file
+# glib_enum_c = source template file
+# glib_enum_headers = list of headers to parse
+#
+# before including Makefile.am.enums. You will also need to have
+# the following targets already defined:
+#
+# CLEANFILES
+# DISTCLEANFILES
+# BUILT_SOURCES
+# EXTRA_DIST
+#
+# Author: Emmanuele Bassi <ebassi@linux.intel.com>
+
+enum_tmpl_h=$(glib_enum_h:.h=.h.in)
+enum_tmpl_c=$(glib_enum_c:.c=.c.in)
+
+CLEANFILES += stamp-enum-types
+DISTCLEANFILES += $(glib_enum_h) $(glib_enum_c)
+BUILT_SOURCES += $(glib_enum_h) $(glib_enum_c)
+EXTRA_DIST += $(enum_tmpl_h) $(enum_tmpl_c)
+
+stamp-enum-types: $(glib_enum_headers)
+ $(QUIET_GEN)mkdir -p `dirname $(builddir)/$(glib_enum_h)`
+ $(QUIET_GEN)$(GLIB_MKENUMS) \
+ --template $(srcdir)/$(enum_tmpl_h) \
+ $(glib_enum_headers) > xgen-eh \
+ && (cmp -s xgen-eh $(builddir)/$(glib_enum_h) || cp -f xgen-eh $(builddir)/$(glib_enum_h)) \
+ && rm -f xgen-eh \
+ && echo timestamp > $(@F)
+
+$(glib_enum_h): stamp-enum-types
+ @true
+
+$(glib_enum_c): $(glib_enum_h)
+ $(QUIET_GEN)mkdir -p `dirname $(builddir)/$(glib_enum_c)`
+ $(QUIET_GEN)$(GLIB_MKENUMS) \
+ --template $(srcdir)/$(enum_tmpl_c) \
+ $(glib_enum_headers) > xgen-ec \
+ && cp -f xgen-ec $(builddir)/$(glib_enum_c) \
+ && rm -f xgen-ec
+
diff --git a/configure.ac b/configure.ac
index a1af560..7f53d3c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,6 +21,8 @@ AC_CONFIG_MACRO_DIR([m4])
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
+AC_PATH_PROG([GLIB_MKENUMS], [glib-mkenums])
+
AC_ARG_ENABLE([deprecations],
[AS_HELP_STRING([--enable-deprecations],
[allow deprecated API usage @<:@default=yes@:>@])],
diff --git a/debian/changelog b/debian/changelog
index 7e08ca0..22ee67b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,21 @@
+libdbusmenu (0.3.98-0ubuntu5~ppa1) UNRELEASED; urgency=low
+
+ * Upstream Merge
+ * Add a signal on the menuitem for generic event support
+ * Handle the case of a single NULL entry as well.
+ * Not checking defaults when value is NULL
+ * Add the 'type' variable first when processing new
+ menuitems
+ * Protection from unref'ing NULL variants
+ * Only send the requested properties and request fewer
+ * Add in a defaults database
+ * Only send property updates if the menu item has been
+ seen on the bus.
+ * Add a property for text direction.
+ * Add a property for needing attention.
+
+ -- Ted Gould <ted@ubuntu.com> Thu, 24 Feb 2011 12:38:30 -0600
+
libdbusmenu (0.3.98-0ubuntu4) natty; urgency=low
* Merged from trunk (rev 220)
diff --git a/libdbusmenu-glib/Makefile.am b/libdbusmenu-glib/Makefile.am
index 5ddbeb8..bf80996 100644
--- a/libdbusmenu-glib/Makefile.am
+++ b/libdbusmenu-glib/Makefile.am
@@ -1,6 +1,7 @@
-CLEANFILES =
-
+BUILT_SOURCES =
+CLEANFILES =
+DISTCLEANFILES =
EXTRA_DIST = \
clean-namespaces.xslt \
dbusmenu-glib-0.4.pc.in \
@@ -9,6 +10,8 @@ EXTRA_DIST = \
menuitem-marshal.list \
server-marshal.list
+include $(top_srcdir)/Makefile.am.enum
+
lib_LTLIBRARIES = \
libdbusmenu-glib.la
@@ -19,13 +22,16 @@ libdbusmenu_glibinclude_HEADERS = \
menuitem.h \
menuitem-proxy.h \
server.h \
- client.h
+ client.h \
+ types.h
libdbusmenu_glib_la_SOURCES = \
dbus-menu-clean.xml.h \
dbus-menu-clean.xml.c \
defaults.h \
defaults.c \
+ enum-types.h \
+ enum-types.c \
menuitem.h \
menuitem.c \
menuitem-marshal.h \
@@ -58,6 +64,14 @@ libdbusmenu_glib_la_LIBADD = \
pkgconfig_DATA = dbusmenu-glib-0.4.pc
pkgconfigdir = $(libdir)/pkgconfig
+glib_enum_h = enum-types.h
+glib_enum_c = enum-types.c
+glib_enum_headers = $(addprefix $(srcdir)/, $(libdbusmenu_glibinclude_HEADERS))
+
+DISTCLEANFILES += \
+ enum-types.c \
+ enum-types.h
+
%.xml.h: %.xml
echo "extern const char * $(subst -,_,$(subst .,_,$(basename $(notdir $@))));" > $@
@@ -71,7 +85,7 @@ dbus-menu-clean.xml: dbus-menu.xml
CLEANFILES += dbus-menu-clean.xml
-BUILT_SOURCES = \
+BUILT_SOURCES += \
dbus-menu-clean.xml.c \
dbus-menu-clean.xml.h \
client-marshal.h \
diff --git a/libdbusmenu-glib/client-marshal.list b/libdbusmenu-glib/client-marshal.list
index 866dfa8..96f9302 100644
--- a/libdbusmenu-glib/client-marshal.list
+++ b/libdbusmenu-glib/client-marshal.list
@@ -1,2 +1,3 @@
VOID: OBJECT, UINT
VOID: OBJECT, STRING, VARIANT, UINT, POINTER
+VOID: ENUM
diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c
index 462dd64..3c8d5d2 100644
--- a/libdbusmenu-glib/client.c
+++ b/libdbusmenu-glib/client.c
@@ -39,6 +39,7 @@ License version 3 and version 2.1 along with this program. If not, see
#include "server-marshal.h"
#include "client-marshal.h"
#include "dbus-menu-clean.xml.h"
+#include "enum-types.h"
/* How many property requests should we queue before
sending the message on dbus */
@@ -48,7 +49,9 @@ License version 3 and version 2.1 along with this program. If not, see
enum {
PROP_0,
PROP_DBUSOBJECT,
- PROP_DBUSNAME
+ PROP_DBUSNAME,
+ PROP_STATUS,
+ PROP_TEXT_DIRECTION
};
/* Signals */
@@ -91,6 +94,9 @@ struct _DbusmenuClientPrivate
GArray * delayed_property_list;
GArray * delayed_property_listeners;
gint delayed_idle;
+
+ DbusmenuTextDirection text_direction;
+ DbusmenuStatus status;
};
typedef struct _newItemPropData newItemPropData;
@@ -158,6 +164,7 @@ static void get_properties_globber (DbusmenuClient * client, gint id, const gcha
static GQuark error_domain (void);
static void item_activated (GDBusProxy * proxy, gint id, guint timestamp, DbusmenuClient * client);
static void menuproxy_build_cb (GObject * object, GAsyncResult * res, gpointer user_data);
+static void menuproxy_prop_changed_cb (GDBusProxy * proxy, GVariant * properties, GStrv invalidated, gpointer user_data);
static void menuproxy_name_changed_cb (GObject * object, GParamSpec * pspec, gpointer user_data);
static void menuproxy_signal_cb (GDBusProxy * proxy, gchar * sender, gchar * signal, GVariant * params, gpointer user_data);
static void type_handler_destroy (gpointer user_data);
@@ -275,6 +282,16 @@ dbusmenu_client_class_init (DbusmenuClientClass *klass)
"Name of the DBus client we're connecting to.",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class, PROP_STATUS,
+ g_param_spec_enum(DBUSMENU_CLIENT_PROP_STATUS, "Status of viewing the menus",
+ "Whether the menus should be given special visuals",
+ DBUSMENU_TYPE_STATUS, DBUSMENU_STATUS_NORMAL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class, PROP_TEXT_DIRECTION,
+ g_param_spec_enum(DBUSMENU_CLIENT_PROP_TEXT_DIRECTION, "Direction text values have",
+ "Signals which direction the default text direction is for the menus",
+ DBUSMENU_TYPE_TEXT_DIRECTION, DBUSMENU_TEXT_DIRECTION_NONE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
if (dbusmenu_node_info == NULL) {
GError * error = NULL;
@@ -317,11 +334,13 @@ dbusmenu_client_init (DbusmenuClient *self)
priv->layoutcall = NULL;
- gchar * layout_props[3];
+ gchar * layout_props[5];
layout_props[0] = DBUSMENU_MENUITEM_PROP_TYPE;
layout_props[1] = DBUSMENU_MENUITEM_PROP_LABEL;
- layout_props[2] = NULL;
- priv->layout_props = g_variant_new_strv((const gchar * const *)layout_props, 2);
+ layout_props[2] = DBUSMENU_MENUITEM_PROP_VISIBLE;
+ layout_props[3] = DBUSMENU_MENUITEM_PROP_ENABLED;
+ layout_props[4] = NULL;
+ priv->layout_props = g_variant_new_strv((const gchar * const *)layout_props, 4);
g_variant_ref_sink(priv->layout_props);
priv->current_revision = 0;
@@ -336,6 +355,9 @@ dbusmenu_client_init (DbusmenuClient *self)
priv->delayed_property_list = g_array_new(TRUE, FALSE, sizeof(gchar *));
priv->delayed_property_listeners = g_array_new(FALSE, FALSE, sizeof(properties_listener_t));
+ priv->text_direction = DBUSMENU_TEXT_DIRECTION_NONE;
+ priv->status = DBUSMENU_STATUS_NORMAL;
+
return;
}
@@ -485,6 +507,12 @@ get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec)
case PROP_DBUSOBJECT:
g_value_set_string(value, priv->dbus_object);
break;
+ case PROP_STATUS:
+ g_value_set_enum(value, priv->status);
+ break;
+ case PROP_TEXT_DIRECTION:
+ g_value_set_enum(value, priv->text_direction);
+ break;
default:
g_warning("Unknown property %d.", id);
return;
@@ -996,6 +1024,19 @@ menuproxy_build_cb (GObject * object, GAsyncResult * res, gpointer user_data)
priv->menuproxy_cancel = NULL;
}
+ /* Check the text direction if available */
+ GVariant * textdir = g_dbus_proxy_get_cached_property(priv->menuproxy, "text-direction");
+ if (textdir != NULL) {
+ GVariant * str = textdir;
+ if (g_variant_is_of_type(str, G_VARIANT_TYPE_VARIANT)) {
+ str = g_variant_get_variant(str);
+ }
+
+ priv->text_direction = dbusmenu_text_direction_get_value_from_nick(g_variant_get_string(str, NULL));
+
+ g_variant_unref(textdir);
+ }
+
/* If we get here, we don't need the DBus proxy */
if (priv->dbusproxy != 0) {
g_bus_unwatch_name(priv->dbusproxy);
@@ -1004,6 +1045,7 @@ menuproxy_build_cb (GObject * object, GAsyncResult * res, gpointer user_data)
g_signal_connect(priv->menuproxy, "g-signal", G_CALLBACK(menuproxy_signal_cb), client);
g_signal_connect(priv->menuproxy, "notify::g-name-owner", G_CALLBACK(menuproxy_name_changed_cb), client);
+ g_signal_connect(priv->menuproxy, "g-properties-changed", G_CALLBACK(menuproxy_prop_changed_cb), client);
gchar * name_owner = g_dbus_proxy_get_name_owner(priv->menuproxy);
if (name_owner != NULL) {
@@ -1014,6 +1056,63 @@ menuproxy_build_cb (GObject * object, GAsyncResult * res, gpointer user_data)
return;
}
+/* Handle the properites changing */
+static void
+menuproxy_prop_changed_cb (GDBusProxy * proxy, GVariant * properties, GStrv invalidated, gpointer user_data)
+{
+ DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(user_data);
+ DbusmenuTextDirection olddir = priv->text_direction;
+ DbusmenuStatus oldstatus = priv->status;
+
+ /* Invalidate first */
+ gchar * invalid;
+ gint i = 0;
+ for (invalid = invalidated[i]; invalid != NULL; invalid = invalidated[++i]) {
+ if (g_strcmp0(invalid, "text-direction") == 0) {
+ priv->text_direction = DBUSMENU_TEXT_DIRECTION_NONE;
+ }
+ if (g_strcmp0(invalid, "status") == 0) {
+ priv->status = DBUSMENU_STATUS_NORMAL;
+ }
+ }
+
+ /* Check updates */
+ GVariantIter iters;
+ gchar * key; GVariant * value;
+ g_variant_iter_init(&iters, properties);
+ while (g_variant_iter_next(&iters, "{sv}", &key, &value)) {
+ if (g_strcmp0(key, "text-direction") == 0) {
+ GVariant * str = value;
+ if (g_variant_is_of_type(str, G_VARIANT_TYPE_VARIANT)) {
+ str = g_variant_get_variant(str);
+ }
+
+ priv->text_direction = dbusmenu_text_direction_get_value_from_nick(g_variant_get_string(str, NULL));
+ }
+ if (g_strcmp0(key, "status") == 0) {
+ GVariant * str = value;
+ if (g_variant_is_of_type(str, G_VARIANT_TYPE_VARIANT)) {
+ str = g_variant_get_variant(str);
+ }
+
+ priv->status = dbusmenu_status_get_value_from_nick(g_variant_get_string(str, NULL));
+ }
+
+ g_variant_unref(value);
+ g_free(key);
+ }
+
+ if (olddir != priv->text_direction) {
+ g_object_notify(G_OBJECT(user_data), DBUSMENU_CLIENT_PROP_TEXT_DIRECTION);
+ }
+
+ if (oldstatus != priv->status) {
+ g_object_notify(G_OBJECT(user_data), DBUSMENU_CLIENT_PROP_STATUS);
+ }
+
+ return;
+}
+
/* Handle the case where we change owners */
static void
menuproxy_name_changed_cb (GObject * object, GParamSpec * pspec, gpointer user_data)
@@ -1490,10 +1589,22 @@ parse_layout_xml(DbusmenuClient * client, GVariant * layout, DbusmenuMenuitem *
menu item. Sometimes they may just be copies */
if (childmi != NULL) {
GVariantIter iter;
- g_variant_iter_init(&iter, g_variant_get_child_value(child, 1));
gchar * prop;
GVariant * value;
+ /* Set the type first as it can manage the behavior of
+ all other properties. */
+ g_variant_iter_init(&iter, g_variant_get_child_value(child, 1));
+ while (g_variant_iter_next(&iter, "{sv}", &prop, &value)) {
+ if (g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_TYPE) == 0) {
+ dbusmenu_menuitem_property_set_variant(childmi, prop, value);
+ }
+ g_free(prop);
+ g_variant_unref(value);
+ }
+
+ /* Now go through and do all the properties. */
+ g_variant_iter_init(&iter, g_variant_get_child_value(child, 1));
while (g_variant_iter_next(&iter, "{sv}", &prop, &value)) {
dbusmenu_menuitem_property_set_variant(childmi, prop, value);
g_free(prop);
@@ -1862,3 +1973,42 @@ dbusmenu_client_add_type_handler_full (DbusmenuClient * client, const gchar * ty
return TRUE;
}
+/**
+ dbusmenu_client_get_text_direction:
+ @client: #DbusmenuClient to check the text direction on
+
+ Gets the text direction that the server is exporting. If
+ the server is not exporting a direction then the value
+ #DBUSMENU_TEXT_DIRECTION_NONE will be returned.
+
+ Return value: Text direction being exported.
+*/
+DbusmenuTextDirection
+dbusmenu_client_get_text_direction (DbusmenuClient * client)
+{
+ g_return_val_if_fail(DBUSMENU_IS_CLIENT(client), DBUSMENU_TEXT_DIRECTION_NONE);
+ DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
+ return priv->text_direction;
+}
+
+/**
+ dbusmenu_client_get_status:
+ @client: #DbusmenuClient to check the status on
+
+ Gets the recommended current status that the server
+ is exporting for the menus. In situtations where the
+ value is #DBUSMENU_STATUS_NOTICE it is recommended that
+ the client show the menus to the user an a more noticible
+ way.
+
+ Return value: Status being exported.
+*/
+DbusmenuStatus
+dbusmenu_client_get_status (DbusmenuClient * client)
+{
+ g_return_val_if_fail(DBUSMENU_IS_CLIENT(client), DBUSMENU_STATUS_NORMAL);
+ DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
+ return priv->status;
+}
+
+
diff --git a/libdbusmenu-glib/client.h b/libdbusmenu-glib/client.h
index 79c0ee2..c04e840 100644
--- a/libdbusmenu-glib/client.h
+++ b/libdbusmenu-glib/client.h
@@ -33,6 +33,7 @@ License version 3 and version 2.1 along with this program. If not, see
#include <glib-object.h>
#include "menuitem.h"
+#include "types.h"
G_BEGIN_DECLS
@@ -48,9 +49,12 @@ G_BEGIN_DECLS
#define DBUSMENU_CLIENT_SIGNAL_NEW_MENUITEM "new-menuitem"
#define DBUSMENU_CLIENT_SIGNAL_ITEM_ACTIVATE "item-activate"
#define DBUSMENU_CLIENT_SIGNAL_EVENT_RESULT "event-result"
+#define DBUSMENU_CLIENT_SIGNAL_TEXT_DIRECTION_CHANGED "text-direction-changed"
#define DBUSMENU_CLIENT_PROP_DBUS_NAME "dbus-name"
#define DBUSMENU_CLIENT_PROP_DBUS_OBJECT "dbus-object"
+#define DBUSMENU_CLIENT_PROP_STATUS "status"
+#define DBUSMENU_CLIENT_PROP_TEXT_DIRECTION "text-direction"
#define DBUSMENU_CLIENT_TYPES_DEFAULT "standard"
#define DBUSMENU_CLIENT_TYPES_SEPARATOR "separator"
@@ -155,6 +159,8 @@ void dbusmenu_client_send_about_to_show(DbusmenuClient * client,
gint id,
void (*cb) (gpointer user_data),
gpointer cb_data);
+DbusmenuTextDirection dbusmenu_client_get_text_direction (DbusmenuClient * client);
+DbusmenuStatus dbusmenu_client_get_status (DbusmenuClient * client);
/**
SECTION:client
diff --git a/libdbusmenu-glib/dbus-menu-clean.xml.c b/libdbusmenu-glib/dbus-menu-clean.xml.c
index 475adb5..4925a3e 100644
--- a/libdbusmenu-glib/dbus-menu-clean.xml.c
+++ b/libdbusmenu-glib/dbus-menu-clean.xml.c
@@ -10,6 +10,14 @@ const char * dbus_menu_clean_xml =
" \n"
" </property>\n"
"\n"
+" <property name=\"text-direction\" type=\"s\" access=\"read\">\n"
+" \n"
+" </property>\n"
+"\n"
+" <property name=\"state\" type=\"s\" access=\"read\">\n"
+" \n"
+" </property>\n"
+"\n"
"\n"
"\n"
" <method name=\"GetLayout\">\n"
diff --git a/libdbusmenu-glib/dbus-menu.xml b/libdbusmenu-glib/dbus-menu.xml
index c0831e5..829c16e 100644
--- a/libdbusmenu-glib/dbus-menu.xml
+++ b/libdbusmenu-glib/dbus-menu.xml
@@ -171,6 +171,24 @@ License version 3 and version 2.1 along with this program. If not, see
</dox:d>
</property>
+ <property name="text-direction" type="s" access="read">
+ <dox:d>
+ Represents the way the text direction of the application. This
+ allows the server to handle mismatches intelligently. For left-
+ to-right the string is "ltr" for right-to-left it is "rtl".
+ </dox:d>
+ </property>
+
+ <property name="state" type="s" access="read">
+ <dox:d>
+ Tells if the menus are in a normal state or they believe that they
+ could use some attention. Cases for showing them would be if help
+ were referring to them or they accessors were being highlighted.
+ This property can have two values: "normal" in almost all cases and
+ "notice" when they should have a higher priority to be shown.
+ </dox:d>
+ </property>
+
<!-- Functions -->
<method name="GetLayout">
diff --git a/libdbusmenu-glib/enum-types.c b/libdbusmenu-glib/enum-types.c
new file mode 100644
index 0000000..dae615c
--- /dev/null
+++ b/libdbusmenu-glib/enum-types.c
@@ -0,0 +1,183 @@
+
+/* Generated data (by glib-mkenums) */
+
+/*
+Enums from the dbusmenu headers
+
+Copyright 2011 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 either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the
+ Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, 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 applicable version of the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public
+License version 3 and version 2.1 along with this program. If not, see
+<http://www.gnu.org/licenses/>
+*/
+
+#include "enum-types.h"
+
+#include "./types.h"
+/**
+ dbusmenu_text_direction_get_type:
+
+ Builds a GLib type for the #DbusmenuTextDirection enumeration.
+
+ Return value: A unique #GType for the #DbusmenuTextDirection enum.
+*/
+GType
+dbusmenu_text_direction_get_type (void)
+{
+ static GType etype = 0;
+ if (G_UNLIKELY(etype == 0)) {
+ static const GEnumValue values[] = {
+ { DBUSMENU_TEXT_DIRECTION_NONE, "DBUSMENU_TEXT_DIRECTION_NONE", "none" },
+ { DBUSMENU_TEXT_DIRECTION_LTR, "DBUSMENU_TEXT_DIRECTION_LTR", "ltr" },
+ { DBUSMENU_TEXT_DIRECTION_RTL, "DBUSMENU_TEXT_DIRECTION_RTL", "rtl" },
+ { 0, NULL, NULL}
+ };
+
+ etype = g_enum_register_static (g_intern_static_string("DbusmenuTextDirection"), values);
+ }
+
+ return etype;
+}
+
+/**
+ dbusmenu_text_direction_get_nick:
+ @value: The value of DbusmenuTextDirection to get the nick of
+
+ Looks up in the enum table for the nick of @value.
+
+ Return value: The nick for the given value or #NULL on error
+*/
+const gchar *
+dbusmenu_text_direction_get_nick (DbusmenuTextDirection value)
+{
+ GEnumClass * class = G_ENUM_CLASS(g_type_class_ref(dbusmenu_text_direction_get_type()));
+ g_return_val_if_fail(class != NULL, NULL);
+
+ const gchar * ret = NULL;
+ GEnumValue * val = g_enum_get_value(class, value);
+ if (val != NULL) {
+ ret = val->value_nick;
+ }
+
+ g_type_class_unref(class);
+ return ret;
+}
+
+/**
+ dbusmenu_text_direction_get_value_from_nick:
+ @nick: The enum nick to lookup
+
+ Looks up in the enum table for the value of @nick.
+
+ Return value: The value for the given @nick
+*/
+DbusmenuTextDirection
+dbusmenu_text_direction_get_value_from_nick (const gchar * nick)
+{
+ GEnumClass * class = G_ENUM_CLASS(g_type_class_ref(dbusmenu_text_direction_get_type()));
+ g_return_val_if_fail(class != NULL, 0);
+
+ DbusmenuTextDirection ret = 0;
+ GEnumValue * val = g_enum_get_value_by_nick(class, nick);
+ if (val != NULL) {
+ ret = val->value;
+ }
+
+ g_type_class_unref(class);
+ return ret;
+}
+
+
+/**
+ dbusmenu_status_get_type:
+
+ Builds a GLib type for the #DbusmenuStatus enumeration.
+
+ Return value: A unique #GType for the #DbusmenuStatus enum.
+*/
+GType
+dbusmenu_status_get_type (void)
+{
+ static GType etype = 0;
+ if (G_UNLIKELY(etype == 0)) {
+ static const GEnumValue values[] = {
+ { DBUSMENU_STATUS_NORMAL, "DBUSMENU_STATUS_NORMAL", "normal" },
+ { DBUSMENU_STATUS_NOTICE, "DBUSMENU_STATUS_NOTICE", "notice" },
+ { 0, NULL, NULL}
+ };
+
+ etype = g_enum_register_static (g_intern_static_string("DbusmenuStatus"), values);
+ }
+
+ return etype;
+}
+
+/**
+ dbusmenu_status_get_nick:
+ @value: The value of DbusmenuStatus to get the nick of
+
+ Looks up in the enum table for the nick of @value.
+
+ Return value: The nick for the given value or #NULL on error
+*/
+const gchar *
+dbusmenu_status_get_nick (DbusmenuStatus value)
+{
+ GEnumClass * class = G_ENUM_CLASS(g_type_class_ref(dbusmenu_status_get_type()));
+ g_return_val_if_fail(class != NULL, NULL);
+
+ const gchar * ret = NULL;
+ GEnumValue * val = g_enum_get_value(class, value);
+ if (val != NULL) {
+ ret = val->value_nick;
+ }
+
+ g_type_class_unref(class);
+ return ret;
+}
+
+/**
+ dbusmenu_status_get_value_from_nick:
+ @nick: The enum nick to lookup
+
+ Looks up in the enum table for the value of @nick.
+
+ Return value: The value for the given @nick
+*/
+DbusmenuStatus
+dbusmenu_status_get_value_from_nick (const gchar * nick)
+{
+ GEnumClass * class = G_ENUM_CLASS(g_type_class_ref(dbusmenu_status_get_type()));
+ g_return_val_if_fail(class != NULL, 0);
+
+ DbusmenuStatus ret = 0;
+ GEnumValue * val = g_enum_get_value_by_nick(class, nick);
+ if (val != NULL) {
+ ret = val->value;
+ }
+
+ g_type_class_unref(class);
+ return ret;
+}
+
+
+
+/* Generated data ends here */
+
diff --git a/libdbusmenu-glib/enum-types.c.in b/libdbusmenu-glib/enum-types.c.in
new file mode 100644
index 0000000..9395f5f
--- /dev/null
+++ b/libdbusmenu-glib/enum-types.c.in
@@ -0,0 +1,116 @@
+/*** BEGIN file-header ***/
+/*
+Enums from the dbusmenu headers
+
+Copyright 2011 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 either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the
+ Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, 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 applicable version of the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public
+License version 3 and version 2.1 along with this program. If not, see
+<http://www.gnu.org/licenses/>
+*/
+
+#include "enum-types.h"
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+#include "@filename@"
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+/**
+ @enum_name@_get_type:
+
+ Builds a GLib type for the #@EnumName@ enumeration.
+
+ Return value: A unique #GType for the #@EnumName@ enum.
+*/
+GType
+@enum_name@_get_type (void)
+{
+ static GType etype = 0;
+ if (G_UNLIKELY(etype == 0)) {
+ static const G@Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+ { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+ { 0, NULL, NULL}
+ };
+
+ etype = g_@type@_register_static (g_intern_static_string("@EnumName@"), values);
+ }
+
+ return etype;
+}
+
+/**
+ @enum_name@_get_nick:
+ @value: The value of @EnumName@ to get the nick of
+
+ Looks up in the enum table for the nick of @value.
+
+ Return value: The nick for the given value or #NULL on error
+*/
+const gchar *
+@enum_name@_get_nick (@EnumName@ value)
+{
+ GEnumClass * class = G_ENUM_CLASS(g_type_class_ref(@enum_name@_get_type()));
+ g_return_val_if_fail(class != NULL, NULL);
+
+ const gchar * ret = NULL;
+ GEnumValue * val = g_enum_get_value(class, value);
+ if (val != NULL) {
+ ret = val->value_nick;
+ }
+
+ g_type_class_unref(class);
+ return ret;
+}
+
+/**
+ @enum_name@_get_value_from_nick:
+ @nick: The enum nick to lookup
+
+ Looks up in the enum table for the value of @nick.
+
+ Return value: The value for the given @nick
+*/
+@EnumName@
+@enum_name@_get_value_from_nick (const gchar * nick)
+{
+ GEnumClass * class = G_ENUM_CLASS(g_type_class_ref(@enum_name@_get_type()));
+ g_return_val_if_fail(class != NULL, 0);
+
+ @EnumName@ ret = 0;
+ GEnumValue * val = g_enum_get_value_by_nick(class, nick);
+ if (val != NULL) {
+ ret = val->value;
+ }
+
+ g_type_class_unref(class);
+ return ret;
+}
+
+
+/*** END value-tail ***/
diff --git a/libdbusmenu-glib/enum-types.h b/libdbusmenu-glib/enum-types.h
new file mode 100644
index 0000000..c370210
--- /dev/null
+++ b/libdbusmenu-glib/enum-types.h
@@ -0,0 +1,56 @@
+
+/* Generated data (by glib-mkenums) */
+
+/*
+Enums from the dbusmenu headers
+
+Copyright 2011 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 either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the
+ Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, 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 applicable version of the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public
+License version 3 and version 2.1 along with this program. If not, see
+<http://www.gnu.org/licenses/>
+*/
+
+#ifndef __DBUSMENU_ENUM_TYPES_H__
+#define __DBUSMENU_ENUM_TYPES_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* Enumerations from file: "./types.h" */
+#include "./types.h"
+GType dbusmenu_text_direction_get_type (void) G_GNUC_CONST;
+const gchar * dbusmenu_text_direction_get_nick (DbusmenuTextDirection value) G_GNUC_CONST;
+DbusmenuTextDirection dbusmenu_text_direction_get_value_from_nick (const gchar * nick) G_GNUC_CONST;
+#define DBUSMENU_TYPE_TEXT_DIRECTION (dbusmenu_text_direction_get_type())
+
+GType dbusmenu_status_get_type (void) G_GNUC_CONST;
+const gchar * dbusmenu_status_get_nick (DbusmenuStatus value) G_GNUC_CONST;
+DbusmenuStatus dbusmenu_status_get_value_from_nick (const gchar * nick) G_GNUC_CONST;
+#define DBUSMENU_TYPE_STATUS (dbusmenu_status_get_type())
+
+
+G_END_DECLS
+
+#endif /* __DBUSMENU_ENUM_TYPES_H__ */
+
+/* Generated data ends here */
+
diff --git a/libdbusmenu-glib/enum-types.h.in b/libdbusmenu-glib/enum-types.h.in
new file mode 100644
index 0000000..8c5f463
--- /dev/null
+++ b/libdbusmenu-glib/enum-types.h.in
@@ -0,0 +1,56 @@
+/*** BEGIN file-header ***/
+/*
+Enums from the dbusmenu headers
+
+Copyright 2011 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 either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the
+ Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, 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 applicable version of the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public
+License version 3 and version 2.1 along with this program. If not, see
+<http://www.gnu.org/licenses/>
+*/
+
+#ifndef __DBUSMENU_ENUM_TYPES_H__
+#define __DBUSMENU_ENUM_TYPES_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/*** END file-header ***/
+
+/*** BEGIN file-tail ***/
+
+G_END_DECLS
+
+#endif /* __DBUSMENU_ENUM_TYPES_H__ */
+/*** END file-tail ***/
+
+/*** BEGIN file-production ***/
+/* Enumerations from file: "@filename@" */
+#include "@filename@"
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType @enum_name@_get_type (void) G_GNUC_CONST;
+const gchar * @enum_name@_get_nick (@EnumName@ value) G_GNUC_CONST;
+@EnumName@ @enum_name@_get_value_from_nick (const gchar * nick) G_GNUC_CONST;
+#define DBUSMENU_TYPE_@ENUMSHORT@ (@enum_name@_get_type())
+
+/*** END value-header ***/
diff --git a/libdbusmenu-glib/menuitem-marshal.c b/libdbusmenu-glib/menuitem-marshal.c
index bb2b6d7..de227fd 100644
--- a/libdbusmenu-glib/menuitem-marshal.c
+++ b/libdbusmenu-glib/menuitem-marshal.c
@@ -168,3 +168,46 @@ _dbusmenu_menuitem_marshal_VOID__OBJECT_UINT (GClosure *closure,
/* VOID:UINT (./menuitem-marshal.list:6) */
+/* BOOLEAN:STRING,VARIANT,UINT (./menuitem-marshal.list:7) */
+void
+_dbusmenu_menuitem_marshal_BOOLEAN__STRING_VARIANT_UINT (GClosure *closure,
+ GValue *return_value G_GNUC_UNUSED,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint G_GNUC_UNUSED,
+ gpointer marshal_data)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__STRING_VARIANT_UINT) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ guint arg_3,
+ gpointer data2);
+ register GMarshalFunc_BOOLEAN__STRING_VARIANT_UINT callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+ gboolean v_return;
+
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 4);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__STRING_VARIANT_UINT) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ g_marshal_value_peek_string (param_values + 1),
+ g_marshal_value_peek_variant (param_values + 2),
+ g_marshal_value_peek_uint (param_values + 3),
+ data2);
+
+ g_value_set_boolean (return_value, v_return);
+}
+
diff --git a/libdbusmenu-glib/menuitem-marshal.h b/libdbusmenu-glib/menuitem-marshal.h
index 0cde7ad..0315ae8 100644
--- a/libdbusmenu-glib/menuitem-marshal.h
+++ b/libdbusmenu-glib/menuitem-marshal.h
@@ -39,6 +39,14 @@ extern void _dbusmenu_menuitem_marshal_VOID__OBJECT_UINT (GClosure *closure,
/* VOID:UINT (./menuitem-marshal.list:6) */
#define _dbusmenu_menuitem_marshal_VOID__UINT g_cclosure_marshal_VOID__UINT
+/* BOOLEAN:STRING,VARIANT,UINT (./menuitem-marshal.list:7) */
+extern void _dbusmenu_menuitem_marshal_BOOLEAN__STRING_VARIANT_UINT (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
G_END_DECLS
#endif /* ___dbusmenu_menuitem_marshal_MARSHAL_H__ */
diff --git a/libdbusmenu-glib/menuitem-marshal.list b/libdbusmenu-glib/menuitem-marshal.list
index e3cb272..4382ed7 100644
--- a/libdbusmenu-glib/menuitem-marshal.list
+++ b/libdbusmenu-glib/menuitem-marshal.list
@@ -4,3 +4,4 @@ VOID: OBJECT, UINT
VOID: OBJECT
VOID: VOID
VOID: UINT
+BOOLEAN: STRING, VARIANT, UINT
diff --git a/libdbusmenu-glib/menuitem-private.h b/libdbusmenu-glib/menuitem-private.h
index 89319dc..336769d 100644
--- a/libdbusmenu-glib/menuitem-private.h
+++ b/libdbusmenu-glib/menuitem-private.h
@@ -38,6 +38,7 @@ gboolean dbusmenu_menuitem_realized (DbusmenuMenuitem * mi);
void dbusmenu_menuitem_set_realized (DbusmenuMenuitem * mi);
GVariant * dbusmenu_menuitem_properties_variant (DbusmenuMenuitem * mi, const gchar ** properties);
gboolean dbusmenu_menuitem_property_is_default (DbusmenuMenuitem * mi, const gchar * property);
+gboolean dbusmenu_menuitem_exposed (DbusmenuMenuitem * mi);
G_END_DECLS
diff --git a/libdbusmenu-glib/menuitem.c b/libdbusmenu-glib/menuitem.c
index 1a39736..9fa0e1a 100644
--- a/libdbusmenu-glib/menuitem.c
+++ b/libdbusmenu-glib/menuitem.c
@@ -61,6 +61,7 @@ struct _DbusmenuMenuitemPrivate
gboolean root;
gboolean realized;
DbusmenuDefaults * defaults;
+ gboolean exposed;
};
/* Signals */
@@ -73,6 +74,7 @@ enum {
REALIZED,
SHOW_TO_USER,
ABOUT_TO_SHOW,
+ EVENT,
LAST_SIGNAL
};
@@ -246,6 +248,23 @@ dbusmenu_menuitem_class_init (DbusmenuMenuitemClass *klass)
NULL, NULL,
_dbusmenu_menuitem_marshal_VOID__VOID,
G_TYPE_BOOLEAN, 0, G_TYPE_NONE);
+ /**
+ DbusmenuMenuitem::event:
+ @arg0: The #DbusmenuMenuitem object.
+ @arg1: Name of the event
+ @arg2: Information passed along with the event
+ @arg3: X11 timestamp of when the event happened
+
+ Emitted when an event is passed through. The event is signalled
+ after handle_event is called.
+ */
+ signals[EVENT] = g_signal_new(DBUSMENU_MENUITEM_SIGNAL_EVENT,
+ G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(DbusmenuMenuitemClass, event),
+ g_signal_accumulator_true_handled, NULL,
+ _dbusmenu_menuitem_marshal_BOOLEAN__STRING_VARIANT_UINT,
+ G_TYPE_BOOLEAN, 3, G_TYPE_STRING, G_TYPE_VARIANT, G_TYPE_UINT);
g_object_class_install_property (object_class, PROP_ID,
g_param_spec_int(PROP_ID_S, "ID for the menu item",
@@ -316,6 +335,7 @@ dbusmenu_menuitem_init (DbusmenuMenuitem *self)
priv->realized = FALSE;
priv->defaults = dbusmenu_defaults_ref_default();
+ priv->exposed = FALSE;
return;
}
@@ -1025,6 +1045,36 @@ dbusmenu_menuitem_property_set_variant (DbusmenuMenuitem * mi, const gchar * pro
g_return_val_if_fail(property != NULL, FALSE);
DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
+ GVariant * default_value = NULL;
+
+ if (value != NULL) {
+ const gchar * type = menuitem_get_type(mi);
+
+ /* Check the expected type to see if we want to have a warning */
+ GVariantType * default_type = dbusmenu_defaults_default_get_type(priv->defaults, type, property);
+ if (default_type != NULL) {
+ /* If we have an expected type we should check to see if
+ the value we've been given is of the same type and generate
+ a warning if it isn't */
+ if (!g_variant_is_of_type(value, default_type)) {
+ g_warning("Setting menuitem property '%s' with value of type '%s' when expecting '%s'", property, g_variant_get_type_string(value), g_variant_type_peek_string(default_type));
+ }
+ }
+
+ /* Check the defaults database to see if we have a default
+ for this property. */
+ default_value = dbusmenu_defaults_default_get(priv->defaults, type, property);
+ if (default_value != NULL) {
+ /* Now see if we're setting this to the same value as the
+ default. If we are then we just want to swallow this variant
+ and make the function behave like we're clearing it. */
+ if (g_variant_equal(default_value, value)) {
+ g_variant_ref_sink(value);
+ g_variant_unref(value);
+ value = NULL;
+ }
+ }
+ }
const gchar * type = menuitem_get_type(mi);
@@ -1343,7 +1393,7 @@ dbusmenu_menuitem_properties_variant (DbusmenuMenuitem * mi, const gchar ** prop
GVariant * final_variant = NULL;
- if (properties == NULL && g_hash_table_size(priv->properties) > 0) {
+ if ((properties == NULL || properties[0] == NULL) && g_hash_table_size(priv->properties) > 0) {
GVariantBuilder builder;
g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
@@ -1436,6 +1486,8 @@ GVariant *
dbusmenu_menuitem_build_variant (DbusmenuMenuitem * mi, const gchar ** properties, gint recurse)
{
g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), NULL);
+ DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
+ priv->exposed = TRUE;
gint id = 0;
if (!dbusmenu_menuitem_get_root(mi)) {
@@ -1460,7 +1512,7 @@ dbusmenu_menuitem_build_variant (DbusmenuMenuitem * mi, const gchar ** propertie
/* Pillage the children */
GList * children = dbusmenu_menuitem_get_children(mi);
- if (children == NULL && recurse != 0) {
+ if (children == NULL || recurse == 0) {
g_variant_builder_add_value(&tupleb, g_variant_new_array(G_VARIANT_TYPE_VARIANT, NULL, 0));
} else {
GVariantBuilder childrenbuilder;
@@ -1542,9 +1594,13 @@ dbusmenu_menuitem_handle_event (DbusmenuMenuitem * mi, const gchar * name, GVari
#endif
DbusmenuMenuitemClass * class = DBUSMENU_MENUITEM_GET_CLASS(mi);
- if (class->handle_event != NULL) {
+ gboolean handled = FALSE;
+ g_signal_emit(G_OBJECT(mi), EVENT, g_quark_from_string(name), name, variant, timestamp, &handled);
+
+ if (!handled && class->handle_event != NULL) {
return class->handle_event(mi, name, variant, timestamp);
}
+
return;
}
@@ -1618,3 +1674,13 @@ dbusmenu_menuitem_property_is_default (DbusmenuMenuitem * mi, const gchar * prop
g_warn_if_reached();
return FALSE;
}
+
+/* Check to see if this menu item has been sent into the bus yet or
+ not. If no one cares we can give less info */
+gboolean
+dbusmenu_menuitem_exposed (DbusmenuMenuitem * mi)
+{
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), FALSE);
+ DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
+ return priv->exposed;
+}
diff --git a/libdbusmenu-glib/menuitem.h b/libdbusmenu-glib/menuitem.h
index afd6084..35d7ca8 100644
--- a/libdbusmenu-glib/menuitem.h
+++ b/libdbusmenu-glib/menuitem.h
@@ -51,6 +51,7 @@ G_BEGIN_DECLS
#define DBUSMENU_MENUITEM_SIGNAL_REALIZED_ID (g_signal_lookup(DBUSMENU_MENUITEM_SIGNAL_REALIZED, DBUSMENU_TYPE_MENUITEM))
#define DBUSMENU_MENUITEM_SIGNAL_SHOW_TO_USER "show-to-user"
#define DBUSMENU_MENUITEM_SIGNAL_ABOUT_TO_SHOW "about-to-show"
+#define DBUSMENU_MENUITEM_SIGNAL_EVENT "event"
#define DBUSMENU_MENUITEM_PROP_TYPE "type"
#define DBUSMENU_MENUITEM_PROP_VISIBLE "visible"
@@ -134,6 +135,7 @@ typedef GVariant * (*dbusmenu_menuitem_buildvariant_slot_t) (DbusmenuMenuitem *
* @handle_event: This function is to override how events are handled by subclasses. Look at #dbusmenu_menuitem_handle_event for lots of good information.
* @send_about_to_show: Virtual function that notifies server that the client is about to show a menu.
* @show_to_user: Slot for #DbusmenuMenuitem::show-to-user.
+ * @event: Slot for #DbsumenuMenuitem::event.
*
* @reserved1: Reserved for future use.
* @reserved2: Reserved for future use.
@@ -163,13 +165,14 @@ struct _DbusmenuMenuitemClass
void (*show_to_user) (DbusmenuMenuitem * mi, guint timestamp, gpointer cb_data);
gboolean (*about_to_show) (void);
+ void (*event) (const gchar * name, GVariant * value, guint timestamp);
+
/*< Private >*/
void (*reserved1) (void);
void (*reserved2) (void);
void (*reserved3) (void);
void (*reserved4) (void);
void (*reserved5) (void);
- void (*reserved6) (void);
};
GType dbusmenu_menuitem_get_type (void);
diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c
index de8a9b9..c3faa6b 100644
--- a/libdbusmenu-glib/server.c
+++ b/libdbusmenu-glib/server.c
@@ -30,11 +30,13 @@ License version 3 and version 2.1 along with this program. If not, see
#include "config.h"
#endif
+#include <glib/gi18n.h>
#include <gio/gio.h>
#include "menuitem-private.h"
#include "server.h"
#include "server-marshal.h"
+#include "enum-types.h"
#include "dbus-menu-clean.xml.h"
@@ -55,6 +57,9 @@ struct _DbusmenuServerPrivate
GCancellable * bus_lookup;
guint dbus_registration;
+ DbusmenuTextDirection text_direction;
+ DbusmenuStatus status;
+
GArray * prop_array;
guint property_idle;
};
@@ -77,7 +82,9 @@ enum {
PROP_0,
PROP_DBUS_OBJECT,
PROP_ROOT_NODE,
- PROP_VERSION
+ PROP_VERSION,
+ PROP_TEXT_DIRECTION,
+ PROP_STATUS
};
/* Errors */
@@ -124,6 +131,7 @@ static void get_property (GObject * obj,
guint id,
GValue * value,
GParamSpec * pspec);
+static void default_text_direction (DbusmenuServer * server);
static void register_object (DbusmenuServer * server);
static void bus_got_cb (GObject * obj,
GAsyncResult * result,
@@ -289,6 +297,16 @@ dbusmenu_server_class_init (DbusmenuServerClass *class)
"The version of the DBusmenu API that we're implementing.",
DBUSMENU_VERSION_NUMBER, DBUSMENU_VERSION_NUMBER, DBUSMENU_VERSION_NUMBER,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class, PROP_TEXT_DIRECTION,
+ g_param_spec_enum(DBUSMENU_SERVER_PROP_TEXT_DIRECTION, "The default direction of text",
+ "The object that represents this set of menus on DBus",
+ DBUSMENU_TYPE_TEXT_DIRECTION, DBUSMENU_TEXT_DIRECTION_NONE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class, PROP_STATUS,
+ g_param_spec_enum(DBUSMENU_SERVER_PROP_STATUS, "Status of viewing the menus",
+ "Exports over DBus whether the menus should be given special visuals",
+ DBUSMENU_TYPE_STATUS, DBUSMENU_STATUS_NORMAL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
if (dbusmenu_node_info == NULL) {
GError * error = NULL;
@@ -348,6 +366,9 @@ dbusmenu_server_init (DbusmenuServer *self)
priv->bus_lookup = NULL;
priv->dbus_registration = 0;
+ default_text_direction(self);
+ priv->status = DBUSMENU_STATUS_NORMAL;
+
return;
}
@@ -463,6 +484,64 @@ set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec)
}
layout_update_signal(DBUSMENU_SERVER(obj));
break;
+ case PROP_TEXT_DIRECTION: {
+ DbusmenuTextDirection indir = g_value_get_enum(value);
+ DbusmenuTextDirection olddir = priv->text_direction;
+
+ /* If being set to none we need to go back to default, otherwise
+ we'll set things the way that we've been told */
+ if (indir == DBUSMENU_TEXT_DIRECTION_NONE) {
+ default_text_direction(DBUSMENU_SERVER(obj));
+ } else {
+ priv->text_direction = indir;
+ }
+
+ /* If the value has changed we need to signal that on DBus */
+ if (priv->text_direction != olddir && priv->bus != NULL && priv->dbusobject != NULL) {
+ GVariantBuilder params;
+ g_variant_builder_init(&params, G_VARIANT_TYPE_ARRAY);
+ g_variant_builder_add_value(&params, g_variant_new_string(DBUSMENU_INTERFACE));
+ GVariant * dict = g_variant_new_dict_entry(g_variant_new_string("text-direction"), g_variant_new_string(dbusmenu_text_direction_get_nick(priv->text_direction)));
+ g_variant_builder_add_value(&params, g_variant_new_array(NULL, &dict, 1));
+ g_variant_builder_add_value(&params, g_variant_new_array(G_VARIANT_TYPE_STRING, NULL, 0));
+ GVariant * vparams = g_variant_builder_end(&params);
+
+ g_dbus_connection_emit_signal(priv->bus,
+ NULL,
+ priv->dbusobject,
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ vparams,
+ NULL);
+ }
+
+ break;
+ }
+ case PROP_STATUS: {
+ DbusmenuStatus instatus = g_value_get_enum(value);
+
+ /* If the value has changed we need to signal that on DBus */
+ if (priv->status != instatus && priv->bus != NULL && priv->dbusobject != NULL) {
+ GVariantBuilder params;
+ g_variant_builder_init(&params, G_VARIANT_TYPE_ARRAY);
+ g_variant_builder_add_value(&params, g_variant_new_string(DBUSMENU_INTERFACE));
+ GVariant * dict = g_variant_new_dict_entry(g_variant_new_string("status"), g_variant_new_string(dbusmenu_status_get_nick(instatus)));
+ g_variant_builder_add_value(&params, g_variant_new_array(NULL, &dict, 1));
+ g_variant_builder_add_value(&params, g_variant_new_array(G_VARIANT_TYPE_STRING, NULL, 0));
+ GVariant * vparams = g_variant_builder_end(&params);
+
+ g_dbus_connection_emit_signal(priv->bus,
+ NULL,
+ priv->dbusobject,
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ vparams,
+ NULL);
+ }
+
+ priv->status = instatus;
+ break;
+ }
default:
g_return_if_reached();
break;
@@ -486,6 +565,12 @@ get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec)
case PROP_VERSION:
g_value_set_uint(value, DBUSMENU_VERSION_NUMBER);
break;
+ case PROP_TEXT_DIRECTION:
+ g_value_set_enum(value, priv->text_direction);
+ break;
+ case PROP_STATUS:
+ g_value_set_enum(value, priv->status);
+ break;
default:
g_return_if_reached();
break;
@@ -494,6 +579,49 @@ get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec)
return;
}
+/* Determines the default text direction */
+static void
+default_text_direction (DbusmenuServer * server)
+{
+ DbusmenuTextDirection dir = DBUSMENU_TEXT_DIRECTION_NONE;
+ DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server);
+
+ const gchar * env = g_getenv("DBUSMENU_TEXT_DIRECTION");
+ if (env != NULL) {
+ if (g_strcmp0(env, "ltr") == 0) {
+ dir = DBUSMENU_TEXT_DIRECTION_LTR;
+ } else if (g_strcmp0(env, "rtl") == 0) {
+ dir = DBUSMENU_TEXT_DIRECTION_RTL;
+ } else {
+ g_warning("Value of 'DBUSMENU_TEXT_DIRECTION' is '%s' which is not one of 'rtl' or 'ltr'", env);
+ }
+ }
+
+ if (dir == DBUSMENU_TEXT_DIRECTION_NONE) {
+ /* TRANSLATORS: This is the direction of the text and can
+ either be the value 'ltr' for left-to-right text (English)
+ or 'rtl' for right-to-left (Arabic). */
+ const gchar * default_dir = C_("default text direction", "ltr");
+
+ if (g_strcmp0(default_dir, "ltr") == 0) {
+ dir = DBUSMENU_TEXT_DIRECTION_LTR;
+ } else if (g_strcmp0(default_dir, "rtl") == 0) {
+ dir = DBUSMENU_TEXT_DIRECTION_RTL;
+ } else {
+ g_warning("Translation has an invalid value '%s' for default text direction. Defaulting to left-to-right.", default_dir);
+ dir = DBUSMENU_TEXT_DIRECTION_LTR;
+ }
+ }
+
+ /* Shouldn't happen, but incase future patches make a mistake
+ this'll catch them */
+ g_return_if_fail(dir != DBUSMENU_TEXT_DIRECTION_NONE);
+
+ priv->text_direction = dir;
+
+ return;
+}
+
/* Register the object on the dbus bus */
static void
register_object (DbusmenuServer * server)
@@ -611,9 +739,16 @@ bus_get_prop (GDBusConnection * connection, const gchar * sender, const gchar *
/* None of these should happen */
g_return_val_if_fail(g_strcmp0(interface, DBUSMENU_INTERFACE) == 0, NULL);
g_return_val_if_fail(g_strcmp0(path, priv->dbusobject) == 0, NULL);
- g_return_val_if_fail(g_strcmp0(property, "version") == 0, NULL);
- return g_variant_new_uint32(DBUSMENU_VERSION_NUMBER);
+ if (g_strcmp0(property, "version") == 0) {
+ return g_variant_new_uint32(DBUSMENU_VERSION_NUMBER);
+ } else if (g_strcmp0(property, "text-direction") == 0) {
+ return g_variant_new_string(dbusmenu_text_direction_get_nick(priv->text_direction));
+ } else {
+ g_warning("Unknown property '%s'", property);
+ }
+
+ return NULL;
}
/* Handle actually signalling in the idle loop. This way we collect all
@@ -656,7 +791,7 @@ layout_update_signal (DbusmenuServer * server)
typedef struct _prop_idle_item_t prop_idle_item_t;
struct _prop_idle_item_t {
- gint id;
+ DbusmenuMenuitem * mi;
GArray * array;
};
@@ -686,6 +821,7 @@ prop_array_teardown (GArray * prop_array)
}
}
+ g_object_unref(G_OBJECT(iitem->mi));
g_array_free(iitem->array, TRUE);
}
@@ -719,6 +855,12 @@ menuitem_property_idle (gpointer user_data)
for (i = 0; i < priv->prop_array->len; i++) {
prop_idle_item_t * iitem = &g_array_index(priv->prop_array, prop_idle_item_t, i);
+ /* if it's not exposed we're going to block it's properties
+ from getting into the dbus message */
+ if (dbusmenu_menuitem_exposed(iitem->mi) == FALSE) {
+ continue;
+ }
+
GVariantBuilder dictbuilder;
gboolean dictinit = FALSE;
@@ -756,7 +898,7 @@ menuitem_property_idle (gpointer user_data)
GVariantBuilder tuplebuilder;
g_variant_builder_init(&tuplebuilder, G_VARIANT_TYPE_TUPLE);
- g_variant_builder_add_value(&tuplebuilder, g_variant_new_int32(iitem->id));
+ g_variant_builder_add_value(&tuplebuilder, g_variant_new_int32(dbusmenu_menuitem_get_id(iitem->mi)));
g_variant_builder_add_value(&tuplebuilder, g_variant_builder_end(&dictbuilder));
if (!item_init) {
@@ -773,7 +915,7 @@ menuitem_property_idle (gpointer user_data)
GVariantBuilder tuplebuilder;
g_variant_builder_init(&tuplebuilder, G_VARIANT_TYPE_TUPLE);
- g_variant_builder_add_value(&tuplebuilder, g_variant_new_int32(iitem->id));
+ g_variant_builder_add_value(&tuplebuilder, g_variant_new_int32(dbusmenu_menuitem_get_id(iitem->mi)));
g_variant_builder_add_value(&tuplebuilder, g_variant_builder_end(&removedictbuilder));
if (!removeitem_init) {
@@ -786,9 +928,11 @@ menuitem_property_idle (gpointer user_data)
}
GVariant * megadata[2];
+ gboolean gotsomething = FALSE;
if (item_init) {
megadata[0] = g_variant_builder_end(&itembuilder);
+ gotsomething = TRUE;
} else {
GError * error = NULL;
megadata[0] = g_variant_parse(G_VARIANT_TYPE("a(ia{sv})"), "[ ]", NULL, NULL, &error);
@@ -801,6 +945,7 @@ menuitem_property_idle (gpointer user_data)
if (removeitem_init) {
megadata[1] = g_variant_builder_end(&removeitembuilder);
+ gotsomething = TRUE;
} else {
GError * error = NULL;
megadata[1] = g_variant_parse(G_VARIANT_TYPE("a(ia(s))"), "[ ]", NULL, NULL, &error);
@@ -811,7 +956,7 @@ menuitem_property_idle (gpointer user_data)
}
}
- if (priv->dbusobject != NULL && priv->bus != NULL) {
+ if (gotsomething && priv->dbusobject != NULL && priv->bus != NULL) {
g_dbus_connection_emit_signal(priv->bus,
NULL,
priv->dbusobject,
@@ -854,7 +999,7 @@ menuitem_property_changed (DbusmenuMenuitem * mi, gchar * property, GVariant * v
prop_idle_item_t * item = NULL;
for (i = 0; i < priv->prop_array->len; i++) {
prop_idle_item_t * iitem = &g_array_index(priv->prop_array, prop_idle_item_t, i);
- if (iitem->id == item_id) {
+ if (iitem->mi == mi) {
item = iitem;
break;
}
@@ -864,7 +1009,8 @@ menuitem_property_changed (DbusmenuMenuitem * mi, gchar * property, GVariant * v
/* If not, we'll need to build ourselves one */
if (item == NULL) {
prop_idle_item_t myitem;
- myitem.id = item_id;
+ myitem.mi = mi;
+ g_object_ref(G_OBJECT(mi));
myitem.array = g_array_new(FALSE, FALSE, sizeof(prop_idle_prop_t));
g_array_append_val(priv->prop_array, myitem);
@@ -1460,5 +1606,95 @@ dbusmenu_server_set_root (DbusmenuServer * self, DbusmenuMenuitem * root)
return;
}
+/**
+ dbusmenu_server_get_text_direction:
+ @server: The #DbusmenuServer object to get the text direction from
+
+ Returns the value of the text direction that is being exported
+ over DBus for this server. It should relate to the direction
+ of the labels and other text fields that are being exported by
+ this server.
+
+ Return value: Text direction exported for this server.
+*/
+DbusmenuTextDirection
+dbusmenu_server_get_text_direction (DbusmenuServer * server)
+{
+ g_return_val_if_fail(DBUSMENU_IS_SERVER(server), DBUSMENU_TEXT_DIRECTION_NONE);
+
+ GValue val = {0};
+ g_value_init(&val, DBUSMENU_TYPE_TEXT_DIRECTION);
+ g_object_get_property(G_OBJECT(server), DBUSMENU_SERVER_PROP_TEXT_DIRECTION, &val);
+
+ DbusmenuTextDirection retval = g_value_get_enum(&val);
+ g_value_unset(&val);
+
+ return retval;
+}
+
+/**
+ dbusmenu_server_set_text_direction:
+ @server: The #DbusmenuServer object to set the text direction on
+ Sets the text direction that should be exported over DBus for
+ this server. If the value is set to #DBUSMENU_TEXT_DIRECTION_NONE
+ the default detection will be used for setting the value and
+ exported over DBus.
+*/
+void
+dbusmenu_server_set_text_direction (DbusmenuServer * server, DbusmenuTextDirection dir)
+{
+ g_return_if_fail(DBUSMENU_IS_SERVER(server));
+ g_return_if_fail(dir == DBUSMENU_TEXT_DIRECTION_NONE || dir == DBUSMENU_TEXT_DIRECTION_LTR || dir == DBUSMENU_TEXT_DIRECTION_RTL);
+
+ GValue newval = {0};
+ g_value_init(&newval, DBUSMENU_TYPE_TEXT_DIRECTION);
+ g_value_set_enum(&newval, dir);
+ g_object_set_property(G_OBJECT(server), DBUSMENU_SERVER_PROP_TEXT_DIRECTION, &newval);
+ g_value_unset(&newval);
+ return;
+}
+/**
+ dbusmenu_server_get_status:
+ @server: The #DbusmenuServer to get the status from
+
+ Gets the current statust hat the server is sending out over
+ DBus.
+
+ Return value: The current status the server is sending
+*/
+DbusmenuStatus
+dbusmenu_server_get_status (DbusmenuServer * server)
+{
+ g_return_val_if_fail(DBUSMENU_IS_SERVER(server), DBUSMENU_STATUS_NORMAL);
+
+ GValue val = {0};
+ g_value_init(&val, DBUSMENU_TYPE_STATUS);
+ g_object_get_property(G_OBJECT(server), DBUSMENU_SERVER_PROP_STATUS, &val);
+
+ DbusmenuStatus retval = g_value_get_enum(&val);
+ g_value_unset(&val);
+
+ return retval;
+}
+
+/**
+ dbusmenu_server_set_status:
+ @server: The #DbusmenuServer to set the status on
+
+ Changes the status of the server.
+*/
+void
+dbusmenu_server_set_status (DbusmenuServer * server, DbusmenuStatus status)
+{
+ g_return_if_fail(DBUSMENU_IS_SERVER(server));
+
+ GValue val = {0};
+ g_value_init(&val, DBUSMENU_TYPE_STATUS);
+ g_value_set_enum(&val, status);
+ g_object_set_property(G_OBJECT(server), DBUSMENU_SERVER_PROP_STATUS, &val);
+ g_value_unset(&val);
+
+ return;
+}
diff --git a/libdbusmenu-glib/server.h b/libdbusmenu-glib/server.h
index 5668258..54cf5fc 100644
--- a/libdbusmenu-glib/server.h
+++ b/libdbusmenu-glib/server.h
@@ -33,6 +33,7 @@ License version 3 and version 2.1 along with this program. If not, see
#include <glib-object.h>
#include "menuitem.h"
+#include "types.h"
G_BEGIN_DECLS
@@ -52,6 +53,8 @@ G_BEGIN_DECLS
#define DBUSMENU_SERVER_PROP_DBUS_OBJECT "dbus-object"
#define DBUSMENU_SERVER_PROP_ROOT_NODE "root-node"
#define DBUSMENU_SERVER_PROP_VERSION "version"
+#define DBUSMENU_SERVER_PROP_TEXT_DIRECTION "text-direction"
+#define DBUSMENU_SERVER_PROP_STATUS "status"
typedef struct _DbusmenuServerPrivate DbusmenuServerPrivate;
@@ -106,9 +109,16 @@ struct _DbusmenuServer {
DbusmenuServerPrivate * priv;
};
-GType dbusmenu_server_get_type (void);
-DbusmenuServer * dbusmenu_server_new (const gchar * object);
-void dbusmenu_server_set_root (DbusmenuServer * server, DbusmenuMenuitem * root);
+GType dbusmenu_server_get_type (void);
+DbusmenuServer * dbusmenu_server_new (const gchar * object);
+void dbusmenu_server_set_root (DbusmenuServer * server,
+ DbusmenuMenuitem * root);
+DbusmenuTextDirection dbusmenu_server_get_text_direction (DbusmenuServer * server);
+void dbusmenu_server_set_text_direction (DbusmenuServer * server,
+ DbusmenuTextDirection dir);
+DbusmenuStatus dbusmenu_server_get_status (DbusmenuServer * server);
+void dbusmenu_server_set_status (DbusmenuServer * server,
+ DbusmenuStatus status);
/**
SECIONT:server
diff --git a/libdbusmenu-glib/types.h b/libdbusmenu-glib/types.h
new file mode 100644
index 0000000..e573476
--- /dev/null
+++ b/libdbusmenu-glib/types.h
@@ -0,0 +1,65 @@
+/*
+Types that are used in several objects.
+
+Copyright 2011 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 either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the
+Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, 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 applicable version of the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public
+License version 3 and version 2.1 along with this program. If not, see
+<http://www.gnu.org/licenses/>
+*/
+
+#ifndef __DBUSMENU_TYPES_H__
+#define __DBUSMENU_TYPES_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/**
+ DbusmenuTextDirection:
+ @DBUSMENU_TEXT_DIRECTION_NONE: Unspecified text direction
+ @DBUSMENU_TEXT_DIRECTION_LTR: Left-to-right text direction
+ @DBUSMENU_TEXT_DIRECTION_RTL: Right-to-left text direction
+
+ The direction of text that the strings that this server
+ will be sending strings as.
+*/
+typedef enum { /*< prefix=DBUSMENU_TEXT_DIRECTION >*/
+ DBUSMENU_TEXT_DIRECTION_NONE, /*< nick=none >*/
+ DBUSMENU_TEXT_DIRECTION_LTR, /*< nick=ltr >*/
+ DBUSMENU_TEXT_DIRECTION_RTL /*< nick=rtl >*/
+} DbusmenuTextDirection;
+
+/**
+ DbusmenuStatus:
+ @DBUSMENU_STATUS_NORMAL: Everything is normal
+ @DBUSMENU_STATUS_NOTICE: The menus should be shown at a higher priority
+
+ Tracks how the menus should be presented to the user.
+*/
+typedef enum { /*< prefix=DBUSMENU_STATUS >*/
+ DBUSMENU_STATUS_NORMAL, /*< nick=normal >*/
+ DBUSMENU_STATUS_NOTICE /*< nick=notice >*/
+} DbusmenuStatus;
+
+G_END_DECLS
+
+#endif /* __DBUSMENU_TYPES_H__ */
+
diff --git a/po/POTFILES.in b/po/POTFILES.in
index a386915..d6ac240 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1 +1,2 @@
libdbusmenu-glib/defaults.c
+libdbusmenu-glib/server.c