[gnome-shell/wip/fmuellner/ease-actors: 20/20] js: Use implicit animations for animatable properties



commit 52926e4cad12f6b57561d3f8826c94af94963526
Author: Florian Müllner <fmuellner gnome org>
Date:   Fri Jul 20 21:46:19 2018 +0200

    js: Use implicit animations for animatable properties
    
    We now have everything in place to replace Tweener for all animatable
    properties with implicit animations, which has the following benefits:
    
     - they run entirely in C, while Tweener requires context switches
       to JS each frame
    
     - they are more reliable, as Tweener only detects when an animation
       is overwritten with another Tween, while Clutter considers any
       property change
    
    https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/22

 js/gdm/authPrompt.js              |  52 +++----
 js/gdm/batch.js                   |   2 +-
 js/gdm/loginDialog.js             |  65 ++++----
 js/gdm/util.js                    |  61 ++++----
 js/ui/altTab.js                   |  34 ++---
 js/ui/animation.js                |  24 ++-
 js/ui/appDisplay.js               |  50 +++---
 js/ui/background.js               |  15 +-
 js/ui/boxpointer.js               |  54 +++----
 js/ui/closeDialog.js              |  27 ++--
 js/ui/dash.js                     |  67 ++++-----
 js/ui/dnd.js                      |  62 ++++----
 js/ui/iconGrid.js                 | 160 ++++++++++----------
 js/ui/keyboard.js                 |  28 ++--
 js/ui/layout.js                   |  73 ++++-----
 js/ui/lightbox.js                 |  38 ++---
 js/ui/lookingGlass.js             |  78 +++++-----
 js/ui/messageList.js              |  92 +++++++-----
 js/ui/messageTray.js              |  30 ++--
 js/ui/modalDialog.js              |  50 +++---
 js/ui/osdWindow.js                |  27 ++--
 js/ui/overview.js                 |  45 +++---
 js/ui/overviewControls.js         |  18 ++-
 js/ui/pageIndicators.js           |  11 +-
 js/ui/panel.js                    |  27 ++--
 js/ui/pointerA11yTimeout.js       |  17 +--
 js/ui/popupMenu.js                |  47 +++---
 js/ui/ripples.js                  |  29 ++--
 js/ui/runDialog.js                |  20 +--
 js/ui/screenShield.js             | 115 +++++++-------
 js/ui/screenshot.js               |  35 ++---
 js/ui/switcherPopup.js            |  15 +-
 js/ui/viewSelector.js             |  43 +++---
 js/ui/windowManager.js            | 309 ++++++++++++++++++--------------------
 js/ui/workspace.js                | 132 ++++++++--------
 js/ui/workspaceSwitcherPopup.js   |  21 +--
 js/ui/workspacesView.js           |  12 +-
 src/gnome-shell-extension-tool.in |  12 +-
 38 files changed, 1001 insertions(+), 996 deletions(-)
---
diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js
index 46b58e6b6..370464514 100644
--- a/js/gdm/authPrompt.js
+++ b/js/gdm/authPrompt.js
@@ -8,7 +8,6 @@ const Batch = imports.gdm.batch;
 const GdmUtil = imports.gdm.util;
 const Params = imports.misc.params;
 const ShellEntry = imports.ui.shellEntry;
-const Tweener = imports.ui.tweener;
 const UserWidget = imports.ui.userWidget;
 
 var DEFAULT_BUTTON_WELL_ICON_SIZE = 16;
@@ -267,7 +266,7 @@ var AuthPrompt = class {
         let oldActor = this._defaultButtonWellActor;
 
         if (oldActor)
-            Tweener.removeTweens(oldActor);
+            oldActor.remove_all_transitions();
 
         let wasSpinner;
         if (oldActor == this._spinner.actor)
@@ -290,18 +289,18 @@ var AuthPrompt = class {
                         this._spinner.stop();
                 }
             } else {
-                Tweener.addTween(oldActor,
-                                 { opacity: 0,
-                                   time: DEFAULT_BUTTON_WELL_ANIMATION_TIME / 1000,
-                                   delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY / 1000,
-                                   transition: 'linear',
-                                   onComplete: () => {
-                                       if (wasSpinner) {
-                                           if (this._spinner)
-                                               this._spinner.stop();
-                                       }
-                                   }
-                                 });
+                oldActor.ease({
+                    opacity: 0,
+                    duration: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
+                    delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
+                    mode: Clutter.AnimationMode.LINEAR,
+                    onComplete: () => {
+                        if (wasSpinner) {
+                            if (this._spinner)
+                                this._spinner.stop();
+                        }
+                    }
+                });
             }
         }
 
@@ -312,11 +311,12 @@ var AuthPrompt = class {
             if (!animate)
                 actor.opacity = 255;
             else
-                Tweener.addTween(actor,
-                                 { opacity: 255,
-                                   time: DEFAULT_BUTTON_WELL_ANIMATION_TIME / 1000,
-                                   delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY / 1000,
-                                   transition: 'linear' });
+                actor.ease({
+                    opacity: 255,
+                    duration: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
+                    delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
+                    mode: Clutter.AnimationMode.LINEAR
+                });
         }
 
         this._defaultButtonWellActor = actor;
