GObjectified MutterPlugin.

This commit is contained in:
Tomas Frydrych 2008-12-17 09:33:56 +00:00
parent 57a2d20d61
commit c61eb77a70
10 changed files with 1474 additions and 850 deletions

View File

@ -9,7 +9,7 @@ m4_define([metacity_micro_version], [2])
m4_define([metacity_version], m4_define([metacity_version],
[metacity_major_version.metacity_minor_version.metacity_micro_version]) [metacity_major_version.metacity_minor_version.metacity_micro_version])
m4_define([metacity_clutter_plugin_api_version], [1]) m4_define([metacity_clutter_plugin_api_version], [2])
AC_INIT([metacity], [metacity_version], AC_INIT([metacity], [metacity_version],
[http://bugzilla.gnome.org/enter_bug.cgi?product=metacity]) [http://bugzilla.gnome.org/enter_bug.cgi?product=metacity])

View File

@ -112,6 +112,9 @@ metacity_SOURCES += \
compositor/mutter/mutter-plugin-manager.h \ compositor/mutter/mutter-plugin-manager.h \
compositor/mutter/tidy/tidy-texture-frame.c \ compositor/mutter/tidy/tidy-texture-frame.c \
compositor/mutter/tidy/tidy-texture-frame.h \ compositor/mutter/tidy/tidy-texture-frame.h \
compositor/mutter/mutter-module.c \
compositor/mutter/mutter-module.h \
compositor/mutter/mutter-plugin.c \
include/mutter-plugin.h include/mutter-plugin.h
endif endif

View File

@ -348,6 +348,11 @@ mutter_window_constructed (GObject *object)
} }
priv->actor = mutter_shaped_texture_new (); priv->actor = mutter_shaped_texture_new ();
if (!clutter_glx_texture_pixmap_using_extension (
CLUTTER_GLX_TEXTURE_PIXMAP (priv->actor)))
g_warning ("NOTE: Not using GLX TFP!\n");
clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->actor); clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->actor);
update_shape ((Mutter *) update_shape ((Mutter *)
@ -2291,6 +2296,10 @@ clutter_cmp_update_workspace_geometry (MetaCompositor *compositor,
MetaWorkspace *workspace) MetaWorkspace *workspace)
{ {
#ifdef HAVE_COMPOSITE_EXTENSIONS #ifdef HAVE_COMPOSITE_EXTENSIONS
#if 0
/* FIXME -- should do away with this function in favour of MetaWorkspace
* signal.
*/
MetaScreen *screen = meta_workspace_get_screen (workspace); MetaScreen *screen = meta_workspace_get_screen (workspace);
MetaCompScreen *info; MetaCompScreen *info;
MutterPluginManager *mgr; MutterPluginManager *mgr;
@ -2303,6 +2312,7 @@ clutter_cmp_update_workspace_geometry (MetaCompositor *compositor,
mutter_plugin_manager_update_workspace (mgr, workspace); mutter_plugin_manager_update_workspace (mgr, workspace);
#endif #endif
#endif
} }
static void static void

View File

@ -0,0 +1,206 @@
/* -*- 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.
*/
#include "mutter-plugin.h"
#include "mutter-module.h"
#include <gmodule.h>
enum
{
PROP_0,
PROP_PATH,
};
struct _MutterModulePrivate
{
GModule *lib;
gchar *path;
GType plugin_type;
};
#define MUTTER_MODULE_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_MODULE, MutterModulePrivate))
G_DEFINE_TYPE (MutterModule, mutter_module, G_TYPE_TYPE_MODULE);
static gboolean
mutter_module_load (GTypeModule *gmodule)
{
MutterModulePrivate *priv = MUTTER_MODULE (gmodule)->priv;
MutterPluginVersion *info = NULL;
GType (*register_type) (GTypeModule *) = NULL;
if (priv->lib && priv->plugin_type)
return TRUE;
g_assert (priv->path);
if (!priv->lib &&
!(priv->lib = g_module_open (priv->path, G_MODULE_BIND_LOCAL)))
{
g_warning ("Could not load library [%s]", priv->path);
return FALSE;
}
if (g_module_symbol (priv->lib, "mutter_plugin_version", (gpointer *)&info) &&
g_module_symbol (priv->lib, "mutter_plugin_register_type",
(gpointer *)&register_type) &&
info && register_type)
{
if (info->version_api != METACITY_CLUTTER_PLUGIN_API_VERSION)
g_warning ("Plugin API mismatch for [%s]", priv->path);
else
{
GType plugin_type;
if (!(plugin_type = register_type (gmodule)))
{
g_warning ("Could not register type for plugin %s",
priv->path);
return FALSE;
}
else
{
priv->plugin_type = plugin_type;
}
return TRUE;
}
}
else
g_warning ("Broken plugin module [%s]", priv->path);
return FALSE;
}
static void
mutter_module_unload (GTypeModule *gmodule)
{
MutterModulePrivate *priv = MUTTER_MODULE (gmodule)->priv;
g_module_close (priv->lib);
priv->lib = NULL;
priv->plugin_type = 0;
}
static void
mutter_module_dispose (GObject *object)
{
G_OBJECT_CLASS (mutter_module_parent_class)->dispose (object);
}
static void
mutter_module_finalize (GObject *object)
{
MutterModulePrivate *priv = MUTTER_MODULE (object)->priv;
g_free (priv->path);
priv->path = NULL;
G_OBJECT_CLASS (mutter_module_parent_class)->finalize (object);
}
static void
mutter_module_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MutterModulePrivate *priv = MUTTER_MODULE (object)->priv;
switch (prop_id)
{
case PROP_PATH:
g_free (priv->path);
priv->path = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
mutter_module_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MutterModulePrivate *priv = MUTTER_MODULE (object)->priv;
switch (prop_id)
{
case PROP_PATH:
g_value_set_string (value, priv->path);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
mutter_module_class_init (MutterModuleClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GTypeModuleClass *gmodule_class = G_TYPE_MODULE_CLASS (klass);
gobject_class->finalize = mutter_module_finalize;
gobject_class->dispose = mutter_module_dispose;
gobject_class->set_property = mutter_module_set_property;
gobject_class->get_property = mutter_module_get_property;
gmodule_class->load = mutter_module_load;
gmodule_class->unload = mutter_module_unload;
g_object_class_install_property (gobject_class,
PROP_PATH,
g_param_spec_string ("path",
"Path",
"Load path",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_type_class_add_private (gobject_class, sizeof (MutterModulePrivate));
}
static void
mutter_module_init (MutterModule *self)
{
MutterModulePrivate *priv;
self->priv = priv = MUTTER_MODULE_GET_PRIVATE (self);
}
GType
mutter_module_get_plugin_type (MutterModule *module)
{
MutterModulePrivate *priv = MUTTER_MODULE (module)->priv;
return priv->plugin_type;
}

View File

@ -0,0 +1,57 @@
/* -*- 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.
*/
#ifndef MUTTER_MODULE_H_
#define MUTTER_MODULE_H_
#include <glib-object.h>
#define MUTTER_TYPE_MODULE (mutter_module_get_type ())
#define MUTTER_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_MODULE, MutterModule))
#define MUTTER_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_MODULE, MutterModuleClass))
#define MUTTER_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_MODULE_TYPE))
#define MUTTER_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_MODULE))
#define MUTTER_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_MODULE, MutterModuleClass))
typedef struct _MutterModule MutterModule;
typedef struct _MutterModuleClass MutterModuleClass;
typedef struct _MutterModulePrivate MutterModulePrivate;
struct _MutterModule
{
GTypeModule parent;
MutterModulePrivate *priv;
};
struct _MutterModuleClass
{
GTypeModuleClass parent_class;
};
GType mutter_module_get_type (void);
GType mutter_module_get_plugin_type (MutterModule *module);
#endif

View File

@ -26,215 +26,52 @@
#include "prefs.h" #include "prefs.h"
#include "errors.h" #include "errors.h"
#include "workspace.h" #include "workspace.h"
#include "mutter-module.h"
#include <gmodule.h>
#include <string.h> #include <string.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/shape.h>
#include <clutter/x11/clutter-x11.h>
static gboolean mutter_plugin_manager_reload ( /*
MutterPluginManager *plugin_mgr); * There is only one instace of each module per the process.
*/
static GHashTable *plugin_modules = NULL;
static gboolean mutter_plugin_manager_reload (MutterPluginManager *plugin_mgr);
struct MutterPluginManager struct MutterPluginManager
{ {
MetaScreen *screen; MetaScreen *screen;
GList *plugins; /* TODO -- maybe use hash table */ GList *plugins;
GList *unload; /* Plugins that are disabled and pending unload */ GList *unload; /* Plugins that are disabled and pending unload */
guint idle_unload_id; guint idle_unload_id;
}; };
typedef struct MutterPluginPrivate
{
char *name;
MutterPluginManager *self;
GModule *module;
gulong features;
/* We use this to track the number of effects currently being managed
* by a plugin. Currently this is used to block unloading while effects
* are in progress. */
gint running;
gboolean disabled : 1;
} MutterPluginPrivate;
static void
free_plugin_workspaces (MutterPlugin *plugin)
{
GList *l;
l = plugin->work_areas;
while (l)
{
g_free (l->data);
l = l->next;
}
if (plugin->work_areas)
g_list_free (plugin->work_areas);
plugin->work_areas = NULL;
}
/*
* Gets work area geometry and stores it in list in the plugin.
*
* If the plugin list is already populated, we simply replace it (we are
* dealing with a small number of items in the list and unfrequent changes).
*/
static void
update_plugin_workspaces (MetaScreen *screen,
MutterPlugin *plugin)
{
GList *l, *l2 = NULL;
l = meta_screen_get_workspaces (screen);
while (l)
{
MetaWorkspace *w = l->data;
MetaRectangle *r;
r = g_new0 (MetaRectangle, 1);
meta_workspace_get_work_area_all_xineramas (w, (MetaRectangle*)r);
l2 = g_list_append (l2, r);
l = l->next;
}
free_plugin_workspaces (plugin);
plugin->work_areas = l2;
}
/**
* parse_disable_params:
* @params: as read from gconf, a ':' seperated list of plugin options
* @features: The mask of features the plugin advertises
*
* This function returns a new mask of features removing anything that
* the user has disabled.
*/
static gulong
parse_disable_params (const char *params, MutterPlugin *plugin)
{
char *p;
gulong features = 0;
/*
* Feature flags: identify events that the plugin can handle; a plugin can
* handle one or more events.
*/
if (plugin->minimize)
features |= MUTTER_PLUGIN_MINIMIZE;
if (plugin->maximize)
features |= MUTTER_PLUGIN_MAXIMIZE;
if (plugin->unmaximize)
features |= MUTTER_PLUGIN_UNMAXIMIZE;
if (plugin->map)
features |= MUTTER_PLUGIN_MAP;
if (plugin->destroy)
features |= MUTTER_PLUGIN_DESTROY;
if (plugin->switch_workspace)
features |= MUTTER_PLUGIN_SWITCH_WORKSPACE;
if (!params)
return features;
if ((p = strstr (params, "disable:")))
{
gchar *d = g_strdup (p+8);
p = strchr (d, ';');
if (p)
*p = 0;
if (strstr (d, "minimize"))
features &= ~ MUTTER_PLUGIN_MINIMIZE;
if (strstr (d, "maximize"))
features &= ~ MUTTER_PLUGIN_MAXIMIZE;
if (strstr (d, "unmaximize"))
features &= ~ MUTTER_PLUGIN_UNMAXIMIZE;
if (strstr (d, "map"))
features &= ~ MUTTER_PLUGIN_MAP;
if (strstr (d, "destroy"))
features &= ~ MUTTER_PLUGIN_DESTROY;
if (strstr (d, "switch-workspace"))
features &= ~MUTTER_PLUGIN_SWITCH_WORKSPACE;
g_free (d);
}
return features;
}
/* /*
* Checks that the plugin is compatible with the WM and sets up the plugin * Checks that the plugin is compatible with the WM and sets up the plugin
* struct. * struct.
*/ */
static MutterPlugin * static MutterPlugin *
mutter_plugin_load (MutterPluginManager *plugin_mgr, mutter_plugin_load (MutterPluginManager *mgr,
GModule *module, MutterModule *module,
const gchar *params) const gchar *params)
{ {
MutterPlugin *plugin; MutterPlugin *plugin = NULL;
GType plugin_type = mutter_module_get_plugin_type (module);
if (g_module_symbol (module, "mutter_plugin", (gpointer *)&plugin)) if (!plugin_type)
{ {
if (plugin->version_api == METACITY_CLUTTER_PLUGIN_API_VERSION) g_warning ("Plugin type not registered !!!");
{ return NULL;
MutterPluginPrivate *priv;
priv = g_new0 (MutterPluginPrivate, 1);
priv->name = _(plugin->name);
priv->module = module;
priv->self = plugin_mgr;
/* FIXME: instead of hanging private data of the plugin descriptor
* we could make the descriptor const if we were to hang it off
* a plugin manager structure */
plugin->manager_private = priv;
update_plugin_workspaces (plugin_mgr->screen, plugin);
priv->features = parse_disable_params (params, plugin);
/*
* Check for and run the plugin init function.
*/
if (!plugin->do_init || !(plugin->do_init (params)))
{
g_free (priv);
free_plugin_workspaces (plugin);
return NULL;
}
meta_verbose ("Loaded plugin [%s]\n", priv->name);
return plugin;
}
} }
return NULL; plugin = g_object_new (plugin_type,
"screen", mgr->screen,
"params", params,
NULL);
return plugin;
} }
/* /*
@ -245,22 +82,13 @@ mutter_plugin_load (MutterPluginManager *plugin_mgr,
static gboolean static gboolean
mutter_plugin_unload (MutterPlugin *plugin) mutter_plugin_unload (MutterPlugin *plugin)
{ {
MutterPluginPrivate *priv; if (mutter_plugin_running (plugin))
GModule *module;
priv = plugin->manager_private;
module = priv->module;
if (priv->running)
{ {
priv->disabled = TRUE; g_object_set (plugin, "disabled", TRUE, NULL);
return FALSE; return FALSE;
} }
g_free (priv); g_object_unref (plugin);
plugin->manager_private = NULL;
g_module_close (module);
return TRUE; return TRUE;
} }
@ -353,10 +181,20 @@ prefs_changed_callback (MetaPreference pref,
{ {
mutter_plugin_manager_reload (plugin_mgr); mutter_plugin_manager_reload (plugin_mgr);
} }
else if (pref == META_PREF_NUM_WORKSPACES) }
static MutterModule *
mutter_plugin_manager_get_module (const gchar *path)
{
MutterModule *module = g_hash_table_lookup (plugin_modules, path);
if (!module &&
(module = g_object_new (MUTTER_TYPE_MODULE, "path", path, NULL)))
{ {
mutter_plugin_manager_update_workspaces (plugin_mgr); g_hash_table_insert (plugin_modules, g_strdup (path), module);
} }
return module;
} }
/* /*
@ -388,8 +226,8 @@ mutter_plugin_manager_load (MutterPluginManager *plugin_mgr)
if (plugin_string) if (plugin_string)
{ {
GModule *plugin; MutterModule *module;
gchar *path; gchar *path;
params = strchr (plugin_string, ':'); params = strchr (plugin_string, ':');
@ -404,20 +242,35 @@ mutter_plugin_manager_load (MutterPluginManager *plugin_mgr)
else else
path = g_strconcat (dpath, plugin_string, ".so", NULL); path = g_strconcat (dpath, plugin_string, ".so", NULL);
if ((plugin = g_module_open (path, G_MODULE_BIND_LOCAL))) module = mutter_plugin_manager_get_module (path);
if (module)
{ {
MutterPlugin *p; MutterPlugin *p;
if ((p = mutter_plugin_load (plugin_mgr, plugin, params))) /*
plugin_mgr->plugins = g_list_prepend (plugin_mgr->plugins, p); * 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.
*/
g_type_module_use (G_TYPE_MODULE (module));
if ((p = mutter_plugin_load (plugin_mgr, module, params)))
{
plugin_mgr->plugins = g_list_prepend (plugin_mgr->plugins, p);
}
else else
{ {
g_message ("Plugin load for [%s] failed", path); g_warning ("Plugin load for [%s] failed", path);
g_module_close (plugin);
} }
g_type_module_unuse (G_TYPE_MODULE (module));
} }
else else
g_message ("Unable to load plugin [%s]: %s", path, g_module_error()); g_warning ("Unable to load plugin module [%s]: %s",
path, g_module_error());
g_free (path); g_free (path);
g_free (plugin_string); g_free (plugin_string);
@ -459,57 +312,17 @@ mutter_plugin_manager_init (MutterPluginManager *plugin_mgr)
return mutter_plugin_manager_load (plugin_mgr); return mutter_plugin_manager_load (plugin_mgr);
} }
void
mutter_plugin_manager_update_workspace (MutterPluginManager *plugin_mgr,
MetaWorkspace *workspace)
{
GList *l;
gint index;
index = meta_workspace_index (workspace);
l = plugin_mgr->plugins;
while (l)
{
MutterPlugin *plugin = l->data;
MetaRectangle *rect = g_list_nth_data (plugin->work_areas, index);
if (rect)
{
meta_workspace_get_work_area_all_xineramas (workspace, rect);
}
else
{
/* Something not entirely right; redo the whole thing */
update_plugin_workspaces (plugin_mgr->screen, plugin);
return;
}
l = l->next;
}
}
void
mutter_plugin_manager_update_workspaces (MutterPluginManager *plugin_mgr)
{
GList *l;
l = plugin_mgr->plugins;
while (l)
{
MutterPlugin *plugin = l->data;
update_plugin_workspaces (plugin_mgr->screen, plugin);
l = l->next;
}
}
MutterPluginManager * MutterPluginManager *
mutter_plugin_manager_new (MetaScreen *screen) mutter_plugin_manager_new (MetaScreen *screen)
{ {
MutterPluginManager *plugin_mgr; MutterPluginManager *plugin_mgr;
if (!plugin_modules)
{
plugin_modules = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
NULL);
}
plugin_mgr = g_new0 (MutterPluginManager, 1); plugin_mgr = g_new0 (MutterPluginManager, 1);
plugin_mgr->screen = screen; plugin_mgr->screen = screen;
@ -533,12 +346,12 @@ mutter_plugin_manager_kill_effect (MutterPluginManager *plugin_mgr,
while (l) while (l)
{ {
MutterPlugin *plugin = l->data; MutterPlugin *plugin = l->data;
MutterPluginPrivate *priv = plugin->manager_private; MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
if (!priv->disabled if (!mutter_plugin_disabled (plugin)
&& (priv->features & events) && (mutter_plugin_features (plugin) & events)
&& plugin->kill_effect) && klass->kill_effect)
plugin->kill_effect (actor, events); klass->kill_effect (plugin, actor, events);
l = l->next; l = l->next;
} }
@ -567,43 +380,41 @@ mutter_plugin_manager_event_simple (MutterPluginManager *plugin_mgr,
while (l) while (l)
{ {
MutterPlugin *plugin = l->data; MutterPlugin *plugin = l->data;
MutterPluginPrivate *priv = plugin->manager_private; MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
if (!priv->disabled && (priv->features & event)) if (!mutter_plugin_disabled (plugin) &&
(mutter_plugin_features (plugin) & event))
{ {
retval = TRUE; retval = TRUE;
switch (event) switch (event)
{ {
case MUTTER_PLUGIN_MINIMIZE: case MUTTER_PLUGIN_MINIMIZE:
if (plugin->minimize) if (klass->minimize)
{ {
mutter_plugin_manager_kill_effect ( mutter_plugin_manager_kill_effect (
plugin_mgr, plugin_mgr,
actor, actor,
ALL_BUT_SWITCH); ALL_BUT_SWITCH);
priv->running++; klass->minimize (plugin, actor);
plugin->minimize (actor);
} }
break; break;
case MUTTER_PLUGIN_MAP: case MUTTER_PLUGIN_MAP:
if (plugin->map) if (klass->map)
{ {
mutter_plugin_manager_kill_effect ( mutter_plugin_manager_kill_effect (
plugin_mgr, plugin_mgr,
actor, actor,
ALL_BUT_SWITCH); ALL_BUT_SWITCH);
priv->running++; klass->map (plugin, actor);
plugin->map (actor);
} }
break; break;
case MUTTER_PLUGIN_DESTROY: case MUTTER_PLUGIN_DESTROY:
if (plugin->destroy) if (klass->destroy)
{ {
priv->running++; klass->destroy (plugin, actor);
plugin->destroy (actor);
} }
break; break;
default: default:
@ -641,37 +452,38 @@ mutter_plugin_manager_event_maximize (MutterPluginManager *plugin_mgr,
while (l) while (l)
{ {
MutterPlugin *plugin = l->data; MutterPlugin *plugin = l->data;
MutterPluginPrivate *priv = plugin->manager_private; MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
if (!priv->disabled && (priv->features & event)) if (!mutter_plugin_disabled (plugin) &&
(mutter_plugin_features (plugin) & event))
{ {
retval = TRUE; retval = TRUE;
switch (event) switch (event)
{ {
case MUTTER_PLUGIN_MAXIMIZE: case MUTTER_PLUGIN_MAXIMIZE:
if (plugin->maximize) if (klass->maximize)
{ {
mutter_plugin_manager_kill_effect ( mutter_plugin_manager_kill_effect (
plugin_mgr, plugin_mgr,
actor, actor,
ALL_BUT_SWITCH); ALL_BUT_SWITCH);
plugin->maximize (actor, klass->maximize (plugin, actor,
target_x, target_y, target_x, target_y,
target_width, target_height); target_width, target_height);
} }
break; break;
case MUTTER_PLUGIN_UNMAXIMIZE: case MUTTER_PLUGIN_UNMAXIMIZE:
if (plugin->unmaximize) if (klass->unmaximize)
{ {
mutter_plugin_manager_kill_effect ( mutter_plugin_manager_kill_effect (
plugin_mgr, plugin_mgr,
actor, actor,
ALL_BUT_SWITCH); ALL_BUT_SWITCH);
plugin->unmaximize (actor, klass->unmaximize (plugin, actor,
target_x, target_y, target_x, target_y,
target_width, target_height); target_width, target_height);
} }
break; break;
default: default:
@ -706,13 +518,13 @@ mutter_plugin_manager_switch_workspace (MutterPluginManager *plugin_mgr,
while (l) while (l)
{ {
MutterPlugin *plugin = l->data; MutterPlugin *plugin = l->data;
MutterPluginPrivate *priv = plugin->manager_private; MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
if (!priv->disabled && if (!mutter_plugin_disabled (plugin) &&
(priv->features & MUTTER_PLUGIN_SWITCH_WORKSPACE) && (mutter_plugin_features (plugin) & MUTTER_PLUGIN_SWITCH_WORKSPACE) &&
(actors && *actors)) (actors && *actors))
{ {
if (plugin->switch_workspace) if (klass->switch_workspace)
{ {
retval = TRUE; retval = TRUE;
mutter_plugin_manager_kill_effect ( mutter_plugin_manager_kill_effect (
@ -720,7 +532,7 @@ mutter_plugin_manager_switch_workspace (MutterPluginManager *plugin_mgr,
MUTTER_WINDOW ((*actors)->data), MUTTER_WINDOW ((*actors)->data),
MUTTER_PLUGIN_SWITCH_WORKSPACE); MUTTER_PLUGIN_SWITCH_WORKSPACE);
plugin->switch_workspace (actors, from, to, direction); klass->switch_workspace (plugin, actors, from, to, direction);
} }
} }
@ -751,11 +563,12 @@ mutter_plugin_manager_xevent_filter (MutterPluginManager *plugin_mgr,
while (l) while (l)
{ {
MutterPlugin *plugin = l->data; MutterPlugin *plugin = l->data;
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
if (plugin->xevent_filter) if (klass->xevent_filter)
{ {
if (plugin->xevent_filter (xev) == TRUE) if (klass->xevent_filter (plugin, xev) == TRUE)
return TRUE; return TRUE;
} }
@ -765,176 +578,3 @@ mutter_plugin_manager_xevent_filter (MutterPluginManager *plugin_mgr,
return FALSE; return FALSE;
} }
/*
* Public accessors for plugins, exposed from mutter-plugin.h
*/
ClutterActor *
mutter_plugin_get_overlay_group (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = plugin->manager_private;
MutterPluginManager *plugin_mgr = priv->self;
return mutter_get_overlay_group_for_screen (plugin_mgr->screen);
}
ClutterActor *
mutter_plugin_get_stage (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = plugin->manager_private;
MutterPluginManager *plugin_mgr = priv->self;
return mutter_get_stage_for_screen (plugin_mgr->screen);
}
ClutterActor *
mutter_plugin_get_window_group (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = plugin->manager_private;
MutterPluginManager *plugin_mgr = priv->self;
return mutter_get_window_group_for_screen (plugin_mgr->screen);
}
void
mutter_plugin_effect_completed (MutterPlugin *plugin,
MutterWindow *actor,
unsigned long event)
{
MutterPluginPrivate *priv = plugin->manager_private;
priv->running--;
if (!actor)
{
g_warning ("Plugin [%s] passed NULL for actor!",
(plugin && plugin->name) ? plugin->name : "unknown");
}
mutter_window_effect_completed (actor, event);
}
void
mutter_plugin_query_screen_size (MutterPlugin *plugin,
int *width,
int *height)
{
MutterPluginPrivate *priv = plugin->manager_private;
MutterPluginManager *plugin_mgr = priv->self;
meta_screen_get_size (plugin_mgr->screen, width, height);
}
void
mutter_plugin_set_stage_reactive (MutterPlugin *plugin,
gboolean reactive)
{
MutterPluginPrivate *priv = plugin->manager_private;
MutterPluginManager *mgr = priv->self;
MetaDisplay *display = meta_screen_get_display (mgr->screen);
Display *xdpy = meta_display_get_xdisplay (display);
Window xstage, xoverlay;
ClutterActor *stage;
stage = mutter_get_stage_for_screen (mgr->screen);
xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
xoverlay = mutter_get_overlay_window (mgr->screen);
static XserverRegion region = None;
if (region == None)
region = XFixesCreateRegion (xdpy, NULL, 0);
if (reactive)
{
XFixesSetWindowShapeRegion (xdpy, xstage,
ShapeInput, 0, 0, None);
XFixesSetWindowShapeRegion (xdpy, xoverlay,
ShapeInput, 0, 0, None);
}
else
{
XFixesSetWindowShapeRegion (xdpy, xstage,
ShapeInput, 0, 0, region);
XFixesSetWindowShapeRegion (xdpy, xoverlay,
ShapeInput, 0, 0, region);
}
}
void
mutter_plugin_set_stage_input_area (MutterPlugin *plugin,
gint x, gint y, gint width, gint height)
{
MutterPluginPrivate *priv = plugin->manager_private;
MutterPluginManager *mgr = priv->self;
MetaDisplay *display = meta_screen_get_display (mgr->screen);
Display *xdpy = meta_display_get_xdisplay (display);
Window xstage, xoverlay;
ClutterActor *stage;
XRectangle rect;
XserverRegion region;
stage = mutter_get_stage_for_screen (mgr->screen);
xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
xoverlay = mutter_get_overlay_window (mgr->screen);
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
region = XFixesCreateRegion (xdpy, &rect, 1);
XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);
XFixesSetWindowShapeRegion (xdpy, xoverlay, ShapeInput, 0, 0, region);
XFixesDestroyRegion (xdpy, region);
}
void
mutter_plugin_set_stage_input_region (MutterPlugin *plugin,
XserverRegion region)
{
MutterPluginPrivate *priv = plugin->manager_private;
MutterPluginManager *mgr = priv->self;
MetaDisplay *display = meta_screen_get_display (mgr->screen);
Display *xdpy = meta_display_get_xdisplay (display);
Window xstage, xoverlay;
ClutterActor *stage;
stage = mutter_get_stage_for_screen (mgr->screen);
xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
xoverlay = mutter_get_overlay_window (mgr->screen);
XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);
XFixesSetWindowShapeRegion (xdpy, xoverlay, ShapeInput, 0, 0, region);
}
GList *
mutter_plugin_get_windows (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = plugin->manager_private;
MutterPluginManager *plugin_mgr = priv->self;
return mutter_get_windows (plugin_mgr->screen);
}
Display *
mutter_plugin_get_xdisplay (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = plugin->manager_private;
MutterPluginManager *mgr = priv->self;
MetaDisplay *display = meta_screen_get_display (mgr->screen);
Display *xdpy = meta_display_get_xdisplay (display);
return xdpy;
}
MetaScreen *
mutter_plugin_get_screen (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = plugin->manager_private;
MutterPluginManager *mgr = priv->self;
return mgr->screen;
}

View File

@ -0,0 +1,574 @@
/* -*- 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.
*/
#include "mutter-plugin.h"
#include "screen.h"
#include "display.h"
#include <string.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/shape.h>
#include <clutter/x11/clutter-x11.h>
G_DEFINE_ABSTRACT_TYPE (MutterPlugin, mutter_plugin, G_TYPE_OBJECT);
#define MUTTER_PLUGIN_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_PLUGIN, MutterPluginPrivate))
enum
{
PROP_0,
PROP_SCREEN,
PROP_PARAMS,
PROP_FEATURES,
PROP_DISABLED,
PROP_DEBUG_MODE,
};
struct _MutterPluginPrivate
{
MetaScreen *screen;
gchar *params;
gulong features;
gint running;
gboolean disabled : 1;
gboolean debug : 1;
};
static void
mutter_plugin_dispose (GObject *object)
{
G_OBJECT_CLASS (mutter_plugin_parent_class)->dispose (object);
}
static void
mutter_plugin_finalize (GObject *object)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
g_free (priv->params);
priv->params = NULL;
G_OBJECT_CLASS (mutter_plugin_parent_class)->finalize (object);
}
static void
mutter_plugin_parse_params (MutterPlugin *plugin)
{
char *p;
gulong features = 0;
MutterPluginPrivate *priv = plugin->priv;
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
/*
* Feature flags: identify events that the plugin can handle; a plugin can
* handle one or more events.
*/
if (klass->minimize)
features |= MUTTER_PLUGIN_MINIMIZE;
if (klass->maximize)
features |= MUTTER_PLUGIN_MAXIMIZE;
if (klass->unmaximize)
features |= MUTTER_PLUGIN_UNMAXIMIZE;
if (klass->map)
features |= MUTTER_PLUGIN_MAP;
if (klass->destroy)
features |= MUTTER_PLUGIN_DESTROY;
if (klass->switch_workspace)
features |= MUTTER_PLUGIN_SWITCH_WORKSPACE;
if (priv->params)
{
gboolean debug = FALSE;
if ((p = strstr (priv->params, "disable:")))
{
gchar *d = g_strdup (p+8);
p = strchr (d, ';');
if (p)
*p = 0;
if (strstr (d, "minimize"))
features &= ~ MUTTER_PLUGIN_MINIMIZE;
if (strstr (d, "maximize"))
features &= ~ MUTTER_PLUGIN_MAXIMIZE;
if (strstr (d, "unmaximize"))
features &= ~ MUTTER_PLUGIN_UNMAXIMIZE;
if (strstr (d, "map"))
features &= ~ MUTTER_PLUGIN_MAP;
if (strstr (d, "destroy"))
features &= ~ MUTTER_PLUGIN_DESTROY;
if (strstr (d, "switch-workspace"))
features &= ~MUTTER_PLUGIN_SWITCH_WORKSPACE;
g_free (d);
}
if (strstr (priv->params, "debug"))
debug = TRUE;
if (debug != priv->debug)
{
priv->debug = debug;
g_object_notify (G_OBJECT (plugin), "debug-mode");
}
}
if (features != priv->features)
{
priv->features = features;
g_object_notify (G_OBJECT (plugin), "features");
}
}
static void
mutter_plugin_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
switch (prop_id)
{
case PROP_SCREEN:
priv->screen = g_value_get_object (value);
break;
case PROP_PARAMS:
priv->params = g_value_dup_string (value);
mutter_plugin_parse_params (MUTTER_PLUGIN (object));
break;
case PROP_DISABLED:
priv->disabled = g_value_get_boolean (value);
break;
case PROP_DEBUG_MODE:
priv->debug = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
mutter_plugin_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
switch (prop_id)
{
case PROP_SCREEN:
g_value_set_object (value, priv->screen);
break;
case PROP_PARAMS:
g_value_set_string (value, priv->params);
break;
case PROP_DISABLED:
g_value_set_boolean (value, priv->disabled);
break;
case PROP_DEBUG_MODE:
g_value_set_boolean (value, priv->debug);
break;
case PROP_FEATURES:
g_value_set_ulong (value, priv->features);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
mutter_plugin_real_minimize (MutterPlugin *plugin, MutterWindow *actor)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
priv->running++;
}
static void
mutter_plugin_real_maximize (MutterPlugin *plugin,
MutterWindow *actor,
gint x,
gint y,
gint width,
gint height)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
priv->running++;
}
static void
mutter_plugin_real_unmaximize (MutterPlugin *plugin,
MutterWindow *actor,
gint x,
gint y,
gint width,
gint height)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
priv->running++;
}
static void
mutter_plugin_real_map (MutterPlugin *plugin, MutterWindow *actor)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
priv->running++;
}
static void
mutter_plugin_real_destroy (MutterPlugin *plugin, MutterWindow *actor)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
priv->running++;
}
static void
mutter_plugin_real_switch_workspace (MutterPlugin *plugin,
const GList **actors,
gint from,
gint to,
MetaMotionDirection direction)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
priv->running++;
}
static void
mutter_plugin_class_init (MutterPluginClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
MutterPluginClass *plugin_class = MUTTER_PLUGIN_CLASS (klass);
gobject_class->finalize = mutter_plugin_finalize;
gobject_class->dispose = mutter_plugin_dispose;
gobject_class->set_property = mutter_plugin_set_property;
gobject_class->get_property = mutter_plugin_get_property;
plugin_class->map = mutter_plugin_real_map;
plugin_class->minimize = mutter_plugin_real_minimize;
plugin_class->maximize = mutter_plugin_real_maximize;
plugin_class->unmaximize = mutter_plugin_real_unmaximize;
plugin_class->destroy = mutter_plugin_real_destroy;
plugin_class->switch_workspace = mutter_plugin_real_switch_workspace;
g_object_class_install_property (gobject_class,
PROP_SCREEN,
g_param_spec_object ("screen",
"MetaScreen",
"MetaScreen",
META_TYPE_SCREEN,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (gobject_class,
PROP_PARAMS,
g_param_spec_string ("params",
"Parameters",
"Plugin Parameters",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_object_class_install_property (gobject_class,
PROP_FEATURES,
g_param_spec_ulong ("features",
"Features",
"Plugin Features",
0 , G_MAXULONG, 0,
G_PARAM_READABLE));
g_object_class_install_property (gobject_class,
PROP_DISABLED,
g_param_spec_boolean ("disabled",
"Plugin disabled",
"Plugin disabled",
FALSE,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_DEBUG_MODE,
g_param_spec_boolean ("debug-mode",
"Debug Mode",
"Debug Mode",
FALSE,
G_PARAM_READABLE));
g_type_class_add_private (gobject_class, sizeof (MutterPluginPrivate));
}
static void
mutter_plugin_init (MutterPlugin *self)
{
MutterPluginPrivate *priv;
self->priv = priv = MUTTER_PLUGIN_GET_PRIVATE (self);
}
gulong
mutter_plugin_features (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return priv->features;
}
gboolean
mutter_plugin_disabled (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return priv->disabled;
}
gboolean
mutter_plugin_running (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return (priv->running > 0);
}
gboolean
mutter_plugin_debug_mode (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return priv->debug;
}
const MutterPluginInfo *
mutter_plugin_get_info (MutterPlugin *plugin)
{
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
if (klass && klass->plugin_info)
return klass->plugin_info (plugin);
return NULL;
}
ClutterActor *
mutter_plugin_get_overlay_group (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return mutter_get_overlay_group_for_screen (priv->screen);
}
ClutterActor *
mutter_plugin_get_stage (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return mutter_get_stage_for_screen (priv->screen);
}
ClutterActor *
mutter_plugin_get_window_group (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return mutter_get_window_group_for_screen (priv->screen);
}
void
mutter_plugin_effect_completed (MutterPlugin *plugin,
MutterWindow *actor,
unsigned long event)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
if (priv->running-- < 0)
{
g_warning ("Error in running effect accounting, adjusting.");
priv->running = 0;
}
if (!actor)
{
const MutterPluginInfo *info;
const gchar *name = NULL;
if (plugin && (info = mutter_plugin_get_info (plugin)))
name = info->name;
g_warning ("Plugin [%s] passed NULL for actor!",
name ? name : "unknown");
}
mutter_window_effect_completed (actor, event);
}
void
mutter_plugin_query_screen_size (MutterPlugin *plugin,
int *width,
int *height)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
meta_screen_get_size (priv->screen, width, height);
}
void
mutter_plugin_set_stage_reactive (MutterPlugin *plugin,
gboolean reactive)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaScreen *screen = priv->screen;
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
Window xstage, xoverlay;
ClutterActor *stage;
stage = mutter_get_stage_for_screen (screen);
xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
xoverlay = mutter_get_overlay_window (screen);
static XserverRegion region = None;
if (region == None)
region = XFixesCreateRegion (xdpy, NULL, 0);
if (reactive)
{
XFixesSetWindowShapeRegion (xdpy, xstage,
ShapeInput, 0, 0, None);
XFixesSetWindowShapeRegion (xdpy, xoverlay,
ShapeInput, 0, 0, None);
}
else
{
XFixesSetWindowShapeRegion (xdpy, xstage,
ShapeInput, 0, 0, region);
XFixesSetWindowShapeRegion (xdpy, xoverlay,
ShapeInput, 0, 0, region);
}
}
void
mutter_plugin_set_stage_input_area (MutterPlugin *plugin,
gint x, gint y, gint width, gint height)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaScreen *screen = priv->screen;
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
Window xstage, xoverlay;
ClutterActor *stage;
XRectangle rect;
XserverRegion region;
stage = mutter_get_stage_for_screen (screen);
xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
xoverlay = mutter_get_overlay_window (screen);
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
region = XFixesCreateRegion (xdpy, &rect, 1);
XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);
XFixesSetWindowShapeRegion (xdpy, xoverlay, ShapeInput, 0, 0, region);
XFixesDestroyRegion (xdpy, region);
}
void
mutter_plugin_set_stage_input_region (MutterPlugin *plugin,
XserverRegion region)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaScreen *screen = priv->screen;
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
Window xstage, xoverlay;
ClutterActor *stage;
stage = mutter_get_stage_for_screen (screen);
xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
xoverlay = mutter_get_overlay_window (screen);
XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);
XFixesSetWindowShapeRegion (xdpy, xoverlay, ShapeInput, 0, 0, region);
}
GList *
mutter_plugin_get_windows (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return mutter_get_windows (priv->screen);
}
Display *
mutter_plugin_get_xdisplay (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaDisplay *display = meta_screen_get_display (priv->screen);
Display *xdpy = meta_display_get_xdisplay (display);
return xdpy;
}
MetaScreen *
mutter_plugin_get_screen (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return priv->screen;
}

View File

@ -138,6 +138,15 @@ mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex)
if (priv->mask_texture != COGL_INVALID_HANDLE) if (priv->mask_texture != COGL_INVALID_HANDLE)
{ {
GLuint mask_gl_tex;
GLenum mask_gl_target;
cogl_texture_get_gl_texture (priv->mask_texture,
&mask_gl_tex, &mask_gl_target);
if (mask_gl_target == CGL_TEXTURE_RECTANGLE_ARB)
glDeleteTextures (1, &mask_gl_tex);
cogl_texture_unref (priv->mask_texture); cogl_texture_unref (priv->mask_texture);
priv->mask_texture = COGL_INVALID_HANDLE; priv->mask_texture = COGL_INVALID_HANDLE;
} }
@ -233,6 +242,7 @@ mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
CoglHandle paint_tex; CoglHandle paint_tex;
guint tex_width, tex_height; guint tex_width, tex_height;
GLuint mask_gl_tex; GLuint mask_gl_tex;
GLenum mask_target;
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex)); paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
@ -253,6 +263,7 @@ mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
{ {
guchar *mask_data; guchar *mask_data;
const XRectangle *rect; const XRectangle *rect;
GLenum paint_gl_target;
/* Create data for an empty image */ /* Create data for an empty image */
mask_data = g_malloc0 (tex_width * tex_height); mask_data = g_malloc0 (tex_width * tex_height);
@ -279,26 +290,53 @@ mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
memset (p, 255, x2 - x1); memset (p, 255, x2 - x1);
} }
priv->mask_texture = cogl_texture_new_from_data (tex_width, tex_height, cogl_texture_get_gl_texture (paint_tex, NULL, &paint_gl_target);
-1, FALSE,
COGL_PIXEL_FORMAT_A_8, if (paint_gl_target == CGL_TEXTURE_RECTANGLE_ARB)
COGL_PIXEL_FORMAT_ANY, {
tex_width, GLuint tex;
mask_data);
glGenTextures (1, &tex);
glBindTexture (CGL_TEXTURE_RECTANGLE_ARB, tex);
glPixelStorei (GL_UNPACK_ROW_LENGTH, tex_width);
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
glTexImage2D (CGL_TEXTURE_RECTANGLE_ARB, 0,
GL_ALPHA, tex_width, tex_height,
0, GL_ALPHA, GL_UNSIGNED_BYTE, mask_data);
priv->mask_texture
= cogl_texture_new_from_foreign (tex,
CGL_TEXTURE_RECTANGLE_ARB,
tex_width, tex_height,
0, 0,
COGL_PIXEL_FORMAT_A_8);
}
else
priv->mask_texture = cogl_texture_new_from_data (tex_width, tex_height,
-1, FALSE,
COGL_PIXEL_FORMAT_A_8,
COGL_PIXEL_FORMAT_ANY,
tex_width,
mask_data);
g_free (mask_data); g_free (mask_data);
priv->mask_width = tex_width; priv->mask_width = tex_width;
priv->mask_height = tex_height; priv->mask_height = tex_height;
cogl_texture_get_gl_texture (priv->mask_texture, &mask_gl_tex, NULL); cogl_texture_get_gl_texture (priv->mask_texture, &mask_gl_tex, &mask_target);
mutter_shaped_texture_get_gl_size (priv->mask_texture, mutter_shaped_texture_get_gl_size (priv->mask_texture,
&priv->mask_gl_width, &priv->mask_gl_width,
&priv->mask_gl_height); &priv->mask_gl_height);
if ((guint) priv->mask_gl_width == tex_width if (mask_target == GL_TEXTURE_RECTANGLE_ARB)
&& (guint) priv->mask_gl_height == tex_height) mutter_shaped_texture_set_coord_array (0.0f, 0.0f, tex_width, tex_height,
priv->mask_tex_coords);
else if ((guint) priv->mask_gl_width == tex_width
&& (guint) priv->mask_gl_height == tex_height)
mutter_shaped_texture_set_coord_array (0.0f, 0.0f, 1.0f, 1.0f, mutter_shaped_texture_set_coord_array (0.0f, 0.0f, 1.0f, 1.0f,
priv->mask_tex_coords); priv->mask_tex_coords);
else else
@ -322,6 +360,7 @@ mutter_shaped_texture_paint (ClutterActor *actor)
GLboolean vertex_array_was_enabled, tex_coord_array_was_enabled; GLboolean vertex_array_was_enabled, tex_coord_array_was_enabled;
GLboolean color_array_was_enabled; GLboolean color_array_was_enabled;
GLuint paint_gl_tex, mask_gl_tex; GLuint paint_gl_tex, mask_gl_tex;
GLenum paint_target, mask_target;
guint paint_gl_width, paint_gl_height; guint paint_gl_width, paint_gl_height;
GLfloat vertex_coords[8], paint_tex_coords[8]; GLfloat vertex_coords[8], paint_tex_coords[8];
ClutterActorBox alloc; ClutterActorBox alloc;
@ -358,18 +397,18 @@ mutter_shaped_texture_paint (ClutterActor *actor)
mutter_shaped_texture_ensure_mask (stex); mutter_shaped_texture_ensure_mask (stex);
cogl_texture_get_gl_texture (paint_tex, &paint_gl_tex, NULL); cogl_texture_get_gl_texture (paint_tex, &paint_gl_tex, &paint_target);
cogl_texture_get_gl_texture (priv->mask_texture, &mask_gl_tex, NULL); cogl_texture_get_gl_texture (priv->mask_texture, &mask_gl_tex, &mask_target);
/* We need to keep track of the some of the old state so that we /* We need to keep track of the some of the old state so that we
don't confuse Cogl */ don't confuse Cogl */
texture_was_enabled = glIsEnabled (GL_TEXTURE_2D); texture_was_enabled = glIsEnabled (paint_target);
blend_was_enabled = glIsEnabled (GL_BLEND); blend_was_enabled = glIsEnabled (GL_BLEND);
vertex_array_was_enabled = glIsEnabled (GL_VERTEX_ARRAY); vertex_array_was_enabled = glIsEnabled (GL_VERTEX_ARRAY);
tex_coord_array_was_enabled = glIsEnabled (GL_TEXTURE_COORD_ARRAY); tex_coord_array_was_enabled = glIsEnabled (GL_TEXTURE_COORD_ARRAY);
color_array_was_enabled = glIsEnabled (GL_COLOR_ARRAY); color_array_was_enabled = glIsEnabled (GL_COLOR_ARRAY);
glEnable (GL_TEXTURE_2D); glEnable (paint_target);
glEnable (GL_BLEND); glEnable (GL_BLEND);
glEnableClientState (GL_VERTEX_ARRAY); glEnableClientState (GL_VERTEX_ARRAY);
glEnableClientState (GL_TEXTURE_COORD_ARRAY); glEnableClientState (GL_TEXTURE_COORD_ARRAY);
@ -379,7 +418,7 @@ mutter_shaped_texture_paint (ClutterActor *actor)
cogl_color (&white); cogl_color (&white);
/* Put the main painting texture in the first texture unit */ /* Put the main painting texture in the first texture unit */
glBindTexture (GL_TEXTURE_2D, paint_gl_tex); glBindTexture (paint_target, paint_gl_tex);
/* We need the actual size of the texture so that we can calculate /* We need the actual size of the texture so that we can calculate
the right texture coordinates if NPOTs textures are not supported the right texture coordinates if NPOTs textures are not supported
@ -391,9 +430,9 @@ mutter_shaped_texture_paint (ClutterActor *actor)
/* Put the mask texture in the second texture unit */ /* Put the mask texture in the second texture unit */
tst_active_texture (GL_TEXTURE1); tst_active_texture (GL_TEXTURE1);
tst_client_active_texture (GL_TEXTURE1); tst_client_active_texture (GL_TEXTURE1);
glBindTexture (GL_TEXTURE_2D, mask_gl_tex); glBindTexture (mask_target, mask_gl_tex);
glEnable (GL_TEXTURE_2D); glEnable (mask_target);
glEnableClientState (GL_TEXTURE_COORD_ARRAY); glEnableClientState (GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer (2, GL_FLOAT, 0, priv->mask_tex_coords); glTexCoordPointer (2, GL_FLOAT, 0, priv->mask_tex_coords);
@ -419,8 +458,11 @@ mutter_shaped_texture_paint (ClutterActor *actor)
- alloc.y1), - alloc.y1),
vertex_coords); vertex_coords);
if ((guint) paint_gl_width == tex_width if (paint_target == GL_TEXTURE_RECTANGLE_ARB)
&& (guint) paint_gl_height == tex_height) mutter_shaped_texture_set_coord_array (0.0f, 0.0f, tex_width, tex_height,
paint_tex_coords);
else if ((guint) paint_gl_width == tex_width
&& (guint) paint_gl_height == tex_height)
mutter_shaped_texture_set_coord_array (0.0f, 0.0f, 1.0f, 1.0f, mutter_shaped_texture_set_coord_array (0.0f, 0.0f, 1.0f, 1.0f,
paint_tex_coords); paint_tex_coords);
else else
@ -434,7 +476,7 @@ mutter_shaped_texture_paint (ClutterActor *actor)
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
/* Disable the second texture unit and coord array */ /* Disable the second texture unit and coord array */
glDisable (GL_TEXTURE_2D); glDisable (mask_target);
glDisableClientState (GL_TEXTURE_COORD_ARRAY); glDisableClientState (GL_TEXTURE_COORD_ARRAY);
/* Go back to operating on the first texture unit */ /* Go back to operating on the first texture unit */
@ -443,7 +485,7 @@ mutter_shaped_texture_paint (ClutterActor *actor)
/* Restore the old state */ /* Restore the old state */
if (!texture_was_enabled) if (!texture_was_enabled)
glDisable (GL_TEXTURE_2D); glDisable (paint_target);
if (!blend_was_enabled) if (!blend_was_enabled)
glDisable (GL_BLEND); glDisable (GL_BLEND);
if (!vertex_array_was_enabled) if (!vertex_array_was_enabled)

View File

@ -21,7 +21,6 @@
* 02111-1307, USA. * 02111-1307, USA.
*/ */
#define MUTTER_BUILDING_PLUGIN 1
#include "mutter-plugin.h" #include "mutter-plugin.h"
#include <libintl.h> #include <libintl.h>
@ -39,35 +38,63 @@
#define SWITCH_TIMEOUT 500 #define SWITCH_TIMEOUT 500
#define ACTOR_DATA_KEY "MCCP-Default-actor-data" #define ACTOR_DATA_KEY "MCCP-Default-actor-data"
#define MUTTER_TYPE_DEFAULT_PLUGIN (mutter_default_plugin_get_type ())
#define MUTTER_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPlugin))
#define MUTTER_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPluginClass))
#define MUTTER_IS_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_DEFAULT_PLUGIN_TYPE))
#define MUTTER_IS_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_DEFAULT_PLUGIN))
#define MUTTER_DEFAULT_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPluginClass))
#define MUTTER_DEFAULT_PLUGIN_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPluginPrivate))
typedef struct _MutterDefaultPlugin MutterDefaultPlugin;
typedef struct _MutterDefaultPluginClass MutterDefaultPluginClass;
typedef struct _MutterDefaultPluginPrivate MutterDefaultPluginPrivate;
struct _MutterDefaultPlugin
{
MutterPlugin parent;
MutterDefaultPluginPrivate *priv;
};
struct _MutterDefaultPluginClass
{
MutterPluginClass parent_class;
};
static GQuark actor_data_quark = 0; static GQuark actor_data_quark = 0;
static gboolean do_init (const char *params); static void minimize (MutterPlugin *plugin,
static void minimize (MutterWindow *actor); MutterWindow *actor);
static void map (MutterWindow *actor); static void map (MutterPlugin *plugin,
static void destroy (MutterWindow *actor); MutterWindow *actor);
static void maximize (MutterWindow *actor, static void destroy (MutterPlugin *plugin,
MutterWindow *actor);
static void maximize (MutterPlugin *plugin,
MutterWindow *actor,
gint x, gint y, gint width, gint height); gint x, gint y, gint width, gint height);
static void unmaximize (MutterWindow *actor, static void unmaximize (MutterPlugin *plugin,
MutterWindow *actor,
gint x, gint y, gint width, gint height); gint x, gint y, gint width, gint height);
static void switch_workspace (const GList **actors, gint from, gint to, static void switch_workspace (MutterPlugin *plugin,
const GList **actors, gint from, gint to,
MetaMotionDirection direction); MetaMotionDirection direction);
static void kill_effect (MutterWindow *actor, gulong event); static void kill_effect (MutterPlugin *plugin,
MutterWindow *actor, gulong event);
static gboolean reload (const char *params); static const MutterPluginInfo * plugin_info (MutterPlugin *plugin);
MUTTER_PLUGIN_DECLARE(MutterDefaultPlugin, mutter_default_plugin);
/*
* Create the plugin struct; function pointers initialized in
* g_module_check_init().
*/
MUTTER_DECLARE_PLUGIN();
/* /*
* Plugin private data that we store in the .plugin_private member. * Plugin private data that we store in the .plugin_private member.
*/ */
typedef struct _PluginState struct _MutterDefaultPluginPrivate
{ {
ClutterEffectTemplate *destroy_effect; ClutterEffectTemplate *destroy_effect;
ClutterEffectTemplate *minimize_effect; ClutterEffectTemplate *minimize_effect;
@ -82,8 +109,150 @@ typedef struct _PluginState
ClutterActor *desktop1; ClutterActor *desktop1;
ClutterActor *desktop2; ClutterActor *desktop2;
MutterPluginInfo info;
gboolean debug_mode : 1; gboolean debug_mode : 1;
} PluginState; };
static void
mutter_default_plugin_dispose (GObject *object)
{
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (object)->priv;
g_object_unref (priv->destroy_effect);
g_object_unref (priv->minimize_effect);
g_object_unref (priv->maximize_effect);
g_object_unref (priv->switch_workspace_effect);
G_OBJECT_CLASS (mutter_default_plugin_parent_class)->dispose (object);
}
static void
mutter_default_plugin_finalize (GObject *object)
{
G_OBJECT_CLASS (mutter_default_plugin_parent_class)->finalize (object);
}
static void
mutter_default_plugin_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
switch (prop_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
mutter_default_plugin_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
switch (prop_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
mutter_default_plugin_constructed (GObject *object)
{
MutterPlugin *plugin = MUTTER_PLUGIN (object);
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (object)->priv;
guint destroy_timeout = DESTROY_TIMEOUT;
guint minimize_timeout = MINIMIZE_TIMEOUT;
guint maximize_timeout = MAXIMIZE_TIMEOUT;
guint map_timeout = MAP_TIMEOUT;
guint switch_timeout = SWITCH_TIMEOUT;
if (mutter_plugin_debug_mode (plugin))
{
g_debug ("Plugin %s: Entering debug mode.", priv->info.name);
priv->debug_mode = TRUE;
/*
* Double the effect duration to make them easier to observe.
*/
destroy_timeout *= 2;
minimize_timeout *= 2;
maximize_timeout *= 2;
map_timeout *= 2;
switch_timeout *= 2;
}
priv->destroy_effect
= clutter_effect_template_new (clutter_timeline_new_for_duration (
destroy_timeout),
CLUTTER_ALPHA_SINE_INC);
priv->minimize_effect
= clutter_effect_template_new (clutter_timeline_new_for_duration (
minimize_timeout),
CLUTTER_ALPHA_SINE_INC);
priv->maximize_effect
= clutter_effect_template_new (clutter_timeline_new_for_duration (
maximize_timeout),
CLUTTER_ALPHA_SINE_INC);
priv->map_effect
= clutter_effect_template_new (clutter_timeline_new_for_duration (
map_timeout),
CLUTTER_ALPHA_SINE_INC);
priv->switch_workspace_effect
= clutter_effect_template_new (clutter_timeline_new_for_duration (
switch_timeout),
CLUTTER_ALPHA_SINE_INC);
}
static void
mutter_default_plugin_class_init (MutterDefaultPluginClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
MutterPluginClass *plugin_class = MUTTER_PLUGIN_CLASS (klass);
gobject_class->finalize = mutter_default_plugin_finalize;
gobject_class->dispose = mutter_default_plugin_dispose;
gobject_class->constructed = mutter_default_plugin_constructed;
gobject_class->set_property = mutter_default_plugin_set_property;
gobject_class->get_property = mutter_default_plugin_get_property;
plugin_class->map = map;
plugin_class->minimize = minimize;
plugin_class->maximize = maximize;
plugin_class->unmaximize = unmaximize;
plugin_class->destroy = destroy;
plugin_class->switch_workspace = switch_workspace;
plugin_class->kill_effect = kill_effect;
plugin_class->plugin_info = plugin_info;
g_type_class_add_private (gobject_class, sizeof (MutterDefaultPluginPrivate));
}
static void
mutter_default_plugin_init (MutterDefaultPlugin *self)
{
MutterDefaultPluginPrivate *priv;
self->priv = priv = MUTTER_DEFAULT_PLUGIN_GET_PRIVATE (self);
priv->info.name = "Default Effects";
priv->info.version = "0.1";
priv->info.author = "Intel Corp.";
priv->info.license = "GPL";
priv->info.description = "This is an example of a plugin implementation.";
}
/* /*
@ -102,8 +271,6 @@ typedef struct _ActorPrivate
gboolean is_maximized : 1; gboolean is_maximized : 1;
} ActorPrivate; } ActorPrivate;
static PluginState *plugin_state;
/* /*
* Actor private data accessor * Actor private data accessor
*/ */
@ -134,53 +301,72 @@ get_actor_private (MutterWindow *actor)
return priv; return priv;
} }
typedef struct SwitchWorkspaceData
{
MutterPlugin *plugin;
const GList **actors;
} SwitchWorkspaceData;
static void static void
on_switch_workspace_effect_complete (ClutterActor *group, gpointer data) on_switch_workspace_effect_complete (ClutterActor *group, gpointer data)
{ {
PluginState *state = plugin_state; SwitchWorkspaceData *sw_data = data;
GList *l = *((GList**)data); MutterPlugin *plugin = sw_data->plugin;
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
GList *l = *((GList**)sw_data->actors);
MutterWindow *actor_for_cb = l->data; MutterWindow *actor_for_cb = l->data;
while (l) while (l)
{ {
ClutterActor *a = l->data; ClutterActor *a = l->data;
MutterWindow *mc_window = MUTTER_WINDOW (a); MutterWindow *mc_window = MUTTER_WINDOW (a);
ActorPrivate *priv = get_actor_private (mc_window); ActorPrivate *apriv = get_actor_private (mc_window);
if (priv->orig_parent) if (apriv->orig_parent)
{ {
clutter_actor_reparent (a, priv->orig_parent); clutter_actor_reparent (a, apriv->orig_parent);
priv->orig_parent = NULL; apriv->orig_parent = NULL;
} }
l = l->next; l = l->next;
} }
clutter_actor_destroy (state->desktop1); clutter_actor_destroy (priv->desktop1);
clutter_actor_destroy (state->desktop2); clutter_actor_destroy (priv->desktop2);
state->actors = NULL; priv->actors = NULL;
state->tml_switch_workspace1 = NULL; priv->tml_switch_workspace1 = NULL;
state->tml_switch_workspace2 = NULL; priv->tml_switch_workspace2 = NULL;
state->desktop1 = NULL; priv->desktop1 = NULL;
state->desktop2 = NULL; priv->desktop2 = NULL;
mutter_plugin_effect_completed (mutter_get_plugin(), actor_for_cb, g_free (data);
mutter_plugin_effect_completed (plugin, actor_for_cb,
MUTTER_PLUGIN_SWITCH_WORKSPACE); MUTTER_PLUGIN_SWITCH_WORKSPACE);
} }
static void static void
switch_workspace (const GList **actors, gint from, gint to, switch_workspace (MutterPlugin *plugin,
const GList **actors, gint from, gint to,
MetaMotionDirection direction) MetaMotionDirection direction)
{ {
MutterPlugin *plugin = mutter_get_plugin(); MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
PluginState *state = plugin_state;
GList *l; GList *l;
gint n_workspaces; gint n_workspaces;
ClutterActor *workspace0 = clutter_group_new (); ClutterActor *workspace0 = clutter_group_new ();
ClutterActor *workspace1 = clutter_group_new (); ClutterActor *workspace1 = clutter_group_new ();
ClutterActor *stage; ClutterActor *stage;
int screen_width, screen_height; int screen_width, screen_height;
MetaScreen *screen = mutter_plugin_get_screen (plugin);
SwitchWorkspaceData *sw_data = g_new (SwitchWorkspaceData, 1);
/* Must chain up first */
MUTTER_PLUGIN_CLASS (mutter_default_plugin_parent_class)->
switch_workspace (plugin, actors, from, to, direction);
sw_data->plugin = plugin;
sw_data->actors = actors;
stage = mutter_plugin_get_stage (plugin); stage = mutter_plugin_get_stage (plugin);
@ -201,19 +387,19 @@ switch_workspace (const GList **actors, gint from, gint to,
if (from == to) if (from == to)
{ {
mutter_plugin_effect_completed (mutter_get_plugin(), NULL, mutter_plugin_effect_completed (plugin, NULL,
MUTTER_PLUGIN_SWITCH_WORKSPACE); MUTTER_PLUGIN_SWITCH_WORKSPACE);
return; return;
} }
n_workspaces = g_list_length (plugin->work_areas); n_workspaces = meta_screen_get_n_workspaces (screen);
l = g_list_last (*((GList**) actors)); l = g_list_last (*((GList**) actors));
while (l) while (l)
{ {
MutterWindow *mc_window = l->data; MutterWindow *mc_window = l->data;
ActorPrivate *priv = get_actor_private (mc_window); ActorPrivate *apriv = get_actor_private (mc_window);
ClutterActor *window = CLUTTER_ACTOR (mc_window); ClutterActor *window = CLUTTER_ACTOR (mc_window);
gint win_workspace; gint win_workspace;
@ -227,7 +413,7 @@ switch_workspace (const GList **actors, gint from, gint to,
clutter_actor_get_position (window, &x, &y); clutter_actor_get_position (window, &x, &y);
clutter_actor_get_size (window, &w, &h); clutter_actor_get_size (window, &w, &h);
priv->orig_parent = clutter_actor_get_parent (window); apriv->orig_parent = clutter_actor_get_parent (window);
clutter_actor_reparent (window, clutter_actor_reparent (window,
win_workspace == to ? workspace1 : workspace0); win_workspace == to ? workspace1 : workspace0);
@ -237,30 +423,30 @@ switch_workspace (const GList **actors, gint from, gint to,
else if (win_workspace < 0) else if (win_workspace < 0)
{ {
/* Sticky window */ /* Sticky window */
priv->orig_parent = NULL; apriv->orig_parent = NULL;
} }
else else
{ {
/* Window on some other desktop */ /* Window on some other desktop */
clutter_actor_hide (window); clutter_actor_hide (window);
priv->orig_parent = NULL; apriv->orig_parent = NULL;
} }
l = l->prev; l = l->prev;
} }
state->actors = (GList **)actors; priv->actors = (GList **)actors;
state->desktop1 = workspace0; priv->desktop1 = workspace0;
state->desktop2 = workspace1; priv->desktop2 = workspace1;
state->tml_switch_workspace2 = priv->tml_switch_workspace2 =
clutter_effect_scale (state->switch_workspace_effect, clutter_effect_scale (priv->switch_workspace_effect,
workspace1, 1.0, 1.0, workspace1, 1.0, 1.0,
on_switch_workspace_effect_complete, on_switch_workspace_effect_complete,
(gpointer)actors); (gpointer)sw_data);
state->tml_switch_workspace1 = priv->tml_switch_workspace1 =
clutter_effect_scale (state->switch_workspace_effect, clutter_effect_scale (priv->switch_workspace_effect,
workspace0, 0.0, 0.0, workspace0, 0.0, 0.0,
NULL, NULL); NULL, NULL);
} }
@ -277,6 +463,7 @@ on_minimize_effect_complete (ClutterActor *actor, gpointer data)
* Must reverse the effect of the effect; must hide it first to ensure * Must reverse the effect of the effect; must hide it first to ensure
* that the restoration will not be visible. * that the restoration will not be visible.
*/ */
MutterPlugin *plugin = data;
ActorPrivate *apriv; ActorPrivate *apriv;
MutterWindow *mc_window = MUTTER_WINDOW (actor); MutterWindow *mc_window = MUTTER_WINDOW (actor);
@ -292,7 +479,7 @@ on_minimize_effect_complete (ClutterActor *actor, gpointer data)
CLUTTER_GRAVITY_NORTH_WEST); CLUTTER_GRAVITY_NORTH_WEST);
/* Now notify the manager that we are done with this effect */ /* Now notify the manager that we are done with this effect */
mutter_plugin_effect_completed (mutter_get_plugin(), mc_window, mutter_plugin_effect_completed (plugin, mc_window,
MUTTER_PLUGIN_MINIMIZE); MUTTER_PLUGIN_MINIMIZE);
} }
@ -301,11 +488,15 @@ on_minimize_effect_complete (ClutterActor *actor, gpointer data)
* completion). * completion).
*/ */
static void static void
minimize (MutterWindow *mc_window) minimize (MutterPlugin *plugin, MutterWindow *mc_window)
{ {
PluginState *state = plugin_state; MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
MetaCompWindowType type; MetaCompWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (mc_window); ClutterActor *actor = CLUTTER_ACTOR (mc_window);
/* Must chain up first */
MUTTER_PLUGIN_CLASS (mutter_default_plugin_parent_class)->
minimize (plugin, mc_window);
type = mutter_window_get_window_type (mc_window); type = mutter_window_get_window_type (mc_window);
@ -318,16 +509,16 @@ minimize (MutterWindow *mc_window)
clutter_actor_move_anchor_point_from_gravity (actor, clutter_actor_move_anchor_point_from_gravity (actor,
CLUTTER_GRAVITY_CENTER); CLUTTER_GRAVITY_CENTER);
apriv->tml_minimize = clutter_effect_scale (state->minimize_effect, apriv->tml_minimize = clutter_effect_scale (priv->minimize_effect,
actor, actor,
0.0, 0.0,
0.0, 0.0,
(ClutterEffectCompleteFunc) (ClutterEffectCompleteFunc)
on_minimize_effect_complete, on_minimize_effect_complete,
NULL); plugin);
} }
else else
mutter_plugin_effect_completed (mutter_get_plugin(), mc_window, mutter_plugin_effect_completed (plugin, mc_window,
MUTTER_PLUGIN_MINIMIZE); MUTTER_PLUGIN_MINIMIZE);
} }
@ -341,6 +532,7 @@ on_maximize_effect_complete (ClutterActor *actor, gpointer data)
/* /*
* Must reverse the effect of the effect. * Must reverse the effect of the effect.
*/ */
MutterPlugin * plugin = data;
MutterWindow *mc_window = MUTTER_WINDOW (actor); MutterWindow *mc_window = MUTTER_WINDOW (actor);
ActorPrivate *apriv = get_actor_private (mc_window); ActorPrivate *apriv = get_actor_private (mc_window);
@ -352,7 +544,7 @@ on_maximize_effect_complete (ClutterActor *actor, gpointer data)
CLUTTER_GRAVITY_NORTH_WEST); CLUTTER_GRAVITY_NORTH_WEST);
/* Now notify the manager that we are done with this effect */ /* Now notify the manager that we are done with this effect */
mutter_plugin_effect_completed (mutter_get_plugin(), mc_window, mutter_plugin_effect_completed (plugin, mc_window,
MUTTER_PLUGIN_MAXIMIZE); MUTTER_PLUGIN_MAXIMIZE);
} }
@ -365,9 +557,11 @@ on_maximize_effect_complete (ClutterActor *actor, gpointer data)
* (Something like a sound would be more appropriate.) * (Something like a sound would be more appropriate.)
*/ */
static void static void
maximize (MutterWindow *mc_window, maximize (MutterPlugin *plugin,
MutterWindow *mc_window,
gint end_x, gint end_y, gint end_width, gint end_height) gint end_x, gint end_y, gint end_width, gint end_height)
{ {
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
MetaCompWindowType type; MetaCompWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (mc_window); ClutterActor *actor = CLUTTER_ACTOR (mc_window);
@ -376,6 +570,10 @@ maximize (MutterWindow *mc_window,
gint anchor_x = 0; gint anchor_x = 0;
gint anchor_y = 0; gint anchor_y = 0;
/* Must chain up first */
MUTTER_PLUGIN_CLASS (mutter_default_plugin_parent_class)->
maximize (plugin, mc_window, end_x, end_y, end_width, end_height);
type = mutter_window_get_window_type (mc_window); type = mutter_window_get_window_type (mc_window);
if (type == META_COMP_WINDOW_NORMAL) if (type == META_COMP_WINDOW_NORMAL)
@ -404,18 +602,18 @@ maximize (MutterWindow *mc_window,
clutter_actor_move_anchor_point (actor, anchor_x, anchor_y); clutter_actor_move_anchor_point (actor, anchor_x, anchor_y);
apriv->tml_maximize = apriv->tml_maximize =
clutter_effect_scale (plugin_state->maximize_effect, clutter_effect_scale (priv->maximize_effect,
actor, actor,
scale_x, scale_x,
scale_y, scale_y,
(ClutterEffectCompleteFunc) (ClutterEffectCompleteFunc)
on_maximize_effect_complete, on_maximize_effect_complete,
NULL); plugin);
return; return;
} }
mutter_plugin_effect_completed (mutter_get_plugin(), mc_window, mutter_plugin_effect_completed (plugin, mc_window,
MUTTER_PLUGIN_MAXIMIZE); MUTTER_PLUGIN_MAXIMIZE);
} }
@ -425,11 +623,16 @@ maximize (MutterWindow *mc_window,
* (Just a skeleton code.) * (Just a skeleton code.)
*/ */
static void static void
unmaximize (MutterWindow *mc_window, unmaximize (MutterPlugin *plugin,
MutterWindow *mc_window,
gint end_x, gint end_y, gint end_width, gint end_height) gint end_x, gint end_y, gint end_width, gint end_height)
{ {
MetaCompWindowType type = mutter_window_get_window_type (mc_window); MetaCompWindowType type = mutter_window_get_window_type (mc_window);
/* Must chain up first */
MUTTER_PLUGIN_CLASS (mutter_default_plugin_parent_class)->
unmaximize (plugin, mc_window, end_x, end_y, end_width, end_height);
if (type == META_COMP_WINDOW_NORMAL) if (type == META_COMP_WINDOW_NORMAL)
{ {
ActorPrivate *apriv = get_actor_private (mc_window); ActorPrivate *apriv = get_actor_private (mc_window);
@ -438,7 +641,7 @@ unmaximize (MutterWindow *mc_window,
} }
/* Do this conditionally, if the effect requires completion callback. */ /* Do this conditionally, if the effect requires completion callback. */
mutter_plugin_effect_completed (mutter_get_plugin(), mc_window, mutter_plugin_effect_completed (plugin, mc_window,
MUTTER_PLUGIN_UNMAXIMIZE); MUTTER_PLUGIN_UNMAXIMIZE);
} }
@ -448,6 +651,7 @@ on_map_effect_complete (ClutterActor *actor, gpointer data)
/* /*
* Must reverse the effect of the effect. * Must reverse the effect of the effect.
*/ */
MutterPlugin *plugin = data;
MutterWindow *mc_window = MUTTER_WINDOW (actor); MutterWindow *mc_window = MUTTER_WINDOW (actor);
ActorPrivate *apriv = get_actor_private (mc_window); ActorPrivate *apriv = get_actor_private (mc_window);
@ -457,7 +661,7 @@ on_map_effect_complete (ClutterActor *actor, gpointer data)
CLUTTER_GRAVITY_NORTH_WEST); CLUTTER_GRAVITY_NORTH_WEST);
/* Now notify the manager that we are done with this effect */ /* Now notify the manager that we are done with this effect */
mutter_plugin_effect_completed (mutter_get_plugin(), mc_window, MUTTER_PLUGIN_MAP); mutter_plugin_effect_completed (plugin, mc_window, MUTTER_PLUGIN_MAP);
} }
/* /*
@ -465,11 +669,16 @@ on_map_effect_complete (ClutterActor *actor, gpointer data)
* completion). * completion).
*/ */
static void static void
map (MutterWindow *mc_window) map (MutterPlugin *plugin, MutterWindow *mc_window)
{ {
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
MetaCompWindowType type; MetaCompWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (mc_window); ClutterActor *actor = CLUTTER_ACTOR (mc_window);
/* Must chain up first */
MUTTER_PLUGIN_CLASS (mutter_default_plugin_parent_class)->
map (plugin, mc_window);
type = mutter_window_get_window_type (mc_window); type = mutter_window_get_window_type (mc_window);
if (type == META_COMP_WINDOW_NORMAL) if (type == META_COMP_WINDOW_NORMAL)
@ -482,19 +691,19 @@ map (MutterWindow *mc_window)
clutter_actor_set_scale (actor, 0.0, 0.0); clutter_actor_set_scale (actor, 0.0, 0.0);
clutter_actor_show (actor); clutter_actor_show (actor);
apriv->tml_map = clutter_effect_scale (plugin_state->map_effect, apriv->tml_map = clutter_effect_scale (priv->map_effect,
actor, actor,
1.0, 1.0,
1.0, 1.0,
(ClutterEffectCompleteFunc) (ClutterEffectCompleteFunc)
on_map_effect_complete, on_map_effect_complete,
NULL); plugin);
apriv->is_minimized = FALSE; apriv->is_minimized = FALSE;
} }
else else
mutter_plugin_effect_completed (mutter_get_plugin(), mc_window, mutter_plugin_effect_completed (plugin, mc_window,
MUTTER_PLUGIN_MAP); MUTTER_PLUGIN_MAP);
} }
@ -505,7 +714,7 @@ map (MutterWindow *mc_window)
static void static void
on_destroy_effect_complete (ClutterActor *actor, gpointer data) on_destroy_effect_complete (ClutterActor *actor, gpointer data)
{ {
MutterPlugin *plugin = mutter_get_plugin(); MutterPlugin *plugin = data;
MutterWindow *mc_window = MUTTER_WINDOW (actor); MutterWindow *mc_window = MUTTER_WINDOW (actor);
ActorPrivate *apriv = get_actor_private (mc_window); ActorPrivate *apriv = get_actor_private (mc_window);
@ -519,11 +728,16 @@ on_destroy_effect_complete (ClutterActor *actor, gpointer data)
* Simple TV-out like effect. * Simple TV-out like effect.
*/ */
static void static void
destroy (MutterWindow *mc_window) destroy (MutterPlugin *plugin, MutterWindow *mc_window)
{ {
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
MetaCompWindowType type; MetaCompWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (mc_window); ClutterActor *actor = CLUTTER_ACTOR (mc_window);
/* Must chain up first */
MUTTER_PLUGIN_CLASS (mutter_default_plugin_parent_class)->
destroy (plugin, mc_window);
type = mutter_window_get_window_type (mc_window); type = mutter_window_get_window_type (mc_window);
if (type == META_COMP_WINDOW_NORMAL) if (type == META_COMP_WINDOW_NORMAL)
@ -533,34 +747,34 @@ destroy (MutterWindow *mc_window)
clutter_actor_move_anchor_point_from_gravity (actor, clutter_actor_move_anchor_point_from_gravity (actor,
CLUTTER_GRAVITY_CENTER); CLUTTER_GRAVITY_CENTER);
apriv->tml_destroy = clutter_effect_scale (plugin_state->destroy_effect, apriv->tml_destroy = clutter_effect_scale (priv->destroy_effect,
actor, actor,
1.0, 1.0,
0.0, 0.0,
(ClutterEffectCompleteFunc) (ClutterEffectCompleteFunc)
on_destroy_effect_complete, on_destroy_effect_complete,
NULL); plugin);
} }
else else
mutter_plugin_effect_completed (mutter_get_plugin(), mc_window, mutter_plugin_effect_completed (plugin, mc_window,
MUTTER_PLUGIN_DESTROY); MUTTER_PLUGIN_DESTROY);
} }
static void static void
kill_effect (MutterWindow *mc_window, gulong event) kill_effect (MutterPlugin *plugin, MutterWindow *mc_window, gulong event)
{ {
ActorPrivate *apriv; ActorPrivate *apriv;
ClutterActor *actor = CLUTTER_ACTOR (mc_window); ClutterActor *actor = CLUTTER_ACTOR (mc_window);
if (event & MUTTER_PLUGIN_SWITCH_WORKSPACE) if (event & MUTTER_PLUGIN_SWITCH_WORKSPACE)
{ {
PluginState *state = plugin_state; MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
if (state->tml_switch_workspace1) if (priv->tml_switch_workspace1)
{ {
clutter_timeline_stop (state->tml_switch_workspace1); clutter_timeline_stop (priv->tml_switch_workspace1);
clutter_timeline_stop (state->tml_switch_workspace2); clutter_timeline_stop (priv->tml_switch_workspace2);
on_switch_workspace_effect_complete (state->desktop1, state->actors); on_switch_workspace_effect_complete (priv->desktop1, priv->actors);
} }
if (!(event & ~MUTTER_PLUGIN_SWITCH_WORKSPACE)) if (!(event & ~MUTTER_PLUGIN_SWITCH_WORKSPACE))
@ -597,144 +811,10 @@ kill_effect (MutterWindow *mc_window, gulong event)
} }
} }
static const MutterPluginInfo *
const gchar * g_module_check_init (GModule *module); plugin_info (MutterPlugin *plugin)
const gchar *
g_module_check_init (GModule *module)
{ {
MutterPlugin *plugin = mutter_get_plugin (); MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
/* Human readable name (for use in UI) */ return &priv->info;
plugin->name = "Default Effects";
/* Plugin load time initialiser */
plugin->do_init = do_init;
/* Effect handlers */
plugin->minimize = minimize;
plugin->destroy = destroy;
plugin->map = map;
plugin->maximize = maximize;
plugin->unmaximize = unmaximize;
plugin->switch_workspace = switch_workspace;
plugin->kill_effect = kill_effect;
/* The reload handler */
plugin->reload = reload;
return NULL;
} }
/*
* Core of the plugin init function, called for initial initialization and
* by the reload() function. Returns TRUE on success.
*/
static gboolean
do_init (const char *params)
{
guint destroy_timeout = DESTROY_TIMEOUT;
guint minimize_timeout = MINIMIZE_TIMEOUT;
guint maximize_timeout = MAXIMIZE_TIMEOUT;
guint map_timeout = MAP_TIMEOUT;
guint switch_timeout = SWITCH_TIMEOUT;
plugin_state = g_new0 (PluginState, 1);
if (params)
{
if (strstr (params, "debug"))
{
g_debug ("%s: Entering debug mode.", mutter_get_plugin()->name);
plugin_state->debug_mode = TRUE;
/*
* Double the effect duration to make them easier to observe.
*/
destroy_timeout *= 2;
minimize_timeout *= 2;
maximize_timeout *= 2;
map_timeout *= 2;
switch_timeout *= 2;
}
}
plugin_state->destroy_effect
= clutter_effect_template_new (clutter_timeline_new_for_duration (
destroy_timeout),
CLUTTER_ALPHA_SINE_INC);
plugin_state->minimize_effect
= clutter_effect_template_new (clutter_timeline_new_for_duration (
minimize_timeout),
CLUTTER_ALPHA_SINE_INC);
plugin_state->maximize_effect
= clutter_effect_template_new (clutter_timeline_new_for_duration (
maximize_timeout),
CLUTTER_ALPHA_SINE_INC);
plugin_state->map_effect
= clutter_effect_template_new (clutter_timeline_new_for_duration (
map_timeout),
CLUTTER_ALPHA_SINE_INC);
plugin_state->switch_workspace_effect
= clutter_effect_template_new (clutter_timeline_new_for_duration (
switch_timeout),
CLUTTER_ALPHA_SINE_INC);
return TRUE;
}
static void
free_plugin_private (PluginState *state)
{
if (!state)
return;
g_object_unref (state->destroy_effect);
g_object_unref (state->minimize_effect);
g_object_unref (state->maximize_effect);
g_object_unref (state->switch_workspace_effect);
g_free (state);
}
/*
* Called by the plugin manager when we stuff like the command line parameters
* changed.
*/
static gboolean
reload (const char *params)
{
PluginState *state;
state = plugin_state;
if (do_init (params))
{
/* Success; free the old state */
free_plugin_private (plugin_state);
return TRUE;
}
else
{
/* Fail -- fall back to the old state. */
plugin_state = state;
}
return FALSE;
}
/*
* GModule unload function -- do any cleanup required.
*/
G_MODULE_EXPORT void g_module_unload (GModule *module);
G_MODULE_EXPORT void
g_module_unload (GModule *module)
{
free_plugin_private (plugin_state);
}

