[gnome-shell/wip/fmuellner/es6-classes: 7/9] cleanup: Port GObject classes to JS6 classes



commit e68dfed1f7f0e172e4858407a4ddf0373f068d2c
Author: Florian Müllner <fmuellner gnome org>
Date:   Tue Oct 31 02:23:39 2017 +0100

    cleanup: Port GObject classes to JS6 classes
    
    GJS added API for defining GObject classes with ES6 class syntax
    last cycle, use it to port the remaining Lang.Class classes to
    the new syntax.
    
    https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/361

 js/extensionPrefs/main.js               |  29 ++---
 js/gdm/loginDialog.js                   |  95 +++++++-------
 js/misc/inputMethod.js                  |  54 ++++----
 js/misc/systemActions.js                |  71 +++++-----
 js/misc/util.js                         |  20 ++-
 js/portalHelper/main.js                 |  69 +++++-----
 js/ui/altTab.js                         | 222 +++++++++++++++-----------------
 js/ui/appDisplay.js                     |  27 ++--
 js/ui/boxpointer.js                     |  64 +++++----
 js/ui/closeDialog.js                    |  33 +++--
 js/ui/components/telepathyClient.js     |  33 +++--
 js/ui/dash.js                           |  86 ++++++-------
 js/ui/dateMenu.js                       |  65 ++++------
 js/ui/dialog.js                         |  57 ++++----
 js/ui/edgeDragAction.js                 |  18 ++-
 js/ui/iconGrid.js                       | 144 ++++++++++-----------
 js/ui/inhibitShortcutsDialog.js         |  27 ++--
 js/ui/kbdA11yDialog.js                  |  11 +-
 js/ui/keyboard.js                       |  19 ++-
 js/ui/layout.js                         | 139 ++++++++++----------
 js/ui/lightbox.js                       |  20 ++-
 js/ui/lookingGlass.js                   |  31 ++---
 js/ui/messageList.js                    |  41 +++---
 js/ui/messageTray.js                    |  27 ++--
 js/ui/osdWindow.js                      |  14 +-
 js/ui/overviewControls.js               |  53 ++++----
 js/ui/padOsd.js                         |  65 +++++-----
 js/ui/panel.js                          | 134 +++++++++----------
 js/ui/panelMenu.js                      |  46 +++----
 js/ui/screenShield.js                   |  22 ++--
 js/ui/search.js                         |  28 ++--
 js/ui/status/accessibility.js           |  22 ++--
 js/ui/status/keyboard.js                |  61 ++++-----
 js/ui/switchMonitor.js                  |  35 +++--
 js/ui/switcherPopup.js                  | 109 ++++++++--------
 js/ui/userWidget.js                     |  19 ++-
 js/ui/viewSelector.js                   |  25 ++--
 js/ui/windowManager.js                  |  33 ++---
 js/ui/workspace.js                      |  28 ++--
 js/ui/workspaceSwitcherPopup.js         |  36 +++---
 js/ui/workspaceThumbnail.js             |  90 +++++++------
 js/ui/workspacesView.js                 |   9 +-
 tests/interactive/scroll-view-sizing.js |  40 +++---
 43 files changed, 1036 insertions(+), 1235 deletions(-)
---
diff --git a/js/extensionPrefs/main.js b/js/extensionPrefs/main.js
index e6b1a6eb7..c3a27085a 100644
--- a/js/extensionPrefs/main.js
+++ b/js/extensionPrefs/main.js
@@ -1,4 +1,3 @@
-const Lang = imports.lang;
 const Gettext = imports.gettext;
 const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
@@ -240,24 +239,20 @@ var Application = class {
     }
 };
 
