diff --git a/data/dbus-interfaces/org.gnome.Shell.xml b/data/dbus-interfaces/org.gnome.Shell.xml
index 38154cbdb..3ffb5c374 100644
--- a/data/dbus-interfaces/org.gnome.Shell.xml
+++ b/data/dbus-interfaces/org.gnome.Shell.xml
@@ -35,6 +35,7 @@
+
diff --git a/js/ui/background.js b/js/ui/background.js
index b4a599da8..9c6a1636d 100644
--- a/js/ui/background.js
+++ b/js/ui/background.js
@@ -733,6 +733,11 @@ var BackgroundManager = class BackgroundManager {
this._newBackgroundActor = null;
this.emit('changed');
+ if (Main.layoutManager.screenTransition.visible) {
+ oldBackgroundActor.destroy();
+ return;
+ }
+
oldBackgroundActor.ease({
opacity: 0,
duration: FADE_ANIMATION_TIME,
diff --git a/js/ui/layout.js b/js/ui/layout.js
index 102bed041..68941049d 100644
--- a/js/ui/layout.js
+++ b/js/ui/layout.js
@@ -18,6 +18,9 @@ var BACKGROUND_FADE_ANIMATION_TIME = 1000;
var HOT_CORNER_PRESSURE_THRESHOLD = 100; // pixels
var HOT_CORNER_PRESSURE_TIMEOUT = 1000; // ms
+const SCREEN_TRANSITION_DELAY = 250; // ms
+const SCREEN_TRANSITION_DURATION = 500; // ms
+
function isPopupMetaWindow(actor) {
switch (actor.meta_window.get_window_type()) {
case Meta.WindowType.DROPDOWN_MENU:
@@ -298,6 +301,13 @@ var LayoutManager = GObject.registerClass({
monitorManager.connect('monitors-changed',
this._monitorsChanged.bind(this));
this._monitorsChanged();
+
+ this.screenTransition = new ScreenTransition();
+ this.uiGroup.add_child(this.screenTransition);
+ this.screenTransition.add_constraint(new Clutter.BindConstraint({
+ source: this.uiGroup,
+ coordinate: Clutter.BindCoordinate.ALL,
+ }));
}
// This is called by Main after everything else is constructed
@@ -309,6 +319,7 @@ var LayoutManager = GObject.registerClass({
showOverview() {
this.overviewGroup.show();
+ this.screenTransition.hide();
this._inOverview = true;
this._updateVisibility();
@@ -316,6 +327,7 @@ var LayoutManager = GObject.registerClass({
hideOverview() {
this.overviewGroup.hide();
+ this.screenTransition.hide();
this._inOverview = false;
this._updateVisibility();
@@ -1369,3 +1381,42 @@ var PressureBarrier = class PressureBarrier {
}
};
Signals.addSignalMethods(PressureBarrier.prototype);
+
+var ScreenTransition = GObject.registerClass(
+class ScreenTransition extends Clutter.Actor {
+ _init() {
+ super._init({ visible: false });
+ }
+
+ vfunc_hide() {
+ this.content = null;
+ super.vfunc_hide();
+ }
+
+ run() {
+ if (this.visible)
+ return;
+
+ Main.uiGroup.set_child_above_sibling(this, null);
+
+ const rect = new imports.gi.cairo.RectangleInt({
+ x: 0,
+ y: 0,
+ width: global.screen_width,
+ height: global.screen_height,
+ });
+ const [, , , scale] = global.stage.get_capture_final_size(rect);
+ this.content = global.stage.paint_to_content(rect, scale, Clutter.PaintFlag.NO_CURSORS);
+
+ this.opacity = 255;
+ this.show();
+
+ this.ease({
+ opacity: 0,
+ duration: SCREEN_TRANSITION_DURATION,
+ delay: SCREEN_TRANSITION_DELAY,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ onStopped: () => this.hide(),
+ });
+ }
+});
diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js
index e44875a52..9f1e75d02 100644
--- a/js/ui/shellDBus.js
+++ b/js/ui/shellDBus.js
@@ -251,6 +251,19 @@ var GnomeShell = class {
invocation.return_value(GLib.Variant.new('(b)', [ungrabSucceeded]));
}
+ ScreenTransitionAsync(params, invocation) {
+ try {
+ this._senderChecker.checkInvocation(invocation);
+ } catch (e) {
+ invocation.return_gerror(e);
+ return;
+ }
+
+ Main.layoutManager.screenTransition.run();
+
+ invocation.return_value(null);
+ }
+
_emitAcceleratorActivated(action, device, timestamp) {
let destination = this._grabbedAccelerators.get(action);
if (!destination)