← Back to team overview

ubuntu-sdk-team team mailing list archive

[Merge] lp:~sergio-j-cazzolato/ubuntu-ui-toolkit/remove-upstart-tests-dependencies into lp:ubuntu-ui-toolkit

 

Sergio Cazzolato has proposed merging lp:~sergio-j-cazzolato/ubuntu-ui-toolkit/remove-upstart-tests-dependencies into lp:ubuntu-ui-toolkit.

Commit message:
This change is done to remove the dependencies with upstart in the tests.
To start apps with env vars is gonna be used the launch_test_application method provided by autopilot in its test base class which is a wrapper for the ubuntu-app-launch tools (API).

This change removes all the dependencies with upstart, so all the projects which are using the initctl api and fixtures will be impacted.

An update in the documentation or in the blog is gonna be done also to communicate this change to the developers.



Requested reviews:
  Ubuntu SDK team (ubuntu-sdk-team)

For more details, see:
https://code.launchpad.net/~sergio-j-cazzolato/ubuntu-ui-toolkit/remove-upstart-tests-dependencies/+merge/315042
-- 
Your team Ubuntu SDK team is requested to review the proposed merge of lp:~sergio-j-cazzolato/ubuntu-ui-toolkit/remove-upstart-tests-dependencies into lp:ubuntu-ui-toolkit.
=== modified file 'debian/control'
--- debian/control	2016-11-21 12:16:49 +0000
+++ debian/control	2017-01-18 17:08:31 +0000
@@ -353,6 +353,7 @@
 Section: devel
 Architecture: any
 Depends: qml-module-qt-labs-folderlistmodel,
+         qml-module-qtqml-models2,
          qml-module-qtquick-xmllistmodel,
          qml-module-ubuntu-components (= ${binary:Version}) | qml-module-ubuntu-components-gles,
          ubuntu-ui-toolkit-theme (= ${binary:Version}),

=== modified file 'debian/control.gles'
--- debian/control.gles	2016-11-21 12:16:49 +0000
+++ debian/control.gles	2017-01-18 17:08:31 +0000
@@ -37,6 +37,7 @@
                lsb-release,
                pep8,
                python-autopilot (>= 1.4),
+               python3-debian,
                python3-sphinx,
                python3:any,
                python:any,

=== modified file 'src/UbuntuToolkit/UbuntuToolkit.pro'
--- src/UbuntuToolkit/UbuntuToolkit.pro	2016-11-04 09:37:32 +0000
+++ src/UbuntuToolkit/UbuntuToolkit.pro	2017-01-18 17:08:31 +0000
@@ -106,6 +106,8 @@
     $$PWD/uclistitemstyle_p.h \
     $$PWD/ucmainviewbase_p.h \
     $$PWD/ucmainviewbase_p_p.h \
+    $$PWD/ucmainwindow_p.h \
+    $$PWD/ucmainwindow_p_p.h \
     $$PWD/ucmargins_p.h \
     $$PWD/ucmathutils_p.h \
     $$PWD/ucmouse_p.h \
@@ -203,6 +205,7 @@
     $$PWD/uclistitemlayout.cpp \
     $$PWD/uclistitemstyle.cpp \
     $$PWD/ucmainviewbase.cpp \
+    $$PWD/ucmainwindow.cpp \
     $$PWD/ucmathutils.cpp \
     $$PWD/ucmousefilters.cpp \
     $$PWD/ucpagetreenode.cpp \

=== modified file 'src/UbuntuToolkit/ubuntutoolkitmodule.cpp'
--- src/UbuntuToolkit/ubuntutoolkitmodule.cpp	2016-09-29 10:19:06 +0000
+++ src/UbuntuToolkit/ubuntutoolkitmodule.cpp	2017-01-18 17:08:31 +0000
@@ -39,6 +39,7 @@
 #include "inversemouseareatype_p.h"
 #include "listener_p.h"
 #include "livetimer_p.h"
+#include "ucmainwindow_p.h"
 #include "menu_p.h"
 #include "menubar_p.h"
 #include "menugroup_p.h"
@@ -439,6 +440,7 @@
     qmlRegisterType<SplitView>(uri, 1, 0, "SplitView");
     qmlRegisterType<SplitViewLayout>(uri, 1, 0, "SplitViewLayout");
     qmlRegisterType<ViewColumn>(uri, 1, 0, "ViewColumn");
+    qmlRegisterType<UCMainWindow>(uri, 1, 0, "MainWindow");
     qmlRegisterType<Menu>(uri, 1, 0, "Menu");
     qmlRegisterType<MenuBar>(uri, 1, 0, "MenuBar");
     qmlRegisterType<MenuGroup>(uri, 1, 0, "MenuGroup");

