meta-plugin-manager: Only allow one plugin to be loaded

The "multiple plugins loaded at once" strategy was always a big fiction:
while it may be viable if you're super careful, it's fragile and requires
a bit of infrastructure that we would be better off without.

Note that for simplicity, we're keeping the MetaPluginManager, but it only
manages one plugin. A possible future cleanup would be to remove it entirely.

https://bugzilla.gnome.org/show_bug.cgi?id=676855
This commit is contained in:
Jasper St. Pierre 2012-04-05 01:29:39 -04:00
parent 574c0c3287
commit f9454e29db
7 changed files with 111 additions and 298 deletions

View File

@ -557,9 +557,7 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
clutter_actor_hide (info->hidden_group); clutter_actor_hide (info->hidden_group);
info->plugin_mgr = info->plugin_mgr = meta_plugin_manager_new (screen);
meta_plugin_manager_get (screen);
meta_plugin_manager_initialize (info->plugin_mgr);
/* /*
* Delay the creation of the overlay window as long as we can, to avoid * Delay the creation of the overlay window as long as we can, to avoid

View File

@ -35,34 +35,32 @@
#include <clutter/x11/clutter-x11.h> #include <clutter/x11/clutter-x11.h>
static GSList *plugin_types; static GType plugin_type = G_TYPE_NONE;
/*
* 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.)
*/
static MetaPluginManager *default_plugin_manager;
struct MetaPluginManager struct MetaPluginManager
{ {
MetaScreen *screen; MetaScreen *screen;
MetaPlugin *plugin;
GList /* MetaPlugin */ *plugins; /* TODO -- maybe use hash table */
}; };
void
meta_plugin_manager_set_plugin_type (GType gtype)
{
if (plugin_type != G_TYPE_NONE)
meta_fatal ("Mutter plugin already set: %s", g_type_name (plugin_type));
plugin_type = gtype;
}
/* /*
* Loads the given plugin. * Loads the given plugin.
*/ */
void void
meta_plugin_manager_load (MetaPluginManager *plugin_mgr, meta_plugin_manager_load (const gchar *plugin_name)
const gchar *plugin_name)
{ {
const gchar *dpath = MUTTER_PLUGIN_DIR "/"; const gchar *dpath = MUTTER_PLUGIN_DIR "/";
gchar *path; gchar *path;
MetaModule *module; MetaModule *module;
GType plugin_type;
if (g_path_is_absolute (plugin_name)) if (g_path_is_absolute (plugin_name))
path = g_strdup (plugin_name); path = g_strdup (plugin_name);
@ -81,159 +79,52 @@ meta_plugin_manager_load (MetaPluginManager *plugin_mgr,
exit (1); exit (1);
} }
plugin_type = meta_module_get_plugin_type (module); meta_plugin_manager_set_plugin_type (meta_module_get_plugin_type (module));
meta_plugin_manager_register (plugin_mgr, plugin_type);
g_type_module_unuse (G_TYPE_MODULE (module)); g_type_module_unuse (G_TYPE_MODULE (module));
g_free (path); g_free (path);
} }
/* MetaPluginManager *
* Registers the given plugin type
*/
void
meta_plugin_manager_register (MetaPluginManager *plugin_mgr,
GType plugin_type)
{
MetaPlugin *plugin;
plugin_types = g_slist_prepend (plugin_types, GSIZE_TO_POINTER (plugin_type));
plugin = g_object_new (plugin_type, NULL);
plugin_mgr->plugins = g_list_prepend (plugin_mgr->plugins, plugin);
}
void
meta_plugin_manager_initialize (MetaPluginManager *plugin_mgr)
{
GList *iter;
if (!plugin_mgr->plugins)
{
/*
* If no plugins are specified, load the default plugin.
*/
meta_plugin_manager_load (plugin_mgr, "default");
}
for (iter = plugin_mgr->plugins; iter; iter = iter->next)
{
MetaPlugin *plugin = (MetaPlugin*) iter->data;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
g_object_set (plugin,
"screen", plugin_mgr->screen,
NULL);
if (klass->start)
klass->start (plugin);
}
}
static MetaPluginManager *
meta_plugin_manager_new (MetaScreen *screen) meta_plugin_manager_new (MetaScreen *screen)
{ {
MetaPluginManager *plugin_mgr; MetaPluginManager *plugin_mgr;
MetaPlugin *plugin;
plugin_mgr = g_new0 (MetaPluginManager, 1); plugin_mgr = g_new0 (MetaPluginManager, 1);
plugin_mgr->screen = screen; plugin_mgr->screen = screen;
plugin_mgr->plugin = plugin = g_object_new (plugin_type, "screen", screen, NULL);
if (screen) META_PLUGIN_GET_CLASS (plugin)->start (plugin);
g_object_set_data (G_OBJECT (screen), "meta-plugin-manager", plugin_mgr);
return plugin_mgr; return plugin_mgr;
} }
MetaPluginManager *
meta_plugin_manager_get_default (void)
{
if (!default_plugin_manager)
{
default_plugin_manager = meta_plugin_manager_new (NULL);
}
return default_plugin_manager;
}
MetaPluginManager *
meta_plugin_manager_get (MetaScreen *screen)
{
MetaPluginManager *plugin_mgr;
plugin_mgr = g_object_get_data (G_OBJECT (screen), "meta-plugin-manager");
if (plugin_mgr)
return plugin_mgr;
if (!default_plugin_manager)
meta_plugin_manager_get_default ();
if (!default_plugin_manager->screen)
{
/* The default plugin manager is so far unused, we can recycle it */
default_plugin_manager->screen = screen;
g_object_set_data (G_OBJECT (screen), "meta-plugin-manager", default_plugin_manager);
return default_plugin_manager;
}
else
{
GSList *iter;
GType plugin_type;
MetaPlugin *plugin;
plugin_mgr = meta_plugin_manager_new (screen);
for (iter = plugin_types; iter; iter = iter->next)
{
plugin_type = (GType)GPOINTER_TO_SIZE (iter->data);
plugin = g_object_new (plugin_type, "screen", screen, NULL);
plugin_mgr->plugins = g_list_prepend (plugin_mgr->plugins, plugin);
}
return plugin_mgr;
}
}
static void static void
meta_plugin_manager_kill_window_effects (MetaPluginManager *plugin_mgr, meta_plugin_manager_kill_window_effects (MetaPluginManager *plugin_mgr,
MetaWindowActor *actor) MetaWindowActor *actor)
{ {
GList *l = plugin_mgr->plugins; MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
while (l) if (klass->kill_window_effects)
{ klass->kill_window_effects (plugin, actor);
MetaPlugin *plugin = l->data;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if (klass->kill_window_effects)
klass->kill_window_effects (plugin, actor);
l = l->next;
}
} }
static void static void
meta_plugin_manager_kill_switch_workspace (MetaPluginManager *plugin_mgr) meta_plugin_manager_kill_switch_workspace (MetaPluginManager *plugin_mgr)
{ {
GList *l = plugin_mgr->plugins; MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
while (l) if (klass->kill_switch_workspace)
{ klass->kill_switch_workspace (plugin);
MetaPlugin *plugin = l->data;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if (klass->kill_switch_workspace)
klass->kill_switch_workspace (plugin);
l = l->next;
}
} }
/* /*
* Public method that the compositor hooks into for events that require * Public method that the compositor hooks into for events that require
* no additional parameters. * no additional parameters.
* *
* Returns TRUE if at least one of the plugins handled the event type (i.e., * Returns TRUE if the plugin handled the event type (i.e.,
* if the return value is FALSE, there will be no subsequent call to the * if the return value is FALSE, there will be no subsequent call to the
* manager completed() callback, and the compositor must ensure that any * manager completed() callback, and the compositor must ensure that any
* appropriate post-effect cleanup is carried out. * appropriate post-effect cleanup is carried out.
@ -243,55 +134,48 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
MetaWindowActor *actor, MetaWindowActor *actor,
unsigned long event) unsigned long event)
{ {
GList *l = plugin_mgr->plugins; MetaPlugin *plugin = plugin_mgr->plugin;
gboolean retval = FALSE; MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen); MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
gboolean retval = FALSE;
if (display->display_opening) if (display->display_opening)
return FALSE; return FALSE;
while (l) switch (event)
{ {
MetaPlugin *plugin = l->data; case META_PLUGIN_MINIMIZE:
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); if (klass->minimize)
switch (event)
{ {
case META_PLUGIN_MINIMIZE: retval = TRUE;
if (klass->minimize) meta_plugin_manager_kill_window_effects (plugin_mgr,
{ actor);
retval = TRUE;
meta_plugin_manager_kill_window_effects (plugin_mgr,
actor);
_meta_plugin_effect_started (plugin); _meta_plugin_effect_started (plugin);
klass->minimize (plugin, actor); klass->minimize (plugin, actor);
}
break;
case META_PLUGIN_MAP:
if (klass->map)
{
retval = TRUE;
meta_plugin_manager_kill_window_effects (plugin_mgr,
actor);
_meta_plugin_effect_started (plugin);
klass->map (plugin, actor);
}
break;
case META_PLUGIN_DESTROY:
if (klass->destroy)
{
retval = TRUE;
_meta_plugin_effect_started (plugin);
klass->destroy (plugin, actor);
}
break;
default:
g_warning ("Incorrect handler called for event %lu", event);
} }
break;
case META_PLUGIN_MAP:
if (klass->map)
{
retval = TRUE;
meta_plugin_manager_kill_window_effects (plugin_mgr,
actor);
l = l->next; _meta_plugin_effect_started (plugin);
klass->map (plugin, actor);
}
break;
case META_PLUGIN_DESTROY:
if (klass->destroy)
{
retval = TRUE;
_meta_plugin_effect_started (plugin);
klass->destroy (plugin, actor);
}
break;
default:
g_warning ("Incorrect handler called for event %lu", event);
} }
return retval; return retval;
@ -301,7 +185,7 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
* The public method that the compositor hooks into for maximize and unmaximize * The public method that the compositor hooks into for maximize and unmaximize
* events. * events.
* *
* Returns TRUE if at least one of the plugins handled the event type (i.e., * Returns TRUE if the plugin handled the event type (i.e.,
* if the return value is FALSE, there will be no subsequent call to the * if the return value is FALSE, there will be no subsequent call to the
* manager completed() callback, and the compositor must ensure that any * manager completed() callback, and the compositor must ensure that any
* appropriate post-effect cleanup is carried out. * appropriate post-effect cleanup is carried out.
@ -315,51 +199,44 @@ meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
gint target_width, gint target_width,
gint target_height) gint target_height)
{ {
GList *l = plugin_mgr->plugins; MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
gboolean retval = FALSE; gboolean retval = FALSE;
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
if (display->display_opening) if (display->display_opening)
return FALSE; return FALSE;
while (l) switch (event)
{ {
MetaPlugin *plugin = l->data; case META_PLUGIN_MAXIMIZE:
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); if (klass->maximize)
switch (event)
{ {
case META_PLUGIN_MAXIMIZE: retval = TRUE;
if (klass->maximize) meta_plugin_manager_kill_window_effects (plugin_mgr,
{ actor);
retval = TRUE;
meta_plugin_manager_kill_window_effects (plugin_mgr,
actor);
_meta_plugin_effect_started (plugin); _meta_plugin_effect_started (plugin);
klass->maximize (plugin, actor, klass->maximize (plugin, actor,
target_x, target_y, target_x, target_y,
target_width, target_height); target_width, target_height);
}
break;
case META_PLUGIN_UNMAXIMIZE:
if (klass->unmaximize)
{
retval = TRUE;
meta_plugin_manager_kill_window_effects (plugin_mgr,
actor);
_meta_plugin_effect_started (plugin);
klass->unmaximize (plugin, actor,
target_x, target_y,
target_width, target_height);
}
break;
default:
g_warning ("Incorrect handler called for event %lu", event);
} }
break;
case META_PLUGIN_UNMAXIMIZE:
if (klass->unmaximize)
{
retval = TRUE;
meta_plugin_manager_kill_window_effects (plugin_mgr,
actor);
l = l->next; _meta_plugin_effect_started (plugin);
klass->unmaximize (plugin, actor,
target_x, target_y,
target_width, target_height);
}
break;
default:
g_warning ("Incorrect handler called for event %lu", event);
} }
return retval; return retval;
@ -368,7 +245,7 @@ meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
/* /*
* The public method that the compositor hooks into for desktop switching. * 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., * Returns TRUE if the plugin handled the event type (i.e.,
* if the return value is FALSE, there will be no subsequent call to the * if the return value is FALSE, there will be no subsequent call to the
* manager completed() callback, and the compositor must ensure that any * manager completed() callback, and the compositor must ensure that any
* appropriate post-effect cleanup is carried out. * appropriate post-effect cleanup is carried out.
@ -379,28 +256,21 @@ meta_plugin_manager_switch_workspace (MetaPluginManager *plugin_mgr,
gint to, gint to,
MetaMotionDirection direction) MetaMotionDirection direction)
{ {
GList *l = plugin_mgr->plugins; MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
gboolean retval = FALSE; gboolean retval = FALSE;
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
if (display->display_opening) if (display->display_opening)
return FALSE; return FALSE;
while (l) if (klass->switch_workspace)
{ {
MetaPlugin *plugin = l->data; retval = TRUE;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); meta_plugin_manager_kill_switch_workspace (plugin_mgr);
if (klass->switch_workspace) _meta_plugin_effect_started (plugin);
{ klass->switch_workspace (plugin, from, to, direction);
retval = TRUE;
meta_plugin_manager_kill_switch_workspace (plugin_mgr);
_meta_plugin_effect_started (plugin);
klass->switch_workspace (plugin, from, to, direction);
}
l = l->next;
} }
return retval; return retval;
@ -409,7 +279,7 @@ meta_plugin_manager_switch_workspace (MetaPluginManager *plugin_mgr,
/* /*
* The public method that the compositor hooks into for desktop switching. * 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., * Returns TRUE if the plugin handled the event type (i.e.,
* if the return value is FALSE, there will be no subsequent call to the * if the return value is FALSE, there will be no subsequent call to the
* manager completed() callback, and the compositor must ensure that any * manager completed() callback, and the compositor must ensure that any
* appropriate post-effect cleanup is carried out. * appropriate post-effect cleanup is carried out.
@ -418,49 +288,20 @@ gboolean
meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr, meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr,
XEvent *xev) XEvent *xev)
{ {
GList *l; MetaPlugin *plugin = plugin_mgr->plugin;
gboolean have_plugin_xevent_func; MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if (!plugin_mgr) if (!plugin_mgr)
return FALSE; return FALSE;
l = plugin_mgr->plugins;
/* We need to make sure that clutter gets certain events, like /* We need to make sure that clutter gets certain events, like
* ConfigureNotify on the stage window. If there is a plugin that * ConfigureNotify on the stage window. If there is a plugin that
* provides an xevent_filter function, then it's the responsibility * provides an xevent_filter function, then it's the responsibility
* of that plugin to pass events to Clutter. Otherwise, we send the * of that plugin to pass events to Clutter. Otherwise, we send the
* event directly to Clutter ourselves. * 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; if (klass->xevent_filter && klass->xevent_filter (plugin, xev))
return TRUE;
while (l) else
{
MetaPlugin *plugin = l->data;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if (klass->xevent_filter)
{
have_plugin_xevent_func = TRUE;
if (klass->xevent_filter (plugin, xev) == TRUE)
return TRUE;
}
l = l->next;
}
if (!have_plugin_xevent_func)
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE; return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
return FALSE;
} }

View File

@ -46,14 +46,9 @@
*/ */
typedef struct MetaPluginManager MetaPluginManager; typedef struct MetaPluginManager MetaPluginManager;
MetaPluginManager * meta_plugin_manager_get (MetaScreen *screen); MetaPluginManager * meta_plugin_manager_new (MetaScreen *screen);
MetaPluginManager * meta_plugin_manager_get_default (void);
void meta_plugin_manager_load (MetaPluginManager *mgr, void meta_plugin_manager_load (const gchar *plugin_name);
const gchar *plugin_name);
void meta_plugin_manager_register (MetaPluginManager *mgr,
GType plugin_type);
void meta_plugin_manager_initialize (MetaPluginManager *mgr);
gboolean meta_plugin_manager_event_simple (MetaPluginManager *mgr, gboolean meta_plugin_manager_event_simple (MetaPluginManager *mgr,
MetaWindowActor *actor, MetaWindowActor *actor,

View File

@ -52,7 +52,6 @@ struct _MetaPluginPrivate
MetaScreen *screen; MetaScreen *screen;
gint running; gint running;
gboolean debug : 1; gboolean debug : 1;
}; };
@ -332,19 +331,3 @@ meta_plugin_get_screen (MetaPlugin *plugin)
return priv->screen; return priv->screen;
} }
/**
* meta_plugin_type_register:
* @plugin_type: a #MetaPlugin type
*
* Register @plugin_type as a compositor plugin type to be used.
* You must call this before calling meta_init().
*/
void
meta_plugin_type_register (GType plugin_type)
{
MetaPluginManager *plugin_manager;
plugin_manager = meta_plugin_manager_get_default ();
meta_plugin_manager_register (plugin_manager, plugin_type);
}

