diff --git a/data/org.gnome.shell.gschema.xml.in b/data/org.gnome.shell.gschema.xml.in
index 085db60c4..031930a4b 100644
--- a/data/org.gnome.shell.gschema.xml.in
+++ b/data/org.gnome.shell.gschema.xml.in
@@ -41,18 +41,6 @@
[]
<_summary>History for command (Alt-F2) dialog
-
- 'single'
- <_summary>Overview workspace view mode
- <_description>
- The selected workspace view mode in the overview.
- Supported values are "single" and "grid".
-
-
-
-
-
-
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 63678dc5d..9ce36261f 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -257,18 +257,11 @@ StTooltip StLabel {
/* Overview */
-.workspaces {
+.workspaces-view {
color: white;
-}
-
-.workspaces.single {
spacing: 25px;
}
-.workspaces.mosaic {
- spacing: 15px;
-}
-
.workspaces-bar {
spacing: 5px;
}
diff --git a/js/ui/workspace.js b/js/ui/workspace.js
index ec7e24a23..154f7e806 100644
--- a/js/ui/workspace.js
+++ b/js/ui/workspace.js
@@ -20,9 +20,6 @@ const FOCUS_ANIMATION_TIME = 0.15;
const WINDOW_DND_SIZE = 256;
-const FRAME_COLOR = new Clutter.Color();
-FRAME_COLOR.from_pixel(0xffffffff);
-
const SCROLL_SCALE_AMOUNT = 100 / 5;
const LIGHTBOX_FADE_TIME = 0.1;
@@ -54,11 +51,6 @@ function _clamp(value, min, max) {
return Math.max(min, Math.min(max, value));
}
-// Spacing between workspaces. At the moment, the same spacing is used
-// in both zoomed-in and zoomed-out views; this is slightly
-// metaphor-breaking, but the alternatives are also weird.
-const GRID_SPACING = 15;
-const FRAME_SIZE = GRID_SPACING / 3;
function ScaledPoint(x, y, scaleX, scaleY) {
[this.x, this.y, this.scaleX, this.scaleY] = arguments;
@@ -576,8 +568,6 @@ Workspace.prototype = {
this._visible = false;
- this._frame = null;
-
this.leavingOverview = false;
},
@@ -639,9 +629,6 @@ Workspace.prototype = {
this._lightbox.show();
else
this._lightbox.hide();
-
- if (this._frame)
- this._frame.set_opacity(showLightbox ? 150 : 255);
},
/**
@@ -662,32 +649,6 @@ Workspace.prototype = {
this._lightbox.highlight(actor);
},
- // Mark the workspace selected/not-selected
- setSelected : function(selected) {
- // Don't draw a frame if we only have one workspace
- if (selected && global.screen.n_workspaces > 1) {
- if (this._frame)
- return;
-
- // FIXME: do something cooler-looking using clutter-cairo
- this._frame = new Clutter.Rectangle({ color: FRAME_COLOR });
- this.actor.add_actor(this._frame);
- this._frame.set_position(- FRAME_SIZE / this.actor.scale_x,
- - FRAME_SIZE / this.actor.scale_y);
- this._frame.set_size(this.actor.width + 2 * FRAME_SIZE / this.actor.scale_x,
- this.actor.height + 2 * FRAME_SIZE / this.actor.scale_y);
- this._frame.lower_bottom();
-
- this._framePosHandler = this.actor.connect('notify::scale-x', Lang.bind(this, this._updateFramePosition));
- } else {
- if (!this._frame)
- return;
- this.actor.disconnect(this._framePosHandler);
- this._frame.destroy();
- this._frame = null;
- }
- },
-
/**
* setReactive:
* @reactive: %true iff the workspace should be reactive
@@ -698,13 +659,6 @@ Workspace.prototype = {
this.actor.reactive = reactive;
},
- _updateFramePosition : function() {
- this._frame.set_position(- FRAME_SIZE / this.actor.scale_x,
- - FRAME_SIZE / this.actor.scale_y);
- this._frame.set_size(this.actor.width + 2 * FRAME_SIZE / this.actor.scale_x,
- this.actor.height + 2 * FRAME_SIZE / this.actor.scale_y);
- },
-
_isCloneVisible: function(clone) {
return this._showOnlyWindows == null || (clone.metaWindow in this._showOnlyWindows);
},
@@ -1080,8 +1034,8 @@ Workspace.prototype = {
// be after the workspace animation finishes.
let [cloneX, cloneY] = clone.actor.get_position();
let [cloneWidth, cloneHeight] = clone.actor.get_size();
- cloneX = this.gridX + this.scale * cloneX;
- cloneY = this.gridY + this.scale * cloneY;
+ cloneX = this.x + this.scale * cloneX;
+ cloneY = this.y + this.scale * cloneY;
cloneWidth = this.scale * clone.actor.scale_x * cloneWidth;
cloneHeight = this.scale * clone.actor.scale_y * cloneHeight;
@@ -1120,8 +1074,8 @@ Workspace.prototype = {
let wsHeight = this.actor.height * this.scale;
let pointerHasMoved = (this._cursorX != x && this._cursorY != y);
- let inWorkspace = (this.gridX < x && x < this.gridX + wsWidth &&
- this.gridY < y && y < this.gridY + wsHeight);
+ let inWorkspace = (this.x < x && x < this.x + wsWidth &&
+ this.y < y && y < this.y + wsHeight);
if (pointerHasMoved && inWorkspace) {
// store current cursor position
@@ -1245,7 +1199,7 @@ Workspace.prototype = {
// Animate the full-screen to Overview transition.
zoomToOverview : function() {
- this.actor.set_position(this.gridX, this.gridY);
+ this.actor.set_position(this.x, this.y);
this.actor.set_scale(this.scale, this.scale);
// Position and scale the windows.
@@ -1303,69 +1257,6 @@ Workspace.prototype = {
this._visible = false;
},
- // Animates grid shrinking/expanding when a row or column
- // of workspaces is added or removed
- resizeToGrid : function (oldScale) {
- this._hideAllOverlays();
- Tweener.addTween(this.actor,
- { x: this.gridX,
- y: this.gridY,
- scale_x: this.scale,
- scale_y: this.scale,
- time: Overview.ANIMATION_TIME,
- transition: 'easeOutQuad',
- onComplete: Lang.bind(this, this._fadeInAllOverlays)
- });
- },
-
- // Animates the addition of a new (empty) workspace
- slideIn : function(oldScale) {
- if (this.gridCol > this.gridRow) {
- this.actor.set_position(global.screen_width, this.gridY);
- this.actor.set_scale(oldScale, oldScale);
- } else {
- this.actor.set_position(this.gridX, global.screen_height);
- this.actor.set_scale(this.scale, this.scale);
- }
- Tweener.addTween(this.actor,
- { x: this.gridX,
- y: this.gridY,
- scale_x: this.scale,
- scale_y: this.scale,
- time: Overview.ANIMATION_TIME,
- transition: 'easeOutQuad'
- });
-
- this._visible = true;
- },
-
- // Animates the removal of a workspace
- slideOut : function(onComplete) {
- let destX = this.actor.x, destY = this.actor.y;
-
- this._hideAllOverlays();
-
- if (this.gridCol > this.gridRow)
- destX = global.screen_width;
- else
- destY = global.screen_height;
- Tweener.addTween(this.actor,
- { x: destX,
- y: destY,
- scale_x: this.scale,
- scale_y: this.scale,
- time: Overview.ANIMATION_TIME,
- transition: 'easeOutQuad',
- onComplete: onComplete
- });
-
- this._visible = false;
-
- // Don't let the user try to select this workspace as it's
- // making its exit.
- this.actor.reactive = false;
- },
-
destroy : function() {
this.actor.destroy();
},
@@ -1555,11 +1446,11 @@ function _workspaceRelativeModifier(workspace) {
}
return [ { name: 'x',
- parameters: { workspacePos: workspace.gridX,
+ parameters: { workspacePos: workspace.x,
overviewPos: overviewPosX,
overviewScale: overviewScale } },
{ name: 'y',
- parameters: { workspacePos: workspace.gridY,
+ parameters: { workspacePos: workspace.y,
overviewPos: overviewPosY,
overviewScale: overviewScale } }
];
diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js
index 82d486810..2bb2a06aa 100644
--- a/js/ui/workspacesView.js
+++ b/js/ui/workspacesView.js
@@ -19,459 +19,9 @@ const WORKSPACE_SWITCH_TIME = 0.25;
// Note that mutter has a compile-time limit of 36
const MAX_WORKSPACES = 16;
-// The values here are also used for GSettings, and the key and value
-// names must match
-const WorkspacesViewType = {
- SINGLE: 'single',
- GRID: 'grid'
-};
-const WORKSPACES_VIEW_KEY = 'workspaces-view';
-
const WORKSPACE_DRAGGING_SCALE = 0.85;
-function GenericWorkspacesView(width, height, x, y, workspaces) {
- this._init(width, height, x, y, workspaces);
-}
-
-GenericWorkspacesView.prototype = {
- _init: function(width, height, x, y, workspaces) {
- this.actor = new St.Group({ style_class: 'workspaces' });
-
- this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
-
- this.actor.connect('style-changed', Lang.bind(this,
- function() {
- let node = this.actor.get_theme_node();
- this._spacing = node.get_length('spacing');
- if (Main.overview.animationInProgress)
- this._computeWorkspacePositions();
- else
- this._transitionWorkspaces();
- }));
-
- this._width = width;
- this._height = height;
- this._x = x;
- this._y = y;
- this._spacing = 0;
-
- this._windowSelectionAppId = null;
- this._highlightWindow = null;
-
- let activeWorkspaceIndex = global.screen.get_active_workspace_index();
- this._workspaces = workspaces;
-
- // Add workspace actors
- for (let w = 0; w < global.screen.n_workspaces; w++)
- this._workspaces[w].actor.reparent(this.actor);
- 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();
- }));
-
- 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);
- }
- },
-
- getActiveWorkspace: function() {
- let active = global.screen.get_active_workspace_index();
- return this._workspaces[active];
- },
-
- _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];
-
- if (this._windowSelectionAppId != null)
- this._clearApplicationWindowSelection(false);
-
- activeWorkspace.actor.raise_top();
-
- for (let w = 0; w < this._workspaces.length; w++)
- this._workspaces[w].zoomFromOverview();
- },
-
- destroy: function() {
- this.actor.destroy();
- },
-
- _onDestroy: function() {
- Main.overview.disconnect(this._overviewShowingId);
- global.window_manager.disconnect(this._switchWorkspaceNotifyId);
- global.screen.disconnect(this._restackedNotifyId);
- },
-
- getScale: function() {
- return this._workspaces[0].scale;
- },
-
- _onRestacked: function() {
- let stack = global.get_window_actors();
- 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];
- },
-
- createControllerBar: function() {
- throw new Error('Not implemented');
- },
-
- canAddWorkspace: function() {
- return global.screen.n_workspaces < MAX_WORKSPACES;
- },
-
- addWorkspace: function() {
- if (!this.canAddWorkspace()) {
- Main.overview.shellInfo.setMessage(_("Can't add a new workspace because maximum workspaces limit has been reached."));
- return null;
- }
-
- return global.screen.append_new_workspace(false, global.get_current_time());
- },
-
- _getWorkspaceIndexToRemove: function() {
- throw new Error('Not implemented');
- },
-
- canRemoveWorkspace: function() {
- return this._getWorkspaceIndexToRemove() > 0;
- },
-
- removeWorkspace: function() {
- if (!this.canRemoveWorkspace()) {
- Main.overview.shellInfo.setMessage(_("Can't remove the first workspace."));
- return;
- }
- let index = this._getWorkspaceIndexToRemove();
- let metaWorkspace = this._workspaces[index].metaWorkspace;
- global.screen.remove_workspace(metaWorkspace,
- global.get_current_time());
- },
-
- updateWorkspaces: function() {
- throw new Error('Not implemented');
- },
-
- _transitionWorkspaces: function() {
- throw new Error('Not implemented');
- },
-
- _computeWorkspacePositions: function() {
- throw new Error('Not implemented');
- },
-
- _activeWorkspaceChanged: function() {
- throw new Error('Not implemented');
- },
-
- _handleDragOverNewWorkspace: function(source, dropActor, x, y, time) {
- if (source instanceof Workspace.WindowClone)
- return DND.DragMotionResult.MOVE_DROP;
- if (source.shellWorkspaceLaunch)
- return DND.DragMotionResult.COPY_DROP;
- return DND.DragMotionResult.CONTINUE;
- },
-
- _acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
- let ws = this.addWorkspace();
- if (ws == null)
- return false;
- return this.acceptNewWorkspaceDrop(source, dropActor, x, y, time);
- }
-};
-
-function MosaicView(width, height, x, y, workspaces) {
- this._init(width, height, x, y, workspaces);
-}
-
-MosaicView.prototype = {
- __proto__: GenericWorkspacesView.prototype,
-
- _init: function(width, height, x, y, workspaces) {
- GenericWorkspacesView.prototype._init.call(this, width, height, x, y, workspaces);
-
- this.actor.add_style_class_name('mosaic');
- this.actor.set_clip(x - Workspace.FRAME_SIZE,
- y - Workspace.FRAME_SIZE,
- width + 2 * Workspace.FRAME_SIZE,
- height + 2 * Workspace.FRAME_SIZE);
- 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!
- _computeWorkspacePositions: function() {
- let gridWidth = Math.ceil(Math.sqrt(this._workspaces.length));
- let gridHeight = Math.ceil(this._workspaces.length / gridWidth);
-
- // adjust vertical spacing so workspaces can preserve their aspect
- // ratio without exceeding this._height
- let verticalSpacing = this._spacing * this._height / this._width;
-
- let wsWidth = (this._width - (gridWidth - 1) * this._spacing) / gridWidth;
- let wsHeight = (this._height - (gridHeight - 1) * verticalSpacing) / gridHeight;
- 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;
-
- workspace.gridX = this._x + workspace.gridCol * (wsWidth + this._spacing);
- workspace.gridY = this._y + workspace.gridRow * (wsHeight + verticalSpacing);
- workspace.scale = scale;
-
- if (horiz) {
- col++;
- if (col == span) {
- row = 0;
- horiz = false;
- }
- } else {
- row++;
- if (row == span) {
- col = 0;
- horiz = true;
- span++;
- }
- }
- }
- },
-
- _transitionWorkspaces: function() {
- // update workspace parameters
- this._computeWorkspacePositions();
-
- 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));
- let oldGridHeight = Math.ceil(oldNumWorkspaces / oldGridWidth);
-
- // Add actors
- if (newNumWorkspaces > oldNumWorkspaces)
- for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++)
- this.actor.add_actor(this._workspaces[w].actor);
-
- // Figure out the new layout
- this._computeWorkspacePositions();
- 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
- // New workspaces can contain windows.
- for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
- this._workspaces[w].positionWindows(0);
- this._workspaces[w].slideIn(oldScale);
- }
- } else {
- // Slide old workspaces out
- for (let w = 0; w < lostWorkspaces.length; w++) {
- let workspace = lostWorkspaces[w];
- workspace.slideOut(function () { workspace.destroy(); });
- }
- }
-
- // 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);
- },
-
- createControllerBar: function() {
- return null;
- },
-
- _getWorkspaceIndexToRemove: function() {
- return this._workspaces.length - 1;
- }
-};
-
function WorkspaceIndicator(activateWorkspace, workspaceAcceptDrop, workspaceHandleDragOver, scrollEventCb) {
this._init(activateWorkspace, workspaceAcceptDrop, workspaceHandleDragOver, scrollEventCb);
@@ -602,29 +152,29 @@ WorkspaceIndicator.prototype = {
}
};
-function SingleView(width, height, x, y, workspaces) {
+function WorkspacesView(width, height, x, y, workspaces) {
this._init(width, height, x, y, workspaces);
}
-SingleView.prototype = {
- __proto__: GenericWorkspacesView.prototype,
-
+WorkspacesView.prototype = {
_init: function(width, height, x, y, workspaces) {
- GenericWorkspacesView.prototype._init.call(this, width, height, x, y, workspaces);
-
- this._itemDragBeginId = Main.overview.connect('item-drag-begin',
- Lang.bind(this, this._dragBegin));
- this._itemDragEndId = Main.overview.connect('item-drag-end',
- Lang.bind(this, this._dragEnd));
- for (let i = 0; i < this._workspaces.length; i++) {
- this._workspaces[i]._windowDragBeginId = this._workspaces[i].connect('window-drag-begin',
- Lang.bind(this, this._dragBegin));
- this._workspaces[i]._windowDragEndId = this._workspaces[i].connect('window-drag-end',
- Lang.bind(this, this._dragEnd));
- }
-
- this.actor.add_style_class_name('single');
+ this.actor = new St.Group({ style_class: 'workspaces-view' });
this.actor.set_clip(x, y, width, height);
+
+ this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
+
+ this.actor.connect('style-changed', Lang.bind(this,
+ function() {
+ let node = this.actor.get_theme_node();
+ this._spacing = node.get_length('spacing');
+ this._computeWorkspacePositions();
+ }));
+
+ this._width = width;
+ this._height = height;
+ this._x = x;
+ this._y = y;
+ this._spacing = 0;
this._activeWorkspaceX = 0; // x offset of active ws while dragging
this._activeWorkspaceY = 0; // y offset of active ws while dragging
this._lostWorkspaces = [];
@@ -634,8 +184,34 @@ SingleView.prototype = {
this._inDrag = false; // dragging a window
this._lastMotionTime = -1; // used to track "stopping" while dragging workspaces
- let active = global.screen.get_active_workspace_index();
- this._scrollAdjustment = new St.Adjustment({ value: active,
+ let activeWorkspaceIndex = global.screen.get_active_workspace_index();
+ this._workspaces = workspaces;
+
+ // Add workspace actors
+ for (let w = 0; w < global.screen.n_workspaces; w++) {
+ this._workspaces[w].actor.reparent(this.actor);
+ this._workspaces[w]._windowDragBeginId =
+ this._workspaces[w].connect('window-drag-begin',
+ Lang.bind(this, this._dragBegin));
+ this._workspaces[w]._windowDragEndId =
+ this._workspaces[w].connect('window-drag-end',
+ Lang.bind(this, this._dragEnd));
+ }
+ 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();
+ }));
+
+ this._scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex,
lower: 0,
page_increment: 1,
page_size: 1,
@@ -649,6 +225,187 @@ SingleView.prototype = {
this._buttonPressId = 0;
this._capturedEventId = 0;
this._timeoutId = 0;
+
+ this._windowSelectionAppId = null;
+ this._highlightWindow = null;
+
+ this._switchWorkspaceNotifyId =
+ global.window_manager.connect('switch-workspace',
+ Lang.bind(this, this._activeWorkspaceChanged));
+ this._restackedNotifyId =
+ global.screen.connect('restacked',
+ Lang.bind(this, this._onRestacked));
+
+ this._itemDragBeginId = Main.overview.connect('item-drag-begin',
+ Lang.bind(this, this._dragBegin));
+ this._itemDragEndId = Main.overview.connect('item-drag-end',
+ Lang.bind(this, this._dragEnd));
+ },
+
+ _lookupWorkspaceForMetaWindow: function (metaWindow) {
+ for (let i = 0; i < this._workspaces.length; i++) {
+ if (this._workspaces[i].containsMetaWindow(metaWindow))
+ return this._workspaces[i];
+ }
+ 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);
+ }
+ },
+
+ getActiveWorkspace: function() {
+ let active = global.screen.get_active_workspace_index();
+ return this._workspaces[active];
+ },
+
+ _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];
+
+ if (this._windowSelectionAppId != null)
+ this._clearApplicationWindowSelection(false);
+
+ activeWorkspace.actor.raise_top();
+
+ for (let w = 0; w < this._workspaces.length; w++)
+ this._workspaces[w].zoomFromOverview();
+ },
+
+ destroy: function() {
+ this.actor.destroy();
+ },
+
+ getScale: function() {
+ return this._workspaces[0].scale;
+ },
+
+ _onRestacked: function() {
+ let stack = global.get_window_actors();
+ 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.x, activeWorkspace.y];
+ },
+
+ canAddWorkspace: function() {
+ return global.screen.n_workspaces < MAX_WORKSPACES;
+ },
+
+ addWorkspace: function() {
+ let ws = null;
+ if (!this.canAddWorkspace()) {
+ Main.overview.shellInfo.setMessage(_("Can't add a new workspace because maximum workspaces limit has been reached."));
+ } else {
+ let currentTime = global.get_current_time();
+ ws = global.screen.append_new_workspace(false, currentTime);
+ ws.activate(currentTime);
+ }
+
+ return ws;
+ },
+
+ canRemoveWorkspace: function() {
+ return this._getWorkspaceIndexToRemove() > 0;
+ },
+
+ removeWorkspace: function() {
+ if (!this.canRemoveWorkspace()) {
+ Main.overview.shellInfo.setMessage(_("Can't remove the first workspace."));
+ return;
+ }
+ let index = this._getWorkspaceIndexToRemove();
+ let metaWorkspace = this._workspaces[index].metaWorkspace;
+ global.screen.remove_workspace(metaWorkspace,
+ global.get_current_time());
+ },
+
+ _handleDragOverNewWorkspace: function(source, dropActor, x, y, time) {
+ if (source instanceof Workspace.WindowClone)
+ return DND.DragMotionResult.MOVE_DROP;
+ if (source.shellWorkspaceLaunch)
+ return DND.DragMotionResult.COPY_DROP;
+ return DND.DragMotionResult.CONTINUE;
+ },
+
+ _acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
+ let ws = this.addWorkspace();
+ if (ws == null)
+ return false;
+ return this.acceptNewWorkspaceDrop(source, dropActor, x, y, time);
},
// Compute the position, scale and opacity of the workspaces, but don't
@@ -673,55 +430,10 @@ SingleView.prototype = {
workspace.opacity = (this._inDrag && w != active) ? 200 : 255;
- workspace.gridRow = 0;
- workspace.gridCol = 0;
-
workspace.scale = scale;
- workspace.gridX = this._x + this._activeWorkspaceX
- + (w - active) * (_width + this._spacing);
- workspace.gridY = this._y + this._activeWorkspaceY;
-
- workspace.setSelected(false);
- }
- },
-
- _transitionWorkspaces: function() {
- // update workspace parameters
- this._computeWorkspacePositions();
-
- 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);
- }});
+ workspace.x = this._x + this._activeWorkspaceX
+ + (w - active) * (_width + this._spacing);
+ workspace.y = this._y + this._activeWorkspaceY;
}
},
@@ -855,7 +567,7 @@ SingleView.prototype = {
_updateWorkspaceActors: function(showAnimation) {
let active = global.screen.get_active_workspace_index();
let targetWorkspaceNewX = this._x + this._activeWorkspaceX;
- let targetWorkspaceCurrentX = this._workspaces[active].gridX;
+ let targetWorkspaceCurrentX = this._workspaces[active].x;
let dx = targetWorkspaceNewX - targetWorkspaceCurrentX;
this._setWorkspaceDraggable(active, true);
@@ -866,11 +578,11 @@ SingleView.prototype = {
Tweener.removeTweens(workspace.actor);
- workspace.gridX += dx;
+ workspace.x += dx;
if (showAnimation) {
- let params = { x: workspace.gridX,
- y: workspace.gridY,
+ let params = { x: workspace.x,
+ y: workspace.y,
scale_x: workspace.scale,
scale_y: workspace.scale,
opacity: workspace.opacity,
@@ -891,7 +603,7 @@ SingleView.prototype = {
Tweener.addTween(workspace.actor, params);
} else {
workspace.actor.set_scale(workspace.scale, workspace.scale);
- workspace.actor.set_position(workspace.gridX, workspace.gridY);
+ workspace.actor.set_position(workspace.x, workspace.y);
workspace.actor.opacity = workspace.opacity;
if (w == 0)
this._updateVisibility();
@@ -903,13 +615,13 @@ SingleView.prototype = {
Tweener.removeTweens(workspace.actor);
- workspace.gridX += dx;
+ workspace.x += dx;
workspace.actor.show();
workspace.hideWindowsOverlays();
if (showAnimation) {
Tweener.addTween(workspace.actor,
- { x: workspace.gridX,
+ { x: workspace.x,
time: WORKSPACE_SWITCH_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
@@ -1011,7 +723,10 @@ SingleView.prototype = {
},
_onDestroy: function() {
- GenericWorkspacesView.prototype._onDestroy.call(this);
+ Main.overview.disconnect(this._overviewShowingId);
+ global.window_manager.disconnect(this._switchWorkspaceNotifyId);
+ global.screen.disconnect(this._restackedNotifyId);
+
this._setWorkspaceDraggable(this._dragIndex, false);
if (this._timeoutId) {
Mainloop.source_remove(this._timeoutId);
@@ -1210,14 +925,6 @@ SingleView.prototype = {
return actor;
},
- addWorkspace: function() {
- let ws = GenericWorkspacesView.prototype.addWorkspace.call(this);
- if (ws != null)
- ws.activate(global.get_current_time());
-
- return ws;
- },
-
_getWorkspaceIndexToRemove: function() {
return global.screen.get_active_workspace_index();
}
@@ -1232,27 +939,8 @@ WorkspacesControls.prototype = {
this.actor = new St.BoxLayout({ style_class: 'workspaces-bar' });
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
- let view = global.settings.get_string(WORKSPACES_VIEW_KEY).toUpperCase();
- if (view in WorkspacesViewType)
- this._currentViewType = WorkspacesViewType[view];
- else
- this._currentViewType = WorkspacesViewType.SINGLE;
-
this._currentView = null;
- // View switcher button
- this._toggleViewButton = new St.Button();
- this._updateToggleButtonStyle();
-
- this._toggleViewButton.connect('clicked', Lang.bind(this, function() {
- if (this._currentViewType == WorkspacesViewType.SINGLE)
- this._setView(WorkspacesViewType.GRID);
- else
- this._setView(WorkspacesViewType.SINGLE);
- }));
-
- this.actor.add(this._toggleViewButton, { y_fill: false, y_align: St.Align.START });
-
// View specific controls
this._viewControls = new St.Bin({ x_fill: true, y_fill: true });
this.actor.add(this._viewControls, { expand: true, x_fill: true });
@@ -1283,12 +971,12 @@ WorkspacesControls.prototype = {
this._nWorkspacesNotifyId =
global.screen.connect('notify::n-workspaces',
- Lang.bind(this, this._workspacesChanged));
+ Lang.bind(this, this.updateControlsSensitivity));
this._switchWorkspaceNotifyId =
global.window_manager.connect('switch-workspace',
Lang.bind(this, this.updateControlsSensitivity));
- this._workspacesChanged();
+ this.updateControlsSensitivity();
},
updateControls: function(view) {
@@ -1316,26 +1004,6 @@ WorkspacesControls.prototype = {
}
},
- _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;
- global.settings.set_string(WORKSPACES_VIEW_KEY, view);
- },
-
_onDestroy: function() {
if (this._nWorkspacesNotifyId > 0) {
global.screen.disconnect(this._nWorkspacesNotifyId);
@@ -1358,15 +1026,6 @@ WorkspacesControls.prototype = {
this._setButtonSensitivity(this._removeButton, this._currentView.canRemoveWorkspace());
this._setButtonSensitivity(this._addButton, this._currentView.canAddWorkspace());
}
- },
-
- _workspacesChanged: function() {
- let showToggleButton = (global.screen.n_workspaces > 1);
- Tweener.addTween(this._toggleViewButton,
- { opacity: showToggleButton ? 255 : 0,
- time: WORKSPACE_SWITCH_TIME,
- transition: 'easeOutQuad' });
- this.updateControlsSensitivity();
}
};
Signals.addSignalMethods(WorkspacesControls.prototype);
@@ -1394,40 +1053,18 @@ WorkspacesManager.prototype = {
this.controlsBar.actor.connect('destroy',
Lang.bind(this, this._onDestroy));
- this._viewChangedId =
- global.settings.connect('changed::' + WORKSPACES_VIEW_KEY,
- Lang.bind(this, this._updateView));
this._nWorkspacesNotifyId =
global.screen.connect('notify::n-workspaces',
Lang.bind(this, this._workspacesChanged));
},
_updateView: function() {
- let viewType, newView;
-
- let view = global.settings.get_string(WORKSPACES_VIEW_KEY).toUpperCase();
- if (view in WorkspacesViewType)
- viewType = WorkspacesViewType[view];
- else
- viewType = WorkspacesViewType.SINGLE;
-
- switch (viewType) {
- case WorkspacesViewType.SINGLE:
- newView = new SingleView(this._workspacesWidth,
+ let newView = new WorkspacesView(this._workspacesWidth,
this._workspacesHeight,
this._workspacesX,
this._workspacesY,
this._workspaces);
- break;
- case WorkspacesViewType.GRID:
- default:
- newView = new MosaicView(this._workspacesWidth,
- this._workspacesHeight,
- this._workspacesX,
- this._workspacesY,
- this._workspaces);
- break;
- }
+
if (this.workspacesView)
this.workspacesView.destroy();
this.workspacesView = newView;