diff --git a/js/ui/overview.js b/js/ui/overview.js index 6d86bdae0..d5f739272 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -485,31 +485,6 @@ Overview.prototype = { this.emit('window-drag-end'); }, - // Returns the scale the Overview has when we just start zooming out - // to overview mode. That is, when just the active workspace is showing. - getZoomedInScale : function() { - return 1 / this.workspaces.getScale(); - }, - - // Returns the position the Overview has when we just start zooming out - // to overview mode. That is, when just the active workspace is showing. - getZoomedInPosition : function() { - let [posX, posY] = this.workspaces.getActiveWorkspacePosition(); - let scale = this.getZoomedInScale(); - - return [- posX * scale, - posY * scale]; - }, - - // Returns the current scale of the Overview. - getScale : function() { - return this.workspaces.actor.scaleX; - }, - - // Returns the current position of the Overview. - getPosition : function() { - return [this.workspaces.actor.x, this.workspaces.actor.y]; - }, - // show: // // Animates the overview visible and grabs mouse and keyboard input @@ -563,30 +538,13 @@ Overview.prototype = { }); } - // Create a zoom out effect. First scale the workspaces view up and - // position it so that the active workspace fills up the whole screen, - // then transform it to its normal dimensions and position. - // The opposite transition is used in hide(). - this.workspaces.actor.scaleX = this.workspaces.actor.scaleY = this.getZoomedInScale(); - [this.workspaces.actor.x, this.workspaces.actor.y] = this.getZoomedInPosition(); - let primary = global.get_primary_monitor(); - Tweener.addTween(this.workspaces.actor, - { x: primary.x - this._group.x, - y: primary.y - this._group.y, - scaleX: 1, - scaleY: 1, - transition: 'easeOutQuad', - time: ANIMATION_TIME, - onComplete: this._showDone, - onCompleteScope: this - }); - - // Make the other elements fade in. this._group.opacity = 0; Tweener.addTween(this._group, { opacity: 255, transition: 'easeOutQuad', - time: ANIMATION_TIME + time: ANIMATION_TIME, + onComplete: this._showDone, + onCompleteScope: this }); this._coverPane.raise_top(); @@ -698,27 +656,13 @@ Overview.prototype = { this.workspaces.hide(); - // Create a zoom in effect by transforming the workspaces view so that - // the active workspace fills up the whole screen. The opposite - // transition is used in show(). - let scale = this.getZoomedInScale(); - let [posX, posY] = this.getZoomedInPosition(); - Tweener.addTween(this.workspaces.actor, - { x: posX, - y: posY, - scaleX: scale, - scaleY: scale, - transition: 'easeOutQuad', - time: ANIMATION_TIME, - onComplete: this._hideDone, - onCompleteScope: this - }); - // Make other elements fade out. Tweener.addTween(this._group, { opacity: 0, transition: 'easeOutQuad', - time: ANIMATION_TIME + time: ANIMATION_TIME, + onComplete: this._hideDone, + onCompleteScope: this }); this._coverPane.raise_top(); diff --git a/js/ui/workspace.js b/js/ui/workspace.js index d75794f8a..8a6c05eeb 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -327,6 +327,7 @@ WindowOverlay.prototype = { this._windowClone = windowClone; this._parentActor = parentActor; + this._hidden = false; let title = new St.Label({ style_class: 'window-caption', text: metaWindow.title }); @@ -372,11 +373,13 @@ WindowOverlay.prototype = { }, hide: function() { + this._hidden = true; this.closeButton.hide(); this.title.hide(); }, show: function() { + this._hidden = false; let [x, y, mask] = global.get_pointer(); let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y); @@ -387,8 +390,8 @@ WindowOverlay.prototype = { }, fadeIn: function() { + this.show(); this.title.opacity = 0; - this.title.show(); this._parentActor.raise_top(); Tweener.addTween(this.title, { opacity: 255, @@ -480,6 +483,12 @@ WindowOverlay.prototype = { }, _onEnter: function() { + // We might get enter events on the clone while the overlay is + // hidden, e.g. during animations, we ignore these events, + // as the close button will be shown as needed when the overlays + // are shown again + if (this._hidden) + return; this._parentActor.raise_top(); this.closeButton.show(); this.emit('show-close-button'); @@ -520,7 +529,7 @@ WindowOverlay.prototype = { Signals.addSignalMethods(WindowOverlay.prototype); const WindowPositionFlags = { - ZOOM: 1 << 0, + INITIAL: 1 << 0, ANIMATE: 1 << 1 }; @@ -536,27 +545,26 @@ Workspace.prototype = { // When dragging a window, we use this slot for reserve space. this._reservedSlot = null; this.metaWorkspace = metaWorkspace; + this._x = 0; + this._y = 0; + this._width = 0; + this._height = 0; + this._windowOverlaysGroup = new Clutter.Group(); // Without this the drop area will be overlapped. this._windowOverlaysGroup.set_size(0, 0); this.actor = new Clutter.Group(); - this.actor._delegate = this; + this.actor.set_size(0, 0); + + this._dropRect = new Clutter.Rectangle({ opacity: 0 }); + this._dropRect._delegate = this; + + this.actor.add_actor(this._dropRect); + this.actor.add_actor(this._windowOverlaysGroup); this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); - // Items in _windowOverlaysGroup should not be scaled, so we don't - // add them to this.actor, but to its parent whenever it changes - this.actor.connect('parent-set', Lang.bind(this, this._onParentSet)); - - // Auto-sizing is unreliable in the presence of ClutterClone, so rather than - // implicitly counting on the workspace actor to be sized to the size of the - // included desktop actor clone, set the size explicitly to the screen size. - // See http://bugzilla.openedhand.com/show_bug.cgi?id=1755 - this.actor.width = global.screen_width; - this.actor.height = global.screen_height; - this.scale = 1.0; - let windows = Main.getWindowActorsForWorkspace(this.metaWorkspace.index()); // Create clones for windows that should be @@ -579,6 +587,22 @@ Workspace.prototype = { this.leavingOverview = false; }, + setGeometry: function(x, y, width, height) { + this._x = x; + this._y = y; + this._width = width; + this._height = height; + + // This is sometimes called during allocation, so we do this later + Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, + function () { + this._dropRect.set_position(x, y); + this._dropRect.set_size(width, height); + return false; + })); + + }, + _lookupIndex: function (metaWindow) { for (let i = 0; i < this._windows.length; i++) { if (this._windows[i].metaWindow == metaWindow) { @@ -588,17 +612,6 @@ Workspace.prototype = { return -1; }, - _onParentSet: function(actor, old_parent) { - let new_parent = this.actor.get_parent(); - if (new_parent == null) - return; - - if (old_parent) - this._windowOverlaysGroup.reparent(new_parent); - else - new_parent.add_actor(this._windowOverlaysGroup); - }, - containsMetaWindow: function (metaWindow) { return this._lookupIndex(metaWindow) >= 0; }, @@ -679,8 +692,8 @@ Workspace.prototype = { actorWidth = actor.width * actor.scale_x; actorHeight = actor.height * actor.scale_y; - xDelta = actor.x + actorWidth / 2.0 - xCenter * global.screen_width; - yDelta = actor.y + actorHeight / 2.0 - yCenter * global.screen_height; + xDelta = actor.x + actorWidth / 2.0 - xCenter * this._width - this._x; + yDelta = actor.y + actorHeight / 2.0 - yCenter * this._height - this._y; distanceSquared = xDelta * xDelta + yDelta * yDelta; return distanceSquared; @@ -765,38 +778,35 @@ Workspace.prototype = { }, /** - * _getSlotRelativeGeometry: + * _getSlotGeometry: * @slot: A layout slot * - * Returns: the workspace-relative [x, y, width, height] + * Returns: the screen-relative [x, y, width, height] * of a given window layout slot. */ - _getSlotRelativeGeometry: function(slot) { + _getSlotGeometry: function(slot) { let [xCenter, yCenter, fraction] = slot; - let width = global.screen_width * fraction; - let height = global.screen_height * fraction; + let width = this._width * fraction; + let height = this._height * fraction; - let x = xCenter * global.screen_width - width / 2; - let y = yCenter * global.screen_height - height / 2; + let x = this._x + xCenter * this._width - width / 2 ; + let y = this._y + yCenter * this._height - height / 2; return [x, y, width, height]; }, /** - * _computeWindowRelativeLayout: + * _computeWindowLayout: * @metaWindow: A #MetaWindow * @slot: A layout slot * * Given a window and slot to fit it in, compute its - * workspace-relative [x, y, scale] where scale applies + * screen-relative [x, y, scale] where scale applies * to both X and Y directions. */ - _computeWindowRelativeLayout: function(metaWindow, slot) { - let [xCenter, yCenter, fraction] = slot; - let [x, y, width, height] = this._getSlotRelativeGeometry(slot); - - xCenter = xCenter * global.screen_width; + _computeWindowLayout: function(metaWindow, slot) { + let [x, y, width, height] = this._getSlotGeometry(slot); let rect = metaWindow.get_outer_rect(); let buttonOuterHeight, captionHeight; @@ -804,23 +814,19 @@ Workspace.prototype = { if (this._windowOverlays[0]) { [buttonOuterHeight, captionHeight] = this._windowOverlays[0].chromeHeights(); - buttonOuterWidth = this._windowOverlays[0].chromeWidth() / this.scale; + buttonOuterWidth = this._windowOverlays[0].chromeWidth(); } else [buttonOuterHeight, captionHeight] = [0, 0]; - buttonOuterHeight /= this.scale; - captionHeight /= this.scale; - let desiredWidth = global.screen_width * fraction; - let desiredHeight = global.screen_height * fraction; - let scale = Math.min((desiredWidth - buttonOuterWidth) / rect.width, - (desiredHeight - buttonOuterHeight - captionHeight) / rect.height, - 1.0 / this.scale); + let scale = Math.min((width - buttonOuterWidth) / rect.width, + (height - buttonOuterHeight - captionHeight) / rect.height, + 1.0); - x = Math.floor(xCenter - 0.5 * scale * rect.width); + x = Math.floor(x + (width - scale * rect.width) / 2); // We want to center the window in case we have just one if (metaWindow.get_workspace().n_windows == 1) - y = Math.floor(yCenter * global.screen_height - 0.5 * scale * rect.height); + y = Math.floor(y + (height - scale * rect.height) / 2); else y = Math.floor(y + height - rect.height * scale - captionHeight); @@ -846,7 +852,7 @@ Workspace.prototype = { /** * positionWindows: * @flags: - * ZOOM - workspace is moving at the same time and we need to take that into account. + * INITIAL - this is the initial positioning of the windows. * ANIMATE - Indicates that we need animate changing position. */ positionWindows : function(flags) { @@ -859,7 +865,7 @@ Workspace.prototype = { if (this._reservedSlot) clones.push(this._reservedSlot); - let workspaceZooming = flags & WindowPositionFlags.ZOOM; + let initialPositioning = flags & WindowPositionFlags.INITIAL; let animate = flags & WindowPositionFlags.ANIMATE; // Start the animations @@ -881,7 +887,7 @@ Workspace.prototype = { if (clone.inDrag) continue; - let [x, y, scale] = this._computeWindowRelativeLayout(metaWindow, slot); + let [x, y, scale] = this._computeWindowLayout(metaWindow, slot); if (overlay) overlay.hide(); @@ -890,7 +896,7 @@ Workspace.prototype = { /* Hidden windows should fade in and grow * therefore we need to resize them now so they * can be scaled up later */ - if (workspaceZooming) { + if (initialPositioning) { clone.actor.opacity = 0; clone.actor.scale_x = 0; clone.actor.scale_y = 0; @@ -911,7 +917,6 @@ Workspace.prototype = { y: y, scale_x: scale, scale_y: scale, - workspace_relative: workspaceZooming ? this : null, time: Overview.ANIMATION_TIME, transition: 'easeOutQuad', onComplete: Lang.bind(this, function() { @@ -934,7 +939,7 @@ Workspace.prototype = { let clone = clones[i]; let metaWindow = clone.metaWindow; if (i == 0) { - clone.setStackAbove(null); + clone.setStackAbove(this._dropRect); } else { let previousClone = clones[i - 1]; clone.setStackAbove(previousClone.actor); @@ -954,10 +959,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.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; + cloneWidth = clone.actor.scale_x * cloneWidth; + cloneHeight = clone.actor.scale_y * cloneHeight; if (overlay) { overlay.updatePositions(cloneX, cloneY, cloneWidth, cloneHeight); @@ -982,12 +985,10 @@ Workspace.prototype = { return true; let [x, y, mask] = global.get_pointer(); - let wsWidth = this.actor.width * this.scale; - let wsHeight = this.actor.height * this.scale; let pointerHasMoved = (this._cursorX != x && this._cursorY != y); - let inWorkspace = (this.x < x && x < this.x + wsWidth && - this.y < y && y < this.y + wsHeight); + let inWorkspace = (this._x < x && x < this._x + this._width && + this._y < y && y < this._y + this._height); if (pointerHasMoved && inWorkspace) { // store current cursor position @@ -1088,13 +1089,20 @@ Workspace.prototype = { let clone = this._addWindowClone(win); if (win._overviewHint) { - let x = (win._overviewHint.x - this.actor.x) / this.scale; - let y = (win._overviewHint.y - this.actor.y) / this.scale; - let scale = win._overviewHint.scale / this.scale; + let x = win._overviewHint.x - this.actor.x; + let y = win._overviewHint.y - this.actor.y; + let scale = win._overviewHint.scale; delete win._overviewHint; clone.actor.set_position (x, y); clone.actor.set_scale (scale, scale); + } else { + // Position new windows at the top corner of the workspace rather + // than where they were placed for real to avoid the window + // being clipped to the workspaceView. Its not really more + // natural for the window to suddenly appear in the overview + // on some seemingly random location anyway. + clone.actor.set_position (this._x, this._y); } this.positionWindows(WindowPositionFlags.ANIMATE); @@ -1114,14 +1122,11 @@ Workspace.prototype = { // Animate the full-screen to Overview transition. zoomToOverview : function() { - this.actor.set_position(this.x, this.y); - this.actor.set_scale(this.scale, this.scale); - // Position and scale the windows. if (Main.overview.animationInProgress) - this.positionWindows(WindowPositionFlags.ANIMATE | WindowPositionFlags.ZOOM); + this.positionWindows(WindowPositionFlags.ANIMATE | WindowPositionFlags.INITIAL); else - this.positionWindows(WindowPositionFlags.ZOOM); + this.positionWindows(WindowPositionFlags.INITIAL); }, // Animates the return from Overview mode @@ -1139,7 +1144,7 @@ Workspace.prototype = { this._overviewHiddenId = Main.overview.connect('hidden', Lang.bind(this, this._doneLeavingOverview)); - if (this._metaWorkspace == currentWorkspace) + if (this.metaWorkspace != currentWorkspace) return; // Position and scale the windows. @@ -1154,7 +1159,6 @@ Workspace.prototype = { y: clone.origY, scale_x: 1.0, scale_y: 1.0, - workspace_relative: this, time: Overview.ANIMATION_TIME, opacity: 255, transition: 'easeOutQuad' @@ -1165,7 +1169,6 @@ Workspace.prototype = { { scale_x: 0, scale_y: 0, opacity: 0, - workspace_relative: this, time: Overview.ANIMATION_TIME, transition: 'easeOutQuad' }); @@ -1335,56 +1338,3 @@ Workspace.prototype = { }; Signals.addSignalMethods(Workspace.prototype); - -// Create a SpecialPropertyModifier to let us move windows in a -// straight line on the screen even though their containing workspace -// is also moving. -Tweener.registerSpecialPropertyModifier('workspace_relative', _workspaceRelativeModifier, _workspaceRelativeGet); - -function _workspaceRelativeModifier(workspace) { - let [startX, startY] = Main.overview.getPosition(); - let overviewPosX, overviewPosY, overviewScale; - - if (!workspace) - return []; - - if (workspace.leavingOverview) { - let [zoomedInX, zoomedInY] = Main.overview.getZoomedInPosition(); - overviewPosX = { begin: startX, end: zoomedInX }; - overviewPosY = { begin: startY, end: zoomedInY }; - overviewScale = { begin: Main.overview.getScale(), - end: Main.overview.getZoomedInScale() }; - } else { - overviewPosX = { begin: startX, end: 0 }; - overviewPosY = { begin: startY, end: 0 }; - overviewScale = { begin: Main.overview.getScale(), end: 1 }; - } - - return [ { name: 'x', - parameters: { workspacePos: workspace.x, - overviewPos: overviewPosX, - overviewScale: overviewScale } }, - { name: 'y', - parameters: { workspacePos: workspace.y, - overviewPos: overviewPosY, - overviewScale: overviewScale } } - ]; -} - -function _workspaceRelativeGet(begin, end, time, params) { - let curOverviewPos = (1 - time) * params.overviewPos.begin + - time * params.overviewPos.end; - let curOverviewScale = (1 - time) * params.overviewScale.begin + - time * params.overviewScale.end; - - // Calculate the screen position of the window. - let screen = (1 - time) * - ((begin + params.workspacePos) * params.overviewScale.begin + - params.overviewPos.begin) + - time * - ((end + params.workspacePos) * params.overviewScale.end + - params.overviewPos.end); - - // Return the workspace coordinates. - return (screen - curOverviewPos) / curOverviewScale - params.workspacePos; -} diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index e3e242643..df69f9968 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -25,14 +25,13 @@ const MAX_WORKSPACES = 16; const CONTROLS_POP_IN_TIME = 0.1; -function WorkspacesView(width, height, x, y, workspaces) { - this._init(width, height, x, y, workspaces); +function WorkspacesView(workspaces) { + this._init(workspaces); } WorkspacesView.prototype = { - _init: function(width, height, x, y, workspaces) { + _init: function(workspaces) { this.actor = new St.Group({ style_class: 'workspaces-view' }); - this.actor.set_clip(x, y, width, height); // The actor itself isn't a drop target, so we don't want to pick on its area this.actor.set_size(0, 0); @@ -43,19 +42,16 @@ WorkspacesView.prototype = { function() { let node = this.actor.get_theme_node(); this._spacing = node.get_length('spacing'); - this._computeWorkspacePositions(); + this._updateWorkspaceActors(false); })); this.actor.connect('notify::mapped', Lang.bind(this, this._onMappedChanged)); - this._width = width; - this._height = height; - this._x = x; - this._y = y; - this._zoomScale = 1.0; + this._width = 0; + this._height = 0; + this._x = 0; + this._y = 0; 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 = []; this._animating = false; // tweening this._scrolling = false; // swipe-scrolling @@ -81,6 +77,11 @@ WorkspacesView.prototype = { for (let w = 0; w < this._workspaces.length; w++) this._workspaces[w].zoomToOverview(); })); + this._overviewShownId = + Main.overview.connect('shown', + Lang.bind(this, function() { + this.actor.set_clip(this._x, this._y, this._width, this._height); + })); this._scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex, lower: 0, @@ -109,30 +110,17 @@ WorkspacesView.prototype = { this._swipeScrollEndId = 0; }, - setZoomScale: function(zoomScale) { - if (zoomScale == this._zoomScale) - return; + setGeometry: function(x, y, width, height) { + if (this._x == x && this._y == y && + this._width == width && this._height == height) + return; + this._width = width; + this._height = height; + this._x = x; + this._y = y; - this._zoomScale = zoomScale; - if (this._zoomOut) { - // If we are already zoomed out, then we have to reposition. - // Note that when shown initially zoomOut is false, so we - // won't trigger this. - - // setZoomScale can be invoked when the workspaces view is - // reallocated. Since we just want to animate things to the - // new position it seems OK to call updateWorkspaceActors - // immediately - adding a tween doesn't immediately cause - // a new allocation. But hide/show of the window overlays we - // do around animation does, so we need to do it later. - // This can be removed when we fix things to not hide/show - // the window overlay. - Meta.later_add(Meta.LaterType.BEFORE_REDRAW, - Lang.bind(this, function() { - this._computeWorkspacePositions(); - this._updateWorkspaceActors(true); - })); - } + for (let i = 0; i < this._workspaces.length; i++) + this._workspaces[i].setGeometry(x, y, width, height); }, _lookupWorkspaceForMetaWindow: function (metaWindow) { @@ -154,6 +142,8 @@ WorkspacesView.prototype = { activeWorkspace.actor.raise_top(); + this.actor.remove_clip(this._x, this._y, this._width, this._height); + for (let w = 0; w < this._workspaces.length; w++) this._workspaces[w].zoomFromOverview(); }, @@ -162,93 +152,27 @@ WorkspacesView.prototype = { this.actor.destroy(); }, - getScale: function() { - return this._workspaces[0].scale; - }, - syncStacking: function(stackIndices) { for (let i = 0; i < this._workspaces.length; i++) this._workspaces[i].syncStacking(stackIndices); }, - // 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]; - }, - - zoomOut: function() { - if (this._zoomOut) - return; - - this._zoomOut = true; - this._computeWorkspacePositions(); - this._updateWorkspaceActors(true); - }, - - zoomIn: function() { - if (!this._zoomOut) - return; - - this._zoomOut = false; - this._computeWorkspacePositions(); - this._updateWorkspaceActors(true); - }, - - // Compute the position, scale and opacity of the workspaces, but don't - // actually change the actors to match - _computeWorkspacePositions: function() { - let active = global.screen.get_active_workspace_index(); - let zoomScale = this._zoomOut ? this._zoomScale : 1; - let scale = zoomScale * this._width / global.screen_width; - - let _width = this._workspaces[0].actor.width * scale; - let _height = this._workspaces[0].actor.height * scale; - - this._activeWorkspaceX = (this._width - _width) / 2; - this._activeWorkspaceY = (this._height - _height) / 2; - - for (let w = 0; w < this._workspaces.length; w++) { - let workspace = this._workspaces[w]; - - workspace.opacity = (this._inDrag && w != active) ? 200 : 255; - - workspace.scale = scale; - workspace.x = this._x + this._activeWorkspaceX; - - // We adjust the center because the zoomScale is to leave space for - // the expanded workspace control so we want to zoom to either the - // left part of the area or the right part of the area - let offset = 0.5 * (1 - this._zoomScale) * this._width; - let rtl = (St.Widget.get_default_direction () == St.TextDirection.RTL); - if (this._zoomOut) - workspace.x += rtl ? offset : - offset; - - // We divide by zoomScale so that adjacent workspaces are always offscreen - // except when we are switching between workspaces - workspace.y = this._y + this._activeWorkspaceY - + (w - active) * (_height + this._spacing) / zoomScale; - } + updateWindowPositions: function() { + for (let w = 0; w < this._workspaces.length; w++) + this._workspaces[w].positionWindows(Workspace.WindowPositionFlags.ANIMATE); }, _scrollToActive: function(showAnimation) { let active = global.screen.get_active_workspace_index(); - this._computeWorkspacePositions(); this._updateWorkspaceActors(showAnimation); this._updateScrollAdjustment(active, showAnimation); }, - // Update workspace actors parameters to the values calculated in - // _computeWorkspacePositions() + // Update workspace actors parameters // @showAnimation: iff %true, transition between states _updateWorkspaceActors: function(showAnimation) { let active = global.screen.get_active_workspace_index(); - let targetWorkspaceNewY = this._y + this._activeWorkspaceY; - let targetWorkspaceCurrentY = this._workspaces[active].y; - let dy = targetWorkspaceNewY - targetWorkspaceCurrentY; this._animating = showAnimation; @@ -257,14 +181,12 @@ WorkspacesView.prototype = { Tweener.removeTweens(workspace.actor); - workspace.y += dy; + let opacity = (this._inDrag && w != active) ? 200 : 255; + let y = (w - active) * (this._height + this._spacing); if (showAnimation) { - let params = { x: workspace.x, - y: workspace.y, - scale_x: workspace.scale, - scale_y: workspace.scale, - opacity: workspace.opacity, + let params = { y: y, + opacity: opacity, time: WORKSPACE_SWITCH_TIME, transition: 'easeOutQuad' }; @@ -281,9 +203,8 @@ WorkspacesView.prototype = { } Tweener.addTween(workspace.actor, params); } else { - workspace.actor.set_scale(workspace.scale, workspace.scale); - workspace.actor.set_position(workspace.x, workspace.y); - workspace.actor.opacity = workspace.opacity; + workspace.actor.set_position(0, y); + workspace.actor.opacity = opacity; if (w == 0) this._updateVisibility(); } @@ -294,7 +215,6 @@ WorkspacesView.prototype = { Tweener.removeTweens(workspace.actor); - workspace.y += dy; workspace.actor.show(); workspace.hideWindowsOverlays(); @@ -338,7 +258,6 @@ WorkspacesView.prototype = { this._lostWorkspaces[l].destroy(); this._lostWorkspaces = []; - this._computeWorkspacePositions(); this._updateWorkspaceActors(false); }, @@ -380,7 +299,6 @@ WorkspacesView.prototype = { for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) this.actor.add_actor(this._workspaces[w].actor); - this._computeWorkspacePositions(); this._updateWorkspaceActors(false); } else { this._lostWorkspaces = lostWorkspaces; @@ -399,6 +317,7 @@ WorkspacesView.prototype = { _onDestroy: function() { this._scrollAdjustment.run_dispose(); Main.overview.disconnect(this._overviewShowingId); + Main.overview.disconnect(this._overviewShownId); global.window_manager.disconnect(this._switchWorkspaceNotifyId); if (this._timeoutId) { @@ -557,12 +476,6 @@ WorkspacesView.prototype = { Main.overview.hide(); } - if (result == Overview.SwipeScrollResult.SWIPE) - // The active workspace has changed; while swipe-scrolling - // has already taken care of the positioning, the cached - // positions need to be updated - this._computeWorkspacePositions(); - // Make sure title captions etc are shown as necessary this._updateVisibility(); }, @@ -590,7 +503,7 @@ WorkspacesView.prototype = { return; let currentY = firstWorkspaceY; - let newY = this._y - adj.value / (adj.upper - 1) * workspacesHeight; + let newY = - adj.value / (adj.upper - 1) * workspacesHeight; let dy = newY - currentY; @@ -662,43 +575,10 @@ WorkspacesDisplay.prototype = { this._workspaces[i] = new Workspace.Workspace(metaWorkspace); } - let rtl = (St.Widget.get_default_direction () == St.TextDirection.RTL); - - let totalAllocation = this.actor.allocation; - let totalWidth = totalAllocation.x2 - totalAllocation.x1; - let totalHeight = totalAllocation.y2 - totalAllocation.y1; - - let controlsVisible = this._controls.get_theme_node().get_length('visible-width'); - - totalWidth -= controlsVisible; - - // Workspaces expect to have the same ratio as the screen, so take - // this into account when fitting the workspace into the available space - let width, height; - let totalRatio = totalWidth / totalHeight; - let wsRatio = global.screen_width / global.screen_height; - if (wsRatio > totalRatio) { - width = totalWidth; - height = Math.floor(totalWidth / wsRatio); - } else { - width = Math.floor(totalHeight * wsRatio); - height = totalHeight; - } - - // Position workspaces in the available space - let [x, y] = this.actor.get_transformed_position(); - x = Math.floor(x + Math.abs(totalWidth - width) / 2); - y = Math.floor(y + Math.abs(totalHeight - height) / 2); - - if (rtl) - x += controlsVisible; - - let newView = new WorkspacesView(width, height, x, y, this._workspaces); - this._updateZoomScale(); - if (this.workspacesView) this.workspacesView.destroy(); - this.workspacesView = newView; + this.workspacesView = new WorkspacesView(this._workspaces); + this._updateWorkspacesGeometry(); this._nWorkspacesNotifyId = global.screen.connect('notify::n-workspaces', @@ -809,22 +689,34 @@ WorkspacesDisplay.prototype = { childBox.y2 = box.y2- box.y1; this._controls.allocate(childBox, flags); - this._updateZoomScale(); + this._updateWorkspacesGeometry(); }, - _updateZoomScale: function() { + _updateWorkspacesGeometry: function() { if (!this.workspacesView) return; - let totalAllocation = this.actor.allocation; - let totalWidth = totalAllocation.x2 - totalAllocation.x1; - let totalHeight = totalAllocation.y2 - totalAllocation.y1; + let width = this.actor.allocation.x2 - this.actor.allocation.x1; + let height = this.actor.allocation.y2 - this.actor.allocation.y1; - let [controlsMin, controlsNatural] = this._controls.get_preferred_width(totalHeight); + let [controlsMin, controlsNatural] = this._controls.get_preferred_width(height); let controlsVisible = this._controls.get_theme_node().get_length('visible-width'); - let zoomScale = (totalWidth - controlsNatural) / (totalWidth - controlsVisible); - this.workspacesView.setZoomScale(zoomScale); + let [x, y] = this.actor.get_transformed_position(); + + let rtl = (St.Widget.get_default_direction () == St.TextDirection.RTL); + + if (this._zoomOut) { + width -= controlsNatural; + if (rtl) + x += controlsNatural; + } else { + width -= controlsVisible; + if (rtl) + x += controlsVisible; + } + + this.workspacesView.setGeometry(x, y, width, height); }, _onRestacked: function() { @@ -893,6 +785,7 @@ WorkspacesDisplay.prototype = { let shouldZoom = this._controls.hover || this._inDrag; if (shouldZoom != this._zoomOut) { this._zoomOut = shouldZoom; + this._updateWorkspacesGeometry(); if (!this.workspacesView) return; @@ -902,10 +795,7 @@ WorkspacesDisplay.prototype = { time: WORKSPACE_SWITCH_TIME, transition: 'easeOutQuad' }); - if (shouldZoom) - this.workspacesView.zoomOut(); - else - this.workspacesView.zoomIn(); + this.workspacesView.updateWindowPositions(); } },