diff --git a/js/ui/magnifier.js b/js/ui/magnifier.js
new file mode 100644
index 0000000..965a3ef
--- /dev/null
+++ b/js/ui/magnifier.js
@@ -0,0 +1,172 @@
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+const Clutter = imports.gi.Clutter;
+const Shell = imports.gi.Shell;
+const Big = imports.gi.Big;
+
+const DND = imports.ui.dnd;
+
+const DEFAULT_BACKGROUND_COLOR = new Clutter.Color();
+DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff);
+
+function Magnifier() {
+
+    // If magnifier is magnifying/showing
+    var _active = false;
+
+    // The Big.Box that shows the magnified view
+    var _magView = null;
+
+    // Clone of the stage's UIGroup.  The child of _magView.
+    var _uiGroupClone = null;
+
+    // Magnification power in the horizontal direction.  Default is 2x.
+    var _xMagFactor = 2;
+
+    // Magnification power in the vertical direction.  Default is 2x.
+    var _yMagFactor = 2;
+
+    let global = Shell.Global.get();
+
+    // Outer box is used to draw a frame around the magnified view.
+    const BORDER_COLOR = new Clutter.Color();
+    BORDER_COLOR.from_pixel(0x800000ff);
+    _magView = new Big.Box ({ border: 8, border_color: BORDER_COLOR, name: "Magnifier" });
+
+    // Hard coded (default) position of magnified view, for now
+    let posX = global.stage.get_width()/2;
+    let posY = global.stage.get_height() * .66;
+    _magView.set_position(0, posY);
+
+    // Use group to clip the contents
+    let aGroup = new Clutter.Group({ clip_to_allocation: true });
+    _magView.append(aGroup, Big.BoxPackFlags.EXPAND);
+    aGroup.set_size(posX, posY/2);
+
+    // Clone the that contains all of UI on the screen.  This is the
+    // chrome, the windows, etc.
+    _uiGroupClone = new Clutter.Clone ({ source: global.uiGroup });
+    aGroup.add_actor (_uiGroupClone);
+
+    // The contents of the clone are scaled from their original size
+    // to the allocated size of the clone, this is not useful to us
+    // since we want to scale by a fixed factor; the size of the window
+    // group is unpredictable because windows can go outside the
+    // screen, but we can set it to something fixed, since the size
+    // of a clutter actor doesn't affect clipping or display. Then we
+    // set the size of the clone to the same size. Actual size picked
+    // doesn't matter - I used the size of my monitor.
+    global.window_group.set_size (1400, 1050);
+    _uiGroupClone.set_size (1400, 1050);
+
+    // Fixed factor scaling
+    _uiGroupClone.set_scale (_xMagFactor, _yMagFactor);
+
+    _magView.hide();
+    global.stage.add_actor (_magView);
+
+    /**
+     * setActive:
+     * @activate  Boolean to activate of de-activate the Magnifier.
+     *            The magnified view is shown or hidden depending
+     *            on the sense of the argument, but remains an
+     *            actor on the stage.
+     */
+    Magnifier.prototype.setActive = function (activate) {
+        if (activate) {
+          _magView.show();
+          _active = true;
+        }
+        else {
+          _magView.hide();
+          _active = false;
+        }
+    }   // end setActive().
+
+    /**
+     * setMagFactor:
+     * @inXmagFactor    the power to set the horizontal magnification factor to
+     *                  of the magnified view, e.g. 2x, 10x, etc.
+     * @inYmagFactor    the power to set the vertical magnification factor to
+     *                  of the magnified view.
+     */
+    Magnifier.prototype.setMagFactor = function (inXmagFactor, inYMagFactor) {
+        _xMagFactor = inXmagFactor;
+        _yMagFactor = inYMagFactor;
+        _uiGroupClone.set_scale (_xMagFactor, _yMagFactor);
+
+    }   // end setMagFactor().
+
+    /**
+     * getMagFactor:
+     * @return  an array, {x, y}, that contains the horizontal and vertical
+     *          magnficaction factors (2x, 10X, etc.).
+     */
+    Magnifier.prototype.getMagFactor = function() {
+        return [_xMagFactor, _yMagFactor];
+
+    }   // end getMagFactor().
+
+    /**
+     * Consult if the Magnifier can magnify in full-screen mode.
+     * @return  true if it can or false otherwise.
+     */
+    Magnifier.prototype.fullScreenCapable = function() {
+        return true;
+
+    }   // end fullScreenCapable().
+
+    /**
+     * setSize:
+     * @inWidth     The width to set the magnified view to.
+     * @inHeight    The height to set the magnified view to.
+     */
+    Magnifier.prototype.setSize = function (inWidth, inHeight) {
+        _magView.set_size (inWidth, inHeight);
+
+    }   // end setSize().
+
+    /**
+     * getSize:
+     * @return  an array, [width, height], that specifies the size of the
+     *          magnified view.
+     */
+    Magnifier.prototype.getSize = function() {
+        return _magView.get_size();
+
+    }   // end getSize().
+
+    /**
+     * setPosition:
+     * @inX     The x-coord of the new position.
+     * @inY     The y-coord of the new position.
+     * @return  The old position [x, y].
+     */
+    Magnifier.prototype.setPosition = function (inX, inY) {
+        let [x, y] = _magView.get_position();
+        _magView.set_position (inX, inY);
+        return [x, y];
+
+    }   // end setPosition().
+
+    /**
+     * getPosition:
+     * @return  an array, [x, y], that gives the position of the
+     *          magnified view.
+     */
+    Magnifier.prototype.getPosition = function() {
+        return _magView.get_position();
+
+    }   // end getPosition().
+
+    /**
+     * Set the Magnifier to full-screen mode.
+     */
+    Magnifier.prototype.setFullScreenMode = function() {
+        let [width, height] = global.stage.get_size();
+        _magView.set_position (0, 0);
+        _magView.set_size (global.screen_width, global.screen_height);
+
+    }   // end setFullScreenMode().
+
+}   // end Magnifier().
diff --git a/js/ui/main.js b/js/ui/main.js
index 5251ce8..87bb881 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -18,6 +18,7 @@ const LookingGlass = imports.ui.lookingGlass;
 const Sidebar = imports.ui.sidebar;
 const Tweener = imports.ui.tweener;
 const WindowManager = imports.ui.windowManager;
