2008-09-18 11:09:11 -04:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2008 Intel Corp.
|
|
|
|
*
|
|
|
|
* Author: Tomas Frydrych <tf@linux.intel.com>
|
|
|
|
*
|
|
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
* 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2008-10-28 06:45:45 -04:00
|
|
|
#include "config.h"
|
2009-08-12 00:12:52 -04:00
|
|
|
#include "compositor-private.h"
|
2010-10-18 13:27:14 -04:00
|
|
|
#include "meta-plugin-manager.h"
|
2008-09-18 11:09:11 -04:00
|
|
|
#include "prefs.h"
|
|
|
|
#include "errors.h"
|
|
|
|
#include "workspace.h"
|
2010-10-18 13:27:14 -04:00
|
|
|
#include "meta-module.h"
|
2009-08-05 14:05:10 -04:00
|
|
|
#include "../core/window-private.h"
|
2008-09-18 11:09:11 -04:00
|
|
|
|
|
|
|
#include <string.h>
|
2011-02-03 12:51:35 -05:00
|
|
|
#include <stdlib.h>
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2009-07-22 14:37:43 -04:00
|
|
|
#include <clutter/x11/clutter-x11.h>
|
|
|
|
|
2008-12-17 04:33:56 -05:00
|
|
|
/*
|
|
|
|
* There is only one instace of each module per the process.
|
|
|
|
*/
|
|
|
|
static GHashTable *plugin_modules = NULL;
|
|
|
|
|
2010-04-12 17:42:46 -04:00
|
|
|
/*
|
|
|
|
* We have one "default plugin manager" that acts for the first screen,
|
|
|
|
* but also can be used before we open any screens, and additional
|
|
|
|
* plugin managers for each screen. (This is ugly. Probably we should
|
|
|
|
* have one plugin manager and only make the plugins per-screen.)
|
|
|
|
*/
|
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
static MetaPluginManager *default_plugin_manager;
|
2010-04-12 17:42:46 -04:00
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
static gboolean meta_plugin_manager_reload (MetaPluginManager *plugin_mgr);
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
struct MetaPluginManager
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
|
|
|
MetaScreen *screen;
|
|
|
|
|
2011-02-25 14:38:04 -05:00
|
|
|
gboolean plugin_load_attempted;
|
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
GList /* MetaPlugin */ *plugins; /* TODO -- maybe use hash table */
|
|
|
|
GList *unload; /* Plugins that are disabled and pending unload */
|
2008-09-18 11:09:11 -04:00
|
|
|
|
|
|
|
guint idle_unload_id;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Checks that the plugin is compatible with the WM and sets up the plugin
|
|
|
|
* struct.
|
|
|
|
*/
|
2010-10-18 13:27:14 -04:00
|
|
|
static MetaPlugin *
|
|
|
|
meta_plugin_load (MetaPluginManager *mgr,
|
|
|
|
MetaModule *module,
|
|
|
|
const gchar *params)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaPlugin *plugin = NULL;
|
|
|
|
GType plugin_type = meta_module_get_plugin_type (module);
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2008-12-17 04:33:56 -05:00
|
|
|
if (!plugin_type)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2008-12-17 04:33:56 -05:00
|
|
|
g_warning ("Plugin type not registered !!!");
|
|
|
|
return NULL;
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
|
|
|
|
2008-12-17 04:33:56 -05:00
|
|
|
plugin = g_object_new (plugin_type,
|
|
|
|
"params", params,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
return plugin;
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Attempst to unload a plugin; returns FALSE if plugin cannot be unloaded at
|
|
|
|
* present (e.g., and effect is in progress) and should be scheduled for
|
|
|
|
* removal later.
|
|
|
|
*/
|
|
|
|
static gboolean
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_unload (MetaPlugin *plugin)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
if (meta_plugin_running (plugin))
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2008-12-17 04:33:56 -05:00
|
|
|
g_object_set (plugin, "disabled", TRUE, NULL);
|
2008-09-18 11:09:11 -04:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2008-12-17 04:33:56 -05:00
|
|
|
g_object_unref (plugin);
|
2008-09-18 11:09:11 -04:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Iddle callback to remove plugins that could not be removed directly and are
|
|
|
|
* pending for removal.
|
|
|
|
*/
|
|
|
|
static gboolean
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_idle_unload (MetaPluginManager *plugin_mgr)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2008-10-13 07:23:47 -04:00
|
|
|
GList *l = plugin_mgr->unload;
|
2008-09-18 11:09:11 -04:00
|
|
|
gboolean dont_remove = TRUE;
|
|
|
|
|
|
|
|
while (l)
|
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaPlugin *plugin = l->data;
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
if (meta_plugin_unload (plugin))
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
|
|
|
/* Remove from list */
|
|
|
|
GList *p = l->prev;
|
|
|
|
GList *n = l->next;
|
|
|
|
|
|
|
|
if (!p)
|
2008-10-13 07:23:47 -04:00
|
|
|
plugin_mgr->unload = n;
|
2008-09-18 11:09:11 -04:00
|
|
|
else
|
|
|
|
p->next = n;
|
|
|
|
|
|
|
|
if (n)
|
|
|
|
n->prev = p;
|
|
|
|
|
|
|
|
g_list_free_1 (l);
|
|
|
|
|
|
|
|
l = n;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
l = l->next;
|
|
|
|
}
|
|
|
|
|
2008-10-13 07:23:47 -04:00
|
|
|
if (!plugin_mgr->unload)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
|
|
|
/* If no more unloads are pending, remove the handler as well */
|
|
|
|
dont_remove = FALSE;
|
2008-10-13 07:23:47 -04:00
|
|
|
plugin_mgr->idle_unload_id = 0;
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return dont_remove;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unloads all plugins
|
|
|
|
*/
|
|
|
|
static void
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_unload (MetaPluginManager *plugin_mgr)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2008-10-13 07:23:47 -04:00
|
|
|
GList *plugins = plugin_mgr->plugins;
|
2008-09-18 11:09:11 -04:00
|
|
|
|
|
|
|
while (plugins)
|
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaPlugin *plugin = plugins->data;
|
2008-09-18 11:09:11 -04:00
|
|
|
|
|
|
|
/* If the plugin could not be removed, move it to the unload list */
|
2010-10-18 13:27:14 -04:00
|
|
|
if (!meta_plugin_unload (plugin))
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2008-10-13 07:23:47 -04:00
|
|
|
plugin_mgr->unload = g_list_prepend (plugin_mgr->unload, plugin);
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2008-10-13 07:23:47 -04:00
|
|
|
if (!plugin_mgr->idle_unload_id)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2008-10-13 07:23:47 -04:00
|
|
|
plugin_mgr->idle_unload_id = g_idle_add ((GSourceFunc)
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_idle_unload,
|
2008-10-13 07:23:47 -04:00
|
|
|
plugin_mgr);
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
plugins = plugins->next;
|
|
|
|
}
|
|
|
|
|
2008-10-13 07:23:47 -04:00
|
|
|
g_list_free (plugin_mgr->plugins);
|
|
|
|
plugin_mgr->plugins = NULL;
|
2011-02-25 14:38:04 -05:00
|
|
|
|
|
|
|
plugin_mgr->plugin_load_attempted = FALSE;
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
prefs_changed_callback (MetaPreference pref,
|
|
|
|
void *data)
|
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaPluginManager *plugin_mgr = data;
|
2008-09-18 11:09:11 -04:00
|
|
|
|
|
|
|
if (pref == META_PREF_CLUTTER_PLUGINS)
|
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_reload (plugin_mgr);
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
2008-12-17 04:33:56 -05:00
|
|
|
}
|
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
static MetaModule *
|
|
|
|
meta_plugin_manager_get_module (const gchar *path)
|
2008-12-17 04:33:56 -05:00
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaModule *module = g_hash_table_lookup (plugin_modules, path);
|
2008-12-17 04:33:56 -05:00
|
|
|
|
|
|
|
if (!module &&
|
2010-10-18 13:27:14 -04:00
|
|
|
(module = g_object_new (META_TYPE_MODULE, "path", path, NULL)))
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2008-12-17 04:33:56 -05:00
|
|
|
g_hash_table_insert (plugin_modules, g_strdup (path), module);
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
2008-12-17 04:33:56 -05:00
|
|
|
|
|
|
|
return module;
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Loads all plugins listed in gconf registry.
|
|
|
|
*/
|
2008-11-13 17:06:07 -05:00
|
|
|
gboolean
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_load (MetaPluginManager *plugin_mgr)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2008-10-29 06:28:48 -04:00
|
|
|
const gchar *dpath = MUTTER_PLUGIN_DIR "/";
|
2008-10-09 10:33:06 -04:00
|
|
|
GSList *plugins, *fallback = NULL;
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2011-02-25 14:38:04 -05:00
|
|
|
if (plugin_mgr->plugin_load_attempted)
|
|
|
|
return TRUE;
|
|
|
|
plugin_mgr->plugin_load_attempted = TRUE;
|
|
|
|
|
2008-09-18 11:09:11 -04:00
|
|
|
plugins = meta_prefs_get_clutter_plugins ();
|
|
|
|
|
2008-10-09 10:33:06 -04:00
|
|
|
if (!plugins)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If no plugins are specified, try to load the default plugin.
|
|
|
|
*/
|
|
|
|
fallback = g_slist_append (fallback, "default");
|
|
|
|
plugins = fallback;
|
|
|
|
}
|
|
|
|
|
2008-09-18 11:09:11 -04:00
|
|
|
while (plugins)
|
|
|
|
{
|
2008-10-13 07:23:47 -04:00
|
|
|
gchar *plugin_string;
|
2008-09-18 11:09:11 -04:00
|
|
|
gchar *params;
|
|
|
|
|
2008-10-13 07:23:47 -04:00
|
|
|
plugin_string = g_strdup (plugins->data);
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2008-10-13 07:23:47 -04:00
|
|
|
if (plugin_string)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaModule *module;
|
2008-12-17 04:33:56 -05:00
|
|
|
gchar *path;
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2008-10-13 07:23:47 -04:00
|
|
|
params = strchr (plugin_string, ':');
|
2008-09-18 11:09:11 -04:00
|
|
|
|
|
|
|
if (params)
|
|
|
|
{
|
|
|
|
*params = 0;
|
|
|
|
++params;
|
|
|
|
}
|
|
|
|
|
2008-10-31 02:13:53 -04:00
|
|
|
if (g_path_is_absolute (plugin_string))
|
|
|
|
path = g_strdup (plugin_string);
|
|
|
|
else
|
|
|
|
path = g_strconcat (dpath, plugin_string, ".so", NULL);
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
module = meta_plugin_manager_get_module (path);
|
2008-12-17 04:33:56 -05:00
|
|
|
|
|
|
|
if (module)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2008-12-18 07:56:32 -05:00
|
|
|
gboolean use_succeeded;
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2008-12-17 04:33:56 -05:00
|
|
|
/*
|
|
|
|
* This dlopens the module and registers the plugin type with the
|
|
|
|
* GType system, if the module is not already loaded. When we
|
|
|
|
* create a plugin, the type system also calls g_type_module_use()
|
|
|
|
* to guarantee the module will not be unloaded during the plugin
|
|
|
|
* life time. Consequently we can unuse() the module again.
|
|
|
|
*/
|
2008-12-18 07:56:32 -05:00
|
|
|
use_succeeded = g_type_module_use (G_TYPE_MODULE (module));
|
2008-12-17 04:33:56 -05:00
|
|
|
|
2008-11-13 17:06:07 -05:00
|
|
|
if (use_succeeded)
|
2008-10-07 11:29:03 -04:00
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaPlugin *plugin = meta_plugin_load (plugin_mgr, module, params);
|
2010-04-12 17:34:49 -04:00
|
|
|
|
|
|
|
if (plugin)
|
|
|
|
plugin_mgr->plugins = g_list_prepend (plugin_mgr->plugins, plugin);
|
|
|
|
else
|
|
|
|
g_warning ("Plugin load for [%s] failed", path);
|
|
|
|
|
|
|
|
g_type_module_unuse (G_TYPE_MODULE (module));
|
2008-10-07 11:29:03 -04:00
|
|
|
}
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
2008-10-07 11:29:03 -04:00
|
|
|
else
|
2011-02-03 12:51:35 -05:00
|
|
|
{
|
|
|
|
/* This is fatal under the assumption that a monitoring
|
|
|
|
* process like gnome-session will take over and handle
|
|
|
|
* our untimely exit.
|
|
|
|
*/
|
|
|
|
g_printerr ("Unable to load plugin module [%s]: %s",
|
|
|
|
path, g_module_error());
|
|
|
|
exit (1);
|
|
|
|
}
|
2008-10-28 07:30:29 -04:00
|
|
|
|
2008-09-18 11:09:11 -04:00
|
|
|
g_free (path);
|
2008-10-13 07:23:47 -04:00
|
|
|
g_free (plugin_string);
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
plugins = plugins->next;
|
|
|
|
}
|
|
|
|
|
2008-10-09 10:33:06 -04:00
|
|
|
|
|
|
|
if (fallback)
|
|
|
|
g_slist_free (fallback);
|
|
|
|
|
2010-04-12 17:34:49 -04:00
|
|
|
if (plugin_mgr->plugins != NULL)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2008-10-13 07:23:47 -04:00
|
|
|
meta_prefs_add_listener (prefs_changed_callback, plugin_mgr);
|
2008-09-18 11:09:11 -04:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2011-02-25 14:38:04 -05:00
|
|
|
/**
|
|
|
|
* meta_plugin_manager_initialize_early:
|
|
|
|
* @plugin_mgr: a #MetaPluginManager
|
|
|
|
*
|
|
|
|
* This function invokes any plugin handling code that needs to be run
|
|
|
|
* effectively immediately after we know which plugins are going to be
|
|
|
|
* used. This means before the process has an X connection, or
|
|
|
|
* talks to the session manager, for example.
|
|
|
|
*
|
|
|
|
* An example intended use is claiming DBus names.
|
|
|
|
*/
|
|
|
|
gboolean
|
|
|
|
meta_plugin_manager_initialize_early (MetaPluginManager *plugin_mgr)
|
|
|
|
{
|
|
|
|
GList *iter;
|
|
|
|
|
|
|
|
for (iter = plugin_mgr->plugins; iter; iter = iter->next)
|
|
|
|
{
|
|
|
|
MetaPlugin *plugin = (MetaPlugin*) iter->data;
|
|
|
|
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
|
|
|
|
|
|
|
if (klass->early_initialize)
|
|
|
|
klass->early_initialize (plugin);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-11-13 17:06:07 -05:00
|
|
|
gboolean
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_initialize (MetaPluginManager *plugin_mgr)
|
2008-11-13 17:06:07 -05:00
|
|
|
{
|
|
|
|
GList *iter;
|
|
|
|
|
2010-04-12 17:34:49 -04:00
|
|
|
for (iter = plugin_mgr->plugins; iter; iter = iter->next)
|
2008-11-13 17:06:07 -05:00
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaPlugin *plugin = (MetaPlugin*) iter->data;
|
|
|
|
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
2008-11-13 17:06:07 -05:00
|
|
|
|
2010-04-12 17:34:49 -04:00
|
|
|
g_object_set (plugin,
|
|
|
|
"screen", plugin_mgr->screen,
|
|
|
|
NULL);
|
2008-11-13 17:06:07 -05:00
|
|
|
|
2010-04-12 17:34:49 -04:00
|
|
|
if (klass->start)
|
|
|
|
klass->start (plugin);
|
2008-11-13 17:06:07 -05:00
|
|
|
}
|
2010-04-12 17:34:49 -04:00
|
|
|
|
2008-11-13 17:06:07 -05:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-09-18 11:09:11 -04:00
|
|
|
/*
|
|
|
|
* Reloads all plugins
|
|
|
|
*/
|
|
|
|
static gboolean
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_reload (MetaPluginManager *plugin_mgr)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
|
|
|
/* TODO -- brute force; should we build a list of plugins to load and list of
|
|
|
|
* plugins to unload? We are probably not going to have large numbers of
|
|
|
|
* plugins loaded at the same time, so it might not be worth it.
|
|
|
|
*/
|
2009-08-12 00:12:52 -04:00
|
|
|
|
|
|
|
/* Prevent stale grabs on unloaded plugins */
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_check_end_modal (plugin_mgr->screen);
|
2009-08-12 00:12:52 -04:00
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_unload (plugin_mgr);
|
|
|
|
return meta_plugin_manager_load (plugin_mgr);
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
static MetaPluginManager *
|
|
|
|
meta_plugin_manager_new (MetaScreen *screen)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaPluginManager *plugin_mgr;
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2008-12-17 04:33:56 -05:00
|
|
|
if (!plugin_modules)
|
|
|
|
{
|
|
|
|
plugin_modules = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
plugin_mgr = g_new0 (MetaPluginManager, 1);
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2008-10-13 07:23:47 -04:00
|
|
|
plugin_mgr->screen = screen;
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2010-04-12 17:42:46 -04:00
|
|
|
if (screen)
|
2010-10-18 13:27:14 -04:00
|
|
|
g_object_set_data (G_OBJECT (screen), "meta-plugin-manager", plugin_mgr);
|
2010-04-12 17:42:46 -04:00
|
|
|
|
2008-10-13 07:23:47 -04:00
|
|
|
return plugin_mgr;
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaPluginManager *
|
|
|
|
meta_plugin_manager_get_default (void)
|
2010-04-12 17:42:46 -04:00
|
|
|
{
|
|
|
|
if (!default_plugin_manager)
|
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
default_plugin_manager = meta_plugin_manager_new (NULL);
|
2010-04-12 17:42:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return default_plugin_manager;
|
|
|
|
}
|
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaPluginManager *
|
|
|
|
meta_plugin_manager_get (MetaScreen *screen)
|
2010-04-12 17:42:46 -04:00
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaPluginManager *plugin_mgr;
|
2010-04-12 17:42:46 -04:00
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
plugin_mgr = g_object_get_data (G_OBJECT (screen), "meta-plugin-manager");
|
2010-04-12 17:42:46 -04:00
|
|
|
if (plugin_mgr)
|
|
|
|
return plugin_mgr;
|
|
|
|
|
|
|
|
if (!default_plugin_manager)
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_get_default ();
|
2010-04-12 17:42:46 -04:00
|
|
|
|
|
|
|
if (!default_plugin_manager->screen)
|
|
|
|
{
|
|
|
|
/* The default plugin manager is so far unused, we can recycle it */
|
|
|
|
default_plugin_manager->screen = screen;
|
2010-10-18 13:27:14 -04:00
|
|
|
g_object_set_data (G_OBJECT (screen), "meta-plugin-manager", default_plugin_manager);
|
2010-04-12 17:42:46 -04:00
|
|
|
|
|
|
|
return default_plugin_manager;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
return meta_plugin_manager_new (screen);
|
2010-04-12 17:42:46 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-07 11:29:03 -04:00
|
|
|
static void
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_kill_window_effects (MetaPluginManager *plugin_mgr,
|
|
|
|
MetaWindowActor *actor)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2008-10-13 07:23:47 -04:00
|
|
|
GList *l = plugin_mgr->plugins;
|
2008-09-18 11:09:11 -04:00
|
|
|
|
|
|
|
while (l)
|
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaPlugin *plugin = l->data;
|
|
|
|
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
if (!meta_plugin_disabled (plugin)
|
2010-06-16 17:15:56 -04:00
|
|
|
&& klass->kill_window_effects)
|
|
|
|
klass->kill_window_effects (plugin, actor);
|
|
|
|
|
|
|
|
l = l->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_kill_switch_workspace (MetaPluginManager *plugin_mgr)
|
2010-06-16 17:15:56 -04:00
|
|
|
{
|
|
|
|
GList *l = plugin_mgr->plugins;
|
|
|
|
|
|
|
|
while (l)
|
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaPlugin *plugin = l->data;
|
|
|
|
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
2010-06-16 17:15:56 -04:00
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
if (!meta_plugin_disabled (plugin)
|
|
|
|
&& (meta_plugin_features (plugin) & META_PLUGIN_SWITCH_WORKSPACE)
|
2010-06-16 17:15:56 -04:00
|
|
|
&& klass->kill_switch_workspace)
|
|
|
|
klass->kill_switch_workspace (plugin);
|
2008-09-18 11:09:11 -04:00
|
|
|
|
|
|
|
l = l->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Public method that the compositor hooks into for events that require
|
|
|
|
* no additional parameters.
|
|
|
|
*
|
|
|
|
* Returns TRUE if at least one of the plugins handled the event type (i.e.,
|
|
|
|
* if the return value is FALSE, there will be no subsequent call to the
|
|
|
|
* manager completed() callback, and the compositor must ensure that any
|
|
|
|
* appropriate post-effect cleanup is carried out.
|
|
|
|
*/
|
|
|
|
gboolean
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
|
|
|
MetaWindowActor *actor,
|
|
|
|
unsigned long event)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2008-10-13 07:23:47 -04:00
|
|
|
GList *l = plugin_mgr->plugins;
|
2008-09-18 11:09:11 -04:00
|
|
|
gboolean retval = FALSE;
|
2009-08-05 14:05:10 -04:00
|
|
|
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
|
|
|
|
|
|
|
if (display->display_opening)
|
|
|
|
return FALSE;
|
2008-09-18 11:09:11 -04:00
|
|
|
|
|
|
|
while (l)
|
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaPlugin *plugin = l->data;
|
|
|
|
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
if (!meta_plugin_disabled (plugin) &&
|
|
|
|
(meta_plugin_features (plugin) & event))
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
|
|
|
retval = TRUE;
|
|
|
|
|
|
|
|
switch (event)
|
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
case META_PLUGIN_MINIMIZE:
|
2008-12-17 04:33:56 -05:00
|
|
|
if (klass->minimize)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_kill_window_effects (
|
2008-10-13 07:23:47 -04:00
|
|
|
plugin_mgr,
|
2010-06-16 17:15:56 -04:00
|
|
|
actor);
|
2008-10-13 07:23:47 -04:00
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
_meta_plugin_effect_started (plugin);
|
2008-12-17 04:33:56 -05:00
|
|
|
klass->minimize (plugin, actor);
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
|
|
|
break;
|
2010-10-18 13:27:14 -04:00
|
|
|
case META_PLUGIN_MAP:
|
2008-12-17 04:33:56 -05:00
|
|
|
if (klass->map)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_kill_window_effects (
|
2008-10-13 07:23:47 -04:00
|
|
|
plugin_mgr,
|
2010-06-16 17:15:56 -04:00
|
|
|
actor);
|
2008-10-13 07:23:47 -04:00
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
_meta_plugin_effect_started (plugin);
|
2008-12-17 04:33:56 -05:00
|
|
|
klass->map (plugin, actor);
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
|
|
|
break;
|
2010-10-18 13:27:14 -04:00
|
|
|
case META_PLUGIN_DESTROY:
|
2008-12-17 04:33:56 -05:00
|
|
|
if (klass->destroy)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
_meta_plugin_effect_started (plugin);
|
2008-12-17 04:33:56 -05:00
|
|
|
klass->destroy (plugin, actor);
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_warning ("Incorrect handler called for event %lu", event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
l = l->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2008-10-07 04:01:58 -04:00
|
|
|
* The public method that the compositor hooks into for maximize and unmaximize
|
|
|
|
* events.
|
2008-09-18 11:09:11 -04:00
|
|
|
*
|
|
|
|
* Returns TRUE if at least one of the plugins handled the event type (i.e.,
|
|
|
|
* if the return value is FALSE, there will be no subsequent call to the
|
|
|
|
* manager completed() callback, and the compositor must ensure that any
|
|
|
|
* appropriate post-effect cleanup is carried out.
|
|
|
|
*/
|
|
|
|
gboolean
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
|
|
|
|
MetaWindowActor *actor,
|
|
|
|
unsigned long event,
|
|
|
|
gint target_x,
|
|
|
|
gint target_y,
|
|
|
|
gint target_width,
|
|
|
|
gint target_height)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2008-10-13 07:23:47 -04:00
|
|
|
GList *l = plugin_mgr->plugins;
|
2008-09-18 11:09:11 -04:00
|
|
|
gboolean retval = FALSE;
|
2009-08-05 14:05:10 -04:00
|
|
|
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
|
|
|
|
|
|
|
if (display->display_opening)
|
|
|
|
return FALSE;
|
2008-09-18 11:09:11 -04:00
|
|
|
|
|
|
|
while (l)
|
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaPlugin *plugin = l->data;
|
|
|
|
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
if (!meta_plugin_disabled (plugin) &&
|
|
|
|
(meta_plugin_features (plugin) & event))
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
|
|
|
retval = TRUE;
|
|
|
|
|
|
|
|
switch (event)
|
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
case META_PLUGIN_MAXIMIZE:
|
2008-12-17 04:33:56 -05:00
|
|
|
if (klass->maximize)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_kill_window_effects (
|
2008-10-13 07:23:47 -04:00
|
|
|
plugin_mgr,
|
2010-06-16 17:15:56 -04:00
|
|
|
actor);
|
2008-10-13 07:23:47 -04:00
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
_meta_plugin_effect_started (plugin);
|
2008-12-17 04:33:56 -05:00
|
|
|
klass->maximize (plugin, actor,
|
|
|
|
target_x, target_y,
|
|
|
|
target_width, target_height);
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
|
|
|
break;
|
2010-10-18 13:27:14 -04:00
|
|
|
case META_PLUGIN_UNMAXIMIZE:
|
2008-12-17 04:33:56 -05:00
|
|
|
if (klass->unmaximize)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_kill_window_effects (
|
2008-10-13 07:23:47 -04:00
|
|
|
plugin_mgr,
|
2010-06-16 17:15:56 -04:00
|
|
|
actor);
|
2008-12-22 16:53:10 -05:00
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
_meta_plugin_effect_started (plugin);
|
2008-12-17 04:33:56 -05:00
|
|
|
klass->unmaximize (plugin, actor,
|
|
|
|
target_x, target_y,
|
|
|
|
target_width, target_height);
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_warning ("Incorrect handler called for event %lu", event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
l = l->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The public method that the compositor hooks into for desktop switching.
|
|
|
|
*
|
|
|
|
* Returns TRUE if at least one of the plugins handled the event type (i.e.,
|
|
|
|
* if the return value is FALSE, there will be no subsequent call to the
|
|
|
|
* manager completed() callback, and the compositor must ensure that any
|
|
|
|
* appropriate post-effect cleanup is carried out.
|
|
|
|
*/
|
|
|
|
gboolean
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_switch_workspace (MetaPluginManager *plugin_mgr,
|
|
|
|
gint from,
|
|
|
|
gint to,
|
|
|
|
MetaMotionDirection direction)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2008-10-13 07:23:47 -04:00
|
|
|
GList *l = plugin_mgr->plugins;
|
2008-09-18 11:09:11 -04:00
|
|
|
gboolean retval = FALSE;
|
2009-08-05 14:05:10 -04:00
|
|
|
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
|
|
|
|
|
|
|
if (display->display_opening)
|
|
|
|
return FALSE;
|
2008-09-18 11:09:11 -04:00
|
|
|
|
|
|
|
while (l)
|
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaPlugin *plugin = l->data;
|
|
|
|
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
if (!meta_plugin_disabled (plugin) &&
|
|
|
|
(meta_plugin_features (plugin) & META_PLUGIN_SWITCH_WORKSPACE))
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2008-12-17 04:33:56 -05:00
|
|
|
if (klass->switch_workspace)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
|
|
|
retval = TRUE;
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_kill_switch_workspace (plugin_mgr);
|
2008-10-13 07:23:47 -04:00
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
_meta_plugin_effect_started (plugin);
|
2010-06-16 17:15:56 -04:00
|
|
|
klass->switch_workspace (plugin, from, to, direction);
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
l = l->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
2008-10-02 07:16:15 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The public method that the compositor hooks into for desktop switching.
|
|
|
|
*
|
|
|
|
* Returns TRUE if at least one of the plugins handled the event type (i.e.,
|
|
|
|
* if the return value is FALSE, there will be no subsequent call to the
|
|
|
|
* manager completed() callback, and the compositor must ensure that any
|
|
|
|
* appropriate post-effect cleanup is carried out.
|
|
|
|
*/
|
|
|
|
gboolean
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr,
|
|
|
|
XEvent *xev)
|
2008-10-02 07:16:15 -04:00
|
|
|
{
|
2008-10-07 11:29:03 -04:00
|
|
|
GList *l;
|
2009-07-22 14:37:43 -04:00
|
|
|
gboolean have_plugin_xevent_func;
|
2008-10-07 11:29:03 -04:00
|
|
|
|
2008-10-13 07:23:47 -04:00
|
|
|
if (!plugin_mgr)
|
2008-10-07 11:29:03 -04:00
|
|
|
return FALSE;
|
|
|
|
|
2008-10-13 07:23:47 -04:00
|
|
|
l = plugin_mgr->plugins;
|
2008-10-02 07:16:15 -04:00
|
|
|
|
2009-07-22 14:37:43 -04:00
|
|
|
/* We need to make sure that clutter gets certain events, like
|
|
|
|
* ConfigureNotify on the stage window. If there is a plugin that
|
|
|
|
* provides an xevent_filter function, then it's the responsibility
|
|
|
|
* of that plugin to pass events to Clutter. Otherwise, we send the
|
|
|
|
* event directly to Clutter ourselves.
|
|
|
|
*
|
|
|
|
* What happens if there are two plugins with xevent_filter functions
|
|
|
|
* is undefined; in general, multiple competing plugins are something
|
|
|
|
* we don't support well or care much about.
|
|
|
|
*
|
|
|
|
* FIXME: Really, we should just always handle sending the event to
|
|
|
|
* clutter if a plugin doesn't report the event as handled by
|
|
|
|
* returning TRUE, but it doesn't seem worth breaking compatibility
|
|
|
|
* of the plugin interface right now to achieve this; the way it is
|
|
|
|
* now works fine in practice.
|
|
|
|
*/
|
|
|
|
have_plugin_xevent_func = FALSE;
|
|
|
|
|
2008-10-02 07:16:15 -04:00
|
|
|
while (l)
|
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaPlugin *plugin = l->data;
|
|
|
|
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
2008-10-02 07:16:15 -04:00
|
|
|
|
2008-12-17 04:33:56 -05:00
|
|
|
if (klass->xevent_filter)
|
2008-10-02 07:16:15 -04:00
|
|
|
{
|
2009-07-22 14:37:43 -04:00
|
|
|
have_plugin_xevent_func = TRUE;
|
2008-12-17 04:33:56 -05:00
|
|
|
if (klass->xevent_filter (plugin, xev) == TRUE)
|
2008-10-02 07:16:15 -04:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
l = l->next;
|
|
|
|
}
|
|
|
|
|
2009-07-22 14:37:43 -04:00
|
|
|
if (!have_plugin_xevent_func)
|
|
|
|
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
|
|
|
|
|
2008-10-02 07:16:15 -04:00
|
|
|
return FALSE;
|
|
|
|
}
|