@@ -365,12 +365,12 @@ var AuthPrompt = class {
     _fadeOutMessage() {
         if (this._message.opacity == 0)
             return;
-        Tweener.removeTweens(this._message);
-        Tweener.addTween(this._message,
-                         { opacity: 0,
-                           time: MESSAGE_FADE_OUT_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad'
-                         });
+        this._message.remove_all_transitions();
+        this._message.ease({
+            opacity: 0,
+            duration: MESSAGE_FADE_OUT_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD
+        });
     }
 
     setMessage(message, type) {
@@ -385,7 +385,7 @@ var AuthPrompt = class {
             this._message.remove_style_class_name('login-dialog-message-hint');
 
         if (message) {
-            Tweener.removeTweens(this._message);
+            this._message.remove_all_transitions();
             this._message.text = message;
             this._message.opacity = 255;
         } else {
diff --git a/js/gdm/batch.js b/js/gdm/batch.js
index 66baa05f9..74af4f0a8 100644
--- a/js/gdm/batch.js
+++ b/js/gdm/batch.js
@@ -20,7 +20,7 @@
  * In order for transformation animations to look good, they need to be
  * incremental and have some order to them (e.g., fade out hidden items,
  * then shrink to close the void left over). Chaining animations in this way can
- * be error-prone and wordy using just Tweener callbacks.
+ * be error-prone and wordy using just ease() callbacks.
  *
  * The classes in this file help with this:
  *
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
index 531b227c1..13db8c6ec 100644
--- a/js/gdm/loginDialog.js
+++ b/js/gdm/loginDialog.js
@@ -759,14 +759,15 @@ var LoginDialog = GObject.registerClass({
 
     _fadeInBannerView() {
         this._bannerView.show();
-        Tweener.addTween(this._bannerView,
-                         { opacity: 255,
-                           time: _FADE_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad' });
+        this._bannerView.ease({
+            opacity: 255,
+            duration: _FADE_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD
+        });
     }
 
     _hideBannerView() {
-        Tweener.removeTweens(this._bannerView);
+        this._bannerView.remove_all_transitions();
         this._bannerView.opacity = 0;
         this._bannerView.hide();
     }
@@ -859,10 +860,11 @@ var LoginDialog = GObject.registerClass({
             return;
         this._authPrompt.actor.opacity = 0;
         this._authPrompt.actor.show();
-        Tweener.addTween(this._authPrompt.actor,
-                         { opacity: 255,
-                           time: _FADE_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad' });
+        this._authPrompt.actor.ease({
+            opacity: 255,
+            duration: _FADE_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD
+        });
         this._fadeInBannerView();
     }
 
@@ -921,15 +923,16 @@ var LoginDialog = GObject.registerClass({
             return;
 
         this._bindOpacity();
-        Tweener.addTween(this,
-                         { opacity: 255,
-                           time: _FADE_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: () => {
-                               if (this._authPrompt.verificationStatus != 
AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
-                                   this._authPrompt.reset();
-                               this._unbindOpacity();
-                           } });
+        this.actor.ease({
+            opacity: 255,
+            duration: _FADE_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => {
+                if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
+                    this._authPrompt.reset();
+                this._unbindOpacity();
+            }
+        });
     }
 
     _gotGreeterSessionProxy(proxy) {
@@ -943,14 +946,15 @@ var LoginDialog = GObject.registerClass({
 
     _startSession(serviceName) {
         this._bindOpacity();
-        Tweener.addTween(this,
-                         { opacity: 0,
-                           time: _FADE_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: () => {
-                               this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
-                               this._unbindOpacity();
-                           } });
+        this.actor.ease({
+            opacity: 0,
+            duration: _FADE_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => {
+                this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
+                this._unbindOpacity();
+            }
+        });
     }
 
     _onSessionOpened(client, serviceName) {
@@ -1223,10 +1227,11 @@ var LoginDialog = GObject.registerClass({
 
         Main.pushModal(this, { actionMode: Shell.ActionMode.LOGIN_SCREEN });
 
-        Tweener.addTween(this,
-                         { opacity: 255,
-                           time: 1,
-                           transition: 'easeInQuad' });
+        this.ease({
+            opacity: 255,
+            duration: 1000,
+            mode: Clutter.AnimationMode.EASE_IN_QUAD
+        });
 
         return true;
     }
diff --git a/js/gdm/util.js b/js/gdm/util.js
index 2794fab13..66d5feec8 100644
--- a/js/gdm/util.js
+++ b/js/gdm/util.js
@@ -11,7 +11,6 @@ const OVirt = imports.gdm.oVirt;
 const Main = imports.ui.main;
 const Params = imports.misc.params;
 const SmartcardManager = imports.misc.smartcardManager;
-const Tweener = imports.ui.tweener;
 
 var PASSWORD_SERVICE_NAME = 'gdm-password';
 var FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
@@ -51,16 +50,16 @@ function fadeInActor(actor) {
 
     actor.opacity = 0;
     actor.set_height(0);
-    Tweener.addTween(actor,
-                     { opacity: 255,
-                       height: naturalHeight,
-                       time: FADE_ANIMATION_TIME / 1000,
-                       transition: 'easeOutQuad',
-                       onComplete() {
-                           this.set_height(-1);
-                           hold.release();
-                       },
-                     });
+    actor.ease({
+        opacity: 255,
+        height: naturalHeight,
+        duration: FADE_ANIMATION_TIME,
+        mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+        onComplete: () => {
+            this.set_height(-1);
+            hold.release();
+        }
+    });
 
     return hold;
 }
@@ -73,17 +72,17 @@ function fadeOutActor(actor) {
     }
 
     let hold = new Batch.Hold();
-    Tweener.addTween(actor,
-                     { opacity: 0,
-                       height: 0,
-                       time: FADE_ANIMATION_TIME / 1000,
-                       transition: 'easeOutQuad',
-                       onComplete() {
-                           this.hide();
-                           this.set_height(-1);
-                           hold.release();
-                       },
-                     });
+    actor.ease({
+        opacity: 0,
+        height: 0,
+        duration: FADE_ANIMATION_TIME,
+        mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+        onComplete: () => {
+            this.hide();
+            this.set_height(-1);
+            hold.release();
+        }
+    });
     return hold;
 }
 
@@ -103,15 +102,15 @@ function cloneAndFadeOutActor(actor) {
     clone.set_position(x, y);
 
     let hold = new Batch.Hold();
-    Tweener.addTween(clone,
-                     { opacity: 0,
-                       time: CLONE_FADE_ANIMATION_TIME / 1000,
-                       transition: 'easeOutQuad',
-                       onComplete() {
-                           clone.destroy();
-                           hold.release();
-                       }
-                     });
+    clone.ease({
+        opacity: 0,
+        duration: CLONE_FADE_ANIMATION_TIME,
+        mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+        onComplete: () => {
+            clone.destroy();
+            hold.release();
+        }
+    });
     return hold;
 }
 
diff --git a/js/ui/altTab.js b/js/ui/altTab.js
index fba4050f4..65c34d5d7 100644
--- a/js/ui/altTab.js
+++ b/js/ui/altTab.js
@@ -7,7 +7,6 @@ const Mainloop = imports.mainloop;
 
 const Main = imports.ui.main;
 const SwitcherPopup = imports.ui.switcherPopup;
-const Tweener = imports.ui.tweener;
 
 var APP_ICON_HOVER_TIMEOUT = 200; // milliseconds
 
@@ -361,16 +360,15 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
     }
 
     _destroyThumbnails() {
-        let thumbnailsActor = this._thumbnails;
-        Tweener.addTween(thumbnailsActor,
-                         { opacity: 0,
-                           time: THUMBNAIL_FADE_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: () => {
-                               thumbnailsActor.destroy();
-                               this.thumbnailsVisible = false;
-                           }
-                         });
+        this._thumbnails.ease({
+            opacity: 0,
+            duration: THUMBNAIL_FADE_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => {
+                this._thumbnails.destroy();
+                this.thumbnailsVisible = false;
+            }
+        });
         this._thumbnails = null;
         if (this._switcherList._items[this._selectedIndex])
             this._switcherList._items[this._selectedIndex].remove_accessible_state (Atk.StateType.EXPANDED);
@@ -393,12 +391,14 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
         this._thumbnails.get_allocation_box();
 
         this._thumbnails.opacity = 0;
-        Tweener.addTween(this._thumbnails,
-                         { opacity: 255,
-                           time: THUMBNAIL_FADE_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: () => this.thumbnailsVisible = true
-                         });
+        this._thumbnails.ease({
+            opacity: 255,
+            duration: THUMBNAIL_FADE_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => {
+                this.thumbnailsVisible = true;
+            }
+        });
 
         this._switcherList._items[this._selectedIndex].add_accessible_state (Atk.StateType.EXPANDED);
     }
diff --git a/js/ui/animation.js b/js/ui/animation.js
index a3d362dac..d66eaa404 100644
--- a/js/ui/animation.js
+++ b/js/ui/animation.js
@@ -1,11 +1,9 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 /* exported Animation, AnimatedIcon, Spinner */
 
-const { GLib, Gio, St } = imports.gi;
+const { Clutter, GLib, Gio, St } = imports.gi;
 const Mainloop = imports.mainloop;
 
-const Tweener = imports.ui.tweener;
-
 var ANIMATED_ICON_UPDATE_TIMEOUT = 16;
 var SPINNER_ANIMATION_TIME = 300;
 var SPINNER_ANIMATION_DELAY = 1000;
@@ -138,15 +136,15 @@ var Spinner = class extends AnimatedIcon {
     }
 
     play() {
-        Tweener.removeTweens(this.actor);
+        this.actor.remove_all_transitions();
 
         if (this._animate) {
             super.play();
-            Tweener.addTween(this.actor, {
+            this.actor.ease({
                 opacity: 255,
-                delay: SPINNER_ANIMATION_DELAY / 1000,
-                time: SPINNER_ANIMATION_TIME / 1000,
-                transition: 'linear'
+                delay: SPINNER_ANIMATION_DELAY,
+                duration: SPINNER_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.LINEAR
             });
         } else {
             this.actor.opacity = 255;
@@ -155,16 +153,14 @@ var Spinner = class extends AnimatedIcon {
     }
 
     stop() {
-        Tweener.removeTweens(this.actor);
+        this.actor.remove_all_transitions();
 
         if (this._animate) {
-            Tweener.addTween(this.actor, {
+            this.actor.ease({
                 opacity: 0,
-                time: SPINNER_ANIMATION_TIME / 1000,
+                time: SPINNER_ANIMATION_TIME,
                 transition: 'linear',
-                onComplete: () => {
-                    super.stop();
-                }
+                onComplete: () => super.stop()
             });
         } else {
             this.actor.opacity = 0;
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index cec1d602b..5fe140949 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -206,22 +206,24 @@ class BaseAppView {
     }
 
     animateSwitch(animationDirection) {
-        Tweener.removeTweens(this.actor);
-        Tweener.removeTweens(this._grid);
+        this.actor.remove_all_transitions();
+        this._grid.remove_all_transitions();
 
-        let params = { time: VIEWS_SWITCH_TIME / 1000,
-                       transition: 'easeOutQuad' };
+        let params = {
+            duration: VIEWS_SWITCH_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD
+        };
         if (animationDirection == IconGrid.AnimationDirection.IN) {
             this.actor.show();
             params.opacity = 255;
-            params.delay = VIEWS_SWITCH_ANIMATION_DELAY / 1000;
+            params.delay = VIEWS_SWITCH_ANIMATION_DELAY;
         } else {
             params.opacity = 0;
             params.delay = 0;
             params.onComplete = () => this.actor.hide();
         }
 
-        Tweener.addTween(this._grid, params);
+        this._grid.ease(params);
     }
 }
 Signals.addSignalMethods(BaseAppView.prototype);
@@ -439,13 +441,12 @@ var AllView = class AllView extends BaseAppView {
 
         if (this._currentPopup && this._displayingPopup &&
             animationDirection == IconGrid.AnimationDirection.OUT)
-            Tweener.addTween(this._currentPopup.actor,
-                             { time: VIEWS_SWITCH_TIME / 1000,
-                               transition: 'easeOutQuad',
-                               opacity: 0,
-                               onComplete() {
-                                   this.opacity = 255;
-                               } });
+            this._currentPopup.actor.ease({
+                opacity: 0,
+                duration: VIEWS_SWITCH_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                onComplete: () => this.opacity = 255
+            });
 
         if (animationDirection == IconGrid.AnimationDirection.OUT)
             this._pageIndicators.animateIndicators(animationDirection);
@@ -615,15 +616,16 @@ var AllView = class AllView extends BaseAppView {
 
     _updateIconOpacities(folderOpen) {
         for (let id in this._items) {
-            let params, opacity;
+            let opacity;
             if (folderOpen && !this._items[id].actor.checked)
                 opacity =  INACTIVE_GRID_OPACITY;
             else
                 opacity = 255;
-            params = { opacity: opacity,
-                       time: INACTIVE_GRID_OPACITY_ANIMATION_TIME / 1000,
-                       transition: 'easeOutQuad' };
-            Tweener.addTween(this._items[id].actor, params);
+            this._items[id].actor.ease({
+                opacity: opacity,
+                duration: INACTIVE_GRID_OPACITY_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD
+            });
         }
     }
 
@@ -831,7 +833,7 @@ var AppDisplay = class AppDisplay {
             if (this._controls.mapped)
                 return;
 
-            Tweener.removeTweens(this._controls);
+            this._controls.remove_all_transitions();
             this._controls.opacity = 255;
         });
 
@@ -897,11 +899,11 @@ var AppDisplay = class AppDisplay {
             finalOpacity = 0;
         }
 
-        Tweener.addTween(this._controls,
-                         { time: IconGrid.ANIMATION_TIME_IN,
-                           transition: 'easeInOutQuad',
-                           opacity: finalOpacity,
-                         });
+        this._controls.ease({
+            opacity: finalOpacity,
+            duration: IconGrid.ANIMATION_TIME_IN,
+            mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD
+        });
 
         currentView.animate(animationDirection, onComplete);
     }
diff --git a/js/ui/background.js b/js/ui/background.js
index 9684325e0..babc1e487 100644
--- a/js/ui/background.js
+++ b/js/ui/background.js
@@ -99,7 +99,6 @@ const Signals = imports.signals;
 const LoginManager = imports.misc.loginManager;
 const Main = imports.ui.main;
 const Params = imports.misc.params;
-const Tweener = imports.ui.tweener;
 
 var DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
 
@@ -710,14 +709,12 @@ var BackgroundManager = class BackgroundManager {
         this._newBackgroundActor = null;
         this.emit('changed');
 
-        Tweener.addTween(oldBackgroundActor,
-                         { opacity: 0,
-                           time: FADE_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete() {
-                               oldBackgroundActor.destroy();
-                           }
-                         });
+        oldBackgroundActor.ease({
+            opacity: 0,
+            duration: FADE_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => oldBackgroundActor.destroy()
+        });
     }
 
     _updateBackgroundActor() {
diff --git a/js/ui/boxpointer.js b/js/ui/boxpointer.js
index a5ce4baaf..7da11e133 100644
--- a/js/ui/boxpointer.js
+++ b/js/ui/boxpointer.js
@@ -4,7 +4,6 @@
 const { Clutter, GObject, Shell, St } = imports.gi;
 
 const Main = imports.ui.main;
-const Tweener = imports.ui.tweener;
 
 var PopupAnimation = {
     NONE:  0,
@@ -106,16 +105,18 @@ var BoxPointer = GObject.registerClass({
             }
         }
 
-        Tweener.addTween(this, { opacity: 255,
-                                 translation_x: 0,
-                                 translation_y: 0,
-                                 transition: 'linear',
-                                 onComplete: () => {
-                                     this._unmuteInput();
-                                     if (onComplete)
-                                         onComplete();
-                                 },
-                                 time: animationTime / 1000 });
+        this.ease({
+            opacity: 255,
+            translation_x: 0,
+            translation_y: 0,
+            duration: animationTime,
+            mode: Clutter.AnimationMode.LINEAR,
+            onComplete: () => {
+                this._unmuteInput();
+                if (onComplete)
+                    onComplete();
+            }
+        });
     }
 
     close(animate, onComplete) {
@@ -148,21 +149,22 @@ var BoxPointer = GObject.registerClass({
 
         this._muteInput();
 
-        Tweener.removeTweens(this);
-        Tweener.addTween(this, { opacity: fade ? 0 : 255,
-                                 translation_x: translationX,
-                                 translation_y: translationY,
-                                 transition: 'linear',
-                                 time: animationTime / 1000,
-                                 onComplete: () => {
-                                     this.hide();
-                                     this.opacity = 0;
-                                     this.translation_x = 0;
-                                     this.translation_y = 0;
-                                     if (onComplete)
-                                         onComplete();
-                                 }
-                               });
+        this.remove_all_transitions();
+        this.ease({
+            opacity: fade ? 0 : 255,
+            translation_x: translationX,
+            translation_y: translationY,
+            duration: animationTime,
+            mode: Clutter.AnimationMode.LINEAR,
+            onComplete: () => {
+                this.hide();
+                this.opacity = 0;
+                this.translation_x = 0;
+                this.translation_y = 0;
+                if (onComplete)
+                    onComplete();
+            }
+        });
     }
 
     _adjustAllocationForArrow(isWidth, minSize, natSize) {
diff --git a/js/ui/closeDialog.js b/js/ui/closeDialog.js
index 944755849..6d0519f8e 100644
--- a/js/ui/closeDialog.js
+++ b/js/ui/closeDialog.js
@@ -5,7 +5,6 @@ const { Clutter, Gio, GLib, GObject, Meta, Shell } = imports.gi;
 
 const Dialog = imports.ui.dialog;
 const Main = imports.ui.main;
-const Tweener = imports.ui.tweener;
 
 var FROZEN_WINDOW_BRIGHTNESS = -0.3;
 var DIALOG_TRANSITION_TIME = 150;
@@ -149,12 +148,12 @@ var CloseDialog = GObject.registerClass({
         this._dialog.scale_y = 0;
         this._dialog.set_pivot_point(0.5, 0.5);
 
-        Tweener.addTween(this._dialog,
-                         { scale_y: 1,
-                           transition: 'linear',
-                           time: DIALOG_TRANSITION_TIME / 1000,
-                           onComplete: this._onFocusChanged.bind(this)
-                         });
+        this._dialog.ease({
+            scale_y: 1,
+            mode: Clutter.AnimationMode.LINEAR,
+            duration: DIALOG_TRANSITION_TIME,
+            onComplete: this._onFocusChanged.bind(this)
+        });
     }
 
     vfunc_hide() {
@@ -176,14 +175,12 @@ var CloseDialog = GObject.registerClass({
         this._dialog = null;
         this._removeWindowEffect();
 
-        Tweener.addTween(dialog,
-                         { scale_y: 0,
-                           transition: 'linear',
-                           time: DIALOG_TRANSITION_TIME / 1000,
-                           onComplete: () => {
-                               dialog.destroy();
-                           }
-                         });
+        dialog.ease({
+            scale_y: 0,
+            mode: Clutter.AnimationMode.LINEAR,
+            duration: DIALOG_TRANSITION_TIME,
+            onComplete: () => dialog.destroy()
+        });
     }
 
     vfunc_focus() {
diff --git a/js/ui/dash.js b/js/ui/dash.js
index 75749d48f..ca0257f54 100644
--- a/js/ui/dash.js
+++ b/js/ui/dash.js
@@ -10,7 +10,6 @@ const AppFavorites = imports.ui.appFavorites;
 const DND = imports.ui.dnd;
 const IconGrid = imports.ui.iconGrid;
 const Main = imports.ui.main;
-const Tweener = imports.ui.tweener;
 
 var DASH_ANIMATION_TIME = 200;
 var DASH_ITEM_LABEL_SHOW_TIME = 150;
@@ -100,11 +99,11 @@ class DashItemContainer extends St.Widget {
             x = stageX + this.get_width() + xOffset;
 
         this.label.set_position(x, y);
-        Tweener.addTween(this.label,
-                         { opacity: 255,
-                           time: DASH_ITEM_LABEL_SHOW_TIME / 1000,
-                           transition: 'easeOutQuad',
-                         });
+        this.label.ease({
+            opacity: 255,
+            duration: DASH_ITEM_LABEL_SHOW_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD
+        });
     }
 
     setLabelText(text) {
@@ -113,14 +112,12 @@ class DashItemContainer extends St.Widget {
     }
 
     hideLabel() {
-        Tweener.addTween(this.label,
-                         { opacity: 0,
-                           time: DASH_ITEM_LABEL_HIDE_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: () => {
-                               this.label.hide();
-                           }
-                         });
+        this.label.ease({
+            opacity: 0,
+            duration: DASH_ITEM_LABEL_HIDE_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => this.label.hide()
+        });
     }
 
     setChild(actor) {
@@ -138,13 +135,13 @@ class DashItemContainer extends St.Widget {
             return;
 
         let time = animate ? DASH_ANIMATION_TIME : 0;
-        Tweener.addTween(this,
-                         { scale_x: 1.0,
-                           scale_y: 1.0,
-                           opacity: 255,
-                           time: time / 1000,
-                           transition: 'easeOutQuad'
-                         });
+        this.ease({
+            scale_x: 1,
+            scale_y: 1,
+            opacity: 255,
+            duration: time,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD
+        });
     }
 
     animateOutAndDestroy() {
@@ -156,14 +153,14 @@ class DashItemContainer extends St.Widget {
         }
 
         this.animatingOut = true;
-        Tweener.addTween(this,
-                         { scale_x: 0,
-                           scale_y: 0,
-                           opacity: 0,
-                           time: DASH_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: () => this.destroy()
-                         });
+        this.ease({
+            scale_x: 0,
+            scale_y: 0,
+            opacity: 0,
+            duration: DASH_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => this.destroy()
+        });
     }
 });
 
@@ -612,12 +609,12 @@ var Dash = class Dash {
             icon.icon.set_size(icon.icon.width * scale,
                                icon.icon.height * scale);
 
-            Tweener.addTween(icon.icon,
-                             { width: targetWidth,
-                               height: targetHeight,
-                               time: DASH_ANIMATION_TIME / 1000,
-                               transition: 'easeOutQuad',
-                             });
+            icon.icon.ease({
+                width: targetWidth,
+                height: targetHeight,
+                time: DASH_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD
+            });
         }
     }
 
diff --git a/js/ui/dnd.js b/js/ui/dnd.js
index 66984a714..db05f6922 100644
--- a/js/ui/dnd.js
+++ b/js/ui/dnd.js
@@ -429,19 +429,22 @@ var _Draggable = class _Draggable {
                 // to the final position because that tween would
                 // fight with updates as the user continues dragging
                 // the mouse; instead we do the position computations in
-                // an onUpdate() function.
-                Tweener.addTween(this._dragActor,
-                                 { scale_x: scale * origScale,
-                                   scale_y: scale * origScale,
-                                   time: SCALE_ANIMATION_TIME / 1000,
-                                   transition: 'easeOutQuad',
-                                   onUpdate: () => {
-                                       let currentScale = this._dragActor.scale_x / origScale;
-                                       this._dragOffsetX = currentScale * origDragOffsetX;
-                                       this._dragOffsetY = currentScale * origDragOffsetY;
-                                       this._dragActor.set_position(this._dragX + this._dragOffsetX,
-                                                                    this._dragY + this._dragOffsetY);
-                                   } });
+                // a ::new-frame handler.
+                this._dragActor.ease({
+                    scale_x: scale * origScale,
+                    scale_y: scale * origScale,
+                    duration: SCALE_ANIMATION_TIME,
+                    mode: Clutter.AnimationMode.EASE_OUT_QUAD
+                });
+
+                this._dragActor.get_transition('scale-x').connect('new-frame', () => {
+                    let currentScale = this._dragActor.scale_x / origScale;
+                    this._dragOffsetX = currentScale * origDragOffsetX;
+                    this._dragOffsetY = currentScale * origDragOffsetY;
+                    this._dragActor.set_position(
+                        this._dragX + this._dragOffsetX,
+                        this._dragY + this._dragOffsetY);
+                });
             }
         }
     }
@@ -658,13 +661,13 @@ var _Draggable = class _Draggable {
 
         let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation();
 
-        this._animateDragEnd(eventTime,
-                             { x: snapBackX,
-                               y: snapBackY,
-                               scale_x: snapBackScale,
-                               scale_y: snapBackScale,
-                               time: SNAP_BACK_ANIMATION_TIME / 1000,
-                             });
+        this._animateDragEnd(eventTime, {
+            x: snapBackX,
+            y: snapBackY,
+            scale_x: snapBackScale,
+            scale_y: snapBackScale,
+            duration: SNAP_BACK_ANIMATION_TIME
+        });
     }
 
     _restoreDragActor(eventTime) {
@@ -676,21 +679,22 @@ var _Draggable = class _Draggable {
         this._dragActor.set_scale(restoreScale, restoreScale);
         this._dragActor.opacity = 0;
 
-        this._animateDragEnd(eventTime,
-                             { time: REVERT_ANIMATION_TIME / 1000 });
+        this._animateDragEnd(eventTime, {
+            duration: REVERT_ANIMATION_TIME
+        });
     }
 
     _animateDragEnd(eventTime, params) {
         this._animationInProgress = true;
 
-        params['opacity']          = this._dragOrigOpacity;
-        params['transition']       = 'easeOutQuad';
-        params['onComplete']       = this._onAnimationComplete;
-        params['onCompleteScope']  = this;
-        params['onCompleteParams'] = [this._dragActor, eventTime];
-
         // start the animation
-        Tweener.addTween(this._dragActor, params);
+        this._dragActor.ease(Object.assign(params, {
+            opacity: this._dragOrigOpacity,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => {
+                this._onAnimationComplete(this._dragActor, eventTime);
+            }
+        }));
     }
 
     _finishAnimation() {
diff --git a/js/ui/iconGrid.js b/js/ui/iconGrid.js
index 2ff439879..cf6b48b20 100644
--- a/js/ui/iconGrid.js
+++ b/js/ui/iconGrid.js
@@ -4,7 +4,6 @@
 const { Clutter, GLib, GObject, Meta, St } = imports.gi;
 
 const Params = imports.misc.params;
-const Tweener = imports.ui.tweener;
 const Main = imports.ui.main;
 
 var ICON_SIZE = 96;
@@ -169,18 +168,16 @@ function zoomOutActor(actor) {
     let containedX = clamp(scaledX, monitor.x, monitor.x + monitor.width - scaledWidth);
     let containedY = clamp(scaledY, monitor.y, monitor.y + monitor.height - scaledHeight);
 
-    Tweener.addTween(actorClone,
-                     { time: APPICON_ANIMATION_OUT_TIME / 1000,
-                       scale_x: APPICON_ANIMATION_OUT_SCALE,
-                       scale_y: APPICON_ANIMATION_OUT_SCALE,
-                       translation_x: containedX - scaledX,
-                       translation_y: containedY - scaledY,
-                       opacity: 0,
-                       transition: 'easeOutQuad',
-                       onComplete() {
-                           actorClone.destroy();
-                       }
-                    });
+    actorClone.ease({
+        scale_x: APPICON_ANIMATION_OUT_SCALE,
+        scale_y: APPICON_ANIMATION_OUT_SCALE,
+        translation_x: containedX - scaledX,
+        translation_y: containedY - scaledY,
+        opacity: 0,
+        duration: APPICON_ANIMATION_OUT_TIME,
+        mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+        onComplete: () => actorClone.destroy()
+    });
 }
 
 var IconGrid = GObject.registerClass({
@@ -459,25 +456,27 @@ var IconGrid = GObject.registerClass({
             let delay = index / actors.length * maxDelay;
             let bounceUpTime = ANIMATION_TIME_IN / 4;
             let isLastItem = index == actors.length - 1;
-            Tweener.addTween(actor,
-                             { time: bounceUpTime / 1000,
-                               transition: 'easeInOutQuad',
-                               delay: delay / 1000,
-                               scale_x: ANIMATION_BOUNCE_ICON_SCALE,
-                               scale_y: ANIMATION_BOUNCE_ICON_SCALE,
-                               onComplete: () => {
-                                   Tweener.addTween(actor,
-                                                    { time: (ANIMATION_TIME_IN - bounceUpTime) / 1000,
-                                                      transition: 'easeInOutQuad',
-                                                      scale_x: 1,
-                                                      scale_y: 1,
-                                                      onComplete: () => {
-                                                          if (isLastItem)
-                                                              this._animationDone();
-                                                      }
-                                                    });
-                               }
-                             });
+            actor.ease({
+                scale_x: ANIMATION_BOUNCE_ICON_SCALE,
+                scale_y: ANIMATION_BOUNCE_ICON_SCALE,
+                duration: bounceUpTime,
+                mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
+                delay: delay,
+                onComplete: () => {
+                    let duration = ANIMATION_TIME_IN - bounceUpTime;
+                    actor.ease({
+                        scale_x: 1,
+                        scale_y: 1,
+                        duration,
+                        mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
+                        onComplete: () => {
+                            if (isLastItem)
+                                this._animationDone();
+                            actor.reactive = true;
+                        }
+                    });
+                }
+            });
         }
     }
 
@@ -536,21 +535,25 @@ var IconGrid = GObject.registerClass({
 
                 let delay = (1 - (actor._distance - minDist) / normalization) * ANIMATION_MAX_DELAY_FOR_ITEM;
                 let [finalX, finalY]  = actor._transformedPosition;
-                movementParams = { time: ANIMATION_TIME_IN / 1000,
-                                   transition: 'easeInOutQuad',
-                                   delay: delay / 1000,
-                                   x: finalX,
-                                   y: finalY,
-                                   scale_x: 1,
-                                   scale_y: 1,
-                                   onComplete: () => {
-                                       if (isLastItem)
-                                           this._animationDone();
-                                   } };
-                fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM / 1000,
-                               transition: 'easeInOutQuad',
-                               delay: delay / 1000,
-                               opacity: 255 };
+                movementParams = {
+                    x: finalX,
+                    y: finalY,
+                    scale_x: 1,
+                    scale_y: 1,
+                    duration: ANIMATION_TIME_IN,
+                    mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
+                    delay,
+                    onComplete: () => {
+                        if (isLastItem)
+                            this._animationDone();
+                    }
+                };
+                fadeParams = {
+                    opacity: 255,
+                    duration: ANIMATION_FADE_IN_TIME_FOR_ITEM,
+                    mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
+                    delay
+                };
             } else {
                 let isLastItem = actor._distance == maxDist;
 
@@ -558,26 +561,30 @@ var IconGrid = GObject.registerClass({
                 actorClone.set_position(startX, startY);
 
                 let delay = (actor._distance - minDist) / normalization * ANIMATION_MAX_DELAY_OUT_FOR_ITEM;
-                movementParams = { time: ANIMATION_TIME_OUT / 1000,
-                                   transition: 'easeInOutQuad',
-                                   delay: delay / 1000,
-                                   x: adjustedSourcePositionX,
-                                   y: adjustedSourcePositionY,
-                                   scale_x: scaleX,
-                                   scale_y: scaleY,
-                                   onComplete: () => {
-                                       if (isLastItem)
-                                           this._animationDone();
-                                   } };
-                fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM / 1000,
-                               transition: 'easeInOutQuad',
-                               delay: (ANIMATION_TIME_OUT + delay - ANIMATION_FADE_IN_TIME_FOR_ITEM) / 1000,
-                               opacity: 0 };
+                movementParams = {
+                    x: adjustedSourcePositionX,
+                    y: adjustedSourcePositionY,
+                    scale_x: scaleX,
+                    scale_y: scaleY,
+                    duration: ANIMATION_TIME_OUT,
+                    mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
+                    delay,
+                    onComplete: () => {
+                        if (isLastItem) {
+                            this._animationDone();
+                        }
+                    }
+                };
+                fadeParams = {
+                    opacity: 0,
+                    duration: ANIMATION_FADE_IN_TIME_FOR_ITEM,
+                    mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
+                    delay: ANIMATION_TIME_OUT + delay - ANIMATION_FADE_IN_TIME_FOR_ITEM
+                };
             }
 
-
-            Tweener.addTween(actorClone, movementParams);
-            Tweener.addTween(actorClone, fadeParams);
+            actorClone.ease(movementParams);
+            actorClone.ease(fadeParams);
         }
     }
 
@@ -982,13 +989,14 @@ var PaginatedIconGrid = GObject.registerClass({
 
         for (let i = 0; i < children.length; i++) {
             children[i].translation_y = 0;
-            let params = { translation_y: translationY,
-                           time: EXTRA_SPACE_ANIMATION_TIME / 1000,
-                           transition: 'easeInOutQuad'
-                         };
+            let params = {
+                translation_y: translationY,
+                duration: EXTRA_SPACE_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD
+            };
             if (i == (children.length - 1))
                 params.onComplete = () => this.emit('space-opened');
-            Tweener.addTween(children[i], params);
+            children[i].ease(params);
         }
     }
 
@@ -1001,12 +1009,12 @@ var PaginatedIconGrid = GObject.registerClass({
         for (let i = 0; i < this._translatedChildren.length; i++) {
             if (!this._translatedChildren[i].translation_y)
                 continue;
-            Tweener.addTween(this._translatedChildren[i],
-                             { translation_y: 0,
-                               time: EXTRA_SPACE_ANIMATION_TIME / 1000,
-                               transition: 'easeInOutQuad',
-                               onComplete: () => this.emit('space-closed')
-                             });
+            this._translatedChildren[i].ease({
+                translation_y: 0,
+                duration: EXTRA_SPACE_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
+                onComplete: () => this.emit('space-closed')
+            });
         }
     }
 });
diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js
index fcce61116..f8e929165 100644
--- a/js/ui/keyboard.js
+++ b/js/ui/keyboard.js
@@ -1654,19 +1654,23 @@ var Keyboard = class Keyboard {
             return;
 
         if (show) {
-            Tweener.addTween(windowActor,
-                             { y: windowActor.y - deltaY,
-                               time: Layout.KEYBOARD_ANIMATION_TIME / 1000,
-                               transition: 'easeOutQuad',
-                               onComplete: this._windowSlideAnimationComplete,
-                               onCompleteParams: [window, -deltaY] });
+            windowActor.ease({
+                y: windowActor.y - deltaY,
+                duration: Layout.KEYBOARD_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                onComplete: () => {
+                    this._windowSlideAnimationComplete(window, -deltaY);
+                }
+            });
         } else {
-            Tweener.addTween(windowActor,
-                             { y: windowActor.y + deltaY,
-                               time: Layout.KEYBOARD_ANIMATION_TIME / 1000,
-                               transition: 'easeInQuad',
-                               onComplete: this._windowSlideAnimationComplete,
-                               onCompleteParams: [window, deltaY] });
+            windowActor.ease({
+                y: windowActor.y + deltaY,
+                duration: Layout.KEYBOARD_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_IN_QUAD,
+                onComplete: () => {
+                    this._windowSlideAnimationComplete(window, deltaY);
+                }
+            });
         }
     }
 
diff --git a/js/ui/layout.js b/js/ui/layout.js
index 76bcaa054..fe4248766 100644
--- a/js/ui/layout.js
+++ b/js/ui/layout.js
@@ -11,7 +11,6 @@ const LoginManager = imports.misc.loginManager;
 const DND = imports.ui.dnd;
 const Main = imports.ui.main;
 const Params = imports.misc.params;
-const Tweener = imports.ui.tweener;
 const Ripples = imports.ui.ripples;
 
 var STARTUP_ANIMATION_TIME = 500;
@@ -464,10 +463,11 @@ var LayoutManager = GObject.registerClass({
                 let backgroundActor = this._bgManagers[i].backgroundActor;
                 backgroundActor.show();
                 backgroundActor.opacity = 0;
-                Tweener.addTween(backgroundActor,
-                                 { opacity: 255,
-                                   time: BACKGROUND_FADE_ANIMATION_TIME / 1000,
-                                   transition: 'easeOutQuad' });
+                backgroundActor.ease({
+                    opacity: 255,
+                    duration: BACKGROUND_FADE_ANIMATION_TIME,
+                    mode: Clutter.AnimationMode.EASE_OUT_QUAD
+                });
             }
         }
     }
@@ -698,23 +698,23 @@ var LayoutManager = GObject.registerClass({
     }
 
     _startupAnimationGreeter() {
-        Tweener.addTween(this.panelBox,
-                         { translation_y: 0,
-                           time: STARTUP_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: this._startupAnimationComplete,
-                           onCompleteScope: this });
+        this.panelBox.ease({
+            translation_y: 0,
+            duration: STARTUP_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => this._startupAnimationComplete()
+        });
     }
 
     _startupAnimationSession() {
-        Tweener.addTween(this.uiGroup,
-                         { scale_x: 1,
-                           scale_y: 1,
-                           opacity: 255,
-                           time: STARTUP_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: this._startupAnimationComplete,
-                           onCompleteScope: this });
+        this.uiGroup.ease({
+            scale_x: 1,
+            scale_y: 1,
+            opacity: 255,
+            duration: STARTUP_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => this._startupAnimationComplete()
+        });
     }
 
     _startupAnimationComplete() {
@@ -740,14 +740,15 @@ var LayoutManager = GObject.registerClass({
 
     showKeyboard() {
         this.keyboardBox.show();
-        Tweener.addTween(this.keyboardBox,
-                         { anchor_y: this.keyboardBox.height,
-                           opacity: 255,
-                           time: KEYBOARD_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: this._showKeyboardComplete,
-                           onCompleteScope: this
-                         });
+        this.keyboardBox.ease({
+            anchor_y: this.keyboardBox.height,
+            opacity: 255,
+            duration: KEYBOARD_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => {
+                this._showKeyboardComplete();
+            }
+        });
         this.emit('keyboard-visible-changed', true);
     }
 
@@ -766,14 +767,16 @@ var LayoutManager = GObject.registerClass({
             this.keyboardBox.disconnect(this._keyboardHeightNotifyId);
             this._keyboardHeightNotifyId = 0;
         }
-        Tweener.addTween(this.keyboardBox,
-                         { anchor_y: 0,
-                           opacity: 0,
-                           time: immediate ? 0 : KEYBOARD_ANIMATION_TIME / 1000,
-                           transition: 'easeInQuad',
-                           onComplete: this._hideKeyboardComplete,
-                           onCompleteScope: this
-                         });
+        this.keyboardBox.ease({
+            anchor_y: 0,
+            opacity: 0,
+            duration: immediate ? 0
+                                : KEYBOARD_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_IN_QUAD,
+            onComplete: () => {
+                this._hideKeyboardComplete();
+            }
+        });
 
         this.emit('keyboard-visible-changed', false);
     }
diff --git a/js/ui/lightbox.js b/js/ui/lightbox.js
index 079f61b10..189d29547 100644
--- a/js/ui/lightbox.js
+++ b/js/ui/lightbox.js
@@ -168,16 +168,16 @@ var Lightbox = class Lightbox {
                                }
                              });
         } else {
-            Tweener.removeTweens(this.actor);
-            Tweener.addTween(this.actor,
-                             { opacity: 255 * this._fadeFactor,
-                               time: fadeInTime / 1000,
-                               transition: 'easeOutQuad',
-                               onComplete: () => {
-                                   this.shown = true;
-                                   this.emit('shown');
-                               }
-                             });
+            this.actor.remove_all_transitions();
+            this.actor.ease({
+                opacity: 255 * this._fadeFactor,
+                duration: fadeInTime,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                onComplete: () => {
+                    this.shown = true;
+                    this.emit('shown');
+                }
+            });
         }
 
         this.actor.show();
@@ -202,15 +202,15 @@ var Lightbox = class Lightbox {
                                }
                              });
         } else {
-            Tweener.removeTweens(this.actor);
-            Tweener.addTween(this.actor,
-                             { opacity: 0,
-                               time: fadeOutTime / 1000,
-                               transition: 'easeOutQuad',
-                               onComplete: () => {
-                                   this.actor.hide();
-                               }
-                             });
+            this.actor.remove_all_transitions();
+            this.actor.ease({
+                opacity: 0,
+                duration: fadeOutTime,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                onComplete: () => {
+                    this.actor.hide();
+                }
+            });
         }
     }
 
diff --git a/js/ui/lookingGlass.js b/js/ui/lookingGlass.js
index 47d2e7301..9e09b1177 100644
--- a/js/ui/lookingGlass.js
+++ b/js/ui/lookingGlass.js
@@ -10,7 +10,6 @@ const System = imports.system;
 const History = imports.misc.history;
 const ExtensionUtils = imports.misc.extensionUtils;
 const ShellEntry = imports.ui.shellEntry;
-const Tweener = imports.ui.tweener;
 const Main = imports.ui.main;
 const JsParse = imports.misc.jsParse;
 
@@ -37,6 +36,8 @@ var AUTO_COMPLETE_DOUBLE_TAB_DELAY = 500;
 var AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION = 200;
 var AUTO_COMPLETE_GLOBAL_KEYWORDS = _getAutoCompleteGlobalKeywords();
 
+const LG_ANIMATION_TIME = 500;
+
 function _getAutoCompleteGlobalKeywords() {
     const keywords = ['true', 'false', 'null', 'new'];
     // Don't add the private properties of window (i.e., ones starting with '_')
@@ -419,9 +420,12 @@ var ObjInspector = class ObjInspector {
         this.actor.show();
         if (sourceActor) {
             this.actor.set_scale(0, 0);
-            Tweener.addTween(this.actor, { scale_x: 1, scale_y: 1,
-                                           transition: 'easeOutQuad',
-                                           time: 0.2 });
+            this.actor.ease({
+                scale_x: 1,
+                scale_y: 1,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                time: 200
+            });
         } else {
             this.actor.set_scale(1, 1);
         }
@@ -941,7 +945,7 @@ var LookingGlass = class LookingGlass {
         this._completionActor.set_text(completions.join(', '));
 
         // Setting the height to -1 allows us to get its actual preferred height rather than
-        // whatever was last given in set_height by Tweener.
+        // whatever was last set when animating
         this._completionActor.set_height(-1);
         let [, naturalHeight] = this._completionActor.get_preferred_height(this._resultsArea.get_width());
 
@@ -950,28 +954,32 @@ var LookingGlass = class LookingGlass {
             this._completionActor.height = naturalHeight;
         } else {
             let settings = St.Settings.get();
+            let duration = AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / settings.slow_down_factor;
             this._completionActor.show();
-            Tweener.removeTweens(this._completionActor);
-            Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION 
/ (1000 * settings.slow_down_factor),
-                                                      transition: 'easeOutQuad',
-                                                      height: naturalHeight,
-                                                      opacity: 255
-                                                    });
+            this._completionActor.remove_all_transitions();
+            this._completionActor.ease({
+                height: naturalHeight,
+                opacity: 255,
+                duration,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD
+            });
         }
     }
 
     _hideCompletions() {
         if (this._completionActor) {
             let settings = St.Settings.get();
-            Tweener.removeTweens(this._completionActor);
-            Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION 
/ (1000 * settings.slow_down_factor),
-                                                      transition: 'easeOutQuad',
-                                                      height: 0,
-                                                      opacity: 0,
-                                                      onComplete: () => {
-                                                          this._completionActor.hide();
-                                                      }
-                                                    });
+            let duration = AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / settings.slow_down_factor;
+            this._completionActor.remove_all_transitions();
+            this._completionActor.ease({
+                height: 0,
+                opacity: 0,
+                duration,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                onComplete: () => {
+                    this._completionActor.hide();
+                }
+            });
         }
     }
 
@@ -1080,15 +1088,16 @@ var LookingGlass = class LookingGlass {
         this._open = true;
         this._history.lastItem();
 
-        Tweener.removeTweens(this.actor);
+        this.actor.remove_all_transitions();
 
         // We inverse compensate for the slow-down so you can change the factor
         // through LookingGlass without long waits.
-        let settings = St.Settings.get();
-        Tweener.addTween(this.actor, { time: 0.5 / settings.slow_down_factor,
-                                       transition: 'easeOutQuad',
-                                       y: this._targetY
-                                     });
+        let duration = LG_ANIMATION_TIME / St.Settings.get().slow_down_factor;
+        this.actor.ease({
+            y: this._targetY,
+            duration,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD
+        });
     }
 
     close() {
@@ -1098,20 +1107,21 @@ var LookingGlass = class LookingGlass {
         this._objInspector.actor.hide();
 
         this._open = false;
-        Tweener.removeTweens(this.actor);
+        this.actor.remove_all_transitions();
 
         this.setBorderPaintTarget(null);
 
         Main.popModal(this._entry);
 
         let settings = St.Settings.get();
-        Tweener.addTween(this.actor, { time: Math.min(0.5 / settings.slow_down_factor, 0.5),
-                                       transition: 'easeOutQuad',
-                                       y: this._hiddenY,
-                                       onComplete: () => {
-                                           this.actor.hide();
-                                       }
-                                     });
+        let duration = Math.min(LG_ANIMATION_TIME / settings.slow_down_factor,
+                                LG_ANIMATION_TIME);
+        this.actor.ease({
+            y: this._hiddenY,
+            duration,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => this.actor.hide()
+        });
     }
 };
 Signals.addSignalMethods(LookingGlass.prototype);
diff --git a/js/ui/messageList.js b/js/ui/messageList.js
index ae7874b31..8fbd79a84 100644
--- a/js/ui/messageList.js
+++ b/js/ui/messageList.js
@@ -445,10 +445,11 @@ var Message = class Message {
                                time: MessageTray.ANIMATION_TIME / 1000,
                                transition: 'easeOutQuad' });
             this._actionBin.scale_y = 0;
-            Tweener.addTween(this._actionBin,
-                             { scale_y: 1,
-                               time: MessageTray.ANIMATION_TIME / 1000,
-                               transition: 'easeOutQuad' });
+            this._actionBin.ease({
+                scale_y: 1,
+                duration: MessageTray.ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD
+            });
         } else {
             this._bodyStack.layout_manager.expansion = 1;
             this._actionBin.scale_y = 1;
@@ -463,14 +464,15 @@ var Message = class Message {
                              { expansion: 0,
                                time: MessageTray.ANIMATION_TIME / 1000,
                                transition: 'easeOutQuad' });
-            Tweener.addTween(this._actionBin,
-                             { scale_y: 0,
-                               time: MessageTray.ANIMATION_TIME / 1000,
-                               transition: 'easeOutQuad',
-                               onComplete: () => {
-                                   this._actionBin.hide();
-                                   this.expanded = false;
-                               } });
+            this._actionBin.ease({
+                scale_y: 0,
+                duration: MessageTray.ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                onComplete: () => {
+                    this._actionBin.hide();
+                    this.expanded = false;
+                }
+            });
         } else {
             this._bodyStack.layout_manager.expansion = 0;
             this._actionBin.scale_y = 0;
@@ -581,10 +583,12 @@ var MessageListSection = class MessageListSection {
         this._list.insert_child_at_index(obj.container, index);
 
         if (animate)
-            Tweener.addTween(obj.container, { scale_x: 1,
-                                              scale_y: 1,
-                                              time: MESSAGE_ANIMATION_TIME / 1000,
-                                              transition: 'easeOutQuad' });
+            obj.container.ease({
+                scale_x: 1,
+                scale_y: 1,
+                duration: MESSAGE_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD
+            });
     }
 
     moveMessage(message, index, animate) {
@@ -597,16 +601,20 @@ var MessageListSection = class MessageListSection {
 
         let onComplete = () => {
             this._list.set_child_at_index(obj.container, index);
-            Tweener.addTween(obj.container, { scale_x: 1,
-                                              scale_y: 1,
-                                              time: MESSAGE_ANIMATION_TIME / 1000,
-                                              transition: 'easeOutQuad' });
+            obj.container.ease({
+                scale_x: 1,
+                scale_y: 1,
+                duration: MESSAGE_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD
+            });
         };
-        Tweener.addTween(obj.container, { scale_x: 0,
-                                          scale_y: 0,
-                                          time: MESSAGE_ANIMATION_TIME / 1000,
-                                          transition: 'easeOutQuad',
-                                          onComplete: onComplete });
+        obj.container.ease({
+            scale_x: 0,
+            scale_y: 0,
+            duration: MESSAGE_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete
+        });
     }
 
     removeMessage(message, animate) {
@@ -619,13 +627,16 @@ var MessageListSection = class MessageListSection {
         this._messages.delete(message);
 
         if (animate) {
-            Tweener.addTween(obj.container, { scale_x: 0, scale_y: 0,
-                                              time: MESSAGE_ANIMATION_TIME / 1000,
-                                              transition: 'easeOutQuad',
-                                              onComplete() {
-                                                  obj.container.destroy();
-                                                  global.sync_pointer();
-                                              } });
+            obj.container.ease({
+                scale_x: 0,
+                scale_y: 0,
+                duration: MESSAGE_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                onComplete: () => {
+                    obj.container.destroy();
+                    global.sync_pointer();
+                }
+            });
         } else {
             obj.container.destroy();
             global.sync_pointer();
@@ -647,15 +658,14 @@ var MessageListSection = class MessageListSection {
             for (let i = 0; i < messages.length; i++) {
                 let message = messages[i];
                 let obj = this._messages.get(message);
-                Tweener.addTween(obj.container,
-                                 { anchor_x: this._list.width,
-                                   opacity: 0,
-                                   time: MESSAGE_ANIMATION_TIME / 1000,
-                                   delay: i * delay / 1000,
-                                   transition: 'easeOutQuad',
-                                   onComplete() {
-                                       message.close();
-                                   } });
+                obj.container.ease({
+                    anchor_x: this._list.width,
+                    opacity: 0,
+                    duration: MESSAGE_ANIMATION_TIME,
+                    delay: i * delay,
+                    mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                    onComplete: () => message.close()
+                });
             }
         }
     }
diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js
index 920e71b1d..4e1841fc0 100644
--- a/js/ui/messageTray.js
+++ b/js/ui/messageTray.js
@@ -12,7 +12,6 @@ const GnomeSession = imports.misc.gnomeSession;
 const Layout = imports.ui.layout;
 const Main = imports.ui.main;
 const Params = imports.misc.params;
-const Tweener = imports.ui.tweener;
 
 const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
 
@@ -1321,16 +1320,16 @@ var MessageTray = class MessageTray {
         // notification is being shown.
 
         this._notificationState = State.SHOWING;
-        Tweener.removeTweens(this._bannerBin);
-        Tweener.addTween(this._bannerBin, {
+        this._bannerBin.remove_all_transitions();
+        this._bannerBin.ease({
             opacity: 255,
-            time: ANIMATION_TIME / 1000,
-            transition: 'linear'
+            duration: ANIMATION_TIME,
+            mode: Clutter.AnimationMode.LINEAR
         });
-        Tweener.addTween(this._bannerBin, {
+        this._bannerBin.ease({
             y: 0,
-            time: ANIMATION_TIME / 1000,
-            transition: 'easeOutBack',
+            duration: ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_BACK,
             onComplete: () => {
                 this._notificationState = State.SHOWN;
                 this._showNotificationCompleted();
@@ -1394,19 +1393,19 @@ var MessageTray = class MessageTray {
         }
 
         this._resetNotificationLeftTimeout();
+        this._bannerBin.remove_all_transitions();
 
         if (animate) {
             this._notificationState = State.HIDING;
-            Tweener.removeTweens(this._bannerBin);
-            Tweener.addTween(this._bannerBin, {
+            this._bannerBin.ease({
                 opacity: 0,
-                time: ANIMATION_TIME / 1000,
-                transition: 'linear'
+                duration: ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_BACK
             });
-            Tweener.addTween(this._bannerBin, {
+            this._bannerBin.ease({
                 y: -this._bannerBin.height,
-                time: ANIMATION_TIME / 1000,
-                transition: 'easeOutBack',
+                duration: ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_BACK,
                 onComplete: () => {
                     this._notificationState = State.HIDDEN;
                     this._hideNotificationCompleted();
@@ -1414,7 +1413,6 @@ var MessageTray = class MessageTray {
                 }
             });
         } else {
-            Tweener.removeTweens(this._bannerBin);
             this._bannerBin.y = -this._bannerBin.height;
             this._bannerBin.opacity = 0;
             this._notificationState = State.HIDDEN;
diff --git a/js/ui/modalDialog.js b/js/ui/modalDialog.js
index 3d33a0fa1..1d2c694dc 100644
--- a/js/ui/modalDialog.js
+++ b/js/ui/modalDialog.js
@@ -8,7 +8,6 @@ const Layout = imports.ui.layout;
 const Lightbox = imports.ui.lightbox;
 const Main = imports.ui.main;
 const Params = imports.misc.params;
-const Tweener = imports.ui.tweener;
 
 var OPEN_AND_CLOSE_TIME = 100;
 var FADE_OUT_DIALOG_TIME = 1000;
@@ -125,15 +124,15 @@ var ModalDialog = GObject.registerClass({
             this._lightbox.show();
         this.opacity = 0;
         this.show();
-        Tweener.addTween(this,
-                         { opacity: 255,
-                           time: this._shouldFadeIn ? OPEN_AND_CLOSE_TIME / 1000 : 0,
-                           transition: 'easeOutQuad',
-                           onComplete: () => {
-                               this._setState(State.OPENED);
-                               this.emit('opened');
-                           }
-                         });
+        this.ease({
+            opacity: 255,
+            duration: this._shouldFadeIn ? OPEN_AND_CLOSE_TIME : 0,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => {
+                this._setState(State.OPENED);
+                this.emit('opened');
+            }
+        });
     }
 
     setInitialKeyFocus(actor) {
@@ -176,15 +175,16 @@ var ModalDialog = GObject.registerClass({
         this.popModal(timestamp);
         this._savedKeyFocus = null;
 
-        if (this._shouldFadeOut)
-            Tweener.addTween(this,
-                             { opacity: 0,
-                               time: OPEN_AND_CLOSE_TIME / 1000,
-                               transition: 'easeOutQuad',
-                               onComplete: this._closeComplete.bind(this)
-                             });
-        else
+        if (this._shouldFadeOut) {
+            this.ease({
+                opacity: 0,
+                duration: OPEN_AND_CLOSE_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                onComplete: () => this._closeComplete()
+            });
+        } else {
             this._closeComplete();
+        }
     }
 
     // Drop modal status without closing the dialog; this makes the
@@ -249,13 +249,11 @@ var ModalDialog = GObject.registerClass({
             return;
 
         this.popModal(timestamp);
-        Tweener.addTween(this.dialogLayout,
-                         { opacity: 0,
-                           time: FADE_OUT_DIALOG_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: () => {
-                               this._setState(State.FADED_OUT);
-                           }
-                         });
+        this.dialogLayout.ease({
+            opacity: 0,
+            duration: FADE_OUT_DIALOG_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => this.state = State.FADED_OUT
+        });
     }
 });
diff --git a/js/ui/osdWindow.js b/js/ui/osdWindow.js
index 3a20cd9b9..d2656a560 100644
--- a/js/ui/osdWindow.js
+++ b/js/ui/osdWindow.js
@@ -133,10 +133,11 @@ var OsdWindow = class {
             this.actor.opacity = 0;
             this.actor.get_parent().set_child_above_sibling(this.actor, null);
 
-            Tweener.addTween(this.actor,
-                             { opacity: 255,
-                               time: FADE_TIME / 1000,
-                               transition: 'easeOutQuad' });
+            this.actor.ease({
+                opacity: 255,
+                duration: FADE_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD
+            });
         }
 
         if (this._hideTimeoutId)
@@ -156,15 +157,15 @@ var OsdWindow = class {
 
     _hide() {
         this._hideTimeoutId = 0;
-        Tweener.addTween(this.actor,
-                         { opacity: 0,
-                           time: FADE_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: () => {
-                               this._reset();
-                               Meta.enable_unredirect_for_display(global.display);
-                           }
-                         });
+        this.actor.ease({
+            opacity: 0,
+            duration: FADE_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => {
+                this._reset();
+                Meta.enable_unredirect_for_display(global.display);
+            }
+        });
         return GLib.SOURCE_REMOVE;
     }
 
diff --git a/js/ui/overview.js b/js/ui/overview.js
index e8d22e0f9..57dcca278 100644
--- a/js/ui/overview.js
+++ b/js/ui/overview.js
@@ -427,10 +427,11 @@ var Overview = class {
     fadeInDesktop() {
         this._desktopFade.opacity = 0;
         this._desktopFade.show();
-        Tweener.addTween(this._desktopFade,
-                         { opacity: 255,
-                           time: ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad' });
+        this._desktopFade.ease({
+            opacity: 255,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            duration: ANIMATION_TIME
+        });
     }
 
     fadeOutDesktop() {
@@ -444,11 +445,11 @@ var Overview = class {
 
         this._desktopFade.opacity = 255;
         this._desktopFade.show();
-        Tweener.addTween(this._desktopFade,
-                         { opacity: 0,
-                           time: ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad'
-                         });
+        this._desktopFade.ease({
+            opacity: 0,
+            mode: Clutter.Animates.EASE_OUT_QUAD,
+            duration: ANIMATION_TIME
+        });
     }
 
     // Checks if the Activities button is currently sensitive to
@@ -528,13 +529,12 @@ var Overview = class {
         this.viewSelector.show();
 
         this._overview.opacity = 0;
-        Tweener.addTween(this._overview,
-                         { opacity: 255,
-                           transition: 'easeOutQuad',
-                           time: ANIMATION_TIME / 1000,
-                           onComplete: this._showDone,
-                           onCompleteScope: this
-                         });
+        this._overview.ease({
+            opacity: 255,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            duration: ANIMATION_TIME,
+            onComplete: () => this._showDone()
+        });
         this._shadeBackgrounds();
 
         this._coverPane.raise_top();
@@ -592,13 +592,12 @@ var Overview = class {
         this.viewSelector.animateFromOverview();
 
         // Make other elements fade out.
-        Tweener.addTween(this._overview,
-                         { opacity: 0,
-                           transition: 'easeOutQuad',
-                           time: ANIMATION_TIME / 1000,
-                           onComplete: this._hideDone,
-                           onCompleteScope: this
-                         });
+        this._overview.ease({
+            opacity: 0,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            duration: ANIMATION_TIME,
+            onComplete: () => this._hideDone()
+        });
         this._unshadeBackgrounds();
 
         this._coverPane.raise_top();
diff --git a/js/ui/overviewControls.js b/js/ui/overviewControls.js
index cf6fcf3a7..9ada31e9e 100644
--- a/js/ui/overviewControls.js
+++ b/js/ui/overviewControls.js
@@ -196,17 +196,19 @@ var SlidingControl = class {
     }
 
     fadeIn() {
-        Tweener.addTween(this.actor, { opacity: 255,
-                                       time: SIDE_CONTROLS_ANIMATION_TIME / (2 * 1000),
-                                       transition: 'easeInQuad'
-                                     });
+        this.actor.ease({
+            opacity: 255,
+            duration: SIDE_CONTROLS_ANIMATION_TIME / 2,
+            mode: Clutter.AnimationMode.EASE_IN_QUAD
+        });
     }
 
     fadeHalf() {
-        Tweener.addTween(this.actor, { opacity: 128,
-                                       time: SIDE_CONTROLS_ANIMATION_TIME / (2 * 1000),
-                                       transition: 'easeOutQuad'
-                                     });
+        this.actor.ease({
+            opacity: 128,
+            duration: SIDE_CONTROLS_ANIMATION_TIME / 2,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD
+        });
     }
 
     slideIn() {
diff --git a/js/ui/pageIndicators.js b/js/ui/pageIndicators.js
index c28e001e8..008867740 100644
--- a/js/ui/pageIndicators.js
+++ b/js/ui/pageIndicators.js
@@ -3,7 +3,6 @@
 
 const { Clutter, GLib, GObject, Meta, St } = imports.gi;
 
-const Tweener = imports.ui.tweener;
 const { ANIMATION_TIME_OUT, ANIMATION_MAX_DELAY_OUT_FOR_ITEM, AnimationDirection } = imports.ui.iconGrid;
 
 var INDICATORS_BASE_TIME = 250;
@@ -118,7 +117,7 @@ class AnimatedPageIndicators extends PageIndicators {
             return;
 
         for (let i = 0; i < this._nPages; i++)
-            Tweener.removeTweens(children[i]);
+            children[i].remove_all_transitions();
 
         let offset;
         if (this.get_text_direction() == Clutter.TextDirection.RTL)
@@ -138,11 +137,11 @@ class AnimatedPageIndicators extends PageIndicators {
 
         for (let i = 0; i < this._nPages; i++) {
             children[i].translation_x = isAnimationIn ? offset : 0;
-            Tweener.addTween(children[i], {
+            children[i].ease({
                 translation_x: isAnimationIn ? 0 : offset,
-                time: (baseTime + delay * i) / 1000,
-                transition: 'easeInOutQuad',
-                delay: isAnimationIn ? ANIMATION_DELAY / 1000 : 0
+                duration: baseTime + delay * i,
+                mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
+                delay: isAnimationIn ? ANIMATION_DELAY : 0
             });
         }
     }
diff --git a/js/ui/panel.js b/js/ui/panel.js
index 433982005..b5da45432 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -13,7 +13,6 @@ const Overview = imports.ui.overview;
 const PopupMenu = imports.ui.popupMenu;
 const PanelMenu = imports.ui.panelMenu;
 const Main = imports.ui.main;
-const Tweener = imports.ui.tweener;
 
 var PANEL_ICON_SIZE = 16;
 var APP_MENU_ICON_MARGIN = 0;
@@ -262,11 +261,12 @@ var AppMenuButton = GObject.registerClass({
         this._visible = true;
         this.reactive = true;
         this.show();
-        Tweener.removeTweens(this);
-        Tweener.addTween(this,
-                         { opacity: 255,
-                           time: Overview.ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad' });
+        this.remove_all_transitions();
+        this.ease({
+            opacity: 255,
+            duration: Overview.ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD
+        });
     }
 
     fadeOut() {
@@ -275,14 +275,13 @@ var AppMenuButton = GObject.registerClass({
 
         this._visible = false;
         this.reactive = false;
-        Tweener.removeTweens(this);
-        Tweener.addTween(this,
-                         { opacity: 0,
-                           time: Overview.ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: () => {
-                               this.hide();
-                           } });
+        this.remove_all_transitions();
+        this.ease({
+            opacity: 0,
+            mode: Clutter.Animation.EASE_OUT_QUAD,
+            duration: Overview.ANIMATION_TIME,
+            onComplete: () => this.hide()
+        });
     }
 
     _syncIcon() {
diff --git a/js/ui/pointerA11yTimeout.js b/js/ui/pointerA11yTimeout.js
index 0bbe4a46c..77b17ac37 100644
--- a/js/ui/pointerA11yTimeout.js
+++ b/js/ui/pointerA11yTimeout.js
@@ -1,6 +1,5 @@
 /* exported PointerA11yTimeout */
 const { Clutter, GLib, GObject, Meta, St } = imports.gi;
-const Tweener = imports.ui.tweener;
 const Main = imports.ui.main;
 const Cairo = imports.cairo;
 
@@ -57,7 +56,7 @@ class PieTimer extends St.DrawingArea {
     }
 
     start(x, y, duration) {
-        Tweener.removeTweens(this);
+        this.remove_all_transitions();
 
         this.x = x - this.width / 2;
         this.y = y - this.height / 2;
@@ -67,16 +66,16 @@ class PieTimer extends St.DrawingArea {
         this._startTime = GLib.get_monotonic_time() / 1000.0;
         this._duration = duration;
 
-        Tweener.addTween(this,
-                         { opacity: 255,
-                           time: duration / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: () => this.stop()
-                          });
+        this.ease({
+            opacity: 255,
+            duration,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => this.stop()
+        });
     }
 
     stop() {
-        Tweener.removeTweens(this);
+        this.remove_all_transitions();
         this.hide();
     }
 });
diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js
index cab383e92..1943b269f 100644
--- a/js/ui/popupMenu.js
+++ b/js/ui/popupMenu.js
@@ -10,7 +10,6 @@ const BoxPointer = imports.ui.boxpointer;
 const GrabHelper = imports.ui.grabHelper;
 const Main = imports.ui.main;
 const Params = imports.misc.params;
-const Tweener = imports.ui.tweener;
 
 var Ornament = {
     NONE: 0,
@@ -1013,16 +1012,17 @@ var PopupSubMenu = class extends PopupMenuBase {
         if (animate) {
             let [, naturalHeight] = this.actor.get_preferred_height(-1);
             this.actor.height = 0;
-            Tweener.addTween(this.actor,
-                             { height: naturalHeight,
-                               time: 0.25,
-                               onComplete: () => {
-                                   this.actor.set_height(-1);
-                               }
-                             });
-            Tweener.addTween(this._arrow,
-                             { rotation_angle_z: targetAngle,
-                               time: 0.25 });
+            this.actor.ease({
+                height: naturalHeight,
+                duration: 250,
+                mode: Clutter.AnimationMode.EASE_OUT_EXPO,
+                onComplete: () => this.actor.set_height(-1)
+            });
+            this._arrow.ease({
+                rotation_angle_z: targetAngle,
+                duration: 250,
+                mode: Clutter.AnimationMode.EASE_OUT_EXPO
+            });
         } else {
             this._arrow.rotation_angle_z = targetAngle;
         }
@@ -1042,17 +1042,20 @@ var PopupSubMenu = class extends PopupMenuBase {
             animate = false;
 
         if (animate) {
-            Tweener.addTween(this.actor,
-                             { height: 0,
-                               time: 0.25,
-                               onComplete: () => {
-                                   this.actor.hide();
-                                   this.actor.set_height(-1);
-                               },
-                             });
-            Tweener.addTween(this._arrow,
-                             { rotation_angle_z: 0,
-                               time: 0.25 });
+            this.actor.ease({
+                height: 0,
+                duration: 250,
+                mode: Clutter.AnimationMode.EASE_OUT_EXPO,
+                onComplete: () => {
+                    this.actor.hide();
+                    this.actor.set_height(-1);
+                }
+            });
+            this._arrow.ease({
+                rotation_angle_z: 0,
+                duration: 250,
+                mode: Clutter.AnimationMode.EASE_OUT_EXPO
+            });
         } else {
             this._arrow.rotation_angle_z = 0;
             this.actor.hide();
diff --git a/js/ui/ripples.js b/js/ui/ripples.js
index cbdfaaf7f..2c81345f9 100644
--- a/js/ui/ripples.js
+++ b/js/ui/ripples.js
@@ -1,8 +1,7 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 /* exported Ripples */
 
-const { St } = imports.gi;
-const Tweener = imports.ui.tweener;
+const { Clutter, St } = imports.gi;
 
 // Shamelessly copied from the layout "hotcorner" ripples implementation
 var Ripples = class Ripples {
@@ -35,7 +34,7 @@ var Ripples = class Ripples {
         this._ripple3.set_pivot_point(px, py);
     }
 
-    _animRipple(ripple, delay, time, startScale, startOpacity, finalScale) {
+    _animRipple(ripple, delay, duration, startScale, startOpacity, finalScale) {
         // We draw a ripple by using a source image and animating it scaling
         // outwards and fading away. We want the ripples to move linearly
         // or it looks unrealistic, but if the opacity of the ripple goes
@@ -50,16 +49,20 @@ var Ripples = class Ripples {
         ripple.scale_x = ripple.scale_y = startScale;
         ripple.set_translation( - this._px * ripple.width, - this._py * ripple.height, 0.0);
 
-        Tweener.addTween(ripple, { opacity: 0,
-                                   delay: delay,
-                                   time: time,
-                                   transition: 'easeInQuad' });
-        Tweener.addTween(ripple, { scale_x: finalScale,
-                                   scale_y: finalScale,
-                                   delay: delay,
-                                   time: time,
-                                   transition: 'linear',
-                                   onComplete: () => ripple.visible = false });
+        ripple.ease({
+            opacity: 0,
+            delay,
+            duration,
+            mode: Clutter.AnimationMode.EASE_IN_QUAD
+        });
+        ripple.ease({
+            scale_x: finalScale,
+            scale_y: finalScale,
+            delay,
+            duration,
+            mode: Clutter.AnimationMode.LINEAR,
+            onComplete: () => ripple.visible = false
+        });
     }
 
     addTo(stage) {
diff --git a/js/ui/runDialog.js b/js/ui/runDialog.js
index 0ff8d840d..ea15ea746 100644
--- a/js/ui/runDialog.js
+++ b/js/ui/runDialog.js
@@ -6,7 +6,6 @@ const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
 const Main = imports.ui.main;
 const ModalDialog = imports.ui.modalDialog;
 const ShellEntry = imports.ui.shellEntry;
-const Tweener = imports.ui.tweener;
 const Util = imports.misc.util;
 const History = imports.misc.history;
 
@@ -243,15 +242,16 @@ class RunDialog extends ModalDialog.ModalDialog {
             let [, errorBoxNaturalHeight] = this._errorBox.get_preferred_height(-1);
 
             let parentActor = this._errorBox.get_parent();
-            Tweener.addTween(parentActor,
-                             { height: parentActor.height + errorBoxNaturalHeight,
-                               time: DIALOG_GROW_TIME / 1000,
-                               transition: 'easeOutQuad',
-                               onComplete: () => {
-                                   parentActor.set_height(-1);
-                                   this._errorBox.show();
-                               }
-                             });
+            let height = parentActor.height + errorBoxNaturalHeight;
+            parentActor.ease({
+                height,
+                duration: DIALOG_GROW_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                onComplete: () => {
+                    parentActor.set_height(-1);
+                    this._errorBox.show();
+                }
+            });
         }
     }
 
diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js
index 552ca4c3d..8e4fba1ee 100644
--- a/js/ui/screenShield.js
+++ b/js/ui/screenShield.js
@@ -17,7 +17,6 @@ const Overview = imports.ui.overview;
 const MessageTray = imports.ui.messageTray;
 const ShellDBus = imports.ui.shellDBus;
 const SmartcardManager = imports.misc.smartcardManager;
-const Tweener = imports.ui.tweener;
 
 const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
 const LOCK_ENABLED_KEY = 'lock-enabled';
@@ -250,15 +249,15 @@ var NotificationsBox = class {
             let widget = obj.sourceBox;
             let [, natHeight] = widget.get_preferred_height(-1);
             widget.height = 0;
-            Tweener.addTween(widget,
-                             { height: natHeight,
-                               transition: 'easeOutQuad',
-                               time: 0.25,
-                               onComplete: () => {
-                                   this._scrollView.vscrollbar_policy = St.PolicyType.AUTOMATIC;
-                                   widget.set_height(-1);
-                               }
-                             });
+            widget.ease({
+                height: natHeight,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                duration: 250,
+                onComplete: () => {
+                    this._scrollView.vscrollbar_policy = St.PolicyType.AUTOMATIC;
+                    widget.set_height(-1);
+                }
+            });
 
             this._updateVisibility();
             if (obj.sourceBox.visible)
@@ -734,26 +733,26 @@ var ScreenShield = class {
         let maxOpacity = 255 * ARROW_ANIMATION_PEAK_OPACITY;
         for (let i = 0; i < arrows.length; i++) {
             arrows[i].opacity = 0;
-            Tweener.addTween(arrows[i],
-                             { opacity: maxOpacity,
-                               delay: (unitaryDelay * (N_ARROWS - (i + 1))) / 1000,
-                               time: ARROW_ANIMATION_TIME / (2 * 1000),
-                               transition: 'easeOutQuad',
-                               onComplete: () => {
-                                   Tweener.addTween(arrors[i], {
-                                       opacity: 0,
-                                       time: ARROW_ANIMATION_TIME / (2 * 1000),
-                                       transition: 'easeInQuad'
-                                   });
-                               }
-                             });
+            arrows[i].ease({
+                opacity: maxOpacity,
+                delay: unitaryDelay * (N_ARROWS - (i + 1)),
+                duration: ARROW_ANIMATION_TIME / 2,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                onComplete: () => {
+                    arrows[i].ease({
+                        opacity: 0,
+                        duration: ARROW_ANIMATION_TIME / 2,
+                        mode: Clutter.AnimationMode.EASE_IN_QUAD
+                    });
+                }
+            });
         }
 
         return GLib.SOURCE_CONTINUE;
     }
 
     _onDragBegin() {
-        Tweener.removeTweens(this._lockScreenGroup);
+        this._lockScreenGroup.remove_all_transitions();
         this._lockScreenState = MessageTray.State.HIDING;
 
         if (this._isLocked)
@@ -785,17 +784,17 @@ var ScreenShield = class {
             // restore the lock screen to its original place
             // try to use the same speed as the normal animation
             let h = global.stage.height;
-            let time = MANUAL_FADE_TIME * (-this._lockScreenGroup.y) / h;
-            Tweener.removeTweens(this._lockScreenGroup);
-            Tweener.addTween(this._lockScreenGroup,
-                             { y: 0,
-                               time: time / 1000,
-                               transition: 'easeInQuad',
-                               onComplete: () => {
-                                   this._lockScreenGroup.fixed_position_set = false;
-                                   this._lockScreenState = MessageTray.State.SHOWN;
-                               }
-                             });
+            let duration = MANUAL_FADE_TIME * (-this._lockScreenGroup.y) / h;
+            this._lockScreenGroup.remove_all_transitions();
+            this._lockScreenGroup.ease({
+                y: 0,
+                duration,
+                mode: Clutter.AnimationMode.EASE_IN_QUAD,
+                onComplete: () => {
+                    this._lockScreenGroup.fixed_position_set = false;
+                    this._lockScreenState = MessageTray.State.SHOWN;
+                }
+            });
 
             this._maybeCancelDialog();
         }
@@ -925,7 +924,7 @@ var ScreenShield = class {
 
         this._lockScreenState = MessageTray.State.HIDING;
 
-        Tweener.removeTweens(this._lockScreenGroup);
+        this._lockScreenGroup.remove_all_transitions();
 
         if (animate) {
             // Tween the lock screen out of screen
@@ -937,14 +936,14 @@ var ScreenShield = class {
             let minVelocity = global.stage.height / CURTAIN_SLIDE_TIME;
 
             velocity = Math.max(minVelocity, velocity);
-            let time = delta / velocity;
-
-            Tweener.addTween(this._lockScreenGroup,
-                             { y: -h,
-                               time: time / 1000,
-                               transition: 'easeInQuad',
-                               onComplete: this._hideLockScreenComplete.bind(this),
-                             });
+            let duration = delta / velocity;
+
+            this._lockScreenGroup.ease({
+                y: -h,
+                duration,
+                mode: Clutter.AnimationMode.EASE_IN_QUAD,
+                onComplete: () => this._hideLockScreenComplete()
+            });
         } else {
             this._hideLockScreenComplete();
         }
@@ -1004,16 +1003,15 @@ var ScreenShield = class {
 
         if (params.animateLockScreen) {
             this._lockScreenGroup.y = -global.screen_height;
-            Tweener.removeTweens(this._lockScreenGroup);
-            Tweener.addTween(this._lockScreenGroup,
-                             { y: 0,
-                               time: MANUAL_FADE_TIME / 1000,
-                               transition: 'easeOutQuad',
-                               onComplete: () => {
-                                   this._lockScreenShown({ fadeToBlack: fadeToBlack,
-                                                           animateFade: true });
-                               }
-                             });
+            this._lockScreenGroup.remove_all_transitions();
+            this._lockScreenGroup.ease({
+                y: 0,
+                duration: MANUAL_FADE_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                onComplete: () => {
+                    this._lockScreenShown({ fadeToBlack, animateFade: true });
+                }
+            });
         } else {
             this._lockScreenGroup.fixed_position_set = false;
             this._lockScreenShown({ fadeToBlack: fadeToBlack,
@@ -1217,13 +1215,12 @@ var ScreenShield = class {
             this._isModal = false;
         }
 
-        Tweener.addTween(this._lockDialogGroup, {
+        this._lockDialogGroup.ease({
             scale_x: 0,
             scale_y: 0,
-            time: animate ? Overview.ANIMATION_TIME / 1000 : 0,
-            transition: 'easeOutQuad',
-            onComplete: this._completeDeactivate.bind(this),
-            onCompleteScope: this
+            duration: animate ? Overview.ANIMATION_TIME : 0,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => this._completeDeactivate()
         });
     }
 
diff --git a/js/ui/screenshot.js b/js/ui/screenshot.js
index 877a7a2eb..377879bfb 100644
--- a/js/ui/screenshot.js
+++ b/js/ui/screenshot.js
@@ -7,7 +7,6 @@ const Signals = imports.signals;
 const GrabHelper = imports.ui.grabHelper;
 const Lightbox = imports.ui.lightbox;
 const Main = imports.ui.main;
-const Tweener = imports.ui.tweener;
 
 const { loadInterfaceXML } = imports.misc.fileUtils;
 
@@ -298,14 +297,12 @@ var SelectArea = class {
 
     _onButtonRelease() {
         this._result = this._getGeometry();
-        Tweener.addTween(this._group,
-                         { opacity: 0,
-                           time: 0.2,
-                           transition: 'easeOutQuad',
-                           onComplete: () => {
-                               this._grabHelper.ungrab();
-                           }
-                         });
+        this._group.ease({
+            opacity: 0,
+            duration: 200,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => this._grabHelper.ungrab()
+        });
         return Clutter.EVENT_PROPAGATE;
     }
 
@@ -382,15 +379,15 @@ var Flashspot = class extends Lightbox.Lightbox {
     fire(doneCallback) {
         this.actor.show();
         this.actor.opacity = 255;
-        Tweener.addTween(this.actor,
-                         { opacity: 0,
-                           time: FLASHSPOT_ANIMATION_OUT_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: () => {
-                               if (doneCallback)
-                                   doneCallback();
-                               this.destroy();
-                           }
-                         });
+        this.actor.ease({
+            opacity: 0,
+            duration: FLASHSPOT_ANIMATION_OUT_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => {
+                if (doneCallback)
+                    doneCallback();
+                this.destroy();
+            }
+        });
     }
 };
diff --git a/js/ui/switcherPopup.js b/js/ui/switcherPopup.js
index ec5bbaae9..5167bb568 100644
--- a/js/ui/switcherPopup.js
+++ b/js/ui/switcherPopup.js
@@ -5,7 +5,6 @@ const { Clutter, GLib, GObject, Meta, St } = imports.gi;
 const Mainloop = imports.mainloop;
 
 const Main = imports.ui.main;
-const Tweener = imports.ui.tweener;
 
 var POPUP_DELAY_TIMEOUT = 150; // milliseconds
 
@@ -284,14 +283,12 @@ var SwitcherPopup = GObject.registerClass({
     fadeAndDestroy() {
         this._popModal();
         if (this.opacity > 0) {
-            Tweener.addTween(this,
-                             { opacity: 0,
-                               time: POPUP_FADE_OUT_TIME / 1000,
-                               transition: 'easeOutQuad',
-                               onComplete: () => {
-                                   this.destroy();
-                               }
-                             });
+            this.ease({
+                opacity: 0,
+                duration: POPUP_FADE_OUT_TIME,
+                mode: Clutter.Animation.EASE_OUT_QUAD,
+                onComplete: () => this.destroy()
+            });
         } else {
             this.destroy();
         }
diff --git a/js/ui/viewSelector.js b/js/ui/viewSelector.js
index f3257479d..9aef3b9dd 100644
--- a/js/ui/viewSelector.js
+++ b/js/ui/viewSelector.js
@@ -10,7 +10,6 @@ const OverviewControls = imports.ui.overviewControls;
 const Params = imports.misc.params;
 const Search = imports.ui.search;
 const ShellEntry = imports.ui.shellEntry;
-const Tweener = imports.ui.tweener;
 const WorkspacesView = imports.ui.workspacesView;
 const EdgeDragAction = imports.ui.edgeDragAction;
 const IconGrid = imports.ui.iconGrid;
@@ -322,23 +321,21 @@ var ViewSelector = class {
     }
 
     _fadePageIn() {
-        Tweener.addTween(this._activePage,
-                         { opacity: 255,
-                           time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad'
-                         });
+        this._activePage.ease({
+            opacity: 255,
+            duration: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD
+        });
     }
 
     _fadePageOut(page) {
         let oldPage = page;
-        Tweener.addTween(page,
-                         { opacity: 0,
-                           time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: () => {
-                               this._animateIn(oldPage);
-                           }
-                         });
+        page.ease({
+            opacity: 0,
+            duration: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => this._animateIn(oldPage)
+        });
     }
 
     _animateIn(oldPage) {
@@ -605,18 +602,20 @@ var ViewSelector = class {
 
     fadeIn() {
         let actor = this._activePage;
-        Tweener.addTween(actor, { opacity: 255,
-                                  time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME / (2 * 1000),
-                                  transition: 'easeInQuad'
-                                });
+        actor.ease({
+            opacity: 255,
+            duration: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME / 2,
+            mode: Clutter.AnimationMode.EASE_IN_QUAD
+        });
     }
 
     fadeHalf() {
         let actor = this._activePage;
-        Tweener.addTween(actor, { opacity: 128,
-                                  time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME / (2 * 1000),
-                                  transition: 'easeOutQuad'
-                                });
+        actor.ease({
+            opacity: 128,
+            duration: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME / 2,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD
+        });
     }
 };
 Signals.addSignalMethods(ViewSelector.prototype);
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
index 04046b131..d932c22fb 100644
--- a/js/ui/windowManager.js
+++ b/js/ui/windowManager.js
@@ -414,15 +414,15 @@ var TilePreview = class {
 
         this._showing = true;
         this.actor.show();
-        Tweener.addTween(this.actor,
-                         { x: tileRect.x,
-                           y: tileRect.y,
-                           width: tileRect.width,
-                           height: tileRect.height,
-                           opacity: 255,
-                           time: WINDOW_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad'
-                         });
+        this.actor.ease({
+            x: tileRect.x,
+            y: tileRect.y,
+            width: tileRect.width,
+            height: tileRect.height,
+            opacity: 255,
+            duration: WINDOW_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD
+        });
     }
 
     hide() {
@@ -430,12 +430,12 @@ var TilePreview = class {
             return;
 
         this._showing = false;
-        Tweener.addTween(this.actor,
-                         { opacity: 0,
-                           time: WINDOW_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: this._reset.bind(this)
-                         });
+        this.actor.ease({
+            opacity: 0,
+            duration: WINDOW_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => this._reset()
+        });
     }
 
     _reset() {
@@ -1137,15 +1137,13 @@ var WindowManager = class {
             return;
         let switchData = this._switchData;
         this._switchData = null;
-        Tweener.addTween(switchData.container,
-                         { x: 0,
-                           y: 0,
-                           time: WINDOW_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: this._finishWorkspaceSwitch,
-                           onCompleteScope: this,
-                           onCompleteParams: [switchData],
-                         });
+        switchData.container.ease({
+            x: 0,
+            y: 0,
+            duration: WINDOW_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => this._finishWorkspaceSwitch(switchData)
+        });
     }
 
     _actionSwitchWorkspace(action, direction) {
@@ -1283,17 +1281,17 @@ var WindowManager = class {
         this._minimizing.push(actor);
 
         if (actor.meta_window.is_monitor_sized()) {
-            Tweener.addTween(actor,
-                             { opacity: 0,
-                               time: MINIMIZE_WINDOW_ANIMATION_TIME / 1000,
-                               transition: 'easeOutQuad',
-                               onComplete: this._minimizeWindowDone,
-                               onCompleteScope: this,
-                               onCompleteParams: [shellwm, actor],
-                               onOverwrite: this._minimizeWindowOverwritten,
-                               onOverwriteScope: this,
-                               onOverwriteParams: [shellwm, actor]
-                             });
+            actor.ease({
+                opacity: 0,
+                duration: MINIMIZE_WINDOW_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                onStopped: isFinished => {
+                    if (isFinished)
+                        this._minimizeWindowDone(shellwm, actor);
+                    else
+                        this._minimizeWindowOverwritten(shellwm, actor);
+                }
+            });
         } else {
             let xDest, yDest, xScale, yScale;
             let [success, geom] = actor.meta_window.get_icon_geometry();
@@ -1316,26 +1314,26 @@ var WindowManager = class {
                 yScale = 0;
             }
 
-            Tweener.addTween(actor,
-                             { scale_x: xScale,
-                               scale_y: yScale,
-                               x: xDest,
-                               y: yDest,
-                               time: MINIMIZE_WINDOW_ANIMATION_TIME / 1000,
-                               transition: 'easeInExpo',
-                               onComplete: this._minimizeWindowDone,
-                               onCompleteScope: this,
-                               onCompleteParams: [shellwm, actor],
-                               onOverwrite: this._minimizeWindowOverwritten,
-                               onOverwriteScope: this,
-                               onOverwriteParams: [shellwm, actor]
-                             });
+            actor.ease({
+                scale_x: xScale,
+                scale_y: yScale,
+                x: xDest,
+                y: yDest,
+                duration: MINIMIZE_WINDOW_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_IN_EXPO,
+                onStopped: isFinished => {
+                    if (isFinished)
+                        this._minimizeWindowDone(shellwm, actor);
+                    else
+                        this._minimizeWindowOverwritten(shellwm, actor);
+                }
+            });
         }
     }
 
     _minimizeWindowDone(shellwm, actor) {
         if (this._removeEffect(this._minimizing, actor)) {
-            Tweener.removeTweens(actor);
+            actor.remove_all_transitions();
             actor.set_scale(1.0, 1.0);
             actor.set_opacity(255);
             actor.set_pivot_point(0, 0);
@@ -1364,17 +1362,17 @@ var WindowManager = class {
         if (actor.meta_window.is_monitor_sized()) {
             actor.opacity = 0;
             actor.set_scale(1.0, 1.0);
-            Tweener.addTween(actor,
-                             { opacity: 255,
-                               time: MINIMIZE_WINDOW_ANIMATION_TIME / 1000,
-                               transition: 'easeOutQuad',
-                               onComplete: this._unminimizeWindowDone,
-                               onCompleteScope: this,
-                               onCompleteParams: [shellwm, actor],
-                               onOverwrite: this._unminimizeWindowOverwritten,
-                               onOverwriteScope: this,
-                               onOverwriteParams: [shellwm, actor]
-                             });
+            actor.ease({
+                opacity: 255,
+                duration: MINIMIZE_WINDOW_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                onStopped: isFinished => {
+                    if (isFinished)
+                        this._unminimizeWindowDone(shellwm, actor);
+                    else
+                        this._unminimizeWindowOverwritten(shellwm, actor);
+                }
+            });
         } else {
             let [success, geom] = actor.meta_window.get_icon_geometry();
             if (success) {
@@ -1398,26 +1396,26 @@ var WindowManager = class {
             let [xDest, yDest] = [rect.x, rect.y];
 
             actor.show();
-            Tweener.addTween(actor,
-                             { scale_x: 1.0,
-                               scale_y: 1.0,
-                               x: xDest,
-                               y: yDest,
-                               time: MINIMIZE_WINDOW_ANIMATION_TIME / 1000,
-                               transition: 'easeInExpo',
-                               onComplete: this._unminimizeWindowDone,
-                               onCompleteScope: this,
-                               onCompleteParams: [shellwm, actor],
-                               onOverwrite: this._unminimizeWindowOverwritten,
-                               onOverwriteScope: this,
-                               onOverwriteParams: [shellwm, actor]
-                             });
+            actor.ease({
+                scale_x: 1,
+                scale_y: 1,
+                x: xDest,
+                y: yDest,
+                duration: MINIMIZE_WINDOW_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_IN_EXPO,
+                onStopped: isFinished => {
+                    if (isFinished)
+                        this._unminimizeWindowDone(shellwm, actor);
+                    else
+                        this._unminimizeWindowOverwritten(shellwm, actor);
+                }
+            });
         }
     }
 
     _unminimizeWindowDone(shellwm, actor) {
         if (this._removeEffect(this._unminimizing, actor)) {
-            Tweener.removeTweens(actor);
+            actor.remove_all_transitions();
             actor.set_scale(1.0, 1.0);
             actor.set_opacity(255);
             actor.set_pivot_point(0, 0);
@@ -1483,15 +1481,15 @@ var WindowManager = class {
         this._resizing.push(actor);
 
         // Now scale and fade out the clone
-        Tweener.addTween(actorClone,
-                         { x: targetRect.x,
-                           y: targetRect.y,
-                           scale_x: scaleX,
-                           scale_y: scaleY,
-                           opacity: 0,
-                           time: WINDOW_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad'
-                         });
+        actorClone.ease({
+            x: targetRect.x,
+            y: targetRect.y,
+            scale_x: scaleX,
+            scale_y: scaleY,
+            opacity: 0,
+            duration: WINDOW_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD
+        });
 
         actor.translation_x = -targetRect.x + sourceRect.x;
         actor.translation_y = -targetRect.y + sourceRect.y;
@@ -1501,20 +1499,20 @@ var WindowManager = class {
         actor.scale_y = 1 / scaleY;
 
         // Scale it to its actual new size
-        Tweener.addTween(actor,
-                         { scale_x: 1.0,
-                           scale_y: 1.0,
-                           translation_x: 0,
-                           translation_y: 0,
-                           time: WINDOW_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: this._sizeChangeWindowDone,
-                           onCompleteScope: this,
-                           onCompleteParams: [shellwm, actor],
-                           onOverwrite: this._sizeChangeWindowOverwritten,
-                           onOverwriteScope: this,
-                           onOverwriteParams: [shellwm, actor]
-                         });
+        actor.ease({
+            scale_x: 1,
+            scale_y: 1,
+            translation_x: 0,
+            translation_y: 0,
+            duration: WINDOW_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onStopped: isFinished => {
+                if (isFinished)
+                    this._sizeChangeWindowDone(shellwm, actor);
+                else
+                    this._sizeChangeWindowOverwritten(shellwm, actor);
+            }
+        });
 
         // Now unfreeze actor updates, to get it to the new size.
         // It's important that we don't wait until the animation is completed to
@@ -1534,7 +1532,7 @@ var WindowManager = class {
 
     _sizeChangeWindowDone(shellwm, actor) {
         if (this._removeEffect(this._resizing, actor)) {
-            Tweener.removeTweens(actor);
+            actor.remove_all_transitions();
             actor.scale_x = 1.0;
             actor.scale_y = 1.0;
             actor.translation_x = 0;
@@ -1652,19 +1650,19 @@ var WindowManager = class {
             actor.show();
             this._mapping.push(actor);
 
-            Tweener.addTween(actor,
-                             { opacity: 255,
-                               scale_x: 1,
-                               scale_y: 1,
-                               time: SHOW_WINDOW_ANIMATION_TIME / 1000,
-                               transition: 'easeOutExpo',
-                               onComplete: this._mapWindowDone,
-                               onCompleteScope: this,
-                               onCompleteParams: [shellwm, actor],
-                               onOverwrite: this._mapWindowOverwrite,
-                               onOverwriteScope: this,
-                               onOverwriteParams: [shellwm, actor]
-                             });
+            actor.ease({
+                opacity: 255,
+                scale_x: 1,
+                scale_y: 1,
+                duration: SHOW_WINDOW_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_EXPO,
+                onStopped: isFinished => {
+                    if (isFinished)
+                        this._mapWindowDone(shellwm, actor);
+                    else
+                        this._mapWindowOverwrite(shellwm, actor);
+                }
+            });
             break;
         case Meta.WindowType.MODAL_DIALOG:
         case Meta.WindowType.DIALOG:
@@ -1674,19 +1672,19 @@ var WindowManager = class {
             actor.show();
             this._mapping.push(actor);
 
-            Tweener.addTween(actor,
-                             { opacity: 255,
-                               scale_x: 1,
-                               scale_y: 1,
-                               time: DIALOG_SHOW_WINDOW_ANIMATION_TIME / 1000,
-                               transition: 'easeOutQuad',
-                               onComplete: this._mapWindowDone,
-                               onCompleteScope: this,
-                               onCompleteParams: [shellwm, actor],
-                               onOverwrite: this._mapWindowOverwrite,
-                               onOverwriteScope: this,
-                               onOverwriteParams: [shellwm, actor]
-                             });
+            actor.ease({
+                opacity: 255,
+                scale_x: 1,
+                scale_y: 1,
+                duration: DIALOG_SHOW_WINDOW_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                onStopped: isFinished => {
+                    if (isFinished)
+                        this._mapWindowDone(shellwm, actor);
+                    else
+                        this._mapWindowOverwrite(shellwm, actor);
+                }
+            });
             break;
         default:
             shellwm.completed_map(actor);
@@ -1696,7 +1694,7 @@ var WindowManager = class {
 
     _mapWindowDone(shellwm, actor) {
         if (this._removeEffect(this._mapping, actor)) {
-            Tweener.removeTweens(actor);
+            actor.remove_all_transitions();
             actor.opacity = 255;
             actor.set_pivot_point(0, 0);
             actor.scale_y = 1;
@@ -1740,19 +1738,14 @@ var WindowManager = class {
             actor.set_pivot_point(0.5, 0.5);
             this._destroying.push(actor);
 
-            Tweener.addTween(actor,
-                             { opacity: 0,
-                               scale_x: 0.8,
-                               scale_y: 0.8,
-                               time: DESTROY_WINDOW_ANIMATION_TIME / 1000,
-                               transition: 'easeOutQuad',
-                               onComplete: this._destroyWindowDone,
-                               onCompleteScope: this,
-                               onCompleteParams: [shellwm, actor],
-                               onOverwrite: this._destroyWindowDone,
-                               onOverwriteScope: this,
-                               onOverwriteParams: [shellwm, actor]
-                             });
+            actor.ease({
+                opacity: 0,
+                scale_x: 0.8,
+                scale_y: 0.8,
+                duration: DESTROY_WINDOW_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                onStopped: () => this._destroyWindowDone(shellwm, actor)
+            });
             break;
         case Meta.WindowType.MODAL_DIALOG:
         case Meta.WindowType.DIALOG:
@@ -1762,22 +1755,17 @@ var WindowManager = class {
             if (window.is_attached_dialog()) {
                 let parent = window.get_transient_for();
                 actor._parentDestroyId = parent.connect('unmanaged', () => {
-                    Tweener.removeTweens(actor);
+                    actor.remove_all_transitions();
                     this._destroyWindowDone(shellwm, actor);
                 });
             }
 
-            Tweener.addTween(actor,
-                             { scale_y: 0,
-                               time: DIALOG_DESTROY_WINDOW_ANIMATION_TIME / 1000,
-                               transition: 'easeOutQuad',
-                               onComplete: this._destroyWindowDone,
-                               onCompleteScope: this,
-                               onCompleteParams: [shellwm, actor],
-                               onOverwrite: this._destroyWindowDone,
-                               onOverwriteScope: this,
-                               onOverwriteParams: [shellwm, actor]
-                             });
+            actor.ease({
+                scale_y: 0,
+                duration: DIALOG_DESTROY_WINDOW_ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+                onStopped: () => this._destroyWindowDone(shellwm, actor)
+            });
             break;
         default:
             shellwm.completed_destroy(actor);
@@ -1982,7 +1970,6 @@ var WindowManager = class {
                 global.workspace_manager.get_active_workspace())
                 w.window.hide();
         }
-        Tweener.removeTweens(switchData.container);
         switchData.container.destroy();
         switchData.movingWindowBin.destroy();
 
@@ -2015,15 +2002,13 @@ var WindowManager = class {
         xDest = -xDest;
         yDest = -yDest;
 
-        Tweener.addTween(this._switchData.container,
-                         { x: xDest,
-                           y: yDest,
-                           time: WINDOW_ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: this._switchWorkspaceDone,
-                           onCompleteScope: this,
-                           onCompleteParams: [shellwm]
-                         });
+        this._switchData.container.ease({
+            x: xDest,
+            y: yDest,
+            duration: WINDOW_ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => this._switchWorkspaceDone(shellwm)
+        });
     }
 
     _switchWorkspaceDone(shellwm) {
diff --git a/js/ui/workspace.js b/js/ui/workspace.js
index cfa88c4e1..7df297e7d 100644
--- a/js/ui/workspace.js
+++ b/js/ui/workspace.js
@@ -8,14 +8,13 @@ const Signals = imports.signals;
 const DND = imports.ui.dnd;
 const Main = imports.ui.main;
 const Overview = imports.ui.overview;
-const Tweener = imports.ui.tweener;
 
 var WINDOW_DND_SIZE = 256;
 
 var WINDOW_CLONE_MAXIMUM_SCALE = 1.0;
 
 var WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 750;
-var WINDOW_OVERLAY_FADE_TIME = 0.1;
+var WINDOW_OVERLAY_FADE_TIME = 100;
 
 var WINDOW_REPOSITIONING_DELAY = 750;
 
@@ -541,9 +540,9 @@ var WindowOverlay = class {
         let title = this.title;
         let border = this.border;
 
-        Tweener.removeTweens(button);
-        Tweener.removeTweens(border);
-        Tweener.removeTweens(title);
+        button.remove_all_transitions();
+        border.remove_all_transitions();
+        title.remove_all_transitions();
 
         let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot;
 
@@ -610,16 +609,16 @@ var WindowOverlay = class {
     }
 
     _animateOverlayActor(actor, x, y, width, height) {
-        let params = { x: x,
-                       y: y,
-                       width: width,
-                       time: Overview.ANIMATION_TIME / 1000,
-                       transition: 'easeOutQuad' };
+        let params = {
+            x, y, width,
+            duration: Overview.ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD
+        };
 
         if (height !== undefined)
             params.height = height;
 
-        Tweener.addTween(actor, params);
+        actor.ease(params);
     }
 
     _windowCanClose() {
@@ -648,20 +647,22 @@ var WindowOverlay = class {
         toAnimate.forEach(a => {
             a.show();
             a.opacity = 0;
-            Tweener.addTween(a,
-                             { opacity: 255,
-                               time: WINDOW_OVERLAY_FADE_TIME / 1000,
-                               transition: 'easeOutQuad' });
+            a.ease({
+                opacity: 255,
+                duration: WINDOW_OVERLAY_FADE_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD
+            });
         });
     }
 
     _animateInvisible() {
         [this.closeButton, this.border, this.title].forEach(a => {
             a.opacity = 255;
-            Tweener.addTween(a,
-                             { opacity: 0,
-                               time: WINDOW_OVERLAY_FADE_TIME / 1000,
-                               transition: 'easeInQuad' });
+            a.ease({
+                opacity: 0,
+                duration: WINDOW_OVERLAY_FADE_TIME,
+                mode: Clutter.AnimationMode.EASE_IN_QUAD
+            });
         });
     }
 
@@ -1344,17 +1345,17 @@ var Workspace = class {
                         clone.y = y;
                     }
 
-                    Tweener.addTween(clone,
-                                     { opacity: 255,
-                                       time: Overview.ANIMATION_TIME / 1000,
-                                       transition: 'easeInQuad'
-                                     });
+                    clone.ease({
+                        opacity: 255,
+                        mode: Clutter.AnimationMode.EASE_IN_QUAD,
+                        duration: Overview.ANIMATION_TIME
+                    });
                 }
 
                 this._animateClone(clone, clone.overlay, x, y, scale);
             } else {
                 // cancel any active tweens (otherwise they might override our changes)
-                Tweener.removeTweens(clone);
+                clone.remove_all_transitions();
                 clone.set_position(x, y);
                 clone.set_scale(scale, scale);
                 clone.set_opacity(255);
@@ -1384,18 +1385,16 @@ var Workspace = class {
     }
 
     _animateClone(clone, overlay, x, y, scale) {
-        Tweener.addTween(clone,
-                         { x: x,
-                           y: y,
-                           scale_x: scale,
-                           scale_y: scale,
-                           time: Overview.ANIMATION_TIME / 1000,
-                           transition: 'easeOutQuad',
-                           onComplete: () => {
-                               this._showWindowOverlay(clone, overlay);
-                           }
-                         });
-
+        clone.ease({
+            x, y,
+            scale_x: scale,
+            scale_y: scale,
+            duration: Overview.ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => {
+                this._showWindowOverlay(clone, overlay);
+            }
+        });
         clone.overlay.relayout(true);
     }
 
@@ -1629,10 +1628,8 @@ var Workspace = class {
         if (this._windows.length == 0)
             return;
 
-        for (let i = 0; i < this._windows.length; i++) {
-            let clone = this._windows[i];
-            Tweener.removeTweens(clone);
-        }
+        for (let i = 0; i < this._windows.length; i++)
+            this._windows[i].remove_all_transitions();
 
         if (this._repositionWindowsId > 0) {
             Mainloop.source_remove(this._repositionWindowsId);
@@ -1681,7 +1678,7 @@ var Workspace = class {
         }
     }
 
-    _fadeWindow(index, time, opacity) {
+    _fadeWindow(index, duration, opacity) {
         let clone = this._windows[index];
         let overlay = this._windowOverlays[index];
 
@@ -1694,11 +1691,11 @@ var Workspace = class {
             clone.scale_y = 1;
             clone.x = origX;
             clone.y = origY;
-            Tweener.addTween(clone,
-                             { time: time / 1000,
-                               opacity: opacity,
-                               transition: 'easeOutQuad'
-                             });
+            clone.ease({
+                opacity,
+                duration,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD
+            });
         } else {
             // The window is hidden
             clone.opacity = 0;
@@ -1716,10 +1713,8 @@ var Workspace = class {
 
         this.leavingOverview = true;
 
-        for (let i = 0; i < this._windows.length; i++) {
-            let clone = this._windows[i];
-            Tweener.removeTweens(clone);
-        }
+        for (let i = 0; i < this._windows.length; i++)
+            this._windows[i].remove_all_transitions();
 
         if (this._repositionWindowsId > 0) {
             Mainloop.source_remove(this._repositionWindowsId);
@@ -1744,24 +1739,24 @@ var Workspace = class {
 
         if (clone.metaWindow.showing_on_its_workspace()) {
             let [origX, origY] = clone.getOriginalPosition();
-            Tweener.addTween(clone,
-                             { x: origX,
-                               y: origY,
-                               scale_x: 1.0,
-                               scale_y: 1.0,
-                               time: Overview.ANIMATION_TIME / 1000,
-                               opacity: 255,
-                               transition: 'easeOutQuad'
-                             });
+            clone.ease({
+                x: origX,
+                y: origY,
+                scale_x: 1,
+                scale_y: 1,
+                opacity: 255,
+                duration: Overview.ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD
+            });
         } else {
             // The window is hidden, make it shrink and fade it out
-            Tweener.addTween(clone,
-                             { scale_x: 0,
-                               scale_y: 0,
-                               opacity: 0,
-                               time: Overview.ANIMATION_TIME / 1000,
-                               transition: 'easeOutQuad'
-                             });
+            clone.ease({
+                scale_x: 0,
+                scale_y: 0,
+                opacity: 0,
+                duration: Overview.ANIMATION_TIME,
+                mode: Clutter.AnimationMode.EASE_OUT_QUAD
+            });
         }
     }
 
@@ -1769,12 +1764,11 @@ var Workspace = class {
         this.actor.destroy();
     }
 
-    _onDestroy(actor) {
+    _onDestroy() {
         if (this._overviewHiddenId) {
             Main.overview.disconnect(this._overviewHiddenId);
             this._overviewHiddenId = 0;
         }
-        Tweener.removeTweens(actor);
 
         if (this.metaWorkspace) {
             this.metaWorkspace.disconnect(this._windowAddedId);
diff --git a/js/ui/workspaceSwitcherPopup.js b/js/ui/workspaceSwitcherPopup.js
index 8375557f3..d5519fa8b 100644
--- a/js/ui/workspaceSwitcherPopup.js
+++ b/js/ui/workspaceSwitcherPopup.js
@@ -5,7 +5,6 @@ const { Clutter, GLib, GObject, Meta, St } = imports.gi;
 const Mainloop = imports.mainloop;
 
 const Main = imports.ui.main;
-const Tweener = imports.ui.tweener;
 
 var ANIMATION_TIME = 100;
 var DISPLAY_TIMEOUT = 600;
@@ -182,10 +181,11 @@ class WorkspaceSwitcherPopup extends St.Widget {
     }
 
     _show() {
-        Tweener.addTween(this._container, { opacity: 255,
-                                            time: ANIMATION_TIME / 1000,
-                                            transition: 'easeOutQuad'
-                                           });
+        this._container.ease({
+            opacity: 255,
+            duration: ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD
+        });
         this.show();
     }
 
@@ -204,11 +204,12 @@ class WorkspaceSwitcherPopup extends St.Widget {
     _onTimeout() {
         Mainloop.source_remove(this._timeoutId);
         this._timeoutId = 0;
-        Tweener.addTween(this._container, { opacity: 0.0,
-                                            time: ANIMATION_TIME / 1000,
-                                            transition: 'easeOutQuad',
-                                            onComplete: () => this.destroy()
-                                           });
+        this._container.ease({
+            opacity: 0.0,
+            duration: ANIMATION_TIME,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+            onComplete: () => this.destroy()
+        });
         return GLib.SOURCE_REMOVE;
     }
 
diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js
index 417b8fcee..5acc3e438 100644
--- a/js/ui/workspacesView.js
+++ b/js/ui/workspacesView.js
@@ -188,7 +188,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
         for (let w = 0; w < this._workspaces.length; w++) {
             let workspace = this._workspaces[w];
 
-            Tweener.removeTweens(workspace.actor);
+            workspace.actor.remove_all_transitions();
 
             let params = {};
             if (workspaceManager.layout_rows == -1)
@@ -199,21 +199,21 @@ var WorkspacesView = class extends WorkspacesViewBase {
                 params.x = (w - active) * this._fullGeometry.width;
 
             if (showAnimation) {
-                let tweenParams = Object.assign(params, {
-                    time: WORKSPACE_SWITCH_TIME / 1000,
-                    transition: 'easeOutQuad'
+                let easeParams = Object.assign(params, {
+                    duration: WORKSPACE_SWITCH_TIME,
+                    mode: Clutter.AnimationMode.EASE_OUT_QUAD
                 });
                 // we have to call _updateVisibility() once before the
                 // animation and once afterwards - it does not really
                 // matter which tween we use, so we pick the first one ...
                 if (w == 0) {
                     this._updateVisibility();
-                    tweenParams.onComplete = () => {
+                    easeParams.onComplete = () => {
                         this._animating = false;
                         this._updateVisibility();
                     };
                 }
-                Tweener.addTween(workspace.actor, tweenParams);
+                workspace.actor.ease(easeParams);
             } else {
                 workspace.actor.set(params);
                 if (w == 0)
diff --git a/src/gnome-shell-extension-tool.in b/src/gnome-shell-extension-tool.in
index f6c37629c..6843e8757 100755
--- a/src/gnome-shell-extension-tool.in
+++ b/src/gnome-shell-extension-tool.in
@@ -23,7 +23,6 @@ SAMPLE_EXTENSION_FILES = {
     "extension.js": """
 const St = imports.gi.St;
 const Main = imports.ui.main;
-const Tweener = imports.ui.tweener;
 
 let text, button;
 
@@ -45,11 +44,12 @@ function _showHello() {
     text.set_position(monitor.x + Math.floor(monitor.width / 2 - text.width / 2),
                       monitor.y + Math.floor(monitor.height / 2 - text.height / 2));
 
-    Tweener.addTween(text,
-                     { opacity: 0,
-                       time: 2,
-                       transition: 'easeOutQuad',
-                       onComplete: _hideHello });
+    text.ease({
+        opacity: 0,
+        duration: 2000,
+        mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+        onComplete: () => _hideHello()
+    });
 }
 
 function init() {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]