aboutsummaryrefslogtreecommitdiff
path: root/libdbusmenu-glib/menuitem.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdbusmenu-glib/menuitem.c')
-rw-r--r--libdbusmenu-glib/menuitem.c220
1 files changed, 139 insertions, 81 deletions
diff --git a/libdbusmenu-glib/menuitem.c b/libdbusmenu-glib/menuitem.c
index 73b765b..827d6c5 100644
--- a/libdbusmenu-glib/menuitem.c
+++ b/libdbusmenu-glib/menuitem.c
@@ -70,6 +70,7 @@ enum {
CHILD_MOVED,
REALIZED,
SHOW_TO_USER,
+ ABOUT_TO_SHOW,
LAST_SIGNAL
};
@@ -94,7 +95,7 @@ static void set_property (GObject * obj, guint id, const GValue * value, GParamS
static void get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec);
static void g_value_transform_STRING_BOOLEAN (const GValue * in, GValue * out);
static void g_value_transform_STRING_INT (const GValue * in, GValue * out);
-static void handle_event (DbusmenuMenuitem * mi, const gchar * name, const GValue * value, guint timestamp);
+static void handle_event (DbusmenuMenuitem * mi, const gchar * name, GVariant * value, guint timestamp);
static void send_about_to_show (DbusmenuMenuitem * mi, void (*cb) (DbusmenuMenuitem * mi, gpointer user_data), gpointer cb_data);
/* GObject stuff */
@@ -129,8 +130,8 @@ dbusmenu_menuitem_class_init (DbusmenuMenuitemClass *klass)
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(DbusmenuMenuitemClass, property_changed),
NULL, NULL,
- _dbusmenu_menuitem_marshal_VOID__STRING_POINTER,
- G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_POINTER);
+ _dbusmenu_menuitem_marshal_VOID__STRING_VARIANT,
+ G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_VARIANT);
/**
DbusmenuMenuitem::item-activated:
@arg0: The #DbusmenuMenuitem object.
@@ -229,6 +230,21 @@ dbusmenu_menuitem_class_init (DbusmenuMenuitemClass *klass)
g_cclosure_marshal_VOID__UINT,
G_TYPE_NONE, 1, G_TYPE_UINT, G_TYPE_NONE);
+ /**
+ DbusmenuMenuitem::about-to-show:
+ @arg0: The #DbusmenuMenuitem object.
+
+ Emitted when the submenu for this item
+ is about to be shown
+ */
+ signals[ABOUT_TO_SHOW] = g_signal_new(DBUSMENU_MENUITEM_SIGNAL_ABOUT_TO_SHOW,
+ G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(DbusmenuMenuitemClass, about_to_show),
+ NULL, NULL,
+ _dbusmenu_menuitem_marshal_VOID__VOID,
+ G_TYPE_BOOLEAN, 0, G_TYPE_NONE);
+
g_object_class_install_property (object_class, PROP_ID,
g_param_spec_int(PROP_ID_S, "ID for the menu item",
"This is a unique indentifier for the menu item.",
@@ -271,15 +287,12 @@ g_value_transform_STRING_INT (const GValue * in, GValue * out)
static gint menuitem_next_id = 1;
-/* A small little function to both clear the insides of a
- value as well as the memory it itself uses. */
+/* Make the unref function match the prototype need for the
+ hashtable destructor */
static void
-_g_value_free (gpointer data)
+_g_variant_unref (gpointer data)
{
- if (data == NULL) return;
- GValue * value = (GValue*)data;
- g_value_unset(value);
- g_free(data);
+ g_variant_unref((GVariant *)data);
return;
}
@@ -295,7 +308,7 @@ dbusmenu_menuitem_init (DbusmenuMenuitem *self)
priv->id = -1;
priv->children = NULL;
- priv->properties = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, _g_value_free);
+ priv->properties = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, _g_variant_unref);
priv->root = FALSE;
priv->realized = FALSE;
@@ -380,7 +393,7 @@ get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec)
/* Handles the activate event if it is sent. */
static void
-handle_event (DbusmenuMenuitem * mi, const gchar * name, const GValue * value, guint timestamp)
+handle_event (DbusmenuMenuitem * mi, const gchar * name, GVariant * value, guint timestamp)
{
if (g_strcmp0(name, "clicked") == 0) {
g_signal_emit(G_OBJECT(mi), signals[ITEM_ACTIVATED], 0, timestamp, TRUE);
@@ -401,7 +414,8 @@ send_about_to_show (DbusmenuMenuitem * mi, void (*cb) (DbusmenuMenuitem * mi, gp
if (dbusmenu_menuitem_get_children(mi) == NULL) {
g_warning("About to Show called on an item wihtout submenus. We're ignoring it.");
} else {
- g_signal_emit(G_OBJECT(mi), signals[ITEM_ACTIVATED], 0, 0 /* timestamp */, TRUE);
+ gboolean dummy;
+ g_signal_emit(G_OBJECT(mi), signals[ABOUT_TO_SHOW], 0, &dummy);
}
if (cb != NULL) {
@@ -916,10 +930,11 @@ dbusmenu_menuitem_find_id (DbusmenuMenuitem * mi, gint id)
gboolean
dbusmenu_menuitem_property_set (DbusmenuMenuitem * mi, const gchar * property, const gchar * value)
{
- GValue val = {0};
- g_value_init(&val, G_TYPE_STRING);
- g_value_set_static_string(&val, value);
- return dbusmenu_menuitem_property_set_value(mi, property, &val);
+ GVariant * variant = NULL;
+ if (value != NULL) {
+ variant = g_variant_new_string(value);
+ }
+ return dbusmenu_menuitem_property_set_variant(mi, property, variant);
}
/**
@@ -940,10 +955,8 @@ dbusmenu_menuitem_property_set (DbusmenuMenuitem * mi, const gchar * property, c
gboolean
dbusmenu_menuitem_property_set_bool (DbusmenuMenuitem * mi, const gchar * property, const gboolean value)
{
- GValue val = {0};
- g_value_init(&val, G_TYPE_BOOLEAN);
- g_value_set_boolean(&val, value);
- return dbusmenu_menuitem_property_set_value(mi, property, &val);
+ GVariant * variant = g_variant_new("b", value);
+ return dbusmenu_menuitem_property_set_variant(mi, property, variant);
}
/**
@@ -964,14 +977,12 @@ dbusmenu_menuitem_property_set_bool (DbusmenuMenuitem * mi, const gchar * proper
gboolean
dbusmenu_menuitem_property_set_int (DbusmenuMenuitem * mi, const gchar * property, const gint value)
{
- GValue val = {0};
- g_value_init(&val, G_TYPE_INT);
- g_value_set_int(&val, value);
- return dbusmenu_menuitem_property_set_value(mi, property, &val);
+ GVariant * variant = g_variant_new("i", value);
+ return dbusmenu_menuitem_property_set_variant(mi, property, variant);
}
/**
- dbusmenu_menuitem_property_set:
+ dbusmenu_menuitem_property_set_variant:
@mi: The #DbusmenuMenuitem to set the property on.
@property: Name of the property to set.
@value: The value of the property.
@@ -986,37 +997,38 @@ dbusmenu_menuitem_property_set_int (DbusmenuMenuitem * mi, const gchar * propert
Return value: A boolean representing if the property value was set.
*/
gboolean
-dbusmenu_menuitem_property_set_value (DbusmenuMenuitem * mi, const gchar * property, const GValue * value)
+dbusmenu_menuitem_property_set_variant (DbusmenuMenuitem * mi, const gchar * property, GVariant * value)
{
g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), FALSE);
g_return_val_if_fail(property != NULL, FALSE);
- g_return_val_if_fail(G_IS_VALUE(value), FALSE);
DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
- /* g_debug("Setting a property. ID: %d Prop: %s Value: %s", priv->id, property, value); */
- #if 0
- gpointer lookup = g_hash_table_lookup(priv->properties, property);
- if (g_strcmp0((gchar *)lookup, value) == 0) {
- /* The value is the same as the value currently in the
- table so we don't really care. Just say everything's okay */
- return TRUE;
- }
- #endif
+ gboolean replaced = FALSE;
+ gpointer currentval = g_hash_table_lookup(priv->properties, property);
- gchar * lprop = g_strdup(property);
- GValue * lval = g_new0(GValue, 1);
- g_value_init(lval, G_VALUE_TYPE(value));
- g_value_copy(value, lval);
+ if (value != NULL) {
+ gchar * lprop = g_strdup(property);
+ g_variant_ref(value);
- g_hash_table_replace(priv->properties, lprop, lval);
- #ifdef MASSIVEDEBUGGING
- gchar * valstr = g_strdup_value_contents(lval);
- g_debug("Menuitem %d (%s) signalling property '%s' changed to '%s'", ID(mi), LABEL(mi), property, g_utf8_strlen(valstr, 50) < 25 ? valstr : "<too long>");
- g_free(valstr);
- #endif
+ if (currentval == NULL || !g_variant_equal((GVariant*)currentval, value)) {
+ g_hash_table_replace(priv->properties, lprop, value);
+ replaced = TRUE;
+ }
+ } else {
+ if (currentval != NULL) {
+ g_hash_table_remove(priv->properties, property);
+ replaced = TRUE;
+ }
+ }
- g_signal_emit(G_OBJECT(mi), signals[PROPERTY_CHANGED], 0, lprop, lval, TRUE);
+ /* NOTE: The actual value is invalid at this point
+ becuse it has been unref'd when replaced in the hash
+ table. But the fact that there was a value is
+ the imporant part. */
+ if (currentval == NULL || replaced) {
+ g_signal_emit(G_OBJECT(mi), signals[PROPERTY_CHANGED], 0, property, value, TRUE);
+ }
return TRUE;
}
@@ -1037,14 +1049,14 @@ dbusmenu_menuitem_property_set_value (DbusmenuMenuitem * mi, const gchar * prope
const gchar *
dbusmenu_menuitem_property_get (DbusmenuMenuitem * mi, const gchar * property)
{
- const GValue * value = dbusmenu_menuitem_property_get_value(mi, property);
- if (value == NULL) return NULL;
- if (G_VALUE_TYPE(value) != G_TYPE_STRING) return NULL;
- return g_value_get_string(value);
+ GVariant * variant = dbusmenu_menuitem_property_get_variant(mi, property);
+ if (variant == NULL) return NULL;
+ if (!g_variant_type_equal(g_variant_get_type(variant), G_VARIANT_TYPE_STRING)) return NULL;
+ return g_variant_get_string(variant, NULL);
}
/**
- dbusmenu_menuitem_property_get_value:
+ dbusmenu_menuitem_property_get_variant:
@mi: The #DbusmenuMenuitem to look for the property on.
@property: The property to grab.
@@ -1052,17 +1064,17 @@ dbusmenu_menuitem_property_get (DbusmenuMenuitem * mi, const gchar * property)
it exits. #NULL will be returned if the property doesn't
exist.
- Return value: A GValue for the property.
+ Return value: A GVariant for the property.
*/
-const GValue *
-dbusmenu_menuitem_property_get_value (DbusmenuMenuitem * mi, const gchar * property)
+GVariant *
+dbusmenu_menuitem_property_get_variant (DbusmenuMenuitem * mi, const gchar * property)
{
g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), NULL);
g_return_val_if_fail(property != NULL, NULL);
DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
- return (const GValue *)g_hash_table_lookup(priv->properties, property);
+ return (GVariant *)g_hash_table_lookup(priv->properties, property);
}
/**
@@ -1078,19 +1090,25 @@ dbusmenu_menuitem_property_get_value (DbusmenuMenuitem * mi, const gchar * prope
gboolean
dbusmenu_menuitem_property_get_bool (DbusmenuMenuitem * mi, const gchar * property)
{
- const GValue * value = dbusmenu_menuitem_property_get_value(mi, property);
- if (value == NULL) return FALSE;
- if (G_VALUE_TYPE(value) != G_TYPE_BOOLEAN) {
- if (g_value_type_transformable(G_VALUE_TYPE(value), G_TYPE_BOOLEAN)) {
- GValue boolval = {0};
- g_value_init(&boolval, G_TYPE_BOOLEAN);
- g_value_transform(value, &boolval);
- return g_value_get_boolean(&boolval);
+ GVariant * variant = dbusmenu_menuitem_property_get_variant(mi, property);
+ if (variant == NULL) return FALSE;
+
+ if (g_variant_type_equal(g_variant_get_type(variant), G_VARIANT_TYPE_BOOLEAN)) {
+ return g_variant_get_boolean(variant);
+ }
+
+ if (g_variant_type_equal(g_variant_get_type(variant), G_VARIANT_TYPE_STRING)) {
+ const gchar * string = g_variant_get_string(variant, NULL);
+
+ if (!g_strcmp0(string, "TRUE") || !g_strcmp0(string, "true") || !g_strcmp0(string, "True")) {
+ return TRUE;
} else {
return FALSE;
}
}
- return g_value_get_boolean(value);
+
+ g_warning("Property '%s' has been requested as an boolean but is not one.", property);
+ return FALSE;
}
/**
@@ -1106,19 +1124,20 @@ dbusmenu_menuitem_property_get_bool (DbusmenuMenuitem * mi, const gchar * proper
gint
dbusmenu_menuitem_property_get_int (DbusmenuMenuitem * mi, const gchar * property)
{
- const GValue * value = dbusmenu_menuitem_property_get_value(mi, property);
- if (value == NULL) return 0;
- if (G_VALUE_TYPE(value) != G_TYPE_INT) {
- if (g_value_type_transformable(G_VALUE_TYPE(value), G_TYPE_INT)) {
- GValue intval = {0};
- g_value_init(&intval, G_TYPE_INT);
- g_value_transform(value, &intval);
- return g_value_get_int(&intval);
- } else {
- return 0;
- }
+ GVariant * variant = dbusmenu_menuitem_property_get_variant(mi, property);
+ if (variant == NULL) return 0;
+
+ if (g_variant_type_equal(g_variant_get_type(variant), G_VARIANT_TYPE_INT32)) {
+ return g_variant_get_int32(variant);
}
- return g_value_get_int(value);
+
+ if (g_variant_type_equal(g_variant_get_type(variant), G_VARIANT_TYPE_STRING)) {
+ const gchar * string = g_variant_get_string(variant, NULL);
+ return atoi(string);
+ }
+
+ g_warning("Property '%s' has been requested as an int but is not one.", property);
+ return 0;
}
@@ -1220,6 +1239,45 @@ dbusmenu_menuitem_properties_copy (DbusmenuMenuitem * mi)
return ret;
}
+/* Looks at each value in the hashtable and tries to convert it
+ into a variant and add it to our variant builder */
+static void
+variant_helper (gpointer in_key, gpointer in_value, gpointer user_data)
+{
+ g_variant_builder_add((GVariantBuilder *)user_data, "{sv}", in_key, in_value);
+ return;
+}
+
+/**
+ dbusmenu_menuitem_properties_variant:
+ @mi: #DbusmenuMenuitem to get properties from
+
+ Grabs the properties of the menuitem as a GVariant with the
+ type "a{sv}".
+
+ Return Value: A GVariant of type "a{sv}" or NULL on error.
+*/
+GVariant *
+dbusmenu_menuitem_properties_variant (DbusmenuMenuitem * mi)
+{
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), NULL);
+
+ DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
+
+ GVariant * final_variant = NULL;
+
+ if (g_hash_table_size(priv->properties) > 0) {
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, g_variant_type_new("a{sv}"));
+
+ g_hash_table_foreach(priv->properties, variant_helper, &builder);
+
+ final_variant = g_variant_builder_end(&builder);
+ }
+
+ return final_variant;
+}
+
/**
dbusmenu_menuitem_set_root:
@mi: #DbusmenuMenuitem to set whether it's root
@@ -1332,7 +1390,7 @@ dbusmenu_menuitem_foreach (DbusmenuMenuitem * mi, void (*func) (DbusmenuMenuitem
dbusmenu_menuitem_handle_event:
@mi: The #DbusmenuMenuitem to send the signal on.
@name: The name of the signal
- @value: A value that could be set for the event
+ @variant: A value that could be set for the event
@timestamp: The timestamp of when the event happened
This function is called to create an event. It is likely
@@ -1348,7 +1406,7 @@ dbusmenu_menuitem_foreach (DbusmenuMenuitem * mi, void (*func) (DbusmenuMenuitem
reason not to.
*/
void
-dbusmenu_menuitem_handle_event (DbusmenuMenuitem * mi, const gchar * name, const GValue * value, guint timestamp)
+dbusmenu_menuitem_handle_event (DbusmenuMenuitem * mi, const gchar * name, GVariant * variant, guint timestamp)
{
g_return_if_fail(DBUSMENU_IS_MENUITEM(mi));
#ifdef MASSIVEDEBUGGING
@@ -1357,7 +1415,7 @@ dbusmenu_menuitem_handle_event (DbusmenuMenuitem * mi, const gchar * name, const
DbusmenuMenuitemClass * class = DBUSMENU_MENUITEM_GET_CLASS(mi);
if (class->handle_event != NULL) {
- return class->handle_event(mi, name, value, timestamp);
+ return class->handle_event(mi, name, variant, timestamp);
}
return;
}