Track changes to the screen's n-workspaces property, and add and remove

workspaces from the overlay as needed. #564181

svn path=/trunk/; revision=127
This commit is contained in:
Dan Winship 2008-12-15 21:03:07 +00:00
parent 97ae22dae5
commit 8c59c2b5bf

View File

@ -37,6 +37,8 @@ function Workspaces(x, y, width, height) {
Workspaces.prototype = {
_init : function(x, y, width, height) {
let me = this;
this.actor = new Clutter.Group();
this._x = x;
@ -54,7 +56,6 @@ Workspaces.prototype = {
// of its clone windows together when the workspace is
// activated), figure out their initial grid positions, and
// add the desktop windows
this._workspaces = [];
for (let w = 0; w < global.screen.n_workspaces; w++) {
this._workspaces[w] = new Clutter.Group();
if (w == activeWorkspaceIndex)
@ -98,7 +99,6 @@ Workspaces.prototype = {
let desktop = workspace.get_nth_child(0);
desktop.set_position(workspace.zoomedOutX, workspace.zoomedOutY);
desktop.origX = desktop.origY = 0;
Tweener.addTween(desktop,
{ x: workspace.gridX,
@ -124,6 +124,13 @@ Workspaces.prototype = {
windowIndex++;
}
}
// Track changes to the number of workspaces
this._nWorkspacesNotifyId =
global.screen.connect('notify::n-workspaces',
function() {
me._workspacesChanged();
});
},
hide : function() {
@ -162,6 +169,8 @@ Workspaces.prototype = {
},
destroy : function() {
let global = Shell.Global.get();
for (let w = 0; w < this._workspaces.length; w++) {
this._workspaces[w].destroy();
}
@ -169,6 +178,8 @@ Workspaces.prototype = {
this._backdrop.destroy();
this._backdrop = null;
global.screen.disconnect(this._nWorkspacesNotifyId);
},
// Assign grid positions to workspaces. We can't just do a simple
@ -182,6 +193,11 @@ Workspaces.prototype = {
//
// FIXME: need to make the metacity internal layout agree with this!
_positionWorkspaces : function(global, activeWorkspace) {
if (!activeWorkspace) {
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
activeWorkspace = this._workspaces[activeWorkspaceIndex];
}
let gridWidth = Math.ceil(Math.sqrt(this._workspaces.length));
let gridHeight = Math.ceil(this._workspaces.length / gridWidth);
@ -232,9 +248,23 @@ Workspaces.prototype = {
this._backdropHeight = gridHeight * (global.screen_height + GRID_SPACING) - GRID_SPACING;
},
_createDesktopActors : function(windows) {
let me = this;
_setupDesktop : function(desktop, workspaceNum) {
let global = Shell.Global.get();
let workspace = global.screen.get_workspace_by_index(workspaceNum);
desktop.connect("button-press-event",
function(clone, event) {
workspace.activate(event.get_time());
Main.hide_overlay();
});
this._workspaces[workspaceNum].add_actor(desktop);
desktop.origX = desktop.origY = 0;
},
_createDesktopActors : function(windows) {
if (!windows) {
let global = Shell.Global.get();
windows = global.get_windows();
}
// Find the desktop window or windows
for (let i = 0; i < windows.length; i++) {
@ -242,26 +272,23 @@ Workspaces.prototype = {
continue;
if (windows[i].get_meta_window().is_on_all_workspaces()) {
for (let w = 0; w < this._workspaces.length; w++)
this._workspaces[w].add_actor(this._cloneWindow(windows[i]));
for (let w = 0; w < this._workspaces.length; w++) {
if (this._workspaces[w].get_n_children() == 0)
this._setupDesktop(this._cloneWindow(windows[i]), w);
}
break;
} else
this._workspaces[windows[i].get_workspace()].add_actor(this._cloneWindow(windows[i]));
} else {
let desktopWorkspace = windows[i].get_workspace;
if (this._workspaces[desktopWorkspace].get_n_children() == 0)
this._setupDesktop(this._cloneWindow(windows[i]), desktopWorkspace);
}
}
// Create dummy desktops for workspaces that don't have
// desktop windows, and hook up button events on all desktops
for (let w = 0; w < this._workspaces.length; w++) {
if (this._workspaces[w].get_n_children() == 0)
this._workspaces[w].add_actor(this._createDesktopRectangle());
let workspace = global.screen.get_workspace_by_index(w);
this._workspaces[w].get_nth_child(0).connect(
"button-press-event",
function(clone, event) {
workspace.activate(event.get_time());
me._deactivate();
});
this._setupDesktop(this._createDesktopRectangle(), w);
}
},
@ -372,11 +399,111 @@ Workspaces.prototype = {
workspace.activate_with_focus(w.get_meta_window(), time);
} else
w.get_meta_window().activate(time);
this._deactivate();
Main.hide_overlay();
},
_deactivate : function() {
Main.hide_overlay();
_workspacesChanged : function() {
let global = Shell.Global.get();
let oldNumWorkspaces = this._workspaces.length;
let newNumWorkspaces = global.screen.n_workspaces;
if (oldNumWorkspaces == newNumWorkspaces)
return;
let oldScale = this._workspaces[0].gridScale;
let oldGridWidth = Math.ceil(Math.sqrt(oldNumWorkspaces));
let oldGridHeight = Math.ceil(oldNumWorkspaces / oldGridWidth);
let lostWorkspaces = [];
if (newNumWorkspaces > oldNumWorkspaces) {
// Create new workspace groups
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
this._workspaces[w] = new Clutter.Group();
this.actor.add_actor(this._workspaces[w]);
}
} else {
// Truncate the list of workspaces
// FIXME: assumes that the workspaces are being removed from
// the end of the list, not the start/middle
lostWorkspaces = this._workspaces.splice(newNumWorkspaces);
}
// Figure out the new layout
this._positionWorkspaces(global);
let newScale = this._workspaces[0].gridScale;
let newGridWidth = Math.ceil(Math.sqrt(newNumWorkspaces));
let newGridHeight = Math.ceil(newNumWorkspaces / newGridWidth);
if (newGridWidth != oldGridWidth || newGridHeight != oldGridHeight) {
// We need to resize/move the existing workspaces/windows
let existingWorkspaces = Math.min(oldNumWorkspaces, newNumWorkspaces);
for (let w = 0; w < existingWorkspaces; w++) {
let workspace = this._workspaces[w];
let windows = workspace.get_children();
let desktop = windows[0];
for (let i = 0; i < windows.length; i++) {
let newX = workspace.gridX + (windows[i].x - desktop.x) * newScale / oldScale;
let newY = workspace.gridY + (windows[i].y - desktop.y) * newScale / oldScale;
let newWindowScale = windows[i].scale_x * newScale / oldScale;
Tweener.addTween(windows[i],
{ x: newX,
y: newY,
scale_x: newWindowScale,
scale_y: newWindowScale,
time: Overlay.ANIMATION_TIME,
transition: "easeOutQuad"
});
}
}
}
if (newNumWorkspaces > oldNumWorkspaces) {
// Slide new workspaces in from offscreen
this._createDesktopActors();
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
let workspace = this._workspaces[w];
let desktop = this._workspaces[w].get_nth_child(0);
if (workspace.gridCol > workspace.gridRow) {
desktop.set_position(global.screen_width, workspace.gridY);
desktop.set_scale(oldScale, oldScale);
} else {
desktop.set_position(workspace.gridX, global.screen_height);
desktop.set_scale(workspace.gridScale, workspace.gridScale);
}
Tweener.addTween(desktop,
{ x: workspace.gridX,
y: workspace.gridY,
scale_x: workspace.gridScale,
scale_y: workspace.gridScale,
time: Overlay.ANIMATION_TIME,
transition: "easeOutQuad"
});
}
} else {
// Slide old workspaces out
for (let w = 0; w < lostWorkspaces.length; w++) {
let workspace = lostWorkspaces[w];
let desktop = lostWorkspaces[w].get_nth_child(0);
let destX = desktop.x, destY = desktop.y;
if (workspace.gridCol > workspace.gridRow)
destX = global.screen_width;
else
destY = global.screen_height;
Tweener.addTween(desktop,
{ x: destX,
y: destY,
scale_x: newScale,
scale_y: newScale,
time: Overlay.ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: function() { workspace.destroy(); }
});
}
// FIXME: deal with windows on the lost workspaces
}
}
};