on xenial help sign in
Add a warning dialog when disconnecting the external monitor.
19014f1Michael Zanetti
plugins/Utils/CMakeLists.txt+2
@@ -10,6 +10,8 @@ include_directories(
10
10
11set(QMLPLUGIN_SRC
11set(QMLPLUGIN_SRC
12 activefocuslogger.cpp
12 activefocuslogger.cpp
13+ ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
14+ applicationsfiltermodel.cpp
13 constants.cpp
15 constants.cpp
14 HomeKeyWatcher.cpp
16 HomeKeyWatcher.cpp
15 inputwatcher.cpp
17 inputwatcher.cpp
plugins/Utils/applicationsfiltermodel.cppnew file+101
@@ -0,0 +1,101 @@
1+/*
2+ * Copyright (C) 2015 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+// unity-api
18+#include <unity/shell/application/ApplicationManagerInterface.h>
19+#include <unity/shell/application/ApplicationInfoInterface.h>
20+
21+#include "applicationsfiltermodel.h"
22+
23+using namespace unity::shell::application;
24+
25+ApplicationsFilterModel::ApplicationsFilterModel(QObject *parent):
26+ QSortFilterProxyModel(parent),
27+ m_appModel(nullptr),
28+ m_filterTouchApps(false),
29+ m_filterLegacyApps(false)
30+{
31+}
32+
33+ApplicationManagerInterface *ApplicationsFilterModel::applicationsModel() const
34+{
35+ return m_appModel;
36+}
37+
38+void ApplicationsFilterModel::setApplicationsModel(ApplicationManagerInterface *applicationsModel)
39+{
40+ if (m_appModel != applicationsModel) {
41+ if (m_appModel) {
42+ disconnect(m_appModel, &ApplicationManagerInterface::countChanged, this, &ApplicationsFilterModel::countChanged);
43+ }
44+ m_appModel = applicationsModel;
45+ setSourceModel(m_appModel);
46+ Q_EMIT applicationsModelChanged();
47+ connect(m_appModel, &ApplicationManagerInterface::countChanged, this, &ApplicationsFilterModel::countChanged);
48+ }
49+}
50+
51+bool ApplicationsFilterModel::filterTouchApps() const
52+{
53+ return m_filterTouchApps;
54+}
55+
56+void ApplicationsFilterModel::setFilterTouchApps(bool filterTouchApps)
57+{
58+ if (m_filterTouchApps != filterTouchApps) {
59+ m_filterTouchApps = filterTouchApps;
60+ Q_EMIT filterTouchAppsChanged();
61+
62+ invalidateFilter();
63+ Q_EMIT countChanged();
64+ }
65+}
66+
67+bool ApplicationsFilterModel::filterLegacyApps() const
68+{
69+ return m_filterLegacyApps;
70+}
71+
72+void ApplicationsFilterModel::setFilterLegacyApps(bool filterLegacyApps)
73+{
74+ if (m_filterLegacyApps != filterLegacyApps) {
75+ m_filterLegacyApps = filterLegacyApps;
76+ Q_EMIT filterLegacyAppsChanged();
77+
78+ invalidateFilter();
79+ Q_EMIT countChanged();
80+ }
81+}
82+
83+bool ApplicationsFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
84+{
85+ Q_UNUSED(source_parent);
86+
87+ ApplicationInfoInterface *app = m_appModel->get(source_row);
88+ Q_ASSERT(app);
89+ if (m_filterLegacyApps && !app->isTouchApp()) {
90+ return false;
91+ }
92+ if (m_filterTouchApps && app->isTouchApp()) {
93+ return false;
94+ }
95+ return true;
96+}
97+
98+ApplicationInfoInterface *ApplicationsFilterModel::get(int index) const
99+{
100+ return m_appModel->get(mapToSource(this->index(index, 0)).row());
101+}
plugins/Utils/applicationsfiltermodel.hnew file+69
@@ -0,0 +1,69 @@
1+/*
2+ * Copyright (C) 2015 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef APPLICATIONSFILTERMODEL_H
18+#define APPLICATIONSFILTERMODEL_H
19+
20+#include <QSortFilterProxyModel>
21+
22+namespace unity {
23+namespace shell {
24+namespace application {
25+class ApplicationManagerInterface;
26+class ApplicationInfoInterface;
27+}
28+}
29+}
30+using namespace unity::shell::application;
31+
32+class ApplicationsFilterModel: public QSortFilterProxyModel
33+{
34+ Q_OBJECT
35+
36+ Q_PROPERTY(unity::shell::application::ApplicationManagerInterface* applicationsModel READ applicationsModel WRITE setApplicationsModel NOTIFY applicationsModelChanged)
37+ Q_PROPERTY(bool filterTouchApps READ filterTouchApps WRITE setFilterTouchApps NOTIFY filterTouchAppsChanged)
38+ Q_PROPERTY(bool filterLegacyApps READ filterLegacyApps WRITE setFilterLegacyApps NOTIFY filterLegacyAppsChanged)
39+
40+ Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
41+public:
42+ ApplicationsFilterModel(QObject *parent = 0);
43+
44+ ApplicationManagerInterface* applicationsModel() const;
45+ void setApplicationsModel(ApplicationManagerInterface* applicationsModel);
46+
47+ bool filterTouchApps() const;
48+ void setFilterTouchApps(bool filterTouchApps);
49+
50+ bool filterLegacyApps() const;
51+ void setFilterLegacyApps(bool filterLegacyApps);
52+
53+ bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
54+
55+ Q_INVOKABLE unity::shell::application::ApplicationInfoInterface* get(int index) const;
56+
57+Q_SIGNALS:
58+ void applicationsModelChanged();
59+ void filterTouchAppsChanged();
60+ void filterLegacyAppsChanged();
61+ void countChanged();
62+
63+private:
64+ ApplicationManagerInterface* m_appModel;
65+ bool m_filterTouchApps;
66+ bool m_filterLegacyApps;
67+};
68+
69+#endif
plugins/Utils/plugin.cpp+2
@@ -35,6 +35,7 @@
35#include "windowstatestorage.h"
35#include "windowstatestorage.h"
36#include "constants.h"
36#include "constants.h"
37#include "timezoneFormatter.h"
37#include "timezoneFormatter.h"
38+#include "applicationsfiltermodel.h"
38
39
39static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
40static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
40{
41{
@@ -66,6 +67,7 @@ void UtilsPlugin::registerTypes(const char *uri)
66 qmlRegisterSingletonType<TimezoneFormatter>(uri, 0, 1, "TimezoneFormatter",
67 qmlRegisterSingletonType<TimezoneFormatter>(uri, 0, 1, "TimezoneFormatter",
67 [](QQmlEngine*, QJSEngine*) -> QObject* { return new TimezoneFormatter; });
68 [](QQmlEngine*, QJSEngine*) -> QObject* { return new TimezoneFormatter; });
68 qmlRegisterType<ActiveFocusLogger>(uri, 0, 1, "ActiveFocusLogger");
69 qmlRegisterType<ActiveFocusLogger>(uri, 0, 1, "ActiveFocusLogger");
70+ qmlRegisterType<ApplicationsFilterModel>(uri, 0, 1, "ApplicationsFilterModel");
69}
71}
70
72
71void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
73void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
qml/Components/Dialogs.qml+29−2
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2014-2015 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@ import Unity.Session 0.1
21import GlobalShortcut 1.0
21import GlobalShortcut 1.0
22import Ubuntu.Components 1.3
22import Ubuntu.Components 1.3
23import Unity.Platform 1.0
23import Unity.Platform 1.0
24+import Utils 0.1
24import "../Greeter"
25import "../Greeter"
25
26
26Item {
27Item {
@@ -45,6 +46,31 @@ Item {
45 d.showPowerDialog();
46 d.showPowerDialog();
46 }
47 }
47
48
49+ onUsageScenarioChanged: {
50+ if (usageScenario != "desktop" && legacyAppsModel.count > 0 && !d.modeSwitchWarningPopup) {
51+ var comp = Qt.createComponent(Qt.resolvedUrl("ModeSwitchWarningDialog.qml"))
52+ d.modeSwitchWarningPopup = comp.createObject(root, {model: legacyAppsModel});
53+ d.modeSwitchWarningPopup.forceClose.connect(function() {
54+ while (legacyAppsModel.count > 0) {
55+ ApplicationManager.stopApplication(legacyAppsModel.get(0).appId);
56+ }
57+ d.modeSwitchWarningPopup.hide();
58+ d.modeSwitchWarningPopup.destroy();
59+ d.modeSwitchWarningPopup = null;
60+ })
61+ } else if (usageScenario == "desktop" && d.modeSwitchWarningPopup) {
62+ d.modeSwitchWarningPopup.hide();
63+ d.modeSwitchWarningPopup.destroy();
64+ d.modeSwitchWarningPopup = null;
65+ }
66+ }
67+
68+ ApplicationsFilterModel {
69+ id: legacyAppsModel
70+ applicationsModel: ApplicationManager
71+ filterTouchApps: true
72+ }
73+
48 GlobalShortcut { // reboot/shutdown dialog
74 GlobalShortcut { // reboot/shutdown dialog
49 shortcut: Qt.Key_PowerDown
75 shortcut: Qt.Key_PowerDown
50 active: Platform.isPC
76 active: Platform.isPC
@@ -91,6 +117,8 @@ Item {
91 id: d // private stuff
117 id: d // private stuff
92 objectName: "dialogsPrivate"
118 objectName: "dialogsPrivate"
93
119
120+ property var modeSwitchWarningPopup: null
121+
94 function showPowerDialog() {
122 function showPowerDialog() {
95 if (!dialogLoader.active) {
123 if (!dialogLoader.active) {
96 dialogLoader.sourceComponent = powerDialogComponent;
124 dialogLoader.sourceComponent = powerDialogComponent;
@@ -270,5 +298,4 @@ Item {
270 unitySessionService.endSession();
298 unitySessionService.endSession();
271 }
299 }
272 }
300 }
273−
274}
301}
qml/Components/ModeSwitchWarningDialog.qmlnew file+95
@@ -0,0 +1,95 @@
1+/*
2+ * Copyright (C) 2015 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.4
18+import QtQuick.Layouts 1.1
19+import Ubuntu.Components 1.3
20+import Ubuntu.Components.ListItems 1.3
21+import Ubuntu.Components.Popups 1.3
22+
23+ShellDialog {
24+ id: root
25+ objectName: "modeSwitchWarningDialog"
26+
27+ property alias model: appRepeater.model
28+
29+ signal forceClose();
30+
31+ Label {
32+ text: i18n.tr("Apps may have unsaved data:")
33+ fontSize: "large"
34+ color: "#5D5D5D"
35+ }
36+
37+ Repeater {
38+ id: appRepeater
39+ RowLayout {
40+ spacing: units.gu(2)
41+ Image {
42+ Layout.preferredHeight: units.gu(2)
43+ Layout.preferredWidth: units.gu(2)
44+ source: model.icon
45+ sourceSize.width: width
46+ sourceSize.height: height
47+ }
48+ Label {
49+ Layout.fillWidth: true
50+ text: model.name
51+ color: "#888888"
52+ }
53+ }
54+ }
55+
56+ Label {
57+ text: i18n.tr("Re-dock, save your work and close these apps to continue.")
58+ wrapMode: Text.WordWrap
59+ color: "#888888"
60+ }
61+
62+ Label {
63+ text: i18n.tr("Or force close now (unsaved data will be lost).")
64+ wrapMode: Text.WordWrap
65+ color: "#888888"
66+ }
67+
68+ ThinDivider {}
69+
70+ RowLayout {
71+ Label {
72+ objectName: "reconnectLabel"
73+ Layout.fillWidth: true
74+ property bool clicked: false
75+ property string notClickedText: i18n.tr("OK, I will reconnect")
76+ property string clickedText: i18n.tr("Reconnect now!")
77+ text: clicked ? clickedText : notClickedText
78+ color: "#333333"
79+
80+ MouseArea {
81+ anchors.fill: parent
82+ onClicked: parent.clicked = true;
83+ }
84+ }
85+
86+ Button {
87+ objectName: "forceCloseButton"
88+ text: i18n.tr("Close all")
89+ color: UbuntuColors.red
90+ onClicked: {
91+ root.forceClose();
92+ }
93+ }
94+ }
95+}
qml/Components/ShellDialog.qml+1−1
@@ -31,7 +31,7 @@ Dialog {
31 // NB: PopupBase, Dialog's superclass, will check for the existence of this property
31 // NB: PopupBase, Dialog's superclass, will check for the existence of this property
32 property bool reparentToRootItem: false
32 property bool reparentToRootItem: false
33
33
34− onVisibleChanged: { if (!visible) { dialogLoader.active = false; } }
34+ onVisibleChanged: { if (!visible && dialogLoader) { dialogLoader.active = false; } }
35
35
36 Keys.onEscapePressed: hide()
36 Keys.onEscapePressed: hide()
37
37
qml/Dash/graphics/phone/screenshots/libreoffice@12.pngnew file

Binary file not shown.

tests/mocks/Unity/Application/ApplicationManager.cpp+1
@@ -465,6 +465,7 @@ void ApplicationManager::buildListOfAvailableApplications()
465 application->setAppId("libreoffice");
465 application->setAppId("libreoffice");
466 application->setName("LibreOffice");
466 application->setName("LibreOffice");
467 application->setIconId("libreoffice");
467 application->setIconId("libreoffice");
468+ application->setScreenshotId("libreoffice");
468 application->setIsTouchApp(false);
469 application->setIsTouchApp(false);
469 m_availableApplications.append(application);
470 m_availableApplications.append(application);
470}
471}
tests/mocks/Unity/Launcher/MockLauncherModel.cpp+3
@@ -75,6 +75,9 @@ MockLauncherModel::MockLauncherModel(QObject* parent): LauncherModelInterface(pa
75 item = new MockLauncherItem("calendar-app", "/usr/share/applications/calendar-app.desktop","Calendar", "calendar", this);
75 item = new MockLauncherItem("calendar-app", "/usr/share/applications/calendar-app.desktop","Calendar", "calendar", this);
76 item->setPinned(true);
76 item->setPinned(true);
77 m_list.append(item);
77 m_list.append(item);
78+ item = new MockLauncherItem("libreoffice", "/usr/share/applications/libreoffice.desktop","Libre Office", "libreoffice", this);
79+ item->setPinned(true);
80+ m_list.append(item);
78}
81}
79
82
80MockLauncherModel::~MockLauncherModel()
83MockLauncherModel::~MockLauncherModel()
tests/mocks/Utils/CMakeLists.txt+2
@@ -18,6 +18,8 @@ set(QMLPLUGIN_SRC
18 ${CMAKE_SOURCE_DIR}/plugins/Utils/windowscreenshotprovider.cpp
18 ${CMAKE_SOURCE_DIR}/plugins/Utils/windowscreenshotprovider.cpp
19 ${CMAKE_SOURCE_DIR}/plugins/Utils/easingcurve.cpp
19 ${CMAKE_SOURCE_DIR}/plugins/Utils/easingcurve.cpp
20 ${CMAKE_SOURCE_DIR}/plugins/Utils/inputwatcher.cpp
20 ${CMAKE_SOURCE_DIR}/plugins/Utils/inputwatcher.cpp
21+ ${CMAKE_SOURCE_DIR}/plugins/Utils/applicationsfiltermodel.cpp
22+ ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
21 constants.cpp
23 constants.cpp
22 plugin.cpp
24 plugin.cpp
23 windowstatestorage.cpp
25 windowstatestorage.cpp
tests/mocks/Utils/plugin.cpp+2
@@ -35,6 +35,7 @@
35#include <windowkeysfilter.h>
35#include <windowkeysfilter.h>
36#include <windowscreenshotprovider.h>
36#include <windowscreenshotprovider.h>
37#include <easingcurve.h>
37#include <easingcurve.h>
38+#include <applicationsfiltermodel.h>
38
39
39static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
40static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
40{
41{
@@ -63,6 +64,7 @@ void FakeUtilsPlugin::registerTypes(const char *uri)
63 qmlRegisterType<InputWatcher>(uri, 0, 1, "InputWatcher");
64 qmlRegisterType<InputWatcher>(uri, 0, 1, "InputWatcher");
64 qmlRegisterSingletonType<Constants>(uri, 0, 1, "Constants", createConstants);
65 qmlRegisterSingletonType<Constants>(uri, 0, 1, "Constants", createConstants);
65 qmlRegisterType<ActiveFocusLogger>(uri, 0, 1, "ActiveFocusLogger");
66 qmlRegisterType<ActiveFocusLogger>(uri, 0, 1, "ActiveFocusLogger");
67+ qmlRegisterType<ApplicationsFilterModel>(uri, 0, 1, "ApplicationsFilterModel");
66}
68}
67
69
68void FakeUtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
70void FakeUtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
tests/qmltests/CMakeLists.txt+1
@@ -11,6 +11,7 @@ add_unity8_qmltest(Components Dialogs LIGHTDM)
11add_unity8_qmltest(Components DraggingArea)
11add_unity8_qmltest(Components DraggingArea)
12add_unity8_qmltest(Components LazyImage)
12add_unity8_qmltest(Components LazyImage)
13add_unity8_qmltest(Components Lockscreen)
13add_unity8_qmltest(Components Lockscreen)
14+add_unity8_qmltest(Components ModeSwitchWarningDialog)
14add_unity8_qmlunittest(Components PhysicalKeysMapper)
15add_unity8_qmlunittest(Components PhysicalKeysMapper)
15add_unity8_qmltest(Components Rating)
16add_unity8_qmltest(Components Rating)
16add_unity8_qmltest(Components ResponsiveGridView)
17add_unity8_qmltest(Components ResponsiveGridView)
tests/qmltests/Components/tst_ModeSwitchWarningDialog.qmlnew file+75
@@ -0,0 +1,75 @@
1+/*
2+ * Copyright 2015 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.4
18+import QtTest 1.0
19+import "../../../qml/Components"
20+import Unity.Test 0.1 as UT
21+import Ubuntu.Components 1.3
22+import Ubuntu.Components.Popups 1.3
23+
24+Rectangle {
25+ id: root
26+ width: units.gu(40)
27+ height: units.gu(70)
28+ color: "lightgrey"
29+
30+ ListModel {
31+ id: fakeModel
32+ ListElement { icon: "../graphics/applicationIcons/facebook.png"; name: "Facebook" }
33+ ListElement { icon: "../graphics/applicationIcons/gmail.png"; name: "Mail" }
34+ }
35+
36+ function openWarning() {
37+ return PopupUtils.open(Qt.resolvedUrl("../../../qml/Components/ModeSwitchWarningDialog.qml"), root, { model: fakeModel });
38+ }
39+
40+ Button {
41+ anchors.centerIn: parent
42+ text: "trigger warning"
43+ onClicked: {
44+ openWarning();
45+ }
46+ }
47+
48+ SignalSpy {
49+ id: spy
50+ signalName: "forceClose"
51+ }
52+
53+ UT.UnityTestCase {
54+ name: "ModeSwitchWarning"
55+ when: windowShown
56+
57+ function test_labelChangesOnClick() {
58+ var popup = openWarning();
59+ var reconnectLabel = findChild(popup, "reconnectLabel");
60+ tryCompare(reconnectLabel, "text", reconnectLabel.notClickedText)
61+ mouseClick(reconnectLabel, reconnectLabel.width / 2, reconnectLabel.height / 2)
62+ tryCompare(reconnectLabel, "text", reconnectLabel.clickedText)
63+ }
64+
65+ function test_closeButtonEmitsSignal() {
66+ var popup = openWarning();
67+ spy.target = popup;
68+ spy.clear();
69+ var closeButton = findChild(popup, "forceCloseButton");
70+ mouseClick(closeButton, closeButton.width / 2, closeButton.height / 2)
71+ tryCompare(spy, "count", 1)
72+
73+ }
74+ }
75+}
tests/qmltests/tst_Shell.qml+57
@@ -1885,5 +1885,62 @@ Rectangle {
1885 compare(app1.session.surface.activeFocus, false);
1885 compare(app1.session.surface.activeFocus, false);
1886 compare(app1.requestedState, ApplicationInfoInterface.RequestedRunning);
1886 compare(app1.requestedState, ApplicationInfoInterface.RequestedRunning);
1887 }
1887 }
1888+
1889+ function test_switchToStagedForcesLegacyAppClosing_data() {
1890+ return [
1891+ {tag: "forceClose", replug: false },
1892+ {tag: "replug", replug: true }
1893+ ];
1894+ }
1895+
1896+ function test_switchToStagedForcesLegacyAppClosing(data) {
1897+ loadShell("desktop")
1898+ shell.usageScenario = "desktop"
1899+ waitForRendering(shell);
1900+
1901+ ApplicationManager.startApplication("camera-app")
1902+
1903+ shell.usageScenario = "phone"
1904+ waitForRendering(shell);
1905+
1906+ // No legacy app running yet... Popup must *not* show.
1907+ var popup = findChild(root, "modeSwitchWarningDialog");
1908+ compare(popup, null);
1909+
1910+ shell.usageScenario = "desktop"
1911+ waitForRendering(shell);
1912+
1913+ // Now start a legacy app
1914+ ApplicationManager.startApplication("libreoffice")
1915+
1916+ shell.usageScenario = "phone"
1917+ waitForRendering(shell);
1918+
1919+ // The popup must appear now
1920+ popup = findChild(root, "modeSwitchWarningDialog");
1921+ compare(popup !== null, true);
1922+
1923+ if (data.replug) {
1924+ shell.usageScenario = "desktop"
1925+ waitForRendering(shell);
1926+
1927+ } else {
1928+ var forceCloseButton = findChild(popup, "forceCloseButton");
1929+ mouseClick(forceCloseButton, forceCloseButton.width / 2, forceCloseButton.height / 2);
1930+ waitForRendering(root);
1931+ }
1932+
1933+ // Popup must be gone now
1934+ popup = findChild(root, "modeSwitchWarningDialog");
1935+ compare(popup === null, true);
1936+
1937+ if (data.replug) {
1938+ // Libreoffice must still be running
1939+ compare(ApplicationManager.findApplication("libreoffice") !== null, true);
1940+ } else {
1941+ // Libreoffice must be gone now
1942+ compare(ApplicationManager.findApplication("libreoffice") === null, true);
1943+ }
1944+ }
1888 }
1945 }
1889}
1946}