Kaydet (Commit) 7c2c9dc2 authored tarafından Thomas Martitz's avatar Thomas Martitz

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.
üst d3f62375
......@@ -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);
}
......@@ -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);
......
......@@ -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
......
......@@ -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;
}
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment