Merge branch 'moblin-plugin' into clutter

Conflicts:

	src/compositor/clutter/compositor-clutter-plugin-manager.c
	src/compositor/mutter/plugins/Makefile.am
	src/compositor/mutter/plugins/moblin.c
	src/include/compositor-clutter-plugin.h
	src/include/compositor-clutter.h
This commit is contained in:
Tomas Frydrych 2008-10-16 23:02:34 +01:00
commit dc33ad1adf
10 changed files with 1502 additions and 115 deletions

View File

@ -0,0 +1,780 @@
/* -*- 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 "compositor-clutter-plugin-manager.h"
#include "compositor-clutter.h"
#include "prefs.h"
#include "errors.h"
#include "workspace.h"
#include <gmodule.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 meta_compositor_clutter_plugin_manager_reload (MetaCompositorClutterPluginManager *mgr);
struct MetaCompositorClutterPluginManager
{
MetaScreen *screen;
GList *plugins; /* TODO -- maybe use hash table */
GList *unload; /* Plugins that are disabled and pending unload */
guint idle_unload_id;
};
typedef struct MetaCompositorClutterPluginPrivate MetaCompositorClutterPluginPrivate;
struct MetaCompositorClutterPluginPrivate
{
MetaCompositorClutterPluginManager *self;
GModule *module;
gboolean disabled : 1;
};
static void
free_plugin_workspaces (MetaCompositorClutterPlugin *plg)
{
GList *l;
l = plg->work_areas;
while (l)
{
g_free (l->data);
l = l->next;
}
if (plg->work_areas)
g_list_free (plg->work_areas);
plg->work_areas = NULL;
}
/*
* Gets work area geometry and stores it in list in the plugin.
*
* If the plg 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,
MetaCompositorClutterPlugin *plg)
{
GList *l, *l2 = NULL;
l = meta_screen_get_workspaces (screen);
while (l)
{
MetaWorkspace *w = l->data;
PluginWorkspaceRectangle *r;
r = g_new0 (PluginWorkspaceRectangle, 1);
meta_workspace_get_work_area_all_xineramas (w, (MetaRectangle*)r);
l2 = g_list_append (l2, r);
l = l->next;
}
free_plugin_workspaces (plg);
plg->work_areas = l2;
}
/*
* Checks that the plugin is compatible with the WM and sets up the plugin
* struct.
*/
static MetaCompositorClutterPlugin *
meta_compositor_clutter_plugin_load (MetaCompositorClutterPluginManager *mgr,
GModule *module,
const gchar *params)
{
MetaCompositorClutterPlugin *plg;
if (g_module_symbol (module,
META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT_NAME,
(gpointer *)&plg))
{
if (plg->version_api == METACITY_CLUTTER_PLUGIN_API_VERSION)
{
MetaCompositorClutterPluginPrivate *priv;
gboolean (*init_func) (void);
priv = g_new0 (MetaCompositorClutterPluginPrivate, 1);
plg->params = g_strdup (params);
plg->manager_private = priv;
priv->module = module;
priv->self = mgr;
meta_screen_get_size (mgr->screen,
&plg->screen_width, &plg->screen_height);
update_plugin_workspaces (mgr->screen, plg);
/*
* Check for and run the plugin init function.
*/
if (g_module_symbol (module,
META_COMPOSITOR_CLUTTER_PLUGIN_INIT_FUNC_NAME,
(gpointer *)&init_func) &&
!init_func())
{
g_free (plg->params);
g_free (priv);
free_plugin_workspaces (plg);
return NULL;
}
meta_verbose ("Loaded plugin [%s]\n", plg->name);
return plg;
}
}
return NULL;
}
/*
* Attempst to unload a plugin; returns FALSE if plugin cannot be unloaded at
* present (e.g., and effect is in progress) and should be scheduled for
* removal later.
*/
static gboolean
meta_compositor_clutter_plugin_unload (MetaCompositorClutterPlugin *plg)
{
MetaCompositorClutterPluginPrivate *priv;
GModule *module;
priv = plg->manager_private;
module = priv->module;
if (plg->running)
{
priv->disabled = TRUE;
return FALSE;
}
g_free (plg->params);
plg->params = NULL;
g_free (priv);
plg->manager_private = NULL;
g_module_close (module);
return TRUE;
}
/*
* Iddle callback to remove plugins that could not be removed directly and are
* pending for removal.
*/
static gboolean
meta_compositor_clutter_plugin_manager_idle_unload (MetaCompositorClutterPluginManager *mgr)
{
GList *l = mgr->unload;
gboolean dont_remove = TRUE;
while (l)
{
MetaCompositorClutterPlugin *plg = l->data;
if (meta_compositor_clutter_plugin_unload (plg))
{
/* Remove from list */
GList *p = l->prev;
GList *n = l->next;
if (!p)
mgr->unload = n;
else
p->next = n;
if (n)
n->prev = p;
g_list_free_1 (l);
l = n;
}
else
l = l->next;
}
if (!mgr->unload)
{
/* If no more unloads are pending, remove the handler as well */
dont_remove = FALSE;
mgr->idle_unload_id = 0;
}
return dont_remove;
}
/*
* Unloads all plugins
*/
static void
meta_compositor_clutter_plugin_manager_unload (MetaCompositorClutterPluginManager *mgr)
{
GList *plugins = mgr->plugins;
while (plugins)
{
MetaCompositorClutterPlugin *plg = plugins->data;
/* If the plugin could not be removed, move it to the unload list */
if (!meta_compositor_clutter_plugin_unload (plg))
{
mgr->unload = g_list_prepend (mgr->unload, plg);
if (!mgr->idle_unload_id)
{
mgr->idle_unload_id = g_idle_add ((GSourceFunc)
meta_compositor_clutter_plugin_manager_idle_unload,
mgr);
}
}
plugins = plugins->next;
}
g_list_free (mgr->plugins);
mgr->plugins = NULL;
}
static void
prefs_changed_callback (MetaPreference pref,
void *data)
{
MetaCompositorClutterPluginManager *mgr = data;
if (pref == META_PREF_CLUTTER_PLUGINS)
{
meta_compositor_clutter_plugin_manager_reload (mgr);
}
else if (pref == META_PREF_NUM_WORKSPACES)
{
meta_compositor_clutter_plugin_manager_update_workspaces (mgr);
}
}
/*
* Loads all plugins listed in gconf registry.
*/
static gboolean
meta_compositor_clutter_plugin_manager_load (MetaCompositorClutterPluginManager *mgr)
{
const gchar *dpath = METACITY_PKGLIBDIR "/plugins/clutter/";
GSList *plugins, *fallback = NULL;
plugins = meta_prefs_get_clutter_plugins ();
if (!plugins)
{
/*
* If no plugins are specified, try to load the default plugin.
*/
fallback = g_slist_append (fallback, "default");
plugins = fallback;
}
while (plugins)
{
gchar *plg_string;
gchar *params;
plg_string = g_strdup (plugins->data);
if (plg_string)
{
GModule *plg;
gchar *path;
params = strchr (plg_string, ':');
if (params)
{
*params = 0;
++params;
}
path = g_strconcat (dpath, plg_string, ".so", NULL);
if ((plg = g_module_open (path, 0)))
{
MetaCompositorClutterPlugin *p;
if ((p = meta_compositor_clutter_plugin_load (mgr,
plg, params)))
mgr->plugins = g_list_prepend (mgr->plugins, p);
else
{
g_message ("Plugin load for [%s] failed\n", path);
g_module_close (plg);
}
}
else
g_message ("Unable to load plugin [%s]\n", path);
g_free (path);
g_free (plg_string);
}
plugins = plugins->next;
}
if (fallback)
g_slist_free (fallback);
if (mgr->plugins != NULL)
{
meta_prefs_add_listener (prefs_changed_callback, mgr);
return TRUE;
}
return FALSE;
}
/*
* Reloads all plugins
*/
static gboolean
meta_compositor_clutter_plugin_manager_reload (MetaCompositorClutterPluginManager *mgr)
{
/* TODO -- brute force; should we build a list of plugins to load and list of
* plugins to unload? We are probably not going to have large numbers of
* plugins loaded at the same time, so it might not be worth it.
*/
meta_compositor_clutter_plugin_manager_unload (mgr);
return meta_compositor_clutter_plugin_manager_load (mgr);
}
static gboolean
meta_compositor_clutter_plugin_manager_init (MetaCompositorClutterPluginManager *mgr)
{
return meta_compositor_clutter_plugin_manager_load (mgr);
}
void
meta_compositor_clutter_plugin_manager_update_workspace (MetaCompositorClutterPluginManager *mgr, MetaWorkspace *w)
{
GList *l;
gint n;
n = meta_workspace_index (w);
l = mgr->plugins;
while (l)
{
MetaCompositorClutterPlugin *plg = l->data;
PluginWorkspaceRectangle *r = g_list_nth_data (plg->work_areas, n);
if (r)
{
meta_workspace_get_work_area_all_xineramas (w, (MetaRectangle*)r);
}
else
{
/* Something not entirely right; redo the whole thing */
update_plugin_workspaces (mgr->screen, plg);
return;
}
l = l->next;
}
}
void
meta_compositor_clutter_plugin_manager_update_workspaces (MetaCompositorClutterPluginManager *mgr)
{
GList *l;
l = mgr->plugins;
while (l)
{
MetaCompositorClutterPlugin *plg = l->data;
update_plugin_workspaces (mgr->screen, plg);
l = l->next;
}
}
MetaCompositorClutterPluginManager *
meta_compositor_clutter_plugin_manager_new (MetaScreen *screen)
{
MetaCompositorClutterPluginManager *mgr;
mgr = g_new0 (MetaCompositorClutterPluginManager, 1);
mgr->screen = screen;
if (!meta_compositor_clutter_plugin_manager_init (mgr))
{
g_free (mgr);
mgr = NULL;
}
return mgr;
}
static void
meta_compositor_clutter_plugin_manager_kill_effect (MetaCompositorClutterPluginManager *mgr,
MetaCompWindow *actor,
unsigned long events)
{
GList *l = mgr->plugins;
while (l)
{
MetaCompositorClutterPlugin *plg = l->data;
MetaCompositorClutterPluginPrivate *priv = plg->manager_private;
if (!priv->disabled && (plg->features & events) && plg->kill_effect)
plg->kill_effect (actor, events);
l = l->next;
}
}
#define ALL_BUT_SWITCH \
META_COMPOSITOR_CLUTTER_PLUGIN_ALL_EFFECTS & \
~META_COMPOSITOR_CLUTTER_PLUGIN_SWITCH_WORKSPACE
/*
* Public method that the compositor hooks into for events that require
* no additional parameters.
*
* Returns TRUE if at least one of the plugins handled the event type (i.e.,
* if the return value is FALSE, there will be no subsequent call to the
* manager completed() callback, and the compositor must ensure that any
* appropriate post-effect cleanup is carried out.
*/
gboolean
meta_compositor_clutter_plugin_manager_event_simple (MetaCompositorClutterPluginManager *mgr,
MetaCompWindow *actor,
unsigned long event)
{
GList *l = mgr->plugins;
gboolean retval = FALSE;
while (l)
{
MetaCompositorClutterPlugin *plg = l->data;
MetaCompositorClutterPluginPrivate *priv = plg->manager_private;
if (!priv->disabled && (plg->features & event))
{
retval = TRUE;
switch (event)
{
case META_COMPOSITOR_CLUTTER_PLUGIN_MINIMIZE:
if (plg->minimize)
{
meta_compositor_clutter_plugin_manager_kill_effect (mgr,
actor,
ALL_BUT_SWITCH);
plg->minimize (actor);
}
break;
case META_COMPOSITOR_CLUTTER_PLUGIN_MAP:
if (plg->map)
{
meta_compositor_clutter_plugin_manager_kill_effect (mgr,
actor,
ALL_BUT_SWITCH);
plg->map (actor);
}
break;
case META_COMPOSITOR_CLUTTER_PLUGIN_DESTROY:
if (plg->destroy)
{
plg->destroy (actor);
}
break;
default:
g_warning ("Incorrect handler called for event %lu", event);
}
}
l = l->next;
}
return retval;
}
/*
* The public method that the compositor hooks into for maximize and unmaximize
* events.
*
* Returns TRUE if at least one of the plugins handled the event type (i.e.,
* if the return value is FALSE, there will be no subsequent call to the
* manager completed() callback, and the compositor must ensure that any
* appropriate post-effect cleanup is carried out.
*/
gboolean
meta_compositor_clutter_plugin_manager_event_maximize (MetaCompositorClutterPluginManager *mgr,
MetaCompWindow *actor,
unsigned long event,
gint target_x,
gint target_y,
gint target_width,
gint target_height)
{
GList *l = mgr->plugins;
gboolean retval = FALSE;
while (l)
{
MetaCompositorClutterPlugin *plg = l->data;
MetaCompositorClutterPluginPrivate *priv = plg->manager_private;
if (!priv->disabled && (plg->features & event))
{
retval = TRUE;
switch (event)
{
case META_COMPOSITOR_CLUTTER_PLUGIN_MAXIMIZE:
if (plg->maximize)
{
meta_compositor_clutter_plugin_manager_kill_effect (mgr,
actor,
ALL_BUT_SWITCH);
plg->maximize (actor,
target_x, target_y,
target_width, target_height);
}
break;
case META_COMPOSITOR_CLUTTER_PLUGIN_UNMAXIMIZE:
if (plg->unmaximize)
{
meta_compositor_clutter_plugin_manager_kill_effect (mgr,
actor,
ALL_BUT_SWITCH);
plg->unmaximize (actor,
target_x, target_y,
target_width, target_height);
}
break;
default:
g_warning ("Incorrect handler called for event %lu", event);
}
}
l = l->next;
}
return retval;
}
/*
* The public method that the compositor hooks into for desktop switching.
*
* Returns TRUE if at least one of the plugins handled the event type (i.e.,
* if the return value is FALSE, there will be no subsequent call to the
* manager completed() callback, and the compositor must ensure that any
* appropriate post-effect cleanup is carried out.
*/
gboolean
meta_compositor_clutter_plugin_manager_switch_workspace (MetaCompositorClutterPluginManager *mgr,
const GList **actors,
gint from,
gint to,
MetaMotionDirection direction)
{
GList *l = mgr->plugins;
gboolean retval = FALSE;
while (l)
{
MetaCompositorClutterPlugin *plg = l->data;
MetaCompositorClutterPluginPrivate *priv = plg->manager_private;
if (!priv->disabled &&
(plg->features & META_COMPOSITOR_CLUTTER_PLUGIN_SWITCH_WORKSPACE) &&
(actors && *actors))
{
if (plg->switch_workspace)
{
retval = TRUE;
meta_compositor_clutter_plugin_manager_kill_effect (mgr,
META_COMP_WINDOW ((*actors)->data),
META_COMPOSITOR_CLUTTER_PLUGIN_SWITCH_WORKSPACE);
plg->switch_workspace (actors, from, to, direction);
}
}
l = l->next;
}
return retval;
}
/*
* The public method that the compositor hooks into for desktop switching.
*
* Returns TRUE if at least one of the plugins handled the event type (i.e.,
* if the return value is FALSE, there will be no subsequent call to the
* manager completed() callback, and the compositor must ensure that any
* appropriate post-effect cleanup is carried out.
*/
gboolean
meta_compositor_clutter_plugin_manager_xevent_filter
(MetaCompositorClutterPluginManager *mgr, XEvent *xev)
{
GList *l;
if (!mgr)
return FALSE;
l = mgr->plugins;
while (l)
{
MetaCompositorClutterPlugin *plg = l->data;
if (plg->xevent_filter)
{
if (plg->xevent_filter (xev) == TRUE)
return TRUE;
}
l = l->next;
}
return FALSE;
}
/*
* Public accessors for plugins, exposed from compositor-clutter-plugin.h
*/
ClutterActor *
meta_comp_clutter_plugin_get_overlay_group (MetaCompositorClutterPlugin *plugin)
{
MetaCompositorClutterPluginPrivate *priv = plugin->manager_private;
MetaCompositorClutterPluginManager *mgr = priv->self;
return meta_compositor_clutter_get_overlay_group_for_screen (mgr->screen);
}
ClutterActor *
meta_comp_clutter_plugin_get_stage (MetaCompositorClutterPlugin *plugin)
{
MetaCompositorClutterPluginPrivate *priv = plugin->manager_private;
MetaCompositorClutterPluginManager *mgr = priv->self;
return meta_compositor_clutter_get_stage_for_screen (mgr->screen);
}
void
meta_comp_clutter_plugin_effect_completed (MetaCompositorClutterPlugin *plugin,
MetaCompWindow *actor,
unsigned long event)
{
if (!actor)
{
g_warning ("Plugin [%s] passed NULL for actor!",
(plugin && plugin->name) ? plugin->name : "unknown");
}
meta_compositor_clutter_window_effect_completed (actor, event);
}
void
meta_comp_clutter_plugin_set_stage_reactive (MetaCompositorClutterPlugin *plugin,
gboolean reactive)
{
MetaCompositorClutterPluginPrivate *priv = plugin->manager_private;
MetaCompositorClutterPluginManager *mgr = priv->self;
MetaDisplay *display = meta_screen_get_display (mgr->screen);
Display *xdpy = meta_display_get_xdisplay (display);
Window xstage, xoverlay;
ClutterActor *stage;
stage = meta_compositor_clutter_get_stage_for_screen (mgr->screen);
xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
xoverlay = meta_compositor_clutter_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
meta_comp_clutter_plugin_set_stage_input_area (MetaCompositorClutterPlugin *plugin,
gint x, gint y, gint width, gint height)
{
MetaCompositorClutterPluginPrivate *priv = plugin->manager_private;
MetaCompositorClutterPluginManager *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 = meta_compositor_clutter_get_stage_for_screen (mgr->screen);
xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
xoverlay = meta_compositor_clutter_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);
}

