Basic plugin infastructure and a sample simple plugin.
This commit is contained in:
parent
d509097967
commit
9b3a0d1ad8
60
.gitignore
vendored
Normal file
60
.gitignore
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
Makefile.in.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
compile
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
.deps
|
||||
src/metacity-wm.desktop
|
||||
*.o
|
||||
*.a
|
||||
*.lo
|
||||
*.la
|
||||
.libs
|
||||
*.swp
|
||||
tidy-enum-types.[ch]
|
||||
tidy-marshal.[ch]
|
||||
stamp-tidy-enum-types.h
|
||||
stamp-tidy-marshal.h
|
||||
stamp-h1
|
||||
*.gmo
|
||||
*.make
|
||||
*~
|
||||
stamp-it
|
||||
.intltool-merge-cache
|
||||
POTFILES
|
||||
50-metacity-desktop-key.xml
|
||||
50-metacity-key.xml
|
||||
inlinepixbufs.h
|
||||
libmetacity-private.pc
|
||||
metacity
|
||||
metacity-dialog
|
||||
metacity-theme-viewer
|
||||
metacity.desktop
|
||||
metacity.schemas
|
||||
testasyncgetprop
|
||||
testboxes
|
||||
testgradient
|
||||
metacity-grayscale
|
||||
metacity-mag
|
||||
metacity-message
|
||||
metacity-window-demo
|
||||
focus-window
|
||||
test-gravity
|
||||
test-resizing
|
||||
test-size-hints
|
||||
wm-tester
|
||||
INSTALL
|
||||
mkinstalldirs
|
14
configure.in
14
configure.in
@ -8,6 +8,9 @@ m4_define([metacity_micro_version], [2])
|
||||
|
||||
m4_define([metacity_version],
|
||||
[metacity_major_version.metacity_minor_version.metacity_micro_version])
|
||||
|
||||
m4_define([metacity_clutter_plugin_api_version], [1])
|
||||
|
||||
AC_INIT([metacity], [metacity_version],
|
||||
[http://bugzilla.gnome.org/enter_bug.cgi?product=metacity])
|
||||
|
||||
@ -17,6 +20,15 @@ AC_CONFIG_HEADERS(config.h)
|
||||
AM_INIT_AUTOMAKE
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
METACITY_MAJOR_VERSION=metacity_major_version
|
||||
METACITY_MINOR_VERSION=metacity_minor_version
|
||||
METACITY_MICRO_VERSION=metacity_micro_version
|
||||
METACITY_CLUTTER_PLUGIN_API_VERSION=metacity_clutter_plugin_api_version
|
||||
AC_SUBST(METACITY_MAJOR_VERSION)
|
||||
AC_SUBST(METACITY_MINOR_VERSION)
|
||||
AC_SUBST(METACITY_MICRO_VERSION)
|
||||
AC_SUBST(METACITY_CLUTTER_PLUGIN_API_VERSION)
|
||||
|
||||
# Honor aclocal flags
|
||||
AC_SUBST(ACLOCAL_AMFLAGS, "\${ACLOCAL_FLAGS}")
|
||||
|
||||
@ -290,6 +302,7 @@ fi
|
||||
if test x$have_clutter = xyes; then
|
||||
CLUTTER_PACKAGE=clutter-0.8
|
||||
METACITY_PC_MODULES="$METACITY_PC_MODULES $CLUTTER_PACKAGE "
|
||||
PKG_CHECK_MODULES(CLUTTER, $CLUTTER_PACKAGE)
|
||||
AC_DEFINE(WITH_CLUTTER, , [Building with Clutter compositor])
|
||||
fi
|
||||
|
||||
@ -509,6 +522,7 @@ src/wm-tester/Makefile
|
||||
src/libmetacity-private.pc
|
||||
src/tools/Makefile
|
||||
src/themes/Makefile
|
||||
src/compositor/clutter-plugins/Makefile
|
||||
po/Makefile.in
|
||||
])
|
||||
|
||||
|
@ -2,7 +2,11 @@ lib_LTLIBRARIES = libmetacity-private.la
|
||||
|
||||
SUBDIRS=wm-tester tools themes
|
||||
|
||||
INCLUDES=@METACITY_CFLAGS@ -I $(srcdir)/include -DMETACITY_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMETACITY_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" -DMETACITY_PKGDATADIR=\"$(pkgdatadir)\" -DMETACITY_DATADIR=\"$(datadir)\" -DG_LOG_DOMAIN=\"metacity\" -DSN_API_NOT_YET_FROZEN=1
|
||||
if WITH_CLUTTER
|
||||
SUBDIRS += compositor/clutter-plugins
|
||||
endif
|
||||
|
||||
INCLUDES=@METACITY_CFLAGS@ -I $(srcdir)/include -DMETACITY_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMETACITY_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" -DMETACITY_PKGDATADIR=\"$(pkgdatadir)\" -DMETACITY_DATADIR=\"$(datadir)\" -DG_LOG_DOMAIN=\"metacity\" -DSN_API_NOT_YET_FROZEN=1 -DMETACITY_MAJOR_VERSION=$(METACITY_MAJOR_VERSION) -DMETACITY_MINOR_VERSION=$(METACITY_MINOR_VERSION) -DMETACITY_MICRO_VERSION=$(METACITY_MICRO_VERSION) -DMETACITY_CLUTTER_PLUGIN_API_VERSION=$(METACITY_CLUTTER_PLUGIN_API_VERSION) -DMETACITY_PKGLIBDIR=\"$(pkglibdir)\"
|
||||
|
||||
metacity_SOURCES= \
|
||||
core/async-getprop.c \
|
||||
@ -99,8 +103,11 @@ metacity_SOURCES= \
|
||||
ui/ui.c
|
||||
|
||||
if WITH_CLUTTER
|
||||
metacity_SOURCES += compositor/compositor-clutter.c \
|
||||
compositor/compositor-clutter.h
|
||||
metacity_SOURCES += compositor/compositor-clutter.c \
|
||||
compositor/compositor-clutter.h \
|
||||
include/compositor-clutter-plugin.h \
|
||||
compositor/compositor-clutter-plugin-manager.c \
|
||||
compositor/compositor-clutter-plugin-manager.h
|
||||
endif
|
||||
|
||||
# by setting libmetacity_private_la_CFLAGS, the files shared with
|
||||
|
21
src/compositor/clutter-plugins/Makefile.am
Normal file
21
src/compositor/clutter-plugins/Makefile.am
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
pkglibdir=$(libdir)/@PACKAGE@/plugins/clutter
|
||||
|
||||
if WITH_CLUTTER
|
||||
|
||||
INCLUDES=@METACITY_CFLAGS@ -I $(top_srcdir)/src/include -DMETACITY_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMETACITY_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" -DMETACITY_PKGDATADIR=\"$(pkgdatadir)\" -DMETACITY_DATADIR=\"$(datadir)\" -DG_LOG_DOMAIN=\"metacity\" -DSN_API_NOT_YET_FROZEN=1 -DMETACITY_MAJOR_VERSION=$(METACITY_MAJOR_VERSION) -DMETACITY_MINOR_VERSION=$(METACITY_MINOR_VERSION) -DMETACITY_MICRO_VERSION=$(METACITY_MICRO_VERSION) -DMETACITY_CLUTTER_PLUGIN_API_VERSION=$(METACITY_CLUTTER_PLUGIN_API_VERSION) -DMETACITY_PKGLIBDIR=\"$(pkglibdir)\"
|
||||
|
||||
simple_la_CFLAGS = -fPIC
|
||||
simple_la_SOURCES = simple.c
|
||||
simple_la_LDFLAGS = -module -avoid-version
|
||||
simple_la_LIBADD = @CLUTTER_LIBS@
|
||||
pkglib_LTLIBRARIES = simple.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).
|
||||
install-exec-hook:
|
||||
rm $(pkglibdir)/*.a
|
||||
rm $(pkglibdir)/*.la
|
||||
|
||||
endif
|
41
src/compositor/clutter-plugins/README
Normal file
41
src/compositor/clutter-plugins/README
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
Plugins implement effects associated with WM events, such as window map,
|
||||
minimizing, maximizing, unmaximizing, destruction and workspace switching. The
|
||||
plugin API is documented in src/include/compositor-clutter-plugin.h; in
|
||||
addition the simple plugin can be used as a reference implementation.
|
||||
|
||||
The API is intended to be generic, exposing no implementation details of the WM
|
||||
to the plugins; this will facilitate reuse without modification with another WM
|
||||
(there are plans to use the same plugin API with Matchbox 2).
|
||||
|
||||
Multiple plugins can implement the same effect and be loaded at the same time;
|
||||
however, stacking arbitrary effects in this way might not work as expected;
|
||||
this is particularly true of more complex effects, such as those for workspace
|
||||
switching.
|
||||
|
||||
Plugins are installed in ${prefix}/lib/metacity/plugins/clutter; from there the
|
||||
WM will load plugins listed in the clutter_plugins key in the Metacity gconf
|
||||
general preferences group. Each entry in preferences has the format
|
||||
|
||||
'name: optional parameters'
|
||||
|
||||
where 'name' is the name of the library without the .so suffix.
|
||||
|
||||
As noted above, additional parameters can be passed to the plugin via the
|
||||
preference key. In such case, the plugin name is immediately followed by a
|
||||
colon, separating it from the parameters. Two common parameters should be
|
||||
handled by all plugins:
|
||||
|
||||
'debug' indicates that the plugin is run in a debug mode (what exactly that
|
||||
means is left to the plugin to determine).
|
||||
|
||||
'disable' parameter indicates which effects within the plugin should be
|
||||
disabled; the format of the disable parameter is
|
||||
|
||||
'disable: effect1[, effect2];'
|
||||
|
||||
where effect1, etc., matches the effects listed in the
|
||||
compositor-clutter-plugin.h file (currently one of 'map', 'destroy',
|
||||
'maximize', 'unmaximize', 'switch-workspace'). Example 'disable:
|
||||
minimize, maximize;'.
|
||||
|
811
src/compositor/clutter-plugins/simple.c
Normal file
811
src/compositor/clutter-plugins/simple.c
Normal file
@ -0,0 +1,811 @@
|
||||
/* -*- 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.
|
||||
*/
|
||||
|
||||
#define META_COMPOSITOR_CLUTTER_BUILDING_PLUGIN 1
|
||||
#include "compositor-clutter-plugin.h"
|
||||
|
||||
#include <libintl.h>
|
||||
#define _(x) dgettext (GETTEXT_PACKAGE, x)
|
||||
#define N_(x) x
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <gmodule.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DESTROY_TIMEOUT 600
|
||||
#define MINIMIZE_TIMEOUT 600
|
||||
#define MAXIMIZE_TIMEOUT 600
|
||||
#define MAP_TIMEOUT 600
|
||||
#define SWITCH_TIMEOUT 1000
|
||||
|
||||
#define ACTOR_DATA_KEY "MCCP-Simple-actor-data"
|
||||
|
||||
typedef struct PluginPrivate PluginPrivate;
|
||||
typedef struct ActorPrivate ActorPrivate;
|
||||
|
||||
static void minimize (ClutterActor *actor, MetaCompWindowType type,
|
||||
gint workspace);
|
||||
static void map (ClutterActor *actor, MetaCompWindowType type,
|
||||
gint workspace);
|
||||
static void destroy (ClutterActor *actor, MetaCompWindowType type,
|
||||
gint workspace);
|
||||
static void maximize (ClutterActor *actor, MetaCompWindowType type,
|
||||
gint workspace,
|
||||
gint x, gint y, gint width, gint height);
|
||||
static void unmaximize (ClutterActor *actor, MetaCompWindowType type,
|
||||
gint workspace,
|
||||
gint x, gint y, gint width, gint height);
|
||||
|
||||
static void switch_workspace (const GList **actors, gint from, gint to);
|
||||
|
||||
static void kill_effect (ClutterActor *actor, gulong event);
|
||||
|
||||
static gboolean reload (void);
|
||||
|
||||
/*
|
||||
* First we create the header struct and initialize its static members.
|
||||
* Any dynamically allocated data should be initialized in the
|
||||
* init () function below.
|
||||
*/
|
||||
MetaCompositorClutterPlugin META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT =
|
||||
{
|
||||
/*
|
||||
* These are predefined values; do not modify.
|
||||
*/
|
||||
.version_major = METACITY_MAJOR_VERSION,
|
||||
.version_minor = METACITY_MINOR_VERSION,
|
||||
.version_micro = METACITY_MICRO_VERSION,
|
||||
.version_api = METACITY_CLUTTER_PLUGIN_API_VERSION,
|
||||
|
||||
/* Human readable name (for use in UI) */
|
||||
.name = "Simple Effects",
|
||||
|
||||
/* Which types of events this plugin supports */
|
||||
.features = META_COMPOSITOR_CLUTTER_PLUGIN_MINIMIZE |
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_DESTROY |
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_MAP |
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_MAXIMIZE |
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_UNMAXIMIZE |
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_SWITCH_WORKSPACE,
|
||||
|
||||
|
||||
/* And the corresponding handlers */
|
||||
.minimize = minimize,
|
||||
.destroy = destroy,
|
||||
.map = map,
|
||||
.maximize = maximize,
|
||||
.unmaximize = unmaximize,
|
||||
.switch_workspace = switch_workspace,
|
||||
|
||||
.kill_effect = kill_effect,
|
||||
|
||||
/* The reload handler */
|
||||
.reload = reload
|
||||
};
|
||||
|
||||
/*
|
||||
* Plugin private data that we store in the .plugin_private member.
|
||||
*/
|
||||
struct PluginPrivate
|
||||
{
|
||||
ClutterEffectTemplate *destroy_effect;
|
||||
ClutterEffectTemplate *minimize_effect;
|
||||
ClutterEffectTemplate *maximize_effect;
|
||||
ClutterEffectTemplate *map_effect;
|
||||
ClutterEffectTemplate *switch_workspace_effect;
|
||||
|
||||
/* Valid only when switch_workspace effect is in progress */
|
||||
ClutterTimeline *tml_switch_workspace1;
|
||||
ClutterTimeline *tml_switch_workspace2;
|
||||
GList **actors;
|
||||
ClutterActor *desktop1;
|
||||
ClutterActor *desktop2;
|
||||
|
||||
gboolean debug_mode : 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Per actor private data we attach to each actor.
|
||||
*/
|
||||
struct ActorPrivate
|
||||
{
|
||||
ClutterActor *orig_parent;
|
||||
|
||||
gint workspace;
|
||||
|
||||
ClutterTimeline *tml_minimize;
|
||||
ClutterTimeline *tml_maximize;
|
||||
ClutterTimeline *tml_destroy;
|
||||
ClutterTimeline *tml_map;
|
||||
|
||||
gboolean is_minimized : 1;
|
||||
gboolean is_maximized : 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Actor private data accessor
|
||||
*/
|
||||
static ActorPrivate *
|
||||
get_actor_private (ClutterActor *actor)
|
||||
{
|
||||
ActorPrivate * priv = g_object_get_data (G_OBJECT (actor), ACTOR_DATA_KEY);
|
||||
|
||||
if (!priv)
|
||||
{
|
||||
priv = g_new0 (ActorPrivate, 1);
|
||||
g_object_set_data_full (G_OBJECT (actor), ACTOR_DATA_KEY, priv, g_free);
|
||||
}
|
||||
|
||||
return priv;
|
||||
}
|
||||
|
||||
static void
|
||||
on_switch_workspace_effect_complete (ClutterActor *group, gpointer data)
|
||||
{
|
||||
MetaCompositorClutterPlugin *plugin = &META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT;
|
||||
PluginPrivate *ppriv = plugin->plugin_private;
|
||||
GList *l = *((GList**)data);
|
||||
ClutterActor *actor_for_cb = l->data;
|
||||
|
||||
while (l)
|
||||
{
|
||||
ClutterActor *a = l->data;
|
||||
ActorPrivate *priv = get_actor_private (a);
|
||||
|
||||
if (priv->orig_parent)
|
||||
{
|
||||
clutter_actor_reparent (a, priv->orig_parent);
|
||||
priv->orig_parent = NULL;
|
||||
}
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
clutter_actor_destroy (ppriv->desktop1);
|
||||
clutter_actor_destroy (ppriv->desktop2);
|
||||
|
||||
ppriv->actors = NULL;
|
||||
ppriv->tml_switch_workspace1 = NULL;
|
||||
ppriv->tml_switch_workspace2 = NULL;
|
||||
ppriv->desktop1 = NULL;
|
||||
ppriv->desktop2 = NULL;
|
||||
|
||||
if (plugin->completed)
|
||||
plugin->completed (plugin, actor_for_cb,
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_SWITCH_WORKSPACE);
|
||||
}
|
||||
|
||||
static void
|
||||
switch_workspace (const GList **actors, gint from, gint to)
|
||||
{
|
||||
MetaCompositorClutterPlugin *plugin = &META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT;
|
||||
PluginPrivate *ppriv = plugin->plugin_private;
|
||||
GList *l;
|
||||
gint n_workspaces;
|
||||
ClutterActor *group1 = clutter_group_new ();
|
||||
ClutterActor *group2 = clutter_group_new ();
|
||||
ClutterActor *stage = plugin->stage;
|
||||
|
||||
#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);
|
||||
#endif
|
||||
|
||||
clutter_actor_set_scale (group2, 0.0, 0.0);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), group2);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), group1);
|
||||
|
||||
if (from == to)
|
||||
{
|
||||
if (plugin->completed)
|
||||
plugin->completed (plugin, NULL,
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_SWITCH_WORKSPACE);
|
||||
return;
|
||||
}
|
||||
|
||||
n_workspaces = g_list_length (plugin->work_areas);
|
||||
|
||||
l = g_list_last (*((GList**) actors));
|
||||
|
||||
while (l)
|
||||
{
|
||||
ClutterActor *a = l->data;
|
||||
ActorPrivate *priv = get_actor_private (a);
|
||||
gint workspace;
|
||||
|
||||
workspace = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (a),
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_WORKSPACE_KEY));
|
||||
|
||||
priv->workspace = workspace;
|
||||
|
||||
if (workspace == to || workspace == from)
|
||||
{
|
||||
gint x, y;
|
||||
guint w, h;
|
||||
|
||||
clutter_actor_get_position (a, &x, &y);
|
||||
clutter_actor_get_size (a, &w, &h);
|
||||
|
||||
priv->orig_parent = clutter_actor_get_parent (a);
|
||||
|
||||
clutter_actor_reparent (a, workspace == to ? group2 : group1);
|
||||
clutter_actor_show_all (a);
|
||||
clutter_actor_raise_top (a);
|
||||
}
|
||||
else if (workspace < 0)
|
||||
{
|
||||
/* Sticky window */
|
||||
priv->orig_parent = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Window on some other desktop */
|
||||
clutter_actor_hide (a);
|
||||
priv->orig_parent = NULL;
|
||||
}
|
||||
|
||||
l = l->prev;
|
||||
}
|
||||
|
||||
ppriv->actors = (GList **)actors;
|
||||
ppriv->desktop1 = group1;
|
||||
ppriv->desktop2 = group2;
|
||||
|
||||
ppriv->tml_switch_workspace2 = clutter_effect_scale (
|
||||
ppriv->switch_workspace_effect,
|
||||
group2, 1.0, 1.0,
|
||||
on_switch_workspace_effect_complete,
|
||||
(gpointer)actors);
|
||||
|
||||
ppriv->tml_switch_workspace1 = clutter_effect_scale (
|
||||
ppriv->switch_workspace_effect,
|
||||
group1, 0.0, 0.0,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Minimize effect completion callback; this function restores actor state, and
|
||||
* calls the manager callback function.
|
||||
*/
|
||||
static void
|
||||
on_minimize_effect_complete (ClutterActor *actor, gpointer data)
|
||||
{
|
||||
/*
|
||||
* Must reverse the effect of the effect; must hide it first to ensure
|
||||
* that the restoration will not be visible.
|
||||
*/
|
||||
MetaCompositorClutterPlugin *plugin = &META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT;
|
||||
ActorPrivate *apriv = get_actor_private (actor);
|
||||
|
||||
apriv->tml_minimize = NULL;
|
||||
|
||||
clutter_actor_hide (actor);
|
||||
|
||||
clutter_actor_set_scale (actor, 1.0, 1.0);
|
||||
clutter_actor_move_anchor_point_from_gravity (actor,
|
||||
CLUTTER_GRAVITY_NORTH_WEST);
|
||||
|
||||
/* Decrease the running effect counter */
|
||||
plugin->running--;
|
||||
|
||||
/* Now notify the manager that we are done with this effect */
|
||||
if (plugin->completed)
|
||||
plugin->completed (plugin, actor, META_COMPOSITOR_CLUTTER_PLUGIN_MINIMIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple minimize handler: it applies a scale effect (which must be reversed on
|
||||
* completion).
|
||||
*/
|
||||
static void
|
||||
minimize (ClutterActor *actor, MetaCompWindowType type, gint workspace)
|
||||
|
||||
{
|
||||
MetaCompositorClutterPlugin *plugin = &META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT;
|
||||
PluginPrivate *priv = plugin->plugin_private;
|
||||
|
||||
if (type == META_COMP_WINDOW_NORMAL)
|
||||
{
|
||||
ActorPrivate *apriv = get_actor_private (actor);
|
||||
|
||||
apriv->is_minimized = TRUE;
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (actor,
|
||||
CLUTTER_GRAVITY_CENTER);
|
||||
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT.running++;
|
||||
|
||||
apriv->tml_minimize = clutter_effect_scale (priv->minimize_effect,
|
||||
actor,
|
||||
0.0,
|
||||
0.0,
|
||||
(ClutterEffectCompleteFunc)
|
||||
on_minimize_effect_complete,
|
||||
NULL);
|
||||
}
|
||||
else if (plugin->completed)
|
||||
plugin->completed (plugin, actor, META_COMPOSITOR_CLUTTER_PLUGIN_MINIMIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Minimize effect completion callback; this function restores actor state, and
|
||||
* calls the manager callback function.
|
||||
*/
|
||||
static void
|
||||
on_maximize_effect_complete (ClutterActor *actor, gpointer data)
|
||||
{
|
||||
/*
|
||||
* Must reverse the effect of the effect.
|
||||
*/
|
||||
MetaCompositorClutterPlugin *plugin = &META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT;
|
||||
ActorPrivate *apriv = get_actor_private (actor);
|
||||
|
||||
apriv->tml_maximize = NULL;
|
||||
|
||||
clutter_actor_set_scale (actor, 1.0, 1.0);
|
||||
clutter_actor_move_anchor_point_from_gravity (actor,
|
||||
CLUTTER_GRAVITY_NORTH_WEST);
|
||||
|
||||
/* Decrease the running effect counter */
|
||||
plugin->running--;
|
||||
|
||||
/* Now notify the manager that we are done with this effect */
|
||||
if (plugin->completed)
|
||||
plugin->completed (plugin, actor, META_COMPOSITOR_CLUTTER_PLUGIN_MAXIMIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* The Nature of Maximize operation is such that it is difficult to do a visual
|
||||
* effect that would work well. Scaling, the obvious effect, does not work that
|
||||
* well, because at the end of the effect we end up with window content bigger
|
||||
* and differently laid out than in the real window; this is a proof concept.
|
||||
*
|
||||
* (Something like a sound would be more appropriate.)
|
||||
*/
|
||||
static void
|
||||
maximize (ClutterActor *actor, MetaCompWindowType type, gint workspace,
|
||||
gint end_x, gint end_y, gint end_width, gint end_height)
|
||||
{
|
||||
MetaCompositorClutterPlugin *plugin = &META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT;
|
||||
PluginPrivate *priv = plugin->plugin_private;
|
||||
|
||||
gdouble scale_x = 1.0;
|
||||
gdouble scale_y = 1.0;
|
||||
gint anchor_x = 0;
|
||||
gint anchor_y = 0;
|
||||
|
||||
if (type == META_COMP_WINDOW_NORMAL)
|
||||
{
|
||||
ActorPrivate *apriv = get_actor_private (actor);
|
||||
guint width, height;
|
||||
gint x, y;
|
||||
|
||||
apriv->is_maximized = TRUE;
|
||||
|
||||
clutter_actor_get_size (actor, &width, &height);
|
||||
clutter_actor_get_position (actor, &x, &y);
|
||||
|
||||
/*
|
||||
* Work out the scale and anchor point so that the window is expanding
|
||||
* smoothly into the target size.
|
||||
*/
|
||||
scale_x = (gdouble)end_width / (gdouble) width;
|
||||
scale_y = (gdouble)end_height / (gdouble) height;
|
||||
|
||||
anchor_x = (gdouble)(x - end_x)*(gdouble)width /
|
||||
((gdouble)(end_width - width));
|
||||
anchor_y = (gdouble)(y - end_y)*(gdouble)height /
|
||||
((gdouble)(end_height - height));
|
||||
|
||||
clutter_actor_move_anchor_point (actor, anchor_x, anchor_y);
|
||||
|
||||
apriv->tml_maximize = clutter_effect_scale (priv->maximize_effect,
|
||||
actor,
|
||||
scale_x,
|
||||
scale_y,
|
||||
(ClutterEffectCompleteFunc)
|
||||
on_maximize_effect_complete,
|
||||
NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (plugin->completed)
|
||||
plugin->completed (plugin, actor, META_COMPOSITOR_CLUTTER_PLUGIN_MAXIMIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* See comments on the maximize() function.
|
||||
*
|
||||
* (Just a skeleton code.)
|
||||
*/
|
||||
static void
|
||||
unmaximize (ClutterActor *actor, MetaCompWindowType type, gint workspace,
|
||||
gint end_x, gint end_y, gint end_width, gint end_height)
|
||||
{
|
||||
MetaCompositorClutterPlugin *plugin = &META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT;
|
||||
|
||||
if (type == META_COMP_WINDOW_NORMAL)
|
||||
{
|
||||
ActorPrivate *apriv = get_actor_private (actor);
|
||||
|
||||
apriv->is_maximized = FALSE;
|
||||
|
||||
printf ("Doing unmaximize to target %d,%d;%dx%d\n",
|
||||
end_x, end_y, end_width, end_height);
|
||||
}
|
||||
|
||||
/* Do this conditionally, if the effect requires completion callback. */
|
||||
plugin->completed (plugin, actor, META_COMPOSITOR_CLUTTER_PLUGIN_UNMAXIMIZE);
|
||||
}
|
||||
|
||||
static void
|
||||
on_map_effect_complete (ClutterActor *actor, gpointer data)
|
||||
{
|
||||
/*
|
||||
* Must reverse the effect of the effect.
|
||||
*/
|
||||
MetaCompositorClutterPlugin *plugin = &META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT;
|
||||
ActorPrivate *apriv = get_actor_private (actor);
|
||||
|
||||
apriv->tml_map = NULL;
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (actor,
|
||||
CLUTTER_GRAVITY_NORTH_WEST);
|
||||
|
||||
/* Decrease the running effect counter */
|
||||
plugin->running--;
|
||||
|
||||
/* Now notify the manager that we are done with this effect */
|
||||
if (plugin->completed)
|
||||
plugin->completed (plugin, actor, META_COMPOSITOR_CLUTTER_PLUGIN_MAP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple map handler: it applies a scale effect which must be reversed on
|
||||
* completion).
|
||||
*/
|
||||
static void
|
||||
map (ClutterActor *actor, MetaCompWindowType type, gint workspace)
|
||||
{
|
||||
MetaCompositorClutterPlugin *plugin = &META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT;
|
||||
PluginPrivate *priv = plugin->plugin_private;
|
||||
|
||||
if (type == META_COMP_WINDOW_NORMAL)
|
||||
{
|
||||
ActorPrivate *apriv = get_actor_private (actor);
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (actor,
|
||||
CLUTTER_GRAVITY_CENTER);
|
||||
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT.running++;
|
||||
|
||||
clutter_actor_set_scale (actor, 0.0, 0.0);
|
||||
clutter_actor_show (actor);
|
||||
|
||||
apriv->tml_map = clutter_effect_scale (priv->map_effect,
|
||||
actor,
|
||||
1.0,
|
||||
1.0,
|
||||
(ClutterEffectCompleteFunc)
|
||||
on_map_effect_complete,
|
||||
NULL);
|
||||
|
||||
apriv->is_minimized = FALSE;
|
||||
|
||||
}
|
||||
else if (plugin->completed)
|
||||
plugin->completed (plugin, actor, META_COMPOSITOR_CLUTTER_PLUGIN_MAP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy effect completion callback; this is a simple effect that requires no
|
||||
* further action than decreasing the running effect counter and notifying the
|
||||
* manager that the effect is completed.
|
||||
*/
|
||||
static void
|
||||
on_destroy_effect_complete (ClutterActor *actor, gpointer data)
|
||||
{
|
||||
MetaCompositorClutterPlugin *plugin = &META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT;
|
||||
ActorPrivate *apriv = get_actor_private (actor);
|
||||
|
||||
apriv->tml_destroy = NULL;
|
||||
|
||||
plugin->running--;
|
||||
|
||||
if (plugin->completed)
|
||||
plugin->completed (plugin, actor, META_COMPOSITOR_CLUTTER_PLUGIN_DESTROY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple TV-out like effect.
|
||||
*/
|
||||
static void
|
||||
destroy (ClutterActor *actor, MetaCompWindowType type, gint workspace)
|
||||
{
|
||||
MetaCompositorClutterPlugin *plugin = &META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT;
|
||||
PluginPrivate *priv = plugin->plugin_private;
|
||||
|
||||
if (type == META_COMP_WINDOW_NORMAL)
|
||||
{
|
||||
ActorPrivate *apriv = get_actor_private (actor);
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (actor,
|
||||
CLUTTER_GRAVITY_CENTER);
|
||||
|
||||
plugin->running++;
|
||||
|
||||
apriv->tml_destroy = clutter_effect_scale (priv->destroy_effect,
|
||||
actor,
|
||||
1.0,
|
||||
0.0,
|
||||
(ClutterEffectCompleteFunc)
|
||||
on_destroy_effect_complete,
|
||||
NULL);
|
||||
}
|
||||
else if (plugin->completed)
|
||||
plugin->completed (plugin, actor, META_COMPOSITOR_CLUTTER_PLUGIN_DESTROY);
|
||||
}
|
||||
|
||||
static void
|
||||
kill_effect (ClutterActor *actor, gulong event)
|
||||
{
|
||||
MetaCompositorClutterPlugin *plugin = &META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT;
|
||||
ActorPrivate *apriv;
|
||||
|
||||
if (!(plugin->features & event))
|
||||
{
|
||||
/* Event we do not support */
|
||||
return;
|
||||
}
|
||||
|
||||
if (event & META_COMPOSITOR_CLUTTER_PLUGIN_SWITCH_WORKSPACE)
|
||||
{
|
||||
PluginPrivate *ppriv = plugin->plugin_private;
|
||||
|
||||
if (ppriv->tml_switch_workspace1)
|
||||
{
|
||||
clutter_timeline_stop (ppriv->tml_switch_workspace1);
|
||||
clutter_timeline_stop (ppriv->tml_switch_workspace2);
|
||||
on_switch_workspace_effect_complete (ppriv->desktop1, ppriv->actors);
|
||||
}
|
||||
|
||||
if (!(event & ~META_COMPOSITOR_CLUTTER_PLUGIN_SWITCH_WORKSPACE))
|
||||
{
|
||||
/* Workspace switch only, nothing more to do */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
apriv = get_actor_private (actor);
|
||||
|
||||
if ((event & META_COMPOSITOR_CLUTTER_PLUGIN_MINIMIZE) && apriv->tml_minimize)
|
||||
{
|
||||
clutter_timeline_stop (apriv->tml_minimize);
|
||||
on_minimize_effect_complete (actor, NULL);
|
||||
}
|
||||
|
||||
if ((event & META_COMPOSITOR_CLUTTER_PLUGIN_MAXIMIZE) && apriv->tml_maximize)
|
||||
{
|
||||
clutter_timeline_stop (apriv->tml_maximize);
|
||||
on_maximize_effect_complete (actor, NULL);
|
||||
}
|
||||
|
||||
if ((event & META_COMPOSITOR_CLUTTER_PLUGIN_MAP) && apriv->tml_map)
|
||||
{
|
||||
clutter_timeline_stop (apriv->tml_map);
|
||||
on_map_effect_complete (actor, NULL);
|
||||
}
|
||||
|
||||
if ((event & META_COMPOSITOR_CLUTTER_PLUGIN_DESTROY) && apriv->tml_destroy)
|
||||
{
|
||||
clutter_timeline_stop (apriv->tml_destroy);
|
||||
on_destroy_effect_complete (actor, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
const gchar * g_module_check_init (GModule *module);
|
||||
const gchar *
|
||||
g_module_check_init (GModule *module)
|
||||
{
|
||||
/*
|
||||
* Unused; left here for documentation purposes.
|
||||
*
|
||||
* NB: this function is called *before* the plugin manager does its own
|
||||
* initialization of the plugin struct, so you cannot process fields
|
||||
* like .params in here; use the init function below instead.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Core of the plugin init function, called for initial initialization and
|
||||
* by the reload() function. Returns TRUE on success.
|
||||
*/
|
||||
static gboolean
|
||||
do_init ()
|
||||
{
|
||||
MetaCompositorClutterPlugin *plugin = &META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT;
|
||||
|
||||
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;
|
||||
const gchar *name;
|
||||
|
||||
plugin->plugin_private = priv;
|
||||
|
||||
name = plugin->name;
|
||||
plugin->name = _(name);
|
||||
|
||||
params = plugin->params;
|
||||
|
||||
if (params)
|
||||
{
|
||||
gchar *p;
|
||||
|
||||
if (strstr (params, "debug"))
|
||||
{
|
||||
g_debug ("%s: Entering debug mode.",
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT.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;
|
||||
}
|
||||
|
||||
if ((p = strstr (params, "disable:")))
|
||||
{
|
||||
gchar *d = g_strdup (p+8);
|
||||
|
||||
p = strchr (d, ';');
|
||||
|
||||
if (p)
|
||||
*p = 0;
|
||||
|
||||
if (strstr (d, "minimize"))
|
||||
plugin->features &= ~ META_COMPOSITOR_CLUTTER_PLUGIN_MINIMIZE;
|
||||
|
||||
if (strstr (d, "maximize"))
|
||||
plugin->features &= ~ META_COMPOSITOR_CLUTTER_PLUGIN_MAXIMIZE;
|
||||
|
||||
if (strstr (d, "unmaximize"))
|
||||
plugin->features &= ~ META_COMPOSITOR_CLUTTER_PLUGIN_UNMAXIMIZE;
|
||||
|
||||
if (strstr (d, "map"))
|
||||
plugin->features &= ~ META_COMPOSITOR_CLUTTER_PLUGIN_MAP;
|
||||
|
||||
if (strstr (d, "destroy"))
|
||||
plugin->features &= ~ META_COMPOSITOR_CLUTTER_PLUGIN_DESTROY;
|
||||
|
||||
if (strstr (d, "switch-workspace"))
|
||||
plugin->features &= ~META_COMPOSITOR_CLUTTER_PLUGIN_SWITCH_WORKSPACE;
|
||||
|
||||
g_free (d);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_INIT_FUNC
|
||||
{
|
||||
return do_init ();
|
||||
}
|
||||
|
||||
static void
|
||||
free_plugin_private (PluginPrivate *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_free (priv);
|
||||
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT.plugin_private = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by the plugin manager when we stuff like the command line parameters
|
||||
* changed.
|
||||
*/
|
||||
static gboolean
|
||||
reload ()
|
||||
{
|
||||
PluginPrivate *priv;
|
||||
|
||||
priv = META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT.plugin_private;
|
||||
|
||||
if (do_init ())
|
||||
{
|
||||
/* Success; free the old private struct */
|
||||
free_plugin_private (priv);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fail -- fall back to the old private. */
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT.plugin_private = priv;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* GModule unload function -- do any cleanup required.
|
||||
*/
|
||||
void g_module_unload (GModule *module);
|
||||
void g_module_unload (GModule *module)
|
||||
{
|
||||
PluginPrivate *priv;
|
||||
|
||||
priv = META_COMPOSITOR_CLUTTER_PLUGIN_STRUCT.plugin_private;
|
||||
|
||||
free_plugin_private (priv);
|
||||
}
|
644
src/compositor/compositor-clutter-plugin-manager.c
Normal file
644
src/compositor/compositor-clutter-plugin-manager.c
Normal file
@ -0,0 +1,644 @@
|
||||
/* -*- 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>
|
||||
|
||||
static gboolean meta_compositor_clutter_plugin_manager_reload (MetaCompositorClutterPluginManager *mgr);
|
||||
|
||||
struct MetaCompositorClutterPluginManager
|
||||
{
|
||||
MetaScreen *screen;
|
||||
ClutterActor *stage;
|
||||
|
||||
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
|
||||
{
|
||||
GModule *module;
|
||||
|
||||
gboolean disabled : 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* This function gets called when an effect completes. It is responsible for
|
||||
* any post-effect cleanup.
|
||||
*/
|
||||
static void
|
||||
meta_compositor_clutter_effect_completed (MetaCompositorClutterPlugin *plugin,
|
||||
ClutterActor *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);
|
||||
}
|
||||
|
||||
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 (MetaScreen *screen,
|
||||
ClutterActor *stage,
|
||||
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->completed = meta_compositor_clutter_effect_completed;
|
||||
plg->stage = stage;
|
||||
plg->manager_private = priv;
|
||||
priv->module = module;
|
||||
|
||||
meta_screen_get_size (screen,
|
||||
&plg->screen_width, &plg->screen_height);
|
||||
|
||||
update_plugin_workspaces (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;
|
||||
|
||||
plugins = meta_prefs_get_clutter_plugins ();
|
||||
|
||||
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->screen,
|
||||
mgr->stage,
|
||||
plg, params)))
|
||||
mgr->plugins = g_list_prepend (mgr->plugins, p);
|
||||
else
|
||||
g_module_close (plg);
|
||||
}
|
||||
|
||||
g_free (path);
|
||||
g_free (plg_string);
|
||||
}
|
||||
|
||||
plugins = plugins->next;
|
||||
}
|
||||
|
||||
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,
|
||||
ClutterActor *stage)
|
||||
{
|
||||
MetaCompositorClutterPluginManager *mgr;
|
||||
|
||||
mgr = g_new0 (MetaCompositorClutterPluginManager, 1);
|
||||
|
||||
mgr->screen = screen;
|
||||
mgr->stage = stage;
|
||||
|
||||
if (!meta_compositor_clutter_plugin_manager_init (mgr))
|
||||
{
|
||||
g_free (mgr);
|
||||
mgr = NULL;
|
||||
}
|
||||
|
||||
return mgr;
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_clutter_plugin_manager_kill_effect (MetaCompositorClutterPluginManager *mgr,
|
||||
ClutterActor *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_0 (MetaCompositorClutterPluginManager *mgr,
|
||||
ClutterActor *actor,
|
||||
unsigned long event,
|
||||
MetaCompWindowType type,
|
||||
gint workspace)
|
||||
{
|
||||
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, type, workspace);
|
||||
}
|
||||
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, type, workspace);
|
||||
}
|
||||
break;
|
||||
case META_COMPOSITOR_CLUTTER_PLUGIN_DESTROY:
|
||||
if (plg->destroy)
|
||||
{
|
||||
plg->destroy (actor, type, workspace);
|
||||
}
|
||||
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 events that require
|
||||
* up to 4 additional integer 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_4i (MetaCompositorClutterPluginManager *mgr,
|
||||
ClutterActor *actor,
|
||||
unsigned long event,
|
||||
MetaCompWindowType type,
|
||||
gint workspace,
|
||||
gint i0,
|
||||
gint i1,
|
||||
gint i2,
|
||||
gint i3)
|
||||
{
|
||||
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, type, workspace, i0, i1, i2, i3);
|
||||
}
|
||||
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, type, workspace, i0, i1, i2, i3);
|
||||
}
|
||||
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)
|
||||
{
|
||||
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,
|
||||
CLUTTER_ACTOR ((*actors)->data),
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_SWITCH_WORKSPACE);
|
||||
plg->switch_workspace (actors, from, to);
|
||||
}
|
||||
}
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
58
src/compositor/compositor-clutter-plugin-manager.h
Normal file
58
src/compositor/compositor-clutter-plugin-manager.h
Normal file
@ -0,0 +1,58 @@
|
||||
/* -*- 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_MANAGER_H_
|
||||
#define META_COMPOSITOR_CLUTTER_PLUGIN_MANAGER_H_
|
||||
|
||||
#include "types.h"
|
||||
#include "screen.h"
|
||||
#include "compositor-clutter-plugin.h"
|
||||
|
||||
typedef struct MetaCompositorClutterPluginManager MetaCompositorClutterPluginManager;
|
||||
|
||||
MetaCompositorClutterPluginManager * meta_compositor_clutter_plugin_manager_new (MetaScreen *screen, ClutterActor *stage);
|
||||
gboolean meta_compositor_clutter_plugin_manager_event_0 (MetaCompositorClutterPluginManager *mgr,
|
||||
ClutterActor *actor,
|
||||
unsigned long event,
|
||||
MetaCompWindowType type,
|
||||
gint workspace);
|
||||
|
||||
gboolean meta_compositor_clutter_plugin_manager_event_4i (MetaCompositorClutterPluginManager *mgr,
|
||||
ClutterActor *actor,
|
||||
unsigned long event,
|
||||
MetaCompWindowType type,
|
||||
gint workspace,
|
||||
gint i0,
|
||||
gint i1,
|
||||
gint i2,
|
||||
gint i3);
|
||||
void meta_compositor_clutter_plugin_manager_update_workspaces (MetaCompositorClutterPluginManager *mgr);
|
||||
|
||||
void meta_compositor_clutter_plugin_manager_update_workspace (MetaCompositorClutterPluginManager *mgr, MetaWorkspace *w);
|
||||
|
||||
gboolean meta_compositor_clutter_plugin_manager_switch_workspace (MetaCompositorClutterPluginManager *mgr,
|
||||
const GList **actors,
|
||||
gint from,
|
||||
gint to);
|
||||
|
||||
#endif
|
@ -17,6 +17,7 @@
|
||||
#include "window.h"
|
||||
#include "compositor-private.h"
|
||||
#include "compositor-clutter.h"
|
||||
#include "compositor-clutter-plugin-manager.h"
|
||||
#include "xprops.h"
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xlibint.h>
|
||||
@ -41,16 +42,13 @@
|
||||
#define TILE_WIDTH (3*MAX_TILE_SZ)
|
||||
#define TILE_HEIGHT (3*MAX_TILE_SZ)
|
||||
|
||||
#define DESTROY_TIMEOUT 300
|
||||
#define MINIMIZE_TIMEOUT 600
|
||||
|
||||
/*
|
||||
* Register GType wrapper for XWindowAttributes, so we do not have to
|
||||
* query window attributes in the MetaCompWindow constructor but can pass
|
||||
* them as a property to the constructor (so we can gracefully handle the case
|
||||
* where no attributes can be retrieved).
|
||||
*
|
||||
* NB -- we only need a subset of the attribute; at some point we might want
|
||||
* NB -- we only need a subset of the attributes; at some point we might want
|
||||
* to just store the relevant values rather than the whole struct.
|
||||
*/
|
||||
#define META_TYPE_XATTRS (meta_xattrs_get_type ())
|
||||
@ -110,27 +108,8 @@ composite_at_least_version (MetaDisplay *display, int maj, int min)
|
||||
|
||||
return (major > maj || (major == maj && minor >= min));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
typedef enum _MetaCompWindowType
|
||||
{
|
||||
/*
|
||||
* Types shared with MetaWindow
|
||||
*/
|
||||
META_COMP_WINDOW_NORMAL = META_WINDOW_NORMAL,
|
||||
META_COMP_WINDOW_DESKTOP = META_WINDOW_DESKTOP,
|
||||
META_COMP_WINDOW_DOCK = META_WINDOW_DOCK,
|
||||
META_COMP_WINDOW_MENU = META_WINDOW_MENU,
|
||||
|
||||
/*
|
||||
* Extended types that WM does not care about, but we do.
|
||||
*/
|
||||
META_COMP_WINDOW_TOOLTIP = 0xf000,
|
||||
META_COMP_WINDOW_DROP_DOWN_MENU,
|
||||
META_COMP_WINDOW_DND,
|
||||
} MetaCompWindowType;
|
||||
|
||||
typedef struct _MetaCompositorClutter
|
||||
{
|
||||
MetaCompositor compositor;
|
||||
@ -157,8 +136,9 @@ typedef struct _MetaCompScreen
|
||||
Window output;
|
||||
GSList *dock_windows;
|
||||
|
||||
ClutterEffectTemplate *destroy_effect;
|
||||
ClutterEffectTemplate *minimize_effect;
|
||||
gint switch_workspace_in_progress;
|
||||
|
||||
MetaCompositorClutterPluginManager *plugin_mgr;
|
||||
} MetaCompScreen;
|
||||
|
||||
/*
|
||||
@ -204,12 +184,28 @@ struct _MetaCompWindowPrivate
|
||||
|
||||
guint8 opacity;
|
||||
|
||||
gboolean needs_shadow : 1;
|
||||
gboolean shaped : 1;
|
||||
gboolean destroy_pending : 1;
|
||||
gboolean argb32 : 1;
|
||||
gboolean minimize_in_progress : 1;
|
||||
gboolean disposed : 1;
|
||||
/*
|
||||
* These need to be counters rather than flags, since more plugins
|
||||
* can implement same effect; the practicality of stacking effects
|
||||
* might be dubious, but we have to at least handle it correctly.
|
||||
*/
|
||||
gint minimize_in_progress;
|
||||
gint maximize_in_progress;
|
||||
gint unmaximize_in_progress;
|
||||
gint map_in_progress;
|
||||
gint destroy_in_progress;
|
||||
|
||||
gboolean needs_shadow : 1;
|
||||
gboolean shaped : 1;
|
||||
gboolean destroy_pending : 1;
|
||||
gboolean argb32 : 1;
|
||||
gboolean disposed : 1;
|
||||
gboolean is_minimized : 1;
|
||||
|
||||
/* Desktop switching flags */
|
||||
gboolean needs_map : 1;
|
||||
gboolean needs_unmap : 1;
|
||||
gboolean needs_repair : 1;
|
||||
};
|
||||
|
||||
enum
|
||||
@ -515,6 +511,12 @@ meta_comp_window_get_window_type (MetaCompWindow *self)
|
||||
Atom *atoms;
|
||||
gint i;
|
||||
|
||||
if (priv->attrs.override_redirect)
|
||||
{
|
||||
priv->type = META_COMP_WINDOW_OVERRIDE;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the window is managed by the WM, get the type from the WM,
|
||||
* otherwise do it the hard way.
|
||||
@ -613,7 +615,7 @@ meta_comp_window_has_shadow (MetaCompWindow *self)
|
||||
MetaCompWindowPrivate * priv = self->priv;
|
||||
|
||||
/*
|
||||
* Do not add shadows to ARGB windows (since they are probably transparent
|
||||
* Do not add shadows to ARGB windows (since they are probably transparent)
|
||||
*/
|
||||
if (priv->argb32 || priv->opacity != 0xff)
|
||||
{
|
||||
@ -685,6 +687,170 @@ meta_comp_window_has_shadow (MetaCompWindow *self)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void repair_win (MetaCompWindow *cw);
|
||||
static void map_win (MetaCompWindow *cw);
|
||||
static void unmap_win (MetaCompWindow *cw);
|
||||
|
||||
static void
|
||||
meta_compositor_clutter_finish_workspace_switch (MetaCompScreen *info)
|
||||
{
|
||||
GList *last = g_list_last (info->windows);
|
||||
GList *l = last;
|
||||
|
||||
while (l)
|
||||
{
|
||||
MetaCompWindow *cw = l->data;
|
||||
MetaCompWindowPrivate *priv = cw->priv;
|
||||
|
||||
if (priv->needs_map && !priv->needs_unmap)
|
||||
{
|
||||
map_win (cw);
|
||||
}
|
||||
|
||||
if (priv->needs_unmap)
|
||||
{
|
||||
unmap_win (cw);
|
||||
}
|
||||
|
||||
l = l->prev;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now fix up stacking order in case the plugin messed it up.
|
||||
*/
|
||||
l = last;
|
||||
while (l)
|
||||
{
|
||||
ClutterActor *a = l->data;
|
||||
GList *prev = l->prev;
|
||||
|
||||
if (prev)
|
||||
{
|
||||
ClutterActor *above_me = prev->data;
|
||||
|
||||
clutter_actor_raise (above_me, a);
|
||||
}
|
||||
else
|
||||
{
|
||||
ClutterActor *a = l->data;
|
||||
clutter_actor_raise_top (a);
|
||||
}
|
||||
|
||||
l = prev;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_clutter_window_effect_completed (ClutterActor *actor,
|
||||
gulong event)
|
||||
{
|
||||
MetaCompWindow *cw = META_COMP_WINDOW (actor);
|
||||
MetaCompWindowPrivate *priv = cw->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case META_COMPOSITOR_CLUTTER_PLUGIN_MINIMIZE:
|
||||
{
|
||||
ClutterActor *a = CLUTTER_ACTOR (cw);
|
||||
gint height = clutter_actor_get_height (a);
|
||||
|
||||
priv->minimize_in_progress--;
|
||||
if (priv->minimize_in_progress < 0)
|
||||
{
|
||||
g_warning ("Error in minimize accounting.");
|
||||
priv->minimize_in_progress = 0;
|
||||
}
|
||||
|
||||
if (!priv->minimize_in_progress)
|
||||
{
|
||||
priv->is_minimized = TRUE;
|
||||
clutter_actor_set_position (a, 0, -height);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case META_COMPOSITOR_CLUTTER_PLUGIN_MAP:
|
||||
/*
|
||||
* Make sure that the actor is at the correct place in case
|
||||
* the plugin fscked.
|
||||
*/
|
||||
priv->map_in_progress--;
|
||||
|
||||
if (priv->map_in_progress < 0)
|
||||
{
|
||||
g_warning ("Error in map accounting.");
|
||||
priv->map_in_progress = 0;
|
||||
}
|
||||
|
||||
if (!priv->map_in_progress)
|
||||
{
|
||||
priv->is_minimized = FALSE;
|
||||
clutter_actor_set_anchor_point (actor, 0, 0);
|
||||
clutter_actor_set_position (actor, priv->attrs.x, priv->attrs.y);
|
||||
clutter_actor_show_all (actor);
|
||||
}
|
||||
break;
|
||||
case META_COMPOSITOR_CLUTTER_PLUGIN_DESTROY:
|
||||
priv->destroy_in_progress--;
|
||||
|
||||
if (priv->destroy_in_progress < 0)
|
||||
{
|
||||
g_warning ("Error in destroy accounting.");
|
||||
priv->destroy_in_progress = 0;
|
||||
}
|
||||
|
||||
if (!priv->destroy_in_progress)
|
||||
{
|
||||
clutter_actor_destroy (actor);
|
||||
}
|
||||
break;
|
||||
case META_COMPOSITOR_CLUTTER_PLUGIN_UNMAXIMIZE:
|
||||
priv->unmaximize_in_progress--;
|
||||
if (priv->unmaximize_in_progress < 0)
|
||||
{
|
||||
g_warning ("Error in unmaximize accounting.");
|
||||
priv->unmaximize_in_progress = 0;
|
||||
}
|
||||
|
||||
if (!priv->unmaximize_in_progress)
|
||||
{
|
||||
clutter_actor_set_position (actor, priv->attrs.x, priv->attrs.y);
|
||||
meta_comp_window_detach (cw);
|
||||
repair_win (cw);
|
||||
}
|
||||
break;
|
||||
case META_COMPOSITOR_CLUTTER_PLUGIN_MAXIMIZE:
|
||||
priv->maximize_in_progress--;
|
||||
if (priv->maximize_in_progress < 0)
|
||||
{
|
||||
g_warning ("Error in maximize accounting.");
|
||||
priv->maximize_in_progress = 0;
|
||||
}
|
||||
|
||||
if (!priv->maximize_in_progress)
|
||||
{
|
||||
clutter_actor_set_position (actor, priv->attrs.x, priv->attrs.y);
|
||||
meta_comp_window_detach (cw);
|
||||
repair_win (cw);
|
||||
}
|
||||
break;
|
||||
case META_COMPOSITOR_CLUTTER_PLUGIN_SWITCH_WORKSPACE:
|
||||
/* FIXME -- must redo stacking order */
|
||||
info->switch_workspace_in_progress--;
|
||||
if (info->switch_workspace_in_progress < 0)
|
||||
{
|
||||
g_warning ("Error in workspace_switch accounting!");
|
||||
info->switch_workspace_in_progress = 0;
|
||||
}
|
||||
|
||||
if (!info->switch_workspace_in_progress)
|
||||
meta_compositor_clutter_finish_workspace_switch (info);
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
clutter_cmp_destroy (MetaCompositor *compositor)
|
||||
@ -694,19 +860,23 @@ clutter_cmp_destroy (MetaCompositor *compositor)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* If force is TRUE, free the back pixmap; if FALSE, only free it if the
|
||||
* backing pixmap has actually changed.
|
||||
*/
|
||||
static void
|
||||
meta_comp_window_detach (MetaCompWindow *self)
|
||||
{
|
||||
MetaCompWindowPrivate *priv = self->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
MetaCompWindowPrivate *priv = self->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
if (priv->back_pixmap)
|
||||
{
|
||||
XFreePixmap (xdisplay, priv->back_pixmap);
|
||||
priv->back_pixmap = None;
|
||||
}
|
||||
if (!priv->back_pixmap)
|
||||
return;
|
||||
|
||||
XFreePixmap (xdisplay, priv->back_pixmap);
|
||||
priv->back_pixmap = None;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -719,8 +889,6 @@ destroy_win (MetaDisplay *display, Window xwindow)
|
||||
if (cw == NULL)
|
||||
return;
|
||||
|
||||
meta_verbose ("destroying a window... 0x%x (%p)\n", (guint) xwindow, cw);
|
||||
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (cw));
|
||||
}
|
||||
|
||||
@ -752,7 +920,8 @@ restack_win (MetaCompWindow *cw, Window above)
|
||||
info->windows = g_list_delete_link (info->windows, sibling);
|
||||
info->windows = g_list_append (info->windows, cw);
|
||||
|
||||
clutter_actor_raise_top (CLUTTER_ACTOR (cw));
|
||||
if (!info->switch_workspace_in_progress)
|
||||
clutter_actor_raise_top (CLUTTER_ACTOR (cw));
|
||||
}
|
||||
else if (previous_above != above)
|
||||
{
|
||||
@ -772,7 +941,8 @@ restack_win (MetaCompWindow *cw, Window above)
|
||||
info->windows = g_list_delete_link (info->windows, sibling);
|
||||
info->windows = g_list_insert_before (info->windows, index, cw);
|
||||
|
||||
clutter_actor_raise (CLUTTER_ACTOR (cw), above_win);
|
||||
if (!info->switch_workspace_in_progress)
|
||||
clutter_actor_raise (CLUTTER_ACTOR (cw), above_win);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -790,60 +960,116 @@ resize_win (MetaCompWindow *cw,
|
||||
|
||||
priv->attrs.x = x;
|
||||
priv->attrs.y = y;
|
||||
|
||||
clutter_actor_set_position (CLUTTER_ACTOR (cw), x, y);
|
||||
|
||||
/* Note, let named named pixmap resync actually resize actor */
|
||||
|
||||
if (priv->attrs.width != width || priv->attrs.height != height)
|
||||
meta_comp_window_detach (cw);
|
||||
|
||||
priv->attrs.width = width;
|
||||
priv->attrs.height = height;
|
||||
priv->attrs.border_width = border_width;
|
||||
priv->attrs.override_redirect = override_redirect;
|
||||
|
||||
if (priv->maximize_in_progress ||
|
||||
priv->unmaximize_in_progress ||
|
||||
priv->map_in_progress)
|
||||
return;
|
||||
|
||||
meta_comp_window_detach (cw);
|
||||
clutter_actor_set_position (CLUTTER_ACTOR (cw), x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
map_win (MetaDisplay *display, MetaScreen *screen, Window id)
|
||||
map_win (MetaCompWindow *cw)
|
||||
{
|
||||
MetaCompWindow *cw = find_window_for_screen (screen, id);
|
||||
MetaCompWindowPrivate *priv;
|
||||
MetaCompScreen *info;
|
||||
|
||||
if (cw == NULL)
|
||||
return;
|
||||
|
||||
priv = cw->priv;
|
||||
info = meta_screen_get_compositor_data (priv->screen);
|
||||
|
||||
if (priv->attrs.map_state == IsViewable)
|
||||
return;
|
||||
|
||||
priv->attrs.map_state = IsViewable;
|
||||
|
||||
priv->minimize_in_progress = FALSE;
|
||||
/*
|
||||
* Now repair the window; this ensures that the actor is correctly sized
|
||||
* before we run any effects on it.
|
||||
*/
|
||||
priv->needs_map = FALSE;
|
||||
meta_comp_window_detach (cw);
|
||||
repair_win (cw);
|
||||
|
||||
clutter_actor_show (CLUTTER_ACTOR (cw));
|
||||
/*
|
||||
* Make sure the position is set correctly (we might have got moved while
|
||||
* unmapped.
|
||||
*/
|
||||
if (!info->switch_workspace_in_progress)
|
||||
{
|
||||
clutter_actor_set_anchor_point (CLUTTER_ACTOR (cw), 0, 0);
|
||||
clutter_actor_set_position (CLUTTER_ACTOR (cw),
|
||||
cw->priv->attrs.x, cw->priv->attrs.y);
|
||||
}
|
||||
|
||||
priv->map_in_progress++;
|
||||
|
||||
/*
|
||||
* If a plugin manager is present, try to run an effect; if no effect of this
|
||||
* type is present, destroy the actor.
|
||||
*/
|
||||
if (info->switch_workspace_in_progress || !info->plugin_mgr ||
|
||||
!meta_compositor_clutter_plugin_manager_event_0 (info->plugin_mgr,
|
||||
CLUTTER_ACTOR (cw),
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_MAP,
|
||||
cw->priv->type, 0))
|
||||
{
|
||||
clutter_actor_show_all (CLUTTER_ACTOR (cw));
|
||||
priv->map_in_progress--;
|
||||
priv->is_minimized = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
unmap_win (MetaDisplay *display, MetaScreen *screen, Window id)
|
||||
unmap_win (MetaCompWindow *cw)
|
||||
{
|
||||
MetaCompWindow *cw = find_window_for_screen (screen, id);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
MetaCompWindowPrivate *priv;
|
||||
MetaCompScreen *info;
|
||||
|
||||
if (cw == NULL)
|
||||
return;
|
||||
|
||||
priv = cw->priv;
|
||||
info = meta_screen_get_compositor_data (priv->screen);
|
||||
|
||||
/*
|
||||
* If the needs_unmap flag is set, we carry on even if the winow is
|
||||
* already marked as unmapped; this is necessary so windows temporarily
|
||||
* shown during an effect (like desktop switch) are properly hidden again.
|
||||
*/
|
||||
if (priv->attrs.map_state == IsUnmapped && !priv->needs_unmap)
|
||||
return;
|
||||
|
||||
if (priv->window && priv->window == info->focus_window)
|
||||
info->focus_window = NULL;
|
||||
|
||||
if (info->switch_workspace_in_progress)
|
||||
{
|
||||
/*
|
||||
* Cannot unmap windows while switching desktops effect is in progress.
|
||||
*/
|
||||
priv->needs_unmap = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
priv->attrs.map_state = IsUnmapped;
|
||||
|
||||
meta_comp_window_detach (cw);
|
||||
|
||||
if (!priv->minimize_in_progress)
|
||||
clutter_actor_hide (CLUTTER_ACTOR (cw));
|
||||
{
|
||||
ClutterActor *a = CLUTTER_ACTOR (cw);
|
||||
clutter_actor_hide (a);
|
||||
}
|
||||
|
||||
priv->needs_unmap = FALSE;
|
||||
priv->needs_map = FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -895,7 +1121,6 @@ add_win (MetaScreen *screen, MetaWindow *window, Window xwindow)
|
||||
CLUTTER_ACTOR (cw));
|
||||
clutter_actor_hide (CLUTTER_ACTOR (cw));
|
||||
|
||||
/* Only add the window to the list of docks if it needs a shadow */
|
||||
if (priv->type == META_COMP_WINDOW_DOCK)
|
||||
{
|
||||
meta_verbose ("Appending 0x%x to dock windows\n", (guint)xwindow);
|
||||
@ -940,18 +1165,23 @@ add_win (MetaScreen *screen, MetaWindow *window, Window xwindow)
|
||||
g_hash_table_insert (info->windows_by_xid, (gpointer) xwindow, cw);
|
||||
|
||||
if (priv->attrs.map_state == IsViewable)
|
||||
map_win (display, screen, xwindow);
|
||||
{
|
||||
/* Need to reset the map_state for map_win() to work */
|
||||
priv->attrs.map_state = IsUnmapped;
|
||||
map_win (cw);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
repair_win (MetaCompWindow *cw)
|
||||
{
|
||||
MetaCompWindowPrivate *priv = cw->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
MetaCompWindowPrivate *priv = cw->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
Window xwindow = priv->xwindow;
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
Window xwindow = priv->xwindow;
|
||||
gboolean full = FALSE;
|
||||
|
||||
if (xwindow == meta_screen_get_xroot (screen) ||
|
||||
xwindow == clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)))
|
||||
@ -962,8 +1192,23 @@ repair_win (MetaCompWindow *cw)
|
||||
if (priv->back_pixmap == None)
|
||||
{
|
||||
gint pxm_width, pxm_height;
|
||||
XWindowAttributes attr;
|
||||
|
||||
priv->back_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
|
||||
meta_error_trap_push (display);
|
||||
|
||||
XGrabServer (xdisplay);
|
||||
|
||||
XGetWindowAttributes (xdisplay, xwindow, &attr);
|
||||
|
||||
if (attr.map_state == IsViewable)
|
||||
priv->back_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
|
||||
else
|
||||
{
|
||||
priv->back_pixmap = None;
|
||||
}
|
||||
|
||||
XUngrabServer (xdisplay);
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
|
||||
if (priv->back_pixmap == None)
|
||||
{
|
||||
@ -984,6 +1229,8 @@ repair_win (MetaCompWindow *cw)
|
||||
|
||||
if (priv->shadow)
|
||||
clutter_actor_set_size (priv->shadow, pxm_width, pxm_height);
|
||||
|
||||
full = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -995,9 +1242,10 @@ repair_win (MetaCompWindow *cw)
|
||||
* If we are using TFP we update the whole texture (this simply trigers
|
||||
* the texture rebind).
|
||||
*/
|
||||
if (CLUTTER_GLX_IS_TEXTURE_PIXMAP (priv->actor) &&
|
||||
clutter_glx_texture_pixmap_using_extension (
|
||||
CLUTTER_GLX_TEXTURE_PIXMAP (priv->actor)))
|
||||
if (full ||
|
||||
(CLUTTER_GLX_IS_TEXTURE_PIXMAP (priv->actor) &&
|
||||
clutter_glx_texture_pixmap_using_extension (
|
||||
CLUTTER_GLX_TEXTURE_PIXMAP (priv->actor))))
|
||||
{
|
||||
XDamageSubtract (xdisplay, priv->damage, None, None);
|
||||
|
||||
@ -1041,6 +1289,8 @@ repair_win (MetaCompWindow *cw)
|
||||
}
|
||||
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
|
||||
priv->needs_repair = FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -1109,9 +1359,20 @@ process_damage (MetaCompositorClutter *compositor,
|
||||
|
||||
priv = cw->priv;
|
||||
|
||||
if (priv->destroy_pending)
|
||||
return;
|
||||
if (priv->destroy_pending ||
|
||||
priv->maximize_in_progress ||
|
||||
priv->unmaximize_in_progress)
|
||||
{
|
||||
priv->needs_repair = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the event queue does not already contain DetstroyNotify for this
|
||||
* window -- if it does, we need to stop updating the pixmap (to avoid damage
|
||||
* notifications that come from the window teardown), and process the destroy
|
||||
* immediately.
|
||||
*/
|
||||
if (XCheckTypedWindowEvent (dpy, drawable, DestroyNotify, &next))
|
||||
{
|
||||
priv->destroy_pending = TRUE;
|
||||
@ -1138,6 +1399,9 @@ process_configure_notify (MetaCompositorClutter *compositor,
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Check for root window geometry change
|
||||
*/
|
||||
GSList *l = meta_display_get_screens (display);
|
||||
|
||||
while (l)
|
||||
@ -1188,8 +1452,8 @@ process_circulate_notify (MetaCompositorClutter *compositor,
|
||||
above = top->priv->xwindow;
|
||||
else
|
||||
above = None;
|
||||
restack_win (cw, above);
|
||||
|
||||
restack_win (cw, above);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1213,7 +1477,7 @@ process_unmap (MetaCompositorClutter *compositor,
|
||||
XEvent next;
|
||||
MetaCompWindowPrivate *priv = cw->priv;
|
||||
|
||||
if (priv->destroy_pending)
|
||||
if (priv->attrs.map_state == IsUnmapped || priv->destroy_pending)
|
||||
return;
|
||||
|
||||
if (XCheckTypedWindowEvent (dpy, xwin, DestroyNotify, &next))
|
||||
@ -1224,7 +1488,7 @@ process_unmap (MetaCompositorClutter *compositor,
|
||||
}
|
||||
|
||||
meta_verbose ("processing unmap of 0x%x (%p)\n", (guint)xwin, cw);
|
||||
unmap_win (compositor->display, priv->screen, xwin);
|
||||
unmap_win (cw);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1237,7 +1501,7 @@ process_map (MetaCompositorClutter *compositor,
|
||||
event->window);
|
||||
|
||||
if (cw)
|
||||
map_win (compositor->display, cw->priv->screen, event->window);
|
||||
map_win (cw);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1374,21 +1638,13 @@ clutter_cmp_manage_screen (MetaCompositor *compositor,
|
||||
|
||||
XReparentWindow (xdisplay, xwin, info->output, 0, 0);
|
||||
|
||||
info->plugin_mgr =
|
||||
meta_compositor_clutter_plugin_manager_new (screen, info->stage);
|
||||
|
||||
clutter_actor_show_all (info->stage);
|
||||
|
||||
/* Now we're up and running we can show the output if needed */
|
||||
show_overlay_window (screen, info->output);
|
||||
|
||||
info->destroy_effect
|
||||
= clutter_effect_template_new (clutter_timeline_new_for_duration (
|
||||
DESTROY_TIMEOUT),
|
||||
CLUTTER_ALPHA_SINE_INC);
|
||||
|
||||
|
||||
info->minimize_effect
|
||||
= clutter_effect_template_new (clutter_timeline_new_for_duration (
|
||||
MINIMIZE_TIMEOUT),
|
||||
CLUTTER_ALPHA_SINE_INC);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1531,22 +1787,16 @@ clutter_cmp_set_active_window (MetaCompositor *compositor,
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
on_destroy_effect_complete (ClutterActor *actor,
|
||||
gpointer user_data)
|
||||
{
|
||||
clutter_actor_destroy (actor);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_cmp_destroy_window (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
MetaCompWindow *cw = NULL;
|
||||
MetaScreen *screen = meta_window_get_screen (window);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
MetaFrame *f = meta_window_get_frame (window);
|
||||
MetaCompWindow *cw = NULL;
|
||||
MetaScreen *screen = meta_window_get_screen (window);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
MetaFrame *f = meta_window_get_frame (window);
|
||||
MetaCompWindowPrivate *priv;
|
||||
|
||||
/* Chances are we actually get the window frame here */
|
||||
cw = find_window_for_screen (screen,
|
||||
@ -1555,6 +1805,8 @@ clutter_cmp_destroy_window (MetaCompositor *compositor,
|
||||
if (!cw)
|
||||
return;
|
||||
|
||||
priv = cw->priv;
|
||||
|
||||
/*
|
||||
* We remove the window from internal lookup hashes and thus any other
|
||||
* unmap events etc fail
|
||||
@ -1564,38 +1816,22 @@ clutter_cmp_destroy_window (MetaCompositor *compositor,
|
||||
(gpointer) (f ? meta_frame_get_xwindow (f) :
|
||||
meta_window_get_xwindow (window)));
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (CLUTTER_ACTOR (cw),
|
||||
CLUTTER_GRAVITY_CENTER);
|
||||
|
||||
clutter_effect_fade (info->destroy_effect,
|
||||
CLUTTER_ACTOR (cw),
|
||||
0,
|
||||
on_destroy_effect_complete,
|
||||
(gpointer)cw);
|
||||
|
||||
clutter_effect_scale (info->destroy_effect ,
|
||||
CLUTTER_ACTOR (cw),
|
||||
1.0,
|
||||
0.0,
|
||||
NULL,
|
||||
NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
on_minimize_effect_complete (ClutterActor *actor,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaCompWindow *cw = (MetaCompWindow *)user_data;
|
||||
|
||||
/*
|
||||
* Must reverse the effect of the effect once we hide the actor.
|
||||
* If a plugin manager is present, try to run an effect; if no effect of this
|
||||
* type is present, destroy the actor.
|
||||
*/
|
||||
clutter_actor_hide (CLUTTER_ACTOR (cw));
|
||||
clutter_actor_set_opacity (CLUTTER_ACTOR (cw), cw->priv->opacity);
|
||||
clutter_actor_set_scale (CLUTTER_ACTOR (cw), 1.0, 1.0);
|
||||
clutter_actor_move_anchor_point_from_gravity (CLUTTER_ACTOR (cw),
|
||||
CLUTTER_GRAVITY_NORTH_WEST);
|
||||
priv->destroy_in_progress++;
|
||||
|
||||
if (!info->plugin_mgr ||
|
||||
!meta_compositor_clutter_plugin_manager_event_0 (info->plugin_mgr,
|
||||
CLUTTER_ACTOR (cw),
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_DESTROY,
|
||||
cw->priv->type, 0))
|
||||
{
|
||||
priv->destroy_in_progress--;
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (cw));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1617,29 +1853,185 @@ clutter_cmp_minimize_window (MetaCompositor *compositor, MetaWindow *window)
|
||||
if (!cw)
|
||||
return;
|
||||
|
||||
meta_verbose ("Animating minimize of 0x%x\n",
|
||||
(guint)meta_window_get_xwindow (window));
|
||||
/*
|
||||
* If there is a plugin manager, try to run an effect; if no effect is
|
||||
* executed, hide the actor.
|
||||
*/
|
||||
cw->priv->minimize_in_progress++;
|
||||
|
||||
cw->priv->minimize_in_progress = TRUE;
|
||||
if (!info->plugin_mgr ||
|
||||
!meta_compositor_clutter_plugin_manager_event_0 (info->plugin_mgr,
|
||||
CLUTTER_ACTOR (cw),
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_MINIMIZE,
|
||||
cw->priv->type, 0))
|
||||
{
|
||||
ClutterActor *a = CLUTTER_ACTOR (cw);
|
||||
gint height = clutter_actor_get_height (a);
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (CLUTTER_ACTOR (cw),
|
||||
CLUTTER_GRAVITY_SOUTH_WEST);
|
||||
|
||||
clutter_effect_fade (info->minimize_effect,
|
||||
CLUTTER_ACTOR (cw),
|
||||
0,
|
||||
on_minimize_effect_complete,
|
||||
(gpointer)cw);
|
||||
|
||||
clutter_effect_scale (info->minimize_effect,
|
||||
CLUTTER_ACTOR (cw),
|
||||
0.0,
|
||||
0.0,
|
||||
NULL,
|
||||
NULL);
|
||||
cw->priv->is_minimized = TRUE;
|
||||
cw->priv->minimize_in_progress--;
|
||||
clutter_actor_set_position (a, 0, -height);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_cmp_maximize_window (MetaCompositor *compositor, MetaWindow *window,
|
||||
gint x, gint y, gint width, gint height)
|
||||
{
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
MetaCompWindow *cw;
|
||||
MetaCompScreen *info;
|
||||
MetaScreen *screen;
|
||||
MetaFrame *f = meta_window_get_frame (window);
|
||||
|
||||
screen = meta_window_get_screen (window);
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
/* Chances are we actually get the window frame here */
|
||||
cw = find_window_for_screen (screen,
|
||||
f ? meta_frame_get_xwindow (f) :
|
||||
meta_window_get_xwindow (window));
|
||||
if (!cw)
|
||||
return;
|
||||
|
||||
cw->priv->maximize_in_progress++;
|
||||
|
||||
if (!info->plugin_mgr ||
|
||||
!meta_compositor_clutter_plugin_manager_event_4i (info->plugin_mgr,
|
||||
CLUTTER_ACTOR (cw),
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_MAXIMIZE,
|
||||
cw->priv->type, 0, x, y, width, height))
|
||||
{
|
||||
cw->priv->maximize_in_progress--;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_cmp_unmaximize_window (MetaCompositor *compositor, MetaWindow *window,
|
||||
gint x, gint y, gint width, gint height)
|
||||
{
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
MetaCompWindow *cw;
|
||||
MetaCompScreen *info;
|
||||
MetaScreen *screen;
|
||||
MetaFrame *f = meta_window_get_frame (window);
|
||||
|
||||
screen = meta_window_get_screen (window);
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
/* Chances are we actually get the window frame here */
|
||||
cw = find_window_for_screen (screen,
|
||||
f ? meta_frame_get_xwindow (f) :
|
||||
meta_window_get_xwindow (window));
|
||||
if (!cw)
|
||||
return;
|
||||
|
||||
cw->priv->unmaximize_in_progress++;
|
||||
|
||||
if (!info->plugin_mgr ||
|
||||
!meta_compositor_clutter_plugin_manager_event_4i (info->plugin_mgr,
|
||||
CLUTTER_ACTOR (cw),
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_UNMAXIMIZE,
|
||||
cw->priv->type, 0, x, y, width, height))
|
||||
{
|
||||
cw->priv->unmaximize_in_progress--;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_cmp_update_workspace_geometry (MetaCompositor *compositor,
|
||||
MetaWorkspace *workspace)
|
||||
{
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
MetaScreen *screen = meta_workspace_get_screen (workspace);
|
||||
MetaCompScreen *info;
|
||||
MetaCompositorClutterPluginManager *mgr;
|
||||
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
mgr = info->plugin_mgr;
|
||||
|
||||
if (!mgr || !workspace)
|
||||
return;
|
||||
|
||||
meta_compositor_clutter_plugin_manager_update_workspace (mgr, workspace);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_cmp_switch_workspace (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
MetaWorkspace *from,
|
||||
MetaWorkspace *to)
|
||||
{
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
MetaCompScreen *info;
|
||||
GList *l;
|
||||
gint to_indx, from_indx;
|
||||
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
to_indx = meta_workspace_index (to);
|
||||
from_indx = meta_workspace_index (from);
|
||||
|
||||
l = info->windows;
|
||||
while (l)
|
||||
{
|
||||
MetaCompWindow *cw = l->data;
|
||||
MetaWindow *mw = cw->priv->window;
|
||||
gboolean sticky;
|
||||
gint workspace = -1;
|
||||
|
||||
sticky = (!mw || meta_window_is_on_all_workspaces (mw));
|
||||
|
||||
if (!sticky)
|
||||
{
|
||||
MetaWorkspace *w;
|
||||
|
||||
w = meta_window_get_workspace (cw->priv->window);
|
||||
workspace = meta_workspace_index (w);
|
||||
|
||||
/*
|
||||
* If the window is not on the target workspace, mark it for
|
||||
* unmap.
|
||||
*/
|
||||
if (to_indx != workspace)
|
||||
{
|
||||
cw->priv->needs_unmap = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
cw->priv->needs_map = TRUE;
|
||||
cw->priv->needs_unmap = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach workspace number to the actor, so the plugin can use it.
|
||||
*/
|
||||
g_object_set_data (G_OBJECT (cw),
|
||||
META_COMPOSITOR_CLUTTER_PLUGIN_WORKSPACE_KEY,
|
||||
GINT_TO_POINTER (workspace));
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
info->switch_workspace_in_progress++;
|
||||
|
||||
if (!info->plugin_mgr ||
|
||||
!meta_compositor_clutter_plugin_manager_switch_workspace (
|
||||
info->plugin_mgr,
|
||||
(const GList **)&info->windows,
|
||||
from_indx,
|
||||
to_indx))
|
||||
{
|
||||
info->switch_workspace_in_progress--;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static MetaCompositor comp_info = {
|
||||
clutter_cmp_destroy,
|
||||
clutter_cmp_manage_screen,
|
||||
@ -1651,7 +2043,11 @@ static MetaCompositor comp_info = {
|
||||
clutter_cmp_get_window_pixmap,
|
||||
clutter_cmp_set_active_window,
|
||||
clutter_cmp_destroy_window,
|
||||
clutter_cmp_minimize_window
|
||||
clutter_cmp_minimize_window,
|
||||
clutter_cmp_maximize_window,
|
||||
clutter_cmp_unmaximize_window,
|
||||
clutter_cmp_update_workspace_geometry,
|
||||
clutter_cmp_switch_workspace
|
||||
};
|
||||
|
||||
MetaCompositor *
|
||||
|
@ -26,7 +26,10 @@
|
||||
#define META_COMPOSITOR_CLUTTER_H_
|
||||
|
||||
#include "types.h"
|
||||
#include "compositor-clutter-plugin.h"
|
||||
|
||||
MetaCompositor *meta_compositor_clutter_new (MetaDisplay *display);
|
||||
|
||||
void meta_compositor_clutter_window_effect_completed (ClutterActor *actor, gulong event);
|
||||
|
||||
#endif
|
||||
|
@ -55,6 +55,28 @@ struct _MetaCompositor
|
||||
|
||||
void (*minimize_window) (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
|
||||
void (*maximize_window) (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
void (*unmaximize_window) (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
void (*update_workspace_geometry) (MetaCompositor *compositor,
|
||||
MetaWorkspace *workspace);
|
||||
|
||||
void (*switch_workspace) (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
MetaWorkspace *from,
|
||||
MetaWorkspace *to);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -81,17 +81,6 @@ composite_at_least_version (MetaDisplay *display,
|
||||
|
||||
#endif
|
||||
|
||||
typedef enum _MetaCompWindowType
|
||||
{
|
||||
META_COMP_WINDOW_NORMAL,
|
||||
META_COMP_WINDOW_DND,
|
||||
META_COMP_WINDOW_DESKTOP,
|
||||
META_COMP_WINDOW_DOCK,
|
||||
META_COMP_WINDOW_MENU,
|
||||
META_COMP_WINDOW_DROP_DOWN_MENU,
|
||||
META_COMP_WINDOW_TOOLTIP,
|
||||
} MetaCompWindowType;
|
||||
|
||||
typedef enum _MetaShadowType
|
||||
{
|
||||
META_SHADOW_SMALL,
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "compositor-private.h"
|
||||
#include "compositor-xrender.h"
|
||||
#include "compositor-clutter.h"
|
||||
#include "prefs.h"
|
||||
|
||||
#ifdef WITH_CLUTTER
|
||||
int meta_compositor_can_use_clutter__ = 0;
|
||||
@ -35,7 +36,7 @@ meta_compositor_new (MetaDisplay *display)
|
||||
#ifdef WITH_CLUTTER
|
||||
/* At some point we would have a way to select between backends */
|
||||
/* return meta_compositor_xrender_new (display); */
|
||||
if (meta_compositor_can_use_clutter__)
|
||||
if (meta_compositor_can_use_clutter__ && !meta_prefs_get_clutter_disabled ())
|
||||
return meta_compositor_clutter_new (display);
|
||||
else
|
||||
#endif
|
||||
@ -188,3 +189,55 @@ meta_compositor_minimize_window (MetaCompositor *compositor,
|
||||
compositor->minimize_window (compositor, window);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_maximize_window (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
if (compositor && compositor->maximize_window)
|
||||
compositor->maximize_window (compositor, window, x, y, width, height);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_unmaximize_window (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
|
||||
{
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
if (compositor && compositor->unmaximize_window)
|
||||
compositor->unmaximize_window (compositor, window, x, y, width, height);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_update_workspace_geometry (MetaCompositor *compositor,
|
||||
MetaWorkspace *workspace)
|
||||
{
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
if (compositor && compositor->update_workspace_geometry)
|
||||
compositor->update_workspace_geometry (compositor, workspace);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_switch_workspace (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
MetaWorkspace *from,
|
||||
MetaWorkspace *to)
|
||||
{
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
if (compositor && compositor->switch_workspace)
|
||||
compositor->switch_workspace (compositor, screen, from, to);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
#include <config.h>
|
||||
#include "constraints.h"
|
||||
#include "workspace.h"
|
||||
#include "workspace-private.h"
|
||||
#include "place.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <config.h>
|
||||
#include "core.h"
|
||||
#include "frame-private.h"
|
||||
#include "workspace.h"
|
||||
#include "workspace-private.h"
|
||||
#include "prefs.h"
|
||||
|
||||
/* Looks up the MetaWindow representing the frame of the given X window.
|
||||
|
@ -49,7 +49,6 @@
|
||||
typedef struct _MetaKeyBinding MetaKeyBinding;
|
||||
typedef struct _MetaStack MetaStack;
|
||||
typedef struct _MetaUISlave MetaUISlave;
|
||||
typedef struct _MetaWorkspace MetaWorkspace;
|
||||
|
||||
typedef struct _MetaWindowPropHooks MetaWindowPropHooks;
|
||||
typedef struct _MetaGroupPropHooks MetaGroupPropHooks;
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include "prefs.h"
|
||||
#include "resizepopup.h"
|
||||
#include "xprops.h"
|
||||
#include "workspace.h"
|
||||
#include "workspace-private.h"
|
||||
#include "bell.h"
|
||||
#include "effects.h"
|
||||
#include "compositor.h"
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "edge-resistance.h"
|
||||
#include "boxes.h"
|
||||
#include "display-private.h"
|
||||
#include "workspace.h"
|
||||
#include "workspace-private.h"
|
||||
|
||||
/* A simple macro for whether a given window's edges are potentially
|
||||
* relevant for resistance/snapping during a move/resize operation
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
#include <config.h>
|
||||
#include "keybindings.h"
|
||||
#include "workspace.h"
|
||||
#include "workspace-private.h"
|
||||
#include "errors.h"
|
||||
#include "edge-resistance.h"
|
||||
#include "ui.h"
|
||||
|
317
src/core/prefs.c
317
src/core/prefs.c
@ -2,11 +2,11 @@
|
||||
|
||||
/* Metacity preferences */
|
||||
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington, Copyright (C) 2002 Red Hat Inc.
|
||||
* Copyright (C) 2006 Elijah Newren
|
||||
* Copyright (C) 2008 Thomas Thurman
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@ -16,7 +16,7 @@
|
||||
* 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
|
||||
@ -63,6 +63,10 @@
|
||||
|
||||
#define KEY_WORKSPACE_NAME_PREFIX "/apps/metacity/workspace_names/name_"
|
||||
|
||||
#ifdef WITH_CLUTTER
|
||||
#define KEY_CLUTTER_DISABLED "/apps/metacity/general/clutter_disabled"
|
||||
#define KEY_CLUTTER_PLUGINS "/apps/metacity/general/clutter_plugins"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GCONF
|
||||
static GConfClient *default_client = NULL;
|
||||
@ -105,6 +109,11 @@ static char *terminal_command = NULL;
|
||||
|
||||
static char *workspace_names[MAX_REASONABLE_WORKSPACES] = { NULL, };
|
||||
|
||||
#ifdef WITH_CLUTTER
|
||||
static gboolean clutter_disabled = FALSE;
|
||||
static GSList *clutter_plugins = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GCONF
|
||||
static gboolean handle_preference_update_enum (const gchar *key, GConfValue *value);
|
||||
|
||||
@ -407,6 +416,13 @@ static MetaBoolPreference preferences_bool[] =
|
||||
&compositing_manager,
|
||||
FALSE,
|
||||
},
|
||||
#ifdef WITH_CLUTTER
|
||||
{ "/apps/metacity/general/clutter_disabled",
|
||||
META_PREF_CLUTTER_DISABLED,
|
||||
&clutter_disabled,
|
||||
FALSE,
|
||||
},
|
||||
#endif
|
||||
{ NULL, 0, NULL, FALSE },
|
||||
};
|
||||
|
||||
@ -568,7 +584,7 @@ handle_preference_init_int (void)
|
||||
{
|
||||
MetaIntPreference *cursor = preferences_int;
|
||||
|
||||
|
||||
|
||||
while (cursor->key!=NULL)
|
||||
{
|
||||
gint value;
|
||||
@ -613,7 +629,7 @@ handle_preference_update_enum (const gchar *key, GConfValue *value)
|
||||
if (cursor->key==NULL)
|
||||
/* Didn't recognise that key. */
|
||||
return FALSE;
|
||||
|
||||
|
||||
/* Setting it to null (that is, removing it) always means
|
||||
* "don't change".
|
||||
*/
|
||||
@ -636,7 +652,7 @@ handle_preference_update_enum (const gchar *key, GConfValue *value)
|
||||
*/
|
||||
|
||||
old_value = * ((gint *) cursor->target);
|
||||
|
||||
|
||||
/* Now look it up... */
|
||||
|
||||
if (!gconf_string_to_enum (cursor->symtab,
|
||||
@ -651,7 +667,7 @@ handle_preference_update_enum (const gchar *key, GConfValue *value)
|
||||
* (We know the old value, so we can look up a suitable string in
|
||||
* the symtab.)
|
||||
*/
|
||||
|
||||
|
||||
meta_warning (_("GConf key '%s' is set to an invalid value\n"),
|
||||
key);
|
||||
return TRUE;
|
||||
@ -681,7 +697,7 @@ handle_preference_update_bool (const gchar *key, GConfValue *value)
|
||||
if (cursor->target==NULL)
|
||||
/* No work for us to do. */
|
||||
return TRUE;
|
||||
|
||||
|
||||
if (value==NULL)
|
||||
{
|
||||
/* Value was destroyed; let's get out of here. */
|
||||
@ -710,7 +726,7 @@ handle_preference_update_bool (const gchar *key, GConfValue *value)
|
||||
*/
|
||||
|
||||
old_value = * ((gboolean *) cursor->target);
|
||||
|
||||
|
||||
/* Now look it up... */
|
||||
|
||||
*((gboolean *) cursor->target) = gconf_value_get_bool (value);
|
||||
@ -796,7 +812,7 @@ handle_preference_update_int (const gchar *key, GConfValue *value)
|
||||
if (cursor->target==NULL)
|
||||
/* No work for us to do. */
|
||||
return TRUE;
|
||||
|
||||
|
||||
if (value==NULL)
|
||||
{
|
||||
/* Value was destroyed. */
|
||||
@ -836,7 +852,7 @@ handle_preference_update_int (const gchar *key, GConfValue *value)
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -876,7 +892,7 @@ meta_prefs_remove_listener (MetaPrefsChangedFunc func,
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
@ -891,9 +907,9 @@ emit_changed (MetaPreference pref)
|
||||
|
||||
meta_topic (META_DEBUG_PREFS, "Notifying listeners that pref %s changed\n",
|
||||
meta_preference_to_string (pref));
|
||||
|
||||
|
||||
copy = g_list_copy (listeners);
|
||||
|
||||
|
||||
tmp = copy;
|
||||
|
||||
while (tmp != NULL)
|
||||
@ -915,24 +931,24 @@ changed_idle_handler (gpointer data)
|
||||
GList *copy;
|
||||
|
||||
changed_idle = 0;
|
||||
|
||||
|
||||
copy = g_list_copy (changes); /* reentrancy paranoia */
|
||||
|
||||
g_list_free (changes);
|
||||
changes = NULL;
|
||||
|
||||
|
||||
tmp = copy;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaPreference pref = GPOINTER_TO_INT (tmp->data);
|
||||
|
||||
emit_changed (pref);
|
||||
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
g_list_free (copy);
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -940,7 +956,7 @@ static void
|
||||
queue_changed (MetaPreference pref)
|
||||
{
|
||||
meta_topic (META_DEBUG_PREFS, "Queueing change of pref %s\n",
|
||||
meta_preference_to_string (pref));
|
||||
meta_preference_to_string (pref));
|
||||
|
||||
if (g_list_find (changes, GINT_TO_POINTER (pref)) == NULL)
|
||||
changes = g_list_prepend (changes, GINT_TO_POINTER (pref));
|
||||
@ -993,10 +1009,10 @@ meta_prefs_init (void)
|
||||
#ifdef HAVE_GCONF
|
||||
GError *err = NULL;
|
||||
gchar **gconf_dir_cursor;
|
||||
|
||||
|
||||
if (default_client != NULL)
|
||||
return;
|
||||
|
||||
|
||||
/* returns a reference which we hold forever */
|
||||
default_client = gconf_client_get_default ();
|
||||
|
||||
@ -1018,6 +1034,13 @@ meta_prefs_init (void)
|
||||
handle_preference_init_string ();
|
||||
handle_preference_init_int ();
|
||||
|
||||
#ifdef WITH_CLUTTER
|
||||
clutter_plugins = gconf_client_get_list (default_client, KEY_CLUTTER_PLUGINS,
|
||||
GCONF_VALUE_STRING, &err);
|
||||
|
||||
cleanup_error (&err);
|
||||
#endif
|
||||
|
||||
/* @@@ Is there any reason we don't do the add_dir here? */
|
||||
for (gconf_dir_cursor=gconf_dirs_we_are_interested_in;
|
||||
*gconf_dir_cursor!=NULL;
|
||||
@ -1041,10 +1064,10 @@ meta_prefs_init (void)
|
||||
*/
|
||||
titlebar_font = pango_font_description_from_string ("Sans Bold 10");
|
||||
current_theme = g_strdup ("Atlanta");
|
||||
|
||||
|
||||
init_button_layout();
|
||||
#endif /* HAVE_GCONF */
|
||||
|
||||
|
||||
init_bindings ();
|
||||
init_commands ();
|
||||
init_workspace_names ();
|
||||
@ -1074,7 +1097,7 @@ change_notify (GConfClient *client,
|
||||
const char *key;
|
||||
GConfValue *value;
|
||||
gint i=0;
|
||||
|
||||
|
||||
key = gconf_entry_get_key (entry);
|
||||
value = gconf_entry_get_value (entry);
|
||||
|
||||
@ -1200,12 +1223,31 @@ change_notify (GConfClient *client,
|
||||
if (update_workspace_name (key, str))
|
||||
queue_changed (META_PREF_WORKSPACE_NAMES);
|
||||
}
|
||||
#ifdef WITH_CLUTTER
|
||||
else if (g_str_equal (key, KEY_CLUTTER_PLUGINS))
|
||||
{
|
||||
GError *err = NULL;
|
||||
GSList *l;
|
||||
|
||||
l = gconf_client_get_list (default_client, KEY_CLUTTER_PLUGINS,
|
||||
GCONF_VALUE_STRING, &err);
|
||||
|
||||
if (!l)
|
||||
{
|
||||
cleanup_error (&err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
clutter_plugins = l;
|
||||
queue_changed (META_PREF_CLUTTER_PLUGINS);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_PREFS, "Key %s doesn't mean anything to Metacity\n",
|
||||
key);
|
||||
}
|
||||
|
||||
|
||||
out:
|
||||
/* nothing */
|
||||
return; /* AIX compiler wants something after a label like out: */
|
||||
@ -1217,7 +1259,7 @@ cleanup_error (GError **error)
|
||||
if (*error)
|
||||
{
|
||||
meta_warning ("%s\n", (*error)->message);
|
||||
|
||||
|
||||
g_error_free (*error);
|
||||
*error = NULL;
|
||||
}
|
||||
@ -1255,7 +1297,7 @@ static void
|
||||
maybe_give_disable_workarounds_warning (void)
|
||||
{
|
||||
static gboolean first_disable = TRUE;
|
||||
|
||||
|
||||
if (first_disable && disable_workarounds)
|
||||
{
|
||||
first_disable = FALSE;
|
||||
@ -1389,7 +1431,7 @@ mouse_button_mods_handler (MetaPreference pref,
|
||||
{
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Failed to parse new gconf value\n");
|
||||
|
||||
|
||||
meta_warning (_("\"%s\" found in configuration database is "
|
||||
"not a valid value for mouse button modifier\n"),
|
||||
string_value);
|
||||
@ -1401,7 +1443,7 @@ mouse_button_mods_handler (MetaPreference pref,
|
||||
static gboolean
|
||||
button_layout_equal (const MetaButtonLayout *a,
|
||||
const MetaButtonLayout *b)
|
||||
{
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
@ -1440,7 +1482,7 @@ button_function_from_string (const char *str)
|
||||
return META_BUTTON_FUNCTION_ABOVE;
|
||||
else if (strcmp (str, "stick") == 0)
|
||||
return META_BUTTON_FUNCTION_STICK;
|
||||
else
|
||||
else
|
||||
/* don't know; give up */
|
||||
return META_BUTTON_FUNCTION_LAST;
|
||||
}
|
||||
@ -1478,11 +1520,11 @@ button_layout_handler (MetaPreference pref,
|
||||
MetaButtonLayout new_layout;
|
||||
char **sides;
|
||||
int i;
|
||||
|
||||
|
||||
/* We need to ignore unknown button functions, for
|
||||
* compat with future versions
|
||||
*/
|
||||
|
||||
|
||||
sides = g_strsplit (string_value, ":", 2);
|
||||
|
||||
if (sides[0] != NULL)
|
||||
@ -1498,7 +1540,7 @@ button_layout_handler (MetaPreference pref,
|
||||
new_layout.left_buttons_has_spacer[i] = FALSE;
|
||||
++i;
|
||||
}
|
||||
|
||||
|
||||
buttons = g_strsplit (sides[0], ",", -1);
|
||||
i = 0;
|
||||
b = 0;
|
||||
@ -1535,13 +1577,13 @@ button_layout_handler (MetaPreference pref,
|
||||
buttons[b]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
++b;
|
||||
}
|
||||
|
||||
new_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST;
|
||||
new_layout.left_buttons_has_spacer[i] = FALSE;
|
||||
|
||||
|
||||
g_strfreev (buttons);
|
||||
}
|
||||
|
||||
@ -1558,7 +1600,7 @@ button_layout_handler (MetaPreference pref,
|
||||
new_layout.right_buttons_has_spacer[i] = FALSE;
|
||||
++i;
|
||||
}
|
||||
|
||||
|
||||
buttons = g_strsplit (sides[1], ",", -1);
|
||||
i = 0;
|
||||
b = 0;
|
||||
@ -1594,24 +1636,24 @@ button_layout_handler (MetaPreference pref,
|
||||
buttons[b]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
++b;
|
||||
}
|
||||
|
||||
new_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST;
|
||||
new_layout.right_buttons_has_spacer[i] = FALSE;
|
||||
|
||||
|
||||
g_strfreev (buttons);
|
||||
}
|
||||
|
||||
g_strfreev (sides);
|
||||
|
||||
|
||||
/* Invert the button layout for RTL languages */
|
||||
if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
|
||||
{
|
||||
MetaButtonLayout rtl_layout;
|
||||
int j;
|
||||
|
||||
|
||||
for (i = 0; new_layout.left_buttons[i] != META_BUTTON_FUNCTION_LAST; i++);
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
@ -1623,7 +1665,7 @@ button_layout_handler (MetaPreference pref,
|
||||
}
|
||||
rtl_layout.right_buttons[j] = META_BUTTON_FUNCTION_LAST;
|
||||
rtl_layout.right_buttons_has_spacer[j] = FALSE;
|
||||
|
||||
|
||||
for (i = 0; new_layout.right_buttons[i] != META_BUTTON_FUNCTION_LAST; i++);
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
@ -1638,7 +1680,7 @@ button_layout_handler (MetaPreference pref,
|
||||
|
||||
new_layout = rtl_layout;
|
||||
}
|
||||
|
||||
|
||||
if (button_layout_equal (&button_layout, &new_layout))
|
||||
{
|
||||
/* Same as before, so duck out */
|
||||
@ -1671,7 +1713,7 @@ gboolean
|
||||
meta_prefs_get_application_based (void)
|
||||
{
|
||||
return FALSE; /* For now, we never want this to do anything */
|
||||
|
||||
|
||||
return application_based;
|
||||
}
|
||||
|
||||
@ -1683,7 +1725,7 @@ meta_prefs_get_disable_workarounds (void)
|
||||
|
||||
#ifdef HAVE_GCONF
|
||||
#define MAX_REASONABLE_AUTO_RAISE_DELAY 10000
|
||||
|
||||
|
||||
#endif /* HAVE_GCONF */
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
@ -1704,7 +1746,7 @@ meta_preference_to_string (MetaPreference pref)
|
||||
|
||||
case META_PREF_RAISE_ON_CLICK:
|
||||
return "RAISE_ON_CLICK";
|
||||
|
||||
|
||||
case META_PREF_THEME:
|
||||
return "THEME";
|
||||
|
||||
@ -1737,7 +1779,7 @@ meta_preference_to_string (MetaPreference pref)
|
||||
|
||||
case META_PREF_AUTO_RAISE:
|
||||
return "AUTO_RAISE";
|
||||
|
||||
|
||||
case META_PREF_AUTO_RAISE_DELAY:
|
||||
return "AUTO_RAISE_DELAY";
|
||||
|
||||
@ -1779,6 +1821,12 @@ meta_preference_to_string (MetaPreference pref)
|
||||
|
||||
case META_PREF_COMPOSITING_MANAGER:
|
||||
return "COMPOSITING_MANAGER";
|
||||
#ifdef WITH_CLUTTER
|
||||
case META_PREF_CLUTTER_DISABLED:
|
||||
return "CLUTTER_DISABLED";
|
||||
case META_PREF_CLUTTER_PLUGINS:
|
||||
return "CLUTTER_PLUGINS";
|
||||
#endif
|
||||
}
|
||||
|
||||
return "(unknown)";
|
||||
@ -1790,7 +1838,7 @@ meta_prefs_set_num_workspaces (int n_workspaces)
|
||||
{
|
||||
#ifdef HAVE_GCONF
|
||||
GError *err;
|
||||
|
||||
|
||||
if (default_client == NULL)
|
||||
return;
|
||||
|
||||
@ -1798,7 +1846,7 @@ meta_prefs_set_num_workspaces (int n_workspaces)
|
||||
n_workspaces = 1;
|
||||
if (n_workspaces > MAX_REASONABLE_WORKSPACES)
|
||||
n_workspaces = MAX_REASONABLE_WORKSPACES;
|
||||
|
||||
|
||||
err = NULL;
|
||||
gconf_client_set_int (default_client,
|
||||
KEY_NUM_WORKSPACES,
|
||||
@ -1824,7 +1872,7 @@ static MetaKeyPref screen_bindings[] = {
|
||||
{ META_KEYBINDING_WORKSPACE_5, NULL, FALSE },
|
||||
{ META_KEYBINDING_WORKSPACE_6, NULL, FALSE },
|
||||
{ META_KEYBINDING_WORKSPACE_7, NULL, FALSE },
|
||||
{ META_KEYBINDING_WORKSPACE_8, NULL, FALSE },
|
||||
{ META_KEYBINDING_WORKSPACE_8, NULL, FALSE },
|
||||
{ META_KEYBINDING_WORKSPACE_9, NULL, FALSE },
|
||||
{ META_KEYBINDING_WORKSPACE_10, NULL, FALSE },
|
||||
{ META_KEYBINDING_WORKSPACE_11, NULL, FALSE },
|
||||
@ -1855,7 +1903,7 @@ static MetaKeyPref screen_bindings[] = {
|
||||
{ META_KEYBINDING_COMMAND_5, NULL, FALSE },
|
||||
{ META_KEYBINDING_COMMAND_6, NULL, FALSE },
|
||||
{ META_KEYBINDING_COMMAND_7, NULL, FALSE },
|
||||
{ META_KEYBINDING_COMMAND_8, NULL, FALSE },
|
||||
{ META_KEYBINDING_COMMAND_8, NULL, FALSE },
|
||||
{ META_KEYBINDING_COMMAND_9, NULL, FALSE },
|
||||
{ META_KEYBINDING_COMMAND_10, NULL, FALSE },
|
||||
{ META_KEYBINDING_COMMAND_11, NULL, FALSE },
|
||||
@ -1941,7 +1989,7 @@ init_bindings (void)
|
||||
#ifdef HAVE_GCONF
|
||||
int i;
|
||||
GError *err;
|
||||
|
||||
|
||||
i = 0;
|
||||
while (window_bindings[i].name)
|
||||
{
|
||||
@ -1958,7 +2006,7 @@ init_bindings (void)
|
||||
|
||||
update_binding (&window_bindings[i], str_val);
|
||||
|
||||
g_free (str_val);
|
||||
g_free (str_val);
|
||||
g_free (key);
|
||||
|
||||
key = g_strconcat (KEY_WINDOW_BINDINGS_PREFIX, "/",
|
||||
@ -2000,7 +2048,7 @@ init_bindings (void)
|
||||
|
||||
update_binding (&screen_bindings[i], str_val);
|
||||
|
||||
g_free (str_val);
|
||||
g_free (str_val);
|
||||
g_free (key);
|
||||
|
||||
key = g_strconcat (KEY_SCREEN_BINDINGS_PREFIX, "/",
|
||||
@ -2033,7 +2081,7 @@ init_bindings (void)
|
||||
/* Find which window_bindings entry this window_string_bindings entry
|
||||
* corresponds to.
|
||||
*/
|
||||
while (strcmp(window_bindings[which].name,
|
||||
while (strcmp(window_bindings[which].name,
|
||||
window_string_bindings[i].name) != 0)
|
||||
which++;
|
||||
|
||||
@ -2051,12 +2099,12 @@ init_bindings (void)
|
||||
/* Find which window_bindings entry this window_string_bindings entry
|
||||
* corresponds to.
|
||||
*/
|
||||
while (strcmp(screen_bindings[which].name,
|
||||
while (strcmp(screen_bindings[which].name,
|
||||
screen_string_bindings[i].name) != 0)
|
||||
which++;
|
||||
|
||||
/* Set the binding */
|
||||
update_binding (&screen_bindings[which],
|
||||
update_binding (&screen_bindings[which],
|
||||
screen_string_bindings[i].keybinding);
|
||||
|
||||
++i;
|
||||
@ -2070,7 +2118,7 @@ init_commands (void)
|
||||
#ifdef HAVE_GCONF
|
||||
int i;
|
||||
GError *err;
|
||||
|
||||
|
||||
i = 0;
|
||||
while (i < MAX_COMMANDS)
|
||||
{
|
||||
@ -2085,7 +2133,7 @@ init_commands (void)
|
||||
|
||||
update_command (key, str_val);
|
||||
|
||||
g_free (str_val);
|
||||
g_free (str_val);
|
||||
g_free (key);
|
||||
|
||||
++i;
|
||||
@ -2103,7 +2151,7 @@ init_workspace_names (void)
|
||||
#ifdef HAVE_GCONF
|
||||
int i;
|
||||
GError *err;
|
||||
|
||||
|
||||
i = 0;
|
||||
while (i < MAX_REASONABLE_WORKSPACES)
|
||||
{
|
||||
@ -2119,8 +2167,8 @@ init_workspace_names (void)
|
||||
update_workspace_name (key, str_val);
|
||||
|
||||
g_assert (workspace_names[i] != NULL);
|
||||
|
||||
g_free (str_val);
|
||||
|
||||
g_free (str_val);
|
||||
g_free (key);
|
||||
|
||||
++i;
|
||||
@ -2144,11 +2192,11 @@ update_binding (MetaKeyPref *binding,
|
||||
MetaVirtualModifier mods;
|
||||
MetaKeyCombo *combo;
|
||||
gboolean changed;
|
||||
|
||||
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Binding \"%s\" has new gconf value \"%s\"\n",
|
||||
binding->name, value ? value : "none");
|
||||
|
||||
|
||||
keysym = 0;
|
||||
keycode = 0;
|
||||
mods = 0;
|
||||
@ -2172,7 +2220,7 @@ update_binding (MetaKeyPref *binding,
|
||||
binding->bindings = g_slist_alloc();
|
||||
binding->bindings->data = blank;
|
||||
}
|
||||
|
||||
|
||||
combo = binding->bindings->data;
|
||||
|
||||
#ifdef HAVE_GCONF
|
||||
@ -2187,7 +2235,7 @@ update_binding (MetaKeyPref *binding,
|
||||
gchar *old_setting;
|
||||
gchar *key;
|
||||
GError *err = NULL;
|
||||
|
||||
|
||||
meta_warning ("Cannot bind \"%s\" to %s: it needs a modifier "
|
||||
"such as Ctrl or Alt.\n",
|
||||
binding->name,
|
||||
@ -2214,7 +2262,7 @@ update_binding (MetaKeyPref *binding,
|
||||
|
||||
key = g_strconcat (KEY_SCREEN_BINDINGS_PREFIX, "/",
|
||||
binding->name, NULL);
|
||||
|
||||
|
||||
gconf_client_set_string (gconf_client_get_default (),
|
||||
key, old_setting, &err);
|
||||
|
||||
@ -2225,7 +2273,7 @@ update_binding (MetaKeyPref *binding,
|
||||
g_error_free (err);
|
||||
err = NULL;
|
||||
}
|
||||
|
||||
|
||||
g_free (old_setting);
|
||||
g_free (key);
|
||||
|
||||
@ -2236,18 +2284,18 @@ update_binding (MetaKeyPref *binding,
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
changed = FALSE;
|
||||
if (keysym != combo->keysym ||
|
||||
keycode != combo->keycode ||
|
||||
mods != combo->modifiers)
|
||||
{
|
||||
changed = TRUE;
|
||||
|
||||
|
||||
combo->keysym = keysym;
|
||||
combo->keycode = keycode;
|
||||
combo->modifiers = mods;
|
||||
|
||||
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n",
|
||||
binding->name, combo->keysym, combo->keycode,
|
||||
@ -2258,7 +2306,7 @@ update_binding (MetaKeyPref *binding,
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Keybinding for \"%s\" is unchanged\n", binding->name);
|
||||
}
|
||||
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
@ -2279,7 +2327,7 @@ update_list_binding (MetaKeyPref *binding,
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Binding \"%s\" has new gconf value\n",
|
||||
binding->name);
|
||||
|
||||
|
||||
if (binding->bindings == NULL)
|
||||
{
|
||||
/* We need to insert a dummy element into the list, because the first
|
||||
@ -2290,7 +2338,7 @@ update_list_binding (MetaKeyPref *binding,
|
||||
binding->bindings = g_slist_alloc();
|
||||
binding->bindings->data = blank;
|
||||
}
|
||||
|
||||
|
||||
/* Okay, so, we're about to provide a new list of key combos for this
|
||||
* action. Delete any pre-existing list.
|
||||
*/
|
||||
@ -2302,7 +2350,7 @@ update_list_binding (MetaKeyPref *binding,
|
||||
}
|
||||
g_slist_free (binding->bindings->next);
|
||||
binding->bindings->next = NULL;
|
||||
|
||||
|
||||
while (pref_iterator)
|
||||
{
|
||||
keysym = 0;
|
||||
@ -2326,7 +2374,7 @@ update_list_binding (MetaKeyPref *binding,
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
|
||||
if (!meta_ui_parse_accelerator (pref_string, &keysym, &keycode, &mods))
|
||||
{
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
@ -2357,7 +2405,7 @@ update_list_binding (MetaKeyPref *binding,
|
||||
pref_iterator = pref_iterator->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
changed = TRUE;
|
||||
|
||||
combo = g_malloc0 (sizeof (MetaKeyCombo));
|
||||
@ -2371,7 +2419,7 @@ update_list_binding (MetaKeyPref *binding,
|
||||
binding->name, keysym, keycode, mods);
|
||||
|
||||
pref_iterator = pref_iterator->next;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
@ -2379,7 +2427,7 @@ static const gchar*
|
||||
relative_key (const gchar* key)
|
||||
{
|
||||
const gchar* end;
|
||||
|
||||
|
||||
end = strrchr (key, '/');
|
||||
|
||||
++end;
|
||||
@ -2391,13 +2439,13 @@ relative_key (const gchar* key)
|
||||
* notify
|
||||
*/
|
||||
static gboolean
|
||||
find_and_update_binding (MetaKeyPref *bindings,
|
||||
find_and_update_binding (MetaKeyPref *bindings,
|
||||
const char *name,
|
||||
const char *value)
|
||||
{
|
||||
const char *key;
|
||||
int i;
|
||||
|
||||
|
||||
if (*name == '/')
|
||||
key = relative_key (name);
|
||||
else
|
||||
@ -2477,7 +2525,7 @@ update_command (const char *name,
|
||||
{
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
|
||||
p = strrchr (name, '_');
|
||||
if (p == NULL)
|
||||
{
|
||||
@ -2485,7 +2533,7 @@ update_command (const char *name,
|
||||
"Command %s has no underscore?\n", name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
++p;
|
||||
|
||||
if (g_ascii_isdigit (*p))
|
||||
@ -2513,7 +2561,7 @@ update_command (const char *name,
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (i >= MAX_COMMANDS)
|
||||
{
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
@ -2528,14 +2576,14 @@ update_command (const char *name,
|
||||
"Command %d is unchanged\n", i);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
g_free (commands[i]);
|
||||
commands[i] = g_strdup (value);
|
||||
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Updated command %d to \"%s\"\n",
|
||||
i, commands[i] ? commands[i] : "none");
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -2545,7 +2593,7 @@ const char*
|
||||
meta_prefs_get_command (int i)
|
||||
{
|
||||
g_return_val_if_fail (i >= 0 && i < MAX_COMMANDS, NULL);
|
||||
|
||||
|
||||
return commands[i];
|
||||
}
|
||||
|
||||
@ -2566,7 +2614,7 @@ meta_prefs_get_gconf_key_for_command (int i)
|
||||
key = g_strdup_printf (KEY_COMMAND_PREFIX"%d", i + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
@ -2589,7 +2637,7 @@ update_workspace_name (const char *name,
|
||||
{
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
|
||||
p = strrchr (name, '_');
|
||||
if (p == NULL)
|
||||
{
|
||||
@ -2597,7 +2645,7 @@ update_workspace_name (const char *name,
|
||||
"Workspace name %s has no underscore?\n", name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
++p;
|
||||
|
||||
if (!g_ascii_isdigit (*p))
|
||||
@ -2606,10 +2654,10 @@ update_workspace_name (const char *name,
|
||||
"Workspace name %s doesn't end in number?\n", name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
i = atoi (p);
|
||||
i -= 1; /* count from 0 not 1 */
|
||||
|
||||
|
||||
if (i >= MAX_REASONABLE_WORKSPACES)
|
||||
{
|
||||
meta_topic (META_DEBUG_PREFS,
|
||||
@ -2622,7 +2670,7 @@ update_workspace_name (const char *name,
|
||||
meta_topic (META_DEBUG_PREFS,
|
||||
"Workspace name %d is unchanged\n", i);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is a bad hack. We have to treat empty string as
|
||||
* "unset" because the root window property can't contain
|
||||
@ -2652,11 +2700,11 @@ update_workspace_name (const char *name,
|
||||
workspace_names[i] = d;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
meta_topic (META_DEBUG_PREFS,
|
||||
"Updated workspace name %d to \"%s\"\n",
|
||||
i, workspace_names[i] ? workspace_names[i] : "none");
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* HAVE_GCONF */
|
||||
@ -2671,7 +2719,7 @@ meta_prefs_get_workspace_name (int i)
|
||||
meta_topic (META_DEBUG_PREFS,
|
||||
"Getting workspace name for %d: \"%s\"\n",
|
||||
i, workspace_names[i]);
|
||||
|
||||
|
||||
return workspace_names[i];
|
||||
}
|
||||
|
||||
@ -2682,7 +2730,7 @@ meta_prefs_change_workspace_name (int i,
|
||||
#ifdef HAVE_GCONF
|
||||
char *key;
|
||||
GError *err;
|
||||
|
||||
|
||||
g_return_if_fail (i >= 0 && i < MAX_REASONABLE_WORKSPACES);
|
||||
|
||||
meta_topic (META_DEBUG_PREFS,
|
||||
@ -2697,7 +2745,7 @@ meta_prefs_change_workspace_name (int i,
|
||||
*/
|
||||
if (name && *name == '\0')
|
||||
name = NULL;
|
||||
|
||||
|
||||
if ((name == NULL && workspace_names[i] == NULL) ||
|
||||
(name && workspace_names[i] && strcmp (name, workspace_names[i]) == 0))
|
||||
{
|
||||
@ -2706,7 +2754,7 @@ meta_prefs_change_workspace_name (int i,
|
||||
i, name ? name : "none");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
key = gconf_key_for_workspace_name (i);
|
||||
|
||||
err = NULL;
|
||||
@ -2718,7 +2766,7 @@ meta_prefs_change_workspace_name (int i,
|
||||
gconf_client_unset (default_client,
|
||||
key, &err);
|
||||
|
||||
|
||||
|
||||
if (err)
|
||||
{
|
||||
meta_warning (_("Error setting name for workspace %d to \"%s\": %s\n"),
|
||||
@ -2726,7 +2774,7 @@ meta_prefs_change_workspace_name (int i,
|
||||
err->message);
|
||||
g_error_free (err);
|
||||
}
|
||||
|
||||
|
||||
g_free (key);
|
||||
#else
|
||||
g_free (workspace_names[i]);
|
||||
@ -2739,9 +2787,9 @@ static char*
|
||||
gconf_key_for_workspace_name (int i)
|
||||
{
|
||||
char *key;
|
||||
|
||||
|
||||
key = g_strdup_printf (KEY_WORKSPACE_NAME_PREFIX"%d", i + 1);
|
||||
|
||||
|
||||
return key;
|
||||
}
|
||||
#endif /* HAVE_GCONF */
|
||||
@ -2774,7 +2822,7 @@ void
|
||||
meta_prefs_get_screen_bindings (const MetaKeyPref **bindings,
|
||||
int *n_bindings)
|
||||
{
|
||||
|
||||
|
||||
*bindings = screen_bindings;
|
||||
*n_bindings = (int) G_N_ELEMENTS (screen_bindings) - 1;
|
||||
}
|
||||
@ -2845,7 +2893,7 @@ meta_prefs_get_keybinding_action (const char *name)
|
||||
{
|
||||
if (strcmp (screen_bindings[i].name, name) == 0)
|
||||
return (MetaKeyBindingAction) i;
|
||||
|
||||
|
||||
--i;
|
||||
}
|
||||
|
||||
@ -2888,7 +2936,7 @@ meta_prefs_get_window_binding (const char *name,
|
||||
*keysym = *modifiers = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
--i;
|
||||
}
|
||||
|
||||
@ -2923,12 +2971,67 @@ meta_prefs_set_compositing_manager (gboolean whether)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WITH_CLUTTER
|
||||
gboolean
|
||||
meta_prefs_get_clutter_disabled (void)
|
||||
{
|
||||
return clutter_disabled;
|
||||
}
|
||||
|
||||
void
|
||||
meta_prefs_set_clutter_disabled (gboolean whether)
|
||||
{
|
||||
#ifdef HAVE_GCONF
|
||||
GError *err = NULL;
|
||||
|
||||
gconf_client_set_bool (default_client,
|
||||
KEY_CLUTTER_DISABLED,
|
||||
whether,
|
||||
&err);
|
||||
|
||||
if (err)
|
||||
{
|
||||
meta_warning (_("Error setting clutter status status: %s\n"),
|
||||
err->message);
|
||||
g_error_free (err);
|
||||
}
|
||||
#else
|
||||
clutter_disabled = whether;
|
||||
#endif
|
||||
}
|
||||
|
||||
GSList *
|
||||
meta_prefs_get_clutter_plugins (void)
|
||||
{
|
||||
return clutter_plugins;
|
||||
}
|
||||
|
||||
void
|
||||
meta_prefs_set_clutter_plugins (GSList *list)
|
||||
{
|
||||
GError *err = NULL;
|
||||
|
||||
gconf_client_set_list (default_client,
|
||||
KEY_CLUTTER_PLUGINS,
|
||||
GCONF_VALUE_STRING,
|
||||
list,
|
||||
&err);
|
||||
|
||||
if (err)
|
||||
{
|
||||
meta_warning (_("Error setting clutter plugin list: %s\n"),
|
||||
err->message);
|
||||
g_error_free (err);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GCONF
|
||||
static void
|
||||
init_button_layout(void)
|
||||
{
|
||||
MetaButtonLayout button_layout_ltr = {
|
||||
{
|
||||
{
|
||||
/* buttons in the group on the left side */
|
||||
META_BUTTON_FUNCTION_MENU,
|
||||
META_BUTTON_FUNCTION_LAST
|
||||
@ -2942,7 +3045,7 @@ init_button_layout(void)
|
||||
}
|
||||
};
|
||||
MetaButtonLayout button_layout_rtl = {
|
||||
{
|
||||
{
|
||||
/* buttons in the group on the left side */
|
||||
META_BUTTON_FUNCTION_CLOSE,
|
||||
META_BUTTON_FUNCTION_MAXIMIZE,
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include "window-private.h"
|
||||
#include "frame-private.h"
|
||||
#include "prefs.h"
|
||||
#include "workspace.h"
|
||||
#include "workspace-private.h"
|
||||
#include "keybindings.h"
|
||||
#include "stack.h"
|
||||
#include "xprops.h"
|
||||
@ -2800,3 +2800,10 @@ meta_screen_unset_cm_selection (MetaScreen *screen)
|
||||
XSetSelectionOwner (screen->display->xdisplay, a, None, CurrentTime);
|
||||
}
|
||||
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
||||
|
||||
GList *
|
||||
meta_screen_get_workspaces (MetaScreen *screen)
|
||||
{
|
||||
return screen->workspaces;
|
||||
}
|
||||
|
||||
|
@ -49,12 +49,6 @@ typedef struct _MetaWindowQueue MetaWindowQueue;
|
||||
typedef gboolean (*MetaWindowForeachFunc) (MetaWindow *window,
|
||||
void *data);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_MAXIMIZE_HORIZONTAL = 1 << 0,
|
||||
META_MAXIMIZE_VERTICAL = 1 << 1
|
||||
} MetaMaximizeFlags;
|
||||
|
||||
typedef enum {
|
||||
META_CLIENT_TYPE_UNKNOWN = 0,
|
||||
META_CLIENT_TYPE_APPLICATION = 1,
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "util.h"
|
||||
#include "frame-private.h"
|
||||
#include "errors.h"
|
||||
#include "workspace.h"
|
||||
#include "workspace-private.h"
|
||||
#include "stack.h"
|
||||
#include "keybindings.h"
|
||||
#include "ui.h"
|
||||
@ -2582,9 +2582,23 @@ meta_window_maximize (MetaWindow *window,
|
||||
directions,
|
||||
NULL);
|
||||
|
||||
/* move_resize with new maximization constraints
|
||||
*/
|
||||
meta_window_queue(window, META_QUEUE_MOVE_RESIZE);
|
||||
if (window->display->compositor)
|
||||
{
|
||||
meta_window_move_resize_now (window);
|
||||
|
||||
meta_compositor_maximize_window (window->display->compositor,
|
||||
window,
|
||||
window->frame->rect.x,
|
||||
window->frame->rect.y,
|
||||
window->frame->rect.width,
|
||||
window->frame->rect.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* move_resize with new maximization constraints
|
||||
*/
|
||||
meta_window_queue(window, META_QUEUE_MOVE_RESIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2681,12 +2695,32 @@ meta_window_unmaximize (MetaWindow *window,
|
||||
window->display->grab_anchor_window_pos = target_rect;
|
||||
}
|
||||
|
||||
meta_window_move_resize (window,
|
||||
FALSE,
|
||||
target_rect.x,
|
||||
target_rect.y,
|
||||
target_rect.width,
|
||||
target_rect.height);
|
||||
if (window->display->compositor)
|
||||
{
|
||||
meta_window_move_resize (window,
|
||||
FALSE,
|
||||
target_rect.x,
|
||||
target_rect.y,
|
||||
target_rect.width,
|
||||
target_rect.height);
|
||||
meta_window_move_resize_now (window);
|
||||
|
||||
meta_compositor_unmaximize_window (window->display->compositor,
|
||||
window,
|
||||
window->frame->rect.x,
|
||||
window->frame->rect.y,
|
||||
window->frame->rect.width,
|
||||
window->frame->rect.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_window_move_resize (window,
|
||||
FALSE,
|
||||
target_rect.x,
|
||||
target_rect.y,
|
||||
target_rect.width,
|
||||
target_rect.height);
|
||||
}
|
||||
|
||||
if (window->display->grab_wireframe_active)
|
||||
{
|
||||
@ -8170,3 +8204,19 @@ meta_window_get_type_atom (MetaWindow *window)
|
||||
{
|
||||
return window->type_atom;
|
||||
}
|
||||
|
||||
MetaWorkspace *
|
||||
meta_window_get_workspace (MetaWindow *window)
|
||||
{
|
||||
if (window->on_all_workspaces)
|
||||
return window->screen->active_workspace;
|
||||
|
||||
return window->workspace;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_window_is_on_all_workspaces (MetaWindow *window)
|
||||
{
|
||||
return window->on_all_workspaces;
|
||||
}
|
||||
|
||||
|
@ -30,9 +30,10 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_WORKSPACE_H
|
||||
#define META_WORKSPACE_H
|
||||
#ifndef META_WORKSPACE_PRIVATE_H
|
||||
#define META_WORKSPACE_PRIVATE_H
|
||||
|
||||
#include "workspace.h"
|
||||
#include "window-private.h"
|
||||
|
||||
/* Negative to avoid conflicting with real workspace
|
||||
@ -80,7 +81,6 @@ void meta_workspace_activate_with_focus (MetaWorkspace *workspace,
|
||||
guint32 timestamp);
|
||||
void meta_workspace_activate (MetaWorkspace *workspace,
|
||||
guint32 timestamp);
|
||||
int meta_workspace_index (MetaWorkspace *workspace);
|
||||
GList* meta_workspace_list_windows (MetaWorkspace *workspace);
|
||||
|
||||
void meta_workspace_invalidate_work_area (MetaWorkspace *workspace);
|
||||
@ -89,8 +89,6 @@ void meta_workspace_invalidate_work_area (MetaWorkspace *workspace);
|
||||
void meta_workspace_get_work_area_for_xinerama (MetaWorkspace *workspace,
|
||||
int which_xinerama,
|
||||
MetaRectangle *area);
|
||||
void meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace,
|
||||
MetaRectangle *area);
|
||||
GList* meta_workspace_get_onscreen_region (MetaWorkspace *workspace);
|
||||
GList* meta_workspace_get_onxinerama_region (MetaWorkspace *workspace,
|
||||
int which_xinerama);
|
@ -25,8 +25,14 @@
|
||||
|
||||
#include <config.h>
|
||||
#include "workspace.h"
|
||||
#include "workspace-private.h"
|
||||
#include "errors.h"
|
||||
#include "prefs.h"
|
||||
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
#include "compositor.h"
|
||||
#endif
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -383,6 +389,19 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
|
||||
meta_topic (META_DEBUG_FOCUS, "Focusing default window on new workspace\n");
|
||||
meta_workspace_focus_default_window (workspace, NULL, timestamp);
|
||||
}
|
||||
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
{
|
||||
/*
|
||||
* Notify the compositor that the active workspace changed.
|
||||
*/
|
||||
MetaScreen *screen = workspace->screen;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
MetaCompositor *comp = meta_display_get_compositor (display);
|
||||
|
||||
meta_compositor_switch_workspace (comp, screen, old, workspace);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@ -682,6 +701,19 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
|
||||
|
||||
/* We're all done, YAAY! Record that everything has been validated. */
|
||||
workspace->work_areas_invalid = FALSE;
|
||||
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
{
|
||||
/*
|
||||
* Notify the compositor that the workspace geometry has changed.
|
||||
*/
|
||||
MetaScreen *screen = workspace->screen;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
MetaCompositor *comp = meta_display_get_compositor (display);
|
||||
|
||||
meta_compositor_update_workspace_geometry (comp, workspace);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@ -974,3 +1006,10 @@ focus_ancestor_or_mru_window (MetaWorkspace *workspace,
|
||||
timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
MetaScreen *
|
||||
meta_workspace_get_screen (MetaWorkspace *workspace)
|
||||
{
|
||||
return workspace->screen;
|
||||
}
|
||||
|
||||
|
257
src/include/compositor-clutter-plugin.h
Normal file
257
src/include/compositor-clutter-plugin.h
Normal file
@ -0,0 +1,257 @@
|
||||
/* -*- 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 <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
|
||||
|
||||
/*
|
||||
* A key that the switch_workspace() handler can use to retrive workspace
|
||||
* the actor is on.
|
||||
*/
|
||||
#define META_COMPOSITOR_CLUTTER_PLUGIN_WORKSPACE_KEY "MCCP-Manager-workspace"
|
||||
|
||||
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) (ClutterActor *actor,
|
||||
MetaCompWindowType type,
|
||||
gint workspace);
|
||||
|
||||
void (*maximize) (ClutterActor *actor,
|
||||
MetaCompWindowType type,
|
||||
gint workspace,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
|
||||
void (*unmaximize) (ClutterActor *actor,
|
||||
MetaCompWindowType type,
|
||||
gint workspace,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
|
||||
void (*map) (ClutterActor *actor,
|
||||
MetaCompWindowType type,
|
||||
gint workspace);
|
||||
|
||||
void (*destroy) (ClutterActor *actor,
|
||||
MetaCompWindowType type,
|
||||
gint workspace);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* 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) (ClutterActor *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);
|
||||
|
||||
#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
|
||||
*/
|
||||
|
||||
ClutterActor *stage;
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Manager callback for completed effects; this function must be called on the
|
||||
* completion of each effect.
|
||||
*
|
||||
* For switch-workspace effect the plugin might pass back any actor from the
|
||||
* actor list, but the actor parameter must not be NULL.
|
||||
*/
|
||||
void (*completed) (MetaCompositorClutterPlugin *plugin,
|
||||
ClutterActor *actor,
|
||||
unsigned long event);
|
||||
|
||||
/* Private; manager private data. */
|
||||
void *manager_private;
|
||||
};
|
||||
|
||||
#endif
|
@ -27,6 +27,28 @@
|
||||
|
||||
#include "types.h"
|
||||
#include "boxes.h"
|
||||
#include "window.h"
|
||||
#include "workspace.h"
|
||||
|
||||
typedef enum _MetaCompWindowType
|
||||
{
|
||||
/*
|
||||
* Types shared with MetaWindow
|
||||
*/
|
||||
META_COMP_WINDOW_NORMAL = META_WINDOW_NORMAL,
|
||||
META_COMP_WINDOW_DESKTOP = META_WINDOW_DESKTOP,
|
||||
META_COMP_WINDOW_DOCK = META_WINDOW_DOCK,
|
||||
META_COMP_WINDOW_MENU = META_WINDOW_MENU,
|
||||
|
||||
/*
|
||||
* Extended types that WM does not care about, but we do.
|
||||
*/
|
||||
META_COMP_WINDOW_TOOLTIP = 0xf000,
|
||||
META_COMP_WINDOW_DROP_DOWN_MENU,
|
||||
META_COMP_WINDOW_DND,
|
||||
META_COMP_WINDOW_OVERRIDE,
|
||||
} MetaCompWindowType;
|
||||
|
||||
|
||||
#ifdef WITH_CLUTTER
|
||||
extern int meta_compositor_can_use_clutter__;
|
||||
@ -79,6 +101,31 @@ void
|
||||
meta_compositor_minimize_window (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
|
||||
void
|
||||
meta_compositor_maximize_window (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
void
|
||||
meta_compositor_unmaximize_window (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
void
|
||||
meta_compositor_update_workspace_geometry (MetaCompositor *compositor,
|
||||
MetaWorkspace *workspace);
|
||||
|
||||
void
|
||||
meta_compositor_switch_workspace (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
MetaWorkspace *from,
|
||||
MetaWorkspace *to);
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -2,10 +2,10 @@
|
||||
|
||||
/* Metacity preferences */
|
||||
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
* Copyright (C) 2006 Elijah Newren
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@ -15,7 +15,7 @@
|
||||
* 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
|
||||
@ -59,7 +59,11 @@ typedef enum
|
||||
META_PREF_GNOME_ANIMATIONS,
|
||||
META_PREF_CURSOR_THEME,
|
||||
META_PREF_CURSOR_SIZE,
|
||||
META_PREF_COMPOSITING_MANAGER
|
||||
META_PREF_COMPOSITING_MANAGER,
|
||||
#ifdef WITH_CLUTTER
|
||||
META_PREF_CLUTTER_DISABLED,
|
||||
META_PREF_CLUTTER_PLUGINS
|
||||
#endif
|
||||
} MetaPreference;
|
||||
|
||||
typedef void (* MetaPrefsChangedFunc) (MetaPreference pref,
|
||||
@ -120,6 +124,21 @@ gboolean meta_prefs_get_compositing_manager (void);
|
||||
*/
|
||||
void meta_prefs_set_compositing_manager (gboolean whether);
|
||||
|
||||
#ifdef WITH_CLUTTER
|
||||
|
||||
gboolean meta_prefs_get_clutter_disabled (void);
|
||||
void meta_prefs_set_clutter_disabled (gboolean whether);
|
||||
|
||||
GSList * meta_prefs_get_clutter_plugins (void);
|
||||
|
||||
/**
|
||||
* Sets whether the compositor is turned on.
|
||||
*
|
||||
* \param whether TRUE to turn on, FALSE to turn off
|
||||
*/
|
||||
void meta_prefs_set_clutter_plugins (GSList *list);
|
||||
#endif
|
||||
|
||||
/* Screen bindings */
|
||||
#define META_KEYBINDING_WORKSPACE_1 "switch_to_workspace_1"
|
||||
#define META_KEYBINDING_WORKSPACE_2 "switch_to_workspace_2"
|
||||
|
@ -45,4 +45,5 @@ void meta_screen_set_cm_selection (MetaScreen *screen);
|
||||
void meta_screen_unset_cm_selection (MetaScreen *screen);
|
||||
#endif
|
||||
|
||||
GList *meta_screen_get_workspaces (MetaScreen *screen);
|
||||
#endif
|
||||
|
@ -27,5 +27,5 @@ typedef struct _MetaDisplay MetaDisplay;
|
||||
typedef struct _MetaFrame MetaFrame;
|
||||
typedef struct _MetaScreen MetaScreen;
|
||||
typedef struct _MetaWindow MetaWindow;
|
||||
|
||||
typedef struct _MetaWorkspace MetaWorkspace;
|
||||
#endif
|
||||
|
@ -41,6 +41,12 @@ typedef enum
|
||||
META_WINDOW_SPLASHSCREEN,
|
||||
} MetaWindowType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_MAXIMIZE_HORIZONTAL = 1 << 0,
|
||||
META_MAXIMIZE_VERTICAL = 1 << 1
|
||||
} MetaMaximizeFlags;
|
||||
|
||||
MetaFrame *meta_window_get_frame (MetaWindow *window);
|
||||
gboolean meta_window_has_focus (MetaWindow *window);
|
||||
gboolean meta_window_is_shaded (MetaWindow *window);
|
||||
@ -50,5 +56,6 @@ MetaDisplay *meta_window_get_display (MetaWindow *window);
|
||||
Window meta_window_get_xwindow (MetaWindow *window);
|
||||
MetaWindowType meta_window_get_type (MetaWindow *window);
|
||||
Atom meta_window_get_type_atom (MetaWindow *window);
|
||||
|
||||
MetaWorkspace *meta_window_get_workspace (MetaWindow *window);
|
||||
gboolean meta_window_is_on_all_workspaces (MetaWindow *window);
|
||||
#endif
|
||||
|
44
src/include/workspace.h
Normal file
44
src/include/workspace.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* \file workspace.h Workspaces
|
||||
*
|
||||
* A workspace is a set of windows which all live on the same
|
||||
* screen. (You may also see the name "desktop" around the place,
|
||||
* which is the EWMH's name for the same thing.) Only one workspace
|
||||
* of a screen may be active at once; all windows on all other workspaces
|
||||
* are unmapped.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
* Copyright (C) 2004, 2005 Elijah Newren
|
||||
*
|
||||
* 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_WORKSPACE_H
|
||||
#define META_WORKSPACE_H
|
||||
|
||||
#include "types.h"
|
||||
#include "boxes.h"
|
||||
#include "screen.h"
|
||||
|
||||
int meta_workspace_index (MetaWorkspace *workspace);
|
||||
MetaScreen *meta_workspace_get_screen (MetaWorkspace *workspace);
|
||||
void meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace,
|
||||
MetaRectangle *area);
|
||||
#endif
|
@ -340,6 +340,36 @@
|
||||
</locale>
|
||||
</schema>
|
||||
|
||||
<schema>
|
||||
<key>/schemas/apps/metacity/general/clutter_disabled</key>
|
||||
<applyto>/apps/metacity/general/clutter_disabled</applyto>
|
||||
<owner>metacity</owner>
|
||||
<type>bool</type>
|
||||
<default>false</default>
|
||||
<locale name="C">
|
||||
<short>Clutter Disabled</short>
|
||||
<long>
|
||||
Determines whether Clutter compositing backend should be disabled.
|
||||
Change to this option will not take effect until Metacity is
|
||||
restarted.
|
||||
</long>
|
||||
</locale>
|
||||
</schema>
|
||||
|
||||
<schema>
|
||||
<key>/schemas/apps/metacity/general/clutter_plugins</key>
|
||||
<applyto>/apps/metacity/general/clutter_plugins</applyto>
|
||||
<owner>metacity</owner>
|
||||
<type>list</type>
|
||||
<default></default>
|
||||
<locale name="C">
|
||||
<short>Clutter Plugins</short>
|
||||
<long>
|
||||
Plugins to load for the Clutter-based compositing manager.
|
||||
</long>
|
||||
</locale>
|
||||
</schema>
|
||||
|
||||
<schema>
|
||||
<key>/schemas/apps/metacity/workspace_names/name</key>
|
||||
<applyto>/apps/metacity/workspace_names/name_1</applyto>
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "tabpopup.h"
|
||||
/* FIXME these two includes are 100% broken ...
|
||||
*/
|
||||
#include "../core/workspace.h"
|
||||
#include "../core/workspace-private.h"
|
||||
#include "../core/frame-private.h"
|
||||
#include "draw-workspace.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
Loading…
Reference in New Issue
Block a user