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.c63
1 files changed, 37 insertions, 26 deletions
diff --git a/libdbusmenu-glib/menuitem.c b/libdbusmenu-glib/menuitem.c
index 34147a3..f7867e4 100644
--- a/libdbusmenu-glib/menuitem.c
+++ b/libdbusmenu-glib/menuitem.c
@@ -1146,13 +1146,14 @@ dbusmenu_menuitem_property_set_variant (DbusmenuMenuitem * mi, const gchar * pro
{
g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), FALSE);
g_return_val_if_fail(property != NULL, FALSE);
+ g_return_val_if_fail(g_utf8_validate(property, -1, NULL), FALSE);
DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
GVariant * default_value = NULL;
- if (value != NULL) {
- const gchar * type = menuitem_get_type(mi);
+ const gchar * type = menuitem_get_type(mi);
+ if (value != NULL) {
/* 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) {
@@ -1163,23 +1164,25 @@ dbusmenu_menuitem_property_set_variant (DbusmenuMenuitem * mi, const gchar * pro
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;
- }
+ /* 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 && 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;
}
}
+
gboolean replaced = FALSE;
+ gboolean remove = FALSE;
gpointer currentval = g_hash_table_lookup(priv->properties, property);
if (value != NULL) {
@@ -1194,10 +1197,21 @@ dbusmenu_menuitem_property_set_variant (DbusmenuMenuitem * mi, const gchar * pro
gchar * lprop = g_strdup(property);
g_variant_ref_sink(value);
- g_hash_table_replace(priv->properties, lprop, value);
+ /* Really important that this is _insert as that means the value
+ that we just created in the _strdup is free'd and not the one
+ currently in the hashtable. That could be the same as the one
+ being passed in and then the signal emit would be done with a
+ bad value */
+ g_hash_table_insert(priv->properties, lprop, value);
} else {
if (currentval != NULL) {
- g_hash_table_remove(priv->properties, property);
+ /* So the question you should be asking if you're paying attention
+ is "Why not just do the remove here?" It's a good question with
+ an interesting answer. Bascially it's the same reason as above,
+ in a couple cases the passed in properties is the value in the hash
+ table so we can avoid strdup'ing it by removing it (and thus free'ing
+ it) after the signal emition */
+ remove = TRUE;
replaced = TRUE;
}
}
@@ -1218,6 +1232,10 @@ dbusmenu_menuitem_property_set_variant (DbusmenuMenuitem * mi, const gchar * pro
g_signal_emit(G_OBJECT(mi), signals[PROPERTY_CHANGED], 0, property, signalval, TRUE);
}
+ if (remove) {
+ g_hash_table_remove(priv->properties, property);
+ }
+
return TRUE;
}
@@ -1371,9 +1389,7 @@ dbusmenu_menuitem_property_remove (DbusmenuMenuitem * mi, const gchar * property
g_return_if_fail(DBUSMENU_IS_MENUITEM(mi));
g_return_if_fail(property != NULL);
- DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
-
- g_hash_table_remove(priv->properties, property);
+ dbusmenu_menuitem_property_set_variant(mi, property, NULL);
return;
}
@@ -1753,13 +1769,8 @@ dbusmenu_menuitem_property_is_default (DbusmenuMenuitem * mi, const gchar * prop
return FALSE;
}
- currentval = dbusmenu_defaults_default_get(priv->defaults, menuitem_get_type(mi), property);
- if (currentval != NULL) {
- return TRUE;
- }
-
- g_warn_if_reached();
- return FALSE;
+ /* If we haven't stored it locally, then it's the default */
+ return TRUE;
}
/* Check to see if this menu item has been sent into the bus yet or