overview: Do not zoom the desktop background
While scaling the desktop background with the window previews represents workspaces quite intuitively, the approach is not without problems. As window previews in the overview behave quite differently to "real" windows, the representation of workspaces as miniature versions of "real" workspaces is flawed. The scaling also makes the transitions to and from the overview much more visually expensive, without adding much benefit. Leaving the background in place provides more visual stability to the transitions and emphasizes the distinctive behavior of elements in the overview. https://bugzilla.gnome.org/show_bug.cgi?id=634948
This commit is contained in:
parent
738fc375c0
commit
6432de95cc
@ -257,10 +257,6 @@ StTooltip StLabel {
|
||||
|
||||
/* Overview */
|
||||
|
||||
.overview {
|
||||
background-color: #111;
|
||||
}
|
||||
|
||||
.new-workspace-area {
|
||||
border: 2px solid rgba(255, 255, 255, 0.8);
|
||||
border-radius: 10px;
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Signals = imports.signals;
|
||||
const Lang = imports.lang;
|
||||
@ -172,7 +173,16 @@ function Overview() {
|
||||
|
||||
Overview.prototype = {
|
||||
_init : function() {
|
||||
this._group = new St.Group({ style_class: 'overview' });
|
||||
this._desktopFade = new St.Bin();
|
||||
global.overlay_group.add_actor(this._desktopFade);
|
||||
|
||||
// The actual global.background_actor is inside global.window_group,
|
||||
// which is hidden when displaying the overview, so we display a clone.
|
||||
this._background = new Clutter.Clone({ source: global.background_actor });
|
||||
this._background.hide();
|
||||
global.overlay_group.add_actor(this._background);
|
||||
|
||||
this._group = new St.Group({ name: 'overview' });
|
||||
this._group._delegate = this;
|
||||
this._group.connect('destroy', Lang.bind(this,
|
||||
function() {
|
||||
@ -209,10 +219,6 @@ Overview.prototype = {
|
||||
reactive: true });
|
||||
this._group.add_actor(this._transparentBackground);
|
||||
|
||||
// Background color for the Overview
|
||||
this._backOver = new St.Label();
|
||||
this._group.add_actor(this._backOver);
|
||||
|
||||
this._group.hide();
|
||||
global.overlay_group.add_actor(this._group);
|
||||
|
||||
@ -238,6 +244,20 @@ Overview.prototype = {
|
||||
this.workspaces = null;
|
||||
},
|
||||
|
||||
_getDesktopClone: function() {
|
||||
let windows = global.get_window_actors().filter(function(w) {
|
||||
return w.meta_window.get_window_type() == Meta.WindowType.DESKTOP;
|
||||
});
|
||||
if (windows.length == 0)
|
||||
return null;
|
||||
|
||||
let clone = new Clutter.Clone({ source: windows[0].get_texture() });
|
||||
clone.source.connect('destroy', Lang.bind(this, function() {
|
||||
clone.destroy();
|
||||
}));
|
||||
return clone;
|
||||
},
|
||||
|
||||
_onViewChanged: function() {
|
||||
if (!this.visible)
|
||||
return;
|
||||
@ -314,11 +334,6 @@ Overview.prototype = {
|
||||
this._workspacesBarWidth = this._workspacesWidth;
|
||||
this._workspacesBarY = primary.height - displayGridRowHeight;
|
||||
|
||||
// The parent (this._group) is positioned at the top left of the primary monitor
|
||||
// while this._backOver occupies the entire screen.
|
||||
this._backOver.set_position(- primary.x, - primary.y);
|
||||
this._backOver.set_size(global.screen_width, global.screen_height);
|
||||
|
||||
this._paneContainer.set_position(this._dash.actor.x + this._dash.actor.width + DEFAULT_PADDING,
|
||||
this._workspacesY);
|
||||
// Dynamic width
|
||||
@ -456,6 +471,19 @@ Overview.prototype = {
|
||||
this._group.add_actor(this._workspacesBar);
|
||||
this._workspacesBar.raise(this.workspaces.actor);
|
||||
|
||||
if (!this._desktopFade.child)
|
||||
this._desktopFade.child = this._getDesktopClone();
|
||||
|
||||
if (!this.workspaces.getActiveWorkspace().hasMaximizedWindows()) {
|
||||
this._desktopFade.opacity = 255;
|
||||
this._desktopFade.show();
|
||||
Tweener.addTween(this._desktopFade,
|
||||
{ opacity: 0,
|
||||
time: ANIMATION_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
}
|
||||
|
||||
// All the the actors in the window group are completely obscured,
|
||||
// hiding the group holding them while the Overview is displayed greatly
|
||||
// increases performance of the Overview especially when there are many
|
||||
@ -465,6 +493,7 @@ Overview.prototype = {
|
||||
// clones of them, this would obviously no longer be necessary.
|
||||
global.window_group.hide();
|
||||
this._group.show();
|
||||
this._background.show();
|
||||
|
||||
// Create a zoom out effect. First scale the Overview group up and
|
||||
// position it so that the active workspace fills up the whole screen,
|
||||
@ -502,6 +531,16 @@ Overview.prototype = {
|
||||
|
||||
this.animationInProgress = true;
|
||||
this._hideInProgress = true;
|
||||
|
||||
if (!this.workspaces.getActiveWorkspace().hasMaximizedWindows()) {
|
||||
this._desktopFade.opacity = 0;
|
||||
this._desktopFade.show();
|
||||
Tweener.addTween(this._desktopFade,
|
||||
{ opacity: 255,
|
||||
time: ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
}
|
||||
|
||||
if (this._activeDisplayPane != null)
|
||||
this._activeDisplayPane.close();
|
||||
this.workspaces.hide();
|
||||
@ -559,6 +598,7 @@ Overview.prototype = {
|
||||
return;
|
||||
|
||||
this.animationInProgress = false;
|
||||
this._desktopFade.hide();
|
||||
this._coverPane.lower_bottom();
|
||||
|
||||
this.emit('shown');
|
||||
@ -576,6 +616,8 @@ Overview.prototype = {
|
||||
this._workspacesManager = null;
|
||||
|
||||
this._dash.hide();
|
||||
this._desktopFade.hide();
|
||||
this._background.hide();
|
||||
this._group.hide();
|
||||
|
||||
this.visible = false;
|
||||
|
@ -289,76 +289,9 @@ WindowClone.prototype = {
|
||||
this.emit('drag-end');
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(WindowClone.prototype);
|
||||
|
||||
|
||||
function DesktopClone(window) {
|
||||
this._init(window);
|
||||
}
|
||||
|
||||
DesktopClone.prototype = {
|
||||
_init : function(window) {
|
||||
this.actor = new Clutter.Group({ reactive: true });
|
||||
|
||||
let background = new Clutter.Clone({ source: global.background_actor });
|
||||
this.actor.add_actor(background);
|
||||
|
||||
if (window) {
|
||||
this._desktop = new Clutter.Clone({ source: window.get_texture() });
|
||||
this.actor.add_actor(this._desktop);
|
||||
this._desktop.hide();
|
||||
} else {
|
||||
this._desktop = null;
|
||||
}
|
||||
|
||||
this.actor.connect('button-release-event',
|
||||
Lang.bind(this, this._onButtonRelease));
|
||||
},
|
||||
|
||||
zoomFromOverview: function(fadeInIcons) {
|
||||
if (this._desktop == null)
|
||||
return;
|
||||
|
||||
if (fadeInIcons) {
|
||||
this._desktop.opacity = 0;
|
||||
this._desktop.show();
|
||||
Tweener.addTween(this._desktop,
|
||||
{ opacity: 255,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
}
|
||||
},
|
||||
|
||||
zoomToOverview: function(fadeOutIcons) {
|
||||
if (this._desktop == null)
|
||||
return;
|
||||
|
||||
if (fadeOutIcons) {
|
||||
this._desktop.opacity = 255;
|
||||
this._desktop.show();
|
||||
Tweener.addTween(this._desktop,
|
||||
{ opacity: 0,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this,
|
||||
function() {
|
||||
this._desktop.hide();
|
||||
})
|
||||
});
|
||||
} else {
|
||||
this._desktop.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_onButtonRelease : function (actor, event) {
|
||||
this.emit('selected', event.get_time());
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(DesktopClone.prototype);
|
||||
|
||||
|
||||
/**
|
||||
* @windowClone: Corresponding window clone
|
||||
* @parentActor: The actor which will be the parent of all overlay items
|
||||
@ -561,7 +494,6 @@ WindowOverlay.prototype = {
|
||||
this._parentActor.queue_relayout();
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(WindowOverlay.prototype);
|
||||
|
||||
const WindowPositionFlags = {
|
||||
@ -585,10 +517,20 @@ Workspace.prototype = {
|
||||
// Without this the drop area will be overlapped.
|
||||
this._windowOverlaysGroup.set_size(0, 0);
|
||||
|
||||
this.actor = new Clutter.Group();
|
||||
this.actor = new Clutter.Group({ reactive: true });
|
||||
this.actor._delegate = this;
|
||||
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
this.actor.connect('button-release-event', Lang.bind(this,
|
||||
function(actor, event) {
|
||||
// Only switch to the workspace when there's no application
|
||||
// windows open. The problem is that it's too easy to miss
|
||||
// an app window and get the wrong one focused.
|
||||
if (this._windows.length == 0) {
|
||||
this.metaWorkspace.activate(event.get_time());
|
||||
Main.overview.hide();
|
||||
}
|
||||
}));
|
||||
|
||||
// Items in _windowOverlaysGroup should not be scaled, so we don't
|
||||
// add them to this.actor, but to its parent whenever it changes
|
||||
@ -604,35 +546,10 @@ Workspace.prototype = {
|
||||
|
||||
let windows = global.get_window_actors().filter(this._isMyWindow, this);
|
||||
|
||||
// Find the desktop window
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
if (windows[i].meta_window.get_window_type() == Meta.WindowType.DESKTOP) {
|
||||
this._desktop = new DesktopClone(windows[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If there wasn't one, fake it
|
||||
if (!this._desktop)
|
||||
this._desktop = new DesktopClone();
|
||||
|
||||
this._desktop.connect('selected',
|
||||
Lang.bind(this,
|
||||
function(clone, time) {
|
||||
// Only switch to the workspace when there's no application windows
|
||||
// open (we always have one window for the desktop). The problem
|
||||
// is that it's too easy to miss an app window and get the wrong
|
||||
// one focused.
|
||||
if (this._windows.length == 1) {
|
||||
this.metaWorkspace.activate(time);
|
||||
Main.overview.hide();
|
||||
}
|
||||
}));
|
||||
this.actor.add_actor(this._desktop.actor);
|
||||
|
||||
// Create clones for remaining windows that should be
|
||||
// visible in the Overview
|
||||
this._windows = [this._desktop];
|
||||
this._windowOverlays = [ null ];
|
||||
this._windows = [];
|
||||
this._windowOverlays = [];
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
if (this._isOverviewWindow(windows[i])) {
|
||||
this._addWindowClone(windows[i]);
|
||||
@ -747,10 +664,10 @@ Workspace.prototype = {
|
||||
// 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(this._desktop.actor.x - FRAME_SIZE / this.actor.scale_x,
|
||||
this._desktop.actor.y - FRAME_SIZE / this.actor.scale_y);
|
||||
this._frame.set_size(this._desktop.actor.width + 2 * FRAME_SIZE / this.actor.scale_x,
|
||||
this._desktop.actor.height + 2 * FRAME_SIZE / this.actor.scale_y);
|
||||
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));
|
||||
@ -770,14 +687,14 @@ Workspace.prototype = {
|
||||
* Set the workspace (desktop) reactive
|
||||
**/
|
||||
setReactive: function(reactive) {
|
||||
this._desktop.actor.reactive = reactive;
|
||||
this.actor.reactive = reactive;
|
||||
},
|
||||
|
||||
_updateFramePosition : function() {
|
||||
this._frame.set_position(this._desktop.actor.x - FRAME_SIZE / this.actor.scale_x,
|
||||
this._desktop.actor.y - FRAME_SIZE / this.actor.scale_y);
|
||||
this._frame.set_size(this._desktop.actor.width + 2 * FRAME_SIZE / this.actor.scale_x,
|
||||
this._desktop.actor.height + 2 * FRAME_SIZE / this.actor.scale_y);
|
||||
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) {
|
||||
@ -788,7 +705,7 @@ Workspace.prototype = {
|
||||
* _getVisibleClones:
|
||||
*
|
||||
* Returns a list WindowClone objects where the clone isn't filtered
|
||||
* out by any application filter. The clone for the desktop is excluded.
|
||||
* out by any application filter.
|
||||
* The returned array will always be newly allocated; it is not in any
|
||||
* defined order, and thus it's convenient to call .sort() with your
|
||||
* choice of sorting function.
|
||||
@ -796,7 +713,7 @@ Workspace.prototype = {
|
||||
_getVisibleClones: function() {
|
||||
let visible = [];
|
||||
|
||||
for (let i = 1; i < this._windows.length; i++) {
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
let clone = this._windows[i];
|
||||
|
||||
if (!this._isCloneVisible(clone))
|
||||
@ -808,7 +725,7 @@ Workspace.prototype = {
|
||||
},
|
||||
|
||||
_resetCloneVisibility: function () {
|
||||
for (let i = 1; i < this._windows.length; i++) {
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
let clone = this._windows[i];
|
||||
let overlay = this._windowOverlays[i];
|
||||
|
||||
@ -1007,9 +924,9 @@ Workspace.prototype = {
|
||||
let buttonOuterHeight, captionHeight;
|
||||
let buttonOuterWidth = 0;
|
||||
|
||||
if (this._windowOverlays[1]) {
|
||||
[buttonOuterHeight, captionHeight] = this._windowOverlays[1].chromeHeights();
|
||||
buttonOuterWidth = this._windowOverlays[1].chromeWidth() / this.scale;
|
||||
if (this._windowOverlays[0]) {
|
||||
[buttonOuterHeight, captionHeight] = this._windowOverlays[0].chromeHeights();
|
||||
buttonOuterWidth = this._windowOverlays[0].chromeWidth() / this.scale;
|
||||
} else
|
||||
[buttonOuterHeight, captionHeight] = [0, 0];
|
||||
buttonOuterHeight /= this.scale;
|
||||
@ -1172,7 +1089,7 @@ Workspace.prototype = {
|
||||
},
|
||||
|
||||
_fadeInAllOverlays: function() {
|
||||
for (let i = 1; i < this._windows.length; i++) {
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
let clone = this._windows[i];
|
||||
let overlay = this._windowOverlays[i];
|
||||
if (this._showOnlyWindows != null && !(clone.metaWindow in this._showOnlyWindows))
|
||||
@ -1182,7 +1099,7 @@ Workspace.prototype = {
|
||||
},
|
||||
|
||||
_hideAllOverlays: function() {
|
||||
for (let i = 1; i< this._windows.length; i++) {
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
let overlay = this._windowOverlays[i];
|
||||
overlay.hide();
|
||||
}
|
||||
@ -1309,8 +1226,8 @@ Workspace.prototype = {
|
||||
},
|
||||
|
||||
// check for maximized windows on the workspace
|
||||
_haveMaximizedWindows: function() {
|
||||
for (let i = 1; i < this._windows.length; i++) {
|
||||
hasMaximizedWindows: function() {
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
let metaWindow = this._windows[i].metaWindow;
|
||||
if (metaWindow.showing_on_its_workspace() &&
|
||||
metaWindow.maximized_horizontally &&
|
||||
@ -1331,12 +1248,6 @@ Workspace.prototype = {
|
||||
else
|
||||
this.positionWindows(WindowPositionFlags.ZOOM);
|
||||
|
||||
let active = global.screen.get_active_workspace();
|
||||
let fadeInIcons = (Main.overview.animationInProgress &&
|
||||
active == this.metaWorkspace &&
|
||||
!this._haveMaximizedWindows());
|
||||
this._desktop.zoomToOverview(fadeInIcons);
|
||||
|
||||
this._visible = true;
|
||||
},
|
||||
|
||||
@ -1354,7 +1265,7 @@ Workspace.prototype = {
|
||||
this._doneLeavingOverview));
|
||||
|
||||
// Position and scale the windows.
|
||||
for (let i = 1; i < this._windows.length; i++) {
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
let clone = this._windows[i];
|
||||
|
||||
clone.zoomFromOverview();
|
||||
@ -1383,11 +1294,6 @@ Workspace.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
let active = global.screen.get_active_workspace();
|
||||
let fadeOutIcons = (active == this.metaWorkspace &&
|
||||
!this._haveMaximizedWindows());
|
||||
this._desktop.zoomFromOverview(fadeOutIcons);
|
||||
|
||||
this._visible = false;
|
||||
},
|
||||
|
||||
@ -1451,7 +1357,7 @@ Workspace.prototype = {
|
||||
|
||||
// Don't let the user try to select this workspace as it's
|
||||
// making its exit.
|
||||
this._desktop.reactive = false;
|
||||
this.actor.reactive = false;
|
||||
},
|
||||
|
||||
destroy : function() {
|
||||
@ -1475,7 +1381,7 @@ Workspace.prototype = {
|
||||
// their parent (this.actor), but we might have a zoomed window
|
||||
// which has been reparented to the stage - _windows[0] holds
|
||||
// the desktop window, which is never reparented
|
||||
for (let w = 1; w < this._windows.length; w++)
|
||||
for (let w = 0; w < this._windows.length; w++)
|
||||
this._windows[w].destroy();
|
||||
this._windows = [];
|
||||
},
|
||||
@ -1534,7 +1440,7 @@ Workspace.prototype = {
|
||||
},
|
||||
|
||||
_onShowOverlayClose: function (windowOverlay) {
|
||||
for (let i = 1; i < this._windowOverlays.length; i++) {
|
||||
for (let i = 0; i < this._windowOverlays.length; i++) {
|
||||
let overlay = this._windowOverlays[i];
|
||||
if (overlay == windowOverlay)
|
||||
continue;
|
||||
|
@ -117,6 +117,11 @@ GenericWorkspacesView.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
getActiveWorkspace: function() {
|
||||
let active = global.screen.get_active_workspace_index();
|
||||
return this._workspaces[active];
|
||||
},
|
||||
|
||||
_clearApplicationWindowSelection: function(reposition) {
|
||||
if (this._windowSelectionAppId == null)
|
||||
return;
|
||||
@ -826,7 +831,7 @@ SingleView.prototype = {
|
||||
if (index < 0 || index >= global.n_workspaces)
|
||||
return;
|
||||
|
||||
let dragActor = this._workspaces[index]._desktop.actor;
|
||||
let dragActor = this._workspaces[index].actor;
|
||||
|
||||
if (draggable) {
|
||||
this._workspaces[index].actor.reactive = true;
|
||||
@ -856,6 +861,9 @@ SingleView.prototype = {
|
||||
|
||||
// start dragging the active workspace
|
||||
_onButtonPress: function(actor, event) {
|
||||
if (actor != event.get_source())
|
||||
return;
|
||||
|
||||
if (this._dragIndex == -1)
|
||||
return;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user