[gnome-shell] Animate workspace view switches
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] Animate workspace view switches
- Date: Thu, 18 Mar 2010 22:41:22 +0000 (UTC)
commit 5a6c9f176ea470a8153796aad7a740dad59eba57
Author: Florian Müllner <fmuellner src gnome org>
Date: Mon Feb 15 14:29:34 2010 +0100
Animate workspace view switches
Replace the hard switch between linear and mosaic workspace view
with a an animated transition between the views.
https://bugzilla.gnome.org/show_bug.cgi?id=610191
js/ui/overview.js | 3 -
js/ui/workspace.js | 3 +
js/ui/workspacesView.js | 193 ++++++++++++++++++++++++++++++++++++----------
3 files changed, 154 insertions(+), 45 deletions(-)
---
diff --git a/js/ui/overview.js b/js/ui/overview.js
index 8bf7d93..3a5278a 100644
--- a/js/ui/overview.js
+++ b/js/ui/overview.js
@@ -263,9 +263,6 @@ Overview.prototype = {
// Show new workspacesView
this._group.add_actor(this._workspaces.actor);
this._dash.actor.raise(this._workspaces.actor);
-
- // Set new position and scale to workspaces.
- this.emit('showing');
},
_recalculateGridSizes: function () {
diff --git a/js/ui/workspace.js b/js/ui/workspace.js
index 4c58a49..8b570a4 100644
--- a/js/ui/workspace.js
+++ b/js/ui/workspace.js
@@ -1212,6 +1212,9 @@ Workspace.prototype = {
cloneWidth = this.scale * clone.actor.scale_x * cloneWidth;
cloneHeight = this.scale * clone.actor.scale_y * cloneHeight;
+ if (!this._windowOverlaysGroup.visible)
+ this._windowOverlaysGroup.show();
+
if (overlay) {
overlay.updatePositions(cloneX, cloneY, cloneWidth, cloneHeight);
overlay.fadeIn();
diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js
index dc7947c..bdf786e 100644
--- a/js/ui/workspacesView.js
+++ b/js/ui/workspacesView.js
@@ -55,7 +55,10 @@ GenericWorkspacesView.prototype = {
let node = this.actor.get_theme_node();
let [a, spacing] = node.get_length('spacing', false);
this._spacing = spacing;
- this._positionWorkspaces();
+ if (Main.overview.animationInProgress)
+ this._positionWorkspaces();
+ else
+ this._transitionWorkspaces();
}));
this._width = width;
@@ -248,6 +251,10 @@ GenericWorkspacesView.prototype = {
throw new Error("Not implemented");
},
+ _transitionWorkspaces: function() {
+ throw new Error("Not implemented");
+ },
+
_positionWorkspaces: function() {
throw new Error("Not implemented");
},
@@ -326,6 +333,54 @@ MosaicView.prototype = {
}
},
+ _transitionWorkspaces: function() {
+ // update workspace parameters
+ this._positionWorkspaces();
+
+ let active = global.screen.get_active_workspace_index();
+ let activeWorkspace = this._workspaces[active];
+ // scale is the factor needed to translate from the new scale
+ // (this view) to the currently active scale (previous view)
+ let scale = this._workspaces[0].actor.scale_x / activeWorkspace.scale;
+
+ for (let w = 0; w < this._workspaces.length; w++) {
+ let workspace = this._workspaces[w];
+ let originX, originY;
+ let dx, dy;
+
+ // The correct transition would be a straightforward animation
+ // of each workspace's old position/scale to the new one;
+ // however, this looks overly busy, so we only use a zoom effect.
+ // Unfortunately this implies that we cannot pretend to not knowing
+ // the other view's layout at this point:
+ // We position the workspaces in the grid, which we scale up so
+ // that the active workspace fills the viewport.
+ dx = workspace.gridX - activeWorkspace.gridX;
+ dy = workspace.gridY - activeWorkspace.gridY;
+ originX = this._x + scale * dx;
+ originY = this._y + scale * dy;
+
+ workspace.actor.set_position(originX, originY);
+
+ workspace.positionWindows(Workspace.WindowPositionFlags.ANIMATE);
+ workspace.setSelected(false);
+ workspace.hideWindowsOverlays();
+
+ Tweener.addTween(workspace.actor,
+ { x: workspace.gridX,
+ y: workspace.gridY,
+ scale_x: workspace.scale,
+ scale_y: workspace.scale,
+ time: Overview.ANIMATION_TIME,
+ transition: 'easeOutQuad',
+ onComplete: function() {
+ workspace.zoomToOverview(false);
+ if (workspace.metaWorkspace.index() == active)
+ workspace.setSelected(true);
+ }});
+ }
+ },
+
updateWorkspaces: function(oldNumWorkspaces, newNumWorkspaces, lostWorkspaces) {
let oldScale = this._workspaces[0].scale;
let oldGridWidth = Math.ceil(Math.sqrt(oldNumWorkspaces));
@@ -529,6 +584,46 @@ SingleView.prototype = {
this._rightShadow.gridY = this._y + (this._height - this._rightShadow.height * scale) / 2;
},
+ _transitionWorkspaces: function() {
+ // update workspace parameters
+ this._positionWorkspaces();
+
+ let active = global.screen.get_active_workspace_index();
+ let activeActor = this._workspaces[active].actor;
+ // scale is the factor needed to translate from the currently
+ // active scale (previous view) to the new scale (this view)
+ let scale = this._workspaces[active].scale / activeActor.scale_x;
+
+ for (let w = 0; w < this._workspaces.length; w++) {
+ let workspace = this._workspaces[w];
+ let targetX, targetY;
+
+ // The correct transition would be a straightforward animation
+ // of each workspace's old position/scale to the new one;
+ // however, this looks overly busy, so we only use a zoom effect.
+ // Therefore we scale up each workspace's distance to the active
+ // workspace, so the latter fills the viewport while the other
+ // workspaces maintain their relative position
+ targetX = this._x + scale * (workspace.actor.x - activeActor.x);
+ targetY = this._y + scale * (workspace.actor.y - activeActor.y);
+
+ workspace.positionWindows(Workspace.WindowPositionFlags.ANIMATE);
+ workspace.setSelected(false);
+ workspace._hideAllOverlays();
+
+ Tweener.addTween(workspace.actor,
+ { x: targetX,
+ y: targetY,
+ scale_x: workspace.scale,
+ scale_y: workspace.scale,
+ time: Overview.ANIMATION_TIME,
+ transition: 'easeOutQuad',
+ onComplete: function() {
+ workspace.zoomToOverview(false);
+ }});
+ }
+ },
+
_scrollToActive: function(showAnimation) {
let active = global.screen.get_active_workspace_index();
@@ -1228,11 +1323,9 @@ function WorkspacesControls() {
WorkspacesControls.prototype = {
_init: function() {
this.actor = new St.BoxLayout({ style_class: 'workspaces-bar' });
- this._gconf = Shell.GConf.get_default();
+ this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
- this._toggleViewButton = null;
- this._addButton = null;
- this._removeButton = null;
+ this._gconf = Shell.GConf.get_default();
let view = this._gconf.get_string(WORKSPACES_VIEW_KEY).toUpperCase();
if (view in WorkspacesViewType)
@@ -1240,30 +1333,7 @@ WorkspacesControls.prototype = {
else
this._currentViewType = WorkspacesViewType.SINGLE;
- this._nWorkspacesNotifyId =
- global.screen.connect('notify::n-workspaces',
- Lang.bind(this, this._workspacesChanged));
-
- this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
- },
-
- _updateToggleButtonStyle: function() {
- if (this._currentViewType == WorkspacesViewType.SINGLE)
- this._toggleViewButton.set_style_class_name('workspace-controls switch-mosaic');
- else
- this._toggleViewButton.set_style_class_name('workspace-controls switch-single');
- },
-
- _setView: function(view) {
- if (this._currentViewType == view)
- return;
- this._currentViewType = view;
- this._updateToggleButtonStyle();
- this._gconf.set_string(WORKSPACES_VIEW_KEY, view);
- },
-
- updateControls: function(currentView) {
- this.actor.remove_all();
+ this._currentView = null;
// View switcher button
this._toggleViewButton = new St.Button();
@@ -1279,40 +1349,79 @@ WorkspacesControls.prototype = {
this.actor.add(this._toggleViewButton, { y_fill: false, y_align: St.Align.START });
// View specific controls
- let viewControls = currentView.createControllerBar();
- if (!viewControls)
- viewControls = new St.Bin();
- this.actor.add(viewControls, { expand: true,
- x_fill: true,
- y_fill: true,
- y_align: St.Align.MIDDLE,
- x_align: St.Align.START });
+ this._viewControls = new St.Bin({ x_fill: true, y_fill: true });
+ this.actor.add(this._viewControls, { expand: true, x_fill: true });
// Add/remove workspace buttons
this._removeButton = new St.Button({ style_class: 'workspace-controls remove' });
this._removeButton.connect('clicked', Lang.bind(this, function() {
- currentView.removeWorkspace();
+ this._currentView.removeWorkspace();
}));
this.actor.add(this._removeButton, { y_fill: false,
y_align: St.Align.START });
this._addButton = new St.Button({ style_class: 'workspace-controls add' });
this._addButton.connect('clicked', Lang.bind(this, function() {
- currentView.addWorkspace()
+ this._currentView.addWorkspace()
}));
this._addButton._delegate = this._addButton;
this._addButton._delegate.acceptDrop = Lang.bind(this,
function(source, actor, x, y, time) {
- let view = currentView;
- return view._acceptNewWorkspaceDrop(source, actor, x, y, time);
-return false;
+ return this._currentView._acceptNewWorkspaceDrop(source, actor, x, y, time);
});
this.actor.add(this._addButton, { y_fill: false,
y_align: St.Align.START });
+ this._nWorkspacesNotifyId =
+ global.screen.connect('notify::n-workspaces',
+ Lang.bind(this, this._workspacesChanged));
+
this._workspacesChanged();
},
+ updateControls: function(view) {
+ this._currentView = view;
+
+ let newControls = this._currentView.createControllerBar();
+ if (newControls) {
+ this._viewControls.child = newControls;
+ this._viewControls.child.opacity = 0;
+ Tweener.addTween(this._viewControls.child,
+ { opacity: 255,
+ time: Overview.ANIMATION_TIME,
+ transition: 'easeOutQuad' });
+ } else {
+ if (this._viewControls.child)
+ Tweener.addTween(this._viewControls.child,
+ { opacity: 0,
+ time: Overview.ANIMATION_TIME,
+ transition: 'easeOutQuad',
+ onComplete: Lang.bind(this, function() {
+ this._viewControls.child.destroy();
+ })});
+ }
+ },
+
+ _updateToggleButtonStyle: function() {
+ if (this._currentViewType == WorkspacesViewType.SINGLE)
+ this._toggleViewButton.set_style_class_name('workspace-controls switch-mosaic');
+ else
+ this._toggleViewButton.set_style_class_name('workspace-controls switch-single');
+ },
+
+ _setView: function(view) {
+ if (this._currentViewType == view)
+ return;
+
+ if (WorkspacesViewType.SINGLE == view)
+ this._toggleViewButton.set_style_class_name('workspace-controls switch-mosaic');
+ else
+ this._toggleViewButton.set_style_class_name('workspace-controls switch-single');
+
+ this._currentViewType = view;
+ this._gconf.set_string(WORKSPACES_VIEW_KEY, view);
+ },
+
setCanRemove: function(canRemove) {
this._setButtonSensitivity(this._removeButton, canRemove);
},
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]