workspace: Fade in instead of zoom to return desktop
The zooming animation of the windows looks nice when animating from the workspace display page, but looks weird from other pages like apps page or search page since the windows come from nowhere with an initial position not known to the user. Instead of that just fade the desktop with the windows in its original position. https://bugzilla.gnome.org/show_bug.cgi?id=732901
This commit is contained in:
parent
805b686576
commit
687e1ebf69
@ -623,7 +623,7 @@ const Overview = new Lang.Class({
|
|||||||
this.animationInProgress = true;
|
this.animationInProgress = true;
|
||||||
this.visibleTarget = false;
|
this.visibleTarget = false;
|
||||||
|
|
||||||
this.viewSelector.zoomFromOverview();
|
this.viewSelector.animateFromOverview();
|
||||||
|
|
||||||
// Make other elements fade out.
|
// Make other elements fade out.
|
||||||
Tweener.addTween(this._stack,
|
Tweener.addTween(this._stack,
|
||||||
|
@ -260,6 +260,16 @@ const ViewSelector = new Lang.Class({
|
|||||||
this._stageKeyPressId = 0;
|
this._stageKeyPressId = 0;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
Main.overview.connect('shown', Lang.bind(this,
|
||||||
|
function() {
|
||||||
|
// If we were animating from the desktop view to the
|
||||||
|
// apps page the workspace page was visible, allowing
|
||||||
|
// the windows to animate, but now we no longer want to
|
||||||
|
// show it given that we are now on the apps page or
|
||||||
|
// search page.
|
||||||
|
if (this._activePage != this._workspacesPage)
|
||||||
|
this._workspacesPage.opacity = 0;
|
||||||
|
}));
|
||||||
|
|
||||||
Main.wm.addKeybinding('toggle-application-view',
|
Main.wm.addKeybinding('toggle-application-view',
|
||||||
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
||||||
@ -295,29 +305,36 @@ const ViewSelector = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_toggleAppsPage: function() {
|
_toggleAppsPage: function() {
|
||||||
Main.overview.show();
|
|
||||||
this._showAppsButton.checked = !this._showAppsButton.checked;
|
this._showAppsButton.checked = !this._showAppsButton.checked;
|
||||||
|
Main.overview.show();
|
||||||
},
|
},
|
||||||
|
|
||||||
showApps: function() {
|
showApps: function() {
|
||||||
Main.overview.show();
|
|
||||||
this._showAppsButton.checked = true;
|
this._showAppsButton.checked = true;
|
||||||
|
Main.overview.show();
|
||||||
},
|
},
|
||||||
|
|
||||||
show: function() {
|
show: function() {
|
||||||
this.reset();
|
this.reset();
|
||||||
|
this._workspacesDisplay.show(this._showAppsButton.checked);
|
||||||
this._workspacesDisplay.show();
|
|
||||||
this._activePage = null;
|
this._activePage = null;
|
||||||
this._showPage(this._workspacesPage);
|
if (this._showAppsButton.checked)
|
||||||
|
this._showPage(this._appsPage);
|
||||||
|
else
|
||||||
|
this._showPage(this._workspacesPage);
|
||||||
|
|
||||||
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
|
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
|
||||||
Main.overview.fadeOutDesktop();
|
Main.overview.fadeOutDesktop();
|
||||||
},
|
},
|
||||||
|
|
||||||
zoomFromOverview: function() {
|
animateFromOverview: function() {
|
||||||
|
// Make sure workspace page is fully visible to allow
|
||||||
|
// workspace.js do the animation of the windows
|
||||||
|
this._workspacesPage.opacity = 255;
|
||||||
|
|
||||||
|
this._workspacesDisplay.animateFromOverview(this._activePage != this._workspacesPage);
|
||||||
|
|
||||||
this._showAppsButton.checked = false;
|
this._showAppsButton.checked = false;
|
||||||
this._workspacesDisplay.zoomFromOverview();
|
|
||||||
|
|
||||||
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
|
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
|
||||||
Main.overview.fadeInDesktop();
|
Main.overview.fadeInDesktop();
|
||||||
@ -369,6 +386,9 @@ const ViewSelector = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_showPage: function(page) {
|
_showPage: function(page) {
|
||||||
|
if (!Main.overview.visible)
|
||||||
|
return;
|
||||||
|
|
||||||
if (page == this._activePage)
|
if (page == this._activePage)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -34,6 +34,8 @@ const DRAGGING_WINDOW_OPACITY = 100;
|
|||||||
const LAYOUT_SCALE_WEIGHT = 1;
|
const LAYOUT_SCALE_WEIGHT = 1;
|
||||||
const LAYOUT_SPACE_WEIGHT = 0.1;
|
const LAYOUT_SPACE_WEIGHT = 0.1;
|
||||||
|
|
||||||
|
const WINDOW_ANIMATION_MAX_NUMBER_BLENDING = 3;
|
||||||
|
|
||||||
function _interpolate(start, end, step) {
|
function _interpolate(start, end, step) {
|
||||||
return start + (end - start) * step;
|
return start + (end - start) * step;
|
||||||
}
|
}
|
||||||
@ -1258,10 +1260,11 @@ const Workspace = new Lang.Class({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We will reposition windows when enter again overview anyway.
|
// We will reposition windows anyway when enter again overview or when ending the windows
|
||||||
|
// animations whith fade animation.
|
||||||
// In this way we avoid unwanted animations of windows repositioning while
|
// In this way we avoid unwanted animations of windows repositioning while
|
||||||
// animating overview
|
// animating overview.
|
||||||
if (this.leavingOverview)
|
if (this.leavingOverview || this._animatingWindowsFade)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let initialPositioning = flags & WindowPositionFlags.INITIAL;
|
let initialPositioning = flags & WindowPositionFlags.INITIAL;
|
||||||
@ -1562,14 +1565,141 @@ const Workspace = new Lang.Class({
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Animate the full-screen to Overview transition.
|
fadeToOverview: function() {
|
||||||
zoomToOverview : function() {
|
// We don't want to reposition windows while animating in this way.
|
||||||
|
this._animatingWindowsFade = true;
|
||||||
|
this._overviewShownId = Main.overview.connect('shown', Lang.bind(this,
|
||||||
|
this._doneShowingOverview));
|
||||||
|
if (this._windows.length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this.metaWorkspace != null && this.metaWorkspace != global.screen.get_active_workspace())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Special case maximized windows, since it doesn't make sense
|
||||||
|
// to animate windows below in the stack
|
||||||
|
let topMaximizedWindow;
|
||||||
|
// It is ok to treat the case where there is no maximized
|
||||||
|
// window as if the bottom-most window was maximized given that
|
||||||
|
// it won't affect the result of the animation
|
||||||
|
for (topMaximizedWindow = this._windows.length - 1; topMaximizedWindow > 0; topMaximizedWindow--) {
|
||||||
|
let metaWindow = this._windows[topMaximizedWindow].metaWindow;
|
||||||
|
if (metaWindow.maximized_horizontally && metaWindow.maximized_vertically)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let nTimeSlots = Math.min(WINDOW_ANIMATION_MAX_NUMBER_BLENDING + 1, this._windows.length - topMaximizedWindow);
|
||||||
|
let windowBaseTime = Overview.ANIMATION_TIME / nTimeSlots;
|
||||||
|
|
||||||
|
let topIndex = this._windows.length - 1;
|
||||||
|
for (let i = 0; i < this._windows.length; i++) {
|
||||||
|
if (i < topMaximizedWindow) {
|
||||||
|
// below top-most maximized window, don't animate
|
||||||
|
let overlay = this._windowOverlays[i];
|
||||||
|
if (overlay)
|
||||||
|
overlay.hide();
|
||||||
|
this._windows[i].actor.opacity = 0;
|
||||||
|
} else {
|
||||||
|
let fromTop = topIndex - i;
|
||||||
|
let time;
|
||||||
|
if (fromTop < nTimeSlots) // animate top-most windows gradually
|
||||||
|
time = windowBaseTime * (nTimeSlots - fromTop);
|
||||||
|
else
|
||||||
|
time = windowBaseTime;
|
||||||
|
|
||||||
|
this._windows[i].actor.opacity = 255;
|
||||||
|
this._fadeWindow(i, time, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
fadeFromOverview: function() {
|
||||||
|
this.leavingOverview = true;
|
||||||
|
this._overviewHiddenId = Main.overview.connect('hidden', Lang.bind(this,
|
||||||
|
this._doneLeavingOverview));
|
||||||
|
if (this._windows.length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (let i = 0; i < this._windows.length; i++) {
|
||||||
|
let clone = this._windows[i];
|
||||||
|
Tweener.removeTweens(clone.actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._repositionWindowsId > 0) {
|
||||||
|
Mainloop.source_remove(this._repositionWindowsId);
|
||||||
|
this._repositionWindowsId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.metaWorkspace != null && this.metaWorkspace != global.screen.get_active_workspace())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Special case maximized windows, since it doesn't make sense
|
||||||
|
// to animate windows below in the stack
|
||||||
|
let topMaximizedWindow;
|
||||||
|
// It is ok to treat the case where there is no maximized
|
||||||
|
// window as if the bottom-most window was maximized given that
|
||||||
|
// it won't affect the result of the animation
|
||||||
|
for (topMaximizedWindow = this._windows.length - 1; topMaximizedWindow > 0; topMaximizedWindow--) {
|
||||||
|
let metaWindow = this._windows[topMaximizedWindow].metaWindow;
|
||||||
|
if (metaWindow.maximized_horizontally && metaWindow.maximized_vertically)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let nTimeSlots = Math.min(WINDOW_ANIMATION_MAX_NUMBER_BLENDING + 1, this._windows.length - topMaximizedWindow);
|
||||||
|
let windowBaseTime = Overview.ANIMATION_TIME / nTimeSlots;
|
||||||
|
|
||||||
|
let topIndex = this._windows.length - 1;
|
||||||
|
for (let i = 0; i < this._windows.length; i++) {
|
||||||
|
if (i < topMaximizedWindow) {
|
||||||
|
// below top-most maximized window, don't animate
|
||||||
|
let overlay = this._windowOverlays[i];
|
||||||
|
if (overlay)
|
||||||
|
overlay.hide();
|
||||||
|
this._windows[i].actor.opacity = 0;
|
||||||
|
} else {
|
||||||
|
let fromTop = topIndex - i;
|
||||||
|
let time;
|
||||||
|
if (fromTop < nTimeSlots) // animate top-most windows gradually
|
||||||
|
time = windowBaseTime * (fromTop + 1);
|
||||||
|
else
|
||||||
|
time = windowBaseTime * nTimeSlots;
|
||||||
|
|
||||||
|
this._windows[i].actor.opacity = 0;
|
||||||
|
this._fadeWindow(i, time, 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_fadeWindow: function(index, time, opacity) {
|
||||||
|
let clone = this._windows[index];
|
||||||
|
let overlay = this._windowOverlays[index];
|
||||||
|
|
||||||
|
if (overlay)
|
||||||
|
overlay.hide();
|
||||||
|
|
||||||
|
if (clone.metaWindow.showing_on_its_workspace()) {
|
||||||
|
let [origX, origY] = clone.getOriginalPosition();
|
||||||
|
clone.actor.scale_x = 1;
|
||||||
|
clone.actor.scale_y = 1;
|
||||||
|
clone.actor.x = origX;
|
||||||
|
clone.actor.y = origY;
|
||||||
|
Tweener.addTween(clone.actor,
|
||||||
|
{ time: time,
|
||||||
|
opacity: opacity,
|
||||||
|
transition: 'easeOutQuad'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// The window is hidden
|
||||||
|
clone.actor.opacity = 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
zoomToOverview: function() {
|
||||||
// Position and scale the windows.
|
// Position and scale the windows.
|
||||||
this._recalculateWindowPositions(WindowPositionFlags.ANIMATE | WindowPositionFlags.INITIAL);
|
this._recalculateWindowPositions(WindowPositionFlags.ANIMATE | WindowPositionFlags.INITIAL);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Animates the return from Overview mode
|
zoomFromOverview: function() {
|
||||||
zoomFromOverview : function() {
|
|
||||||
let currentWorkspace = global.screen.get_active_workspace();
|
let currentWorkspace = global.screen.get_active_workspace();
|
||||||
|
|
||||||
this.leavingOverview = true;
|
this.leavingOverview = true;
|
||||||
@ -1590,35 +1720,37 @@ const Workspace = new Lang.Class({
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Position and scale the windows.
|
// Position and scale the windows.
|
||||||
for (let i = 0; i < this._windows.length; i++) {
|
for (let i = 0; i < this._windows.length; i++)
|
||||||
let clone = this._windows[i];
|
this._zoomWindowFromOverview(i);
|
||||||
let overlay = this._windowOverlays[i];
|
},
|
||||||
|
|
||||||
if (overlay)
|
_zoomWindowFromOverview: function(index) {
|
||||||
overlay.hide();
|
let clone = this._windows[index];
|
||||||
|
let overlay = this._windowOverlays[index];
|
||||||
|
|
||||||
if (clone.metaWindow.showing_on_its_workspace()) {
|
if (overlay)
|
||||||
let [origX, origY] = clone.getOriginalPosition();
|
overlay.hide();
|
||||||
|
|
||||||
Tweener.addTween(clone.actor,
|
if (clone.metaWindow.showing_on_its_workspace()) {
|
||||||
{ x: origX,
|
let [origX, origY] = clone.getOriginalPosition();
|
||||||
y: origY,
|
Tweener.addTween(clone.actor,
|
||||||
scale_x: 1.0,
|
{ x: origX,
|
||||||
scale_y: 1.0,
|
y: origY,
|
||||||
time: Overview.ANIMATION_TIME,
|
scale_x: 1.0,
|
||||||
opacity: 255,
|
scale_y: 1.0,
|
||||||
transition: 'easeOutQuad'
|
time: Overview.ANIMATION_TIME,
|
||||||
});
|
opacity: 255,
|
||||||
} else {
|
transition: 'easeOutQuad'
|
||||||
// The window is hidden, make it shrink and fade it out
|
});
|
||||||
Tweener.addTween(clone.actor,
|
} else {
|
||||||
{ scale_x: 0,
|
// The window is hidden, make it shrink and fade it out
|
||||||
scale_y: 0,
|
Tweener.addTween(clone.actor,
|
||||||
opacity: 0,
|
{ scale_x: 0,
|
||||||
time: Overview.ANIMATION_TIME,
|
scale_y: 0,
|
||||||
transition: 'easeOutQuad'
|
opacity: 0,
|
||||||
});
|
time: Overview.ANIMATION_TIME,
|
||||||
}
|
transition: 'easeOutQuad'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1657,6 +1789,11 @@ const Workspace = new Lang.Class({
|
|||||||
this.leavingOverview = false;
|
this.leavingOverview = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_doneShowingOverview: function() {
|
||||||
|
this._animatingWindowsFade = false;
|
||||||
|
this._recalculateWindowPositions(WindowPositionFlags.INITIAL);
|
||||||
|
},
|
||||||
|
|
||||||
// Tests if @actor belongs to this workspaces and monitor
|
// Tests if @actor belongs to this workspaces and monitor
|
||||||
_isMyWindow : function (actor) {
|
_isMyWindow : function (actor) {
|
||||||
let win = actor.meta_window;
|
let win = actor.meta_window;
|
||||||
|
@ -21,6 +21,11 @@ const WORKSPACE_SWITCH_TIME = 0.25;
|
|||||||
// Note that mutter has a compile-time limit of 36
|
// Note that mutter has a compile-time limit of 36
|
||||||
const MAX_WORKSPACES = 16;
|
const MAX_WORKSPACES = 16;
|
||||||
|
|
||||||
|
const AnimationType = {
|
||||||
|
ZOOM: 0,
|
||||||
|
FADE: 1
|
||||||
|
};
|
||||||
|
|
||||||
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
|
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
|
||||||
|
|
||||||
const WorkspacesViewBase = new Lang.Class({
|
const WorkspacesViewBase = new Lang.Class({
|
||||||
@ -142,17 +147,25 @@ const WorkspacesView = new Lang.Class({
|
|||||||
return this._workspaces[active];
|
return this._workspaces[active];
|
||||||
},
|
},
|
||||||
|
|
||||||
zoomToOverview: function() {
|
animateToOverview: function(animationType) {
|
||||||
for (let w = 0; w < this._workspaces.length; w++)
|
for (let w = 0; w < this._workspaces.length; w++) {
|
||||||
this._workspaces[w].zoomToOverview();
|
if (animationType == AnimationType.ZOOM)
|
||||||
|
this._workspaces[w].zoomToOverview();
|
||||||
|
else
|
||||||
|
this._workspaces[w].fadeToOverview();
|
||||||
|
}
|
||||||
this._updateWorkspaceActors(false);
|
this._updateWorkspaceActors(false);
|
||||||
},
|
},
|
||||||
|
|
||||||
zoomFromOverview: function() {
|
animateFromOverview: function(animationType) {
|
||||||
this.actor.remove_clip();
|
this.actor.remove_clip();
|
||||||
|
|
||||||
for (let w = 0; w < this._workspaces.length; w++)
|
for (let w = 0; w < this._workspaces.length; w++) {
|
||||||
this._workspaces[w].zoomFromOverview();
|
if (animationType == AnimationType.ZOOM)
|
||||||
|
this._workspaces[w].zoomFromOverview();
|
||||||
|
else
|
||||||
|
this._workspaces[w].fadeFromOverview();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
syncStacking: function(stackIndices) {
|
syncStacking: function(stackIndices) {
|
||||||
@ -365,12 +378,18 @@ const ExtraWorkspaceView = new Lang.Class({
|
|||||||
this._workspace.setActualGeometry(this._actualGeometry);
|
this._workspace.setActualGeometry(this._actualGeometry);
|
||||||
},
|
},
|
||||||
|
|
||||||
zoomToOverview: function() {
|
animateToOverview: function(animationType) {
|
||||||
this._workspace.zoomToOverview();
|
if (animationType == AnimationType.ZOOM)
|
||||||
|
this._workspace.zoomToOverview();
|
||||||
|
else
|
||||||
|
this._workspace.fadeToOverview();
|
||||||
},
|
},
|
||||||
|
|
||||||
zoomFromOverview: function() {
|
animateFromOverview: function(animationType) {
|
||||||
this._workspace.zoomFromOverview();
|
if (animationType == AnimationType.ZOOM)
|
||||||
|
this._workspace.zoomFromOverview();
|
||||||
|
else
|
||||||
|
this._workspace.fadeFromOverview();
|
||||||
},
|
},
|
||||||
|
|
||||||
syncStacking: function(stackIndices) {
|
syncStacking: function(stackIndices) {
|
||||||
@ -462,10 +481,16 @@ const WorkspacesDisplay = new Lang.Class({
|
|||||||
return this._getPrimaryView().actor.navigate_focus(from, direction, false);
|
return this._getPrimaryView().actor.navigate_focus(from, direction, false);
|
||||||
},
|
},
|
||||||
|
|
||||||
show: function() {
|
show: function(fadeOnPrimary) {
|
||||||
this._updateWorkspacesViews();
|
this._updateWorkspacesViews();
|
||||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
for (let i = 0; i < this._workspacesViews.length; i++) {
|
||||||
this._workspacesViews[i].zoomToOverview();
|
let animationType;
|
||||||
|
if (fadeOnPrimary && i == this._primaryIndex)
|
||||||
|
animationType = AnimationType.FADE;
|
||||||
|
else
|
||||||
|
animationType = AnimationType.ZOOM;
|
||||||
|
this._workspacesViews[i].animateToOverview(animationType);
|
||||||
|
}
|
||||||
|
|
||||||
this._restackedNotifyId =
|
this._restackedNotifyId =
|
||||||
Main.overview.connect('windows-restacked',
|
Main.overview.connect('windows-restacked',
|
||||||
@ -474,9 +499,15 @@ const WorkspacesDisplay = new Lang.Class({
|
|||||||
this._scrollEventId = Main.overview.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
|
this._scrollEventId = Main.overview.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
|
||||||
},
|
},
|
||||||
|
|
||||||
zoomFromOverview: function() {
|
animateFromOverview: function(fadeOnPrimary) {
|
||||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
for (let i = 0; i < this._workspacesViews.length; i++) {
|
||||||
this._workspacesViews[i].zoomFromOverview();
|
let animationType;
|
||||||
|
if (fadeOnPrimary && i == this._primaryIndex)
|
||||||
|
animationType = AnimationType.FADE;
|
||||||
|
else
|
||||||
|
animationType = AnimationType.ZOOM;
|
||||||
|
this._workspacesViews[i].animateFromOverview(animationType);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
hide: function() {
|
hide: function() {
|
||||||
|
Loading…
Reference in New Issue
Block a user