-var DescriptionLabel = new Lang.Class({
-    Name: 'DescriptionLabel',
-    Extends: Gtk.Label,
-
+var DescriptionLabel = GObject.registerClass(
+class DescriptionLabel extends Gtk.Label {
     vfunc_get_preferred_height_for_width(width) {
         // Hack: Request the maximum height allowed by the line limit
         if (this.lines > 0)
-            return this.parent(0);
-        return this.parent(width);
+            return super.vfunc_get_preferred_height_for_width(0);
+        return super.vfunc_get_preferred_height_for_width(width);
     }
 });
 
-var ExtensionRow = new Lang.Class({
-    Name: 'ExtensionRow',
-    Extends: Gtk.ListBoxRow,
-
+var ExtensionRow = GObject.registerClass(
+class ExtensionRow extends Gtk.ListBoxRow {
     _init(uuid) {
-        this.parent();
+        super._init();
 
         this.uuid = uuid;
 
@@ -275,7 +270,7 @@ var ExtensionRow = new Lang.Class({
             });
 
         this._buildUI();
-    },
+    }
 
     _buildUI() {
         let extension = ExtensionUtils.extensions[this.uuid];
@@ -322,7 +317,7 @@ var ExtensionRow = new Lang.Class({
         });
         this._switch.connect('state-set', () => true);
         hbox.add(this._switch);
-    },
+    }
 
     _canEnable() {
         let extension = ExtensionUtils.extensions[this.uuid];
@@ -330,12 +325,12 @@ var ExtensionRow = new Lang.Class({
 
         return !this._settings.get_boolean('disable-user-extensions') &&
                !(checkVersion && ExtensionUtils.isOutOfDate(extension));
-    },
+    }
 
     _isEnabled() {
         let extensions = this._settings.get_strv('enabled-extensions');
         return extensions.indexOf(this.uuid) != -1;
-    },
+    }
 
     _enable() {
         let extensions = this._settings.get_strv('enabled-extensions');
@@ -344,7 +339,7 @@ var ExtensionRow = new Lang.Class({
 
         extensions.push(this.uuid);
         this._settings.set_strv('enabled-extensions', extensions);
-    },
+    }
 
     _disable() {
         let extensions = this._settings.get_strv('enabled-extensions');
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
index 252caa24d..a22f55e59 100644
--- a/js/gdm/loginDialog.js
+++ b/js/gdm/loginDialog.js
@@ -24,7 +24,6 @@ const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
 const Meta = imports.gi.Meta;
 const Pango = imports.gi.Pango;
 const Shell = imports.gi.Shell;
@@ -400,13 +399,11 @@ var SessionMenuButton = class {
 };
 Signals.addSignalMethods(SessionMenuButton.prototype);
 
-var LoginDialog = new Lang.Class({
-    Name: 'LoginDialog',
-    Extends: St.Widget,
+var LoginDialog = GObject.registerClass({
     Signals: { 'failed': {} },
-
+}, class LoginDialog extends St.Widget {
     _init(parentActor) {
-        this.parent({ style_class: 'login-dialog',
+        super._init({ style_class: 'login-dialog',
                       visible: false });
 
         this.get_accessible().set_role(Atk.Role.WINDOW);
@@ -524,7 +521,7 @@ var LoginDialog = new Lang.Class({
         // focus later
         this._startupCompleteId = Main.layoutManager.connect('startup-complete',
                                                              this._updateDisableUserList.bind(this));
-    },
+    }
 
     _getBannerAllocation(dialogBox) {
         let actorBox = new Clutter.ActorBox();
@@ -538,7 +535,7 @@ var LoginDialog = new Lang.Class({
         actorBox.y2 = actorBox.y1 + natHeight;
 
         return actorBox;
-    },
+    }
 
     _getLogoBinAllocation(dialogBox) {
         let actorBox = new Clutter.ActorBox();
@@ -552,7 +549,7 @@ var LoginDialog = new Lang.Class({
         actorBox.y2 = actorBox.y1 + natHeight;
 
         return actorBox;
-    },
+    }
 
     _getCenterActorAllocation(dialogBox, actor) {
         let actorBox = new Clutter.ActorBox();
@@ -570,7 +567,7 @@ var LoginDialog = new Lang.Class({
         actorBox.y2 = actorBox.y1 + natHeight;
 
         return actorBox;
-    },
+    }
 
     vfunc_allocate(dialogBox, flags) {
         this.set_allocation(dialogBox, flags);
@@ -713,7 +710,7 @@ var LoginDialog = new Lang.Class({
 
         if (logoAllocation)
             this._logoBin.allocate(logoAllocation, flags);
-    },
+    }
 
     _ensureUserListLoaded() {
         if (!this._userManager.is_loaded) {
@@ -729,7 +726,7 @@ var LoginDialog = new Lang.Class({
             let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, this._loadUserList.bind(this));
             GLib.Source.set_name_by_id(id, '[gnome-shell] _loadUserList');
         }
-    },
+    }
 
     _updateDisableUserList() {
         let disableUserList = this._settings.get_boolean(GdmUtil.DISABLE_USER_LIST_KEY);
@@ -744,7 +741,7 @@ var LoginDialog = new Lang.Class({
             if (this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
                 this._authPrompt.reset();
         }
-    },
+    }
 
     _updateCancelButton() {
         let cancelVisible;
@@ -757,7 +754,7 @@ var LoginDialog = new Lang.Class({
             cancelVisible = true;
 
         this._authPrompt.cancelButton.visible = cancelVisible;
-    },
+    }
 
     _updateBanner() {
         let enabled = this._settings.get_boolean(GdmUtil.BANNER_MESSAGE_KEY);
@@ -769,7 +766,7 @@ var LoginDialog = new Lang.Class({
         } else {
             this._bannerLabel.hide();
         }
-    },
+    }
 
     _fadeInBannerView() {
         this._bannerView.show();
@@ -777,13 +774,13 @@ var LoginDialog = new Lang.Class({
                          { opacity: 255,
                            time: _FADE_ANIMATION_TIME,
                            transition: 'easeOutQuad' });
-    },
+    }
 
     _hideBannerView() {
         Tweener.removeTweens(this._bannerView);
         this._bannerView.opacity = 0;
         this._bannerView.hide();
-    },
+    }
 
     _updateLogoTexture(cache, file) {
         if (this._logoFile && !this._logoFile.equal(file))
@@ -796,14 +793,14 @@ var LoginDialog = new Lang.Class({
                                                                        -1, _LOGO_ICON_HEIGHT,
                                                                        scaleFactor));
         }
-    },
+    }
 
     _updateLogo() {
         let path = this._settings.get_string(GdmUtil.LOGO_KEY);
 
         this._logoFile = path ? Gio.file_new_for_path(path) : null;
         this._updateLogoTexture(this._textureCache, this._logoFile);
-    },
+    }
 
     _onPrompted() {
         if (this._shouldShowSessionMenuButton()) {
@@ -813,7 +810,7 @@ var LoginDialog = new Lang.Class({
             this._sessionMenuButton.updateSensitivity(false);
         }
         this._showPrompt();
-    },
+    }
 
     _resetGreeterProxy() {
         if (GLib.getenv('GDM_GREETER_TEST') != '1') {
@@ -829,7 +826,7 @@ var LoginDialog = new Lang.Class({
             this._timedLoginRequestedId = this._greeter.connect('timed-login-requested',
                                                                 this._onTimedLoginRequested.bind(this));
         }
-    },
+    }
 
     _onReset(authPrompt, beginRequest) {
         this._resetGreeterProxy();
@@ -850,11 +847,11 @@ var LoginDialog = new Lang.Class({
         } else {
             this._hideUserListAndBeginVerification();
         }
-    },
+    }
 
     _onDefaultSessionChanged(client, sessionId) {
         this._sessionMenuButton.setActiveSession(sessionId);
-    },
+    }
 
     _shouldShowSessionMenuButton() {
         if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFYING &&
@@ -865,7 +862,7 @@ var LoginDialog = new Lang.Class({
           return false;
 
         return true;
-    },
+    }
 
     _showPrompt() {
         if (this._authPrompt.actor.visible)
@@ -877,7 +874,7 @@ var LoginDialog = new Lang.Class({
                            time: _FADE_ANIMATION_TIME,
                            transition: 'easeOutQuad' });
         this._fadeInBannerView();
-    },
+    }
 
     _showRealmLoginHint(realmManager, hint) {
         if (!hint)
@@ -890,7 +887,7 @@ var LoginDialog = new Lang.Class({
         // Translators: this message is shown below the username entry field
         // to clue the user in on how to login to the local network realm
         this._authPrompt.setMessage(_("(e.g., user or %s)").format(hint), GdmUtil.MessageType.HINT);
-    },
+    }
 
     _askForUsernameAndBeginVerification() {
         this._authPrompt.setPasswordChar('');
@@ -917,7 +914,7 @@ var LoginDialog = new Lang.Class({
         this._sessionMenuButton.updateSensitivity(false);
         this._authPrompt.updateSensitivity(true);
         this._showPrompt();
-    },
+    }
 
     _loginScreenSessionActivated() {
         if (this.opacity == 255 && this._authPrompt.verificationStatus == 
AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
@@ -941,7 +938,7 @@ var LoginDialog = new Lang.Class({
                                    this._authPrompt.reset();
                            },
                            onCompleteScope: this });
-    },
+    }
 
     _gotGreeterSessionProxy(proxy) {
         this._greeterSessionProxy = proxy;
@@ -950,7 +947,7 @@ var LoginDialog = new Lang.Class({
                 if (proxy.Active)
                     this._loginScreenSessionActivated();
             });
-    },
+    }
 
     _startSession(serviceName) {
         Tweener.addTween(this,
@@ -970,11 +967,11 @@ var LoginDialog = new Lang.Class({
                                this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
                            },
                            onCompleteScope: this });
-    },
+    }
 
     _onSessionOpened(client, serviceName) {
         this._authPrompt.finish(() => { this._startSession(serviceName); });
-    },
+    }
 
     _waitForItemForUser(userName) {
         let item = this._userList.getItemFromUserName(userName);
@@ -994,7 +991,7 @@ var LoginDialog = new Lang.Class({
         hold.connect('release', () => { this._userList.disconnect(signalId); });
 
         return hold;
-    },
+    }
 
     _blockTimedLoginUntilIdle() {
         let hold = new Batch.Hold();
@@ -1007,7 +1004,7 @@ var LoginDialog = new Lang.Class({
             });
         GLib.Source.set_name_by_id(this._timedLoginIdleTimeOutId, '[gnome-shell] 
this._timedLoginIdleTimeOutId');
         return hold;
-    },
+    }
 
     _startTimedLogin(userName, delay) {
         let firstRun = true;
@@ -1080,7 +1077,7 @@ var LoginDialog = new Lang.Class({
         this._timedLoginBatch = new Batch.ConsecutiveBatch(this, tasks);
 
         return this._timedLoginBatch.run();
-    },
+    }
 
     _onTimedLoginRequested(client, userName, seconds) {
         if (this._timedLoginBatch)
@@ -1097,28 +1094,28 @@ var LoginDialog = new Lang.Class({
 
            return Clutter.EVENT_PROPAGATE;
         });
-    },
+    }
 
     _setUserListExpanded(expanded) {
         this._userList.updateStyle(expanded);
         this._userSelectionBox.visible = expanded;
-    },
+    }
 
     _hideUserList() {
         this._setUserListExpanded(false);
         if (this._userSelectionBox.visible)
             GdmUtil.cloneAndFadeOutActor(this._userSelectionBox);
-    },
+    }
 
     _hideUserListAskForUsernameAndBeginVerification() {
         this._hideUserList();
         this._askForUsernameAndBeginVerification();
-    },
+    }
 
     _hideUserListAndBeginVerification() {
         this._hideUserList();
         this._authPrompt.begin();
-    },
+    }
 
     _showUserList() {
         this._ensureUserListLoaded();
@@ -1128,7 +1125,7 @@ var LoginDialog = new Lang.Class({
         this._setUserListExpanded(true);
         this._notListedButton.show();
         this._userList.actor.grab_key_focus();
-    },
+    }
 
     _beginVerificationForItem(item) {
         this._authPrompt.setUser(item.user);
@@ -1139,7 +1136,7 @@ var LoginDialog = new Lang.Class({
         this._authPrompt.begin({ userName: userName,
                                  hold: hold });
         return hold;
-    },
+    }
 
     _onUserListActivated(activatedItem) {
         this._user = activatedItem.user;
@@ -1149,7 +1146,7 @@ var LoginDialog = new Lang.Class({
         let batch = new Batch.ConcurrentBatch(this, [GdmUtil.cloneAndFadeOutActor(this._userSelectionBox),
                                                      this._beginVerificationForItem(activatedItem)]);
         batch.run();
-    },
+    }
 
     _onDestroy() {
         if (this._userManagerLoadedId) {
@@ -1190,7 +1187,7 @@ var LoginDialog = new Lang.Class({
             this._realmManager.release();
             this._realmManager = null;
         }
-    },
+    }
 
     _loadUserList() {
         if (this._userListLoaded)
@@ -1228,7 +1225,7 @@ var LoginDialog = new Lang.Class({
             });
 
         return GLib.SOURCE_REMOVE;
-    },
+    }
 
     open() {
         Main.ctrlAltTabManager.addGroup(this,
@@ -1247,22 +1244,22 @@ var LoginDialog = new Lang.Class({
                            transition: 'easeInQuad' });
 
         return true;
-    },
+    }
 
     close() {
         Main.popModal(this);
         Main.ctrlAltTabManager.removeGroup(this);
-    },
+    }
 
     cancel() {
         this._authPrompt.cancel();
-    },
+    }
 
     addCharacter(unichar) {
         // Don't allow type ahead at the login screen
-    },
+    }
 
     finish(onComplete) {
         this._authPrompt.finish(onComplete);
-    },
+    }
 });
diff --git a/js/misc/inputMethod.js b/js/misc/inputMethod.js
index 98761a63d..4788a6d9e 100644
--- a/js/misc/inputMethod.js
+++ b/js/misc/inputMethod.js
@@ -1,16 +1,14 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 const Clutter = imports.gi.Clutter;
+const GObject = imports.gi.GObject;
 const IBus = imports.gi.IBus;
 const Keyboard = imports.ui.status.keyboard;
-const Lang = imports.lang;
 const Signals = imports.signals;
 
-var InputMethod = new Lang.Class({
-    Name: 'InputMethod',
-    Extends: Clutter.InputMethod,
-
+var InputMethod = GObject.registerClass(
+class InputMethod extends Clutter.InputMethod {
     _init() {
-        this.parent();
+        super._init();
         this._hints = 0;
         this._purpose = 0;
         this._currentFocus = null;
@@ -29,11 +27,11 @@ var InputMethod = new Lang.Class({
 
         if (this._ibus.is_connected())
             this._onConnected();
-    },
+    }
 
     get currentFocus() {
         return this._currentFocus;
-    },
+    }
 
     _updateCapabilities() {
         let caps = 0;
@@ -48,16 +46,16 @@ var InputMethod = new Lang.Class({
 
         if (this._context)
             this._context.set_capabilities(caps);
-    },
+    }
 
     _onSourceChanged() {
         this._currentSource = this._inputSourceManager.currentSource;
-    },
+    }
 
     _onConnected() {
         this._ibus.create_input_context_async ('gnome-shell', -1, null,
                                                this._setContext.bind(this));
-    },
+    }
 
     _setContext(bus, res) {
         this._context = this._ibus.create_input_context_async_finish(res);
@@ -69,7 +67,7 @@ var InputMethod = new Lang.Class({
         this._context.connect('forward-key-event', this._onForwardKeyEvent.bind(this));
 
         this._updateCapabilities();
-    },
+    }
 
     _clear() {
         this._context = null;
@@ -78,20 +76,20 @@ var InputMethod = new Lang.Class({
         this._preeditStr = ''
         this._preeditPos = 0;
         this._preeditVisible = false;
-    },
+    }
 
     _emitRequestSurrounding() {
         if (this._context.needs_surrounding_text())
             this.emit('request-surrounding');
-    },
+    }
 
     _onCommitText(context, text) {
         this.commit(text.get_text());
-    },
+    }
 
     _onDeleteSurroundingText(context) {
         this.delete_surrounding();
-    },
+    }
 
     _onUpdatePreeditText(context, text, pos, visible) {
         if (text == null)
@@ -107,17 +105,17 @@ var InputMethod = new Lang.Class({
         this._preeditStr = preedit;
         this._preeditPos = pos;
         this._preeditVisible = visible;
-    },
+    }
 
     _onShowPreeditText(context) {
         this._preeditVisible = true;
         this.set_preedit_text(this._preeditStr, this._preeditPos);
-    },
+    }
 
     _onHidePreeditText(context) {
         this.set_preedit_text(null, this._preeditPos);
         this._preeditVisible = false;
-    },
+    }
 
     _onForwardKeyEvent(context, keyval, keycode, state) {
         let press = (state & IBus.ModifierType.RELEASE_MASK) == 0;
@@ -131,7 +129,7 @@ var InputMethod = new Lang.Class({
             time = global.display.get_current_time_roundtrip();
 
         this.forward_key(keyval, keycode + 8, state & Clutter.ModifierType.MODIFIER_MASK, time, press);
-    },
+    }
 
     vfunc_focus_in(focus) {
         this._currentFocus = focus;
@@ -140,7 +138,7 @@ var InputMethod = new Lang.Class({
             this._updateCapabilities();
             this._emitRequestSurrounding();
         }
-    },
+    }
 
     vfunc_focus_out() {
         this._currentFocus = null;
@@ -154,7 +152,7 @@ var InputMethod = new Lang.Class({
             this.set_preedit_text(null, 0);
             this._preeditStr = null;
         }
-    },
+    }
 
     vfunc_reset() {
         if (this._context) {
@@ -167,7 +165,7 @@ var InputMethod = new Lang.Class({
             this.set_preedit_text(null, 0);
             this._preeditStr = null;
         }
-    },
+    }
 
     vfunc_set_cursor_location(rect) {
         if (this._context) {
@@ -175,7 +173,7 @@ var InputMethod = new Lang.Class({
                                               rect.get_width(), rect.get_height());
             this._emitRequestSurrounding();
         }
-    },
+    }
 
     vfunc_set_surrounding(text, cursor, anchor) {
         if (!this._context || !text)
@@ -183,7 +181,7 @@ var InputMethod = new Lang.Class({
 
         let ibusText = IBus.Text.new_from_string(text);
         this._context.set_surrounding_text(ibusText, cursor, anchor);
-    },
+    }
 
     vfunc_update_content_hints(hints) {
         let ibusHints = 0;
@@ -203,7 +201,7 @@ var InputMethod = new Lang.Class({
         this._hints = ibusHints;
         if (this._context)
             this._context.set_content_type(this._purpose, this._hints);
-    },
+    }
 
     vfunc_update_content_purpose(purpose) {
         let ibusPurpose = 0;
@@ -229,7 +227,7 @@ var InputMethod = new Lang.Class({
         this._purpose = ibusPurpose;
         if (this._context)
             this._context.set_content_type(this._purpose, this._hints);
-    },
+    }
 
     vfunc_filter_key_event(event) {
         if (!this._context)
@@ -256,5 +254,5 @@ var InputMethod = new Lang.Class({
                                                   }
                                               });
         return true;
-    },
+    }
 });
diff --git a/js/misc/systemActions.js b/js/misc/systemActions.js
index 3c1713745..8b2175e04 100644
--- a/js/misc/systemActions.js
+++ b/js/misc/systemActions.js
@@ -3,7 +3,6 @@ const Clutter = imports.gi.Clutter;
 const Gdm = imports.gi.Gdm;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
-const Lang = imports.lang;
 const Meta = imports.gi.Meta;
 const GObject = imports.gi.GObject;
 
@@ -44,9 +43,7 @@ function getDefault() {
     return _singleton;
 }
 
-const SystemActions = new Lang.Class({
-    Name: 'SystemActions',
-    Extends: GObject.Object,
+const SystemActions = GObject.registerClass({
     Properties: {
         'can-power-off': GObject.ParamSpec.boolean('can-power-off',
                                                    'can-power-off',
@@ -83,10 +80,10 @@ const SystemActions = new Lang.Class({
                                                           'orientation-lock-icon',
                                                           GObject.ParamFlags.READWRITE,
                                                           null)
-    },
-
+    }
+}, class SystemActions extends GObject.Object {
     _init() {
-        this.parent();
+        super._init();
 
         this._canHavePowerOff = true;
         this._canHaveSuspend = true;
@@ -186,35 +183,35 @@ const SystemActions = new Lang.Class({
 
         Main.sessionMode.connect('updated', () => { this._sessionUpdated(); });
         this._sessionUpdated();
-    },
+    }
 
     get can_power_off() {
         return this._actions.get(POWER_OFF_ACTION_ID).available;
-    },
+    }
 
     get can_suspend() {
         return this._actions.get(SUSPEND_ACTION_ID).available;
-    },
+    }
 
     get can_lock_screen() {
         return this._actions.get(LOCK_SCREEN_ACTION_ID).available;
-    },
+    }
 
     get can_switch_user() {
         return this._actions.get(SWITCH_USER_ACTION_ID).available;
-    },
+    }
 
     get can_logout() {
         return this._actions.get(LOGOUT_ACTION_ID).available;
-    },
+    }
 
     get can_lock_orientation() {
         return this._actions.get(LOCK_ORIENTATION_ACTION_ID).available;
-    },
+    }
 
     get orientation_lock_icon() {
         return this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName;
-    },
+    }
 
     _sensorProxyAppeared() {
         this._sensorProxy = new SensorProxy(Gio.DBus.system, SENSOR_BUS_NAME, SENSOR_OBJECT_PATH,
@@ -227,7 +224,7 @@ const SystemActions = new Lang.Class({
                                           () => { this._updateOrientationLock(); });
                 this._updateOrientationLock();
             });
-    },
+    }
 
     _updateOrientationLock() {
         let available = false;
@@ -238,7 +235,7 @@ const SystemActions = new Lang.Class({
         this._actions.get(LOCK_ORIENTATION_ACTION_ID).available = available;
 
         this.notify('can-lock-orientation');
-    },
+    }
 
     _updateOrientationLockIcon() {
         let locked = this._orientationSettings.get_boolean('orientation-lock');
@@ -247,14 +244,14 @@ const SystemActions = new Lang.Class({
         this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName = iconName;
 
         this.notify('orientation-lock-icon');
-    },
+    }
 
     _sessionUpdated() {
         this._updateLockScreen();
         this._updatePowerOff();
         this._updateSuspend();
         this._updateMultiUser();
-    },
+    }
 
     forceUpdate() {
         // Whether those actions are available or not depends on both lockdown
@@ -262,7 +259,7 @@ const SystemActions = new Lang.Class({
         // latter, so their value may be outdated; force an update now
         this._updateHaveShutdown();
         this._updateHaveSuspend();
-    },
+    }
 
     getMatchingActions(terms) {
         // terms is a list of strings
@@ -275,15 +272,15 @@ const SystemActions = new Lang.Class({
                 results.push(key);
 
         return results;
-    },
+    }
 
     getName(id) {
         return this._actions.get(id).name;
-    },
+    }
 
     getIconName(id) {
         return this._actions.get(id).iconName;
-    },
+    }
 
     activateAction(id) {
         switch (id) {
@@ -306,14 +303,14 @@ const SystemActions = new Lang.Class({
                 this.activateLockOrientation();
                 break;
         }
-    },
+    }
 
     _updateLockScreen() {
         let showLock = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
         let allowLockScreen = !this._lockdownSettings.get_boolean(DISABLE_LOCK_SCREEN_KEY);
         this._actions.get(LOCK_SCREEN_ACTION_ID).available = showLock && allowLockScreen && 
LoginManager.canLock();
         this.notify('can-lock-screen');
-    },
+    }
 
     _updateHaveShutdown() {
         this._session.CanShutdownRemote((result, error) => {
@@ -323,7 +320,7 @@ const SystemActions = new Lang.Class({
             this._canHavePowerOff = result[0];
             this._updatePowerOff();
         });
-    },
+    }
 
     _updatePowerOff() {
         let disabled = Main.sessionMode.isLocked ||
@@ -331,7 +328,7 @@ const SystemActions = new Lang.Class({
                         this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY));
         this._actions.get(POWER_OFF_ACTION_ID).available = this._canHavePowerOff && !disabled;
         this.notify('can-power-off');
-    },
+    }
 
     _updateHaveSuspend() {
         this._loginManager.canSuspend(
@@ -340,7 +337,7 @@ const SystemActions = new Lang.Class({
                 this._suspendNeedsAuth = needsAuth;
                 this._updateSuspend();
             });
-    },
+    }
 
     _updateSuspend() {
         let disabled = (Main.sessionMode.isLocked &&
@@ -349,12 +346,12 @@ const SystemActions = new Lang.Class({
                         this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY));
         this._actions.get(SUSPEND_ACTION_ID).available = this._canHaveSuspend && !disabled;
         this.notify('can-suspend');
-    },
+    }
 
     _updateMultiUser() {
         this._updateLogout();
         this._updateSwitchUser();
-    },
+    }
 
     _updateSwitchUser() {
         let allowSwitch = !this._lockdownSettings.get_boolean(DISABLE_USER_SWITCH_KEY);
@@ -366,7 +363,7 @@ const SystemActions = new Lang.Class({
         this.notify('can-switch-user');
 
         return visible;
-    },
+    }
 
     _updateLogout() {
         let user = this._userManager.get_user(GLib.get_user_name());
@@ -384,7 +381,7 @@ const SystemActions = new Lang.Class({
         this.notify('can-logout');
 
         return visible;
-    },
+    }
 
     activateLockOrientation() {
         if (!this._actions.get(LOCK_ORIENTATION_ACTION_ID).available)
@@ -392,14 +389,14 @@ const SystemActions = new Lang.Class({
 
         let locked = this._orientationSettings.get_boolean('orientation-lock');
         this._orientationSettings.set_boolean('orientation-lock', !locked);
-    },
+    }
 
     activateLockScreen() {
         if (!this._actions.get(LOCK_SCREEN_ACTION_ID).available)
             throw new Error('The lock-screen action is not available!');
 
         Main.screenShield.lock(true);
-    },
+    }
 
     activateSwitchUser() {
         if (!this._actions.get(SWITCH_USER_ACTION_ID).available)
@@ -412,7 +409,7 @@ const SystemActions = new Lang.Class({
             Gdm.goto_login_session_sync(null);
             return false;
         });
-    },
+    }
 
     activateLogout() {
         if (!this._actions.get(LOGOUT_ACTION_ID).available)
@@ -420,14 +417,14 @@ const SystemActions = new Lang.Class({
 
         Main.overview.hide();
         this._session.LogoutRemote(0);
-    },
+    }
 
     activatePowerOff() {
         if (!this._actions.get(POWER_OFF_ACTION_ID).available)
             throw new Error('The power-off action is not available!');
 
         this._session.ShutdownRemote(0);
-    },
+    }
 
     activateSuspend() {
         if (!this._actions.get(SUSPEND_ACTION_ID).available)
diff --git a/js/misc/util.js b/js/misc/util.js
index 25fe3d02e..c5b22dccf 100644
--- a/js/misc/util.js
+++ b/js/misc/util.js
@@ -4,7 +4,7 @@ const Clutter = imports.gi.Clutter;
 const Gettext = imports.gettext;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
-const Lang = imports.lang;
+const GObject = imports.gi.GObject;
 const Mainloop = imports.mainloop;
 const Signals = imports.signals;
 const Shell = imports.gi.Shell;
@@ -348,12 +348,10 @@ function insertSorted(array, val, cmp) {
     return pos;
 }
 
-var CloseButton = new Lang.Class({
-    Name: 'CloseButton',
-    Extends: St.Button,
-
+var CloseButton = GObject.registerClass(
+class CloseButton extends St.Button {
     _init(boxpointer) {
-        this.parent({ style_class: 'notification-close'});
+        super._init({ style_class: 'notification-close'});
 
         // This is a bit tricky. St.Bin has its own x-align/y-align properties
         // that compete with Clutter's properties. This should be fixed for
@@ -370,7 +368,7 @@ var CloseButton = new Lang.Class({
         this._boxPointer = boxpointer;
         if (boxpointer)
             this._boxPointer.connect('arrow-side-changed', this._sync.bind(this));
-    },
+    }
 
     _computeBoxPointerOffset() {
         if (!this._boxPointer || !this._boxPointer.actor.get_stage())
@@ -381,7 +379,7 @@ var CloseButton = new Lang.Class({
             return this._boxPointer.getArrowHeight();
         else
             return 0;
-    },
+    }
 
     _sync() {
         let themeNode = this.get_theme_node();
@@ -389,12 +387,12 @@ var CloseButton = new Lang.Class({
         let offY = this._computeBoxPointerOffset();
         this.translation_x = themeNode.get_length('-shell-close-overlap-x')
         this.translation_y = themeNode.get_length('-shell-close-overlap-y') + offY;
-    },
+    }
 
     vfunc_style_changed() {
         this._sync();
-        this.parent();
-    },
+        super.vfunc_style_changed();
+    }
 });
 
 function makeCloseButton(boxpointer) {
diff --git a/js/portalHelper/main.js b/js/portalHelper/main.js
index a788b7479..cbc29d056 100644
--- a/js/portalHelper/main.js
+++ b/js/portalHelper/main.js
@@ -4,7 +4,6 @@ const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
 const Gio = imports.gi.Gio;
 const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
 const Pango = imports.gi.Pango;
 const Soup = imports.gi.Soup;
 const WebKit = imports.gi.WebKit2;
@@ -33,12 +32,10 @@ const CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT = 30 * GLib.USEC_PER_SEC;
 
 const HelperDBusInterface = loadInterfaceXML('org.gnome.Shell.PortalHelper');
 
-var PortalHeaderBar = new Lang.Class({
-    Name: 'PortalHeaderBar',
-    Extends: Gtk.HeaderBar,
-
+var PortalHeaderBar = GObject.registerClass(
+class PortalHeaderBar extends Gtk.HeaderBar {
     _init() {
-        this.parent({ show_close_button: true });
+        super._init({ show_close_button: true });
 
         // See ephy-title-box.c in epiphany for the layout
         let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL,
@@ -73,11 +70,11 @@ var PortalHeaderBar = new Lang.Class({
         hbox.add(this.subtitleLabel);
 
         vbox.show_all();
-    },
+    }
 
     setSubtitle(label) {
         this.subtitleLabel.set_text(label);
-    },
+    }
 
     setSecurityIcon(securityLevel) {
         switch (securityLevel) {
@@ -95,15 +92,13 @@ var PortalHeaderBar = new Lang.Class({
             this._lockImage.set_tooltip_text(_('Your connection to this hotspot login is not secure. 
Passwords or other information you enter on this page can be viewed by people nearby.'));
             break;
         }
-    },
+    }
 });
 
-var PortalWindow = new Lang.Class({
-    Name: 'PortalWindow',
-    Extends: Gtk.ApplicationWindow,
-
+var PortalWindow = GObject.registerClass(
+class PortalWindow extends Gtk.ApplicationWindow {
     _init(application, url, timestamp, doneCallback) {
-        this.parent({ application: application });
+        super._init({ application: application });
 
         this.connect('delete-event', this.destroyWindow.bind(this));
         this._headerBar = new PortalHeaderBar();
@@ -144,11 +139,11 @@ var PortalWindow = new Lang.Class({
         this.present_with_time(timestamp);
 
         this.application.set_accels_for_action('app.quit', ['<Primary>q', '<Primary>w']);
-    },
+    }
 
     destroyWindow() {
         this.destroy();
-    },
+    }
 
     _syncUri() {
         let uri = this._webView.uri;
@@ -156,12 +151,12 @@ var PortalWindow = new Lang.Class({
             this._headerBar.setSubtitle(GLib.uri_unescape_string(uri, null));
         else
             this._headerBar.setSubtitle('');
-    },
+    }
 
     refresh() {
         this._everSeenRedirect = false;
         this._webView.load_uri(this._originalUrl);
-    },
+    }
 
     vfunc_delete_event(event) {
         if (this._recheckAtExit)
@@ -169,7 +164,7 @@ var PortalWindow = new Lang.Class({
         else
             this._doneCallback(PortalHelperResult.CANCELLED);
         return false;
-    },
+    }
 
     _onLoadChanged(view, loadEvent) {
         if (loadEvent == WebKit.LoadEvent.STARTED) {
@@ -183,11 +178,11 @@ var PortalWindow = new Lang.Class({
             else
                 this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
         }
-    },
+    }
 
     _onInsecureContentDetected() {
         this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
-    },
+    }
 
     _onLoadFailedWithTlsErrors(view, failingURI, certificate, errors) {
         this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
@@ -195,7 +190,7 @@ var PortalWindow = new Lang.Class({
         this._webContext.allow_tls_certificate_for_host(certificate, uri.get_host());
         this._webView.load_uri(failingURI);
         return true;
-    },
+    }
 
     _onDecidePolicy(view, decision, type) {
         if (type == WebKit.PolicyDecisionType.NEW_WINDOW_ACTION) {
@@ -262,15 +257,13 @@ var PortalWindow = new Lang.Class({
 
         decision.use();
         return true;
-    },
+    }
 });
 
-var WebPortalHelper = new Lang.Class({
-    Name: 'WebPortalHelper',
-    Extends: Gtk.Application,
-
+var WebPortalHelper = GObject.registerClass(
+class WebPortalHelper extends Gtk.Application {
     _init() {
-        this.parent({ application_id: 'org.gnome.Shell.PortalHelper',
+        super._init({ application_id: 'org.gnome.Shell.PortalHelper',
                       flags: Gio.ApplicationFlags.IS_SERVICE,
                       inactivity_timeout: 30000 });
 
@@ -280,30 +273,30 @@ var WebPortalHelper = new Lang.Class({
         let action = new Gio.SimpleAction({ name: 'quit' });
         action.connect('activate', () => { this.active_window.destroyWindow(); });
         this.add_action(action);
-    },
+    }
 
     vfunc_dbus_register(connection, path) {
         this._dbusImpl.export(connection, path);
-        this.parent(connection, path);
+        super.vfunc_dbus_register(connection, path);
         return true;
-    },
+    }
 
     vfunc_dbus_unregister(connection, path) {
         this._dbusImpl.unexport_from_connection(connection);
-        this.parent(connection, path);
-    },
+        super.vfunc_dbus_unregister(connection, path);
+    }
 
     vfunc_activate() {
         // If launched manually (for example for testing), force a dummy authentication
         // session with the default url
         this.Authenticate('/org/gnome/dummy', '', 0);
-    },
+    }
 
     Authenticate(connection, url, timestamp) {
         this._queue.push({ connection: connection, url: url, timestamp: timestamp });
 
         this._processQueue();
-    },
+    }
 
     Close(connection) {
         for (let i = 0; i < this._queue.length; i++) {
@@ -318,7 +311,7 @@ var WebPortalHelper = new Lang.Class({
         }
 
         this._processQueue();
-    },
+    }
 
     Refresh(connection) {
         for (let i = 0; i < this._queue.length; i++) {
@@ -330,7 +323,7 @@ var WebPortalHelper = new Lang.Class({
                 break;
             }
         }
-    },
+    }
 
     _processQueue() {
         if (this._queue.length == 0)
@@ -343,7 +336,7 @@ var WebPortalHelper = new Lang.Class({
         top.window = new PortalWindow(this, top.url, top.timestamp, result => {
             this._dbusImpl.emit_signal('Done', new GLib.Variant('(ou)', [top.connection, result]));
         });
-    },
+    }
 });
 
 function initEnvironment() {
diff --git a/js/ui/altTab.js b/js/ui/altTab.js
index 7544a3d1f..d2162f858 100644
--- a/js/ui/altTab.js
+++ b/js/ui/altTab.js
@@ -4,7 +4,6 @@ const Clutter = imports.gi.Clutter;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
-const Lang = imports.lang;
 const Mainloop = imports.mainloop;
 const Meta = imports.gi.Meta;
 const Shell = imports.gi.Shell;
@@ -59,12 +58,10 @@ function getWindows(workspace) {
     }).filter((w, i, a) => !w.skip_taskbar && a.indexOf(w) == i);
 }
 
-var AppSwitcherPopup = new Lang.Class({
-    Name: 'AppSwitcherPopup',
-    Extends: SwitcherPopup.SwitcherPopup,
-
+var AppSwitcherPopup = GObject.registerClass(
+class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
     _init() {
-        this.parent();
+        super._init();
 
         this._thumbnails = null;
         this._thumbnailTimeoutId = 0;
@@ -79,10 +76,10 @@ var AppSwitcherPopup = new Lang.Class({
 
         this._switcherList = new AppSwitcher(apps, this);
         this._items = this._switcherList.icons;
-    },
+    }
 
     vfunc_allocate(box, flags) {
-        this.parent(box, flags);
+        super.vfunc_allocate(box, flags);
 
         // Allocate the thumbnails
         // We try to avoid overflowing the screen so we base the resulting size on
@@ -117,7 +114,7 @@ var AppSwitcherPopup = new Lang.Class({
             childBox.y2 = childBox.y1 + childNaturalHeight;
             this._thumbnails.allocate(childBox, flags);
         }
-    },
+    }
 
     _initialSelection(backward, binding) {
         if (binding == 'switch-group') {
@@ -140,7 +137,7 @@ var AppSwitcherPopup = new Lang.Class({
         } else {
             this._select(1);
         }
-    },
+    }
 
     _nextWindow() {
         // We actually want the second window if we're in the unset state
@@ -148,14 +145,15 @@ var AppSwitcherPopup = new Lang.Class({
             this._currentWindow = 0;
         return SwitcherPopup.mod(this._currentWindow + 1,
                                  this._items[this._selectedIndex].cachedWindows.length);
-    },
+    }
+
     _previousWindow() {
         // Also assume second window here
         if (this._currentWindow == -1)
             this._currentWindow = 1;
         return SwitcherPopup.mod(this._currentWindow - 1,
                                  this._items[this._selectedIndex].cachedWindows.length);
-    },
+    }
 
     _closeAppWindow(appIndex, windowIndex) {
         let appIcon = this._items[appIndex];
@@ -167,7 +165,7 @@ var AppSwitcherPopup = new Lang.Class({
             return;
 
         window.delete(global.get_current_time());
-    },
+    }
 
     _quitApplication(appIndex) {
         let appIcon = this._items[appIndex];
@@ -175,7 +173,7 @@ var AppSwitcherPopup = new Lang.Class({
             return;
 
         appIcon.app.request_quit();
-    },
+    }
 
     _keyPressHandler(keysym, action) {
         if (action == Meta.KeyBindingAction.SWITCH_GROUP) {
@@ -214,7 +212,7 @@ var AppSwitcherPopup = new Lang.Class({
         }
 
         return Clutter.EVENT_STOP;
-    },
+    }
 
     _scrollHandler(direction) {
         if (direction == Clutter.ScrollDirection.UP) {
@@ -244,7 +242,7 @@ var AppSwitcherPopup = new Lang.Class({
                     this._select(this._next());
             }
         }
-    },
+    }
 
     _itemActivatedHandler(n) {
         // If the user clicks on the selected app, activate the
@@ -254,24 +252,24 @@ var AppSwitcherPopup = new Lang.Class({
             this._select(n, this._currentWindow);
         else
             this._select(n);
-    },
+    }
 
     _itemEnteredHandler(n) {
         this._select(n);
-    },
+    }
 
     _windowActivated(thumbnailList, n) {
         let appIcon = this._items[this._selectedIndex];
         Main.activateWindow(appIcon.cachedWindows[n]);
         this.fadeAndDestroy();
-    },
+    }
 
     _windowEntered(thumbnailList, n) {
         if (!this.mouseActive)
             return;
 
         this._select(this._selectedIndex, n);
-    },
+    }
 
     _windowRemoved(thumbnailList, n) {
         let appIcon = this._items[this._selectedIndex];
@@ -282,7 +280,7 @@ var AppSwitcherPopup = new Lang.Class({
             let newIndex = Math.min(n, appIcon.cachedWindows.length - 1);
             this._select(this._selectedIndex, newIndex);
         }
-    },
+    }
 
     _finish(timestamp) {
         let appIcon = this._items[this._selectedIndex];
@@ -291,17 +289,17 @@ var AppSwitcherPopup = new Lang.Class({
         else if (appIcon.cachedWindows[this._currentWindow])
             Main.activateWindow(appIcon.cachedWindows[this._currentWindow], timestamp);
 
-        this.parent();
-    },
+        super._finish(timestamp);
+    }
 
     _onDestroy() {
-        this.parent();
+        super._onDestroy();
 
         if (this._thumbnails)
             this._destroyThumbnails();
         if (this._thumbnailTimeoutId != 0)
             Mainloop.source_remove(this._thumbnailTimeoutId);
-    },
+    }
 
     /**
      * _select:
@@ -357,7 +355,7 @@ var AppSwitcherPopup = new Lang.Class({
                 this._timeoutPopupThumbnails.bind(this));
             GLib.Source.set_name_by_id(this._thumbnailTimeoutId, '[gnome-shell] 
this._timeoutPopupThumbnails');
         }
-    },
+    }
 
     _timeoutPopupThumbnails() {
         if (!this._thumbnails)
@@ -365,7 +363,7 @@ var AppSwitcherPopup = new Lang.Class({
         this._thumbnailTimeoutId = 0;
         this._thumbnailsFocused = false;
         return GLib.SOURCE_REMOVE;
-    },
+    }
 
     _destroyThumbnails() {
         let thumbnailsActor = this._thumbnails;
@@ -379,9 +377,9 @@ var AppSwitcherPopup = new Lang.Class({
                            }
                          });
         this._thumbnails = null;
-        if  (this._switcherList._items[this._selectedIndex])
+        if (this._switcherList._items[this._selectedIndex])
             this._switcherList._items[this._selectedIndex].remove_accessible_state (Atk.StateType.EXPANDED);
-    },
+    }
 
     _createThumbnails() {
         this._thumbnails = new ThumbnailList (this._items[this._selectedIndex].cachedWindows);
@@ -472,26 +470,24 @@ class CyclerHighlight {
 
 // We don't show an actual popup, so just provide what SwitcherPopup
 // expects instead of inheriting from SwitcherList
-var CyclerList = new Lang.Class({
-    Name: 'CyclerList',
-    Extends: St.Widget,
+var CyclerList = GObject.registerClass({
     Signals: { 'item-activated': { param_types: [GObject.TYPE_INT] },
                'item-entered': { param_types: [GObject.TYPE_INT] },
                'item-removed': { param_types: [GObject.TYPE_INT] },
                'item-highlighted': { param_types: [GObject.TYPE_INT] } },
-
+}, class CyclerList extends St.Widget {
     highlight(index, justOutline) {
         this.emit('item-highlighted', index);
     }
 });
 
-var CyclerPopup = new Lang.Class({
-    Name: 'CyclerPopup',
-    Extends: SwitcherPopup.SwitcherPopup,
-    Abstract: true,
-
+var CyclerPopup = GObject.registerClass(
+class CyclerPopup extends SwitcherPopup.SwitcherPopup {
     _init() {
-        this.parent();
+        if (new.target === CyclerPopup)
+            throw new TypeError('Cannot instantiate abstract class ' + new.target.name);
+
+        super._init();
 
         this._items = this._getWindows();
 
@@ -505,12 +501,12 @@ var CyclerPopup = new Lang.Class({
         this._switcherList.connect('item-highlighted', (list, index) => {
             this._highlightItem(index);
         });
-    },
+    }
 
     _highlightItem(index, justOutline) {
         this._highlight.window = this._items[index];
         global.window_group.set_child_above_sibling(this._highlight.actor, null);
-    },
+    }
 
     _finish() {
         let window = this._items[this._selectedIndex];
@@ -535,25 +531,23 @@ var CyclerPopup = new Lang.Class({
             Main.wm.actionMoveWindow(window, ws);
         }
 
-        this.parent();
-    },
+        super._finish();
+    }
 
     _onDestroy() {
         this._highlight.actor.destroy();
 
-        this.parent();
+        super._onDestroy();
     }
 });
 
 
-var GroupCyclerPopup = new Lang.Class({
-    Name: 'GroupCyclerPopup',
-    Extends: CyclerPopup,
-
+var GroupCyclerPopup = GObject.registerClass(
+class GroupCyclerPopup extends CyclerPopup {
     _getWindows() {
         let app = Shell.WindowTracker.get_default().focus_app;
         return app ? app.get_windows() : [];
-    },
+    }
 
     _keyPressHandler(keysym, action) {
         if (action == Meta.KeyBindingAction.CYCLE_GROUP)
@@ -567,12 +561,10 @@ var GroupCyclerPopup = new Lang.Class({
     }
 });
 
-var WindowSwitcherPopup = new Lang.Class({
-    Name: 'WindowSwitcherPopup',
-    Extends: SwitcherPopup.SwitcherPopup,
-
+var WindowSwitcherPopup = GObject.registerClass(
+class WindowSwitcherPopup extends SwitcherPopup.SwitcherPopup {
     _init() {
-        this.parent();
+        super._init();
         this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
 
         let windows = this._getWindowList();
@@ -583,7 +575,7 @@ var WindowSwitcherPopup = new Lang.Class({
         let mode = this._settings.get_enum('app-icon-mode');
         this._switcherList = new WindowList(windows, mode);
         this._items = this._switcherList.icons;
-    },
+    }
 
     _getWindowList() {
         let workspace = null;
@@ -595,7 +587,7 @@ var WindowSwitcherPopup = new Lang.Class({
         }
 
         return getWindows(workspace);
-    },
+    }
 
     _closeWindow(windowIndex) {
         let windowIcon = this._items[windowIndex];
@@ -603,7 +595,7 @@ var WindowSwitcherPopup = new Lang.Class({
             return;
 
         windowIcon.window.delete(global.get_current_time());
-    },
+    }
 
     _keyPressHandler(keysym, action) {
         if (action == Meta.KeyBindingAction.SWITCH_WINDOWS) {
@@ -622,23 +614,22 @@ var WindowSwitcherPopup = new Lang.Class({
         }
 
         return Clutter.EVENT_STOP;
-    },
+    }
 
     _finish() {
         Main.activateWindow(this._items[this._selectedIndex].window);
 
-        this.parent();
+        super._finish();
     }
 });
 
-var WindowCyclerPopup = new Lang.Class({
-    Name: 'WindowCyclerPopup',
-    Extends: CyclerPopup,
-
+var WindowCyclerPopup = GObject.registerClass(
+class WindowCyclerPopup extends CyclerPopup {
     _init() {
+        super._init();
+
         this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
-        this.parent();
-    },
+    }
 
     _getWindows() {
         let workspace = null;
@@ -650,7 +641,7 @@ var WindowCyclerPopup = new Lang.Class({
         }
 
         return getWindows(workspace);
-    },
+    }
 
     _keyPressHandler(keysym, action) {
         if (action == Meta.KeyBindingAction.CYCLE_WINDOWS)
@@ -664,12 +655,10 @@ var WindowCyclerPopup = new Lang.Class({
     }
 });
 
-var AppIcon = new Lang.Class({
-    Name: 'AppIcon',
-    Extends: St.BoxLayout,
-
+var AppIcon = GObject.registerClass(
+class AppIcon extends St.BoxLayout {
     _init(app) {
-        this.parent({ style_class: 'alt-tab-app',
+        super._init({ style_class: 'alt-tab-app',
                       vertical: true });
 
         this.app = app;
@@ -679,28 +668,26 @@ var AppIcon = new Lang.Class({
         this.add(this._iconBin, { x_fill: false, y_fill: false } );
         this.label = new St.Label({ text: this.app.get_name() });
         this.add(this.label, { x_fill: false });
-    },
+    }
 
     set_size(size) {
         this.icon = this.app.create_icon_texture(size);
         this._iconBin.child = this.icon;
         this._iconBin.set_size(size, size);
-    },
+    }
 
     vfunc_get_preferred_width(forHeight) {
-        let [minWidth, ] = this.parent(forHeight);
+        let [minWidth, ] = super.vfunc_get_preferred_width(forHeight);
 
         minWidth = Math.max(minWidth, forHeight);
         return [minWidth, minWidth];
     }
 });
 
-var AppSwitcher = new Lang.Class({
-    Name: 'AppSwitcher',
-    Extends: SwitcherPopup.SwitcherList,
-
+var AppSwitcher = GObject.registerClass(
+class AppSwitcher extends SwitcherPopup.SwitcherList {
     _init(apps, altTabPopup) {
-        this.parent(true);
+        super._init(true);
 
         this.icons = [];
         this._arrows = [];
@@ -734,7 +721,7 @@ var AppSwitcher = new Lang.Class({
         this._mouseTimeOutId = 0;
 
         this.connect('destroy', this._onDestroy.bind(this));
-    },
+    }
 
     _onDestroy() {
         if (this._mouseTimeOutId != 0)
@@ -743,7 +730,7 @@ var AppSwitcher = new Lang.Class({
         this.icons.forEach(icon => {
             icon.app.disconnect(icon._stateChangedId);
         });
-    },
+    }
 
     _setIconSize() {
         let j = 0;
@@ -784,16 +771,16 @@ var AppSwitcher = new Lang.Class({
                 break;
             this.icons[i].set_size(iconSize);
         }
-    },
+    }
 
     vfunc_get_preferred_height(forWidth) {
         this._setIconSize();
-        return this.parent(forWidth);
-    },
+        return super.vfunc_get_preferred_height(forWidth);
+    }
 
     vfunc_allocate(box, flags) {
         // Allocate the main list items
-        this.parent(box, flags);
+        super.vfunc_allocate(box, flags);
 
         let contentBox = this.get_theme_node().get_content_box(box);
 
@@ -810,7 +797,7 @@ var AppSwitcher = new Lang.Class({
             childBox.y2 = childBox.y1 + arrowHeight;
             this._arrows[i].allocate(childBox, flags);
         }
-    },
+    }
 
     // We override SwitcherList's _onItemEnter method to delay
     // activation when the thumbnail list is open
@@ -827,14 +814,14 @@ var AppSwitcher = new Lang.Class({
             GLib.Source.set_name_by_id(this._mouseTimeOutId, '[gnome-shell] this._enterItem');
         } else
            this._itemEntered(index);
-    },
+    }
 
     _enterItem(index) {
         let [x, y, mask] = global.get_pointer();
         let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y);
         if (this._items[index].contains(pickedActor))
             this._itemEntered(index);
-    },
+    }
 
     // We override SwitcherList's highlight() method to also deal with
     // the AppSwitcher->ThumbnailList arrows. Apps with only 1 window
@@ -851,7 +838,7 @@ var AppSwitcher = new Lang.Class({
                 this._arrows[this._curApp].remove_style_pseudo_class('highlighted');
         }
 
-        this.parent(n, justOutline);
+        super.highlight(n, justOutline);
         this._curApp = n;
 
         if (this._curApp != -1) {
@@ -860,7 +847,7 @@ var AppSwitcher = new Lang.Class({
             else
                 this._arrows[this._curApp].add_style_pseudo_class('highlighted');
         }
-    },
+    }
 
     _addIcon(appIcon) {
         this.icons.push(appIcon);
@@ -881,7 +868,7 @@ var AppSwitcher = new Lang.Class({
             arrow.hide();
         else
             item.add_accessible_state (Atk.StateType.EXPANDABLE);
-    },
+    }
 
     _removeIcon(app) {
         let index = this.icons.findIndex(icon => {
@@ -892,15 +879,13 @@ var AppSwitcher = new Lang.Class({
 
         this.icons.splice(index, 1);
         this.removeItem(index);
-    },
+    }
 });
 
-var ThumbnailList = new Lang.Class({
-    Name: 'ThumbnailList',
-    Extends: SwitcherPopup.SwitcherList,
-
+var ThumbnailList = GObject.registerClass(
+class ThumbnailList extends SwitcherPopup.SwitcherList {
     _init(windows) {
-        this.parent(false);
+        super._init(false);
 
         this._labels = new Array();
         this._thumbnailBins = new Array();
@@ -933,7 +918,7 @@ var ThumbnailList = new Lang.Class({
         }
 
         this.connect('destroy', this._onDestroy.bind(this));
-    },
+    }
 
     addClones(availHeight) {
         if (!this._thumbnailBins.length)
@@ -966,7 +951,7 @@ var ThumbnailList = new Lang.Class({
 
         // Make sure we only do this once
         this._thumbnailBins = new Array();
-    },
+    }
 
     _removeThumbnail(source, clone) {
         let index = this._clones.indexOf(clone);
@@ -982,23 +967,20 @@ var ThumbnailList = new Lang.Class({
             this.highlight(SwitcherPopup.mod(index, this._clones.length));
         else
             this.destroy();
-    },
+    }
 
     _onDestroy() {
         this._clones.forEach(clone => {
             if (clone.source)
                 clone.source.disconnect(clone._destroyId);
         });
-    },
-
+    }
 });
 
-var WindowIcon = new Lang.Class({
-    Name: 'WindowIcon',
-    Extends: St.BoxLayout,
-
+var WindowIcon = GObject.registerClass(
+class WindowIcon extends St.BoxLayout {
     _init(window, mode) {
-        this.parent({ style_class: 'alt-tab-app',
+        super._init({ style_class: 'alt-tab-app',
                       vertical: true });
 
         this.window = window;
@@ -1039,7 +1021,7 @@ var WindowIcon = new Lang.Class({
         }
 
         this._icon.set_size(size * scaleFactor, size * scaleFactor);
-    },
+    }
 
     _createAppIcon(app, size) {
         let appIcon = app ? app.create_icon_texture(size)
@@ -1052,12 +1034,10 @@ var WindowIcon = new Lang.Class({
     }
 });
 
-var WindowList = new Lang.Class({
-    Name: 'WindowList',
-    Extends: SwitcherPopup.SwitcherList,
-
+var WindowList = GObject.registerClass(
+class WindowList extends SwitcherPopup.SwitcherList {
     _init(windows, mode) {
-        this.parent(true);
+        super._init(true);
 
         this._label = new St.Label({ x_align: Clutter.ActorAlign.CENTER,
                                      y_align: Clutter.ActorAlign.CENTER });
@@ -1079,16 +1059,16 @@ var WindowList = new Lang.Class({
         }
 
         this.connect('destroy', this._onDestroy.bind(this));
-    },
+    }
 
     _onDestroy() {
         this.icons.forEach(icon => {
             icon.window.disconnect(icon._unmanagedSignalId);
         });
-    },
+    }
 
     vfunc_get_preferred_height(forWidth) {
-        let [minHeight, natHeight] = this.parent(forWidth);
+        let [minHeight, natHeight] = super.vfunc_get_preferred_height(forWidth);
 
         let spacing = this.get_theme_node().get_padding(St.Side.BOTTOM);
         let [labelMin, labelNat] = this._label.get_preferred_height(-1);
@@ -1097,7 +1077,7 @@ var WindowList = new Lang.Class({
         natHeight += labelNat + spacing;
 
         return [minHeight, natHeight];
-    },
+    }
 
     vfunc_allocate(box, flags) {
         let themeNode = this.get_theme_node();
@@ -1115,19 +1095,19 @@ var WindowList = new Lang.Class({
         childBox.x2 = box.x2;
         childBox.y1 = box.y1;
         childBox.y2 = box.y2 - totalLabelHeight;
-        this.parent(childBox, flags);
+        super.vfunc_allocate(childBox, flags);
 
         // Hooking up the parent vfunc will call this.set_allocation() with
         // the height without the label height, so call it again with the
         // correct size here.
         this.set_allocation(box, flags);
-    },
+    }
 
     highlight(index, justOutline) {
-        this.parent(index, justOutline);
+        super.highlight(index, justOutline);
 
         this._label.set_text(index == -1 ? '' : this.icons[index].label.text);
-    },
+    }
 
     _removeWindow(window) {
         let index = this.icons.findIndex(icon => {
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 0feb26ff5..8b9429762 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -6,7 +6,6 @@ const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 const Shell = imports.gi.Shell;
-const Lang = imports.lang;
 const Signals = imports.signals;
 const Meta = imports.gi.Meta;
 const St = imports.gi.St;
@@ -247,26 +246,24 @@ class BaseAppView {
 };
 Signals.addSignalMethods(BaseAppView.prototype);
 
-var PageIndicatorsActor = new Lang.Class({
-    Name:'PageIndicatorsActor',
-    Extends: St.BoxLayout,
-
+var PageIndicatorsActor = GObject.registerClass(
+class PageIndicatorsActor extends St.BoxLayout {
     _init() {
-        this.parent({ style_class: 'page-indicators',
+        super._init({ style_class: 'page-indicators',
                       vertical: true,
                       x_expand: true, y_expand: true,
                       x_align: Clutter.ActorAlign.END,
                       y_align: Clutter.ActorAlign.CENTER,
                       reactive: true,
                       clip_to_allocation: true });
-    },
+    }
 
     vfunc_get_preferred_height(forWidth) {
         // We want to request the natural height of all our children as our
         // natural height, so we chain up to St.BoxLayout, but we only request 0
         // as minimum height, since it's not that important if some indicators
         // are not shown
-        let [, natHeight] = this.parent(forWidth);
+        let [, natHeight] = super.vfunc_get_preferred_height(forWidth);
         return [0, natHeight];
     }
 });
@@ -843,10 +840,8 @@ var Views = {
     ALL: 1
 };
 
-var ControlsBoxLayout = Lang.Class({
-    Name: 'ControlsBoxLayout',
-    Extends: Clutter.BoxLayout,
-
+var ControlsBoxLayout = GObject.registerClass(
+class ControlsBoxLayout extends Clutter.BoxLayout {
     /**
      * Override the BoxLayout behavior to use the maximum preferred width of all
      * buttons for each child
@@ -868,19 +863,17 @@ var ControlsBoxLayout = Lang.Class({
     }
 });
 
-var ViewStackLayout = new Lang.Class({
-    Name: 'ViewStackLayout',
-    Extends: Clutter.BinLayout,
+var ViewStackLayout = GObject.registerClass({
     Signals: { 'allocated-size-changed': { param_types: [GObject.TYPE_INT,
                                                          GObject.TYPE_INT] } },
-
+}, class ViewStackLayout extends Clutter.BinLayout {
     vfunc_allocate(actor, box, flags) {
         let availWidth = box.x2 - box.x1;
         let availHeight = box.y2 - box.y1;
         // Prepare children of all views for the upcoming allocation, calculate all
         // the needed values to adapt available size
         this.emit('allocated-size-changed', availWidth, availHeight);
-        this.parent(actor, box, flags);
+        super.vfunc_allocate(actor, box, flags);
     }
 });
 
diff --git a/js/ui/boxpointer.js b/js/ui/boxpointer.js
index 8d916887c..2abaa8246 100644
--- a/js/ui/boxpointer.js
+++ b/js/ui/boxpointer.js
@@ -1,7 +1,7 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
 const Clutter = imports.gi.Clutter;
-const Lang = imports.lang;
+const GObject = imports.gi.GObject;
 const Meta = imports.gi.Meta;
 const Shell = imports.gi.Shell;
 const Signals = imports.signals;
@@ -32,13 +32,11 @@ var POPUP_ANIMATION_TIME = 0.15;
  * totally inside the monitor if possible.
  *
  */
-var BoxPointer = new Lang.Class({
-    Name: 'BoxPointer',
-    Extends: St.Widget,
+var BoxPointer = GObject.registerClass({
     Signals: { 'arrow-side-changed': {} },
-
+}, class BoxPointer extends St.Widget {
     _init(arrowSide, binProperties) {
-        this.parent();
+        super._init();
 
         this.actor = this;
 
@@ -61,24 +59,24 @@ var BoxPointer = new Lang.Class({
         this._sourceAlignment = 0.5;
         this._capturedEventId = 0;
         this._muteInput();
-    },
+    }
 
     get arrowSide() {
         return this._arrowSide;
-    },
+    }
 
     _muteInput() {
         if (this._capturedEventId == 0)
             this._capturedEventId = this.connect('captured-event',
                                                  () => Clutter.EVENT_STOP);
-    },
+    }
 
     _unmuteInput() {
         if (this._capturedEventId != 0) {
             this.disconnect(this._capturedEventId);
             this._capturedEventId = 0;
         }
-    },
+    }
 
     // BoxPointer.show() and BoxPointer.hide() are here for only compatibility
     // purposes, and will be removed in 3.32.
@@ -94,7 +92,7 @@ var BoxPointer = new Lang.Class({
         }
 
         this.visible = true;
-    },
+    }
 
     hide(animate, onComplete) {
         if (animate !== undefined) {
@@ -108,7 +106,7 @@ var BoxPointer = new Lang.Class({
         }
 
         this.visible = false;
-    },
+    }
 
     open(animate, onComplete) {
         let themeNode = this.get_theme_node();
@@ -149,7 +147,7 @@ var BoxPointer = new Lang.Class({
                                          onComplete();
                                  },
                                  time: animationTime });
-    },
+    }
 
     close(animate, onComplete) {
         if (!this.visible)
@@ -196,7 +194,7 @@ var BoxPointer = new Lang.Class({
                                          onComplete();
                                  }
                                });
-    },
+    }
 
     _adjustAllocationForArrow(isWidth, minSize, natSize) {
         let themeNode = this.get_theme_node();
@@ -211,7 +209,7 @@ var BoxPointer = new Lang.Class({
         }
 
         return [minSize, natSize];
-    },
+    }
 
     vfunc_get_preferred_width(forHeight) {
         let themeNode = this.get_theme_node();
@@ -221,7 +219,7 @@ var BoxPointer = new Lang.Class({
         width = this._adjustAllocationForArrow(true, ...width);
 
         return themeNode.adjust_preferred_width(...width);
-    },
+    }
 
     vfunc_get_preferred_height(forWidth) {
         let themeNode = this.get_theme_node();
@@ -232,7 +230,7 @@ var BoxPointer = new Lang.Class({
         height = this._adjustAllocationForArrow(false, ...height);
 
         return themeNode.adjust_preferred_height(...height);
-    },
+    }
 
     vfunc_allocate(box, flags) {
         this.set_allocation(box, flags);
@@ -276,7 +274,7 @@ var BoxPointer = new Lang.Class({
             this._reposition();
             this._updateFlip();
         }
-    },
+    }
 
     _drawBorder(area) {
         let themeNode = this.get_theme_node();
@@ -458,7 +456,7 @@ var BoxPointer = new Lang.Class({
         }
 
         cr.$dispose();
-    },
+    }
 
     setPosition(sourceActor, alignment) {
         // We need to show it now to force an allocation,
@@ -470,7 +468,7 @@ var BoxPointer = new Lang.Class({
 
         this._reposition();
         this._updateFlip();
-    },
+    }
 
     setSourceAlignment(alignment) {
         this._sourceAlignment = alignment;
@@ -479,7 +477,7 @@ var BoxPointer = new Lang.Class({
             return;
 
         this.setPosition(this._sourceActor, this._arrowAlignment);
-    },
+    }
 
     _reposition() {
         let sourceActor = this._sourceActor;
@@ -593,7 +591,7 @@ var BoxPointer = new Lang.Class({
         this._xPosition = Math.floor(x);
         this._yPosition = Math.floor(y);
         this._shiftActor();
-    },
+    }
 
     // @origin: Coordinate specifying middle of the arrow, along
     // the Y axis for St.Side.LEFT, St.Side.RIGHT from the top and X axis from
@@ -603,7 +601,7 @@ var BoxPointer = new Lang.Class({
             this._arrowOrigin = origin;
             this._border.queue_repaint();
         }
-    },
+    }
 
     // @actor: an actor relative to which the arrow is positioned.
     // Differently from setPosition, this will not move the boxpointer itself,
@@ -613,7 +611,7 @@ var BoxPointer = new Lang.Class({
             this._arrowActor = actor;
             this._border.queue_repaint();
         }
-    },
+    }
 
     _shiftActor() {
         // Since the position of the BoxPointer depends on the allocated size
@@ -624,7 +622,7 @@ var BoxPointer = new Lang.Class({
         // x == y == 0.
         this.set_anchor_point(-(this._xPosition + this._xOffset),
                               -(this._yPosition + this._yOffset));
-    },
+    }
 
     _calculateArrowSide(arrowSide) {
         let sourceAllocation = Shell.util_get_transformed_allocation(this._sourceActor);
@@ -658,7 +656,7 @@ var BoxPointer = new Lang.Class({
         }
 
         return arrowSide;
-    },
+    }
 
     _updateFlip() {
         let arrowSide = this._calculateArrowSide(this._userArrowSide);
@@ -672,36 +670,36 @@ var BoxPointer = new Lang.Class({
 
             this.emit('arrow-side-changed');
         }
-    },
+    }
 
     set xOffset(offset) {
         this._xOffset = offset;
         this._shiftActor();
-    },
+    }
 
     get xOffset() {
         return this._xOffset;
-    },
+    }
 
     set yOffset(offset) {
         this._yOffset = offset;
         this._shiftActor();
-    },
+    }
 
     get yOffset() {
         return this._yOffset;
-    },
+    }
 
     updateArrowSide(side) {
         this._arrowSide = side;
         this._border.queue_repaint();
 
         this.emit('arrow-side-changed');
-    },
+    }
 
     getPadding(side) {
         return this.bin.get_theme_node().get_padding(side);
-    },
+    }
 
     getArrowHeight() {
         return this.get_theme_node().get_length('-arrow-rise');
diff --git a/js/ui/closeDialog.js b/js/ui/closeDialog.js
index 2d019213e..f90d25f8e 100644
--- a/js/ui/closeDialog.js
+++ b/js/ui/closeDialog.js
@@ -4,7 +4,6 @@ const Clutter = imports.gi.Clutter;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
-const Lang = imports.lang;
 const Meta = imports.gi.Meta;
 const Shell = imports.gi.Shell;
 
@@ -16,31 +15,29 @@ var FROZEN_WINDOW_BRIGHTNESS = -0.3
 var DIALOG_TRANSITION_TIME = 0.15
 var ALIVE_TIMEOUT = 5000;
 
-var CloseDialog = new Lang.Class({
-    Name: 'CloseDialog',
-    Extends: GObject.Object,
+var CloseDialog = GObject.registerClass({
     Implements: [ Meta.CloseDialog ],
     Properties: {
         'window': GObject.ParamSpec.override('window', Meta.CloseDialog)
     },
-
+}, class CloseDialog extends GObject.Object {
     _init(window) {
-        this.parent();
+        super._init();
         this._window = window;
         this._dialog = null;
         this._tracked = undefined;
         this._timeoutId = 0;
         this._windowFocusChangedId = 0;
         this._keyFocusChangedId = 0;
-    },
+    }
 
     get window() {
         return this._window;
-    },
+    }
 
     set window(window) {
         this._window = window;
-    },
+    }
 
     _createDialogContent() {
         let tracker = Shell.WindowTracker.get_default();
@@ -52,7 +49,7 @@ var CloseDialog = new Lang.Class({
                          "continue or force the application to quit entirely.");
         let icon = new Gio.ThemedIcon({ name: 'dialog-warning-symbolic' });
         return new Dialog.MessageDialogContent({ icon, title, subtitle });
-    },
+    }
 
     _initDialog() {
         if (this._dialog)
@@ -72,7 +69,7 @@ var CloseDialog = new Lang.Class({
                                  key:    Clutter.Escape });
 
         global.focus_manager.add_group(this._dialog);
-    },
+    }
 
     _addWindowEffect() {
         // We set the effect on the surface actor, so the dialog itself
@@ -83,21 +80,21 @@ var CloseDialog = new Lang.Class({
         let effect = new Clutter.BrightnessContrastEffect();
         effect.set_brightness(FROZEN_WINDOW_BRIGHTNESS);
         surfaceActor.add_effect_with_name("gnome-shell-frozen-window", effect);
-    },
+    }
 
     _removeWindowEffect() {
         let windowActor = this._window.get_compositor_private();
         let surfaceActor = windowActor.get_first_child();
         surfaceActor.remove_effect_by_name("gnome-shell-frozen-window");
-    },
+    }
 
     _onWait() {
         this.response(Meta.CloseDialogResponse.WAIT);
-    },
+    }
 
     _onClose() {
         this.response(Meta.CloseDialogResponse.FORCE_CLOSE);
-    },
+    }
 
     _onFocusChanged() {
         if (Meta.is_wayland_compositor())
@@ -128,7 +125,7 @@ var CloseDialog = new Lang.Class({
         });
 
         this._tracked = shouldTrack;
-    },
+    }
 
     vfunc_show() {
         if (this._dialog != null)
@@ -162,7 +159,7 @@ var CloseDialog = new Lang.Class({
                            time: DIALOG_TRANSITION_TIME,
                            onComplete: this._onFocusChanged.bind(this)
                          });
-    },
+    }
 
     vfunc_hide() {
         if (this._dialog == null)
@@ -191,7 +188,7 @@ var CloseDialog = new Lang.Class({
                                dialog.destroy();
                            }
                          });
-    },
+    }
 
     vfunc_focus() {
         if (this._dialog)
diff --git a/js/ui/components/telepathyClient.js b/js/ui/components/telepathyClient.js
index d26e8a07e..41b4985f4 100644
--- a/js/ui/components/telepathyClient.js
+++ b/js/ui/components/telepathyClient.js
@@ -3,6 +3,7 @@
 const Clutter = imports.gi.Clutter;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 const Lang = imports.lang;
 const Mainloop = imports.mainloop;
@@ -111,10 +112,8 @@ var TelepathyComponent = class {
     }
 };
 
-var TelepathyClient = HAVE_TP ? new Lang.Class({
-    Name: 'TelepathyClient',
-    Extends: Tp.BaseClient,
-
+var TelepathyClient = HAVE_TP ? GObject.registerClass(
+class TelepathyClient extends Tp.BaseClient {
     _init() {
         // channel path -> ChatSource
         this._chatSources = {};
@@ -138,7 +137,7 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
         // channel matching its filters is detected.
         // The second argument, recover, means _observeChannels will be run
         // for any existing channel as well.
-        this.parent({ name: 'GnomeShell',
+        super._init({ name: 'GnomeShell',
                       account_manager: this._accountManager,
                       uniquify_name: true });
 
@@ -156,7 +155,7 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
         // needed
         this.set_delegated_channels_callback(
             this._delegatedChannelsCb.bind(this));
-    },
+    }
 
     vfunc_observe_channels(account, conn, channels,
                                      dispatchOp, requests, context) {
@@ -177,7 +176,7 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
         }
 
         context.accept();
-    },
+    }
 
     _createChatSource(account, conn, channel, contact) {
         if (this._chatSources[channel.get_object_path()])
@@ -189,13 +188,13 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
         source.connect('destroy', () => {
             delete this._chatSources[channel.get_object_path()];
         });
-    },
+    }
 
     vfunc_handle_channels(account, conn, channels, requests,
                                     user_action_time, context) {
         this._handlingChannels(account, conn, channels, true);
         context.accept();
-    },
+    }
 
     _handlingChannels(account, conn, channels, notify) {
         let len = channels.length;
@@ -229,7 +228,7 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
                     source.notify();
             }
         }
-    },
+    }
 
     vfunc_add_dispatch_operation(account, conn, channels,
                                            dispatchOp, context) {
@@ -247,7 +246,7 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
         else
             context.fail(new Tp.Error({ code: Tp.Error.INVALID_ARGUMENT,
                                         message: 'Unsupported channel type' }));
-    },
+    }
 
     _approveTextChannel(account, conn, channel, dispatchOp, context) {
         let [targetHandle, targetHandleType] = channel.get_handle();
@@ -269,12 +268,12 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
         });
 
         context.accept();
-    },
+    }
 
     _delegatedChannelsCb(client, channels) {
         // Nothing to do as we don't make a distinction between observed and
         // handled channels.
-    },
+    }
 }) : null;
 
 var ChatSource = class extends MessageTray.Source {
@@ -794,12 +793,10 @@ var ChatNotification = class extends MessageTray.Notification {
     }
 };
 
-var ChatLineBox = new Lang.Class({
-    Name: 'ChatLineBox',
-    Extends: St.BoxLayout,
-
+var ChatLineBox = GObject.registerClass(
+class ChatLineBox extends St.BoxLayout {
     vfunc_get_preferred_height(forWidth) {
-        let [, natHeight] = this.parent(forWidth);
+        let [, natHeight] = super.vfunc_get_preferred_height(forWidth);
         return [natHeight, natHeight];
     }
 });
diff --git a/js/ui/dash.js b/js/ui/dash.js
index be529213e..74e0aca87 100644
--- a/js/ui/dash.js
+++ b/js/ui/dash.js
@@ -3,8 +3,8 @@
 const Clutter = imports.gi.Clutter;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
 const Signals = imports.signals;
-const Lang = imports.lang;
 const Meta = imports.gi.Meta;
 const Shell = imports.gi.Shell;
 const St = imports.gi.St;
@@ -33,12 +33,10 @@ function getAppFromSource(source) {
 
 // A container like StBin, but taking the child's scale into account
 // when requesting a size
-var DashItemContainer = new Lang.Class({
-    Name: 'DashItemContainer',
-    Extends: St.Widget,
-
+var DashItemContainer = GObject.registerClass(
+class DashItemContainer extends St.Widget {
     _init() {
-        this.parent({ style_class: 'dash-item-container',
+        super._init({ style_class: 'dash-item-container',
                       pivot_point: new Clutter.Point({ x: .5, y: .5 }),
                       x_expand: true,
                       x_align: Clutter.ActorAlign.CENTER });
@@ -59,23 +57,23 @@ var DashItemContainer = new Lang.Class({
                 this.child.destroy();
             this.label.destroy();
         });
-    },
+    }
 
     vfunc_get_preferred_height(forWidth) {
         let themeNode = this.get_theme_node();
         forWidth = themeNode.adjust_for_width(forWidth);
-        let [minHeight, natHeight] = this.parent(forWidth);
+        let [minHeight, natHeight] = super.vfunc_get_preferred_height(forWidth);
         return themeNode.adjust_preferred_height(minHeight * this.scale_y,
                                                  natHeight * this.scale_y);
-    },
+    }
 
     vfunc_get_preferred_width(forHeight) {
         let themeNode = this.get_theme_node();
         forHeight = themeNode.adjust_for_height(forHeight);
-        let [minWidth, natWidth] = this.parent(forHeight);
+        let [minWidth, natWidth] = super.vfunc_get_preferred_width(forHeight);
         return themeNode.adjust_preferred_width(minWidth * this.scale_x,
                                                 natWidth * this.scale_x);
-    },
+    }
 
     showLabel() {
         if (!this._labelText)
@@ -109,12 +107,12 @@ var DashItemContainer = new Lang.Class({
                            time: DASH_ITEM_LABEL_SHOW_TIME,
                            transition: 'easeOutQuad',
                          });
-    },
+    }
 
     setLabelText(text) {
         this._labelText = text;
         this.child.accessible_name = text;
-    },
+    }
 
     hideLabel() {
         Tweener.addTween(this.label,
@@ -125,7 +123,7 @@ var DashItemContainer = new Lang.Class({
                                this.label.hide();
                            }
                          });
-    },
+    }
 
     setChild(actor) {
         if (this.child == actor)
@@ -138,7 +136,7 @@ var DashItemContainer = new Lang.Class({
 
         this.set_scale(this._childScale, this._childScale);
         this.set_opacity(this._childOpacity);
-    },
+    }
 
     show(animate) {
         if (this.child == null)
@@ -151,7 +149,7 @@ var DashItemContainer = new Lang.Class({
                            time: time,
                            transition: 'easeOutQuad'
                          });
-    },
+    }
 
     animateOutAndDestroy() {
         this.label.hide();
@@ -171,37 +169,35 @@ var DashItemContainer = new Lang.Class({
                                this.destroy();
                            }
                          });
-    },
+    }
 
     set childScale(scale) {
         this._childScale = scale;
 
         this.set_scale(scale, scale);
         this.queue_relayout();
-    },
+    }
 
     get childScale() {
         return this._childScale;
-    },
+    }
 
     set childOpacity(opacity) {
         this._childOpacity = opacity;
 
         this.set_opacity(opacity);
         this.queue_redraw();
-    },
+    }
 
     get childOpacity() {
         return this._childOpacity;
     }
 });
 
-var ShowAppsIcon = new Lang.Class({
-    Name: 'ShowAppsIcon',
-    Extends: DashItemContainer,
-
+var ShowAppsIcon = GObject.registerClass(
+class ShowAppsIcon extends DashItemContainer {
     _init() {
-        this.parent();
+        super._init();
 
         this.toggleButton = new St.Button({ style_class: 'show-apps',
                                             track_hover: true,
@@ -217,7 +213,7 @@ var ShowAppsIcon = new Lang.Class({
 
         this.setChild(this.toggleButton);
         this.setDragApp(null);
-    },
+    }
 
     _createIcon(size) {
         this._iconActor = new St.Icon({ icon_name: 'view-app-grid-symbolic',
@@ -225,7 +221,7 @@ var ShowAppsIcon = new Lang.Class({
                                         style_class: 'show-apps-icon',
                                         track_hover: true });
         return this._iconActor;
-    },
+    }
 
     _canRemoveApp(app) {
         if (app == null)
@@ -237,7 +233,7 @@ var ShowAppsIcon = new Lang.Class({
         let id = app.get_id();
         let isFavorite = AppFavorites.getAppFavorites().isFavorite(id);
         return isFavorite;
-    },
+    }
 
     setDragApp(app) {
         let canRemove = this._canRemoveApp(app);
@@ -250,14 +246,14 @@ var ShowAppsIcon = new Lang.Class({
             this.setLabelText(_("Remove from Favorites"));
         else
             this.setLabelText(_("Show Applications"));
-    },
+    }
 
     handleDragOver(source, actor, x, y, time) {
         if (!this._canRemoveApp(getAppFromSource(source)))
             return DND.DragMotionResult.NO_DROP;
 
         return DND.DragMotionResult.MOVE_DROP;
-    },
+    }
 
     acceptDrop(source, actor, x, y, time) {
         let app = getAppFromSource(source);
@@ -275,36 +271,30 @@ var ShowAppsIcon = new Lang.Class({
     }
 });
 
-var DragPlaceholderItem = new Lang.Class({
-    Name: 'DragPlaceholderItem',
-    Extends: DashItemContainer,
-
+var DragPlaceholderItem = GObject.registerClass(
+class DragPlaceholderItem extends DashItemContainer {
     _init() {
-        this.parent();
+        super._init();
         this.setChild(new St.Bin({ style_class: 'placeholder' }));
     }
 });
 
-var EmptyDropTargetItem = new Lang.Class({
-    Name: 'EmptyDropTargetItem',
-    Extends: DashItemContainer,
-
+var EmptyDropTargetItem = GObject.registerClass(
+class EmptyDropTargetItem extends DashItemContainer {
     _init() {
-        this.parent();
+        super._init();
         this.setChild(new St.Bin({ style_class: 'empty-dash-drop-target' }));
     }
 });
 
-var DashActor = new Lang.Class({
-    Name: 'DashActor',
-    Extends: St.Widget,
-
+var DashActor = GObject.registerClass(
+class DashActor extends St.Widget {
     _init() {
         let layout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.VERTICAL });
-        this.parent({ name: 'dash',
+        super._init({ name: 'dash',
                       layout_manager: layout,
                       clip_to_allocation: true });
-    },
+    }
 
     vfunc_allocate(box, flags) {
         let contentBox = this.get_theme_node().get_content_box(box);
@@ -325,7 +315,7 @@ var DashActor = new Lang.Class({
         childBox.y1 = contentBox.y2 - showAppsNatHeight;
         childBox.y2 = contentBox.y2;
         showAppsButton.allocate(childBox, flags);
-    },
+    }
 
     vfunc_get_preferred_height(forWidth) {
         // We want to request the natural height of all our children
@@ -333,7 +323,7 @@ var DashActor = new Lang.Class({
         // then calls BoxLayout), but we only request the showApps
         // button as the minimum size
 
-        let [, natHeight] = this.parent(forWidth);
+        let [, natHeight] = super.vfunc_get_preferred_height(forWidth);
 
         let themeNode = this.get_theme_node();
         let adjustedForWidth = themeNode.adjust_for_width(forWidth);
diff --git a/js/ui/dateMenu.js b/js/ui/dateMenu.js
index a95c09ec2..b2e2f0cd8 100644
--- a/js/ui/dateMenu.js
+++ b/js/ui/dateMenu.js
@@ -6,7 +6,6 @@ const GnomeDesktop = imports.gi.GnomeDesktop;
 const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 const GWeather = imports.gi.GWeather;
-const Lang = imports.lang;
 const Mainloop = imports.mainloop;
 const Pango = imports.gi.Pango;
 const Cairo = imports.cairo;
@@ -371,21 +370,19 @@ var MessagesIndicator = class MessagesIndicator {
     }
 };
 
-var IndicatorPad = new Lang.Class({
-    Name: 'IndicatorPad',
-    Extends: St.Widget,
-
+var IndicatorPad = GObject.registerClass(
+class IndicatorPad extends St.Widget {
     _init(actor) {
         this._source = actor;
         this._source.connect('notify::visible', () => { this.queue_relayout(); });
-        this.parent();
-    },
+        super._init();
+    }
 
     vfunc_get_preferred_width(container, forHeight) {
         if (this._source.visible)
             return this._source.get_preferred_width(forHeight);
         return [0, 0];
-    },
+    }
 
     vfunc_get_preferred_height(container, forWidth) {
         if (this._source.visible)
@@ -394,17 +391,15 @@ var IndicatorPad = new Lang.Class({
     }
 });
 
-var FreezableBinLayout = new Lang.Class({
-    Name: 'FreezableBinLayout',
-    Extends: Clutter.BinLayout,
-
+var FreezableBinLayout = GObject.registerClass(
+class FreezableBinLayout extends Clutter.BinLayout {
     _init() {
-        this.parent();
+        super._init();
 
         this._frozen = false;
         this._savedWidth = [NaN, NaN];
         this._savedHeight = [NaN, NaN];
-    },
+    }
 
     set frozen(v) {
         if (this._frozen == v)
@@ -413,22 +408,22 @@ var FreezableBinLayout = new Lang.Class({
         this._frozen = v;
         if (!this._frozen)
             this.layout_changed();
-    },
+    }
 
     vfunc_get_preferred_width(container, forHeight) {
         if (!this._frozen || this._savedWidth.some(isNaN))
-            return this.parent(container, forHeight);
+            return super.vfunc_get_preferred_width(container, forHeight);
         return this._savedWidth;
-    },
+    }
 
     vfunc_get_preferred_height(container, forWidth) {
         if (!this._frozen || this._savedHeight.some(isNaN))
-            return this.parent(container, forWidth);
+            return super.vfunc_get_preferred_height(container, forWidth);
         return this._savedHeight;
-    },
+    }
 
     vfunc_allocate(container, allocation, flags) {
-        this.parent(container, allocation, flags);
+        super.vfunc_allocate(container, allocation, flags);
 
         let [width, height] = allocation.get_size();
         this._savedWidth = [width, width];
@@ -436,26 +431,22 @@ var FreezableBinLayout = new Lang.Class({
     }
 });
 
-var CalendarColumnLayout = new Lang.Class({
-    Name: 'CalendarColumnLayout',
-    Extends: Clutter.BoxLayout,
-
+var CalendarColumnLayout = GObject.registerClass(
+class CalendarColumnLayout extends Clutter.BoxLayout {
     _init(actor) {
-        this.parent({ orientation: Clutter.Orientation.VERTICAL });
+        super._init({ orientation: Clutter.Orientation.VERTICAL });
         this._calActor = actor;
-    },
+    }
 
     vfunc_get_preferred_width(container, forHeight) {
         if (!this._calActor || this._calActor.get_parent() != container)
-            return this.parent(container, forHeight);
+            return super.vfunc_get_preferred_width(container, forHeight);
         return this._calActor.get_preferred_width(forHeight);
     }
 });
 
-var DateMenuButton = new Lang.Class({
-    Name: 'DateMenuButton',
-    Extends: PanelMenu.Button,
-
+var DateMenuButton = GObject.registerClass(
+class DateMenuButton extends PanelMenu.Button {
     _init() {
         let item;
         let hbox;
@@ -464,7 +455,7 @@ var DateMenuButton = new Lang.Class({
         let menuAlignment = 0.5;
         if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
             menuAlignment = 1.0 - menuAlignment;
-        this.parent(menuAlignment);
+        super._init(menuAlignment);
 
         this._clockDisplay = new St.Label({ y_align: Clutter.ActorAlign.CENTER });
         this._indicator = new MessagesIndicator();
@@ -545,11 +536,11 @@ var DateMenuButton = new Lang.Class({
 
         Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
         this._sessionUpdated();
-    },
+    }
 
     _getEventSource() {
         return new Calendar.DBusEventSource();
-    },
+    }
 
     _setEventSource(eventSource) {
         if (this._eventSource)
@@ -559,7 +550,7 @@ var DateMenuButton = new Lang.Class({
         this._messageList.setEventSource(eventSource);
 
         this._eventSource = eventSource;
-    },
+    }
 
     _updateTimeZone() {
         // SpiderMonkey caches the time zone so we must explicitly clear it
@@ -568,7 +559,7 @@ var DateMenuButton = new Lang.Class({
         System.clearDateCaches();
 
         this._calendar.updateTimeZone();
-    },
+    }
 
     _sessionUpdated() {
         let eventSource;
@@ -584,5 +575,5 @@ var DateMenuButton = new Lang.Class({
         // but the corresponding app (clocks, weather); however we can consider
         // that display-specific settings, so re-use "allowSettings" here ...
         this._displaysSection.visible = Main.sessionMode.allowSettings;
-    },
+    }
 });
diff --git a/js/ui/dialog.js b/js/ui/dialog.js
index 0dd33706b..f9d116eee 100644
--- a/js/ui/dialog.js
+++ b/js/ui/dialog.js
@@ -5,14 +5,11 @@ const Gio = imports.gi.Gio;
 const GObject = imports.gi.GObject;
 const Pango = imports.gi.Pango;
 const St = imports.gi.St;
-const Lang = imports.lang;
-
-var Dialog = new Lang.Class({
-    Name: 'Dialog',
-    Extends: St.Widget,
 
+var Dialog = GObject.registerClass(
+class Dialog extends St.Widget {
     _init(parentActor, styleClass) {
-        this.parent({ layout_manager: new Clutter.BinLayout() });
+        super._init({ layout_manager: new Clutter.BinLayout() });
         this.connect('destroy', this._onDestroy.bind(this));
 
         this._initialKeyFocus = null;
@@ -28,7 +25,7 @@ var Dialog = new Lang.Class({
         this._parentActor = parentActor;
         this._eventId = this._parentActor.connect('event', this._modalEventHandler.bind(this));
         this._parentActor.add_child(this);
-    },
+    }
 
     _createDialog() {
         this._dialog = new St.BoxLayout({ style_class: 'modal-dialog',
@@ -55,13 +52,13 @@ var Dialog = new Lang.Class({
         this._dialog.add(this.buttonLayout,
                          { x_align: St.Align.MIDDLE,
                            y_align: St.Align.START });
-    },
+    }
 
     _onDestroy() {
         if (this._eventId != 0)
             this._parentActor.disconnect(this._eventId);
         this._eventId = 0;
-    },
+    }
 
     _modalEventHandler(actor, event) {
         if (event.type() == Clutter.EventType.KEY_PRESS) {
@@ -87,7 +84,7 @@ var Dialog = new Lang.Class({
         }
 
         return Clutter.EVENT_PROPAGATE;
-    },
+    }
 
     _setInitialKeyFocus(actor) {
         if (this._initialKeyFocus)
@@ -99,15 +96,15 @@ var Dialog = new Lang.Class({
             this._initialKeyFocus = null;
             this._initialKeyFocusDestroyId = 0;
         });
-    },
+    }
 
     get initialKeyFocus() {
         return this._initialKeyFocus || this;
-    },
+    }
 
     addContent(actor) {
         this.contentLayout.add (actor, { expand: true });
-    },
+    }
 
     addButton(buttonInfo) {
         let { label, action, key } = buttonInfo;
@@ -144,17 +141,15 @@ var Dialog = new Lang.Class({
         this.buttonLayout.add_actor(button);
 
         return button;
-    },
+    }
 
     clearButtons() {
         this.buttonLayout.destroy_all_children();
         this._buttonKeys = {};
-    },
+    }
 });
 
-var MessageDialogContent = new Lang.Class({
-    Name: 'MessageDialogContent',
-    Extends: St.BoxLayout,
+var MessageDialogContent = GObject.registerClass({
     Properties: {
         'icon': GObject.ParamSpec.object('icon', 'icon', 'icon',
                                          GObject.ParamFlags.READWRITE |
@@ -172,8 +167,8 @@ var MessageDialogContent = new Lang.Class({
                                          GObject.ParamFlags.READWRITE |
                                          GObject.ParamFlags.CONSTRUCT,
                                          null)
-    },
-
+    }
+}, class MessageDialogContent extends St.BoxLayout {
     _init(params) {
         this._icon = new St.Icon({ y_align: Clutter.ActorAlign.START });
         this._title = new St.Label({ style_class: 'headline' });
@@ -192,7 +187,7 @@ var MessageDialogContent = new Lang.Class({
         if (!params.hasOwnProperty('style_class'))
             params.style_class = 'message-dialog-main-layout';
 
-        this.parent(params);
+        super._init(params);
 
         this.messageBox = new St.BoxLayout({ style_class: 'message-dialog-content',
                                              x_expand: true,
@@ -204,45 +199,45 @@ var MessageDialogContent = new Lang.Class({
 
         this.add_actor(this._icon);
         this.add_actor(this.messageBox);
-    },
+    }
 
     get icon() {
         return this._icon.gicon;
-    },
+    }
 
     get title() {
         return this._title.text;
-    },
+    }
 
     get subtitle() {
         return this._subtitle.text;
-    },
+    }
 
     get body() {
         return this._body.text;
-    },
+    }
 
     set icon(icon) {
         Object.assign(this._icon, { gicon: icon, visible: icon != null });
         this.notify('icon');
-    },
+    }
 
     set title(title) {
         this._setLabel(this._title, 'title', title);
-    },
+    }
 
     set subtitle(subtitle) {
         this._setLabel(this._subtitle, 'subtitle', subtitle);
-    },
+    }
 
     set body(body) {
         this._setLabel(this._body, 'body', body);
-    },
+    }
 
     _setLabel(label, prop, value) {
         Object.assign(label, { text: value || '', visible: value != null });
         this.notify(prop);
-    },
+    }
 
     insertBeforeBody(actor) {
         this.messageBox.insert_child_below(actor, this._body);
diff --git a/js/ui/edgeDragAction.js b/js/ui/edgeDragAction.js
index d49aa69d9..ec94c1b42 100644
--- a/js/ui/edgeDragAction.js
+++ b/js/ui/edgeDragAction.js
@@ -1,6 +1,6 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
-const Lang = imports.lang;
+const GObject = imports.gi.GObject;
 const Signals = imports.signals;
 const Meta = imports.gi.Meta;
 const Clutter = imports.gi.Clutter;
@@ -11,26 +11,24 @@ const Main = imports.ui.main;
 var EDGE_THRESHOLD = 20;
 var DRAG_DISTANCE = 80;
 
-var EdgeDragAction = new Lang.Class({
-    Name: 'EdgeDragAction',
-    Extends: Clutter.GestureAction,
+var EdgeDragAction = GObject.registerClass({
     Signals: { 'activated': {} },
-
+}, class EdgeDragAction extends Clutter.GestureAction {
     _init(side, allowedModes) {
-        this.parent();
+        super._init();
         this._side = side;
         this._allowedModes = allowedModes;
         this.set_n_touch_points(1);
 
         global.display.connect('grab-op-begin', () => { this.cancel(); });
-    },
+    }
 
     _getMonitorRect(x, y) {
         let rect = new Meta.Rectangle({ x: x - 1, y: y - 1, width: 1, height: 1 });
         let monitorIndex = global.display.get_monitor_index_for_rect(rect);
 
         return global.display.get_monitor_geometry(monitorIndex);
-    },
+    }
 
     vfunc_gesture_prepare(action, actor) {
         if (this.get_n_current_points() == 0)
@@ -46,7 +44,7 @@ var EdgeDragAction = new Lang.Class({
                 (this._side == St.Side.RIGHT && x > monitorRect.x + monitorRect.width - EDGE_THRESHOLD) ||
                 (this._side == St.Side.TOP && y < monitorRect.y + EDGE_THRESHOLD) ||
                 (this._side == St.Side.BOTTOM && y > monitorRect.y + monitorRect.height - EDGE_THRESHOLD));
-    },
+    }
 
     vfunc_gesture_progress(action, actor) {
         let [startX, startY] = this.get_press_coords(0);
@@ -66,7 +64,7 @@ var EdgeDragAction = new Lang.Class({
         }
 
         return true;
-    },
+    }
 
     vfunc_gesture_end(action, actor) {
         let [startX, startY] = this.get_press_coords(0);
diff --git a/js/ui/iconGrid.js b/js/ui/iconGrid.js
index 82b335cc5..6d6e2284f 100644
--- a/js/ui/iconGrid.js
+++ b/js/ui/iconGrid.js
@@ -1,13 +1,13 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
 const Clutter = imports.gi.Clutter;
+const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 const Meta = imports.gi.Meta;
 const Shell = imports.gi.Shell;
 const Signals = imports.signals;
 const St = imports.gi.St;
 
-const Lang = imports.lang;
 const Params = imports.misc.params;
 const Tweener = imports.ui.tweener;
 const Main = imports.ui.main;
@@ -34,10 +34,8 @@ var AnimationDirection = {
 var APPICON_ANIMATION_OUT_SCALE = 3;
 var APPICON_ANIMATION_OUT_TIME = 0.25;
 
-var BaseIcon = new Lang.Class({
-    Name: 'BaseIcon',
-    Extends: St.Bin,
-
+var BaseIcon = GObject.registerClass(
+class BaseIcon extends St.Bin {
     _init(label, params) {
         params = Params.parse(params, { createIcon: null,
                                         setSizeManually: false,
@@ -47,7 +45,7 @@ var BaseIcon = new Lang.Class({
         if (params.showLabel)
             styleClass += ' overview-icon-with-label';
 
-        this.parent({ style_class: styleClass,
+        super._init({ style_class: styleClass,
                       x_fill: true,
                       y_fill: true });
 
@@ -79,18 +77,18 @@ var BaseIcon = new Lang.Class({
 
         let cache = St.TextureCache.get_default();
         this._iconThemeChangedId = cache.connect('icon-theme-changed', this._onIconThemeChanged.bind(this));
-    },
+    }
 
     vfunc_get_preferred_width(forHeight) {
         // Return the actual height to keep the squared aspect
         return this.get_preferred_height(-1);
-    },
+    }
 
     // This can be overridden by a subclass, or by the createIcon
     // parameter to _init()
     createIcon(size) {
         throw new Error('no implementation of createIcon in ' + this);
-    },
+    }
 
     setIconSize(size) {
         if (!this._setSizeManually)
@@ -100,7 +98,7 @@ var BaseIcon = new Lang.Class({
             return;
 
         this._createIconTexture(size);
-    },
+    }
 
     _createIconTexture(size) {
         if (this.icon)
@@ -109,7 +107,7 @@ var BaseIcon = new Lang.Class({
         this.icon = this.createIcon(this.iconSize);
 
         this._iconBin.child = this.icon;
-    },
+    }
 
     vfunc_style_changed() {
         let node = this.get_theme_node();
@@ -126,7 +124,7 @@ var BaseIcon = new Lang.Class({
             return;
 
         this._createIconTexture(size);
-    },
+    }
 
     _onDestroy() {
         if (this._iconThemeChangedId > 0) {
@@ -134,11 +132,11 @@ var BaseIcon = new Lang.Class({
             cache.disconnect(this._iconThemeChangedId);
             this._iconThemeChangedId = 0;
         }
-    },
+    }
 
     _onIconThemeChanged() {
         this._createIconTexture(this.iconSize);
-    },
+    }
 
     animateZoomOut() {
         // Animate only the child instead of the entire actor, so the
@@ -187,14 +185,12 @@ function zoomOutActor(actor) {
                     });
 }
 
-var IconGrid = new Lang.Class({
-    Name: 'IconGrid',
-    Extends: St.Widget,
+var IconGrid = GObject.registerClass({
     Signals: {'animation-done': {},
               'child-focused': { param_types: [Clutter.Actor.$gtype]} },
-
+}, class IconGrid extends St.Widget {
     _init(params) {
-        this.parent({ style_class: 'icon-grid',
+        super._init({ style_class: 'icon-grid',
                       y_align: Clutter.ActorAlign.START });
 
         this.actor = this;
@@ -236,19 +232,19 @@ var IconGrid = new Lang.Class({
 
         this.connect('actor-added', this._childAdded.bind(this));
         this.connect('actor-removed', this._childRemoved.bind(this));
-    },
+    }
 
     _keyFocusIn(actor) {
         this.emit('child-focused', actor);
-    },
+    }
 
     _childAdded(grid, child) {
         child._iconGridKeyFocusInId = child.connect('key-focus-in', this._keyFocusIn.bind(this));
-    },
+    }
 
     _childRemoved(grid, child) {
         child.disconnect(child._iconGridKeyFocusInId);
-    },
+    }
 
     vfunc_get_preferred_width(forHeight) {
         if (this._fillParent)
@@ -268,11 +264,11 @@ var IconGrid = new Lang.Class({
         let natSize = nColumns * this._getHItemSize() + totalSpacing + this.leftPadding + this.rightPadding;
 
         return this.get_theme_node().adjust_preferred_width(minSize, natSize);
-    },
+    }
 
     _getVisibleChildren() {
         return this.get_children().filter(actor => actor.visible);
-    },
+    }
 
     vfunc_get_preferred_height(forWidth) {
         if (this._fillParent)
@@ -302,7 +298,7 @@ var IconGrid = new Lang.Class({
         let height = nRows * this._getVItemSize() + totalSpacing + this.topPadding + this.bottomPadding;
 
         return themeNode.adjust_preferred_height(height, height);
-    },
+    }
 
     vfunc_allocate(box, flags) {
         this.set_allocation(box, flags);
@@ -363,7 +359,7 @@ var IconGrid = new Lang.Class({
                 x += this._getHItemSize() + spacing;
             }
         }
-    },
+    }
 
     vfunc_get_paint_volume(paintVolume) {
         // Setting the paint volume does not make sense when we don't have
@@ -402,7 +398,7 @@ var IconGrid = new Lang.Class({
         }
 
         return true;
-    },
+    }
 
     /**
      * Intended to be override by subclasses if they need a different
@@ -410,12 +406,12 @@ var IconGrid = new Lang.Class({
      */
     _getChildrenToAnimate() {
         return this._getVisibleChildren();
-    },
+    }
 
     _cancelAnimation() {
         this._clonesAnimating.forEach(clone => { clone.destroy(); });
         this._clonesAnimating = [];
-    },
+    }
 
     _animationDone() {
         this._clonesAnimating.forEach(clone => {
@@ -425,7 +421,7 @@ var IconGrid = new Lang.Class({
         });
         this._clonesAnimating = [];
         this.emit('animation-done');
-    },
+    }
 
     animatePulse(animationDirection) {
         if (animationDirection != AnimationDirection.IN)
@@ -474,7 +470,7 @@ var IconGrid = new Lang.Class({
                               }
                             });
         }
-    },
+    }
 
     animateSpring(animationDirection, sourceActor) {
         this._cancelAnimation();
@@ -574,7 +570,7 @@ var IconGrid = new Lang.Class({
             Tweener.addTween(actorClone, movementParams);
             Tweener.addTween(actorClone, fadeParams);
         }
-    },
+    }
 
     _getAllocatedChildSizeAndSpacing(child) {
         let [,, natWidth, natHeight] = child.get_preferred_size();
@@ -583,7 +579,7 @@ var IconGrid = new Lang.Class({
         let height = Math.min(this._getVItemSize(), natHeight);
         let ySpacing = Math.max(0, height - natHeight) / 2;
         return [width, height, xSpacing, ySpacing];
-    },
+    }
 
     _calculateChildBox(child, x, y, box) {
         /* Center the item in its allocation horizontally */
@@ -601,15 +597,15 @@ var IconGrid = new Lang.Class({
         childBox.x2 = childBox.x1 + width;
         childBox.y2 = childBox.y1 + height;
         return childBox;
-    },
+    }
 
     columnsForWidth(rowWidth) {
         return this._computeLayout(rowWidth)[0];
-    },
+    }
 
     getRowLimit() {
         return this._rowLimit;
-    },
+    }
 
     _computeLayout(forWidth) {
         let nColumns = 0;
@@ -626,7 +622,7 @@ var IconGrid = new Lang.Class({
             usedWidth -= spacing;
 
         return [nColumns, usedWidth];
-    },
+    }
 
     _onStyleChanged() {
         let themeNode = this.get_theme_node();
@@ -634,7 +630,7 @@ var IconGrid = new Lang.Class({
         this._hItemSize = themeNode.get_length('-shell-grid-horizontal-item-size') || ICON_SIZE;
         this._vItemSize = themeNode.get_length('-shell-grid-vertical-item-size') || ICON_SIZE;
         this.queue_relayout();
-    },
+    }
 
     nRows(forWidth) {
         let children = this._getVisibleChildren();
@@ -643,35 +639,35 @@ var IconGrid = new Lang.Class({
         if (this._rowLimit)
             nRows = Math.min(nRows, this._rowLimit);
         return nRows;
-    },
+    }
 
     rowsForHeight(forHeight) {
         return Math.floor((forHeight - (this.topPadding + this.bottomPadding) + this._getSpacing()) / 
(this._getVItemSize() + this._getSpacing()));
-    },
+    }
 
     usedHeightForNRows(nRows) {
         return (this._getVItemSize() + this._getSpacing()) * nRows - this._getSpacing() + this.topPadding + 
this.bottomPadding;
-    },
+    }
 
     usedWidth(forWidth) {
         return this.usedWidthForNColumns(this.columnsForWidth(forWidth));
-    },
+    }
 
     usedWidthForNColumns(columns) {
         let usedWidth = columns  * (this._getHItemSize() + this._getSpacing());
         usedWidth -= this._getSpacing();
         return usedWidth + this.leftPadding + this.rightPadding;
-    },
+    }
 
     removeAll() {
         this._items = [];
         this.remove_all_children();
-    },
+    }
 
     destroyAll() {
         this._items = [];
         this.destroy_all_children();
-    },
+    }
 
     addItem(item, index) {
         if (!item.icon instanceof BaseIcon)
@@ -682,35 +678,35 @@ var IconGrid = new Lang.Class({
             this.insert_child_at_index(item.actor, index);
         else
             this.add_actor(item.actor);
-    },
+    }
 
     removeItem(item) {
         this.remove_child(item.actor);
-    },
+    }
 
     getItemAtIndex(index) {
         return this.get_child_at_index(index);
-    },
+    }
 
     visibleItemsCount() {
         return this.get_children().filter(c => c.is_visible()).length;
-    },
+    }
 
     setSpacing(spacing) {
         this._fixedSpacing = spacing;
-    },
+    }
 
     _getSpacing() {
         return this._fixedSpacing ? this._fixedSpacing : this._spacing;
-    },
+    }
 
     _getHItemSize() {
         return this._fixedHItemSize ? this._fixedHItemSize : this._hItemSize;
-    },
+    }
 
     _getVItemSize() {
         return this._fixedVItemSize ? this._fixedVItemSize : this._vItemSize;
-    },
+    }
 
     _updateSpacingForSize(availWidth, availHeight) {
         let maxEmptyVArea = availHeight - this._minRows * this._getVItemSize();
@@ -743,7 +739,7 @@ var IconGrid = new Lang.Class({
         this.setSpacing(spacing);
         if (this._padWithSpacing)
             this.topPadding = this.rightPadding = this.bottomPadding = this.leftPadding = spacing;
-    },
+    }
 
     /**
      * This function must to be called before iconGrid allocation,
@@ -768,7 +764,7 @@ var IconGrid = new Lang.Class({
         }
         Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
                        this._updateIconSizes.bind(this));
-    },
+    }
 
     // Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up
     _updateIconSizes() {
@@ -780,25 +776,23 @@ var IconGrid = new Lang.Class({
     }
 });
 
-var PaginatedIconGrid = new Lang.Class({
-    Name: 'PaginatedIconGrid',
-    Extends: IconGrid,
+var PaginatedIconGrid = GObject.registerClass({
     Signals: {'space-opened': {},
               'space-closed': {} },
-
+}, class PaginatedIconGrid extends IconGrid {
     _init(params) {
-        this.parent(params);
+        super._init(params);
         this._nPages = 0;
         this.currentPage = 0;
         this._rowsPerPage = 0;
         this._spaceBetweenPages = 0;
         this._childrenPerPage = 0;
-    },
+    }
 
     vfunc_get_preferred_height(forWidth) {
         let height = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * 
this._nPages + this._spaceBetweenPages * this._nPages;
         return [height, height];
-    },
+    }
 
     vfunc_allocate(box, flags) {
          if (this._childrenPerPage == 0)
@@ -853,7 +847,7 @@ var PaginatedIconGrid = new Lang.Class({
             } else
                 x += this._getHItemSize() + spacing;
         }
-    },
+    }
 
     // Overriden from IconGrid
     _getChildrenToAnimate() {
@@ -862,7 +856,7 @@ var PaginatedIconGrid = new Lang.Class({
         let lastIndex = firstIndex + this._childrenPerPage;
 
         return children.slice(firstIndex, lastIndex);
-    },
+    }
 
     _computePages(availWidthPerPage, availHeightPerPage) {
         let [nColumns, usedWidth] = this._computeLayout(availWidthPerPage);
@@ -881,24 +875,24 @@ var PaginatedIconGrid = new Lang.Class({
         this._nPages = Math.ceil(nRows / this._rowsPerPage);
         this._spaceBetweenPages = availHeightPerPage - (this.topPadding + this.bottomPadding) - 
this._availableHeightPerPageForItems();
         this._childrenPerPage = nColumns * this._rowsPerPage;
-    },
+    }
 
     adaptToSize(availWidth, availHeight) {
-        this.parent(availWidth, availHeight);
+        super.adaptToSize(availWidth, availHeight);
         this._computePages(availWidth, availHeight);
-    },
+    }
 
     _availableHeightPerPageForItems() {
         return this.usedHeightForNRows(this._rowsPerPage) - (this.topPadding + this.bottomPadding);
-    },
+    }
 
     nPages() {
         return this._nPages;
-    },
+    }
 
     getPageHeight() {
         return this._availableHeightPerPageForItems();
-    },
+    }
 
     getPageY(pageNumber) {
         if (!this._nPages)
@@ -907,7 +901,7 @@ var PaginatedIconGrid = new Lang.Class({
         let firstPageItem = pageNumber * this._childrenPerPage
         let childBox = this._getVisibleChildren()[firstPageItem].get_allocation_box();
         return childBox.y1 - this.topPadding;
-    },
+    }
 
     getItemPage(item) {
         let children = this._getVisibleChildren();
@@ -917,7 +911,7 @@ var PaginatedIconGrid = new Lang.Class({
             return 0;
         }
         return Math.floor(index / this._childrenPerPage);
-    },
+    }
 
     /**
     * openExtraSpace:
@@ -969,7 +963,7 @@ var PaginatedIconGrid = new Lang.Class({
             this._translateChildren(childrenDown, Gtk.DirectionType.DOWN, nRowsDown);
             this._translatedChildren = childrenUp.concat(childrenDown);
         }
-    },
+    }
 
     _translateChildren(children, direction, nRows) {
         let translationY = nRows * (this._getVItemSize() + this._getSpacing());
@@ -989,7 +983,7 @@ var PaginatedIconGrid = new Lang.Class({
                 params.onComplete = () => { this.emit('space-opened'); };
             Tweener.addTween(children[i], params);
         }
-    },
+    }
 
     closeExtraSpace() {
         if (!this._translatedChildren || !this._translatedChildren.length) {
diff --git a/js/ui/inhibitShortcutsDialog.js b/js/ui/inhibitShortcutsDialog.js
index 0db654336..16c96400d 100644
--- a/js/ui/inhibitShortcutsDialog.js
+++ b/js/ui/inhibitShortcutsDialog.js
@@ -2,7 +2,6 @@ const Clutter = imports.gi.Clutter;
 const Gio = imports.gi.Gio;
 const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
 const Meta = imports.gi.Meta;
 const Shell = imports.gi.Shell;
 const St = imports.gi.St;
@@ -16,41 +15,39 @@ const APP_WHITELIST = ['gnome-control-center.desktop'];
 
 var DialogResponse = Meta.InhibitShortcutsDialogResponse;
 
-var InhibitShortcutsDialog = new Lang.Class({
-    Name: 'InhibitShortcutsDialog',
-    Extends: GObject.Object,
+var InhibitShortcutsDialog = GObject.registerClass({
     Implements: [Meta.InhibitShortcutsDialog],
     Properties: {
         'window': GObject.ParamSpec.override('window', Meta.InhibitShortcutsDialog)
-    },
-
+    }
+}, class InhibitShortcutsDialog extends GObject.Object {
     _init(window) {
-        this.parent();
+        super._init();
         this._window = window;
 
         this._dialog = new ModalDialog.ModalDialog();
         this._buildLayout();
-    },
+    }
 
     get window() {
         return this._window;
-    },
+    }
 
     set window(window) {
         this._window = window;
-    },
+    }
 
     get _app() {
         let windowTracker = Shell.WindowTracker.get_default();
         return windowTracker.get_window_app(this._window);
-    },
+    }
 
     _getRestoreAccel() {
         let settings = new Gio.Settings({ schema_id: WAYLAND_KEYBINDINGS_SCHEMA });
         let accel = settings.get_strv('restore-shortcuts')[0] || '';
         return Gtk.accelerator_get_label.apply(null,
                                                Gtk.accelerator_parse(accel));
-    },
+    }
 
     _buildLayout() {
         let name = this._app ? this._app.get_name() : this._window.title;
@@ -82,19 +79,19 @@ var InhibitShortcutsDialog = new Lang.Class({
                                      this._emitResponse(DialogResponse.ALLOW);
                                  },
                                  default: true });
-    },
+    }
 
     _emitResponse(response) {
         this.emit('response', response);
         this._dialog.close();
-    },
+    }
 
     vfunc_show() {
         if (this._app && APP_WHITELIST.indexOf(this._app.get_id()) != -1)
             this._emitResponse(DialogResponse.ALLOW);
         else
             this._dialog.open();
-    },
+    }
 
     vfunc_hide() {
         this._dialog.close();
diff --git a/js/ui/kbdA11yDialog.js b/js/ui/kbdA11yDialog.js
index 739e0883b..d789abac5 100644
--- a/js/ui/kbdA11yDialog.js
+++ b/js/ui/kbdA11yDialog.js
@@ -1,7 +1,6 @@
 const Clutter = imports.gi.Clutter;
 const Gio = imports.gi.Gio;
 const GObject = imports.gi.GObject;
-const Lang = imports.lang;
 const Dialog = imports.ui.dialog;
 const ModalDialog = imports.ui.modalDialog;
 
@@ -9,17 +8,17 @@ const KEYBOARD_A11Y_SCHEMA    = 'org.gnome.desktop.a11y.keyboard';
 const KEY_STICKY_KEYS_ENABLED = 'stickykeys-enable';
 const KEY_SLOW_KEYS_ENABLED   = 'slowkeys-enable';
 
-var KbdA11yDialog = new Lang.Class({
-    Name: 'KbdA11yDialog',
-    Extends: GObject.Object,
-
+var KbdA11yDialog = new GObject.registerClass(
+class KbdA11yDialog extends GObject.Object {
     _init() {
+        super._init();
+
         this._a11ySettings = new Gio.Settings({ schema_id: KEYBOARD_A11Y_SCHEMA });
 
         let deviceManager = Clutter.DeviceManager.get_default();
         deviceManager.connect('kbd-a11y-flags-changed',
                               this._showKbdA11yDialog.bind(this));
-    },
+    }
 
     _showKbdA11yDialog(deviceManager, newFlags, whatChanged) {
         let dialog = new ModalDialog.ModalDialog();
diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js
index 518379cbe..8bd31c8e8 100644
--- a/js/ui/keyboard.js
+++ b/js/ui/keyboard.js
@@ -5,7 +5,6 @@ const Clutter = imports.gi.Clutter;
 const Gdk = imports.gi.Gdk;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
-const Lang = imports.lang;
 const GObject = imports.gi.GObject;
 const Meta = imports.gi.Meta;
 const Shell = imports.gi.Shell;
@@ -56,15 +55,13 @@ const defaultKeysPost = [
       [{ width: 1.5, action: 'languageMenu', extraClassName: 'layout-key' }, { width: 1.5, action: 'hide', 
extraClassName: 'hide-key' }] ],
 ];
 
-var KeyContainer = new Lang.Class({
-    Name: 'KeyContainer',
-    Extends: St.Widget,
-
+var KeyContainer = new GObject.registerClass(
+class KeyContainer extends St.Widget {
     _init() {
         let gridLayout = new Clutter.GridLayout({ orientation: Clutter.Orientation.HORIZONTAL,
                                                   column_homogeneous: true,
                                                   row_homogeneous: true });
-        this.parent({ layout_manager: gridLayout });
+        super._init({ layout_manager: gridLayout });
         this._gridLayout = gridLayout;
         this._currentRow = 0;
         this._currentCol = 0;
@@ -72,7 +69,7 @@ var KeyContainer = new Lang.Class({
 
         this._currentRow = null;
         this._rows = [];
-    },
+    }
 
     appendRow(length) {
         this._currentRow++;
@@ -82,7 +79,7 @@ var KeyContainer = new Lang.Class({
         row.keys = [];
         row.width = 0;
         this._rows.push(row);
-    },
+    }
 
     appendKey(key, width = 1, height = 1) {
         let keyInfo = {
@@ -99,7 +96,7 @@ var KeyContainer = new Lang.Class({
 
         this._currentCol += width;
         this._maxCols = Math.max(this._currentCol, this._maxCols);
-    },
+    }
 
     vfunc_allocate(box, flags) {
         if (box.get_width() > 0 && box.get_height() > 0 && this._maxCols > 0) {
@@ -123,8 +120,8 @@ var KeyContainer = new Lang.Class({
             }
         }
 
-        this.parent (box, flags);
-    },
+        super.vfunc_allocate(box, flags);
+    }
 
     layoutButtons() {
         let nCol = 0, nRow = 0;
diff --git a/js/ui/layout.js b/js/ui/layout.js
index 22b2807a9..5bf3ec573 100644
--- a/js/ui/layout.js
+++ b/js/ui/layout.js
@@ -3,7 +3,6 @@
 const Clutter = imports.gi.Clutter;
 const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
-const Lang = imports.lang;
 const Meta = imports.gi.Meta;
 const Shell = imports.gi.Shell;
 const Signals = imports.signals;
@@ -36,9 +35,7 @@ function isPopupMetaWindow(actor) {
     }
 }
 
-var MonitorConstraint = new Lang.Class({
-    Name: 'MonitorConstraint',
-    Extends: Clutter.Constraint,
+var MonitorConstraint = GObject.registerClass({
     Properties: {'primary': GObject.ParamSpec.boolean('primary', 
                                                       'Primary', 'Track primary monitor',
                                                       GObject.ParamFlags.READABLE | 
GObject.ParamFlags.WRITABLE,
@@ -51,18 +48,18 @@ var MonitorConstraint = new Lang.Class({
                                                         'Work-area', 'Track monitor\'s work-area',
                                                         GObject.ParamFlags.READABLE | 
GObject.ParamFlags.WRITABLE,
                                                         false)},
-
+}, class MonitorConstraint extends Clutter.Constraint {
     _init(props) {
         this._primary = false;
         this._index = -1;
         this._workArea = false;
 
-        this.parent(props);
-    },
+        super._init(props);
+    }
 
     get primary() {
         return this._primary;
-    },
+    }
 
     set primary(v) {
         if (v)
@@ -71,11 +68,11 @@ var MonitorConstraint = new Lang.Class({
         if (this.actor)
             this.actor.queue_relayout();
         this.notify('primary');
-    },
+    }
 
     get index() {
         return this._index;
-    },
+    }
 
     set index(v) {
         this._primary = false;
@@ -83,11 +80,11 @@ var MonitorConstraint = new Lang.Class({
         if (this.actor)
             this.actor.queue_relayout();
         this.notify('index');
-    },
+    }
 
     get work_area() {
         return this._workArea;
-    },
+    }
 
     set work_area(v) {
         if (v == this._workArea)
@@ -96,7 +93,7 @@ var MonitorConstraint = new Lang.Class({
         if (this.actor)
             this.actor.queue_relayout();
         this.notify('work-area');
-    },
+    }
 
     vfunc_set_actor(actor) {
         if (actor) {
@@ -124,8 +121,8 @@ var MonitorConstraint = new Lang.Class({
             this._workareasChangedId = 0;
         }
 
-        this.parent(actor);
-    },
+        super.vfunc_set_actor(actor);
+    }
 
     vfunc_update_allocation(actor, actorBox) {
         if (!this._primary && this._index < 0)
@@ -173,17 +170,15 @@ const defaultParams = {
     affectsInputRegion: true
 };
 
-var LayoutManager = new Lang.Class({
-    Name: 'LayoutManager',
-    Extends: GObject.Object,
+var LayoutManager = GObject.registerClass({
     Signals: { 'hot-corners-changed': {},
                'startup-complete': {},
                'startup-prepared': {},
                'monitors-changed': {},
                'keyboard-visible-changed': { param_types: [GObject.TYPE_BOOLEAN] } },
-
+}, class LayoutManager extends GObject.Object {
     _init() {
-        this.parent();
+        super._init();
 
         this._rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL);
         this.monitors = [];
@@ -294,33 +289,33 @@ var LayoutManager = new Lang.Class({
                     Meta.Background.refresh_all();
                 });
         }
-    },
+    }
 
     // This is called by Main after everything else is constructed
     init() {
         Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
 
         this._loadBackground();
-    },
+    }
 
     showOverview() {
         this.overviewGroup.show();
 
         this._inOverview = true;
         this._updateVisibility();
-    },
+    }
 
     hideOverview() {
         this.overviewGroup.hide();
 
         this._inOverview = false;
         this._updateVisibility();
-    },
+    }
 
     _sessionUpdated() {
         this._updateVisibility();
         this._queueUpdateRegions();
-    },
+    }
 
     _updateMonitors() {
         let display = global.display;
@@ -358,7 +353,7 @@ var LayoutManager = new Lang.Class({
             this.primaryMonitor = null;
             this.bottomMonitor = null;
         }
-    },
+    }
 
     _updateHotCorners() {
         // destroy old hot corners
@@ -417,11 +412,11 @@ var LayoutManager = new Lang.Class({
         }
 
         this.emit('hot-corners-changed');
-    },
+    }
 
     _addBackgroundMenu(bgManager) {
         BackgroundMenu.addBackgroundMenu(bgManager.backgroundActor, this);
-    },
+    }
 
     _createBackgroundManager(monitorIndex) {
         let bgManager = new Background.BackgroundManager({ container: this._backgroundGroup,
@@ -432,7 +427,7 @@ var LayoutManager = new Lang.Class({
         this._addBackgroundMenu(bgManager);
 
         return bgManager;
-    },
+    }
 
     _showSecondaryBackgrounds() {
         for (let i = 0; i < this.monitors.length; i++) {
@@ -446,7 +441,7 @@ var LayoutManager = new Lang.Class({
                                    transition: 'easeOutQuad' });
             }
         }
-    },
+    }
 
     _updateBackgrounds() {
         let i;
@@ -465,13 +460,13 @@ var LayoutManager = new Lang.Class({
             if (i != this.primaryIndex && this._startingUp)
                 bgManager.backgroundActor.hide();
         }
-    },
+    }
 
     _updateKeyboardBox() {
         this.keyboardBox.set_position(this.keyboardMonitor.x,
                                       this.keyboardMonitor.y + this.keyboardMonitor.height);
         this.keyboardBox.set_size(this.keyboardMonitor.width, -1);
-    },
+    }
 
     _updateBoxes() {
         this.screenShieldGroup.set_position(0, 0);
@@ -484,7 +479,7 @@ var LayoutManager = new Lang.Class({
         this.panelBox.set_size(this.primaryMonitor.width, -1);
 
         this.keyboardIndex = this.primaryIndex;
-    },
+    }
 
     _panelBoxChanged() {
         this._updatePanelBarrier();
@@ -494,7 +489,7 @@ var LayoutManager = new Lang.Class({
             if (corner)
                 corner.setBarrierSize(size);
         });
-    },
+    }
 
     _updatePanelBarrier() {
         if (this._rightPanelBarrier) {
@@ -513,7 +508,7 @@ var LayoutManager = new Lang.Class({
                                                          x2: primary.x + primary.width, y2: primary.y + 
this.panelBox.height,
                                                          directions: Meta.BarrierDirection.NEGATIVE_X });
         }
-    },
+    }
 
     _monitorsChanged() {
         this._updateMonitors();
@@ -525,7 +520,7 @@ var LayoutManager = new Lang.Class({
         this._queueUpdateRegions();
 
         this.emit('monitors-changed');
-    },
+    }
 
     _isAboveOrBelowPrimary(monitor) {
         let primary = this.monitors[this.primaryIndex];
@@ -539,16 +534,16 @@ var LayoutManager = new Lang.Class({
             return true;
 
         return false;
-    },
+    }
 
     get currentMonitor() {
         let index = global.display.get_current_monitor();
         return this.monitors[index];
-    },
+    }
 
     get keyboardMonitor() {
         return this.monitors[this.keyboardIndex];
-    },
+    }
 
     get focusIndex() {
         let i = Main.layoutManager.primaryIndex;
@@ -558,22 +553,22 @@ var LayoutManager = new Lang.Class({
         else if (global.display.focus_window != null)
             i = global.display.focus_window.get_monitor();
         return i;
-    },
+    }
 
     get focusMonitor() {
         if (this.focusIndex < 0)
             return null;
         return this.monitors[this.focusIndex];
-    },
+    }
 
     set keyboardIndex(v) {
         this._keyboardIndex = v;
         this._updateKeyboardBox();
-    },
+    }
 
     get keyboardIndex() {
         return this._keyboardIndex;
-    },
+    }
 
     _loadBackground() {
         if (!this.primaryMonitor) {
@@ -596,7 +591,7 @@ var LayoutManager = new Lang.Class({
 
             this._prepareStartupAnimation();
         });
-    },
+    }
 
     // Startup Animations
     //
@@ -662,7 +657,7 @@ var LayoutManager = new Lang.Class({
             return GLib.SOURCE_REMOVE;
         });
         GLib.Source.set_name_by_id(id, '[gnome-shell] this._startupAnimation');
-    },
+    }
 
     _startupAnimation() {
         if (Meta.is_restart())
@@ -671,7 +666,7 @@ var LayoutManager = new Lang.Class({
             this._startupAnimationGreeter();
         else
             this._startupAnimationSession();
-    },
+    }
 
     _startupAnimationGreeter() {
         Tweener.addTween(this.panelBox,
@@ -680,7 +675,7 @@ var LayoutManager = new Lang.Class({
                            transition: 'easeOutQuad',
                            onComplete: this._startupAnimationComplete,
                            onCompleteScope: this });
-    },
+    }
 
     _startupAnimationSession() {
         Tweener.addTween(this.uiGroup,
@@ -691,7 +686,7 @@ var LayoutManager = new Lang.Class({
                            transition: 'easeOutQuad',
                            onComplete: this._startupAnimationComplete,
                            onCompleteScope: this });
-    },
+    }
 
     _startupAnimationComplete() {
         this._coverPane.destroy();
@@ -712,7 +707,7 @@ var LayoutManager = new Lang.Class({
         this._queueUpdateRegions();
 
         this.emit('startup-complete');
-    },
+    }
 
     showKeyboard() {
         this.keyboardBox.show();
@@ -725,7 +720,7 @@ var LayoutManager = new Lang.Class({
                            onCompleteScope: this
                          });
         this.emit('keyboard-visible-changed', true);
-    },
+    }
 
     _showKeyboardComplete() {
         // Poke Chrome to update the input shape; it doesn't notice
@@ -735,7 +730,7 @@ var LayoutManager = new Lang.Class({
         this._keyboardHeightNotifyId = this.keyboardBox.connect('notify::height', () => {
             this.keyboardBox.anchor_y = this.keyboardBox.height;
         });
-    },
+    }
 
     hideKeyboard(immediate) {
         if (this._keyboardHeightNotifyId) {
@@ -752,12 +747,12 @@ var LayoutManager = new Lang.Class({
                          });
 
         this.emit('keyboard-visible-changed', false);
-    },
+    }
 
     _hideKeyboardComplete() {
         this.keyboardBox.hide();
         this._updateRegions();
-    },
+    }
 
     // setDummyCursorGeometry:
     //
@@ -772,7 +767,7 @@ var LayoutManager = new Lang.Class({
     setDummyCursorGeometry(x, y, w, h) {
         this.dummyCursor.set_position(Math.round(x), Math.round(y));
         this.dummyCursor.set_size(Math.round(w), Math.round(h));
-    },
+    }
 
     // addChrome:
     // @actor: an actor to add to the chrome
@@ -798,7 +793,7 @@ var LayoutManager = new Lang.Class({
         if (this.uiGroup.contains(global.top_window_group))
             this.uiGroup.set_child_below_sibling(actor, global.top_window_group);
         this._trackActor(actor, params);
-    },
+    }
 
     // trackChrome:
     // @actor: a descendant of the chrome to begin tracking
@@ -830,7 +825,7 @@ var LayoutManager = new Lang.Class({
         }
 
         this._trackActor(actor, params);
-    },
+    }
 
     // untrackChrome:
     // @actor: an actor previously tracked via trackChrome()
@@ -838,7 +833,7 @@ var LayoutManager = new Lang.Class({
     // Undoes the effect of trackChrome()
     untrackChrome(actor) {
         this._untrackActor(actor);
-    },
+    }
 
     // removeChrome:
     // @actor: a chrome actor
@@ -847,7 +842,7 @@ var LayoutManager = new Lang.Class({
     removeChrome(actor) {
         this.uiGroup.remove_actor(actor);
         this._untrackActor(actor);
-    },
+    }
 
     _findActor(actor) {
         for (let i = 0; i < this._trackedActors.length; i++) {
@@ -856,7 +851,7 @@ var LayoutManager = new Lang.Class({
                 return i;
         }
         return -1;
-    },
+    }
 
     _trackActor(actor, params) {
         if (this._findActor(actor) != -1)
@@ -876,7 +871,7 @@ var LayoutManager = new Lang.Class({
         this._trackedActors.push(actorData);
         this._updateActorVisibility(actorData);
         this._queueUpdateRegions();
-    },
+    }
 
     _untrackActor(actor) {
         let i = this._findActor(actor);
@@ -891,7 +886,7 @@ var LayoutManager = new Lang.Class({
         actor.disconnect(actorData.destroyId);
 
         this._queueUpdateRegions();
-    },
+    }
 
     _updateActorVisibility(actorData) {
         if (!actorData.trackFullscreen)
@@ -901,7 +896,7 @@ var LayoutManager = new Lang.Class({
         actorData.actor.visible = !(global.window_group.visible &&
                                     monitor &&
                                     monitor.inFullscreen);
-    },
+    }
 
     _updateVisibility() {
         let windowsVisible = Main.sessionMode.hasWindows && !this._inOverview;
@@ -910,7 +905,7 @@ var LayoutManager = new Lang.Class({
         global.top_window_group.visible = windowsVisible;
 
         this._trackedActors.forEach(this._updateActorVisibility.bind(this));
-    },
+    }
 
     getWorkAreaForMonitor(monitorIndex) {
         // Assume that all workspaces will have the same
@@ -918,7 +913,7 @@ var LayoutManager = new Lang.Class({
         let workspaceManager = global.workspace_manager;
         let ws = workspaceManager.get_workspace_by_index(0);
         return ws.get_work_area_for_monitor(monitorIndex);
-    },
+    }
 
     // This call guarantees that we return some monitor to simplify usage of it
     // In practice all tracked actors should be visible on some monitor anyway
@@ -927,14 +922,14 @@ var LayoutManager = new Lang.Class({
         let [w, h] = actor.get_transformed_size();
         let rect = new Meta.Rectangle({ x: x, y: y, width: w, height: h });
         return global.display.get_monitor_index_for_rect(rect);
-    },
+    }
 
     findMonitorForActor(actor) {
         let index = this.findIndexForActor(actor);
         if (index >= 0 && index < this.monitors.length)
             return this.monitors[index];
         return null;
-    },
+    }
 
     _queueUpdateRegions() {
         if (this._startingUp)
@@ -943,19 +938,19 @@ var LayoutManager = new Lang.Class({
         if (!this._updateRegionIdle)
             this._updateRegionIdle = Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
                                                     this._updateRegions.bind(this));
-    },
+    }
 
     _getWindowActorsForWorkspace(workspace) {
         return global.get_window_actors().filter(actor => {
             let win = actor.meta_window;
             return win.located_on_workspace(workspace);
         });
-    },
+    }
 
     _updateFullscreen() {
         this._updateVisibility();
         this._queueUpdateRegions();
-    },
+    }
 
     _windowsRestacked() {
         let changed = false;
@@ -967,7 +962,7 @@ var LayoutManager = new Lang.Class({
             this._updateVisibility();
             this._queueUpdateRegions();
         }
-    },
+    }
 
     _updateRegions() {
         if (this._updateRegionIdle) {
@@ -1067,13 +1062,13 @@ var LayoutManager = new Lang.Class({
         }
 
         return GLib.SOURCE_REMOVE;
-    },
+    }
 
     modalEnded() {
         // We don't update the stage input region while in a modal,
         // so queue an update now.
         this._queueUpdateRegions();
-    },
+    }
 });
 
 
diff --git a/js/ui/lightbox.js b/js/ui/lightbox.js
index 120aafd6f..920f1d3a0 100644
--- a/js/ui/lightbox.js
+++ b/js/ui/lightbox.js
@@ -1,7 +1,7 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
 const Clutter = imports.gi.Clutter;
-const Lang = imports.lang;
+const GObject = imports.gi.GObject;
 const Meta = imports.gi.Meta;
 const Signals = imports.signals;
 const St = imports.gi.St;
@@ -27,38 +27,36 @@ t = clamp(t, 0.0, 1.0);\n\
 float pixel_brightness = mix(1.0, 1.0 - vignette_sharpness, t);\n\
 cogl_color_out.a = cogl_color_out.a * (1 - pixel_brightness * brightness);';
 
-var RadialShaderQuad = new Lang.Class({
-    Name: 'RadialShaderQuad',
-    Extends: Shell.GLSLQuad,
-
+var RadialShaderQuad = GObject.registerClass(
+class RadialShaderQuad extends Shell.GLSLQuad {
     _init(params) {
-        this.parent(params);
+        super._init(params);
 
         this._brightnessLocation = this.get_uniform_location('brightness');
         this._sharpnessLocation = this.get_uniform_location('vignette_sharpness');
 
         this.brightness = 1.0;
         this.vignetteSharpness = 0.0;
-    },
+    }
 
     vfunc_build_pipeline() {
         this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT,
                               VIGNETTE_DECLARATIONS, VIGNETTE_CODE, true);
-    },
+    }
 
     get brightness() {
         return this._brightness;
-    },
+    }
 
     set brightness(v) {
         this._brightness = v;
         this.set_uniform_float(this._brightnessLocation,
                                1, [this._brightness]);
-    },
+    }
 
     get vignetteSharpness() {
         return this._sharpness;
-    },
+    }
 
     set vignetteSharpness(v) {
         this._sharpness = v;
diff --git a/js/ui/lookingGlass.js b/js/ui/lookingGlass.js
index 26e21c4ee..ce1402149 100644
--- a/js/ui/lookingGlass.js
+++ b/js/ui/lookingGlass.js
@@ -11,7 +11,6 @@ const Pango = imports.gi.Pango;
 const St = imports.gi.St;
 const Shell = imports.gi.Shell;
 const Signals = imports.signals;
-const Lang = imports.lang;
 const Mainloop = imports.mainloop;
 const System = imports.system;
 
@@ -462,10 +461,8 @@ var ObjInspector = class ObjInspector {
     }
 };
 
-var RedBorderEffect = new Lang.Class({
-    Name: 'RedBorderEffect',
-    Extends: Clutter.Effect,
-
+var RedBorderEffect = GObject.registerClass(
+class RedBorderEffect extends Clutter.Effect {
     vfunc_paint() {
         let actor = this.get_actor();
         actor.continue_paint();
@@ -485,17 +482,15 @@ var RedBorderEffect = new Lang.Class({
                        geom.width - width, geom.height - width);
         Cogl.rectangle(0, geom.height - width,
                        width, width);
-    },
+    }
 });
 
-var Inspector = new Lang.Class({
-    Name: 'Inspector',
-    Extends: Clutter.Actor,
+var Inspector = GObject.registerClass({
     Signals: { 'closed': {},
                'target': { param_types: [Clutter.Actor.$gtype, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] } },
-
+}, class Inspector extends Clutter.Actor {
     _init(lookingGlass) {
-        this.parent({ width: 0,
+        super._init({ width: 0,
                       height: 0 });
 
         Main.uiGroup.add_actor(this);
@@ -524,7 +519,7 @@ var Inspector = new Lang.Class({
         this._pointerTarget = null;
 
         this._lookingGlass = lookingGlass;
-    },
+    }
 
     vfunc_allocate(box, flags) {
         this.set_allocation(box, flags);
@@ -543,7 +538,7 @@ var Inspector = new Lang.Class({
         childBox.y1 = primary.y + Math.floor((primary.height - natHeight) / 2);
         childBox.y2 = childBox.y1 + natHeight;
         this._eventHandler.allocate(childBox, flags);
-    },
+    }
 
     _close() {
         Clutter.ungrab_pointer();
@@ -551,13 +546,13 @@ var Inspector = new Lang.Class({
         this._eventHandler.destroy();
         this._eventHandler = null;
         this.emit('closed');
-    },
+    }
 
     _onKeyPressEvent(actor, event) {
         if (event.get_key_symbol() == Clutter.Escape)
             this._close();
         return Clutter.EVENT_STOP;
-    },
+    }
 
     _onButtonPressEvent(actor, event) {
         if (this._target) {
@@ -566,7 +561,7 @@ var Inspector = new Lang.Class({
         }
         this._close();
         return Clutter.EVENT_STOP;
-    },
+    }
 
     _onScrollEvent(actor, event) {
         switch (event.get_scroll_direction()) {
@@ -600,12 +595,12 @@ var Inspector = new Lang.Class({
             break;
         }
         return Clutter.EVENT_STOP;
-    },
+    }
 
     _onMotionEvent(actor, event) {
         this._update(event);
         return Clutter.EVENT_STOP;
-    },
+    }
 
     _update(event) {
         let [stageX, stageY] = event.get_coords();
diff --git a/js/ui/messageList.js b/js/ui/messageList.js
index f8ef745d4..510f1b007 100644
--- a/js/ui/messageList.js
+++ b/js/ui/messageList.js
@@ -3,7 +3,6 @@ const Clutter = imports.gi.Clutter;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
-const Lang = imports.lang;
 const Main = imports.ui.main;
 const MessageTray = imports.ui.messageTray;
 const Meta = imports.gi.Meta;
@@ -160,14 +159,12 @@ var URLHighlighter = class URLHighlighter {
     }
 };
 
-var ScaleLayout = new Lang.Class({
-    Name: 'ScaleLayout',
-    Extends: Clutter.BinLayout,
-
+var ScaleLayout = new GObject.registerClass(
+class ScaleLayout extends Clutter.BinLayout {
     _init(params) {
         this._container = null;
-        this.parent(params);
-    },
+        super._init(params);
+    }
 
     _connectContainer(container) {
         if (this._container == container)
@@ -187,45 +184,43 @@ var ScaleLayout = new Lang.Class({
                 });
                 this._signals.push(id);
             }
-    },
+    }
 
     vfunc_get_preferred_width(container, forHeight) {
         this._connectContainer(container);
 
-        let [min, nat] = this.parent(container, forHeight);
+        let [min, nat] = super.vfunc_get_preferred_width(container, forHeight);
         return [Math.floor(min * container.scale_x),
                 Math.floor(nat * container.scale_x)];
-    },
+    }
 
     vfunc_get_preferred_height(container, forWidth) {
         this._connectContainer(container);
 
-        let [min, nat] = this.parent(container, forWidth);
+        let [min, nat] = super.vfunc_get_preferred_height(container, forWidth);
         return [Math.floor(min * container.scale_y),
                 Math.floor(nat * container.scale_y)];
     }
 });
 
-var LabelExpanderLayout = new Lang.Class({
-    Name: 'LabelExpanderLayout',
-    Extends: Clutter.LayoutManager,
+var LabelExpanderLayout = GObject.registerClass({
     Properties: { 'expansion': GObject.ParamSpec.double('expansion',
                                                         'Expansion',
                                                         'Expansion of the layout, between 0 (collapsed) ' +
                                                         'and 1 (fully expanded',
                                                          GObject.ParamFlags.READABLE | 
GObject.ParamFlags.WRITABLE,
                                                          0, 1, 0)},
-
+}, class LabelExpanderLayout extends Clutter.LayoutManager {
     _init(params) {
         this._expansion = 0;
         this._expandLines = DEFAULT_EXPAND_LINES;
 
-        this.parent(params);
-    },
+        super._init(params);
+    }
 
     get expansion() {
         return this._expansion;
-    },
+    }
 
     set expansion(v) {
         if (v == this._expansion)
@@ -238,7 +233,7 @@ var LabelExpanderLayout = new Lang.Class({
             this._container.get_child_at_index(i).visible = (i == visibleIndex);
 
         this.layout_changed();
-    },
+    }
 
     set expandLines(v) {
         if (v == this._expandLines)
@@ -246,11 +241,11 @@ var LabelExpanderLayout = new Lang.Class({
         this._expandLines = v;
         if (this._expansion > 0)
             this.layout_changed();
-    },
+    }
 
     vfunc_set_container(container) {
         this._container = container;
-    },
+    }
 
     vfunc_get_preferred_width(container, forHeight) {
         let [min, nat] = [0, 0];
@@ -265,7 +260,7 @@ var LabelExpanderLayout = new Lang.Class({
         }
 
         return [min, nat];
-    },
+    }
 
     vfunc_get_preferred_height(container, forWidth) {
         let [min, nat] = [0, 0];
@@ -283,7 +278,7 @@ var LabelExpanderLayout = new Lang.Class({
         }
 
         return [min, nat];
-    },
+    }
 
     vfunc_allocate(container, box, flags) {
         for (let i = 0; i < container.get_n_children(); i++) {
diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js
index ebc7ae2fc..0fd739834 100644
--- a/js/ui/messageTray.js
+++ b/js/ui/messageTray.js
@@ -6,7 +6,6 @@ const Gio = imports.gi.Gio;
 const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 const Atk = imports.gi.Atk;
-const Lang = imports.lang;
 const Mainloop = imports.mainloop;
 const Meta = imports.gi.Meta;
 const Pango = imports.gi.Pango;
@@ -568,12 +567,10 @@ class NotificationBanner extends Calendar.NotificationMessage {
     }
 };
 
-var SourceActor = new Lang.Class({
-    Name: 'SourceActor',
-    Extends: St.Widget,
-
+var SourceActor = GObject.registerClass(
+class SourceActor extends St.Widget {
     _init(source, size) {
-        this.parent();
+        super._init();
 
         this._source = source;
         this._size = size;
@@ -595,12 +592,12 @@ var SourceActor = new Lang.Class({
 
         this._iconUpdatedId = this._source.connect('icon-updated', this._updateIcon.bind(this));
         this._updateIcon();
-    },
+    }
 
     setIcon(icon) {
         this._iconBin.child = icon;
         this._iconSet = true;
-    },
+    }
 
     _updateIcon() {
         if (this._actorDestroyed)
@@ -611,12 +608,10 @@ var SourceActor = new Lang.Class({
     }
 });
 
-var SourceActorWithLabel = new Lang.Class({
-    Name: 'SourceActorWithLabel',
-    Extends: SourceActor,
-
+var SourceActorWithLabel = GObject.registerClass(
+class SourceActorWithLabel extends SourceActor {
     _init(source, size) {
-        this.parent(source, size);
+        super._init(source, size);
 
         this._counterLabel = new St.Label({ x_align: Clutter.ActorAlign.CENTER,
                                             x_expand: true,
@@ -642,10 +637,10 @@ var SourceActorWithLabel = new Lang.Class({
         this.connect('destroy', () => {
             this._source.disconnect(this._countUpdatedId);
         });
-    },
+    }
 
     vfunc_allocate(box, flags) {
-        this.parent(box, flags);
+        super.vfunc_allocate(box, flags);
 
         let childBox = new Clutter.ActorBox();
 
@@ -666,7 +661,7 @@ var SourceActorWithLabel = new Lang.Class({
         childBox.y2 = box.y2;
 
         this._counterBin.allocate(childBox, flags);
-    },
+    }
 
     _updateCount() {
         if (this._actorDestroyed)
diff --git a/js/ui/osdWindow.js b/js/ui/osdWindow.js
index 557fe1d4b..018d4f660 100644
--- a/js/ui/osdWindow.js
+++ b/js/ui/osdWindow.js
@@ -2,10 +2,10 @@
 
 const Clutter = imports.gi.Clutter;
 const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
 const St = imports.gi.St;
 
 const BarLevel = imports.ui.barLevel;
-const Lang = imports.lang;
 const Layout = imports.ui.layout;
 const Main = imports.ui.main;
 const Mainloop = imports.mainloop;
@@ -49,20 +49,18 @@ var LevelBar = class extends BarLevel.BarLevel {
     }
 };
 
-var OsdWindowConstraint = new Lang.Class({
-    Name: 'OsdWindowConstraint',
-    Extends: Clutter.Constraint,
-
+var OsdWindowConstraint = GObject.registerClass(
+class OsdWindowConstraint extends Clutter.Constraint {
     _init(props) {
         this._minSize = 0;
-        this.parent(props);
-    },
+        super._init(props);
+    }
 
     set minSize(v) {
         this._minSize = v;
         if (this.actor)
             this.actor.queue_relayout();
-    },
+    }
 
     vfunc_update_allocation(actor, actorBox) {
         // Clutter will adjust the allocation for margins,
diff --git a/js/ui/overviewControls.js b/js/ui/overviewControls.js
index d57c27ac2..3cf354423 100644
--- a/js/ui/overviewControls.js
+++ b/js/ui/overviewControls.js
@@ -2,7 +2,6 @@
 
 const GObject = imports.gi.GObject;
 const Clutter = imports.gi.Clutter;
-const Lang = imports.lang;
 const Meta = imports.gi.Meta;
 const St = imports.gi.St;
 const Shell = imports.gi.Shell;
@@ -30,17 +29,15 @@ var SlideDirection = {
     RIGHT: 1
 };
 
-var SlideLayout = new Lang.Class({
-    Name: 'SlideLayout',
-    Extends: Clutter.FixedLayout,
-
+var SlideLayout = GObject.registerClass(
+class SlideLayout extends Clutter.FixedLayout {
     _init(params) {
         this._slideX = 1;
         this._translationX = undefined;
         this._direction = SlideDirection.LEFT;
 
-        this.parent(params);
-    },
+        super._init(params);
+    }
 
     vfunc_get_preferred_width(container, forHeight) {
         let child = container.get_first_child();
@@ -51,7 +48,7 @@ var SlideLayout = new Lang.Class({
         natWidth *= this._slideX;
 
         return [minWidth, natWidth];
-    },
+    }
 
     vfunc_allocate(container, box, flags) {
         let child = container.get_first_child();
@@ -74,34 +71,34 @@ var SlideLayout = new Lang.Class({
         actorBox.y2 = actorBox.y1 + availHeight;
 
         child.allocate(actorBox, flags);
-    },
+    }
 
     set slideX(value) {
         this._slideX = value;
         this.layout_changed();
-    },
+    }
 
     get slideX() {
         return this._slideX;
-    },
+    }
 
     set slideDirection(direction) {
         this._direction = direction;
         this.layout_changed();
-    },
+    }
 
     get slideDirection() {
         return this._direction;
-    },
+    }
 
     set translationX(value) {
         this._translationX = value;
         this.layout_changed();
-    },
+    }
 
     get translationX() {
         return this._translationX;
-    },
+    }
 });
 
 var SlidingControl = class {
@@ -354,15 +351,13 @@ var DashSlider = class extends SlidingControl {
     }
 };
 
-var DashSpacer = new Lang.Class({
-    Name: 'DashSpacer',
-    Extends: St.Widget,
-
+var DashSpacer = GObject.registerClass(
+class DashSpacer extends St.Widget {
     _init(params) {
-        this.parent(params);
+        super._init(params);
 
         this._bindConstraint = null;
-    },
+    }
 
     setDashActor(dashActor) {
         if (this._bindConstraint) {
@@ -375,30 +370,28 @@ var DashSpacer = new Lang.Class({
                                                                 coordinate: Clutter.BindCoordinate.SIZE });
             this.add_constraint(this._bindConstraint);
         }
-    },
+    }
 
     vfunc_get_preferred_width(forHeight) {
         let box = this.get_allocation_box();
-        let minWidth = this.parent(forHeight)[0];
+        let minWidth = super.vfunc_get_preferred_width(forHeight)[0];
         let natWidth = box.x2 - box.x1;
         return [minWidth, natWidth];
-    },
+    }
 
     vfunc_get_preferred_height(forWidth) {
         let box = this.get_allocation_box();
-        let minHeight = this.parent(forWidth)[0];
+        let minHeight = super.vfunc_get_preferred_height(forWidth)[0];
         let natHeight = box.y2 - box.y1;
         return [minHeight, natHeight];
     }
 });
 
-var ControlsLayout = new Lang.Class({
-    Name: 'ControlsLayout',
-    Extends: Clutter.BinLayout,
+var ControlsLayout = GObject.registerClass({
     Signals: { 'allocation-changed': { flags: GObject.SignalFlags.RUN_LAST } },
-
+}, class ControlsLayout extends Clutter.BinLayout {
     vfunc_allocate(container, box, flags) {
-        this.parent(container, box, flags);
+        super.vfunc_allocate(container, box, flags);
         this.emit('allocation-changed');
     }
 });
diff --git a/js/ui/padOsd.js b/js/ui/padOsd.js
index 79b3eeb79..2cc449d9f 100644
--- a/js/ui/padOsd.js
+++ b/js/ui/padOsd.js
@@ -1,6 +1,5 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
-const Lang = imports.lang;
 const Meta = imports.gi.Meta;
 const Shell = imports.gi.Shell;
 const Clutter = imports.gi.Clutter;
@@ -285,9 +284,7 @@ var ActionEditor = class {
 };
 Signals.addSignalMethods(ActionEditor.prototype);
 
-var PadDiagram = new Lang.Class({
-    Name: 'PadDiagram',
-    Extends: St.DrawingArea,
+var PadDiagram = GObject.registerClass({
     Properties: { 'left-handed': GObject.ParamSpec.boolean('left-handed',
                                                            'left-handed', 'Left handed',
                                                            GObject.ParamFlags.READWRITE |
@@ -303,7 +300,7 @@ var PadDiagram = new Lang.Class({
                                                            GObject.ParamFlags.READWRITE |
                                                            GObject.ParamFlags.CONSTRUCT_ONLY,
                                                            Clutter.Actor.$gtype) },
-
+}, class PadDiagram extends St.DrawingArea {
     _init(params) {
         let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/pad-osd.css');
         let [success, css, etag] = file.load_contents(null);
@@ -314,20 +311,20 @@ var PadDiagram = new Lang.Class({
         this._css = css;
         this._labels = [];
         this._activeButtons = [];
-        this.parent(params);
-    },
+        super._init(params);
+    }
 
     get left_handed() {
         return this._leftHanded;
-    },
+    }
 
     set left_handed(leftHanded) {
         this._leftHanded = leftHanded;
-    },
+    }
 
     get image() {
         return this._imagePath;
-    },
+    }
 
     set image(imagePath) {
         let originalHandle = Rsvg.Handle.new_from_file(imagePath);
@@ -337,17 +334,17 @@ var PadDiagram = new Lang.Class({
 
         this._imagePath = imagePath;
         this._handle = this._composeStyledDiagram();
-    },
+    }
 
     get editor_actor() {
         return this._editorActor;
-    },
+    }
 
     set editor_actor(actor) {
         actor.hide();
         this._editorActor = actor;
         this.add_actor(actor);
-    },
+    }
 
     _wrappingSvgHeader() {
         return ('<?xml version="1.0" encoding="UTF-8" standalone="no"?>' +
@@ -355,13 +352,13 @@ var PadDiagram = new Lang.Class({
                 'xmlns:xi="http://www.w3.org/2001/XInclude"; ' +
                 'width="' + this._imageWidth + '" height="' + this._imageHeight + '"> ' +
                 '<style type="text/css">');
-    },
+    }
 
     _wrappingSvgFooter() {
         return ('</style>' +
                 '<xi:include href="' + this._imagePath + '" />' +
                 '</svg>');
-    },
+    }
 
     _cssString() {
         let css = this._css;
@@ -375,7 +372,7 @@ var PadDiagram = new Lang.Class({
         }
 
         return css;
-    },
+    }
 
     _composeStyledDiagram() {
         let svgData = '';
@@ -393,7 +390,7 @@ var PadDiagram = new Lang.Class({
         handle.close();
 
         return handle;
-    },
+    }
 
     _updateDiagramScale() {
         if (this._handle == null)
@@ -404,7 +401,7 @@ var PadDiagram = new Lang.Class({
         let scaleX = this._actorWidth / dimensions.width;
         let scaleY = this._actorHeight / dimensions.height;
         this._scale = Math.min(scaleX, scaleY);
-    },
+    }
 
     _allocateChild(child, x, y, direction) {
         let [prefHeight, natHeight] = child.get_preferred_height(-1);
@@ -422,10 +419,10 @@ var PadDiagram = new Lang.Class({
         childBox.y1 = y - natHeight / 2;
         childBox.y2 = y + natHeight / 2;
         child.allocate(childBox, 0);
-    },
+    }
 
     vfunc_allocate(box, flags) {
-        this.parent(box, flags);
+        super.vfunc_allocate(box, flags);
         this._updateDiagramScale();
 
         for (let i = 0; i < this._labels.length; i++) {
@@ -439,7 +436,7 @@ var PadDiagram = new Lang.Class({
             let [found, x, y, arrangement] = this.getLabelCoords(action, idx, dir);
             this._allocateChild(this._editorActor, x, y, arrangement);
         }
-    },
+    }
 
     vfunc_repaint() {
         if (this._handle == null)
@@ -461,7 +458,7 @@ var PadDiagram = new Lang.Class({
         this._handle.render_cairo(cr);
         cr.restore();
         cr.$dispose();
-    },
+    }
 
     _transformPoint(x, y) {
         if (this._handle == null || this._scale == null)
@@ -472,7 +469,7 @@ var PadDiagram = new Lang.Class({
         x = x * this._scale + this._actorWidth / 2 - dimensions.width / 2 * this._scale;
         y = y * this._scale + this._actorHeight / 2 - dimensions.height / 2 * this._scale;;
         return [Math.round(x), Math.round(y)];
-    },
+    }
 
     _getItemLabelCoords(labelName, leaderName) {
         if (this._handle == null)
@@ -504,7 +501,7 @@ var PadDiagram = new Lang.Class({
         let [x, y] = this._transformPoint(pos.x, pos.y)
 
         return [true, x, y, direction];
-    },
+    }
 
     getButtonLabelCoords(button) {
         let ch = String.fromCharCode('A'.charCodeAt() + button);
@@ -512,7 +509,7 @@ var PadDiagram = new Lang.Class({
         let leaderName = 'Leader' + ch;
 
         return this._getItemLabelCoords(labelName, leaderName);
-    },
+    }
 
     getRingLabelCoords(number, dir) {
         let numStr = number > 0 ? (number + 1).toString() : '';
@@ -521,7 +518,7 @@ var PadDiagram = new Lang.Class({
         let leaderName = 'LeaderRing' + numStr + dirStr;
 
         return this._getItemLabelCoords(labelName, leaderName);
-    },
+    }
 
     getStripLabelCoords(number, dir) {
         let numStr = number > 0 ? (number + 1).toString() : '';
@@ -530,7 +527,7 @@ var PadDiagram = new Lang.Class({
         let leaderName = 'LeaderStrip' + numStr + dirStr;
 
         return this._getItemLabelCoords(labelName, leaderName);
-    },
+    }
 
     getLabelCoords(action, idx, dir) {
         if (action == Meta.PadActionType.BUTTON)
@@ -541,19 +538,19 @@ var PadDiagram = new Lang.Class({
             return this.getStripLabelCoords(idx, dir);
 
         return [false];
-    },
+    }
 
     _invalidateSvg() {
         if (this._handle == null)
             return;
         this._handle = this._composeStyledDiagram();
         this.queue_repaint();
-    },
+    }
 
     activateButton(button) {
         this._activeButtons.push(button);
         this._invalidateSvg();
-    },
+    }
 
     deactivateButton(button) {
         for (let i = 0; i < this._activeButtons.length; i++) {
@@ -561,12 +558,12 @@ var PadDiagram = new Lang.Class({
                 this._activeButtons.splice(i, 1);
         }
         this._invalidateSvg();
-    },
+    }
 
     addLabel(label, type, idx, dir) {
         this._labels.push([label, type, idx, dir]);
         this.add_actor(label);
-    },
+    }
 
     _applyLabel(label, action, idx, dir, str) {
         if (str != null) {
@@ -576,7 +573,7 @@ var PadDiagram = new Lang.Class({
             this._allocateChild(label, x, y, arrangement);
         }
         label.show();
-    },
+    }
 
     stopEdition(continues, str) {
         this._editorActor.hide();
@@ -594,7 +591,7 @@ var PadDiagram = new Lang.Class({
                 this._prevEdited = this._curEdited;
             this._curEdited = null;
         }
-    },
+    }
 
     startEdition(action, idx, dir) {
         let editedLabel;
diff --git a/js/ui/panel.js b/js/ui/panel.js
index 13eab5bed..3e3f4d4d8 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -4,8 +4,8 @@ const Cairo = imports.cairo;
 const Clutter = imports.gi.Clutter;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
 const Mainloop = imports.mainloop;
 const Meta = imports.gi.Meta;
 const Pango = imports.gi.Pango;
@@ -83,13 +83,11 @@ function _unpremultiply(color) {
  * this menu also handles startup notification for it.  So when we
  * have an active startup notification, we switch modes to display that.
  */
-var AppMenuButton = new Lang.Class({
-    Name: 'AppMenuButton',
-    Extends: PanelMenu.Button,
+var AppMenuButton = GObject.registerClass({
     Signals: {'changed': {}},
-
+}, class AppMenuButton extends PanelMenu.Button {
     _init(panel) {
-        this.parent(0.0, null, true);
+        super._init(0.0, null, true);
 
         this.actor.accessible_role = Atk.Role.MENU;
 
@@ -148,7 +146,7 @@ var AppMenuButton = new Lang.Class({
             global.window_manager.connect('switch-workspace', this._sync.bind(this));
 
         this._sync();
-    },
+    }
 
     fadeIn() {
         if (this._visible)
@@ -162,7 +160,7 @@ var AppMenuButton = new Lang.Class({
                          { opacity: 255,
                            time: Overview.ANIMATION_TIME,
                            transition: 'easeOutQuad' });
-    },
+    }
 
     fadeOut() {
         if (!this._visible)
@@ -179,7 +177,7 @@ var AppMenuButton = new Lang.Class({
                                this.hide();
                            },
                            onCompleteScope: this });
-    },
+    }
 
     _onStyleChanged(actor) {
         let node = actor.get_theme_node();
@@ -190,7 +188,7 @@ var AppMenuButton = new Lang.Class({
         this._spinner = new Animation.AnimatedIcon(this._spinnerIcon, PANEL_ICON_SIZE);
         this._container.add_actor(this._spinner.actor);
         this._spinner.actor.hide();
-    },
+    }
 
     _syncIcon() {
         if (!this._targetApp)
@@ -198,14 +196,14 @@ var AppMenuButton = new Lang.Class({
 
         let icon = this._targetApp.create_icon_texture(PANEL_ICON_SIZE - APP_MENU_ICON_MARGIN);
         this._iconBox.set_child(icon);
-    },
+    }
 
     _onIconThemeChanged() {
         if (this._iconBox.child == null)
             return;
 
         this._syncIcon();
-    },
+    }
 
     stopAnimation() {
         if (this._stop)
@@ -227,7 +225,7 @@ var AppMenuButton = new Lang.Class({
                                this._spinner.actor.hide();
                            }
                          });
-    },
+    }
 
     startAnimation() {
         this._stop = false;
@@ -237,7 +235,7 @@ var AppMenuButton = new Lang.Class({
 
         this._spinner.play();
         this._spinner.actor.show();
-    },
+    }
 
     _onAppStateChanged(appSys, app) {
         let state = app.state;
@@ -250,7 +248,7 @@ var AppMenuButton = new Lang.Class({
         // changing.  An example case is how we map OpenOffice.org based on the window
         // title which is a dynamic property.
         this._sync();
-    },
+    }
 
     _focusAppChanged() {
         let tracker = Shell.WindowTracker.get_default();
@@ -263,7 +261,7 @@ var AppMenuButton = new Lang.Class({
                 return;
         }
         this._sync();
-    },
+    }
 
     _findTargetApp() {
         let workspaceManager = global.workspace_manager;
@@ -278,7 +276,7 @@ var AppMenuButton = new Lang.Class({
                 return this._startingApps[i];
 
         return null;
-    },
+    }
 
     _sync() {
         let targetApp = this._findTargetApp();
@@ -332,7 +330,7 @@ var AppMenuButton = new Lang.Class({
         this._syncIcon();
         this._maybeSetMenu();
         this.emit('changed');
-    },
+    }
 
     _maybeSetMenu() {
         let menu;
@@ -365,7 +363,7 @@ var AppMenuButton = new Lang.Class({
         this.setMenu(menu);
         if (menu)
             this._menuManager.addMenu(menu);
-    },
+    }
 
     _onDestroy() {
         if (this._appStateChangedSignalId > 0) {
@@ -395,16 +393,14 @@ var AppMenuButton = new Lang.Class({
             this._switchWorkspaceNotifyId = 0;
         }
 
-        this.parent();
+        super._onDestroy();
     }
 });
 
-var ActivitiesButton = new Lang.Class({
-    Name: 'ActivitiesButton',
-    Extends: PanelMenu.Button,
-
+var ActivitiesButton = GObject.registerClass(
+class ActivitiesButton extends PanelMenu.Button {
     _init() {
-        this.parent(0.0, null, true);
+        super._init(0.0, null, true);
         this.actor.accessible_role = Atk.Role.TOGGLE_BUTTON;
 
         this.actor.name = 'panelActivities';
@@ -430,7 +426,7 @@ var ActivitiesButton = new Lang.Class({
         });
 
         this._xdndTimeOut = 0;
-    },
+    }
 
     handleDragOver(source, actor, x, y, time) {
         if (source != Main.xdndHandler)
@@ -444,7 +440,7 @@ var ActivitiesButton = new Lang.Class({
         GLib.Source.set_name_by_id(this._xdndTimeOut, '[gnome-shell] this._xdndToggleOverview');
 
         return DND.DragMotionResult.CONTINUE;
-    },
+    }
 
     _onCapturedEvent(actor, event) {
         if (event.type() == Clutter.EventType.BUTTON_PRESS ||
@@ -453,10 +449,10 @@ var ActivitiesButton = new Lang.Class({
                 return Clutter.EVENT_STOP;
         }
         return Clutter.EVENT_PROPAGATE;
-    },
+    }
 
     _onEvent(actor, event) {
-        this.parent(actor, event);
+        super._onEvent(actor, event);
 
         if (event.type() == Clutter.EventType.TOUCH_END ||
             event.type() == Clutter.EventType.BUTTON_RELEASE)
@@ -464,7 +460,7 @@ var ActivitiesButton = new Lang.Class({
                 Main.overview.toggle();
 
         return Clutter.EVENT_PROPAGATE;
-    },
+    }
 
     _onKeyRelease(actor, event) {
         let symbol = event.get_key_symbol();
@@ -473,7 +469,7 @@ var ActivitiesButton = new Lang.Class({
                 Main.overview.toggle();
         }
         return Clutter.EVENT_PROPAGATE;
-    },
+    }
 
     _xdndToggleOverview(actor) {
         let [x, y, mask] = global.get_pointer();
@@ -652,23 +648,21 @@ var PanelCorner = class {
     }
 };
 
-var AggregateLayout = new Lang.Class({
-    Name: 'AggregateLayout',
-    Extends: Clutter.BoxLayout,
-
+var AggregateLayout = GObject.registerClass(
+class AggregateLayout extends Clutter.BoxLayout {
     _init(params) {
         if (!params)
             params = {};
         params['orientation'] = Clutter.Orientation.VERTICAL;
-        this.parent(params);
+        super._init(params);
 
         this._sizeChildren = [];
-    },
+    }
 
     addSizeChild(actor) {
         this._sizeChildren.push(actor);
         this.layout_changed();
-    },
+    }
 
     vfunc_get_preferred_width(container, forHeight) {
         let themeNode = container.get_theme_node();
@@ -685,12 +679,10 @@ var AggregateLayout = new Lang.Class({
     }
 });
 
-var AggregateMenu = new Lang.Class({
-    Name: 'AggregateMenu',
-    Extends: PanelMenu.Button,
-
+var AggregateMenu = GObject.registerClass(
+class AggregateMenu extends PanelMenu.Button {
     _init() {
-        this.parent(0.0, C_("System menu in the top bar", "System"), false);
+        super._init(0.0, C_("System menu in the top bar", "System"), false);
         this.menu.actor.add_style_class_name('aggregate-menu');
 
         let menuLayout = new AggregateLayout();
@@ -757,7 +749,7 @@ var AggregateMenu = new Lang.Class({
         menuLayout.addSizeChild(this._rfkill.menu.actor);
         menuLayout.addSizeChild(this._power.menu.actor);
         menuLayout.addSizeChild(this._system.menu.actor);
-    },
+    }
 });
 
 const PANEL_ITEM_IMPLEMENTATIONS = {
@@ -769,12 +761,10 @@ const PANEL_ITEM_IMPLEMENTATIONS = {
     'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
 };
 
-var Panel = new Lang.Class({
-    Name: 'Panel',
-    Extends: St.Widget,
-
+var Panel = GObject.registerClass(
+class Panel extends St.Widget {
     _init() {
-        this.parent({ name: 'panel',
+        super._init({ name: 'panel',
                       reactive: true });
 
         // For compatibility with extensions that still use the
@@ -827,7 +817,7 @@ var Panel = new Lang.Class({
 
         global.display.connect('workareas-changed', () => { this.queue_relayout(); });
         this._updatePanel();
-    },
+    }
 
     _onWindowActorAdded(container, metaWindowActor) {
         let signalIds = [];
@@ -835,7 +825,7 @@ var Panel = new Lang.Class({
             signalIds.push(metaWindowActor.connect(s, this._updateSolidStyle.bind(this)));
         });
         this._trackedWindows.set(metaWindowActor, signalIds);
-    },
+    }
 
     _onWindowActorRemoved(container, metaWindowActor) {
         this._trackedWindows.get(metaWindowActor).forEach(id => {
@@ -843,7 +833,7 @@ var Panel = new Lang.Class({
         });
         this._trackedWindows.delete(metaWindowActor);
         this._updateSolidStyle();
-    },
+    }
 
     vfunc_get_preferred_width(actor, forHeight) {
         let primaryMonitor = Main.layoutManager.primaryMonitor;
@@ -852,10 +842,10 @@ var Panel = new Lang.Class({
             return [0, primaryMonitor.width];
 
         return [0,  0];
-    },
+    }
 
     vfunc_allocate(box, flags) {
-        this.parent(box, flags);
+        super.vfunc_allocate(box, flags);
 
         let allocWidth = box.x2 - box.x1;
         let allocHeight = box.y2 - box.y1;
@@ -931,7 +921,7 @@ var Panel = new Lang.Class({
         childBox.y1 = allocHeight;
         childBox.y2 = allocHeight + cornerHeight;
         this._rightCorner.actor.allocate(childBox, flags);
-    },
+    }
 
     _onButtonPress(actor, event) {
         if (Main.modalCount > 0)
@@ -977,7 +967,7 @@ var Panel = new Lang.Class({
                                      stageX, stageY);
 
         return Clutter.EVENT_STOP;
-    },
+    }
 
     _onKeyPress(actor, event) {
         let symbol = event.get_key_symbol();
@@ -987,7 +977,7 @@ var Panel = new Lang.Class({
         }
 
         return Clutter.EVENT_PROPAGATE;
-    },
+    }
 
     _toggleMenu(indicator) {
         if (!indicator) // menu not supported by current session mode
@@ -1000,15 +990,15 @@ var Panel = new Lang.Class({
         menu.toggle();
         if (menu.isOpen)
             menu.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
-    },
+    }
 
     toggleAppMenu() {
         this._toggleMenu(this.statusArea.appMenu);
-    },
+    }
 
     toggleCalendar() {
         this._toggleMenu(this.statusArea.dateMenu);
-    },
+    }
 
     closeCalendar() {
         let indicator = this.statusArea.dateMenu;
@@ -1020,7 +1010,7 @@ var Panel = new Lang.Class({
             return;
 
         menu.close();
-    },
+    }
 
     set boxOpacity(value) {
         let isReactive = value > 0;
@@ -1031,11 +1021,11 @@ var Panel = new Lang.Class({
         this._centerBox.reactive = isReactive;
         this._rightBox.opacity = value;
         this._rightBox.reactive = isReactive;
-    },
+    }
 
     get boxOpacity() {
         return this._leftBox.opacity;
-    },
+    }
 
     _updatePanel() {
         let panel = Main.sessionMode.panel;
@@ -1068,7 +1058,7 @@ var Panel = new Lang.Class({
             this._leftCorner.setStyleParent(this._leftBox);
             this._rightCorner.setStyleParent(this._rightBox);
         }
-    },
+    }
 
     _updateSolidStyle() {
         if (this.has_style_pseudo_class('overview') || !Main.sessionMode.hasWindows) {
@@ -1103,7 +1093,7 @@ var Panel = new Lang.Class({
         else
             this._removeStyleClassName('solid');
 
-    },
+    }
 
     _hideIndicators() {
         for (let role in PANEL_ITEM_IMPLEMENTATIONS) {
@@ -1112,7 +1102,7 @@ var Panel = new Lang.Class({
                 continue;
             indicator.container.hide();
         }
-    },
+    }
 
     _ensureIndicator(role) {
         let indicator = this.statusArea[role];
@@ -1126,7 +1116,7 @@ var Panel = new Lang.Class({
             this.statusArea[role] = indicator;
         }
         return indicator;
-    },
+    }
 
     _updateBox(elements, box) {
         let nChildren = box.get_n_children();
@@ -1139,7 +1129,7 @@ var Panel = new Lang.Class({
 
             this._addToPanelBox(role, indicator, i + nChildren, box);
         }
-    },
+    }
 
     _addToPanelBox(role, indicator, position, box) {
         let container = indicator.container;
@@ -1160,7 +1150,7 @@ var Panel = new Lang.Class({
         });
         indicator.connect('menu-set', this._onMenuSet.bind(this));
         this._onMenuSet(indicator);
-    },
+    }
 
     addToStatusArea(role, indicator, position, box) {
         if (this.statusArea[role])
@@ -1179,19 +1169,19 @@ var Panel = new Lang.Class({
         this.statusArea[role] = indicator;
         this._addToPanelBox(role, indicator, position, boxContainer);
         return indicator;
-    },
+    }
 
     _addStyleClassName(className) {
         this.add_style_class_name(className);
         this._rightCorner.actor.add_style_class_name(className);
         this._leftCorner.actor.add_style_class_name(className);
-    },
+    }
 
     _removeStyleClassName(className) {
         this.remove_style_class_name(className);
         this._rightCorner.actor.remove_style_class_name(className);
         this._leftCorner.actor.remove_style_class_name(className);
-    },
+    }
 
     _onMenuSet(indicator) {
         if (!indicator.menu || indicator.menu.hasOwnProperty('_openChangedId'))
diff --git a/js/ui/panelMenu.js b/js/ui/panelMenu.js
index d6c7b10b7..13cc72f7b 100644
--- a/js/ui/panelMenu.js
+++ b/js/ui/panelMenu.js
@@ -2,8 +2,8 @@
 
 const Clutter = imports.gi.Clutter;
 const Gio = imports.gi.Gio;
+const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
 const Shell = imports.gi.Shell;
 const Signals = imports.signals;
 const St = imports.gi.St;
@@ -13,14 +13,12 @@ const Main = imports.ui.main;
 const Params = imports.misc.params;
 const PopupMenu = imports.ui.popupMenu;
 
-var ButtonBox = new Lang.Class({
-    Name: 'ButtonBox',
-    Extends: St.Widget,
-
+var ButtonBox = GObject.registerClass(
+class ButtonBox extends St.Widget {
     _init(params) {
         params = Params.parse(params, { style_class: 'panel-button' }, true);
 
-        this.parent(params);
+        super._init(params);
 
         this.actor = this;
         this._delegate = this;
@@ -33,14 +31,14 @@ var ButtonBox = new Lang.Class({
         this.connect('destroy', this._onDestroy.bind(this));
 
         this._minHPadding = this._natHPadding = 0.0;
-    },
+    }
 
     _onStyleChanged(actor) {
         let themeNode = actor.get_theme_node();
 
         this._minHPadding = themeNode.get_length('-minimum-hpadding');
         this._natHPadding = themeNode.get_length('-natural-hpadding');
-    },
+    }
 
     vfunc_get_preferred_width(forHeight) {
         let child = this.get_first_child();
@@ -55,7 +53,7 @@ var ButtonBox = new Lang.Class({
         naturalSize += 2 * this._natHPadding;
 
         return [minimumSize, naturalSize];
-    },
+    }
 
     vfunc_get_preferred_height(forWidth) {
         let child = this.get_first_child();
@@ -64,7 +62,7 @@ var ButtonBox = new Lang.Class({
             return child.get_preferred_height(-1);
 
         return [0, 0];
-    },
+    }
 
     vfunc_allocate(box, flags) {
         this.set_allocation(box, flags);
@@ -91,21 +89,19 @@ var ButtonBox = new Lang.Class({
         childBox.y2 = availHeight;
 
         child.allocate(childBox, flags);
-    },
+    }
 
     _onDestroy() {
         this.container.child = null;
         this.container.destroy();
-    },
+    }
 });
 
-var Button = new Lang.Class({
-    Name: 'PanelMenuButton',
-    Extends: ButtonBox,
+var Button = GObject.registerClass({
     Signals: {'menu-set': {} },
-
+}, class PanelMenuButton extends ButtonBox {
     _init(menuAlignment, nameText, dontCreateMenu) {
-        this.parent({ reactive: true,
+        super._init({ reactive: true,
                       can_focus: true,
                       track_hover: true,
                       accessible_name: nameText ? nameText : "",
@@ -118,13 +114,13 @@ var Button = new Lang.Class({
             this.menu = new PopupMenu.PopupDummyMenu(this.actor);
         else
             this.setMenu(new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP, 0));
-    },
+    }
 
     setSensitive(sensitive) {
         this.reactive = sensitive;
         this.can_focus = sensitive;
         this.track_hover = sensitive;
-    },
+    }
 
     setMenu(menu) {
         if (this.menu)
@@ -140,7 +136,7 @@ var Button = new Lang.Class({
             this.menu.actor.hide();
         }
         this.emit('menu-set');
-    },
+    }
 
     _onEvent(actor, event) {
         if (this.menu &&
@@ -149,7 +145,7 @@ var Button = new Lang.Class({
             this.menu.toggle();
 
         return Clutter.EVENT_PROPAGATE;
-    },
+    }
 
     _onVisibilityChanged() {
         if (!this.menu)
@@ -157,7 +153,7 @@ var Button = new Lang.Class({
 
         if (!this.actor.visible)
             this.menu.close();
-    },
+    }
 
     _onMenuKeyPress(actor, event) {
         if (global.focus_manager.navigate_from_event(event))
@@ -173,7 +169,7 @@ var Button = new Lang.Class({
             }
         }
         return Clutter.EVENT_PROPAGATE;
-    },
+    }
 
     _onOpenStateChanged(menu, open) {
         if (open)
@@ -193,10 +189,10 @@ var Button = new Lang.Class({
         // factor when computing max-height
         let maxHeight = Math.round((workArea.height - verticalMargins) / scaleFactor);
         this.menu.actor.style = ('max-height: %spx;').format(maxHeight);
-    },
+    }
 
     _onDestroy() {
-        this.parent();
+        super._onDestroy();
 
         if (this.menu)
             this.menu.destroy();
diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js
index b0119455a..f5ba1c299 100644
--- a/js/ui/screenShield.js
+++ b/js/ui/screenShield.js
@@ -6,8 +6,8 @@ const Clutter = imports.gi.Clutter;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const GnomeDesktop = imports.gi.GnomeDesktop;
+const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
 const Mainloop = imports.mainloop;
 const Meta = imports.gi.Meta;
 const Shell = imports.gi.Shell;
@@ -340,12 +340,10 @@ var NotificationsBox = class {
 };
 Signals.addSignalMethods(NotificationsBox.prototype);
 
-var Arrow = new Lang.Class({
-    Name: 'Arrow',
-    Extends: St.Bin,
-
+var Arrow = GObject.registerClass(
+class ScreenShieldArrow extends St.Bin {
     _init(params) {
-        this.parent(params);
+        super._init(params);
         this.x_fill = this.y_fill = true;
 
         this._drawingArea = new St.DrawingArea();
@@ -354,7 +352,7 @@ var Arrow = new Lang.Class({
 
         this._shadowHelper = null;
         this._shadowWidth = this._shadowHeight = 0;
-    },
+    }
 
     _drawArrow(arrow) {
         let cr = arrow.get_context();
@@ -372,10 +370,10 @@ var Arrow = new Lang.Class({
         cr.lineTo(w - thickness / 2, h - thickness / 2);
         cr.stroke();
         cr.$dispose();
-    },
+    }
 
     vfunc_get_paint_volume(volume) {
-        if (!this.parent(volume))
+        if (!super.vfunc_get_paint_volume(volume))
             return false;
 
         if (!this._shadow)
@@ -388,7 +386,7 @@ var Arrow = new Lang.Class({
         volume.set_height(Math.max(shadow_box.y2 - shadow_box.y1, volume.get_height()));
 
         return true;
-    },
+    }
 
     vfunc_style_changed() {
         let node = this.get_theme_node();
@@ -398,8 +396,8 @@ var Arrow = new Lang.Class({
         else
             this._shadowHelper = null;
 
-        this.parent();
-    },
+        super.vfunc_style_changed();
+    }
 
     vfunc_paint() {
         if (this._shadowHelper) {
diff --git a/js/ui/search.js b/js/ui/search.js
index a3ddf537a..df359ae70 100644
--- a/js/ui/search.js
+++ b/js/ui/search.js
@@ -1,9 +1,9 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
 const Clutter = imports.gi.Clutter;
-const Lang = imports.lang;
 const GLib = imports.gi.GLib;
 const Gio = imports.gi.Gio;
+const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 const Meta = imports.gi.Meta;
 const Signals = imports.signals;
@@ -24,10 +24,8 @@ const SEARCH_PROVIDERS_SCHEMA = 'org.gnome.desktop.search-providers';
 var MAX_LIST_SEARCH_RESULTS_ROWS = 5;
 var MAX_GRID_SEARCH_RESULTS_ROWS = 1;
 
-var MaxWidthBin = new Lang.Class({
-    Name: 'MaxWidthBin',
-    Extends: St.Bin,
-
+var MaxWidthBin = GObject.registerClass(
+class MaxWidthBin extends St.Bin {
     vfunc_allocate(box, flags) {
         let themeNode = this.get_theme_node();
         let maxWidth = themeNode.get_max_width();
@@ -40,7 +38,7 @@ var MaxWidthBin = new Lang.Class({
             adjustedBox.x2 -= Math.floor(excessWidth / 2);
         }
 
-        this.parent(adjustedBox, flags);
+        super.vfunc_allocate(adjustedBox, flags);
     }
 });
 
@@ -724,15 +722,11 @@ var SearchResults = class {
 };
 Signals.addSignalMethods(SearchResults.prototype);
 
-var ProviderInfo = new Lang.Class({
-    Name: 'ProviderInfo',
-    Extends: St.Button,
-
-    PROVIDER_ICON_SIZE: 32,
-
+var ProviderInfo = GObject.registerClass(
+class ProviderInfo extends St.Button {
     _init(provider) {
         this.provider = provider;
-        this.parent({ style_class: 'search-provider-icon',
+        super._init({ style_class: 'search-provider-icon',
                       reactive: true,
                       can_focus: true,
                       accessible_name: provider.appInfo.get_name(),
@@ -760,14 +754,18 @@ var ProviderInfo = new Lang.Class({
 
         this._content.add_actor(icon);
         this._content.add_actor(detailsBox);
-    },
+    }
+
+    get PROVIDER_ICON_SIZE() {
+        return 32;
+    }
 
     animateLaunch() {
         let appSys = Shell.AppSystem.get_default();
         let app = appSys.lookup_app(this.provider.appInfo.get_id());
         if (app.state == Shell.AppState.STOPPED)
             IconGrid.zoomOutActor(this._content);
-    },
+    }
 
     setMoreCount(count) {
         this._moreLabel.text = ngettext("%d more", "%d more", count).format(count);
diff --git a/js/ui/status/accessibility.js b/js/ui/status/accessibility.js
index adf3ca781..7c438cfaa 100644
--- a/js/ui/status/accessibility.js
+++ b/js/ui/status/accessibility.js
@@ -3,7 +3,7 @@
 const Clutter = imports.gi.Clutter;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
-const Lang = imports.lang;
+const GObject = imports.gi.GObject;
 const Mainloop = imports.mainloop;
 const St = imports.gi.St;
 
@@ -34,12 +34,10 @@ const KEY_TEXT_SCALING_FACTOR       = 'text-scaling-factor';
 
 const HIGH_CONTRAST_THEME           = 'HighContrast';
 
-var ATIndicator = new Lang.Class({
-    Name: 'ATIndicator',
-    Extends: PanelMenu.Button,
-
+var ATIndicator = GObject.registerClass(
+class ATIndicator extends PanelMenu.Button {
     _init() {
-        this.parent(0.0, _("Accessibility"));
+        super._init(0.0, _("Accessibility"));
 
         this._hbox = new St.BoxLayout({ style_class: 'panel-status-menu-box' });
         this._hbox.add_child(new St.Icon({ style_class: 'system-status-icon',
@@ -85,7 +83,7 @@ var ATIndicator = new Lang.Class({
         this.menu.addMenuItem(mouseKeys);
 
         this._syncMenuVisibility();
-    },
+    }
 
     _syncMenuVisibility() {
         this._syncMenuVisibilityIdle = 0;
@@ -96,7 +94,7 @@ var ATIndicator = new Lang.Class({
         this.actor.visible = alwaysShow || items.some(f => !!f.state);
 
         return GLib.SOURCE_REMOVE;
-    },
+    }
 
     _queueSyncMenuVisibility() {
         if (this._syncMenuVisibilityIdle)
@@ -104,7 +102,7 @@ var ATIndicator = new Lang.Class({
 
         this._syncMenuVisibilityIdle = Mainloop.idle_add(this._syncMenuVisibility.bind(this));
         GLib.Source.set_name_by_id(this._syncMenuVisibilityIdle, '[gnome-shell] this._syncMenuVisibility');
-    },
+    }
 
     _buildItemExtended(string, initial_value, writable, on_set) {
         let widget = new PopupMenu.PopupSwitchMenuItem(string, initial_value);
@@ -115,7 +113,7 @@ var ATIndicator = new Lang.Class({
                 on_set(item.state);
             });
         return widget;
-    },
+    }
 
     _buildItem(string, schema, key) {
         let settings = new Gio.Settings({ schema_id: schema });
@@ -130,7 +128,7 @@ var ATIndicator = new Lang.Class({
             settings.is_writable(key),
             enabled => settings.set_boolean(key, enabled));
         return widget;
-    },
+    }
 
     _buildHCItem() {
         let interfaceSettings = new Gio.Settings({ schema_id: DESKTOP_INTERFACE_SCHEMA });
@@ -183,7 +181,7 @@ var ATIndicator = new Lang.Class({
                 }
             });
         return highContrast;
-    },
+    }
 
     _buildFontItem() {
         let settings = new Gio.Settings({ schema_id: DESKTOP_INTERFACE_SCHEMA });
diff --git a/js/ui/status/keyboard.js b/js/ui/status/keyboard.js
index 81646a481..0e5b18504 100644
--- a/js/ui/status/keyboard.js
+++ b/js/ui/status/keyboard.js
@@ -3,8 +3,8 @@
 const Clutter = imports.gi.Clutter;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
 const IBus = imports.gi.IBus;
-const Lang = imports.lang;
 const Meta = imports.gi.Meta;
 const Shell = imports.gi.Shell;
 const Signals = imports.signals;
@@ -73,18 +73,16 @@ var InputSource = class {
 };
 Signals.addSignalMethods(InputSource.prototype);
 
-var InputSourcePopup = new Lang.Class({
-    Name: 'InputSourcePopup',
-    Extends: SwitcherPopup.SwitcherPopup,
-
+var InputSourcePopup = GObject.registerClass(
+class InputSourcePopup extends SwitcherPopup.SwitcherPopup {
     _init(items, action, actionBackward) {
-        this.parent(items);
+        super._init(items);
 
         this._action = action;
         this._actionBackward = actionBackward;
 
         this._switcherList = new InputSourceSwitcher(this._items);
-    },
+    }
 
     _keyPressHandler(keysym, action) {
         if (action == this._action)
@@ -99,25 +97,23 @@ var InputSourcePopup = new Lang.Class({
             return Clutter.EVENT_PROPAGATE;
 
         return Clutter.EVENT_STOP;
-    },
+    }
 
     _finish() {
-        this.parent();
+        super._finish();
 
         this._items[this._selectedIndex].activate(true);
-    },
+    }
 });
 
-var InputSourceSwitcher = new Lang.Class({
-    Name: 'InputSourceSwitcher',
-    Extends: SwitcherPopup.SwitcherList,
-
+var InputSourceSwitcher = GObject.registerClass(
+class InputSourceSwitcher extends SwitcherPopup.SwitcherList {
     _init(items) {
-        this.parent(true);
+        super._init(true);
 
         for (let i = 0; i < items.length; i++)
             this._addIcon(items[i]);
-    },
+    }
 
     _addIcon(item) {
         let box = new St.BoxLayout({ vertical: true });
@@ -780,9 +776,8 @@ function getInputSourceManager() {
     return _inputSourceManager;
 }
 
-var InputSourceIndicatorContainer = new Lang.Class({
-    Name: 'InputSourceIndicatorContainer',
-    Extends: St.Widget,
+var InputSourceIndicatorContainer = GObject.registerClass(
+class InputSourceIndicatorContainer extends St.Widget {
 
     vfunc_get_preferred_width(forHeight) {
         // Here, and in vfunc_get_preferred_height, we need to query
@@ -793,7 +788,7 @@ var InputSourceIndicatorContainer = new Lang.Class({
             return [Math.max(maxWidth[0], width[0]),
                     Math.max(maxWidth[1], width[1])];
         }, [0, 0]);
-    },
+    }
 
     vfunc_get_preferred_height(forWidth) {
         return this.get_children().reduce((maxHeight, child) => {
@@ -801,7 +796,7 @@ var InputSourceIndicatorContainer = new Lang.Class({
             return [Math.max(maxHeight[0], height[0]),
                     Math.max(maxHeight[1], height[1])];
         }, [0, 0]);
-    },
+    }
 
     vfunc_allocate(box, flags) {
         this.set_allocation(box, flags);
@@ -818,12 +813,10 @@ var InputSourceIndicatorContainer = new Lang.Class({
     }
 });
 
-var InputSourceIndicator = new Lang.Class({
-    Name: 'InputSourceIndicator',
-    Extends: PanelMenu.Button,
-
+var InputSourceIndicator = GObject.registerClass(
+class InputSourceIndicator extends PanelMenu.Button {
     _init() {
-        this.parent(0.0, _("Keyboard"));
+        super._init(0.0, _("Keyboard"));
 
         this.connect('destroy', this._onDestroy.bind(this));
 
@@ -856,7 +849,7 @@ var InputSourceIndicator = new Lang.Class({
         this._inputSourceManagerCurrentSourceChangedId =
             this._inputSourceManager.connect('current-source-changed', 
this._currentSourceChanged.bind(this));
         this._inputSourceManager.reload();
-    },
+    }
 
     _onDestroy() {
         if (this._inputSourceManager) {
@@ -864,7 +857,7 @@ var InputSourceIndicator = new Lang.Class({
             this._inputSourceManager.disconnect(this._inputSourceManagerCurrentSourceChangedId);
             this._inputSourceManager = null;
         }
-    },
+    }
 
     _sessionUpdated() {
         // re-using "allowSettings" for the keyboard layout is a bit shady,
@@ -872,7 +865,7 @@ var InputSourceIndicator = new Lang.Class({
         // from shell menus"; we can always add a separate sessionMode
         // option if need arises.
         this._showLayoutItem.actor.visible = Main.sessionMode.allowSettings;
-    },
+    }
 
     _sourcesChanged() {
         for (let i in this._menuItems)
@@ -903,7 +896,7 @@ var InputSourceIndicator = new Lang.Class({
             this.menu.addMenuItem(menuItem, menuIndex++);
             this._container.add_actor(indicatorLabel);
         }
-    },
+    }
 
     _currentSourceChanged(manager, oldSource) {
         let nVisibleSources = Object.keys(this._inputSourceManager.inputSources).length;
@@ -932,7 +925,7 @@ var InputSourceIndicator = new Lang.Class({
 
         this._menuItems[newSource.index].setOrnament(PopupMenu.Ornament.DOT);
         this._indicatorLabels[newSource.index].show();
-    },
+    }
 
     _buildPropSection(properties) {
         this._propSeparator.actor.hide();
@@ -945,7 +938,7 @@ var InputSourceIndicator = new Lang.Class({
             this._propSection.actor.show();
             this._propSeparator.actor.show();
         }
-    },
+    }
 
     _buildPropSubMenu(menu, props) {
         if (!props)
@@ -1047,7 +1040,7 @@ var InputSourceIndicator = new Lang.Class({
             item.setSensitive(prop.get_sensitive());
             menu.addMenuItem(item);
         }
-    },
+    }
 
     _showLayout() {
         Main.overview.hide();
@@ -1074,5 +1067,5 @@ var InputSourceIndicator = new Lang.Class({
             description = description + '\t' + xkbVariant;
 
         Util.spawn(['gkbd-keyboard-display', '-l', description]);
-    },
+    }
 });
diff --git a/js/ui/switchMonitor.js b/js/ui/switchMonitor.js
index 31b4f3376..8b726ba06 100644
--- a/js/ui/switchMonitor.js
+++ b/js/ui/switchMonitor.js
@@ -1,7 +1,7 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
 const Clutter = imports.gi.Clutter;
-const Lang = imports.lang;
+const GObject = imports.gi.GObject;
 const Meta = imports.gi.Meta;
 const St = imports.gi.St;
 
@@ -9,10 +9,8 @@ const SwitcherPopup = imports.ui.switcherPopup;
 
 var APP_ICON_SIZE = 96;
 
-var SwitchMonitorPopup = new Lang.Class({
-    Name: 'SwitchMonitorPopup',
-    Extends: SwitcherPopup.SwitcherPopup,
-
+var SwitchMonitorPopup = GObject.registerClass(
+class SwitchMonitorPopup extends SwitcherPopup.SwitcherPopup {
     _init() {
         let items = [{ icon:  'view-mirror-symbolic',
                        /* Translators: this is for display mirroring i.e. cloning.
@@ -35,23 +33,23 @@ var SwitchMonitorPopup = new Lang.Class({
                         */
                        label: _('Built-in Only') }];
 
-        this.parent(items);
+        super._init(items);
 
         this._switcherList = new SwitchMonitorSwitcher(items);
-    },
+    }
 
     show(backward, binding, mask) {
         if (!Meta.MonitorManager.get().can_switch_config())
             return false;
 
-        return this.parent(backward, binding, mask);
-    },
+        return super.show(backward, binding, mask);
+    }
 
     _initialSelection() {
         let currentConfig = Meta.MonitorManager.get().get_switch_config();
         let selectConfig = (currentConfig + 1) % Meta.MonitorSwitchConfigType.UNKNOWN;
         this._select(selectConfig);
-    },
+    }
 
     _keyPressHandler(keysym, action) {
         if (action == Meta.KeyBindingAction.SWITCH_MONITOR)
@@ -64,25 +62,23 @@ var SwitchMonitorPopup = new Lang.Class({
             return Clutter.EVENT_PROPAGATE;
 
         return Clutter.EVENT_STOP;
-    },
+    }
 
     _finish() {
-        this.parent();
+        super._finish();
 
         Meta.MonitorManager.get().switch_config(this._selectedIndex);
-    },
+    }
 });
 
-var SwitchMonitorSwitcher = new Lang.Class({
-    Name: 'SwitchMonitorSwitcher',
-    Extends: SwitcherPopup.SwitcherList,
-
+var SwitchMonitorSwitcher = GObject.registerClass(
+class SwitchMonitorSwitcher extends SwitcherPopup.SwitcherList {
     _init(items) {
-        this.parent(true);
+        super._init(true);
 
         for (let i = 0; i < items.length; i++)
             this._addIcon(items[i]);
-    },
+    }
 
     _addIcon(item) {
         let box = new St.BoxLayout({ style_class: 'alt-tab-app',
@@ -98,4 +94,3 @@ var SwitchMonitorSwitcher = new Lang.Class({
         this.addItem(box, text);
     }
 });
-
diff --git a/js/ui/switcherPopup.js b/js/ui/switcherPopup.js
index 1bef1af70..d941acf22 100644
--- a/js/ui/switcherPopup.js
+++ b/js/ui/switcherPopup.js
@@ -4,7 +4,6 @@ const Clutter = imports.gi.Clutter;
 const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
 const Mainloop = imports.mainloop;
 const Meta = imports.gi.Meta;
 const Shell = imports.gi.Shell;
@@ -38,13 +37,13 @@ function primaryModifier(mask) {
     return primary;
 }
 
-var SwitcherPopup = new Lang.Class({
-    Name: 'SwitcherPopup',
-    Extends: St.Widget,
-    Abstract: true,
-
+var SwitcherPopup = GObject.registerClass(
+class SwitcherPopup extends St.Widget {
     _init(items) {
-        this.parent({ style_class: 'switcher-popup',
+        if (new.target === SwitcherPopup)
+            throw new TypeError('Cannot instantiate abstract class ' + new.target.name);
+
+        super._init({ style_class: 'switcher-popup',
                       reactive: true,
                       visible: false });
 
@@ -72,7 +71,7 @@ var SwitcherPopup = new Lang.Class({
         // Initially disable hover so we ignore the enter-event if
         // the switcher appears underneath the current pointer location
         this._disableHover();
-    },
+    }
 
     vfunc_allocate(box, flags) {
         this.set_allocation(box, flags);
@@ -93,7 +92,7 @@ var SwitcherPopup = new Lang.Class({
         childBox.y1 = primary.y + Math.floor((primary.height - childNaturalHeight) / 2);
         childBox.y2 = childBox.y1 + childNaturalHeight;
         this._switcherList.allocate(childBox, flags);
-    },
+    }
 
     _initialSelection(backward, binding) {
         if (backward)
@@ -102,7 +101,7 @@ var SwitcherPopup = new Lang.Class({
             this._select(0);
         else
             this._select(1);
-    },
+    }
 
     show(backward, binding, mask) {
         if (this._items.length == 0)
@@ -161,19 +160,19 @@ var SwitcherPopup = new Lang.Class({
                                                            });
         GLib.Source.set_name_by_id(this._initialDelayTimeoutId, '[gnome-shell] Main.osdWindow.cancel');
         return true;
-    },
+    }
 
     _next() {
         return mod(this._selectedIndex + 1, this._items.length);
-    },
+    }
 
     _previous() {
         return mod(this._selectedIndex - 1, this._items.length);
-    },
+    }
 
     _keyPressHandler(keysym, action) {
         throw new Error('Not implemented');
-    },
+    }
 
     _keyPressEvent(actor, event) {
         let keysym = event.get_key_symbol();
@@ -190,7 +189,7 @@ var SwitcherPopup = new Lang.Class({
             this.fadeAndDestroy();
 
         return Clutter.EVENT_STOP;
-    },
+    }
 
     _keyReleaseEvent(actor, event) {
         if (this._modifierMask) {
@@ -204,43 +203,43 @@ var SwitcherPopup = new Lang.Class({
         }
 
         return Clutter.EVENT_STOP;
-    },
+    }
 
     _clickedOutside(actor, event) {
         this.fadeAndDestroy();
         return Clutter.EVENT_PROPAGATE;
-    },
+    }
 
     _scrollHandler(direction) {
         if (direction == Clutter.ScrollDirection.UP)
             this._select(this._previous());
         else if (direction == Clutter.ScrollDirection.DOWN)
             this._select(this._next());
-    },
+    }
 
     _scrollEvent(actor, event) {
         this._scrollHandler(event.get_scroll_direction());
         return Clutter.EVENT_PROPAGATE;
-    },
+    }
 
     _itemActivatedHandler(n) {
         this._select(n);
-    },
+    }
 
     _itemActivated(switcher, n) {
         this._itemActivatedHandler(n);
         this._finish(global.get_current_time());
-    },
+    }
 
     _itemEnteredHandler(n) {
         this._select(n);
-    },
+    }
 
     _itemEntered(switcher, n) {
         if (!this.mouseActive)
             return;
         this._itemEnteredHandler(n);
-    },
+    }
 
     _itemRemovedHandler(n) {
         if (this._items.length > 0) {
@@ -249,11 +248,11 @@ var SwitcherPopup = new Lang.Class({
         } else {
             this.fadeAndDestroy();
         }
-    },
+    }
 
     _itemRemoved(switcher, n) {
         this._itemRemovedHandler(n);
-    },
+    }
 
     _disableHover() {
         this.mouseActive = false;
@@ -263,13 +262,13 @@ var SwitcherPopup = new Lang.Class({
 
         this._motionTimeoutId = Mainloop.timeout_add(DISABLE_HOVER_TIMEOUT, this._mouseTimedOut.bind(this));
         GLib.Source.set_name_by_id(this._motionTimeoutId, '[gnome-shell] this._mouseTimedOut');
-    },
+    }
 
     _mouseTimedOut() {
         this._motionTimeoutId = 0;
         this.mouseActive = true;
         return GLib.SOURCE_REMOVE;
-    },
+    }
 
     _resetNoModsTimeout() {
         if (this._noModsTimeoutId != 0)
@@ -281,14 +280,14 @@ var SwitcherPopup = new Lang.Class({
                                                          this._noModsTimeoutId = 0;
                                                          return GLib.SOURCE_REMOVE;
                                                      });
-    },
+    }
 
     _popModal() {
         if (this._haveModal) {
             Main.popModal(this);
             this._haveModal = false;
         }
-    },
+    }
 
     fadeAndDestroy() {
         this._popModal();
@@ -304,11 +303,11 @@ var SwitcherPopup = new Lang.Class({
         } else {
             this.destroy();
         }
-    },
+    }
 
     _finish(timestamp) {
         this.fadeAndDestroy();
-    },
+    }
 
     _onDestroy() {
         this._popModal();
@@ -319,7 +318,7 @@ var SwitcherPopup = new Lang.Class({
             Mainloop.source_remove(this._initialDelayTimeoutId);
         if (this._noModsTimeoutId != 0)
             Mainloop.source_remove(this._noModsTimeoutId);
-    },
+    }
 
     _select(num) {
         this._selectedIndex = num;
@@ -327,34 +326,30 @@ var SwitcherPopup = new Lang.Class({
     }
 });
 
-var SwitcherButton = new Lang.Class({
-    Name: 'SwitcherButton',
-    Extends: St.Button,
-
+var SwitcherButton = GObject.registerClass(
+class SwitcherButton extends St.Button {
     _init(square) {
-        this.parent({ style_class: 'item-box',
+        super._init({ style_class: 'item-box',
                       reactive: true });
 
         this._square = square;
-    },
+    }
 
     vfunc_get_preferred_width(forHeight) {
         if (this._square)
             return this.get_preferred_height(-1);
         else
-            return this.parent(forHeight);
+            return super.vfunc_get_preferred_width(forHeight);
     }
 });
 
-var SwitcherList = new Lang.Class({
-    Name: 'SwitcherList',
-    Extends: St.Widget,
+var SwitcherList = GObject.registerClass({
     Signals: { 'item-activated': { param_types: [GObject.TYPE_INT] },
                'item-entered': { param_types: [GObject.TYPE_INT] },
                'item-removed': { param_types: [GObject.TYPE_INT] } },
-
+}, class SwitcherList extends St.Widget {
     _init(squareItems) {
-        this.parent({ style_class: 'switcher-list' });
+        super._init({ style_class: 'switcher-list' });
 
         this._list = new St.BoxLayout({ style_class: 'switcher-list-item-container',
                                         vertical: false,
@@ -397,7 +392,7 @@ var SwitcherList = new Lang.Class({
         this._scrollableLeft = false;
 
         layoutManager.homogeneous = squareItems;
-    },
+    }
 
     addItem(item, label) {
         let bbox = new SwitcherButton(this._squareItems);
@@ -414,17 +409,17 @@ var SwitcherList = new Lang.Class({
         this._items.push(bbox);
 
         return bbox;
-    },
+    }
 
     removeItem(index) {
         let item = this._items.splice(index, 1);
         item[0].destroy();
         this.emit('item-removed', index);
-    },
+    }
 
     _onItemClicked(index) {
         this._itemActivated(index);
-    },
+    }
 
     _onItemEnter(index) {
         // Avoid reentrancy
@@ -433,7 +428,7 @@ var SwitcherList = new Lang.Class({
             this._itemEntered(index);
         }
         return Clutter.EVENT_PROPAGATE;
-    },
+    }
 
     highlight(index, justOutline) {
         if (this._items[this._highlighted]) {
@@ -460,7 +455,7 @@ var SwitcherList = new Lang.Class({
         else if (this._items[index].allocation.x1 - value < 0)
             this._scrollToLeft();
 
-    },
+    }
 
     _scrollToLeft() {
         let adjustment = this._scrollView.hscroll.adjustment;
@@ -484,7 +479,7 @@ var SwitcherList = new Lang.Class({
                                 this.queue_relayout();
                            }
                           });
-    },
+    }
 
     _scrollToRight() {
         let adjustment = this._scrollView.hscroll.adjustment;
@@ -508,15 +503,15 @@ var SwitcherList = new Lang.Class({
                                 this.queue_relayout();
                             }
                           });
-    },
+    }
 
     _itemActivated(n) {
         this.emit('item-activated', n);
-    },
+    }
 
     _itemEntered(n) {
         this.emit('item-entered', n);
-    },
+    }
 
     _maxChildWidth(forHeight) {
         let maxChildMin = 0;
@@ -535,7 +530,7 @@ var SwitcherList = new Lang.Class({
         }
 
         return [maxChildMin, maxChildNat];
-    },
+    }
 
     vfunc_get_preferred_width(forHeight) {
         let themeNode = this.get_theme_node();
@@ -543,7 +538,7 @@ var SwitcherList = new Lang.Class({
         let [minListWidth, ] = this._list.get_preferred_width(forHeight);
 
         return themeNode.adjust_preferred_width(maxChildMin, minListWidth);
-    },
+    }
 
     vfunc_get_preferred_height(forWidth) {
         let maxChildMin = 0;
@@ -563,7 +558,7 @@ var SwitcherList = new Lang.Class({
 
         let themeNode = this.get_theme_node();
         return themeNode.adjust_preferred_height(maxChildMin, maxChildNat);
-    },
+    }
 
     vfunc_allocate(box, flags) {
         this.set_allocation(box, flags);
diff --git a/js/ui/userWidget.js b/js/ui/userWidget.js
index 9730b73af..a702ad842 100644
--- a/js/ui/userWidget.js
+++ b/js/ui/userWidget.js
@@ -7,7 +7,6 @@ const AccountsService = imports.gi.AccountsService;
 const GLib = imports.gi.GLib;
 const Gio = imports.gi.Gio;
 const GObject = imports.gi.GObject;
-const Lang = imports.lang;
 const St = imports.gi.St;
 
 const Params = imports.misc.params;
@@ -64,12 +63,10 @@ var Avatar = class {
     }
 };
 
-var UserWidgetLabel = new Lang.Class({
-    Name: 'UserWidgetLabel',
-    Extends: St.Widget,
-
+var UserWidgetLabel = GObject.registerClass(
+class UserWidgetLabel extends St.Widget {
     _init(user) {
-        this.parent({ layout_manager: new Clutter.BinLayout() });
+        super._init({ layout_manager: new Clutter.BinLayout() });
 
         this._user = user;
 
@@ -93,7 +90,7 @@ var UserWidgetLabel = new Lang.Class({
         // the actor is destroyed (which is guaranteed to be as part of a normal
         // destroy() call from JS, possibly from some ancestor)
         this.connect('destroy', this._onDestroy.bind(this));
-    },
+    }
 
     _onDestroy() {
         if (this._userLoadedId != 0) {
@@ -105,7 +102,7 @@ var UserWidgetLabel = new Lang.Class({
             this._user.disconnect(this._userChangedId);
             this._userChangedId = 0;
         }
-    },
+    }
 
     vfunc_allocate(box, flags) {
         this.set_allocation(box, flags);
@@ -132,11 +129,11 @@ var UserWidgetLabel = new Lang.Class({
         childBox.y2 = availHeight;
 
         this._currentLabel.allocate(childBox, flags);
-    },
+    }
 
     vfunc_paint() {
         this._currentLabel.paint();
-    },
+    }
 
     _updateUser() {
         if (this._user.is_loaded) {
@@ -146,7 +143,7 @@ var UserWidgetLabel = new Lang.Class({
             this._realNameLabel.text = '';
             this._userNameLabel.text = '';
         }
-    },
+    }
 });
 
 var UserWidget = class {
diff --git a/js/ui/viewSelector.js b/js/ui/viewSelector.js
index 8cd5454b3..b902eb364 100644
--- a/js/ui/viewSelector.js
+++ b/js/ui/viewSelector.js
@@ -7,7 +7,6 @@ const Gtk = imports.gi.Gtk;
 const Mainloop = imports.mainloop;
 const Meta = imports.gi.Meta;
 const Signals = imports.signals;
-const Lang = imports.lang;
 const Shell = imports.gi.Shell;
 const St = imports.gi.St;
 const GObject = imports.gi.GObject;
@@ -32,14 +31,12 @@ var ViewPage = {
     SEARCH: 3
 };
 
-var FocusTrap = new Lang.Class({
-    Name: 'FocusTrap',
-    Extends: St.Widget,
-
+var FocusTrap = GObject.registerClass(
+class FocusTrap extends St.Widget {
     vfunc_navigate_focus(from, direction) {
         if (direction == Gtk.DirectionType.TAB_FORWARD ||
             direction == Gtk.DirectionType.TAB_BACKWARD)
-            return this.parent(from, direction);
+            return super.vfunc_navigate_focus(from, direction);
         return false;
     }
 });
@@ -73,24 +70,22 @@ var TouchpadShowOverviewAction = class {
 };
 Signals.addSignalMethods(TouchpadShowOverviewAction.prototype);
 
-var ShowOverviewAction = new Lang.Class({
-    Name: 'ShowOverviewAction',
-    Extends: Clutter.GestureAction,
+var ShowOverviewAction = GObject.registerClass({
     Signals: { 'activated': { param_types: [GObject.TYPE_DOUBLE] } },
-
+}, class ShowOverviewAction extends Clutter.GestureAction {
     _init() {
-        this.parent();
+        super._init();
         this.set_n_touch_points(3);
 
         global.display.connect('grab-op-begin', () => {
             this.cancel();
         });
-    },
+    }
 
     vfunc_gesture_prepare(action, actor) {
         return Main.actionMode == Shell.ActionMode.NORMAL &&
                this.get_n_current_points() == this.get_n_touch_points();
-    },
+    }
 
     _getBoundingRect(motion) {
         let minX, minY, maxX, maxY;
@@ -119,12 +114,12 @@ var ShowOverviewAction = new Lang.Class({
                                     y: minY,
                                     width: maxX - minX,
                                     height: maxY - minY });
-    },
+    }
 
     vfunc_gesture_begin(action, actor) {
         this._initialRect = this._getBoundingRect(false);
         return true;
-    },
+    }
 
     vfunc_gesture_end(action, actor) {
         let rect = this._getBoundingRect(true);
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
index 8527e08e4..8c4cb36d8 100644
--- a/js/ui/windowManager.js
+++ b/js/ui/windowManager.js
@@ -4,7 +4,6 @@ const Clutter = imports.gi.Clutter;
 const GLib = imports.gi.GLib;
 const Gio = imports.gi.Gio;
 const GObject = imports.gi.GObject;
-const Lang = imports.lang;
 const Mainloop = imports.mainloop;
 const Meta = imports.gi.Meta;
 const Pango = imports.gi.Pango;
@@ -525,45 +524,43 @@ var TouchpadWorkspaceSwitchAction = class {
 };
 Signals.addSignalMethods(TouchpadWorkspaceSwitchAction.prototype);
 
-var WorkspaceSwitchAction = new Lang.Class({
-    Name: 'WorkspaceSwitchAction',
-    Extends: Clutter.SwipeAction,
+var WorkspaceSwitchAction = GObject.registerClass({
     Signals: { 'activated': { param_types: [Meta.MotionDirection.$gtype] },
                'motion':    { param_types: [GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] },
                'cancel':    { param_types: [] }},
-
+}, class WorkspaceSwitchAction extends Clutter.SwipeAction {
     _init() {
-        this.parent();
+        super._init();
         this.set_n_touch_points(4);
         this._swept = false;
 
         global.display.connect('grab-op-begin', () => {
             this.cancel();
         });
-    },
+    }
 
     vfunc_gesture_prepare(actor) {
         let allowedModes = Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW;
 
         this._swept = false;
 
-        if (!this.parent(actor))
+        if (!super.vfunc_gesture_prepare(actor))
             return false;
 
         return (allowedModes & Main.actionMode);
-    },
+    }
 
     vfunc_gesture_progress(actor) {
         let [x, y] = this.get_motion_coords(0);
         let [xPress, yPress] = this.get_press_coords(0);
         this.emit('motion', x - xPress, y - yPress);
         return true;
-    },
+    }
 
     vfunc_gesture_cancel(actor) {
         if (!this._swept)
             this.emit('cancel');
-    },
+    }
 
     vfunc_swipe(actor, direction) {
         let [x, y] = this.get_motion_coords(0);
@@ -590,19 +587,17 @@ var WorkspaceSwitchAction = new Lang.Class({
     }
 });
 
-var AppSwitchAction = new Lang.Class({
-    Name: 'AppSwitchAction',
-    Extends: Clutter.GestureAction,
+var AppSwitchAction = GObject.registerClass({
     Signals: { 'activated': {} },
-
+}, class AppSwitchAction extends Clutter.GestureAction {
     _init() {
-        this.parent();
+        super._init();
         this.set_n_touch_points(3);
 
         global.display.connect('grab-op-begin', () => {
             this.cancel();
         });
-    },
+    }
 
     vfunc_gesture_prepare(action, actor) {
         if (Main.actionMode != Shell.ActionMode.NORMAL) {
@@ -611,7 +606,7 @@ var AppSwitchAction = new Lang.Class({
         }
 
         return this.get_n_current_points() <= 4;
-    },
+    }
 
     vfunc_gesture_begin(action, actor) {
         // in milliseconds
@@ -635,7 +630,7 @@ var AppSwitchAction = new Lang.Class({
         }
 
         return this.get_n_current_points() <= 4;
-    },
+    }
 
     vfunc_gesture_progress(action, actor) {
         const MOTION_THRESHOLD = 30;
diff --git a/js/ui/workspace.js b/js/ui/workspace.js
index d002cd008..f3b557e7e 100644
--- a/js/ui/workspace.js
+++ b/js/ui/workspace.js
@@ -2,7 +2,7 @@
 
 const Clutter = imports.gi.Clutter;
 const GLib = imports.gi.GLib;
-const Lang = imports.lang;
+const GObject = imports.gi.GObject;
 const Mainloop = imports.mainloop;
 const Meta = imports.gi.Meta;
 const Pango = imports.gi.Pango;
@@ -40,24 +40,22 @@ function _interpolate(start, end, step) {
     return start + (end - start) * step;
 }
 
-var WindowCloneLayout = new Lang.Class({
-    Name: 'WindowCloneLayout',
-    Extends: Clutter.LayoutManager,
-
+var WindowCloneLayout = GObject.registerClass(
+class WindowCloneLayout extends Clutter.LayoutManager {
     _init(boundingBox) {
-        this.parent();
+        super._init();
 
         this._boundingBox = boundingBox;
-    },
+    }
 
     get boundingBox() {
         return this._boundingBox;
-    },
+    }
 
     set boundingBox(b) {
         this._boundingBox = b;
         this.layout_changed();
-    },
+    }
 
     _makeBoxForWindow(window) {
         // We need to adjust the position of the actor because of the
@@ -78,15 +76,15 @@ var WindowCloneLayout = new Lang.Class({
         box.set_size(inputRect.width, inputRect.height);
 
         return box;
-    },
+    }
 
     vfunc_get_preferred_height(container, forWidth) {
         return [this._boundingBox.height, this._boundingBox.height];
-    },
+    }
 
     vfunc_get_preferred_width(container, forHeight) {
         return [this._boundingBox.width, this._boundingBox.width];
-    },
+    }
 
     vfunc_allocate(container, box, flags) {
         container.get_children().forEach(child => {
@@ -1072,10 +1070,8 @@ function rectEqual(one, two) {
             one.height == two.height);
 }
 
-const WorkspaceActor = new Lang.Class({
-    Name: 'WorkspaceActor',
-    Extends: St.Widget,
-
+const WorkspaceActor = GObject.registerClass(
+class WorkspaceActor extends St.Widget {
     vfunc_get_focus_chain() {
         return this.get_children().filter(c => c.visible).sort((a,b) => {
             let cloneA = (a._delegate && a._delegate instanceof WindowClone) ? a._delegate: null;
diff --git a/js/ui/workspaceSwitcherPopup.js b/js/ui/workspaceSwitcherPopup.js
index 8fa5bb5ec..e96385345 100644
--- a/js/ui/workspaceSwitcherPopup.js
+++ b/js/ui/workspaceSwitcherPopup.js
@@ -2,7 +2,7 @@
 
 const Clutter = imports.gi.Clutter;
 const GLib = imports.gi.GLib;
-const Lang = imports.lang;
+const GObject = imports.gi.GObject;
 const Mainloop = imports.mainloop;
 const Meta  = imports.gi.Meta;
 const Shell = imports.gi.Shell;
@@ -15,12 +15,10 @@ const Tweener = imports.ui.tweener;
 var ANIMATION_TIME = 0.1;
 var DISPLAY_TIMEOUT = 600;
 
-var WorkspaceSwitcherPopupList = new Lang.Class({
-    Name: 'WorkspaceSwitcherPopupList',
-    Extends: St.Widget,
-
+var WorkspaceSwitcherPopupList = GObject.registerClass(
+class WorkspaceSwitcherPopupList extends St.Widget {
     _init() {
-        this.parent({ style_class: 'workspace-switcher' });
+        super._init({ style_class: 'workspace-switcher' });
 
         this._itemSpacing = 0;
         this._childHeight = 0;
@@ -29,7 +27,7 @@ var WorkspaceSwitcherPopupList = new Lang.Class({
         this.connect('style-changed', () => {
            this._itemSpacing = this.get_theme_node().get_length('spacing');
         });
-    },
+    }
 
     vfunc_get_preferred_height(forWidth) {
         let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
@@ -53,14 +51,14 @@ var WorkspaceSwitcherPopupList = new Lang.Class({
         this._childHeight = (height - spacing) / workspaceManager.n_workspaces;
 
         return themeNode.adjust_preferred_height(height, height);
-    },
+    }
 
     vfunc_get_preferred_width(forHeight) {
         let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
         this._childWidth = Math.round(this._childHeight * workArea.width / workArea.height);
 
         return [this._childWidth, this._childWidth];
-    },
+    }
 
     vfunc_allocate(box, flags) {
         this.set_allocation(box, flags);
@@ -81,15 +79,13 @@ var WorkspaceSwitcherPopupList = new Lang.Class({
             prevChildBoxY2 = childBox.y2;
             child.allocate(childBox, flags);
         }
-    },
+    }
 });
 
-var WorkspaceSwitcherPopup = new Lang.Class({
-    Name: 'WorkspaceSwitcherPopup',
-    Extends: St.Widget,
-
+var WorkspaceSwitcherPopup = GObject.registerClass(
+class WorkspaceSwitcherPopup extends St.Widget {
     _init() {
-        this.parent({ x: 0,
+        super._init({ x: 0,
                       y: 0,
                       width: global.screen_width,
                       height: global.screen_height,
@@ -119,7 +115,7 @@ var WorkspaceSwitcherPopup = new Lang.Class({
                                                                     this._redisplay.bind(this)));
 
         this.connect('destroy', this._onDestroy.bind(this));
-    },
+    }
 
     _redisplay() {
         let workspaceManager = global.workspace_manager;
@@ -145,7 +141,7 @@ var WorkspaceSwitcherPopup = new Lang.Class({
         let [containerMinWidth, containerNatWidth] = this._container.get_preferred_width(containerNatHeight);
         this._container.x = workArea.x + Math.floor((workArea.width - containerNatWidth) / 2);
         this._container.y = workArea.y + Math.floor((workArea.height - containerNatHeight) / 2);
-    },
+    }
 
     _show() {
         Tweener.addTween(this._container, { opacity: 255,
@@ -153,7 +149,7 @@ var WorkspaceSwitcherPopup = new Lang.Class({
                                             transition: 'easeOutQuad'
                                            });
         this.actor.show();
-    },
+    }
 
     display(direction, activeWorkspaceIndex) {
         this._direction = direction;
@@ -165,7 +161,7 @@ var WorkspaceSwitcherPopup = new Lang.Class({
         this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, this._onTimeout.bind(this));
         GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._onTimeout');
         this._show();
-    },
+    }
 
     _onTimeout() {
         Mainloop.source_remove(this._timeoutId);
@@ -177,7 +173,7 @@ var WorkspaceSwitcherPopup = new Lang.Class({
                                             onCompleteScope: this
                                            });
         return GLib.SOURCE_REMOVE;
-    },
+    }
 
     _onDestroy() {
         if (this._timeoutId)
diff --git a/js/ui/workspaceThumbnail.js b/js/ui/workspaceThumbnail.js
index 386a29fe0..f56e549ff 100644
--- a/js/ui/workspaceThumbnail.js
+++ b/js/ui/workspaceThumbnail.js
@@ -3,7 +3,7 @@
 const Clutter = imports.gi.Clutter;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
-const Lang = imports.lang;
+const GObject = imports.gi.GObject;
 const Mainloop = imports.mainloop;
 const Meta = imports.gi.Meta;
 const Shell = imports.gi.Shell;
@@ -35,23 +35,21 @@ var MUTTER_SCHEMA = 'org.gnome.mutter';
 
 /* A layout manager that requests size only for primary_actor, but then allocates
    all using a fixed layout */
-var PrimaryActorLayout = new Lang.Class({
-    Name: 'PrimaryActorLayout',
-    Extends: Clutter.FixedLayout,
-
+var PrimaryActorLayout = GObject.registerClass(
+class PrimaryActorLayout extends Clutter.FixedLayout {
     _init(primaryActor) {
-        this.parent();
+        super._init();
 
         this.primaryActor = primaryActor;
-    },
+    }
 
     vfunc_get_preferred_width(container, forHeight) {
         return this.primaryActor.get_preferred_width(forHeight);
-    },
+    }
 
     vfunc_get_preferred_height(container, forWidth) {
         return this.primaryActor.get_preferred_height(forWidth);
-    },
+    }
 });
 
 var WindowClone = class {
@@ -608,12 +606,10 @@ var WorkspaceThumbnail = class {
 Signals.addSignalMethods(WorkspaceThumbnail.prototype);
 
 
-var ThumbnailsBox = new Lang.Class({
-    Name: 'ThumbnailsBox',
-    Extends: St.Widget,
-
+var ThumbnailsBox = GObject.registerClass(
+class ThumbnailsBox extends St.Widget {
     _init() {
-        this.parent({ reactive: true,
+        super._init({ reactive: true,
                       style_class: 'workspace-thumbnails',
                       request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT });
 
@@ -683,7 +679,7 @@ var ThumbnailsBox = new Lang.Class({
         this._nWorkspacesNotifyId = 0;
         this._syncStackingId = 0;
         this._workareasChangedId = 0;
-    },
+    }
 
     _updateSwitcherVisibility() {
         let workspaceManager = global.workspace_manager;
@@ -691,7 +687,7 @@ var ThumbnailsBox = new Lang.Class({
         this.visible =
             this._settings.get_boolean('dynamic-workspaces') ||
                 workspaceManager.n_workspaces > 1;
-    },
+    }
 
     _activateThumbnailAtPoint(stageX, stageY, time) {
         let [r, x, y] = this.transform_stage_point(stageX, stageY);
@@ -704,13 +700,13 @@ var ThumbnailsBox = new Lang.Class({
                 break;
             }
         }
-    },
+    }
 
     _onButtonRelease(actor, event) {
         let [stageX, stageY] = event.get_coords();
         this._activateThumbnailAtPoint(stageX, stageY, event.get_time());
         return Clutter.EVENT_STOP;
-    },
+    }
 
     _onTouchEvent(actor, event) {
         if (event.type() == Clutter.EventType.TOUCH_END &&
@@ -720,7 +716,7 @@ var ThumbnailsBox = new Lang.Class({
         }
 
         return Clutter.EVENT_STOP;
-    },
+    }
 
     _onDragBegin() {
         this._dragCancelled = false;
@@ -728,34 +724,34 @@ var ThumbnailsBox = new Lang.Class({
             dragMotion: this._onDragMotion.bind(this)
         };
         DND.addDragMonitor(this._dragMonitor);
-    },
+    }
 
     _onDragEnd() {
         if (this._dragCancelled)
             return;
 
         this._endDrag();
-    },
+    }
 
     _onDragCancelled() {
         this._dragCancelled = true;
         this._endDrag();
-    },
+    }
 
     _endDrag() {
         this._clearDragPlaceholder();
         DND.removeDragMonitor(this._dragMonitor);
-    },
+    }
 
     _onDragMotion(dragEvent) {
         if (!this.contains(dragEvent.targetActor))
             this._onLeave();
         return DND.DragMotionResult.CONTINUE;
-    },
+    }
 
     _onLeave() {
         this._clearDragPlaceholder();
-    },
+    }
 
     _clearDragPlaceholder() {
         if (this._dropPlaceholderPos == -1)
@@ -763,7 +759,7 @@ var ThumbnailsBox = new Lang.Class({
 
         this._dropPlaceholderPos = -1;
         this.queue_relayout();
-    },
+    }
 
     // Draggable target interface
     handleDragOver(source, actor, x, y, time) {
@@ -818,7 +814,7 @@ var ThumbnailsBox = new Lang.Class({
             return source.realWindow ? DND.DragMotionResult.MOVE_DROP : DND.DragMotionResult.COPY_DROP;
         else
             return DND.DragMotionResult.CONTINUE;
-    },
+    }
 
     acceptDrop(source, actor, x, y, time) {
         if (this._dropWorkspace != -1) {
@@ -865,7 +861,7 @@ var ThumbnailsBox = new Lang.Class({
         } else {
             return false;
         }
-    },
+    }
 
     _createThumbnails() {
         let workspaceManager = global.workspace_manager;
@@ -892,7 +888,7 @@ var ThumbnailsBox = new Lang.Class({
         this.addThumbnails(0, workspaceManager.n_workspaces);
 
         this._updateSwitcherVisibility();
-    },
+    }
 
     _destroyThumbnails() {
         if (this._thumbnails.length == 0)
@@ -917,7 +913,7 @@ var ThumbnailsBox = new Lang.Class({
             this._thumbnails[w].destroy();
         this._thumbnails = [];
         this._porthole = null;
-    },
+    }
 
     _workspacesChanged() {
         let validThumbnails =
@@ -944,7 +940,7 @@ var ThumbnailsBox = new Lang.Class({
         }
 
         this._updateSwitcherVisibility();
-    },
+    }
 
     addThumbnails(start, count) {
         let workspaceManager = global.workspace_manager;
@@ -978,7 +974,7 @@ var ThumbnailsBox = new Lang.Class({
 
         // Clear the splice index, we got the message
         this._spliceIndex = -1;
-    },
+    }
 
     removeThumbnails(start, count) {
         let currentPos = 0;
@@ -997,36 +993,36 @@ var ThumbnailsBox = new Lang.Class({
         }
 
         this._queueUpdateStates();
-    },
+    }
 
     _syncStacking(overview, stackIndices) {
         for (let i = 0; i < this._thumbnails.length; i++)
             this._thumbnails[i].syncStacking(stackIndices);
-    },
+    }
 
     set scale(scale) {
         this._scale = scale;
         this.queue_relayout();
-    },
+    }
 
     get scale() {
         return this._scale;
-    },
+    }
 
     set indicatorY(indicatorY) {
         this._indicatorY = indicatorY;
         this.queue_relayout();
-    },
+    }
 
     get indicatorY() {
         return this._indicatorY;
-    },
+    }
 
     _setThumbnailState(thumbnail, state) {
         this._stateCounts[thumbnail.state]--;
         thumbnail.state = state;
         this._stateCounts[thumbnail.state]++;
-    },
+    }
 
     _iterateStateThumbnails(state, callback) {
         if (this._stateCounts[state] == 0)
@@ -1036,7 +1032,7 @@ var ThumbnailsBox = new Lang.Class({
             if (this._thumbnails[i].state == state)
                 callback.call(this, this._thumbnails[i]);
         }
-    },
+    }
 
     _tweenScale() {
         Tweener.addTween(this,
@@ -1045,7 +1041,7 @@ var ThumbnailsBox = new Lang.Class({
                            transition: 'easeOutQuad',
                            onComplete: this._queueUpdateStates,
                            onCompleteScope: this });
-    },
+    }
 
     _updateStates() {
         this._stateUpdateQueued = false;
@@ -1114,7 +1110,7 @@ var ThumbnailsBox = new Lang.Class({
                                }
                              });
         });
-    },
+    }
 
     _queueUpdateStates() {
         if (this._stateUpdateQueued)
@@ -1124,7 +1120,7 @@ var ThumbnailsBox = new Lang.Class({
                        this._updateStates.bind(this));
 
         this._stateUpdateQueued = true;
-    },
+    }
 
     vfunc_get_preferred_height(forWidth) {
         // Note that for getPreferredWidth/Height we cheat a bit and skip propagating
@@ -1144,7 +1140,7 @@ var ThumbnailsBox = new Lang.Class({
         let naturalHeight = totalSpacing + nWorkspaces * this._porthole.height * MAX_THUMBNAIL_SCALE;
 
         return themeNode.adjust_preferred_height(totalSpacing, naturalHeight);
-    },
+    }
 
     vfunc_get_preferred_width(forHeight) {
         if (!this._ensurePorthole())
@@ -1167,7 +1163,7 @@ var ThumbnailsBox = new Lang.Class({
         let width = Math.round(this._porthole.width * scale);
 
         return themeNode.adjust_preferred_width(width, width);
-    },
+    }
 
     // The "porthole" is the portion of the screen that we show in the
     // workspaces
@@ -1179,7 +1175,7 @@ var ThumbnailsBox = new Lang.Class({
             this._porthole = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
 
         return true;
-    },
+    }
 
     vfunc_allocate(box, flags) {
         this.set_allocation(box, flags);
@@ -1321,7 +1317,7 @@ var ThumbnailsBox = new Lang.Class({
         childBox.y1 = indicatorY1 - indicatorTopFullBorder;
         childBox.y2 = (indicatorY2 ? indicatorY2 : (indicatorY1 + thumbnailHeight)) + 
indicatorBottomFullBorder;
         this._indicator.allocate(childBox, flags);
-    },
+    }
 
     _activeWorkspaceChanged(wm, from, to, direction) {
         let thumbnail;
diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js
index 228c3f81b..a06ab32a8 100644
--- a/js/ui/workspacesView.js
+++ b/js/ui/workspacesView.js
@@ -3,7 +3,6 @@
 const Clutter = imports.gi.Clutter;
 const Gio = imports.gi.Gio;
 const GObject = imports.gi.GObject;
-const Lang = imports.lang;
 const Mainloop = imports.mainloop;
 const Meta = imports.gi.Meta;
 const Shell = imports.gi.Shell;
@@ -403,13 +402,11 @@ var ExtraWorkspaceView = class extends WorkspacesViewBase {
     }
 };
 
-var DelegateFocusNavigator = new Lang.Class({
-    Name: 'DelegateFocusNavigator',
-    Extends: St.Widget,
-
+var DelegateFocusNavigator = GObject.registerClass(
+class DelegateFocusNavigator extends St.Widget {
     vfunc_navigate_focus(from, direction) {
         return this._delegate.navigateFocus(from, direction);
-    },
+    }
 });
 
 var WorkspacesDisplay = class {
diff --git a/tests/interactive/scroll-view-sizing.js b/tests/interactive/scroll-view-sizing.js
index aa0631915..9b264d05f 100644
--- a/tests/interactive/scroll-view-sizing.js
+++ b/tests/interactive/scroll-view-sizing.js
@@ -3,8 +3,8 @@
 const UI = imports.testcommon.ui;
 
 const Clutter = imports.gi.Clutter;
+const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
 const Shell = imports.gi.Shell;
 const St = imports.gi.St;
 
@@ -32,19 +32,17 @@ const BOX_WIDTHS = [
 
 const SPACING = 10;
 
-var FlowedBoxes = new Lang.Class({
-    Name: 'FlowedBoxes',
-    Extends: St.Widget,
-
+var FlowedBoxes = GObject.registerClass(
+class FlowedBoxes extends St.Widget {
     _init() {
-        this.parent();
+        super._init();
 
        for (let i = 0; i < BOX_WIDTHS.length; i++) {
            let child = new St.Bin({ width: BOX_WIDTHS[i], height: BOX_HEIGHT,
                                     style: 'border: 1px solid #444444; background: #00aa44' })
            this.add_actor(child);
        }
-    },
+    }
 
     vfunc_get_preferred_width(forHeight) {
         let children = this.get_children();
@@ -62,7 +60,7 @@ var FlowedBoxes = new Lang.Class({
        }
 
         return [maxMinWidth, totalNaturalWidth];
-    },
+    }
 
     _layoutChildren(forWidth, callback) {
         let children = this.get_children();
@@ -92,7 +90,7 @@ var FlowedBoxes = new Lang.Class({
            x = x2;
        }
 
-    },
+    }
 
     vfunc_get_preferred_height(forWidth) {
        let height = 0;
@@ -102,7 +100,7 @@ var FlowedBoxes = new Lang.Class({
           });
 
         return [height, height];
-    },
+    }
 
     vfunc_allocate(box, flags) {
         this.set_allocation(box, flags);
@@ -124,12 +122,10 @@ var FlowedBoxes = new Lang.Class({
 //
 // This is currently only written for the case where the child is height-for-width
 
-var SizingIllustrator = new Lang.Class({
-    Name: 'SizingIllustrator',
-    Extends: St.Widget,
-
+var SizingIllustrator = GObject.registerClass(
+class SizingIllustrator extends St.Widget {
     _init() {
-        this.parent();
+        super._init();
 
        this.minWidthLine = new St.Bin({ style: 'background: red' });
         this.add_actor(this.minWidthLine);
@@ -157,13 +153,13 @@ var SizingIllustrator = new Lang.Class({
 
        this.width = 300;
        this.height = 300;
-    },
+    }
 
     add(child) {
         this.child = child;
         this.add_child(child);
         this.child.lower_bottom();
-    },
+    }
 
     vfunc_get_preferred_width(forHeight) {
         let children = this.get_children();
@@ -177,7 +173,7 @@ var SizingIllustrator = new Lang.Class({
        }
 
         return [0, 400];
-    },
+    }
 
     vfunc_get_preferred_height(forWidth) {
         let children = this.get_children();
@@ -191,7 +187,7 @@ var SizingIllustrator = new Lang.Class({
        }
 
         return [0, 400];
-    },
+    }
 
     vfunc_allocate(box, flags) {
         this.set_allocation(box, flags);
@@ -214,7 +210,7 @@ var SizingIllustrator = new Lang.Class({
        alloc(this.naturalHeightLine, 0, this.naturalHeight, allocWidth, this.naturalHeight + 1);
        alloc(this.currentHeightLine, 0, this.height, allocWidth, this.height + 1);
        alloc(this.handle, this.width, this.height, this.width + 10, this.height + 10);
-    },
+    }
 
     _handlePressed(handle, event) {
        if (event.get_button() == 1) {
@@ -225,14 +221,14 @@ var SizingIllustrator = new Lang.Class({
            this._dragY = y - handleY;
            Clutter.grab_pointer(handle);
        }
-    },
+    }
 
     _handleReleased(handle, event) {
        if (event.get_button() == 1) {
            this._inDrag = false;
            Clutter.ungrab_pointer(handle);
        }
-    },
+    }
 
     _handleMotion(handle, event) {
        if (this._inDrag) {


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