← Back to team overview

ayatana-commits team mailing list archive

[Merge] lp:~ted/dbusmenu/ltr-rtl-property into lp:dbusmenu

 

Ted Gould has proposed merging lp:~ted/dbusmenu/ltr-rtl-property into lp:dbusmenu.

Requested reviews:
  DBus Menu Team (dbusmenu-team)

For more details, see:
https://code.launchpad.net/~ted/dbusmenu/ltr-rtl-property/+merge/50380

Adding tracking of text direction so we can handle cases of mismatched direction between the client and the server.
-- 
https://code.launchpad.net/~ted/dbusmenu/ltr-rtl-property/+merge/50380
Your team ayatana-commits is subscribed to branch lp:dbusmenu.
=== modified file '.bzrignore'
--- .bzrignore	2011-01-27 19:54:18 +0000
+++ .bzrignore	2011-02-18 19:15:28 +0000
@@ -227,3 +227,7 @@
 test-gtk-parser
 test-gtk-parser-test
 test-gtk-parser.xml
+enum-types.c
+enum-types.h
+libdbusmenu_glib_la-enum-types.lo
+stamp-enum-types

=== added file 'Makefile.am.enum'
--- Makefile.am.enum	1970-01-01 00:00:00 +0000
+++ Makefile.am.enum	2011-02-18 19:15:28 +0000
@@ -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@xxxxxxxxxxxxxxx>
+
+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
+

=== modified file 'configure.ac'
--- configure.ac	2011-02-17 16:46:34 +0000
+++ configure.ac	2011-02-18 19:15:28 +0000
@@ -21,6 +21,8 @@
 
 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@:>@])],

=== modified file 'libdbusmenu-glib/Makefile.am'
--- libdbusmenu-glib/Makefile.am	2011-02-09 17:45:41 +0000
+++ libdbusmenu-glib/Makefile.am	2011-02-18 19:15:28 +0000
@@ -1,6 +1,7 @@
 
-CLEANFILES = 
-
+BUILT_SOURCES =
+CLEANFILES =
+DISTCLEANFILES =
 EXTRA_DIST = \
 	clean-namespaces.xslt \
 	dbusmenu-glib-0.4.pc.in \
@@ -9,6 +10,8 @@
 	menuitem-marshal.list \
 	server-marshal.list
 
+include $(top_srcdir)/Makefile.am.enum
+
 lib_LTLIBRARIES = \
 	libdbusmenu-glib.la
 
@@ -19,11 +22,14 @@
 	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 \
+	enum-types.h \
+	enum-types.c \
 	menuitem.h \
 	menuitem.c \
 	menuitem-marshal.h \
@@ -56,6 +62,14 @@
 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 $@))));" > $@
 
@@ -69,7 +83,7 @@
 
 CLEANFILES += dbus-menu-clean.xml
 
-BUILT_SOURCES = \
+BUILT_SOURCES += \
 	dbus-menu-clean.xml.c \
 	dbus-menu-clean.xml.h \
 	client-marshal.h \

=== modified file 'libdbusmenu-glib/client-marshal.list'
--- libdbusmenu-glib/client-marshal.list	2010-11-18 03:11:40 +0000
+++ libdbusmenu-glib/client-marshal.list	2011-02-18 19:15:28 +0000
@@ -1,2 +1,3 @@
 VOID: OBJECT, UINT
 VOID: OBJECT, STRING, VARIANT, UINT, POINTER
+VOID: ENUM

=== modified file 'libdbusmenu-glib/client.c'
--- libdbusmenu-glib/client.c	2011-02-15 17:42:52 +0000
+++ libdbusmenu-glib/client.c	2011-02-18 19:15:28 +0000
@@ -39,6 +39,7 @@
 #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 */
@@ -58,6 +59,7 @@
 	NEW_MENUITEM,
 	ITEM_ACTIVATE,
 	EVENT_RESULT,
+	TEXT_DIRECTION_CHANGED,
 	LAST_SIGNAL
 };
 
@@ -90,6 +92,8 @@
 	GArray * delayed_property_list;
 	GArray * delayed_property_listeners;
 	gint delayed_idle;
+
+	DbusmenuTextDirection text_direction;
 };
 
 typedef struct _newItemPropData newItemPropData;