View File

@ -1645,6 +1645,7 @@ process_property_notify (Mutter *compositor,
static void
show_overlay_window (MetaScreen *screen, Window cow)
{
#if 0
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
XserverRegion region;
@ -1655,6 +1656,7 @@ show_overlay_window (MetaScreen *screen, Window cow)
XFixesSetWindowShapeRegion (xdisplay, cow, ShapeInput, 0, 0, region);
XFixesDestroyRegion (xdisplay, region);
#endif
}
static Window
@ -1667,7 +1669,14 @@ get_output_window (MetaScreen *screen)
xroot = meta_screen_get_xroot (screen);
output = XCompositeGetOverlayWindow (xdisplay, xroot);
XSelectInput (xdisplay, output, ExposureMask);
XSelectInput (xdisplay,
output,
FocusChangeMask |
ExposureMask |
PointerMotionMask |
PropertyChangeMask |
ButtonPressMask | ButtonReleaseMask |
KeyPressMask | KeyReleaseMask);
return output;
}
@ -1748,6 +1757,15 @@ clutter_cmp_manage_screen (MetaCompositor *compositor,
XReparentWindow (xdisplay, xwin, info->output, 0, 0);
XSelectInput (xdisplay,
xwin,
FocusChangeMask |
ExposureMask |
PointerMotionMask |
PropertyChangeMask |
ButtonPressMask | ButtonReleaseMask |
KeyPressMask | KeyReleaseMask);
info->window_group = clutter_group_new ();
info->overlay_group = clutter_group_new ();
@ -1842,6 +1860,29 @@ clutter_cmp_process_event (MetaCompositor *compositor,
event) == TRUE)
return;
}
else
{
GSList *l;
Mutter *clc = (Mutter*)compositor;
l = meta_display_get_screens (clc->display);
while (l)
{
MetaScreen *screen = l->data;
MetaCompScreen *info;
info = meta_screen_get_compositor_data (screen);
if (mutter_plugin_manager_xevent_filter (info->plugin_mgr,
event) == TRUE)
{
return;
}
l = l->next;
}
}
/*
* This trap is so that none of the compositor functions cause
@ -2246,6 +2287,15 @@ mutter_new (MetaDisplay *display)
#endif
}
Window
mutter_get_overlay_window (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
return info->output;
}
/* ------------------------------- */
/* Shadow Generation */

