Branch: refs/heads/master Author: Thomas Martitz kugel@rockbox.org Committer: Thomas Martitz kugel@rockbox.org Date: Wed, 26 Aug 2015 21:49:45 UTC Commit: 7c2c9dc27a909129007d74bb40ac67a643f6a2f4 https://github.com/geany/geany/commit/7c2c9dc27a909129007d74bb40ac67a643f6a2...
Log Message: ----------- plugin api: add destroy_notify to the new keybinding APIs
The destroy_notify can be used to make Geany automatically free the per-KeyGroup or per-KeyBinding user_data. This is particularly useful for vala-based plugins or other (future) language bindings.
The destroy functions can be conviniently hooked into the destroy_notify of the underlying GPtrArrays, therefore this commit also implements such notifies internally.
Modified Paths: -------------- src/keybindings.c src/keybindings.h src/keybindingsprivate.h src/pluginutils.c src/pluginutils.h
Modified: src/keybindings.c 61 lines changed, 40 insertions(+), 21 deletions(-) =================================================================== @@ -202,7 +202,7 @@ GeanyKeyBinding *keybindings_set_item(GeanyKeyGroup *group, gsize key_id, }
-/** Creates a new keybinding using a GeanyKeyBindingFunc and attaches is to a keybinding group +/** Creates a new keybinding using a GeanyKeyBindingFunc and attaches it to a keybinding group * * If given the callback should return @c TRUE if the keybinding was handled, otherwise @c FALSE * to allow other callbacks to be run. This allows for multiplexing keybindings on the same keys, @@ -211,14 +211,15 @@ GeanyKeyBinding *keybindings_set_item(GeanyKeyGroup *group, gsize key_id, * * @param group Group. * @param key_id Keybinding index for the group. - * @param cb New-style callback to be called when activated, or @c NULL to use the group callback. - * @param pdata Plugin-specific data passed back to the callback. * @param key (Lower case) default key, e.g. @c GDK_j, but usually 0 for unset. * @param mod Default modifier, e.g. @c GDK_CONTROL_MASK, but usually 0 for unset. * @param kf_name Key name for the configuration file, such as @c "menu_new". * @param label Label used in the preferences dialog keybindings tab. May contain * underscores - these won't be displayed. * @param menu_item Optional widget to set an accelerator for, or @c NULL. + * @param cb New-style callback to be called when activated, or @c NULL to use the group callback. + * @param pdata Plugin-specific data passed back to the callback. + * @param destroy_notify Function that is invoked to free the plugin data when not needed anymore. * @return The keybinding - normally this is ignored. * * @since 1.26 (API 226) @@ -226,8 +227,9 @@ GeanyKeyBinding *keybindings_set_item(GeanyKeyGroup *group, gsize key_id, **/ GEANY_API_SYMBOL GeanyKeyBinding *keybindings_set_item_full(GeanyKeyGroup *group, gsize key_id, - GeanyKeyBindingFunc cb, gpointer pdata, guint key, GdkModifierType mod, - const gchar *kf_name, const gchar *label, GtkWidget *menu_item) + guint key, GdkModifierType mod, const gchar *kf_name, const gchar *label, + GtkWidget *menu_item, GeanyKeyBindingFunc cb, gpointer pdata, + GDestroyNotify destroy_notify) { GeanyKeyBinding *kb;
@@ -237,10 +239,23 @@ GeanyKeyBinding *keybindings_set_item_full(GeanyKeyGroup *group, gsize key_id, kb = keybindings_set_item(group, key_id, NULL, key, mod, kf_name, label, menu_item); kb->cb_func = cb; kb->cb_data = pdata; + kb->cb_data_destroy = destroy_notify; return kb; }
+static void free_key_binding(gpointer item) +{ + GeanyKeyBinding *kb = item; + + g_free(kb->name); + g_free(kb->label); + + if (kb->cb_data_destroy) + kb->cb_data_destroy(kb->cb_data); +} + + static void add_kb_group(GeanyKeyGroup *group, const gchar *name, const gchar *label, GeanyKeyGroupCallback callback, gboolean plugin) { @@ -252,7 +267,8 @@ static void add_kb_group(GeanyKeyGroup *group, group->cb_func = NULL; group->cb_data = NULL; group->plugin = plugin; - group->key_items = g_ptr_array_new(); + /* Only plugins use the destroy notify thus far */ + group->key_items = g_ptr_array_new_with_free_func(plugin ? free_key_binding : NULL); }
@@ -680,10 +696,27 @@ static void init_default_kb(void) }
+static void free_key_group(gpointer item) +{ + GeanyKeyGroup *group = item; + + g_ptr_array_free(group->key_items, TRUE); + + if (group->plugin) + { + if (group->cb_data_destroy) + group->cb_data_destroy(group->cb_data); + g_free(group->plugin_keys); + g_free(group); + } +} + + void keybindings_init(void) { memset(binding_ids, 0, sizeof binding_ids); keybinding_groups = g_ptr_array_sized_new(GEANY_KEY_GROUP_COUNT); + g_ptr_array_set_free_func(keybinding_groups, free_key_group); kb_accel_group = gtk_accel_group_new();
init_default_kb(); @@ -2591,19 +2624,5 @@ GeanyKeyGroup *keybindings_set_group(GeanyKeyGroup *group, const gchar *section_
void keybindings_free_group(GeanyKeyGroup *group) { - GeanyKeyBinding *kb; - - g_ptr_array_free(group->key_items, TRUE); - - if (group->plugin) - { - foreach_c_array(kb, group->plugin_keys, group->plugin_key_count) - { - g_free(kb->name); - g_free(kb->label); - } - g_free(group->plugin_keys); - g_ptr_array_remove_fast(keybinding_groups, group); - g_free(group); - } + g_ptr_array_remove_fast(keybinding_groups, group); }
Modified: src/keybindings.h 6 lines changed, 4 insertions(+), 2 deletions(-) =================================================================== @@ -89,6 +89,7 @@ struct GeanyKeyBinding GdkModifierType default_mods; GeanyKeyBindingFunc cb_func; gpointer cb_data; + GDestroyNotify cb_data_destroy; };
/* Note: we don't need to break the plugin ABI when appending keybinding or keygroup IDs, @@ -276,8 +277,9 @@ GeanyKeyBinding *keybindings_set_item(GeanyKeyGroup *group, gsize key_id, const gchar *name, const gchar *label, GtkWidget *menu_item);
GeanyKeyBinding *keybindings_set_item_full(GeanyKeyGroup *group, gsize key_id, - GeanyKeyBindingFunc cb, gpointer pdata, guint key, GdkModifierType mod, - const gchar *kf_name, const gchar *label, GtkWidget *menu_item); + guint key, GdkModifierType mod, const gchar *kf_name, const gchar *label, + GtkWidget *menu_item, GeanyKeyBindingFunc func, gpointer pdata, + GDestroyNotify destroy_notify);
GeanyKeyBinding *keybindings_get_item(GeanyKeyGroup *group, gsize key_id);
Modified: src/keybindingsprivate.h 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -40,6 +40,7 @@ struct GeanyKeyGroup GeanyKeyBinding *plugin_keys; /* array of GeanyKeyBinding structs */ GeanyKeyGroupFunc cb_func; /* use this or individual keybinding callbacks (new style) */ gpointer cb_data; + GDestroyNotify cb_data_destroy; /* used to destroy handler_data */ };
G_END_DECLS
Modified: src/pluginutils.c 5 lines changed, 4 insertions(+), 1 deletions(-) =================================================================== @@ -318,6 +318,7 @@ GeanyKeyGroup *plugin_set_key_group(GeanyPlugin *plugin, * @param count Number of keybindings for the group. * @param cb New-style group callback, or @c NULL if you only want individual keybinding callbacks. * @param pdata Plugin specific data, passed to the group callback. + * @param destroy_notify Function that is invoked to free the plugin data when not needed anymore. * @return The plugin's keybinding group. * * @since 1.26 (API 226) @@ -326,13 +327,15 @@ GeanyKeyGroup *plugin_set_key_group(GeanyPlugin *plugin, **/ GEANY_API_SYMBOL GeanyKeyGroup *plugin_set_key_group_full(GeanyPlugin *plugin, - const gchar *section_name, gsize count, GeanyKeyGroupFunc cb, gpointer pdata) + const gchar *section_name, gsize count, + GeanyKeyGroupFunc cb, gpointer pdata, GDestroyNotify destroy_notify) { GeanyKeyGroup *group;
group = plugin_set_key_group(plugin, section_name, count, NULL); group->cb_func = cb; group->cb_data = pdata; + group->cb_data_destroy = destroy_notify;
return group; }
Modified: src/pluginutils.h 2 lines changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -55,7 +55,7 @@ struct GeanyKeyGroup *plugin_set_key_group(struct GeanyPlugin *plugin, const gchar *section_name, gsize count, GeanyKeyGroupCallback callback);
GeanyKeyGroup *plugin_set_key_group_full(struct GeanyPlugin *plugin, - const gchar *section_name, gsize count, GeanyKeyGroupFunc cb, gpointer pdata); + const gchar *section_name, gsize count, GeanyKeyGroupFunc cb, gpointer pdata, GDestroyNotify destroy_notify);
void plugin_show_configure(struct GeanyPlugin *plugin);
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).