@@ -157,6 +161,7 @@
 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);
@@ -245,6 +250,21 @@
 	                                        _dbusmenu_client_marshal_VOID__OBJECT_UINT,
 	                                        G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_UINT);
 	/**
+		DbusmenuClient::text-direction-changed:
+		@arg0: The #DbusmenuClient object
+		@arg1: The new text direction
+
+		Signal sent to show that there was an error in sending the event
+		to the server.
+	*/
+	signals[TEXT_DIRECTION_CHANGED] = g_signal_new(DBUSMENU_CLIENT_SIGNAL_TEXT_DIRECTION_CHANGED,
+	                                        G_TYPE_FROM_CLASS (klass),
+	                                        G_SIGNAL_RUN_LAST,
+	                                        G_STRUCT_OFFSET (DbusmenuClientClass, text_direction_changed),
+	                                        NULL, NULL,
+	                                        _dbusmenu_client_marshal_VOID__ENUM,
+	                                        G_TYPE_NONE, 1, DBUSMENU_TYPE_TEXT_DIRECTION);
+	/**
 		DbusmenuClient::event-error:
 		@arg0: The #DbusmenuClient object
 		@arg1: The #DbusmenuMenuitem sent an event
@@ -328,6 +348,8 @@
 	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;
+
 	return;
 }
 
@@ -983,6 +1005,19 @@
 		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);
@@ -991,6 +1026,7 @@
 
 	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) {
@@ -1001,6 +1037,47 @@
 	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;
+
+	/* 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;
+		}
+	}
+
+	/* 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));
+		}
+
+		g_variant_unref(value);
+		g_free(key);
+	}
+
+	if (olddir != priv->text_direction) {
+		g_signal_emit(G_OBJECT(user_data), signals[TEXT_DIRECTION_CHANGED], 0, priv->text_direction, TRUE);
+	}
+
+	return;
+}
+
 /* Handle the case where we change owners */
 static void
 menuproxy_name_changed_cb (GObject * object, GParamSpec * pspec, gpointer user_data)
@@ -1834,3 +1911,20 @@
 	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;
+}

=== modified file 'libdbusmenu-glib/client.h'
--- libdbusmenu-glib/client.h	2011-01-27 15:35:14 +0000
+++ libdbusmenu-glib/client.h	2011-02-18 19:15:28 +0000
@@ -33,6 +33,7 @@
 #include <glib-object.h>
 
 #include "menuitem.h"
+#include "types.h"
 
 G_BEGIN_DECLS
 
@@ -48,6 +49,7 @@
 #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"
@@ -65,6 +67,7 @@
 	@new_menuitem: Slot for #DbusmenuClient::new-menuitem.
 	@item_activate: Slot for #DbusmenuClient::item-activate.
 	@event_result: Slot for #DbusmenuClient::event-error.
+	@text_direction_changed: Slot for #DbusmenuClient::text-direction-changed.
 	@reserved1: Reserved for future use.
 	@reserved2: Reserved for future use.
 	@reserved3: Reserved for future use.
@@ -85,6 +88,7 @@
 	void (*new_menuitem) (DbusmenuMenuitem * newitem);
 	void (*item_activate) (DbusmenuMenuitem * item, guint timestamp);
 	void (*event_result) (DbusmenuMenuitem * item, gchar * event, GVariant * data, guint timestamp, GError * error);
+	void (*text_direction_changed) (DbusmenuTextDirection newdirection);
 
 	/*< Private >*/
 	void (*reserved1) (void);
@@ -92,7 +96,6 @@
 	void (*reserved3) (void);
 	void (*reserved4) (void);
 	void (*reserved5) (void);
