implement some basic window management effects. #563844

svn path=/trunk/; revision=139
This commit is contained in:
Jonathan Matthew 2008-12-29 04:44:03 +00:00
parent b3aaf2ced5
commit 85c22e484d
5 changed files with 483 additions and 20 deletions

View File

@ -8,6 +8,7 @@ const Tweener = imports.tweener.tweener;
const Main = imports.ui.main;
const WINDOW_ANIMATION_TIME = 0.25;
const SWITCH_ANIMATION_TIME = 0.5;
function WindowManager() {
@ -20,20 +21,219 @@ WindowManager.prototype = {
this._global = Shell.Global.get();
this._shellwm = this._global.window_manager;
this._minimizing = [];
this._maximizing = [];
this._unmaximizing = [];
this._mapping = [];
this._destroying = [];
this._switchData = null;
this._shellwm.connect('switch-workspace',
function(o, from, to, direction) {
let actors = me._shellwm.get_switch_workspace_actors();
me.switchWorkspace(actors, from, to, direction);
me._switchWorkspace(actors, from, to, direction);
});
this._shellwm.connect('kill-switch-workspace',
function(o) {
me.switchWorkspaceDone();
me._switchWorkspaceDone();
});
this._shellwm.connect('minimize',
function(o, actor) {
me._minimizeWindow(actor);
});
this._shellwm.connect('kill-minimize',
function(o, actor) {
me._minimizeWindowDone(actor);
});
this._shellwm.connect('maximize',
function(o, actor, tx, ty, tw, th) {
me._maximizeWindow(actor, tx, ty, tw, th);
});
this._shellwm.connect('kill-maximize',
function(o, actor) {
me._maximizeWindowDone(actor);
});
this._shellwm.connect('unmaximize',
function(o, actor, tx, ty, tw, th) {
me._unmaximizeWindow(actor, tx, ty, tw, th);
});
this._shellwm.connect('kill-unmaximize',
function(o, actor) {
me._unmaximizeWindowDone(actor);
});
this._shellwm.connect('map',
function(o, actor) {
me._mapWindow(actor);
});
this._shellwm.connect('kill-map',
function(o, actor) {
me._mapWindowDone(actor);
});
this._shellwm.connect('destroy',
function(o, actor) {
me._destroyWindow(actor);
});
this._shellwm.connect('kill-destroy',
function(o, actor) {
me._destroyWindowDone(actor);
});
},
switchWorkspace : function(windows, from, to, direction) {
_minimizeWindow : function(actor) {
if (actor.get_window_type() != Meta.CompWindowType.NORMAL) {
this._shellwm.completed_minimize(actor);
return;
}
actor.set_scale(1.0, 1.0);
actor.move_anchor_point_from_gravity(Clutter.Gravity.CENTER);
/* scale window down to 0x0.
* maybe TODO: get icon geometry passed through and move the window towards it?
*/
this._minimizing.push(actor);
Tweener.addTween(actor,
{ scale_x: 0.0,
scale_y: 0.0,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._minimizeWindowDone,
onCompleteScope: this,
onCompleteParams: [actor]
});
},
_minimizeWindowDone : function(actor) {
let idx = this._minimizing.indexOf(actor);
if (idx != -1) {
Tweener.removeTweens(actor);
actor.set_scale(1.0, 1.0);
actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
this._shellwm.completed_minimize(actor);
this._minimizing.splice(idx, 1);
}
},
_maximizeWindow : function(actor, target_x, target_y, target_width, target_height) {
if (actor.get_window_type() != Meta.CompWindowType.NORMAL) {
this._shellwm.completed_maximize(actor);
return;
}
/* this doesn't work very well, as simply scaling up the existing
* window contents doesn't produce anything like the same results as
* actually maximizing the window.
*/
let scale_x = target_width / actor.width;
let scale_y = target_height / actor.height;
let anchor_x = (actor.x - target_x) * actor.width/(target_width - actor.width);
let anchor_y = (actor.y - target_y) * actor.height/(target_height - actor.height);
actor.move_anchor_point(anchor_x, anchor_y);
this._maximizing.push(actor);
Tweener.addTween(actor,
{ scale_x: scale_x,
scale_y: scale_y,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._maximizeWindowDone,
onCompleteScope: this,
onCompleteParams: [actor]
});
},
_maximizeWindowDone : function(actor) {
let idx = this._maximizing.indexOf(actor);
if (idx != -1) {
Tweener.removeTweens(actor);
actor.set_scale(1.0, 1.0);
actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
this._shellwm.completed_maximize(actor);
this._maximizing.splice(idx, 1);
}
},
_unmaximizeWindow : function(actor, target_x, target_y, target_width, target_height) {
this._shellwm.completed_unmaximize(actor);
},
_unmaximizeWindowDone : function(actor) {
},
_mapWindow : function(actor) {
if (actor.get_window_type() != Meta.CompWindowType.NORMAL) {
this._shellwm.completed_map(actor);
return;
}
actor.move_anchor_point_from_gravity(Clutter.Gravity.CENTER);
actor.set_scale(0.0, 0.0);
actor.show();
/* scale window up from 0x0 to normal size */
this._mapping.push(actor);
Tweener.addTween(actor,
{ scale_x: 1.0,
scale_y: 1.0,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._mapWindowDone,
onCompleteScope: this,
onCompleteParams: [actor]
});
},
_mapWindowDone : function(actor) {
let idx = this._mapping.indexOf(actor);
if (idx != -1) {
Tweener.removeTweens(actor);
actor.set_scale(1.0, 1.0);
actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
this._shellwm.completed_map(actor);
this._mapping.splice(idx, 1);
}
},
_destroyWindow : function(actor) {
if (actor.get_window_type() != Meta.CompWindowType.NORMAL) {
this._shellwm.completed_destroy(actor);
return;
}
actor.move_anchor_point_from_gravity(Clutter.Gravity.CENTER);
/* anachronistic 'tv-like' effect - squash on y axis, leave x alone */
this._destroying.push(actor);
Tweener.addTween(actor,
{ scale_x: 1.0,
scale_y: 0.0,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._destroyWindowDone,
onCompleteScope: this,
onCompleteParams: [actor]
});
},
_destroyWindowDone : function(actor) {
let idx = this._destroying.indexOf(actor);
if (idx != -1) {
this._shellwm.completed_destroy(actor);
Tweener.removeTweens(actor);
actor.set_scale(1.0, 1.0);
this._mapping.splice(idx, 1);
}
},
_switchWorkspace : function(windows, from, to, direction) {
// If the overlay is active, it will do the transition itself
if (Main.overlayActive) {
this._shellwm.completed_switch_workspace();
@ -96,7 +296,7 @@ WindowManager.prototype = {
y: yDest,
time: SWITCH_ANIMATION_TIME,
transition: "easeOutBack",
onComplete: this.switchWorkspaceDone
onComplete: this._switchWorkspaceDone
});
Tweener.addTween(switchData.inGroup,
{ x: 0,
@ -106,7 +306,7 @@ WindowManager.prototype = {
});
},
switchWorkspaceDone : function() {
_switchWorkspaceDone : function() {
let switchData = this._switchData;
if (!switchData)
return;

View File

@ -46,7 +46,6 @@ static void gnome_shell_plugin_constructed (GObject *object);
static void gnome_shell_plugin_dispose (GObject *object);
static void gnome_shell_plugin_finalize (GObject *object);
#ifdef NOT_YET
static void gnome_shell_plugin_minimize (MutterPlugin *plugin,
MutterWindow *actor);
static void gnome_shell_plugin_maximize (MutterPlugin *plugin,
@ -65,7 +64,6 @@ static void gnome_shell_plugin_map (MutterPlugin *plugi
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,
@ -121,13 +119,11 @@ gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
gobject_class->dispose = gnome_shell_plugin_dispose;
gobject_class->finalize = gnome_shell_plugin_finalize;
#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
plugin_class->switch_workspace = gnome_shell_plugin_switch_workspace;
plugin_class->kill_effect = gnome_shell_plugin_kill_effect;
@ -212,6 +208,55 @@ get_shell_wm (void)
return wm;
}
static void
gnome_shell_plugin_minimize (MutterPlugin *plugin,
MutterWindow *actor)
{
_shell_wm_minimize (get_shell_wm (),
actor);
}
static void
gnome_shell_plugin_maximize (MutterPlugin *plugin,
MutterWindow *actor,
gint x,
gint y,
gint width,
gint height)
{
_shell_wm_maximize (get_shell_wm (),
actor, x, y, width, height);
}
static void
gnome_shell_plugin_unmaximize (MutterPlugin *plugin,
MutterWindow *actor,
gint x,
gint y,
gint width,
gint height)
{
_shell_wm_unmaximize (get_shell_wm (),
actor, x, y, width, height);
}
static void
gnome_shell_plugin_map (MutterPlugin *plugin,
MutterWindow *actor)
{
_shell_wm_map (get_shell_wm (),
actor);
}
static void
gnome_shell_plugin_destroy (MutterPlugin *plugin,
MutterWindow *actor)
{
_shell_wm_destroy (get_shell_wm (),
actor);
}
static void
gnome_shell_plugin_switch_workspace (MutterPlugin *plugin,
const GList **actors,

View File

@ -1 +1,2 @@
VOID:INT,INT,INT
VOID:OBJECT,INT,INT,INT,INT

View File

@ -14,7 +14,6 @@ struct _ShellWM {
/* Signals */
enum
{
#ifdef NOT_YET
MINIMIZE,
KILL_MINIMIZE,
MAXIMIZE,
@ -25,7 +24,6 @@ enum
KILL_MAP,
DESTROY,
KILL_DESTROY,
#endif
SWITCH_WORKSPACE,
KILL_SWITCH_WORKSPACE,
@ -61,6 +59,96 @@ shell_wm_class_init (ShellWMClass *klass)
gobject_class->finalize = shell_wm_finalize;
shell_wm_signals[MINIMIZE] =
g_signal_new ("minimize",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
MUTTER_TYPE_COMP_WINDOW);
shell_wm_signals[KILL_MINIMIZE] =
g_signal_new ("kill-minimize",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
MUTTER_TYPE_COMP_WINDOW);
shell_wm_signals[MAXIMIZE] =
g_signal_new ("maximize",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
_shell_marshal_VOID__OBJECT_INT_INT_INT_INT,
G_TYPE_NONE, 5,
MUTTER_TYPE_COMP_WINDOW, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
shell_wm_signals[KILL_MAXIMIZE] =
g_signal_new ("kill-maximize",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
MUTTER_TYPE_COMP_WINDOW);
shell_wm_signals[UNMAXIMIZE] =
g_signal_new ("unmaximize",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
_shell_marshal_VOID__OBJECT_INT_INT_INT_INT,
G_TYPE_NONE, 1,
MUTTER_TYPE_COMP_WINDOW, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
shell_wm_signals[KILL_UNMAXIMIZE] =
g_signal_new ("kill-unmaximize",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
MUTTER_TYPE_COMP_WINDOW);
shell_wm_signals[MAP] =
g_signal_new ("map",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
MUTTER_TYPE_COMP_WINDOW);
shell_wm_signals[KILL_MAP] =
g_signal_new ("kill-map",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
MUTTER_TYPE_COMP_WINDOW);
shell_wm_signals[DESTROY] =
g_signal_new ("destroy",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
MUTTER_TYPE_COMP_WINDOW);
shell_wm_signals[KILL_DESTROY] =
g_signal_new ("kill-destroy",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
MUTTER_TYPE_COMP_WINDOW);
shell_wm_signals[SWITCH_WORKSPACE] =
g_signal_new ("switch-workspace",
G_TYPE_FROM_CLASS (klass),
@ -148,29 +236,149 @@ shell_wm_completed_switch_workspace (ShellWM *wm)
shell_wm_set_switch_workspace_actors (wm, NULL);
}
/**
* shell_wm_completed_minimize
* @wm: the ShellWM
* @actor: the MutterWindow actor
*
* The plugin must call this when it has completed a window minimize effect.
**/
void
shell_wm_completed_minimize (ShellWM *wm,
MutterWindow *actor)
{
mutter_plugin_effect_completed (wm->plugin,
actor,
MUTTER_PLUGIN_MINIMIZE);
}
/**
* shell_wm_completed_maximize
* @wm: the ShellWM
* @actor: the MutterWindow actor
*
* The plugin must call this when it has completed a window maximize effect.
**/
void
shell_wm_completed_maximize (ShellWM *wm,
MutterWindow *actor)
{
mutter_plugin_effect_completed (wm->plugin,
actor,
MUTTER_PLUGIN_MAXIMIZE);
}
/**
* shell_wm_completed_unmaximize
* @wm: the ShellWM
* @actor: the MutterWindow actor
*
* The plugin must call this when it has completed a window unmaximize effect.
**/
void
shell_wm_completed_unmaximize (ShellWM *wm,
MutterWindow *actor)
{
mutter_plugin_effect_completed (wm->plugin,
actor,
MUTTER_PLUGIN_UNMAXIMIZE);
}
/**
* shell_wm_completed_map
* @wm: the ShellWM
* @actor: the MutterWindow actor
*
* The plugin must call this when it has completed a window map effect.
**/
void
shell_wm_completed_map (ShellWM *wm,
MutterWindow *actor)
{
mutter_plugin_effect_completed (wm->plugin,
actor,
MUTTER_PLUGIN_MAP);
}
/**
* shell_wm_completed_destroy
* @wm: the ShellWM
* @actor: the MutterWindow actor
*
* The plugin must call this when it has completed a window destroy effect.
**/
void
shell_wm_completed_destroy (ShellWM *wm,
MutterWindow *actor)
{
mutter_plugin_effect_completed (wm->plugin,
actor,
MUTTER_PLUGIN_DESTROY);
}
void
_shell_wm_kill_effect (ShellWM *wm,
MutterWindow *actor,
gulong events)
{
#ifdef NOT_YET
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, actor);
if (events & MUTTER_PLUGIN_MAXIMIZE)
g_signal_emit (wm, shell_wm_signals[KILL_MAXIMIZE], 0);
g_signal_emit (wm, shell_wm_signals[KILL_MAXIMIZE], 0, actor);
if (events & MUTTER_PLUGIN_UNMAXIMIZE)
g_signal_emit (wm, shell_wm_signals[KILL_UNMAXIMIZE], 0);
g_signal_emit (wm, shell_wm_signals[KILL_UNMAXIMIZE], 0, actor);
if (events & MUTTER_PLUGIN_MAP)
g_signal_emit (wm, shell_wm_signals[KILL_MAP], 0);
g_signal_emit (wm, shell_wm_signals[KILL_MAP], 0, actor);
if (events & MUTTER_PLUGIN_DESTROY)
g_signal_emit (wm, shell_wm_signals[KILL_DESTROY], 0);
#endif
g_signal_emit (wm, shell_wm_signals[KILL_DESTROY], 0, actor);
if (events & MUTTER_PLUGIN_SWITCH_WORKSPACE)
g_signal_emit (wm, shell_wm_signals[KILL_SWITCH_WORKSPACE], 0);
}
void
_shell_wm_minimize (ShellWM *wm,
MutterWindow *actor)
{
g_signal_emit (wm, shell_wm_signals[MINIMIZE], 0, actor);
}
void
_shell_wm_maximize (ShellWM *wm,
MutterWindow *actor,
int target_x,
int target_y,
int target_width,
int target_height)
{
g_signal_emit (wm, shell_wm_signals[MAXIMIZE], 0, actor, target_x, target_y, target_width, target_height);
}
void
_shell_wm_unmaximize (ShellWM *wm,
MutterWindow *actor,
int target_x,
int target_y,
int target_width,
int target_height)
{
g_signal_emit (wm, shell_wm_signals[UNMAXIMIZE], 0, actor, target_x, target_y, target_width, target_height);
}
void
_shell_wm_map (ShellWM *wm,
MutterWindow *actor)
{
g_signal_emit (wm, shell_wm_signals[MAP], 0, actor);
}
void
_shell_wm_destroy (ShellWM *wm,
MutterWindow *actor)
{
g_signal_emit (wm, shell_wm_signals[DESTROY], 0, actor);
}
/**
* shell_wm_new:
* @plugin: the #MutterPlugin

View File

@ -27,12 +27,22 @@ GType shell_wm_get_type (void) G_GNUC_CONST;
ShellWM *shell_wm_new (MutterPlugin *plugin);
GList *shell_wm_get_switch_workspace_actors (ShellWM *wm);
void shell_wm_completed_minimize (ShellWM *wm,
MutterWindow *actor);
void shell_wm_completed_maximize (ShellWM *wm,
MutterWindow *actor);
void shell_wm_completed_unmaximize (ShellWM *wm,
MutterWindow *actor);
void shell_wm_completed_map (ShellWM *wm,
MutterWindow *actor);
void shell_wm_completed_destroy (ShellWM *wm,
MutterWindow *actor);
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,
@ -51,7 +61,6 @@ 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,