View File

@ -373,7 +373,7 @@ on_sigterm (void)
* meta_init: (skip) * meta_init: (skip)
* *
* Initialize mutter. Call this after meta_get_option_context() and * Initialize mutter. Call this after meta_get_option_context() and
* meta_plugin_type_register(), and before meta_run(). * meta_plugin_manager_set_plugin_type(), and before meta_run().
*/ */
void void
meta_init (void) meta_init (void)

View File

@ -80,11 +80,7 @@ main (int argc, char **argv)
} }
if (plugin) if (plugin)
{ meta_plugin_manager_load (plugin);
MetaPluginManager *mgr;
mgr = meta_plugin_manager_get_default ();
meta_plugin_manager_load (mgr, plugin);
}
meta_init (); meta_init ();
return meta_run (); return meta_run ();

View File

@ -218,9 +218,6 @@ struct _MetaPluginVersion
return object_name##_register_type (type_module); \ return object_name##_register_type (type_module); \
} \ } \
void
meta_plugin_type_register (GType plugin_type);
void void
meta_plugin_switch_workspace_completed (MetaPlugin *plugin); meta_plugin_switch_workspace_completed (MetaPlugin *plugin);
@ -274,4 +271,7 @@ MetaScreen *meta_plugin_get_screen (MetaPlugin *plugin);
void void
_meta_plugin_effect_started (MetaPlugin *plugin); _meta_plugin_effect_started (MetaPlugin *plugin);
/* XXX: Putting this in here so it's in the public header. */
void meta_plugin_manager_set_plugin_type (GType gtype);
#endif /* META_PLUGIN_H_ */ #endif /* META_PLUGIN_H_ */