-	void (*reserved6) (void);
 };
 
 /**
@@ -155,6 +158,7 @@
                                                         gint id,
                                                         void (*cb) (gpointer user_data),
                                                         gpointer cb_data);
+DbusmenuTextDirection dbusmenu_client_get_text_direction (DbusmenuClient * client);
 
 /**
 	SECTION:client

=== modified file 'libdbusmenu-glib/dbus-menu.xml'
--- libdbusmenu-glib/dbus-menu.xml	2011-02-15 04:32:51 +0000
+++ libdbusmenu-glib/dbus-menu.xml	2011-02-18 19:15:28 +0000
@@ -171,6 +171,14 @@
 			</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>
+
 <!-- Functions -->
 
 		<method name="GetLayout">

=== added file 'libdbusmenu-glib/enum-types.c.in'
--- libdbusmenu-glib/enum-types.c.in	1970-01-01 00:00:00 +0000
+++ libdbusmenu-glib/enum-types.c.in	2011-02-18 19:15:28 +0000
@@ -0,0 +1,116 @@
+/*** BEGIN file-header ***/
+/*
+Enums from the dbusmenu headers
+
+Copyright 2011 Canonical Ltd.
+
+Authors:
+    Ted Gould <ted@xxxxxxxxxxxxx>
+
+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 ***/

=== added file 'libdbusmenu-glib/enum-types.h.in'
--- libdbusmenu-glib/enum-types.h.in	1970-01-01 00:00:00 +0000
+++ libdbusmenu-glib/enum-types.h.in	2011-02-18 19:15:28 +0000
@@ -0,0 +1,56 @@
+/*** BEGIN file-header ***/
+/*
+Enums from the dbusmenu headers
+
+Copyright 2011 Canonical Ltd.
+
+Authors:
+    Ted Gould <ted@xxxxxxxxxxxxx>
+
+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 ***/

=== modified file 'libdbusmenu-glib/server.c'
--- libdbusmenu-glib/server.c	2011-02-15 17:42:52 +0000
+++ libdbusmenu-glib/server.c	2011-02-18 19:15:28 +0000
@@ -30,11 +30,13 @@
 #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,8 @@
 	GCancellable * bus_lookup;
 	guint dbus_registration;
 
+	DbusmenuTextDirection text_direction;
+
 	GArray * prop_array;
 	guint property_idle;
 };
@@ -77,7 +81,8 @@
 	PROP_0,
 	PROP_DBUS_OBJECT,
 	PROP_ROOT_NODE,
-	PROP_VERSION
+	PROP_VERSION,
+	PROP_TEXT_DIRECTION
 };
 
 /* Errors */
@@ -124,6 +129,7 @@
                                                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 +295,11 @@
 	                                              "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));
 
 	if (dbusmenu_node_info == NULL) {
 		GError * error = NULL;
@@ -348,6 +359,8 @@
 	priv->bus_lookup = NULL;
 	priv->dbus_registration = 0;
 
+	default_text_direction(self);
+
 	return;
 }
 
@@ -463,6 +476,39 @@
 		}
 		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;
+	}
 	default:
 		g_return_if_reached();
 		break;
@@ -486,6 +532,9 @@
 	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;
 	default:
 		g_return_if_reached();
 		break;
@@ -494,6 +543,49 @@
 	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 +703,16 @@
 	/* 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
@@ -1458,5 +1557,52 @@
 	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;
+}
 

=== modified file 'libdbusmenu-glib/server.h'
--- libdbusmenu-glib/server.h	2010-10-12 21:14:21 +0000
+++ libdbusmenu-glib/server.h	2011-02-18 19:15:28 +0000
@@ -33,6 +33,7 @@
 #include <glib-object.h>
 
 #include "menuitem.h"
+#include "types.h"
 
 G_BEGIN_DECLS
 
@@ -52,6 +53,7 @@
 #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"
 
 typedef struct _DbusmenuServerPrivate DbusmenuServerPrivate;
 
@@ -106,9 +108,13 @@
 	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);
 
 /**
 	SECIONT:server

=== added file 'libdbusmenu-glib/types.h'
--- libdbusmenu-glib/types.h	1970-01-01 00:00:00 +0000
+++ libdbusmenu-glib/types.h	2011-02-18 19:15:28 +0000
@@ -0,0 +1,54 @@
+/*
+Types that are used in several objects.
+
+Copyright 2011 Canonical Ltd.
+
+Authors:
+    Ted Gould <ted@xxxxxxxxxxxxx>
+
+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;
+
+
+G_END_DECLS
+
+#endif /* __DBUSMENU_TYPES_H__ */
+

=== modified file 'po/POTFILES.in'
--- po/POTFILES.in	2009-03-25 17:33:11 +0000
+++ po/POTFILES.in	2011-02-18 19:15:28 +0000
@@ -0,0 +1,1 @@
+libdbusmenu-glib/server.c


Follow ups