diff options
Diffstat (limited to 'libmatekbd/matekbd-indicator-plugin-manager.c')
-rw-r--r-- | libmatekbd/matekbd-indicator-plugin-manager.c | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/libmatekbd/matekbd-indicator-plugin-manager.c b/libmatekbd/matekbd-indicator-plugin-manager.c new file mode 100644 index 0000000..8236038 --- /dev/null +++ b/libmatekbd/matekbd-indicator-plugin-manager.c @@ -0,0 +1,406 @@ +/* + * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <config.h> + +#include <string.h> + +#include <libxklavier/xklavier.h> + +#include <matekbd-indicator-plugin-manager.h> + +#define FOREACH_INITED_PLUGIN() \ +{ \ + GSList *prec; \ + for( prec = manager->inited_plugin_recs; prec != NULL; prec = prec->next ) \ + { \ + const MatekbdIndicatorPlugin *plugin = \ + ( ( MatekbdIndicatorPluginManagerRecord * ) ( prec->data ) )->plugin; \ + if( plugin != NULL ) \ + { + +#define NEXT_INITED_PLUGIN() \ + } \ + } \ +} + +static void +matekbd_indicator_plugin_manager_add_plugins_dir (MatekbdIndicatorPluginManager * + manager, + const char *dirname) +{ + GDir *dir = g_dir_open (dirname, 0, NULL); + const gchar *filename; + const MatekbdIndicatorPlugin *plugin; + + if (dir == NULL) + return; + + xkl_debug (100, "Scanning [%s]...\n", dirname); + while ((filename = g_dir_read_name (dir)) != NULL) { + gchar *full_path = + g_build_filename (dirname, filename, NULL); + xkl_debug (100, "Loading plugin module [%s]...\n", + full_path); + if (full_path != NULL) { + GModule *module = g_module_open (full_path, 0); + if (module != NULL) { + gpointer get_plugin_func; + if (g_module_symbol + (module, "GetPlugin", + &get_plugin_func)) { + plugin = + ((MatekbdIndicatorPluginGetPluginFunc) + get_plugin_func) (); + if (plugin != NULL) { + MatekbdIndicatorPluginManagerRecord + * rec = + g_new0 + (MatekbdIndicatorPluginManagerRecord, + 1); + xkl_debug (100, + "Loaded plugin from [%s]: [%s]/[%s]...\n", + full_path, + plugin->name, + plugin->description); + rec->full_path = full_path; + rec->module = module; + rec->plugin = plugin; + g_hash_table_insert + (manager->all_plugin_recs, + full_path, rec); + continue; + } + } else + xkl_debug (0, + "Bad plugin: [%s]\n", + full_path); + g_module_close (module); + } else + xkl_debug (0, "Bad module: [%s], %s\n", + full_path, g_module_error ()); + g_free (full_path); + } + } + g_dir_close (dir); +} + +static void +matekbd_indicator_plugin_manager_load_all (MatekbdIndicatorPluginManager * + manager) +{ + if (!g_module_supported ()) { + xkl_debug (0, "Modules are not supported - no plugins!\n"); + return; + } + matekbd_indicator_plugin_manager_add_plugins_dir (manager, + SYS_PLUGIN_DIR); +} + +static void +matekbd_indicator_plugin_manager_rec_term (MatekbdIndicatorPluginManagerRecord * + rec, void *user_data) +{ + const MatekbdIndicatorPlugin *plugin = rec->plugin; + if (plugin != NULL) { + xkl_debug (100, "Terminating plugin: [%s]...\n", + plugin->name); + if (plugin->term_callback) + (*plugin->term_callback) (); + } +} + +static void +matekbd_indicator_plugin_manager_rec_destroy (MatekbdIndicatorPluginManagerRecord + * rec) +{ + xkl_debug (100, "Unloading plugin: [%s]...\n", rec->plugin->name); + + g_module_close (rec->module); + g_free (rec); +} + +void +matekbd_indicator_plugin_manager_init (MatekbdIndicatorPluginManager * manager) +{ + manager->all_plugin_recs = + g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) + matekbd_indicator_plugin_manager_rec_destroy); + matekbd_indicator_plugin_manager_load_all (manager); +} + +void +matekbd_indicator_plugin_manager_term (MatekbdIndicatorPluginManager * manager) +{ + matekbd_indicator_plugin_manager_term_initialized_plugins (manager); + if (manager->all_plugin_recs != NULL) { + g_hash_table_destroy (manager->all_plugin_recs); + manager->all_plugin_recs = NULL; + } +} + +void + matekbd_indicator_plugin_manager_init_enabled_plugins + (MatekbdIndicatorPluginManager * manager, + MatekbdIndicatorPluginContainer * pc, GSList * enabled_plugins) { + GSList *plugin_name_node = enabled_plugins; + if (manager->all_plugin_recs == NULL) + return; + xkl_debug (100, "Initializing all enabled plugins...\n"); + while (plugin_name_node != NULL) { + const char *full_path = plugin_name_node->data; + if (full_path != NULL) { + MatekbdIndicatorPluginManagerRecord *rec = + (MatekbdIndicatorPluginManagerRecord *) + g_hash_table_lookup (manager->all_plugin_recs, + full_path); + + if (rec != NULL) { + const MatekbdIndicatorPlugin *plugin = + rec->plugin; + gboolean initialized = FALSE; + xkl_debug (100, + "Initializing plugin: [%s] from [%s]...\n", + plugin->name, full_path); + if (plugin->init_callback != NULL) + initialized = + (*plugin->init_callback) (pc); + else + initialized = TRUE; + + manager->inited_plugin_recs = + g_slist_append + (manager->inited_plugin_recs, rec); + xkl_debug (100, + "Plugin [%s] initialized: %d\n", + plugin->name, initialized); + } + } + plugin_name_node = g_slist_next (plugin_name_node); + } +} + +void + matekbd_indicator_plugin_manager_term_initialized_plugins + (MatekbdIndicatorPluginManager * manager) { + + if (manager->inited_plugin_recs == NULL) + return; + g_slist_foreach (manager->inited_plugin_recs, + (GFunc) matekbd_indicator_plugin_manager_rec_term, + NULL); + g_slist_free (manager->inited_plugin_recs); + manager->inited_plugin_recs = NULL; +} + +void +matekbd_indicator_plugin_manager_toggle_plugins (MatekbdIndicatorPluginManager * + manager, + MatekbdIndicatorPluginContainer + * pc, + GSList * enabled_plugins) +{ + matekbd_indicator_plugin_manager_term_initialized_plugins (manager); + matekbd_indicator_plugin_manager_init_enabled_plugins (manager, pc, + enabled_plugins); +} + +void +matekbd_indicator_plugin_manager_group_changed (MatekbdIndicatorPluginManager * + manager, GtkWidget * notebook, + int new_group) +{ + FOREACH_INITED_PLUGIN (); + if (plugin->group_changed_callback) + (*plugin->group_changed_callback) (notebook, new_group); + NEXT_INITED_PLUGIN (); +} + +void +matekbd_indicator_plugin_manager_config_changed (MatekbdIndicatorPluginManager * + manager, + MatekbdKeyboardConfig * from, + MatekbdKeyboardConfig * to) +{ + FOREACH_INITED_PLUGIN (); + if (plugin->config_changed_callback) + (*plugin->config_changed_callback) (from, to); + NEXT_INITED_PLUGIN (); +} + +const MatekbdIndicatorPlugin * +matekbd_indicator_plugin_manager_get_plugin (MatekbdIndicatorPluginManager * + manager, const char *full_path) +{ + MatekbdIndicatorPluginManagerRecord *rec = + (MatekbdIndicatorPluginManagerRecord *) + g_hash_table_lookup (manager->all_plugin_recs, + full_path); + if (rec == NULL) + return NULL; + return rec->plugin; +} + +void +matekbd_indicator_plugin_manager_promote_plugin (MatekbdIndicatorPluginManager * + manager, + GSList * enabled_plugins, + const char *full_path) +{ + GSList *the_node = enabled_plugins; + GSList *prev_node = NULL; + + while (the_node != NULL) { + if (!strcmp (the_node->data, full_path)) { + if (prev_node != NULL) { + char *tmp = (char *) prev_node->data; + prev_node->data = the_node->data; + the_node->data = tmp; + } + break; + } + prev_node = the_node; + the_node = g_slist_next (the_node); + } +} + +void +matekbd_indicator_plugin_manager_demote_plugin (MatekbdIndicatorPluginManager * + manager, + GSList * enabled_plugins, + const char *full_path) +{ + GSList *the_node = g_slist_find_custom (enabled_plugins, full_path, + (GCompareFunc) strcmp); + if (the_node != NULL) { + GSList *next_node = g_slist_next (the_node); + if (next_node != NULL) { + char *tmp = (char *) next_node->data; + next_node->data = the_node->data; + the_node->data = tmp; + } + } +} + +void +matekbd_indicator_plugin_manager_enable_plugin (MatekbdIndicatorPluginManager * + manager, + GSList ** enabled_plugins, + const char *full_path) +{ + if (NULL != + matekbd_indicator_plugin_manager_get_plugin (manager, + full_path)) { + *enabled_plugins = + g_slist_append (*enabled_plugins, + (gpointer) g_strdup (full_path)); + } +} + +void +matekbd_indicator_plugin_manager_disable_plugin (MatekbdIndicatorPluginManager * + manager, + GSList ** enabled_plugins, + const char *full_path) +{ + GSList *the_node = + g_slist_find_custom (*enabled_plugins, full_path, + (GCompareFunc) strcmp); + if (the_node != NULL) { + g_free (the_node->data); + *enabled_plugins = + g_slist_delete_link (*enabled_plugins, the_node); + } +} + +int +matekbd_indicator_plugin_manager_window_created (MatekbdIndicatorPluginManager * + manager, Window win, + Window parent) +{ + FOREACH_INITED_PLUGIN (); + if (plugin->window_created_callback) { + int group_to_assign = + (*plugin->window_created_callback) (win, parent); + if (group_to_assign != -1) { + xkl_debug (100, + "Plugin [%s] assigned group %d to new window %ld\n", + plugin->name, group_to_assign, win); + return group_to_assign; + } + } + NEXT_INITED_PLUGIN (); + return -1; +} + +GtkWidget * +matekbd_indicator_plugin_manager_decorate_widget (MatekbdIndicatorPluginManager * + manager, GtkWidget * widget, + const gint group, + const char + *group_description, + MatekbdKeyboardConfig * + kbd_config) +{ + FOREACH_INITED_PLUGIN (); + if (plugin->decorate_widget_callback) { + GtkWidget *decorated_widget = + (*plugin->decorate_widget_callback) (widget, group, + group_description, + kbd_config); + if (decorated_widget != NULL) { + xkl_debug (100, + "Plugin [%s] decorated widget %p to %p\n", + plugin->name, widget, decorated_widget); + return decorated_widget; + } + } + NEXT_INITED_PLUGIN (); + return NULL; +} + +void +matekbd_indicator_plugin_manager_configure_plugin (MatekbdIndicatorPluginManager + * manager, + MatekbdIndicatorPluginContainer + * pc, + const char *full_path, + GtkWindow * parent) +{ + const MatekbdIndicatorPlugin *plugin = + matekbd_indicator_plugin_manager_get_plugin (manager, full_path); + if (plugin->configure_properties_callback != NULL) + plugin->configure_properties_callback (pc, parent); +} + +void +matekbd_indicator_plugin_container_init (MatekbdIndicatorPluginContainer * pc, + MateConfClient * conf_client) +{ + pc->conf_client = conf_client; + g_object_ref (pc->conf_client); +} + +void +matekbd_indicator_plugin_container_term (MatekbdIndicatorPluginContainer * pc) +{ + g_object_unref (pc->conf_client); +} |