=== modified file 'src/UbuntuToolkit/ucapplication.cpp'
--- src/UbuntuToolkit/ucapplication.cpp	2016-09-09 17:49:07 +0000
+++ src/UbuntuToolkit/ucapplication.cpp	2017-01-18 17:08:31 +0000
@@ -39,6 +39,8 @@
 UCApplication::UCApplication(QObject* parent) : QObject(parent), m_context(0)
                                                                , m_inputMethod(QGuiApplication::inputMethod())
 {
+    // Unset organization by default to skip an extra folder component
+    QCoreApplication::setOrganizationName(QStringLiteral(""));
     // Make sure we receive application name changes from C++ modules
     connect(QCoreApplication::instance(), &QCoreApplication::applicationNameChanged,
             this, &UCApplication::applicationNameChanged);
@@ -68,8 +70,7 @@
        to how Unity uses it to distinguish running applications.
      */
     QCoreApplication::setApplicationName(applicationName);
-    // Unset organization to skip an extra folder component
-    QCoreApplication::setOrganizationName(QString());
+    QCoreApplication::setOrganizationName(QCoreApplication::organizationName());
     /*
        Ensure that LocalStorage and WebKit use the same location
        Docs are ambiguous: in practise applicationName is ignored by default

=== modified file 'src/UbuntuToolkit/ucmainviewbase.cpp'
--- src/UbuntuToolkit/ucmainviewbase.cpp	2016-09-12 09:03:50 +0000
+++ src/UbuntuToolkit/ucmainviewbase.cpp	2017-01-18 17:08:31 +0000
@@ -145,6 +145,7 @@
 void UCMainViewBase::setApplicationName(QString applicationName)
 {
     Q_D(UCMainViewBase);
+
     if (d->m_applicationName == applicationName)
         return;
 

=== added file 'src/UbuntuToolkit/ucmainwindow.cpp'
--- src/UbuntuToolkit/ucmainwindow.cpp	1970-01-01 00:00:00 +0000
+++ src/UbuntuToolkit/ucmainwindow.cpp	2017-01-18 17:08:31 +0000
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2016-2017 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ucmainwindow_p_p.h"
+
+#include <QtCore/QCoreApplication>
+
+#include "ucactionmanager_p.h"
+#include "ucactioncontext_p.h"
+#include "ucapplication_p.h"
+#include "uctheme_p.h"
+#include "i18n_p.h"
+#include "quickutils_p.h"
+
+UT_NAMESPACE_BEGIN
+
+/*!
+  \internal
+  \qmlabstract MainWindow
+  \inqmlmodule Ubuntu.Components.Labs
+  \ingroup ubuntu
+  \brief MainWindow is an alternate window-based root Item providing \l units
+  and \l i18n as native properties, an \ actionContext and an \l applicationName.
+  Unlike \l MainView there is no built-in header.
+
+  The simplest way to use a MainWindow is to include a single \l Page object:
+  \qml
+      import QtQuick 2.4
+      import Ubuntu.Components 1.3
+      import Ubuntu.Components.Labs 1.0
+
+      MainWindow {
+          minimumWidth: units.gu(48)
+          minimumHeight: units.gu(60)
+
+          Page {
+	      anchors.fill: parent
+              header: PageHeader {
+                  title: "Simple page"
+              }
+              Button {
+                  anchors {
+                      horizontalCenter: parent.horizontalCenter
+                      top: pageHeader.bottom
+                      topMargin: units.gu(5)
+                  }
+                  width: units.gu(15)
+                  text: "Push me"
+                  onClicked: print("Click!")
+              }
+          }
+      }
+  \endqml
+  Anchors need to be set, there's no automatic fill like with \l MainView.
+
+  Do not include multiple Pages directly, but use \l AdaptivePageLayout
+  inside MainWindow to navigate between several Pages.
+
+  If the \l Page inside the MainWindow includes a Flickable, set the flickable property of
+  the PageHeader to automatically hide and show the header when the user scrolls up or down:
+  \qml
+      import QtQuick 2.4
+      import Ubuntu.Components 1.3
+      import Ubuntu.Components.Labs 1.0
+
+      MainWindow {
+          minimumWidth: units.gu(48)
+          maximumHeight: units.gu(60)
+
+          Page {
+              anchors.fill: parent
+              header: PageHeader {
+                  title: "Page with Flickable"
+                  flickable: myFlickable
+              }
+
+              Flickable {
+                  id: myFlickable
+                  anchors.fill: parent
+                  contentHeight: column.height
+
+                  Column {
+                      id: column
+                      Repeater {
+                          model: 100
+                          Label {
+                              text: "line "+index
+                          }
+                      }
+                  }
+              }
+          }
+      }
+  \endqml
+  The same header behavior is automatic when using a ListView instead of a Flickable in the above
+  example.
+
+  The examples above show how to include a single \l Page inside a MainWindow, but more
+  advanced application structures are possible using \l AdaptivePageLayout.
+**/
+UCMainWindowPrivate::UCMainWindowPrivate()
+    : m_actionContext(nullptr),
+      m_units(nullptr)
+{
+}
+
+void UCMainWindowPrivate::init()
+{
+    Q_Q(UCMainWindow);
+
+    //need to init here because the q pointer is null in constructor
+    m_actionContext = new UCPopupContext(q);
+
+    m_actionContext->setObjectName(QStringLiteral("RootContext"));
+    m_actionContext->setActive(true);
+}
+
+UCMainWindow::UCMainWindow(QWindow *parent)
+    : QQuickWindow(*(new UCMainWindowPrivate), parent)
+{
+    d_func()->init();
+
+    QObject::connect(UbuntuI18n::instance(this), SIGNAL(domainChanged()),
+                     this, SIGNAL(i18nChanged()));
+    QObject::connect(UbuntuI18n::instance(this), SIGNAL(languageChanged()),
+                     this, SIGNAL(i18nChanged()));
+}
+
+/*!
+  \qmlproperty string MainWindow::applicationName
+
+  The property holds the application's name, which must be the same as the
+  desktop file's name.
+  The name also sets the name of the QCoreApplication and defaults for data
+  and cache folders that work on the desktop and under confinement, as well as
+  the default gettext domain.
+  C++ code that writes files may use QStandardPaths::writableLocation with
+  QStandardPaths::DataLocation or QStandardPaths::CacheLocation.
+*/
+QString UCMainWindow::applicationName() const
+{
+    return d_func()->m_applicationName;
+}
+
+void UCMainWindow::setApplicationName(QString applicationName)
+{
+    Q_D(UCMainWindow);
+
+    if (d->m_applicationName == applicationName)
+        return;
+
+    d->m_applicationName = applicationName;
+
+    if (applicationName != QStringLiteral("")) {
+        UbuntuI18n::instance()->setDomain(applicationName);
+        UCApplication::instance()->setApplicationName(applicationName);
+    }
+    Q_EMIT applicationNameChanged(applicationName);
+}
+
+/*!
+  \qmlproperty string MainWindow::organizationName
+
+  The property holds the optional name of the organization. If set, data
+  folders reside in a subfolder of the organizationName. By default no
+  organizationName is set.
+*/
+QString UCMainWindow::organizationName() const
+{
+    return d_func()->m_organizationName;
+}
+
+
+void UCMainWindow::setOrganizationName(QString organizationName)
+{
+    Q_D(UCMainWindow);
+
+    if (d->m_organizationName == organizationName)
+        return;
+
+    d->m_organizationName = organizationName;
+
+    if (organizationName != QStringLiteral("")) {
+        QCoreApplication::setOrganizationName(organizationName);
+    }
+    Q_EMIT organizationNameChanged(organizationName);
+}
+
+/*!
+  \qmlproperty Units MainWindow::units
+
+  Grid units for this particular window - unlike the global context property
+  by the same name.
+*/
+UCUnits* UCMainWindow::units()
+{
+    Q_D(UCMainWindow);
+
+    if (!d->m_units) {
+        d->m_units = new UCUnits(this);
+        QObject::connect(d->m_units, SIGNAL(gridUnitChanged()),
+                         this, SIGNAL(unitsChanged()));
+    }
+    return d->m_units;
+}
+
+/*!
+  \qmlproperty Units MainWindow::i18n
+
+  The property holds its breath for documentation.
+*/
+UbuntuI18n* UCMainWindow::i18n() const
+{
+    return UbuntuI18n::instance();
+}
+
+/*!
+  \qmlproperty ActionContext MainWindow::actionContext
+  \readonly
+  \since Ubuntu.Components 1.3
+  The action context of the MainWindow.
+  */
+UCPopupContext *UCMainWindow::actionContext() const
+{
+    return d_func()->m_actionContext;
+}
+
+UT_NAMESPACE_END
+
+#include "moc_ucmainwindow_p.cpp"

=== added file 'src/UbuntuToolkit/ucmainwindow_p.h'
--- src/UbuntuToolkit/ucmainwindow_p.h	1970-01-01 00:00:00 +0000
+++ src/UbuntuToolkit/ucmainwindow_p.h	2017-01-18 17:08:31 +0000
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2016-2017 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UCMAINWINDOW_P_H
+#define UCMAINWINDOW_P_H
+
+#include <QtQuick/QQuickWindow>
+
+#include <UbuntuToolkit/private/i18n_p.h>
+#include <UbuntuToolkit/private/ucunits_p.h>
+
+UT_NAMESPACE_BEGIN
+
+class UCMainWindowPrivate;
+class UCPopupContext;
+class UCAction;
+
+class UBUNTUTOOLKIT_EXPORT UCMainWindow : public QQuickWindow
+{
+    Q_OBJECT
+    Q_PROPERTY(QString applicationName READ applicationName WRITE setApplicationName NOTIFY applicationNameChanged)
+    Q_PROPERTY(QString organizationName READ organizationName WRITE setOrganizationName NOTIFY organizationNameChanged)
+#ifndef Q_QDOC
+    Q_PROPERTY(UT_PREPEND_NAMESPACE(UCUnits)* units READ units NOTIFY unitsChanged)
+    Q_PROPERTY(UT_PREPEND_NAMESPACE(UbuntuI18n)* i18n READ i18n NOTIFY i18nChanged)
+    Q_PROPERTY(UT_PREPEND_NAMESPACE(UCPopupContext)* actionContext READ actionContext NOTIFY actionContextChanged)
+#else
+    Q_PROPERTY(UCUnits* units READ units NOTIFY unitsChanged)
+    Q_PROPERTY(UbuntuI18n* i18n READ i18n NOTIFY i18nChanged)
+    Q_PROPERTY(UCPopupContext* actionContext READ actionContext NOTIFY actionContextChanged)
+#endif
+
+public:
+    UCMainWindow(QWindow *parent = nullptr);
+
+
+    QString applicationName() const;
+    void setApplicationName(QString applicationName);
+    QString organizationName() const;
+    void setOrganizationName(QString organizationName);
+
+    UCUnits* units();
+    UbuntuI18n* i18n() const;
+
+    UCPopupContext* actionContext() const;
+
+Q_SIGNALS:
+    void applicationNameChanged(QString applicationName);
+    void organizationNameChanged(QString applicationName);
+    void i18nChanged();
+    void unitsChanged();
+#ifndef Q_QDOC
+    void actionContextChanged(UT_PREPEND_NAMESPACE(UCPopupContext)* actionContext);
+#else
+    void actionContextChanged(UCPopupContext* actionContext);
+#endif
+
+private:
+    Q_DECLARE_PRIVATE(UCMainWindow)
+};
+
+UT_NAMESPACE_END
+
+#endif // UCMAINWINDOW_P_H

=== added file 'src/UbuntuToolkit/ucmainwindow_p_p.h'
--- src/UbuntuToolkit/ucmainwindow_p_p.h	1970-01-01 00:00:00 +0000
+++ src/UbuntuToolkit/ucmainwindow_p_p.h	2017-01-18 17:08:31 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016-2017 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UCMAINWINDOW_P_P_H
+#define UCMAINWINDOW_P_P_H
+
+#include <UbuntuToolkit/private/ucmainwindow_p.h>
+
+#include <QtQml/QQmlProperty>
+
+#include <QtQuick/private/qquickwindow_p.h>
+
+UT_NAMESPACE_BEGIN
+
+class UCMainWindow;
+class UCPopupContext;
+
+class UCMainWindowPrivate : public QQuickWindowPrivate
+{
+    Q_DECLARE_PUBLIC(UCMainWindow)
+
+public:
+    UCMainWindowPrivate();
+    void init();
+
+    QString m_applicationName;
+    QString m_organizationName;
+    UCPopupContext* m_actionContext = nullptr;
+    UCUnits* m_units = nullptr;
+
+};
+
+UT_NAMESPACE_END
+
+#endif // UCMAINWINDOW_P_P_H

=== modified file 'src/UbuntuToolkit/ucunits.cpp'
--- src/UbuntuToolkit/ucunits.cpp	2016-09-12 09:03:50 +0000
+++ src/UbuntuToolkit/ucunits.cpp	2017-01-18 17:08:31 +0000
@@ -97,18 +97,44 @@
  * isolated from Qt's own scaling concept.
  */
 
+UCUnits::UCUnits(QWindow *parent) :
+    QObject(parent),
+    m_devicePixelRatio(parent->devicePixelRatio())
+{
+    m_gridUnit = getenvFloat(ENV_GRID_UNIT_PX, DEFAULT_GRID_UNIT_PX * m_devicePixelRatio);
+    QObject::connect(parent, &QWindow::screenChanged,
+                     this, &UCUnits::screenChanged);
+    m_screen = parent->screen();
+    if (m_screen)
+        QObject::connect(m_screen, &QScreen::physicalDotsPerInchChanged,
+                         this, &UCUnits::devicePixelRatioChanged);
+}
+
+void UCUnits::screenChanged(QScreen *screen)
+{
+    if (m_screen)
+        QObject::disconnect(m_screen, &QScreen::physicalDotsPerInchChanged,
+                            this, &UCUnits::devicePixelRatioChanged);
+    m_screen = screen;
+    QObject::connect(m_screen, &QScreen::physicalDotsPerInchChanged,
+                     this, &UCUnits::devicePixelRatioChanged);
+    m_devicePixelRatio = screen->devicePixelRatio();
+    setGridUnit(DEFAULT_GRID_UNIT_PX * m_devicePixelRatio);
+}
+
+void UCUnits::devicePixelRatioChanged(qreal dpi)
+{
+    m_devicePixelRatio = dpi;
+    setGridUnit(DEFAULT_GRID_UNIT_PX * m_devicePixelRatio);
+}
+
 UCUnits *UCUnits::m_units = nullptr;
 
 UCUnits::UCUnits(QObject *parent) :
     QObject(parent),
     m_devicePixelRatio(qGuiApp->devicePixelRatio())
 {
-    // If GRID_UNIT_PX set, always use it. If not, 1GU := DEFAULT_GRID_UNIT_PX * m_devicePixelRatio
-    if (qEnvironmentVariableIsSet(ENV_GRID_UNIT_PX)) {
-        m_gridUnit = getenvFloat(ENV_GRID_UNIT_PX, DEFAULT_GRID_UNIT_PX);
-    } else {
-        m_gridUnit = DEFAULT_GRID_UNIT_PX * m_devicePixelRatio;
-    }
+    m_gridUnit = getenvFloat(ENV_GRID_UNIT_PX, DEFAULT_GRID_UNIT_PX * m_devicePixelRatio);
 
     auto nativeInterface = qGuiApp->platformNativeInterface();
     if (nativeInterface) {

=== modified file 'src/UbuntuToolkit/ucunits_p.h'
--- src/UbuntuToolkit/ucunits_p.h	2016-09-09 17:49:07 +0000
+++ src/UbuntuToolkit/ucunits_p.h	2017-01-18 17:08:31 +0000
@@ -23,6 +23,7 @@
 #include <QtCore/QObject>
 #include <QtCore/QString>
 #include <QtCore/QUrl>
+#include <QtGui/QWindow>
 
 #include <UbuntuToolkit/ubuntutoolkitglobal.h>
 
@@ -48,6 +49,7 @@
     }
 
     explicit UCUnits(QObject *parent = 0);
+    explicit UCUnits(QWindow *parent);
     ~UCUnits();
     Q_INVOKABLE float dp(float value);
     Q_INVOKABLE float gu(float value);
@@ -68,10 +70,13 @@
 
 private Q_SLOTS:
     void windowPropertyChanged(QPlatformWindow *window, const QString &propertyName);
+    void screenChanged(QScreen *screen);
+    void devicePixelRatioChanged(qreal dpi);
 
 private:
     static UCUnits *m_units;
     float m_devicePixelRatio;
+    QScreen *m_screen;
     float m_gridUnit;
 };
 

=== modified file 'src/imports/Components/Popups/1.3/PopupBase.qml'
--- src/imports/Components/Popups/1.3/PopupBase.qml	2016-04-13 19:32:20 +0000
+++ src/imports/Components/Popups/1.3/PopupBase.qml	2017-01-18 17:08:31 +0000
@@ -119,6 +119,14 @@
 
     /*!
       \internal
+      The function saves the active focus for later.
+      */
+    function __setPreviousActiveFocusItem(item) {
+        stateWrapper.prevFocus = item;
+    }
+
+    /*!
+      \internal
       Foreground component excluded from InverseMouseArea
       */
     property Item __foreground
@@ -177,30 +185,14 @@
     /*! \internal */
     onParentChanged: stateWrapper.rootItem = QuickUtils.rootItem(popupBase)
     Component.onCompleted: {
-        stateWrapper.saveActiveFocus();
         stateWrapper.rootItem = QuickUtils.rootItem(popupBase);
     }
 
     Item {
         id: stateWrapper
         property Item rootItem: QuickUtils.rootItem(popupBase)
-
-        property bool windowIsValid: typeof window != "undefined"
         property Item prevFocus
 
-        function saveActiveFocus() {
-            // 'window' context property is exposed to QML after component completion
-            // before rendering is complete, therefore a simple 'if (window)' check is
-            // not enough.
-            if (windowIsValid) {
-                prevFocus = window.activeFocusItem;
-                windowIsValidChanged.disconnect(saveActiveFocus);
-            } else {
-                // connect the function so we can save the original focus item
-                windowIsValidChanged.connect(saveActiveFocus);
-            }
-        }
-
         function restoreActiveFocus() {
             if (prevFocus) {
                 if (prevFocus.hasOwnProperty("requestFocus")) {

=== modified file 'src/imports/Components/Popups/1.3/popupUtils.js'
--- src/imports/Components/Popups/1.3/popupUtils.js	2016-09-15 15:53:27 +0000
+++ src/imports/Components/Popups/1.3/popupUtils.js	2017-01-18 17:08:31 +0000
@@ -66,6 +66,8 @@
     }
 
     var popupObject;
+    // If there's an active item, save it so we can restore it later
+    var prevFocusItem = (typeof window !== "undefined") ? window.activeFocusItem : null;
     if (params !== undefined) {
         popupObject = popupComponent.createObject(rootObject, params);
     } else {
@@ -75,8 +77,11 @@
         print(popupComponent.errorString().slice(0, -1));
         print("PopupUtils.open(): Failed to create the popup object.");
         return;
-    } else if (popupObject.hasOwnProperty("caller") && caller)
+    } else if (popupObject.hasOwnProperty("caller") && caller) {
         popupObject.caller = caller;
+    } else if (popupObject.hasOwnProperty("__setPreviousActiveFocusItem")) {
+        popupObject.__setPreviousActiveFocusItem(prevFocusItem);
+    }
 
     // if caller is specified, connect its cleanup to the popup's close
     // so popups will be removed together with the caller.

=== modified file 'tests/autopilot/ubuntuuitoolkit/__init__.py'
--- tests/autopilot/ubuntuuitoolkit/__init__.py	2016-04-21 03:23:24 +0000
+++ tests/autopilot/ubuntuuitoolkit/__init__.py	2017-01-18 17:08:31 +0000
@@ -18,7 +18,6 @@
 
 from ubuntuuitoolkit import (
     base,
-    environment,
     fixture_setup,
     tests,
     ubuntu_scenarios
@@ -59,7 +58,6 @@
     'ActionBar',
     'check_autopilot_version',
     'CheckBox',
-    'environment',
     'fixture_setup',
     'get_keyboard',
     'get_pointing_device',

=== removed file 'tests/autopilot/ubuntuuitoolkit/environment.py'
--- tests/autopilot/ubuntuuitoolkit/environment.py	2014-08-28 19:05:23 +0000
+++ tests/autopilot/ubuntuuitoolkit/environment.py	1970-01-01 00:00:00 +0000
@@ -1,68 +0,0 @@
-# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
-#
-# Copyright (C) 2014 Canonical Ltd.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; version 3.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import logging
-import subprocess
-
-from autopilot import logging as autopilot_logging
-
-
-logger = logging.getLogger(__name__)
-
-
-def is_initctl_env_var_set(variable, global_=False):
-    """Check True if an initctl environment variable is set.
-
-    :param variable: The name of the variable to check.
-    :param global: if True, the method will operate on the global environment
-        table. Default is False.
-    :return: True if the variable is set. False otherwise.
-
-    """
-    try:
-        get_initctl_env_var(variable, global_)
-        return True
-    except subprocess.CalledProcessError:
-        return False
-
-
-def get_initctl_env_var(variable, global_=False):
-    """Return the value of an initctl environment variable."""
-    command = ['/sbin/initctl', 'get-env', variable]
-    if global_:
-        command += ['--global']
-    output = subprocess.check_output(
-        command, stderr=subprocess.STDOUT, universal_newlines=True)
-    return output.rstrip()
-
-
-@autopilot_logging.log_action(logger.info)
-def set_initctl_env_var(variable, value, global_=False):
-    """Set the value of an initctl environment variable."""
-    command = ['/sbin/initctl', 'set-env', '%s=%s' % (variable, value)]
-    if global_:
-        command += ['--global']
-    subprocess.call(command, stderr=subprocess.STDOUT, universal_newlines=True)
-
-
-@autopilot_logging.log_action(logger.info)
-def unset_initctl_env_var(variable, global_=False):
-    """Remove an initctl environment variable."""
-    command = ['/sbin/initctl', 'unset-env', variable]
-    if global_:
-        command += ['--global']
-    subprocess.call(
-        command, stderr=subprocess.STDOUT, universal_newlines=True)

=== modified file 'tests/autopilot/ubuntuuitoolkit/fixture_setup.py'
--- tests/autopilot/ubuntuuitoolkit/fixture_setup.py	2015-07-09 21:55:03 +0000
+++ tests/autopilot/ubuntuuitoolkit/fixture_setup.py	2017-01-18 17:08:31 +0000
@@ -26,7 +26,7 @@
 from autopilot import display
 from gi.repository import Gio
 
-from ubuntuuitoolkit import base, environment
+from ubuntuuitoolkit import base
 
 
 DEFAULT_QML_FILE_CONTENTS = ("""
@@ -156,45 +156,6 @@
             url_dispatcher_file_path, shell=True)
 
 
-class InitctlEnvironmentVariable(fixtures.Fixture):
-    """Set the value of initctl environment variables."""
-
-    def __init__(self, global_=False, **kwargs):
-        super().__init__()
-        # Added one level of indirection to be able to spy the calls to
-        # environment during tests.
-        self.environment = environment
-        self.variables = kwargs
-        self.global_ = global_
-
-    def setUp(self):
-        super().setUp()
-        for variable, value in self.variables.items():
-            self._add_variable_cleanup(variable)
-            if value is None:
-                self.environment.unset_initctl_env_var(
-                    variable, global_=self.global_)
-            else:
-                self.environment.set_initctl_env_var(
-                    variable, value, global_=self.global_)
-
-    def _add_variable_cleanup(self, variable):
-        if self.environment.is_initctl_env_var_set(
-                variable, global_=self.global_):
-            original_value = self.environment.get_initctl_env_var(
-                variable, global_=self.global_)
-            self.addCleanup(
-                self.environment.set_initctl_env_var,
-                variable,
-                original_value,
-                global_=self.global_)
-        else:
-            self.addCleanup(
-                self.environment.unset_initctl_env_var,
-                variable,
-                global_=self.global_)
-
-
 class FakeHome(fixtures.Fixture):
 
     # We copy the Xauthority file to allow executions using XVFB. If it is not
@@ -210,10 +171,6 @@
         self.directory = self._make_directory_if_not_specified()
         if self.should_copy_xauthority_file:
             self._copy_xauthority_file(self.directory)
-        # We patch both environment variables so it works on the desktop and on
-        # the phone.
-        self.useFixture(
-            InitctlEnvironmentVariable(HOME=self.directory))
         self.useFixture(
             fixtures.EnvironmentVariable('HOME', newvalue=self.directory))
 

=== modified file 'tests/autopilot/ubuntuuitoolkit/tests/__init__.py'
--- tests/autopilot/ubuntuuitoolkit/tests/__init__.py	2015-12-09 14:21:53 +0000
+++ tests/autopilot/ubuntuuitoolkit/tests/__init__.py	2017-01-18 17:08:31 +0000
@@ -16,6 +16,7 @@
 
 """Ubuntu UI Toolkit autopilot tests."""
 
+import fixtures
 import os
 import tempfile
 
@@ -106,9 +107,7 @@
         desktop_file_name = os.path.basename(
             fake_application.desktop_file_path)
         application_name, _ = os.path.splitext(desktop_file_name)
-        self.app = self.launch_upstart_application(
-            application_name,
-            emulator_base=ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase)
+        self.app = self.launch_test_application(application_name)
 
     def use_local_modules(self, local_modules_path):
         env_vars = [
@@ -116,10 +115,9 @@
             'QML2_IMPORT_PATH',
             'UBUNTU_UI_TOOLKIT_THEMES_PATH'
         ]
-        kwargs = {'global_': True}
         for env in env_vars:
-            kwargs[env] = local_modules_path
-        self.useFixture(fixture_setup.InitctlEnvironmentVariable(**kwargs))
+            self.useFixture(fixtures.EnvironmentVariable(env,
+                                                         local_modules_path))
 
 
 class QMLStringAppTestCase(UbuntuUIToolkitWithFakeAppRunningTestCase):

=== modified file 'tests/autopilot/ubuntuuitoolkit/tests/components/test_units.py'
--- tests/autopilot/ubuntuuitoolkit/tests/components/test_units.py	2015-04-14 21:02:06 +0000
+++ tests/autopilot/ubuntuuitoolkit/tests/components/test_units.py	2017-01-18 17:08:31 +0000
@@ -23,10 +23,7 @@
 
 import fixtures
 
-from ubuntuuitoolkit import (
-    fixture_setup,
-    units
-)
+from ubuntuuitoolkit import units
 
 
 logger = logging.getLogger(__name__)
@@ -52,8 +49,6 @@
     def setUp(self):
         self.useFixture(fixtures.EnvironmentVariable(
             'GRID_UNIT_PX', self.grid_unit_px))
-        self.useFixture(fixture_setup.InitctlEnvironmentVariable(
-            global_=True, GRID_UNIT_PX=self.grid_unit_px))
         super().setUp()
 
     def test_gu(self):

=== modified file 'tests/autopilot/ubuntuuitoolkit/tests/gallery/__init__.py'
--- tests/autopilot/ubuntuuitoolkit/tests/gallery/__init__.py	2016-08-10 14:05:48 +0000
+++ tests/autopilot/ubuntuuitoolkit/tests/gallery/__init__.py	2017-01-18 17:08:31 +0000
@@ -17,7 +17,6 @@
 """Tests for the Ubuntu UI Toolkit Gallery"""
 
 import os
-import shutil
 
 from autopilot.matchers import Eventually
 from testtools.matchers import Equals

=== removed file 'tests/autopilot/ubuntuuitoolkit/tests/test_environment.py'
--- tests/autopilot/ubuntuuitoolkit/tests/test_environment.py	2014-08-29 16:12:02 +0000
+++ tests/autopilot/ubuntuuitoolkit/tests/test_environment.py	1970-01-01 00:00:00 +0000
@@ -1,89 +0,0 @@
-# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
-#
-# Copyright (C) 2014 Canonical Ltd.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; version 3.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import uuid
-
-import testtools
-
-from ubuntuuitoolkit import environment
-
-
-class InitctlEnvironmentVariableTestCase(testtools.TestCase):
-
-    def test_is_environment_variable_set_with_unset_variable(self):
-        """Test that is_initctl_env_var_set returns False for unset vars."""
-        variable = 'I do not exist {}'.format(uuid.uuid1())
-        self.assertFalse(environment.is_initctl_env_var_set(variable))
-
-    def test_is_environment_variable_set_with_set_variable(self):
-        """Test that is_initctl_env_var_set returns True for existing vars."""
-        variable = 'Test variable to set {}'.format(uuid.uuid1())
-        self.addCleanup(environment.unset_initctl_env_var, variable)
-
-        environment.set_initctl_env_var(variable, 'dummy')
-
-        self.assertTrue(environment.is_initctl_env_var_set(variable))
-
-    def test_get_environment_variable(self):
-        """Test that get_initctl_env_var returns the right value."""
-        variable = 'Test variable to get {}'.format(uuid.uuid1())
-        self.addCleanup(environment.unset_initctl_env_var, variable)
-        environment.set_initctl_env_var(variable, 'test value')
-
-        self.assertEqual(
-            'test value', environment.get_initctl_env_var(variable))
-
-    def test_unset_environment_variable(self):
-        """Test that unset_initctl_env_var removes the variable."""
-        variable = 'Test variable to unset {}'.format(uuid.uuid1())
-        environment.set_initctl_env_var(variable, 'dummy')
-
-        environment.unset_initctl_env_var(variable)
-
-        self.assertFalse(environment.is_initctl_env_var_set(variable))
-
-    def test_unset_environment_variable_with_unset_variable(self):
-        """Test that unset_initctl_env_var does nothing with unset var."""
-        variable = 'I do not exist {}'.format(uuid.uuid1())
-
-        environment.unset_initctl_env_var(variable)
-
-        self.assertFalse(environment.is_initctl_env_var_set(variable))
-
-    def test_is_global_environment_variable_set_with_unset_variable(self):
-        """Test is_initctl_env_var_set returns False for unset global vars."""
-        variable = 'I do not exist global {}'.format(uuid.uuid1())
-
-        self.assertFalse(environment.is_initctl_env_var_set(
-            variable, global_=True))
-
-    def test_get_global_environment_variable(self):
-        """Test that get_initctl_env_var returns the right global value."""
-        variable = 'Test variable to get {}'.format(uuid.uuid1())
-        self.addCleanup(
-            environment.unset_initctl_env_var, variable, global_=True)
-        environment.set_initctl_env_var(variable, 'test value', global_=True)
-
-        self.assertEqual(
-            'test value',
-            environment.get_initctl_env_var(variable, global_=True))
-
-    def test_unset_global_environment_variable(self):
-        """Test that unset_initctl_env_var removes the global variable."""
-        variable = 'Test variable to unset {}'.format(uuid.uuid1())
-
-        environment.set_initctl_env_var(variable, 'dummy', global_=True)
-        environment.unset_initctl_env_var(variable, global_=True)

=== modified file 'tests/autopilot/ubuntuuitoolkit/tests/test_fixture_setup.py'
--- tests/autopilot/ubuntuuitoolkit/tests/test_fixture_setup.py	2015-07-09 21:55:03 +0000
+++ tests/autopilot/ubuntuuitoolkit/tests/test_fixture_setup.py	2017-01-18 17:08:31 +0000
@@ -19,18 +19,16 @@
 import tempfile
 
 from unittest import mock
-import testscenarios
 import testtools
 from autopilot import (
     display,
-    introspection,
     platform,
     testcase as autopilot_testcase
 )
 from autopilot.matchers import Eventually
 from testtools.matchers import Contains, Equals, FileExists, Not
 
-from ubuntuuitoolkit import base, environment, fixture_setup, tests
+from ubuntuuitoolkit import base, fixture_setup, tests
 
 
 class FakeApplicationTestCase(testtools.TestCase):
@@ -190,9 +188,6 @@
             url_dispatcher_protocols=['testprotocol'])
         self.useFixture(fake_application)
 
-        self.useFixture(fixture_setup.InitctlEnvironmentVariable(
-            QT_LOAD_TESTABILITY=1))
-
         self.addCleanup(
             subprocess.check_output,
             ['ubuntu-app-stop', fake_application.application_name])
@@ -202,135 +197,11 @@
 
         pid = int(subprocess.check_output(
             ['ubuntu-app-pid', fake_application.application_name]).strip())
-
-        application = introspection.get_proxy_object_for_existing_process(
-            pid=pid)
-
-        # We can select a component from the application.
-        application.select_single('Label', objectName='testLabel')
-
-
-class InitctlEnvironmentVariableTestCase(testscenarios.TestWithScenarios):
-
-    scenarios = [
-        ('global_variable', {'global_': True}),
-        ('local_variable', {'global_': False})
-    ]
-
-    def set_original_value(self, value):
-        self.addCleanup(
-            environment.unset_initctl_env_var, 'testenvvarforfixture',
-            global_=self.global_)
-        environment.set_initctl_env_var('testenvvarforfixture',
-                                        value, global_=self.global_)
-
-    def create_fixture(self, value):
-        self.initctl_env_var = fixture_setup.InitctlEnvironmentVariable(
-            testenvvarforfixture=value, global_=self.global_)
-
-    def assertValueIs(self, expected_value):
-        self.assertEqual(
-            expected_value,
-            environment.get_initctl_env_var(
-                'testenvvarforfixture', global_=self.global_))
-
-    def assertVariableIsNotSet(self):
-        self.assertFalse(
-            environment.is_initctl_env_var_set(
-                'testenvvarforfixture', global_=self.global_))
-
-    def assertTestIsSuccessful(self, expected_value, test_name):
-        result = testtools.TestResult()
-
-        class TestWithInitctlEnvVar(testtools.TestCase):
-            def setUp(inner):
-                super().setUp()
-                inner.useFixture(self.initctl_env_var)
-
-            def test_value_set(inner):
-                self.assertValueIs(expected_value)
-
-            def test_variable_not_set(inner):
-                self.assertVariableIsNotSet()
-
-        TestWithInitctlEnvVar(test_name).run(result)
-        self.assertTrue(
-            result.wasSuccessful(), 'Failed to set the environment variable.')
-
-    def test_use_initctl_environment_variable_to_set_unexisting_variable(self):
-        """Test the initctl env var fixture when the var is unset.
-
-        During the test, the new value must be in place.
-        After the test, the variable must be unset again.
-
-        """
-        self.create_fixture('test value')
-        self.assertTestIsSuccessful('test value', 'test_value_set')
-        self.assertVariableIsNotSet()
-
-    def test_use_initctl_environment_variable_to_set_existing_variable(self):
-        """Test the initctl env var fixture when the var is unset.
-
-        During the test, the new value must be in place.
-        After the test, the old value must be set again.
-
-        """
-        self.set_original_value('original test value')
-        self.create_fixture('new test value')
-        self.assertTestIsSuccessful('new test value', 'test_value_set')
-        self.assertValueIs('original test value')
-
-    def test_use_initctl_environment_variable_to_unset_existing_variable(self):
-        """Test the initctl env var fixture to unset a variable.
-
-        During the test, the variable must be unset.
-        After the test, the old value must be set again.
-
-        """
-        self.set_original_value('original test value')
-        self.create_fixture(None)
-        self.assertTestIsSuccessful(None, 'test_variable_not_set')
-        self.assertValueIs('original test value',)
-
-    def test_use_initctl_environment_variable_to_unset_nonexisting_variable(
-            self):
-        """Test the initctl env var fixture to unset a variable.
-
-        During the test, the variable must be unset.
-        After the test, the variable must remain unset.
-
-        """
-        self.create_fixture(None)
-        self.assertTestIsSuccessful(None, 'test_variable_not_set')
-        self.assertVariableIsNotSet()
+        self.assertGreater(pid, 0)
 
 
 class FakeHomeTestCase(testtools.TestCase):
 
-    def test_fake_home_fixture_patches_initctl_env_var(self):
-        original_home = environment.get_initctl_env_var('HOME')
-        fake_home = original_home + 'fake'
-        result = testtools.TestResult()
-
-        def inner_test():
-            class TestWithFakeHome(testtools.TestCase):
-                def test_it(self):
-                    fake_home_fixture = fixture_setup.FakeHome(fake_home)
-                    fake_home_fixture.should_copy_xauthority_file = False
-                    self.useFixture(fake_home_fixture)
-                    self.assertEqual(
-                        fake_home, environment.get_initctl_env_var('HOME'))
-            return TestWithFakeHome('test_it')
-
-        inner_test().run(result)
-
-        self.assertTrue(
-            result.wasSuccessful(),
-            'Failed to fake the home: {}'.format(result.errors))
-        self.assertEqual(
-            original_home,
-            environment.get_initctl_env_var('HOME'))
-
     def test_fake_home_fixture_patches_env_var(self):
         original_home = os.environ.get('HOME')
         fake_home = tempfile.gettempdir()

=== renamed file 'tests/autopilot/ubuntuuitoolkit/tests/test_launcher.window.qml' => 'tests/autopilot/ubuntuuitoolkit/tests/test_launcher.mainwindow.qml'
--- tests/autopilot/ubuntuuitoolkit/tests/test_launcher.window.qml	2016-07-12 12:05:11 +0000
+++ tests/autopilot/ubuntuuitoolkit/tests/test_launcher.mainwindow.qml	2017-01-18 17:08:31 +0000
@@ -17,23 +17,30 @@
 import QtQuick 2.4
 import QtQuick.Window 2.2 // Not Ubuntu.Test
 import Ubuntu.Components 1.3
+import Ubuntu.Components.Labs 1.3
 
-Window {
-    title: "Hello World"
+MainWindow {
+    title: i18n.tr("Hello World")
     minimumWidth: units.gu(30)
     minimumHeight: units.gu(50)
     maximumWidth: units.gu(90)
     maximumHeight: units.gu(120)
-    MainView {
+
+    Item {
+        anchors.fill: parent
         objectName: "mainView"
 
         Page {
-            title: "Launcher/Window"
+            anchors.fill: parent
+            header: PageHeader {
+                title: "Launcher/Window"
+            }
 
             Column {
+                anchors.top: parent.header.bottom
                 Label {
                     objectName: "label"
-                    text: "Lorem ipsum dolor sit amet"
+                    text: i18n.tr("Lorem ipsum dolor sit amet")
                     width: units.gu(25)
                     height: units.gu(25)
                 }

=== modified file 'tests/autopilot/ubuntuuitoolkit/tests/test_launcher.py'
--- tests/autopilot/ubuntuuitoolkit/tests/test_launcher.py	2016-07-12 12:05:11 +0000
+++ tests/autopilot/ubuntuuitoolkit/tests/test_launcher.py	2017-01-18 17:08:31 +0000
@@ -49,6 +49,18 @@
                         Eventually(Equals("Lorem ipsum dolor sit amet")))
 
 
+class LauncherMainWindowTestCase(tests.QMLFileAppTestCase):
+    path = os.path.abspath(__file__)
+    dir_path = os.path.dirname(path)
+    test_qml_file_path = os.path.join(
+        dir_path, 'test_launcher.mainwindow.qml')
+
+    def test_window_root_item(self):
+        label = self.main_view.select_single(objectName="label")
+        self.assertThat(label.text,
+                        Eventually(Equals("Lorem ipsum dolor sit amet")))
+
+
 class LauncherQtTestTestCase(tests.QMLFileAppTestCase):
     path = os.path.abspath(__file__)
     dir_path = os.path.dirname(path)

=== added file 'tests/autopilot/ubuntuuitoolkit/tests/test_launcher.window.qml'
--- tests/autopilot/ubuntuuitoolkit/tests/test_launcher.window.qml	1970-01-01 00:00:00 +0000
+++ tests/autopilot/ubuntuuitoolkit/tests/test_launcher.window.qml	2017-01-18 17:08:31 +0000
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2014-2016 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import QtQuick 2.4
+import QtQuick.Window 2.2 // Not Ubuntu.Test
+import Ubuntu.Components 1.3
+
+Window {
+    title: "Hello World"
+    minimumWidth: units.gu(30)
+    minimumHeight: units.gu(50)
+    maximumWidth: units.gu(90)
+    maximumHeight: units.gu(120)
+    MainView {
+        objectName: "mainView"
+
+        Page {
+            title: "Launcher/Window"
+
+            Column {
+                Label {
+                    objectName: "label"
+                    text: "Lorem ipsum dolor sit amet"
+                    width: units.gu(25)
+                    height: units.gu(25)
+                }
+            }
+        }
+    }
+}

=== modified file 'tests/autopilot/ubuntuuitoolkit/units.py'
--- tests/autopilot/ubuntuuitoolkit/units.py	2015-02-07 05:03:06 +0000
+++ tests/autopilot/ubuntuuitoolkit/units.py	2017-01-18 17:08:31 +0000
@@ -18,18 +18,12 @@
 
 import os
 
-from ubuntuuitoolkit import environment
-
-
 ENV_GRID_UNIT_PX = 'GRID_UNIT_PX'
 DEFAULT_GRID_UNIT_PX = 8
 
 
 def get_grid_unit():
     grid_unit_px = os.environ.get(ENV_GRID_UNIT_PX, None)
-    if not grid_unit_px and environment.is_initctl_env_var_set(
-            ENV_GRID_UNIT_PX):
-        grid_unit_px = environment.get_initctl_env_var(ENV_GRID_UNIT_PX)
     return float(grid_unit_px or DEFAULT_GRID_UNIT_PX)
 
 

=== modified file 'tests/packaging-sorting.sh'
--- tests/packaging-sorting.sh	2016-05-02 08:37:47 +0000
+++ tests/packaging-sorting.sh	2017-01-18 17:08:31 +0000
@@ -15,28 +15,30 @@
 #
 # Author: Timo Jyrinki <timo.jyrinki@xxxxxxxxxxxxx>
 
+# Get the current script directory (compatible with Bash and ZSH)
+SCRIPT_DIR=`dirname ${BASH_SOURCE[0]-$0}`
+SCRIPT_DIR=`cd $SCRIPT_DIR && pwd`
+
+SRC=$SCRIPT_DIR/..
 # Ensure packaging has gone through wrap-and-sort command
-
-if [ ! -f  "/usr/bin/wrap-and-sort" ] ; then
-  echo "Please install 'devscripts' package"
-  exit 1
-fi
-
-cd $(dirname $0)
 tmpdir=$(mktemp -d)
-cp -a ../debian $tmpdir
-
+cp -a $SRC/debian $tmpdir
 wrap-and-sort -a -t -d $tmpdir/debian/
-# Verify control.gles which otherwise isn't picked up
-wrap-and-sort -a -t -d $tmpdir/debian/ -f $tmpdir/debian/control.gles
+[ $? == 2 ] && exit 2
+# Note: control.gles may be moved in gles builds
+if [ -f $tmpdir/debian/control.gles ] ; then
+ # Verify control.gles which otherwise isn't picked up
+ wrap-and-sort -a -t -d $tmpdir/debian/ -f $tmpdir/debian/control.gles
+fi
+[ $? == 2 ] && exit 2
 
-diff -urN ../debian $tmpdir/debian
+diff -urN $SRC/debian $tmpdir/debian
 
 if [ $? == 1 ] ; then
  echo 
  echo 
  echo "*******************************************************"
- echo "Please run 'wrap-and-sort -a -t' to clean up packaging."
+ echo "Please run 'wrap-and-sort -a -t; wrap-and-sort -a -t -f debian/control.gles' to clean up packaging."
  echo "*******************************************************"
  echo 
  exit 1

=== added directory 'tests/unit/mainwindow'
=== added file 'tests/unit/mainwindow/AppName.qml'
--- tests/unit/mainwindow/AppName.qml	1970-01-01 00:00:00 +0000
+++ tests/unit/mainwindow/AppName.qml	2017-01-18 17:08:31 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2013-2017 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import QtQuick 2.4
+import Ubuntu.Components 1.3
+import Ubuntu.Components.Labs 1.0
+
+MainWindow {
+    objectName: "appName"
+    applicationName: "org.gnu.wildebeest"
+
+    Label {
+        text: "Lorem ipsum dolor sit amet"
+    }
+}

=== added file 'tests/unit/mainwindow/OrganizationName.qml'
--- tests/unit/mainwindow/OrganizationName.qml	1970-01-01 00:00:00 +0000
+++ tests/unit/mainwindow/OrganizationName.qml	2017-01-18 17:08:31 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013-2017 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import QtQuick 2.4
+import Ubuntu.Components 1.3
+import Ubuntu.Components.Labs 1.0
+
+MainWindow {
+    objectName: "appName"
+    applicationName: "tv.island.pacific"
+    organizationName: "pacifist"
+
+    Label {
+        text: "Lorem ipsum dolor sit amet"
+    }
+}

=== added file 'tests/unit/mainwindow/mainwindow.pro'
--- tests/unit/mainwindow/mainwindow.pro	1970-01-01 00:00:00 +0000
+++ tests/unit/mainwindow/mainwindow.pro	2017-01-18 17:08:31 +0000
@@ -0,0 +1,5 @@
+CONFIG += custom_qpa   # needed by test to set device pixel ratio correctly
+include(../test-include.pri)
+
+QT += gui
+SOURCES += tst_mainwindow.cpp

=== added file 'tests/unit/mainwindow/tst_mainwindow.cpp'
--- tests/unit/mainwindow/tst_mainwindow.cpp	1970-01-01 00:00:00 +0000
+++ tests/unit/mainwindow/tst_mainwindow.cpp	2017-01-18 17:08:31 +0000
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2012-2016 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Christian Dywan <christian.dywan@xxxxxxxxxxxxx>
+ */
+
+#include <QtCore/QString>
+#include <QtCore/QTextCodec>
+#include <QtCore/QStandardPaths>
+#include <QtCore/QProcessEnvironment>
+#include <QtCore/QDebug>
+#include <QtTest/QTest>
+#include <QtTest/QSignalSpy>
+#include <QtCore/QCoreApplication>
+#include <QtQml/QQmlEngine>
+#include <QtQuick/QQuickView>
+#include <QtQuick/QQuickItem>
+#include <QtCore/QThread>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtCore/QCryptographicHash>
+#include <QtCore/QSettings>
+
+#include <QtQuick/QQuickItem>
+#include <QtQuick/QQuickView>
+#include <QtGui/QGuiApplication>
+#include <QtQml/QQmlEngine>
+#include <QtQml/QQmlContext>
+#include <QtQml/QQmlComponent>
+
+#include <UbuntuToolkit/ubuntutoolkitmodule.h>
+#include <UbuntuToolkit/private/ucapplication_p.h>
+#include <UbuntuToolkit/private/ucunits_p.h>
+
+UT_USE_NAMESPACE
+
+class tst_MainWindow : public QObject
+{
+    Q_OBJECT
+
+public:
+    tst_MainWindow()
+    {
+    }
+
+    QQuickWindow *loadTest(const QString &document)
+    {
+        // Can't use UbuntuTestCase: We need a Window root item
+        QPointer<QQmlEngine> engine(new QQmlEngine());
+        QString modulePath(UBUNTU_QML_IMPORT_PATH);
+        if (!QDir(modulePath).exists()) {
+            qWarning("'%s' doesn't exist", qPrintable(modulePath));
+            return 0;
+        }
+        engine->addImportPath(modulePath);
+        UbuntuToolkitModule::initializeContextProperties(engine);
+        QPointer<QQmlComponent> component(new QQmlComponent(engine));
+        component->loadUrl(QUrl::fromLocalFile(document), QQmlComponent::Asynchronous);
+        while (component->isLoading())
+            QCoreApplication::processEvents();
+        QObject *toplevel(component->create());
+        if (component->errorString() != "") {
+            qWarning("%s", qPrintable(component->errorString()));
+            return 0;
+        }
+        QQuickWindow* window(qobject_cast<QQuickWindow *>(toplevel));
+        if (window)
+            engine->setIncubationController(window->incubationController());
+        else {
+            QQuickItem *rootItem = qobject_cast<QQuickItem *>(toplevel);
+            if (rootItem) {
+                QQuickView *view(new QQuickView(engine, 0));
+                window = view;
+                view->setResizeMode(QQuickView::SizeRootObjectToView);
+                view->setContent(document, component, rootItem);
+            }
+        }
+        return window;
+    }
+
+    QQuickItem *testItem(QQuickItem *that, const QString &identifier)
+    {
+        if (that->property(identifier.toLocal8Bit()).isValid())
+            return that->property(identifier.toLocal8Bit()).value<QQuickItem*>();
+
+        QList<QQuickItem*> children = that->findChildren<QQuickItem*>(identifier);
+        return (children.count() > 0) ? children[0] : 0;
+    }
+
+private Q_SLOTS:
+
+    void initTestCase()
+    {
+    }
+
+    void cleanupTestCase()
+    {
+    }
+
+    // Note: tests/unit/mainview13 contains the UCApplication bits
+
+    void testCase_AppName()
+    {
+        QString applicationName("org.gnu.wildebeest");
+        QQuickWindow *mainWindow(loadTest("AppName.qml"));
+        QVERIFY(mainWindow);
+        QCOMPARE(applicationName, mainWindow->property("applicationName").toString());
+        QCOMPARE(applicationName, QCoreApplication::applicationName());
+        QCOMPARE(QString(""), QCoreApplication::organizationName());
+    }
+
+    void testCase_OrganizationName()
+    {
+        QString applicationName("tv.island.pacific");
+        QString organizationName("pacifist");
+        QQuickWindow *mainWindow(loadTest("OrganizationName.qml"));
+        QVERIFY(mainWindow);
+        QCOMPARE(applicationName, mainWindow->property("applicationName").toString());
+        QCOMPARE(applicationName, QCoreApplication::applicationName());
+        QCOMPARE(organizationName, mainWindow->property("organizationName").toString());
+        QCOMPARE(organizationName, QCoreApplication::organizationName());
+    }
+};
+
+QTEST_MAIN(tst_MainWindow)
+
+#include "tst_mainwindow.moc"

=== modified file 'tests/unit/unit.pro'
--- tests/unit/unit.pro	2016-09-30 05:39:57 +0000
+++ tests/unit/unit.pro	2017-01-18 17:08:31 +0000
@@ -41,6 +41,7 @@
     performance \
     mainview11 \
     mainview13 \
+    mainwindow \
     i18n \
     arguments \
     argument \

=== modified file 'tests/unit/visual/tst_focus.13.qml'
--- tests/unit/visual/tst_focus.13.qml	2016-09-19 16:40:49 +0000
+++ tests/unit/visual/tst_focus.13.qml	2017-01-18 17:08:31 +0000
@@ -414,13 +414,13 @@
                             component: dialogComponent,
                             item: null,
                             foreground_name: "dialogForeground",
-                            bug: "1569979"
+                            bug: "" // this is not buggy
                         },
                         {   tag: "Popover component",
                             component: popoverComponent,
                             item: null,
                             foreground_name: "popover_foreground",
-                            bug: "" // this is the only case without a bug
+                            bug: "" // this is not buggy
                         },
                         {   tag: "Dialog item",
                             component: null,

=== modified file 'tests/unit/visual/tst_popups_dialog.13.qml'
--- tests/unit/visual/tst_popups_dialog.13.qml	2016-06-15 13:46:51 +0000
+++ tests/unit/visual/tst_popups_dialog.13.qml	2017-01-18 17:08:31 +0000
@@ -47,6 +47,21 @@
             keyClick(Qt.Key_Escape);
             tryCompare(test, "dialogDestroyed", true, 500, "Dialog not destroyed");
         }
+
+        function test_focus_restore_ondismiss_dialog() {
+            pressMe.forceActiveFocus();
+
+            tryCompare(window, "activeFocusItem", pressMe);
+
+            var dlg = PopupUtils.open(dialog);
+            waitForRendering(dlg);
+
+            tryCompare(window, "activeFocusItem", dlg.button);
+
+            keyClick(Qt.Key_Escape);
+
+            tryCompare(window, "activeFocusItem", pressMe);
+        }
     }
 
     Component {
@@ -54,10 +69,13 @@
         Dialog {
             id: ahojDialog
             title: "Ahoj"
+            property alias button: closeButton
 
             Button {
+                id: closeButton
                 text: "Close"
                 onClicked: PopupUtils.close(ahojDialog)
+                focus: true
             }
         }
     }