+const Magnifier = imports.ui.magnifier;
 
 const DEFAULT_BACKGROUND_COLOR = new Clutter.Color();
 DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff);
@@ -30,6 +31,9 @@ let runDialog = null;
 let lookingGlass = null;
 let wm = null;
 let recorder = null;
+let inModal = false;
+let uiGroup = null;
+let magnifier = null;
 let modalCount = 0;
 let modalActorFocusStack = [];
 
@@ -77,6 +81,19 @@ function start() {
     sidebar = new Sidebar.Sidebar();
     wm = new WindowManager.WindowManager();
 
+    // Set up stage hierarchy for the Magnifier.
+    // Note:  should this be done somewhere else?
+    //
+    uiGroup = new Clutter.Group( {name: "uiGroup"} );
+    global.stage.remove_actor (global.window_group);
+    global.stage.remove_actor (global.overlay_group);
+    global.stage.remove_actor (chrome.actor);
+    uiGroup.add_actor (global.window_group);
+    uiGroup.add_actor (global.overlay_group);
+    uiGroup.add_actor (chrome.actor);
+    global.stage.add_actor (uiGroup);
+    global.uiGroup = uiGroup;
+
     global.screen.connect('toggle-recording', function() {
         if (recorder == null) {
             recorder = new Shell.Recorder({ stage: global.stage });
@@ -99,6 +116,13 @@ function start() {
 
     global.stage.connect('captured-event', _globalKeyPressHandler);
 
+    // Install magnifier.
+    // Note:  to make active, call magnifier.setActive (true);
+    //
+    magnifier = new Magnifier.Magnifier();
+    global.magnifier = magnifier;
+
+
     Mainloop.idle_add(_removeUnusedWorkspaces);
 }
 
