2010-01-21 21:33:48 -05:00
|
|
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
|
|
|
|
|
|
const Big = imports.gi.Big;
|
|
|
|
const Clutter = imports.gi.Clutter;
|
|
|
|
const GdkPixbuf = imports.gi.GdkPixbuf;
|
|
|
|
const Gdk = imports.gi.Gdk;
|
|
|
|
const Gtk = imports.gi.Gtk;
|
|
|
|
const Lang = imports.lang;
|
|
|
|
const Mainloop = imports.mainloop;
|
|
|
|
const Meta = imports.gi.Meta;
|
|
|
|
const Pango = imports.gi.Pango;
|
|
|
|
const Shell = imports.gi.Shell;
|
|
|
|
const St = imports.gi.St;
|
|
|
|
const Signals = imports.signals;
|
|
|
|
|
|
|
|
const DND = imports.ui.dnd;
|
|
|
|
const Lightbox = imports.ui.lightbox;
|
|
|
|
const Main = imports.ui.main;
|
|
|
|
const Overview = imports.ui.overview;
|
|
|
|
const Panel = imports.ui.panel;
|
|
|
|
const Tweener = imports.ui.tweener;
|
|
|
|
const Workspace = imports.ui.workspace;
|
|
|
|
|
|
|
|
const WORKSPACE_SWITCH_TIME = 0.25;
|
|
|
|
// Note that mutter has a compile-time limit of 36
|
|
|
|
const MAX_WORKSPACES = 16;
|
|
|
|
|
2010-02-13 16:39:13 -05:00
|
|
|
// The values here are also used for gconf, and the key and value
|
|
|
|
// names must match
|
2010-01-21 21:33:48 -05:00
|
|
|
const WorkspacesViewType = {
|
2010-02-13 16:39:13 -05:00
|
|
|
SINGLE: 'single',
|
|
|
|
GRID: 'grid'
|
2010-01-21 21:33:48 -05:00
|
|
|
};
|
2010-02-13 16:39:13 -05:00
|
|
|
const WORKSPACES_VIEW_KEY = 'overview/workspaces_view';
|
2010-01-21 21:33:48 -05:00
|
|
|
|
2010-03-16 11:51:24 -04:00
|
|
|
const WORKSPACE_DRAGGING_SCALE = 0.85;
|
|
|
|
const WORKSPACE_SHADOW_SCALE = (1 - WORKSPACE_DRAGGING_SCALE) / 2;
|
|
|
|
|
2010-01-21 21:33:48 -05:00
|
|
|
function GenericWorkspacesView(width, height, x, y, animate) {
|
|
|
|
this._init(width, height, x, y, animate);
|
|
|
|
}
|
|
|
|
|
|
|
|
GenericWorkspacesView.prototype = {
|
|
|
|
_init: function(width, height, x, y, animate) {
|
|
|
|
this.actor = new St.Bin({ style_class: "workspaces" });
|
|
|
|
this._actor = new Clutter.Group();
|
|
|
|
|
2010-02-18 10:43:58 -05:00
|
|
|
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
|
|
|
|
2010-01-21 21:33:48 -05:00
|
|
|
this.actor.add_actor(this._actor);
|
2010-02-10 01:00:02 -05:00
|
|
|
this.actor.connect('style-changed', Lang.bind(this,
|
|
|
|
function() {
|
|
|
|
let node = this.actor.get_theme_node();
|
|
|
|
let [a, spacing] = node.get_length('spacing', false);
|
|
|
|
this._spacing = spacing;
|
|
|
|
this._positionWorkspaces();
|
|
|
|
}));
|
2010-01-21 21:33:48 -05:00
|
|
|
|
|
|
|
this._width = width;
|
|
|
|
this._height = height;
|
|
|
|
this._x = x;
|
|
|
|
this._y = y;
|
2010-02-10 01:00:02 -05:00
|
|
|
this._spacing = 0;
|
2010-01-21 21:33:48 -05:00
|
|
|
|
|
|
|
this._windowSelectionAppId = null;
|
|
|
|
|
|
|
|
this._workspaces = [];
|
|
|
|
|
|
|
|
this._highlightWindow = null;
|
|
|
|
|
|
|
|
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
|
|
|
|
|
|
|
// Create and position workspace objects
|
|
|
|
for (let w = 0; w < global.screen.n_workspaces; w++) {
|
|
|
|
this._addWorkspaceActor(w);
|
|
|
|
}
|
|
|
|
this._workspaces[activeWorkspaceIndex].actor.raise_top();
|
|
|
|
|
|
|
|
// Position/scale the desktop windows and their children after the
|
|
|
|
// workspaces have been created. This cannot be done first because
|
|
|
|
// window movement depends on the Workspaces object being accessible
|
|
|
|
// as an Overview member.
|
|
|
|
this._overviewShowingId =
|
|
|
|
Main.overview.connect('showing',
|
|
|
|
Lang.bind(this, function() {
|
|
|
|
this._onRestacked();
|
|
|
|
for (let w = 0; w < this._workspaces.length; w++)
|
|
|
|
this._workspaces[w].zoomToOverview(animate);
|
|
|
|
}));
|
|
|
|
|
|
|
|
// Track changes to the number of workspaces
|
|
|
|
this._nWorkspacesNotifyId =
|
|
|
|
global.screen.connect('notify::n-workspaces',
|
|
|
|
Lang.bind(this, this._workspacesChanged));
|
|
|
|
this._switchWorkspaceNotifyId =
|
|
|
|
global.window_manager.connect('switch-workspace',
|
|
|
|
Lang.bind(this, this._activeWorkspaceChanged));
|
|
|
|
this._restackedNotifyId =
|
|
|
|
global.screen.connect('restacked',
|
|
|
|
Lang.bind(this, this._onRestacked));
|
|
|
|
},
|
|
|
|
|
|
|
|
_lookupWorkspaceForMetaWindow: function (metaWindow) {
|
|
|
|
for (let i = 0; i < this._workspaces.length; i++) {
|
|
|
|
if (this._workspaces[i].containsMetaWindow(metaWindow))
|
|
|
|
return this._workspaces[i];
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
|
|
|
|
_lookupCloneForMetaWindow: function (metaWindow) {
|
|
|
|
for (let i = 0; i < this._workspaces.length; i++) {
|
|
|
|
let clone = this._workspaces[i].lookupCloneForMetaWindow(metaWindow);
|
|
|
|
if (clone)
|
|
|
|
return clone;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
|
|
|
|
setHighlightWindow: function (metaWindow) {
|
|
|
|
// Looping over all workspaces is easier than keeping track of the last
|
|
|
|
// highlighted window while trying to handle the window or workspace possibly
|
|
|
|
// going away.
|
|
|
|
for (let i = 0; i < this._workspaces.length; i++) {
|
|
|
|
this._workspaces[i].setHighlightWindow(null);
|
|
|
|
}
|
|
|
|
if (metaWindow != null) {
|
|
|
|
let workspace = this._lookupWorkspaceForMetaWindow(metaWindow);
|
|
|
|
workspace.setHighlightWindow(metaWindow);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_clearApplicationWindowSelection: function(reposition) {
|
|
|
|
if (this._windowSelectionAppId == null)
|
|
|
|
return;
|
|
|
|
this._windowSelectionAppId = null;
|
|
|
|
|
|
|
|
for (let i = 0; i < this._workspaces.length; i++) {
|
|
|
|
this._workspaces[i].setLightboxMode(false);
|
|
|
|
this._workspaces[i].setShowOnlyWindows(null, reposition);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* setApplicationWindowSelection:
|
|
|
|
* @appid: Application identifier string
|
|
|
|
*
|
|
|
|
* Enter a mode which shows only the windows owned by the
|
|
|
|
* given application, and allow highlighting of a specific
|
|
|
|
* window with setHighlightWindow().
|
|
|
|
*/
|
|
|
|
setApplicationWindowSelection: function (appId) {
|
|
|
|
if (appId == null) {
|
|
|
|
this._clearApplicationWindowSelection(true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (appId == this._windowSelectionAppId)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this._windowSelectionAppId = appId;
|
|
|
|
|
|
|
|
let appSys = Shell.AppSystem.get_default();
|
|
|
|
|
|
|
|
let showOnlyWindows = {};
|
|
|
|
let app = appSys.get_app(appId);
|
|
|
|
let windows = app.get_windows();
|
|
|
|
for (let i = 0; i < windows.length; i++) {
|
|
|
|
showOnlyWindows[windows[i]] = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let i = 0; i < this._workspaces.length; i++) {
|
|
|
|
this._workspaces[i].setLightboxMode(true);
|
|
|
|
this._workspaces[i].setShowOnlyWindows(showOnlyWindows, true);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
hide: function() {
|
|
|
|
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
|
|
|
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
|
|
|
|
|
2010-02-17 14:05:06 -05:00
|
|
|
if (this._windowSelectionAppId != null)
|
|
|
|
this._clearApplicationWindowSelection(false);
|
|
|
|
|
2010-01-21 21:33:48 -05:00
|
|
|
activeWorkspace.actor.raise_top();
|
|
|
|
|
|
|
|
for (let w = 0; w < this._workspaces.length; w++)
|
|
|
|
this._workspaces[w].zoomFromOverview();
|
|
|
|
},
|
|
|
|
|
|
|
|
destroy: function() {
|
2010-02-18 10:43:58 -05:00
|
|
|
this.actor.destroy();
|
|
|
|
},
|
|
|
|
|
|
|
|
_onDestroy: function() {
|
2010-01-21 21:33:48 -05:00
|
|
|
for (let w = 0; w < this._workspaces.length; w++)
|
|
|
|
this._workspaces[w].destroy();
|
|
|
|
this._workspaces = [];
|
|
|
|
|
|
|
|
Main.overview.disconnect(this._overviewShowingId);
|
|
|
|
global.screen.disconnect(this._nWorkspacesNotifyId);
|
|
|
|
global.window_manager.disconnect(this._switchWorkspaceNotifyId);
|
|
|
|
global.screen.disconnect(this._restackedNotifyId);
|
|
|
|
},
|
|
|
|
|
|
|
|
getScale: function() {
|
|
|
|
return this._workspaces[0].scale;
|
|
|
|
},
|
|
|
|
|
|
|
|
_onRestacked: function() {
|
|
|
|
let stack = global.get_windows();
|
|
|
|
let stackIndices = {};
|
|
|
|
|
|
|
|
for (let i = 0; i < stack.length; i++) {
|
|
|
|
// Use the stable sequence for an integer to use as a hash key
|
|
|
|
stackIndices[stack[i].get_meta_window().get_stable_sequence()] = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let i = 0; i < this._workspaces.length; i++)
|
|
|
|
this._workspaces[i].syncStacking(stackIndices);
|
|
|
|
},
|
|
|
|
|
|
|
|
// Handles a drop onto the (+) button; assumes the new workspace
|
|
|
|
// has already been added
|
|
|
|
acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
|
|
|
|
return this._workspaces[this._workspaces.length - 1].acceptDrop(source, dropActor, x, y, time);
|
|
|
|
},
|
|
|
|
|
|
|
|
// Get the grid position of the active workspace.
|
|
|
|
getActiveWorkspacePosition: function() {
|
|
|
|
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
|
|
|
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
|
|
|
|
|
|
|
|
return [activeWorkspace.gridX, activeWorkspace.gridY];
|
|
|
|
},
|
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
createControllerBar: function() {
|
|
|
|
throw new Error("Not implemented");
|
2010-01-23 06:24:49 -05:00
|
|
|
},
|
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
canAddWorkspace: function() {
|
|
|
|
return global.screen.n_workspaces < MAX_WORKSPACES;
|
|
|
|
},
|
|
|
|
|
|
|
|
addWorkspace: function() {
|
|
|
|
throw new Error("Not implemented");
|
|
|
|
},
|
|
|
|
|
|
|
|
canRemoveWorkspace: function() {
|
|
|
|
throw new Error("Not implemented");
|
|
|
|
},
|
|
|
|
|
|
|
|
removeWorkspace: function() {
|
2010-01-21 21:33:48 -05:00
|
|
|
throw new Error("Not implemented");
|
|
|
|
},
|
|
|
|
|
|
|
|
_positionWorkspaces: function() {
|
|
|
|
throw new Error("Not implemented");
|
|
|
|
},
|
|
|
|
|
|
|
|
_workspacesChanged: function() {
|
|
|
|
throw new Error("Not implemented");
|
|
|
|
},
|
|
|
|
|
|
|
|
_activeWorkspaceChanged: function() {
|
|
|
|
throw new Error("Not implemented");
|
|
|
|
},
|
|
|
|
|
|
|
|
_addWorkspaceActor: function() {
|
|
|
|
throw new Error("Not implemented");
|
|
|
|
}
|
2010-03-15 09:50:05 -04:00
|
|
|
};
|
2010-01-21 21:33:48 -05:00
|
|
|
|
|
|
|
function MosaicView(width, height, x, y, animate) {
|
|
|
|
this._init(width, height, x, y, animate);
|
|
|
|
}
|
|
|
|
|
|
|
|
MosaicView.prototype = {
|
|
|
|
__proto__: GenericWorkspacesView.prototype,
|
|
|
|
|
|
|
|
_init: function(width, height, x, y, animate) {
|
|
|
|
GenericWorkspacesView.prototype._init.call(this, width, height, x, y, animate);
|
|
|
|
|
2010-02-10 01:00:02 -05:00
|
|
|
this.actor.style_class = "workspaces mosaic";
|
2010-02-16 20:53:18 -05:00
|
|
|
this._actor.set_clip(x - Workspace.FRAME_SIZE,
|
|
|
|
y - Workspace.FRAME_SIZE,
|
|
|
|
width + 2 * Workspace.FRAME_SIZE,
|
|
|
|
height + 2 * Workspace.FRAME_SIZE);
|
2010-01-21 21:33:48 -05:00
|
|
|
this._workspaces[global.screen.get_active_workspace_index()].setSelected(true);
|
|
|
|
},
|
|
|
|
|
|
|
|
// Assign grid positions to workspaces. We can't just do a simple
|
|
|
|
// row-major or column-major numbering, because we don't want the
|
|
|
|
// existing workspaces to get rearranged when we add a row or
|
|
|
|
// column. So we alternate between adding to rows and adding to
|
|
|
|
// columns. (So, eg, when going from a 2x2 grid of 4 workspaces to
|
|
|
|
// a 3x2 grid of 5 workspaces, the 4 existing workspaces stay
|
|
|
|
// where they are, and the 5th one is added to the end of the
|
|
|
|
// first row.)
|
|
|
|
//
|
|
|
|
// FIXME: need to make the metacity internal layout agree with this!
|
|
|
|
_positionWorkspaces: function() {
|
|
|
|
let gridWidth = Math.ceil(Math.sqrt(this._workspaces.length));
|
|
|
|
let gridHeight = Math.ceil(this._workspaces.length / gridWidth);
|
|
|
|
|
2010-02-16 20:53:18 -05:00
|
|
|
// adjust vertical spacing so workspaces can preserve their aspect
|
|
|
|
// ratio without exceeding this._height
|
|
|
|
let verticalSpacing = this._spacing * this._height / this._width;
|
|
|
|
|
2010-02-10 01:00:02 -05:00
|
|
|
let wsWidth = (this._width - (gridWidth - 1) * this._spacing) / gridWidth;
|
2010-02-16 20:53:18 -05:00
|
|
|
let wsHeight = (this._height - (gridHeight - 1) * verticalSpacing) / gridHeight;
|
2010-01-21 21:33:48 -05:00
|
|
|
let scale = wsWidth / global.screen_width;
|
|
|
|
|
|
|
|
let span = 1, n = 0, row = 0, col = 0, horiz = true;
|
|
|
|
|
|
|
|
for (let w = 0; w < this._workspaces.length; w++) {
|
|
|
|
let workspace = this._workspaces[w];
|
|
|
|
|
|
|
|
workspace.gridRow = row;
|
|
|
|
workspace.gridCol = col;
|
|
|
|
|
2010-02-10 01:00:02 -05:00
|
|
|
workspace.gridX = this._x + workspace.gridCol * (wsWidth + this._spacing);
|
2010-02-16 20:53:18 -05:00
|
|
|
workspace.gridY = this._y + workspace.gridRow * (wsHeight + verticalSpacing);
|
2010-01-21 21:33:48 -05:00
|
|
|
workspace.scale = scale;
|
|
|
|
|
|
|
|
if (horiz) {
|
|
|
|
col++;
|
|
|
|
if (col == span) {
|
|
|
|
row = 0;
|
|
|
|
horiz = false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
row++;
|
|
|
|
if (row == span) {
|
|
|
|
col = 0;
|
|
|
|
horiz = true;
|
|
|
|
span++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_workspacesChanged: function() {
|
|
|
|
let oldNumWorkspaces = this._workspaces.length;
|
|
|
|
let newNumWorkspaces = global.screen.n_workspaces;
|
|
|
|
|
|
|
|
if (oldNumWorkspaces == newNumWorkspaces)
|
|
|
|
return;
|
|
|
|
|
|
|
|
let oldScale = this._workspaces[0].scale;
|
|
|
|
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._addWorkspaceActor(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();
|
|
|
|
let newScale = this._workspaces[0].scale;
|
|
|
|
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++)
|
|
|
|
this._workspaces[w].resizeToGrid(oldScale);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newScale != oldScale) {
|
|
|
|
// The workspace scale affects window size/positioning because we clamp
|
|
|
|
// window size to a 1:1 ratio and never scale them up
|
|
|
|
let existingWorkspaces = Math.min(oldNumWorkspaces, newNumWorkspaces);
|
|
|
|
for (let w = 0; w < existingWorkspaces; w++)
|
|
|
|
this._workspaces[w].positionWindows(Workspace.WindowPositionFlags.ANIMATE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newNumWorkspaces > oldNumWorkspaces) {
|
|
|
|
// Slide new workspaces in from offscreen
|
2010-02-19 13:27:07 -05:00
|
|
|
// New workspaces can contain windows.
|
|
|
|
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
|
|
|
|
this._workspaces[w].positionWindows(0);
|
2010-01-21 21:33:48 -05:00
|
|
|
this._workspaces[w].slideIn(oldScale);
|
2010-02-19 13:27:07 -05:00
|
|
|
}
|
2010-01-21 21:33:48 -05:00
|
|
|
} else {
|
|
|
|
// Slide old workspaces out
|
|
|
|
for (let w = 0; w < lostWorkspaces.length; w++) {
|
|
|
|
let workspace = lostWorkspaces[w];
|
|
|
|
workspace.slideOut(function () { workspace.destroy(); });
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: deal with windows on the lost workspaces
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reset the selection state; if we went from > 1 workspace to 1,
|
|
|
|
// this has the side effect of removing the frame border
|
|
|
|
let activeIndex = global.screen.get_active_workspace_index();
|
|
|
|
this._workspaces[activeIndex].setSelected(true);
|
|
|
|
},
|
|
|
|
|
|
|
|
_activeWorkspaceChanged: function(wm, from, to, direction) {
|
|
|
|
this._workspaces[from].setSelected(false);
|
|
|
|
this._workspaces[to].setSelected(true);
|
|
|
|
},
|
|
|
|
|
|
|
|
_addWorkspaceActor: function(workspaceNum) {
|
|
|
|
let workspace = new Workspace.Workspace(workspaceNum, this._actor);
|
|
|
|
this._workspaces[workspaceNum] = workspace;
|
|
|
|
this._actor.add_actor(workspace.actor);
|
|
|
|
},
|
|
|
|
|
|
|
|
createControllerBar: function() {
|
2010-02-12 15:12:39 -05:00
|
|
|
return null;
|
2010-01-21 21:33:48 -05:00
|
|
|
},
|
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
addWorkspace: function() {
|
|
|
|
global.screen.append_new_workspace(false, global.get_current_time());
|
|
|
|
},
|
2010-01-23 06:24:49 -05:00
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
canRemoveWorkspace: function() {
|
|
|
|
return global.screen.n_workspaces > 1;
|
2010-01-21 21:33:48 -05:00
|
|
|
},
|
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
removeWorkspace: function() {
|
|
|
|
let last = this._workspaces.length - 1;
|
|
|
|
global.screen.remove_workspace(this._workspaces[last]._metaWorkspace,
|
|
|
|
global.get_current_time());
|
2010-01-21 21:33:48 -05:00
|
|
|
},
|
|
|
|
|
|
|
|
_acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
|
|
|
|
this._addNewWorkspace();
|
|
|
|
return this.acceptNewWorkspaceDrop(source, dropActor, x, y, time);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-03-16 11:51:24 -04:00
|
|
|
function NewWorkspaceArea() {
|
|
|
|
this._init();
|
|
|
|
}
|
|
|
|
|
|
|
|
NewWorkspaceArea.prototype = {
|
|
|
|
_init: function() {
|
|
|
|
let width = Math.ceil(global.screen_width * WORKSPACE_SHADOW_SCALE);
|
|
|
|
this.actor = new Clutter.Group({ width: width,
|
|
|
|
height: global.screen_height,
|
|
|
|
x: global.screen_width });
|
|
|
|
|
|
|
|
this._child1 = new St.Bin({ style_class: 'new-workspace-area',
|
|
|
|
width: width,
|
|
|
|
height: global.screen_height });
|
|
|
|
this._child2 = new St.Bin({ style_class: 'new-workspace-area-internal',
|
|
|
|
width: width,
|
|
|
|
height: global.screen_height,
|
|
|
|
reactive: true });
|
|
|
|
this.actor.add_actor(this._child1);
|
|
|
|
this.actor.add_actor(this._child2);
|
|
|
|
},
|
|
|
|
|
|
|
|
setStyle: function(isHover) {
|
|
|
|
this._child1.set_style_pseudo_class(isHover ? 'hover' : null);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-01-21 21:33:48 -05:00
|
|
|
function SingleView(width, height, x, y, animate) {
|
|
|
|
this._init(width, height, x, y, animate);
|
|
|
|
}
|
|
|
|
|
|
|
|
SingleView.prototype = {
|
|
|
|
__proto__: GenericWorkspacesView.prototype,
|
|
|
|
|
|
|
|
_init: function(width, height, x, y, animate) {
|
2010-03-16 11:51:24 -04:00
|
|
|
this._newWorkspaceArea = new NewWorkspaceArea();
|
|
|
|
this._leftShadow = new St.Bin({ style_class: 'left-workspaces-shadow',
|
|
|
|
width: Math.ceil(global.screen_width * WORKSPACE_SHADOW_SCALE),
|
|
|
|
height: global.screen_height,
|
|
|
|
x: global.screen_width })
|
|
|
|
this._rightShadow = new St.Bin({ style_class: 'right-workspaces-shadow',
|
|
|
|
width: Math.ceil(global.screen_width * WORKSPACE_SHADOW_SCALE),
|
|
|
|
height: global.screen_height,
|
|
|
|
x: global.screen_width })
|
|
|
|
|
2010-01-21 21:33:48 -05:00
|
|
|
GenericWorkspacesView.prototype._init.call(this, width, height, x, y, animate);
|
|
|
|
|
2010-03-16 11:51:24 -04:00
|
|
|
this._actor.add_actor(this._newWorkspaceArea.actor);
|
|
|
|
this._actor.add_actor(this._leftShadow);
|
|
|
|
this._actor.add_actor(this._rightShadow);
|
|
|
|
|
2010-02-10 01:00:02 -05:00
|
|
|
this.actor.style_class = "workspaces single";
|
2010-01-21 21:33:48 -05:00
|
|
|
this._actor.set_clip(x, y, width, height);
|
|
|
|
this._indicatorsPanel = null;
|
2010-02-12 15:12:39 -05:00
|
|
|
this._indicatorsPanelWidth = 0;
|
2010-02-10 00:56:36 -05:00
|
|
|
this._scroll = null;
|
2010-02-11 09:52:49 -05:00
|
|
|
this._lostWorkspaces = [];
|
2010-02-10 00:56:36 -05:00
|
|
|
this._scrolling = false;
|
|
|
|
this._animatingScroll = false;
|
2010-03-16 11:51:24 -04:00
|
|
|
|
|
|
|
let primary = global.get_primary_monitor();
|
|
|
|
this._dropGroup = new Clutter.Group({ x: 0, y: 0,
|
|
|
|
width: primary.width,
|
|
|
|
height: primary.height });
|
|
|
|
this._dropGroup._delegate = this;
|
|
|
|
global.stage.add_actor(this._dropGroup);
|
|
|
|
this._dropGroup.lower_bottom();
|
|
|
|
this._timeoutId = 0;
|
2010-01-21 21:33:48 -05:00
|
|
|
},
|
|
|
|
|
|
|
|
_positionWorkspaces: function() {
|
2010-03-16 11:51:24 -04:00
|
|
|
let scale;
|
|
|
|
|
|
|
|
if (this._inDrag)
|
|
|
|
scale = this._width * WORKSPACE_DRAGGING_SCALE / global.screen_width;
|
|
|
|
else
|
|
|
|
scale = this._width / global.screen_width;
|
2010-02-10 00:56:36 -05:00
|
|
|
let active = global.screen.get_active_workspace_index();
|
2010-03-16 11:51:24 -04:00
|
|
|
let _width = this._workspaces[0].actor.width * scale;
|
2010-01-21 21:33:48 -05:00
|
|
|
|
|
|
|
for (let w = 0; w < this._workspaces.length; w++) {
|
|
|
|
let workspace = this._workspaces[w];
|
|
|
|
|
2010-03-16 11:51:24 -04:00
|
|
|
if (this._inDrag)
|
|
|
|
workspace.opacity = 200;
|
|
|
|
else
|
|
|
|
workspace.opacity = 255;
|
|
|
|
if (active == w)
|
|
|
|
workspace.opacity = 255;
|
|
|
|
|
2010-01-21 21:33:48 -05:00
|
|
|
workspace.gridRow = 0;
|
|
|
|
workspace.gridCol = 0;
|
|
|
|
|
|
|
|
workspace.scale = scale;
|
2010-03-16 11:51:24 -04:00
|
|
|
workspace.gridX = this._x + (this._width - _width) / 2 + (w - active) * (_width + this._spacing);
|
|
|
|
workspace.gridY = this._y + (this._height - workspace.actor.height * scale) / 2;
|
2010-02-10 00:56:36 -05:00
|
|
|
|
|
|
|
workspace.setSelected(false);
|
|
|
|
}
|
|
|
|
|
2010-03-16 11:51:24 -04:00
|
|
|
this._newWorkspaceArea.scale = scale;
|
|
|
|
this._newWorkspaceArea.gridX = this._x + (this._width - _width) / 2 + (this._workspaces.length - active) * (_width + this._spacing);
|
|
|
|
this._newWorkspaceArea.gridY = this._y + (this._height - this._newWorkspaceArea.actor.height * scale) / 2;
|
2010-02-10 00:56:36 -05:00
|
|
|
|
2010-03-16 11:51:24 -04:00
|
|
|
this._leftShadow.scale = scale;
|
|
|
|
this._leftShadow.gridX = this._x + (this._width - _width) / 2 - (this._leftShadow.width * scale + this._spacing);
|
|
|
|
this._leftShadow.gridY = this._y + (this._height - this._leftShadow.height * scale) / 2;
|
|
|
|
|
|
|
|
this._rightShadow.scale = scale;
|
|
|
|
this._rightShadow.gridX = this._x + (this._width - _width) / 2 + (_width + this._spacing);
|
|
|
|
this._rightShadow.gridY = this._y + (this._height - this._rightShadow.height * scale) / 2;
|
2010-02-10 00:56:36 -05:00
|
|
|
},
|
|
|
|
|
|
|
|
_scrollToActive: function(showAnimation) {
|
|
|
|
let active = global.screen.get_active_workspace_index();
|
|
|
|
|
2010-03-16 11:51:24 -04:00
|
|
|
this._updateWorkspaceActors(showAnimation);
|
2010-02-10 00:56:36 -05:00
|
|
|
this._scrollScrollBarToIndex(active, showAnimation);
|
|
|
|
},
|
|
|
|
|
2010-03-16 11:51:24 -04:00
|
|
|
_updateWorkspaceActors: function(showAnimation) {
|
2010-02-10 00:56:36 -05:00
|
|
|
let active = global.screen.get_active_workspace_index();
|
2010-03-16 11:51:24 -04:00
|
|
|
|
|
|
|
this._positionWorkspaces();
|
|
|
|
|
|
|
|
let dx = this._workspaces[0].gridX - this._workspaces[0].actor.x;
|
2010-02-10 00:56:36 -05:00
|
|
|
|
|
|
|
for (let w = 0; w < this._workspaces.length; w++) {
|
|
|
|
let workspace = this._workspaces[w];
|
|
|
|
|
|
|
|
workspace.actor.show();
|
2010-03-16 11:51:24 -04:00
|
|
|
workspace.hideWindowsOverlays();
|
2010-02-10 00:56:36 -05:00
|
|
|
|
2010-03-16 11:51:24 -04:00
|
|
|
let i = w;
|
2010-02-10 00:56:36 -05:00
|
|
|
if (showAnimation) {
|
|
|
|
Tweener.addTween(workspace.actor,
|
|
|
|
{ x: workspace.gridX,
|
2010-03-16 11:51:24 -04:00
|
|
|
y: workspace.gridY,
|
|
|
|
scale_x: workspace.scale,
|
|
|
|
scale_y: workspace.scale,
|
2010-02-10 00:56:36 -05:00
|
|
|
time: WORKSPACE_SWITCH_TIME,
|
2010-03-16 11:51:24 -04:00
|
|
|
opacity: workspace.opacity,
|
2010-02-10 00:56:36 -05:00
|
|
|
transition: 'easeOutQuad',
|
2010-03-16 11:51:24 -04:00
|
|
|
onCompleteScope: this,
|
2010-02-10 00:56:36 -05:00
|
|
|
onComplete: function() {
|
2010-03-16 11:51:24 -04:00
|
|
|
if (i == active) {
|
|
|
|
if (!this._inDrag)
|
|
|
|
workspace.showWindowsOverlays();
|
|
|
|
} else
|
|
|
|
workspace.actor.visible = Math.abs(i - active) <= 1;
|
2010-02-10 00:56:36 -05:00
|
|
|
}});
|
2010-01-21 21:33:48 -05:00
|
|
|
} else {
|
2010-03-16 11:51:24 -04:00
|
|
|
workspace.actor.set_scale(workspace.scale, workspace.scale);
|
|
|
|
workspace.actor.set_position(workspace.gridX, workspace.gridY);
|
|
|
|
workspace.actor.opacity = workspace.opacity;
|
|
|
|
if (i == active) {
|
|
|
|
if (!this._inDrag)
|
|
|
|
workspace.showWindowsOverlays();
|
|
|
|
} else
|
|
|
|
workspace.actor.visible = Math.abs(i - active) <= 1;
|
2010-01-21 21:33:48 -05:00
|
|
|
}
|
2010-03-16 11:51:24 -04:00
|
|
|
workspace.positionWindows(0);
|
|
|
|
}
|
|
|
|
if (active)
|
|
|
|
this._leftShadow.show();
|
|
|
|
else
|
|
|
|
this._leftShadow.hide();
|
|
|
|
|
|
|
|
if (active == this._workspaces.length - 1)
|
|
|
|
this._rightShadow.hide();
|
|
|
|
else
|
|
|
|
this._rightShadow.show();
|
|
|
|
|
|
|
|
this._leftShadow.raise_top();
|
|
|
|
this._rightShadow.raise_top();
|
|
|
|
|
|
|
|
if (showAnimation) {
|
|
|
|
Tweener.addTween(this._newWorkspaceArea.actor,
|
|
|
|
{ x: this._newWorkspaceArea.gridX,
|
|
|
|
y: this._newWorkspaceArea.gridY,
|
|
|
|
scale_x: this._newWorkspaceArea.scale,
|
|
|
|
scale_y: this._newWorkspaceArea.scale,
|
|
|
|
time: WORKSPACE_SWITCH_TIME,
|
|
|
|
transition: 'easeOutQuad'
|
|
|
|
});
|
|
|
|
this._leftShadow.x = this._leftShadow.gridX;
|
|
|
|
Tweener.addTween(this._leftShadow,
|
|
|
|
{ y: this._leftShadow.gridY,
|
|
|
|
scale_x: this._leftShadow.scale,
|
|
|
|
scale_y: this._leftShadow.scale,
|
|
|
|
time: WORKSPACE_SWITCH_TIME,
|
|
|
|
transition: 'easeOutQuad'
|
|
|
|
});
|
|
|
|
this._rightShadow.x = this._rightShadow.gridX;
|
|
|
|
Tweener.addTween(this._rightShadow,
|
|
|
|
{ y: this._rightShadow.gridY,
|
|
|
|
scale_x: this._rightShadow.scale,
|
|
|
|
scale_y: this._rightShadow.scale,
|
|
|
|
time: WORKSPACE_SWITCH_TIME,
|
|
|
|
transition: 'easeOutQuad'
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this._newWorkspaceArea.actor.set_scale(this._newWorkspaceArea.scale, this._newWorkspaceArea.scale);
|
|
|
|
this._newWorkspaceArea.actor.set_position(this._newWorkspaceArea.gridX, this._newWorkspaceArea.gridY);
|
|
|
|
|
|
|
|
this._leftShadow.set_scale(this._leftShadow.scale, this._leftShadow.scale);
|
|
|
|
this._leftShadow.set_position(this._leftShadow.gridX, this._leftShadow.gridY);
|
|
|
|
this._rightShadow.set_scale(this._rightShadow.scale, this._rightShadow.scale);
|
|
|
|
this._rightShadow.set_position(this._rightShadow.gridX, this._rightShadow.gridY);
|
2010-01-21 21:33:48 -05:00
|
|
|
}
|
2010-02-11 09:52:49 -05:00
|
|
|
|
|
|
|
for (let l = 0; l < this._lostWorkspaces.length; l++) {
|
|
|
|
let workspace = this._lostWorkspaces[l];
|
|
|
|
|
|
|
|
workspace.gridX += dx;
|
|
|
|
workspace.actor.show();
|
|
|
|
workspace._hideAllOverlays();
|
|
|
|
|
|
|
|
if (showAnimation) {
|
|
|
|
Tweener.addTween(workspace.actor,
|
|
|
|
{ x: workspace.gridX,
|
|
|
|
time: WORKSPACE_SWITCH_TIME,
|
|
|
|
transition: 'easeOutQuad',
|
|
|
|
onComplete: Lang.bind(this, this._cleanWorkspaces)
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this._cleanWorkspaces();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_cleanWorkspaces: function() {
|
|
|
|
if (this._lostWorkspaces.length == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (let l = 0; l < this._lostWorkspaces.length; l++)
|
|
|
|
this._lostWorkspaces[l].destroy();
|
|
|
|
this._lostWorkspaces = [];
|
|
|
|
|
|
|
|
this._positionWorkspaces();
|
|
|
|
this._updateWorkspaceActors();
|
2010-01-21 21:33:48 -05:00
|
|
|
},
|
|
|
|
|
2010-02-10 00:56:36 -05:00
|
|
|
_scrollScrollBarToIndex: function(index, showAnimation) {
|
|
|
|
if (!this._scroll || this._scrolling)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this._animatingScroll = true;
|
|
|
|
|
|
|
|
if (showAnimation) {
|
|
|
|
Tweener.addTween(this._scroll.adjustment, {
|
|
|
|
value: index,
|
|
|
|
time: WORKSPACE_SWITCH_TIME,
|
|
|
|
transition: 'easeOutQuad',
|
|
|
|
onComplete: Lang.bind(this,
|
|
|
|
function() {
|
|
|
|
this._animatingScroll = false;
|
|
|
|
})
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this._scroll.adjustment.value = index;
|
|
|
|
this._animatingScroll = false;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2010-01-21 21:33:48 -05:00
|
|
|
_workspacesChanged: function() {
|
|
|
|
let oldNumWorkspaces = this._workspaces.length;
|
|
|
|
let newNumWorkspaces = global.screen.n_workspaces;
|
2010-02-10 00:56:36 -05:00
|
|
|
let active = global.screen.get_active_workspace_index();
|
2010-01-21 21:33:48 -05:00
|
|
|
|
|
|
|
if (oldNumWorkspaces == newNumWorkspaces)
|
|
|
|
return;
|
|
|
|
|
2010-02-10 00:56:36 -05:00
|
|
|
if (this._scroll != null)
|
|
|
|
this._scroll.adjustment.upper = newNumWorkspaces;
|
2010-01-21 21:33:48 -05:00
|
|
|
|
|
|
|
if (newNumWorkspaces > oldNumWorkspaces) {
|
|
|
|
// Create new workspace groups
|
2010-02-10 00:56:36 -05:00
|
|
|
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++)
|
2010-01-21 21:33:48 -05:00
|
|
|
this._addWorkspaceActor(w);
|
2010-02-10 00:56:36 -05:00
|
|
|
this._positionWorkspaces();
|
|
|
|
this._updateWorkspaceActors();
|
|
|
|
this._scrollScrollBarToIndex(active + 1, false);
|
2010-01-21 21:33:48 -05:00
|
|
|
|
|
|
|
} else {
|
2010-02-11 09:52:49 -05:00
|
|
|
let active = global.screen.get_active_workspace_index();
|
|
|
|
let removedNum = oldNumWorkspaces - newNumWorkspaces;
|
|
|
|
let removedIndex = active + 1;
|
|
|
|
this._lostWorkspaces = this._workspaces.splice(removedIndex,
|
|
|
|
removedNum);
|
|
|
|
|
|
|
|
// Don't let the user try to select this workspace as it's
|
|
|
|
// making its exit.
|
|
|
|
for (let l = 0; l < this._lostWorkspaces.length; l++)
|
|
|
|
this._lostWorkspaces[l]._desktop.actor.reactive = false;
|
|
|
|
|
|
|
|
// reassign workspaceNum and metaWorkspace, as lost workspaces
|
|
|
|
// have not necessarily been removed from the end
|
|
|
|
for (let i = removedIndex; i < this._workspaces.length; i++) {
|
|
|
|
let metaWorkspace = global.screen.get_workspace_by_index(i);
|
|
|
|
this._workspaces[i].workspaceNum = i;
|
|
|
|
this._workspaces[i]._metaWorkspace = metaWorkspace;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._scrollScrollBarToIndex(active, false);
|
|
|
|
this._scrollToActive(true);
|
2010-01-21 21:33:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
this._updatePanelVisibility();
|
|
|
|
},
|
|
|
|
|
|
|
|
_activeWorkspaceChanged: function(wm, from, to, direction) {
|
|
|
|
this._updatePanelVisibility();
|
|
|
|
|
2010-02-10 00:56:36 -05:00
|
|
|
if (this._scrolling)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this._scrollToActive(true);
|
2010-01-21 21:33:48 -05:00
|
|
|
},
|
|
|
|
|
2010-03-16 11:51:24 -04:00
|
|
|
_onDestroy: function() {
|
|
|
|
GenericWorkspacesView.prototype._onDestroy.call(this);
|
|
|
|
this._dropGroup.destroy();
|
|
|
|
if (this._timeoutId) {
|
|
|
|
Mainloop.source_remove(this._timeoutId);
|
|
|
|
this._timeoutId = 0;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
acceptDrop: function(source, dropActor, x, y, time) {
|
2010-03-16 19:21:24 -04:00
|
|
|
if (x < this._x || y < this._y || y > this._y + this._height) {
|
|
|
|
this._dropGroup.lower_bottom();
|
|
|
|
dropActor.hide();
|
|
|
|
let target = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y);
|
|
|
|
dropActor.show();
|
|
|
|
|
|
|
|
if (target._delegate && target._delegate != this && target._delegate.acceptDrop) {
|
|
|
|
let [targX, targY] = target.get_transformed_position();
|
|
|
|
return target._delegate.acceptDrop(source, dropActor,
|
|
|
|
(x - targX) / target.scale_x,
|
|
|
|
(y - targY) / target.scale_y,
|
|
|
|
time);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-03-16 11:51:24 -04:00
|
|
|
for (let i = 0; i < this._workspaces.length; i++) {
|
|
|
|
let [dx, dy] = this._workspaces[i].actor.get_transformed_position();
|
|
|
|
let [dw, dh] = this._workspaces[i].actor.get_transformed_size();
|
|
|
|
|
|
|
|
if (x > dx && x < dx + dw && y > dy && y < dy + dh)
|
|
|
|
return this._workspaces[i].acceptDrop(source, dropActor, x, y, time);
|
|
|
|
}
|
|
|
|
|
|
|
|
let [dx, dy] = this._newWorkspaceArea.actor.get_transformed_position();
|
|
|
|
let [dw, dh] = this._newWorkspaceArea.actor.get_transformed_size();
|
2010-03-16 19:21:24 -04:00
|
|
|
if (x > dx && y > dy && y < dy + dh)
|
2010-03-16 11:51:24 -04:00
|
|
|
return this._acceptNewWorkspaceDrop(source, dropActor, x, y, time);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
|
|
|
|
_onWindowDragBegin: function(w, actor) {
|
|
|
|
if (!this._scroll || this._scroll.adjustment.value - Math.round(this._scroll.adjustment.value) != 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this._inDrag = true;
|
|
|
|
this._updateWorkspaceActors(true);
|
|
|
|
|
|
|
|
this._dropGroup.raise_top();
|
|
|
|
},
|
|
|
|
|
|
|
|
handleDragOver: function(self, actor, x, y) {
|
|
|
|
let onPanel = false;
|
|
|
|
|
|
|
|
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
|
|
|
if (x == 0 && activeWorkspaceIndex > 0 && this._dragOverLastX !== 0) {
|
|
|
|
this._workspaces[activeWorkspaceIndex - 1]._metaWorkspace.activate(global.get_current_time());
|
|
|
|
this._workspaces[activeWorkspaceIndex - 1].setReservedSlot(actor._delegate);
|
|
|
|
this._dragOverLastX = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (x == global.screen_width - 1 && this._workspaces[activeWorkspaceIndex + 1] &&
|
|
|
|
this._dragOverLastX != global.screen_width - 1) {
|
|
|
|
this._workspaces[activeWorkspaceIndex + 1]._metaWorkspace.activate(global.get_current_time());
|
|
|
|
this._workspaces[activeWorkspaceIndex + 1].setReservedSlot(actor._delegate);
|
|
|
|
this._dragOverLastX = global.screen_width - 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._dragOverLastX = x;
|
|
|
|
|
|
|
|
let [dx, dy] = this._newWorkspaceArea.actor.get_transformed_position();
|
|
|
|
let [dw, dh] = this._newWorkspaceArea.actor.get_transformed_size();
|
2010-03-16 19:21:24 -04:00
|
|
|
this._newWorkspaceArea.setStyle(x > dx && y > dy && y < dy + dh);
|
2010-03-16 11:51:24 -04:00
|
|
|
|
|
|
|
[dx, dy] = this._leftShadow.get_transformed_position();
|
|
|
|
[dw, dh] = this._leftShadow.get_transformed_size();
|
|
|
|
if (this._workspaces[activeWorkspaceIndex - 1]) {
|
|
|
|
if (x > dx && x < dx + dw && y > dy && y < dy + dh) {
|
|
|
|
onPanel = -1;
|
|
|
|
this._workspaces[activeWorkspaceIndex - 1].actor.opacity = 255;
|
|
|
|
} else
|
|
|
|
this._workspaces[activeWorkspaceIndex - 1].actor.opacity = 200;
|
|
|
|
}
|
|
|
|
|
|
|
|
[dx, dy] = this._rightShadow.get_transformed_position();
|
|
|
|
[dw, dh] = this._rightShadow.get_transformed_size();
|
|
|
|
if (this._workspaces[activeWorkspaceIndex + 1]) {
|
|
|
|
if (x > dx && x < dx + dw && y > dy && y < dy + dh) {
|
|
|
|
onPanel = 1;
|
|
|
|
this._workspaces[activeWorkspaceIndex + 1].actor.opacity = 255;
|
|
|
|
} else
|
|
|
|
this._workspaces[activeWorkspaceIndex + 1].actor.opacity = 200;
|
|
|
|
}
|
|
|
|
if (onPanel) {
|
|
|
|
if (!this._timeoutId)
|
|
|
|
this._timeoutId = Mainloop.timeout_add_seconds (1, Lang.bind(this, function() {
|
|
|
|
let i = global.screen.get_active_workspace_index();
|
|
|
|
if (this._workspaces[i + onPanel]) {
|
|
|
|
this._workspaces[i + onPanel]._metaWorkspace.activate(global.get_current_time());
|
|
|
|
this._workspaces[i + onPanel].setReservedSlot(actor._delegate);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}));
|
|
|
|
} else {
|
|
|
|
if (this._timeoutId) {
|
|
|
|
Mainloop.source_remove(this._timeoutId);
|
|
|
|
this._timeoutId = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_onWindowDragEnd: function(w, actor) {
|
|
|
|
if (this._timeoutId) {
|
|
|
|
Mainloop.source_remove(this._timeoutId);
|
|
|
|
this._timeoutId = 0;
|
|
|
|
}
|
|
|
|
this._dropGroup.lower_bottom();
|
|
|
|
actor.opacity = 255;
|
|
|
|
this._inDrag = false;
|
|
|
|
this._updateWorkspaceActors(true);
|
|
|
|
|
|
|
|
for (let i = 0; i < this._workspaces.length; i++)
|
|
|
|
this._workspaces[i].setReservedSlot(null);
|
|
|
|
},
|
|
|
|
|
2010-01-21 21:33:48 -05:00
|
|
|
_addWorkspaceActor: function(workspaceNum) {
|
|
|
|
let workspace = new Workspace.Workspace(workspaceNum, this._actor);
|
2010-03-16 11:51:24 -04:00
|
|
|
workspace.connect('window-drag-begin', Lang.bind(this, this._onWindowDragBegin));
|
|
|
|
workspace.connect('window-drag-end', Lang.bind(this, this._onWindowDragEnd));
|
2010-02-10 00:56:36 -05:00
|
|
|
this._actor.add_actor(workspace.actor);
|
2010-01-21 21:33:48 -05:00
|
|
|
this._workspaces[workspaceNum] = workspace;
|
|
|
|
},
|
|
|
|
|
2010-02-10 00:56:36 -05:00
|
|
|
// handle changes to the scroll bar's adjustment:
|
|
|
|
// sync the workspaces' positions to the position of the scroll bar handle
|
|
|
|
// and change the active workspace if appropriate
|
|
|
|
_onScroll: function(adj) {
|
|
|
|
if (this._animatingScroll)
|
|
|
|
return;
|
|
|
|
|
|
|
|
let active = global.screen.get_active_workspace_index();
|
|
|
|
let current = Math.round(adj.value);
|
|
|
|
|
|
|
|
if (active != current) {
|
|
|
|
let metaWorkspace = this._workspaces[current]._metaWorkspace;
|
|
|
|
|
|
|
|
if (!this._scrolling) {
|
|
|
|
// This here is a little tricky - we get here when StScrollBar
|
|
|
|
// animates paging; we switch the active workspace, but
|
|
|
|
// leave out any extra animation (just like we would do when
|
|
|
|
// the handle was dragged)
|
|
|
|
// If StScrollBar emitted scroll-start before and scroll-stop
|
|
|
|
// after the animation, this would not be necessary
|
|
|
|
this._scrolling = true;
|
|
|
|
metaWorkspace.activate(global.get_current_time());
|
|
|
|
this._scrolling = false;
|
|
|
|
} else {
|
|
|
|
metaWorkspace.activate(global.get_current_time());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let last = this._workspaces.length - 1;
|
|
|
|
let firstWorkspaceX = this._workspaces[0].actor.x;
|
|
|
|
let lastWorkspaceX = this._workspaces[last].actor.x;
|
|
|
|
let workspacesWidth = lastWorkspaceX - firstWorkspaceX;
|
|
|
|
|
|
|
|
// The scrollbar is hidden when there is only one workspace, so
|
|
|
|
// adj.upper should at least be 2 - but better be safe than sorry
|
|
|
|
if (adj.upper == 1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
let currentX = firstWorkspaceX;
|
|
|
|
let newX = this._x - adj.value / (adj.upper - 1) * workspacesWidth;
|
|
|
|
|
|
|
|
let dx = newX - currentX;
|
|
|
|
|
|
|
|
for (let i = 0; i < this._workspaces.length; i++) {
|
|
|
|
this._workspaces[i]._hideAllOverlays();
|
2010-03-16 11:51:24 -04:00
|
|
|
this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1;
|
2010-02-10 00:56:36 -05:00
|
|
|
this._workspaces[i].actor.x += dx;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this._scrolling && active == adj.value) {
|
|
|
|
// Again, work around the paging in StScrollBar: simulate
|
|
|
|
// the effect of scroll-stop
|
|
|
|
this._scrolling = true;
|
|
|
|
this._scrollToActive(false);
|
|
|
|
this._scrolling = false;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
// handle scroll wheel events:
|
|
|
|
// activate the next or previous workspace and let the signal handler
|
|
|
|
// manage the animation
|
|
|
|
_onScrollEvent: function(actor, event) {
|
|
|
|
let direction = event.get_scroll_direction();
|
|
|
|
let current = global.screen.get_active_workspace_index();
|
|
|
|
let last = global.screen.n_workspaces - 1;
|
|
|
|
let activate = current;
|
|
|
|
if (direction == Clutter.ScrollDirection.DOWN && current < last)
|
|
|
|
activate++;
|
|
|
|
else if (direction == Clutter.ScrollDirection.UP && current > 0)
|
|
|
|
activate--;
|
|
|
|
|
|
|
|
if (activate != current) {
|
|
|
|
let metaWorkspace = this._workspaces[activate]._metaWorkspace;
|
|
|
|
metaWorkspace.activate(global.get_current_time());
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2010-01-21 21:33:48 -05:00
|
|
|
createControllerBar: function() {
|
2010-02-12 15:12:39 -05:00
|
|
|
let actor = new St.BoxLayout({ style_class: 'single-view-controls',
|
2010-02-14 16:06:32 -05:00
|
|
|
pack_start: true,
|
|
|
|
vertical: true });
|
2010-01-21 21:33:48 -05:00
|
|
|
|
2010-02-10 00:56:36 -05:00
|
|
|
let active = global.screen.get_active_workspace_index();
|
|
|
|
let adj = new St.Adjustment({ value: active,
|
2010-01-21 21:33:48 -05:00
|
|
|
lower: 0,
|
2010-02-10 00:56:36 -05:00
|
|
|
page_increment: 1,
|
|
|
|
page_size: 1,
|
|
|
|
step_increment: 0,
|
2010-01-21 21:33:48 -05:00
|
|
|
upper: this._workspaces.length });
|
2010-02-10 00:56:36 -05:00
|
|
|
this._scroll = new St.ScrollBar({ adjustment: adj,
|
|
|
|
vertical: false,
|
|
|
|
name: 'SwitchScroll' });
|
|
|
|
|
|
|
|
// we have set adj.step_increment to 0, so all scroll wheel events
|
|
|
|
// are processed with this handler - this allows us to animate the
|
|
|
|
// workspace switch
|
|
|
|
this._scroll.connect('scroll-event',
|
|
|
|
Lang.bind(this, this._onScrollEvent));
|
|
|
|
|
|
|
|
this._scroll.adjustment.connect('notify::value',
|
|
|
|
Lang.bind(this, this._onScroll));
|
|
|
|
|
|
|
|
|
|
|
|
this._scroll.connect('scroll-start', Lang.bind(this,
|
|
|
|
function() {
|
|
|
|
this._scrolling = true;
|
|
|
|
}));
|
|
|
|
this._scroll.connect('scroll-stop', Lang.bind(this,
|
|
|
|
function() {
|
|
|
|
this._scrolling = false;
|
|
|
|
this._scrollToActive(true);
|
2010-01-21 21:33:48 -05:00
|
|
|
}));
|
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
actor.add(this._createPositionalIndicator(), { expand: true,
|
|
|
|
x_fill: true,
|
|
|
|
y_fill: true });
|
|
|
|
actor.add(this._scroll, { expand: true,
|
|
|
|
x_fill: true,
|
|
|
|
y_fill: false,
|
2010-01-21 21:33:48 -05:00
|
|
|
y_align: St.Align.START });
|
2010-02-12 15:12:39 -05:00
|
|
|
|
|
|
|
this._updatePanelVisibility();
|
2010-01-21 21:33:48 -05:00
|
|
|
|
|
|
|
return actor;
|
|
|
|
},
|
|
|
|
|
|
|
|
_addIndicatorClone: function(i, active) {
|
|
|
|
let actor = new St.Button({ style_class: 'workspace-indicator' });
|
|
|
|
if (active) {
|
2010-01-23 05:22:38 -05:00
|
|
|
actor.style_class = 'workspace-indicator active';
|
2010-01-21 21:33:48 -05:00
|
|
|
}
|
2010-02-10 00:56:36 -05:00
|
|
|
actor.connect('clicked', Lang.bind(this, function() {
|
2010-01-21 21:33:48 -05:00
|
|
|
if (this._workspaces[i] != undefined)
|
|
|
|
this._workspaces[i]._metaWorkspace.activate(global.get_current_time());
|
|
|
|
}));
|
|
|
|
|
2010-02-15 09:01:48 -05:00
|
|
|
actor._delegate = {};
|
|
|
|
actor._delegate.acceptDrop = Lang.bind(this, function(source, actor, x, y, time) {
|
|
|
|
if (this._workspaces[i].acceptDrop(source, actor, x, y, time)) {
|
|
|
|
this._workspaces[i]._metaWorkspace.activate(global.get_current_time());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
2010-02-10 00:56:36 -05:00
|
|
|
actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
|
2010-01-22 14:49:52 -05:00
|
|
|
|
2010-01-21 21:33:48 -05:00
|
|
|
this._indicatorsPanel.add_actor(actor);
|
|
|
|
|
|
|
|
let [a, spacing] = actor.get_theme_node().get_length('border-spacing', false);
|
|
|
|
if (this._indicatorsPanelWidth < spacing * (i + 1) + actor.width * (i + 1))
|
|
|
|
actor.hide();
|
|
|
|
actor.x = spacing * i + actor.width * i;
|
|
|
|
},
|
|
|
|
|
|
|
|
_fillPositionalIndicator: function() {
|
2010-02-12 15:12:39 -05:00
|
|
|
if (this._indicatorsPanel == null || this._indicatorsPanelWidth == 0)
|
2010-01-21 21:33:48 -05:00
|
|
|
return;
|
|
|
|
let width = this._indicatorsPanelWidth;
|
|
|
|
this._indicatorsPanel.remove_all();
|
|
|
|
|
|
|
|
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
|
|
|
for (let i = 0; i < this._workspaces.length; i++) {
|
|
|
|
this._addIndicatorClone(i, i == activeWorkspaceIndex);
|
|
|
|
}
|
|
|
|
this._indicatorsPanel.x = (this._indicatorsPanelWidth - this._indicatorsPanel.width) / 2;
|
|
|
|
},
|
|
|
|
|
|
|
|
_createPositionalIndicator: function() {
|
|
|
|
let actor = new St.Bin({ style_class: 'panel-button' });
|
|
|
|
let group = new Clutter.Group();
|
|
|
|
|
|
|
|
this._indicatorsPanel = new Shell.GenericContainer();
|
|
|
|
this._indicatorsPanel.connect('get-preferred-width', Lang.bind(this, function (actor, fh, alloc) {
|
|
|
|
let children = actor.get_children();
|
|
|
|
let width = 0;
|
|
|
|
for (let i = 0; i < children.length; i++) {
|
|
|
|
if (!children[i].visible)
|
|
|
|
continue;
|
|
|
|
if (children[i].x + children[i].width <= width)
|
|
|
|
continue;
|
|
|
|
width = children[i].x + children[i].width;
|
|
|
|
}
|
|
|
|
alloc.min_size = width;
|
2010-02-01 11:51:40 -05:00
|
|
|
alloc.natural_size = width;
|
2010-01-21 21:33:48 -05:00
|
|
|
}));
|
|
|
|
this._indicatorsPanel.connect('get-preferred-height', Lang.bind(this, function (actor, fw, alloc) {
|
|
|
|
let children = actor.get_children();
|
|
|
|
let height = 0;
|
|
|
|
if (children.length)
|
|
|
|
height = children[0].height;
|
|
|
|
alloc.min_size = height;
|
2010-02-01 11:51:40 -05:00
|
|
|
alloc.natural_size = height;
|
2010-01-21 21:33:48 -05:00
|
|
|
}));
|
|
|
|
this._indicatorsPanel.connect('allocate', Lang.bind(this, function (actor, box, flags) {
|
|
|
|
let children = actor.get_children();
|
|
|
|
for (let i = 0; i < children.length; i++) {
|
|
|
|
if (!children[i].visible)
|
|
|
|
continue;
|
|
|
|
let childBox = new Clutter.ActorBox();
|
|
|
|
childBox.x1 = children[i].x;
|
|
|
|
childBox.y1 = 0;
|
|
|
|
childBox.x2 = children[i].x + children[i].width;
|
|
|
|
childBox.y2 = children[i].height;
|
|
|
|
children[i].allocate(childBox, flags);
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
|
|
|
|
group.add_actor(this._indicatorsPanel);
|
|
|
|
actor.set_child(group);
|
|
|
|
actor.set_alignment(St.Align.START, St.Align.START);
|
|
|
|
actor.set_fill(true, true);
|
|
|
|
this._indicatorsPanel.hide();
|
|
|
|
actor.connect('notify::width', Lang.bind(this, function(actor) {
|
|
|
|
this._indicatorsPanelWidth = actor.width;
|
|
|
|
this._updatePanelVisibility();
|
|
|
|
}));
|
|
|
|
actor.connect('destroy', Lang.bind(this, function() {
|
|
|
|
this._indicatorsPanel = null;
|
|
|
|
}));
|
|
|
|
return actor;
|
|
|
|
},
|
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
canRemoveWorkspace: function() {
|
|
|
|
return global.screen.get_active_workspace_index() != 0;
|
|
|
|
},
|
2010-01-23 06:24:49 -05:00
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
_updatePanelVisibility: function() {
|
2010-01-23 06:24:49 -05:00
|
|
|
let showSwitches = (global.screen.n_workspaces > 1);
|
2010-01-21 21:33:48 -05:00
|
|
|
if (this._scroll != null) {
|
2010-01-23 06:24:49 -05:00
|
|
|
if (showSwitches)
|
2010-01-21 21:33:48 -05:00
|
|
|
this._scroll.show();
|
|
|
|
else
|
|
|
|
this._scroll.hide();
|
|
|
|
}
|
|
|
|
if (this._indicatorsPanel != null) {
|
2010-01-23 06:24:49 -05:00
|
|
|
if (showSwitches)
|
2010-01-21 21:33:48 -05:00
|
|
|
this._indicatorsPanel.show();
|
2010-01-23 06:24:49 -05:00
|
|
|
else
|
|
|
|
this._indicatorsPanel.hide();
|
2010-01-21 21:33:48 -05:00
|
|
|
}
|
|
|
|
this._fillPositionalIndicator();
|
|
|
|
},
|
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
addWorkspace: function() {
|
2010-02-10 00:56:36 -05:00
|
|
|
let ws = global.screen.append_new_workspace(false,
|
|
|
|
global.get_current_time());
|
|
|
|
ws.activate(global.get_current_time());
|
2010-01-21 21:33:48 -05:00
|
|
|
},
|
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
removeWorkspace: function() {
|
|
|
|
let active = global.screen.get_active_workspace_index();
|
|
|
|
global.screen.remove_workspace(this._workspaces[active]._metaWorkspace,
|
|
|
|
global.get_current_time());
|
|
|
|
},
|
|
|
|
|
2010-01-21 21:33:48 -05:00
|
|
|
_acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
|
2010-02-12 15:12:39 -05:00
|
|
|
this.addWorkspace();
|
2010-01-21 21:33:48 -05:00
|
|
|
return this.acceptNewWorkspaceDrop(source, dropActor, x, y, time);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
function WorkspacesControls() {
|
2010-01-21 21:33:48 -05:00
|
|
|
this._init();
|
|
|
|
}
|
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
WorkspacesControls.prototype = {
|
2010-01-21 21:33:48 -05:00
|
|
|
_init: function() {
|
2010-02-12 15:12:39 -05:00
|
|
|
this.actor = null;
|
2010-01-21 21:33:48 -05:00
|
|
|
this._gconf = Shell.GConf.get_default();
|
|
|
|
this._mosaicViewButton = null;
|
|
|
|
this._singleViewButton = null;
|
2010-02-12 15:12:39 -05:00
|
|
|
this._addButton = null;
|
|
|
|
this._removeButton = null;
|
2010-02-13 16:39:13 -05:00
|
|
|
|
|
|
|
let view = this._gconf.get_string(WORKSPACES_VIEW_KEY).toUpperCase();
|
|
|
|
if (view in WorkspacesViewType)
|
|
|
|
this._currentViewType = WorkspacesViewType[view];
|
|
|
|
else
|
|
|
|
this._currentViewType = WorkspacesViewType.SINGLE;
|
2010-02-12 15:12:39 -05:00
|
|
|
|
|
|
|
this._currentView = null;
|
|
|
|
this._nWorkspacesNotifyId = 0;
|
|
|
|
this._switchWorkspaceNotifyId = 0;
|
2010-01-21 21:33:48 -05:00
|
|
|
},
|
|
|
|
|
|
|
|
_setView: function(view) {
|
2010-02-13 16:39:13 -05:00
|
|
|
this._mosaicViewButton.set_checked(WorkspacesViewType.GRID == view);
|
2010-01-21 21:33:48 -05:00
|
|
|
this._singleViewButton.set_checked(WorkspacesViewType.SINGLE == view);
|
|
|
|
|
|
|
|
if (this._currentViewType == view)
|
|
|
|
return;
|
|
|
|
this._currentViewType = view;
|
2010-02-13 16:39:13 -05:00
|
|
|
this._gconf.set_string(WORKSPACES_VIEW_KEY, view);
|
2010-01-21 21:33:48 -05:00
|
|
|
this.emit('view-changed');
|
|
|
|
},
|
|
|
|
|
|
|
|
createCurrentWorkspaceView: function(width, height, x, y, animate) {
|
|
|
|
switch (this._currentViewType) {
|
|
|
|
case WorkspacesViewType.SINGLE:
|
2010-02-12 15:12:39 -05:00
|
|
|
this._currentView = new SingleView(width, height, x, y, animate);
|
|
|
|
break;
|
2010-02-13 16:39:13 -05:00
|
|
|
case WorkspacesViewType.GRID:
|
2010-01-21 21:33:48 -05:00
|
|
|
default:
|
2010-02-12 15:12:39 -05:00
|
|
|
this._currentView = new MosaicView(width, height, x, y, animate);
|
|
|
|
break;
|
2010-01-21 21:33:48 -05:00
|
|
|
}
|
2010-02-12 15:12:39 -05:00
|
|
|
this._updateControlsBar();
|
|
|
|
return this._currentView;
|
2010-01-21 21:33:48 -05:00
|
|
|
},
|
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
_updateControlsBar: function() {
|
|
|
|
if (this.actor)
|
|
|
|
this.actor.remove_all();
|
|
|
|
else
|
|
|
|
this.actor = new St.BoxLayout({ style_class: 'workspaces-bar' });
|
2010-01-21 21:33:48 -05:00
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
// View switcher buttons
|
|
|
|
this._mosaicViewButton = new St.Button({ style_class: 'workspace-controls switch-mosaic',
|
|
|
|
toggle_mode: true });
|
2010-01-21 21:33:48 -05:00
|
|
|
this._mosaicViewButton.connect('clicked', Lang.bind(this, function() {
|
2010-02-13 16:39:13 -05:00
|
|
|
this._setView(WorkspacesViewType.GRID);
|
2010-01-21 21:33:48 -05:00
|
|
|
}));
|
2010-02-12 15:12:39 -05:00
|
|
|
this.actor.add(this._mosaicViewButton, { y_fill: false,
|
|
|
|
y_align: St.Align.START });
|
2010-01-21 21:33:48 -05:00
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
this._singleViewButton = new St.Button({ style_class: 'workspace-controls switch-single',
|
|
|
|
toggle_mode: true });
|
2010-01-21 21:33:48 -05:00
|
|
|
this._singleViewButton.connect('clicked', Lang.bind(this, function() {
|
|
|
|
this._setView(WorkspacesViewType.SINGLE);
|
|
|
|
}));
|
2010-02-12 15:12:39 -05:00
|
|
|
this.actor.add(this._singleViewButton, { y_fill: false,
|
|
|
|
y_align: St.Align.START });
|
2010-01-21 21:33:48 -05:00
|
|
|
|
2010-02-13 16:39:13 -05:00
|
|
|
if (this._currentViewType == WorkspacesViewType.GRID)
|
2010-01-21 21:33:48 -05:00
|
|
|
this._mosaicViewButton.set_checked(true);
|
|
|
|
else
|
|
|
|
this._singleViewButton.set_checked(true);
|
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
// View specific controls
|
|
|
|
let bar = this._currentView.createControllerBar();
|
|
|
|
if (!bar)
|
|
|
|
bar = new St.Bin();
|
|
|
|
|
|
|
|
this.actor.add(bar, { expand: true,
|
|
|
|
x_fill: true,
|
|
|
|
y_fill: true,
|
|
|
|
y_align: St.Align.MIDDLE,
|
|
|
|
x_align: St.Align.START });
|
|
|
|
|
|
|
|
// Add/remove workspace buttons
|
|
|
|
this._removeButton = new St.Button({ style_class: 'workspace-controls remove' });
|
|
|
|
this._removeButton.connect('clicked', Lang.bind(this, function() {
|
|
|
|
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() {
|
|
|
|
this._currentView.addWorkspace()
|
|
|
|
}));
|
|
|
|
this._addButton._delegate = this._addButton;
|
|
|
|
this._addButton._delegate.acceptDrop = Lang.bind(this,
|
|
|
|
function(source, actor, x, y, time) {
|
|
|
|
let view = this._currentView;
|
|
|
|
return view._acceptNewWorkspaceDrop(source, actor, x, y, time);
|
|
|
|
});
|
|
|
|
this.actor.add(this._addButton, { y_fill: false,
|
|
|
|
y_align: St.Align.START });
|
|
|
|
|
2010-01-21 21:33:48 -05:00
|
|
|
this._nWorkspacesNotifyId =
|
|
|
|
global.screen.connect('notify::n-workspaces',
|
|
|
|
Lang.bind(this, this._workspacesChanged));
|
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
this._switchWorkspaceNotifyId =
|
|
|
|
global.window_manager.connect('switch-workspace',
|
|
|
|
Lang.bind(this, this._updateButtonSensitivity));
|
|
|
|
|
|
|
|
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
2010-01-21 21:33:48 -05:00
|
|
|
|
|
|
|
this._workspacesChanged();
|
2010-02-12 15:12:39 -05:00
|
|
|
},
|
|
|
|
|
|
|
|
_onDestroy: function() {
|
|
|
|
this.actor = null;
|
|
|
|
if (this._nWorkspacesNotifyId > 0) {
|
|
|
|
global.screen.disconnect(this._nWorkspacesNotifyId);
|
|
|
|
this._nWorkspacesNotifyId = 0;
|
|
|
|
}
|
|
|
|
if (this._switchWorkspaceNotifyId > 0) {
|
|
|
|
global.window_manager.disconnect(this._switchWorkspaceNotifyId);
|
|
|
|
this._switchWorkspaceNotifyId = 0;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_setButtonSensitivity: function(button, sensitive) {
|
|
|
|
if (button == null)
|
|
|
|
return;
|
|
|
|
button.reactive = sensitive;
|
|
|
|
button.opacity = sensitive ? 255 : 85;
|
|
|
|
},
|
|
|
|
|
|
|
|
_updateButtonSensitivity: function() {
|
|
|
|
this._setButtonSensitivity(this._addButton,
|
|
|
|
this._currentView.canAddWorkspace());
|
|
|
|
this._setButtonSensitivity(this._removeButton,
|
|
|
|
this._currentView.canRemoveWorkspace());
|
2010-01-21 21:33:48 -05:00
|
|
|
},
|
|
|
|
|
|
|
|
_workspacesChanged: function() {
|
2010-02-12 15:12:39 -05:00
|
|
|
if (this.actor == null)
|
2010-01-21 21:33:48 -05:00
|
|
|
return;
|
2010-02-12 15:12:39 -05:00
|
|
|
|
|
|
|
this._updateButtonSensitivity();
|
|
|
|
|
|
|
|
if (global.screen.n_workspaces == 1) {
|
|
|
|
this._mosaicViewButton.hide();
|
|
|
|
this._singleViewButton.hide();
|
|
|
|
} else {
|
|
|
|
this._mosaicViewButton.show();
|
|
|
|
this._singleViewButton.show();
|
|
|
|
}
|
2010-01-21 21:33:48 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-02-12 15:12:39 -05:00
|
|
|
Signals.addSignalMethods(WorkspacesControls.prototype);
|