From 873cedbc95777e7b74960a66883c48945fcecd4c Mon Sep 17 00:00:00 2001 From: monsta Date: Tue, 5 Jan 2016 17:38:52 +0300 Subject: rename mate-panel-*.{c|h} -> panel-*.{c|h} for consistency (libmate-panel-applet files are left alone since there are public header files used by all panel applets) --- .../panel-applets-manager-dbus.c | 603 +++++++++++++++++++++ 1 file changed, 603 insertions(+) create mode 100644 mate-panel/libmate-panel-applet-private/panel-applets-manager-dbus.c (limited to 'mate-panel/libmate-panel-applet-private/panel-applets-manager-dbus.c') diff --git a/mate-panel/libmate-panel-applet-private/panel-applets-manager-dbus.c b/mate-panel/libmate-panel-applet-private/panel-applets-manager-dbus.c new file mode 100644 index 00000000..695f66fb --- /dev/null +++ b/mate-panel/libmate-panel-applet-private/panel-applets-manager-dbus.c @@ -0,0 +1,603 @@ +/* + * panel-applets-manager-dbus.c + * + * Copyright (C) 2010 Carlos Garcia Campos + * Copyright (C) 2010 Vincent Untz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include + +#include +#include +#include + +#include + +#include "panel-applet-frame-dbus.h" +#include "panel-applets-manager-dbus.h" + +G_DEFINE_TYPE_WITH_CODE (MatePanelAppletsManagerDBus, + mate_panel_applets_manager_dbus, + PANEL_TYPE_APPLETS_MANAGER, + g_io_extension_point_implement (MATE_PANEL_APPLETS_MANAGER_EXTENSION_POINT_NAME, + g_define_type_id, + "dbus", + 10)) + +struct _MatePanelAppletsManagerDBusPrivate +{ + GHashTable *applet_factories; + GList *monitors; +}; + +typedef gint (* ActivateAppletFunc) (void); + +typedef struct _MatePanelAppletFactoryInfo { + gchar *id; + gchar *location; + gboolean in_process; + GModule *module; + ActivateAppletFunc activate_applet; + guint n_applets; + + gchar *srcdir; + + GList *applet_list; + gboolean has_old_ids; +} MatePanelAppletFactoryInfo; + +#define MATE_PANEL_APPLET_FACTORY_GROUP "Applet Factory" +#define MATE_PANEL_APPLETS_EXTENSION ".mate-panel-applet" + +static void +mate_panel_applet_factory_info_free (MatePanelAppletFactoryInfo *info) +{ + if (!info) + return; + + g_free (info->id); + g_free (info->location); + g_list_foreach (info->applet_list, + (GFunc) mate_panel_applet_info_free, + NULL); + g_list_free (info->applet_list); + info->applet_list = NULL; + g_free (info->srcdir); + + g_slice_free (MatePanelAppletFactoryInfo, info); +} + +static MatePanelAppletInfo * +_mate_panel_applets_manager_get_applet_info (GKeyFile *applet_file, + const gchar *group, + const gchar *factory_id) +{ + MatePanelAppletInfo *info; + char *iid; + char *name; + char *comment; + char *icon; + char **old_ids; + + iid = g_strdup_printf ("%s::%s", factory_id, group); + name = g_key_file_get_locale_string (applet_file, group, + "Name", NULL, NULL); + comment = g_key_file_get_locale_string (applet_file, group, + "Description", NULL, NULL); + icon = g_key_file_get_string (applet_file, group, "Icon", NULL); + /* MateComponent compatibility */ + old_ids = g_key_file_get_string_list (applet_file, group, + "MateComponentId", NULL, NULL); + + info = mate_panel_applet_info_new (iid, name, comment, icon, (const char **) old_ids); + + g_free (iid); + g_free (name); + g_free (comment); + g_free (icon); + g_strfreev (old_ids); + + return info; +} + +static MatePanelAppletFactoryInfo * +mate_panel_applets_manager_get_applet_factory_info_from_file (const gchar *filename) +{ + MatePanelAppletFactoryInfo *info; + GKeyFile *applet_file; + gchar **groups; + gsize n_groups; + gint i; + GError *error = NULL; + + applet_file = g_key_file_new (); + if (!g_key_file_load_from_file (applet_file, filename, G_KEY_FILE_NONE, &error)) { + g_warning ("Error opening panel applet file %s: %s", + filename, error->message); + g_error_free (error); + g_key_file_free (applet_file); + + return NULL; + } + + info = g_slice_new0 (MatePanelAppletFactoryInfo); + info->id = g_key_file_get_string (applet_file, MATE_PANEL_APPLET_FACTORY_GROUP, "Id", NULL); + if (!info->id) { + g_warning ("Bad panel applet file %s: Could not find 'Id' in group '%s'", + filename, MATE_PANEL_APPLET_FACTORY_GROUP); + mate_panel_applet_factory_info_free (info); + g_key_file_free (applet_file); + + return NULL; + } + + info->in_process = g_key_file_get_boolean (applet_file, MATE_PANEL_APPLET_FACTORY_GROUP, + "InProcess", NULL); + if (info->in_process) { + info->location = g_key_file_get_string (applet_file, MATE_PANEL_APPLET_FACTORY_GROUP, + "Location", NULL); + if (!info->location) { + g_warning ("Bad panel applet file %s: In-process applet without 'Location'", + filename); + mate_panel_applet_factory_info_free (info); + g_key_file_free (applet_file); + + return NULL; + } + } + + info->has_old_ids = FALSE; + + groups = g_key_file_get_groups (applet_file, &n_groups); + for (i = 0; i < n_groups; i++) { + MatePanelAppletInfo *ainfo; + + if (g_strcmp0 (groups[i], MATE_PANEL_APPLET_FACTORY_GROUP) == 0) + continue; + + ainfo = _mate_panel_applets_manager_get_applet_info (applet_file, + groups[i], info->id); + if (mate_panel_applet_info_get_old_ids (ainfo) != NULL) + info->has_old_ids = TRUE; + + info->applet_list = g_list_prepend (info->applet_list, ainfo); + } + g_strfreev (groups); + + g_key_file_free (applet_file); + + if (!info->applet_list) { + mate_panel_applet_factory_info_free (info); + return NULL; + } + + info->srcdir = g_path_get_dirname (filename); + + return info; +} + +static GSList * +mate_panel_applets_manager_get_applets_dirs (void) +{ + const gchar *dir = NULL; + gchar **paths; + guint i; + GSList *retval = NULL; + + dir = g_getenv ("MATE_PANEL_APPLETS_DIR"); + if (!dir || g_strcmp0 (dir, "") == 0) { + return g_slist_prepend (NULL, g_strdup (MATE_PANEL_APPLETS_DIR)); + } + + paths = g_strsplit (dir, ":", 0); + for (i = 0; paths[i]; i++) { + if (g_slist_find_custom (retval, paths[i], (GCompareFunc) g_strcmp0)) + continue; + retval = g_slist_prepend (retval, g_strdup (paths[i])); + } + g_strfreev (paths); + + return g_slist_reverse (retval); +} + +static void +applets_directory_changed (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + gpointer user_data) +{ + MatePanelAppletsManagerDBus *manager = MATE_PANEL_APPLETS_MANAGER_DBUS (user_data); + + switch (event_type) { + case G_FILE_MONITOR_EVENT_CHANGED: + case G_FILE_MONITOR_EVENT_CREATED: { + MatePanelAppletFactoryInfo *info; + MatePanelAppletFactoryInfo *old_info; + gchar *filename; + GSList *dirs, *d; + + filename = g_file_get_path (file); + if (!g_str_has_suffix (filename, MATE_PANEL_APPLETS_EXTENSION)) { + g_free (filename); + return; + } + + info = mate_panel_applets_manager_get_applet_factory_info_from_file (filename); + g_free (filename); + + if (!info) + return; + + old_info = g_hash_table_lookup (manager->priv->applet_factories, info->id); + if (!old_info) { + /* New applet, just insert it */ + g_hash_table_insert (manager->priv->applet_factories, g_strdup (info->id), info); + return; + } + + /* Make sure we don't update an applet that has changed in + * another source dir unless it takes precedence over the + * current one */ + if (g_strcmp0 (info->srcdir, old_info->srcdir) == 0) { + g_hash_table_replace (manager->priv->applet_factories, g_strdup (info->id), info); + return; + } + + dirs = mate_panel_applets_manager_get_applets_dirs (); + + for (d = dirs; d; d = g_slist_next (d)) { + gchar *path = (gchar *) d->data; + + if (g_strcmp0 (path, old_info->srcdir) == 0) { + mate_panel_applet_factory_info_free (info); + break; + } else if (g_strcmp0 (path, info->srcdir) == 0) { + g_hash_table_replace (manager->priv->applet_factories, g_strdup (info->id), info); + break; + } + } + + g_slist_foreach (dirs, (GFunc) g_free, NULL); + g_slist_free (dirs); + } + break; + default: + /* Ignore any other change */ + break; + } +} + +static void +mate_panel_applets_manager_dbus_load_applet_infos (MatePanelAppletsManagerDBus *manager) +{ + GSList *dirs, *d; + GDir *dir; + const gchar *dirent; + GError *error = NULL; + + dirs = mate_panel_applets_manager_get_applets_dirs (); + for (d = dirs; d; d = g_slist_next (d)) { + GFileMonitor *monitor; + GFile *dir_file; + gchar *path = (gchar *) d->data; + + dir = g_dir_open (path, 0, &error); + if (!dir) { + g_warning ("%s", error->message); + g_error_free (error); + g_free (path); + + continue; + } + + /* Monitor dir */ + dir_file = g_file_new_for_path (path); + monitor = g_file_monitor_directory (dir_file, + G_FILE_MONITOR_NONE, + NULL, NULL); + if (monitor) { + g_signal_connect (monitor, "changed", + G_CALLBACK (applets_directory_changed), + manager); + manager->priv->monitors = g_list_prepend (manager->priv->monitors, monitor); + } + g_object_unref (dir_file); + + while ((dirent = g_dir_read_name (dir))) { + MatePanelAppletFactoryInfo *info; + gchar *file; + + if (!g_str_has_suffix (dirent, MATE_PANEL_APPLETS_EXTENSION)) + continue; + + file = g_build_filename (path, dirent, NULL); + info = mate_panel_applets_manager_get_applet_factory_info_from_file (file); + g_free (file); + + if (!info) + continue; + + if (g_hash_table_lookup (manager->priv->applet_factories, info->id)) { + mate_panel_applet_factory_info_free (info); + continue; + } + + g_hash_table_insert (manager->priv->applet_factories, g_strdup (info->id), info); + } + + g_dir_close (dir); + g_free (path); + } + + g_slist_free (dirs); +} + +static GList * +mate_panel_applets_manager_dbus_get_applets (MatePanelAppletsManager *manager) +{ + MatePanelAppletsManagerDBus *dbus_manager = MATE_PANEL_APPLETS_MANAGER_DBUS (manager); + + GHashTableIter iter; + gpointer key, value; + GList *retval = NULL; + + g_hash_table_iter_init (&iter, dbus_manager->priv->applet_factories); + while (g_hash_table_iter_next (&iter, &key, &value)) { + MatePanelAppletFactoryInfo *info; + + info = (MatePanelAppletFactoryInfo *) value; + retval = g_list_concat (retval, g_list_copy (info->applet_list)); + } + + return retval; +} + +static MatePanelAppletFactoryInfo * +get_applet_factory_info (MatePanelAppletsManager *manager, + const gchar *iid) +{ + MatePanelAppletsManagerDBus *dbus_manager = MATE_PANEL_APPLETS_MANAGER_DBUS (manager); + + MatePanelAppletFactoryInfo *info; + const gchar *sp; + gchar *factory_id; + + sp = g_strrstr (iid, "::"); + if (!sp) + return NULL; + + factory_id = g_strndup (iid, strlen (iid) - strlen (sp)); + info = g_hash_table_lookup (dbus_manager->priv->applet_factories, factory_id); + g_free (factory_id); + + return info; +} + +static gboolean +mate_panel_applets_manager_dbus_factory_activate (MatePanelAppletsManager *manager, + const gchar *iid) +{ + MatePanelAppletFactoryInfo *info; + ActivateAppletFunc activate_applet; + + info = get_applet_factory_info (manager, iid); + if (!info) + return FALSE; + + /* Out-of-process applets are activated by the session bus */ + if (!info->in_process) + return TRUE; + + if (info->module) { + if (info->n_applets == 0) { + if (info->activate_applet () != 0) { + g_warning ("Failed to reactivate factory %s\n", iid); + return FALSE; + } + } + info->n_applets++; + + return TRUE; + } + + info->module = g_module_open (info->location, G_MODULE_BIND_LAZY); + if (!info->module) { + /* FIXME: use a GError? */ + g_warning ("Failed to load applet %s: %s\n", + iid, g_module_error ()); + return FALSE; + } + + if (!g_module_symbol (info->module, "_mate_panel_applet_shlib_factory", (gpointer *) &activate_applet)) { + /* FIXME: use a GError? */ + g_warning ("Failed to load applet %s: %s\n", + iid, g_module_error ()); + g_module_close (info->module); + info->module = NULL; + + return FALSE; + } + + /* Activate the applet */ + if (activate_applet () != 0) { + /* FIXME: use a GError? */ + g_warning ("Failed to load applet %s\n", iid); + g_module_close (info->module); + info->module = NULL; + + return FALSE; + } + info->activate_applet = activate_applet; + + info->n_applets = 1; + + return TRUE; +} + +static gboolean +mate_panel_applets_manager_dbus_factory_deactivate (MatePanelAppletsManager *manager, + const gchar *iid) +{ + MatePanelAppletFactoryInfo *info; + + info = get_applet_factory_info (manager, iid); + if (!info) + return FALSE; + + /* Out-of-process applets are deactivated by the session bus */ + if (!info->in_process) + return TRUE; + + if (!info->module) + return TRUE; + + info->n_applets--; + if (info->n_applets == 0) { + /* FIXME: we should close the module here, however applet types + * are registered static */ +#if 0 + g_module_close (info->module); + info->module = NULL; +#endif + } + + return TRUE; +} + +static MatePanelAppletInfo * +mate_panel_applets_manager_dbus_get_applet_info (MatePanelAppletsManager *manager, + const gchar *iid) +{ + MatePanelAppletFactoryInfo *info; + GList *l; + + info = get_applet_factory_info (manager, iid); + if (!info) + return NULL; + + for (l = info->applet_list; l; l = g_list_next (l)) { + MatePanelAppletInfo *ainfo = (MatePanelAppletInfo *) l->data; + + if (g_strcmp0 (mate_panel_applet_info_get_iid (ainfo), iid) == 0) + return ainfo; + } + + return NULL; +} + +static MatePanelAppletInfo * +mate_panel_applets_manager_dbus_get_applet_info_from_old_id (MatePanelAppletsManager *manager, + const gchar *iid) +{ + MatePanelAppletsManagerDBus *dbus_manager = MATE_PANEL_APPLETS_MANAGER_DBUS (manager); + + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init (&iter, dbus_manager->priv->applet_factories); + while (g_hash_table_iter_next (&iter, &key, &value)) { + MatePanelAppletFactoryInfo *info; + GList *l; + + info = (MatePanelAppletFactoryInfo *) value; + if (!info->has_old_ids) + continue; + + for (l = info->applet_list; l; l = g_list_next (l)) { + MatePanelAppletInfo *ainfo; + gint i = 0; + const gchar * const *old_ids; + + ainfo = (MatePanelAppletInfo *) l->data; + + old_ids = mate_panel_applet_info_get_old_ids (ainfo); + + if (old_ids == NULL) + continue; + + while (old_ids[i]) { + if (g_strcmp0 (old_ids[i], iid) == 0) + return ainfo; + i++; + } + } + } + + return NULL; +} + +static gboolean +mate_panel_applets_manager_dbus_load_applet (MatePanelAppletsManager *manager, + const gchar *iid, + MatePanelAppletFrameActivating *frame_act) +{ + return mate_panel_applet_frame_dbus_load (iid, frame_act); +} + +static void +mate_panel_applets_manager_dbus_finalize (GObject *object) +{ + MatePanelAppletsManagerDBus *manager = MATE_PANEL_APPLETS_MANAGER_DBUS (object); + + if (manager->priv->monitors) { + g_list_foreach (manager->priv->monitors, (GFunc) g_object_unref, NULL); + g_list_free (manager->priv->monitors); + manager->priv->monitors = NULL; + } + + if (manager->priv->applet_factories) { + g_hash_table_destroy (manager->priv->applet_factories); + manager->priv->applet_factories = NULL; + } + + G_OBJECT_CLASS (mate_panel_applets_manager_dbus_parent_class)->finalize (object); +} + +static void +mate_panel_applets_manager_dbus_init (MatePanelAppletsManagerDBus *manager) +{ + manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, + PANEL_TYPE_APPLETS_MANAGER_DBUS, + MatePanelAppletsManagerDBusPrivate); + + manager->priv->applet_factories = g_hash_table_new_full (g_str_hash, + g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) mate_panel_applet_factory_info_free); + + mate_panel_applets_manager_dbus_load_applet_infos (manager); +} + +static void +mate_panel_applets_manager_dbus_class_init (MatePanelAppletsManagerDBusClass *class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (class); + MatePanelAppletsManagerClass *manager_class = MATE_PANEL_APPLETS_MANAGER_CLASS (class); + + gobject_class->finalize = mate_panel_applets_manager_dbus_finalize; + + manager_class->get_applets = mate_panel_applets_manager_dbus_get_applets; + manager_class->factory_activate = mate_panel_applets_manager_dbus_factory_activate; + manager_class->factory_deactivate = mate_panel_applets_manager_dbus_factory_deactivate; + manager_class->get_applet_info = mate_panel_applets_manager_dbus_get_applet_info; + manager_class->get_applet_info_from_old_id = mate_panel_applets_manager_dbus_get_applet_info_from_old_id; + manager_class->load_applet = mate_panel_applets_manager_dbus_load_applet; + + g_type_class_add_private (class, sizeof (MatePanelAppletsManagerDBusPrivate)); +} -- cgit v1.2.1