Convert to gnome-shell-plugin to new plugin style

The plugin-gobject branch of Mutter (now merged into our branch) converts
plugins to more-standard GObject GTypePlugin, with the plugin itself
being a GObject class.

gnome-shell-plugin.c: Switch plugin to the new scheme
shell-wm.[ch]: Forward effect signals to ShellWM rather than hooking
  directly into the plugin vtable.
default: Remove this (accidentally committed) file

svn path=/trunk/; revision=133
This commit is contained in:
Owen Taylor 2008-12-22 21:05:08 +00:00
parent 48cda5b179
commit a168f6da42
4 changed files with 198 additions and 880 deletions

View File

@ -1,740 +0,0 @@
/* -*- 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 MUTTER_BUILDING_PLUGIN 1
#include "mutter-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 250
#define MINIMIZE_TIMEOUT 250
#define MAXIMIZE_TIMEOUT 250
#define MAP_TIMEOUT 250
#define SWITCH_TIMEOUT 500
#define ACTOR_DATA_KEY "MCCP-Default-actor-data"
static GQuark actor_data_quark = 0;
static gboolean do_init (const char *params);
static void minimize (MutterWindow *actor);
static void map (MutterWindow *actor);
static void destroy (MutterWindow *actor);
static void maximize (MutterWindow *actor,
gint x, gint y, gint width, gint height);
static void unmaximize (MutterWindow *actor,
gint x, gint y, gint width, gint height);
static void switch_workspace (const GList **actors, gint from, gint to,
MetaMotionDirection direction);
static void kill_effect (MutterWindow *actor, gulong event);
static gboolean reload (const char *params);
/*
* Create the plugin struct; function pointers initialized in
* g_module_check_init().
*/
MUTTER_DECLARE_PLUGIN();
/*
* Plugin private data that we store in the .plugin_private member.
*/
typedef struct _PluginState
{
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;
} PluginState;
/*
* Per actor private data we attach to each actor.
*/
typedef struct _ActorPrivate
{
ClutterActor *orig_parent;
ClutterTimeline *tml_minimize;
ClutterTimeline *tml_maximize;
ClutterTimeline *tml_destroy;
ClutterTimeline *tml_map;
gboolean is_minimized : 1;
gboolean is_maximized : 1;
} ActorPrivate;
static PluginState *plugin_state;
/*
* Actor private data accessor
*/
static void
free_actor_private (gpointer data)
{
if (G_LIKELY (data != NULL))
g_slice_free (ActorPrivate, data);
}
static ActorPrivate *
get_actor_private (MutterWindow *actor)
{
ActorPrivate *priv = g_object_get_qdata (G_OBJECT (actor), actor_data_quark);
if (G_UNLIKELY (actor_data_quark == 0))
actor_data_quark = g_quark_from_static_string (ACTOR_DATA_KEY);
if (G_UNLIKELY (!priv))
{
priv = g_slice_new0 (ActorPrivate);
g_object_set_qdata_full (G_OBJECT (actor),
actor_data_quark, priv,
free_actor_private);
}
return priv;
}
static void
on_switch_workspace_effect_complete (ClutterActor *group, gpointer data)
{
PluginState *state = plugin_state;
GList *l = *((GList**)data);
MutterWindow *actor_for_cb = l->data;
while (l)
{
ClutterActor *a = l->data;
MutterWindow *mc_window = MUTTER_WINDOW (a);
ActorPrivate *priv = get_actor_private (mc_window);
if (priv->orig_parent)
{
clutter_actor_reparent (a, priv->orig_parent);
priv->orig_parent = NULL;
}
l = l->next;
}
clutter_actor_destroy (state->desktop1);
clutter_actor_destroy (state->desktop2);
state->actors = NULL;
state->tml_switch_workspace1 = NULL;
state->tml_switch_workspace2 = NULL;
state->desktop1 = NULL;
state->desktop2 = NULL;
mutter_plugin_effect_completed (mutter_get_plugin(), actor_for_cb,
MUTTER_PLUGIN_SWITCH_WORKSPACE);
}
static void
switch_workspace (const GList **actors, gint from, gint to,
MetaMotionDirection direction)
{
MutterPlugin *plugin = mutter_get_plugin();
PluginState *state = plugin_state;
GList *l;
gint n_workspaces;
ClutterActor *workspace0 = clutter_group_new ();
ClutterActor *workspace1 = clutter_group_new ();
ClutterActor *stage;
int screen_width, screen_height;
stage = mutter_plugin_get_stage (plugin);
mutter_plugin_query_screen_size (plugin,
&screen_width,
&screen_height);
clutter_actor_set_anchor_point (workspace1,
screen_width,
screen_height);
clutter_actor_set_position (workspace1,
screen_width,
screen_height);
clutter_actor_set_scale (workspace1, 0.0, 0.0);
clutter_container_add_actor (CLUTTER_CONTAINER (stage), workspace1);
clutter_container_add_actor (CLUTTER_CONTAINER (stage), workspace0);
if (from == to)
{
mutter_plugin_effect_completed (mutter_get_plugin(), NULL,
MUTTER_PLUGIN_SWITCH_WORKSPACE);
return;
}
n_workspaces = g_list_length (plugin->work_areas);
l = g_list_last (*((GList**) actors));
while (l)
{
MutterWindow *mc_window = l->data;
ActorPrivate *priv = get_actor_private (mc_window);
ClutterActor *window = CLUTTER_ACTOR (mc_window);
gint win_workspace;
win_workspace = mutter_window_get_workspace (mc_window);
if (win_workspace == to || win_workspace == from)
{
gint x, y;
guint w, h;
clutter_actor_get_position (window, &x, &y);
clutter_actor_get_size (window, &w, &h);
priv->orig_parent = clutter_actor_get_parent (window);
clutter_actor_reparent (window,
win_workspace == to ? workspace1 : workspace0);
clutter_actor_show_all (window);
clutter_actor_raise_top (window);
}
else if (win_workspace < 0)
{
/* Sticky window */
priv->orig_parent = NULL;
}
else
{
/* Window on some other desktop */
clutter_actor_hide (window);
priv->orig_parent = NULL;
}
l = l->prev;
}
state->actors = (GList **)actors;
state->desktop1 = workspace0;
state->desktop2 = workspace1;
state->tml_switch_workspace2 =
clutter_effect_scale (state->switch_workspace_effect,
workspace1, 1.0, 1.0,
on_switch_workspace_effect_complete,
(gpointer)actors);
state->tml_switch_workspace1 =
clutter_effect_scale (state->switch_workspace_effect,
workspace0, 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.
*/
ActorPrivate *apriv;
MutterWindow *mc_window = MUTTER_WINDOW (actor);
apriv = get_actor_private (MUTTER_WINDOW (actor));
apriv->tml_minimize = NULL;
clutter_actor_hide (actor);
/* FIXME - we shouldn't assume the original scale, it should be saved
* at the start of the effect */
clutter_actor_set_scale (actor, 1.0, 1.0);
clutter_actor_move_anchor_point_from_gravity (actor,
CLUTTER_GRAVITY_NORTH_WEST);
/* Now notify the manager that we are done with this effect */
mutter_plugin_effect_completed (mutter_get_plugin(), mc_window,
MUTTER_PLUGIN_MINIMIZE);
}
/*
* Simple minimize handler: it applies a scale effect (which must be reversed on
* completion).
*/
static void
minimize (MutterWindow *mc_window)
{
PluginState *state = plugin_state;
MetaCompWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (mc_window);
type = mutter_window_get_window_type (mc_window);
if (type == META_COMP_WINDOW_NORMAL)
{
ActorPrivate *apriv = get_actor_private (mc_window);
apriv->is_minimized = TRUE;
clutter_actor_move_anchor_point_from_gravity (actor,
CLUTTER_GRAVITY_CENTER);
apriv->tml_minimize = clutter_effect_scale (state->minimize_effect,
actor,
0.0,
0.0,
(ClutterEffectCompleteFunc)
on_minimize_effect_complete,
NULL);
}
else
mutter_plugin_effect_completed (mutter_get_plugin(), mc_window,
MUTTER_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.
*/
MutterWindow *mc_window = MUTTER_WINDOW (actor);
ActorPrivate *apriv = get_actor_private (mc_window);
apriv->tml_maximize = NULL;
/* FIXME - don't assume the original scale was 1.0 */
clutter_actor_set_scale (actor, 1.0, 1.0);
clutter_actor_move_anchor_point_from_gravity (actor,
CLUTTER_GRAVITY_NORTH_WEST);
/* Now notify the manager that we are done with this effect */
mutter_plugin_effect_completed (mutter_get_plugin(), mc_window,
MUTTER_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 (MutterWindow *mc_window,
gint end_x, gint end_y, gint end_width, gint end_height)
{
MetaCompWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (mc_window);
gdouble scale_x = 1.0;
gdouble scale_y = 1.0;
gint anchor_x = 0;
gint anchor_y = 0;
type = mutter_window_get_window_type (mc_window);
if (type == META_COMP_WINDOW_NORMAL)
{
ActorPrivate *apriv = get_actor_private (mc_window);
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 (plugin_state->maximize_effect,
actor,
scale_x,
scale_y,
(ClutterEffectCompleteFunc)
on_maximize_effect_complete,
NULL);
return;
}
mutter_plugin_effect_completed (mutter_get_plugin(), mc_window,
MUTTER_PLUGIN_MAXIMIZE);
}
/*
* See comments on the maximize() function.
*
* (Just a skeleton code.)
*/
static void
unmaximize (MutterWindow *mc_window,
gint end_x, gint end_y, gint end_width, gint end_height)
{
MetaCompWindowType type = mutter_window_get_window_type (mc_window);
if (type == META_COMP_WINDOW_NORMAL)
{
ActorPrivate *apriv = get_actor_private (mc_window);
apriv->is_maximized = FALSE;
}
/* Do this conditionally, if the effect requires completion callback. */
mutter_plugin_effect_completed (mutter_get_plugin(), mc_window,
MUTTER_PLUGIN_UNMAXIMIZE);
}
static void
on_map_effect_complete (ClutterActor *actor, gpointer data)
{
/*
* Must reverse the effect of the effect.
*/
MutterWindow *mc_window = MUTTER_WINDOW (actor);
ActorPrivate *apriv = get_actor_private (mc_window);
apriv->tml_map = NULL;
clutter_actor_move_anchor_point_from_gravity (actor,
CLUTTER_GRAVITY_NORTH_WEST);
/* Now notify the manager that we are done with this effect */
mutter_plugin_effect_completed (mutter_get_plugin(), mc_window, MUTTER_PLUGIN_MAP);
}
/*
* Simple map handler: it applies a scale effect which must be reversed on
* completion).
*/
static void
map (MutterWindow *mc_window)
{
MetaCompWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (mc_window);
type = mutter_window_get_window_type (mc_window);
if (type == META_COMP_WINDOW_NORMAL)
{
ActorPrivate *apriv = get_actor_private (mc_window);
clutter_actor_move_anchor_point_from_gravity (actor,
CLUTTER_GRAVITY_CENTER);
clutter_actor_set_scale (actor, 0.0, 0.0);
clutter_actor_show (actor);
apriv->tml_map = clutter_effect_scale (plugin_state->map_effect,
actor,
1.0,
1.0,
(ClutterEffectCompleteFunc)
on_map_effect_complete,
NULL);
apriv->is_minimized = FALSE;
}
else
mutter_plugin_effect_completed (mutter_get_plugin(), mc_window,
MUTTER_PLUGIN_MAP);
}
/*
* Destroy effect completion callback; this is a simple effect that requires no
* further action than notifying the manager that the effect is completed.
*/
static void
on_destroy_effect_complete (ClutterActor *actor, gpointer data)
{
MutterPlugin *plugin = mutter_get_plugin();
MutterWindow *mc_window = MUTTER_WINDOW (actor);
ActorPrivate *apriv = get_actor_private (mc_window);
apriv->tml_destroy = NULL;
mutter_plugin_effect_completed (plugin, mc_window,
MUTTER_PLUGIN_DESTROY);
}
/*
* Simple TV-out like effect.
*/
static void
destroy (MutterWindow *mc_window)
{
MetaCompWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (mc_window);
type = mutter_window_get_window_type (mc_window);
if (type == META_COMP_WINDOW_NORMAL)
{
ActorPrivate *apriv = get_actor_private (mc_window);
clutter_actor_move_anchor_point_from_gravity (actor,
CLUTTER_GRAVITY_CENTER);
apriv->tml_destroy = clutter_effect_scale (plugin_state->destroy_effect,
actor,
1.0,
0.0,
(ClutterEffectCompleteFunc)
on_destroy_effect_complete,
NULL);
}
else
mutter_plugin_effect_completed (mutter_get_plugin(), mc_window,
MUTTER_PLUGIN_DESTROY);
}
static void
kill_effect (MutterWindow *mc_window, gulong event)
{
ActorPrivate *apriv;
ClutterActor *actor = CLUTTER_ACTOR (mc_window);
if (event & MUTTER_PLUGIN_SWITCH_WORKSPACE)
{
PluginState *state = plugin_state;
if (state->tml_switch_workspace1)
{
clutter_timeline_stop (state->tml_switch_workspace1);
clutter_timeline_stop (state->tml_switch_workspace2);
on_switch_workspace_effect_complete (state->desktop1, state->actors);
}
if (!(event & ~MUTTER_PLUGIN_SWITCH_WORKSPACE))
{
/* Workspace switch only, nothing more to do */
return;
}
}
apriv = get_actor_private (mc_window);
if ((event & MUTTER_PLUGIN_MINIMIZE) && apriv->tml_minimize)
{
clutter_timeline_stop (apriv->tml_minimize);
on_minimize_effect_complete (actor, NULL);
}
if ((event & MUTTER_PLUGIN_MAXIMIZE) && apriv->tml_maximize)
{
clutter_timeline_stop (apriv->tml_maximize);
on_maximize_effect_complete (actor, NULL);
}
if ((event & MUTTER_PLUGIN_MAP) && apriv->tml_map)
{
clutter_timeline_stop (apriv->tml_map);
on_map_effect_complete (actor, NULL);
}
if ((event & MUTTER_PLUGIN_DESTROY) && apriv->tml_destroy)
{
clutter_timeline_stop (apriv->tml_destroy);
on_destroy_effect_complete (actor, NULL);
}
}
const gchar * g_module_check_init (GModule *module);
const gchar *
g_module_check_init (GModule *module)
{
MutterPlugin *plugin = mutter_get_plugin ();
/* Human readable name (for use in UI) */
plugin->name = "Default Effects";
/* Plugin load time initialiser */
plugin->do_init = do_init;
/* Effect handlers */
plugin->minimize = minimize;
plugin->destroy = destroy;
plugin->map = map;
plugin->maximize = maximize;
plugin->unmaximize = unmaximize;
plugin->switch_workspace = switch_workspace;
plugin->kill_effect = kill_effect;
/* The reload handler */
plugin->reload = reload;
return NULL;
}
/*
* Core of the plugin init function, called for initial initialization and
* by the reload() function. Returns TRUE on success.
*/
static gboolean
do_init (const char *params)
{
guint destroy_timeout = DESTROY_TIMEOUT;
guint minimize_timeout = MINIMIZE_TIMEOUT;
guint maximize_timeout = MAXIMIZE_TIMEOUT;
guint map_timeout = MAP_TIMEOUT;
guint switch_timeout = SWITCH_TIMEOUT;
plugin_state = g_new0 (PluginState, 1);
if (params)
{
if (strstr (params, "debug"))
{
g_debug ("%s: Entering debug mode.", mutter_get_plugin()->name);
plugin_state->debug_mode = TRUE;
/*
* Double the effect duration to make them easier to observe.
*/
destroy_timeout *= 2;
minimize_timeout *= 2;
maximize_timeout *= 2;
map_timeout *= 2;
switch_timeout *= 2;
}
}
plugin_state->destroy_effect
= clutter_effect_template_new (clutter_timeline_new_for_duration (
destroy_timeout),
CLUTTER_ALPHA_SINE_INC);
plugin_state->minimize_effect
= clutter_effect_template_new (clutter_timeline_new_for_duration (
minimize_timeout),
CLUTTER_ALPHA_SINE_INC);
plugin_state->maximize_effect
= clutter_effect_template_new (clutter_timeline_new_for_duration (
maximize_timeout),
CLUTTER_ALPHA_SINE_INC);
plugin_state->map_effect
= clutter_effect_template_new (clutter_timeline_new_for_duration (
map_timeout),
CLUTTER_ALPHA_SINE_INC);
plugin_state->switch_workspace_effect
= clutter_effect_template_new (clutter_timeline_new_for_duration (
switch_timeout),
CLUTTER_ALPHA_SINE_INC);
return TRUE;
}
static void
free_plugin_private (PluginState *state)
{
if (!state)
return;
g_object_unref (state->destroy_effect);
g_object_unref (state->minimize_effect);
g_object_unref (state->maximize_effect);
g_object_unref (state->switch_workspace_effect);
g_free (state);
}
/*
* Called by the plugin manager when we stuff like the command line parameters
* changed.
*/
static gboolean
reload (const char *params)
{
PluginState *state;
state = plugin_state;
if (do_init (params))
{
/* Success; free the old state */
free_plugin_private (plugin_state);
return TRUE;
}
else
{
/* Fail -- fall back to the old state. */
plugin_state = state;
}
return FALSE;
}
/*
* GModule unload function -- do any cleanup required.
*/
G_MODULE_EXPORT void g_module_unload (GModule *module);
G_MODULE_EXPORT void
g_module_unload (GModule *module)
{
free_plugin_private (plugin_state);
}

View File

@ -40,67 +40,113 @@
#include "display.h" #include "display.h"
#include "shell-global.h" #include "shell-global.h"
#include "shell-wm.h"
static gboolean do_init (const char *params); static void gnome_shell_plugin_constructed (GObject *object);
static gboolean reload (const char *params); static void gnome_shell_plugin_dispose (GObject *object);
static void gnome_shell_plugin_finalize (GObject *object);
static gboolean xevent_filter (XEvent *xev); #ifdef NOT_YET
static void gnome_shell_plugin_minimize (MutterPlugin *plugin,
MutterWindow *actor);
static void gnome_shell_plugin_maximize (MutterPlugin *plugin,
MutterWindow *actor,
gint x,
gint y,
gint width,
gint height);
static void gnome_shell_plugin_unmaximize (MutterPlugin *plugin,
MutterWindow *actor,
gint x,
gint y,
gint width,
gint height);
static void gnome_shell_plugin_map (MutterPlugin *plugin,
MutterWindow *actor);
static void gnome_shell_plugin_destroy (MutterPlugin *plugin,
MutterWindow *actor);
#endif
static void gnome_shell_plugin_switch_workspace (MutterPlugin *plugin,
const GList **actors,
gint from,
gint to,
MetaMotionDirection direction);
static void gnome_shell_plugin_kill_effect (MutterPlugin *plugin,
MutterWindow *actor,
gulong events);
static gboolean gnome_shell_plugin_xevent_filter (MutterPlugin *plugin,
XEvent *event);
static const MutterPluginInfo *gnome_shell_plugin_plugin_info (MutterPlugin *plugin);
#define GNOME_TYPE_SHELL_PLUGIN (gnome_shell_plugin_get_type ())
#define GNOME_SHELL_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_SHELL_PLUGIN, GnomeShellPlugin))
#define GNOME_SHELL_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_TYPE_SHELL_PLUGIN, GnomeShellPluginClass))
#define GNOME_IS_SHELL_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_SHELL_PLUGIN_TYPE))
#define GNOME_IS_SHELL_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_TYPE_SHELL_PLUGIN))
#define GNOME_SHELL_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNOME_TYPE_SHELL_PLUGIN, GnomeShellPluginClass))
typedef struct _GnomeShellPlugin GnomeShellPlugin;
typedef struct _GnomeShellPluginClass GnomeShellPluginClass;
struct _GnomeShellPlugin
{
MutterPlugin parent;
GjsContext *gjs_context;
Atom panel_action;
Atom panel_action_run_dialog;
Atom panel_action_main_menu;
};
struct _GnomeShellPluginClass
{
MutterPluginClass parent_class;
};
/* /*
* Create the plugin struct; function pointers initialized in * Create the plugin struct; function pointers initialized in
* g_module_check_init(). * g_module_check_init().
*/ */
MUTTER_DECLARE_PLUGIN(); MUTTER_PLUGIN_DECLARE(GnomeShellPlugin, gnome_shell_plugin);
/* static void
* Plugin private data that we store in the .plugin_private member. gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
*/
typedef struct _PluginState
{ {
gboolean debug_mode : 1; GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GjsContext *gjs_context; MutterPluginClass *plugin_class = MUTTER_PLUGIN_CLASS (klass);
Atom panel_action;
Atom panel_action_run_dialog;
Atom panel_action_main_menu;
} PluginState;
gobject_class->constructed = gnome_shell_plugin_constructed;
gobject_class->dispose = gnome_shell_plugin_dispose;
gobject_class->finalize = gnome_shell_plugin_finalize;
static PluginState *plugin_state; #ifdef NOT_YET
plugin_class->map = gnome_shell_plugin_map;
plugin_class->minimize = gnome_shell_plugin_minimize;
plugin_class->maximize = gnome_shell_plugin_maximize;
plugin_class->unmaximize = gnome_shell_plugin_unmaximize;
plugin_class->destroy = gnome_shell_plugin_destroy;
#endif
const gchar * g_module_check_init (GModule *module); plugin_class->switch_workspace = gnome_shell_plugin_switch_workspace;
const gchar * plugin_class->kill_effect = gnome_shell_plugin_kill_effect;
g_module_check_init (GModule *module)
{
MutterPlugin *plugin = mutter_get_plugin ();
/* Human readable name (for use in UI) */ plugin_class->xevent_filter = gnome_shell_plugin_xevent_filter;
plugin->name = "GNOME Shell"; plugin_class->plugin_info = gnome_shell_plugin_plugin_info;
/* Plugin load time initialiser */
plugin->do_init = do_init;
/* The reload handler */
plugin->reload = reload;
/* Event handling */
plugin->xevent_filter = xevent_filter;
/* This will also create the ShellWM, which will set the appropriate
* window management callbacks in plugin.
*/
_shell_global_set_plugin (shell_global_get(), plugin);
return NULL;
} }
/* static void
* Core of the plugin init function, called for initial initialization and gnome_shell_plugin_init (GnomeShellPlugin *shell_plugin)
* by the reload() function. Returns TRUE on success.
*/
static gboolean
do_init (const char *params)
{ {
MutterPlugin *plugin = mutter_get_plugin(); _shell_global_set_plugin (shell_global_get(), MUTTER_PLUGIN(shell_plugin));
}
static void
gnome_shell_plugin_constructed (GObject *object)
{
MutterPlugin *plugin = MUTTER_PLUGIN (object);
GnomeShellPlugin *shell_plugin = GNOME_SHELL_PLUGIN (object);
MetaScreen *screen; MetaScreen *screen;
MetaDisplay *display; MetaDisplay *display;
GError *error = NULL; GError *error = NULL;
@ -111,18 +157,6 @@ do_init (const char *params)
screen = mutter_plugin_get_screen (plugin); screen = mutter_plugin_get_screen (plugin);
display = meta_screen_get_display (screen); display = meta_screen_get_display (screen);
plugin_state = g_new0 (PluginState, 1);
if (params)
{
if (strstr (params, "debug"))
{
g_debug ("%s: Entering debug mode.", mutter_get_plugin()->name);
plugin_state->debug_mode = TRUE;
}
}
g_irepository_prepend_search_path (GNOME_SHELL_PKGLIBDIR); g_irepository_prepend_search_path (GNOME_SHELL_PKGLIBDIR);
shell_js = g_getenv("GNOME_SHELL_JS"); shell_js = g_getenv("GNOME_SHELL_JS");
@ -130,17 +164,17 @@ do_init (const char *params)
shell_js = JSDIR; shell_js = JSDIR;
search_path = g_strsplit(shell_js, ":", -1); search_path = g_strsplit(shell_js, ":", -1);
plugin_state->gjs_context = gjs_context_new_with_search_path(search_path); shell_plugin->gjs_context = gjs_context_new_with_search_path(search_path);
g_strfreev(search_path); g_strfreev(search_path);
plugin_state->panel_action = XInternAtom (meta_display_get_xdisplay (display), shell_plugin->panel_action = XInternAtom (meta_display_get_xdisplay (display),
"_GNOME_PANEL_ACTION", FALSE); "_GNOME_PANEL_ACTION", FALSE);
plugin_state->panel_action_run_dialog = XInternAtom (meta_display_get_xdisplay (display), shell_plugin->panel_action_run_dialog = XInternAtom (meta_display_get_xdisplay (display),
"_GNOME_PANEL_ACTION_RUN_DIALOG", FALSE); "_GNOME_PANEL_ACTION_RUN_DIALOG", FALSE);
plugin_state->panel_action_main_menu = XInternAtom (meta_display_get_xdisplay (display), shell_plugin->panel_action_main_menu = XInternAtom (meta_display_get_xdisplay (display),
"_GNOME_PANEL_ACTION_MAIN_MENU", FALSE); "_GNOME_PANEL_ACTION_MAIN_MENU", FALSE);
if (!gjs_context_eval (plugin_state->gjs_context, if (!gjs_context_eval (shell_plugin->gjs_context,
"const Main = imports.ui.main; Main.start();", "const Main = imports.ui.main; Main.start();",
-1, -1,
"<main>", "<main>",
@ -150,54 +184,65 @@ do_init (const char *params)
g_warning ("Evaling main.js failed: %s", error->message); g_warning ("Evaling main.js failed: %s", error->message);
g_error_free (error); g_error_free (error);
} }
return TRUE;
} }
static void static void
free_plugin_private (PluginState *state) gnome_shell_plugin_dispose (GObject *object)
{ {
if (!state) G_OBJECT_CLASS(gnome_shell_plugin_parent_class)->dispose (object);
return;
g_free (state);
} }
/* static void
* Called by the plugin manager when we stuff like the command line parameters gnome_shell_plugin_finalize (GObject *object)
* changed.
*/
static gboolean
reload (const char *params)
{ {
PluginState *state; G_OBJECT_CLASS(gnome_shell_plugin_parent_class)->finalize (object);
}
state = plugin_state; static ShellWM *
get_shell_wm (void)
{
ShellWM *wm;
if (do_init (params)) g_object_get (shell_global_get (),
{ "window-manager", &wm,
/* Success; free the old state */ NULL);
free_plugin_private (plugin_state); /* drop extra ref added by g_object_get */
return TRUE; g_object_unref (wm);
}
else
{
/* Fail -- fall back to the old state. */
plugin_state = state;
}
return FALSE; return wm;
}
static void
gnome_shell_plugin_switch_workspace (MutterPlugin *plugin,
const GList **actors,
gint from,
gint to,
MetaMotionDirection direction)
{
_shell_wm_switch_workspace (get_shell_wm(),
actors, from, to, direction);
}
static void
gnome_shell_plugin_kill_effect (MutterPlugin *plugin,
MutterWindow *actor,
gulong events)
{
_shell_wm_kill_effect (get_shell_wm(),
actor, events);
} }
static gboolean static gboolean
handle_panel_event (XEvent *xev) handle_panel_event (GnomeShellPlugin *shell_plugin,
XEvent *xev)
{ {
MutterPlugin *plugin = MUTTER_PLUGIN (shell_plugin);
MetaScreen *screen; MetaScreen *screen;
MetaDisplay *display; MetaDisplay *display;
XClientMessageEvent *xev_client; XClientMessageEvent *xev_client;
Window root; Window root;
screen = mutter_plugin_get_screen (mutter_get_plugin ()); screen = mutter_plugin_get_screen (plugin);
display = meta_screen_get_display (screen); display = meta_screen_get_display (screen);
if (xev->type != ClientMessage) if (xev->type != ClientMessage)
@ -207,14 +252,14 @@ handle_panel_event (XEvent *xev)
xev_client = (XClientMessageEvent*) xev; xev_client = (XClientMessageEvent*) xev;
if (!(xev_client->window == root && if (!(xev_client->window == root &&
xev_client->message_type == plugin_state->panel_action && xev_client->message_type == shell_plugin->panel_action &&
xev_client->format == 32)) xev_client->format == 32))
return FALSE; return FALSE;
if (xev_client->data.l[0] == plugin_state->panel_action_run_dialog) if (xev_client->data.l[0] == shell_plugin->panel_action_run_dialog)
g_signal_emit_by_name (shell_global_get (), "panel-run-dialog", g_signal_emit_by_name (shell_global_get (), "panel-run-dialog",
(guint32) xev_client->data.l[1]); (guint32) xev_client->data.l[1]);
else if (xev_client->data.l[0] == plugin_state->panel_action_main_menu) else if (xev_client->data.l[0] == shell_plugin->panel_action_main_menu)
g_signal_emit_by_name (shell_global_get (), "panel-main-menu", g_signal_emit_by_name (shell_global_get (), "panel-main-menu",
(guint32) xev_client->data.l[1]); (guint32) xev_client->data.l[1]);
@ -222,20 +267,26 @@ handle_panel_event (XEvent *xev)
} }
static gboolean static gboolean
xevent_filter (XEvent *xev) gnome_shell_plugin_xevent_filter (MutterPlugin *plugin,
XEvent *xev)
{ {
if (handle_panel_event (xev)) GnomeShellPlugin *shell_plugin = GNOME_SHELL_PLUGIN (plugin);
if (handle_panel_event (shell_plugin, xev))
return TRUE; return TRUE;
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE; return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
} }
/* static const
* GModule unload function -- do any cleanup required. MutterPluginInfo *gnome_shell_plugin_plugin_info (MutterPlugin *plugin)
*/
G_MODULE_EXPORT void g_module_unload (GModule *module);
G_MODULE_EXPORT void
g_module_unload (GModule *module)
{ {
free_plugin_private (plugin_state); static const MutterPluginInfo info = {
} .name = "GNOME Shell",
.version = "0.1",
.author = "Various",
.license = "GPLv2+",
.description = "Provides GNOME Shell core functionality"
};
return &info;
}

View File

@ -80,28 +80,13 @@ shell_wm_class_init (ShellWMClass *klass)
G_TYPE_NONE, 0); G_TYPE_NONE, 0);
} }
static ShellWM * void
shell_wm_get (void) _shell_wm_switch_workspace (ShellWM *wm,
const GList **actors,
gint from,
gint to,
MetaMotionDirection direction)
{ {
ShellWM *wm;
g_object_get (shell_global_get (),
"window-manager", &wm,
NULL);
/* drop extra ref added by g_object_get */
g_object_unref (wm);
return wm;
}
static void
shell_wm_switch_workspace (const GList **actors,
gint from,
gint to,
MetaMotionDirection direction)
{
ShellWM *wm = shell_wm_get ();
shell_wm_set_switch_workspace_actors (wm, (GList *)*actors); shell_wm_set_switch_workspace_actors (wm, (GList *)*actors);
g_signal_emit (wm, shell_wm_signals[SWITCH_WORKSPACE], 0, g_signal_emit (wm, shell_wm_signals[SWITCH_WORKSPACE], 0,
from, to, direction); from, to, direction);
@ -164,12 +149,11 @@ shell_wm_completed_switch_workspace (ShellWM *wm)
} }
static void void
shell_wm_kill_effect (MutterWindow *actor, _shell_wm_kill_effect (ShellWM *wm,
gulong events) MutterWindow *actor,
gulong events)
{ {
ShellWM *wm = shell_wm_get ();
#ifdef NOT_YET #ifdef NOT_YET
if (events & MUTTER_PLUGIN_MINIMIZE) if (events & MUTTER_PLUGIN_MINIMIZE)
g_signal_emit (wm, shell_wm_signals[KILL_MINIMIZE], 0); g_signal_emit (wm, shell_wm_signals[KILL_MINIMIZE], 0);
@ -203,15 +187,5 @@ shell_wm_new (MutterPlugin *plugin)
wm = g_object_new (SHELL_TYPE_WM, NULL); wm = g_object_new (SHELL_TYPE_WM, NULL);
wm->plugin = plugin; wm->plugin = plugin;
#ifdef NOT_YET
plugin->minimize = shell_wm_minimize;
plugin->maximize = shell_wm_maximize;
plugin->unmaximize = shell_wm_unmaximize;
plugin->map = shell_wm_map;
plugin->destroy = shell_wm_destroy;
#endif
plugin->switch_workspace = shell_wm_switch_workspace;
plugin->kill_effect = shell_wm_kill_effect;
return wm; return wm;
} }

View File

@ -29,6 +29,39 @@ ShellWM *shell_wm_new (MutterPlugin *plugin);
GList *shell_wm_get_switch_workspace_actors (ShellWM *wm); GList *shell_wm_get_switch_workspace_actors (ShellWM *wm);
void shell_wm_completed_switch_workspace (ShellWM *wm); void shell_wm_completed_switch_workspace (ShellWM *wm);
/* These forward along the different effects from GnomeShellPlugin */
#ifdef NOT_YET
void _shell_wm_minimize (ShellWM *wm,
MutterWindow *actor);
void _shell_wm_maximize (ShellWM *wm,
MutterWindow *actor,
gint x,
gint y,
gint width,
gint height);
void _shell_wm_unmaximize (ShellWM *wm,
MutterWindow *actor,
gint x,
gint y,
gint width,
gint height);
void _shell_wm_map (ShellWM *wm,
MutterWindow *actor);
void _shell_wm_destroy (ShellWM *wm,
MutterWindow *actor);
#endif
void _shell_wm_switch_workspace (ShellWM *wm,
const GList **actors,
gint from,
gint to,
MetaMotionDirection direction);
void _shell_wm_kill_effect (ShellWM *wm,
MutterWindow *actor,
gulong events);
G_END_DECLS G_END_DECLS
#endif /* __SHELL_WM_H__ */ #endif /* __SHELL_WM_H__ */