diff options
author | Ted Gould <ted@gould.cx> | 2011-02-21 11:22:46 -0600 |
---|---|---|
committer | Ted Gould <ted@gould.cx> | 2011-02-21 11:22:46 -0600 |
commit | 2f92a8662f5a84f9ef35dd847539f573f60edc5f (patch) | |
tree | 9c00fda471a88fcc331c858bc2de66076f7de9ef /libdbusmenu-gtk/menuitem.c | |
parent | 71020d95b0eb9f583523628261d26336a5dceb39 (diff) | |
parent | 34248e4fe3aeef17be5fe9f2339057fbaee81ad2 (diff) | |
download | libdbusmenu-2f92a8662f5a84f9ef35dd847539f573f60edc5f.tar.gz libdbusmenu-2f92a8662f5a84f9ef35dd847539f573f60edc5f.tar.bz2 libdbusmenu-2f92a8662f5a84f9ef35dd847539f573f60edc5f.zip |
Another update to trunk
Diffstat (limited to 'libdbusmenu-gtk/menuitem.c')
-rw-r--r-- | libdbusmenu-gtk/menuitem.c | 227 |
1 files changed, 205 insertions, 22 deletions
diff --git a/libdbusmenu-gtk/menuitem.c b/libdbusmenu-gtk/menuitem.c index 23ff311..508b43f 100644 --- a/libdbusmenu-gtk/menuitem.c +++ b/libdbusmenu-gtk/menuitem.c @@ -27,19 +27,21 @@ License version 3 and version 2.1 along with this program. If not, see */ #include "menuitem.h" +#include <gdk/gdk.h> +#include <gtk/gtk.h> /** - dbusmenu_menuitem_property_set_image: - @menuitem: The #DbusmenuMenuitem to set the property on. - @property: Name of the property to set. - @data: The image to place on the property. - - This function takes the pixbuf that is stored in @data and - turns it into a base64 encoded PNG so that it can be placed - onto a standard #DbusmenuMenuitem property. - - Return value: Whether the function was able to set the property - or not. + * dbusmenu_menuitem_property_set_image: + * @menuitem: The #DbusmenuMenuitem to set the property on. + * @property: Name of the property to set. + * @data: The image to place on the property. + * + * This function takes the pixbuf that is stored in @data and + * turns it into a base64 encoded PNG so that it can be placed + * onto a standard #DbusmenuMenuitem property. + * + * Return value: Whether the function was able to set the property + * or not. */ gboolean dbusmenu_menuitem_property_set_image (DbusmenuMenuitem * menuitem, const gchar * property, const GdkPixbuf * data) @@ -75,17 +77,17 @@ dbusmenu_menuitem_property_set_image (DbusmenuMenuitem * menuitem, const gchar * } /** - dbusmenu_menuitem_property_get_image: - @menuitem: The #DbusmenuMenuite to look for the property on - @property: The name of the property to look for. - - This function looks on the menu item for a property by the - name of @property. If one exists it tries to turn it into - a #GdkPixbuf. It assumes that the property is a base64 encoded - PNG file like the one created by #dbusmenu_menuite_property_set_image. - - Return value: A pixbuf or #NULL to signal error. -*/ + * dbusmenu_menuitem_property_get_image: + * @menuitem: The #DbusmenuMenuitem to look for the property on + * @property: The name of the property to look for. + * + * This function looks on the menu item for a property by the + * name of @property. If one exists it tries to turn it into + * a #GdkPixbuf. It assumes that the property is a base64 encoded + * PNG file like the one created by #dbusmenu_menuite_property_set_image. + * + * Return value: (transfer full): A pixbuf or #NULL to signal error. + */ GdkPixbuf * dbusmenu_menuitem_property_get_image (DbusmenuMenuitem * menuitem, const gchar * property) { @@ -128,3 +130,184 @@ dbusmenu_menuitem_property_get_image (DbusmenuMenuitem * menuitem, const gchar * return icon; } +/** + * dbusmenu_menuitem_property_set_shortcut_string: + * @menuitem: The #DbusmenuMenuitem to set the shortcut on + * @shortcut: String describing the shortcut + * + * This function takes a GTK shortcut string as defined in + * #gtk_accelerator_parse and turns that into the information + * required to send it over DBusmenu. + * + * Return value: Whether it was successful at setting the property. + */ +gboolean +dbusmenu_menuitem_property_set_shortcut_string (DbusmenuMenuitem * menuitem, const gchar * shortcut) +{ + g_return_val_if_fail(DBUSMENU_IS_MENUITEM(menuitem), FALSE); + g_return_val_if_fail(shortcut != NULL, FALSE); + + guint key = 0; + GdkModifierType modifier = 0; + + gtk_accelerator_parse(shortcut, &key, &modifier); + + if (key == 0) { + g_warning("Unable to parse shortcut string '%s'", shortcut); + return FALSE; + } + + return dbusmenu_menuitem_property_set_shortcut(menuitem, key, modifier); +} + +/** + * dbusmenu_menuitem_property_set_shortcut: + * @menuitem: The #DbusmenuMenuitem to set the shortcut on + * @key: The keycode of the key to send + * @modifier: A bitmask of modifiers used to activate the item + * + * Takes the modifer described by @key and @modifier and places that into + * the format sending across Dbus for shortcuts. + * + * Return value: Whether it was successful at setting the property. + */ +gboolean +dbusmenu_menuitem_property_set_shortcut (DbusmenuMenuitem * menuitem, guint key, GdkModifierType modifier) +{ + g_return_val_if_fail(DBUSMENU_IS_MENUITEM(menuitem), FALSE); + g_return_val_if_fail(gtk_accelerator_valid(key, modifier), FALSE); + + GVariantBuilder builder; + g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY); + + if (modifier & GDK_CONTROL_MASK) { + g_variant_builder_add(&builder, "s", DBUSMENU_MENUITEM_SHORTCUT_CONTROL); + } + if (modifier & GDK_MOD1_MASK) { + g_variant_builder_add(&builder, "s", DBUSMENU_MENUITEM_SHORTCUT_ALT); + } + if (modifier & GDK_SHIFT_MASK) { + g_variant_builder_add(&builder, "s", DBUSMENU_MENUITEM_SHORTCUT_SHIFT); + } + if (modifier & GDK_SUPER_MASK) { + g_variant_builder_add(&builder, "s", DBUSMENU_MENUITEM_SHORTCUT_SUPER); + } + + const gchar * keyname = gdk_keyval_name(key); + g_variant_builder_add(&builder, "s", keyname); + + GVariant * inside = g_variant_builder_end(&builder); + g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY); + g_variant_builder_add_value(&builder, inside); + GVariant * outsidevariant = g_variant_builder_end(&builder); + + return dbusmenu_menuitem_property_set_variant(menuitem, DBUSMENU_MENUITEM_PROP_SHORTCUT, outsidevariant); +} + +/* Look at the closures in an accel group and find + the one that matches the one we've been passed */ +static gboolean +find_closure (GtkAccelKey * key, GClosure * closure, gpointer user_data) +{ + return closure == user_data; +} + +/** + * dbusmenu_menuitem_property_set_shortcut_menuitem: + * @menuitem: The #DbusmenuMenuitem to set the shortcut on + * @gmi: A menu item to steal the shortcut off of + * + * Takes the shortcut that is installed on a menu item and calls + * #dbusmenu_menuitem_property_set_shortcut with it. It also sets + * up listeners to watch it change. + * + * Return value: Whether it was successful at setting the property. + */ +gboolean +dbusmenu_menuitem_property_set_shortcut_menuitem (DbusmenuMenuitem * menuitem, const GtkMenuItem * gmi) +{ + g_return_val_if_fail(DBUSMENU_IS_MENUITEM(menuitem), FALSE); + g_return_val_if_fail(GTK_IS_MENU_ITEM(gmi), FALSE); + + GClosure * closure = NULL; + GtkWidget *label = gtk_bin_get_child(GTK_BIN (gmi)); + + if (GTK_IS_ACCEL_LABEL (label)) + { + g_object_get (label, + "accel-closure", &closure, + NULL); + } + + if (closure == NULL) + return FALSE; + + GtkAccelGroup * group = gtk_accel_group_from_accel_closure(closure); + + /* Apparently this is more common than I thought. */ + if (group == NULL) { + return FALSE; + } + + GtkAccelKey * key = gtk_accel_group_find(group, find_closure, closure); + /* Again, not much we can do except complain loudly. */ + g_return_val_if_fail(key != NULL, FALSE); + + if (!gtk_accelerator_valid (key->accel_key, key->accel_mods)) + return FALSE; + + return dbusmenu_menuitem_property_set_shortcut(menuitem, key->accel_key, key->accel_mods); +} + +/** + * dbusmenu_menuitem_property_get_shortcut: + * @menuitem: The #DbusmenuMenuitem to get the shortcut off + * @key: (out): Location to put the key value + * @modifier: (out): Location to put the modifier mask + * + * This function gets a GTK shortcut as a key and a mask + * for use to set the accelerators. + */ +void +dbusmenu_menuitem_property_get_shortcut (DbusmenuMenuitem * menuitem, guint * key, GdkModifierType * modifier) +{ + *key = 0; + *modifier = 0; + + g_return_if_fail(DBUSMENU_IS_MENUITEM(menuitem)); + + GVariant * wrapper = dbusmenu_menuitem_property_get_variant(menuitem, DBUSMENU_MENUITEM_PROP_SHORTCUT); + if (wrapper == NULL) { + return; + } + + if (g_variant_n_children(wrapper) != 1) { + g_warning("Unable to parse shortcut, too many keys"); + g_variant_unref(wrapper); + return; + } + + GVariantIter iter; + g_variant_iter_init(&iter, g_variant_get_child_value(wrapper, 0)); + gchar * string; + + while(g_variant_iter_next(&iter, "s", &string)) { + if (g_strcmp0(string, DBUSMENU_MENUITEM_SHORTCUT_CONTROL) == 0) { + *modifier |= GDK_CONTROL_MASK; + } else if (g_strcmp0(string, DBUSMENU_MENUITEM_SHORTCUT_ALT) == 0) { + *modifier |= GDK_MOD1_MASK; + } else if (g_strcmp0(string, DBUSMENU_MENUITEM_SHORTCUT_SHIFT) == 0) { + *modifier |= GDK_SHIFT_MASK; + } else if (g_strcmp0(string, DBUSMENU_MENUITEM_SHORTCUT_SUPER) == 0) { + *modifier |= GDK_SUPER_MASK; + } else { + GdkModifierType tempmod; + gtk_accelerator_parse(string, key, &tempmod); + } + + g_free(string); + } + + return; +} + |