View File

@ -33,20 +33,8 @@
#include <gmodule.h> #include <gmodule.h>
/* /*
* This file defines the plugin API. * FIXME -- move these to a private include
* * Required by plugin manager.
* Effects plugin is shared library loaded via g_module_open(); it is
* recommended that the GModule API is used (otherwise you are on your own to
* do proper plugin clean up when the module is unloaded).
*
* The plugin interface is exported via the MutterPlugin struct.
*/
typedef struct MutterPlugin MutterPlugin;
/*
* Effect flags: identify events that the plugin can handle, used by kill_effect
* function.
*/ */
#define MUTTER_PLUGIN_MINIMIZE (1<<0) #define MUTTER_PLUGIN_MINIMIZE (1<<0)
#define MUTTER_PLUGIN_MAXIMIZE (1<<1) #define MUTTER_PLUGIN_MAXIMIZE (1<<1)
@ -57,19 +45,96 @@ typedef struct MutterPlugin MutterPlugin;
#define MUTTER_PLUGIN_ALL_EFFECTS (~0) #define MUTTER_PLUGIN_ALL_EFFECTS (~0)
#define MUTTER_DECLARE_PLUGIN() G_MODULE_EXPORT MutterPlugin mutter_plugin = \ #define MUTTER_TYPE_PLUGIN (mutter_plugin_get_type ())
{ \ #define MUTTER_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_PLUGIN, MutterPlugin))
METACITY_MAJOR_VERSION, \ #define MUTTER_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_PLUGIN, MutterPluginClass))
METACITY_MINOR_VERSION, \ #define MUTTER_IS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_PLUGIN_TYPE))
METACITY_MICRO_VERSION, \ #define MUTTER_IS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_PLUGIN))
METACITY_CLUTTER_PLUGIN_API_VERSION \ #define MUTTER_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_PLUGIN, MutterPluginClass))
}; \
static inline MutterPlugin * mutter_get_plugin () \
{ \
return &mutter_plugin; \
}
struct MutterPlugin typedef struct _MutterPlugin MutterPlugin;
typedef struct _MutterPluginClass MutterPluginClass;
typedef struct _MutterPluginVersion MutterPluginVersion;
typedef struct _MutterPluginInfo MutterPluginInfo;
typedef struct _MutterPluginPrivate MutterPluginPrivate;
struct _MutterPlugin
{
GObject parent;
MutterPluginPrivate *priv;
};
struct _MutterPluginClass
{
GObjectClass parent_class;
void (*minimize) (MutterPlugin *plugin,
MutterWindow *actor);
void (*maximize) (MutterPlugin *plugin,
MutterWindow *actor,
gint x,
gint y,
gint width,
gint height);
void (*unmaximize) (MutterPlugin *plugin,
MutterWindow *actor,
gint x,
gint y,
gint width,
gint height);
void (*map) (MutterPlugin *plugin,
MutterWindow *actor);
void (*destroy) (MutterPlugin *plugin,
MutterWindow *actor);
void (*switch_workspace) (MutterPlugin *plugin,
const GList **actors,
gint from,
gint to,
MetaMotionDirection direction);
/*
* Called if an effect should be killed prematurely; the plugin must
* call the completed() callback as if the effect terminated naturally.
* The events parameter is a bitmask indicating which effects are to be
* killed.
*/
void (*kill_effect) (MutterPlugin *plugin,
MutterWindow *actor,
gulong events);
/* General XEvent filter. This is fired *before* metacity itself handles
* an event. Return TRUE to block any further processing.
*/
gboolean (*xevent_filter) (MutterPlugin *plugin,
XEvent *event);
const MutterPluginInfo * (*plugin_info) (MutterPlugin *plugin);
};
struct _MutterPluginInfo
{
const gchar *name;
const gchar *version;
const gchar *author;
const gchar *license;
const gchar *description;
};
GType mutter_plugin_get_type (void);
gulong mutter_plugin_features (MutterPlugin *plugin);
gboolean mutter_plugin_disabled (MutterPlugin *plugin);
gboolean mutter_plugin_running (MutterPlugin *plugin);
gboolean mutter_plugin_debug_mode (MutterPlugin *plugin);
const MutterPluginInfo * mutter_plugin_get_info (MutterPlugin *plugin);
struct _MutterPluginVersion
{ {
/* /*
* Version information; the first three numbers match the Metacity version * Version information; the first three numbers match the Metacity version
@ -83,134 +148,81 @@ struct MutterPlugin
/* /*
* Version of the plugin API; this is unrelated to the matacity version * Version of the plugin API; this is unrelated to the matacity version
* per se. The API version is checked by the plugin manager and must match * per se. The API version is checked by the plugin manager and must match
* the one used by it (see clutter-plugins/simple.c for sample code). * the one used by it (see clutter-plugins/default.c for sample code).
*/ */
guint version_api; guint version_api;
#ifndef MUTTER_BUILDING_PLUGIN
const
#endif
gchar *name; /* Human-readable name for UI */
/*
* This function is called once the plugin has been loaded.
*
* @params is a string containing additional parameters for the plugin and is
* specified after the plugin name in the gconf database, separated by a
* colon.
*
* The following parameter tokens need to be handled by all
* plugins:
*
* 'debug'
* Indicates running in debug mode; the plugin
* might want to print useful debug info, or
* extend effect duration, etc.
*
* 'disable: ...;'
*
* The disable token indicates that the effects
* listed after the colon should be disabled.
*
* The list is comma-separated, terminated by a
* semicolon and consisting of the following
* tokens:
*
* minimize
* maximize
* unmaximize
* map
* destroy
* switch-workspace
*
* FIXME: ^^^ Instead of configuring in terms of what should be
* disabled, and needing a mechanism for coping with the user
* mistakenly not disabling the right things, it might be neater
* if plugins were enabled on a per effect basis in the first
* place. I.e. in gconf we could have effect:plugin key value
* pairs.
*/
gboolean (*do_init) (const char *params);
/*
* Event handlers
*
* Plugins must not make any special assumptions about the nature of
* ClutterActor, as the implementation details can change.
*
* Plugins must restore actor properties on completion (i.e., fade effects
* must restore opacity back to the original value, scale effects scale,
* etc.).
*
* On completion, each event handler must call the manager completed()
* callback function.
*/
void (*minimize) (MutterWindow *actor);
void (*maximize) (MutterWindow *actor,
gint x,
gint y,
gint width,
gint height);
void (*unmaximize) (MutterWindow *actor,
gint x,
gint y,
gint width,
gint height);
void (*map) (MutterWindow *actor);
void (*destroy) (MutterWindow *actor);
/*
* Each actor in the list has a workspace number attached to it using
* g_object_set_data() with key MUTTER_PLUGIN_WORKSPACE_KEY;
* workspace < 0 indicates the window is sticky (i.e., on all desktops).
* TODO: Add accessor for sticky bit in new MutterWindow structure
*/
void (*switch_workspace) (const GList **actors,
gint from,
gint to,
MetaMotionDirection direction);
/*
* Called if an effect should be killed prematurely; the plugin must
* call the completed() callback as if the effect terminated naturally.
* The events parameter is a bitmask indicating which effects are to be
* killed.
*/
void (*kill_effect) (MutterWindow *actor,
gulong events);
/*
* The plugin manager will call this function when module should be reloaded.
* This happens, for example, when the parameters for the plugin changed.
*/
gboolean (*reload) (const char *params);
/* General XEvent filter. This is fired *before* metacity itself handles
* an event. Return TRUE to block any further processing.
*/
gboolean (*xevent_filter) (XEvent *event);
/* List of PluginWorkspaceRectangles defining the geometry of individual
* workspaces. */
GList *work_areas;
void *plugin_private; /* Plugin private data go here; use the plugin init
* function to allocate and initialize any private
* data.
*/
/* Private; manager private data. */
void *manager_private;
}; };
#ifndef MUTTER_PLUGIN_FROM_MANAGER_ /*
static inline MutterPlugin *mutter_get_plugin (); * Convenience macro to set up the plugin type. Based on GEdit.
#endif */
#define MUTTER_PLUGIN_DECLARE(ObjectName, object_name) \
G_MODULE_EXPORT MutterPluginVersion mutter_plugin_version = \
{ \
METACITY_MAJOR_VERSION, \
METACITY_MINOR_VERSION, \
METACITY_MICRO_VERSION, \
METACITY_CLUTTER_PLUGIN_API_VERSION \
}; \
\
static GType g_define_type_id = 0; \
\
/* Prototypes */ \
G_MODULE_EXPORT \
GType object_name##_get_type (void); \
\
G_MODULE_EXPORT \
GType object_name##_register_type (GTypeModule *type_module); \
\
G_MODULE_EXPORT \
GType mutter_plugin_register_type (GTypeModule *type_module); \
\
GType \
object_name##_get_type () \
{ \
return g_define_type_id; \
} \
\
static void object_name##_init (ObjectName *self); \
static void object_name##_class_init (ObjectName##Class *klass); \
static gpointer object_name##_parent_class = NULL; \
static void object_name##_class_intern_init (gpointer klass) \
{ \
object_name##_parent_class = g_type_class_peek_parent (klass); \
object_name##_class_init ((ObjectName##Class *) klass); \
} \
\
GType \
object_name##_register_type (GTypeModule *type_module) \
{ \
static const GTypeInfo our_info = \
{ \
sizeof (ObjectName##Class), \
NULL, /* base_init */ \
NULL, /* base_finalize */ \
(GClassInitFunc) object_name##_class_intern_init, \
NULL, \
NULL, /* class_data */ \
sizeof (ObjectName), \
0, /* n_preallocs */ \
(GInstanceInitFunc) object_name##_init \
}; \
\
g_define_type_id = g_type_module_register_type (type_module, \
MUTTER_TYPE_PLUGIN, \
#ObjectName, \
&our_info, \
0); \
\
\
return g_define_type_id; \
} \
\
G_MODULE_EXPORT GType \
mutter_plugin_register_type (GTypeModule *type_module) \
{ \
return object_name##_register_type (type_module); \
} \
void void
mutter_plugin_effect_completed (MutterPlugin *plugin, mutter_plugin_effect_completed (MutterPlugin *plugin,