View File

@ -28,6 +28,10 @@
#include <gmodule.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);
@ -741,7 +745,7 @@ mutter_plugin_manager_xevent_filter (
* Public accessors for plugins, exposed from mutter-plugin.h
*/
ClutterActor *
meta_comp_clutter_plugin_get_overlay_group (MutterPlugin *plugin)
mutter_plugin_get_overlay_group (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = plugin->manager_private;
MutterPluginManager *plugin_mgr = priv->self;
@ -750,7 +754,7 @@ meta_comp_clutter_plugin_get_overlay_group (MutterPlugin *plugin)
}
ClutterActor *
meta_comp_clutter_plugin_get_stage (MutterPlugin *plugin)
mutter_plugin_get_stage (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = plugin->manager_private;
MutterPluginManager *plugin_mgr = priv->self;
@ -759,7 +763,7 @@ meta_comp_clutter_plugin_get_stage (MutterPlugin *plugin)
}
void
meta_comp_clutter_plugin_effect_completed (MutterPlugin *plugin,
mutter_plugin_effect_completed (MutterPlugin *plugin,
MutterWindow *actor,
unsigned long event)
{
@ -773,7 +777,7 @@ meta_comp_clutter_plugin_effect_completed (MutterPlugin *plugin,
}
void
meta_comp_clutter_plugin_query_screen_size (MutterPlugin *plugin,
mutter_plugin_query_screen_size (MutterPlugin *plugin,
int *width,
int *height)
{
@ -783,3 +787,66 @@ meta_comp_clutter_plugin_query_screen_size (MutterPlugin *plugin,
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);
}

View File

@ -12,6 +12,13 @@ default_la_SOURCES = default.c
default_la_LDFLAGS = -module -avoid-version -no-undefined
default_la_LIBADD = @CLUTTER_LIBS@
moblin_la_CFLAGS = -fPIC
moblin_la_SOURCES = moblin.c
moblin_la_LDFLAGS = -module -avoid-version -no-undefined
moblin_la_LIBADD = @CLUTTER_LIBS@
pkglib_LTLIBRARIES = default.la moblin.la
# post-install hook to remove the .la and .a files we are not interested in
# (There is no way to stop libtool generating static libs locally, and we
# cannot do this globally because of libmetacity-private.so).

View File

@ -202,7 +202,7 @@ on_switch_workspace_effect_complete (ClutterActor *group, gpointer data)
state->desktop1 = NULL;
state->desktop2 = NULL;
meta_comp_clutter_plugin_effect_completed (&mutter_plugin, actor_for_cb,
mutter_plugin_effect_completed (&mutter_plugin, actor_for_cb,
MUTTER_PLUGIN_SWITCH_WORKSPACE);
}
@ -219,9 +219,9 @@ switch_workspace (const GList **actors, gint from, gint to,
ClutterActor *stage;
int screen_width, screen_height;
stage = meta_comp_clutter_plugin_get_stage (plugin);
stage = mutter_plugin_get_stage (plugin);
meta_comp_clutter_plugin_query_screen_size (plugin,
mutter_plugin_query_screen_size (plugin,
&screen_width,
&screen_height);
clutter_actor_set_anchor_point (workspace1,
@ -238,7 +238,7 @@ switch_workspace (const GList **actors, gint from, gint to,
if (from == to)
{
meta_comp_clutter_plugin_effect_completed (&mutter_plugin, NULL,
mutter_plugin_effect_completed (&mutter_plugin, NULL,
MUTTER_PLUGIN_SWITCH_WORKSPACE);
return;
}
@ -331,7 +331,7 @@ on_minimize_effect_complete (ClutterActor *actor, gpointer data)
/* Decrease the running effect counter */
mutter_plugin.running--;
/* Now notify the manager that we are done with this effect */
meta_comp_clutter_plugin_effect_completed (&mutter_plugin, mc_window,
mutter_plugin_effect_completed (&mutter_plugin, mc_window,
MUTTER_PLUGIN_MINIMIZE);
}
@ -368,7 +368,7 @@ minimize (MutterWindow *mc_window)
NULL);
}
else
meta_comp_clutter_plugin_effect_completed (&mutter_plugin, mc_window,
mutter_plugin_effect_completed (&mutter_plugin, mc_window,
MUTTER_PLUGIN_MINIMIZE);
}
@ -396,7 +396,7 @@ on_maximize_effect_complete (ClutterActor *actor, gpointer data)
mutter_plugin.running--;
/* Now notify the manager that we are done with this effect */
meta_comp_clutter_plugin_effect_completed (&mutter_plugin, mc_window,
mutter_plugin_effect_completed (&mutter_plugin, mc_window,
MUTTER_PLUGIN_MAXIMIZE);
}
@ -459,7 +459,7 @@ maximize (MutterWindow *mc_window,
return;
}
meta_comp_clutter_plugin_effect_completed (&mutter_plugin, mc_window,
mutter_plugin_effect_completed (&mutter_plugin, mc_window,
MUTTER_PLUGIN_MAXIMIZE);
}
@ -482,7 +482,7 @@ unmaximize (MutterWindow *mc_window,
}
/* Do this conditionally, if the effect requires completion callback. */
meta_comp_clutter_plugin_effect_completed (&mutter_plugin, mc_window,
mutter_plugin_effect_completed (&mutter_plugin, mc_window,
MUTTER_PLUGIN_UNMAXIMIZE);
}
@ -504,7 +504,7 @@ on_map_effect_complete (ClutterActor *actor, gpointer data)
mutter_plugin.running--;
/* Now notify the manager that we are done with this effect */
meta_comp_clutter_plugin_effect_completed (&mutter_plugin, mc_window,
mutter_plugin_effect_completed (&mutter_plugin, mc_window,
MUTTER_PLUGIN_MAP);
}
@ -544,7 +544,7 @@ map (MutterWindow *mc_window)
}
else
meta_comp_clutter_plugin_effect_completed (&mutter_plugin, mc_window,
mutter_plugin_effect_completed (&mutter_plugin, mc_window,
MUTTER_PLUGIN_MAP);
}
@ -564,7 +564,7 @@ on_destroy_effect_complete (ClutterActor *actor, gpointer data)
mutter_plugin.running--;
meta_comp_clutter_plugin_effect_completed (plugin, mc_window,
mutter_plugin_effect_completed (plugin, mc_window,
MUTTER_PLUGIN_DESTROY);
}
@ -597,7 +597,7 @@ destroy (MutterWindow *mc_window)
NULL);
}
else
meta_comp_clutter_plugin_effect_completed (&mutter_plugin, mc_window,
mutter_plugin_effect_completed (&mutter_plugin, mc_window,
MUTTER_PLUGIN_DESTROY);
}

View File

@ -29,6 +29,7 @@
#define N_(x) x
#include <clutter/clutter.h>
#include <clutter/x11/clutter-x11.h>
#include <gmodule.h>
#include <string.h>
@ -37,12 +38,16 @@
#define MAXIMIZE_TIMEOUT 250
#define MAP_TIMEOUT 250
#define SWITCH_TIMEOUT 500
#define PANEL_SLIDE_TIMEOUT 250; \
#define PANEL_SLIDE_THRESHOLD 2
#define PANEL_HEIGHT 40
#define ACTOR_DATA_KEY "MCCP-Moblin-actor-data"
typedef struct PluginPrivate PluginPrivate;
typedef struct ActorPrivate ActorPrivate;
static gboolean do_init (const char *params);
static void minimize (MutterWindow *actor);
static void map (MutterWindow *actor);
static void destroy (MutterWindow *actor);
@ -56,14 +61,16 @@ static void switch_workspace (const GList **actors, gint from, gint to,
static void kill_effect (MutterWindow *actor, gulong event);
static gboolean reload (void);
static gboolean xevent_filter (XEvent *xev);
static gboolean reload (const char *params);
/*
* First we create the header struct and initialize its static members.
* Any dynamically allocated data should be initialized in the
* init () function below.
*/
MutterPlugin MUTTER_PLUGIN_STRUCT =
G_MODULE_EXPORT MutterPlugin mutter_plugin =
{
/*
* These are predefined values; do not modify.
@ -74,15 +81,17 @@ MutterPlugin MUTTER_PLUGIN_STRUCT =
.version_api = METACITY_CLUTTER_PLUGIN_API_VERSION,
/* Human readable name (for use in UI) */
.name = "Default Effects",
.name = "Experimental effects",
/* Plugin load time initialiser */
.do_init = do_init,
/* Which types of events this plugin supports */
.features = MUTTER_PLUGIN_MINIMIZE |
MUTTER_PLUGIN_DESTROY |
MUTTER_PLUGIN_MAP |
MUTTER_PLUGIN_MAXIMIZE |
MUTTER_PLUGIN_UNMAXIMIZE |
MUTTER_PLUGIN_SWITCH_WORKSPACE,
MUTTER_PLUGIN_UNMAXIMIZE,
/* And the corresponding handlers */
@ -92,8 +101,8 @@ MutterPlugin MUTTER_PLUGIN_STRUCT =
.maximize = maximize,
.unmaximize = unmaximize,
.switch_workspace = switch_workspace,
.kill_effect = kill_effect,
.xevent_filter = xevent_filter,
/* The reload handler */
.reload = reload
@ -109,6 +118,7 @@ struct PluginPrivate
ClutterEffectTemplate *maximize_effect;
ClutterEffectTemplate *map_effect;
ClutterEffectTemplate *switch_workspace_effect;
ClutterEffectTemplate *panel_slide_effect;
/* Valid only when switch_workspace effect is in progress */
ClutterTimeline *tml_switch_workspace1;
@ -117,7 +127,12 @@ struct PluginPrivate
ClutterActor *desktop1;
ClutterActor *desktop2;
ClutterActor *panel;
gboolean debug_mode : 1;
gboolean panel_out : 1;
gboolean panel_out_in_progress : 1;
gboolean panel_back_in_progress : 1;
};
/*
@ -157,7 +172,7 @@ static inline
MutterPlugin *
get_plugin ()
{
return &MUTTER_PLUGIN_STRUCT;
return &mutter_plugin;
}
static void
@ -192,7 +207,7 @@ on_switch_workspace_effect_complete (ClutterActor *group, gpointer data)
ppriv->desktop1 = NULL;
ppriv->desktop2 = NULL;
meta_comp_clutter_plugin_effect_completed (plugin, actor_for_cb,
mutter_plugin_effect_completed (plugin, actor_for_cb,
MUTTER_PLUGIN_SWITCH_WORKSPACE);
}
@ -207,16 +222,17 @@ switch_workspace (const GList **actors, gint from, gint to,
ClutterActor *group1 = clutter_group_new ();
ClutterActor *group2 = clutter_group_new ();
ClutterActor *stage;
gint screen_width;
gint screen_height;
stage = meta_comp_clutter_plugin_get_stage (plugin);
stage = mutter_plugin_get_stage (plugin);
mutter_plugin_query_screen_size (plugin, &screen_width, &screen_height);
#if 1
clutter_actor_set_anchor_point (group2,
plugin->screen_width,
plugin->screen_height);
clutter_actor_set_position (group2,
plugin->screen_width,
plugin->screen_height);
clutter_actor_set_anchor_point (group2, screen_width, screen_height);
clutter_actor_set_position (group2, screen_width, screen_height);
#endif
clutter_actor_set_scale (group2, 0.0, 0.0);
@ -226,7 +242,7 @@ switch_workspace (const GList **actors, gint from, gint to,
if (from == to)
{
meta_comp_clutter_plugin_effect_completed (plugin, NULL,
mutter_plugin_effect_completed (plugin, NULL,
MUTTER_PLUGIN_SWITCH_WORKSPACE);
return;
}
@ -242,7 +258,7 @@ switch_workspace (const GList **actors, gint from, gint to,
ClutterActor *a = CLUTTER_ACTOR (mcw);
gint workspace;
workspace = meta_comp_window_get_workspace (mcw);
workspace = mutter_window_get_workspace (mcw);
if (workspace == to || workspace == from)
{
@ -318,7 +334,7 @@ on_minimize_effect_complete (ClutterActor *actor, gpointer data)
plugin->running--;
/* Now notify the manager that we are done with this effect */
meta_comp_clutter_plugin_effect_completed (plugin, mcw,
mutter_plugin_effect_completed (plugin, mcw,
MUTTER_PLUGIN_MINIMIZE);
}
@ -332,12 +348,12 @@ minimize (MutterWindow *mcw)
{
MutterPlugin *plugin = get_plugin ();
PluginPrivate *priv = plugin->plugin_private;
MutterWindowType type;
MetaCompWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (mcw);
type = meta_comp_window_get_window_type (mcw);
type = mutter_window_get_window_type (mcw);
if (type == MUTTER_WINDOW_NORMAL)
if (type == META_COMP_WINDOW_NORMAL)
{
ActorPrivate *apriv = get_actor_private (mcw);
@ -346,7 +362,7 @@ minimize (MutterWindow *mcw)
clutter_actor_move_anchor_point_from_gravity (actor,
CLUTTER_GRAVITY_CENTER);
MUTTER_PLUGIN_STRUCT.running++;
plugin->running++;
apriv->tml_minimize = clutter_effect_scale (priv->minimize_effect,
actor,
@ -357,7 +373,7 @@ minimize (MutterWindow *mcw)
NULL);
}
else
meta_comp_clutter_plugin_effect_completed (plugin, mcw,
mutter_plugin_effect_completed (plugin, mcw,
MUTTER_PLUGIN_MINIMIZE);
}
@ -385,7 +401,7 @@ on_maximize_effect_complete (ClutterActor *actor, gpointer data)
plugin->running--;
/* Now notify the manager that we are done with this effect */
meta_comp_clutter_plugin_effect_completed (plugin, mcw,
mutter_plugin_effect_completed (plugin, mcw,
MUTTER_PLUGIN_MAXIMIZE);
}
@ -403,7 +419,7 @@ maximize (MutterWindow *mcw,
{
MutterPlugin *plugin = get_plugin ();
PluginPrivate *priv = plugin->plugin_private;
MutterWindowType type;
MetaCompWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (mcw);
gdouble scale_x = 1.0;
@ -411,9 +427,9 @@ maximize (MutterWindow *mcw,
gint anchor_x = 0;
gint anchor_y = 0;
type = meta_comp_window_get_window_type (mcw);
type = mutter_window_get_window_type (mcw);
if (type == MUTTER_WINDOW_NORMAL)
if (type == META_COMP_WINDOW_NORMAL)
{
ActorPrivate *apriv = get_actor_private (mcw);
guint width, height;
@ -449,7 +465,7 @@ maximize (MutterWindow *mcw,
return;
}
meta_comp_clutter_plugin_effect_completed (plugin, mcw,
mutter_plugin_effect_completed (plugin, mcw,
MUTTER_PLUGIN_MAXIMIZE);
}
@ -463,11 +479,11 @@ unmaximize (MutterWindow *mcw,
gint end_x, gint end_y, gint end_width, gint end_height)
{
MutterPlugin *plugin = get_plugin ();
MutterWindowType type;
MetaCompWindowType type;
type = meta_comp_window_get_window_type (mcw);
type = mutter_window_get_window_type (mcw);
if (type == MUTTER_WINDOW_NORMAL)
if (type == META_COMP_WINDOW_NORMAL)
{
ActorPrivate *apriv = get_actor_private (mcw);
@ -475,7 +491,7 @@ unmaximize (MutterWindow *mcw,
}
/* Do this conditionally, if the effect requires completion callback. */
meta_comp_clutter_plugin_effect_completed (plugin, mcw,
mutter_plugin_effect_completed (plugin, mcw,
MUTTER_PLUGIN_UNMAXIMIZE);
}
@ -498,7 +514,7 @@ on_map_effect_complete (ClutterActor *actor, gpointer data)
plugin->running--;
/* Now notify the manager that we are done with this effect */
meta_comp_clutter_plugin_effect_completed (plugin, mcw,
mutter_plugin_effect_completed (plugin, mcw,
MUTTER_PLUGIN_MAP);
}
@ -511,19 +527,19 @@ map (MutterWindow *mcw)
{
MutterPlugin *plugin = get_plugin ();
PluginPrivate *priv = plugin->plugin_private;
MutterWindowType type;
MetaCompWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (mcw);
type = meta_comp_window_get_window_type (mcw);
type = mutter_window_get_window_type (mcw);
if (type == MUTTER_WINDOW_NORMAL)
if (type == META_COMP_WINDOW_NORMAL)
{
ActorPrivate *apriv = get_actor_private (mcw);
clutter_actor_move_anchor_point_from_gravity (actor,
CLUTTER_GRAVITY_CENTER);
MUTTER_PLUGIN_STRUCT.running++;
plugin->running++;
clutter_actor_set_scale (actor, 0.0, 0.0);
clutter_actor_show (actor);
@ -540,7 +556,7 @@ map (MutterWindow *mcw)
}
else
meta_comp_clutter_plugin_effect_completed (plugin, mcw,
mutter_plugin_effect_completed (plugin, mcw,
MUTTER_PLUGIN_MAP);
}
@ -560,7 +576,7 @@ on_destroy_effect_complete (ClutterActor *actor, gpointer data)
plugin->running--;
meta_comp_clutter_plugin_effect_completed (plugin, mcw,
mutter_plugin_effect_completed (plugin, mcw,
MUTTER_PLUGIN_DESTROY);
}
@ -572,12 +588,12 @@ destroy (MutterWindow *mcw)
{
MutterPlugin *plugin = get_plugin ();
PluginPrivate *priv = plugin->plugin_private;
MutterWindowType type;
MetaCompWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (mcw);
type = meta_comp_window_get_window_type (mcw);
type = mutter_window_get_window_type (mcw);
if (type == MUTTER_WINDOW_NORMAL)
if (type == META_COMP_WINDOW_NORMAL)
{
ActorPrivate *apriv = get_actor_private (mcw);
@ -595,10 +611,46 @@ destroy (MutterWindow *mcw)
NULL);
}
else
meta_comp_clutter_plugin_effect_completed (plugin, mcw,
mutter_plugin_effect_completed (plugin, mcw,
MUTTER_PLUGIN_DESTROY);
}
static void
on_panel_effect_complete (ClutterActor *panel, gpointer data)
{
gboolean reactive = GPOINTER_TO_INT (data);
MutterPlugin *plugin = get_plugin ();
PluginPrivate *priv = plugin->plugin_private;
gint screen_width, screen_height;
mutter_plugin_query_screen_size (plugin, &screen_width, &screen_height);
if (reactive)
{
priv->panel_out_in_progress = FALSE;
mutter_plugin_set_stage_reactive (plugin, reactive);
}
else
{
priv->panel_back_in_progress = FALSE;
mutter_plugin_set_stage_input_area (plugin, 0, 0,
screen_width, 1);
}
}
static gboolean
xevent_filter (XEvent *xev)
{
MutterPlugin *plugin = get_plugin ();
ClutterActor *stage;
stage = mutter_plugin_get_stage (plugin);
clutter_x11_handle_event (xev);
return FALSE;
}
static void
kill_effect (MutterWindow *mcw, gulong event)
{
@ -674,30 +726,100 @@ g_module_check_init (GModule *module)
}
#endif
static gboolean
stage_input_cb (ClutterActor *stage, ClutterEvent *event, gpointer data)
{
if (event->type == CLUTTER_MOTION)
{
ClutterMotionEvent *mev = (ClutterMotionEvent *) event;
MutterPlugin *plugin = get_plugin ();
PluginPrivate *priv = plugin->plugin_private;
if (priv->panel_out_in_progress || priv->panel_back_in_progress)
return FALSE;
if (priv->panel_out)
{
guint height = clutter_actor_get_height (priv->panel);
gint x = clutter_actor_get_x (priv->panel);
if (mev->y > (gint)height)
{
priv->panel_back_in_progress = TRUE;
clutter_effect_move (priv->panel_slide_effect,
priv->panel, x, -height,
on_panel_effect_complete,
GINT_TO_POINTER (FALSE));
priv->panel_out = FALSE;
}
return TRUE;
}
else if (mev->y < PANEL_SLIDE_THRESHOLD)
{
gint x = clutter_actor_get_x (priv->panel);
priv->panel_out_in_progress = TRUE;
clutter_effect_move (priv->panel_slide_effect,
priv->panel, x, 0,
on_panel_effect_complete,
GINT_TO_POINTER (TRUE));
priv->panel_out = TRUE;
return TRUE;
}
return FALSE;
}
return FALSE;
}
static ClutterActor *
make_panel (gint width)
{
ClutterActor *panel;
ClutterActor *background;
ClutterColor clr = {0xff, 0, 0, 0xff};
panel = clutter_group_new ();
/* FIME -- size and color */
background = clutter_rectangle_new_with_color (&clr);
clutter_container_add_actor (CLUTTER_CONTAINER (panel), background);
clutter_actor_set_size (background, width, PANEL_HEIGHT);
return panel;
}
/*
* Core of the plugin init function, called for initial initialization and
* by the reload() function. Returns TRUE on success.
*/
static gboolean
do_init ()
do_init (const char *params)
{
MutterPlugin *plugin = get_plugin ();
PluginPrivate *priv = g_new0 (PluginPrivate, 1);
const gchar *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;
guint panel_slide_timeout = PANEL_SLIDE_TIMEOUT;
const gchar *name;
ClutterActor *overlay;
ClutterActor *panel;
gint screen_width, screen_height;
plugin->plugin_private = priv;
name = plugin->name;
plugin->name = _(name);
params = plugin->params;
mutter_plugin_query_screen_size (plugin, &screen_width, &screen_height);
if (params)
{
@ -706,7 +828,7 @@ do_init ()
if (strstr (params, "debug"))
{
g_debug ("%s: Entering debug mode.",
MUTTER_PLUGIN_STRUCT.name);
plugin->name);
priv->debug_mode = TRUE;
@ -777,17 +899,35 @@ do_init ()
switch_timeout),
CLUTTER_ALPHA_SINE_INC);
return TRUE;
}
overlay = mutter_plugin_get_overlay_group (plugin);
MUTTER_PLUGIN_INIT_FUNC
{
return do_init ();
panel = priv->panel = make_panel (screen_width);
clutter_container_add_actor (CLUTTER_CONTAINER (overlay), panel);
priv->panel_slide_effect
= clutter_effect_template_new (clutter_timeline_new_for_duration (
panel_slide_timeout),
CLUTTER_ALPHA_SINE_INC);
clutter_actor_set_position (panel, 0,
-clutter_actor_get_height (panel));
g_signal_connect (mutter_plugin_get_stage (plugin),
"motion-event", G_CALLBACK (stage_input_cb), NULL);
mutter_plugin_set_stage_input_area (plugin, 0, 0, screen_width, 1);
clutter_set_motion_events_enabled (TRUE);
return TRUE;
}
static void
free_plugin_private (PluginPrivate *priv)
{
if (!priv)
return;
g_object_unref (priv->destroy_effect);
g_object_unref (priv->minimize_effect);
g_object_unref (priv->maximize_effect);
@ -795,7 +935,7 @@ free_plugin_private (PluginPrivate *priv)
g_free (priv);
MUTTER_PLUGIN_STRUCT.plugin_private = NULL;
get_plugin()->plugin_private = NULL;
}
/*
@ -803,13 +943,12 @@ free_plugin_private (PluginPrivate *priv)
* changed.
*/
static gboolean
reload ()
reload (const char *params)
{
PluginPrivate *priv;
MutterPlugin *plugin = get_plugin ();
PluginPrivate *priv = plugin->plugin_private;
priv = MUTTER_PLUGIN_STRUCT.plugin_private;
if (do_init ())
if (do_init (params))
{
/* Success; free the old private struct */
free_plugin_private (priv);
@ -818,7 +957,7 @@ reload ()
else
{
/* Fail -- fall back to the old private. */
MUTTER_PLUGIN_STRUCT.plugin_private = priv;
plugin->plugin_private = priv;
}
return FALSE;
@ -827,12 +966,10 @@ reload ()
/*
* GModule unload function -- do any cleanup required.
*/
void g_module_unload (GModule *module);
void g_module_unload (GModule *module)
G_MODULE_EXPORT void g_module_unload (GModule *module);
G_MODULE_EXPORT void g_module_unload (GModule *module)
{
PluginPrivate *priv;
priv = MUTTER_PLUGIN_STRUCT.plugin_private;
PluginPrivate *priv = get_plugin()->plugin_private;
free_plugin_private (priv);
}

View File

@ -0,0 +1,255 @@
/* -*- 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 META_COMPOSITOR_CLUTTER_PLUGIN_H_
#define META_COMPOSITOR_CLUTTER_PLUGIN_H_
#include "types.h"
#include "config.h"
#include "compositor.h"
#include "compositor-clutter.h"
#include <clutter/clutter.h>
/*
* This file defines the plugin API.
*
* Effects plugin is shared library loaded via dlopen(); 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 MetaCompositorClutterPlugin struct.
*/
/*
* Alias MetaRectangle to PluginWorkspaceRectangle in anticipation of
* making this file metacity-independent (we want the plugins to be portable
* between different WMs.
*/
typedef MetaRectangle PluginWorkspaceRectangle;
/*
* The name of the header struct; use as:
*
* MetaCompositorClutterPlugin META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT =
* {
* ...
* };
*
* See clutter-plugins/simple.c for example code.
*/
#define META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT MCCPS__
/*
* Definition for the plugin init function; use as:
*
* META_COMPOSITOR_CLUTTER_PLUGIN_INIT_FUNC
* {
* init code ...
* }
*
* See clutter-plugins/simple.c for example code.
*/
#define META_COMPOSITOR_CLUTTER_PLUGIN_INIT_FUNC \
gboolean mccp_init__(void); \
gboolean mccp_init__()
/* Private; must match the above */
#define META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT_NAME "MCCPS__"
#define META_COMPOSITOR_CLUTTER_PLUGIN_INIT_FUNC_NAME "mccp_init__"
typedef struct MetaCompositorClutterPlugin MetaCompositorClutterPlugin;
/*
* Feature flags: identify events that the plugin can handle; a plugin can
* handle one or more events.
*/
#define META_COMPOSITOR_CLUTTER_PLUGIN_MINIMIZE 0x00000001UL
#define META_COMPOSITOR_CLUTTER_PLUGIN_MAXIMIZE 0x00000002UL
#define META_COMPOSITOR_CLUTTER_PLUGIN_UNMAXIMIZE 0x00000004UL
#define META_COMPOSITOR_CLUTTER_PLUGIN_MAP 0x00000008UL
#define META_COMPOSITOR_CLUTTER_PLUGIN_DESTROY 0x00000010UL
#define META_COMPOSITOR_CLUTTER_PLUGIN_SWITCH_WORKSPACE 0x00000020UL
#define META_COMPOSITOR_CLUTTER_PLUGIN_ALL_EFFECTS 0xffffffffUL
struct MetaCompositorClutterPlugin
{
/*
* Version information; the first three numbers match the Metacity version
* with which the plugin was compiled (see clutter-plugins/simple.c for sample
* code).
*/
guint version_major;
guint version_minor;
guint version_micro;
/*
* 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
* the one used by it (see clutter-plugins/simple.c for sample code).
*/
guint version_api;
#ifndef META_COMPOSITOR_CLUTTER_BUILDING_PLUGIN
const
#endif
gchar *name; /* Human-readable name for UI */
gulong features; /* or-ed feature flags */
/*
* 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) (MetaCompWindow *actor);
void (*maximize) (MetaCompWindow *actor,
gint x,
gint y,
gint width,
gint height);
void (*unmaximize) (MetaCompWindow *actor,
gint x,
gint y,
gint width,
gint height);
void (*map) (MetaCompWindow *actor);
void (*destroy) (MetaCompWindow *actor);
/*
* Each actor in the list has a workspace number attached to it using
* g_object_set_data() with key META_COMPOSITOR_CLUTTER_PLUGIN_WORKSPACE_KEY;
* workspace < 0 indicates the window is sticky (i.e., on all desktops).
*/
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) (MetaCompWindow *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) (void);
/* General XEvent filter. This is fired *before* metacity itself handles
* an event. Return TRUE to block any further processing.
*/
gboolean (*xevent_filter) (XEvent *event);
#ifdef META_COMPOSITOR_CLUTTER_BUILDING_PLUGIN
const
#endif
gchar *params; /* String containing additional parameters for the plugin;
* this is specified after the pluing 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
*/
gint screen_width;
gint screen_height;
GList *work_areas; /* List of PluginWorkspaceRectangles defining the
* geometry of individual workspaces.
*/
gint running; /* Plugin must increase this counter for each effect it starts
* decrease it again once the effect finishes.
*/
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;
};
void
meta_comp_clutter_plugin_effect_completed (MetaCompositorClutterPlugin *plugin,
MetaCompWindow *actor,
unsigned long event);
ClutterActor *
meta_comp_clutter_plugin_get_overlay_group (MetaCompositorClutterPlugin *plugin);
ClutterActor *
meta_comp_clutter_plugin_get_stage (MetaCompositorClutterPlugin *plugin);
void
meta_comp_clutter_plugin_set_stage_reactive (MetaCompositorClutterPlugin *plugin,
gboolean reactive);
void
meta_comp_clutter_plugin_set_stage_input_area (MetaCompositorClutterPlugin *plugin,
gint x, gint y, gint width, gint height);
#endif

View File

@ -0,0 +1,76 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2008 Matthew Allum
* Copyright (C) 2007 Iain Holmes
* Based on xcompmgr - (c) 2003 Keith Packard
* xfwm4 - (c) 2005-2007 Olivier Fourdan
*
* 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 META_COMPOSITOR_CLUTTER_H_
#define META_COMPOSITOR_CLUTTER_H_
#include <clutter/clutter.h>
#include "types.h"
/*
* MetaCompWindow object (ClutterGroup sub-class)
*/
#define META_TYPE_COMP_WINDOW (meta_comp_window_get_type ())
#define META_COMP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_COMP_WINDOW, MetaCompWindow))
#define META_COMP_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_COMP_WINDOW, MetaCompWindowClass))
#define IS_META_COMP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_COMP_WINDOW_TYPE))
#define META_IS_COMP_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_COMP_WINDOW))
#define META_COMP_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_COMP_WINDOW, MetaCompWindowClass))
typedef struct _MetaCompWindow MetaCompWindow;
typedef struct _MetaCompWindowClass MetaCompWindowClass;
typedef struct _MetaCompWindowPrivate MetaCompWindowPrivate;
struct _MetaCompWindowClass
{
ClutterGroupClass parent_class;
};
struct _MetaCompWindow
{
ClutterGroup parent;
MetaCompWindowPrivate *priv;
};
GType meta_comp_window_get_type (void);
Window meta_comp_window_get_x_window (MetaCompWindow *mcw);
MetaCompWindowType meta_comp_window_get_window_type (MetaCompWindow *mcw);
gint meta_comp_window_get_workspace (MetaCompWindow *mcw);
/* Compositor API */
MetaCompositor *meta_compositor_clutter_new (MetaDisplay *display);
void meta_compositor_clutter_window_effect_completed (MetaCompWindow *actor, gulong event);
ClutterActor * meta_compositor_clutter_get_stage_for_screen (MetaScreen *screen);
ClutterActor * meta_compositor_clutter_get_overlay_group_for_screen (MetaScreen *screen);
Window meta_compositor_clutter_get_overlay_window (MetaScreen *screen);
#endif

View File

@ -69,5 +69,6 @@ void mutter_window_effect_completed (MutterWindow *actor, gulong event);
ClutterActor * mutter_get_stage_for_screen (MetaScreen *screen);
ClutterActor * mutter_get_overlay_group_for_screen (MetaScreen *screen);
Window mutter_get_overlay_window (MetaScreen *screen);
#endif

View File

@ -202,19 +202,33 @@ struct MutterPlugin
};
void
meta_comp_clutter_plugin_effect_completed (MutterPlugin *plugin,
mutter_plugin_effect_completed (MutterPlugin *plugin,
MutterWindow *actor,
unsigned long event);
ClutterActor *
meta_comp_clutter_plugin_get_overlay_group (MutterPlugin *plugin);
mutter_plugin_get_overlay_group (MutterPlugin *plugin);
ClutterActor *
meta_comp_clutter_plugin_get_stage (MutterPlugin *plugin);
mutter_plugin_get_stage (MutterPlugin *plugin);
void
meta_comp_clutter_plugin_query_screen_size (MutterPlugin *plugin,
mutter_plugin_query_screen_size (MutterPlugin *plugin,
int *width,
int *height);
ClutterActor *
mutter_plugin_get_overlay_group (MutterPlugin *plugin);
ClutterActor *
mutter_plugin_get_stage (MutterPlugin *plugin);
void
mutter_plugin_set_stage_reactive (MutterPlugin *plugin,
gboolean reactive);
void
mutter_plugin_set_stage_input_area (MutterPlugin *plugin,
gint x, gint y, gint width, gint height);
#endif /* MUTTER_PLUGIN_H_ */