Merge lp:~gerboland/qtmir/initialSurfaceGeometry into lp:qtmir
- initialSurfaceGeometry
- Merge into trunk
Status: | Work in progress |
---|---|
Proposed branch: | lp:~gerboland/qtmir/initialSurfaceGeometry |
Merge into: | lp:qtmir |
Prerequisite: | lp:~dandrader/qtmir/lifecycle |
Diff against target: |
5503 lines (+1949/-1606) 45 files modified
CMakeLists.txt (+3/-1) debian/changelog (+7/-0) debian/control (+1/-1) src/common/globals.h (+76/-0) src/modules/Unity/Application/CMakeLists.txt (+2/-0) src/modules/Unity/Application/application.cpp (+341/-69) src/modules/Unity/Application/application.h (+61/-19) src/modules/Unity/Application/application_manager.cpp (+118/-245) src/modules/Unity/Application/application_manager.h (+22/-20) src/modules/Unity/Application/applicationcontroller.h (+2/-1) src/modules/Unity/Application/applicationscreenshotprovider.cpp (+1/-1) src/modules/Unity/Application/mirsurfaceitem.cpp (+25/-25) src/modules/Unity/Application/mirsurfaceitem.h (+21/-78) src/modules/Unity/Application/mirsurfaceiteminterface.h (+89/-0) src/modules/Unity/Application/mirsurfaceitemmodel.h (+2/-2) src/modules/Unity/Application/mirsurfacemanager.cpp (+6/-6) src/modules/Unity/Application/mirsurfacemanager.h (+4/-4) src/modules/Unity/Application/plugin.cpp (+30/-32) src/modules/Unity/Application/session.cpp (+123/-73) src/modules/Unity/Application/session.h (+15/-8) src/modules/Unity/Application/session_interface.h (+31/-23) src/modules/Unity/Application/sessionmanager.cpp (+2/-2) src/modules/Unity/Application/sessionmanager.h (+3/-1) src/modules/Unity/Application/taskcontroller.cpp (+8/-13) src/modules/Unity/Application/taskcontroller.h (+4/-6) src/modules/Unity/Application/upstart/applicationcontroller.cpp (+10/-2) src/platforms/mirserver/CMakeLists.txt (+2/-0) src/platforms/mirserver/mirserver.cpp (+1/-2) src/platforms/mirserver/mirshell.cpp (+28/-23) src/platforms/mirserver/mirshell.h (+16/-12) tests/modules/Application/CMakeLists.txt (+5/-0) tests/modules/Application/application_test.cpp (+145/-71) tests/modules/ApplicationManager/CMakeLists.txt (+5/-1) tests/modules/ApplicationManager/application_manager_test.cpp (+410/-831) tests/modules/MirSurfaceItem/CMakeLists.txt (+3/-1) tests/modules/MirSurfaceItem/mirsurfaceitem_test.cpp (+1/-1) tests/modules/SessionManager/CMakeLists.txt (+4/-0) tests/modules/SessionManager/session_manager_test.cpp (+1/-1) tests/modules/SessionManager/session_test.cpp (+57/-24) tests/modules/TaskController/CMakeLists.txt (+1/-0) tests/modules/common/fake_mirsurfaceitem.h (+95/-0) tests/modules/common/mock_mirsurfaceitem.h (+50/-0) tests/modules/common/mock_session.h (+44/-5) tests/modules/common/qtmir_test.cpp (+61/-0) tests/modules/common/qtmir_test.h (+13/-2) |
To merge this branch: | bzr merge lp:~gerboland/qtmir/initialSurfaceGeometry |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Albert Astals Cid (community) | Needs Fixing | ||
Michał Sawicz | Approve | ||
Daniel d'Andrada | Pending | ||
Review via email: mp+231725@code.launchpad.net |
This proposal supersedes a proposal from 2014-08-12.
Commit message
Implement a callback mechanism to allow shell override the initial surface geometry requested by clients
Description of the change
* Are there any related MPs required for this MP to build/function as expected? Please list.
https:/
* Did you perform an exploratory manual test run of your code change and any related functionality?
Y
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A
* If you changed the UI, has there been a design review?
N/A
Michał Sawicz (saviq) wrote : Posted in a previous version of this proposal | # |
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal | # |
Comments addressed, please check out rev 234
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:235
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Daniel d'Andrada (dandrader) : Posted in a previous version of this proposal | # |
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal | # |
In src/platforms/
+ void sessionAboutToC
That line is way too long.
In tests/modules/
+ QJSValue callback = jsEngine-
Here as well.
Looks good otherwise.
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal | # |
Done
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:236
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Daniel d'Andrada (dandrader) : Posted in a previous version of this proposal | # |
Michał Sawicz (saviq) wrote : Posted in a previous version of this proposal | # |
Minor inline.
Gerry Boland (gerboland) : Posted in a previous version of this proposal | # |
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:237
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:238
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Gerry Boland (gerboland) : Posted in a previous version of this proposal | # |
Gerry Boland (gerboland) : Posted in a previous version of this proposal | # |
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:240
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:241
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:241
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:243
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:244
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : | # |
635 + std::shared_
...
601 + //auto sharedPtr = the_placement_
602 + if (m_placementStr
603 +
604 + return static_
Better as:
std::weak_
....
return m_placementStra
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:261
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Albert Astals Cid (aacid) wrote : | # |
Code looks good, haven't time to test. If nobody beats me to it, i'll do on Monday
Albert Astals Cid (aacid) wrote : | # |
Doesn't merge correctly
Text conflict in debian/changelog
Text conflict in src/modules/
Text conflict in src/modules/
3 conflicts encountered.
- 262. By Gerry Boland
-
Merge trunk & fix conflicts
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:262
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Albert Astals Cid (aacid) wrote : | # |
Let's wait for https:/
- 263. By Gerry Boland
-
Move Surface Types & States into Globals enum class. Expand surfaceSizer parameter to include state
- 264. By Gerry Boland
-
Merge trunk
- 265. By Gerry Boland
-
Merge trunk, required many changes
- 266. By Gerry Boland
-
Remove accidental commits
- 267. By Gerry Boland
-
Remove local build tweak
- 268. By Gerry Boland
-
Merge trunk
- 269. By Gerry Boland
-
Merge detach-
state-from- focus and resolve conflicts
Unmerged revisions
- 269. By Gerry Boland
-
Merge detach-
state-from- focus and resolve conflicts - 268. By Gerry Boland
-
Merge trunk
- 267. By Gerry Boland
-
Remove local build tweak
- 266. By Gerry Boland
-
Remove accidental commits
- 265. By Gerry Boland
-
Merge trunk, required many changes
- 264. By Gerry Boland
-
Merge trunk
- 263. By Gerry Boland
-
Move Surface Types & States into Globals enum class. Expand surfaceSizer parameter to include state
- 262. By Gerry Boland
-
Merge trunk & fix conflicts
- 261. By Gerry Boland
-
Merge trunk
- 260. By Gerry Boland
-
Workaround MirServer API missing the_placement_
strategy method (bug lp:1407687)
Preview Diff
1 | === modified file 'CMakeLists.txt' | |||
2 | --- CMakeLists.txt 2015-05-21 18:48:59 +0000 | |||
3 | +++ CMakeLists.txt 2015-07-13 21:57:32 +0000 | |||
4 | @@ -80,7 +80,9 @@ | |||
5 | 80 | pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt) | 80 | pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt) |
6 | 81 | pkg_check_modules(QTDBUSTEST libqtdbustest-1 REQUIRED) | 81 | pkg_check_modules(QTDBUSTEST libqtdbustest-1 REQUIRED) |
7 | 82 | pkg_check_modules(QTDBUSMOCK libqtdbusmock-1 REQUIRED) | 82 | pkg_check_modules(QTDBUSMOCK libqtdbusmock-1 REQUIRED) |
9 | 83 | pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=6) | 83 | pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=7) |
10 | 84 | |||
11 | 85 | include_directories(${APPLICATION_API_INCLUDE_DIRS}) | ||
12 | 84 | 86 | ||
13 | 85 | add_definitions(-DMIR_REQUIRE_DEPRECATED_EVENT_OPT_IN=1) | 87 | add_definitions(-DMIR_REQUIRE_DEPRECATED_EVENT_OPT_IN=1) |
14 | 86 | 88 | ||
15 | 87 | 89 | ||
16 | === modified file 'debian/changelog' | |||
17 | --- debian/changelog 2015-06-17 13:46:09 +0000 | |||
18 | +++ debian/changelog 2015-07-13 21:57:32 +0000 | |||
19 | @@ -1,3 +1,10 @@ | |||
20 | 1 | qtmir (0.4.6) UNRELEASED; urgency=medium | ||
21 | 2 | |||
22 | 3 | * Implement a callback mechanism to allow shell override the initial | ||
23 | 4 | surface geometry requested by clients | ||
24 | 5 | |||
25 | 6 | -- Gerry Boland <gerry.boland@canonical.com> Mon, 12 Jul 2015 14:47:07 +0100 | ||
26 | 7 | |||
27 | 1 | qtmir (0.4.5+15.10.20150617-0ubuntu1) wily; urgency=medium | 8 | qtmir (0.4.5+15.10.20150617-0ubuntu1) wily; urgency=medium |
28 | 2 | 9 | ||
29 | 3 | [ Gerry Boland ] | 10 | [ Gerry Boland ] |
30 | 4 | 11 | ||
31 | === modified file 'debian/control' | |||
32 | --- debian/control 2015-06-17 13:45:56 +0000 | |||
33 | +++ debian/control 2015-07-13 21:57:32 +0000 | |||
34 | @@ -28,7 +28,7 @@ | |||
35 | 28 | libubuntu-app-launch2-dev, | 28 | libubuntu-app-launch2-dev, |
36 | 29 | libubuntu-application-api-dev (>= 2.1.0), | 29 | libubuntu-application-api-dev (>= 2.1.0), |
37 | 30 | libudev-dev, | 30 | libudev-dev, |
39 | 31 | libunity-api-dev (>= 7.97), | 31 | libunity-api-dev (>= 7.99), |
40 | 32 | liburl-dispatcher1-dev, | 32 | liburl-dispatcher1-dev, |
41 | 33 | libxkbcommon-dev, | 33 | libxkbcommon-dev, |
42 | 34 | libxrender-dev, | 34 | libxrender-dev, |
43 | 35 | 35 | ||
44 | === added file 'src/common/globals.h' | |||
45 | --- src/common/globals.h 1970-01-01 00:00:00 +0000 | |||
46 | +++ src/common/globals.h 2015-07-13 21:57:32 +0000 | |||
47 | @@ -0,0 +1,76 @@ | |||
48 | 1 | /* | ||
49 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
50 | 3 | * | ||
51 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
52 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
53 | 6 | * the Free Software Foundation. | ||
54 | 7 | * | ||
55 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
56 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
57 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
58 | 11 | * Lesser General Public License for more details. | ||
59 | 12 | * | ||
60 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
61 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
62 | 15 | */ | ||
63 | 16 | |||
64 | 17 | #ifndef GLOBALS_H | ||
65 | 18 | #define GLOBALS_H | ||
66 | 19 | |||
67 | 20 | #include <QObject> | ||
68 | 21 | #include <QSize> | ||
69 | 22 | #include <mir_toolkit/common.h> | ||
70 | 23 | |||
71 | 24 | namespace qtmir { | ||
72 | 25 | |||
73 | 26 | class Globals | ||
74 | 27 | { | ||
75 | 28 | Q_GADGET | ||
76 | 29 | Q_ENUMS(SurfaceState) | ||
77 | 30 | Q_ENUMS(SurfaceType) | ||
78 | 31 | |||
79 | 32 | public: | ||
80 | 33 | enum SurfaceState { | ||
81 | 34 | Unknown = mir_surface_state_unknown, | ||
82 | 35 | Restored = mir_surface_state_restored, | ||
83 | 36 | Minimized = mir_surface_state_minimized, | ||
84 | 37 | Maximized = mir_surface_state_maximized, | ||
85 | 38 | VertMaximized = mir_surface_state_vertmaximized, | ||
86 | 39 | /* SemiMaximized = mir_surface_state_semimaximized, // see mircommon/mir_toolbox/common.h*/ | ||
87 | 40 | Fullscreen = mir_surface_state_fullscreen, | ||
88 | 41 | }; | ||
89 | 42 | |||
90 | 43 | enum SurfaceType { | ||
91 | 44 | Normal = mir_surface_type_normal, | ||
92 | 45 | Utility = mir_surface_type_utility, | ||
93 | 46 | Dialog = mir_surface_type_dialog, | ||
94 | 47 | Overlay = mir_surface_type_overlay, | ||
95 | 48 | Freestyle = mir_surface_type_freestyle, | ||
96 | 49 | Popover = mir_surface_type_popover, | ||
97 | 50 | InputMethod = mir_surface_type_inputmethod, | ||
98 | 51 | }; | ||
99 | 52 | |||
100 | 53 | enum OrientationAngle { | ||
101 | 54 | Angle0 = 0, | ||
102 | 55 | Angle90 = 90, | ||
103 | 56 | Angle180 = 180, | ||
104 | 57 | Angle270 = 270 | ||
105 | 58 | }; | ||
106 | 59 | |||
107 | 60 | private: | ||
108 | 61 | Globals() = default; | ||
109 | 62 | ~Globals() = default; | ||
110 | 63 | }; | ||
111 | 64 | |||
112 | 65 | |||
113 | 66 | struct SurfaceParameters | ||
114 | 67 | { | ||
115 | 68 | QSize geometry; | ||
116 | 69 | Globals::SurfaceState state; | ||
117 | 70 | }; | ||
118 | 71 | |||
119 | 72 | } // namespace qtmir | ||
120 | 73 | |||
121 | 74 | Q_DECLARE_METATYPE(qtmir::Globals::OrientationAngle) | ||
122 | 75 | |||
123 | 76 | #endif // GLOBALS_H | ||
124 | 0 | 77 | ||
125 | === modified file 'src/modules/Unity/Application/CMakeLists.txt' | |||
126 | --- src/modules/Unity/Application/CMakeLists.txt 2015-05-21 18:48:59 +0000 | |||
127 | +++ src/modules/Unity/Application/CMakeLists.txt 2015-07-13 21:57:32 +0000 | |||
128 | @@ -46,9 +46,11 @@ | |||
129 | 46 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h | 46 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h |
130 | 47 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h | 47 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h |
131 | 48 | # Feed the automoc monster | 48 | # Feed the automoc monster |
132 | 49 | mirsurfaceiteminterface.h | ||
133 | 49 | session_interface.h | 50 | session_interface.h |
134 | 50 | applicationcontroller.h | 51 | applicationcontroller.h |
135 | 51 | settings_interface.h | 52 | settings_interface.h |
136 | 53 | ../../../common/globals.h | ||
137 | 52 | ) | 54 | ) |
138 | 53 | 55 | ||
139 | 54 | add_library(unityapplicationplugin SHARED | 56 | add_library(unityapplicationplugin SHARED |
140 | 55 | 57 | ||
141 | === modified file 'src/modules/Unity/Application/application.cpp' | |||
142 | --- src/modules/Unity/Application/application.cpp 2015-04-10 14:54:44 +0000 | |||
143 | +++ src/modules/Unity/Application/application.cpp 2015-07-13 21:57:32 +0000 | |||
144 | @@ -1,5 +1,5 @@ | |||
145 | 1 | /* | 1 | /* |
147 | 2 | * Copyright (C) 2013-2014 Canonical, Ltd. | 2 | * Copyright (C) 2013-2015 Canonical, Ltd. |
148 | 3 | * | 3 | * |
149 | 4 | * This program is free software: you can redistribute it and/or modify it under | 4 | * This program is free software: you can redistribute it and/or modify it under |
150 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | 5 | * the terms of the GNU Lesser General Public License version 3, as published by |
151 | @@ -37,25 +37,28 @@ | |||
152 | 37 | namespace qtmir | 37 | namespace qtmir |
153 | 38 | { | 38 | { |
154 | 39 | 39 | ||
157 | 40 | Application::Application(const QSharedPointer<TaskController>& taskController, | 40 | QStringList Application::lifecycleExceptions; |
158 | 41 | const QSharedPointer<SharedWakelock>& sharedWakelock, | 41 | |
159 | 42 | Application::Application(const QSharedPointer<SharedWakelock>& sharedWakelock, | ||
160 | 42 | DesktopFileReader *desktopFileReader, | 43 | DesktopFileReader *desktopFileReader, |
161 | 43 | State state, | ||
162 | 44 | const QStringList &arguments, | 44 | const QStringList &arguments, |
163 | 45 | ApplicationManager *parent) | 45 | ApplicationManager *parent) |
164 | 46 | : ApplicationInfoInterface(desktopFileReader->appId(), parent) | 46 | : ApplicationInfoInterface(desktopFileReader->appId(), parent) |
165 | 47 | , m_taskController(taskController) | ||
166 | 48 | , m_sharedWakelock(sharedWakelock) | 47 | , m_sharedWakelock(sharedWakelock) |
167 | 49 | , m_desktopData(desktopFileReader) | 48 | , m_desktopData(desktopFileReader) |
168 | 50 | , m_pid(0) | 49 | , m_pid(0) |
169 | 51 | , m_stage((m_desktopData->stageHint() == "SideStage") ? Application::SideStage : Application::MainStage) | 50 | , m_stage((m_desktopData->stageHint() == "SideStage") ? Application::SideStage : Application::MainStage) |
171 | 52 | , m_state(state) | 51 | , m_state(InternalState::Starting) |
172 | 53 | , m_focused(false) | 52 | , m_focused(false) |
173 | 54 | , m_canBeResumed(true) | ||
174 | 55 | , m_arguments(arguments) | 53 | , m_arguments(arguments) |
175 | 56 | , m_session(nullptr) | 54 | , m_session(nullptr) |
176 | 55 | , m_requestedState(RequestedRunning) | ||
177 | 56 | , m_processState(ProcessUnknown) | ||
178 | 57 | { | 57 | { |
180 | 58 | qCDebug(QTMIR_APPLICATIONS) << "Application::Application - appId=" << desktopFileReader->appId() << "state=" << state; | 58 | qCDebug(QTMIR_APPLICATIONS) << "Application::Application - appId=" << desktopFileReader->appId(); |
181 | 59 | |||
182 | 60 | // Because m_state is InternalState::Starting | ||
183 | 61 | acquireWakelock(); | ||
184 | 59 | 62 | ||
185 | 60 | // FIXME(greyback) need to save long appId internally until ubuntu-app-launch can hide it from us | 63 | // FIXME(greyback) need to save long appId internally until ubuntu-app-launch can hide it from us |
186 | 61 | m_longAppId = desktopFileReader->file().remove(QRegExp(".desktop$")).split('/').last(); | 64 | m_longAppId = desktopFileReader->file().remove(QRegExp(".desktop$")).split('/').last(); |
187 | @@ -69,10 +72,33 @@ | |||
188 | 69 | { | 72 | { |
189 | 70 | qCDebug(QTMIR_APPLICATIONS) << "Application::~Application"; | 73 | qCDebug(QTMIR_APPLICATIONS) << "Application::~Application"; |
190 | 71 | 74 | ||
191 | 75 | // (ricmm) -- To be on the safe side, better wipe the application QML compile cache if it crashes on startup | ||
192 | 76 | if (m_processState == Application::ProcessUnknown | ||
193 | 77 | || state() == Application::Starting | ||
194 | 78 | || state() == Application::Running) { | ||
195 | 79 | wipeQMLCache(); | ||
196 | 80 | } | ||
197 | 81 | |||
198 | 72 | delete m_session; | 82 | delete m_session; |
199 | 73 | delete m_desktopData; | 83 | delete m_desktopData; |
200 | 74 | } | 84 | } |
201 | 75 | 85 | ||
202 | 86 | |||
203 | 87 | void Application::wipeQMLCache() | ||
204 | 88 | { | ||
205 | 89 | QString path(QDir::homePath() + QStringLiteral("/.cache/QML/Apps/")); | ||
206 | 90 | QDir dir(path); | ||
207 | 91 | QStringList apps = dir.entryList(); | ||
208 | 92 | for (int i = 0; i < apps.size(); i++) { | ||
209 | 93 | if (apps.at(i).contains(appId())) { | ||
210 | 94 | qCDebug(QTMIR_APPLICATIONS) << "Application appId=" << apps.at(i) << " Wiping QML Cache"; | ||
211 | 95 | dir.cd(apps.at(i)); | ||
212 | 96 | dir.removeRecursively(); | ||
213 | 97 | break; | ||
214 | 98 | } | ||
215 | 99 | } | ||
216 | 100 | } | ||
217 | 101 | |||
218 | 76 | bool Application::isValid() const | 102 | bool Application::isValid() const |
219 | 77 | { | 103 | { |
220 | 78 | return m_desktopData->loaded(); | 104 | return m_desktopData->loaded(); |
221 | @@ -159,6 +185,30 @@ | |||
222 | 159 | return color; | 185 | return color; |
223 | 160 | } | 186 | } |
224 | 161 | 187 | ||
225 | 188 | const char* Application::internalStateToStr(InternalState state) | ||
226 | 189 | { | ||
227 | 190 | switch (state) { | ||
228 | 191 | case InternalState::Starting: | ||
229 | 192 | return "Starting"; | ||
230 | 193 | case InternalState::Running: | ||
231 | 194 | return "Running"; | ||
232 | 195 | case InternalState::RunningInBackground: | ||
233 | 196 | return "RunningInBackground"; | ||
234 | 197 | case InternalState::SuspendingWaitSession: | ||
235 | 198 | return "SuspendingWaitSession"; | ||
236 | 199 | case InternalState::SuspendingWaitProcess: | ||
237 | 200 | return "SuspendingWaitProcess"; | ||
238 | 201 | case InternalState::Suspended: | ||
239 | 202 | return "Suspended"; | ||
240 | 203 | case InternalState::StoppedUnexpectedly: | ||
241 | 204 | return "StoppedUnexpectedly"; | ||
242 | 205 | case InternalState::Stopped: | ||
243 | 206 | return "Stopped"; | ||
244 | 207 | default: | ||
245 | 208 | return "???"; | ||
246 | 209 | } | ||
247 | 210 | } | ||
248 | 211 | |||
249 | 162 | bool Application::splashShowHeader() const | 212 | bool Application::splashShowHeader() const |
250 | 163 | { | 213 | { |
251 | 164 | QString showHeader = m_desktopData->splashShowHeader(); | 214 | QString showHeader = m_desktopData->splashShowHeader(); |
252 | @@ -204,7 +254,104 @@ | |||
253 | 204 | 254 | ||
254 | 205 | Application::State Application::state() const | 255 | Application::State Application::state() const |
255 | 206 | { | 256 | { |
257 | 207 | return m_state; | 257 | // The public state is a simplified version of the internal one as our consumers |
258 | 258 | // don't have to know or care about all the nasty details. | ||
259 | 259 | switch (m_state) { | ||
260 | 260 | case InternalState::Starting: | ||
261 | 261 | return Starting; | ||
262 | 262 | case InternalState::Running: | ||
263 | 263 | case InternalState::RunningInBackground: | ||
264 | 264 | case InternalState::SuspendingWaitSession: | ||
265 | 265 | case InternalState::SuspendingWaitProcess: | ||
266 | 266 | return Running; | ||
267 | 267 | case InternalState::Suspended: | ||
268 | 268 | return Suspended; | ||
269 | 269 | case InternalState::Stopped: | ||
270 | 270 | default: | ||
271 | 271 | return Stopped; | ||
272 | 272 | } | ||
273 | 273 | } | ||
274 | 274 | |||
275 | 275 | Application::RequestedState Application::requestedState() const | ||
276 | 276 | { | ||
277 | 277 | return m_requestedState; | ||
278 | 278 | } | ||
279 | 279 | |||
280 | 280 | void Application::setRequestedState(RequestedState value) | ||
281 | 281 | { | ||
282 | 282 | if (m_requestedState == value) { | ||
283 | 283 | // nothing to do | ||
284 | 284 | return; | ||
285 | 285 | } | ||
286 | 286 | |||
287 | 287 | qCDebug(QTMIR_APPLICATIONS) << "Application::setRequestedState - appId=" << appId() | ||
288 | 288 | << "requestedState=" << applicationStateToStr(value); | ||
289 | 289 | m_requestedState = value; | ||
290 | 290 | Q_EMIT requestedStateChanged(m_requestedState); | ||
291 | 291 | |||
292 | 292 | applyRequestedState(); | ||
293 | 293 | } | ||
294 | 294 | |||
295 | 295 | void Application::applyRequestedState() | ||
296 | 296 | { | ||
297 | 297 | if (m_requestedState == RequestedRunning) { | ||
298 | 298 | applyRequestedRunning(); | ||
299 | 299 | } else { | ||
300 | 300 | applyRequestedSuspended(); | ||
301 | 301 | } | ||
302 | 302 | } | ||
303 | 303 | |||
304 | 304 | void Application::applyRequestedRunning() | ||
305 | 305 | { | ||
306 | 306 | switch (m_state) { | ||
307 | 307 | case InternalState::Starting: | ||
308 | 308 | // should leave the app alone until it reaches Running state | ||
309 | 309 | break; | ||
310 | 310 | case InternalState::Running: | ||
311 | 311 | // already where it's wanted to be | ||
312 | 312 | break; | ||
313 | 313 | case InternalState::RunningInBackground: | ||
314 | 314 | case InternalState::SuspendingWaitSession: | ||
315 | 315 | case InternalState::Suspended: | ||
316 | 316 | resume(); | ||
317 | 317 | break; | ||
318 | 318 | case InternalState::SuspendingWaitProcess: | ||
319 | 319 | // should leave the app alone until it reaches Suspended state | ||
320 | 320 | break; | ||
321 | 321 | case InternalState::StoppedUnexpectedly: | ||
322 | 322 | respawn(); | ||
323 | 323 | break; | ||
324 | 324 | case InternalState::Stopped: | ||
325 | 325 | // dead end. | ||
326 | 326 | break; | ||
327 | 327 | } | ||
328 | 328 | } | ||
329 | 329 | |||
330 | 330 | void Application::applyRequestedSuspended() | ||
331 | 331 | { | ||
332 | 332 | switch (m_state) { | ||
333 | 333 | case InternalState::Starting: | ||
334 | 334 | // should leave the app alone until it reaches Running state | ||
335 | 335 | break; | ||
336 | 336 | case InternalState::Running: | ||
337 | 337 | if (m_processState == ProcessRunning) { | ||
338 | 338 | suspend(); | ||
339 | 339 | } else { | ||
340 | 340 | // we can't suspend it since we have no information on the app process | ||
341 | 341 | Q_ASSERT(m_processState == ProcessUnknown); | ||
342 | 342 | } | ||
343 | 343 | break; | ||
344 | 344 | case InternalState::RunningInBackground: | ||
345 | 345 | case InternalState::SuspendingWaitSession: | ||
346 | 346 | case InternalState::SuspendingWaitProcess: | ||
347 | 347 | case InternalState::Suspended: | ||
348 | 348 | // it's already going where we it's wanted | ||
349 | 349 | break; | ||
350 | 350 | case InternalState::StoppedUnexpectedly: | ||
351 | 351 | case InternalState::Stopped: | ||
352 | 352 | // the app doesn't have a process in the first place, so there's nothing to suspend | ||
353 | 353 | break; | ||
354 | 354 | } | ||
355 | 208 | } | 355 | } |
356 | 209 | 356 | ||
357 | 210 | bool Application::focused() const | 357 | bool Application::focused() const |
358 | @@ -219,12 +366,7 @@ | |||
359 | 219 | 366 | ||
360 | 220 | bool Application::canBeResumed() const | 367 | bool Application::canBeResumed() const |
361 | 221 | { | 368 | { |
368 | 222 | return m_canBeResumed; | 369 | return m_processState != ProcessUnknown; |
363 | 223 | } | ||
364 | 224 | |||
365 | 225 | void Application::setCanBeResumed(const bool resume) | ||
366 | 226 | { | ||
367 | 227 | m_canBeResumed = resume; | ||
369 | 228 | } | 370 | } |
370 | 229 | 371 | ||
371 | 230 | pid_t Application::pid() const | 372 | pid_t Application::pid() const |
372 | @@ -242,7 +384,7 @@ | |||
373 | 242 | m_arguments = arguments; | 384 | m_arguments = arguments; |
374 | 243 | } | 385 | } |
375 | 244 | 386 | ||
377 | 245 | void Application::setSession(Session *newSession) | 387 | void Application::setSession(SessionInterface *newSession) |
378 | 246 | { | 388 | { |
379 | 247 | qCDebug(QTMIR_APPLICATIONS) << "Application::setSession - appId=" << appId() << "session=" << newSession; | 389 | qCDebug(QTMIR_APPLICATIONS) << "Application::setSession - appId=" << appId() << "session=" << newSession; |
380 | 248 | 390 | ||
381 | @@ -261,10 +403,25 @@ | |||
382 | 261 | if (m_session) { | 403 | if (m_session) { |
383 | 262 | m_session->setParent(this); | 404 | m_session->setParent(this); |
384 | 263 | m_session->setApplication(this); | 405 | m_session->setApplication(this); |
389 | 264 | m_session->setState(state()); | 406 | |
390 | 265 | 407 | switch (m_state) { | |
391 | 266 | connect(m_session, &SessionInterface::suspended, this, &Application::onSessionSuspended); | 408 | case InternalState::Starting: |
392 | 267 | connect(m_session, &SessionInterface::resumed, this, &Application::onSessionResumed); | 409 | case InternalState::Running: |
393 | 410 | case InternalState::RunningInBackground: | ||
394 | 411 | m_session->resume(); | ||
395 | 412 | break; | ||
396 | 413 | case InternalState::SuspendingWaitSession: | ||
397 | 414 | case InternalState::SuspendingWaitProcess: | ||
398 | 415 | case InternalState::Suspended: | ||
399 | 416 | m_session->suspend(); | ||
400 | 417 | break; | ||
401 | 418 | case InternalState::Stopped: | ||
402 | 419 | default: | ||
403 | 420 | m_session->stop(); | ||
404 | 421 | break; | ||
405 | 422 | } | ||
406 | 423 | |||
407 | 424 | connect(m_session, &SessionInterface::stateChanged, this, &Application::onSessionStateChanged); | ||
408 | 268 | connect(m_session, &SessionInterface::fullscreenChanged, this, &Application::fullscreenChanged); | 425 | connect(m_session, &SessionInterface::fullscreenChanged, this, &Application::fullscreenChanged); |
409 | 269 | 426 | ||
410 | 270 | if (oldFullscreen != fullscreen()) | 427 | if (oldFullscreen != fullscreen()) |
411 | @@ -288,37 +445,53 @@ | |||
412 | 288 | } | 445 | } |
413 | 289 | } | 446 | } |
414 | 290 | 447 | ||
416 | 291 | void Application::setState(Application::State state) | 448 | void Application::setInternalState(Application::InternalState state) |
417 | 292 | { | 449 | { |
439 | 293 | qCDebug(QTMIR_APPLICATIONS) << "Application::setState - appId=" << appId() << "state=" << applicationStateToStr(state); | 450 | if (m_state == state) { |
440 | 294 | if (m_state != state) { | 451 | return; |
441 | 295 | if (session()) { | 452 | } |
442 | 296 | session()->setState((Session::State)state); | 453 | |
443 | 297 | } else { | 454 | qCDebug(QTMIR_APPLICATIONS) << "Application::setInternalState - appId=" << appId() |
444 | 298 | // If we have have no session, we may have to respawn it. | 455 | << "state=" << internalStateToStr(state); |
445 | 299 | switch (state) | 456 | |
446 | 300 | { | 457 | auto oldPublicState = this->state(); |
447 | 301 | case Session::State::Running: | 458 | m_state = state; |
448 | 302 | if (m_state == Session::State::Stopped) { | 459 | |
449 | 303 | respawn(); | 460 | switch (m_state) { |
450 | 304 | state = Session::State::Starting; | 461 | case InternalState::Starting: |
451 | 305 | } | 462 | case InternalState::Running: |
452 | 306 | break; | 463 | acquireWakelock(); |
453 | 307 | default: | 464 | break; |
454 | 308 | break; | 465 | case InternalState::RunningInBackground: |
455 | 309 | } | 466 | releaseWakelock(); |
456 | 310 | } | 467 | break; |
457 | 311 | m_state = state; | 468 | case InternalState::Suspended: |
458 | 312 | Q_EMIT stateChanged(state); | 469 | releaseWakelock(); |
459 | 313 | } | 470 | break; |
460 | 471 | case InternalState::StoppedUnexpectedly: | ||
461 | 472 | releaseWakelock(); | ||
462 | 473 | break; | ||
463 | 474 | case InternalState::Stopped: | ||
464 | 475 | Q_EMIT stopped(); | ||
465 | 476 | releaseWakelock(); | ||
466 | 477 | break; | ||
467 | 478 | case InternalState::SuspendingWaitSession: | ||
468 | 479 | case InternalState::SuspendingWaitProcess: | ||
469 | 480 | // transitory states. leave as it is | ||
470 | 481 | default: | ||
471 | 482 | break; | ||
472 | 483 | }; | ||
473 | 484 | |||
474 | 485 | if (this->state() != oldPublicState) { | ||
475 | 486 | Q_EMIT stateChanged(this->state()); | ||
476 | 487 | } | ||
477 | 488 | |||
478 | 489 | applyRequestedState(); | ||
479 | 314 | } | 490 | } |
480 | 315 | 491 | ||
481 | 316 | void Application::setFocused(bool focused) | 492 | void Application::setFocused(bool focused) |
482 | 317 | { | 493 | { |
483 | 318 | qCDebug(QTMIR_APPLICATIONS) << "Application::setFocused - appId=" << appId() << "focused=" << focused; | 494 | qCDebug(QTMIR_APPLICATIONS) << "Application::setFocused - appId=" << appId() << "focused=" << focused; |
484 | 319 | if (focused) { | ||
485 | 320 | holdWakelock(true); | ||
486 | 321 | } | ||
487 | 322 | 495 | ||
488 | 323 | if (m_focused != focused) { | 496 | if (m_focused != focused) { |
489 | 324 | m_focused = focused; | 497 | m_focused = focused; |
490 | @@ -326,25 +499,84 @@ | |||
491 | 326 | } | 499 | } |
492 | 327 | } | 500 | } |
493 | 328 | 501 | ||
506 | 329 | void Application::onSessionSuspended() | 502 | void Application::setProcessState(ProcessState newProcessState) |
507 | 330 | { | 503 | { |
508 | 331 | qCDebug(QTMIR_APPLICATIONS) << "Application::onSessionSuspended - appId=" << appId(); | 504 | if (m_processState == newProcessState) { |
509 | 332 | m_taskController->suspend(longAppId()); | 505 | return; |
510 | 333 | holdWakelock(false); | 506 | } |
511 | 334 | } | 507 | |
512 | 335 | 508 | m_processState = newProcessState; | |
513 | 336 | void Application::onSessionResumed() | 509 | |
514 | 337 | { | 510 | switch (m_processState) { |
515 | 338 | qCDebug(QTMIR_APPLICATIONS) << "Application::onSessionResumed - appId=" << appId(); | 511 | case ProcessUnknown: |
516 | 339 | holdWakelock(true); | 512 | // it would be a coding error |
517 | 340 | m_taskController->resume(longAppId()); | 513 | Q_ASSERT(false); |
518 | 514 | break; | ||
519 | 515 | case ProcessRunning: | ||
520 | 516 | if (m_state == InternalState::StoppedUnexpectedly) { | ||
521 | 517 | setInternalState(InternalState::Starting); | ||
522 | 518 | } | ||
523 | 519 | break; | ||
524 | 520 | case ProcessSuspended: | ||
525 | 521 | Q_ASSERT(m_state == InternalState::SuspendingWaitProcess); | ||
526 | 522 | setInternalState(InternalState::Suspended); | ||
527 | 523 | break; | ||
528 | 524 | case ProcessStopped: | ||
529 | 525 | // we assume the session always stop before the process | ||
530 | 526 | Q_ASSERT(!m_session || m_session->state() == Session::Stopped); | ||
531 | 527 | if (m_state == InternalState::Starting) { | ||
532 | 528 | setInternalState(InternalState::Stopped); | ||
533 | 529 | } else { | ||
534 | 530 | Q_ASSERT(m_state == InternalState::Stopped | ||
535 | 531 | || m_state == InternalState::StoppedUnexpectedly); | ||
536 | 532 | } | ||
537 | 533 | break; | ||
538 | 534 | } | ||
539 | 535 | |||
540 | 536 | applyRequestedState(); | ||
541 | 537 | } | ||
542 | 538 | |||
543 | 539 | void Application::suspend() | ||
544 | 540 | { | ||
545 | 541 | Q_ASSERT(m_state == InternalState::Running); | ||
546 | 542 | Q_ASSERT(m_session != nullptr); | ||
547 | 543 | |||
548 | 544 | if (!lifecycleExceptions.filter(appId().section('_',0,0)).empty()) { | ||
549 | 545 | // Present in exceptions list. | ||
550 | 546 | // There's no need to keep the wakelock as the process is never suspended | ||
551 | 547 | // and thus has no cleanup to perform when (for example) the display is | ||
552 | 548 | // blanked. | ||
553 | 549 | setInternalState(InternalState::RunningInBackground); | ||
554 | 550 | } else { | ||
555 | 551 | setInternalState(InternalState::SuspendingWaitSession); | ||
556 | 552 | m_session->suspend(); | ||
557 | 553 | } | ||
558 | 554 | } | ||
559 | 555 | |||
560 | 556 | void Application::resume() | ||
561 | 557 | { | ||
562 | 558 | if (m_state == InternalState::Suspended) { | ||
563 | 559 | setInternalState(InternalState::Running); | ||
564 | 560 | Q_EMIT resumeProcessRequested(); | ||
565 | 561 | if (m_processState == ProcessSuspended) { | ||
566 | 562 | setProcessState(ProcessRunning); // should we wait for a resumed() signal? | ||
567 | 563 | } | ||
568 | 564 | m_session->resume(); | ||
569 | 565 | } else if (m_state == InternalState::SuspendingWaitSession) { | ||
570 | 566 | setInternalState(InternalState::Running); | ||
571 | 567 | m_session->resume(); | ||
572 | 568 | } else if (m_state == InternalState::RunningInBackground) { | ||
573 | 569 | setInternalState(InternalState::Running); | ||
574 | 570 | } | ||
575 | 341 | } | 571 | } |
576 | 342 | 572 | ||
577 | 343 | void Application::respawn() | 573 | void Application::respawn() |
578 | 344 | { | 574 | { |
579 | 345 | qCDebug(QTMIR_APPLICATIONS) << "Application::respawn - appId=" << appId(); | 575 | qCDebug(QTMIR_APPLICATIONS) << "Application::respawn - appId=" << appId(); |
582 | 346 | holdWakelock(true); | 576 | |
583 | 347 | m_taskController->start(appId(), m_arguments); | 577 | setInternalState(InternalState::Starting); |
584 | 578 | |||
585 | 579 | Q_EMIT startProcessRequested(); | ||
586 | 348 | } | 580 | } |
587 | 349 | 581 | ||
588 | 350 | QString Application::longAppId() const | 582 | QString Application::longAppId() const |
589 | @@ -362,20 +594,60 @@ | |||
590 | 362 | return m_rotatesWindowContents; | 594 | return m_rotatesWindowContents; |
591 | 363 | } | 595 | } |
592 | 364 | 596 | ||
594 | 365 | Session* Application::session() const | 597 | SessionInterface* Application::session() const |
595 | 366 | { | 598 | { |
596 | 367 | return m_session; | 599 | return m_session; |
597 | 368 | } | 600 | } |
598 | 369 | 601 | ||
608 | 370 | void Application::holdWakelock(bool enable) const | 602 | void Application::acquireWakelock() const |
609 | 371 | { | 603 | { |
610 | 372 | if (appId() == "unity8-dash") | 604 | if (appId() == "unity8-dash") |
611 | 373 | return; | 605 | return; |
612 | 374 | 606 | ||
613 | 375 | if (enable) { | 607 | m_sharedWakelock->acquire(this); |
614 | 376 | m_sharedWakelock->acquire(this); | 608 | } |
615 | 377 | } else { | 609 | |
616 | 378 | m_sharedWakelock->release(this); | 610 | void Application::releaseWakelock() const |
617 | 611 | { | ||
618 | 612 | if (appId() == "unity8-dash") | ||
619 | 613 | return; | ||
620 | 614 | |||
621 | 615 | m_sharedWakelock->release(this); | ||
622 | 616 | } | ||
623 | 617 | |||
624 | 618 | void Application::onSessionStateChanged(Session::State sessionState) | ||
625 | 619 | { | ||
626 | 620 | switch (sessionState) { | ||
627 | 621 | case Session::Starting: | ||
628 | 622 | break; | ||
629 | 623 | case Session::Running: | ||
630 | 624 | if (m_state == InternalState::Starting) { | ||
631 | 625 | setInternalState(InternalState::Running); | ||
632 | 626 | } | ||
633 | 627 | break; | ||
634 | 628 | case Session::Suspending: | ||
635 | 629 | break; | ||
636 | 630 | case Session::Suspended: | ||
637 | 631 | Q_ASSERT(m_state == InternalState::SuspendingWaitSession); | ||
638 | 632 | setInternalState(InternalState::SuspendingWaitProcess); | ||
639 | 633 | Q_EMIT suspendProcessRequested(); | ||
640 | 634 | break; | ||
641 | 635 | case Session::Stopped: | ||
642 | 636 | if (!canBeResumed() | ||
643 | 637 | || m_state == InternalState::Starting | ||
644 | 638 | || m_state == InternalState::Running) { | ||
645 | 639 | /* 1. application is not managed by upstart | ||
646 | 640 | * 2. application is managed by upstart, but has stopped before it managed | ||
647 | 641 | * to create a surface, we can assume it crashed on startup, and thus | ||
648 | 642 | * cannot be resumed | ||
649 | 643 | * 3. application is managed by upstart and is in foreground (i.e. has | ||
650 | 644 | * Running state), if Mir reports the application disconnects, it | ||
651 | 645 | * either crashed or stopped itself. | ||
652 | 646 | */ | ||
653 | 647 | setInternalState(InternalState::Stopped); | ||
654 | 648 | } else { | ||
655 | 649 | setInternalState(InternalState::StoppedUnexpectedly); | ||
656 | 650 | } | ||
657 | 379 | } | 651 | } |
658 | 380 | } | 652 | } |
659 | 381 | 653 | ||
660 | 382 | 654 | ||
661 | === modified file 'src/modules/Unity/Application/application.h' | |||
662 | --- src/modules/Unity/Application/application.h 2015-01-19 11:48:32 +0000 | |||
663 | +++ src/modules/Unity/Application/application.h 2015-07-13 21:57:32 +0000 | |||
664 | @@ -1,5 +1,5 @@ | |||
665 | 1 | /* | 1 | /* |
667 | 2 | * Copyright (C) 2013-2014 Canonical, Ltd. | 2 | * Copyright (C) 2013-2015 Canonical, Ltd. |
668 | 3 | * | 3 | * |
669 | 4 | * This program is free software: you can redistribute it and/or modify it under | 4 | * This program is free software: you can redistribute it and/or modify it under |
670 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | 5 | * the terms of the GNU Lesser General Public License version 3, as published by |
671 | @@ -28,6 +28,8 @@ | |||
672 | 28 | // Unity API | 28 | // Unity API |
673 | 29 | #include <unity/shell/application/ApplicationInfoInterface.h> | 29 | #include <unity/shell/application/ApplicationInfoInterface.h> |
674 | 30 | 30 | ||
675 | 31 | #include "session_interface.h" | ||
676 | 32 | |||
677 | 31 | namespace mir { | 33 | namespace mir { |
678 | 32 | namespace scene { | 34 | namespace scene { |
679 | 33 | class Session; | 35 | class Session; |
680 | @@ -39,7 +41,6 @@ | |||
681 | 39 | 41 | ||
682 | 40 | class ApplicationManager; | 42 | class ApplicationManager; |
683 | 41 | class DesktopFileReader; | 43 | class DesktopFileReader; |
684 | 42 | class TaskController; | ||
685 | 43 | class Session; | 44 | class Session; |
686 | 44 | class SharedWakelock; | 45 | class SharedWakelock; |
687 | 45 | 46 | ||
688 | @@ -51,15 +52,32 @@ | |||
689 | 51 | Q_PROPERTY(QString exec READ exec CONSTANT) | 52 | Q_PROPERTY(QString exec READ exec CONSTANT) |
690 | 52 | Q_PROPERTY(bool fullscreen READ fullscreen NOTIFY fullscreenChanged) | 53 | Q_PROPERTY(bool fullscreen READ fullscreen NOTIFY fullscreenChanged) |
691 | 53 | Q_PROPERTY(Stage stage READ stage WRITE setStage NOTIFY stageChanged) | 54 | Q_PROPERTY(Stage stage READ stage WRITE setStage NOTIFY stageChanged) |
693 | 54 | Q_PROPERTY(Session* session READ session NOTIFY sessionChanged DESIGNABLE false) | 55 | Q_PROPERTY(SessionInterface* session READ session NOTIFY sessionChanged DESIGNABLE false) |
694 | 55 | 56 | ||
695 | 56 | public: | 57 | public: |
696 | 57 | Q_DECLARE_FLAGS(Stages, Stage) | 58 | Q_DECLARE_FLAGS(Stages, Stage) |
697 | 58 | 59 | ||
700 | 59 | Application(const QSharedPointer<TaskController>& taskController, | 60 | enum ProcessState { |
701 | 60 | const QSharedPointer<SharedWakelock>& sharedWakelock, | 61 | ProcessUnknown, |
702 | 62 | ProcessRunning, | ||
703 | 63 | ProcessSuspended, | ||
704 | 64 | ProcessStopped | ||
705 | 65 | }; | ||
706 | 66 | |||
707 | 67 | enum class InternalState { | ||
708 | 68 | Starting, | ||
709 | 69 | Running, | ||
710 | 70 | RunningInBackground, | ||
711 | 71 | SuspendingWaitSession, | ||
712 | 72 | SuspendingWaitProcess, | ||
713 | 73 | Suspended, | ||
714 | 74 | StoppedUnexpectedly, | ||
715 | 75 | Stopped // It closed itself, crashed or it stopped and we can't respawn it | ||
716 | 76 | // In any case, this is a dead end. | ||
717 | 77 | }; | ||
718 | 78 | |||
719 | 79 | Application(const QSharedPointer<SharedWakelock>& sharedWakelock, | ||
720 | 61 | DesktopFileReader *desktopFileReader, | 80 | DesktopFileReader *desktopFileReader, |
721 | 62 | State state, | ||
722 | 63 | const QStringList &arguments, | 81 | const QStringList &arguments, |
723 | 64 | ApplicationManager *parent); | 82 | ApplicationManager *parent); |
724 | 65 | virtual ~Application(); | 83 | virtual ~Application(); |
725 | @@ -71,6 +89,8 @@ | |||
726 | 71 | QUrl icon() const override; | 89 | QUrl icon() const override; |
727 | 72 | Stage stage() const override; | 90 | Stage stage() const override; |
728 | 73 | State state() const override; | 91 | State state() const override; |
729 | 92 | RequestedState requestedState() const override; | ||
730 | 93 | void setRequestedState(RequestedState) override; | ||
731 | 74 | bool focused() const override; | 94 | bool focused() const override; |
732 | 75 | QString splashTitle() const override; | 95 | QString splashTitle() const override; |
733 | 76 | QUrl splashImage() const override; | 96 | QUrl splashImage() const override; |
734 | @@ -82,12 +102,16 @@ | |||
735 | 82 | bool rotatesWindowContents() const override; | 102 | bool rotatesWindowContents() const override; |
736 | 83 | 103 | ||
737 | 84 | void setStage(Stage stage); | 104 | void setStage(Stage stage); |
741 | 85 | void setState(State state); | 105 | |
742 | 86 | 106 | ||
743 | 87 | Session* session() const; | 107 | void setProcessState(ProcessState value); |
744 | 108 | |||
745 | 109 | QStringList arguments() const { return m_arguments; } | ||
746 | 110 | |||
747 | 111 | SessionInterface* session() const; | ||
748 | 112 | void setSession(SessionInterface *session); | ||
749 | 88 | 113 | ||
750 | 89 | bool canBeResumed() const; | 114 | bool canBeResumed() const; |
751 | 90 | void setCanBeResumed(const bool); | ||
752 | 91 | 115 | ||
753 | 92 | bool isValid() const; | 116 | bool isValid() const; |
754 | 93 | QString desktopFile() const; | 117 | QString desktopFile() const; |
755 | @@ -98,40 +122,58 @@ | |||
756 | 98 | 122 | ||
757 | 99 | pid_t pid() const; | 123 | pid_t pid() const; |
758 | 100 | 124 | ||
759 | 125 | // for tests | ||
760 | 126 | InternalState internalState() const { return m_state; } | ||
761 | 127 | |||
762 | 128 | static QStringList lifecycleExceptions; | ||
763 | 129 | |||
764 | 101 | Q_SIGNALS: | 130 | Q_SIGNALS: |
765 | 102 | void fullscreenChanged(bool fullscreen); | 131 | void fullscreenChanged(bool fullscreen); |
766 | 103 | void stageChanged(Stage stage); | 132 | void stageChanged(Stage stage); |
768 | 104 | void sessionChanged(Session *session); | 133 | void sessionChanged(SessionInterface *session); |
769 | 134 | |||
770 | 135 | void startProcessRequested(); | ||
771 | 136 | void suspendProcessRequested(); | ||
772 | 137 | void resumeProcessRequested(); | ||
773 | 138 | void stopped(); | ||
774 | 105 | 139 | ||
775 | 106 | private Q_SLOTS: | 140 | private Q_SLOTS: |
778 | 107 | void onSessionSuspended(); | 141 | void onSessionStateChanged(SessionInterface::State sessionState); |
777 | 108 | void onSessionResumed(); | ||
779 | 109 | 142 | ||
780 | 110 | void respawn(); | 143 | void respawn(); |
781 | 111 | 144 | ||
782 | 112 | private: | 145 | private: |
783 | 146 | |||
784 | 113 | QString longAppId() const; | 147 | QString longAppId() const; |
786 | 114 | void holdWakelock(bool enable) const; | 148 | void acquireWakelock() const; |
787 | 149 | void releaseWakelock() const; | ||
788 | 115 | void setPid(pid_t pid); | 150 | void setPid(pid_t pid); |
789 | 116 | void setArguments(const QStringList arguments); | 151 | void setArguments(const QStringList arguments); |
790 | 117 | void setFocused(bool focus); | 152 | void setFocused(bool focus); |
792 | 118 | void setSession(Session *session); | 153 | void setInternalState(InternalState state); |
793 | 154 | void wipeQMLCache(); | ||
794 | 155 | void suspend(); | ||
795 | 156 | void resume(); | ||
796 | 119 | QColor colorFromString(const QString &colorString, const char *colorName) const; | 157 | QColor colorFromString(const QString &colorString, const char *colorName) const; |
797 | 158 | static const char* internalStateToStr(InternalState state); | ||
798 | 159 | void applyRequestedState(); | ||
799 | 160 | void applyRequestedRunning(); | ||
800 | 161 | void applyRequestedSuspended(); | ||
801 | 120 | 162 | ||
802 | 121 | QSharedPointer<TaskController> m_taskController; | ||
803 | 122 | QSharedPointer<SharedWakelock> m_sharedWakelock; | 163 | QSharedPointer<SharedWakelock> m_sharedWakelock; |
804 | 123 | DesktopFileReader* m_desktopData; | 164 | DesktopFileReader* m_desktopData; |
805 | 124 | QString m_longAppId; | 165 | QString m_longAppId; |
806 | 125 | qint64 m_pid; | 166 | qint64 m_pid; |
807 | 126 | Stage m_stage; | 167 | Stage m_stage; |
808 | 127 | Stages m_supportedStages; | 168 | Stages m_supportedStages; |
810 | 128 | State m_state; | 169 | InternalState m_state; |
811 | 129 | bool m_focused; | 170 | bool m_focused; |
812 | 130 | bool m_canBeResumed; | ||
813 | 131 | QStringList m_arguments; | 171 | QStringList m_arguments; |
814 | 132 | Qt::ScreenOrientations m_supportedOrientations; | 172 | Qt::ScreenOrientations m_supportedOrientations; |
815 | 133 | bool m_rotatesWindowContents; | 173 | bool m_rotatesWindowContents; |
817 | 134 | Session *m_session; | 174 | SessionInterface *m_session; |
818 | 175 | RequestedState m_requestedState; | ||
819 | 176 | ProcessState m_processState; | ||
820 | 135 | 177 | ||
821 | 136 | friend class ApplicationManager; | 178 | friend class ApplicationManager; |
822 | 137 | friend class SessionManager; | 179 | friend class SessionManager; |
823 | 138 | 180 | ||
824 | === modified file 'src/modules/Unity/Application/application_manager.cpp' | |||
825 | --- src/modules/Unity/Application/application_manager.cpp 2015-05-21 18:38:27 +0000 | |||
826 | +++ src/modules/Unity/Application/application_manager.cpp 2015-07-13 21:57:32 +0000 | |||
827 | @@ -1,5 +1,5 @@ | |||
828 | 1 | /* | 1 | /* |
830 | 2 | * Copyright (C) 2013,2014 Canonical, Ltd. | 2 | * Copyright (C) 2013-2015 Canonical, Ltd. |
831 | 3 | * | 3 | * |
832 | 4 | * This program is free software: you can redistribute it and/or modify it under | 4 | * This program is free software: you can redistribute it and/or modify it under |
833 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | 5 | * the terms of the GNU Lesser General Public License version 3, as published by |
834 | @@ -29,6 +29,7 @@ | |||
835 | 29 | 29 | ||
836 | 30 | // mirserver | 30 | // mirserver |
837 | 31 | #include "mirserver.h" | 31 | #include "mirserver.h" |
838 | 32 | #include "mirshell.h" | ||
839 | 32 | #include "nativeinterface.h" | 33 | #include "nativeinterface.h" |
840 | 33 | #include "sessionlistener.h" | 34 | #include "sessionlistener.h" |
841 | 34 | #include "sessionauthorizer.h" | 35 | #include "sessionauthorizer.h" |
842 | @@ -47,6 +48,8 @@ | |||
843 | 47 | #include <QDebug> | 48 | #include <QDebug> |
844 | 48 | #include <QByteArray> | 49 | #include <QByteArray> |
845 | 49 | #include <QDir> | 50 | #include <QDir> |
846 | 51 | #include <QJSEngine> | ||
847 | 52 | #include <QJSValue> | ||
848 | 50 | 53 | ||
849 | 51 | // std | 54 | // std |
850 | 52 | #include <csignal> | 55 | #include <csignal> |
851 | @@ -90,23 +93,31 @@ | |||
852 | 90 | manager, &ApplicationManager::authorizeSession, Qt::BlockingQueuedConnection); | 93 | manager, &ApplicationManager::authorizeSession, Qt::BlockingQueuedConnection); |
853 | 91 | } | 94 | } |
854 | 92 | 95 | ||
855 | 96 | void connectToMirShell(ApplicationManager *manager, MirShell *shell) | ||
856 | 97 | { | ||
857 | 98 | QObject::connect(shell, &MirShell::sessionAboutToCreateSurface, | ||
858 | 99 | manager, &ApplicationManager::onSessionAboutToCreateSurface, Qt::BlockingQueuedConnection); | ||
859 | 100 | } | ||
860 | 101 | |||
861 | 93 | void connectToTaskController(ApplicationManager *manager, TaskController *controller) | 102 | void connectToTaskController(ApplicationManager *manager, TaskController *controller) |
862 | 94 | { | 103 | { |
863 | 95 | QObject::connect(controller, &TaskController::processStarting, | 104 | QObject::connect(controller, &TaskController::processStarting, |
864 | 96 | manager, &ApplicationManager::onProcessStarting); | 105 | manager, &ApplicationManager::onProcessStarting); |
865 | 97 | QObject::connect(controller, &TaskController::processStopped, | 106 | QObject::connect(controller, &TaskController::processStopped, |
866 | 98 | manager, &ApplicationManager::onProcessStopped); | 107 | manager, &ApplicationManager::onProcessStopped); |
867 | 108 | QObject::connect(controller, &TaskController::processSuspended, | ||
868 | 109 | manager, &ApplicationManager::onProcessSuspended); | ||
869 | 99 | QObject::connect(controller, &TaskController::processFailed, | 110 | QObject::connect(controller, &TaskController::processFailed, |
870 | 100 | manager, &ApplicationManager::onProcessFailed); | 111 | manager, &ApplicationManager::onProcessFailed); |
872 | 101 | QObject::connect(controller, &TaskController::requestFocus, | 112 | QObject::connect(controller, &TaskController::focusRequested, |
873 | 102 | manager, &ApplicationManager::onFocusRequested); | 113 | manager, &ApplicationManager::onFocusRequested); |
875 | 103 | QObject::connect(controller, &TaskController::requestResume, | 114 | QObject::connect(controller, &TaskController::resumeRequested, |
876 | 104 | manager, &ApplicationManager::onResumeRequested); | 115 | manager, &ApplicationManager::onResumeRequested); |
877 | 105 | } | 116 | } |
878 | 106 | 117 | ||
879 | 107 | } // namespace | 118 | } // namespace |
880 | 108 | 119 | ||
882 | 109 | ApplicationManager* ApplicationManager::Factory::Factory::create() | 120 | ApplicationManager* ApplicationManager::Factory::Factory::create(QJSEngine *jsEngine) |
883 | 110 | { | 121 | { |
884 | 111 | NativeInterface *nativeInterface = dynamic_cast<NativeInterface*>(QGuiApplication::platformNativeInterface()); | 122 | NativeInterface *nativeInterface = dynamic_cast<NativeInterface*>(QGuiApplication::platformNativeInterface()); |
885 | 112 | 123 | ||
886 | @@ -139,11 +150,13 @@ | |||
887 | 139 | sharedWakelock, | 150 | sharedWakelock, |
888 | 140 | fileReaderFactory, | 151 | fileReaderFactory, |
889 | 141 | procInfo, | 152 | procInfo, |
891 | 142 | settings | 153 | settings, |
892 | 154 | jsEngine | ||
893 | 143 | ); | 155 | ); |
894 | 144 | 156 | ||
895 | 145 | connectToSessionListener(appManager, sessionListener); | 157 | connectToSessionListener(appManager, sessionListener); |
896 | 146 | connectToSessionAuthorizer(appManager, sessionAuthorizer); | 158 | connectToSessionAuthorizer(appManager, sessionAuthorizer); |
897 | 159 | connectToMirShell(appManager, mirServer.lock()->shell()); | ||
898 | 147 | connectToTaskController(appManager, taskController.data()); | 160 | connectToTaskController(appManager, taskController.data()); |
899 | 148 | 161 | ||
900 | 149 | // Emit signal to notify Upstart that Mir is ready to receive client connections | 162 | // Emit signal to notify Upstart that Mir is ready to receive client connections |
901 | @@ -159,12 +172,12 @@ | |||
902 | 159 | } | 172 | } |
903 | 160 | 173 | ||
904 | 161 | 174 | ||
906 | 162 | ApplicationManager* ApplicationManager::singleton() | 175 | ApplicationManager* ApplicationManager::singleton(QJSEngine *jsEngine) |
907 | 163 | { | 176 | { |
908 | 164 | static ApplicationManager* instance; | 177 | static ApplicationManager* instance; |
909 | 165 | if (!instance) { | 178 | if (!instance) { |
910 | 166 | Factory appFactory; | 179 | Factory appFactory; |
912 | 167 | instance = appFactory.create(); | 180 | instance = appFactory.create(jsEngine); |
913 | 168 | } | 181 | } |
914 | 169 | return instance; | 182 | return instance; |
915 | 170 | } | 183 | } |
916 | @@ -176,20 +189,19 @@ | |||
917 | 176 | const QSharedPointer<DesktopFileReader::Factory>& desktopFileReaderFactory, | 189 | const QSharedPointer<DesktopFileReader::Factory>& desktopFileReaderFactory, |
918 | 177 | const QSharedPointer<ProcInfo>& procInfo, | 190 | const QSharedPointer<ProcInfo>& procInfo, |
919 | 178 | const QSharedPointer<SettingsInterface>& settings, | 191 | const QSharedPointer<SettingsInterface>& settings, |
920 | 192 | QJSEngine *jsEngine, | ||
921 | 179 | QObject *parent) | 193 | QObject *parent) |
922 | 180 | : ApplicationManagerInterface(parent) | 194 | : ApplicationManagerInterface(parent) |
923 | 181 | , m_mirServer(mirServer) | 195 | , m_mirServer(mirServer) |
924 | 182 | , m_focusedApplication(nullptr) | 196 | , m_focusedApplication(nullptr) |
925 | 183 | , m_mainStageApplication(nullptr) | ||
926 | 184 | , m_sideStageApplication(nullptr) | ||
927 | 185 | , m_dbusWindowStack(new DBusWindowStack(this)) | 197 | , m_dbusWindowStack(new DBusWindowStack(this)) |
928 | 186 | , m_taskController(taskController) | 198 | , m_taskController(taskController) |
929 | 187 | , m_desktopFileReaderFactory(desktopFileReaderFactory) | 199 | , m_desktopFileReaderFactory(desktopFileReaderFactory) |
930 | 188 | , m_procInfo(procInfo) | 200 | , m_procInfo(procInfo) |
931 | 189 | , m_sharedWakelock(sharedWakelock) | 201 | , m_sharedWakelock(sharedWakelock) |
932 | 190 | , m_settings(settings) | 202 | , m_settings(settings) |
935 | 191 | , m_suspended(false) | 203 | , m_surfaceAboutToBeCreatedCallback(QJSValue::UndefinedValue) |
936 | 192 | , m_forceDashActive(false) | 204 | , m_jsEngine(jsEngine) |
937 | 193 | { | 205 | { |
938 | 194 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::ApplicationManager (this=%p)" << this; | 206 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::ApplicationManager (this=%p)" << this; |
939 | 195 | setObjectName("qtmir::ApplicationManager"); | 207 | setObjectName("qtmir::ApplicationManager"); |
940 | @@ -198,7 +210,7 @@ | |||
941 | 198 | m_roleNames.insert(RoleFullscreen, "fullscreen"); | 210 | m_roleNames.insert(RoleFullscreen, "fullscreen"); |
942 | 199 | 211 | ||
943 | 200 | if (settings.data()) { | 212 | if (settings.data()) { |
945 | 201 | m_lifecycleExceptions = m_settings->get("lifecycleExemptAppids").toStringList(); | 213 | Application::lifecycleExceptions = m_settings->get("lifecycleExemptAppids").toStringList(); |
946 | 202 | connect(m_settings.data(), &Settings::changed, this, &ApplicationManager::onSettingsChanged); | 214 | connect(m_settings.data(), &Settings::changed, this, &ApplicationManager::onSettingsChanged); |
947 | 203 | } | 215 | } |
948 | 204 | } | 216 | } |
949 | @@ -206,6 +218,7 @@ | |||
950 | 206 | ApplicationManager::~ApplicationManager() | 218 | ApplicationManager::~ApplicationManager() |
951 | 207 | { | 219 | { |
952 | 208 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::~ApplicationManager"; | 220 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::~ApplicationManager"; |
953 | 221 | m_surfaceAboutToBeCreatedCallback = QJSValue::UndefinedValue; //unset immediately to avoid racing on shutdown | ||
954 | 209 | } | 222 | } |
955 | 210 | 223 | ||
956 | 211 | int ApplicationManager::rowCount(const QModelIndex &parent) const | 224 | int ApplicationManager::rowCount(const QModelIndex &parent) const |
957 | @@ -289,96 +302,23 @@ | |||
958 | 289 | } | 302 | } |
959 | 290 | } | 303 | } |
960 | 291 | 304 | ||
962 | 292 | bool ApplicationManager::suspended() const | 305 | QJSValue ApplicationManager::surfaceAboutToBeCreatedCallback() const |
963 | 293 | { | 306 | { |
965 | 294 | return m_suspended; | 307 | return m_surfaceAboutToBeCreatedCallback; |
966 | 295 | } | 308 | } |
967 | 296 | 309 | ||
969 | 297 | void ApplicationManager::setSuspended(bool suspended) | 310 | void ApplicationManager::setSurfaceAboutToBeCreatedCallback(const QJSValue &callback) |
970 | 298 | { | 311 | { |
972 | 299 | if (suspended == m_suspended) { | 312 | if (m_surfaceAboutToBeCreatedCallback.equals(callback)) |
973 | 300 | return; | 313 | return; |
974 | 301 | } | ||
975 | 302 | m_suspended = suspended; | ||
976 | 303 | Q_EMIT suspendedChanged(); | ||
977 | 304 | 314 | ||
985 | 305 | if (m_suspended) { | 315 | if (callback.isCallable()) { |
986 | 306 | suspendApplication(m_mainStageApplication); | 316 | m_surfaceAboutToBeCreatedCallback = callback; |
980 | 307 | suspendApplication(m_sideStageApplication); | ||
981 | 308 | if (m_focusedApplication) { | ||
982 | 309 | m_focusedApplication->setFocused(false); | ||
983 | 310 | m_dbusWindowStack->FocusedWindowChanged(0, QString(), 0); | ||
984 | 311 | } | ||
987 | 312 | } else { | 317 | } else { |
1057 | 313 | resumeApplication(m_mainStageApplication); | 318 | qWarning() << "ApplicationManager::setSurfaceAboutToBeCreatedCallback - attempted to register a non-function!"; |
1058 | 314 | resumeApplication(m_sideStageApplication); | 319 | m_surfaceAboutToBeCreatedCallback = QJSValue::UndefinedValue; |
1059 | 315 | if (m_focusedApplication) { | 320 | } |
1060 | 316 | m_focusedApplication->setFocused(true); | 321 | Q_EMIT surfaceAboutToBeCreatedCallbackChanged(); |
992 | 317 | m_dbusWindowStack->FocusedWindowChanged(0, m_focusedApplication->appId(), m_focusedApplication->stage()); | ||
993 | 318 | } | ||
994 | 319 | } | ||
995 | 320 | } | ||
996 | 321 | |||
997 | 322 | bool ApplicationManager::forceDashActive() const | ||
998 | 323 | { | ||
999 | 324 | return m_forceDashActive; | ||
1000 | 325 | } | ||
1001 | 326 | |||
1002 | 327 | void ApplicationManager::setForceDashActive(bool forceDashActive) | ||
1003 | 328 | { | ||
1004 | 329 | if (m_forceDashActive == forceDashActive) { | ||
1005 | 330 | return; | ||
1006 | 331 | } | ||
1007 | 332 | |||
1008 | 333 | m_forceDashActive = forceDashActive; | ||
1009 | 334 | Q_EMIT forceDashActiveChanged(); | ||
1010 | 335 | |||
1011 | 336 | Application *dashApp = findApplication("unity8-dash"); | ||
1012 | 337 | if (!dashApp) { | ||
1013 | 338 | qCWarning(QTMIR_APPLICATIONS) << "Dash doesn't seem to be running... Ignoring."; | ||
1014 | 339 | return; | ||
1015 | 340 | } | ||
1016 | 341 | |||
1017 | 342 | if (m_forceDashActive && dashApp->state() != Application::Running) { | ||
1018 | 343 | resumeApplication(dashApp); | ||
1019 | 344 | } else if (!m_forceDashActive && dashApp->state() == Application::Running | ||
1020 | 345 | && m_mainStageApplication != dashApp | ||
1021 | 346 | && m_sideStageApplication != dashApp) { | ||
1022 | 347 | suspendApplication(dashApp); | ||
1023 | 348 | } | ||
1024 | 349 | } | ||
1025 | 350 | |||
1026 | 351 | bool ApplicationManager::suspendApplication(Application *application) | ||
1027 | 352 | { | ||
1028 | 353 | if (application == nullptr) | ||
1029 | 354 | return false; | ||
1030 | 355 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::suspendApplication - appId=" << application->appId(); | ||
1031 | 356 | |||
1032 | 357 | // Present in exceptions list, explicitly release wakelock and return. There's no need to keep the wakelock | ||
1033 | 358 | // as the process is never suspended and thus has no cleanup to perform when (for example) the display is blanked | ||
1034 | 359 | if (!m_lifecycleExceptions.filter(application->appId().section('_',0,0)).empty()) { | ||
1035 | 360 | m_sharedWakelock->release(application); | ||
1036 | 361 | return false; | ||
1037 | 362 | } | ||
1038 | 363 | |||
1039 | 364 | if (m_forceDashActive && application->appId() == "unity8-dash") { | ||
1040 | 365 | return false; | ||
1041 | 366 | } | ||
1042 | 367 | |||
1043 | 368 | if (application->state() == Application::Running) | ||
1044 | 369 | application->setState(Application::Suspended); | ||
1045 | 370 | |||
1046 | 371 | return true; | ||
1047 | 372 | } | ||
1048 | 373 | |||
1049 | 374 | void ApplicationManager::resumeApplication(Application *application) | ||
1050 | 375 | { | ||
1051 | 376 | if (application == nullptr) | ||
1052 | 377 | return; | ||
1053 | 378 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::resumeApplication - appId=" << application->appId(); | ||
1054 | 379 | |||
1055 | 380 | if (application->state() == Application::Suspended || application->state() == Application::Stopped) | ||
1056 | 381 | application->setState(Application::Running); | ||
1061 | 382 | } | 322 | } |
1062 | 383 | 323 | ||
1063 | 384 | bool ApplicationManager::focusApplication(const QString &inputAppId) | 324 | bool ApplicationManager::focusApplication(const QString &inputAppId) |
1064 | @@ -392,27 +332,8 @@ | |||
1065 | 392 | return false; | 332 | return false; |
1066 | 393 | } | 333 | } |
1067 | 394 | 334 | ||
1068 | 395 | resumeApplication(application); | ||
1069 | 396 | |||
1070 | 397 | // set state of previously focused app to suspended | ||
1071 | 398 | if (m_focusedApplication) { | 335 | if (m_focusedApplication) { |
1072 | 399 | m_focusedApplication->setFocused(false); | 336 | m_focusedApplication->setFocused(false); |
1073 | 400 | Application *lastApplication = applicationForStage(application->stage()); | ||
1074 | 401 | if (lastApplication != application) { | ||
1075 | 402 | suspendApplication(lastApplication); | ||
1076 | 403 | } | ||
1077 | 404 | } | ||
1078 | 405 | |||
1079 | 406 | if (application->stage() == Application::MainStage) { | ||
1080 | 407 | m_mainStageApplication = application; | ||
1081 | 408 | } else { | ||
1082 | 409 | m_sideStageApplication = application; | ||
1083 | 410 | } | ||
1084 | 411 | |||
1085 | 412 | if (!m_suspended) { | ||
1086 | 413 | resumeApplication(application); // in case unfocusCurrentApplication() was last called | ||
1087 | 414 | } else { | ||
1088 | 415 | suspendApplication(application); // Make sure we also have this one suspended if everything is suspended | ||
1089 | 416 | } | 337 | } |
1090 | 417 | 338 | ||
1091 | 418 | m_focusedApplication = application; | 339 | m_focusedApplication = application; |
1092 | @@ -422,9 +343,6 @@ | |||
1093 | 422 | Q_EMIT focusedApplicationIdChanged(); | 343 | Q_EMIT focusedApplicationIdChanged(); |
1094 | 423 | m_dbusWindowStack->FocusedWindowChanged(0, application->appId(), application->stage()); | 344 | m_dbusWindowStack->FocusedWindowChanged(0, application->appId(), application->stage()); |
1095 | 424 | 345 | ||
1096 | 425 | // FIXME(dandrader): lying here. The operation is async. So we will only know whether | ||
1097 | 426 | // the focusing was successful once the server replies. Maybe the API in unity-api should | ||
1098 | 427 | // reflect that? | ||
1099 | 428 | return true; | 346 | return true; |
1100 | 429 | } | 347 | } |
1101 | 430 | 348 | ||
1102 | @@ -432,9 +350,6 @@ | |||
1103 | 432 | { | 350 | { |
1104 | 433 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::unfocusCurrentApplication"; | 351 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::unfocusCurrentApplication"; |
1105 | 434 | 352 | ||
1106 | 435 | suspendApplication(m_sideStageApplication); | ||
1107 | 436 | suspendApplication(m_mainStageApplication); | ||
1108 | 437 | |||
1109 | 438 | m_focusedApplication = nullptr; | 353 | m_focusedApplication = nullptr; |
1110 | 439 | Q_EMIT focusedApplicationIdChanged(); | 354 | Q_EMIT focusedApplicationIdChanged(); |
1111 | 440 | } | 355 | } |
1112 | @@ -484,10 +399,8 @@ | |||
1113 | 484 | application->setArguments(arguments); | 399 | application->setArguments(arguments); |
1114 | 485 | } else { | 400 | } else { |
1115 | 486 | application = new Application( | 401 | application = new Application( |
1116 | 487 | m_taskController, | ||
1117 | 488 | m_sharedWakelock, | 402 | m_sharedWakelock, |
1118 | 489 | m_desktopFileReaderFactory->createInstance(appId, m_taskController->findDesktopFileForAppId(appId)), | 403 | m_desktopFileReaderFactory->createInstance(appId, m_taskController->findDesktopFileForAppId(appId)), |
1119 | 490 | Application::Starting, | ||
1120 | 491 | arguments, | 404 | arguments, |
1121 | 492 | this); | 405 | this); |
1122 | 493 | 406 | ||
1123 | @@ -514,10 +427,8 @@ | |||
1124 | 514 | Application *application = findApplication(appId); | 427 | Application *application = findApplication(appId); |
1125 | 515 | if (!application) { // then shell did not start this application, so ubuntu-app-launch must have - add to list | 428 | if (!application) { // then shell did not start this application, so ubuntu-app-launch must have - add to list |
1126 | 516 | application = new Application( | 429 | application = new Application( |
1127 | 517 | m_taskController, | ||
1128 | 518 | m_sharedWakelock, | 430 | m_sharedWakelock, |
1129 | 519 | m_desktopFileReaderFactory->createInstance(appId, m_taskController->findDesktopFileForAppId(appId)), | 431 | m_desktopFileReaderFactory->createInstance(appId, m_taskController->findDesktopFileForAppId(appId)), |
1130 | 520 | Application::Starting, | ||
1131 | 521 | QStringList(), | 432 | QStringList(), |
1132 | 522 | this); | 433 | this); |
1133 | 523 | 434 | ||
1134 | @@ -530,17 +441,17 @@ | |||
1135 | 530 | Q_EMIT focusRequested(appId); | 441 | Q_EMIT focusRequested(appId); |
1136 | 531 | } | 442 | } |
1137 | 532 | else { | 443 | else { |
1138 | 533 | // url-dispatcher can relaunch apps which have been OOM-killed - AppMan must accept the newly spawned | ||
1139 | 534 | // application and focus it immediately (as user expects app to still be running). | ||
1140 | 535 | if (application->state() == Application::Stopped) { | 444 | if (application->state() == Application::Stopped) { |
1141 | 445 | // url-dispatcher can relaunch apps which have been OOM-killed - AppMan must accept the newly spawned | ||
1142 | 446 | // application and focus it immediately (as user expects app to still be running). | ||
1143 | 536 | qCDebug(QTMIR_APPLICATIONS) << "Stopped application appId=" << appId << "is being resumed externally"; | 447 | qCDebug(QTMIR_APPLICATIONS) << "Stopped application appId=" << appId << "is being resumed externally"; |
1144 | 537 | application->setState(Application::Starting); | ||
1145 | 538 | Q_EMIT focusRequested(appId); | 448 | Q_EMIT focusRequested(appId); |
1146 | 539 | } else { | 449 | } else { |
1147 | 540 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::onProcessStarting application already found with appId" | 450 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::onProcessStarting application already found with appId" |
1148 | 541 | << appId; | 451 | << appId; |
1149 | 542 | } | 452 | } |
1150 | 543 | } | 453 | } |
1151 | 454 | application->setProcessState(Application::ProcessRunning); | ||
1152 | 544 | } | 455 | } |
1153 | 545 | 456 | ||
1154 | 546 | /** | 457 | /** |
1155 | @@ -559,14 +470,7 @@ | |||
1156 | 559 | return false; | 470 | return false; |
1157 | 560 | } | 471 | } |
1158 | 561 | 472 | ||
1159 | 562 | if (application == m_focusedApplication) { | ||
1160 | 563 | // unfocus, and let shell decide what next to focus | ||
1161 | 564 | m_focusedApplication = nullptr; | ||
1162 | 565 | Q_EMIT focusedApplicationIdChanged(); | ||
1163 | 566 | } | ||
1164 | 567 | |||
1165 | 568 | remove(application); | 473 | remove(application); |
1166 | 569 | m_dbusWindowStack->WindowDestroyed(0, appId); | ||
1167 | 570 | 474 | ||
1168 | 571 | bool result = m_taskController->stop(application->longAppId()); | 475 | bool result = m_taskController->stop(application->longAppId()); |
1169 | 572 | 476 | ||
1170 | @@ -583,10 +487,7 @@ | |||
1171 | 583 | 487 | ||
1172 | 584 | void ApplicationManager::onProcessFailed(const QString &appId, const bool duringStartup) | 488 | void ApplicationManager::onProcessFailed(const QString &appId, const bool duringStartup) |
1173 | 585 | { | 489 | { |
1178 | 586 | /* Applications fail if they fail to launch, crash or are killed. If failed to start, must | 490 | // Applications fail if they fail to launch, crash or are killed. |
1175 | 587 | * immediately remove from list of applications. If crash or kill, instead we set flag on the | ||
1176 | 588 | * Application to indicate it can be resumed. | ||
1177 | 589 | */ | ||
1179 | 590 | 491 | ||
1180 | 591 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::onProcessFailed - appId=" << appId << "duringStartup=" << duringStartup; | 492 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::onProcessFailed - appId=" << appId << "duringStartup=" << duringStartup; |
1181 | 592 | 493 | ||
1182 | @@ -598,20 +499,8 @@ | |||
1183 | 598 | } | 499 | } |
1184 | 599 | 500 | ||
1185 | 600 | Q_UNUSED(duringStartup); // FIXME(greyback) upstart reports app that fully started up & crashes as failing during startup?? | 501 | Q_UNUSED(duringStartup); // FIXME(greyback) upstart reports app that fully started up & crashes as failing during startup?? |
1200 | 601 | if (application->state() == Application::Starting) { | 502 | application->setProcessState(Application::ProcessStopped); |
1201 | 602 | if (application == m_focusedApplication) { | 503 | application->setPid(0); |
1188 | 603 | m_focusedApplication = nullptr; | ||
1189 | 604 | Q_EMIT focusedApplicationIdChanged(); | ||
1190 | 605 | } | ||
1191 | 606 | remove(application); | ||
1192 | 607 | m_dbusWindowStack->WindowDestroyed(0, application->appId()); | ||
1193 | 608 | delete application; | ||
1194 | 609 | } else { | ||
1195 | 610 | // We need to set flags on the Application to say the app can be resumed, and thus should not be removed | ||
1196 | 611 | // from the list by onProcessStopped. | ||
1197 | 612 | application->setCanBeResumed(true); | ||
1198 | 613 | application->setPid(0); | ||
1199 | 614 | } | ||
1202 | 615 | } | 504 | } |
1203 | 616 | 505 | ||
1204 | 617 | void ApplicationManager::onProcessStopped(const QString &appId) | 506 | void ApplicationManager::onProcessStopped(const QString &appId) |
1205 | @@ -626,29 +515,15 @@ | |||
1206 | 626 | return; | 515 | return; |
1207 | 627 | } | 516 | } |
1208 | 628 | 517 | ||
1232 | 629 | // if shell did not stop the application, but ubuntu-app-launch says it died, we assume the process has been | 518 | application->setProcessState(Application::ProcessStopped); |
1233 | 630 | // killed, so it can be respawned later. Only exception is if that application is focused or running | 519 | application->setPid(0); |
1234 | 631 | // as then it most likely crashed. Update this logic when ubuntu-app-launch gives some failure info. | 520 | } |
1235 | 632 | bool removeApplication = true; | 521 | |
1236 | 633 | 522 | void ApplicationManager::onProcessSuspended(const QString &appId) | |
1237 | 634 | if (application == m_focusedApplication) { | 523 | { |
1238 | 635 | // Very bad case where focused application dies. Remove from list. Should give error message | 524 | Application *application = findApplication(appId); |
1239 | 636 | m_focusedApplication = nullptr; | 525 | if (application) { |
1240 | 637 | Q_EMIT focusedApplicationIdChanged(); | 526 | application->setProcessState(Application::ProcessSuspended); |
1218 | 638 | } | ||
1219 | 639 | |||
1220 | 640 | // The following scenario is the only time that we do NOT remove the application from the app list: | ||
1221 | 641 | if ((application->state() == Application::Suspended || application->state() == Application::Stopped) | ||
1222 | 642 | && application->pid() == 0 // i.e. onProcessFailed was called, which resets the PID of this application | ||
1223 | 643 | && application->canBeResumed()) { | ||
1224 | 644 | removeApplication = false; | ||
1225 | 645 | } | ||
1226 | 646 | |||
1227 | 647 | if (removeApplication) { | ||
1228 | 648 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::onProcessStopped - removing appId=" << appId; | ||
1229 | 649 | remove(application); | ||
1230 | 650 | m_dbusWindowStack->WindowDestroyed(0, application->appId()); | ||
1231 | 651 | delete application; | ||
1241 | 652 | } | 527 | } |
1242 | 653 | } | 528 | } |
1243 | 654 | 529 | ||
1244 | @@ -670,10 +545,10 @@ | |||
1245 | 670 | return; | 545 | return; |
1246 | 671 | } | 546 | } |
1247 | 672 | 547 | ||
1250 | 673 | // If app Stopped, trust that ubuntu-app-launch respawns it itself, and AppManager will | 548 | // We interpret this as a focus request for a suspended app. |
1251 | 674 | // be notified of that through the onProcessStartReportReceived slot. Else resume. | 549 | // Shell will have this app resumed if it complies with the focus request |
1252 | 675 | if (application->state() == Application::Suspended) { | 550 | if (application->state() == Application::Suspended) { |
1254 | 676 | application->setState(Application::Running); | 551 | Q_EMIT focusRequested(appId); |
1255 | 677 | } | 552 | } |
1256 | 678 | } | 553 | } |
1257 | 679 | 554 | ||
1258 | @@ -693,7 +568,7 @@ | |||
1259 | 693 | void ApplicationManager::onSettingsChanged(const QString &key) | 568 | void ApplicationManager::onSettingsChanged(const QString &key) |
1260 | 694 | { | 569 | { |
1261 | 695 | if (key == "lifecycleExemptAppids") { | 570 | if (key == "lifecycleExemptAppids") { |
1263 | 696 | m_lifecycleExceptions = m_settings->get("lifecycleExemptAppids").toStringList(); | 571 | Application::lifecycleExceptions = m_settings->get("lifecycleExemptAppids").toStringList(); |
1264 | 697 | } | 572 | } |
1265 | 698 | } | 573 | } |
1266 | 699 | 574 | ||
1267 | @@ -732,7 +607,6 @@ | |||
1268 | 732 | 607 | ||
1269 | 733 | if (info->startsWith("maliit-server") || info->contains("qt5/libexec/QtWebProcess")) { | 608 | if (info->startsWith("maliit-server") || info->contains("qt5/libexec/QtWebProcess")) { |
1270 | 734 | authorized = true; | 609 | authorized = true; |
1271 | 735 | m_hiddenPIDs << pid; | ||
1272 | 736 | return; | 610 | return; |
1273 | 737 | } | 611 | } |
1274 | 738 | 612 | ||
1275 | @@ -792,15 +666,12 @@ | |||
1276 | 792 | 666 | ||
1277 | 793 | QStringList arguments(info->asStringList()); | 667 | QStringList arguments(info->asStringList()); |
1278 | 794 | application = new Application( | 668 | application = new Application( |
1279 | 795 | m_taskController, | ||
1280 | 796 | m_sharedWakelock, | 669 | m_sharedWakelock, |
1281 | 797 | desktopData, | 670 | desktopData, |
1282 | 798 | Application::Starting, | ||
1283 | 799 | arguments, | 671 | arguments, |
1284 | 800 | this); | 672 | this); |
1285 | 801 | application->setPid(pid); | 673 | application->setPid(pid); |
1286 | 802 | application->setStage(stage); | 674 | application->setStage(stage); |
1287 | 803 | application->setCanBeResumed(false); | ||
1288 | 804 | add(application); | 675 | add(application); |
1289 | 805 | authorized = true; | 676 | authorized = true; |
1290 | 806 | } | 677 | } |
1291 | @@ -812,66 +683,56 @@ | |||
1292 | 812 | 683 | ||
1293 | 813 | void ApplicationManager::onSessionStopping(std::shared_ptr<ms::Session> const& session) | 684 | void ApplicationManager::onSessionStopping(std::shared_ptr<ms::Session> const& session) |
1294 | 814 | { | 685 | { |
1295 | 815 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::onSessionStopping - sessionName=" << session->name().c_str(); | ||
1296 | 816 | |||
1297 | 817 | // in case application closed not by hand of shell, check again here: | ||
1298 | 818 | Application* application = findApplicationWithSession(session); | 686 | Application* application = findApplicationWithSession(session); |
1299 | 819 | if (application) { | 687 | if (application) { |
1333 | 820 | /* Can remove the application from the running apps list immediately in these curcumstances: | 688 | m_dbusWindowStack->WindowDestroyed(0, application->appId()); |
1334 | 821 | * 1. application is not managed by upstart (this message from Mir is only notice the app has stopped, must do | 689 | } |
1335 | 822 | * it here) | 690 | } |
1336 | 823 | * 2. application is managed by upstart, but has stopped before it managed to create a surface, we can assume | 691 | |
1337 | 824 | * it crashed on startup, and thus cannot be resumed - so remove it. | 692 | void ApplicationManager::onSessionAboutToCreateSurface(const std::shared_ptr<mir::scene::Session> &session, |
1338 | 825 | * 3. application is managed by upstart and is in foreground (i.e. has Running state), if Mir reports the | 693 | qtmir::SurfaceParameters ¶ms) |
1339 | 826 | * application disconnects, it either crashed or stopped itself. Either case, remove it. | 694 | { |
1340 | 827 | */ | 695 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::onSessionAboutToCreateSurface - sessionName=" |
1341 | 828 | if (!application->canBeResumed() | 696 | << session->name().c_str() << "geometry=" << params.geometry |
1342 | 829 | || application->state() == Application::Starting | 697 | << "state" << params.state; |
1343 | 830 | || application->state() == Application::Running) { | 698 | |
1344 | 831 | m_dbusWindowStack->WindowDestroyed(0, application->appId()); | 699 | if (m_surfaceAboutToBeCreatedCallback.isCallable()) { |
1345 | 832 | remove(application); | 700 | QJSValue argument = m_jsEngine->newObject(); |
1346 | 833 | 701 | argument.setProperty("width", params.geometry.width()); | |
1347 | 834 | // (ricmm) -- To be on the safe side, better wipe the application QML compile cache if it crashes on startup | 702 | argument.setProperty("height", params.geometry.height()); |
1348 | 835 | QString path(QDir::homePath() + QStringLiteral("/.cache/QML/Apps/")); | 703 | argument.setProperty("state", params.state); |
1349 | 836 | QDir dir(path); | 704 | |
1350 | 837 | QStringList apps = dir.entryList(); | 705 | Application* application = findApplicationWithSession(session.get()); |
1351 | 838 | for (int i = 0; i < apps.size(); i++) { | 706 | if (application) |
1352 | 839 | if (apps.at(i).contains(application->appId())) { | 707 | argument.setProperty("appId", application->appId()); |
1353 | 840 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::onSessionStopping appId=" << apps.at(i) << " Wiping QML Cache"; | 708 | |
1354 | 841 | dir.cd(apps.at(i)); | 709 | QJSValue output = m_surfaceAboutToBeCreatedCallback.call(QJSValueList() << argument); |
1355 | 842 | dir.removeRecursively(); | 710 | if (output.isObject()) { |
1356 | 843 | break; | 711 | QJSValue width = output.property("width"); |
1357 | 844 | } | 712 | QJSValue height = output.property("height"); |
1358 | 845 | } | 713 | QJSValue state = output.property("state"); |
1359 | 846 | 714 | if (width.isNumber()) | |
1360 | 847 | delete application; | 715 | params.geometry.setWidth(width.toInt()); |
1361 | 848 | 716 | if (height.isNumber()) | |
1362 | 849 | if (application == m_focusedApplication) { | 717 | params.geometry.setHeight(height.toInt()); |
1363 | 850 | m_focusedApplication = nullptr; | 718 | if (state.isNumber()) |
1364 | 851 | Q_EMIT focusedApplicationIdChanged(); | 719 | params.state = static_cast<Globals::SurfaceState>(state.toInt()); |
1332 | 852 | } | ||
1365 | 853 | } else { | 720 | } else { |
1369 | 854 | // otherwise, we do not have enough information to make any changes to the model, so await events from | 721 | qWarning() << "ApplicationManager::onSessionAboutToCreateSurface - unrecognised object returned from JS callback!!" |
1370 | 855 | // upstart to go further, but set the app state | 722 | << "Surface size has *not* been overridden by shell!"; |
1368 | 856 | application->setState(Application::Stopped); | ||
1371 | 857 | } | 723 | } |
1372 | 858 | } | 724 | } |
1373 | 859 | m_hiddenPIDs.removeOne(session->process_id()); | ||
1374 | 860 | } | 725 | } |
1375 | 861 | 726 | ||
1378 | 862 | void ApplicationManager::onSessionCreatedSurface(ms::Session const* session, | 727 | void ApplicationManager::onSessionCreatedSurface(const ms::Session *session, |
1379 | 863 | std::shared_ptr<ms::Surface> const& surface) | 728 | const std::shared_ptr<ms::Surface> &surface) |
1380 | 864 | { | 729 | { |
1381 | 865 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::onSessionCreatedSurface - sessionName=" << session->name().c_str(); | 730 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::onSessionCreatedSurface - sessionName=" << session->name().c_str(); |
1382 | 866 | Q_UNUSED(surface); | 731 | Q_UNUSED(surface); |
1383 | 867 | 732 | ||
1384 | 868 | Application* application = findApplicationWithSession(session); | 733 | Application* application = findApplicationWithSession(session); |
1386 | 869 | if (application && application->state() == Application::Starting) { | 734 | if (application) { |
1387 | 870 | m_dbusWindowStack->WindowCreated(0, application->appId()); | 735 | m_dbusWindowStack->WindowCreated(0, application->appId()); |
1388 | 871 | application->setState(Application::Running); | ||
1389 | 872 | if ((application != m_mainStageApplication && application != m_sideStageApplication) || m_suspended) { | ||
1390 | 873 | suspendApplication(application); | ||
1391 | 874 | } | ||
1392 | 875 | } | 736 | } |
1393 | 876 | } | 737 | } |
1394 | 877 | 738 | ||
1395 | @@ -900,16 +761,6 @@ | |||
1396 | 900 | return nullptr; | 761 | return nullptr; |
1397 | 901 | } | 762 | } |
1398 | 902 | 763 | ||
1399 | 903 | Application* ApplicationManager::applicationForStage(Application::Stage stage) | ||
1400 | 904 | { | ||
1401 | 905 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::focusedApplicationForStage" << stage; | ||
1402 | 906 | |||
1403 | 907 | if (stage == Application::MainStage) | ||
1404 | 908 | return m_mainStageApplication; | ||
1405 | 909 | else | ||
1406 | 910 | return m_sideStageApplication; | ||
1407 | 911 | } | ||
1408 | 912 | |||
1409 | 913 | void ApplicationManager::add(Application* application) | 764 | void ApplicationManager::add(Application* application) |
1410 | 914 | { | 765 | { |
1411 | 915 | Q_ASSERT(application != nullptr); | 766 | Q_ASSERT(application != nullptr); |
1412 | @@ -920,6 +771,28 @@ | |||
1413 | 920 | connect(application, &Application::stateChanged, this, [this](Application::State) { onAppDataChanged(RoleState); }); | 771 | connect(application, &Application::stateChanged, this, [this](Application::State) { onAppDataChanged(RoleState); }); |
1414 | 921 | connect(application, &Application::stageChanged, this, [this](Application::Stage) { onAppDataChanged(RoleStage); }); | 772 | connect(application, &Application::stageChanged, this, [this](Application::Stage) { onAppDataChanged(RoleStage); }); |
1415 | 922 | 773 | ||
1416 | 774 | QString appId = application->appId(); | ||
1417 | 775 | QString longAppId = application->longAppId(); | ||
1418 | 776 | QStringList arguments = application->arguments(); | ||
1419 | 777 | |||
1420 | 778 | // The connection is queued as a workaround an issue in the PhoneStage animation that | ||
1421 | 779 | // happens when you tap on a killed app in the spread to bring it to foreground, causing | ||
1422 | 780 | // a Application::respawn() to take place. | ||
1423 | 781 | // In any case, it seems like in general QML works better when don't do too many things | ||
1424 | 782 | // in the same event loop iteration. | ||
1425 | 783 | connect(application, &Application::startProcessRequested, | ||
1426 | 784 | this, [=]() { m_taskController->start(appId, arguments); }, | ||
1427 | 785 | Qt::QueuedConnection); | ||
1428 | 786 | |||
1429 | 787 | connect(application, &Application::suspendProcessRequested, this, [=]() { m_taskController->suspend(longAppId); } ); | ||
1430 | 788 | connect(application, &Application::resumeProcessRequested, this, [=]() { m_taskController->resume(longAppId); } ); | ||
1431 | 789 | |||
1432 | 790 | connect(application, &Application::stopped, this, [=]() { | ||
1433 | 791 | remove(application); | ||
1434 | 792 | application->deleteLater(); | ||
1435 | 793 | }); | ||
1436 | 794 | |||
1437 | 795 | |||
1438 | 923 | beginInsertRows(QModelIndex(), m_applications.count(), m_applications.count()); | 796 | beginInsertRows(QModelIndex(), m_applications.count(), m_applications.count()); |
1439 | 924 | m_applications.append(application); | 797 | m_applications.append(application); |
1440 | 925 | endInsertRows(); | 798 | endInsertRows(); |
1441 | @@ -935,11 +808,6 @@ | |||
1442 | 935 | Q_ASSERT(application != nullptr); | 808 | Q_ASSERT(application != nullptr); |
1443 | 936 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::remove - appId=" << application->appId(); | 809 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::remove - appId=" << application->appId(); |
1444 | 937 | 810 | ||
1445 | 938 | if (application == m_sideStageApplication) | ||
1446 | 939 | m_sideStageApplication = nullptr; | ||
1447 | 940 | if (application == m_mainStageApplication) | ||
1448 | 941 | m_mainStageApplication = nullptr; | ||
1449 | 942 | |||
1450 | 943 | application->disconnect(this); | 811 | application->disconnect(this); |
1451 | 944 | 812 | ||
1452 | 945 | int i = m_applications.indexOf(application); | 813 | int i = m_applications.indexOf(application); |
1453 | @@ -953,6 +821,11 @@ | |||
1454 | 953 | Q_EMIT emptyChanged(); | 821 | Q_EMIT emptyChanged(); |
1455 | 954 | } | 822 | } |
1456 | 955 | } | 823 | } |
1457 | 824 | |||
1458 | 825 | if (application == m_focusedApplication) { | ||
1459 | 826 | m_focusedApplication = nullptr; | ||
1460 | 827 | Q_EMIT focusedApplicationIdChanged(); | ||
1461 | 828 | } | ||
1462 | 956 | } | 829 | } |
1463 | 957 | 830 | ||
1464 | 958 | void ApplicationManager::move(int from, int to) { | 831 | void ApplicationManager::move(int from, int to) { |
1465 | 959 | 832 | ||
1466 | === modified file 'src/modules/Unity/Application/application_manager.h' | |||
1467 | --- src/modules/Unity/Application/application_manager.h 2015-03-24 23:38:33 +0000 | |||
1468 | +++ src/modules/Unity/Application/application_manager.h 2015-07-13 21:57:32 +0000 | |||
1469 | @@ -1,5 +1,5 @@ | |||
1470 | 1 | /* | 1 | /* |
1472 | 2 | * Copyright (C) 2013 Canonical, Ltd. | 2 | * Copyright (C) 2013-2015 Canonical, Ltd. |
1473 | 3 | * | 3 | * |
1474 | 4 | * This program is free software: you can redistribute it and/or modify it under | 4 | * This program is free software: you can redistribute it and/or modify it under |
1475 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | 5 | * the terms of the GNU Lesser General Public License version 3, as published by |
1476 | @@ -21,6 +21,7 @@ | |||
1477 | 21 | #include <memory> | 21 | #include <memory> |
1478 | 22 | 22 | ||
1479 | 23 | // Qt | 23 | // Qt |
1480 | 24 | #include <QJSEngine> | ||
1481 | 24 | #include <QObject> | 25 | #include <QObject> |
1482 | 25 | #include <QStringList> | 26 | #include <QStringList> |
1483 | 26 | 27 | ||
1484 | @@ -28,6 +29,7 @@ | |||
1485 | 28 | #include <unity/shell/application/ApplicationManagerInterface.h> | 29 | #include <unity/shell/application/ApplicationManagerInterface.h> |
1486 | 29 | 30 | ||
1487 | 30 | // local | 31 | // local |
1488 | 32 | #include "globals.h" | ||
1489 | 31 | #include "application.h" | 33 | #include "application.h" |
1490 | 32 | #include "desktopfilereader.h" | 34 | #include "desktopfilereader.h" |
1491 | 33 | 35 | ||
1492 | @@ -40,6 +42,7 @@ | |||
1493 | 40 | } | 42 | } |
1494 | 41 | 43 | ||
1495 | 42 | class MirServer; | 44 | class MirServer; |
1496 | 45 | class QJSValue; | ||
1497 | 43 | 46 | ||
1498 | 44 | namespace qtmir { | 47 | namespace qtmir { |
1499 | 45 | 48 | ||
1500 | @@ -63,7 +66,7 @@ | |||
1501 | 63 | class Factory | 66 | class Factory |
1502 | 64 | { | 67 | { |
1503 | 65 | public: | 68 | public: |
1505 | 66 | ApplicationManager* create(); | 69 | ApplicationManager* create(QJSEngine *jsEngine); |
1506 | 67 | }; | 70 | }; |
1507 | 68 | 71 | ||
1508 | 69 | // FIXME: these roles should be added to unity-api and removed from here | 72 | // FIXME: these roles should be added to unity-api and removed from here |
1509 | @@ -79,7 +82,7 @@ | |||
1510 | 79 | }; | 82 | }; |
1511 | 80 | Q_DECLARE_FLAGS(ExecFlags, Flag) | 83 | Q_DECLARE_FLAGS(ExecFlags, Flag) |
1512 | 81 | 84 | ||
1514 | 82 | static ApplicationManager* singleton(); | 85 | static ApplicationManager* singleton(QJSEngine *jsEngine); |
1515 | 83 | 86 | ||
1516 | 84 | explicit ApplicationManager( | 87 | explicit ApplicationManager( |
1517 | 85 | const QSharedPointer<MirServer> &mirServer, | 88 | const QSharedPointer<MirServer> &mirServer, |
1518 | @@ -88,15 +91,16 @@ | |||
1519 | 88 | const QSharedPointer<DesktopFileReader::Factory> &desktopFileReaderFactory, | 91 | const QSharedPointer<DesktopFileReader::Factory> &desktopFileReaderFactory, |
1520 | 89 | const QSharedPointer<ProcInfo> &processInfo, | 92 | const QSharedPointer<ProcInfo> &processInfo, |
1521 | 90 | const QSharedPointer<SettingsInterface> &settings, | 93 | const QSharedPointer<SettingsInterface> &settings, |
1522 | 94 | QJSEngine *jsEngine, | ||
1523 | 91 | QObject *parent = 0); | 95 | QObject *parent = 0); |
1524 | 92 | virtual ~ApplicationManager(); | 96 | virtual ~ApplicationManager(); |
1525 | 93 | 97 | ||
1526 | 94 | // ApplicationManagerInterface | 98 | // ApplicationManagerInterface |
1527 | 95 | QString focusedApplicationId() const override; | 99 | QString focusedApplicationId() const override; |
1532 | 96 | bool suspended() const override; | 100 | |
1533 | 97 | void setSuspended(bool suspended) override; | 101 | QJSValue surfaceAboutToBeCreatedCallback() const override; |
1534 | 98 | bool forceDashActive() const override; | 102 | void setSurfaceAboutToBeCreatedCallback(const QJSValue &callback) override; |
1535 | 99 | void setForceDashActive(bool forceDashActive) override; | 103 | |
1536 | 100 | Q_INVOKABLE qtmir::Application* get(int index) const override; | 104 | Q_INVOKABLE qtmir::Application* get(int index) const override; |
1537 | 101 | Q_INVOKABLE qtmir::Application* findApplication(const QString &appId) const override; | 105 | Q_INVOKABLE qtmir::Application* findApplication(const QString &appId) const override; |
1538 | 102 | Q_INVOKABLE bool requestFocusApplication(const QString &appId) override; | 106 | Q_INVOKABLE bool requestFocusApplication(const QString &appId) override; |
1539 | @@ -110,7 +114,7 @@ | |||
1540 | 110 | QVariant data(const QModelIndex & index, int role) const override; | 114 | QVariant data(const QModelIndex & index, int role) const override; |
1541 | 111 | 115 | ||
1542 | 112 | Q_INVOKABLE qtmir::Application *startApplication(const QString &appId, ExecFlags flags, | 116 | Q_INVOKABLE qtmir::Application *startApplication(const QString &appId, ExecFlags flags, |
1544 | 113 | const QStringList &arguments = QStringList()); | 117 | const QStringList &arguments = QStringList()); |
1545 | 114 | Q_INVOKABLE void move(int from, int to); | 118 | Q_INVOKABLE void move(int from, int to); |
1546 | 115 | 119 | ||
1547 | 116 | bool isEmpty() const { return rowCount() == 0; } | 120 | bool isEmpty() const { return rowCount() == 0; } |
1548 | @@ -121,20 +125,24 @@ | |||
1549 | 121 | public Q_SLOTS: | 125 | public Q_SLOTS: |
1550 | 122 | void authorizeSession(const quint64 pid, bool &authorized); | 126 | void authorizeSession(const quint64 pid, bool &authorized); |
1551 | 123 | 127 | ||
1554 | 124 | void onSessionStarting(std::shared_ptr<mir::scene::Session> const& session); | 128 | void onSessionStarting(const std::shared_ptr<mir::scene::Session> &session); |
1555 | 125 | void onSessionStopping(std::shared_ptr<mir::scene::Session> const& session); | 129 | void onSessionStopping(const std::shared_ptr<mir::scene::Session> &session); |
1556 | 126 | 130 | ||
1558 | 127 | void onSessionCreatedSurface(mir::scene::Session const*, std::shared_ptr<mir::scene::Surface> const&); | 131 | void onSessionAboutToCreateSurface(const std::shared_ptr<mir::scene::Session> &session, |
1559 | 132 | SurfaceParameters &surfaceParameters); | ||
1560 | 133 | void onSessionCreatedSurface(const mir::scene::Session *session, | ||
1561 | 134 | const std::shared_ptr<mir::scene::Surface> &surface); | ||
1562 | 128 | 135 | ||
1563 | 129 | void onProcessStarting(const QString& appId); | 136 | void onProcessStarting(const QString& appId); |
1564 | 130 | void onProcessStopped(const QString& appId); | 137 | void onProcessStopped(const QString& appId); |
1565 | 138 | void onProcessSuspended(const QString& appId); | ||
1566 | 131 | void onProcessFailed(const QString& appId, const bool duringStartup); | 139 | void onProcessFailed(const QString& appId, const bool duringStartup); |
1567 | 132 | void onFocusRequested(const QString& appId); | 140 | void onFocusRequested(const QString& appId); |
1568 | 133 | void onResumeRequested(const QString& appId); | 141 | void onResumeRequested(const QString& appId); |
1569 | 134 | 142 | ||
1570 | 135 | Q_SIGNALS: | 143 | Q_SIGNALS: |
1571 | 136 | void focusRequested(const QString &appId); | ||
1572 | 137 | void emptyChanged(); | 144 | void emptyChanged(); |
1573 | 145 | void surfaceAboutToBeCreatedCallbackChanged(); | ||
1574 | 138 | 146 | ||
1575 | 139 | private Q_SLOTS: | 147 | private Q_SLOTS: |
1576 | 140 | void onAppDataChanged(const int role); | 148 | void onAppDataChanged(const int role); |
1577 | @@ -146,9 +154,7 @@ | |||
1578 | 146 | void remove(Application* application); | 154 | void remove(Application* application); |
1579 | 147 | Application* findApplicationWithSession(const std::shared_ptr<mir::scene::Session> &session); | 155 | Application* findApplicationWithSession(const std::shared_ptr<mir::scene::Session> &session); |
1580 | 148 | Application* findApplicationWithSession(const mir::scene::Session *session); | 156 | Application* findApplicationWithSession(const mir::scene::Session *session); |
1581 | 149 | Application* applicationForStage(Application::Stage stage); | ||
1582 | 150 | QModelIndex findIndex(Application* application); | 157 | QModelIndex findIndex(Application* application); |
1583 | 151 | bool suspendApplication(Application *application); | ||
1584 | 152 | void resumeApplication(Application *application); | 158 | void resumeApplication(Application *application); |
1585 | 153 | QString toString() const; | 159 | QString toString() const; |
1586 | 154 | 160 | ||
1587 | @@ -158,19 +164,15 @@ | |||
1588 | 158 | 164 | ||
1589 | 159 | QList<Application*> m_applications; | 165 | QList<Application*> m_applications; |
1590 | 160 | Application* m_focusedApplication; | 166 | Application* m_focusedApplication; |
1591 | 161 | Application* m_mainStageApplication; | ||
1592 | 162 | Application* m_sideStageApplication; | ||
1593 | 163 | QStringList m_lifecycleExceptions; | ||
1594 | 164 | DBusWindowStack* m_dbusWindowStack; | 167 | DBusWindowStack* m_dbusWindowStack; |
1595 | 165 | QSharedPointer<TaskController> m_taskController; | 168 | QSharedPointer<TaskController> m_taskController; |
1596 | 166 | QSharedPointer<DesktopFileReader::Factory> m_desktopFileReaderFactory; | 169 | QSharedPointer<DesktopFileReader::Factory> m_desktopFileReaderFactory; |
1597 | 167 | QSharedPointer<ProcInfo> m_procInfo; | 170 | QSharedPointer<ProcInfo> m_procInfo; |
1598 | 168 | QSharedPointer<SharedWakelock> m_sharedWakelock; | 171 | QSharedPointer<SharedWakelock> m_sharedWakelock; |
1599 | 169 | QSharedPointer<SettingsInterface> m_settings; | 172 | QSharedPointer<SettingsInterface> m_settings; |
1600 | 173 | QJSValue m_surfaceAboutToBeCreatedCallback; | ||
1601 | 174 | QJSEngine *m_jsEngine; | ||
1602 | 170 | static ApplicationManager* the_application_manager; | 175 | static ApplicationManager* the_application_manager; |
1603 | 171 | QList<pid_t> m_hiddenPIDs; | ||
1604 | 172 | bool m_suspended; | ||
1605 | 173 | bool m_forceDashActive; | ||
1606 | 174 | 176 | ||
1607 | 175 | friend class Application; | 177 | friend class Application; |
1608 | 176 | friend class DBusWindowStack; | 178 | friend class DBusWindowStack; |
1609 | 177 | 179 | ||
1610 | === modified file 'src/modules/Unity/Application/applicationcontroller.h' | |||
1611 | --- src/modules/Unity/Application/applicationcontroller.h 2014-09-18 22:03:02 +0000 | |||
1612 | +++ src/modules/Unity/Application/applicationcontroller.h 2015-07-13 21:57:32 +0000 | |||
1613 | @@ -57,8 +57,9 @@ | |||
1614 | 57 | void applicationAboutToBeStarted(const QString &appId); | 57 | void applicationAboutToBeStarted(const QString &appId); |
1615 | 58 | void applicationStarted(const QString &appId); | 58 | void applicationStarted(const QString &appId); |
1616 | 59 | void applicationStopped(const QString &appId); | 59 | void applicationStopped(const QString &appId); |
1617 | 60 | void applicationPaused(const QString &appId); | ||
1618 | 60 | void applicationFocusRequest(const QString &appId); | 61 | void applicationFocusRequest(const QString &appId); |
1620 | 61 | void applicationResumeRequest(const QString &appId); | 62 | void applicationResumeRequested(const QString &appId); |
1621 | 62 | 63 | ||
1622 | 63 | void applicationError(const QString &appId, ApplicationController::Error error); | 64 | void applicationError(const QString &appId, ApplicationController::Error error); |
1623 | 64 | 65 | ||
1624 | 65 | 66 | ||
1625 | === modified file 'src/modules/Unity/Application/applicationscreenshotprovider.cpp' | |||
1626 | --- src/modules/Unity/Application/applicationscreenshotprovider.cpp 2014-09-18 09:38:41 +0000 | |||
1627 | +++ src/modules/Unity/Application/applicationscreenshotprovider.cpp 2015-07-13 21:57:32 +0000 | |||
1628 | @@ -55,7 +55,7 @@ | |||
1629 | 55 | 55 | ||
1630 | 56 | // TODO: if app not ready, return an app-provided splash image. If app has been stopped with saved state | 56 | // TODO: if app not ready, return an app-provided splash image. If app has been stopped with saved state |
1631 | 57 | // return the screenshot that was saved to disk. | 57 | // return the screenshot that was saved to disk. |
1633 | 58 | Session* session = app->session(); | 58 | SessionInterface* session = app->session(); |
1634 | 59 | if (!session || !session->session() || !session->session()->default_surface()) { | 59 | if (!session || !session->session() || !session->session()->default_surface()) { |
1635 | 60 | qWarning() << "ApplicationScreenshotProvider - app session not found - asking for screenshot too early"; | 60 | qWarning() << "ApplicationScreenshotProvider - app session not found - asking for screenshot too early"; |
1636 | 61 | return QImage(); | 61 | return QImage(); |
1637 | 62 | 62 | ||
1638 | === modified file 'src/modules/Unity/Application/mirsurfaceitem.cpp' | |||
1639 | --- src/modules/Unity/Application/mirsurfaceitem.cpp 2015-05-21 18:38:27 +0000 | |||
1640 | +++ src/modules/Unity/Application/mirsurfaceitem.cpp 2015-07-13 21:57:32 +0000 | |||
1641 | @@ -190,13 +190,13 @@ | |||
1642 | 190 | MirShell *shell, | 190 | MirShell *shell, |
1643 | 191 | std::shared_ptr<SurfaceObserver> observer, | 191 | std::shared_ptr<SurfaceObserver> observer, |
1644 | 192 | QQuickItem *parent) | 192 | QQuickItem *parent) |
1646 | 193 | : QQuickItem(parent) | 193 | : MirSurfaceItemInterface(parent) |
1647 | 194 | , m_surface(surface) | 194 | , m_surface(surface) |
1648 | 195 | , m_session(session) | 195 | , m_session(session) |
1649 | 196 | , m_shell(shell) | 196 | , m_shell(shell) |
1650 | 197 | , m_firstFrameDrawn(false) | 197 | , m_firstFrameDrawn(false) |
1651 | 198 | , m_live(true) | 198 | , m_live(true) |
1653 | 199 | , m_orientationAngle(Angle0) | 199 | , m_orientationAngle(Globals::Angle0) |
1654 | 200 | , m_textureProvider(nullptr) | 200 | , m_textureProvider(nullptr) |
1655 | 201 | , m_lastTouchEvent(nullptr) | 201 | , m_lastTouchEvent(nullptr) |
1656 | 202 | { | 202 | { |
1657 | @@ -296,22 +296,22 @@ | |||
1658 | 296 | return m_session.data(); | 296 | return m_session.data(); |
1659 | 297 | } | 297 | } |
1660 | 298 | 298 | ||
1672 | 299 | MirSurfaceItem::Type MirSurfaceItem::type() const | 299 | Globals::SurfaceType MirSurfaceItem::type() const |
1673 | 300 | { | 300 | { |
1674 | 301 | return static_cast<MirSurfaceItem::Type>(m_surface->type()); | 301 | return static_cast<Globals::SurfaceType>(m_surface->type()); |
1675 | 302 | } | 302 | } |
1676 | 303 | 303 | ||
1677 | 304 | MirSurfaceItem::State MirSurfaceItem::state() const | 304 | Globals::SurfaceState MirSurfaceItem::state() const |
1678 | 305 | { | 305 | { |
1679 | 306 | return static_cast<MirSurfaceItem::State>(m_surface->state()); | 306 | return static_cast<Globals::SurfaceState>(m_surface->state()); |
1680 | 307 | } | 307 | } |
1681 | 308 | 308 | ||
1682 | 309 | MirSurfaceItem::OrientationAngle MirSurfaceItem::orientationAngle() const | 309 | Globals::OrientationAngle MirSurfaceItem::orientationAngle() const |
1683 | 310 | { | 310 | { |
1684 | 311 | return m_orientationAngle; | 311 | return m_orientationAngle; |
1685 | 312 | } | 312 | } |
1686 | 313 | 313 | ||
1688 | 314 | void MirSurfaceItem::setOrientationAngle(MirSurfaceItem::OrientationAngle angle) | 314 | void MirSurfaceItem::setOrientationAngle(Globals::OrientationAngle angle) |
1689 | 315 | { | 315 | { |
1690 | 316 | qCDebug(QTMIR_SURFACES, "MirSurfaceItem::setOrientationAngle(%d)", angle); | 316 | qCDebug(QTMIR_SURFACES, "MirSurfaceItem::setOrientationAngle(%d)", angle); |
1691 | 317 | 317 | ||
1692 | @@ -321,16 +321,16 @@ | |||
1693 | 321 | MirOrientation mirOrientation; | 321 | MirOrientation mirOrientation; |
1694 | 322 | 322 | ||
1695 | 323 | switch (angle) { | 323 | switch (angle) { |
1697 | 324 | case Angle0: | 324 | case Globals::Angle0: |
1698 | 325 | mirOrientation = mir_orientation_normal; | 325 | mirOrientation = mir_orientation_normal; |
1699 | 326 | break; | 326 | break; |
1701 | 327 | case Angle90: | 327 | case Globals::Angle90: |
1702 | 328 | mirOrientation = mir_orientation_right; | 328 | mirOrientation = mir_orientation_right; |
1703 | 329 | break; | 329 | break; |
1705 | 330 | case Angle180: | 330 | case Globals::Angle180: |
1706 | 331 | mirOrientation = mir_orientation_inverted; | 331 | mirOrientation = mir_orientation_inverted; |
1707 | 332 | break; | 332 | break; |
1709 | 333 | case Angle270: | 333 | case Globals::Angle270: |
1710 | 334 | mirOrientation = mir_orientation_left; | 334 | mirOrientation = mir_orientation_left; |
1711 | 335 | break; | 335 | break; |
1712 | 336 | default: | 336 | default: |
1713 | @@ -375,7 +375,7 @@ | |||
1714 | 375 | { | 375 | { |
1715 | 376 | if (!m_firstFrameDrawn) { | 376 | if (!m_firstFrameDrawn) { |
1716 | 377 | m_firstFrameDrawn = true; | 377 | m_firstFrameDrawn = true; |
1718 | 378 | Q_EMIT firstFrameDrawn(this); | 378 | Q_EMIT firstFrameDrawn(); |
1719 | 379 | } | 379 | } |
1720 | 380 | 380 | ||
1721 | 381 | scheduleTextureUpdate(); | 381 | scheduleTextureUpdate(); |
1722 | @@ -456,7 +456,7 @@ | |||
1723 | 456 | 456 | ||
1724 | 457 | void MirSurfaceItem::mousePressEvent(QMouseEvent *event) | 457 | void MirSurfaceItem::mousePressEvent(QMouseEvent *event) |
1725 | 458 | { | 458 | { |
1727 | 459 | if (type() == InputMethod) { | 459 | if (type() == Globals::SurfaceType::InputMethod) { |
1728 | 460 | // FIXME: Hack to get the VKB use case working while we don't have the proper solution in place. | 460 | // FIXME: Hack to get the VKB use case working while we don't have the proper solution in place. |
1729 | 461 | if (isMouseInsideUbuntuKeyboard(event)) { | 461 | if (isMouseInsideUbuntuKeyboard(event)) { |
1730 | 462 | auto ev = makeMirEvent(event, mir_pointer_action_button_down); | 462 | auto ev = makeMirEvent(event, mir_pointer_action_button_down); |
1731 | @@ -562,7 +562,7 @@ | |||
1732 | 562 | 562 | ||
1733 | 563 | touchEvent.updateTouchPointStatesAndType(); | 563 | touchEvent.updateTouchPointStatesAndType(); |
1734 | 564 | 564 | ||
1736 | 565 | auto ev = makeMirEvent(touchEvent.modifiers, touchEvent.touchPoints, | 565 | auto ev = makeMirEvent(touchEvent.modifiers, touchEvent.touchPoints, |
1737 | 566 | touchEvent.touchPointStates, touchEvent.timestamp); | 566 | touchEvent.touchPointStates, touchEvent.timestamp); |
1738 | 567 | m_surface->consume(*ev); | 567 | m_surface->consume(*ev); |
1739 | 568 | 568 | ||
1740 | @@ -615,7 +615,7 @@ | |||
1741 | 615 | Qt::TouchPointStates touchPointStates) | 615 | Qt::TouchPointStates touchPointStates) |
1742 | 616 | { | 616 | { |
1743 | 617 | bool accepted = true; | 617 | bool accepted = true; |
1745 | 618 | if (type() == InputMethod && eventType == QEvent::TouchBegin) { | 618 | if (type() == Globals::SurfaceType::InputMethod && eventType == QEvent::TouchBegin) { |
1746 | 619 | // FIXME: Hack to get the VKB use case working while we don't have the proper solution in place. | 619 | // FIXME: Hack to get the VKB use case working while we don't have the proper solution in place. |
1747 | 620 | if (hasTouchInsideUbuntuKeyboard(touchPoints)) { | 620 | if (hasTouchInsideUbuntuKeyboard(touchPoints)) { |
1748 | 621 | validateAndDeliverTouchEvent(eventType, timestamp, mods, touchPoints, touchPointStates); | 621 | validateAndDeliverTouchEvent(eventType, timestamp, mods, touchPoints, touchPointStates); |
1749 | @@ -659,21 +659,21 @@ | |||
1750 | 659 | && pos.y() <= (ubuntuKeyboardInfo->y() + ubuntuKeyboardInfo->height()); | 659 | && pos.y() <= (ubuntuKeyboardInfo->y() + ubuntuKeyboardInfo->height()); |
1751 | 660 | } | 660 | } |
1752 | 661 | 661 | ||
1754 | 662 | void MirSurfaceItem::setType(const Type &type) | 662 | void MirSurfaceItem::setType(const Globals::SurfaceType &type) |
1755 | 663 | { | 663 | { |
1756 | 664 | if (this->type() != type) { | 664 | if (this->type() != type) { |
1757 | 665 | m_shell->set_surface_attribute(m_session->session(), m_surface, mir_surface_attrib_type, static_cast<int>(type)); | 665 | m_shell->set_surface_attribute(m_session->session(), m_surface, mir_surface_attrib_type, static_cast<int>(type)); |
1758 | 666 | } | 666 | } |
1759 | 667 | } | 667 | } |
1760 | 668 | 668 | ||
1762 | 669 | void MirSurfaceItem::setState(const State &state) | 669 | void MirSurfaceItem::setState(const Globals::SurfaceState &state) |
1763 | 670 | { | 670 | { |
1764 | 671 | if (this->state() != state) { | 671 | if (this->state() != state) { |
1765 | 672 | m_shell->set_surface_attribute(m_session->session(), m_surface, mir_surface_attrib_state, static_cast<int>(state)); | 672 | m_shell->set_surface_attribute(m_session->session(), m_surface, mir_surface_attrib_state, static_cast<int>(state)); |
1766 | 673 | } | 673 | } |
1767 | 674 | } | 674 | } |
1768 | 675 | 675 | ||
1770 | 676 | void MirSurfaceItem::setLive(const bool live) | 676 | void MirSurfaceItem::setLive(bool live) |
1771 | 677 | { | 677 | { |
1772 | 678 | if (m_live != live) { | 678 | if (m_live != live) { |
1773 | 679 | m_live = live; | 679 | m_live = live; |
1774 | 680 | 680 | ||
1775 | === modified file 'src/modules/Unity/Application/mirsurfaceitem.h' | |||
1776 | --- src/modules/Unity/Application/mirsurfaceitem.h 2015-05-13 17:18:45 +0000 | |||
1777 | +++ src/modules/Unity/Application/mirsurfaceitem.h 2015-07-13 21:57:32 +0000 | |||
1778 | @@ -22,15 +22,13 @@ | |||
1779 | 22 | // Qt | 22 | // Qt |
1780 | 23 | #include <QMutex> | 23 | #include <QMutex> |
1781 | 24 | #include <QPointer> | 24 | #include <QPointer> |
1782 | 25 | #include <QSet> | ||
1783 | 26 | #include <QQuickItem> | ||
1784 | 27 | #include <QTimer> | 25 | #include <QTimer> |
1785 | 28 | #include <QQmlListProperty> | 26 | #include <QQmlListProperty> |
1786 | 29 | 27 | ||
1787 | 30 | // mir | 28 | // mir |
1788 | 31 | #include <mir/scene/surface.h> | 29 | #include <mir/scene/surface.h> |
1789 | 32 | #include <mir_toolkit/common.h> | ||
1790 | 33 | 30 | ||
1791 | 31 | #include "mirsurfaceiteminterface.h" | ||
1792 | 34 | #include "session_interface.h" | 32 | #include "session_interface.h" |
1793 | 35 | 33 | ||
1794 | 36 | class SurfaceObserver; | 34 | class SurfaceObserver; |
1795 | @@ -41,24 +39,10 @@ | |||
1796 | 41 | class MirSurfaceManager; | 39 | class MirSurfaceManager; |
1797 | 42 | class QSGMirSurfaceNode; | 40 | class QSGMirSurfaceNode; |
1798 | 43 | class QMirSurfaceTextureProvider; | 41 | class QMirSurfaceTextureProvider; |
1799 | 44 | class Application; | ||
1800 | 45 | 42 | ||
1802 | 46 | class MirSurfaceItem : public QQuickItem | 43 | class MirSurfaceItem : public MirSurfaceItemInterface |
1803 | 47 | { | 44 | { |
1804 | 48 | Q_OBJECT | 45 | Q_OBJECT |
1805 | 49 | Q_ENUMS(Type) | ||
1806 | 50 | Q_ENUMS(State) | ||
1807 | 51 | Q_ENUMS(OrientationAngle) | ||
1808 | 52 | |||
1809 | 53 | Q_PROPERTY(Type type READ type NOTIFY typeChanged) | ||
1810 | 54 | Q_PROPERTY(State state READ state NOTIFY stateChanged) | ||
1811 | 55 | Q_PROPERTY(QString name READ name NOTIFY nameChanged) | ||
1812 | 56 | Q_PROPERTY(bool live READ live NOTIFY liveChanged) | ||
1813 | 57 | |||
1814 | 58 | // How many degrees, clockwise, the UI in the surface has to rotate to match with the | ||
1815 | 59 | // shell UI orientation | ||
1816 | 60 | Q_PROPERTY(OrientationAngle orientationAngle READ orientationAngle WRITE setOrientationAngle | ||
1817 | 61 | NOTIFY orientationAngleChanged DESIGNABLE false) | ||
1818 | 62 | 46 | ||
1819 | 63 | public: | 47 | public: |
1820 | 64 | explicit MirSurfaceItem(std::shared_ptr<mir::scene::Surface> surface, | 48 | explicit MirSurfaceItem(std::shared_ptr<mir::scene::Surface> surface, |
1821 | @@ -66,57 +50,29 @@ | |||
1822 | 66 | MirShell *shell, | 50 | MirShell *shell, |
1823 | 67 | std::shared_ptr<SurfaceObserver> observer, | 51 | std::shared_ptr<SurfaceObserver> observer, |
1824 | 68 | QQuickItem *parent = 0); | 52 | QQuickItem *parent = 0); |
1853 | 69 | ~MirSurfaceItem(); | 53 | virtual ~MirSurfaceItem(); |
1826 | 70 | |||
1827 | 71 | enum Type { | ||
1828 | 72 | Normal = mir_surface_type_normal, | ||
1829 | 73 | Utility = mir_surface_type_utility, | ||
1830 | 74 | Dialog = mir_surface_type_dialog, | ||
1831 | 75 | Overlay = mir_surface_type_overlay, | ||
1832 | 76 | Freestyle = mir_surface_type_freestyle, | ||
1833 | 77 | Popover = mir_surface_type_popover, | ||
1834 | 78 | InputMethod = mir_surface_type_inputmethod, | ||
1835 | 79 | }; | ||
1836 | 80 | |||
1837 | 81 | enum State { | ||
1838 | 82 | Unknown = mir_surface_state_unknown, | ||
1839 | 83 | Restored = mir_surface_state_restored, | ||
1840 | 84 | Minimized = mir_surface_state_minimized, | ||
1841 | 85 | Maximized = mir_surface_state_maximized, | ||
1842 | 86 | VertMaximized = mir_surface_state_vertmaximized, | ||
1843 | 87 | /* SemiMaximized = mir_surface_state_semimaximized, // see mircommon/mir_toolbox/common.h*/ | ||
1844 | 88 | Fullscreen = mir_surface_state_fullscreen, | ||
1845 | 89 | }; | ||
1846 | 90 | |||
1847 | 91 | enum OrientationAngle { | ||
1848 | 92 | Angle0 = 0, | ||
1849 | 93 | Angle90 = 90, | ||
1850 | 94 | Angle180 = 180, | ||
1851 | 95 | Angle270 = 270 | ||
1852 | 96 | }; | ||
1854 | 97 | 54 | ||
1855 | 98 | //getters | 55 | //getters |
1861 | 99 | Type type() const; | 56 | Globals::SurfaceType type() const override; |
1862 | 100 | State state() const; | 57 | Globals::SurfaceState state() const override; |
1863 | 101 | QString name() const; | 58 | QString name() const override; |
1864 | 102 | bool live() const; | 59 | bool live() const override; |
1865 | 103 | SessionInterface *session() const; | 60 | SessionInterface *session() const override; |
1866 | 61 | Globals::OrientationAngle orientationAngle() const override; | ||
1867 | 104 | 62 | ||
1869 | 105 | Q_INVOKABLE void release(); | 63 | Q_INVOKABLE void release() override; |
1870 | 106 | 64 | ||
1871 | 107 | // Item surface/texture management | 65 | // Item surface/texture management |
1872 | 108 | bool isTextureProvider() const { return true; } | 66 | bool isTextureProvider() const { return true; } |
1873 | 109 | QSGTextureProvider *textureProvider() const; | 67 | QSGTextureProvider *textureProvider() const; |
1874 | 110 | 68 | ||
1884 | 111 | void stopFrameDropper(); | 69 | void stopFrameDropper() override; |
1885 | 112 | void startFrameDropper(); | 70 | void startFrameDropper() override; |
1886 | 113 | 71 | ||
1887 | 114 | bool isFirstFrameDrawn() const { return m_firstFrameDrawn; } | 72 | bool isFirstFrameDrawn() const override { return m_firstFrameDrawn; } |
1888 | 115 | 73 | ||
1889 | 116 | OrientationAngle orientationAngle() const; | 74 | void setOrientationAngle(Globals::OrientationAngle angle) override; |
1890 | 117 | void setOrientationAngle(OrientationAngle angle); | 75 | void setSession(SessionInterface *app) override; |
1882 | 118 | |||
1883 | 119 | void setSession(SessionInterface *app); | ||
1891 | 120 | 76 | ||
1892 | 121 | // to allow easy touch event injection from tests | 77 | // to allow easy touch event injection from tests |
1893 | 122 | bool processTouchEvent(int eventType, | 78 | bool processTouchEvent(int eventType, |
1894 | @@ -125,14 +81,6 @@ | |||
1895 | 125 | const QList<QTouchEvent::TouchPoint> &touchPoints, | 81 | const QList<QTouchEvent::TouchPoint> &touchPoints, |
1896 | 126 | Qt::TouchPointStates touchPointStates); | 82 | Qt::TouchPointStates touchPointStates); |
1897 | 127 | 83 | ||
1898 | 128 | Q_SIGNALS: | ||
1899 | 129 | void typeChanged(); | ||
1900 | 130 | void stateChanged(); | ||
1901 | 131 | void nameChanged(); | ||
1902 | 132 | void orientationAngleChanged(OrientationAngle angle); | ||
1903 | 133 | void liveChanged(bool live); | ||
1904 | 134 | void firstFrameDrawn(MirSurfaceItem *item); | ||
1905 | 135 | |||
1906 | 136 | protected Q_SLOTS: | 84 | protected Q_SLOTS: |
1907 | 137 | void onSessionStateChanged(SessionInterface::State state); | 85 | void onSessionStateChanged(SessionInterface::State state); |
1908 | 138 | 86 | ||
1909 | @@ -167,9 +115,9 @@ | |||
1910 | 167 | bool updateTexture(); | 115 | bool updateTexture(); |
1911 | 168 | void ensureProvider(); | 116 | void ensureProvider(); |
1912 | 169 | 117 | ||
1916 | 170 | void setType(const Type&); | 118 | void setType(const Globals::SurfaceType&); |
1917 | 171 | void setState(const State&); | 119 | void setState(const Globals::SurfaceState&); |
1918 | 172 | void setLive(const bool); | 120 | void setLive(bool) override; |
1919 | 173 | 121 | ||
1920 | 174 | // called by MirSurfaceManager | 122 | // called by MirSurfaceManager |
1921 | 175 | void setSurfaceValid(const bool); | 123 | void setSurfaceValid(const bool); |
1922 | @@ -197,7 +145,7 @@ | |||
1923 | 197 | bool m_live; | 145 | bool m_live; |
1924 | 198 | 146 | ||
1925 | 199 | //FIXME - have to save the state as Mir has no getter for it (bug:1357429) | 147 | //FIXME - have to save the state as Mir has no getter for it (bug:1357429) |
1927 | 200 | OrientationAngle m_orientationAngle; | 148 | Globals::OrientationAngle m_orientationAngle; |
1928 | 201 | 149 | ||
1929 | 202 | QMirSurfaceTextureProvider *m_textureProvider; | 150 | QMirSurfaceTextureProvider *m_textureProvider; |
1930 | 203 | 151 | ||
1931 | @@ -226,13 +174,8 @@ | |||
1932 | 226 | QList<QTouchEvent::TouchPoint> touchPoints; | 174 | QList<QTouchEvent::TouchPoint> touchPoints; |
1933 | 227 | Qt::TouchPointStates touchPointStates; | 175 | Qt::TouchPointStates touchPointStates; |
1934 | 228 | } *m_lastTouchEvent; | 176 | } *m_lastTouchEvent; |
1935 | 229 | |||
1936 | 230 | friend class MirSurfaceManager; | ||
1937 | 231 | }; | 177 | }; |
1938 | 232 | 178 | ||
1939 | 233 | } // namespace qtmir | 179 | } // namespace qtmir |
1940 | 234 | 180 | ||
1941 | 235 | Q_DECLARE_METATYPE(qtmir::MirSurfaceItem*) | ||
1942 | 236 | Q_DECLARE_METATYPE(qtmir::MirSurfaceItem::OrientationAngle) | ||
1943 | 237 | |||
1944 | 238 | #endif // MIRSURFACEITEM_H | 181 | #endif // MIRSURFACEITEM_H |
1945 | 239 | 182 | ||
1946 | === added file 'src/modules/Unity/Application/mirsurfaceiteminterface.h' | |||
1947 | --- src/modules/Unity/Application/mirsurfaceiteminterface.h 1970-01-01 00:00:00 +0000 | |||
1948 | +++ src/modules/Unity/Application/mirsurfaceiteminterface.h 2015-07-13 21:57:32 +0000 | |||
1949 | @@ -0,0 +1,89 @@ | |||
1950 | 1 | /* | ||
1951 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
1952 | 3 | * | ||
1953 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
1954 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
1955 | 6 | * the Free Software Foundation. | ||
1956 | 7 | * | ||
1957 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
1958 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
1959 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
1960 | 11 | * Lesser General Public License for more details. | ||
1961 | 12 | * | ||
1962 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1963 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1964 | 15 | */ | ||
1965 | 16 | |||
1966 | 17 | #ifndef MIRSURFACEITEMINTERFACE_H | ||
1967 | 18 | #define MIRSURFACEITEMINTERFACE_H | ||
1968 | 19 | |||
1969 | 20 | // Qt | ||
1970 | 21 | #include <QQuickItem> | ||
1971 | 22 | |||
1972 | 23 | // mir | ||
1973 | 24 | #include <mir_toolkit/common.h> | ||
1974 | 25 | |||
1975 | 26 | #include "session_interface.h" | ||
1976 | 27 | #include "globals.h" | ||
1977 | 28 | |||
1978 | 29 | namespace qtmir { | ||
1979 | 30 | |||
1980 | 31 | class MirSurfaceItemInterface : public QQuickItem | ||
1981 | 32 | { | ||
1982 | 33 | Q_OBJECT | ||
1983 | 34 | Q_ENUMS(Type) | ||
1984 | 35 | Q_ENUMS(State) | ||
1985 | 36 | Q_ENUMS(OrientationAngle) | ||
1986 | 37 | |||
1987 | 38 | Q_PROPERTY(qtmir::Globals::SurfaceType type READ type NOTIFY typeChanged) | ||
1988 | 39 | Q_PROPERTY(qtmir::Globals::SurfaceState state READ state NOTIFY stateChanged) | ||
1989 | 40 | Q_PROPERTY(QString name READ name NOTIFY nameChanged) | ||
1990 | 41 | Q_PROPERTY(bool live READ live NOTIFY liveChanged) | ||
1991 | 42 | |||
1992 | 43 | // How many degrees, clockwise, the UI in the surface has to rotate to match with the | ||
1993 | 44 | // shell UI orientation | ||
1994 | 45 | Q_PROPERTY(qtmir::Globals::OrientationAngle orientationAngle READ orientationAngle WRITE setOrientationAngle | ||
1995 | 46 | NOTIFY orientationAngleChanged DESIGNABLE false) | ||
1996 | 47 | |||
1997 | 48 | public: | ||
1998 | 49 | MirSurfaceItemInterface(QQuickItem *parent) : QQuickItem(parent) {} | ||
1999 | 50 | virtual ~MirSurfaceItemInterface() {} | ||
2000 | 51 | |||
2001 | 52 | //getters | ||
2002 | 53 | virtual Globals::SurfaceType type() const = 0; | ||
2003 | 54 | virtual Globals::SurfaceState state() const = 0; | ||
2004 | 55 | virtual QString name() const = 0; | ||
2005 | 56 | virtual bool live() const = 0; | ||
2006 | 57 | virtual SessionInterface *session() const = 0; | ||
2007 | 58 | virtual Globals::OrientationAngle orientationAngle() const = 0; | ||
2008 | 59 | |||
2009 | 60 | virtual Q_INVOKABLE void release() = 0; | ||
2010 | 61 | |||
2011 | 62 | virtual void stopFrameDropper() = 0; | ||
2012 | 63 | virtual void startFrameDropper() = 0; | ||
2013 | 64 | |||
2014 | 65 | virtual bool isFirstFrameDrawn() const = 0; | ||
2015 | 66 | |||
2016 | 67 | virtual void setOrientationAngle(Globals::OrientationAngle angle) = 0; | ||
2017 | 68 | virtual void setSession(SessionInterface *app) = 0; | ||
2018 | 69 | |||
2019 | 70 | Q_SIGNALS: | ||
2020 | 71 | void typeChanged(); | ||
2021 | 72 | void stateChanged(); | ||
2022 | 73 | void nameChanged(); | ||
2023 | 74 | void orientationAngleChanged(Globals::OrientationAngle angle); | ||
2024 | 75 | void liveChanged(bool live); | ||
2025 | 76 | void firstFrameDrawn(); | ||
2026 | 77 | |||
2027 | 78 | private: | ||
2028 | 79 | virtual void setLive(bool) = 0; | ||
2029 | 80 | |||
2030 | 81 | friend class MirSurfaceManager; | ||
2031 | 82 | }; | ||
2032 | 83 | |||
2033 | 84 | } // namespace qtmir | ||
2034 | 85 | |||
2035 | 86 | Q_DECLARE_METATYPE(qtmir::MirSurfaceItemInterface*) | ||
2036 | 87 | |||
2037 | 88 | #endif // MIRSURFACEITEMINTERFACE_H | ||
2038 | 89 | |||
2039 | 0 | 90 | ||
2040 | === modified file 'src/modules/Unity/Application/mirsurfaceitemmodel.h' | |||
2041 | --- src/modules/Unity/Application/mirsurfaceitemmodel.h 2014-08-29 11:15:51 +0000 | |||
2042 | +++ src/modules/Unity/Application/mirsurfaceitemmodel.h 2015-07-13 21:57:32 +0000 | |||
2043 | @@ -22,8 +22,8 @@ | |||
2044 | 22 | 22 | ||
2045 | 23 | namespace qtmir { | 23 | namespace qtmir { |
2046 | 24 | 24 | ||
2049 | 25 | class MirSurfaceItem; | 25 | class MirSurfaceItemInterface; |
2050 | 26 | typedef ObjectListModel<MirSurfaceItem> MirSurfaceItemModel; | 26 | typedef ObjectListModel<MirSurfaceItemInterface> MirSurfaceItemModel; |
2051 | 27 | 27 | ||
2052 | 28 | } // namespace qtmir | 28 | } // namespace qtmir |
2053 | 29 | 29 | ||
2054 | 30 | 30 | ||
2055 | === modified file 'src/modules/Unity/Application/mirsurfacemanager.cpp' | |||
2056 | --- src/modules/Unity/Application/mirsurfacemanager.cpp 2015-03-11 10:10:49 +0000 | |||
2057 | +++ src/modules/Unity/Application/mirsurfacemanager.cpp 2015-07-13 21:57:32 +0000 | |||
2058 | @@ -51,7 +51,7 @@ | |||
2059 | 51 | manager, &MirSurfaceManager::onSessionDestroyingSurface); | 51 | manager, &MirSurfaceManager::onSessionDestroyingSurface); |
2060 | 52 | } | 52 | } |
2061 | 53 | 53 | ||
2063 | 54 | MirSurfaceManager* MirSurfaceManager::singleton() | 54 | MirSurfaceManager* MirSurfaceManager::singleton(QJSEngine *jsEngine) |
2064 | 55 | { | 55 | { |
2065 | 56 | if (!the_surface_manager) { | 56 | if (!the_surface_manager) { |
2066 | 57 | 57 | ||
2067 | @@ -66,7 +66,7 @@ | |||
2068 | 66 | SessionListener *sessionListener = static_cast<SessionListener*>(nativeInterface->nativeResourceForIntegration("SessionListener")); | 66 | SessionListener *sessionListener = static_cast<SessionListener*>(nativeInterface->nativeResourceForIntegration("SessionListener")); |
2069 | 67 | MirShell *shell = static_cast<MirShell*>(nativeInterface->nativeResourceForIntegration("Shell")); | 67 | MirShell *shell = static_cast<MirShell*>(nativeInterface->nativeResourceForIntegration("Shell")); |
2070 | 68 | 68 | ||
2072 | 69 | the_surface_manager = new MirSurfaceManager(nativeInterface->m_mirServer, shell, SessionManager::singleton()); | 69 | the_surface_manager = new MirSurfaceManager(nativeInterface->m_mirServer, shell, SessionManager::singleton(jsEngine)); |
2073 | 70 | 70 | ||
2074 | 71 | connectToSessionListener(the_surface_manager, sessionListener); | 71 | connectToSessionListener(the_surface_manager, sessionListener); |
2075 | 72 | } | 72 | } |
2076 | @@ -112,11 +112,11 @@ | |||
2077 | 112 | session->setSurface(qmlSurface); | 112 | session->setSurface(qmlSurface); |
2078 | 113 | 113 | ||
2079 | 114 | // Only notify QML of surface creation once it has drawn its first frame. | 114 | // Only notify QML of surface creation once it has drawn its first frame. |
2081 | 115 | connect(qmlSurface, &MirSurfaceItem::firstFrameDrawn, this, [&](MirSurfaceItem *item) { | 115 | connect(qmlSurface, &MirSurfaceItemInterface::firstFrameDrawn, this, [=]() { |
2082 | 116 | tracepoint(qtmir, firstFrameDrawn); | 116 | tracepoint(qtmir, firstFrameDrawn); |
2084 | 117 | Q_EMIT surfaceCreated(item); | 117 | Q_EMIT surfaceCreated(qmlSurface); |
2085 | 118 | 118 | ||
2087 | 119 | insert(0, item); | 119 | insert(0, qmlSurface); |
2088 | 120 | }); | 120 | }); |
2089 | 121 | 121 | ||
2090 | 122 | // clean up after MirSurfaceItem is destroyed | 122 | // clean up after MirSurfaceItem is destroyed |
2091 | @@ -139,7 +139,7 @@ | |||
2092 | 139 | qCDebug(QTMIR_SURFACES) << "MirSurfaceManager::onSessionDestroyingSurface - session=" << session | 139 | qCDebug(QTMIR_SURFACES) << "MirSurfaceManager::onSessionDestroyingSurface - session=" << session |
2093 | 140 | << "surface=" << surface.get() << "surface.name=" << surface->name().c_str(); | 140 | << "surface=" << surface.get() << "surface.name=" << surface->name().c_str(); |
2094 | 141 | 141 | ||
2096 | 142 | MirSurfaceItem* item = nullptr; | 142 | MirSurfaceItemInterface* item = nullptr; |
2097 | 143 | { | 143 | { |
2098 | 144 | QMutexLocker lock(&m_mutex); | 144 | QMutexLocker lock(&m_mutex); |
2099 | 145 | auto it = m_mirSurfaceToItemHash.find(surface.get()); | 145 | auto it = m_mirSurfaceToItemHash.find(surface.get()); |
2100 | 146 | 146 | ||
2101 | === modified file 'src/modules/Unity/Application/mirsurfacemanager.h' | |||
2102 | --- src/modules/Unity/Application/mirsurfacemanager.h 2015-03-11 10:10:49 +0000 | |||
2103 | +++ src/modules/Unity/Application/mirsurfacemanager.h 2015-07-13 21:57:32 +0000 | |||
2104 | @@ -61,11 +61,11 @@ | |||
2105 | 61 | ); | 61 | ); |
2106 | 62 | ~MirSurfaceManager(); | 62 | ~MirSurfaceManager(); |
2107 | 63 | 63 | ||
2109 | 64 | static MirSurfaceManager* singleton(); | 64 | static MirSurfaceManager* singleton(QJSEngine *jsEngine); |
2110 | 65 | 65 | ||
2111 | 66 | Q_SIGNALS: | 66 | Q_SIGNALS: |
2114 | 67 | void surfaceCreated(MirSurfaceItem* surface); | 67 | void surfaceCreated(MirSurfaceItemInterface* surface); |
2115 | 68 | void surfaceDestroyed(MirSurfaceItem* surface); | 68 | void surfaceDestroyed(MirSurfaceItemInterface* surface); |
2116 | 69 | // void surfaceResized(MirSurface*); | 69 | // void surfaceResized(MirSurface*); |
2117 | 70 | // void fullscreenSurfaceChanged(); | 70 | // void fullscreenSurfaceChanged(); |
2118 | 71 | 71 | ||
2119 | @@ -74,7 +74,7 @@ | |||
2120 | 74 | void onSessionDestroyingSurface(const mir::scene::Session *, const std::shared_ptr<mir::scene::Surface> &); | 74 | void onSessionDestroyingSurface(const mir::scene::Session *, const std::shared_ptr<mir::scene::Surface> &); |
2121 | 75 | 75 | ||
2122 | 76 | protected: | 76 | protected: |
2124 | 77 | QHash<const mir::scene::Surface *, MirSurfaceItem *> m_mirSurfaceToItemHash; | 77 | QHash<const mir::scene::Surface *, MirSurfaceItemInterface *> m_mirSurfaceToItemHash; |
2125 | 78 | QMutex m_mutex; | 78 | QMutex m_mutex; |
2126 | 79 | 79 | ||
2127 | 80 | private: | 80 | private: |
2128 | 81 | 81 | ||
2129 | === modified file 'src/modules/Unity/Application/plugin.cpp' | |||
2130 | --- src/modules/Unity/Application/plugin.cpp 2015-02-05 10:28:31 +0000 | |||
2131 | +++ src/modules/Unity/Application/plugin.cpp 2015-07-13 21:57:32 +0000 | |||
2132 | @@ -28,41 +28,36 @@ | |||
2133 | 28 | 28 | ||
2134 | 29 | // qtmir | 29 | // qtmir |
2135 | 30 | #include "logging.h" | 30 | #include "logging.h" |
2160 | 31 | 31 | #include "globals.h" | |
2137 | 32 | using namespace qtmir; | ||
2138 | 33 | |||
2139 | 34 | static QObject* applicationManagerSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) { | ||
2140 | 35 | Q_UNUSED(engine); | ||
2141 | 36 | Q_UNUSED(scriptEngine); | ||
2142 | 37 | qCDebug(QTMIR_APPLICATIONS) << "applicationManagerSingleton - engine=" << engine << "scriptEngine=" << scriptEngine; | ||
2143 | 38 | |||
2144 | 39 | return qtmir::ApplicationManager::singleton(); | ||
2145 | 40 | } | ||
2146 | 41 | |||
2147 | 42 | static QObject* surfaceManagerSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) { | ||
2148 | 43 | Q_UNUSED(engine); | ||
2149 | 44 | Q_UNUSED(scriptEngine); | ||
2150 | 45 | qCDebug(QTMIR_APPLICATIONS) << "surfaceManagerSingleton - engine=" << engine << "scriptEngine=" << scriptEngine; | ||
2151 | 46 | |||
2152 | 47 | return qtmir::MirSurfaceManager::singleton(); | ||
2153 | 48 | } | ||
2154 | 49 | |||
2155 | 50 | static QObject* sessionManagerSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) { | ||
2156 | 51 | Q_UNUSED(engine); | ||
2157 | 52 | Q_UNUSED(scriptEngine); | ||
2158 | 53 | return qtmir::SessionManager::singleton(); | ||
2159 | 54 | } | ||
2161 | 55 | 32 | ||
2162 | 56 | namespace { | 33 | namespace { |
2166 | 57 | QObject* ubuntuKeyboardInfoSingleton(QQmlEngine* /*engine*/, QJSEngine* /*scriptEngine*/) { | 34 | |
2167 | 58 | if (!UbuntuKeyboardInfo::instance()) { | 35 | QObject* applicationManagerSingleton(QQmlEngine* /*engine*/, QJSEngine* jsEngine) |
2168 | 59 | new UbuntuKeyboardInfo; | 36 | { |
2169 | 37 | return qtmir::ApplicationManager::singleton(jsEngine); | ||
2170 | 38 | } | ||
2171 | 39 | |||
2172 | 40 | QObject* surfaceManagerSingleton(QQmlEngine* /*engine*/, QJSEngine* jsEngine) | ||
2173 | 41 | { | ||
2174 | 42 | return qtmir::MirSurfaceManager::singleton(jsEngine); | ||
2175 | 43 | } | ||
2176 | 44 | |||
2177 | 45 | QObject* sessionManagerSingleton(QQmlEngine* /*engine*/, QJSEngine* jsEngine) | ||
2178 | 46 | { | ||
2179 | 47 | return qtmir::SessionManager::singleton(jsEngine); | ||
2180 | 48 | } | ||
2181 | 49 | |||
2182 | 50 | QObject* ubuntuKeyboardInfoSingleton(QQmlEngine* /*engine*/, QJSEngine* /*scriptEngine*/) | ||
2183 | 51 | { | ||
2184 | 52 | if (!qtmir::UbuntuKeyboardInfo::instance()) { | ||
2185 | 53 | new qtmir::UbuntuKeyboardInfo; | ||
2186 | 60 | } | 54 | } |
2188 | 61 | return UbuntuKeyboardInfo::instance(); | 55 | return qtmir::UbuntuKeyboardInfo::instance(); |
2189 | 62 | } | 56 | } |
2190 | 63 | } // anonymous namespace | 57 | } // anonymous namespace |
2191 | 64 | 58 | ||
2193 | 65 | class UnityApplicationPlugin : public QQmlExtensionPlugin { | 59 | class UnityApplicationPlugin : public QQmlExtensionPlugin |
2194 | 60 | { | ||
2195 | 66 | Q_OBJECT | 61 | Q_OBJECT |
2196 | 67 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") | 62 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") |
2197 | 68 | 63 | ||
2198 | @@ -71,9 +66,12 @@ | |||
2199 | 71 | qCDebug(QTMIR_APPLICATIONS) << "UnityApplicationPlugin::registerTypes - this=" << this << "uri=" << uri; | 66 | qCDebug(QTMIR_APPLICATIONS) << "UnityApplicationPlugin::registerTypes - this=" << this << "uri=" << uri; |
2200 | 72 | Q_ASSERT(QLatin1String(uri) == QLatin1String("Unity.Application")); | 67 | Q_ASSERT(QLatin1String(uri) == QLatin1String("Unity.Application")); |
2201 | 73 | 68 | ||
2202 | 69 | qmlRegisterUncreatableType<qtmir::Globals>( | ||
2203 | 70 | uri, 0, 1, "QtMir", "QtMir provides enum values, it can't be instantiated"); | ||
2204 | 71 | |||
2205 | 74 | qRegisterMetaType<qtmir::ApplicationManager*>("ApplicationManager*"); //need for queueing signals | 72 | qRegisterMetaType<qtmir::ApplicationManager*>("ApplicationManager*"); //need for queueing signals |
2206 | 75 | qRegisterMetaType<qtmir::Application*>("Application*"); | 73 | qRegisterMetaType<qtmir::Application*>("Application*"); |
2208 | 76 | qRegisterMetaType<qtmir::MirSurfaceItem*>("MirSurfaceItem*"); | 74 | qRegisterMetaType<qtmir::MirSurfaceItemInterface*>("MirSurfaceItemInterface*"); |
2209 | 77 | qRegisterMetaType<qtmir::MirSurfaceItemModel*>("MirSurfaceItemModel*"); | 75 | qRegisterMetaType<qtmir::MirSurfaceItemModel*>("MirSurfaceItemModel*"); |
2210 | 78 | qRegisterMetaType<qtmir::Session*>("Session*"); | 76 | qRegisterMetaType<qtmir::Session*>("Session*"); |
2211 | 79 | qRegisterMetaType<qtmir::SessionInterface*>("SessionInterface*"); | 77 | qRegisterMetaType<qtmir::SessionInterface*>("SessionInterface*"); |
2212 | @@ -92,7 +90,7 @@ | |||
2213 | 92 | uri, 0, 1, "SurfaceManager", surfaceManagerSingleton); | 90 | uri, 0, 1, "SurfaceManager", surfaceManagerSingleton); |
2214 | 93 | qmlRegisterSingletonType<qtmir::SessionManager>( | 91 | qmlRegisterSingletonType<qtmir::SessionManager>( |
2215 | 94 | uri, 0, 1, "SessionManager", sessionManagerSingleton); | 92 | uri, 0, 1, "SessionManager", sessionManagerSingleton); |
2217 | 95 | qmlRegisterUncreatableType<qtmir::MirSurfaceItem>( | 93 | qmlRegisterUncreatableType<qtmir::MirSurfaceItemInterface>( |
2218 | 96 | uri, 0, 1, "MirSurfaceItem", "MirSurfaceItem can't be instantiated from QML"); | 94 | uri, 0, 1, "MirSurfaceItem", "MirSurfaceItem can't be instantiated from QML"); |
2219 | 97 | qmlRegisterUncreatableType<qtmir::Session>( | 95 | qmlRegisterUncreatableType<qtmir::Session>( |
2220 | 98 | uri, 0, 1, "Session", "Session can't be instantiated from QML"); | 96 | uri, 0, 1, "Session", "Session can't be instantiated from QML"); |
2221 | @@ -105,7 +103,7 @@ | |||
2222 | 105 | QQmlExtensionPlugin::initializeEngine(engine, uri); | 103 | QQmlExtensionPlugin::initializeEngine(engine, uri); |
2223 | 106 | 104 | ||
2224 | 107 | qtmir::ApplicationManager* appManager | 105 | qtmir::ApplicationManager* appManager |
2226 | 108 | = static_cast<qtmir::ApplicationManager*>(applicationManagerSingleton(engine, nullptr)); | 106 | = static_cast<qtmir::ApplicationManager*>(applicationManagerSingleton(engine, engine)); |
2227 | 109 | engine->addImageProvider(QLatin1String("application"), new qtmir::ApplicationScreenshotProvider(appManager)); | 107 | engine->addImageProvider(QLatin1String("application"), new qtmir::ApplicationScreenshotProvider(appManager)); |
2228 | 110 | } | 108 | } |
2229 | 111 | }; | 109 | }; |
2230 | 112 | 110 | ||
2231 | === modified file 'src/modules/Unity/Application/session.cpp' | |||
2232 | --- src/modules/Unity/Application/session.cpp 2015-01-15 15:19:26 +0000 | |||
2233 | +++ src/modules/Unity/Application/session.cpp 2015-07-13 21:57:32 +0000 | |||
2234 | @@ -1,5 +1,5 @@ | |||
2235 | 1 | /* | 1 | /* |
2237 | 2 | * Copyright (C) 2014 Canonical, Ltd. | 2 | * Copyright (C) 2014,2015 Canonical, Ltd. |
2238 | 3 | * | 3 | * |
2239 | 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 |
2240 | 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 |
2241 | @@ -60,14 +60,7 @@ | |||
2242 | 60 | QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); | 60 | QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); |
2243 | 61 | 61 | ||
2244 | 62 | m_suspendTimer->setSingleShot(true); | 62 | m_suspendTimer->setSingleShot(true); |
2253 | 63 | connect(m_suspendTimer, &QTimer::timeout, this, [this]() { | 63 | connect(m_suspendTimer, &QTimer::timeout, this, &Session::doSuspend); |
2246 | 64 | if (m_surface) { | ||
2247 | 65 | m_surface->stopFrameDropper(); | ||
2248 | 66 | } else { | ||
2249 | 67 | qDebug() << "Application::suspend - no surface to call stopFrameDropper() on!"; | ||
2250 | 68 | } | ||
2251 | 69 | Q_EMIT suspended(); | ||
2252 | 70 | }); | ||
2254 | 71 | } | 64 | } |
2255 | 72 | 65 | ||
2256 | 73 | Session::~Session() | 66 | Session::~Session() |
2257 | @@ -89,6 +82,17 @@ | |||
2258 | 89 | delete m_children; m_children = nullptr; | 82 | delete m_children; m_children = nullptr; |
2259 | 90 | } | 83 | } |
2260 | 91 | 84 | ||
2261 | 85 | void Session::doSuspend() | ||
2262 | 86 | { | ||
2263 | 87 | Q_ASSERT(m_state == Session::Suspending); | ||
2264 | 88 | if (m_surface) { | ||
2265 | 89 | m_surface->stopFrameDropper(); | ||
2266 | 90 | } else { | ||
2267 | 91 | qDebug() << "Application::suspend - no surface to call stopFrameDropper() on!"; | ||
2268 | 92 | } | ||
2269 | 93 | setState(Suspended); | ||
2270 | 94 | } | ||
2271 | 95 | |||
2272 | 92 | void Session::release() | 96 | void Session::release() |
2273 | 93 | { | 97 | { |
2274 | 94 | qCDebug(QTMIR_SESSIONS) << "Session::release " << name(); | 98 | qCDebug(QTMIR_SESSIONS) << "Session::release " << name(); |
2275 | @@ -120,7 +124,7 @@ | |||
2276 | 120 | return m_application; | 124 | return m_application; |
2277 | 121 | } | 125 | } |
2278 | 122 | 126 | ||
2280 | 123 | MirSurfaceItem* Session::surface() const | 127 | MirSurfaceItemInterface* Session::surface() const |
2281 | 124 | { | 128 | { |
2282 | 125 | // Only notify QML of surface creation once it has drawn its first frame. | 129 | // Only notify QML of surface creation once it has drawn its first frame. |
2283 | 126 | if (m_surface && m_surface->isFirstFrameDrawn()) { | 130 | if (m_surface && m_surface->isFirstFrameDrawn()) { |
2284 | @@ -140,6 +144,13 @@ | |||
2285 | 140 | return m_state; | 144 | return m_state; |
2286 | 141 | } | 145 | } |
2287 | 142 | 146 | ||
2288 | 147 | void Session::setState(State state) { | ||
2289 | 148 | if (state != m_state) { | ||
2290 | 149 | m_state = state; | ||
2291 | 150 | Q_EMIT stateChanged(m_state); | ||
2292 | 151 | } | ||
2293 | 152 | } | ||
2294 | 153 | |||
2295 | 143 | bool Session::fullscreen() const | 154 | bool Session::fullscreen() const |
2296 | 144 | { | 155 | { |
2297 | 145 | return m_fullscreen; | 156 | return m_fullscreen; |
2298 | @@ -159,7 +170,7 @@ | |||
2299 | 159 | Q_EMIT applicationChanged(application); | 170 | Q_EMIT applicationChanged(application); |
2300 | 160 | } | 171 | } |
2301 | 161 | 172 | ||
2303 | 162 | void Session::setSurface(MirSurfaceItem *newSurface) | 173 | void Session::setSurface(MirSurfaceItemInterface *newSurface) |
2304 | 163 | { | 174 | { |
2305 | 164 | qCDebug(QTMIR_SESSIONS) << "Session::setSurface - session=" << name() << "surface=" << newSurface; | 175 | qCDebug(QTMIR_SESSIONS) << "Session::setSurface - session=" << name() << "surface=" << newSurface; |
2306 | 165 | 176 | ||
2307 | @@ -173,34 +184,46 @@ | |||
2308 | 173 | m_surface->setParent(nullptr); | 184 | m_surface->setParent(nullptr); |
2309 | 174 | } | 185 | } |
2310 | 175 | 186 | ||
2312 | 176 | MirSurfaceItem *previousSurface = surface(); | 187 | MirSurfaceItemInterface *previousSurface = surface(); |
2313 | 177 | m_surface = newSurface; | 188 | m_surface = newSurface; |
2314 | 178 | 189 | ||
2315 | 179 | if (newSurface) { | 190 | if (newSurface) { |
2316 | 180 | m_surface->setParent(this); | 191 | m_surface->setParent(this); |
2317 | 181 | m_surface->setSession(this); | 192 | m_surface->setSession(this); |
2318 | 182 | 193 | ||
2319 | 194 | connect(newSurface, &MirSurfaceItemInterface::stateChanged, | ||
2320 | 195 | this, &Session::updateFullscreenProperty); | ||
2321 | 196 | |||
2322 | 183 | // Only notify QML of surface creation once it has drawn its first frame. | 197 | // Only notify QML of surface creation once it has drawn its first frame. |
2326 | 184 | if (!surface()) { | 198 | if (m_surface->isFirstFrameDrawn()) { |
2327 | 185 | connect(newSurface, &MirSurfaceItem::firstFrameDrawn, | 199 | setState(Running); |
2328 | 186 | this, [this] { Q_EMIT surfaceChanged(m_surface); }); | 200 | } else { |
2329 | 201 | connect(newSurface, &MirSurfaceItemInterface::firstFrameDrawn, | ||
2330 | 202 | this, &Session::onFirstSurfaceFrameDrawn); | ||
2331 | 187 | } | 203 | } |
2332 | 188 | |||
2333 | 189 | connect(newSurface, &MirSurfaceItem::stateChanged, | ||
2334 | 190 | this, &Session::updateFullscreenProperty); | ||
2335 | 191 | } | 204 | } |
2336 | 192 | 205 | ||
2337 | 193 | if (previousSurface != surface()) { | 206 | if (previousSurface != surface()) { |
2338 | 207 | qCDebug(QTMIR_SESSIONS).nospace() << "Session::surfaceChanged - session=" << this | ||
2339 | 208 | << " surface=" << m_surface; | ||
2340 | 194 | Q_EMIT surfaceChanged(m_surface); | 209 | Q_EMIT surfaceChanged(m_surface); |
2341 | 195 | } | 210 | } |
2342 | 196 | 211 | ||
2343 | 197 | updateFullscreenProperty(); | 212 | updateFullscreenProperty(); |
2344 | 198 | } | 213 | } |
2345 | 199 | 214 | ||
2346 | 215 | void Session::onFirstSurfaceFrameDrawn() | ||
2347 | 216 | { | ||
2348 | 217 | qCDebug(QTMIR_SESSIONS).nospace() << "Session::surfaceChanged - session=" << this | ||
2349 | 218 | << " surface=" << m_surface; | ||
2350 | 219 | Q_EMIT surfaceChanged(m_surface); | ||
2351 | 220 | setState(Running); | ||
2352 | 221 | } | ||
2353 | 222 | |||
2354 | 200 | void Session::updateFullscreenProperty() | 223 | void Session::updateFullscreenProperty() |
2355 | 201 | { | 224 | { |
2356 | 202 | if (m_surface) { | 225 | if (m_surface) { |
2358 | 203 | setFullscreen(m_surface->state() == MirSurfaceItem::Fullscreen); | 226 | setFullscreen(m_surface->state() == Globals::SurfaceState::Fullscreen); |
2359 | 204 | } else { | 227 | } else { |
2360 | 205 | // Keep the current value of the fullscreen property until we get a new | 228 | // Keep the current value of the fullscreen property until we get a new |
2361 | 206 | // surface | 229 | // surface |
2362 | @@ -216,59 +239,71 @@ | |||
2363 | 216 | } | 239 | } |
2364 | 217 | } | 240 | } |
2365 | 218 | 241 | ||
2419 | 219 | void Session::setState(State state) | 242 | void Session::suspend() |
2420 | 220 | { | 243 | { |
2421 | 221 | qCDebug(QTMIR_SESSIONS) << "Session::setState - session=" << this << "state=" << applicationStateToStr(state); | 244 | qCDebug(QTMIR_SESSIONS) << "Session::suspend - session=" << this << "state=" << applicationStateToStr(m_state); |
2422 | 222 | if (m_state != state) { | 245 | if (m_state == Running) { |
2423 | 223 | switch (state) | 246 | session()->set_lifecycle_state(mir_lifecycle_state_will_suspend); |
2424 | 224 | { | 247 | m_suspendTimer->start(1500); |
2425 | 225 | case Session::State::Suspended: | 248 | |
2426 | 226 | if (m_state == Session::State::Running) { | 249 | foreachPromptSession([this](const std::shared_ptr<ms::PromptSession>& promptSession) { |
2427 | 227 | session()->set_lifecycle_state(mir_lifecycle_state_will_suspend); | 250 | m_promptSessionManager->suspend_prompt_session(promptSession); |
2428 | 228 | m_suspendTimer->start(1500); | 251 | }); |
2429 | 229 | } | 252 | |
2430 | 230 | break; | 253 | foreachChildSession([](SessionInterface* session) { |
2431 | 231 | case Session::State::Running: | 254 | session->suspend(); |
2432 | 232 | if (m_suspendTimer->isActive()) | 255 | }); |
2433 | 233 | m_suspendTimer->stop(); | 256 | |
2434 | 234 | 257 | setState(Suspending); | |
2435 | 235 | if (m_state == Session::State::Suspended) { | 258 | } |
2436 | 236 | if (m_surface) | 259 | } |
2437 | 237 | m_surface->startFrameDropper(); | 260 | |
2438 | 238 | Q_EMIT resumed(); | 261 | void Session::resume() |
2439 | 239 | session()->set_lifecycle_state(mir_lifecycle_state_resumed); | 262 | { |
2440 | 240 | } | 263 | qCDebug(QTMIR_SESSIONS) << "Session::resume - session=" << this << "state=" << applicationStateToStr(m_state); |
2441 | 241 | break; | 264 | |
2442 | 242 | case Session::State::Stopped: | 265 | if (m_state == Suspending || m_state == Suspended) { |
2443 | 243 | stopPromptSessions(); | 266 | doResume(); |
2444 | 244 | if (m_suspendTimer->isActive()) | 267 | } |
2445 | 245 | m_suspendTimer->stop(); | 268 | } |
2446 | 246 | if (m_surface) | 269 | |
2447 | 247 | m_surface->stopFrameDropper(); | 270 | void Session::doResume() |
2448 | 248 | break; | 271 | { |
2449 | 249 | default: | 272 | if (m_state == Suspending) { |
2450 | 250 | break; | 273 | Q_ASSERT(m_suspendTimer->isActive()); |
2451 | 251 | } | 274 | m_suspendTimer->stop(); |
2452 | 252 | 275 | } else if (m_state == Suspended) { | |
2453 | 253 | m_state = state; | 276 | Q_ASSERT(m_surface); |
2454 | 254 | Q_EMIT stateChanged(state); | 277 | m_surface->startFrameDropper(); |
2455 | 255 | 278 | } | |
2456 | 256 | foreachPromptSession([this, state](const std::shared_ptr<ms::PromptSession>& promptSession) { | 279 | |
2457 | 257 | switch (state) { | 280 | session()->set_lifecycle_state(mir_lifecycle_state_resumed); |
2458 | 258 | case Session::State::Suspended: | 281 | |
2459 | 259 | m_promptSessionManager->suspend_prompt_session(promptSession); | 282 | foreachPromptSession([this](const std::shared_ptr<ms::PromptSession>& promptSession) { |
2460 | 260 | break; | 283 | m_promptSessionManager->resume_prompt_session(promptSession); |
2461 | 261 | case Session::State::Running: | 284 | }); |
2462 | 262 | m_promptSessionManager->resume_prompt_session(promptSession); | 285 | |
2463 | 263 | break; | 286 | foreachChildSession([](SessionInterface* session) { |
2464 | 264 | default: | 287 | session->resume(); |
2465 | 265 | break; | 288 | }); |
2466 | 266 | } | 289 | |
2467 | 267 | }); | 290 | setState(Running); |
2468 | 268 | 291 | } | |
2469 | 269 | foreachChildSession([state](SessionInterface* session) { | 292 | |
2470 | 270 | session->setState(state); | 293 | void Session::stop() |
2471 | 271 | }); | 294 | { |
2472 | 295 | if (m_state != Stopped) { | ||
2473 | 296 | stopPromptSessions(); | ||
2474 | 297 | if (m_suspendTimer->isActive()) | ||
2475 | 298 | m_suspendTimer->stop(); | ||
2476 | 299 | if (m_surface) | ||
2477 | 300 | m_surface->stopFrameDropper(); | ||
2478 | 301 | |||
2479 | 302 | foreachChildSession([](SessionInterface* session) { | ||
2480 | 303 | session->stop(); | ||
2481 | 304 | }); | ||
2482 | 305 | |||
2483 | 306 | setState(Stopped); | ||
2484 | 272 | } | 307 | } |
2485 | 273 | } | 308 | } |
2486 | 274 | 309 | ||
2487 | @@ -277,6 +312,9 @@ | |||
2488 | 277 | if (m_live != live) { | 312 | if (m_live != live) { |
2489 | 278 | m_live = live; | 313 | m_live = live; |
2490 | 279 | Q_EMIT liveChanged(m_live); | 314 | Q_EMIT liveChanged(m_live); |
2491 | 315 | if (!live) { | ||
2492 | 316 | setState(Stopped); | ||
2493 | 317 | } | ||
2494 | 280 | } | 318 | } |
2495 | 281 | } | 319 | } |
2496 | 282 | 320 | ||
2497 | @@ -302,7 +340,19 @@ | |||
2498 | 302 | static_cast<Session*>(session)->setParentSession(this); | 340 | static_cast<Session*>(session)->setParentSession(this); |
2499 | 303 | m_children->insert(index, session); | 341 | m_children->insert(index, session); |
2500 | 304 | 342 | ||
2502 | 305 | session->setState(state()); | 343 | switch (m_state) { |
2503 | 344 | case Starting: | ||
2504 | 345 | case Running: | ||
2505 | 346 | session->resume(); | ||
2506 | 347 | break; | ||
2507 | 348 | case Suspending: | ||
2508 | 349 | case Suspended: | ||
2509 | 350 | session->suspend(); | ||
2510 | 351 | break; | ||
2511 | 352 | case Stopped: | ||
2512 | 353 | session->stop(); | ||
2513 | 354 | break; | ||
2514 | 355 | } | ||
2515 | 306 | } | 356 | } |
2516 | 307 | 357 | ||
2517 | 308 | void Session::removeChildSession(SessionInterface* session) | 358 | void Session::removeChildSession(SessionInterface* session) |
2518 | 309 | 359 | ||
2519 | === modified file 'src/modules/Unity/Application/session.h' | |||
2520 | --- src/modules/Unity/Application/session.h 2014-09-11 16:18:40 +0000 | |||
2521 | +++ src/modules/Unity/Application/session.h 2015-07-13 21:57:32 +0000 | |||
2522 | @@ -1,5 +1,5 @@ | |||
2523 | 1 | /* | 1 | /* |
2525 | 2 | * Copyright (C) 2014 Canonical, Ltd. | 2 | * Copyright (C) 2014-2015 Canonical, Ltd. |
2526 | 3 | * | 3 | * |
2527 | 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 |
2528 | 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 |
2529 | @@ -52,15 +52,18 @@ | |||
2530 | 52 | //getters | 52 | //getters |
2531 | 53 | QString name() const override; | 53 | QString name() const override; |
2532 | 54 | unity::shell::application::ApplicationInfoInterface* application() const override; | 54 | unity::shell::application::ApplicationInfoInterface* application() const override; |
2534 | 55 | MirSurfaceItem* surface() const override; | 55 | MirSurfaceItemInterface* surface() const override; |
2535 | 56 | SessionInterface* parentSession() const override; | 56 | SessionInterface* parentSession() const override; |
2536 | 57 | State state() const override; | 57 | State state() const override; |
2537 | 58 | bool fullscreen() const override; | 58 | bool fullscreen() const override; |
2538 | 59 | bool live() const override; | 59 | bool live() const override; |
2539 | 60 | 60 | ||
2540 | 61 | void setApplication(unity::shell::application::ApplicationInfoInterface* item) override; | 61 | void setApplication(unity::shell::application::ApplicationInfoInterface* item) override; |
2543 | 62 | void setSurface(MirSurfaceItem* surface) override; | 62 | void setSurface(MirSurfaceItemInterface* surface) override; |
2544 | 63 | void setState(State state) override; | 63 | |
2545 | 64 | void suspend() override; | ||
2546 | 65 | void resume() override; | ||
2547 | 66 | void stop() override; | ||
2548 | 64 | 67 | ||
2549 | 65 | void addChildSession(SessionInterface* session) override; | 68 | void addChildSession(SessionInterface* session) override; |
2550 | 66 | void insertChildSession(uint index, SessionInterface* session) override; | 69 | void insertChildSession(uint index, SessionInterface* session) override; |
2551 | @@ -74,23 +77,29 @@ | |||
2552 | 74 | 77 | ||
2553 | 75 | SessionModel* childSessions() const override; | 78 | SessionModel* childSessions() const override; |
2554 | 76 | 79 | ||
2555 | 77 | protected: | ||
2556 | 78 | void setFullscreen(bool fullscreen) override; | 80 | void setFullscreen(bool fullscreen) override; |
2557 | 79 | void setLive(const bool) override; | 81 | void setLive(const bool) override; |
2558 | 80 | void appendPromptSession(const std::shared_ptr<mir::scene::PromptSession>& session) override; | 82 | void appendPromptSession(const std::shared_ptr<mir::scene::PromptSession>& session) override; |
2559 | 81 | void removePromptSession(const std::shared_ptr<mir::scene::PromptSession>& session) override; | 83 | void removePromptSession(const std::shared_ptr<mir::scene::PromptSession>& session) override; |
2560 | 82 | 84 | ||
2561 | 85 | public Q_SLOTS: | ||
2562 | 86 | // it's public to ease testing | ||
2563 | 87 | void doSuspend(); | ||
2564 | 88 | |||
2565 | 83 | private Q_SLOTS: | 89 | private Q_SLOTS: |
2566 | 84 | void updateFullscreenProperty(); | 90 | void updateFullscreenProperty(); |
2567 | 91 | void onFirstSurfaceFrameDrawn(); | ||
2568 | 85 | 92 | ||
2569 | 86 | private: | 93 | private: |
2570 | 87 | void setParentSession(Session* session); | 94 | void setParentSession(Session* session); |
2571 | 95 | void setState(State state); | ||
2572 | 96 | void doResume(); | ||
2573 | 88 | 97 | ||
2574 | 89 | void stopPromptSessions(); | 98 | void stopPromptSessions(); |
2575 | 90 | 99 | ||
2576 | 91 | std::shared_ptr<mir::scene::Session> m_session; | 100 | std::shared_ptr<mir::scene::Session> m_session; |
2577 | 92 | Application* m_application; | 101 | Application* m_application; |
2579 | 93 | MirSurfaceItem* m_surface; | 102 | MirSurfaceItemInterface* m_surface; |
2580 | 94 | SessionInterface* m_parentSession; | 103 | SessionInterface* m_parentSession; |
2581 | 95 | SessionModel* m_children; | 104 | SessionModel* m_children; |
2582 | 96 | bool m_fullscreen; | 105 | bool m_fullscreen; |
2583 | @@ -103,6 +112,4 @@ | |||
2584 | 103 | 112 | ||
2585 | 104 | } // namespace qtmir | 113 | } // namespace qtmir |
2586 | 105 | 114 | ||
2587 | 106 | Q_DECLARE_METATYPE(qtmir::Session*) | ||
2588 | 107 | |||
2589 | 108 | #endif // SESSION_H | 115 | #endif // SESSION_H |
2590 | 109 | 116 | ||
2591 | === modified file 'src/modules/Unity/Application/session_interface.h' | |||
2592 | --- src/modules/Unity/Application/session_interface.h 2014-09-22 18:06:58 +0000 | |||
2593 | +++ src/modules/Unity/Application/session_interface.h 2015-07-13 21:57:32 +0000 | |||
2594 | @@ -1,5 +1,5 @@ | |||
2595 | 1 | /* | 1 | /* |
2597 | 2 | * Copyright (C) 2014 Canonical, Ltd. | 2 | * Copyright (C) 2014,2015 Canonical, Ltd. |
2598 | 3 | * | 3 | * |
2599 | 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 |
2600 | 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 |
2601 | @@ -35,11 +35,11 @@ | |||
2602 | 35 | 35 | ||
2603 | 36 | namespace qtmir { | 36 | namespace qtmir { |
2604 | 37 | 37 | ||
2606 | 38 | class MirSurfaceItem; | 38 | class MirSurfaceItemInterface; |
2607 | 39 | 39 | ||
2608 | 40 | class SessionInterface : public QObject { | 40 | class SessionInterface : public QObject { |
2609 | 41 | Q_OBJECT | 41 | Q_OBJECT |
2611 | 42 | Q_PROPERTY(MirSurfaceItem* surface READ surface NOTIFY surfaceChanged) | 42 | Q_PROPERTY(MirSurfaceItemInterface* surface READ surface NOTIFY surfaceChanged) |
2612 | 43 | Q_PROPERTY(unity::shell::application::ApplicationInfoInterface* application READ application NOTIFY applicationChanged DESIGNABLE false) | 43 | Q_PROPERTY(unity::shell::application::ApplicationInfoInterface* application READ application NOTIFY applicationChanged DESIGNABLE false) |
2613 | 44 | Q_PROPERTY(SessionInterface* parentSession READ parentSession NOTIFY parentSessionChanged DESIGNABLE false) | 44 | Q_PROPERTY(SessionInterface* parentSession READ parentSession NOTIFY parentSessionChanged DESIGNABLE false) |
2614 | 45 | Q_PROPERTY(SessionModel* childSessions READ childSessions DESIGNABLE false CONSTANT) | 45 | Q_PROPERTY(SessionModel* childSessions READ childSessions DESIGNABLE false CONSTANT) |
2615 | @@ -49,58 +49,66 @@ | |||
2616 | 49 | SessionInterface(QObject *parent = 0) : QObject(parent) {} | 49 | SessionInterface(QObject *parent = 0) : QObject(parent) {} |
2617 | 50 | virtual ~SessionInterface() {} | 50 | virtual ~SessionInterface() {} |
2618 | 51 | 51 | ||
2621 | 52 | // Session State | 52 | enum State { |
2622 | 53 | typedef unity::shell::application::ApplicationInfoInterface::State State; | 53 | Starting, |
2623 | 54 | Running, | ||
2624 | 55 | Suspending, | ||
2625 | 56 | Suspended, | ||
2626 | 57 | Stopped | ||
2627 | 58 | }; | ||
2628 | 54 | 59 | ||
2629 | 55 | Q_INVOKABLE virtual void release() = 0; | 60 | Q_INVOKABLE virtual void release() = 0; |
2630 | 56 | 61 | ||
2631 | 57 | //getters | 62 | //getters |
2632 | 58 | virtual QString name() const = 0; | 63 | virtual QString name() const = 0; |
2633 | 59 | virtual unity::shell::application::ApplicationInfoInterface* application() const = 0; | 64 | virtual unity::shell::application::ApplicationInfoInterface* application() const = 0; |
2635 | 60 | virtual MirSurfaceItem* surface() const = 0; | 65 | virtual MirSurfaceItemInterface* surface() const = 0; |
2636 | 61 | virtual SessionInterface* parentSession() const = 0; | 66 | virtual SessionInterface* parentSession() const = 0; |
2637 | 67 | virtual SessionModel* childSessions() const = 0; | ||
2638 | 62 | virtual State state() const = 0; | 68 | virtual State state() const = 0; |
2639 | 63 | virtual bool fullscreen() const = 0; | 69 | virtual bool fullscreen() const = 0; |
2640 | 64 | virtual bool live() const = 0; | 70 | virtual bool live() const = 0; |
2641 | 65 | 71 | ||
2642 | 72 | virtual std::shared_ptr<mir::scene::Session> session() const = 0; | ||
2643 | 73 | |||
2644 | 74 | // For MirSurfaceItem and MirSurfaceManager use | ||
2645 | 75 | |||
2646 | 76 | virtual void setSurface(MirSurfaceItemInterface* surface) = 0; | ||
2647 | 77 | |||
2648 | 78 | // For Application use | ||
2649 | 79 | |||
2650 | 66 | virtual void setApplication(unity::shell::application::ApplicationInfoInterface* item) = 0; | 80 | virtual void setApplication(unity::shell::application::ApplicationInfoInterface* item) = 0; |
2653 | 67 | virtual void setSurface(MirSurfaceItem* surface) = 0; | 81 | virtual void suspend() = 0; |
2654 | 68 | virtual void setState(State state) = 0; | 82 | virtual void resume() = 0; |
2655 | 83 | virtual void stop() = 0; | ||
2656 | 84 | |||
2657 | 85 | // For SessionManager use | ||
2658 | 69 | 86 | ||
2659 | 70 | virtual void addChildSession(SessionInterface* session) = 0; | 87 | virtual void addChildSession(SessionInterface* session) = 0; |
2660 | 71 | virtual void insertChildSession(uint index, SessionInterface* session) = 0; | 88 | virtual void insertChildSession(uint index, SessionInterface* session) = 0; |
2661 | 72 | virtual void removeChildSession(SessionInterface* session) = 0; | 89 | virtual void removeChildSession(SessionInterface* session) = 0; |
2662 | 73 | virtual void foreachChildSession(std::function<void(SessionInterface* session)> f) const = 0; | 90 | virtual void foreachChildSession(std::function<void(SessionInterface* session)> f) const = 0; |
2663 | 74 | 91 | ||
2664 | 75 | virtual std::shared_ptr<mir::scene::Session> session() const = 0; | ||
2665 | 76 | |||
2666 | 77 | virtual std::shared_ptr<mir::scene::PromptSession> activePromptSession() const = 0; | 92 | virtual std::shared_ptr<mir::scene::PromptSession> activePromptSession() const = 0; |
2667 | 78 | virtual void foreachPromptSession(std::function<void(const std::shared_ptr<mir::scene::PromptSession>&)> f) const = 0; | 93 | virtual void foreachPromptSession(std::function<void(const std::shared_ptr<mir::scene::PromptSession>&)> f) const = 0; |
2668 | 79 | 94 | ||
2670 | 80 | virtual SessionModel* childSessions() const = 0; | 95 | virtual void setFullscreen(bool fullscreen) = 0; |
2671 | 96 | virtual void setLive(const bool) = 0; | ||
2672 | 97 | virtual void appendPromptSession(const std::shared_ptr<mir::scene::PromptSession>& session) = 0; | ||
2673 | 98 | virtual void removePromptSession(const std::shared_ptr<mir::scene::PromptSession>& session) = 0; | ||
2674 | 81 | 99 | ||
2675 | 82 | Q_SIGNALS: | 100 | Q_SIGNALS: |
2677 | 83 | void surfaceChanged(MirSurfaceItem*); | 101 | void surfaceChanged(MirSurfaceItemInterface*); |
2678 | 84 | void parentSessionChanged(SessionInterface*); | 102 | void parentSessionChanged(SessionInterface*); |
2679 | 85 | void applicationChanged(unity::shell::application::ApplicationInfoInterface* application); | 103 | void applicationChanged(unity::shell::application::ApplicationInfoInterface* application); |
2680 | 86 | void aboutToBeDestroyed(); | 104 | void aboutToBeDestroyed(); |
2681 | 87 | void stateChanged(State state); | 105 | void stateChanged(State state); |
2682 | 88 | void fullscreenChanged(bool fullscreen); | 106 | void fullscreenChanged(bool fullscreen); |
2683 | 89 | void liveChanged(bool live); | 107 | void liveChanged(bool live); |
2684 | 90 | |||
2685 | 91 | void suspended(); | ||
2686 | 92 | void resumed(); | ||
2687 | 93 | |||
2688 | 94 | protected: | ||
2689 | 95 | virtual void setFullscreen(bool fullscreen) = 0; | ||
2690 | 96 | virtual void setLive(const bool) = 0; | ||
2691 | 97 | virtual void appendPromptSession(const std::shared_ptr<mir::scene::PromptSession>& session) = 0; | ||
2692 | 98 | virtual void removePromptSession(const std::shared_ptr<mir::scene::PromptSession>& session) = 0; | ||
2693 | 99 | |||
2694 | 100 | friend class SessionManager; | ||
2695 | 101 | }; | 108 | }; |
2696 | 102 | 109 | ||
2697 | 103 | } // namespace qtmir | 110 | } // namespace qtmir |
2698 | 104 | 111 | ||
2699 | 112 | Q_DECLARE_METATYPE(qtmir::SessionInterface*) | ||
2700 | 105 | 113 | ||
2701 | 106 | #endif // SESSION_INTERFACE_H | 114 | #endif // SESSION_INTERFACE_H |
2702 | 107 | 115 | ||
2703 | === modified file 'src/modules/Unity/Application/sessionmanager.cpp' | |||
2704 | --- src/modules/Unity/Application/sessionmanager.cpp 2015-01-28 14:25:36 +0000 | |||
2705 | +++ src/modules/Unity/Application/sessionmanager.cpp 2015-07-13 21:57:32 +0000 | |||
2706 | @@ -63,7 +63,7 @@ | |||
2707 | 63 | manager, &SessionManager::onPromptProviderRemoved); | 63 | manager, &SessionManager::onPromptProviderRemoved); |
2708 | 64 | } | 64 | } |
2709 | 65 | 65 | ||
2711 | 66 | SessionManager* SessionManager::singleton() | 66 | SessionManager* SessionManager::singleton(QJSEngine *jsEngine) |
2712 | 67 | { | 67 | { |
2713 | 68 | if (!the_session_manager) { | 68 | if (!the_session_manager) { |
2714 | 69 | 69 | ||
2715 | @@ -78,7 +78,7 @@ | |||
2716 | 78 | SessionListener *sessionListener = static_cast<SessionListener*>(nativeInterface->nativeResourceForIntegration("SessionListener")); | 78 | SessionListener *sessionListener = static_cast<SessionListener*>(nativeInterface->nativeResourceForIntegration("SessionListener")); |
2717 | 79 | PromptSessionListener *promptSessionListener = static_cast<PromptSessionListener*>(nativeInterface->nativeResourceForIntegration("PromptSessionListener")); | 79 | PromptSessionListener *promptSessionListener = static_cast<PromptSessionListener*>(nativeInterface->nativeResourceForIntegration("PromptSessionListener")); |
2718 | 80 | 80 | ||
2720 | 81 | the_session_manager = new SessionManager(nativeInterface->m_mirServer, ApplicationManager::singleton()); | 81 | the_session_manager = new SessionManager(nativeInterface->m_mirServer, ApplicationManager::singleton(jsEngine)); |
2721 | 82 | 82 | ||
2722 | 83 | connectToSessionListener(the_session_manager, sessionListener); | 83 | connectToSessionListener(the_session_manager, sessionListener); |
2723 | 84 | connectToPromptSessionListener(the_session_manager, promptSessionListener); | 84 | connectToPromptSessionListener(the_session_manager, promptSessionListener); |
2724 | 85 | 85 | ||
2725 | === modified file 'src/modules/Unity/Application/sessionmanager.h' | |||
2726 | --- src/modules/Unity/Application/sessionmanager.h 2014-12-01 11:05:01 +0000 | |||
2727 | +++ src/modules/Unity/Application/sessionmanager.h 2015-07-13 21:57:32 +0000 | |||
2728 | @@ -38,6 +38,8 @@ | |||
2729 | 38 | } | 38 | } |
2730 | 39 | } | 39 | } |
2731 | 40 | 40 | ||
2732 | 41 | class QJSEngine; | ||
2733 | 42 | |||
2734 | 41 | class MirServer; | 43 | class MirServer; |
2735 | 42 | 44 | ||
2736 | 43 | namespace qtmir { | 45 | namespace qtmir { |
2737 | @@ -57,7 +59,7 @@ | |||
2738 | 57 | ); | 59 | ); |
2739 | 58 | ~SessionManager(); | 60 | ~SessionManager(); |
2740 | 59 | 61 | ||
2742 | 60 | static SessionManager* singleton(); | 62 | static SessionManager* singleton(QJSEngine *jsEngine); |
2743 | 61 | 63 | ||
2744 | 62 | SessionInterface *findSession(const mir::scene::Session* session) const; | 64 | SessionInterface *findSession(const mir::scene::Session* session) const; |
2745 | 63 | 65 | ||
2746 | 64 | 66 | ||
2747 | === modified file 'src/modules/Unity/Application/taskcontroller.cpp' | |||
2748 | --- src/modules/Unity/Application/taskcontroller.cpp 2014-10-20 18:48:53 +0000 | |||
2749 | +++ src/modules/Unity/Application/taskcontroller.cpp 2015-07-13 21:57:32 +0000 | |||
2750 | @@ -50,14 +50,19 @@ | |||
2751 | 50 | &TaskController::processStopped); | 50 | &TaskController::processStopped); |
2752 | 51 | 51 | ||
2753 | 52 | connect(m_appController.data(), | 52 | connect(m_appController.data(), |
2754 | 53 | &ApplicationController::applicationPaused, | ||
2755 | 54 | this, | ||
2756 | 55 | &TaskController::processSuspended); | ||
2757 | 56 | |||
2758 | 57 | connect(m_appController.data(), | ||
2759 | 53 | &ApplicationController::applicationFocusRequest, | 58 | &ApplicationController::applicationFocusRequest, |
2760 | 54 | this, | 59 | this, |
2762 | 55 | &TaskController::onApplicationFocusRequest); | 60 | &TaskController::focusRequested); |
2763 | 56 | 61 | ||
2764 | 57 | connect(m_appController.data(), | 62 | connect(m_appController.data(), |
2766 | 58 | &ApplicationController::applicationResumeRequest, | 63 | &ApplicationController::applicationResumeRequested, |
2767 | 59 | this, | 64 | this, |
2769 | 60 | &TaskController::onApplicationResumeRequest); | 65 | &TaskController::resumeRequested); |
2770 | 61 | 66 | ||
2771 | 62 | connect(m_appController.data(), | 67 | connect(m_appController.data(), |
2772 | 63 | &ApplicationController::applicationError, | 68 | &ApplicationController::applicationError, |
2773 | @@ -108,16 +113,6 @@ | |||
2774 | 108 | return m_appController->resumeApplicationWithAppId(appId); | 113 | return m_appController->resumeApplicationWithAppId(appId); |
2775 | 109 | } | 114 | } |
2776 | 110 | 115 | ||
2777 | 111 | void TaskController::onApplicationFocusRequest(const QString& id) | ||
2778 | 112 | { | ||
2779 | 113 | Q_EMIT requestFocus(id); | ||
2780 | 114 | } | ||
2781 | 115 | |||
2782 | 116 | void TaskController::onApplicationResumeRequest(const QString& id) | ||
2783 | 117 | { | ||
2784 | 118 | Q_EMIT requestResume(id); | ||
2785 | 119 | } | ||
2786 | 120 | |||
2787 | 121 | void TaskController::onApplicationError(const QString& id, ApplicationController::Error error) | 116 | void TaskController::onApplicationError(const QString& id, ApplicationController::Error error) |
2788 | 122 | { | 117 | { |
2789 | 123 | Q_EMIT processFailed(id, (error == ApplicationController::Error::APPLICATION_FAILED_TO_START) ); | 118 | Q_EMIT processFailed(id, (error == ApplicationController::Error::APPLICATION_FAILED_TO_START) ); |
2790 | 124 | 119 | ||
2791 | === modified file 'src/modules/Unity/Application/taskcontroller.h' | |||
2792 | --- src/modules/Unity/Application/taskcontroller.h 2014-10-07 03:21:30 +0000 | |||
2793 | +++ src/modules/Unity/Application/taskcontroller.h 2015-07-13 21:57:32 +0000 | |||
2794 | @@ -1,5 +1,5 @@ | |||
2795 | 1 | /* | 1 | /* |
2797 | 2 | * Copyright (C) 2013-2014 Canonical, Ltd. | 2 | * Copyright (C) 2013-2015 Canonical, Ltd. |
2798 | 3 | * | 3 | * |
2799 | 4 | * This program is free software: you can redistribute it and/or modify it under | 4 | * This program is free software: you can redistribute it and/or modify it under |
2800 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | 5 | * the terms of the GNU Lesser General Public License version 3, as published by |
2801 | @@ -48,14 +48,12 @@ | |||
2802 | 48 | Q_SIGNALS: | 48 | Q_SIGNALS: |
2803 | 49 | void processStarting(const QString &appId); | 49 | void processStarting(const QString &appId); |
2804 | 50 | void processStopped(const QString &appId); | 50 | void processStopped(const QString &appId); |
2805 | 51 | void processSuspended(const QString &appId); | ||
2806 | 51 | void processFailed(const QString &appId, const bool duringStartup); | 52 | void processFailed(const QString &appId, const bool duringStartup); |
2809 | 52 | void requestFocus(const QString &appId); | 53 | void focusRequested(const QString &appId); |
2810 | 53 | void requestResume(const QString &appId); | 54 | void resumeRequested(const QString &appId); |
2811 | 54 | 55 | ||
2812 | 55 | private Q_SLOTS: | 56 | private Q_SLOTS: |
2813 | 56 | void onApplicationFocusRequest(const QString &id); | ||
2814 | 57 | void onApplicationResumeRequest(const QString &id); | ||
2815 | 58 | |||
2816 | 59 | void onApplicationError(const QString &id, ApplicationController::Error error); | 57 | void onApplicationError(const QString &id, ApplicationController::Error error); |
2817 | 60 | 58 | ||
2818 | 61 | private: | 59 | private: |
2819 | 62 | 60 | ||
2820 | === modified file 'src/modules/Unity/Application/upstart/applicationcontroller.cpp' | |||
2821 | --- src/modules/Unity/Application/upstart/applicationcontroller.cpp 2014-11-13 15:47:30 +0000 | |||
2822 | +++ src/modules/Unity/Application/upstart/applicationcontroller.cpp 2015-07-13 21:57:32 +0000 | |||
2823 | @@ -1,5 +1,5 @@ | |||
2824 | 1 | /* | 1 | /* |
2826 | 2 | * Copyright (C) 2014 Canonical, Ltd. | 2 | * Copyright (C) 2014,2015 Canonical, Ltd. |
2827 | 3 | * | 3 | * |
2828 | 4 | * This program is free software: you can redistribute it and/or modify it under | 4 | * This program is free software: you can redistribute it and/or modify it under |
2829 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | 5 | * the terms of the GNU Lesser General Public License version 3, as published by |
2830 | @@ -40,6 +40,7 @@ | |||
2831 | 40 | UbuntuAppLaunchAppObserver stopCallback = nullptr; | 40 | UbuntuAppLaunchAppObserver stopCallback = nullptr; |
2832 | 41 | UbuntuAppLaunchAppObserver focusCallback = nullptr; | 41 | UbuntuAppLaunchAppObserver focusCallback = nullptr; |
2833 | 42 | UbuntuAppLaunchAppObserver resumeCallback = nullptr; | 42 | UbuntuAppLaunchAppObserver resumeCallback = nullptr; |
2834 | 43 | UbuntuAppLaunchAppPausedResumedObserver pausedCallback = nullptr; | ||
2835 | 43 | UbuntuAppLaunchAppFailedObserver failureCallback = nullptr; | 44 | UbuntuAppLaunchAppFailedObserver failureCallback = nullptr; |
2836 | 44 | }; | 45 | }; |
2837 | 45 | 46 | ||
2838 | @@ -125,7 +126,12 @@ | |||
2839 | 125 | 126 | ||
2840 | 126 | impl->resumeCallback = [](const gchar * appId, gpointer userData) { | 127 | impl->resumeCallback = [](const gchar * appId, gpointer userData) { |
2841 | 127 | auto thiz = static_cast<ApplicationController*>(userData); | 128 | auto thiz = static_cast<ApplicationController*>(userData); |
2843 | 128 | Q_EMIT(thiz->applicationResumeRequest(toShortAppIdIfPossible(appId))); | 129 | Q_EMIT(thiz->applicationResumeRequested(toShortAppIdIfPossible(appId))); |
2844 | 130 | }; | ||
2845 | 131 | |||
2846 | 132 | impl->pausedCallback = [](const gchar * appId, GPid *, gpointer userData) { | ||
2847 | 133 | auto thiz = static_cast<ApplicationController*>(userData); | ||
2848 | 134 | Q_EMIT(thiz->applicationPaused(toShortAppIdIfPossible(appId))); | ||
2849 | 129 | }; | 135 | }; |
2850 | 130 | 136 | ||
2851 | 131 | impl->failureCallback = [](const gchar * appId, UbuntuAppLaunchAppFailed failureType, gpointer userData) { | 137 | impl->failureCallback = [](const gchar * appId, UbuntuAppLaunchAppFailed failureType, gpointer userData) { |
2852 | @@ -145,6 +151,7 @@ | |||
2853 | 145 | ubuntu_app_launch_observer_add_app_stop(impl->stopCallback, this); | 151 | ubuntu_app_launch_observer_add_app_stop(impl->stopCallback, this); |
2854 | 146 | ubuntu_app_launch_observer_add_app_focus(impl->focusCallback, this); | 152 | ubuntu_app_launch_observer_add_app_focus(impl->focusCallback, this); |
2855 | 147 | ubuntu_app_launch_observer_add_app_resume(impl->resumeCallback, this); | 153 | ubuntu_app_launch_observer_add_app_resume(impl->resumeCallback, this); |
2856 | 154 | ubuntu_app_launch_observer_add_app_paused(impl->pausedCallback, this); | ||
2857 | 148 | ubuntu_app_launch_observer_add_app_failed(impl->failureCallback, this); | 155 | ubuntu_app_launch_observer_add_app_failed(impl->failureCallback, this); |
2858 | 149 | } | 156 | } |
2859 | 150 | 157 | ||
2860 | @@ -155,6 +162,7 @@ | |||
2861 | 155 | ubuntu_app_launch_observer_delete_app_stop(impl->stopCallback, this); | 162 | ubuntu_app_launch_observer_delete_app_stop(impl->stopCallback, this); |
2862 | 156 | ubuntu_app_launch_observer_delete_app_focus(impl->focusCallback, this); | 163 | ubuntu_app_launch_observer_delete_app_focus(impl->focusCallback, this); |
2863 | 157 | ubuntu_app_launch_observer_delete_app_resume(impl->resumeCallback, this); | 164 | ubuntu_app_launch_observer_delete_app_resume(impl->resumeCallback, this); |
2864 | 165 | ubuntu_app_launch_observer_delete_app_paused(impl->pausedCallback, this); | ||
2865 | 158 | ubuntu_app_launch_observer_delete_app_failed(impl->failureCallback, this); | 166 | ubuntu_app_launch_observer_delete_app_failed(impl->failureCallback, this); |
2866 | 159 | } | 167 | } |
2867 | 160 | 168 | ||
2868 | 161 | 169 | ||
2869 | === modified file 'src/platforms/mirserver/CMakeLists.txt' | |||
2870 | --- src/platforms/mirserver/CMakeLists.txt 2015-05-19 15:10:48 +0000 | |||
2871 | +++ src/platforms/mirserver/CMakeLists.txt 2015-07-13 21:57:32 +0000 | |||
2872 | @@ -31,6 +31,8 @@ | |||
2873 | 31 | ${QT5PLATFORM_SUPPORT_INCLUDE_DIRS} | 31 | ${QT5PLATFORM_SUPPORT_INCLUDE_DIRS} |
2874 | 32 | ${Qt5Gui_PRIVATE_INCLUDE_DIRS} | 32 | ${Qt5Gui_PRIVATE_INCLUDE_DIRS} |
2875 | 33 | ${QT5_PLATFORMSUPPORT_INCLUDE_DIRS} | 33 | ${QT5_PLATFORMSUPPORT_INCLUDE_DIRS} |
2876 | 34 | |||
2877 | 35 | ${APPLICATION_API_INCLUDE_DIRS} | ||
2878 | 34 | ) | 36 | ) |
2879 | 35 | 37 | ||
2880 | 36 | # We have to remove -pedantic for tracepoints.c | 38 | # We have to remove -pedantic for tracepoints.c |
2881 | 37 | 39 | ||
2882 | === modified file 'src/platforms/mirserver/mirserver.cpp' | |||
2883 | --- src/platforms/mirserver/mirserver.cpp 2015-02-09 16:28:40 +0000 | |||
2884 | +++ src/platforms/mirserver/mirserver.cpp 2015-07-13 21:57:32 +0000 | |||
2885 | @@ -92,8 +92,7 @@ | |||
2886 | 92 | the_input_targeter(), | 92 | the_input_targeter(), |
2887 | 93 | the_surface_coordinator(), | 93 | the_surface_coordinator(), |
2888 | 94 | the_session_coordinator(), | 94 | the_session_coordinator(), |
2891 | 95 | the_prompt_session_manager(), | 95 | the_prompt_session_manager()); |
2890 | 96 | the_shell_display_layout()); | ||
2892 | 97 | 96 | ||
2893 | 98 | m_shell = shell; | 97 | m_shell = shell; |
2894 | 99 | return shell; | 98 | return shell; |
2895 | 100 | 99 | ||
2896 | === modified file 'src/platforms/mirserver/mirshell.cpp' | |||
2897 | --- src/platforms/mirserver/mirshell.cpp 2015-05-13 09:40:03 +0000 | |||
2898 | +++ src/platforms/mirserver/mirshell.cpp 2015-07-13 21:57:32 +0000 | |||
2899 | @@ -71,37 +71,42 @@ | |||
2900 | 71 | const std::shared_ptr<mir::shell::InputTargeter> &inputTargeter, | 71 | const std::shared_ptr<mir::shell::InputTargeter> &inputTargeter, |
2901 | 72 | const std::shared_ptr<mir::scene::SurfaceCoordinator> &surfaceCoordinator, | 72 | const std::shared_ptr<mir::scene::SurfaceCoordinator> &surfaceCoordinator, |
2902 | 73 | const std::shared_ptr<mir::scene::SessionCoordinator> &sessionCoordinator, | 73 | const std::shared_ptr<mir::scene::SessionCoordinator> &sessionCoordinator, |
2905 | 74 | const std::shared_ptr<mir::scene::PromptSessionManager> &promptSessionManager, | 74 | const std::shared_ptr<mir::scene::PromptSessionManager> &promptSessionManager) : |
2904 | 75 | const std::shared_ptr<mir::shell::DisplayLayout> &displayLayout) : | ||
2906 | 76 | AbstractShell(inputTargeter, surfaceCoordinator, sessionCoordinator, promptSessionManager, | 75 | AbstractShell(inputTargeter, surfaceCoordinator, sessionCoordinator, promptSessionManager, |
2909 | 77 | [](mir::shell::FocusController*) { return std::make_shared<NullWindowManager>(); }), | 76 | [](mir::shell::FocusController*) { return std::make_shared<NullWindowManager>(); }) |
2908 | 78 | m_displayLayout{displayLayout} | ||
2910 | 79 | { | 77 | { |
2911 | 80 | qCDebug(QTMIR_MIR_MESSAGES) << "MirShell::MirShell"; | 78 | qCDebug(QTMIR_MIR_MESSAGES) << "MirShell::MirShell"; |
2912 | 81 | } | 79 | } |
2913 | 82 | 80 | ||
2915 | 83 | mir::frontend::SurfaceId MirShell::create_surface(const std::shared_ptr<ms::Session> &session, const ms::SurfaceCreationParameters &requestParameters) | 81 | mir::frontend::SurfaceId MirShell::create_surface(const std::shared_ptr<ms::Session> &session, |
2916 | 82 | const ms::SurfaceCreationParameters &requestParameters) | ||
2917 | 84 | { | 83 | { |
2918 | 84 | using namespace mir::geometry; | ||
2919 | 85 | using namespace qtmir; | ||
2920 | 85 | tracepoint(qtmirserver, surfacePlacementStart); | 86 | tracepoint(qtmirserver, surfacePlacementStart); |
2921 | 86 | 87 | ||
2940 | 87 | // TODO: Callback unity8 so that it can make a decision on that. | 88 | SurfaceParameters params; |
2941 | 88 | // unity8 must bear in mind that the called function will be on a Mir thread though. | 89 | params.geometry.setWidth(requestParameters.size.width.as_int()); |
2942 | 89 | // The QPA shouldn't be deciding for itself on such things. | 90 | params.geometry.setHeight(requestParameters.size.height.as_int()); |
2943 | 90 | 91 | if (requestParameters.state.is_set()) { | |
2944 | 91 | ms::SurfaceCreationParameters placedParameters = requestParameters; | 92 | params.state = static_cast<Globals::SurfaceState>(requestParameters.state.value()); |
2945 | 92 | 93 | } else { | |
2946 | 93 | // Just make it fullscreen for now | 94 | params.state = Globals::SurfaceState::Unknown; |
2947 | 94 | mir::geometry::Rectangle rect{requestParameters.top_left, requestParameters.size}; | 95 | } |
2948 | 95 | m_displayLayout->size_to_output(rect); | 96 | |
2949 | 96 | placedParameters.size = rect.size; | 97 | Q_EMIT sessionAboutToCreateSurface(session, params); // can be connected to via Qt::BlockingQueuedConnection |
2950 | 97 | 98 | // to alter surface initial geometry and state | |
2951 | 98 | qCDebug(QTMIR_MIR_MESSAGES) << "MirShell::create_surface(): size requested (" | 99 | |
2952 | 99 | << requestParameters.size.width.as_int() << "," << requestParameters.size.height.as_int() << ") and placed (" | 100 | ms::SurfaceCreationParameters placedParameters = requestParameters; |
2953 | 100 | << placedParameters.size.width.as_int() << "," << placedParameters.size.height.as_int() << ")"; | 101 | placedParameters.size = Size{ Width{params.geometry.width()}, Height{params.geometry.height()} }; |
2954 | 101 | 102 | ||
2955 | 102 | tracepoint(qtmirserver, surfacePlacementEnd); | 103 | qCDebug(QTMIR_MIR_MESSAGES) << "MirPlacementStrategy: requested (" |
2956 | 103 | 104 | << requestParameters.size.width.as_int() << "," << requestParameters.size.height.as_int() << ") and returned (" | |
2957 | 104 | return AbstractShell::create_surface(session, placedParameters); | 105 | << placedParameters.size.width.as_int() << "," << placedParameters.size.height.as_int() << ")"; |
2958 | 106 | |||
2959 | 107 | tracepoint(qtmirserver, surfacePlacementEnd); | ||
2960 | 108 | |||
2961 | 109 | return AbstractShell::create_surface(session, placedParameters); | ||
2962 | 105 | } | 110 | } |
2963 | 106 | 111 | ||
2964 | 107 | void NullWindowManager::add_session(std::shared_ptr<ms::Session> const& /*session*/) | 112 | void NullWindowManager::add_session(std::shared_ptr<ms::Session> const& /*session*/) |
2965 | 108 | 113 | ||
2966 | === modified file 'src/platforms/mirserver/mirshell.h' | |||
2967 | --- src/platforms/mirserver/mirshell.h 2015-03-11 10:10:49 +0000 | |||
2968 | +++ src/platforms/mirserver/mirshell.h 2015-07-13 21:57:32 +0000 | |||
2969 | @@ -17,14 +17,15 @@ | |||
2970 | 17 | #ifndef QPAMIRSERVER_SHELL_H | 17 | #ifndef QPAMIRSERVER_SHELL_H |
2971 | 18 | #define QPAMIRSERVER_SHELL_H | 18 | #define QPAMIRSERVER_SHELL_H |
2972 | 19 | 19 | ||
2973 | 20 | // Mir | ||
2974 | 20 | #include <mir/shell/abstract_shell.h> | 21 | #include <mir/shell/abstract_shell.h> |
2975 | 22 | |||
2976 | 23 | // Qt | ||
2977 | 21 | #include <QObject> | 24 | #include <QObject> |
2978 | 22 | 25 | ||
2984 | 23 | namespace mir { | 26 | // local |
2985 | 24 | namespace shell { | 27 | #include "globals.h" |
2986 | 25 | class DisplayLayout; | 28 | |
2982 | 26 | } | ||
2983 | 27 | } | ||
2987 | 28 | 29 | ||
2988 | 29 | class MirShell : public QObject, public mir::shell::AbstractShell | 30 | class MirShell : public QObject, public mir::shell::AbstractShell |
2989 | 30 | { | 31 | { |
2990 | @@ -35,13 +36,16 @@ | |||
2991 | 35 | const std::shared_ptr<mir::shell::InputTargeter> &inputTargeter, | 36 | const std::shared_ptr<mir::shell::InputTargeter> &inputTargeter, |
2992 | 36 | const std::shared_ptr<mir::scene::SurfaceCoordinator> &surfaceCoordinator, | 37 | const std::shared_ptr<mir::scene::SurfaceCoordinator> &surfaceCoordinator, |
2993 | 37 | const std::shared_ptr<mir::scene::SessionCoordinator> &sessionCoordinator, | 38 | const std::shared_ptr<mir::scene::SessionCoordinator> &sessionCoordinator, |
3001 | 38 | const std::shared_ptr<mir::scene::PromptSessionManager> &promptSessionManager, | 39 | const std::shared_ptr<mir::scene::PromptSessionManager> &promptSessionManager); |
3002 | 39 | const std::shared_ptr<mir::shell::DisplayLayout> &displayLayout); | 40 | |
3003 | 40 | 41 | virtual mir::frontend::SurfaceId create_surface(const std::shared_ptr<mir::scene::Session> &session, | |
3004 | 41 | virtual mir::frontend::SurfaceId create_surface(const std::shared_ptr<mir::scene::Session>& session, const mir::scene::SurfaceCreationParameters ¶ms); | 42 | const mir::scene::SurfaceCreationParameters ¶ms); |
3005 | 42 | 43 | ||
3006 | 43 | private: | 44 | Q_SIGNALS: |
3007 | 44 | std::shared_ptr<mir::shell::DisplayLayout> const m_displayLayout; | 45 | void sessionAboutToCreateSurface(const std::shared_ptr<mir::scene::Session> &session, |
3008 | 46 | qtmir::SurfaceParameters ¶ms); // requires Qt::BlockingQueuedConnection!! | ||
3009 | 47 | |||
3010 | 48 | void surfaceAttributeChanged(mir::scene::Surface const*, const MirSurfaceAttrib, const int); | ||
3011 | 45 | }; | 49 | }; |
3012 | 46 | 50 | ||
3013 | 47 | #endif /* QPAMIRSERVER_SHELL_H */ | 51 | #endif /* QPAMIRSERVER_SHELL_H */ |
3014 | 48 | 52 | ||
3015 | === modified file 'tests/modules/Application/CMakeLists.txt' | |||
3016 | --- tests/modules/Application/CMakeLists.txt 2015-05-21 18:48:59 +0000 | |||
3017 | +++ tests/modules/Application/CMakeLists.txt 2015-07-13 21:57:32 +0000 | |||
3018 | @@ -1,9 +1,12 @@ | |||
3019 | 1 | set( | 1 | set( |
3020 | 2 | APPLICATION_TEST_SOURCES | 2 | APPLICATION_TEST_SOURCES |
3021 | 3 | application_test.cpp | 3 | application_test.cpp |
3022 | 4 | ${CMAKE_SOURCE_DIR}/tests/modules/common/qtmir_test.cpp | ||
3023 | 4 | ) | 5 | ) |
3024 | 5 | 6 | ||
3025 | 6 | include_directories( | 7 | include_directories( |
3026 | 8 | ${APPLICATION_API_INCLUDE_DIRS} | ||
3027 | 9 | ${CMAKE_SOURCE_DIR}/src/common | ||
3028 | 7 | ${CMAKE_SOURCE_DIR}/src/platforms/mirserver | 10 | ${CMAKE_SOURCE_DIR}/src/platforms/mirserver |
3029 | 8 | ${CMAKE_SOURCE_DIR}/src/modules | 11 | ${CMAKE_SOURCE_DIR}/src/modules |
3030 | 9 | ${CMAKE_SOURCE_DIR}/tests/modules/common | 12 | ${CMAKE_SOURCE_DIR}/tests/modules/common |
3031 | @@ -18,6 +21,8 @@ | |||
3032 | 18 | unityapplicationplugin | 21 | unityapplicationplugin |
3033 | 19 | qpa-mirserver | 22 | qpa-mirserver |
3034 | 20 | 23 | ||
3035 | 24 | Qt5::Test | ||
3036 | 25 | |||
3037 | 21 | ${GTEST_BOTH_LIBRARIES} | 26 | ${GTEST_BOTH_LIBRARIES} |
3038 | 22 | ${GMOCK_LIBRARIES} | 27 | ${GMOCK_LIBRARIES} |
3039 | 23 | ) | 28 | ) |
3040 | 24 | 29 | ||
3041 | === modified file 'tests/modules/Application/application_test.cpp' | |||
3042 | --- tests/modules/Application/application_test.cpp 2015-03-04 22:13:06 +0000 | |||
3043 | +++ tests/modules/Application/application_test.cpp 2015-07-13 21:57:32 +0000 | |||
3044 | @@ -20,6 +20,10 @@ | |||
3045 | 20 | 20 | ||
3046 | 21 | #include "qtmir_test.h" | 21 | #include "qtmir_test.h" |
3047 | 22 | 22 | ||
3048 | 23 | #include <mock_session.h> | ||
3049 | 24 | |||
3050 | 25 | #include <QScopedPointer> | ||
3051 | 26 | #include <QSignalSpy> | ||
3052 | 23 | 27 | ||
3053 | 24 | using namespace qtmir; | 28 | using namespace qtmir; |
3054 | 25 | 29 | ||
3055 | @@ -30,93 +34,163 @@ | |||
3056 | 30 | {} | 34 | {} |
3057 | 31 | }; | 35 | }; |
3058 | 32 | 36 | ||
3079 | 33 | TEST_F(ApplicationTests, checkFocusAcquiresWakeLock) | 37 | TEST_F(ApplicationTests, acquiresWakelockWhenRunningAndReleasesWhenSuspended) |
3080 | 34 | { | 38 | { |
3081 | 35 | using namespace ::testing; | 39 | using namespace ::testing; |
3082 | 36 | 40 | QString appId("foo-app"); | |
3083 | 37 | EXPECT_CALL(sharedWakelock, acquire(_)).Times(1); | 41 | |
3084 | 38 | 42 | auto desktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | |
3085 | 39 | startApplication(123, "app"); | 43 | ON_CALL(*desktopFileReader, loaded()).WillByDefault(Return(true)); |
3086 | 40 | applicationManager.focusApplication("app"); | 44 | |
3087 | 41 | } | 45 | QScopedPointer<Application> application(new Application( |
3088 | 42 | 46 | QSharedPointer<MockSharedWakelock>(&sharedWakelock, [](MockSharedWakelock *){}), | |
3089 | 43 | TEST_F(ApplicationTests, checkSuspendReleasesWakeLock) | 47 | desktopFileReader, QStringList(), nullptr)); |
3090 | 44 | { | 48 | |
3091 | 45 | using namespace ::testing; | 49 | application->setProcessState(Application::ProcessRunning); |
3092 | 46 | 50 | ||
3093 | 47 | auto app = startApplication(123, "app"); | 51 | NiceMock<MockSession> *session = new NiceMock<MockSession>; |
3094 | 48 | auto session = app->session(); | 52 | |
3095 | 49 | 53 | EXPECT_CALL(*session, setApplication(_)); | |
3096 | 50 | applicationManager.focusApplication("app"); | 54 | EXPECT_CALL(*session, fullscreen()).WillRepeatedly(Return(false)); |
3097 | 51 | 55 | ||
3098 | 52 | Q_EMIT session->suspended(); | 56 | application->setSession(session); |
3099 | 57 | |||
3100 | 58 | ASSERT_EQ(Application::InternalState::Starting, application->internalState()); | ||
3101 | 59 | |||
3102 | 60 | session->setState(SessionInterface::Running); | ||
3103 | 61 | |||
3104 | 62 | EXPECT_TRUE(sharedWakelock.enabled()); | ||
3105 | 63 | |||
3106 | 64 | ASSERT_EQ(Application::InternalState::Running, application->internalState()); | ||
3107 | 65 | |||
3108 | 66 | application->setRequestedState(Application::RequestedSuspended); | ||
3109 | 67 | |||
3110 | 68 | ASSERT_EQ(SessionInterface::Suspending, session->state()); | ||
3111 | 69 | ASSERT_EQ(Application::InternalState::SuspendingWaitSession, application->internalState()); | ||
3112 | 70 | |||
3113 | 71 | session->setState(SessionInterface::Suspended); | ||
3114 | 72 | |||
3115 | 73 | ASSERT_EQ(Application::InternalState::SuspendingWaitProcess, application->internalState()); | ||
3116 | 74 | |||
3117 | 75 | application->setProcessState(Application::ProcessSuspended); | ||
3118 | 76 | |||
3119 | 77 | ASSERT_EQ(Application::InternalState::Suspended, application->internalState()); | ||
3120 | 78 | |||
3121 | 53 | EXPECT_FALSE(sharedWakelock.enabled()); | 79 | EXPECT_FALSE(sharedWakelock.enabled()); |
3122 | 54 | } | 80 | } |
3123 | 55 | 81 | ||
3124 | 56 | TEST_F(ApplicationTests, checkResumeAcquiresWakeLock) | 82 | TEST_F(ApplicationTests, checkResumeAcquiresWakeLock) |
3125 | 57 | { | 83 | { |
3126 | 58 | using namespace ::testing; | 84 | using namespace ::testing; |
3134 | 59 | 85 | QString appId("foo-app"); | |
3135 | 60 | EXPECT_CALL(sharedWakelock, acquire(_)).Times(1); | 86 | |
3136 | 61 | 87 | auto desktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | |
3137 | 62 | auto app = startApplication(123, "app"); | 88 | ON_CALL(*desktopFileReader, loaded()).WillByDefault(Return(true)); |
3138 | 63 | auto session = app->session(); | 89 | |
3139 | 64 | 90 | QScopedPointer<Application> application(new Application( | |
3140 | 65 | Q_EMIT session->resumed(); | 91 | QSharedPointer<MockSharedWakelock>(&sharedWakelock, [](MockSharedWakelock *){}), |
3141 | 92 | desktopFileReader, QStringList(), nullptr)); | ||
3142 | 93 | NiceMock<MockSession> *session = new NiceMock<MockSession>; | ||
3143 | 94 | |||
3144 | 95 | // Get it running and then suspend it | ||
3145 | 96 | application->setProcessState(Application::ProcessRunning); | ||
3146 | 97 | application->setSession(session); | ||
3147 | 98 | session->setState(SessionInterface::Running); | ||
3148 | 99 | application->setRequestedState(Application::RequestedSuspended); | ||
3149 | 100 | session->setState(SessionInterface::Suspended); | ||
3150 | 101 | application->setProcessState(Application::ProcessSuspended); | ||
3151 | 102 | ASSERT_EQ(Application::InternalState::Suspended, application->internalState()); | ||
3152 | 103 | |||
3153 | 104 | EXPECT_FALSE(sharedWakelock.enabled()); | ||
3154 | 105 | |||
3155 | 106 | application->setRequestedState(Application::RequestedRunning); | ||
3156 | 107 | |||
3157 | 108 | ASSERT_EQ(Application::InternalState::Running, application->internalState()); | ||
3158 | 109 | |||
3159 | 110 | EXPECT_TRUE(sharedWakelock.enabled()); | ||
3160 | 66 | } | 111 | } |
3161 | 67 | 112 | ||
3162 | 68 | TEST_F(ApplicationTests, checkRespawnAcquiresWakeLock) | 113 | TEST_F(ApplicationTests, checkRespawnAcquiresWakeLock) |
3163 | 69 | { | 114 | { |
3164 | 70 | using namespace ::testing; | 115 | using namespace ::testing; |
3202 | 71 | 116 | QString appId("foo-app"); | |
3203 | 72 | EXPECT_CALL(sharedWakelock, acquire(_)).Times(1); | 117 | |
3204 | 73 | const QString appId = "app"; | 118 | auto desktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); |
3205 | 74 | 119 | ON_CALL(*desktopFileReader, loaded()).WillByDefault(Return(true)); | |
3206 | 75 | auto app = startApplication(123, "app"); | 120 | |
3207 | 76 | 121 | QScopedPointer<Application> application(new Application( | |
3208 | 77 | // as respawn fires startApplicationWithAppIdAndArgs again, keep gmock quiet about another call | 122 | QSharedPointer<MockSharedWakelock>(&sharedWakelock, [](MockSharedWakelock *){}), |
3209 | 78 | EXPECT_CALL(appController, startApplicationWithAppIdAndArgs(appId, _)) | 123 | desktopFileReader, QStringList(), nullptr)); |
3210 | 79 | .Times(1) | 124 | NiceMock<MockSession> *session = new NiceMock<MockSession>; |
3211 | 80 | .WillRepeatedly(Return(true)); | 125 | |
3212 | 81 | 126 | // Get it running, suspend it, and finally stop it | |
3213 | 82 | // respawn by setting app state as Stopped, delete the Session associated, then set to Running state | 127 | application->setProcessState(Application::ProcessRunning); |
3214 | 83 | app->setState(Session::State::Stopped); | 128 | application->setSession(session); |
3215 | 84 | delete app->session(); | 129 | session->setState(SessionInterface::Running); |
3216 | 85 | app->setState(Session::State::Running); | 130 | application->setRequestedState(Application::RequestedSuspended); |
3217 | 86 | } | 131 | session->setState(SessionInterface::Suspended); |
3218 | 87 | 132 | application->setProcessState(Application::ProcessSuspended); | |
3219 | 88 | TEST_F(ApplicationTests, checkDashFocusDoesNotAcquireWakeLock) | 133 | ASSERT_EQ(Application::InternalState::Suspended, application->internalState()); |
3220 | 89 | { | 134 | session->setState(SessionInterface::Stopped); |
3221 | 90 | using namespace ::testing; | 135 | application->setProcessState(Application::ProcessStopped); |
3222 | 91 | 136 | ASSERT_EQ(Application::InternalState::StoppedUnexpectedly, application->internalState()); | |
3223 | 92 | EXPECT_CALL(sharedWakelock, acquire(_)).Times(0); | 137 | |
3187 | 93 | |||
3188 | 94 | startApplication(123, "unity8-dash"); | ||
3189 | 95 | applicationManager.focusApplication("unity8-dash"); | ||
3190 | 96 | } | ||
3191 | 97 | |||
3192 | 98 | TEST_F(ApplicationTests, checkDashSuspendDoesNotImpactWakeLock) | ||
3193 | 99 | { | ||
3194 | 100 | using namespace ::testing; | ||
3195 | 101 | |||
3196 | 102 | auto app = startApplication(123, "unity8-dash"); | ||
3197 | 103 | auto session = app->session(); | ||
3198 | 104 | |||
3199 | 105 | applicationManager.focusApplication("unity8-dash"); | ||
3200 | 106 | |||
3201 | 107 | Q_EMIT session->suspended(); | ||
3224 | 108 | EXPECT_FALSE(sharedWakelock.enabled()); | 138 | EXPECT_FALSE(sharedWakelock.enabled()); |
3225 | 139 | |||
3226 | 140 | QSignalSpy spyStartProcess(application.data(), SIGNAL(startProcessRequested())); | ||
3227 | 141 | application->setRequestedState(Application::RequestedRunning); | ||
3228 | 142 | ASSERT_EQ(1, spyStartProcess.count()); | ||
3229 | 143 | application->setProcessState(Application::ProcessRunning); | ||
3230 | 144 | |||
3231 | 145 | ASSERT_EQ(Application::InternalState::Starting, application->internalState()); | ||
3232 | 146 | |||
3233 | 147 | EXPECT_TRUE(sharedWakelock.enabled()); | ||
3234 | 109 | } | 148 | } |
3235 | 110 | 149 | ||
3237 | 111 | TEST_F(ApplicationTests, checkDashResumeDoesNotAcquireWakeLock) | 150 | TEST_F(ApplicationTests, checkDashDoesNotImpactWakeLock) |
3238 | 112 | { | 151 | { |
3239 | 113 | using namespace ::testing; | 152 | using namespace ::testing; |
3240 | 153 | QString appId("unity8-dash"); | ||
3241 | 114 | 154 | ||
3242 | 115 | EXPECT_CALL(sharedWakelock, acquire(_)).Times(0); | 155 | EXPECT_CALL(sharedWakelock, acquire(_)).Times(0); |
3248 | 116 | 156 | EXPECT_CALL(sharedWakelock, release(_)).Times(0); | |
3249 | 117 | auto app = startApplication(123, "unity8-dash"); | 157 | |
3250 | 118 | auto session = app->session(); | 158 | auto desktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); |
3251 | 119 | 159 | ON_CALL(*desktopFileReader, loaded()).WillByDefault(Return(true)); | |
3252 | 120 | Q_EMIT session->resumed(); | 160 | |
3253 | 161 | QScopedPointer<Application> application(new Application( | ||
3254 | 162 | QSharedPointer<MockSharedWakelock>(&sharedWakelock, [](MockSharedWakelock *){}), | ||
3255 | 163 | desktopFileReader, QStringList(), nullptr)); | ||
3256 | 164 | |||
3257 | 165 | application->setProcessState(Application::ProcessRunning); | ||
3258 | 166 | |||
3259 | 167 | NiceMock<MockSession> *session = new NiceMock<MockSession>; | ||
3260 | 168 | |||
3261 | 169 | EXPECT_CALL(*session, setApplication(_)); | ||
3262 | 170 | EXPECT_CALL(*session, fullscreen()).WillRepeatedly(Return(false)); | ||
3263 | 171 | |||
3264 | 172 | application->setSession(session); | ||
3265 | 173 | |||
3266 | 174 | ASSERT_EQ(Application::InternalState::Starting, application->internalState()); | ||
3267 | 175 | |||
3268 | 176 | session->setState(SessionInterface::Running); | ||
3269 | 177 | |||
3270 | 178 | ASSERT_EQ(Application::InternalState::Running, application->internalState()); | ||
3271 | 179 | |||
3272 | 180 | application->setRequestedState(Application::RequestedSuspended); | ||
3273 | 181 | |||
3274 | 182 | ASSERT_EQ(SessionInterface::Suspending, session->state()); | ||
3275 | 183 | ASSERT_EQ(Application::InternalState::SuspendingWaitSession, application->internalState()); | ||
3276 | 184 | |||
3277 | 185 | session->setState(SessionInterface::Suspended); | ||
3278 | 186 | |||
3279 | 187 | ASSERT_EQ(Application::InternalState::SuspendingWaitProcess, application->internalState()); | ||
3280 | 188 | |||
3281 | 189 | application->setProcessState(Application::ProcessSuspended); | ||
3282 | 190 | |||
3283 | 191 | ASSERT_EQ(Application::InternalState::Suspended, application->internalState()); | ||
3284 | 192 | |||
3285 | 193 | application->setRequestedState(Application::RequestedRunning); | ||
3286 | 194 | |||
3287 | 195 | ASSERT_EQ(Application::InternalState::Running, application->internalState()); | ||
3288 | 121 | } | 196 | } |
3289 | 122 | |||
3290 | 123 | 197 | ||
3291 | === modified file 'tests/modules/ApplicationManager/CMakeLists.txt' | |||
3292 | --- tests/modules/ApplicationManager/CMakeLists.txt 2015-05-21 18:48:59 +0000 | |||
3293 | +++ tests/modules/ApplicationManager/CMakeLists.txt 2015-07-13 21:57:32 +0000 | |||
3294 | @@ -2,9 +2,13 @@ | |||
3295 | 2 | APPLICATION_MANAGER_TEST_SOURCES | 2 | APPLICATION_MANAGER_TEST_SOURCES |
3296 | 3 | application_manager_test.cpp | 3 | application_manager_test.cpp |
3297 | 4 | ${CMAKE_SOURCE_DIR}/src/common/debughelpers.cpp | 4 | ${CMAKE_SOURCE_DIR}/src/common/debughelpers.cpp |
3298 | 5 | ${CMAKE_SOURCE_DIR}/tests/modules/common/qtmir_test.cpp | ||
3299 | 6 | ../common/fake_mirsurfaceitem.h | ||
3300 | 5 | ) | 7 | ) |
3301 | 6 | 8 | ||
3302 | 7 | include_directories( | 9 | include_directories( |
3303 | 10 | ${APPLICATION_API_INCLUDE_DIRS} | ||
3304 | 11 | ${CMAKE_SOURCE_DIR}/src/common | ||
3305 | 8 | ${CMAKE_SOURCE_DIR}/src/platforms/mirserver | 12 | ${CMAKE_SOURCE_DIR}/src/platforms/mirserver |
3306 | 9 | ${CMAKE_SOURCE_DIR}/src/modules | 13 | ${CMAKE_SOURCE_DIR}/src/modules |
3307 | 10 | ${CMAKE_SOURCE_DIR}/tests/modules/common | 14 | ${CMAKE_SOURCE_DIR}/tests/modules/common |
3308 | @@ -15,7 +19,7 @@ | |||
3309 | 15 | 19 | ||
3310 | 16 | target_link_libraries( | 20 | target_link_libraries( |
3311 | 17 | applicationmanager_test | 21 | applicationmanager_test |
3313 | 18 | 22 | ||
3314 | 19 | qpa-mirserver | 23 | qpa-mirserver |
3315 | 20 | unityapplicationplugin | 24 | unityapplicationplugin |
3316 | 21 | 25 | ||
3317 | 22 | 26 | ||
3318 | === modified file 'tests/modules/ApplicationManager/application_manager_test.cpp' | |||
3319 | --- tests/modules/ApplicationManager/application_manager_test.cpp 2015-05-13 17:18:45 +0000 | |||
3320 | +++ tests/modules/ApplicationManager/application_manager_test.cpp 2015-07-13 21:57:32 +0000 | |||
3321 | @@ -1,5 +1,5 @@ | |||
3322 | 1 | /* | 1 | /* |
3324 | 2 | * Copyright (C) 2013 Canonical, Ltd. | 2 | * Copyright (C) 2013-2015 Canonical, Ltd. |
3325 | 3 | * | 3 | * |
3326 | 4 | * This program is free software: you can redistribute it and/or modify it under | 4 | * This program is free software: you can redistribute it and/or modify it under |
3327 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | 5 | * the terms of the GNU Lesser General Public License version 3, as published by |
3328 | @@ -23,8 +23,9 @@ | |||
3329 | 23 | 23 | ||
3330 | 24 | #include <Unity/Application/applicationscreenshotprovider.h> | 24 | #include <Unity/Application/applicationscreenshotprovider.h> |
3331 | 25 | 25 | ||
3334 | 26 | #include "mock_surface.h" | 26 | #include "fake_mirsurfaceitem.h" |
3335 | 27 | #include "qtmir_test.h" | 27 | #include "mock_surface.h" |
3336 | 28 | #include "qtmir_test.h" | ||
3337 | 28 | 29 | ||
3338 | 29 | using namespace qtmir; | 30 | using namespace qtmir; |
3339 | 30 | using mir::scene::MockSession; | 31 | using mir::scene::MockSession; |
3340 | @@ -45,100 +46,41 @@ | |||
3341 | 45 | applicationManager.onSessionStopping(session); | 46 | applicationManager.onSessionStopping(session); |
3342 | 46 | sessionManager.onSessionStopping(session); | 47 | sessionManager.onSessionStopping(session); |
3343 | 47 | } | 48 | } |
3344 | 49 | inline void onSessionCreatedSurface(const mir::scene::Session *mirSession, | ||
3345 | 50 | MirSurfaceItemInterface *qmlSurface) { | ||
3346 | 51 | |||
3347 | 52 | SessionInterface* qmlSession = sessionManager.findSession(mirSession); | ||
3348 | 53 | if (qmlSession) { | ||
3349 | 54 | qmlSession->setSurface(qmlSurface); | ||
3350 | 55 | } | ||
3351 | 56 | |||
3352 | 57 | // I assume that applicationManager ignores the mirSurface parameter, so sending | ||
3353 | 58 | // a null shared pointer must suffice | ||
3354 | 59 | std::shared_ptr<mir::scene::Surface> mirSurface(nullptr); | ||
3355 | 60 | applicationManager.onSessionCreatedSurface(mirSession, mirSurface); | ||
3356 | 61 | } | ||
3357 | 62 | |||
3358 | 63 | inline void suspend(Application *application) { | ||
3359 | 64 | application->setRequestedState(Application::RequestedSuspended); | ||
3360 | 65 | ASSERT_EQ(Application::InternalState::SuspendingWaitSession, application->internalState()); | ||
3361 | 66 | static_cast<qtmir::Session*>(application->session())->doSuspend(); | ||
3362 | 67 | ASSERT_EQ(Application::InternalState::SuspendingWaitProcess, application->internalState()); | ||
3363 | 68 | applicationManager.onProcessSuspended(application->appId()); | ||
3364 | 69 | ASSERT_EQ(Application::InternalState::Suspended, application->internalState()); | ||
3365 | 70 | } | ||
3366 | 48 | }; | 71 | }; |
3367 | 49 | 72 | ||
3368 | 50 | TEST_F(ApplicationManagerTests, SuspendingAndResumingARunningApplicationResultsInOomScoreAdjustment) | ||
3369 | 51 | { | ||
3370 | 52 | using namespace ::testing; | ||
3371 | 53 | |||
3372 | 54 | const QString appId("com.canonical.does.not.exist"); | ||
3373 | 55 | |||
3374 | 56 | EXPECT_CALL(appController, startApplicationWithAppIdAndArgs(_, _)).Times(1); | ||
3375 | 57 | EXPECT_CALL(appController, findDesktopFileForAppId(appId)).Times(1); | ||
3376 | 58 | |||
3377 | 59 | EXPECT_CALL(desktopFileReaderFactory, createInstance(_, _)).Times(1); | ||
3378 | 60 | |||
3379 | 61 | auto application = applicationManager.startApplication( | ||
3380 | 62 | appId, | ||
3381 | 63 | ApplicationManager::NoFlag, | ||
3382 | 64 | QStringList()); | ||
3383 | 65 | |||
3384 | 66 | // FIXME - this is doesn't really excerise the actualt behaviour since suspend/resume should be | ||
3385 | 67 | // controlled by state changes. Requires using suspend timer. | ||
3386 | 68 | QMetaObject::invokeMethod(application, "onSessionSuspended"); | ||
3387 | 69 | QMetaObject::invokeMethod(application, "onSessionResumed"); | ||
3388 | 70 | } | ||
3389 | 71 | |||
3390 | 72 | TEST_F(ApplicationManagerTests, SuspendingAndResumingDashResultsInOomScoreAdjustment) | ||
3391 | 73 | { | ||
3392 | 74 | using namespace ::testing; | ||
3393 | 75 | |||
3394 | 76 | quint64 procId = 5921; | ||
3395 | 77 | std::shared_ptr<mir::scene::Surface> aSurface(nullptr); | ||
3396 | 78 | QByteArray cmdLine( "/usr/bin/app1 --desktop_file_hint=unity8-dash"); | ||
3397 | 79 | |||
3398 | 80 | EXPECT_CALL(procInfo,command_line(procId)) | ||
3399 | 81 | .Times(1) | ||
3400 | 82 | .WillOnce(Return(cmdLine)); | ||
3401 | 83 | |||
3402 | 84 | ON_CALL(appController,appIdHasProcessId(_,_)).WillByDefault(Return(false)); | ||
3403 | 85 | |||
3404 | 86 | bool authed = true; | ||
3405 | 87 | |||
3406 | 88 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("Oo", procId); | ||
3407 | 89 | applicationManager.authorizeSession(procId, authed); | ||
3408 | 90 | onSessionStarting(session); | ||
3409 | 91 | |||
3410 | 92 | auto application = applicationManager.findApplication("unity8-dash"); | ||
3411 | 93 | applicationManager.onSessionCreatedSurface(session.get(), aSurface); | ||
3412 | 94 | |||
3413 | 95 | // FIXME - this is doesn't really excerise the actualt behaviour since suspend/resume should be | ||
3414 | 96 | // controlled by state changes. Requires using suspend timer. | ||
3415 | 97 | QMetaObject::invokeMethod(application, "onSessionSuspended"); | ||
3416 | 98 | QMetaObject::invokeMethod(application, "onSessionResumed"); | ||
3417 | 99 | } | ||
3418 | 100 | |||
3419 | 101 | // Currently disabled as we need to make sure that we have a corresponding mir session, too. | ||
3420 | 102 | TEST_F(ApplicationManagerTests, DISABLED_FocusingRunningApplicationResultsInOomScoreAdjustment) | ||
3421 | 103 | { | ||
3422 | 104 | using namespace ::testing; | ||
3423 | 105 | |||
3424 | 106 | const QString appId("com.canonical.does.not.exist"); | ||
3425 | 107 | |||
3426 | 108 | QSet<QString> appIds; | ||
3427 | 109 | |||
3428 | 110 | for (unsigned int i = 0; i < 50; i++) | ||
3429 | 111 | { | ||
3430 | 112 | QString appIdFormat("%1.does.not.exist"); | ||
3431 | 113 | auto appId = appIdFormat.arg(i); | ||
3432 | 114 | |||
3433 | 115 | auto application = applicationManager.startApplication( | ||
3434 | 116 | appId, | ||
3435 | 117 | ApplicationManager::NoFlag, | ||
3436 | 118 | QStringList()); | ||
3437 | 119 | |||
3438 | 120 | std::shared_ptr<mir::scene::Session> mirSession = std::make_shared<MockSession>(appIdFormat.toStdString(), i); | ||
3439 | 121 | onSessionStarting( mirSession ); | ||
3440 | 122 | |||
3441 | 123 | EXPECT_NE(nullptr, application); | ||
3442 | 124 | } | ||
3443 | 125 | |||
3444 | 126 | for (auto appId : appIds) | ||
3445 | 127 | { | ||
3446 | 128 | applicationManager.focusApplication(appId); | ||
3447 | 129 | } | ||
3448 | 130 | } | ||
3449 | 131 | |||
3450 | 132 | TEST_F(ApplicationManagerTests,bug_case_1240400_second_dialer_app_fails_to_authorize_and_gets_mixed_up_with_first_one) | 73 | TEST_F(ApplicationManagerTests,bug_case_1240400_second_dialer_app_fails_to_authorize_and_gets_mixed_up_with_first_one) |
3451 | 133 | { | 74 | { |
3452 | 134 | using namespace ::testing; | 75 | using namespace ::testing; |
3453 | 135 | std::shared_ptr<mir::scene::Surface> aSurface(nullptr); | ||
3454 | 136 | quint64 firstProcId = 5921; | 76 | quint64 firstProcId = 5921; |
3455 | 137 | quint64 secondProcId = 5922; | 77 | quint64 secondProcId = 5922; |
3456 | 138 | const char dialer_app_id[] = "dialer-app"; | 78 | const char dialer_app_id[] = "dialer-app"; |
3457 | 139 | QByteArray cmdLine( "/usr/bin/dialer-app --desktop_file_hint=dialer-app"); | 79 | QByteArray cmdLine( "/usr/bin/dialer-app --desktop_file_hint=dialer-app"); |
3458 | 140 | QByteArray secondcmdLine( "/usr/bin/dialer-app"); | 80 | QByteArray secondcmdLine( "/usr/bin/dialer-app"); |
3459 | 141 | 81 | ||
3460 | 82 | FakeMirSurfaceItem *surface = new FakeMirSurfaceItem; | ||
3461 | 83 | |||
3462 | 142 | EXPECT_CALL(procInfo,command_line(firstProcId)) | 84 | EXPECT_CALL(procInfo,command_line(firstProcId)) |
3463 | 143 | .Times(1) | 85 | .Times(1) |
3464 | 144 | .WillOnce(Return(cmdLine)); | 86 | .WillOnce(Return(cmdLine)); |
3465 | @@ -150,18 +92,20 @@ | |||
3466 | 150 | 92 | ||
3467 | 151 | std::shared_ptr<mir::scene::Session> mirSession = std::make_shared<MockSession>(dialer_app_id, firstProcId); | 93 | std::shared_ptr<mir::scene::Session> mirSession = std::make_shared<MockSession>(dialer_app_id, firstProcId); |
3468 | 152 | applicationManager.authorizeSession(firstProcId, authed); | 94 | applicationManager.authorizeSession(firstProcId, authed); |
3470 | 153 | EXPECT_EQ(true, authed); | 95 | ASSERT_EQ(true, authed); |
3471 | 154 | onSessionStarting(mirSession); | 96 | onSessionStarting(mirSession); |
3475 | 155 | applicationManager.onSessionCreatedSurface(mirSession.get(),aSurface); | 97 | onSessionCreatedSurface(mirSession.get(), surface); |
3476 | 156 | Application * app = applicationManager.findApplication(dialer_app_id); | 98 | surface->drawFirstFrame(); |
3477 | 157 | EXPECT_NE(nullptr,app); | 99 | Application * application = applicationManager.findApplication(dialer_app_id); |
3478 | 100 | ASSERT_NE(nullptr,application); | ||
3479 | 101 | ASSERT_EQ(Application::InternalState::Running, application->internalState()); | ||
3480 | 158 | 102 | ||
3481 | 159 | // now a second session without desktop file is launched: | 103 | // now a second session without desktop file is launched: |
3482 | 160 | applicationManager.authorizeSession(secondProcId, authed); | 104 | applicationManager.authorizeSession(secondProcId, authed); |
3483 | 161 | applicationManager.onProcessStarting(dialer_app_id); | 105 | applicationManager.onProcessStarting(dialer_app_id); |
3484 | 162 | 106 | ||
3485 | 163 | EXPECT_FALSE(authed); | 107 | EXPECT_FALSE(authed); |
3487 | 164 | EXPECT_EQ(app,applicationManager.findApplication(dialer_app_id)); | 108 | EXPECT_EQ(application, applicationManager.findApplication(dialer_app_id)); |
3488 | 165 | } | 109 | } |
3489 | 166 | 110 | ||
3490 | 167 | TEST_F(ApplicationManagerTests,application_dies_while_starting) | 111 | TEST_F(ApplicationManagerTests,application_dies_while_starting) |
3491 | @@ -182,6 +126,7 @@ | |||
3492 | 182 | onSessionStarting(mirSession); | 126 | onSessionStarting(mirSession); |
3493 | 183 | Application * beforeFailure = applicationManager.findApplication(app_id); | 127 | Application * beforeFailure = applicationManager.findApplication(app_id); |
3494 | 184 | applicationManager.onProcessStarting(app_id); | 128 | applicationManager.onProcessStarting(app_id); |
3495 | 129 | onSessionStopping(mirSession); | ||
3496 | 185 | applicationManager.onProcessFailed(app_id, true); | 130 | applicationManager.onProcessFailed(app_id, true); |
3497 | 186 | Application * afterFailure = applicationManager.findApplication(app_id); | 131 | Application * afterFailure = applicationManager.findApplication(app_id); |
3498 | 187 | 132 | ||
3499 | @@ -190,34 +135,6 @@ | |||
3500 | 190 | EXPECT_EQ(nullptr, afterFailure); | 135 | EXPECT_EQ(nullptr, afterFailure); |
3501 | 191 | } | 136 | } |
3502 | 192 | 137 | ||
3503 | 193 | TEST_F(ApplicationManagerTests,application_start_failure_after_starting) | ||
3504 | 194 | { | ||
3505 | 195 | using namespace ::testing; | ||
3506 | 196 | quint64 procId = 5921; | ||
3507 | 197 | std::shared_ptr<mir::scene::Surface> aSurface(nullptr); | ||
3508 | 198 | const char app_id[] = "my-app"; | ||
3509 | 199 | QByteArray cmdLine( "/usr/bin/my-app --desktop_file_hint=my-app"); | ||
3510 | 200 | |||
3511 | 201 | EXPECT_CALL(procInfo,command_line(procId)) | ||
3512 | 202 | .Times(1) | ||
3513 | 203 | .WillOnce(Return(cmdLine)); | ||
3514 | 204 | |||
3515 | 205 | bool authed = true; | ||
3516 | 206 | |||
3517 | 207 | std::shared_ptr<mir::scene::Session> mirSession = std::make_shared<MockSession>(app_id, procId); | ||
3518 | 208 | applicationManager.authorizeSession(procId, authed); | ||
3519 | 209 | onSessionStarting(mirSession); | ||
3520 | 210 | Application * beforeFailure = applicationManager.findApplication(app_id); | ||
3521 | 211 | applicationManager.onSessionCreatedSurface(mirSession.get(), aSurface); | ||
3522 | 212 | applicationManager.onProcessStarting(app_id); | ||
3523 | 213 | applicationManager.onProcessFailed(app_id, false); | ||
3524 | 214 | Application * afterFailure = applicationManager.findApplication(app_id); | ||
3525 | 215 | |||
3526 | 216 | EXPECT_EQ(true, authed); | ||
3527 | 217 | EXPECT_NE(nullptr, beforeFailure); | ||
3528 | 218 | EXPECT_EQ(beforeFailure, afterFailure); | ||
3529 | 219 | } | ||
3530 | 220 | |||
3531 | 221 | TEST_F(ApplicationManagerTests,startApplicationSupportsShortAppId) | 138 | TEST_F(ApplicationManagerTests,startApplicationSupportsShortAppId) |
3532 | 222 | { | 139 | { |
3533 | 223 | using namespace ::testing; | 140 | using namespace ::testing; |
3534 | @@ -400,7 +317,7 @@ | |||
3535 | 400 | quint64 a_procId = 5921; | 317 | quint64 a_procId = 5921; |
3536 | 401 | const char an_app_id[] = "some_app"; | 318 | const char an_app_id[] = "some_app"; |
3537 | 402 | QByteArray a_cmd( "/usr/bin/app1 --desktop_file_hint=some_app"); | 319 | QByteArray a_cmd( "/usr/bin/app1 --desktop_file_hint=some_app"); |
3539 | 403 | std::shared_ptr<mir::scene::Surface> aSurface(nullptr); | 320 | FakeMirSurfaceItem *aSurface = new FakeMirSurfaceItem; |
3540 | 404 | 321 | ||
3541 | 405 | ON_CALL(procInfo,command_line(_)).WillByDefault(Return(a_cmd)); | 322 | ON_CALL(procInfo,command_line(_)).WillByDefault(Return(a_cmd)); |
3542 | 406 | 323 | ||
3543 | @@ -413,8 +330,8 @@ | |||
3544 | 413 | applicationManager.authorizeSession(a_procId, authed); | 330 | applicationManager.authorizeSession(a_procId, authed); |
3545 | 414 | 331 | ||
3546 | 415 | onSessionStarting(first_session); | 332 | onSessionStarting(first_session); |
3549 | 416 | applicationManager.focusApplication(an_app_id); | 333 | onSessionCreatedSurface(first_session.get(), aSurface); |
3550 | 417 | applicationManager.onSessionCreatedSurface(first_session.get(), aSurface); | 334 | aSurface->drawFirstFrame(); |
3551 | 418 | onSessionStarting(second_session); | 335 | onSessionStarting(second_session); |
3552 | 419 | 336 | ||
3553 | 420 | Application * the_app = applicationManager.findApplication(an_app_id); | 337 | Application * the_app = applicationManager.findApplication(an_app_id); |
3554 | @@ -430,211 +347,62 @@ | |||
3555 | 430 | quint64 a_procId = 5921; | 347 | quint64 a_procId = 5921; |
3556 | 431 | const char an_app_id[] = "some_app"; | 348 | const char an_app_id[] = "some_app"; |
3557 | 432 | QByteArray a_cmd("/usr/bin/app1 --desktop_file_hint=some_app"); | 349 | QByteArray a_cmd("/usr/bin/app1 --desktop_file_hint=some_app"); |
3559 | 433 | std::shared_ptr<mir::scene::Surface> aSurface(nullptr); | 350 | FakeMirSurfaceItem *aSurface = new FakeMirSurfaceItem; |
3560 | 434 | 351 | ||
3561 | 435 | ON_CALL(procInfo, command_line(_)).WillByDefault(Return(a_cmd)); | 352 | ON_CALL(procInfo, command_line(_)).WillByDefault(Return(a_cmd)); |
3562 | 436 | ON_CALL(appController, appIdHasProcessId(_,_)).WillByDefault(Return(false)); | 353 | ON_CALL(appController, appIdHasProcessId(_,_)).WillByDefault(Return(false)); |
3564 | 437 | 354 | ||
3565 | 438 | bool authed = true; | 355 | bool authed = true; |
3566 | 439 | 356 | ||
3567 | 440 | std::shared_ptr<mir::scene::Session> a_session = std::make_shared<MockSession>("Oo", a_procId); | 357 | std::shared_ptr<mir::scene::Session> a_session = std::make_shared<MockSession>("Oo", a_procId); |
3569 | 441 | 358 | ||
3570 | 442 | applicationManager.authorizeSession(a_procId, authed); | 359 | applicationManager.authorizeSession(a_procId, authed); |
3571 | 443 | onSessionStarting(a_session); | 360 | onSessionStarting(a_session); |
3692 | 444 | applicationManager.onSessionCreatedSurface(a_session.get(), aSurface); | 361 | onSessionCreatedSurface(a_session.get(), aSurface); |
3693 | 445 | 362 | aSurface->drawFirstFrame(); | |
3694 | 446 | Application * the_app = applicationManager.findApplication(an_app_id); | 363 | |
3695 | 447 | applicationManager.focusApplication(an_app_id); | 364 | Application * the_app = applicationManager.findApplication(an_app_id); |
3696 | 448 | 365 | applicationManager.focusApplication(an_app_id); | |
3697 | 449 | EXPECT_EQ(Application::Running, the_app->state()); | 366 | |
3698 | 450 | EXPECT_EQ(true, the_app->focused()); | 367 | EXPECT_EQ(Application::Running, the_app->state()); |
3699 | 451 | 368 | EXPECT_EQ(true, the_app->focused()); | |
3700 | 452 | applicationManager.focusApplication(an_app_id); | 369 | |
3701 | 453 | EXPECT_EQ(true, the_app->focused()); | 370 | applicationManager.focusApplication(an_app_id); |
3702 | 454 | } | 371 | EXPECT_EQ(true, the_app->focused()); |
3703 | 455 | 372 | } | |
3704 | 456 | TEST_F(ApplicationManagerTests,suspended_suspends_focused_app_and_marks_it_unfocused_in_the_model) | 373 | |
3705 | 457 | { | 374 | TEST_F(ApplicationManagerTests,starting_app_is_suspended_when_it_gets_ready_if_requested) |
3706 | 458 | using namespace ::testing; | 375 | { |
3707 | 459 | quint64 a_procId = 5921; | 376 | using namespace ::testing; |
3708 | 460 | const char an_app_id[] = "some_app"; | 377 | quint64 procId = 5921; |
3709 | 461 | QByteArray a_cmd( "/usr/bin/app1 --desktop_file_hint=some_app"); | 378 | FakeMirSurfaceItem *aSurface = new FakeMirSurfaceItem; |
3710 | 462 | std::shared_ptr<mir::scene::Surface> aSurface(nullptr); | 379 | QByteArray cmdLine( "/usr/bin/app --desktop_file_hint=app"); |
3711 | 463 | 380 | ||
3712 | 464 | ON_CALL(procInfo,command_line(_)).WillByDefault(Return(a_cmd)); | 381 | EXPECT_CALL(procInfo,command_line(procId)) |
3713 | 465 | 382 | .Times(1) | |
3714 | 466 | ON_CALL(appController,appIdHasProcessId(_,_)).WillByDefault(Return(false)); | 383 | .WillOnce(Return(cmdLine)); |
3715 | 467 | 384 | ||
3716 | 468 | bool authed = true; | 385 | ON_CALL(appController,appIdHasProcessId(_,_)).WillByDefault(Return(false)); |
3717 | 469 | 386 | ||
3718 | 470 | std::shared_ptr<mir::scene::Session> first_session = std::make_shared<MockSession>("Oo", a_procId); | 387 | bool authed = true; |
3719 | 471 | std::shared_ptr<mir::scene::Session> second_session = std::make_shared<MockSession>("oO", a_procId); | 388 | |
3720 | 472 | applicationManager.authorizeSession(a_procId, authed); | 389 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("Oo", procId); |
3721 | 473 | 390 | applicationManager.authorizeSession(procId, authed); | |
3722 | 474 | onSessionStarting(first_session); | 391 | onSessionStarting(session); |
3723 | 475 | applicationManager.onSessionCreatedSurface(first_session.get(), aSurface); | 392 | |
3724 | 476 | onSessionStarting(second_session); | 393 | Application * app = applicationManager.findApplication("app"); |
3725 | 477 | 394 | app->setRequestedState(Application::RequestedSuspended); | |
3606 | 478 | Application * the_app = applicationManager.findApplication(an_app_id); | ||
3607 | 479 | applicationManager.focusApplication(an_app_id); | ||
3608 | 480 | |||
3609 | 481 | EXPECT_EQ(Application::Running, the_app->state()); | ||
3610 | 482 | |||
3611 | 483 | applicationManager.setSuspended(true); | ||
3612 | 484 | |||
3613 | 485 | EXPECT_EQ(Application::Suspended, the_app->state()); | ||
3614 | 486 | EXPECT_FALSE(the_app->focused()); | ||
3615 | 487 | |||
3616 | 488 | applicationManager.setSuspended(false); | ||
3617 | 489 | |||
3618 | 490 | EXPECT_EQ(Application::Running, the_app->state()); | ||
3619 | 491 | EXPECT_EQ(true, the_app->focused()); | ||
3620 | 492 | } | ||
3621 | 493 | |||
3622 | 494 | TEST_F(ApplicationManagerTests,suspended_suspends_starting_app_when_it_gets_ready) | ||
3623 | 495 | { | ||
3624 | 496 | using namespace ::testing; | ||
3625 | 497 | quint64 a_procId = 5921; | ||
3626 | 498 | const char an_app_id[] = "some_app"; | ||
3627 | 499 | QByteArray a_cmd( "/usr/bin/app1 --desktop_file_hint=some_app"); | ||
3628 | 500 | std::shared_ptr<mir::scene::Surface> aSurface(nullptr); | ||
3629 | 501 | |||
3630 | 502 | ON_CALL(procInfo,command_line(_)).WillByDefault(Return(a_cmd)); | ||
3631 | 503 | |||
3632 | 504 | ON_CALL(appController,appIdHasProcessId(_,_)).WillByDefault(Return(false)); | ||
3633 | 505 | |||
3634 | 506 | bool authed = true; | ||
3635 | 507 | |||
3636 | 508 | std::shared_ptr<mir::scene::Session> first_session = std::make_shared<MockSession>("Oo", a_procId); | ||
3637 | 509 | applicationManager.authorizeSession(a_procId, authed); | ||
3638 | 510 | |||
3639 | 511 | onSessionStarting(first_session); | ||
3640 | 512 | |||
3641 | 513 | Application * the_app = applicationManager.findApplication(an_app_id); | ||
3642 | 514 | applicationManager.focusApplication(an_app_id); | ||
3643 | 515 | EXPECT_EQ(Application::Starting, the_app->state()); | ||
3644 | 516 | |||
3645 | 517 | applicationManager.setSuspended(true); | ||
3646 | 518 | |||
3647 | 519 | // Not suspending yet, as it's still starting | ||
3648 | 520 | EXPECT_EQ(Application::Starting, the_app->state()); | ||
3649 | 521 | |||
3650 | 522 | // This signals the app is ready now | ||
3651 | 523 | applicationManager.onSessionCreatedSurface(first_session.get(), aSurface); | ||
3652 | 524 | |||
3653 | 525 | // And given that the AppManager is suspended now, this should go to suspended too | ||
3654 | 526 | EXPECT_EQ(Application::Suspended, the_app->state()); | ||
3655 | 527 | EXPECT_FALSE(the_app->focused()); | ||
3656 | 528 | |||
3657 | 529 | applicationManager.setSuspended(false); | ||
3658 | 530 | |||
3659 | 531 | EXPECT_EQ(Application::Running, the_app->state()); | ||
3660 | 532 | EXPECT_EQ(true, the_app->focused()); | ||
3661 | 533 | } | ||
3662 | 534 | |||
3663 | 535 | TEST_F(ApplicationManagerTests,focus_change_suspends_starting_app_when_it_gets_ready) | ||
3664 | 536 | { | ||
3665 | 537 | using namespace ::testing; | ||
3666 | 538 | quint64 first_procId = 5921; | ||
3667 | 539 | quint64 second_procId = 5922; | ||
3668 | 540 | std::shared_ptr<mir::scene::Surface> aSurface(nullptr); | ||
3669 | 541 | QByteArray first_cmdLine( "/usr/bin/app1 --desktop_file_hint=app1"); | ||
3670 | 542 | QByteArray second_cmdLine( "/usr/bin/app2--desktop_file_hint=app2"); | ||
3671 | 543 | |||
3672 | 544 | EXPECT_CALL(procInfo,command_line(first_procId)) | ||
3673 | 545 | .Times(1) | ||
3674 | 546 | .WillOnce(Return(first_cmdLine)); | ||
3675 | 547 | |||
3676 | 548 | ON_CALL(appController,appIdHasProcessId(_,_)).WillByDefault(Return(false)); | ||
3677 | 549 | |||
3678 | 550 | EXPECT_CALL(procInfo,command_line(second_procId)) | ||
3679 | 551 | .Times(1) | ||
3680 | 552 | .WillOnce(Return(second_cmdLine)); | ||
3681 | 553 | |||
3682 | 554 | bool authed = true; | ||
3683 | 555 | |||
3684 | 556 | std::shared_ptr<mir::scene::Session> first_session = std::make_shared<MockSession>("Oo", first_procId); | ||
3685 | 557 | std::shared_ptr<mir::scene::Session> second_session = std::make_shared<MockSession>("oO", second_procId); | ||
3686 | 558 | applicationManager.authorizeSession(first_procId, authed); | ||
3687 | 559 | applicationManager.authorizeSession(second_procId, authed); | ||
3688 | 560 | onSessionStarting(first_session); | ||
3689 | 561 | |||
3690 | 562 | Application * app1 = applicationManager.findApplication("app1"); | ||
3691 | 563 | applicationManager.focusApplication("app1"); | ||
3726 | 564 | 395 | ||
3727 | 565 | // First app starting... | 396 | // First app starting... |
3800 | 566 | EXPECT_EQ(Application::Starting, app1->state()); | 397 | EXPECT_EQ(Application::Starting, app->state()); |
3801 | 567 | 398 | ||
3802 | 568 | onSessionStarting(second_session); | 399 | // Signal app is ready now |
3803 | 569 | Application * app2 = applicationManager.findApplication("app2"); | 400 | applicationManager.onProcessStarting("app"); |
3804 | 570 | applicationManager.focusApplication("app2"); | 401 | onSessionCreatedSurface(session.get(), aSurface); |
3805 | 571 | 402 | aSurface->drawFirstFrame(); | |
3806 | 572 | // Second app starting... | 403 | |
3807 | 573 | EXPECT_EQ(Application::Starting, app2->state()); | 404 | // now that its ready, suspend process should have begun |
3808 | 574 | 405 | EXPECT_EQ(Application::InternalState::SuspendingWaitSession, app->internalState()); | |
3737 | 575 | // Make sure first one is still in starting state | ||
3738 | 576 | EXPECT_EQ(Application::Starting, app1->state()); | ||
3739 | 577 | |||
3740 | 578 | // Signal app1 is ready now | ||
3741 | 579 | applicationManager.onSessionCreatedSurface(first_session.get(), aSurface); | ||
3742 | 580 | |||
3743 | 581 | // Make sure AppMan suspended it now that its ready | ||
3744 | 582 | EXPECT_EQ(Application::Suspended, app1->state()); | ||
3745 | 583 | } | ||
3746 | 584 | |||
3747 | 585 | TEST_F(ApplicationManagerTests,forceDashActive_activates_dash_while_not_focused) | ||
3748 | 586 | { | ||
3749 | 587 | using namespace ::testing; | ||
3750 | 588 | quint64 first_procId = 5921; | ||
3751 | 589 | quint64 second_procId = 5922; | ||
3752 | 590 | std::shared_ptr<mir::scene::Surface> aSurface(nullptr); | ||
3753 | 591 | QByteArray first_cmdLine( "/usr/bin/app1 --desktop_file_hint=unity8-dash"); | ||
3754 | 592 | QByteArray second_cmdLine( "/usr/bin/app2--desktop_file_hint=app2"); | ||
3755 | 593 | |||
3756 | 594 | EXPECT_CALL(procInfo,command_line(first_procId)) | ||
3757 | 595 | .Times(1) | ||
3758 | 596 | .WillOnce(Return(first_cmdLine)); | ||
3759 | 597 | |||
3760 | 598 | ON_CALL(appController,appIdHasProcessId(_,_)).WillByDefault(Return(false)); | ||
3761 | 599 | |||
3762 | 600 | EXPECT_CALL(procInfo,command_line(second_procId)) | ||
3763 | 601 | .Times(1) | ||
3764 | 602 | .WillOnce(Return(second_cmdLine)); | ||
3765 | 603 | |||
3766 | 604 | bool authed = true; | ||
3767 | 605 | |||
3768 | 606 | std::shared_ptr<mir::scene::Session> first_session = std::make_shared<MockSession>("Oo", first_procId); | ||
3769 | 607 | std::shared_ptr<mir::scene::Session> second_session = std::make_shared<MockSession>("oO", second_procId); | ||
3770 | 608 | applicationManager.authorizeSession(first_procId, authed); | ||
3771 | 609 | applicationManager.authorizeSession(second_procId, authed); | ||
3772 | 610 | onSessionStarting(first_session); | ||
3773 | 611 | |||
3774 | 612 | Application * dashApp = applicationManager.findApplication("unity8-dash"); | ||
3775 | 613 | applicationManager.onSessionCreatedSurface(first_session.get(), aSurface); | ||
3776 | 614 | applicationManager.focusApplication("unity8-dash"); | ||
3777 | 615 | |||
3778 | 616 | // Dash app should be ready now... | ||
3779 | 617 | EXPECT_EQ(Application::Running, dashApp->state()); | ||
3780 | 618 | |||
3781 | 619 | // Launch second app | ||
3782 | 620 | onSessionStarting(second_session); | ||
3783 | 621 | applicationManager.onSessionCreatedSurface(second_session.get(), aSurface); | ||
3784 | 622 | applicationManager.focusApplication("app2"); | ||
3785 | 623 | EXPECT_EQ(applicationManager.focusedApplicationId(), "app2"); | ||
3786 | 624 | |||
3787 | 625 | // Make sure the dash is suspended | ||
3788 | 626 | EXPECT_EQ(dashApp->state(), Application::Suspended); | ||
3789 | 627 | |||
3790 | 628 | // Now set the dashactive flag | ||
3791 | 629 | applicationManager.setForceDashActive(true); | ||
3792 | 630 | |||
3793 | 631 | // And make sure the dash is woken up but not focused | ||
3794 | 632 | EXPECT_EQ(applicationManager.focusedApplicationId(), "app2"); | ||
3795 | 633 | EXPECT_EQ(dashApp->state(), Application::Running); | ||
3796 | 634 | |||
3797 | 635 | // Unset the dashactive flag | ||
3798 | 636 | applicationManager.setForceDashActive(false); | ||
3799 | 637 | EXPECT_EQ(dashApp->state(), Application::Suspended); | ||
3809 | 638 | } | 406 | } |
3810 | 639 | 407 | ||
3811 | 640 | TEST_F(ApplicationManagerTests,requestFocusApplication) | 408 | TEST_F(ApplicationManagerTests,requestFocusApplication) |
3812 | @@ -713,20 +481,20 @@ | |||
3813 | 713 | Application *theApp = applicationManager.startApplication(appId, ApplicationManager::NoFlag); | 481 | Application *theApp = applicationManager.startApplication(appId, ApplicationManager::NoFlag); |
3814 | 714 | 482 | ||
3815 | 715 | // check application data | 483 | // check application data |
3820 | 716 | EXPECT_EQ(theApp->state(), Application::Starting); | 484 | EXPECT_EQ(Application::Starting, theApp->state()); |
3821 | 717 | EXPECT_EQ(theApp->appId(), appId); | 485 | EXPECT_EQ(appId, theApp->appId()); |
3822 | 718 | EXPECT_EQ(theApp->name(), name); | 486 | EXPECT_EQ(name, theApp->name()); |
3823 | 719 | EXPECT_EQ(theApp->canBeResumed(), true); | 487 | EXPECT_FALSE(theApp->canBeResumed()); |
3824 | 720 | 488 | ||
3825 | 721 | // check signals were emitted | 489 | // check signals were emitted |
3830 | 722 | EXPECT_EQ(countSpy.count(), 2); //FIXME(greyback) | 490 | EXPECT_EQ(2, countSpy.count()); //FIXME(greyback) |
3831 | 723 | EXPECT_EQ(applicationManager.count(), 1); | 491 | EXPECT_EQ(1, applicationManager.count()); |
3832 | 724 | EXPECT_EQ(addedSpy.count(), 1); | 492 | EXPECT_EQ(1, addedSpy.count()); |
3833 | 725 | EXPECT_EQ(addedSpy.takeFirst().at(0).toString(), appId); | 493 | EXPECT_EQ(appId, addedSpy.takeFirst().at(0).toString()); |
3834 | 726 | 494 | ||
3835 | 727 | // check application in list of apps | 495 | // check application in list of apps |
3836 | 728 | Application *theAppAgain = applicationManager.findApplication(appId); | 496 | Application *theAppAgain = applicationManager.findApplication(appId); |
3838 | 729 | EXPECT_EQ(theAppAgain, theApp); | 497 | EXPECT_EQ(theApp, theAppAgain); |
3839 | 730 | } | 498 | } |
3840 | 731 | 499 | ||
3841 | 732 | /* | 500 | /* |
3842 | @@ -757,18 +525,18 @@ | |||
3843 | 757 | Application *theApp = applicationManager.findApplication(appId); | 525 | Application *theApp = applicationManager.findApplication(appId); |
3844 | 758 | 526 | ||
3845 | 759 | // check application data | 527 | // check application data |
3850 | 760 | EXPECT_EQ(theApp->state(), Application::Starting); | 528 | EXPECT_EQ(Application::Starting, theApp->state()); |
3851 | 761 | EXPECT_EQ(theApp->appId(), appId); | 529 | EXPECT_EQ(appId, theApp->appId()); |
3852 | 762 | EXPECT_EQ(theApp->name(), name); | 530 | EXPECT_EQ(name, theApp->name()); |
3853 | 763 | EXPECT_EQ(theApp->canBeResumed(), true); | 531 | EXPECT_EQ(true, theApp->canBeResumed()); |
3854 | 764 | 532 | ||
3855 | 765 | // check signals were emitted | 533 | // check signals were emitted |
3862 | 766 | EXPECT_EQ(countSpy.count(), 2); //FIXME(greyback) | 534 | EXPECT_EQ(2, countSpy.count()); //FIXME(greyback) |
3863 | 767 | EXPECT_EQ(applicationManager.count(), 1); | 535 | EXPECT_EQ(1, applicationManager.count()); |
3864 | 768 | EXPECT_EQ(addedSpy.count(), 1); | 536 | EXPECT_EQ(1, addedSpy.count()); |
3865 | 769 | EXPECT_EQ(addedSpy.takeFirst().at(0).toString(), appId); | 537 | EXPECT_EQ(appId, addedSpy.takeFirst().at(0).toString()); |
3866 | 770 | EXPECT_EQ(focusSpy.count(), 1); | 538 | EXPECT_EQ(1, focusSpy.count()); |
3867 | 771 | EXPECT_EQ(focusSpy.takeFirst().at(0).toString(), appId); | 539 | EXPECT_EQ(appId, focusSpy.takeFirst().at(0).toString()); |
3868 | 772 | } | 540 | } |
3869 | 773 | 541 | ||
3870 | 774 | /* | 542 | /* |
3871 | @@ -1067,7 +835,6 @@ | |||
3872 | 1067 | 835 | ||
3873 | 1068 | applicationManager.startApplication(appId, ApplicationManager::NoFlag); | 836 | applicationManager.startApplication(appId, ApplicationManager::NoFlag); |
3874 | 1069 | applicationManager.onProcessStarting(appId); | 837 | applicationManager.onProcessStarting(appId); |
3875 | 1070 | applicationManager.focusApplication(appId); | ||
3876 | 1071 | 838 | ||
3877 | 1072 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); | 839 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); |
3878 | 1073 | 840 | ||
3879 | @@ -1075,9 +842,10 @@ | |||
3880 | 1075 | applicationManager.authorizeSession(procId, authed); | 842 | applicationManager.authorizeSession(procId, authed); |
3881 | 1076 | onSessionStarting(session); | 843 | onSessionStarting(session); |
3882 | 1077 | 844 | ||
3884 | 1078 | std::shared_ptr<mir::scene::Surface> surface(nullptr); | 845 | FakeMirSurfaceItem *surface = new FakeMirSurfaceItem; |
3885 | 1079 | 846 | ||
3887 | 1080 | applicationManager.onSessionCreatedSurface(session.get(), surface); | 847 | onSessionCreatedSurface(session.get(), surface); |
3888 | 848 | surface->drawFirstFrame(); | ||
3889 | 1081 | 849 | ||
3890 | 1082 | // Check application state is correctly set | 850 | // Check application state is correctly set |
3891 | 1083 | Application *theApp = applicationManager.findApplication(appId); | 851 | Application *theApp = applicationManager.findApplication(appId); |
3892 | @@ -1124,7 +892,7 @@ | |||
3893 | 1124 | } | 892 | } |
3894 | 1125 | 893 | ||
3895 | 1126 | /* | 894 | /* |
3897 | 1127 | * Test that the foreground application is stopped correctly (is in Running state, has surface) | 895 | * Test that a running application is stopped correctly (is in Running state, has surface) |
3898 | 1128 | */ | 896 | */ |
3899 | 1129 | TEST_F(ApplicationManagerTests,shellStopsForegroundAppCorrectly) | 897 | TEST_F(ApplicationManagerTests,shellStopsForegroundAppCorrectly) |
3900 | 1130 | { | 898 | { |
3901 | @@ -1150,100 +918,61 @@ | |||
3902 | 1150 | applicationManager.authorizeSession(procId, authed); | 918 | applicationManager.authorizeSession(procId, authed); |
3903 | 1151 | onSessionStarting(session); | 919 | onSessionStarting(session); |
3904 | 1152 | 920 | ||
3999 | 1153 | std::shared_ptr<mir::scene::Surface> surface(nullptr); | 921 | FakeMirSurfaceItem *surface = new FakeMirSurfaceItem; |
4000 | 1154 | applicationManager.onSessionCreatedSurface(session.get(), surface); | 922 | onSessionCreatedSurface(session.get(), surface); |
4001 | 1155 | applicationManager.focusApplication(appId); | 923 | surface->drawFirstFrame(); |
4002 | 1156 | EXPECT_EQ(applicationManager.focusedApplicationId(), appId); | 924 | |
4003 | 1157 | 925 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); | |
4004 | 1158 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); | 926 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); |
4005 | 1159 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); | 927 | |
4006 | 1160 | 928 | // Stop app | |
4007 | 1161 | // Stop app | 929 | applicationManager.stopApplication(appId); |
4008 | 1162 | applicationManager.stopApplication(appId); | 930 | |
4009 | 1163 | 931 | EXPECT_EQ(countSpy.count(), 2); //FIXME(greyback) | |
4010 | 1164 | EXPECT_EQ(countSpy.count(), 2); //FIXME(greyback) | 932 | EXPECT_EQ(applicationManager.count(), 0); |
4011 | 1165 | EXPECT_EQ(applicationManager.count(), 0); | 933 | EXPECT_EQ(removedSpy.count(), 1); |
4012 | 1166 | EXPECT_EQ(removedSpy.count(), 1); | 934 | EXPECT_EQ(removedSpy.takeFirst().at(0).toString(), appId); |
4013 | 1167 | EXPECT_EQ(removedSpy.takeFirst().at(0).toString(), appId); | 935 | } |
4014 | 1168 | } | 936 | |
4015 | 1169 | 937 | /* | |
4016 | 1170 | /* | 938 | * Test that a suspended application is stopped correctly |
4017 | 1171 | * Test that the background application is stopped correctly | 939 | */ |
4018 | 1172 | */ | 940 | TEST_F(ApplicationManagerTests,shellStopsSuspendedAppCorrectly) |
4019 | 1173 | TEST_F(ApplicationManagerTests,shellStopsBackgroundAppCorrectly) | 941 | { |
4020 | 1174 | { | 942 | using namespace ::testing; |
4021 | 1175 | using namespace ::testing; | 943 | const QString appId("testAppId"); |
4022 | 1176 | const QString appId("testAppId"); | 944 | quint64 procId = 5551; |
4023 | 1177 | quint64 procId = 5551; | 945 | |
4024 | 1178 | 946 | // Set up Mocks & signal watcher | |
4025 | 1179 | // Set up Mocks & signal watcher | 947 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); |
4026 | 1180 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | 948 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); |
4027 | 1181 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | 949 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); |
4028 | 1182 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | 950 | |
4029 | 1183 | 951 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | |
4030 | 1184 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | 952 | |
4031 | 1185 | 953 | EXPECT_CALL(appController, startApplicationWithAppIdAndArgs(appId, _)) | |
4032 | 1186 | EXPECT_CALL(appController, startApplicationWithAppIdAndArgs(appId, _)) | 954 | .Times(1) |
4033 | 1187 | .Times(1) | 955 | .WillOnce(Return(true)); |
4034 | 1188 | .WillOnce(Return(true)); | 956 | |
4035 | 1189 | 957 | Application *application = applicationManager.startApplication(appId, ApplicationManager::NoFlag); | |
4036 | 1190 | applicationManager.startApplication(appId, ApplicationManager::NoFlag); | 958 | applicationManager.onProcessStarting(appId); |
4037 | 1191 | applicationManager.onProcessStarting(appId); | 959 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); |
4038 | 1192 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); | 960 | bool authed = true; |
4039 | 1193 | bool authed = true; | 961 | applicationManager.authorizeSession(procId, authed); |
4040 | 1194 | applicationManager.authorizeSession(procId, authed); | 962 | onSessionStarting(session); |
4041 | 1195 | onSessionStarting(session); | 963 | applicationManager.onProcessStarting(appId); |
4042 | 1196 | 964 | ||
4043 | 1197 | std::shared_ptr<mir::scene::Surface> surface(nullptr); | 965 | FakeMirSurfaceItem *surface = new FakeMirSurfaceItem; |
4044 | 1198 | applicationManager.onSessionCreatedSurface(session.get(), surface); | 966 | onSessionCreatedSurface(session.get(), surface); |
4045 | 1199 | applicationManager.unfocusCurrentApplication(); | 967 | surface->drawFirstFrame(); |
4046 | 1200 | 968 | ||
4047 | 1201 | EXPECT_EQ(applicationManager.focusedApplicationId(), QString()); | 969 | suspend(application); |
4048 | 1202 | 970 | ||
4049 | 1203 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); | 971 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); |
4050 | 1204 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); | 972 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); |
4051 | 1205 | 973 | ||
4052 | 1206 | // Stop app | 974 | // Stop app |
4053 | 1207 | applicationManager.stopApplication(appId); | 975 | applicationManager.stopApplication(appId); |
3960 | 1208 | |||
3961 | 1209 | EXPECT_EQ(countSpy.count(), 2); //FIXME(greyback) | ||
3962 | 1210 | EXPECT_EQ(applicationManager.count(), 0); | ||
3963 | 1211 | EXPECT_EQ(removedSpy.count(), 1); | ||
3964 | 1212 | EXPECT_EQ(removedSpy.takeFirst().at(0).toString(), appId); | ||
3965 | 1213 | } | ||
3966 | 1214 | |||
3967 | 1215 | /* | ||
3968 | 1216 | * Test that if an application is stopped by upstart, before it has created a surface, AppMan cleans up after it ok | ||
3969 | 1217 | */ | ||
3970 | 1218 | TEST_F(ApplicationManagerTests,upstartNotificationOfStartingAppBeingStopped) | ||
3971 | 1219 | { | ||
3972 | 1220 | using namespace ::testing; | ||
3973 | 1221 | const QString appId("testAppId"); | ||
3974 | 1222 | quint64 procId = 5551; | ||
3975 | 1223 | |||
3976 | 1224 | // Set up Mocks & signal watcher | ||
3977 | 1225 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | ||
3978 | 1226 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | ||
3979 | 1227 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
3980 | 1228 | |||
3981 | 1229 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
3982 | 1230 | |||
3983 | 1231 | EXPECT_CALL(appController, startApplicationWithAppIdAndArgs(appId, _)) | ||
3984 | 1232 | .Times(1) | ||
3985 | 1233 | .WillOnce(Return(true)); | ||
3986 | 1234 | |||
3987 | 1235 | applicationManager.startApplication(appId, ApplicationManager::NoFlag); | ||
3988 | 1236 | applicationManager.onProcessStarting(appId); | ||
3989 | 1237 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); | ||
3990 | 1238 | bool authed = true; | ||
3991 | 1239 | applicationManager.authorizeSession(procId, authed); | ||
3992 | 1240 | onSessionStarting(session); | ||
3993 | 1241 | |||
3994 | 1242 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); | ||
3995 | 1243 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); | ||
3996 | 1244 | |||
3997 | 1245 | // Upstart notifies of stopping app | ||
3998 | 1246 | applicationManager.onProcessStopped(appId); | ||
4054 | 1247 | 976 | ||
4055 | 1248 | EXPECT_EQ(countSpy.count(), 2); //FIXME(greyback) | 977 | EXPECT_EQ(countSpy.count(), 2); //FIXME(greyback) |
4056 | 1249 | EXPECT_EQ(applicationManager.count(), 0); | 978 | EXPECT_EQ(applicationManager.count(), 0); |
4057 | @@ -1278,28 +1007,28 @@ | |||
4058 | 1278 | applicationManager.authorizeSession(procId, authed); | 1007 | applicationManager.authorizeSession(procId, authed); |
4059 | 1279 | onSessionStarting(session); | 1008 | onSessionStarting(session); |
4060 | 1280 | 1009 | ||
4065 | 1281 | std::shared_ptr<mir::scene::Surface> surface(nullptr); | 1010 | FakeMirSurfaceItem *surface = new FakeMirSurfaceItem; |
4066 | 1282 | applicationManager.onSessionCreatedSurface(session.get(), surface); | 1011 | onSessionCreatedSurface(session.get(), surface); |
4067 | 1283 | applicationManager.focusApplication(appId); | 1012 | surface->drawFirstFrame(); |
4064 | 1284 | EXPECT_EQ(applicationManager.focusedApplicationId(), appId); | ||
4068 | 1285 | 1013 | ||
4069 | 1286 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); | 1014 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); |
4070 | 1287 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); | 1015 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); |
4071 | 1288 | 1016 | ||
4072 | 1017 | onSessionStopping(session); | ||
4073 | 1289 | // Upstart notifies of stopping app | 1018 | // Upstart notifies of stopping app |
4074 | 1290 | applicationManager.onProcessStopped(appId); | 1019 | applicationManager.onProcessStopped(appId); |
4075 | 1291 | 1020 | ||
4080 | 1292 | EXPECT_EQ(countSpy.count(), 2); //FIXME(greyback) | 1021 | EXPECT_EQ(2, countSpy.count()); //FIXME(greyback) |
4081 | 1293 | EXPECT_EQ(applicationManager.count(), 0); | 1022 | EXPECT_EQ(0, applicationManager.count()); |
4082 | 1294 | EXPECT_EQ(removedSpy.count(), 1); | 1023 | EXPECT_EQ(1, removedSpy.count()); |
4083 | 1295 | EXPECT_EQ(removedSpy.takeFirst().at(0).toString(), appId); | 1024 | EXPECT_EQ(appId, removedSpy.takeFirst().at(0).toString()); |
4084 | 1296 | } | 1025 | } |
4085 | 1297 | 1026 | ||
4086 | 1298 | /* | 1027 | /* |
4089 | 1299 | * Test that if the foreground Running application is reported to unexpectedly stop by upstart, AppMan | 1028 | * Test that if a running application is reported to have stopped unexpectedly by upstart, AppMan |
4090 | 1300 | * cleans up after it ok (as was not in background, had not lifecycle saved its state, so cannot be resumed) | 1029 | * cleans up after it ok (as was not suspended, had not lifecycle saved its state, so cannot be resumed) |
4091 | 1301 | */ | 1030 | */ |
4093 | 1302 | TEST_F(ApplicationManagerTests,upstartNotifiesOfUnexpectedStopOfForegroundApp) | 1031 | TEST_F(ApplicationManagerTests,upstartNotifiesOfUnexpectedStopOfRunningApp) |
4094 | 1303 | { | 1032 | { |
4095 | 1304 | using namespace ::testing; | 1033 | using namespace ::testing; |
4096 | 1305 | const QString appId("testAppId"); | 1034 | const QString appId("testAppId"); |
4097 | @@ -1323,14 +1052,15 @@ | |||
4098 | 1323 | applicationManager.authorizeSession(procId, authed); | 1052 | applicationManager.authorizeSession(procId, authed); |
4099 | 1324 | onSessionStarting(session); | 1053 | onSessionStarting(session); |
4100 | 1325 | 1054 | ||
4105 | 1326 | std::shared_ptr<mir::scene::Surface> surface(nullptr); | 1055 | FakeMirSurfaceItem *surface = new FakeMirSurfaceItem; |
4106 | 1327 | applicationManager.onSessionCreatedSurface(session.get(), surface); | 1056 | onSessionCreatedSurface(session.get(), surface); |
4107 | 1328 | applicationManager.focusApplication(appId); | 1057 | surface->drawFirstFrame(); |
4104 | 1329 | EXPECT_EQ(applicationManager.focusedApplicationId(), appId); | ||
4108 | 1330 | 1058 | ||
4109 | 1331 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); | 1059 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); |
4110 | 1332 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); | 1060 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); |
4111 | 1333 | 1061 | ||
4112 | 1062 | onSessionStopping(session); | ||
4113 | 1063 | |||
4114 | 1334 | // Upstart notifies of crashing / OOM killed app | 1064 | // Upstart notifies of crashing / OOM killed app |
4115 | 1335 | applicationManager.onProcessFailed(appId, false); | 1065 | applicationManager.onProcessFailed(appId, false); |
4116 | 1336 | 1066 | ||
4117 | @@ -1344,53 +1074,6 @@ | |||
4118 | 1344 | } | 1074 | } |
4119 | 1345 | 1075 | ||
4120 | 1346 | /* | 1076 | /* |
4121 | 1347 | * Test that if a background application is stopped by upstart, AppMan removes it from the app list | ||
4122 | 1348 | * as the event is a result of direct user interaction | ||
4123 | 1349 | */ | ||
4124 | 1350 | TEST_F(ApplicationManagerTests,upstartNotifiesOfStoppingBackgroundApp) | ||
4125 | 1351 | { | ||
4126 | 1352 | using namespace ::testing; | ||
4127 | 1353 | const QString appId("testAppId"); | ||
4128 | 1354 | quint64 procId = 5551; | ||
4129 | 1355 | |||
4130 | 1356 | // Set up Mocks & signal watcher | ||
4131 | 1357 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | ||
4132 | 1358 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | ||
4133 | 1359 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4134 | 1360 | |||
4135 | 1361 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4136 | 1362 | |||
4137 | 1363 | EXPECT_CALL(appController, startApplicationWithAppIdAndArgs(appId, _)) | ||
4138 | 1364 | .Times(1) | ||
4139 | 1365 | .WillOnce(Return(true)); | ||
4140 | 1366 | |||
4141 | 1367 | applicationManager.startApplication(appId, ApplicationManager::NoFlag); | ||
4142 | 1368 | applicationManager.onProcessStarting(appId); | ||
4143 | 1369 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); | ||
4144 | 1370 | bool authed = true; | ||
4145 | 1371 | applicationManager.authorizeSession(procId, authed); | ||
4146 | 1372 | onSessionStarting(session); | ||
4147 | 1373 | |||
4148 | 1374 | std::shared_ptr<mir::scene::Surface> surface(nullptr); | ||
4149 | 1375 | applicationManager.onSessionCreatedSurface(session.get(), surface); | ||
4150 | 1376 | applicationManager.unfocusCurrentApplication(); | ||
4151 | 1377 | EXPECT_EQ(applicationManager.focusedApplicationId(), QString()); | ||
4152 | 1378 | |||
4153 | 1379 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); | ||
4154 | 1380 | QSignalSpy focusSpy(&applicationManager, SIGNAL(focusedApplicationIdChanged())); | ||
4155 | 1381 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); | ||
4156 | 1382 | |||
4157 | 1383 | // Upstart notifies of stopping app | ||
4158 | 1384 | applicationManager.onProcessStopped(appId); | ||
4159 | 1385 | |||
4160 | 1386 | EXPECT_EQ(countSpy.count(), 2); //FIXME(greyback) | ||
4161 | 1387 | EXPECT_EQ(applicationManager.count(), 0); | ||
4162 | 1388 | EXPECT_EQ(focusSpy.count(), 0); | ||
4163 | 1389 | EXPECT_EQ(removedSpy.count(), 1); | ||
4164 | 1390 | EXPECT_EQ(removedSpy.takeFirst().at(0).toString(), appId); | ||
4165 | 1391 | } | ||
4166 | 1392 | |||
4167 | 1393 | /* | ||
4168 | 1394 | * Test that if a background application is reported to unexpectedly stop by upstart, AppMan does not remove | 1077 | * Test that if a background application is reported to unexpectedly stop by upstart, AppMan does not remove |
4169 | 1395 | * it from the app lists but instead considers it Stopped, ready to be resumed. This is due to the fact the | 1078 | * it from the app lists but instead considers it Stopped, ready to be resumed. This is due to the fact the |
4170 | 1396 | * app should have saved its state, so can be resumed. This situation can occur due to the OOM killer, or | 1079 | * app should have saved its state, so can be resumed. This situation can occur due to the OOM killer, or |
4171 | @@ -1413,18 +1096,18 @@ | |||
4172 | 1413 | .Times(1) | 1096 | .Times(1) |
4173 | 1414 | .WillOnce(Return(true)); | 1097 | .WillOnce(Return(true)); |
4174 | 1415 | 1098 | ||
4176 | 1416 | applicationManager.startApplication(appId, ApplicationManager::NoFlag); | 1099 | Application *app = applicationManager.startApplication(appId, ApplicationManager::NoFlag); |
4177 | 1417 | applicationManager.onProcessStarting(appId); | 1100 | applicationManager.onProcessStarting(appId); |
4178 | 1418 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); | 1101 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); |
4179 | 1419 | bool authed = true; | 1102 | bool authed = true; |
4180 | 1420 | applicationManager.authorizeSession(procId, authed); | 1103 | applicationManager.authorizeSession(procId, authed); |
4181 | 1421 | onSessionStarting(session); | 1104 | onSessionStarting(session); |
4182 | 1422 | 1105 | ||
4188 | 1423 | std::shared_ptr<mir::scene::Surface> surface(nullptr); | 1106 | FakeMirSurfaceItem *surface = new FakeMirSurfaceItem; |
4189 | 1424 | applicationManager.onSessionCreatedSurface(session.get(), surface); | 1107 | onSessionCreatedSurface(session.get(), surface); |
4190 | 1425 | applicationManager.focusApplication(appId); | 1108 | surface->drawFirstFrame(); |
4191 | 1426 | applicationManager.unfocusCurrentApplication(); | 1109 | |
4192 | 1427 | EXPECT_EQ(applicationManager.focusedApplicationId(), QString()); | 1110 | suspend(app); |
4193 | 1428 | 1111 | ||
4194 | 1429 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); | 1112 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); |
4195 | 1430 | QSignalSpy focusSpy(&applicationManager, SIGNAL(focusedApplicationIdChanged())); | 1113 | QSignalSpy focusSpy(&applicationManager, SIGNAL(focusedApplicationIdChanged())); |
4196 | @@ -1436,14 +1119,14 @@ | |||
4197 | 1436 | // Upstart notifies of crashing / OOM-killed app | 1119 | // Upstart notifies of crashing / OOM-killed app |
4198 | 1437 | applicationManager.onProcessFailed(appId, false); | 1120 | applicationManager.onProcessFailed(appId, false); |
4199 | 1438 | 1121 | ||
4201 | 1439 | EXPECT_EQ(focusSpy.count(), 0); | 1122 | EXPECT_EQ(0, focusSpy.count()); |
4202 | 1440 | 1123 | ||
4203 | 1441 | // Upstart finally notifies the app stopped | 1124 | // Upstart finally notifies the app stopped |
4204 | 1442 | applicationManager.onProcessStopped(appId); | 1125 | applicationManager.onProcessStopped(appId); |
4205 | 1443 | 1126 | ||
4209 | 1444 | EXPECT_EQ(countSpy.count(), 0); | 1127 | EXPECT_EQ(0, countSpy.count()); |
4210 | 1445 | EXPECT_EQ(applicationManager.count(), 1); | 1128 | EXPECT_EQ(1, applicationManager.count()); |
4211 | 1446 | EXPECT_EQ(removedSpy.count(), 0); | 1129 | EXPECT_EQ(0, removedSpy.count()); |
4212 | 1447 | } | 1130 | } |
4213 | 1448 | 1131 | ||
4214 | 1449 | /* | 1132 | /* |
4215 | @@ -1471,18 +1154,18 @@ | |||
4216 | 1471 | .Times(1) | 1154 | .Times(1) |
4217 | 1472 | .WillOnce(Return(true)); | 1155 | .WillOnce(Return(true)); |
4218 | 1473 | 1156 | ||
4220 | 1474 | applicationManager.startApplication(appId, ApplicationManager::NoFlag); | 1157 | Application *app = applicationManager.startApplication(appId, ApplicationManager::NoFlag); |
4221 | 1475 | applicationManager.onProcessStarting(appId); | 1158 | applicationManager.onProcessStarting(appId); |
4222 | 1476 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); | 1159 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); |
4223 | 1477 | bool authed = true; | 1160 | bool authed = true; |
4224 | 1478 | applicationManager.authorizeSession(procId, authed); | 1161 | applicationManager.authorizeSession(procId, authed); |
4225 | 1479 | onSessionStarting(session); | 1162 | onSessionStarting(session); |
4226 | 1480 | 1163 | ||
4232 | 1481 | std::shared_ptr<mir::scene::Surface> surface(nullptr); | 1164 | FakeMirSurfaceItem *surface = new FakeMirSurfaceItem; |
4233 | 1482 | applicationManager.onSessionCreatedSurface(session.get(), surface); | 1165 | onSessionCreatedSurface(session.get(), surface); |
4234 | 1483 | applicationManager.focusApplication(appId); | 1166 | surface->drawFirstFrame(); |
4235 | 1484 | applicationManager.unfocusCurrentApplication(); | 1167 | |
4236 | 1485 | EXPECT_EQ(applicationManager.focusedApplicationId(), QString()); | 1168 | suspend(app); |
4237 | 1486 | 1169 | ||
4238 | 1487 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); | 1170 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); |
4239 | 1488 | QSignalSpy focusSpy(&applicationManager, SIGNAL(focusedApplicationIdChanged())); | 1171 | QSignalSpy focusSpy(&applicationManager, SIGNAL(focusedApplicationIdChanged())); |
4240 | @@ -1571,10 +1254,9 @@ | |||
4241 | 1571 | onSessionStarting(session); | 1254 | onSessionStarting(session); |
4242 | 1572 | 1255 | ||
4243 | 1573 | // Associate a surface so AppMan considers app Running, check focused | 1256 | // Associate a surface so AppMan considers app Running, check focused |
4248 | 1574 | std::shared_ptr<mir::scene::Surface> surface(nullptr); | 1257 | FakeMirSurfaceItem *surface = new FakeMirSurfaceItem; |
4249 | 1575 | applicationManager.onSessionCreatedSurface(session.get(), surface); | 1258 | onSessionCreatedSurface(session.get(), surface); |
4250 | 1576 | applicationManager.focusApplication(appId); | 1259 | surface->drawFirstFrame(); |
4247 | 1577 | EXPECT_EQ(applicationManager.focusedApplicationId(), appId); | ||
4251 | 1578 | 1260 | ||
4252 | 1579 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); | 1261 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); |
4253 | 1580 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); | 1262 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); |
4254 | @@ -1589,10 +1271,10 @@ | |||
4255 | 1589 | } | 1271 | } |
4256 | 1590 | 1272 | ||
4257 | 1591 | /* | 1273 | /* |
4259 | 1592 | * Test that if a foreground application (one launched via desktop_file_hint) is reported to be stopping by | 1274 | * Test that if an application (one launched via desktop_file_hint) is reported to be stopping by |
4260 | 1593 | * Mir, AppMan removes it from the model immediately | 1275 | * Mir, AppMan removes it from the model immediately |
4261 | 1594 | */ | 1276 | */ |
4263 | 1595 | TEST_F(ApplicationManagerTests,mirNotifiesOfStoppingForegroundAppLaunchedWithDesktopFileHint) | 1277 | TEST_F(ApplicationManagerTests,mirNotifiesOfStoppingAppLaunchedWithDesktopFileHint) |
4264 | 1596 | { | 1278 | { |
4265 | 1597 | using namespace ::testing; | 1279 | using namespace ::testing; |
4266 | 1598 | const QString appId("testAppId"); | 1280 | const QString appId("testAppId"); |
4267 | @@ -1621,10 +1303,9 @@ | |||
4268 | 1621 | onSessionStarting(session); | 1303 | onSessionStarting(session); |
4269 | 1622 | 1304 | ||
4270 | 1623 | // Associate a surface so AppMan considers app Running, check focused | 1305 | // Associate a surface so AppMan considers app Running, check focused |
4275 | 1624 | std::shared_ptr<mir::scene::Surface> surface(nullptr); | 1306 | FakeMirSurfaceItem *surface = new FakeMirSurfaceItem; |
4276 | 1625 | applicationManager.onSessionCreatedSurface(session.get(), surface); | 1307 | onSessionCreatedSurface(session.get(), surface); |
4277 | 1626 | applicationManager.focusApplication(appId); | 1308 | surface->drawFirstFrame(); |
4274 | 1627 | EXPECT_EQ(applicationManager.focusedApplicationId(), appId); | ||
4278 | 1628 | 1309 | ||
4279 | 1629 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); | 1310 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); |
4280 | 1630 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); | 1311 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); |
4281 | @@ -1661,86 +1342,43 @@ | |||
4282 | 1661 | .Times(1) | 1342 | .Times(1) |
4283 | 1662 | .WillOnce(Return(true)); | 1343 | .WillOnce(Return(true)); |
4284 | 1663 | 1344 | ||
4286 | 1664 | applicationManager.startApplication(appId, ApplicationManager::NoFlag); | 1345 | Application *app = applicationManager.startApplication(appId, ApplicationManager::NoFlag); |
4287 | 1665 | applicationManager.onProcessStarting(appId); | 1346 | applicationManager.onProcessStarting(appId); |
4288 | 1666 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); | 1347 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); |
4289 | 1667 | bool authed = true; | 1348 | bool authed = true; |
4290 | 1668 | applicationManager.authorizeSession(procId, authed); | 1349 | applicationManager.authorizeSession(procId, authed); |
4291 | 1669 | onSessionStarting(session); | 1350 | onSessionStarting(session); |
4366 | 1670 | 1351 | EXPECT_EQ(Application::Starting, app->state()); | |
4367 | 1671 | // Associate a surface so AppMan considers app Running, check in background | 1352 | |
4368 | 1672 | std::shared_ptr<mir::scene::Surface> surface(nullptr); | 1353 | app->setRequestedState(Application::RequestedSuspended); |
4369 | 1673 | applicationManager.onSessionCreatedSurface(session.get(), surface); | 1354 | |
4370 | 1674 | applicationManager.focusApplication(appId); | 1355 | // should not suspend an app that`s still starting up |
4371 | 1675 | applicationManager.unfocusCurrentApplication(); | 1356 | ASSERT_EQ(Application::InternalState::Starting, app->internalState()); |
4372 | 1676 | EXPECT_EQ(applicationManager.focusedApplicationId(), QString()); | 1357 | |
4373 | 1677 | 1358 | // Associate a surface so AppMan considers app Running | |
4374 | 1678 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); | 1359 | FakeMirSurfaceItem *surface = new FakeMirSurfaceItem; |
4375 | 1679 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); | 1360 | onSessionCreatedSurface(session.get(), surface); |
4376 | 1680 | 1361 | surface->drawFirstFrame(); | |
4377 | 1681 | // Mir notifies of stopping app | 1362 | |
4378 | 1682 | onSessionStopping(session); | 1363 | ASSERT_EQ(Application::InternalState::SuspendingWaitSession, app->internalState()); |
4379 | 1683 | 1364 | ||
4380 | 1684 | EXPECT_EQ(countSpy.count(), 0); | 1365 | static_cast<qtmir::Session*>(app->session())->doSuspend(); |
4381 | 1685 | EXPECT_EQ(applicationManager.count(), 1); | 1366 | ASSERT_EQ(Application::InternalState::SuspendingWaitProcess, app->internalState()); |
4382 | 1686 | EXPECT_EQ(removedSpy.count(), 0); | 1367 | |
4383 | 1687 | 1368 | applicationManager.onProcessSuspended(app->appId()); | |
4384 | 1688 | Application * app = applicationManager.findApplication(appId); | 1369 | ASSERT_EQ(Application::InternalState::Suspended, app->internalState()); |
4385 | 1689 | EXPECT_NE(nullptr,app); | 1370 | |
4386 | 1690 | EXPECT_EQ(app->state(), Application::Stopped); | 1371 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); |
4387 | 1691 | } | 1372 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); |
4388 | 1692 | 1373 | ||
4389 | 1693 | /* | 1374 | // Mir notifies of stopping app |
4390 | 1694 | * Test that if a background application (one launched via desktop_file_hint) is reported to be stopping by | 1375 | onSessionStopping(session); |
4391 | 1695 | * Mir, AppMan removes it from the model immediately | 1376 | |
4392 | 1696 | */ | 1377 | EXPECT_EQ(0, countSpy.count()); |
4393 | 1697 | TEST_F(ApplicationManagerTests,mirNotifiesOfStoppingBackgroundAppLaunchedWithDesktopFileHint) | 1378 | EXPECT_EQ(1, applicationManager.count()); |
4394 | 1698 | { | 1379 | EXPECT_EQ(0, removedSpy.count()); |
4395 | 1699 | using namespace ::testing; | 1380 | |
4396 | 1700 | const QString appId("testAppId"); | 1381 | EXPECT_EQ(Application::Stopped, app->state()); |
4323 | 1701 | const QString name("Test App"); | ||
4324 | 1702 | quint64 procId = 5551; | ||
4325 | 1703 | QByteArray cmdLine("/usr/bin/testApp --desktop_file_hint="); | ||
4326 | 1704 | cmdLine = cmdLine.append(appId); | ||
4327 | 1705 | |||
4328 | 1706 | // Set up Mocks & signal watcher | ||
4329 | 1707 | EXPECT_CALL(procInfo,command_line(procId)) | ||
4330 | 1708 | .Times(1) | ||
4331 | 1709 | .WillOnce(Return(cmdLine)); | ||
4332 | 1710 | |||
4333 | 1711 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | ||
4334 | 1712 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | ||
4335 | 1713 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4336 | 1714 | ON_CALL(*mockDesktopFileReader, name()).WillByDefault(Return(name)); | ||
4337 | 1715 | |||
4338 | 1716 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4339 | 1717 | |||
4340 | 1718 | // Mir requests authentication for an application that was started | ||
4341 | 1719 | bool authed = true; | ||
4342 | 1720 | applicationManager.authorizeSession(procId, authed); | ||
4343 | 1721 | EXPECT_EQ(authed, true); | ||
4344 | 1722 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); | ||
4345 | 1723 | onSessionStarting(session); | ||
4346 | 1724 | |||
4347 | 1725 | // Associate a surface so AppMan considers app Running, check in background | ||
4348 | 1726 | std::shared_ptr<mir::scene::Surface> surface(nullptr); | ||
4349 | 1727 | applicationManager.onSessionCreatedSurface(session.get(), surface); | ||
4350 | 1728 | applicationManager.focusApplication(appId); | ||
4351 | 1729 | applicationManager.unfocusCurrentApplication(); | ||
4352 | 1730 | EXPECT_EQ(applicationManager.focusedApplicationId(), QString()); | ||
4353 | 1731 | |||
4354 | 1732 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); | ||
4355 | 1733 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); | ||
4356 | 1734 | |||
4357 | 1735 | // Mir notifies of stopping app | ||
4358 | 1736 | onSessionStopping(session); | ||
4359 | 1737 | |||
4360 | 1738 | EXPECT_EQ(countSpy.count(), 2); //FIXME(greyback) | ||
4361 | 1739 | EXPECT_EQ(applicationManager.count(), 0); | ||
4362 | 1740 | EXPECT_EQ(removedSpy.count(), 1); | ||
4363 | 1741 | |||
4364 | 1742 | Application * app = applicationManager.findApplication(appId); | ||
4365 | 1743 | EXPECT_EQ(nullptr,app); | ||
4397 | 1744 | } | 1382 | } |
4398 | 1745 | 1383 | ||
4399 | 1746 | /* | 1384 | /* |
4400 | @@ -1822,45 +1460,6 @@ | |||
4401 | 1822 | } | 1460 | } |
4402 | 1823 | 1461 | ||
4403 | 1824 | /* | 1462 | /* |
4404 | 1825 | * Test that if an application is stopped by upstart, the Mir stopping event is ignored | ||
4405 | 1826 | */ | ||
4406 | 1827 | TEST_F(ApplicationManagerTests,appStoppedByUpstart_mirSessionStoppingEventIgnored) | ||
4407 | 1828 | { | ||
4408 | 1829 | using namespace ::testing; | ||
4409 | 1830 | const QString appId("testAppId"); | ||
4410 | 1831 | quint64 procId = 5551; | ||
4411 | 1832 | |||
4412 | 1833 | // Set up Mocks & signal watcher | ||
4413 | 1834 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | ||
4414 | 1835 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | ||
4415 | 1836 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4416 | 1837 | |||
4417 | 1838 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4418 | 1839 | |||
4419 | 1840 | EXPECT_CALL(appController, startApplicationWithAppIdAndArgs(appId, _)) | ||
4420 | 1841 | .Times(1) | ||
4421 | 1842 | .WillOnce(Return(true)); | ||
4422 | 1843 | |||
4423 | 1844 | applicationManager.startApplication(appId, ApplicationManager::NoFlag); | ||
4424 | 1845 | applicationManager.onProcessStarting(appId); | ||
4425 | 1846 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); | ||
4426 | 1847 | bool authed = true; | ||
4427 | 1848 | applicationManager.authorizeSession(procId, authed); | ||
4428 | 1849 | onSessionStarting(session); | ||
4429 | 1850 | |||
4430 | 1851 | applicationManager.onProcessStopped(appId); | ||
4431 | 1852 | |||
4432 | 1853 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); | ||
4433 | 1854 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); | ||
4434 | 1855 | |||
4435 | 1856 | // Mir notifies of stopping app | ||
4436 | 1857 | onSessionStopping(session); | ||
4437 | 1858 | |||
4438 | 1859 | EXPECT_EQ(countSpy.count(), 0); | ||
4439 | 1860 | EXPECT_EQ(removedSpy.count(), 0); | ||
4440 | 1861 | } | ||
4441 | 1862 | |||
4442 | 1863 | /* | ||
4443 | 1864 | * Webapps have multiple sessions, but only one is linked to the application (other is considered a hidden session). | 1463 | * Webapps have multiple sessions, but only one is linked to the application (other is considered a hidden session). |
4444 | 1865 | * If webapp in foreground stops unexpectedly, remove it and it alone from app list | 1464 | * If webapp in foreground stops unexpectedly, remove it and it alone from app list |
4445 | 1866 | */ | 1465 | */ |
4446 | @@ -1903,8 +1502,9 @@ | |||
4447 | 1903 | applicationManager.authorizeSession(procId2, authed); | 1502 | applicationManager.authorizeSession(procId2, authed); |
4448 | 1904 | onSessionStarting(session2); | 1503 | onSessionStarting(session2); |
4449 | 1905 | EXPECT_EQ(authed, true); | 1504 | EXPECT_EQ(authed, true); |
4452 | 1906 | std::shared_ptr<mir::scene::Surface> surface(nullptr); | 1505 | FakeMirSurfaceItem *surface = new FakeMirSurfaceItem; |
4453 | 1907 | applicationManager.onSessionCreatedSurface(session2.get(), surface); | 1506 | onSessionCreatedSurface(session2.get(), surface); |
4454 | 1507 | surface->drawFirstFrame(); | ||
4455 | 1908 | 1508 | ||
4456 | 1909 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); | 1509 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); |
4457 | 1910 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); | 1510 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); |
4458 | @@ -1950,7 +1550,7 @@ | |||
4459 | 1950 | .Times(1) | 1550 | .Times(1) |
4460 | 1951 | .WillOnce(Return(true)); | 1551 | .WillOnce(Return(true)); |
4461 | 1952 | 1552 | ||
4463 | 1953 | applicationManager.startApplication(appId, ApplicationManager::NoFlag); | 1553 | Application *app = applicationManager.startApplication(appId, ApplicationManager::NoFlag); |
4464 | 1954 | applicationManager.onProcessStarting(appId); | 1554 | applicationManager.onProcessStarting(appId); |
4465 | 1955 | std::shared_ptr<mir::scene::Session> session1 = std::make_shared<MockSession>("", procId1); | 1555 | std::shared_ptr<mir::scene::Session> session1 = std::make_shared<MockSession>("", procId1); |
4466 | 1956 | std::shared_ptr<mir::scene::Session> session2 = std::make_shared<MockSession>("", procId2); | 1556 | std::shared_ptr<mir::scene::Session> session2 = std::make_shared<MockSession>("", procId2); |
4467 | @@ -1958,19 +1558,20 @@ | |||
4468 | 1958 | bool authed = false; | 1558 | bool authed = false; |
4469 | 1959 | applicationManager.authorizeSession(procId1, authed); | 1559 | applicationManager.authorizeSession(procId1, authed); |
4470 | 1960 | onSessionStarting(session1); | 1560 | onSessionStarting(session1); |
4472 | 1961 | EXPECT_EQ(authed, true); | 1561 | EXPECT_EQ(true, authed); |
4473 | 1962 | applicationManager.authorizeSession(procId2, authed); | 1562 | applicationManager.authorizeSession(procId2, authed); |
4474 | 1963 | onSessionStarting(session2); | 1563 | onSessionStarting(session2); |
4476 | 1964 | EXPECT_EQ(authed, true); | 1564 | EXPECT_EQ(true, authed); |
4477 | 1965 | 1565 | ||
4486 | 1966 | // both sessions create surfaces, then unfocus everything. | 1566 | // both sessions create surfaces, then get them all suspended |
4487 | 1967 | std::shared_ptr<mir::scene::Surface> surface1(nullptr); | 1567 | FakeMirSurfaceItem *surface1 = new FakeMirSurfaceItem; |
4488 | 1968 | applicationManager.onSessionCreatedSurface(session1.get(), surface1); | 1568 | onSessionCreatedSurface(session1.get(), surface1); |
4489 | 1969 | std::shared_ptr<mir::scene::Surface> surface2(nullptr); | 1569 | surface1->drawFirstFrame(); |
4490 | 1970 | applicationManager.onSessionCreatedSurface(session2.get(), surface2); | 1570 | FakeMirSurfaceItem *surface2 = new FakeMirSurfaceItem; |
4491 | 1971 | applicationManager.focusApplication(appId); | 1571 | onSessionCreatedSurface(session2.get(), surface2); |
4492 | 1972 | applicationManager.unfocusCurrentApplication(); | 1572 | surface2->drawFirstFrame(); |
4493 | 1973 | EXPECT_EQ(applicationManager.focusedApplicationId(), QString()); | 1573 | suspend(app); |
4494 | 1574 | EXPECT_EQ(Application::Suspended, app->state()); | ||
4495 | 1974 | 1575 | ||
4496 | 1975 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); | 1576 | QSignalSpy countSpy(&applicationManager, SIGNAL(countChanged())); |
4497 | 1976 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); | 1577 | QSignalSpy removedSpy(&applicationManager, SIGNAL(applicationRemoved(const QString &))); |
4498 | @@ -1979,8 +1580,104 @@ | |||
4499 | 1979 | onSessionStopping(session2); | 1580 | onSessionStopping(session2); |
4500 | 1980 | onSessionStopping(session1); | 1581 | onSessionStopping(session1); |
4501 | 1981 | 1582 | ||
4504 | 1982 | EXPECT_EQ(countSpy.count(), 0); | 1583 | EXPECT_EQ(0, countSpy.count()); |
4505 | 1983 | EXPECT_EQ(removedSpy.count(), 0); | 1584 | EXPECT_EQ(0, removedSpy.count()); |
4506 | 1585 | } | ||
4507 | 1586 | |||
4508 | 1587 | /* | ||
4509 | 1588 | * Test requested surface size unchanged if no surfaceSizer registered | ||
4510 | 1589 | */ | ||
4511 | 1590 | TEST_F(ApplicationManagerTests, registerSurfaceSizeUnchangedWhenNoSizerCallbackRegistered) | ||
4512 | 1591 | { | ||
4513 | 1592 | using namespace ::testing; | ||
4514 | 1593 | quint64 procId = 5551; | ||
4515 | 1594 | SurfaceParameters params; | ||
4516 | 1595 | params.geometry = {400, 250}; // can be overridden | ||
4517 | 1596 | |||
4518 | 1597 | const auto session = std::make_shared<MockSession>("", procId); | ||
4519 | 1598 | applicationManager.onSessionAboutToCreateSurface(session, params); | ||
4520 | 1599 | |||
4521 | 1600 | EXPECT_EQ(params.geometry, QSize(400, 250)); | ||
4522 | 1601 | } | ||
4523 | 1602 | |||
4524 | 1603 | /* | ||
4525 | 1604 | * Test registerSurfaceSizerCallback functionality | ||
4526 | 1605 | */ | ||
4527 | 1606 | TEST_F(ApplicationManagerTests, registerSurfaceSizerFunctional) | ||
4528 | 1607 | { | ||
4529 | 1608 | using namespace ::testing; | ||
4530 | 1609 | quint64 procId = 5551; | ||
4531 | 1610 | SurfaceParameters params; | ||
4532 | 1611 | params.geometry = {400, 250}; // can be overridden | ||
4533 | 1612 | |||
4534 | 1613 | QJSValue callback = jsEngine->evaluate("(function(surface) { surface.width = 111; return surface; })"); | ||
4535 | 1614 | applicationManager.setSurfaceAboutToBeCreatedCallback(callback); | ||
4536 | 1615 | |||
4537 | 1616 | const auto session = std::make_shared<MockSession>("", procId); | ||
4538 | 1617 | applicationManager.onSessionAboutToCreateSurface(session, params); | ||
4539 | 1618 | |||
4540 | 1619 | EXPECT_EQ(params.geometry, QSize(111, 250)); | ||
4541 | 1620 | } | ||
4542 | 1621 | |||
4543 | 1622 | /* | ||
4544 | 1623 | * Test deregisterSurfaceSizerCallback correctly removes the callback | ||
4545 | 1624 | */ | ||
4546 | 1625 | TEST_F(ApplicationManagerTests, deregisterSurfaceSizerWorks) | ||
4547 | 1626 | { | ||
4548 | 1627 | using namespace ::testing; | ||
4549 | 1628 | quint64 procId = 5551; | ||
4550 | 1629 | SurfaceParameters params; | ||
4551 | 1630 | params.geometry = {400, 250}; // can be overridden | ||
4552 | 1631 | |||
4553 | 1632 | QJSValue callback = jsEngine->evaluate("(function(surface) { surface.width = 111; return surface; })"); | ||
4554 | 1633 | applicationManager.setSurfaceAboutToBeCreatedCallback(callback); | ||
4555 | 1634 | |||
4556 | 1635 | const auto session = std::make_shared<MockSession>("", procId); | ||
4557 | 1636 | |||
4558 | 1637 | applicationManager.setSurfaceAboutToBeCreatedCallback(false); | ||
4559 | 1638 | applicationManager.onSessionAboutToCreateSurface(session, params); | ||
4560 | 1639 | |||
4561 | 1640 | EXPECT_EQ(params.geometry, QSize(400, 250)); // should be unchanged | ||
4562 | 1641 | } | ||
4563 | 1642 | |||
4564 | 1643 | /* | ||
4565 | 1644 | * Test registerSurfaceSizerCallback rejects an uncallable QJSValue (i.e. something that's not a function was passed) | ||
4566 | 1645 | */ | ||
4567 | 1646 | TEST_F(ApplicationManagerTests, registerSurfaceSizerRejectsNonCallableJSValues) | ||
4568 | 1647 | { | ||
4569 | 1648 | using namespace ::testing; | ||
4570 | 1649 | |||
4571 | 1650 | QJSValue callback = jsEngine->evaluate("21"); | ||
4572 | 1651 | applicationManager.setSurfaceAboutToBeCreatedCallback(callback); | ||
4573 | 1652 | |||
4574 | 1653 | callback = jsEngine->evaluate("true"); | ||
4575 | 1654 | applicationManager.setSurfaceAboutToBeCreatedCallback(callback); | ||
4576 | 1655 | |||
4577 | 1656 | callback = jsEngine->evaluate("{}"); | ||
4578 | 1657 | applicationManager.setSurfaceAboutToBeCreatedCallback(callback); | ||
4579 | 1658 | |||
4580 | 1659 | callback = jsEngine->evaluate("new Array()"); | ||
4581 | 1660 | applicationManager.setSurfaceAboutToBeCreatedCallback(callback); | ||
4582 | 1661 | } | ||
4583 | 1662 | |||
4584 | 1663 | /* | ||
4585 | 1664 | * Test in case that registered SurfaceSizerCallback does not return a type with a 'width' (or 'height') property, | ||
4586 | 1665 | * we return the requested surface width/height unchanged | ||
4587 | 1666 | */ | ||
4588 | 1667 | TEST_F(ApplicationManagerTests, registeredSurfaceSizerDealswithBadReturns) | ||
4589 | 1668 | { | ||
4590 | 1669 | using namespace ::testing; | ||
4591 | 1670 | quint64 procId = 5551; | ||
4592 | 1671 | SurfaceParameters params; | ||
4593 | 1672 | params.geometry = {400, 250}; // can be overridden | ||
4594 | 1673 | |||
4595 | 1674 | QJSValue callback = jsEngine->evaluate("(function(s) { var out = new Object(); out.height = 333; return out; })"); | ||
4596 | 1675 | applicationManager.setSurfaceAboutToBeCreatedCallback(callback); | ||
4597 | 1676 | |||
4598 | 1677 | const auto session = std::make_shared<MockSession>("", procId); | ||
4599 | 1678 | applicationManager.onSessionAboutToCreateSurface(session, params); | ||
4600 | 1679 | |||
4601 | 1680 | EXPECT_EQ(params.geometry, QSize(400, 333)); | ||
4602 | 1984 | } | 1681 | } |
4603 | 1985 | 1682 | ||
4604 | 1986 | /* | 1683 | /* |
4605 | @@ -2007,34 +1704,33 @@ | |||
4606 | 2007 | .Times(1) | 1704 | .Times(1) |
4607 | 2008 | .WillOnce(Return(true)); | 1705 | .WillOnce(Return(true)); |
4608 | 2009 | 1706 | ||
4610 | 2010 | applicationManager.startApplication(appId, ApplicationManager::NoFlag); | 1707 | Application *app = applicationManager.startApplication(appId, ApplicationManager::NoFlag); |
4611 | 2011 | applicationManager.onProcessStarting(appId); | 1708 | applicationManager.onProcessStarting(appId); |
4612 | 2012 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); | 1709 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); |
4613 | 2013 | bool authed = true; | 1710 | bool authed = true; |
4614 | 2014 | applicationManager.authorizeSession(procId, authed); | 1711 | applicationManager.authorizeSession(procId, authed); |
4615 | 2015 | onSessionStarting(session); | 1712 | onSessionStarting(session); |
4616 | 2016 | 1713 | ||
4622 | 2017 | // App creates surface, focuses it, puts it in background, then is OOM killed. | 1714 | // App creates surface, puts it in background, then is OOM killed. |
4623 | 2018 | std::shared_ptr<mir::scene::Surface> surface(nullptr); | 1715 | FakeMirSurfaceItem *surface = new FakeMirSurfaceItem; |
4624 | 2019 | applicationManager.onSessionCreatedSurface(session.get(), surface); | 1716 | onSessionCreatedSurface(session.get(), surface); |
4625 | 2020 | applicationManager.focusApplication(appId); | 1717 | surface->drawFirstFrame(); |
4626 | 2021 | applicationManager.unfocusCurrentApplication(); | 1718 | suspend(app); |
4627 | 2022 | 1719 | ||
4628 | 2023 | onSessionStopping(session); | 1720 | onSessionStopping(session); |
4629 | 2024 | applicationManager.onProcessFailed(appId, false); | 1721 | applicationManager.onProcessFailed(appId, false); |
4630 | 2025 | applicationManager.onProcessStopped(appId); | 1722 | applicationManager.onProcessStopped(appId); |
4631 | 2026 | 1723 | ||
4634 | 2027 | Application *app = applicationManager.findApplication(appId); | 1724 | EXPECT_EQ(Application::Stopped, app->state()); |
4633 | 2028 | EXPECT_EQ(app->state(), Application::Stopped); | ||
4635 | 2029 | 1725 | ||
4636 | 2030 | QSignalSpy focusRequestSpy(&applicationManager, SIGNAL(focusRequested(const QString &))); | 1726 | QSignalSpy focusRequestSpy(&applicationManager, SIGNAL(focusRequested(const QString &))); |
4637 | 2031 | 1727 | ||
4638 | 2032 | // Upstart re-launches app | 1728 | // Upstart re-launches app |
4639 | 2033 | applicationManager.onProcessStarting(appId); | 1729 | applicationManager.onProcessStarting(appId); |
4640 | 2034 | 1730 | ||
4644 | 2035 | EXPECT_EQ(app->state(), Application::Starting); | 1731 | EXPECT_EQ(Application::Starting, app->state()); |
4645 | 2036 | EXPECT_EQ(focusRequestSpy.count(), 1); | 1732 | EXPECT_EQ(1, focusRequestSpy.count()); |
4646 | 2037 | EXPECT_EQ(applicationManager.count(), 1); | 1733 | EXPECT_EQ(1, applicationManager.count()); |
4647 | 2038 | } | 1734 | } |
4648 | 2039 | 1735 | ||
4649 | 2040 | /* | 1736 | /* |
4650 | @@ -2138,142 +1834,61 @@ | |||
4651 | 2138 | } | 1834 | } |
4652 | 2139 | } | 1835 | } |
4653 | 2140 | 1836 | ||
4654 | 2141 | /* | ||
4655 | 2142 | 1 - launch and focus a main stage app | ||
4656 | 2143 | * main stage app is running and focused | ||
4657 | 2144 | 2 - launch and focus a side stage app | ||
4658 | 2145 | * main stage app is running but is not focused | ||
4659 | 2146 | * side stage app is running and has focus | ||
4660 | 2147 | 3 - focus the main stage app | ||
4661 | 2148 | * main stage app is running and has focus | ||
4662 | 2149 | * side stage app is running but is not focused | ||
4663 | 2150 | |||
4664 | 2151 | This is a regression test for the bug where on step 3, the main stage app was momentarily | ||
4665 | 2152 | suspended and then resumed again. | ||
4666 | 2153 | */ | ||
4667 | 2154 | TEST_F(ApplicationManagerTests, focusMainStageAfterSideStage) | ||
4668 | 2155 | { | ||
4669 | 2156 | using namespace testing; | ||
4670 | 2157 | |||
4671 | 2158 | QString webbrowserAppId("webbrowser-app"); | ||
4672 | 2159 | quint64 webbrowserPID = 123; | ||
4673 | 2160 | std::shared_ptr<mir::scene::Surface> webbrowserSurface(nullptr); | ||
4674 | 2161 | |||
4675 | 2162 | QString dialerAppId("dialer-app"); | ||
4676 | 2163 | quint64 dialerPID = 456; | ||
4677 | 2164 | std::shared_ptr<mir::scene::Surface> dialerSurface(nullptr); | ||
4678 | 2165 | |||
4679 | 2166 | /*** Start webbrowser-app (main stage) ***/ | ||
4680 | 2167 | |||
4681 | 2168 | ON_CALL(appController,appIdHasProcessId(webbrowserPID, webbrowserAppId)).WillByDefault(Return(true)); | ||
4682 | 2169 | |||
4683 | 2170 | { | ||
4684 | 2171 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(webbrowserAppId, QFileInfo()); | ||
4685 | 2172 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | ||
4686 | 2173 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(webbrowserAppId)); | ||
4687 | 2174 | ON_CALL(*mockDesktopFileReader, stageHint()).WillByDefault(Return("MainStage")); | ||
4688 | 2175 | |||
4689 | 2176 | ON_CALL(desktopFileReaderFactory, createInstance(webbrowserAppId, _)) | ||
4690 | 2177 | .WillByDefault(Return(mockDesktopFileReader)); | ||
4691 | 2178 | } | ||
4692 | 2179 | |||
4693 | 2180 | EXPECT_CALL(appController, startApplicationWithAppIdAndArgs(webbrowserAppId, _)) | ||
4694 | 2181 | .Times(1) | ||
4695 | 2182 | .WillOnce(Return(true)); | ||
4696 | 2183 | |||
4697 | 2184 | /*auto application =*/ applicationManager.startApplication(webbrowserAppId, ApplicationManager::NoFlag); | ||
4698 | 2185 | applicationManager.onProcessStarting(webbrowserAppId); | ||
4699 | 2186 | |||
4700 | 2187 | { | ||
4701 | 2188 | bool authed = false; | ||
4702 | 2189 | applicationManager.authorizeSession(webbrowserPID, authed); | ||
4703 | 2190 | EXPECT_EQ(authed, true); | ||
4704 | 2191 | } | ||
4705 | 2192 | |||
4706 | 2193 | auto webbrowserSession = std::make_shared<mir::scene::MockSession>(webbrowserAppId.toStdString(), webbrowserPID); | ||
4707 | 2194 | sessionManager.onSessionStarting(webbrowserSession); | ||
4708 | 2195 | applicationManager.focusApplication(webbrowserAppId); | ||
4709 | 2196 | applicationManager.onSessionCreatedSurface(webbrowserSession.get(), webbrowserSurface); | ||
4710 | 2197 | |||
4711 | 2198 | /*** Start dialer-app (side stage) ***/ | ||
4712 | 2199 | |||
4713 | 2200 | ON_CALL(appController, appIdHasProcessId(dialerPID, dialerAppId)).WillByDefault(Return(true)); | ||
4714 | 2201 | |||
4715 | 2202 | { | ||
4716 | 2203 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(dialerAppId, QFileInfo()); | ||
4717 | 2204 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | ||
4718 | 2205 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(dialerAppId)); | ||
4719 | 2206 | ON_CALL(*mockDesktopFileReader, stageHint()).WillByDefault(Return("SideStage")); | ||
4720 | 2207 | |||
4721 | 2208 | ON_CALL(desktopFileReaderFactory, createInstance(dialerAppId, _)) | ||
4722 | 2209 | .WillByDefault(Return(mockDesktopFileReader)); | ||
4723 | 2210 | } | ||
4724 | 2211 | |||
4725 | 2212 | EXPECT_CALL(appController, startApplicationWithAppIdAndArgs(dialerAppId, _)) | ||
4726 | 2213 | .Times(1) | ||
4727 | 2214 | .WillOnce(Return(true)); | ||
4728 | 2215 | |||
4729 | 2216 | /*auto application =*/ applicationManager.startApplication(dialerAppId, ApplicationManager::NoFlag); | ||
4730 | 2217 | applicationManager.onProcessStarting(dialerAppId); | ||
4731 | 2218 | |||
4732 | 2219 | { | ||
4733 | 2220 | bool authed = false; | ||
4734 | 2221 | applicationManager.authorizeSession(dialerPID, authed); | ||
4735 | 2222 | EXPECT_EQ(authed, true); | ||
4736 | 2223 | } | ||
4737 | 2224 | |||
4738 | 2225 | auto dialerSession = std::make_shared<mir::scene::MockSession>(dialerAppId.toStdString(), dialerPID); | ||
4739 | 2226 | sessionManager.onSessionStarting(dialerSession); | ||
4740 | 2227 | applicationManager.focusApplication(dialerAppId); | ||
4741 | 2228 | applicationManager.onSessionCreatedSurface(dialerSession.get(), dialerSurface); | ||
4742 | 2229 | |||
4743 | 2230 | /*** Focus webbrowser ***/ | ||
4744 | 2231 | |||
4745 | 2232 | // Nothing should happen as it's already the running main stage app | ||
4746 | 2233 | EXPECT_CALL(*webbrowserSession.get(), set_lifecycle_state(_)) | ||
4747 | 2234 | .Times(0); | ||
4748 | 2235 | applicationManager.focusApplication(webbrowserAppId); | ||
4749 | 2236 | } | ||
4750 | 2237 | |||
4751 | 2238 | TEST_F(ApplicationManagerTests,lifecycle_exempt_appId_is_not_suspended) | 1837 | TEST_F(ApplicationManagerTests,lifecycle_exempt_appId_is_not_suspended) |
4752 | 2239 | { | 1838 | { |
4753 | 2240 | using namespace ::testing; | 1839 | using namespace ::testing; |
4754 | 2241 | quint64 a_procId = 5921; | 1840 | quint64 a_procId = 5921; |
4758 | 2242 | const char an_app_id[] = "some_app"; | 1841 | const QString appId("some_app"); |
4759 | 2243 | QByteArray a_cmd( "/usr/bin/app1 --desktop_file_hint=some_app"); | 1842 | QByteArray a_cmd("/usr/bin/app1"); |
4757 | 2244 | std::shared_ptr<mir::scene::Surface> aSurface(nullptr); | ||
4760 | 2245 | 1843 | ||
4761 | 2246 | ON_CALL(procInfo,command_line(_)).WillByDefault(Return(a_cmd)); | 1844 | ON_CALL(procInfo,command_line(_)).WillByDefault(Return(a_cmd)); |
4762 | 2247 | 1845 | ||
4766 | 2248 | ON_CALL(appController,appIdHasProcessId(_,_)).WillByDefault(Return(false)); | 1846 | ON_CALL(appController,appIdHasProcessId(a_procId, appId)).WillByDefault(Return(true)); |
4767 | 2249 | 1847 | ||
4768 | 2250 | bool authed = true; | 1848 | // Set up Mocks & signal watcher |
4769 | 1849 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | ||
4770 | 1850 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | ||
4771 | 1851 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4772 | 1852 | |||
4773 | 1853 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4774 | 1854 | |||
4775 | 1855 | |||
4776 | 1856 | Application *the_app = applicationManager.startApplication(appId, ApplicationManager::NoFlag); | ||
4777 | 1857 | applicationManager.onProcessStarting(appId); | ||
4778 | 2251 | 1858 | ||
4779 | 2252 | std::shared_ptr<mir::scene::Session> first_session = std::make_shared<MockSession>("Oo", a_procId); | 1859 | std::shared_ptr<mir::scene::Session> first_session = std::make_shared<MockSession>("Oo", a_procId); |
4780 | 2253 | std::shared_ptr<mir::scene::Session> second_session = std::make_shared<MockSession>("oO", a_procId); | 1860 | std::shared_ptr<mir::scene::Session> second_session = std::make_shared<MockSession>("oO", a_procId); |
4782 | 2254 | applicationManager.authorizeSession(a_procId, authed); | 1861 | { |
4783 | 1862 | bool authed = false; | ||
4784 | 1863 | applicationManager.authorizeSession(a_procId, authed); | ||
4785 | 1864 | ASSERT_EQ(authed, true); | ||
4786 | 1865 | } | ||
4787 | 2255 | 1866 | ||
4788 | 2256 | onSessionStarting(first_session); | 1867 | onSessionStarting(first_session); |
4790 | 2257 | applicationManager.onSessionCreatedSurface(first_session.get(), aSurface); | 1868 | FakeMirSurfaceItem *aSurface = new FakeMirSurfaceItem; |
4791 | 1869 | onSessionCreatedSurface(first_session.get(), aSurface); | ||
4792 | 1870 | aSurface->drawFirstFrame(); | ||
4793 | 2258 | onSessionStarting(second_session); | 1871 | onSessionStarting(second_session); |
4794 | 2259 | 1872 | ||
4795 | 2260 | Application * the_app = applicationManager.findApplication(an_app_id); | ||
4796 | 2261 | applicationManager.focusApplication(an_app_id); | ||
4797 | 2262 | |||
4798 | 2263 | // Add to other apps to the list (Not "some_app") | 1873 | // Add to other apps to the list (Not "some_app") |
4799 | 2264 | QVariantList lifecycleExemptAppIds; | 1874 | QVariantList lifecycleExemptAppIds; |
4800 | 2265 | lifecycleExemptAppIds << "one_app" << "another_app"; | 1875 | lifecycleExemptAppIds << "one_app" << "another_app"; |
4801 | 2266 | ON_CALL(settings,get(_)).WillByDefault(Return(lifecycleExemptAppIds)); | 1876 | ON_CALL(settings,get(_)).WillByDefault(Return(lifecycleExemptAppIds)); |
4802 | 2267 | settings.changed("lifecycleExemptAppids"); | 1877 | settings.changed("lifecycleExemptAppids"); |
4803 | 2268 | 1878 | ||
4812 | 2269 | EXPECT_EQ(Application::Running, the_app->state()); | 1879 | ASSERT_EQ(Application::InternalState::Running, the_app->internalState()); |
4813 | 2270 | 1880 | ||
4814 | 2271 | applicationManager.setSuspended(true); | 1881 | EXPECT_CALL(*(mir::scene::MockSession*)first_session.get(), set_lifecycle_state(mir_lifecycle_state_will_suspend)); |
4815 | 2272 | 1882 | the_app->setRequestedState(Application::RequestedSuspended); | |
4816 | 2273 | // And expect "some_app" to get suspended | 1883 | ASSERT_EQ(Application::InternalState::SuspendingWaitSession, the_app->internalState()); |
4817 | 2274 | EXPECT_EQ(Application::Suspended, the_app->state()); | 1884 | |
4818 | 2275 | 1885 | static_cast<qtmir::Session*>(the_app->session())->doSuspend(); | |
4819 | 2276 | applicationManager.setSuspended(false); | 1886 | ASSERT_EQ(Application::InternalState::SuspendingWaitProcess, the_app->internalState()); |
4820 | 1887 | applicationManager.onProcessSuspended(the_app->appId()); | ||
4821 | 1888 | ASSERT_EQ(Application::InternalState::Suspended, the_app->internalState()); | ||
4822 | 1889 | |||
4823 | 1890 | EXPECT_CALL(*(mir::scene::MockSession*)first_session.get(), set_lifecycle_state(mir_lifecycle_state_resumed)); | ||
4824 | 1891 | the_app->setRequestedState(Application::RequestedRunning); | ||
4825 | 2277 | 1892 | ||
4826 | 2278 | EXPECT_EQ(Application::Running, the_app->state()); | 1893 | EXPECT_EQ(Application::Running, the_app->state()); |
4827 | 2279 | 1894 | ||
4828 | @@ -2284,14 +1899,16 @@ | |||
4829 | 2284 | 1899 | ||
4830 | 2285 | EXPECT_EQ(Application::Running, the_app->state()); | 1900 | EXPECT_EQ(Application::Running, the_app->state()); |
4831 | 2286 | 1901 | ||
4833 | 2287 | applicationManager.setSuspended(true); | 1902 | EXPECT_CALL(*(mir::scene::MockSession*)first_session.get(), set_lifecycle_state(_)).Times(0); |
4834 | 1903 | the_app->setRequestedState(Application::RequestedSuspended); | ||
4835 | 2288 | 1904 | ||
4836 | 2289 | // And expect it to be running still | 1905 | // And expect it to be running still |
4842 | 2290 | EXPECT_EQ(Application::Running, the_app->state()); | 1906 | ASSERT_EQ(Application::InternalState::RunningInBackground, the_app->internalState()); |
4843 | 2291 | 1907 | ||
4844 | 2292 | applicationManager.setSuspended(false); | 1908 | the_app->setRequestedState(Application::RequestedRunning); |
4845 | 2293 | 1909 | ||
4846 | 2294 | EXPECT_EQ(Application::Running, the_app->state()); | 1910 | EXPECT_EQ(Application::Running, the_app->state()); |
4847 | 1911 | ASSERT_EQ(Application::InternalState::Running, the_app->internalState()); | ||
4848 | 2295 | } | 1912 | } |
4849 | 2296 | 1913 | ||
4850 | 2297 | /* | 1914 | /* |
4851 | @@ -2323,51 +1940,13 @@ | |||
4852 | 2323 | onSessionStarting(session); | 1940 | onSessionStarting(session); |
4853 | 2324 | 1941 | ||
4854 | 2325 | // App creates surface, focuses it so state is running | 1942 | // App creates surface, focuses it so state is running |
4902 | 2326 | std::shared_ptr<mir::scene::Surface> surface(nullptr); | 1943 | FakeMirSurfaceItem *surface = new FakeMirSurfaceItem; |
4903 | 2327 | applicationManager.onSessionCreatedSurface(session.get(), surface); | 1944 | onSessionCreatedSurface(session.get(), surface); |
4904 | 2328 | applicationManager.focusApplication(appId); | 1945 | surface->drawFirstFrame(); |
4905 | 2329 | 1946 | ||
4906 | 2330 | applicationManager.unfocusCurrentApplication(); | 1947 | application->setRequestedState(Application::RequestedSuspended); |
4907 | 2331 | 1948 | ||
4908 | 2332 | EXPECT_FALSE(sharedWakelock.enabled()); | 1949 | EXPECT_FALSE(sharedWakelock.enabled()); |
4909 | 2333 | EXPECT_EQ(application->state(), Application::Running); | 1950 | ASSERT_EQ(Application::InternalState::RunningInBackground, application->internalState()); |
4910 | 2334 | } | 1951 | EXPECT_EQ(Application::Running, application->state()); |
4864 | 2335 | |||
4865 | 2336 | /* | ||
4866 | 2337 | * Test lifecycle exempt applications have their wakelocks released on suspend | ||
4867 | 2338 | */ | ||
4868 | 2339 | TEST_F(ApplicationManagerTests,lifecycleExemptAppsHaveWakelockReleasedOnUnSuspend) | ||
4869 | 2340 | { | ||
4870 | 2341 | using namespace ::testing; | ||
4871 | 2342 | |||
4872 | 2343 | const QString appId("com.ubuntu.music"); // member of lifecycle exemption list | ||
4873 | 2344 | const quint64 procId = 12345; | ||
4874 | 2345 | |||
4875 | 2346 | // Set up Mocks & signal watcher | ||
4876 | 2347 | auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo()); | ||
4877 | 2348 | ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true)); | ||
4878 | 2349 | ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId)); | ||
4879 | 2350 | |||
4880 | 2351 | ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader)); | ||
4881 | 2352 | |||
4882 | 2353 | EXPECT_CALL(appController, startApplicationWithAppIdAndArgs(appId, _)) | ||
4883 | 2354 | .Times(1) | ||
4884 | 2355 | .WillOnce(Return(true)); | ||
4885 | 2356 | |||
4886 | 2357 | auto application = applicationManager.startApplication(appId, ApplicationManager::NoFlag); | ||
4887 | 2358 | applicationManager.onProcessStarting(appId); | ||
4888 | 2359 | std::shared_ptr<mir::scene::Session> session = std::make_shared<MockSession>("", procId); | ||
4889 | 2360 | bool authed = true; | ||
4890 | 2361 | applicationManager.authorizeSession(procId, authed); | ||
4891 | 2362 | onSessionStarting(session); | ||
4892 | 2363 | |||
4893 | 2364 | // App creates surface, focuses it so state is running | ||
4894 | 2365 | std::shared_ptr<mir::scene::Surface> surface(nullptr); | ||
4895 | 2366 | applicationManager.onSessionCreatedSurface(session.get(), surface); | ||
4896 | 2367 | applicationManager.focusApplication(appId); | ||
4897 | 2368 | |||
4898 | 2369 | applicationManager.setSuspended(true); | ||
4899 | 2370 | |||
4900 | 2371 | EXPECT_FALSE(sharedWakelock.enabled()); | ||
4901 | 2372 | EXPECT_EQ(application->state(), Application::Running); | ||
4911 | 2373 | } | 1952 | } |
4912 | 2374 | 1953 | ||
4913 | === modified file 'tests/modules/MirSurfaceItem/CMakeLists.txt' | |||
4914 | --- tests/modules/MirSurfaceItem/CMakeLists.txt 2014-12-03 08:56:35 +0000 | |||
4915 | +++ tests/modules/MirSurfaceItem/CMakeLists.txt 2015-07-13 21:57:32 +0000 | |||
4916 | @@ -5,7 +5,9 @@ | |||
4917 | 5 | ) | 5 | ) |
4918 | 6 | 6 | ||
4919 | 7 | include_directories( | 7 | include_directories( |
4921 | 8 | ${CMAKE_SOURCE_DIR}/src/modules/Unity/Application | 8 | ${CMAKE_SOURCE_DIR}/src/common |
4922 | 9 | # ${CMAKE_SOURCE_DIR}/src/modules/Unity/Application | ||
4923 | 10 | ${CMAKE_SOURCE_DIR}/src/modules | ||
4924 | 9 | ${CMAKE_SOURCE_DIR}/tests/modules/common | 11 | ${CMAKE_SOURCE_DIR}/tests/modules/common |
4925 | 10 | ${MIRSERVER_INCLUDE_DIRS} | 12 | ${MIRSERVER_INCLUDE_DIRS} |
4926 | 11 | ) | 13 | ) |
4927 | 12 | 14 | ||
4928 | === modified file 'tests/modules/MirSurfaceItem/mirsurfaceitem_test.cpp' | |||
4929 | --- tests/modules/MirSurfaceItem/mirsurfaceitem_test.cpp 2015-05-01 13:37:03 +0000 | |||
4930 | +++ tests/modules/MirSurfaceItem/mirsurfaceitem_test.cpp 2015-07-13 21:57:32 +0000 | |||
4931 | @@ -23,7 +23,7 @@ | |||
4932 | 23 | #include <QTest> | 23 | #include <QTest> |
4933 | 24 | 24 | ||
4934 | 25 | // the test subject | 25 | // the test subject |
4936 | 26 | #include <mirsurfaceitem.h> | 26 | #include <Unity/Application/mirsurfaceitem.h> |
4937 | 27 | 27 | ||
4938 | 28 | // mocks | 28 | // mocks |
4939 | 29 | #include <mock_surface.h> | 29 | #include <mock_surface.h> |
4940 | 30 | 30 | ||
4941 | === modified file 'tests/modules/SessionManager/CMakeLists.txt' | |||
4942 | --- tests/modules/SessionManager/CMakeLists.txt 2015-05-21 18:48:59 +0000 | |||
4943 | +++ tests/modules/SessionManager/CMakeLists.txt 2015-07-13 21:57:32 +0000 | |||
4944 | @@ -3,9 +3,13 @@ | |||
4945 | 3 | session_manager_test.cpp | 3 | session_manager_test.cpp |
4946 | 4 | session_test.cpp | 4 | session_test.cpp |
4947 | 5 | ${CMAKE_SOURCE_DIR}/src/common/debughelpers.cpp | 5 | ${CMAKE_SOURCE_DIR}/src/common/debughelpers.cpp |
4948 | 6 | ${CMAKE_SOURCE_DIR}/tests/modules/common/qtmir_test.cpp | ||
4949 | 7 | ${CMAKE_SOURCE_DIR}/tests/modules/common/fake_mirsurfaceitem.h | ||
4950 | 6 | ) | 8 | ) |
4951 | 7 | 9 | ||
4952 | 8 | include_directories( | 10 | include_directories( |
4953 | 11 | ${APPLICATION_API_INCLUDE_DIRS} | ||
4954 | 12 | ${CMAKE_SOURCE_DIR}/src/common | ||
4955 | 9 | ${CMAKE_SOURCE_DIR}/src/platforms/mirserver | 13 | ${CMAKE_SOURCE_DIR}/src/platforms/mirserver |
4956 | 10 | ${CMAKE_SOURCE_DIR}/src/modules | 14 | ${CMAKE_SOURCE_DIR}/src/modules |
4957 | 11 | ${CMAKE_SOURCE_DIR}/tests/modules/common | 15 | ${CMAKE_SOURCE_DIR}/tests/modules/common |
4958 | 12 | 16 | ||
4959 | === modified file 'tests/modules/SessionManager/session_manager_test.cpp' | |||
4960 | --- tests/modules/SessionManager/session_manager_test.cpp 2014-12-01 11:05:01 +0000 | |||
4961 | +++ tests/modules/SessionManager/session_manager_test.cpp 2015-07-13 21:57:32 +0000 | |||
4962 | @@ -21,7 +21,7 @@ | |||
4963 | 21 | 21 | ||
4964 | 22 | #include <Unity/Application/session.h> | 22 | #include <Unity/Application/session.h> |
4965 | 23 | 23 | ||
4967 | 24 | #include "qtmir_test.h" | 24 | #include "qtmir_test.h" |
4968 | 25 | 25 | ||
4969 | 26 | using namespace qtmir; | 26 | using namespace qtmir; |
4970 | 27 | using mir::scene::MockSession; | 27 | using mir::scene::MockSession; |
4971 | 28 | 28 | ||
4972 | === modified file 'tests/modules/SessionManager/session_test.cpp' | |||
4973 | --- tests/modules/SessionManager/session_test.cpp 2015-01-09 15:13:29 +0000 | |||
4974 | +++ tests/modules/SessionManager/session_test.cpp 2015-07-13 21:57:32 +0000 | |||
4975 | @@ -1,5 +1,5 @@ | |||
4976 | 1 | /* | 1 | /* |
4978 | 2 | * Copyright (C) 2014 Canonical, Ltd. | 2 | * Copyright (C) 2014,2015 Canonical, Ltd. |
4979 | 3 | * | 3 | * |
4980 | 4 | * This program is free software: you can redistribute it and/or modify it under | 4 | * This program is free software: you can redistribute it and/or modify it under |
4981 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | 5 | * the terms of the GNU Lesser General Public License version 3, as published by |
4982 | @@ -15,16 +15,17 @@ | |||
4983 | 15 | * | 15 | * |
4984 | 16 | */ | 16 | */ |
4985 | 17 | 17 | ||
4986 | 18 | #include <qtmir_test.h> | ||
4987 | 19 | #include <fake_mirsurfaceitem.h> | ||
4988 | 20 | |||
4989 | 18 | #include <Unity/Application/application.h> | 21 | #include <Unity/Application/application.h> |
4990 | 19 | #include <Unity/Application/mirsurfaceitem.h> | 22 | #include <Unity/Application/mirsurfaceitem.h> |
4991 | 20 | 23 | ||
4992 | 21 | #include "qtmir_test.h" | ||
4993 | 22 | #include "stub_scene_surface.h" | 24 | #include "stub_scene_surface.h" |
4994 | 23 | 25 | ||
4995 | 24 | using namespace qtmir; | 26 | using namespace qtmir; |
4996 | 25 | using mir::scene::MockSession; | 27 | using mir::scene::MockSession; |
4997 | 26 | 28 | ||
4998 | 27 | |||
4999 | 28 | namespace ms = mir::scene; | 29 | namespace ms = mir::scene; |
5000 | 29 | namespace mtd = mir::test::doubles; | 30 | namespace mtd = mir::test::doubles; |
See inline.